diff options
-rw-r--r-- | accel-pppd/ctrl/pppoe/pppoe.c | 135 | ||||
-rw-r--r-- | accel-pppd/ctrl/pppoe/pppoe.h | 3 | ||||
-rw-r--r-- | accel-pppd/triton/triton.c | 9 |
3 files changed, 95 insertions, 52 deletions
diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c index 4ff23052..b1445c24 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 9811d632..3b15d120 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 cdcccdb8..3c4de31d 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; |