diff options
Diffstat (limited to 'accel-pptpd/radius/req.c')
-rw-r--r-- | accel-pptpd/radius/req.c | 145 |
1 files changed, 101 insertions, 44 deletions
diff --git a/accel-pptpd/radius/req.c b/accel-pptpd/radius/req.c index ae761547..cc59a431 100644 --- a/accel-pptpd/radius/req.c +++ b/accel-pptpd/radius/req.c @@ -11,11 +11,12 @@ #include "log.h" #include "radius.h" +static int urandom_fd; static int rad_req_read(struct triton_md_handler_t *h); static void rad_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 *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *username) { struct rad_req_t *req = malloc(sizeof(*req)); @@ -23,26 +24,37 @@ struct rad_req_t *rad_rec_alloc(struct radius_pd_t *rpd, int code, const char *u 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->timeout.expire = rad_req_timeout; - if (rad_req_add_str(req, "User-Name", username, strlen(username))) + while (1) { + if (read(urandom_fd, req->RA, 16) != 16) { + if (errno == EINTR) + continue; + log_error("radius:req:read urandom: %s\n", strerror(errno)); + goto out_err; + } + break; + } + + req->pack = rad_packet_alloc(code); + if (!req->pack) + goto out_err; + + if (rad_req_add_str(req, "User-Name", username, strlen(username), 1)) goto out_err; if (conf_nas_identifier) - if (rad_req_add_str(req, "NAS-Identifier", conf_nas_identifier, strlen(conf_nas_identifier))) + if (rad_req_add_str(req, "NAS-Identifier", conf_nas_identifier, strlen(conf_nas_identifier), 1)) goto out_err; if (rad_req_add_int(req, "NAS-Port-Id", rpd->ppp->unit_idx)) goto out_err; - if (rad_req_add_str(req, "NAS-Port-Type", "Sync", 4)) + if (rad_req_add_val(req, "NAS-Port-Type", "Sync", 4)) goto out_err; - if (rad_req_add_str(req, "Service-Type", "Framed-User", 11)) + if (rad_req_add_val(req, "Service-Type", "Framed-User", 4)) goto out_err; - if (rad_req_add_str(req, "Framed-Protocol", "PPP", 3)) + if (rad_req_add_val(req, "Framed-Protocol", "PPP", 4)) goto out_err; return req; @@ -52,9 +64,15 @@ out_err: return NULL; } -void rad_rec_free(struct rad_req_t *req) +void rad_req_free(struct rad_req_t *req) { - + if (req->hnd.fd >= 0 ) + close(req->hnd.fd); + if (req->pack) + rad_packet_free(req->pack); + if (req->reply) + rad_packet_free(req->reply); + free(req); } int rad_req_send(struct rad_req_t *req) @@ -63,22 +81,24 @@ int rad_req_send(struct rad_req_t *req) int n; if (req->hnd.fd == -1) { - req->hnd.fd = socket(PF_INET, SOCK_DGRAM ,0); - if (!req->hnd.fd) { + req->hnd.fd = socket(PF_INET, SOCK_DGRAM, 0); + if (req->hnd.fd < 0) { log_error("radius:socket: %s\n", strerror(errno)); return -1; } + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + if (conf_nas_ip_address) { - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(inet_addr(conf_nas_ip_address)); + addr.sin_addr.s_addr = inet_addr(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(inet_addr(req->server_name)); + addr.sin_addr.s_addr = inet_addr(req->server_name); addr.sin_port = htons(req->server_port); if (connect(req->hnd.fd, (struct sockaddr *) &addr, sizeof(addr))) { @@ -91,28 +111,32 @@ int rad_req_send(struct rad_req_t *req) goto out_err; } - if (rad_packet_build(&req->pack)) + if (rad_packet_build(req->pack, req->RA)) goto out_err; } + if (conf_verbose) { + log_debug("send "); + rad_packet_print(req->pack, log_debug); + } + while (1) { - n = write(req->hnd.fd, req->pack.buf, req->pack.len); + n = write(req->hnd.fd, req->pack->buf, req->pack->len); + //n = sendto(req->hnd.fd, req->pack->buf, req->pack->len, 0, &addr, sizeof(addr)); 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; + goto out_err; + } else if (n != req->pack->len) { + log_error("radius:write: short write %i, excpected %i\n", n, req->pack->len); + goto out_err; } break; } return 0; -out_err_free_pack: - rad_packet_free(&req->pack); out_err: close(req->hnd.fd); req->hnd.fd = -1; @@ -124,7 +148,7 @@ 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->pack.len + 2 + 4 >= REQ_LENGTH_MAX) + if (req->pack->len + 2 + 4 >= REQ_LENGTH_MAX) return -1; attr = rad_dict_find_attr(name); @@ -138,18 +162,19 @@ int rad_req_add_int(struct rad_req_t *req, const char *name, int val) ra->attr = attr; ra->len = 4; ra->val.integer = val; - list_add_tail(&ra->entry, &req->pack.attrs); - req->pack.len += 2 + 4; + ra->printable = 1; + list_add_tail(&ra->entry, &req->pack->attrs); + req->pack->len += 2 + 4; return 0; } -int rad_req_add_str(struct rad_req_t *req, const char *name, const char *val, int len) +int rad_req_add_str(struct rad_req_t *req, const char *name, const char *val, int len, int printable) { struct rad_req_attr_t *ra; struct rad_dict_attr_t *attr; - if (req->pack.len + 2 + len >= REQ_LENGTH_MAX) + if (req->pack->len + 2 + len >= REQ_LENGTH_MAX) return -1; attr = rad_dict_find_attr(name); @@ -157,14 +182,24 @@ int rad_req_add_str(struct rad_req_t *req, const char *name, const char *val, in return -1; ra = malloc(sizeof(*ra)); - if (!ra) + if (!ra) { + log_error("radius: aout of memory\n"); return -1; + } ra->attr = attr; ra->len = len; - ra->val.string = strdup(val); - list_add_tail(&ra->entry, &req->pack.attrs); - req->pack.len += 2 + len; + ra->val.string = malloc(len+1); + if (!ra->val.string) { + log_error("radius: out of memory\n"); + free(ra); + return -1; + } + memcpy(ra->val.string, val, len); + ra->val.string[len] = 0; + ra->printable = printable; + list_add_tail(&ra->entry, &req->pack->attrs); + req->pack->len += 2 + len; return 0; } @@ -175,14 +210,14 @@ int rad_req_add_val(struct rad_req_t *req, const char *name, const char *val, in struct rad_dict_attr_t *attr; struct rad_dict_value_t *v; - if (req->pack.len + 2 + len >= REQ_LENGTH_MAX) + if (req->pack->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); + v = rad_dict_find_val_name(attr, val); if (!v) return -1; @@ -193,39 +228,61 @@ int rad_req_add_val(struct rad_req_t *req, const char *name, const char *val, in ra->attr = attr; ra->len = len; ra->val = v->val; - list_add_tail(&ra->entry, &req->pack.attrs); - req->pack.len += 2 + len; + ra->printable = 1; + list_add_tail(&ra->entry, &req->pack->attrs); + req->pack->len += 2 + len; return 0; } +static void req_wakeup(struct rad_req_t *req) +{ + triton_context_wakeup(req->rpd->ppp->ctrl->ctx); + triton_timer_del(&req->timeout); + triton_md_unregister_handler(&req->hnd); + triton_context_unregister(&req->ctx); +} static int rad_req_read(struct triton_md_handler_t *h) { struct rad_req_t *req = container_of(h, typeof(*req), hnd); req->reply = rad_packet_recv(h->fd); - + req_wakeup(req); + return 0; } static void rad_req_timeout(struct triton_timer_t *t) { + struct rad_req_t *req = container_of(t, typeof(*req), timeout); + + req_wakeup(req); } int rad_req_wait(struct rad_req_t *req, int timeout) { - triton_md_register_handler(req->rpd->ppp->ctrl->ctx, &req->hnd); + triton_context_register(&req->ctx); + triton_md_register_handler(&req->ctx, &req->hnd); if (triton_md_enable_handler(&req->hnd, MD_MODE_READ)) return -1; req->timeout.period = timeout * 1000; - if (triton_timer_add(req->rpd->ppp->ctrl->ctx, &req->timeout, 0)) + if (triton_timer_add(&req->ctx, &req->timeout, 0)) return -1; - triton_ctx_schedule(&req->hnd, &req->timeout); - - triton_timer_del(&req->timeout); - triton_md_unregister_handler(&req->hnd); + triton_context_schedule(req->rpd->ppp->ctrl->ctx); + if (conf_verbose && req->reply) { + log_debug("recv "); + rad_packet_print(req->reply, log_debug); + } return 0; } +void __init req_init(void) +{ + urandom_fd = open("/dev/urandom", O_RDONLY); + if (!urandom_fd) { + perror("radius:req: open /dev/urandom"); + _exit(EXIT_FAILURE); + } +} |