diff options
Diffstat (limited to 'accel-pptpd')
-rw-r--r-- | accel-pptpd/accel-pptpd.conf | 4 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pptp.c | 1 | ||||
-rw-r--r-- | accel-pptpd/pwdb.c | 31 | ||||
-rw-r--r-- | accel-pptpd/pwdb.h | 6 | ||||
-rw-r--r-- | accel-pptpd/radius/CMakeLists.txt | 2 | ||||
-rw-r--r-- | accel-pptpd/radius/dict.c | 55 | ||||
-rw-r--r-- | accel-pptpd/radius/packet.c | 172 | ||||
-rw-r--r-- | accel-pptpd/radius/radius.c | 105 | ||||
-rw-r--r-- | accel-pptpd/radius/radius.h | 74 | ||||
-rw-r--r-- | accel-pptpd/radius/req.c | 216 | ||||
-rw-r--r-- | accel-pptpd/triton/CMakeLists.txt | 1 | ||||
-rw-r--r-- | accel-pptpd/triton/event.c | 103 | ||||
-rw-r--r-- | accel-pptpd/triton/triton.h | 4 | ||||
-rw-r--r-- | accel-pptpd/triton/triton_p.h | 9 |
14 files changed, 714 insertions, 69 deletions
diff --git a/accel-pptpd/accel-pptpd.conf b/accel-pptpd/accel-pptpd.conf index 9b635340..47480220 100644 --- a/accel-pptpd/accel-pptpd.conf +++ b/accel-pptpd/accel-pptpd.conf @@ -15,3 +15,7 @@ echo-interval=3 [radius] dictionary=dictionary +nas-identifier=pptp +nas-ip-address=192.168.10.20 +auth_server=127.0.0.1:1812,secret +acct_server=127.0.0.1:1812,secret diff --git a/accel-pptpd/ctrl/pptp.c b/accel-pptpd/ctrl/pptp.c index b503d85e..66c09786 100644 --- a/accel-pptpd/ctrl/pptp.c +++ b/accel-pptpd/ctrl/pptp.c @@ -529,7 +529,6 @@ static void __init pptp_init(void) addr.sin_port = htons (PPTP_PORT); addr.sin_addr.s_addr = htonl (INADDR_ANY); if (bind (serv.hnd.fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) { - perror("pptp: bind"); log_error("pptp: failed to bind socket: %s\n", strerror(errno)); close(serv.hnd.fd); return; diff --git a/accel-pptpd/pwdb.c b/accel-pptpd/pwdb.c index 8bde8fff..1b682a40 100644 --- a/accel-pptpd/pwdb.c +++ b/accel-pptpd/pwdb.c @@ -6,41 +6,26 @@ static LIST_HEAD(pwdb_handlers); -int __export pwdb_cleartext_check(struct ppp_t *ppp, const char *username,const char *password) +int __export pwdb_check(struct ppp_t *ppp, const char *username, int type, ...) { struct pwdb_t *pwdb; - int r = PWDB_NO_IMPL; - - list_for_each_entry(pwdb, &pwdb_handlers, entry) { - if (!pwdb->cleartext_check) - continue; - r = pwdb->cleartext_check(pwdb, ppp, username, password); - if (r == PWDB_NO_IMPL) - continue; - break; - } - - return r; -} -int __export pwdb_encrypted_check(struct ppp_t *ppp, const char *username, int type, ...) -{ - struct pwdb_t *pwdb; - int r = PWDB_NO_IMPL; + int r, res = PWDB_NO_IMPL; va_list args; va_start(args, type); list_for_each_entry(pwdb, &pwdb_handlers, entry) { - if (!pwdb->encrypted_check) + if (!pwdb->check) continue; - r = pwdb->encrypted_check(pwdb, ppp, username, type, args); + r = pwdb->check(pwdb, ppp, username, type, args); if (r == PWDB_NO_IMPL) continue; - break; + if (r == PWDB_SUCCESS) + return PWDB_SUCCESS; + res = r; } - return r; - + return res; } __export const char *pwdb_get_passwd(struct ppp_t *ppp, const char *username) { diff --git a/accel-pptpd/pwdb.h b/accel-pptpd/pwdb.h index 42f9133c..d3495435 100644 --- a/accel-pptpd/pwdb.h +++ b/accel-pptpd/pwdb.h @@ -13,13 +13,11 @@ struct ppp_t; struct pwdb_t { struct list_head entry; - int (*cleartext_check)(struct pwdb_t *, struct ppp_t *, const char *username, const char *password); - int (*encrypted_check)(struct pwdb_t *, struct ppp_t *, const char *username, int type, va_list args); + int (*check)(struct pwdb_t *, struct ppp_t *, const char *username, int type, va_list args); const char* (*get_passwd)(struct pwdb_t *, struct ppp_t *, const char *username); }; -int pwdb_cleartext_check(struct ppp_t *, const char *username,const char *password); -int pwdb_encrypted_check(struct ppp_t *, const char *username, int type, ...); +int pwdb_check(struct ppp_t *, const char *username, int type, ...); const char *pwdb_get_passwd(struct ppp_t *, const char *username); void pwdb_register(struct pwdb_t *); diff --git a/accel-pptpd/radius/CMakeLists.txt b/accel-pptpd/radius/CMakeLists.txt index a53491f6..17a85784 100644 --- a/accel-pptpd/radius/CMakeLists.txt +++ b/accel-pptpd/radius/CMakeLists.txt @@ -2,6 +2,8 @@ SET(target radius) SET(sources radius.c dict.c + req.c + packet.c ) ADD_LIBRARY(radius SHARED ${sources}) diff --git a/accel-pptpd/radius/dict.c b/accel-pptpd/radius/dict.c index 62a25cfd..992d7d40 100644 --- a/accel-pptpd/radius/dict.c +++ b/accel-pptpd/radius/dict.c @@ -7,23 +7,7 @@ #include "radius.h" #include "log.h" - -struct dict_value_t -{ - struct list_head entry; - rad_value_t val; - const char *name; -}; - -struct dict_attr_t -{ - struct list_head entry; - const char *name; - int id; - int type; - rad_value_t val; - struct list_head values; -}; +static struct rad_dict_t *dict; static char *skip_word(char *ptr) { @@ -78,26 +62,25 @@ struct dict_attr_t *find_attr(struct rad_dict_t *dict, const char *name) } #define BUF_SIZE 1024 -void *rad_load_dict(const char *fname) +int rad_dict_load(const char *fname) { FILE *f; char *buf, *ptr[3], *endptr; int n = 0; - struct rad_dict_t *dict; struct dict_attr_t *attr; struct dict_value_t *val; f = fopen(fname, "r"); if (!f) { log_error("radius: open dictioanary '%s': %s\n", fname, strerror(errno)); - return NULL; + return -1; } buf = malloc(BUF_SIZE); if (!buf) { log_error("radius: out of memory\n"); fclose(f); - return NULL; + return -1; } dict = malloc(sizeof(*dict)); @@ -105,7 +88,7 @@ void *rad_load_dict(const char *fname) log_error("radius: out of memory\n"); fclose(f); free(buf); - return NULL; + return -1; } INIT_LIST_HEAD(&dict->items); @@ -186,16 +169,16 @@ void *rad_load_dict(const char *fname) free(buf); fclose(f); - return dict; + return 0; out_err: - rad_free_dict(dict); + rad_dict_free(dict); free(buf); fclose(f); - return NULL; + return -1; } -void rad_free_dict(struct rad_dict_t *dict) +void rad_dict_free(struct rad_dict_t *dict) { struct dict_attr_t *attr; struct dict_value_t *val; @@ -217,3 +200,23 @@ void rad_free_dict(struct rad_dict_t *dict) free(dict); } +struct rad_dict_attr_t *rad_dict_find_attr(const char *name) +{ + struct rad_dict_attr_t *attr; + + list_for_each_entry(attr, &dict->items, entry) + if (!strcmp(attr->name, name)) + return attr; + + return NULL; +} +struct rad_dict_value_t *rad_dict_find_val(struct rad_dict_attr_t *attr, const char *name) +{ + struct rad_dict_value_t *val; + + list_for_each_entry(val, &attr->values, entry) + if (!strcmp(val->name, name)) + return val; + + return NULL; +} diff --git a/accel-pptpd/radius/packet.c b/accel-pptpd/radius/packet.c new file mode 100644 index 00000000..a22a611e --- /dev/null +++ b/accel-pptpd/radius/packet.c @@ -0,0 +1,172 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdin.h> + +#include "radius.h" + +static int urandom_fd; + +int rad_packet_build(struct rad_packet_t *pack) +{ + struct rad_req_attr_t *attr; + uint8_t *ptr; + + ptr = malloc(pack->len); + if (!ptr) { + log_error("radius:packet: out of memory\n"); + return -1; + } + + *ptr = pack->code; ptr++; + *ptr = pack->id; ptr++; + *(uint16_t*)ptr = pack->len; pt r+= 2; + while (1) { + if (read(erandom_fd, ptr, 16) != 16) { + if (errno == EINTR) + continue; + log_error("radius:packet:read urandom: %s\n", strerror(errno)); + goto out_err; + } + break; + } + ptr+=16; + + list_for_each_entry(attr, &pack->attrs, entry) { + *ptr = attr->attr.id; ptr++; + *ptr = attr->len; ptr++; + switch(attr->attr.type) { + case ATTR_TYPE_INTEGER: + *(uint32_t*)ptr = attr->val.integer; + break; + case ATTR_TYPE_STRING: + memcpy(ptr, attr->val.string); + break; + case ATTR_TYPE_IPADDR: + *(in_addr_t*)ptr = attr->val.ipaddr; + break; + case ATTR_TYPE_DATE: + *(uint32_t*)ptr = attr->val.date; + break; + default: + log_error("radius:packet: unknown attribute type\n"); + abort(); + } + ptr += attr->len; + } + + return 0; +} + +struct rad_packet_t *rad_packet_recv(int fd) +{ + struct rad_packet_t *pack; + struct rad_req_attr_t *attr; + struct rad_dict_attr_t *da; + uint8_t *ptr; + int n, type, len; + + pack = malloc(sizeof(*pack)); + if (!pack) { + log_error("radius:packet: out of memory\n"); + return NULL; + } + + memset(pack, 0, sizeof(*pack)); + INIT_LIST_HEAD(&pack->attrs); + + pack->buf = malloc(REQ_MAX_LENGTH); + if (!pack->buf) { + log_error("radius:packet: out of memory\n"); + free(pack); + return NULL; + } + + while (1) { + n = read(fd, pack->buf, REQ_MAX_LENGTH); + if (n < 0) { + if (errno == EINTR) + continue; + log_error("radius:packet:read: %s\n", strerror(errno)); + goto out_err; + } + break; + } + + if (n < 20) { + log_warn("radius:packet: short packed received (%i)\n", n); + goto out_err; + } + + ptr = (uint8_t *)pack->buf; + + pack->code = *ptr; ptr++; + pack->id = *ptr; ptr++; + pack->len = *(uint16_t*)ptr; ptr += 2; + + if (pack->len > n) { + log_warn("radius:packet: short packet received %i, expected %i\n", pack->len, n); + goto out_err; + } + + ptr += 16; + n -= 20; + + while (n>0) { + type = *ptr; ptr++; + len = *ptr; ptr++; + if (2 + len > n) { + log_error("radius:packet: too long attribute received (%i, %i)\n", type, len); + goto out_err; + } + da = rad_dict_find_attr_type(n); + if (da) { + attr = malloc(sizeof(*attr)); + if (!attr) { + log_error("radius:packet: out of memory\n"); + goto out_err; + } + attr->attr = da; + attr->type = type; + attr->len = len; + if (type == ATTR_TYPE_STRING) { + attr->val.string = malloc(len); + if (!attr->val.string) { + log_error("radius:packet: out of memory\n"); + free(attr); + goto out_err; + } + } else + memcpy(&attr->type.integer, ptr, 4); + list_add_tail(&attr->entry, &pack->attrs); + } else + log_warn("radius:packet: unknown attribute type received (%i)\n", type); + ptr += len; + n -= 2 + len; + } + + return pack; + +out_err: + rad_packet_free(pack); + return NULL; +} + +void rad_packet_free(struct rad_packet_t *pack) +{ + struct rad_req_attr_t *attr; + + if (pack->buf) + free(pack->buf); + + while(!list_empty(&pack->attrs)) { + attr = list_entry(pack->attrs.next, typeof(*attr), entry); + if (attr->attr.type == ATTR_TYPE_STRING) + free(attr->val.string); + list_del(&attr->entry); + free(attr); + } + + free(pack); +} diff --git a/accel-pptpd/radius/radius.c b/accel-pptpd/radius/radius.c index 10fef65f..4d020d5b 100644 --- a/accel-pptpd/radius/radius.c +++ b/accel-pptpd/radius/radius.c @@ -7,23 +7,105 @@ #include "pwdb.h" #include "radius.h" -struct radius_pd_t +static struct ppp_notified_t notified; + +static int check_pap(struct radius_pd_t *rpd, const char *username, va_list args) { - struct ppp_pd_t pd; - struct ppp_t *ppp; -}; + struct rad_req_t *req; + int i, r = PWDB_DENIED; + int id = va_arg(args, int); + const char *passwd = va_arg(args, const char *); -static struct ppp_notified_t notified; + req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST); + if (!req) + return PWDB_DENIED; + + if (rad_req_add_str(req, "User-Password", passwd, strlen(passwd))) + goto out; + + for(i = 0; i < max_try; i++) { + if (rad_req_send(req)) + goto out; + + if (rad_req_wait(req, timeout)) + goto out; + + if (req->answer) + break; + } + +out: + rad_req_free(req); + + return r; +} + +static int check_chap_md5(struct radius_pd_t *rpd, const char *username, va_list args) +{ + int id = va_arg(args, int); + const uint8_t *challenge = va_arg(args, const uint8_t *); +} -int cleartext_check(struct pwdb_t *pwdb, struct ppp_t *ppp, const char *username, const char *password) +static int check_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list args) { - return PWDB_NO_IMPL; + int id = va_arg(args, int); + const uint8_t *challenge = va_arg(args, const uint8_t *); + const uint8_t *lm_response = va_arg(args, const uint8_t *); + const uint8_t *nt_response = va_arg(args, const uint8_t *); + int flags = va_arg(args, int); } -int encrypted_check(struct pwdb_t *pwdb, struct ppp_t *ppp, const char *username, int type, va_list args) + +static int check_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list args) { - return PWDB_NO_IMPL; + int id = va_arg(args, int); + const uint8_t *challenge = va_arg(args, const uint8_t *); + const uint8_t *peer_challenge = va_arg(args, const uint8_t *); + const uint8_t *response = va_arg(args, const uint8_t *); + int flags = va_arg(args, int); + uint8_t *authenticator = va_arg(args, uint8_t *); } +static int check(struct pwdb_t *pwdb, struct ppp_t *ppp, const char *username, int type, va_list _args) +{ + int r = PWDB_NO_IMPL; + va_list args; + int chap_type; + struct ppp_pd_t *pd; + struct radius_pd_t *rpd = NULL; + + list_for_each_entry(pd, &ppp->pd_list, entry) { + if (pd->key == ¬ified) { + rpd = container_of(pd, typeof(*rpd), pd); + break; + } + } + + va_copy(args, _args); + + switch(type) { + case PPP_PAP: + r = check_pap(rpd, username, args); + break; + case PPP_CHAP: + chap_type = va_arg(args, int); + switch(chap_type) { + case 0x05: + r = check_chap_md5(rpd, username, args); + break; + case 0x80: + r = check_mschap_v1(rpd, username, args); + break; + case 0x81: + r = check_mschap_v2(rpd, username, args); + break; + } + break; + } + + va_end(args); + + return r; +} static void ppp_started(struct ppp_notified_t *n, struct ppp_t *ppp) { @@ -50,9 +132,8 @@ static void ppp_finished(struct ppp_notified_t *n, struct ppp_t *ppp) } } -struct pwdb_t pwdb = { - .cleartext_check = cleartext_check, - .encrypted_check = encrypted_check, +static struct pwdb_t pwdb = { + .check = check, }; static struct ppp_notified_t notified = { diff --git a/accel-pptpd/radius/radius.h b/accel-pptpd/radius/radius.h index aac1cd00..3fe78621 100644 --- a/accel-pptpd/radius/radius.h +++ b/accel-pptpd/radius/radius.h @@ -2,12 +2,23 @@ #define __RADIUS_H #include <netinet/in.h> +#include "triton.h" + +#define REQ_LENGTH_MAX 4096 #define ATTR_TYPE_INTEGER 0 #define ATTR_TYPE_STRING 1 #define ATTR_TYPE_DATE 2 #define ATTR_TYPE_IPADDR 3 +#define CODE_ACCESS_REQUEST 1 + +struct radius_pd_t +{ + struct ppp_pd_t pd; + struct ppp_t *ppp; +}; + typedef union { int integer; @@ -21,8 +32,67 @@ struct rad_dict_t struct list_head items; }; -void *rad_load_dict(const char *fname); -void rad_free_dict(struct rad_dict_t *dict); +struct rad_dict_value_t +{ + struct list_head entry; + rad_value_t val; + const char *name; +}; + +struct rad_dict_attr_t +{ + struct list_head entry; + const char *name; + int id; + int type; + struct list_head values; +}; + +struct rad_req_attr_t +{ + struct list_head entry; + struct rad_dict_attr_t *attr; + //struct rad_dict_value_t *val; + rad_value_t val; +}; + +struct rad_packet_t +{ + int code; + int id; + struct list_head attrs; + void *buf; +}; +struct rad_req_t +{ + struct triton_md_handler_t hnd; + struct triton_timer_t timeout; + struct rad_packet_t pack; + struct rad_packet_t *answer; + const char *server_host; + int server_port; + + struct radius_pd_t *rpd; +}; + + +int rad_dict_load(const char *fname); +void rad_dict_free(struct rad_dict_t *dict); +struct rad_dict_attr_t *rad_dict_find_attr(const char *name); +struct rad_dict_attr_t *rad_dict_find_attr_type(int type); +struct rad_dict_value_t *rad_dict_find_val(struct rad_dict_attr_t *, const char *name); + +struct rad_req_t *rad_rec_alloc(struct radius_pd_t *rpd, int code); +void rad_rec_free(struct rad_req_t *); +int rad_req_send(struct rad_req_t *); +int rad_req_add_int(struct rad_req_t *req, const char *name, int val); +int rad_req_add_val(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 rad_packet_build(struct rad_packet_t *pack); +struct rad_packet_t *rad_packet_recv(int fd); +void rad_packet_free(struct rad_packet_t *); + #endif 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; +} + diff --git a/accel-pptpd/triton/CMakeLists.txt b/accel-pptpd/triton/CMakeLists.txt index fd6b5182..41339d97 100644 --- a/accel-pptpd/triton/CMakeLists.txt +++ b/accel-pptpd/triton/CMakeLists.txt @@ -7,6 +7,7 @@ SET(sources_c loader.c log.c mempool.c + event.c ) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) ADD_DEFINITIONS("-DUSE_SPINLOCK") diff --git a/accel-pptpd/triton/event.c b/accel-pptpd/triton/event.c new file mode 100644 index 00000000..17483ec7 --- /dev/null +++ b/accel-pptpd/triton/event.c @@ -0,0 +1,103 @@ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "triton_p.h" + +static int max_events = 1024; +static struct _triton_event_t **events; + +struct event_handler_t +{ + struct list_head entry; + triton_event_func func; +}; + +int event_init(void) +{ + events = malloc(max_events * sizeof(void *)); + if (!events) { + fprintf(stderr,"event:cann't allocate memory\n"); + return -1; + } + + memset(events, 0, max_events * sizeof(void *)); + + return 0; +} + +int triton_event_register_handler(int ev_id, triton_event_func func) +{ + struct _triton_event_t *ev; + struct event_handler_t *h; + + if (ev_id >= max_events) + return -1; + + ev = events[ev_id]; + if (!ev) { + ev = malloc(sizeof(*ev)); + if (!ev) { + triton_log_error("event: out of memory\n"); + return -1; + } + INIT_LIST_HEAD(&ev->handlers); + events[ev_id] = ev; + } + + h = malloc(sizeof(*h)); + if (!h) { + triton_log_error("event: out of memory\n"); + return -1; + } + + h->func = func; + list_add_tail(&h->entry, &ev->handlers); + + return 0; +} + +/*int triton_event_unregister_handler(int ev_id, triton_event_func func) +{ + struct _triton_event_t *ev; + struct event_handler_t *h; + + if (ev_id >= max_events) + return -1; + + ev = events[ev_id]; + if (!ev) { + return -1; + } + + list_for_each_entry(h, &ev->handlers, entry) { + if (h->func == func) { + if (ev->in_progress) + h->func = NULL; + else { + list_del(&h->entry); + free(h); + } + return 0; + } + } + + return -1; +}*/ + +void triton_event_fire(int ev_id, void *arg) +{ + struct _triton_event_t *ev; + struct event_handler_t *h; + + if (ev_id >= max_events) + return; + + ev = events[ev_id]; + if (!ev) + return; + + list_for_each_entry(h, &ev->handlers, entry) + h->func(arg); +} + diff --git a/accel-pptpd/triton/triton.h b/accel-pptpd/triton/triton.h index 1009d67a..d130d86e 100644 --- a/accel-pptpd/triton/triton.h +++ b/accel-pptpd/triton/triton.h @@ -55,6 +55,10 @@ int triton_timer_add(struct triton_ctx_t *ctx, struct triton_timer_t*,int abs_ti int triton_timer_mod(struct triton_timer_t *,int abs_time); void triton_timer_del(struct triton_timer_t *); +typedef void (*triton_event_func)(void *); +int triton_event_register_handler(int ev_id, triton_event_func func); +void triton_event_fire(int ev_id, void *arg); + struct conf_sect_t *conf_get_section(const char *name); char *conf_get_opt(const char *sect, const char *name); diff --git a/accel-pptpd/triton/triton_p.h b/accel-pptpd/triton/triton_p.h index 0f7e7160..c31efd6e 100644 --- a/accel-pptpd/triton/triton_p.h +++ b/accel-pptpd/triton/triton_p.h @@ -57,6 +57,11 @@ struct _triton_timer_t struct triton_timer_t *ud; }; +struct _triton_event_t +{ + struct list_head handlers; +}; + typedef void * mempool_t; mempool_t *mempool_create(int size); void *mempool_alloc(mempool_t*); @@ -64,9 +69,11 @@ void mempool_free(void*); int log_init(void); int md_init(); +int timer_init(); +int event_init(); + void md_run(); void md_terminate(); -int timer_init(); void timer_run(); void timer_terminate(); struct triton_ctx_t *default_ctx; |