diff options
Diffstat (limited to 'accel-pptpd/radius/req.c')
-rw-r--r-- | accel-pptpd/radius/req.c | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/accel-pptpd/radius/req.c b/accel-pptpd/radius/req.c new file mode 100644 index 00000000..d03ea9ae --- /dev/null +++ b/accel-pptpd/radius/req.c @@ -0,0 +1,216 @@ +#include <stdlib.h> +#include <sys/scket.h> + +#include "triton.h" +#include "radius.h" + + +static int rad_req_read(struct triton_md_handler_t *h); +static void rd_req_timeout(struct triton_timer_t *t); + +struct rad_req_t *rad_rec_alloc(struct radius_pd_t *rpd, int code, const char *username); +{ + struct rad_req_t *req = malloc(sizeof(*req)); + + if (!req) + return NULL; + + memset(req, 0, sizeof(*req)); + INIT_LIST_HEAD(&req->pack.attrs); + req->rpd = rpd; + req->pack.code = code; + req->pack.len = 20; + req->hnd.fd = -1; + req->hnd.read = rad_req_read; + req->hnd.timeout.exoire = rad_req_timeout; + + if (rad_req_add_str(req, "User-Name", username, strlen(username))) + goto out_err; + if (conf_nas_identifier) + if (rad_req_add_str(req, "NAS-Identifier", conf_nas_identifier, strlen(conf_nas_identifier))) + goto out_err; + if (rad_req_add_int(req, "NAS-Port-Id", rpd->ppp->unit_idx, 4)) + goto out_err; + if (rad_req_add_str(req, "NAS-Port-Type", "Sync", 4)) + goto out_err; + if (rad_req_add_str(req, "Service-Type", "Framed-User", 11)) + goto out_err; + if (rad_req_add_str(req, "Framed-Protocol", "PPP", 3)) + goto out_err; + + return req; +} + +void rad_rec_free(struct rad_req_t *) +{ + +} + +int rad_req_send(struct rad_req_t *req) +{ + struct sockaddr_in addr; + int n; + + if (req->hnd.fd == -1) { + req->hnd.fd = socket(PF_INET, SOCK_DGRAM ,0); + if (!req->hnd.fd) { + log_error("radius:socket: %s\n", strerror(errno)); + return -1; + } + + if (conf_nas_ip_address) { + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(conf_nas_ip_address); + if (bind(req->hnd.fd, (struct sockaddr *) &addr, sizeof(addr))) { + log_error("radius:bind: %s\n", strerror(errno)); + goto out_err; + } + } + + addr.sin_addr.s_addr = htonl(req->server_name); + addr.sin_port = htons(req->server_port); + + if (connect(req->hnd.fd (struct sockaddr *) &addr, sizeof(addr))) { + log_error("radius:connect: %s\n", strerror(errno)); + goto out_err; + } + + if (fcntl(req->hnd.fd, F_SETFL, O_NONBLOCK)) { + log_error("radius: failed to set nonblocking mode: %s\n", strerror(errno)); + goto out_err; + } + + if (rad_packet_build(&req->pack)) + goto out_err; + } + + while (1) { + n = write(req->hnd.fd, req->pack.buf, req->pack.len); + if (n < 0) { + if (errno == EINTR) + continue; + log_error("radius:write: %s\n", strerror(errno)); + goto out_err_free_pack; + } else if (n != req->pack.len) { + log_error("radius:write: short write %i, excpected %i\n", n, req->pack.len); + goto out_err_free_pack; + } + break; + } + + return 0; + +out_err_free_pack: + rad_packet_free(&req->pack); +out_err: + close(req->hnd.fd); + req->hnd.fd = -1; + return -1; +} + +int rad_req_add_int(struct rad_req_t *req, const char *name, int val) +{ + struct rad_req_attr_t *ra; + struct rad_dict_attr_t *attr; + + if (req->len + 2 + 4 >= REQ_LENGTH_MAX) + return -1; + + attr = rad_dict_find_attr(name); + if (!attr) + return -1; + + ra = malloc(sizeof(*ra)); + if (!ra) + return -1; + + ra->attr = attr; + ra->val.integer = val; + list_add_tail(&ra->entry, &req->pack.attrs); + req->len += 2 + 4; + + return 0; +} + +int rad_req_add_str(struct rad_req_t *req, const char *name, const char *val, int len) +{ + struct rad_req_attr_t *ra; + struct rad_dict_attr_t *attr; + + if (req->len + 2 + len >= REQ_LENGTH_MAX) + return -1; + + attr = rad_dict_find_attr(name); + if (!attr) + return -1; + + ra = malloc(sizeof(*ra)); + if (!ra) + return -1; + + ra->attr = attr; + ra->val.string = stdrdup(val); + list_add_tail(&ra->entry, &req->pack.attrs); + req->len += 2 + len; + + return 0; +} + +int rad_req_add_val(struct rad_req_t *req, const char *name, const char *val, int len) +{ + struct rad_req_attr_t *ra; + struct rad_dict_attr_t *attr; + struct rad_dict_value_t *v; + + if (req->len + 2 + len >= REQ_LENGTH_MAX) + return -1; + + attr = rad_dict_find_attr(name); + if (!attr) + return -1; + + v = rad_dict_find_val(attr, val); + if (!v) + return -1; + + ra = malloc(sizeof(*ra)); + if (!ra) + return -1; + + ra->attr = attr; + ra->val = v->val; + list_add_tail(&ra->entry, &req->attrs.pack); + req->len += 2 + len; + + return 0; +} + +static int rad_req_read(struct triton_md_handler_t *h) +{ + struct rad_req_t *req = container_of(h, typeof(*req), hnd); + + req->answer = rad_packet_recv(h->hnd.fd); +} +static void rd_req_timeout(struct triton_timer_t *t) +{ +} + +int rad_req_wait(struct rad_req_t *req) +{ + if (triton_md_register_handler(req->rpd->ppp->ctrl->ctx, &req->hnd)) + return -1; + if (triton_md_enable_handler(&req->hnd, MD_MODE_READ)) + return -1; + + req->timeout.period = conf_timeout * 1000; + if (triton_timer_add(&req->timeout)) + return -1; + + triton_ctx_schedule(&req->hnd, &req->timeout); + + triton_timer_del(&req->timeout); + triton_md_unregister_handler(&req->hnd); + + return 0; +} + |