summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel-pppd/ctrl/pppoe/pppoe.c135
-rw-r--r--accel-pppd/ctrl/pppoe/pppoe.h3
-rw-r--r--accel-pppd/triton/triton.c9
3 files changed, 95 insertions, 52 deletions
diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c
index 4ff2305..b1445c2 100644
--- a/accel-pppd/ctrl/pppoe/pppoe.c
+++ b/accel-pppd/ctrl/pppoe/pppoe.c
@@ -33,6 +33,8 @@
#include "memdebug.h"
+#define SID_MAX 128
+
struct pppoe_conn_t {
struct list_head entry;
struct triton_context_t ctx;
@@ -114,6 +116,11 @@ pthread_rwlock_t serv_lock = PTHREAD_RWLOCK_INITIALIZER;
LIST_HEAD(serv_list);
static int connlimit_loaded;
+static pthread_mutex_t sid_lock = PTHREAD_MUTEX_INITIALIZER;
+static unsigned long *sid_map;
+static unsigned long *sid_ptr;
+static int sid_idx;
+
static uint8_t bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static void pppoe_send_PADT(struct pppoe_conn_t *conn);
@@ -140,7 +147,6 @@ static void disconnect(struct pppoe_conn_t *conn)
log_ppp_info1("disconnected\n");
pthread_mutex_lock(&conn->serv->lock);
- conn->serv->conn[conn->sid] = NULL;
list_del(&conn->entry);
conn->serv->conn_cnt--;
if (conn->serv->stopping && conn->serv->conn_cnt == 0) {
@@ -148,6 +154,10 @@ static void disconnect(struct pppoe_conn_t *conn)
pppoe_server_free(conn->serv);
} else
pthread_mutex_unlock(&conn->serv->lock);
+
+ pthread_mutex_lock(&sid_lock);
+ sid_map[conn->sid/(8*sizeof(long))] |= 1 << (conn->sid % (8*sizeof(long)));
+ pthread_mutex_unlock(&sid_lock);
_free(conn->ctrl.calling_station_id);
_free(conn->ctrl.called_station_id);
@@ -214,41 +224,50 @@ static int pppoe_rad_send_accounting_request(struct rad_plugin_t *rad, struct ra
return 0;
}
#endif
-
+
static struct pppoe_conn_t *allocate_channel(struct pppoe_serv_t *serv, const uint8_t *addr, const struct pppoe_tag *host_uniq, const struct pppoe_tag *relay_sid, const struct pppoe_tag *service_name, const struct pppoe_tag *tr101, const uint8_t *cookie)
{
struct pppoe_conn_t *conn;
- int sid;
+ unsigned long *old_sid_ptr;
conn = mempool_alloc(conn_pool);
if (!conn) {
- log_emerg("pppoe: out of memory\n");
+ log_error("pppoe: out of memory\n");
return NULL;
}
memset(conn, 0, sizeof(*conn));
- pthread_mutex_lock(&serv->lock);
- for (sid = serv->sid + 1; sid != serv->sid; sid++) {
- if (sid == MAX_SID)
- sid = 1;
- if (!serv->conn[sid]) {
- conn->sid = sid;
- serv->sid = sid;
- serv->conn[sid] = conn;
- list_add_tail(&conn->entry, &serv->conn_list);
- serv->conn_cnt++;
- break;
+ pthread_mutex_lock(&sid_lock);
+ old_sid_ptr = sid_ptr;
+ while (1) {
+ int bit = ffsl(*sid_ptr) - 1;
+
+ if (bit != -1) {
+ conn->sid = sid_idx*8*sizeof(long) + bit;
+ *sid_ptr &= ~(1lu << bit);
}
+
+ if (++sid_idx == SID_MAX/8/sizeof(long)) {
+ sid_ptr = sid_map;
+ sid_idx = 0;
+ } else
+ sid_ptr++;
+
+ if (bit != -1)
+ break;
+
+ if (sid_ptr == old_sid_ptr)
+ break;
}
- pthread_mutex_unlock(&serv->lock);
+ pthread_mutex_unlock(&sid_lock);
if (!conn->sid) {
log_warn("pppoe: no free sid available\n");
mempool_free(conn);
return NULL;
}
-
+
conn->serv = serv;
memcpy(conn->addr, addr, ETH_ALEN);
@@ -340,14 +359,14 @@ static struct pppoe_conn_t *allocate_channel(struct pppoe_serv_t *serv, const ui
if (conf_ip_pool)
conn->ppp.ses.ipv4_pool_name = _strdup(conf_ip_pool);
- triton_context_register(&conn->ctx, &conn->ppp.ses);
- triton_context_wakeup(&conn->ctx);
-
- triton_event_fire(EV_CTRL_STARTING, &conn->ppp.ses);
- triton_event_fire(EV_CTRL_STARTED, &conn->ppp.ses);
-
conn->disc_sock = dup(serv->hnd.fd);
+
+ triton_context_register(&conn->ctx, &conn->ppp.ses);
+ pthread_mutex_lock(&serv->lock);
+ list_add_tail(&conn->entry, &serv->conn_list);
+ pthread_mutex_unlock(&serv->lock);
+
return conn;
}
@@ -355,6 +374,9 @@ static void connect_channel(struct pppoe_conn_t *conn)
{
int sock;
struct sockaddr_pppox sp;
+
+ triton_event_fire(EV_CTRL_STARTING, &conn->ppp.ses);
+ triton_event_fire(EV_CTRL_STARTED, &conn->ppp.ses);
sock = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE);
if (!sock) {
@@ -1078,6 +1100,7 @@ static void pppoe_recv_PADR(struct pppoe_serv_t *serv, uint8_t *pack, int size)
else {
pppoe_send_PADS(conn);
triton_context_call(&conn->ctx, (triton_event_func)connect_channel, conn);
+ triton_context_wakeup(&conn->ctx);
}
}
@@ -1086,6 +1109,7 @@ static void pppoe_recv_PADT(struct pppoe_serv_t *serv, uint8_t *pack)
struct ethhdr *ethhdr = (struct ethhdr *)pack;
struct pppoe_hdr *hdr = (struct pppoe_hdr *)(pack + ETH_HLEN);
struct pppoe_conn_t *conn;
+ uint16_t sid = ntohs(hdr->sid);
if (!memcmp(ethhdr->h_dest, bc_addr, ETH_ALEN)) {
if (conf_verbose)
@@ -1099,9 +1123,13 @@ static void pppoe_recv_PADT(struct pppoe_serv_t *serv, uint8_t *pack)
}
pthread_mutex_lock(&serv->lock);
- conn = serv->conn[ntohs(hdr->sid)];
- if (conn && !memcmp(conn->addr, ethhdr->h_source, ETH_ALEN))
- triton_context_call(&conn->ctx, (void (*)(void *))disconnect, conn);
+ list_for_each_entry(conn, &serv->conn_list, entry) {
+ if (conn->sid == sid) {
+ if (!memcmp(conn->addr, ethhdr->h_source, ETH_ALEN))
+ triton_context_call(&conn->ctx, (void (*)(void *))disconnect, conn);
+ break;
+ }
+ }
pthread_mutex_unlock(&serv->lock);
}
@@ -1316,7 +1344,7 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli)
if (sock < 0) {
if (cli)
cli_sendv(cli, "socket: %s\r\n", strerror(errno));
- log_emerg("pppoe: socket: %s\n", strerror(errno));
+ log_error("pppoe: socket: %s\n", strerror(errno));
_free(serv);
return;
}
@@ -1326,7 +1354,7 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli)
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &f, sizeof(f))) {
if (cli)
cli_sendv(cli, "setsockopt(SO_BROADCAST): %s\r\n", strerror(errno));
- log_emerg("pppoe: setsockopt(SO_BROADCAST): %s\n", strerror(errno));
+ log_error("pppoe: setsockopt(SO_BROADCAST): %s\n", strerror(errno));
goto out_err;
}
@@ -1334,13 +1362,13 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli)
if (ioctl(sock, SIOCGIFHWADDR, &ifr)) {
if (cli)
cli_sendv(cli, "ioctl(SIOCGIFHWADDR): %s\r\n", strerror(errno));
- log_emerg("pppoe: ioctl(SIOCGIFHWADDR): %s\n", strerror(errno));
+ log_error("pppoe: ioctl(SIOCGIFHWADDR): %s\n", strerror(errno));
goto out_err;
}
#ifdef ARPHDR_ETHER
if (ifr.ifr_hwaddr.sa_family != ARPHDR_ETHER) {
- log_emerg("pppoe: interface %s is not ethernet\n", ifname);
+ log_error("pppoe: interface %s is not ethernet\n", ifname);
goto out_err;
}
#endif
@@ -1348,7 +1376,7 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli)
if ((ifr.ifr_hwaddr.sa_data[0] & 1) != 0) {
if (cli)
cli_sendv(cli, "interface %s has not unicast address\r\n", ifname);
- log_emerg("pppoe: interface %s has not unicast address\n", ifname);
+ log_error("pppoe: interface %s has not unicast address\n", ifname);
goto out_err;
}
@@ -1357,20 +1385,20 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli)
if (ioctl(sock, SIOCGIFMTU, &ifr)) {
if (cli)
cli_sendv(cli, "ioctl(SIOCGIFMTU): %s\r\n", strerror(errno));
- log_emerg("pppoe: ioctl(SIOCGIFMTU): %s\n", strerror(errno));
+ log_error("pppoe: ioctl(SIOCGIFMTU): %s\n", strerror(errno));
goto out_err;
}
if (ifr.ifr_mtu < ETH_DATA_LEN) {
if (cli)
cli_sendv(cli, "interface %s has MTU of %i, should be %i\r\n", ifname, ifr.ifr_mtu, ETH_DATA_LEN);
- log_emerg("pppoe: interface %s has MTU of %i, should be %i\n", ifname, ifr.ifr_mtu, ETH_DATA_LEN);
+ log_error("pppoe: interface %s has MTU of %i, should be %i\n", ifname, ifr.ifr_mtu, ETH_DATA_LEN);
}
if (ioctl(sock, SIOCGIFINDEX, &ifr)) {
if (cli)
cli_sendv(cli, "ioctl(SIOCGIFINDEX): %s\r\n", strerror(errno));
- log_emerg("pppoe: ioctl(SIOCGIFINDEX): %s\n", strerror(errno));
+ log_error("pppoe: ioctl(SIOCGIFINDEX): %s\n", strerror(errno));
goto out_err;
}
@@ -1382,14 +1410,14 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli)
if (bind(sock, (struct sockaddr *)&sa, sizeof(sa))) {
if (cli)
cli_sendv(cli, "bind: %s\n", strerror(errno));
- log_emerg("pppoe: bind: %s\n", strerror(errno));
+ log_error("pppoe: bind: %s\n", strerror(errno));
goto out_err;
}
if (fcntl(sock, F_SETFL, O_NONBLOCK)) {
if (cli)
cli_sendv(cli, "failed to set nonblocking mode: %s\n", strerror(errno));
- log_emerg("pppoe: failed to set nonblocking mode: %s\n", strerror(errno));
+ log_error("pppoe: failed to set nonblocking mode: %s\n", strerror(errno));
goto out_err;
}
@@ -1491,7 +1519,7 @@ static int init_secret(struct pppoe_serv_t *serv)
DES_cblock key;
if (read(urandom_fd, serv->secret, SECRET_LENGTH) < 0) {
- log_emerg("pppoe: failed to read /dev/urandom: %s\n", strerror(errno));
+ log_error("pppoe: failed to read /dev/urandom: %s\n", strerror(errno));
return -1;
}
@@ -1595,11 +1623,29 @@ static void load_config(void)
}
}
-static void pppoe_init(void)
+static void load_interfaces()
{
struct conf_sect_t *s = conf_get_section("pppoe");
struct conf_option_t *opt;
+
+ list_for_each_entry(opt, &s->items, entry) {
+ if (!strcmp(opt->name, "interface")) {
+ if (opt->val)
+ pppoe_server_start(opt->val, NULL);
+ }
+ }
+}
+
+static void pppoe_init(void)
+{
int fd;
+ uint8_t *ptr;
+
+ ptr = malloc(SID_MAX/8);
+ memset(ptr, 0xff, SID_MAX/8);
+ ptr[0] = 0xfe;
+ ptr[SID_MAX/8-1] = 0x7f;
+ sid_ptr = sid_map = (unsigned long *)ptr;
fd = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE);
if (fd >= 0)
@@ -1611,23 +1657,18 @@ static void pppoe_init(void)
pado_pool = mempool_create(sizeof(struct delayed_pado_t));
padi_pool = mempool_create(sizeof(struct padi_t));
- if (!s) {
- log_emerg("pppoe: no configuration, disabled...\n");
+ if (!conf_get_section("pppoe")) {
+ log_error("pppoe: no configuration, disabled...\n");
return;
}
- list_for_each_entry(opt, &s->items, entry) {
- if (!strcmp(opt->name, "interface")) {
- if (opt->val)
- pppoe_server_start(opt->val, NULL);
- }
- }
-
load_config();
connlimit_loaded = triton_module_loaded("connlimit");
triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config);
+
+ triton_context_call(NULL, (triton_event_func)load_interfaces, NULL);
}
DEFINE_INIT(21, pppoe_init);
diff --git a/accel-pppd/ctrl/pppoe/pppoe.h b/accel-pppd/ctrl/pppoe/pppoe.h
index 9811d63..3b15d12 100644
--- a/accel-pppd/ctrl/pppoe/pppoe.h
+++ b/accel-pppd/ctrl/pppoe/pppoe.h
@@ -43,7 +43,6 @@
#define VENDOR_ADSL_FORUM 0xde9
-#define MAX_SID 65534
#define SECRET_LENGTH 16
#define COOKIE_LENGTH 24
@@ -75,8 +74,6 @@ struct pppoe_serv_t
DES_key_schedule des_ks;
pthread_mutex_t lock;
- struct pppoe_conn_t *conn[MAX_SID];
- uint16_t sid;
int stopping:1;
unsigned int conn_cnt;
diff --git a/accel-pppd/triton/triton.c b/accel-pppd/triton/triton.c
index cdcccdb..3c4de31 100644
--- a/accel-pppd/triton/triton.c
+++ b/accel-pppd/triton/triton.c
@@ -485,13 +485,18 @@ void __export triton_context_wakeup(struct triton_context_t *ud)
int __export triton_context_call(struct triton_context_t *ud, void (*func)(void *), void *arg)
{
- struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd;
+ struct _triton_context_t *ctx;
struct _triton_ctx_call_t *call = mempool_alloc(call_pool);
int r;
if (!call)
return -1;
-
+
+ if (ud)
+ ctx = (struct _triton_context_t *)ud->tpd;
+ else
+ ctx = (struct _triton_context_t *)default_ctx.tpd;
+
call->func = func;
call->arg = arg;