summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-09-08 15:51:29 +0400
committerKozlov Dmitry <dima@server>2010-09-08 15:51:29 +0400
commit4c6469a9fd820db713251a645ac2499782f796ed (patch)
treefd7c4926eb2a3e2aa047bd14da429f3d6a5f8e6f
parentec759f72fcf7d517fdfe8d043c75d0218363bc78 (diff)
downloadaccel-ppp-4c6469a9fd820db713251a645ac2499782f796ed.tar.gz
accel-ppp-4c6469a9fd820db713251a645ac2499782f796ed.zip
radius: implemented packet exchange
radius: implemented PAP authorization radius: implemented IP assigning triton: implemented userspace context switching and other stuff
-rw-r--r--accel-pptpd/accel-pptpd.conf13
-rw-r--r--accel-pptpd/auth/auth_chap_md5.c4
-rw-r--r--accel-pptpd/auth/auth_mschap_v1.c4
-rw-r--r--accel-pptpd/auth/auth_mschap_v2.c4
-rw-r--r--accel-pptpd/auth/auth_pap.c25
-rw-r--r--accel-pptpd/ctrl/pptp.c14
-rw-r--r--accel-pptpd/ipdb.c25
-rw-r--r--accel-pptpd/ipdb.h15
-rw-r--r--accel-pptpd/ppp/ipcp_opt_ipaddr.c10
-rw-r--r--accel-pptpd/ppp/ppp.c18
-rw-r--r--accel-pptpd/ppp/ppp.h6
-rw-r--r--accel-pptpd/ppp/ppp_auth.c6
-rw-r--r--accel-pptpd/ppp/ppp_ccp.c29
-rw-r--r--accel-pptpd/ppp/ppp_fsm.c14
-rw-r--r--accel-pptpd/ppp/ppp_fsm.h6
-rw-r--r--accel-pptpd/ppp/ppp_ipcp.c53
-rw-r--r--accel-pptpd/ppp/ppp_ipcp.h1
-rw-r--r--accel-pptpd/ppp/ppp_lcp.c35
-rw-r--r--accel-pptpd/ppp/ppp_lcp.h1
-rw-r--r--accel-pptpd/pwdb.c4
-rw-r--r--accel-pptpd/pwdb.h4
-rw-r--r--accel-pptpd/radius/dict.c26
-rw-r--r--accel-pptpd/radius/packet.c169
-rw-r--r--accel-pptpd/radius/radius.c202
-rw-r--r--accel-pptpd/radius/radius.h26
-rw-r--r--accel-pptpd/radius/req.c145
-rw-r--r--accel-pptpd/triton/md.c6
-rw-r--r--accel-pptpd/triton/timer.c6
-rw-r--r--accel-pptpd/triton/triton.c172
-rw-r--r--accel-pptpd/triton/triton.h17
-rw-r--r--accel-pptpd/triton/triton_p.h27
31 files changed, 803 insertions, 284 deletions
diff --git a/accel-pptpd/accel-pptpd.conf b/accel-pptpd/accel-pptpd.conf
index 47480220..ece04f2f 100644
--- a/accel-pptpd/accel-pptpd.conf
+++ b/accel-pptpd/accel-pptpd.conf
@@ -1,11 +1,14 @@
[modules]
./libpptp.so
-./libauth_mschap_v2.so
+./libauth_pap.so
./libradius.so
[core]
log-error=/dev/stderr
+[ppp]
+verbose=1
+
[lcp]
echo-interval=10
echo-failure=3
@@ -16,6 +19,8 @@ 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
+nas-ip-address=127.0.0.1
+gw-ip-address=192.168.100.100
+auth_server=127.0.0.1:1812,testing123
+acct_server=127.0.0.1:1813,secret
+verbose=1
diff --git a/accel-pptpd/auth/auth_chap_md5.c b/accel-pptpd/auth/auth_chap_md5.c
index 5577794f..de2f4716 100644
--- a/accel-pptpd/auth/auth_chap_md5.c
+++ b/accel-pptpd/auth/auth_chap_md5.c
@@ -220,8 +220,8 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
ppp_terminate(ad->ppp, 0);
}
- name=strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
- passwd=pwdb_get_passwd(ad->ppp,name);
+ name = strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
+ passwd = pwdb_get_passwd(ad->ppp,name);
if (!passwd)
{
free(name);
diff --git a/accel-pptpd/auth/auth_mschap_v1.c b/accel-pptpd/auth/auth_mschap_v1.c
index 1cf5eb8b..595fb15e 100644
--- a/accel-pptpd/auth/auth_mschap_v1.c
+++ b/accel-pptpd/auth/auth_mschap_v1.c
@@ -282,8 +282,8 @@ static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response
char *name;
int i;
- name=strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
- passwd=pwdb_get_passwd(ad->ppp,name);
+ name = strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
+ passwd = pwdb_get_passwd(ad->ppp,name);
if (!passwd)
{
free(name);
diff --git a/accel-pptpd/auth/auth_mschap_v2.c b/accel-pptpd/auth/auth_mschap_v2.c
index 502f3686..01127cf7 100644
--- a/accel-pptpd/auth/auth_mschap_v2.c
+++ b/accel-pptpd/auth/auth_mschap_v2.c
@@ -193,8 +193,8 @@ static int generate_response(struct chap_auth_data_t *ad, struct chap_response_t
uint8_t c_hash[SHA_DIGEST_LENGTH];
int i;
- name=strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
- passwd=pwdb_get_passwd(ad->ppp,name);
+ name = strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
+ passwd = pwdb_get_passwd(ad->ppp,name);
if (!passwd)
{
free(name);
diff --git a/accel-pptpd/auth/auth_pap.c b/accel-pptpd/auth/auth_pap.c
index 92ddef52..7337468a 100644
--- a/accel-pptpd/auth/auth_pap.c
+++ b/accel-pptpd/auth/auth_pap.c
@@ -125,7 +125,7 @@ static void pap_send_ack(struct pap_auth_data_t *p, int id)
ppp_chan_send(p->ppp,msg,ntohs(msg->hdr.len)+2);
}
-static void pap_send_nak(struct pap_auth_data_t *p,int id)
+static void pap_send_nak(struct pap_auth_data_t *p, int id)
{
uint8_t buf[128];
struct pap_ack_t *msg=(struct pap_ack_t*)buf;
@@ -143,9 +143,10 @@ static void pap_send_nak(struct pap_auth_data_t *p,int id)
static int pap_recv_req(struct pap_auth_data_t *p,struct pap_hdr_t *hdr)
{
- int ret;
+ int ret, r;
char *peer_id;
char *passwd;
+ const char *passwd2;
int peer_id_len;
int passwd_len;
uint8_t *ptr=(uint8_t*)(hdr+1);
@@ -170,17 +171,23 @@ static int pap_recv_req(struct pap_auth_data_t *p,struct pap_hdr_t *hdr)
peer_id=strndup((const char*)peer_id,peer_id_len);
passwd=strndup((const char*)ptr,passwd_len);
- if (pwdb_check(p->ppp,peer_id,passwd))
- {
+ r = pwdb_check(p->ppp, peer_id, PPP_PAP, passwd);
+ if (r == PWDB_NO_IMPL) {
+ passwd2 = pwdb_get_passwd(p->ppp, peer_id);
+ if (!passwd2 || strcmp(passwd2, passwd))
+ r = PWDB_DENIED;
+ else
+ r = PWDB_SUCCESS;
+ }
+ if (r == PWDB_DENIED) {
log_warn("PAP: authentication error\n");
- pap_send_nak(p,hdr->id);
+ pap_send_nak(p, hdr->id);
auth_failed(p->ppp);
ret=-1;
- }else
- {
- pap_send_ack(p,hdr->id);
+ } else {
+ pap_send_ack(p, hdr->id);
auth_successed(p->ppp);
- ret=0;
+ ret = 0;
}
free(peer_id);
diff --git a/accel-pptpd/ctrl/pptp.c b/accel-pptpd/ctrl/pptp.c
index 66c09786..3a3c2427 100644
--- a/accel-pptpd/ctrl/pptp.c
+++ b/accel-pptpd/ctrl/pptp.c
@@ -27,7 +27,7 @@
struct pptp_conn_t
{
- struct triton_ctx_t ctx;
+ struct triton_context_t ctx;
struct triton_md_handler_t hnd;
struct triton_timer_t timeout_timer;
struct triton_timer_t echo_timer;
@@ -73,7 +73,7 @@ static void disconnect(struct pptp_conn_t *conn)
ppp_terminate(&conn->ppp, 1);
}
- triton_unregister_ctx(&conn->ctx);
+ triton_context_unregister(&conn->ctx);
free(conn->in_buf);
free(conn->out_buf);
@@ -425,7 +425,7 @@ static void pptp_timeout(struct triton_timer_t *t)
struct pptp_conn_t *conn = container_of(t, typeof(*conn), timeout_timer);
disconnect(conn);
}
-static void pptp_close(struct triton_ctx_t *ctx)
+static void pptp_close(struct triton_context_t *ctx)
{
struct pptp_conn_t *conn = container_of(ctx, typeof(*conn), ctx);
if (conn->state == STATE_PPP) {
@@ -455,7 +455,7 @@ static void ppp_finished(struct ppp_t *ppp)
struct pptp_serv_t
{
- struct triton_ctx_t ctx;
+ struct triton_context_t ctx;
struct triton_md_handler_t hnd;
};
@@ -495,14 +495,14 @@ static int pptp_connect(struct triton_md_handler_t *h)
conn->timeout_timer.period = conf_timeout * 1000;
conn->echo_timer.expire = pptp_send_echo;
- triton_register_ctx(&conn->ctx);
+ triton_context_register(&conn->ctx);
triton_md_register_handler(&conn->ctx, &conn->hnd);
triton_md_enable_handler(&conn->hnd,MD_MODE_READ);
triton_timer_add(&conn->ctx, &conn->timeout_timer, 0);
}
return 0;
}
-static void pptp_serv_close(struct triton_ctx_t *ctx)
+static void pptp_serv_close(struct triton_context_t *ctx)
{
struct pptp_serv_t *s=container_of(ctx,typeof(*s),ctx);
triton_md_unregister_handler(&s->hnd);
@@ -546,7 +546,7 @@ static void __init pptp_init(void)
return;
}
- triton_register_ctx(&serv.ctx);
+ triton_context_register(&serv.ctx);
triton_md_register_handler(&serv.ctx, &serv.hnd);
triton_md_enable_handler(&serv.hnd, MD_MODE_READ);
diff --git a/accel-pptpd/ipdb.c b/accel-pptpd/ipdb.c
index 8ac86cb6..7b679dc7 100644
--- a/accel-pptpd/ipdb.c
+++ b/accel-pptpd/ipdb.c
@@ -1,11 +1,28 @@
#include "triton.h"
#include "ipdb.h"
-int __export ipdb_get(in_addr_t *addr, in_addr_t *peer_addr)
+static LIST_HEAD(ipdb_handlers);
+
+int __export ipdb_get(struct ppp_t *ppp, in_addr_t *addr, in_addr_t *peer_addr)
{
- *addr=inet_addr("192.168.200.100");
- *peer_addr=inet_addr("192.168.200.200");
+ struct ipdb_t *ipdb;
+
+ list_for_each_entry(ipdb, &ipdb_handlers, entry)
+ if (!ipdb->get(ppp, addr, peer_addr))
+ return 0;
- return 0;
+ return -1;
}
+void __export ipdb_put(struct ppp_t *ppp, in_addr_t addr, in_addr_t peer_addr)
+{
+ struct ipdb_t *ipdb;
+ list_for_each_entry(ipdb, &ipdb_handlers, entry)
+ if (ipdb->put)
+ ipdb->put(ppp, addr, peer_addr);
+}
+
+void __export ipdb_register(struct ipdb_t *ipdb)
+{
+ list_add_tail(&ipdb->entry, &ipdb_handlers);
+}
diff --git a/accel-pptpd/ipdb.h b/accel-pptpd/ipdb.h
index ed7df6b3..6703a48b 100644
--- a/accel-pptpd/ipdb.h
+++ b/accel-pptpd/ipdb.h
@@ -3,7 +3,20 @@
#include <netinet/in.h>
-int ipdb_get(in_addr_t *addr, in_addr_t *peer_addr);
+#include "ppp.h"
+#include "list.h"
+
+struct ipdb_t
+{
+ struct list_head entry;
+ int (*get)(struct ppp_t *ppp, in_addr_t *addr, in_addr_t *peer_addr);
+ void (*put)(struct ppp_t *ppp, in_addr_t addr, in_addr_t peer_addr);
+};
+
+int ipdb_get(struct ppp_t *ppp, in_addr_t *addr, in_addr_t *peer_addr);
+void ipdb_put(struct ppp_t *ppp, in_addr_t addr, in_addr_t peer_addr);
+
+void ipdb_register(struct ipdb_t *);
#endif
diff --git a/accel-pptpd/ppp/ipcp_opt_ipaddr.c b/accel-pptpd/ppp/ipcp_opt_ipaddr.c
index 2fa92519..ddfb3d20 100644
--- a/accel-pptpd/ppp/ipcp_opt_ipaddr.c
+++ b/accel-pptpd/ppp/ipcp_opt_ipaddr.c
@@ -40,7 +40,6 @@ static struct ipcp_option_t *ipaddr_init(struct ppp_ipcp_t *ipcp)
{
struct ipaddr_option_t *ipaddr_opt=malloc(sizeof(*ipaddr_opt));
memset(ipaddr_opt,0,sizeof(*ipaddr_opt));
- ipdb_get(&ipaddr_opt->addr,&ipaddr_opt->peer_addr);
ipaddr_opt->opt.id=CI_ADDR;
ipaddr_opt->opt.len=6;
@@ -51,6 +50,9 @@ static void ipaddr_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt)
{
struct ipaddr_option_t *ipaddr_opt=container_of(opt,typeof(*ipaddr_opt),opt);
+ if (ipaddr_opt->peer_addr)
+ ipdb_put(ipcp->ppp, ipaddr_opt->addr, ipaddr_opt->peer_addr);
+
free(ipaddr_opt);
}
@@ -58,6 +60,12 @@ static int ipaddr_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *o
{
struct ipaddr_option_t *ipaddr_opt=container_of(opt,typeof(*ipaddr_opt),opt);
struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr;
+
+ if (!ipaddr_opt->addr && ipdb_get(ipcp->ppp, &ipaddr_opt->addr, &ipaddr_opt->peer_addr)) {
+ log_warn("ppp:ipcp: no free IP address\n");
+ return -1;
+ }
+
opt32->hdr.id=CI_ADDR;
opt32->hdr.len=6;
opt32->val=ipaddr_opt->addr;
diff --git a/accel-pptpd/ppp/ppp.c b/accel-pptpd/ppp/ppp.c
index 4ad8221b..247f8198 100644
--- a/accel-pptpd/ppp/ppp.c
+++ b/accel-pptpd/ppp/ppp.c
@@ -17,6 +17,8 @@
#include "ppp_fsm.h"
#include "log.h"
+int conf_ppp_verbose;
+
static LIST_HEAD(layers);
int sock_fd;
@@ -302,7 +304,10 @@ void __export ppp_layer_started(struct ppp_t *ppp, struct ppp_layer_data_t *d)
list_for_each_entry(d,&n->items,entry)
{
d->starting=1;
- d->layer->start(d);
+ if (d->layer->start(d)) {
+ ppp_terminate(ppp, 0);
+ return;
+ }
}
}
}
@@ -464,7 +469,10 @@ static void start_first_layer(struct ppp_t *ppp)
list_for_each_entry(d,&n->items,entry)
{
d->starting=1;
- d->layer->start(d);
+ if (d->layer->start(d)) {
+ ppp_terminate(ppp, 0);
+ return;
+ }
}
}
@@ -487,9 +495,15 @@ struct ppp_layer_data_t *ppp_find_layer_data(struct ppp_t *ppp, struct ppp_layer
static void __init ppp_init(void)
{
+ char *opt;
+
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0) {
perror("socket");
_exit(EXIT_FAILURE);
}
+
+ opt = conf_get_opt("ppp", "verbose");
+ if (opt && atoi(opt) > 0)
+ conf_ppp_verbose = 1;
}
diff --git a/accel-pptpd/ppp/ppp.h b/accel-pptpd/ppp/ppp.h
index da2fb97c..e287b7b1 100644
--- a/accel-pptpd/ppp/ppp.h
+++ b/accel-pptpd/ppp/ppp.h
@@ -45,7 +45,7 @@ struct ppp_t;
struct ppp_ctrl_t
{
- struct triton_ctx_t *ctx;
+ struct triton_context_t *ctx;
void (*started)(struct ppp_t*);
void (*finished)(struct ppp_t*);
};
@@ -111,7 +111,7 @@ struct ppp_layer_t
{
struct list_head entry;
struct ppp_layer_data_t *(*init)(struct ppp_t *);
- void (*start)(struct ppp_layer_data_t*);
+ int (*start)(struct ppp_layer_data_t*);
void (*finish)(struct ppp_layer_data_t*);
void (*free)(struct ppp_layer_data_t *);
};
@@ -146,5 +146,7 @@ void ppp_unregister_notified(struct ppp_notified_t *);
void ppp_notify_started(struct ppp_t *ppp);
void ppp_notify_finished(struct ppp_t *ppp);
+extern int conf_ppp_verbose;
+
extern int sock_fd; // internet socket for ioctls
#endif
diff --git a/accel-pptpd/ppp/ppp_auth.c b/accel-pptpd/ppp/ppp_auth.c
index 32f63d5b..b767fdbd 100644
--- a/accel-pptpd/ppp/ppp_auth.c
+++ b/accel-pptpd/ppp/ppp_auth.c
@@ -22,7 +22,7 @@ static int auth_recv_conf_ack(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, u
static void auth_print(void (*print)(const char *fmt,...),struct lcp_option_t*, uint8_t *ptr);
static struct ppp_layer_data_t *auth_layer_init(struct ppp_t*);
-static void auth_layer_start(struct ppp_layer_data_t *);
+static int auth_layer_start(struct ppp_layer_data_t *);
static void auth_layer_finish(struct ppp_layer_data_t *);
static void auth_layer_free(struct ppp_layer_data_t *);
@@ -257,7 +257,7 @@ static struct ppp_layer_data_t *auth_layer_init(struct ppp_t *ppp)
return &ad->ld;
}
-static void auth_layer_start(struct ppp_layer_data_t *ld)
+static int auth_layer_start(struct ppp_layer_data_t *ld)
{
struct auth_layer_data_t *ad=container_of(ld,typeof(*ad),ld);
@@ -270,6 +270,8 @@ static void auth_layer_start(struct ppp_layer_data_t *ld)
log_debug("auth_layer_started\n");
ppp_layer_started(ad->ppp,ld);
}
+
+ return 0;
}
static void auth_layer_finish(struct ppp_layer_data_t *ld)
diff --git a/accel-pptpd/ppp/ppp_ccp.c b/accel-pptpd/ppp/ppp_ccp.c
index fe10886e..f895da9b 100644
--- a/accel-pptpd/ppp/ppp_ccp.c
+++ b/accel-pptpd/ppp/ppp_ccp.c
@@ -24,7 +24,7 @@ static LIST_HEAD(option_handlers);
static void ccp_layer_up(struct ppp_fsm_t*);
static void ccp_layer_down(struct ppp_fsm_t*);
-static void send_conf_req(struct ppp_fsm_t*);
+static int send_conf_req(struct ppp_fsm_t*);
static void send_conf_ack(struct ppp_fsm_t*);
static void send_conf_nak(struct ppp_fsm_t*);
static void send_conf_rej(struct ppp_fsm_t*);
@@ -90,7 +90,7 @@ static struct ppp_layer_data_t *ccp_layer_init(struct ppp_t *ppp)
return &ccp->ld;
}
-void ccp_layer_start(struct ppp_layer_data_t *ld)
+int ccp_layer_start(struct ppp_layer_data_t *ld)
{
struct ppp_ccp_t *ccp=container_of(ld,typeof(*ccp),ld);
@@ -98,7 +98,10 @@ void ccp_layer_start(struct ppp_layer_data_t *ld)
ccp_options_init(ccp);
ppp_fsm_lower_up(&ccp->fsm);
- ppp_fsm_open(&ccp->fsm);
+ if (ppp_fsm_open(&ccp->fsm))
+ return -1;
+
+ return 0;
}
void ccp_layer_finish(struct ppp_layer_data_t *ld)
@@ -107,12 +110,8 @@ void ccp_layer_finish(struct ppp_layer_data_t *ld)
log_debug("ccp_layer_finish\n");
- ppp_fsm_lower_down(&ccp->fsm);
-
- ppp_unregister_handler(ccp->ppp,&ccp->hnd);
- ccp_options_free(ccp);
-
- ppp_layer_finished(ccp->ppp,ld);
+ ccp->fsm.fsm_state = FSM_Closed;
+ ppp_layer_finished(ccp->ppp,&ccp->ld);
}
void ccp_layer_free(struct ppp_layer_data_t *ld)
@@ -121,6 +120,10 @@ void ccp_layer_free(struct ppp_layer_data_t *ld)
log_debug("ccp_layer_free\n");
+ ppp_unregister_handler(ccp->ppp,&ccp->hnd);
+ ccp_options_free(ccp);
+ ppp_fsm_free(&ccp->fsm);
+
free(ccp);
}
@@ -151,7 +154,7 @@ static void print_ropt(struct recv_opt_t *ropt)
log_debug(" >");
}
-static void send_conf_req(struct ppp_fsm_t *fsm)
+static int send_conf_req(struct ppp_fsm_t *fsm)
{
struct ppp_ccp_t *ccp=container_of(fsm,typeof(*ccp),fsm);
uint8_t *buf=malloc(ccp->conf_req_len), *ptr=buf;
@@ -171,6 +174,8 @@ static void send_conf_req(struct ppp_fsm_t *fsm)
list_for_each_entry(lopt,&ccp->options,entry)
{
n=lopt->h->send_conf_req(ccp,lopt,ptr);
+ if (n < 0)
+ return -1;
if (n)
{
log_debug(" ");
@@ -183,6 +188,8 @@ static void send_conf_req(struct ppp_fsm_t *fsm)
ccp_hdr->len=htons((ptr-buf)-2);
ppp_unit_send(ccp->ppp,ccp_hdr,ptr-buf);
+
+ return 0;
}
static void send_conf_ack(struct ppp_fsm_t *fsm)
@@ -473,7 +480,7 @@ static void ccp_recv(struct ppp_handler_t*h)
if (ccp->fsm.fsm_state==FSM_Initial || ccp->fsm.fsm_state==FSM_Closed)
{
- log_error("CCP: discaring packet\n");
+ log_warn("CCP: discaring packet\n");
return;
}
diff --git a/accel-pptpd/ppp/ppp_fsm.c b/accel-pptpd/ppp/ppp_fsm.c
index 85cf15a2..a99453f0 100644
--- a/accel-pptpd/ppp/ppp_fsm.c
+++ b/accel-pptpd/ppp/ppp_fsm.c
@@ -38,7 +38,7 @@ void ppp_fsm_free(struct ppp_fsm_t *layer)
stop_timer(layer);
}
-void ppp_fsm_lower_up(struct ppp_fsm_t *layer)
+int ppp_fsm_lower_up(struct ppp_fsm_t *layer)
{
switch(layer->fsm_state)
{
@@ -49,12 +49,15 @@ void ppp_fsm_lower_up(struct ppp_fsm_t *layer)
//if (layer->init_req_cnt) layer->init_req_cnt(layer);
init_req_counter(layer,layer->max_configure);
--layer->restart_counter;
- if (layer->send_conf_req) layer->send_conf_req(layer);
+ if (layer->send_conf_req)
+ if (layer->send_conf_req(layer))
+ return -1;
layer->fsm_state=FSM_Req_Sent;
break;
default:
break;
}
+ return 0;
}
void ppp_fsm_lower_down(struct ppp_fsm_t *layer)
@@ -84,7 +87,7 @@ void ppp_fsm_lower_down(struct ppp_fsm_t *layer)
}
}
-void ppp_fsm_open(struct ppp_fsm_t *layer)
+int ppp_fsm_open(struct ppp_fsm_t *layer)
{
switch(layer->fsm_state)
{
@@ -98,7 +101,9 @@ void ppp_fsm_open(struct ppp_fsm_t *layer)
//if (layer->init_req_cnt) layer->init_req_cnt(layer);
init_req_counter(layer,layer->max_configure);
--layer->restart_counter;
- if (layer->send_conf_req) layer->send_conf_req(layer);
+ if (layer->send_conf_req)
+ if (layer->send_conf_req(layer))
+ return -1;
layer->fsm_state=FSM_Req_Sent;
break;
case FSM_Closing:
@@ -111,6 +116,7 @@ void ppp_fsm_open(struct ppp_fsm_t *layer)
default:
break;
}
+ return 0;
}
void ppp_fsm_close(struct ppp_fsm_t *layer)
diff --git a/accel-pptpd/ppp/ppp_fsm.h b/accel-pptpd/ppp/ppp_fsm.h
index bc958fe9..908936db 100644
--- a/accel-pptpd/ppp/ppp_fsm.h
+++ b/accel-pptpd/ppp/ppp_fsm.h
@@ -37,7 +37,7 @@ struct ppp_fsm_t
void (*layer_down)(struct ppp_fsm_t*);
void (*layer_started)(struct ppp_fsm_t*);
void (*layer_finished)(struct ppp_fsm_t*);
- void (*send_conf_req)(struct ppp_fsm_t*);
+ int (*send_conf_req)(struct ppp_fsm_t*);
void (*send_conf_ack)(struct ppp_fsm_t*);
void (*send_conf_nak)(struct ppp_fsm_t*);
void (*send_conf_rej)(struct ppp_fsm_t*);
@@ -46,9 +46,9 @@ struct ppp_fsm_t
void ppp_fsm_init(struct ppp_fsm_t*);
void ppp_fsm_free(struct ppp_fsm_t*);
-void ppp_fsm_lower_up(struct ppp_fsm_t*);
+int ppp_fsm_lower_up(struct ppp_fsm_t*);
void ppp_fsm_lower_down(struct ppp_fsm_t*);
-void ppp_fsm_open(struct ppp_fsm_t*);
+int ppp_fsm_open(struct ppp_fsm_t*);
void ppp_fsm_close(struct ppp_fsm_t*);
void ppp_fsm_timeout0(struct ppp_fsm_t *layer);
void ppp_fsm_timeout1(struct ppp_fsm_t *layer);
diff --git a/accel-pptpd/ppp/ppp_ipcp.c b/accel-pptpd/ppp/ppp_ipcp.c
index 6ac145b2..bb6369e0 100644
--- a/accel-pptpd/ppp/ppp_ipcp.c
+++ b/accel-pptpd/ppp/ppp_ipcp.c
@@ -24,7 +24,7 @@ static LIST_HEAD(option_handlers);
static void ipcp_layer_up(struct ppp_fsm_t*);
static void ipcp_layer_down(struct ppp_fsm_t*);
-static void send_conf_req(struct ppp_fsm_t*);
+static int send_conf_req(struct ppp_fsm_t*);
static void send_conf_ack(struct ppp_fsm_t*);
static void send_conf_nak(struct ppp_fsm_t*);
static void send_conf_rej(struct ppp_fsm_t*);
@@ -90,7 +90,7 @@ static struct ppp_layer_data_t *ipcp_layer_init(struct ppp_t *ppp)
return &ipcp->ld;
}
-void ipcp_layer_start(struct ppp_layer_data_t *ld)
+int ipcp_layer_start(struct ppp_layer_data_t *ld)
{
struct ppp_ipcp_t *ipcp=container_of(ld,typeof(*ipcp),ld);
@@ -98,7 +98,10 @@ void ipcp_layer_start(struct ppp_layer_data_t *ld)
ipcp_options_init(ipcp);
ppp_fsm_lower_up(&ipcp->fsm);
- ppp_fsm_open(&ipcp->fsm);
+ if (ppp_fsm_open(&ipcp->fsm))
+ return -1;
+
+ return 0;
}
void ipcp_layer_finish(struct ppp_layer_data_t *ld)
@@ -107,12 +110,8 @@ void ipcp_layer_finish(struct ppp_layer_data_t *ld)
log_debug("ipcp_layer_finish\n");
- ppp_fsm_lower_down(&ipcp->fsm);
-
- ppp_unregister_handler(ipcp->ppp,&ipcp->hnd);
- ipcp_options_free(ipcp);
-
- ppp_layer_finished(ipcp->ppp,ld);
+ ipcp->fsm.fsm_state = FSM_Closed;
+ ppp_layer_finished(ipcp->ppp,&ipcp->ld);
}
void ipcp_layer_free(struct ppp_layer_data_t *ld)
@@ -121,6 +120,10 @@ void ipcp_layer_free(struct ppp_layer_data_t *ld)
log_debug("ipcp_layer_free\n");
+ ppp_unregister_handler(ipcp->ppp,&ipcp->hnd);
+ ipcp_options_free(ipcp);
+ ppp_fsm_free(&ipcp->fsm);
+
free(ipcp);
}
@@ -151,7 +154,7 @@ static void print_ropt(struct recv_opt_t *ropt)
log_debug(" >");
}
-static void send_conf_req(struct ppp_fsm_t *fsm)
+static int send_conf_req(struct ppp_fsm_t *fsm)
{
struct ppp_ipcp_t *ipcp=container_of(fsm,typeof(*ipcp),fsm);
uint8_t *buf=malloc(ipcp->conf_req_len), *ptr=buf;
@@ -159,30 +162,40 @@ static void send_conf_req(struct ppp_fsm_t *fsm)
struct ipcp_option_t *lopt;
int n;
- log_debug("send [IPCP ConfReq");
ipcp_hdr->proto=htons(PPP_IPCP);
ipcp_hdr->code=CONFREQ;
ipcp_hdr->id=++ipcp->fsm.id;
ipcp_hdr->len=0;
- log_debug(" id=%x",ipcp_hdr->id);
ptr+=sizeof(*ipcp_hdr);
list_for_each_entry(lopt,&ipcp->options,entry)
{
- n=lopt->h->send_conf_req(ipcp,lopt,ptr);
- if (n)
- {
- log_debug(" ");
- lopt->h->print(log_debug,lopt,NULL);
+ n = lopt->h->send_conf_req(ipcp, lopt, ptr);
+ if (n < 0)
+ return -1;
+ if (n) {
ptr+=n;
+ lopt->print = 1;
+ } else
+ lopt->print = 0;
+ }
+
+ if (conf_ppp_verbose) {
+ log_debug("send [IPCP ConfReq id=%x", ipcp_hdr->id);
+ list_for_each_entry(lopt,&ipcp->options,entry){
+ if (lopt->print) {
+ log_debug(" ");
+ lopt->h->print(log_debug,lopt,NULL);
+ }
}
+ log_debug("]\n");
}
-
- log_debug("]\n");
ipcp_hdr->len=htons((ptr-buf)-2);
ppp_unit_send(ipcp->ppp,ipcp_hdr,ptr-buf);
+
+ return 0;
}
static void send_conf_ack(struct ppp_fsm_t *fsm)
@@ -464,7 +477,7 @@ static void ipcp_recv(struct ppp_handler_t*h)
if (ipcp->fsm.fsm_state==FSM_Initial || ipcp->fsm.fsm_state==FSM_Closed)
{
- log_error("IPCP: discaring packet\n");
+ log_warn("IPCP: discaring packet\n");
return;
}
diff --git a/accel-pptpd/ppp/ppp_ipcp.h b/accel-pptpd/ppp/ppp_ipcp.h
index 9e0c99ee..266ab7df 100644
--- a/accel-pptpd/ppp/ppp_ipcp.h
+++ b/accel-pptpd/ppp/ppp_ipcp.h
@@ -56,6 +56,7 @@ struct ipcp_option_t
int id;
int len;
int state;
+ int print:1;
struct ipcp_option_handler_t *h;
};
diff --git a/accel-pptpd/ppp/ppp_lcp.c b/accel-pptpd/ppp/ppp_lcp.c
index afcfc102..22e6313d 100644
--- a/accel-pptpd/ppp/ppp_lcp.c
+++ b/accel-pptpd/ppp/ppp_lcp.c
@@ -27,7 +27,7 @@ static LIST_HEAD(option_handlers);
static void lcp_layer_up(struct ppp_fsm_t*);
static void lcp_layer_down(struct ppp_fsm_t*);
-static void send_conf_req(struct ppp_fsm_t*);
+static int send_conf_req(struct ppp_fsm_t*);
static void send_conf_ack(struct ppp_fsm_t*);
static void send_conf_nak(struct ppp_fsm_t*);
static void send_conf_rej(struct ppp_fsm_t*);
@@ -95,7 +95,7 @@ static struct ppp_layer_data_t *lcp_layer_init(struct ppp_t *ppp)
return &lcp->ld;
}
-void lcp_layer_start(struct ppp_layer_data_t *ld)
+int lcp_layer_start(struct ppp_layer_data_t *ld)
{
struct ppp_lcp_t *lcp=container_of(ld,typeof(*lcp),ld);
@@ -103,7 +103,10 @@ void lcp_layer_start(struct ppp_layer_data_t *ld)
lcp_options_init(lcp);
ppp_fsm_lower_up(&lcp->fsm);
- ppp_fsm_open(&lcp->fsm);
+ if (ppp_fsm_open(&lcp->fsm))
+ return -1;
+
+ return 0;
}
void lcp_layer_finish(struct ppp_layer_data_t *ld)
@@ -161,7 +164,7 @@ static void print_ropt(struct recv_opt_t *ropt)
log_debug(" >");
}
-static void send_conf_req(struct ppp_fsm_t *fsm)
+static int send_conf_req(struct ppp_fsm_t *fsm)
{
struct ppp_lcp_t *lcp=container_of(fsm,typeof(*lcp),fsm);
uint8_t *buf=malloc(lcp->conf_req_len), *ptr=buf;
@@ -169,30 +172,42 @@ static void send_conf_req(struct ppp_fsm_t *fsm)
struct lcp_option_t *lopt;
int n;
- log_debug("send [LCP ConfReq");
lcp_hdr->proto=htons(PPP_LCP);
lcp_hdr->code=CONFREQ;
lcp_hdr->id=++lcp->fsm.id;
lcp_hdr->len=0;
- log_debug(" id=%x",lcp_hdr->id);
ptr+=sizeof(*lcp_hdr);
list_for_each_entry(lopt,&lcp->options,entry)
{
n=lopt->h->send_conf_req(lcp,lopt,ptr);
+ if (n < 0)
+ return -1;
if (n)
{
- log_debug(" ");
- lopt->h->print(log_debug,lopt,NULL);
ptr+=n;
- }
+ lopt->print = 1;
+ } else
+ lopt->print = 0;
}
- log_debug("]\n");
+ if (conf_ppp_verbose) {
+ log_debug("send [LCP ConfReq id=%x", lcp_hdr->id);
+ list_for_each_entry(lopt,&lcp->options,entry)
+ {
+ if (lopt->print) {
+ log_debug(" ");
+ lopt->h->print(log_debug,lopt,NULL);
+ }
+ }
+ log_debug("]\n");
+ }
lcp_hdr->len=htons((ptr-buf)-2);
ppp_chan_send(lcp->ppp,lcp_hdr,ptr-buf);
+
+ return 0;
}
static void send_conf_ack(struct ppp_fsm_t *fsm)
diff --git a/accel-pptpd/ppp/ppp_lcp.h b/accel-pptpd/ppp/ppp_lcp.h
index 46bc17b9..661f200c 100644
--- a/accel-pptpd/ppp/ppp_lcp.h
+++ b/accel-pptpd/ppp/ppp_lcp.h
@@ -90,6 +90,7 @@ struct lcp_option_t
int id;
int len;
int state;
+ int print:1;
struct lcp_option_handler_t *h;
};
diff --git a/accel-pptpd/pwdb.c b/accel-pptpd/pwdb.c
index 1b682a40..24515ec6 100644
--- a/accel-pptpd/pwdb.c
+++ b/accel-pptpd/pwdb.c
@@ -27,10 +27,10 @@ int __export pwdb_check(struct ppp_t *ppp, const char *username, int type, ...)
return res;
}
-__export const char *pwdb_get_passwd(struct ppp_t *ppp, const char *username)
+__export char *pwdb_get_passwd(struct ppp_t *ppp, const char *username)
{
struct pwdb_t *pwdb;
- const char *r = NULL;
+ char *r = NULL;
list_for_each_entry(pwdb, &pwdb_handlers, entry) {
if (!pwdb->get_passwd)
diff --git a/accel-pptpd/pwdb.h b/accel-pptpd/pwdb.h
index d3495435..a1c2cedb 100644
--- a/accel-pptpd/pwdb.h
+++ b/accel-pptpd/pwdb.h
@@ -14,11 +14,11 @@ struct pwdb_t
{
struct list_head entry;
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);
+ char* (*get_passwd)(struct pwdb_t *, struct ppp_t *, const char *username);
};
int pwdb_check(struct ppp_t *, const char *username, int type, ...);
-const char *pwdb_get_passwd(struct ppp_t *, const char *username);
+char *pwdb_get_passwd(struct ppp_t *, const char *username);
void pwdb_register(struct pwdb_t *);
void pwdb_unregister(struct pwdb_t *);
diff --git a/accel-pptpd/radius/dict.c b/accel-pptpd/radius/dict.c
index 00f67af7..d76c2c39 100644
--- a/accel-pptpd/radius/dict.c
+++ b/accel-pptpd/radius/dict.c
@@ -210,7 +210,17 @@ struct rad_dict_attr_t *rad_dict_find_attr(const char *name)
return NULL;
}
-struct rad_dict_value_t *rad_dict_find_val(struct rad_dict_attr_t *attr, const char *name)
+struct rad_dict_attr_t *rad_dict_find_attr_id(int id)
+{
+ struct rad_dict_attr_t *attr;
+
+ list_for_each_entry(attr, &dict->items, entry)
+ if (attr->id == id)
+ return attr;
+
+ return NULL;
+}
+struct rad_dict_value_t *rad_dict_find_val_name(struct rad_dict_attr_t *attr, const char *name)
{
struct rad_dict_value_t *val;
@@ -220,3 +230,17 @@ struct rad_dict_value_t *rad_dict_find_val(struct rad_dict_attr_t *attr, const c
return NULL;
}
+
+struct rad_dict_value_t *rad_dict_find_val(struct rad_dict_attr_t *attr, rad_value_t v)
+{
+ struct rad_dict_value_t *val;
+
+ if (attr->type != ATTR_TYPE_INTEGER)
+ return NULL;
+
+ list_for_each_entry(val, &attr->values, entry)
+ if (val->val.integer == v.integer)
+ return val;
+
+ return NULL;
+}
diff --git a/accel-pptpd/radius/packet.c b/accel-pptpd/radius/packet.c
index f1b4ebea..627b6c5e 100644
--- a/accel-pptpd/radius/packet.c
+++ b/accel-pptpd/radius/packet.c
@@ -4,14 +4,40 @@
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
+#include <fcntl.h>
#include "log.h"
#include "radius.h"
-static int urandom_fd;
+struct rad_packet_t *rad_packet_alloc(int code)
+{
+ struct rad_packet_t *pack;
+
+ pack = malloc(sizeof(*pack));
+ if (!pack) {
+ log_error("radius:packet: out of memory\n");
+ return NULL;
+ }
+
+ memset(pack, 0, sizeof(*pack));
+ pack->code = code;
+ pack->len = 20;
+ pack->id = 1;
+ INIT_LIST_HEAD(&pack->attrs);
+
+ return pack;
+}
-int rad_packet_build(struct rad_packet_t *pack)
+void print_buf(uint8_t *buf,int size)
+{
+ int i;
+ for(i=0;i<size;i++)
+ printf("%x ",buf[i]);
+ printf("\n");
+}
+
+int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA)
{
struct rad_req_attr_t *attr;
uint8_t *ptr;
@@ -22,26 +48,18 @@ int rad_packet_build(struct rad_packet_t *pack)
return -1;
}
+ pack->buf = ptr;
*ptr = pack->code; ptr++;
*ptr = pack->id; ptr++;
- *(uint16_t*)ptr = pack->len; ptr+= 2;
- while (1) {
- if (read(urandom_fd, ptr, 16) != 16) {
- if (errno == EINTR)
- continue;
- log_error("radius:packet:read urandom: %s\n", strerror(errno));
- goto out_err;
- }
- break;
- }
- ptr+=16;
+ *(uint16_t*)ptr = htons(pack->len); ptr+= 2;
+ memcpy(ptr, RA, 16); ptr+=16;
list_for_each_entry(attr, &pack->attrs, entry) {
- *ptr = attr->attr->type; ptr++;
- *ptr = attr->len; ptr++;
+ *ptr = attr->attr->id; ptr++;
+ *ptr = attr->len + 2; ptr++;
switch(attr->attr->type) {
case ATTR_TYPE_INTEGER:
- *(uint32_t*)ptr = attr->val.integer;
+ *(uint32_t*)ptr = htonl(attr->val.integer);
break;
case ATTR_TYPE_STRING:
memcpy(ptr, attr->val.string, attr->len);
@@ -50,20 +68,18 @@ int rad_packet_build(struct rad_packet_t *pack)
*(in_addr_t*)ptr = attr->val.ipaddr;
break;
case ATTR_TYPE_DATE:
- *(uint32_t*)ptr = attr->val.date;
+ *(uint32_t*)ptr = htonl(attr->val.date);
break;
default:
- log_error("radius:packet: unknown attribute type\n");
+ log_error("radius:packet:BUG: unknown attribute type\n");
abort();
}
ptr += attr->len;
}
- return 0;
+ print_buf(pack->buf, pack->len);
-out_err:
- free(ptr);
- return -1;
+ return 0;
}
struct rad_packet_t *rad_packet_recv(int fd)
@@ -72,22 +88,16 @@ struct rad_packet_t *rad_packet_recv(int fd)
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;
- }
+ int n, id, len;
- memset(pack, 0, sizeof(*pack));
- INIT_LIST_HEAD(&pack->attrs);
+ pack = rad_packet_alloc(0);
+ if (!pack)
+ return NULL;
pack->buf = malloc(REQ_LENGTH_MAX);
if (!pack->buf) {
log_error("radius:packet: out of memory\n");
- free(pack);
- return NULL;
+ goto out_err;
}
while (1) {
@@ -110,7 +120,7 @@ struct rad_packet_t *rad_packet_recv(int fd)
pack->code = *ptr; ptr++;
pack->id = *ptr; ptr++;
- pack->len = *(uint16_t*)ptr; ptr += 2;
+ pack->len = ntohs(*(uint16_t*)ptr); ptr += 2;
if (pack->len > n) {
log_warn("radius:packet: short packet received %i, expected %i\n", pack->len, n);
@@ -121,13 +131,17 @@ struct rad_packet_t *rad_packet_recv(int fd)
n -= 20;
while (n>0) {
- type = *ptr; ptr++;
- len = *ptr; ptr++;
+ id = *ptr; ptr++;
+ len = *ptr - 2; ptr++;
+ if (len < 0) {
+ log_warn("radius:packet short attribute len received\n");
+ goto out_err;
+ }
if (2 + len > n) {
- log_error("radius:packet: too long attribute received (%i, %i)\n", type, len);
+ log_warn("radius:packet: too long attribute received (%i, %i)\n", id, len);
goto out_err;
}
- da = rad_dict_find_attr_type(type);
+ da = rad_dict_find_attr_id(id);
if (da) {
attr = malloc(sizeof(*attr));
if (!attr) {
@@ -136,18 +150,28 @@ struct rad_packet_t *rad_packet_recv(int fd)
}
attr->attr = da;
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->val.integer, ptr, 4);
+ switch (da->type) {
+ case ATTR_TYPE_STRING:
+ attr->val.string = malloc(len+1);
+ if (!attr->val.string) {
+ log_error("radius:packet: out of memory\n");
+ free(attr);
+ goto out_err;
+ }
+ memcpy(attr->val.string, ptr, len);
+ attr->val.string[len] = 0;
+ break;
+ case ATTR_TYPE_DATE:
+ case ATTR_TYPE_INTEGER:
+ attr->val.integer = ntohl(*(uint32_t*)ptr);
+ break;
+ case ATTR_TYPE_IPADDR:
+ attr->val.integer = *(uint32_t*)ptr;
+ break;
+ }
list_add_tail(&attr->entry, &pack->attrs);
} else
- log_warn("radius:packet: unknown attribute type received (%i)\n", type);
+ log_warn("radius:packet: unknown attribute received (%i)\n", id);
ptr += len;
n -= 2 + len;
}
@@ -176,3 +200,52 @@ void rad_packet_free(struct rad_packet_t *pack)
free(pack);
}
+
+void rad_packet_print(struct rad_packet_t *pack, void (*print)(const char *fmt, ...))
+{
+ struct rad_req_attr_t *attr;
+ struct rad_dict_value_t *val;
+
+ print("[RADIUS ");
+ switch(pack->code) {
+ case CODE_ACCESS_REQUEST:
+ print("Access-Request");
+ break;
+ case CODE_ACCESS_CHALLENGE:
+ print("Access-Challenge");
+ break;
+ case CODE_ACCESS_ACCEPT:
+ print("Access-Accept");
+ break;
+ case CODE_ACCESS_REJECT:
+ print("Access-Reject");
+ break;
+ default:
+ print("Unknown (%i)", pack->code);
+ }
+ print(" id=%x", pack->id);
+
+ list_for_each_entry(attr, &pack->attrs, entry) {
+ print(" <%s ", attr->attr->name);
+ if (attr->printable) {
+ switch (attr->attr->type) {
+ case ATTR_TYPE_INTEGER:
+ val = rad_dict_find_val(attr->attr, attr->val);
+ if (val)
+ print("%s", val->name);
+ else
+ print("%i", attr->val.integer);
+ break;
+ case ATTR_TYPE_STRING:
+ print("\"%s\"", attr->val.string);
+ break;
+ case ATTR_TYPE_IPADDR:
+ print("%i.%i.%i.%i", attr->val.ipaddr & 0xff, (attr->val.ipaddr >> 8) & 0xff, (attr->val.ipaddr >> 16) & 0xff, (attr->val.ipaddr >> 24) & 0xff);
+ break;
+ }
+ }
+ print(">");
+ }
+ print("]\n");
+}
+
diff --git a/accel-pptpd/radius/radius.c b/accel-pptpd/radius/radius.c
index 2e444ded..a786dea5 100644
--- a/accel-pptpd/radius/radius.c
+++ b/accel-pptpd/radius/radius.c
@@ -3,43 +3,124 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <arpa/inet.h>
+#include <openssl/md5.h>
+
+#include "log.h"
#include "ppp.h"
#include "pwdb.h"
+#include "ipdb.h"
+
#include "radius.h"
int conf_max_try = 3;
int conf_timeout = 3;
char *conf_nas_identifier = "accel-pptpd";
char *conf_nas_ip_address;
+char *conf_gw_ip_address;
+int conf_verbose = 0;
+
+char *conf_auth_server;
+int conf_auth_server_port = 1812;
+char *conf_auth_server_secret;
+
+char *conf_acct_server;
+int conf_acct_server_port = 1813;
+char *conf_acct_server_secret;
static struct ppp_notified_t notified;
+static struct radius_pd_t *find_pd(struct ppp_t *ppp);
+
+static void proc_attrs(struct rad_req_t *req)
+{
+ struct rad_req_attr_t *attr;
+
+ list_for_each_entry(attr, &req->reply->attrs, entry) {
+ if (!strcmp(attr->attr->name, "Framed-IP-Address")) {
+ req->rpd->ipaddr = attr->val.ipaddr;
+ }
+ }
+}
+
+static uint8_t* encrypt_password(const char *passwd, const char *secret, const uint8_t *RA, int *epasswd_len)
+{
+ uint8_t *epasswd;
+ int i, j, chunk_cnt;
+ uint8_t b[16], c[16];
+ MD5_CTX ctx;
+
+ chunk_cnt = (strlen(passwd) - 1) / 16 + 1;
+
+ epasswd = malloc(chunk_cnt * 16);
+ if (!epasswd) {
+ log_error("radius: out of memory\n");
+ return NULL;
+ }
+
+ memset(epasswd, 0, chunk_cnt * 16);
+ memcpy(epasswd, passwd, strlen(passwd));
+ memcpy(c, RA, 16);
+
+ for (i = 0; i < chunk_cnt; i++) {
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, secret, strlen(secret));
+ MD5_Update(&ctx, c, 16);
+ MD5_Final(b, &ctx);
+
+ for(j = 0; j < 16; j++)
+ epasswd[i * 16 + j] ^= b[j];
+
+ memcpy(c, epasswd + i * 16, 16);
+ }
+
+ *epasswd_len = chunk_cnt * 16;
+ return epasswd;
+}
+
static int check_pap(struct radius_pd_t *rpd, const char *username, va_list args)
{
struct rad_req_t *req;
int i, r = PWDB_DENIED;
//int id = va_arg(args, int);
const char *passwd = va_arg(args, const char *);
+ uint8_t *epasswd;
+ int epasswd_len;
req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
if (!req)
return PWDB_DENIED;
+
+ req->server_name = conf_auth_server;
+ req->server_port = conf_auth_server_port;
- if (rad_req_add_str(req, "User-Password", passwd, strlen(passwd)))
+ epasswd = encrypt_password(passwd, conf_auth_server_secret, req->RA, &epasswd_len);
+ if (!epasswd)
goto out;
+ if (rad_req_add_str(req, "Password", (char*)epasswd, epasswd_len, 0)) {
+ free(epasswd);
+ goto out;
+ }
+
+ free(epasswd);
+
for(i = 0; i < conf_max_try; i++) {
if (rad_req_send(req))
goto out;
- if (rad_req_wait(req, conf_timeout))
- goto out;
+ rad_req_wait(req, conf_timeout);
if (req->reply)
break;
}
+ if (req->reply && req->reply->code == CODE_ACCESS_ACCEPT) {
+ proc_attrs(req);
+ r = PWDB_SUCCESS;
+ }
+
out:
rad_req_free(req);
@@ -79,15 +160,7 @@ static int check(struct pwdb_t *pwdb, struct ppp_t *ppp, const char *username, i
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;
- }
- }
+ struct radius_pd_t *rpd = find_pd(ppp);
va_copy(args, _args);
@@ -116,6 +189,22 @@ static int check(struct pwdb_t *pwdb, struct ppp_t *ppp, const char *username, i
return r;
}
+static int get_ip(struct ppp_t *ppp, in_addr_t *addr, in_addr_t *peer_addr)
+{
+ struct radius_pd_t *rpd = find_pd(ppp);
+
+ if (rpd->ipaddr) {
+ if (!conf_gw_ip_address) {
+ log_warn("radius: gw-ip-address not specified, cann't assign IP address...\n");
+ return -1;
+ }
+ *peer_addr = rpd->ipaddr;
+ *addr = inet_addr(conf_gw_ip_address);
+ return 0;
+ }
+ return -1;
+}
+
static void ppp_started(struct ppp_notified_t *n, struct ppp_t *ppp)
{
struct radius_pd_t *pd = malloc(sizeof(*pd));
@@ -128,19 +217,32 @@ static void ppp_started(struct ppp_notified_t *n, struct ppp_t *ppp)
static void ppp_finished(struct ppp_notified_t *n, struct ppp_t *ppp)
{
+ struct radius_pd_t *rpd = find_pd(ppp);
+
+ list_del(&rpd->pd.entry);
+ free(rpd);
+}
+
+static struct radius_pd_t *find_pd(struct ppp_t *ppp)
+{
struct ppp_pd_t *pd;
struct radius_pd_t *rpd;
list_for_each_entry(pd, &ppp->pd_list, entry) {
if (pd->key == &notified) {
rpd = container_of(pd, typeof(*rpd), pd);
- list_del(&pd->entry);
- free(rpd);
- return;
+ return rpd;
}
}
+ log_error("radius:BUG: rpd not found\n");
+ abort();
}
+
+static struct ipdb_t ipdb = {
+ .get = get_ip,
+};
+
static struct pwdb_t pwdb = {
.check = check,
};
@@ -150,17 +252,81 @@ static struct ppp_notified_t notified = {
.finished = ppp_finished,
};
+static int parse_server(const char *opt, char **name, int *port, char **secret)
+{
+ char *str = strdup(opt);
+ char *p1, *p2;
+
+ p1 = strstr(str, ":");
+ p2 = strstr(str, ",");
+
+ if (p1)
+ *p1 = 0;
+ if (p2)
+ *p2 = 0;
+ else
+ return -1;
+
+ *name = str;
+ if (p1) {
+ *port = atoi(p1 + 1);
+ if (*port <=0 )
+ return -1;
+ }
+ *secret = p2 + 1;
+
+ return 0;
+}
+
static void __init radius_init(void)
{
- char *dict = conf_get_opt("radius", "dictionary");
- if (!dict) {
+ char *opt;
+
+ opt = conf_get_opt("radius", "max-try");
+ if (opt && atoi(opt) > 0)
+ conf_max_try = atoi(opt);
+
+ opt = conf_get_opt("radius", "timeout");
+ if (opt && atoi(opt) > 0)
+ conf_timeout = atoi(opt);
+
+ opt = conf_get_opt("radius", "verbose");
+ if (opt && atoi(opt) > 0)
+ conf_verbose = 1;
+
+ opt = conf_get_opt("radius", "nas-ip-address");
+ if (opt)
+ conf_nas_ip_address = opt;
+
+ opt = conf_get_opt("radius", "gw-ip-address");
+ if (opt)
+ conf_gw_ip_address = opt;
+
+ opt = conf_get_opt("radius", "auth_server");
+ if (!opt) {
+ log_error("radius: auth_server not specified\n");
+ _exit(EXIT_FAILURE);
+ } else if (parse_server(opt, &conf_auth_server, &conf_auth_server_port, &conf_auth_server_secret)) {
+ log_error("radius: failed to parse auth_server\n");
+ _exit(EXIT_FAILURE);
+ }
+
+ opt = conf_get_opt("radius", "acct_server");
+ if (opt && parse_server(opt, &conf_acct_server, &conf_acct_server_port, &conf_acct_server_secret)) {
+ log_error("radius: failed to parse acct_server\n");
+ _exit(EXIT_FAILURE);
+ }
+
+ opt = conf_get_opt("radius", "dictionary");
+ if (!opt) {
fprintf(stderr, "radius: dictionary not specified\n");
_exit(EXIT_FAILURE);
}
- if (!rad_dict_load(dict))
+ if (rad_dict_load(opt))
_exit(EXIT_FAILURE);
pwdb_register(&pwdb);
+ ipdb_register(&ipdb);
ppp_register_notified(&notified);
}
diff --git a/accel-pptpd/radius/radius.h b/accel-pptpd/radius/radius.h
index 109981a6..40b83201 100644
--- a/accel-pptpd/radius/radius.h
+++ b/accel-pptpd/radius/radius.h
@@ -1,6 +1,7 @@
#ifndef __RADIUS_H
#define __RADIUS_H
+#include <stdint.h>
#include <netinet/in.h>
#include "triton.h"
#include "ppp.h"
@@ -13,17 +14,21 @@
#define ATTR_TYPE_IPADDR 3
#define CODE_ACCESS_REQUEST 1
+#define CODE_ACCESS_ACCEPT 2
+#define CODE_ACCESS_REJECT 3
+#define CODE_ACCESS_CHALLENGE 11
struct radius_pd_t
{
struct ppp_pd_t pd;
struct ppp_t *ppp;
+ in_addr_t ipaddr;
};
typedef union
{
int integer;
- const char *string;
+ char *string;
time_t date;
in_addr_t ipaddr;
} rad_value_t;
@@ -56,6 +61,7 @@ struct rad_req_attr_t
//struct rad_dict_value_t *val;
rad_value_t val;
int len;
+ int printable:1;
};
struct rad_packet_t
@@ -68,9 +74,11 @@ struct rad_packet_t
};
struct rad_req_t
{
+ struct triton_context_t ctx;
struct triton_md_handler_t hnd;
struct triton_timer_t timeout;
- struct rad_packet_t pack;
+ uint8_t RA[16];
+ struct rad_packet_t *pack;
struct rad_packet_t *reply;
const char *server_name;
int server_port;
@@ -81,14 +89,18 @@ struct rad_req_t
extern int conf_max_try;
extern int conf_timeout;
+extern int conf_verbose;
extern char *conf_nas_identifier;
extern char *conf_nas_ip_address;
+extern char *conf_auth_server;
+extern char *conf_acct_server;
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_dict_attr_t *rad_dict_find_attr_id(int type);
+struct rad_dict_value_t *rad_dict_find_val_name(struct rad_dict_attr_t *, const char *name);
+struct rad_dict_value_t *rad_dict_find_val(struct rad_dict_attr_t *, rad_value_t val);
struct rad_req_t *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *username);
void rad_req_free(struct rad_req_t *);
@@ -96,11 +108,13 @@ int rad_req_send(struct rad_req_t *);
int rad_req_wait(struct rad_req_t *, int);
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_req_add_str(struct rad_req_t *req, const char *name, const char *val, int len, int printable);
-int rad_packet_build(struct rad_packet_t *pack);
+struct rad_packet_t *rad_packet_alloc(int code);
+int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA);
struct rad_packet_t *rad_packet_recv(int fd);
void rad_packet_free(struct rad_packet_t *);
+void rad_packet_print(struct rad_packet_t *pack, void (*print)(const char *fmt, ...));
#endif
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);
+ }
+}
diff --git a/accel-pptpd/triton/md.c b/accel-pptpd/triton/md.c
index 3cb47a6d..05d814cc 100644
--- a/accel-pptpd/triton/md.c
+++ b/accel-pptpd/triton/md.c
@@ -86,16 +86,16 @@ static void *md_thread(void *arg)
return NULL;
}
-void __export triton_md_register_handler(struct triton_ctx_t *ctx, struct triton_md_handler_t *ud)
+void __export triton_md_register_handler(struct triton_context_t *ctx, struct triton_md_handler_t *ud)
{
struct _triton_md_handler_t *h = mempool_alloc(md_pool);
memset(h, 0, sizeof(*h));
h->ud = ud;
h->epoll_event.data.ptr = h;
if (ctx)
- h->ctx = (struct _triton_ctx_t *)ctx->tpd;
+ h->ctx = (struct _triton_context_t *)ctx->tpd;
else
- h->ctx = (struct _triton_ctx_t *)default_ctx->tpd;
+ h->ctx = (struct _triton_context_t *)default_ctx->tpd;
ud->tpd = h;
spin_lock(&h->ctx->lock);
list_add_tail(&h->entry, &h->ctx->handlers);
diff --git a/accel-pptpd/triton/timer.c b/accel-pptpd/triton/timer.c
index f34c19d1..e9fd66a0 100644
--- a/accel-pptpd/triton/timer.c
+++ b/accel-pptpd/triton/timer.c
@@ -86,7 +86,7 @@ void *timer_thread(void *arg)
return NULL;
}
-int __export triton_timer_add(struct triton_ctx_t *ctx, struct triton_timer_t *ud, int abs_time)
+int __export triton_timer_add(struct triton_context_t *ctx, struct triton_timer_t *ud, int abs_time)
{
struct _triton_timer_t *t = mempool_alloc(timer_pool);
@@ -95,9 +95,9 @@ int __export triton_timer_add(struct triton_ctx_t *ctx, struct triton_timer_t *u
t->epoll_event.data.ptr = t;
t->epoll_event.events = EPOLLIN | EPOLLET;
if (ctx)
- t->ctx = (struct _triton_ctx_t *)ctx->tpd;
+ t->ctx = (struct _triton_context_t *)ctx->tpd;
else
- t->ctx = (struct _triton_ctx_t *)default_ctx->tpd;
+ t->ctx = (struct _triton_context_t *)default_ctx->tpd;
t->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
if (t->fd < 0) {
triton_log_error("timer:timerfd_create: %s" ,strerror(errno));
diff --git a/accel-pptpd/triton/triton.c b/accel-pptpd/triton/triton.c
index 9aa7462b..ba08c122 100644
--- a/accel-pptpd/triton/triton.c
+++ b/accel-pptpd/triton/triton.c
@@ -7,7 +7,7 @@
#include "triton_p.h"
-int thread_count = 4;
+int thread_count = 1;
int max_events = 64;
static spinlock_t threads_lock = SPINLOCK_INITIALIZER;
@@ -19,7 +19,7 @@ static LIST_HEAD(ctx_queue);
static spinlock_t ctx_list_lock = SPINLOCK_INITIALIZER;
static LIST_HEAD(ctx_list);
-struct triton_ctx_t *default_ctx;
+struct triton_context_t *default_ctx;
static int terminate;
static mempool_t *ctx_pool;
@@ -31,61 +31,25 @@ void triton_thread_wakeup(struct _triton_thread_t *thread)
static void* triton_thread(struct _triton_thread_t *thread)
{
- struct _triton_md_handler_t *h;
- struct _triton_timer_t *t;
sigset_t set;
int sig;
- uint64_t tt;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGQUIT);
- while(1){
+ while (1) {
sigwait(&set, &sig);
cont:
- if (thread->ctx->need_close) {
- if (thread->ctx->ud->close)
- thread->ctx->ud->close(thread->ctx->ud);
- thread->ctx->need_close = 0;
- }
-
- while (1) {
- spin_lock(&thread->ctx->lock);
- if (!list_empty(&thread->ctx->pending_timers)) {
- t = list_entry(thread->ctx->pending_timers.next, typeof(*t), entry2);
- list_del(&t->entry2);
- t->pending = 0;
- spin_unlock(&thread->ctx->lock);
- read(t->fd, &tt, sizeof(tt));
- t->ud->expire(t->ud);
- }
- if (!list_empty(&thread->ctx->pending_handlers)) {
- h = list_entry(thread->ctx->pending_handlers.next, typeof(*h), entry2);
- list_del(&h->entry2);
- h->pending = 0;
- spin_unlock(&thread->ctx->lock);
-
- if (h->trig_epoll_events & (EPOLLIN | EPOLLERR | EPOLLHUP))
- if (h->ud->read)
- if (h->ud->read(h->ud))
- continue;
- if (h->trig_epoll_events & (EPOLLOUT | EPOLLERR | EPOLLHUP))
- if (h->ud->write)
- if (h->ud->write(h->ud))
- continue;
- h->trig_epoll_events = 0;
- continue;
- }
- thread->ctx->thread = NULL;
- spin_unlock(&thread->ctx->lock);
- if (thread->ctx->need_free)
- mempool_free(thread->ctx);
- thread->ctx = NULL;
- break;
+ if (swapcontext(&thread->uctx, &thread->ctx->uctx)) {
+ triton_log_error("swapcontext: %s\n", strerror(errno));
}
+ if (thread->ctx->need_free)
+ mempool_free(thread->ctx);
+ thread->ctx = NULL;
+
spin_lock(&threads_lock);
if (!list_empty(&ctx_queue)) {
thread->ctx = list_entry(ctx_queue.next, typeof(*thread->ctx), entry2);
@@ -106,6 +70,55 @@ cont:
}
}
+static void ctx_thread(struct _triton_context_t *ctx)
+{
+ struct _triton_md_handler_t *h;
+ struct _triton_timer_t *t;
+ uint64_t tt;
+ ucontext_t *uctx;
+
+ while (1) {
+ uctx = &ctx->thread->uctx;
+ if (ctx->need_close) {
+ if (ctx->ud->close)
+ ctx->ud->close(ctx->ud);
+ ctx->need_close = 0;
+ }
+
+ while (1) {
+ spin_lock(&ctx->lock);
+ if (!list_empty(&ctx->pending_timers)) {
+ t = list_entry(ctx->pending_timers.next, typeof(*t), entry2);
+ list_del(&t->entry2);
+ t->pending = 0;
+ spin_unlock(&ctx->lock);
+ read(t->fd, &tt, sizeof(tt));
+ t->ud->expire(t->ud);
+ continue;
+ }
+ if (!list_empty(&ctx->pending_handlers)) {
+ h = list_entry(ctx->pending_handlers.next, typeof(*h), entry2);
+ list_del(&h->entry2);
+ h->pending = 0;
+ spin_unlock(&ctx->lock);
+ if (h->trig_epoll_events & (EPOLLIN | EPOLLERR | EPOLLHUP))
+ if (h->ud && h->ud->read)
+ h->ud->read(h->ud);
+ if (h->trig_epoll_events & (EPOLLOUT | EPOLLERR | EPOLLHUP))
+ if (h->ud && h->ud->write)
+ h->ud->write(h->ud);
+ h->trig_epoll_events = 0;
+ continue;
+ }
+ ctx->thread = NULL;
+ spin_unlock(&ctx->lock);
+
+ if (swapcontext(&ctx->uctx, uctx))
+ triton_log_error("swapcontext: %s\n", strerror(errno));
+ }
+ }
+}
+
struct _triton_thread_t *create_thread()
{
struct _triton_thread_t *thread = malloc(sizeof(*thread));
@@ -121,9 +134,9 @@ struct _triton_thread_t *create_thread()
return thread;
}
-int triton_queue_ctx(struct _triton_ctx_t *ctx)
+int triton_queue_ctx(struct _triton_context_t *ctx)
{
- if (ctx->thread || ctx->queued)
+ if (ctx->thread || ctx->queued || ctx->sleeping)
return 0;
spin_lock(&threads_lock);
@@ -142,9 +155,9 @@ int triton_queue_ctx(struct _triton_ctx_t *ctx)
return 1;
}
-void __export triton_register_ctx(struct triton_ctx_t *ud)
+int __export triton_context_register(struct triton_context_t *ud)
{
- struct _triton_ctx_t *ctx = mempool_alloc(ctx_pool);
+ struct _triton_context_t *ctx = mempool_alloc(ctx_pool);
memset(ctx, 0, sizeof(*ctx));
ctx->ud = ud;
@@ -154,16 +167,33 @@ void __export triton_register_ctx(struct triton_ctx_t *ud)
INIT_LIST_HEAD(&ctx->pending_handlers);
INIT_LIST_HEAD(&ctx->pending_timers);
+ if (getcontext(&ctx->uctx)) {
+ triton_log_error("getcontext: %s\n", strerror(errno));
+ free(ctx);
+ return -1;
+ }
+
+ ctx->uctx.uc_stack.ss_size = CTX_STACK_SIZE;
+ ctx->uctx.uc_stack.ss_sp = malloc(CTX_STACK_SIZE);
+ if (!ctx->uctx.uc_stack.ss_sp) {
+ triton_log_error("out of memory\n");
+ free(ctx);
+ return -1;
+ }
+ makecontext(&ctx->uctx, (void (*)())ctx_thread, 1, ctx);
+
ud->tpd = ctx;
spin_lock(&ctx_list_lock);
list_add_tail(&ctx->entry, &ctx_list);
spin_unlock(&ctx_list_lock);
+
+ return 0;
}
-void __export triton_unregister_ctx(struct triton_ctx_t *ud)
+void __export triton_context_unregister(struct triton_context_t *ud)
{
- struct _triton_ctx_t *ctx = (struct _triton_ctx_t *)ud->tpd;
+ struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd;
if (!list_empty(&ctx->handlers)) {
triton_log_error("BUG:ctx:triton_unregister_ctx: handlers is not empty");
@@ -175,6 +205,14 @@ void __export triton_unregister_ctx(struct triton_ctx_t *ud)
}
if (!list_empty(&ctx->timers)) {
triton_log_error("BUG:ctx:triton_unregister_ctx: timers is not empty");
+ {
+ struct _triton_timer_t *t;
+ while(!list_empty(&ctx->timers)) {
+ t = list_entry(ctx->timers.next, typeof(*t), entry);
+ t->ud->expire(t->ud);
+ list_del(&t->entry);
+ }
+ }
abort();
}
if (!list_empty(&ctx->pending_timers)) {
@@ -187,17 +225,43 @@ void __export triton_unregister_ctx(struct triton_ctx_t *ud)
list_del(&ctx->entry);
spin_unlock(&ctx_list_lock);
}
+void __export triton_context_schedule(struct triton_context_t *ud)
+{
+ struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd;
+ ucontext_t *uctx = &ctx->thread->uctx;
+
+ spin_lock(&ctx->lock);
+ ctx->sleeping = 1;
+ ctx->thread = NULL;
+ spin_unlock(&ctx->lock);
+
+ if (swapcontext(&ctx->uctx, uctx))
+ triton_log_error("swaswpntext: %s\n", strerror(errno));
+}
+
+void __export triton_context_wakeup(struct triton_context_t *ud)
+{
+ struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd;
+ int r;
+
+ spin_lock(&ctx->lock);
+ ctx->sleeping = 0;
+ r = triton_queue_ctx(ctx);
+ spin_unlock(&ctx->lock);
+ if (r)
+ triton_thread_wakeup(ctx->thread);
+}
int __export triton_init(const char *conf_file, const char *mod_sect)
{
- ctx_pool = mempool_create(sizeof(struct _triton_ctx_t));
+ ctx_pool = mempool_create(sizeof(struct _triton_context_t));
default_ctx = malloc(sizeof(*default_ctx));
if (!default_ctx) {
fprintf(stderr,"cann't allocate memory\n");
return -1;
}
- triton_register_ctx(default_ctx);
+ triton_context_register(default_ctx);
if (conf_load(conf_file))
return -1;
@@ -237,7 +301,7 @@ void __export triton_run()
void __export triton_terminate()
{
- struct _triton_ctx_t *ctx;
+ struct _triton_context_t *ctx;
struct _triton_thread_t *t;
md_terminate();
diff --git a/accel-pptpd/triton/triton.h b/accel-pptpd/triton/triton.h
index 2cc5ccf6..735264a8 100644
--- a/accel-pptpd/triton/triton.h
+++ b/accel-pptpd/triton/triton.h
@@ -5,11 +5,11 @@
#include "list.h"
-struct triton_ctx_t
+struct triton_context_t
{
const void *tpd; // triton private data, don't touch!
- void (*close)(struct triton_ctx_t*);
- void (*free)(struct triton_ctx_t*);
+ void (*close)(struct triton_context_t*);
+ void (*free)(struct triton_context_t*);
};
struct triton_md_handler_t
@@ -41,18 +41,19 @@ struct conf_sect_t
struct list_head items;
};
-void triton_register_ctx(struct triton_ctx_t *);
-void triton_unregister_ctx(struct triton_ctx_t *);
-void triton_ctx_schedule(struct triton_md_handler_t *, struct triton_timer_t *);
+int triton_context_register(struct triton_context_t *);
+void triton_context_unregister(struct triton_context_t *);
+void triton_context_schedule(struct triton_context_t *);
+void triton_context_wakeup(struct triton_context_t *);
#define MD_MODE_READ 1
#define MD_MODE_WRITE 2
-void triton_md_register_handler(struct triton_ctx_t *, struct triton_md_handler_t *);
+void triton_md_register_handler(struct triton_context_t *, struct triton_md_handler_t *);
void triton_md_unregister_handler(struct triton_md_handler_t *h);
int triton_md_enable_handler(struct triton_md_handler_t *h, int mode);
int triton_md_disable_handler(struct triton_md_handler_t *h,int mode);
-int triton_timer_add(struct triton_ctx_t *ctx, struct triton_timer_t*,int abs_time);
+int triton_timer_add(struct triton_context_t *ctx, struct triton_timer_t*,int abs_time);
int triton_timer_mod(struct triton_timer_t *,int abs_time);
void triton_timer_del(struct triton_timer_t *);
diff --git a/accel-pptpd/triton/triton_p.h b/accel-pptpd/triton/triton_p.h
index c31efd6e..0aa37b1f 100644
--- a/accel-pptpd/triton/triton_p.h
+++ b/accel-pptpd/triton/triton_p.h
@@ -3,43 +3,52 @@
#include <pthread.h>
#include <sys/epoll.h>
+#include <ucontext.h>
#include "triton.h"
#include "list.h"
#include "spinlock.h"
+#define CTX_STACK_SIZE 8196
+
struct _triton_thread_t
{
struct list_head entry;
struct list_head entry2;
pthread_t thread;
int terminate:1;
- struct _triton_ctx_t *ctx;
+ struct _triton_context_t *ctx;
+ ucontext_t uctx;
};
-struct _triton_ctx_t
+struct _triton_context_t
{
struct list_head entry;
struct list_head entry2;
+
spinlock_t lock;
+ struct _triton_thread_t *thread;
+
struct list_head handlers;
struct list_head timers;
-
- struct _triton_thread_t *thread;
struct list_head pending_handlers;
struct list_head pending_timers;
+
+ ucontext_t uctx;
+
int queued:1;
+ int sleeping:1;
int need_close:1;
int need_free:1;
- struct triton_ctx_t *ud;
+ struct triton_context_t *ud;
};
struct _triton_md_handler_t
{
struct list_head entry;
struct list_head entry2;
- struct _triton_ctx_t *ctx;
+ struct _triton_context_t *ctx;
struct epoll_event epoll_event;
uint32_t trig_epoll_events;
int pending:1;
@@ -51,7 +60,7 @@ struct _triton_timer_t
struct list_head entry;
struct list_head entry2;
struct epoll_event epoll_event;
- struct _triton_ctx_t *ctx;
+ struct _triton_context_t *ctx;
int fd;
int pending:1;
struct triton_timer_t *ud;
@@ -76,8 +85,8 @@ void md_run();
void md_terminate();
void timer_run();
void timer_terminate();
-struct triton_ctx_t *default_ctx;
-int triton_queue_ctx(struct _triton_ctx_t*);
+struct triton_context_t *default_ctx;
+int triton_queue_ctx(struct _triton_context_t*);
void triton_thread_wakeup(struct _triton_thread_t*);
int conf_load(const char *fname);
void triton_log_error(const char *fmt,...);