summaryrefslogtreecommitdiff
path: root/accel-pptpd
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-09-06 18:27:02 +0400
committerKozlov Dmitry <dima@server>2010-09-06 18:27:02 +0400
commit45243dd2f2be49cd91be1dc28932e6c9040db6a1 (patch)
tree652896ecd889d58d4a3c9d3232c85ff831b31699 /accel-pptpd
parentaf5a96e2d04056b065a36ecbd140a16d0685c7e6 (diff)
downloadaccel-ppp-45243dd2f2be49cd91be1dc28932e6c9040db6a1.tar.gz
accel-ppp-45243dd2f2be49cd91be1dc28932e6c9040db6a1.zip
working on radius module
Diffstat (limited to 'accel-pptpd')
-rw-r--r--accel-pptpd/accel-pptpd.conf4
-rw-r--r--accel-pptpd/ctrl/pptp.c1
-rw-r--r--accel-pptpd/pwdb.c31
-rw-r--r--accel-pptpd/pwdb.h6
-rw-r--r--accel-pptpd/radius/CMakeLists.txt2
-rw-r--r--accel-pptpd/radius/dict.c55
-rw-r--r--accel-pptpd/radius/packet.c172
-rw-r--r--accel-pptpd/radius/radius.c105
-rw-r--r--accel-pptpd/radius/radius.h74
-rw-r--r--accel-pptpd/radius/req.c216
-rw-r--r--accel-pptpd/triton/CMakeLists.txt1
-rw-r--r--accel-pptpd/triton/event.c103
-rw-r--r--accel-pptpd/triton/triton.h4
-rw-r--r--accel-pptpd/triton/triton_p.h9
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 == &notified) {
+ 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;