diff options
Diffstat (limited to 'accel-pptpd/ctrl/pppoe')
-rw-r--r-- | accel-pptpd/ctrl/pppoe/CMakeLists.txt | 17 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pppoe/cli.c | 205 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pppoe/dpado.c | 162 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pppoe/mac_filter.c | 255 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pppoe/pppoe.c | 1288 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pppoe/pppoe.h | 117 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pppoe/tr101.c | 97 |
7 files changed, 0 insertions, 2141 deletions
diff --git a/accel-pptpd/ctrl/pppoe/CMakeLists.txt b/accel-pptpd/ctrl/pppoe/CMakeLists.txt deleted file mode 100644 index f047936..0000000 --- a/accel-pptpd/ctrl/pppoe/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) - -SET(sources - pppoe.c - mac_filter.c - dpado.c - cli.c -) - -IF (RADIUS) -SET(sources ${sources} tr101.c) -ENDIF(RADIUS) - -ADD_LIBRARY(pppoe SHARED ${sources}) -TARGET_LINK_LIBRARIES(pppoe crypto) - -INSTALL(TARGETS pppoe LIBRARY DESTINATION lib/accel-pptp) diff --git a/accel-pptpd/ctrl/pppoe/cli.c b/accel-pptpd/ctrl/pppoe/cli.c deleted file mode 100644 index 9929f66..0000000 --- a/accel-pptpd/ctrl/pppoe/cli.c +++ /dev/null @@ -1,205 +0,0 @@ -#include <string.h> -#include <stdlib.h> -#include <netinet/in.h> -#include <net/ethernet.h> - -#include "triton.h" -#include "cli.h" -#include "ppp.h" -#include "memdebug.h" - -#include "pppoe.h" - -static void show_interfaces(void *cli) -{ - struct pppoe_serv_t *serv; - - cli_send(cli, "interface: connections: state:\r\n"); - cli_send(cli, "-----------------------------------\r\n"); - - pthread_rwlock_rdlock(&serv_lock); - list_for_each_entry(serv, &serv_list, entry) { - cli_sendv(cli, "%9s %11u %6s\r\n", serv->ifname, serv->conn_cnt, serv->stopping ? "stop" : "active"); - } - pthread_rwlock_unlock(&serv_lock); -} - -static void intf_help(char * const *fields, int fields_cnt, void *client) -{ - cli_send(client, "pppoe interface add <name> - start pppoe server on specified interface\r\n"); - cli_send(client, "pppoe interface del <name> - stop pppoe server on specified interface and drop his connections\r\n"); - cli_send(client, "pppoe interface show - show interfaces on which pppoe server started\r\n"); -} - -static int intf_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) -{ - if (fields_cnt == 2) - goto help; - - if (fields_cnt == 3) { - if (!strcmp(fields[2], "show")) - show_interfaces(client); - else - goto help; - - return CLI_CMD_OK; - } - - if (fields_cnt != 4) - goto help; - - if (!strcmp(fields[2], "add")) - pppoe_server_start(fields[3], client); - else if (!strcmp(fields[2], "del")) - pppoe_server_stop(fields[3]); - else - goto help; - - return CLI_CMD_OK; -help: - intf_help(fields, fields_cnt, client); - return CLI_CMD_OK; -} - -//=================================== - -static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) -{ - cli_send(client, "pppoe:\r\n"); - cli_sendv(client, " active: %u\r\n", stat_active); - cli_sendv(client, " delayed PADO: %u\r\n", stat_delayed_pado); - cli_sendv(client, " recv PADI: %lu\r\n", stat_PADI_recv); - cli_sendv(client, " sent PADO: %lu\r\n", stat_PADO_sent); - cli_sendv(client, " recv PADR(dup): %lu(%lu)\r\n", stat_PADR_recv, stat_PADR_dup_recv); - cli_sendv(client, " sent PADS: %lu\r\n", stat_PADS_sent); - - return CLI_CMD_OK; -} - -//=================================== - -static void set_verbose_help(char * const *f, int f_cnt, void *cli) -{ - cli_send(cli, "pppoe set verbose <n> - set verbosity of pppoe logging\r\n"); - cli_send(cli, "pppoe set PADO-delay <delay[,delay1:count1[,delay2:count2[,...]]]> - set PADO delays (ms)\r\n"); - cli_send(cli, "pppoe set Service-Name <name> - set Service-Name to respond\r\n"); - cli_send(cli, "pppoe set Service-Name * - respond with client's Service-Name\r\n"); - cli_send(cli, "pppoe set AC-Name <name> - set AC-Name tag value\r\n"); - cli_send(cli, "pppoe show verbose - show current verbose value\r\n"); - cli_send(cli, "pppoe show PADO-delay - show current PADO delay value\r\n"); - cli_send(cli, "pppoe show Service-Name - show current Service-Name value\r\n"); - cli_send(cli, "pppoe show AC-Name - show current AC-Name tag value\r\n"); -} - -static int show_verbose_exec(const char *cmd, char * const *f, int f_cnt, void *cli) -{ - if (f_cnt != 3) - return CLI_CMD_SYNTAX; - - cli_sendv(cli, "%i\r\n", conf_verbose); - - return CLI_CMD_OK; -} - -static int show_pado_delay_exec(const char *cmd, char * const *f, int f_cnt, void *cli) -{ - if (f_cnt != 3) - return CLI_CMD_SYNTAX; - - cli_sendv(cli, "%s\r\n", conf_pado_delay); - - return CLI_CMD_OK; -} - -static int show_service_name_exec(const char *cmd, char * const *f, int f_cnt, void *cli) -{ - if (f_cnt != 3) - return CLI_CMD_SYNTAX; - - if (conf_service_name) - cli_sendv(cli, "%s\r\n", conf_service_name); - else - cli_sendv(cli, "*\r\n", conf_service_name); - - return CLI_CMD_OK; -} - -static int show_ac_name_exec(const char *cmd, char * const *f, int f_cnt, void *cli) -{ - if (f_cnt != 3) - return CLI_CMD_SYNTAX; - - cli_sendv(cli, "%s\r\n", conf_ac_name); - - return CLI_CMD_OK; -} - -static int set_verbose_exec(const char *cmd, char * const *f, int f_cnt, void *cli) -{ - if (f_cnt != 4) - return CLI_CMD_SYNTAX; - - if (!strcmp(f[3], "0")) - conf_verbose = 0; - else if (!strcmp(f[3], "1")) - conf_verbose = 1; - else - return CLI_CMD_INVAL; - - return CLI_CMD_OK; -} - -static int set_pado_delay_exec(const char *cmd, char * const *f, int f_cnt, void *cli) -{ - if (f_cnt != 4) - return CLI_CMD_SYNTAX; - - if (dpado_parse(f[3])) - return CLI_CMD_INVAL; - - return CLI_CMD_OK; -} - -static int set_service_name_exec(const char *cmd, char * const *f, int f_cnt, void *cli) -{ - if (f_cnt != 4) - return CLI_CMD_SYNTAX; - - if (conf_service_name) - _free(conf_service_name); - - if (!strcmp(f[3], "*")) - conf_service_name = NULL; - else - conf_service_name = _strdup(f[3]); - - return CLI_CMD_OK; -} - -static int set_ac_name_exec(const char *cmd, char * const *f, int f_cnt, void *cli) -{ - if (f_cnt != 4) - return CLI_CMD_SYNTAX; - - _free(conf_ac_name); - conf_ac_name = _strdup(f[3]); - - return CLI_CMD_OK; -} -//=================================== - - -static void __init init(void) -{ - cli_register_simple_cmd2(show_stat_exec, NULL, 2, "show", "stat"); - cli_register_simple_cmd2(intf_exec, intf_help, 2, "pppoe", "interface"); - cli_register_simple_cmd2(set_verbose_exec, set_verbose_help, 3, "pppoe", "set", "verbose"); - cli_register_simple_cmd2(set_pado_delay_exec, NULL, 3, "pppoe", "set", "PADO-delay"); - cli_register_simple_cmd2(set_service_name_exec, NULL, 3, "pppoe", "set", "Service-Name"); - cli_register_simple_cmd2(set_ac_name_exec, NULL, 3, "pppoe", "set", "AC-Name"); - cli_register_simple_cmd2(show_verbose_exec, NULL, 3, "pppoe", "show", "verbose"); - cli_register_simple_cmd2(show_pado_delay_exec, NULL, 3, "pppoe", "show", "PADO-delay"); - cli_register_simple_cmd2(show_service_name_exec, NULL, 3, "pppoe", "show", "Service-Name"); - cli_register_simple_cmd2(show_ac_name_exec, NULL, 3, "pppoe", "show", "AC-Name"); -} - diff --git a/accel-pptpd/ctrl/pppoe/dpado.c b/accel-pptpd/ctrl/pppoe/dpado.c deleted file mode 100644 index 3f56519..0000000 --- a/accel-pptpd/ctrl/pppoe/dpado.c +++ /dev/null @@ -1,162 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include <pthread.h> -#include <errno.h> -#include <limits.h> -#include <netinet/in.h> -#include <net/ethernet.h> - -#include "list.h" -#include "cli.h" -#include "triton.h" -#include "log.h" -#include "memdebug.h" - -#include "pppoe.h" - -struct dpado_range_t -{ - struct list_head entry; - unsigned int conn_cnt; - int pado_delay; -}; - -static pthread_mutex_t dpado_range_lock = PTHREAD_MUTEX_INITIALIZER; -static LIST_HEAD(dpado_range_list); -static struct dpado_range_t *dpado_range_next; -static struct dpado_range_t *dpado_range_prev; -int pado_delay; - -void dpado_check_next(int conn_cnt) -{ - pthread_mutex_lock(&dpado_range_lock); - if (dpado_range_next && conn_cnt == dpado_range_next->conn_cnt) { - pado_delay = dpado_range_next->pado_delay; - dpado_range_prev = dpado_range_next; - if (dpado_range_next->entry.next != &dpado_range_list) - dpado_range_next = list_entry(dpado_range_next->entry.next, typeof(*dpado_range_next), entry); - else - dpado_range_next = NULL; - /*printf("active=%i, prev=%i:%i, next=%i:%i, pado_delay=%i\n", stat_active, - dpado_range_prev?dpado_range_prev->pado_delay:0,dpado_range_prev?dpado_range_prev->conn_cnt:0, - dpado_range_next?dpado_range_next->pado_delay:0,dpado_range_next?dpado_range_next->conn_cnt:0, - pado_delay);*/ - } - pthread_mutex_unlock(&dpado_range_lock); -} - -void dpado_check_prev(int conn_cnt) -{ - pthread_mutex_lock(&dpado_range_lock); - if (dpado_range_prev && conn_cnt == dpado_range_prev->conn_cnt) { - dpado_range_next = dpado_range_prev; - dpado_range_prev = list_entry(dpado_range_prev->entry.prev, typeof(*dpado_range_prev), entry); - pado_delay = dpado_range_prev->pado_delay; - /*printf("active=%i, prev=%i:%i, next=%i:%i, pado_delay=%i\n", stat_active, - dpado_range_prev?dpado_range_prev->pado_delay:0,dpado_range_prev?dpado_range_prev->conn_cnt:0, - dpado_range_next?dpado_range_next->pado_delay:0,dpado_range_next?dpado_range_next->conn_cnt:0, - pado_delay);*/ - } - pthread_mutex_unlock(&dpado_range_lock); -} - -static void strip(char *str) -{ - char *ptr = str; - char *endptr = strchr(str, 0); - while (1) { - ptr = strchr(ptr, ' '); - if (ptr) - memmove(ptr, ptr + 1, endptr - ptr - 1); - else - break; - } -} - -int dpado_parse(const char *str) -{ - char *str1 = _strdup(str); - char *ptr1, *ptr2, *ptr3, *endptr; - LIST_HEAD(range_list); - struct dpado_range_t *r; - - strip(str1); - - ptr1 = str1; - - while (1) { - ptr2 = strchr(ptr1, ','); - if (ptr2) - *ptr2 = 0; - ptr3 = strchr(ptr1, ':'); - if (ptr3) - *ptr3 = 0; - - r = _malloc(sizeof(*r)); - memset(r, 0, sizeof(*r)); - - r->pado_delay = strtol(ptr1, &endptr, 10); - if (*endptr) - goto out_err; - - if (list_empty(&range_list)) - r->conn_cnt = INT_MAX; - else { - if (!ptr3) - goto out_err; - r->conn_cnt = strtol(ptr3 + 1, &endptr, 10); - if (*endptr) - goto out_err; - } - - list_add_tail(&r->entry, &range_list); - //printf("parsed range: %i:%i\n", r->pado_delay, r->conn_cnt); - - if (!ptr2) - break; - - ptr1 = ptr2 + 1; - } - - pthread_mutex_lock(&dpado_range_lock); - while (!list_empty(&dpado_range_list)) { - r = list_entry(dpado_range_list.next, typeof(*r), entry); - list_del(&r->entry); - _free(r); - } - - dpado_range_next = NULL; - dpado_range_prev = NULL; - - while (!list_empty(&range_list)) { - r = list_entry(range_list.next, typeof(*r), entry); - list_del(&r->entry); - list_add_tail(&r->entry, &dpado_range_list); - - if (!dpado_range_prev || stat_active >= r->conn_cnt) - dpado_range_prev = r; - else if (!dpado_range_next) - dpado_range_next = r; - } - - pado_delay = dpado_range_prev->pado_delay; - - if (conf_pado_delay) - _free(conf_pado_delay); - conf_pado_delay = _strdup(str); - /*printf("active=%i, prev=%i:%i, next=%i:%i, pado_delay=%i\n", stat_active, - dpado_range_prev?dpado_range_prev->pado_delay:0,dpado_range_prev?dpado_range_prev->conn_cnt:0, - dpado_range_next?dpado_range_next->pado_delay:0,dpado_range_next?dpado_range_next->conn_cnt:0, - pado_delay);*/ - - pthread_mutex_unlock(&dpado_range_lock); - - _free(str1); - return 0; - -out_err: - _free(str1); - log_emerg("pppoe: pado_delay: invalid format\n"); - return -1; -} - diff --git a/accel-pptpd/ctrl/pppoe/mac_filter.c b/accel-pptpd/ctrl/pppoe/mac_filter.c deleted file mode 100644 index 9b101c6..0000000 --- a/accel-pptpd/ctrl/pppoe/mac_filter.c +++ /dev/null @@ -1,255 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include <pthread.h> -#include <errno.h> -#include <netinet/in.h> -#include <net/ethernet.h> - -#include "list.h" -#include "cli.h" -#include "triton.h" -#include "log.h" -#include "ppp.h" -#include "memdebug.h" - -#include "pppoe.h" - -struct mac_t -{ - struct list_head entry; - uint8_t addr[ETH_ALEN]; -}; - -static LIST_HEAD(mac_list); -static int type; // -1 - disabled, 1 - allow, 0 - denied -static pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER; -static const char *conf_mac_filter; - -int mac_filter_check(const uint8_t *addr) -{ - struct mac_t *mac; - int res = type; - - if (type == -1) - return 0; - - pthread_rwlock_rdlock(&lock); - list_for_each_entry(mac, &mac_list, entry) { - if (memcmp(mac->addr, addr, ETH_ALEN)) - continue; - res = !type; - break; - } - pthread_rwlock_unlock(&lock); - - return res; -} - -static int mac_filter_load(const char *opt) -{ - struct mac_t *mac; - FILE *f; - char *c; - char *name = _strdup(opt); - char *buf = _malloc(1024); - int n[ETH_ALEN]; - int i, line = 0; - - c = strstr(name, ","); - if (!c) - goto err_inval; - - *c = 0; - - if (!strcmp(c + 1, "allow")) - type = 1; - else if (!strcmp(c + 1, "deny")) - type = 0; - else - goto err_inval; - - f = fopen(name, "r"); - if (!f) { - log_emerg("pppoe: open '%s': %s\n", name, strerror(errno)); - goto err; - } - - conf_mac_filter = opt; - - pthread_rwlock_wrlock(&lock); - while (!list_empty(&mac_list)) { - mac = list_entry(mac_list.next, typeof(*mac), entry); - list_del(&mac->entry); - _free(mac); - } - - while (fgets(buf, 1024, f)) { - line++; - if (buf[0] == '#' || buf[0] == ';' || buf[0] == '\n') - continue; - if (sscanf(buf, "%x:%x:%x:%x:%x:%x", - n + 0, n + 1, n + 2, n + 3, n + 4, n + 5) != 6) { - log_warn("pppoe: mac-filter:%s:%i: address is invalid\n", name, line); - continue; - } - mac = _malloc(sizeof(*mac)); - for (i = 0; i < ETH_ALEN; i++) { - if (n[i] > 255) { - log_warn("pppoe: mac-filter:%s:%i: address is invalid\n", name, line); - _free(mac); - continue; - } - mac->addr[i] = n[i]; - } - list_add_tail(&mac->entry, &mac_list); - } - pthread_rwlock_unlock(&lock); - - fclose(f); - - _free(name); - _free(buf); - - return 0; - -err_inval: - log_emerg("pppoe: mac-filter format is invalid\n"); -err: - _free(name); - _free(buf); - return -1; -} - -static void mac_filter_add(const char *addr, void *client) -{ - int n[ETH_ALEN]; - struct mac_t *mac; - int i; - - if (sscanf(addr, "%x:%x:%x:%x:%x:%x", - n + 0, n + 1, n + 2, n + 3, n + 4, n + 5) != 6) { - cli_send(client, "invalid format\r\n"); - return; - } - - mac = _malloc(sizeof(*mac)); - for (i = 0; i < ETH_ALEN; i++) { - if (n[i] > 255) { - _free(mac); - cli_send(client, "invalid format\r\n"); - return; - } - mac->addr[i] = n[i]; - } - - pthread_rwlock_wrlock(&lock); - list_add_tail(&mac->entry, &mac_list); - pthread_rwlock_unlock(&lock); -} - -static void mac_filter_del(const char *addr, void *client) -{ - int n[ETH_ALEN]; - uint8_t a[ETH_ALEN]; - struct mac_t *mac; - int i; - int found = 0; - - if (sscanf(addr, "%x:%x:%x:%x:%x:%x", - n + 0, n + 1, n + 2, n + 3, n + 4, n + 5) != 6) { - cli_send(client, "invalid format\r\n"); - return; - } - - for (i = 0; i < ETH_ALEN; i++) { - if (n[i] > 255) { - cli_send(client, "invalid format\r\n"); - return; - } - a[i] = n[i]; - } - - pthread_rwlock_wrlock(&lock); - list_for_each_entry(mac, &mac_list, entry) { - if (memcmp(a, mac->addr, ETH_ALEN)) - continue; - list_del(&mac->entry); - _free(mac); - found = 1; - break; - } - pthread_rwlock_unlock(&lock); - - if (!found) - cli_send(client, "not found\r\n"); -} - -static void mac_filter_show(void *client) -{ - struct mac_t *mac; - const char *filter_type; - - if (type == 0) - filter_type = "deny"; - else if (type == 1) - filter_type = "allow"; - else - filter_type = "disabled"; - - cli_sendv(client, "filter type: %s\r\n", filter_type); - - pthread_rwlock_rdlock(&lock); - list_for_each_entry(mac, &mac_list, entry) { - cli_sendv(client, "%02x:%02x:%02x:%02x:%02x:%02x\r\n", - mac->addr[0], mac->addr[1], mac->addr[2], - mac->addr[3], mac->addr[4], mac->addr[5]); - } - pthread_rwlock_unlock(&lock); -} - -static void cmd_help(char * const *fields, int fields_cnt, void *client); -static int cmd_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) -{ - if (fields_cnt == 2) - goto help; - - if (!strcmp(fields[2], "reload")) { - if (!conf_mac_filter) - cli_send(client, "error: mac-filter was not specified in the config\r\n"); - else if (mac_filter_load(conf_mac_filter)) - cli_send(client, "error: check logs\r\n"); - } else if (!strcmp(fields[2], "add")) { - if (fields_cnt != 4) - goto help; - mac_filter_add(fields[3], client); - } else if (!strcmp(fields[2], "del")) { - if (fields_cnt != 4) - goto help; - mac_filter_del(fields[3], client); - } else if (!strcmp(fields[2], "show")) { - mac_filter_show(client); - } - - return CLI_CMD_OK; -help: - cmd_help(fields, fields_cnt, client); - return CLI_CMD_OK; -} - -static void cmd_help(char * const *fields, int fields_cnt, void *client) -{ - cli_send(client, "pppoe mac-filter reload - reload mac-filter file\r\n"); - cli_send(client, "pppoe mac-filter add <address> - add address to mac-filter list\r\n"); - cli_send(client, "pppoe mac-filter del <address> - delete address from mac-filter list\r\n"); - cli_send(client, "pppoe mac-filter show - show current mac-filter list\r\n"); -} - -static void __init init(void) -{ - const char *opt = conf_get_opt("pppoe", "mac-filter"); - if (!opt || mac_filter_load(opt)) - type = -1; - - cli_register_simple_cmd2(cmd_exec, cmd_help, 2, "pppoe", "mac-filter"); -} - diff --git a/accel-pptpd/ctrl/pppoe/pppoe.c b/accel-pptpd/ctrl/pppoe/pppoe.c deleted file mode 100644 index 95ae394..0000000 --- a/accel-pptpd/ctrl/pppoe/pppoe.c +++ /dev/null @@ -1,1288 +0,0 @@ -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <errno.h> -#include <string.h> -#include <pthread.h> -#include <fcntl.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <net/ethernet.h> -#include <netpacket/packet.h> -#include <arpa/inet.h> -#include <printf.h> - -#include <openssl/md5.h> - -#include "events.h" -#include "triton.h" -#include "log.h" -#include "ppp.h" -#include "mempool.h" -#include "cli.h" - -#ifdef RADIUS -#include "radius.h" -#endif - -#include "pppoe.h" - -#include "memdebug.h" - -struct pppoe_conn_t -{ - struct list_head entry; - struct triton_context_t ctx; - struct pppoe_serv_t *serv; - int disc_sock; - uint16_t sid; - uint8_t addr[ETH_ALEN]; - int ppp_started:1; - - struct pppoe_tag *relay_sid; - struct pppoe_tag *host_uniq; - struct pppoe_tag *service_name; - struct pppoe_tag *tr101; - uint8_t cookie[COOKIE_LENGTH]; - - struct ppp_ctrl_t ctrl; - struct ppp_t ppp; -#ifdef RADIUS - struct rad_plugin_t radius; -#endif -}; - -struct delayed_pado_t -{ - struct list_head entry; - struct triton_timer_t timer; - struct pppoe_serv_t *serv; - uint8_t addr[ETH_ALEN]; - struct pppoe_tag *host_uniq; - struct pppoe_tag *relay_sid; - struct pppoe_tag *service_name; -}; - -int conf_verbose; -char *conf_service_name; -char *conf_ac_name; -int conf_ifname_in_sid; -char *conf_pado_delay; - -static mempool_t conn_pool; -static mempool_t pado_pool; - -unsigned int stat_active; -unsigned int stat_delayed_pado; -unsigned long stat_PADI_recv; -unsigned long stat_PADO_sent; -unsigned long stat_PADR_recv; -unsigned long stat_PADR_dup_recv; -unsigned long stat_PADS_sent; - -pthread_rwlock_t serv_lock = PTHREAD_RWLOCK_INITIALIZER; -LIST_HEAD(serv_list); - -static uint8_t bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - -static void pppoe_send_PADT(struct pppoe_conn_t *conn); -static void _server_stop(struct pppoe_serv_t *serv); -void pppoe_server_free(struct pppoe_serv_t *serv); -static int init_secret(struct pppoe_serv_t *serv); - -static void disconnect(struct pppoe_conn_t *conn) -{ - if (conn->ppp_started) { - dpado_check_prev(__sync_fetch_and_sub(&stat_active, 1)); - conn->ppp_started = 0; - ppp_terminate(&conn->ppp, TERM_USER_REQUEST, 1); - } - - pppoe_send_PADT(conn); - - close(conn->disc_sock); - - - triton_event_fire(EV_CTRL_FINISHED, &conn->ppp); - - 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) { - pthread_mutex_unlock(&conn->serv->lock); - pppoe_server_free(conn->serv); - } else - pthread_mutex_unlock(&conn->serv->lock); - - _free(conn->ctrl.calling_station_id); - _free(conn->ctrl.called_station_id); - _free(conn->service_name); - if (conn->host_uniq) - _free(conn->host_uniq); - if (conn->relay_sid) - _free(conn->relay_sid); - - triton_context_unregister(&conn->ctx); - - mempool_free(conn); -} - -static void ppp_started(struct ppp_t *ppp) -{ - log_ppp_debug("pppoe: ppp started\n"); -} - -static void ppp_finished(struct ppp_t *ppp) -{ - struct pppoe_conn_t *conn = container_of(ppp, typeof(*conn), ppp); - - log_ppp_debug("pppoe: ppp finished\n"); - - if (conn->ppp_started) { - dpado_check_prev(__sync_fetch_and_sub(&stat_active, 1)); - conn->ppp_started = 0; - triton_context_call(&conn->ctx, (triton_event_func)disconnect, conn); - } -} - -static void pppoe_conn_close(struct triton_context_t *ctx) -{ - struct pppoe_conn_t *conn = container_of(ctx, typeof(*conn), ctx); - - if (conn->ppp_started) - ppp_terminate(&conn->ppp, TERM_ADMIN_RESET, 0); - else - disconnect(conn); -} - -#ifdef RADIUS -static int pppoe_rad_send_access_request(struct rad_plugin_t *rad, struct rad_packet_t *pack) -{ - struct pppoe_conn_t *conn = container_of(rad, typeof(*conn), radius); - - if (conn->tr101) - return tr101_send_access_request(conn->tr101, pack); - - return 0; -} - -static int pppoe_rad_send_accounting_request(struct rad_plugin_t *rad, struct rad_packet_t *pack) -{ - struct pppoe_conn_t *conn = container_of(rad, typeof(*conn), radius); - - if (conn->tr101) - return tr101_send_accounting_request(conn->tr101, pack); - - 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; - - conn = mempool_alloc(conn_pool); - if (!conn) { - log_emerg("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_unlock(&serv->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); - - if (host_uniq) { - conn->host_uniq = _malloc(sizeof(*host_uniq) + ntohs(host_uniq->tag_len)); - memcpy(conn->host_uniq, host_uniq, sizeof(*host_uniq) + ntohs(host_uniq->tag_len)); - } - - if (relay_sid) { - conn->relay_sid = _malloc(sizeof(*relay_sid) + ntohs(relay_sid->tag_len)); - memcpy(conn->relay_sid, relay_sid, sizeof(*relay_sid) + ntohs(relay_sid->tag_len)); - } - - if (tr101) { - conn->tr101 = _malloc(sizeof(*tr101) + ntohs(tr101->tag_len)); - memcpy(conn->tr101, tr101, sizeof(*tr101) + ntohs(tr101->tag_len)); - } - - conn->service_name = _malloc(sizeof(*service_name) + ntohs(service_name->tag_len)); - memcpy(conn->service_name, service_name, sizeof(*service_name) + ntohs(service_name->tag_len)); - - memcpy(conn->cookie, cookie, COOKIE_LENGTH); - - conn->ctx.before_switch = log_switch; - conn->ctx.close = pppoe_conn_close; - conn->ctrl.ctx = &conn->ctx; - conn->ctrl.started = ppp_started; - conn->ctrl.finished = ppp_finished; - conn->ctrl.max_mtu = MAX_PPPOE_MTU; - conn->ctrl.name = "pppoe"; - - conn->ctrl.calling_station_id = _malloc(IFNAMSIZ + 19); - conn->ctrl.called_station_id = _malloc(IFNAMSIZ + 19); - - if (conf_ifname_in_sid == 1 || conf_ifname_in_sid == 3) - sprintf(conn->ctrl.calling_station_id, "%s:%02x:%02x:%02x:%02x:%02x:%02x", serv->ifname, - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - else - sprintf(conn->ctrl.calling_station_id, "%02x:%02x:%02x:%02x:%02x:%02x", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - - if (conf_ifname_in_sid == 2 || conf_ifname_in_sid == 3) - sprintf(conn->ctrl.called_station_id, "%s:%02x:%02x:%02x:%02x:%02x:%02x", serv->ifname, - serv->hwaddr[0], serv->hwaddr[1], serv->hwaddr[2], serv->hwaddr[3], serv->hwaddr[4], serv->hwaddr[5]); - else - sprintf(conn->ctrl.called_station_id, "%02x:%02x:%02x:%02x:%02x:%02x", - serv->hwaddr[0], serv->hwaddr[1], serv->hwaddr[2], serv->hwaddr[3], serv->hwaddr[4], serv->hwaddr[5]); - - ppp_init(&conn->ppp); - - conn->ppp.ctrl = &conn->ctrl; - conn->ppp.chan_name = conn->ctrl.calling_station_id; - - triton_context_register(&conn->ctx, &conn->ppp); - triton_context_wakeup(&conn->ctx); - - triton_event_fire(EV_CTRL_STARTING, &conn->ppp); - triton_event_fire(EV_CTRL_STARTED, &conn->ppp); - - conn->disc_sock = dup(serv->hnd.fd); - - return conn; -} - -static void connect_channel(struct pppoe_conn_t *conn) -{ - int sock; - struct sockaddr_pppox sp; - - sock = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE); - if (!sock) { - log_error("pppoe: socket(PPPOX): %s\n", strerror(errno)); - goto out_err; - } - - memset(&sp, 0, sizeof(sp)); - - sp.sa_family = AF_PPPOX; - sp.sa_protocol = PX_PROTO_OE; - sp.sa_addr.pppoe.sid = htons(conn->sid); - strcpy(sp.sa_addr.pppoe.dev, conn->serv->ifname); - memcpy(sp.sa_addr.pppoe.remote, conn->addr, ETH_ALEN); - - if (connect(sock, (struct sockaddr *)&sp, sizeof(sp))) { - log_error("pppoe: connect: %s\n", strerror(errno)); - goto out_err_close; - } - - conn->ppp.fd = sock; - - if (establish_ppp(&conn->ppp)) - goto out_err_close; - -#ifdef RADIUS - if (conn->tr101) { - conn->radius.send_access_request = pppoe_rad_send_access_request; - conn->radius.send_accounting_request = pppoe_rad_send_accounting_request; - rad_register_plugin(&conn->ppp, &conn->radius); - } -#endif - - conn->ppp_started = 1; - - dpado_check_next(__sync_add_and_fetch(&stat_active, 1)); - - return; - -out_err_close: - close(sock); -out_err: - disconnect(conn); -} - -static struct pppoe_conn_t *find_channel(struct pppoe_serv_t *serv, const uint8_t *cookie) -{ - struct pppoe_conn_t *conn; - - list_for_each_entry(conn, &serv->conn_list, entry) - if (!memcmp(conn->cookie, cookie, COOKIE_LENGTH)) - return conn; - - return NULL; -} - -static void print_tag_string(struct pppoe_tag *tag) -{ - int i; - - for (i = 0; i < ntohs(tag->tag_len); i++) - log_info2("%c", tag->tag_data[i]); -} - -static void print_tag_octets(struct pppoe_tag *tag) -{ - int i; - - for (i = 0; i < ntohs(tag->tag_len); i++) - log_info2("%02x", (uint8_t)tag->tag_data[i]); -} - -static void print_packet(uint8_t *pack) -{ - struct ethhdr *ethhdr = (struct ethhdr *)pack; - struct pppoe_hdr *hdr = (struct pppoe_hdr *)(pack + ETH_HLEN); - struct pppoe_tag *tag; - int n; - - log_info2("[PPPoE "); - - switch (hdr->code) { - case CODE_PADI: - log_info2("PADI"); - break; - case CODE_PADO: - log_info2("PADO"); - break; - case CODE_PADR: - log_info2("PADR"); - break; - case CODE_PADS: - log_info2("PADS"); - break; - case CODE_PADT: - log_info2("PADT"); - break; - } - - log_info2(" %02x:%02x:%02x:%02x:%02x:%02x => %02x:%02x:%02x:%02x:%02x:%02x", - ethhdr->h_source[0], ethhdr->h_source[1], ethhdr->h_source[2], ethhdr->h_source[3], ethhdr->h_source[4], ethhdr->h_source[5], - ethhdr->h_dest[0], ethhdr->h_dest[1], ethhdr->h_dest[2], ethhdr->h_dest[3], ethhdr->h_dest[4], ethhdr->h_dest[5]); - - log_info2(" sid=%04x", ntohs(hdr->sid)); - - for (n = 0; n < ntohs(hdr->length); n += sizeof(*tag) + ntohs(tag->tag_len)) { - tag = (struct pppoe_tag *)(pack + ETH_HLEN + sizeof(*hdr) + n); - switch (ntohs(tag->tag_type)) { - case TAG_END_OF_LIST: - log_info2(" <End-Of-List>"); - break; - case TAG_SERVICE_NAME: - log_info2(" <Service-Name "); - print_tag_string(tag); - log_info2(">"); - break; - case TAG_AC_NAME: - log_info2(" <AC-Name "); - print_tag_string(tag); - log_info2(">"); - break; - case TAG_HOST_UNIQ: - log_info2(" <Host-Uniq "); - print_tag_octets(tag); - log_info2(">"); - break; - case TAG_AC_COOKIE: - log_info2(" <AC-Cookie "); - print_tag_octets(tag); - log_info2(">"); - break; - case TAG_VENDOR_SPECIFIC: - if (ntohs(tag->tag_len) < 4) - log_info2(" <Vendor-Specific invalid>"); - else - log_info2(" <Vendor-Specific %x>", ntohl(*(uint32_t *)tag->tag_data)); - break; - case TAG_RELAY_SESSION_ID: - log_info2(" <Relay-Session-Id"); - print_tag_octets(tag); - log_info2(">"); - break; - case TAG_SERVICE_NAME_ERROR: - log_info2(" <Service-Name-Error>"); - break; - case TAG_AC_SYSTEM_ERROR: - log_info2(" <AC-System-Error>"); - break; - case TAG_GENERIC_ERROR: - log_info2(" <Generic-Error>"); - break; - default: - log_info2(" <Unknown (%x)>", ntohs(tag->tag_type)); - break; - } - } - - log_info2("]\n"); -} - -static void generate_cookie(struct pppoe_serv_t *serv, const uint8_t *src, uint8_t *cookie) -{ - MD5_CTX ctx; - DES_cblock key; - DES_key_schedule ks; - int i; - union { - DES_cblock b[3]; - uint8_t raw[24]; - } u1, u2; - - memset(&key, 0, sizeof(key)); - DES_random_key(&key); - DES_set_key(&key, &ks); - - MD5_Init(&ctx); - MD5_Update(&ctx, serv->secret, SECRET_LENGTH); - MD5_Update(&ctx, serv->hwaddr, ETH_ALEN); - MD5_Update(&ctx, src, ETH_ALEN); - MD5_Update(&ctx, &key, 8); - MD5_Final(u1.raw, &ctx); - - for (i = 0; i < 2; i++) - DES_ecb_encrypt(&u1.b[i], &u2.b[i], &ks, DES_ENCRYPT); - memcpy(u2.b[2], &key, 8); - - for (i = 0; i < 3; i++) - DES_ecb_encrypt(&u2.b[i], &u1.b[i], &serv->des_ks, DES_ENCRYPT); - - memcpy(cookie, u1.raw, 24); -} - -static int check_cookie(struct pppoe_serv_t *serv, const uint8_t *src, const uint8_t *cookie) -{ - MD5_CTX ctx; - DES_key_schedule ks; - int i; - union { - DES_cblock b[3]; - uint8_t raw[24]; - } u1, u2; - - memcpy(u1.raw, cookie, 24); - - for (i = 0; i < 3; i++) - DES_ecb_encrypt(&u1.b[i], &u2.b[i], &serv->des_ks, DES_DECRYPT); - - if (DES_set_key_checked(&u2.b[2], &ks)) - return -1; - - for (i = 0; i < 2; i++) - DES_ecb_encrypt(&u2.b[i], &u1.b[i], &ks, DES_DECRYPT); - - MD5_Init(&ctx); - MD5_Update(&ctx, serv->secret, SECRET_LENGTH); - MD5_Update(&ctx, serv->hwaddr, ETH_ALEN); - MD5_Update(&ctx, src, ETH_ALEN); - MD5_Update(&ctx, u2.b[2], 8); - MD5_Final(u2.raw, &ctx); - - return memcmp(u1.raw, u2.raw, 16); -} - -static void setup_header(uint8_t *pack, const uint8_t *src, const uint8_t *dst, int code, uint16_t sid) -{ - struct ethhdr *ethhdr = (struct ethhdr *)pack; - struct pppoe_hdr *hdr = (struct pppoe_hdr *)(pack + ETH_HLEN); - - memcpy(ethhdr->h_source, src, ETH_ALEN); - memcpy(ethhdr->h_dest, dst, ETH_ALEN); - ethhdr->h_proto = htons(ETH_P_PPP_DISC); - - hdr->ver = 1; - hdr->type = 1; - hdr->code = code; - hdr->sid = htons(sid); - hdr->length = 0; -} - -static void add_tag(uint8_t *pack, int type, const uint8_t *data, int len) -{ - struct pppoe_hdr *hdr = (struct pppoe_hdr *)(pack + ETH_HLEN); - struct pppoe_tag *tag = (struct pppoe_tag *)(pack + ETH_HLEN + sizeof(*hdr) + ntohs(hdr->length)); - - tag->tag_type = htons(type); - tag->tag_len = htons(len); - memcpy(tag->tag_data, data, len); - - hdr->length = htons(ntohs(hdr->length) + sizeof(*tag) + len); -} - -static void add_tag2(uint8_t *pack, const struct pppoe_tag *t) -{ - struct pppoe_hdr *hdr = (struct pppoe_hdr *)(pack + ETH_HLEN); - struct pppoe_tag *tag = (struct pppoe_tag *)(pack + ETH_HLEN + sizeof(*hdr) + ntohs(hdr->length)); - - memcpy(tag, t, sizeof(*t) + ntohs(t->tag_len)); - - hdr->length = htons(ntohs(hdr->length) + sizeof(*tag) + ntohs(t->tag_len)); -} - -static void pppoe_send(int fd, const uint8_t *pack) -{ - struct pppoe_hdr *hdr = (struct pppoe_hdr *)(pack + ETH_HLEN); - int n, s; - - s = ETH_HLEN + sizeof(*hdr) + ntohs(hdr->length); - n = write(fd, pack, s); - if (n < 0 ) - log_error("pppoe: write: %s\n", strerror(errno)); - else if (n != s) { - log_warn("pppoe: short write %i/%i\n", n,s); - } -} - -static void pppoe_send_PADO(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) -{ - uint8_t pack[ETHER_MAX_LEN]; - uint8_t cookie[COOKIE_LENGTH]; - - setup_header(pack, serv->hwaddr, addr, CODE_PADO, 0); - - add_tag(pack, TAG_AC_NAME, (uint8_t *)conf_ac_name, strlen(conf_ac_name)); - if (conf_service_name) - add_tag(pack, TAG_SERVICE_NAME, (uint8_t *)conf_service_name, strlen(conf_service_name)); - - if (service_name) - add_tag2(pack, service_name); - - generate_cookie(serv, addr, cookie); - add_tag(pack, TAG_AC_COOKIE, cookie, COOKIE_LENGTH); - - if (host_uniq) - add_tag2(pack, host_uniq); - - if (relay_sid) - add_tag2(pack, relay_sid); - - if (conf_verbose) { - log_info2("send "); - print_packet(pack); - } - - __sync_add_and_fetch(&stat_PADO_sent, 1); - pppoe_send(serv->hnd.fd, pack); -} - -static void pppoe_send_err(struct pppoe_serv_t *serv, const uint8_t *addr, const struct pppoe_tag *host_uniq, const struct pppoe_tag *relay_sid, int code, int tag_type) -{ - uint8_t pack[ETHER_MAX_LEN]; - - setup_header(pack, serv->hwaddr, addr, code, 0); - - add_tag(pack, TAG_AC_NAME, (uint8_t *)conf_ac_name, strlen(conf_ac_name)); - add_tag(pack, tag_type, NULL, 0); - - if (host_uniq) - add_tag2(pack, host_uniq); - - if (relay_sid) - add_tag2(pack, relay_sid); - - if (conf_verbose) { - log_info2("send "); - print_packet(pack); - } - - pppoe_send(serv->hnd.fd, pack); -} - -static void pppoe_send_PADS(struct pppoe_conn_t *conn) -{ - uint8_t pack[ETHER_MAX_LEN]; - - setup_header(pack, conn->serv->hwaddr, conn->addr, CODE_PADS, conn->sid); - - add_tag(pack, TAG_AC_NAME, (uint8_t *)conf_ac_name, strlen(conf_ac_name)); - - add_tag2(pack, conn->service_name); - - if (conn->host_uniq) - add_tag2(pack, conn->host_uniq); - - if (conn->relay_sid) - add_tag2(pack, conn->relay_sid); - - if (conf_verbose) { - log_info2("send "); - print_packet(pack); - } - - __sync_add_and_fetch(&stat_PADS_sent, 1); - pppoe_send(conn->disc_sock, pack); -} - -static void pppoe_send_PADT(struct pppoe_conn_t *conn) -{ - uint8_t pack[ETHER_MAX_LEN]; - - setup_header(pack, conn->serv->hwaddr, conn->addr, CODE_PADT, conn->sid); - - add_tag(pack, TAG_AC_NAME, (uint8_t *)conf_ac_name, strlen(conf_ac_name)); - - add_tag2(pack, conn->service_name); - - if (conn->host_uniq) - add_tag2(pack, conn->host_uniq); - - if (conn->relay_sid) - add_tag2(pack, conn->relay_sid); - - if (conf_verbose) { - log_info2("send "); - print_packet(pack); - } - - pppoe_send(conn->disc_sock, pack); -} - -static void free_delayed_pado(struct delayed_pado_t *pado) -{ - triton_timer_del(&pado->timer); - - __sync_sub_and_fetch(&stat_delayed_pado, 1); - list_del(&pado->entry); - - if (pado->host_uniq) - _free(pado->host_uniq); - if (pado->relay_sid) - _free(pado->relay_sid); - if (pado->service_name) - _free(pado->service_name); - - mempool_free(pado); -} - -static void pado_timer(struct triton_timer_t *t) -{ - struct delayed_pado_t *pado = container_of(t, typeof(*pado), timer); - - if (!ppp_shutdown) - pppoe_send_PADO(pado->serv, pado->addr, pado->host_uniq, pado->relay_sid, pado->service_name); - - free_delayed_pado(pado); -} - -static void pppoe_recv_PADI(struct pppoe_serv_t *serv, uint8_t *pack, int size) -{ - struct ethhdr *ethhdr = (struct ethhdr *)pack; - struct pppoe_hdr *hdr = (struct pppoe_hdr *)(pack + ETH_HLEN); - struct pppoe_tag *tag; - struct pppoe_tag *host_uniq_tag = NULL; - struct pppoe_tag *relay_sid_tag = NULL; - struct pppoe_tag *service_name_tag = NULL; - int n, service_match = 0; - struct delayed_pado_t *pado; - - __sync_add_and_fetch(&stat_PADI_recv, 1); - - if (ppp_shutdown || pado_delay == -1) - return; - - if (hdr->sid) { - log_warn("pppoe: discarding PADI packet (sid is not zero)\n"); - return; - } - - if (conf_verbose) { - log_info2("recv "); - print_packet(pack); - } - - for (n = 0; n < ntohs(hdr->length); n += sizeof(*tag) + ntohs(tag->tag_len)) { - tag = (struct pppoe_tag *)(pack + ETH_HLEN + sizeof(*hdr) + n); - switch (ntohs(tag->tag_type)) { - case TAG_END_OF_LIST: - break; - case TAG_SERVICE_NAME: - if (conf_service_name && tag->tag_len) { - if (ntohs(tag->tag_len) != strlen(conf_service_name)) - break; - if (memcmp(tag->tag_data, conf_service_name, ntohs(tag->tag_len))) - break; - service_match = 1; - } else { - service_name_tag = tag; - service_match = 1; - } - break; - case TAG_HOST_UNIQ: - host_uniq_tag = tag; - break; - case TAG_RELAY_SESSION_ID: - relay_sid_tag = tag; - break; - } - } - - if (!service_match) { - if (conf_verbose) - log_warn("pppoe: discarding PADI packet (Service-Name mismatch)\n"); - return; - } - - if (pado_delay) { - list_for_each_entry(pado, &serv->pado_list, entry) { - if (memcmp(pado->addr, ethhdr->h_source, ETH_ALEN)) - continue; - if (conf_verbose) - log_warn("pppoe: discarding PADI packet (already queued)\n"); - return; - } - pado = mempool_alloc(pado_pool); - memset(pado, 0, sizeof(*pado)); - pado->serv = serv; - memcpy(pado->addr, ethhdr->h_source, ETH_ALEN); - - if (host_uniq_tag) { - pado->host_uniq = _malloc(sizeof(*host_uniq_tag) + ntohs(host_uniq_tag->tag_len)); - memcpy(pado->host_uniq, host_uniq_tag, sizeof(*host_uniq_tag) + ntohs(host_uniq_tag->tag_len)); - } - - if (relay_sid_tag) { - pado->relay_sid = _malloc(sizeof(*relay_sid_tag) + ntohs(relay_sid_tag->tag_len)); - memcpy(pado->relay_sid, relay_sid_tag, sizeof(*relay_sid_tag) + ntohs(relay_sid_tag->tag_len)); - } - - if (service_name_tag) { - pado->service_name = _malloc(sizeof(*service_name_tag) + ntohs(service_name_tag->tag_len)); - memcpy(pado->service_name, service_name_tag, sizeof(*service_name_tag) + ntohs(service_name_tag->tag_len)); - } - - pado->timer.expire = pado_timer; - pado->timer.period = pado_delay; - - triton_timer_add(&serv->ctx, &pado->timer, 0); - - list_add_tail(&pado->entry, &serv->pado_list); - __sync_add_and_fetch(&stat_delayed_pado, 1); - } else - pppoe_send_PADO(serv, ethhdr->h_source, host_uniq_tag, relay_sid_tag, service_name_tag); -} - -static void pppoe_recv_PADR(struct pppoe_serv_t *serv, uint8_t *pack, int size) -{ - struct ethhdr *ethhdr = (struct ethhdr *)pack; - struct pppoe_hdr *hdr = (struct pppoe_hdr *)(pack + ETH_HLEN); - struct pppoe_tag *tag; - struct pppoe_tag *host_uniq_tag = NULL; - struct pppoe_tag *relay_sid_tag = NULL; - struct pppoe_tag *ac_cookie_tag = NULL; - struct pppoe_tag *service_name_tag = NULL; - struct pppoe_tag *tr101_tag = NULL; - int n, service_match = 0; - struct pppoe_conn_t *conn; - int vendor_id; - - __sync_add_and_fetch(&stat_PADR_recv, 1); - - if (ppp_shutdown) - return; - - if (!memcmp(ethhdr->h_dest, bc_addr, ETH_ALEN)) { - if (conf_verbose) - log_warn("pppoe: discard PADR (destination address is broadcast)\n"); - return; - } - - if (hdr->sid) { - if (conf_verbose) - log_warn("pppoe: discarding PADR packet (sid is not zero)\n"); - return; - } - - if (conf_verbose) { - log_info2("recv "); - print_packet(pack); - } - - for (n = 0; n < ntohs(hdr->length); n += sizeof(*tag) + ntohs(tag->tag_len)) { - tag = (struct pppoe_tag *)(pack + ETH_HLEN + sizeof(*hdr) + n); - switch (ntohs(tag->tag_type)) { - case TAG_END_OF_LIST: - break; - case TAG_SERVICE_NAME: - service_name_tag = tag; - if (tag->tag_len == 0) - service_match = 1; - else if (conf_service_name) { - if (ntohs(tag->tag_len) != strlen(conf_service_name)) - break; - if (memcmp(tag->tag_data, conf_service_name, ntohs(tag->tag_len))) - break; - service_match = 1; - } else { - service_match = 1; - } - break; - case TAG_HOST_UNIQ: - host_uniq_tag = tag; - break; - case TAG_AC_COOKIE: - ac_cookie_tag = tag; - break; - case TAG_RELAY_SESSION_ID: - relay_sid_tag = tag; - break; - case TAG_VENDOR_SPECIFIC: - if (ntohs(tag->tag_len) < 4) - continue; - vendor_id = ntohl(*(uint32_t *)tag->tag_data); - if (vendor_id == VENDOR_ADSL_FORUM) - tr101_tag = tag; - break; - } - } - - if (!ac_cookie_tag) { - if (conf_verbose) - log_warn("pppoe: discard PADR packet (no AC-Cookie tag present)\n"); - return; - } - - if (ntohs(ac_cookie_tag->tag_len) != COOKIE_LENGTH) { - if (conf_verbose) - log_warn("pppoe: discard PADR packet (incorrect AC-Cookie tag length)\n"); - return; - } - - if (check_cookie(serv, ethhdr->h_source, (uint8_t *)ac_cookie_tag->tag_data)) { - if (conf_verbose) - log_warn("pppoe: discard PADR packet (incorrect AC-Cookie)\n"); - return; - } - - if (!service_match) { - if (conf_verbose) - log_warn("pppoe: Service-Name mismatch\n"); - pppoe_send_err(serv, ethhdr->h_source, host_uniq_tag, relay_sid_tag, CODE_PADS, TAG_SERVICE_NAME_ERROR); - return; - } - - pthread_mutex_lock(&serv->lock); - conn = find_channel(serv, (uint8_t *)ac_cookie_tag->tag_data); - if (conn && !conn->ppp.username) { - __sync_add_and_fetch(&stat_PADR_dup_recv, 1); - pppoe_send_PADS(conn); - } - pthread_mutex_unlock(&serv->lock); - - if (conn) - return; - - conn = allocate_channel(serv, ethhdr->h_source, host_uniq_tag, relay_sid_tag, service_name_tag, tr101_tag, (uint8_t *)ac_cookie_tag->tag_data); - if (!conn) - pppoe_send_err(serv, ethhdr->h_source, host_uniq_tag, relay_sid_tag, CODE_PADS, TAG_AC_SYSTEM_ERROR); - else { - pppoe_send_PADS(conn); - triton_context_call(&conn->ctx, (triton_event_func)connect_channel, conn); - } -} - -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; - - if (!memcmp(ethhdr->h_dest, bc_addr, ETH_ALEN)) { - if (conf_verbose) - log_warn("pppoe: discard PADT (destination address is broadcast)\n"); - return; - } - - if (conf_verbose) { - log_info2("recv "); - print_packet(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); - pthread_mutex_unlock(&serv->lock); -} - -static int pppoe_serv_read(struct triton_md_handler_t *h) -{ - struct pppoe_serv_t *serv = container_of(h, typeof(*serv), hnd); - uint8_t pack[ETHER_MAX_LEN]; - struct ethhdr *ethhdr = (struct ethhdr *)pack; - struct pppoe_hdr *hdr = (struct pppoe_hdr *)(pack + ETH_HLEN); - int n; - - while (1) { - n = read(h->fd, pack, sizeof(pack)); - if (n < 0) { - if (errno == EAGAIN) - break; - log_error("pppoe: read: %s\n", strerror(errno)); - return 0; - } - - if (n < ETH_HLEN + sizeof(*hdr)) { - if (conf_verbose) - log_warn("pppoe: short packet received (%i)\n", n); - continue; - } - - if (mac_filter_check(ethhdr->h_source)) - continue; - - if (memcmp(ethhdr->h_dest, bc_addr, ETH_ALEN) && memcmp(ethhdr->h_dest, serv->hwaddr, ETH_ALEN)) - continue; - - if (!memcmp(ethhdr->h_source, bc_addr, ETH_ALEN)) { - if (conf_verbose) - log_warn("pppoe: discarding packet (host address is broadcast)\n"); - continue; - } - - if ((ethhdr->h_source[0] & 1) != 0) { - if (conf_verbose) - log_warn("pppoe: discarding packet (host address is not unicast)\n"); - continue; - } - - if (n < ETH_HLEN + sizeof(*hdr) + ntohs(hdr->length)) { - if (conf_verbose) - log_warn("pppoe: short packet received\n"); - continue; - } - - if (hdr->ver != 1) { - if (conf_verbose) - log_warn("pppoe: discarding packet (unsupported version %i)\n", hdr->ver); - continue; - } - - if (hdr->type != 1) { - if (conf_verbose) - log_warn("pppoe: discarding packet (unsupported type %i)\n", hdr->type); - } - - switch (hdr->code) { - case CODE_PADI: - pppoe_recv_PADI(serv, pack, n); - break; - case CODE_PADR: - pppoe_recv_PADR(serv, pack, n); - break; - case CODE_PADT: - pppoe_recv_PADT(serv, pack); - break; - } - } - return 0; -} - -static void pppoe_serv_close(struct triton_context_t *ctx) -{ - struct pppoe_serv_t *serv = container_of(ctx, typeof(*serv), ctx); - - triton_md_disable_handler(&serv->hnd, MD_MODE_READ | MD_MODE_WRITE); - - serv->stopping = 1; - - pthread_mutex_lock(&serv->lock); - if (!serv->conn_cnt) { - pthread_mutex_unlock(&serv->lock); - pppoe_server_free(serv); - return; - } - pthread_mutex_unlock(&serv->lock); -} - -void pppoe_server_start(const char *ifname, void *cli) -{ - struct pppoe_serv_t *serv; - int sock; - int opt = 1; - struct ifreq ifr; - struct sockaddr_ll sa; - - pthread_rwlock_rdlock(&serv_lock); - list_for_each_entry(serv, &serv_list, entry) { - if (!strcmp(serv->ifname, ifname)) { - if (cli) - cli_send(cli, "error: already exists\r\n"); - pthread_rwlock_unlock(&serv_lock); - return; - } - } - pthread_rwlock_unlock(&serv_lock); - - serv = _malloc(sizeof(*serv)); - memset(serv, 0, sizeof(*serv)); - - if (init_secret(serv)) { - if (cli) - cli_sendv(cli, "init secret failed\r\n"); - _free(serv); - return; - } - - sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PPP_DISC)); - if (sock < 0) { - if (cli) - cli_sendv(cli, "socket: %s\r\n", strerror(errno)); - log_emerg("pppoe: socket: %s\n", strerror(errno)); - _free(serv); - return; - } - - if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt))) { - if (cli) - cli_sendv(cli, "setsockopt(SO_BROADCAST): %s\r\n", strerror(errno)); - log_emerg("pppoe: setsockopt(SO_BROADCAST): %s\n", strerror(errno)); - goto out_err; - } - - strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - 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)); - goto out_err; - } - -#ifdef ARPHDR_ETHER - if (ifr.ifr_hwaddr.sa_family != ARPHDR_ETHER) { - log_emerg("pppoe: interface %s is not ethernet\n", ifname); - goto out_err; - } -#endif - - 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); - goto out_err; - } - - memcpy(serv->hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - 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)); - 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); - } - - 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)); - goto out_err; - } - - memset(&sa, 0, sizeof(sa)); - sa.sll_family = AF_PACKET; - sa.sll_protocol = htons(ETH_P_PPP_DISC); - sa.sll_ifindex = ifr.ifr_ifindex; - - 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)); - 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)); - goto out_err; - } - - serv->ctx.close = pppoe_serv_close; - serv->ctx.before_switch = log_switch; - serv->hnd.fd = sock; - serv->hnd.read = pppoe_serv_read; - serv->ifname = _strdup(ifname); - pthread_mutex_init(&serv->lock, NULL); - - INIT_LIST_HEAD(&serv->conn_list); - INIT_LIST_HEAD(&serv->pado_list); - - triton_context_register(&serv->ctx, NULL); - triton_md_register_handler(&serv->ctx, &serv->hnd); - triton_md_enable_handler(&serv->hnd, MD_MODE_READ); - triton_context_wakeup(&serv->ctx); - - pthread_rwlock_wrlock(&serv_lock); - list_add_tail(&serv->entry, &serv_list); - pthread_rwlock_unlock(&serv_lock); - - return; - -out_err: - close(sock); - _free(serv); -} - -static void _conn_stop(struct pppoe_conn_t *conn) -{ - ppp_terminate(&conn->ppp, 0, TERM_ADMIN_RESET); -} - -static void _server_stop(struct pppoe_serv_t *serv) -{ - struct pppoe_conn_t *conn; - - if (serv->stopping) - return; - - serv->stopping = 1; - triton_md_disable_handler(&serv->hnd, MD_MODE_READ | MD_MODE_WRITE); - - pthread_mutex_lock(&serv->lock); - if (!serv->conn_cnt) { - pthread_mutex_unlock(&serv->lock); - pppoe_server_free(serv); - return; - } - list_for_each_entry(conn, &serv->conn_list, entry) - triton_context_call(&conn->ctx, (triton_event_func)_conn_stop, conn); - pthread_mutex_unlock(&serv->lock); -} - -void pppoe_server_free(struct pppoe_serv_t *serv) -{ - struct delayed_pado_t *pado; - - pthread_rwlock_wrlock(&serv_lock); - list_del(&serv->entry); - pthread_rwlock_unlock(&serv_lock); - - while (!list_empty(&serv->pado_list)) { - pado = list_entry(serv->pado_list.next, typeof(*pado), entry); - free_delayed_pado(pado); - } - - triton_md_unregister_handler(&serv->hnd); - close(serv->hnd.fd); - triton_context_unregister(&serv->ctx); - _free(serv->ifname); - _free(serv); -} - -void pppoe_server_stop(const char *ifname) -{ - struct pppoe_serv_t *serv; - - pthread_rwlock_rdlock(&serv_lock); - list_for_each_entry(serv, &serv_list, entry) { - if (strcmp(serv->ifname, ifname)) - continue; - triton_context_call(&serv->ctx, (triton_event_func)_server_stop, serv); - break; - } - pthread_rwlock_unlock(&serv_lock); -} - -static int init_secret(struct pppoe_serv_t *serv) -{ - int fd; - DES_cblock key; - - fd = open("/dev/urandom", O_RDONLY); - if (fd < 0) { - log_emerg("pppoe: cann't open /dev/urandom: %s\n", strerror(errno)); - return -1; - } - - if (read(fd, serv->secret, SECRET_LENGTH) < 0) { - log_emerg("pppoe: faild to read /dev/urandom\n", strerror(errno)); - close(fd); - return -1; - } - - close(fd); - - memset(key, 0, sizeof(key)); - DES_random_key(&key); - DES_set_key(&key, &serv->des_ks); - - return 0; -} - -static void __init pppoe_init(void) -{ - struct conf_sect_t *s = conf_get_section("pppoe"); - struct conf_option_t *opt; - - conn_pool = mempool_create(sizeof(struct pppoe_conn_t)); - pado_pool = mempool_create(sizeof(struct delayed_pado_t)); - - if (!s) { - log_emerg("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); - } else if (!strcmp(opt->name, "verbose")) { - if (atoi(opt->val) > 0) - conf_verbose = 1; - } else if (!strcmp(opt->name, "ac-name") || !strcmp(opt->name, "AC-Name")) { - if (opt->val && strlen(opt->val)) - conf_ac_name = _strdup(opt->val); - } else if (!strcmp(opt->name, "service-name") || !strcmp(opt->name, "Service-Name")) { - if (opt->val && strlen(opt->val)) - conf_service_name = _strdup(opt->val); - } else if (!strcmp(opt->name, "pado-delay") || !strcmp(opt->name, "PADO-delay")) { - if (dpado_parse(opt->val)) - _exit(EXIT_FAILURE); - } else if (!strcmp(opt->name, "ifname-in-sid")) { - if (!opt->val) - continue; - if (!strcmp(opt->val, "called-sid")) - conf_ifname_in_sid = 1; - else if (!strcmp(opt->val, "calling-sid")) - conf_ifname_in_sid = 2; - else if (!strcmp(opt->val, "both")) - conf_ifname_in_sid = 3; - else if (atoi(opt->val) >= 0) - conf_ifname_in_sid = atoi(opt->val); - } - } - - if (!conf_ac_name) - conf_ac_name = _strdup("accel-pptp"); -} - diff --git a/accel-pptpd/ctrl/pppoe/pppoe.h b/accel-pptpd/ctrl/pppoe/pppoe.h deleted file mode 100644 index 2264dd1..0000000 --- a/accel-pptpd/ctrl/pppoe/pppoe.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef __PPPOE_H -#define __PPPOE_H - -#include <pthread.h> - -#include <openssl/des.h> - -#include <linux/if.h> -#include <linux/if_pppox.h> - -/* PPPoE codes */ -#define CODE_PADI 0x09 -#define CODE_PADO 0x07 -#define CODE_PADR 0x19 -#define CODE_PADS 0x65 -#define CODE_PADT 0xA7 -#define CODE_SESS 0x00 - -/* PPPoE Tags */ -#define TAG_END_OF_LIST 0x0000 -#define TAG_SERVICE_NAME 0x0101 -#define TAG_AC_NAME 0x0102 -#define TAG_HOST_UNIQ 0x0103 -#define TAG_AC_COOKIE 0x0104 -#define TAG_VENDOR_SPECIFIC 0x0105 -#define TAG_RELAY_SESSION_ID 0x0110 -#define TAG_SERVICE_NAME_ERROR 0x0201 -#define TAG_AC_SYSTEM_ERROR 0x0202 -#define TAG_GENERIC_ERROR 0x0203 - -/* Discovery phase states */ -#define STATE_SENT_PADI 0 -#define STATE_RECEIVED_PADO 1 -#define STATE_SENT_PADR 2 -#define STATE_SESSION 3 -#define STATE_TERMINATED 4 - -/* Header size of a PPPoE packet */ -#define PPPOE_OVERHEAD 6 /* type, code, session, length */ -#define HDR_SIZE (sizeof(struct ethhdr) + PPPOE_OVERHEAD) -#define MAX_PPPOE_PAYLOAD (ETH_DATA_LEN - PPPOE_OVERHEAD) -#define MAX_PPPOE_MTU (MAX_PPPOE_PAYLOAD - 2) - -#define VENDOR_ADSL_FORUM 0xde9 - -#define MAX_SID 65534 -#define SECRET_LENGTH 16 -#define COOKIE_LENGTH 24 - -struct pppoe_tag_t -{ - struct list_head entry; - int type; - int len; -}; - -struct pppoe_packet_t -{ - uint8_t src[ETH_ALEN]; - uint8_t dst[ETH_ALEN]; - int code; - uint16_t sid; - struct list_head tags; -}; - -struct pppoe_serv_t -{ - struct list_head entry; - struct triton_context_t ctx; - struct triton_md_handler_t hnd; - uint8_t hwaddr[ETH_ALEN]; - char *ifname; - - uint8_t secret[SECRET_LENGTH]; - 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; - struct list_head conn_list; - struct list_head pado_list; -}; - -extern int conf_verbose; -extern char *conf_service_name; -extern char *conf_ac_name; -extern char *conf_pado_delay; - -extern unsigned int stat_active; -extern unsigned int stat_delayed_pado; -extern unsigned long stat_PADI_recv; -extern unsigned long stat_PADO_sent; -extern unsigned long stat_PADR_recv; -extern unsigned long stat_PADR_dup_recv; -extern unsigned long stat_PADS_sent; - -extern pthread_rwlock_t serv_lock; -extern struct list_head serv_list; - -int mac_filter_check(const uint8_t *addr); -void pppoe_server_start(const char *intf, void *client); -void pppoe_server_stop(const char *intf); - -extern int pado_delay; -void dpado_check_next(int conn_cnt); -void dpado_check_prev(int conn_cnt); -int dpado_parse(const char *str); - -struct rad_packet_t; -int tr101_send_access_request(struct pppoe_tag *tr101, struct rad_packet_t *pack); -int tr101_send_accounting_request(struct pppoe_tag *tr101, struct rad_packet_t *pack); - -#endif - diff --git a/accel-pptpd/ctrl/pppoe/tr101.c b/accel-pptpd/ctrl/pppoe/tr101.c deleted file mode 100644 index cfb0fbc..0000000 --- a/accel-pptpd/ctrl/pppoe/tr101.c +++ /dev/null @@ -1,97 +0,0 @@ -#include <string.h> -#include <stdlib.h> -#include <netinet/in.h> -#include <net/ethernet.h> - -#include "triton.h" -#include "ppp.h" -#include "log.h" -#include "radius.h" -#include "memdebug.h" - -#include "pppoe.h" - -#define OPT_CIRCUIT_ID 0x01 -#define OPT_REMOTE_AGENT_ID 0x02 -#define OPT_ACTUAL_DATA_RATE_UP 0x81 -#define OPT_ACTUAL_DATA_RATE_DOWN 0x82 -#define OPT_MIN_DATA_RATE_UP 0x83 -#define OPT_MAX_DATA_RATE_DOWN 0x84 - -static int tr101_send_request(struct pppoe_tag *tr101, struct rad_packet_t *pack, int type) -{ - uint8_t *ptr = (uint8_t *)tr101->tag_data + 4; - uint8_t *endptr = (uint8_t *)tr101->tag_data + ntohs(tr101->tag_len); - int id, len; - char str[64]; - - while (ptr < endptr) { - if (ptr + 2 > endptr) - goto inval; - id = *ptr++; - len = *ptr++; - if (ptr + len - 2 > endptr) - goto inval; - if (type && id > 0x80) - continue; - switch (id) { - case OPT_CIRCUIT_ID: - if (len - 2 > 63) - goto inval; - memcpy(str, ptr, len); - str[len - 2] = 0; - if (rad_packet_add_str(pack, "ADSL-Forum", "ADSL-Agent-Circuit-Id", str)) - return -1; - break; - case OPT_REMOTE_AGENT_ID: - if (len - 2 > 63) - goto inval; - memcpy(str, ptr, len); - str[len - 2] = 0; - if (rad_packet_add_str(pack, "ADSL-Forum", "ADSL-Agent-Remote-Id", str)) - return -1; - break; - case OPT_ACTUAL_DATA_RATE_UP: - if (len != 6) - goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Data-Rate-Upstream", ntohl(*(uint32_t *)ptr))) - return -1; - break; - case OPT_ACTUAL_DATA_RATE_DOWN: - if (len != 6) - goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Data-Rate-Downstream", ntohl(*(uint32_t *)ptr))) - return -1; - break; - case OPT_MIN_DATA_RATE_UP: - if (len != 6) - goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Minimum-Data-Rate-Upstream", ntohl(*(uint32_t *)ptr))) - return -1; - break; - case OPT_MAX_DATA_RATE_DOWN: - if (len != 6) - goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Maximum-Data-Rate-Upstream", ntohl(*(uint32_t *)ptr))) - return -1; - break; - } - ptr += len - 2; - } - - return 0; - -inval: - log_ppp_warn("pppoe:tr101: invalid tag received\n"); - return -1; -} - -int tr101_send_access_request(struct pppoe_tag *tr101, struct rad_packet_t *pack) -{ - return tr101_send_request(tr101, pack, 1); -} - -int tr101_send_accounting_request(struct pppoe_tag *tr101, struct rad_packet_t *pack) -{ - return tr101_send_request(tr101, pack, 0); -} |