diff options
-rw-r--r-- | accel-pppd/CMakeLists.txt | 8 | ||||
-rw-r--r-- | accel-pppd/accel-ppp.conf.5 | 12 | ||||
-rw-r--r-- | accel-pppd/auth/auth_chap_md5.c | 25 | ||||
-rw-r--r-- | accel-pppd/extra/ipv6pool.c | 3 | ||||
-rw-r--r-- | accel-pppd/ipv6/dhcpv6.c | 4 | ||||
-rw-r--r-- | accel-pppd/main.c | 2 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp.c | 5 | ||||
-rw-r--r-- | accel-pppd/radius/dict.c | 12 | ||||
-rw-r--r-- | accel-pppd/radius/dm_coa.c | 7 | ||||
-rw-r--r-- | accel-pppd/radius/packet.c | 13 | ||||
-rw-r--r-- | accel-pppd/radius/radius.c | 22 | ||||
-rw-r--r-- | accel-pppd/radius/radius.h | 2 | ||||
-rw-r--r-- | accel-pppd/radius/radius_p.h | 5 | ||||
-rw-r--r-- | accel-pppd/radius/req.c | 6 | ||||
-rw-r--r-- | accel-pppd/radius/serv.c | 22 | ||||
-rw-r--r-- | accel-pppd/triton/timer.c | 4 |
16 files changed, 126 insertions, 26 deletions
diff --git a/accel-pppd/CMakeLists.txt b/accel-pppd/CMakeLists.txt index 23a1d0ad..ab8a3508 100644 --- a/accel-pppd/CMakeLists.txt +++ b/accel-pppd/CMakeLists.txt @@ -1,6 +1,8 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") ADD_DEFINITIONS(-DPTHREAD_SPINLOCK) +include(GNUInstallDirs) + INCLUDE_DIRECTORIES(include) IF (MEMDEBUG) @@ -134,9 +136,9 @@ INSTALL(TARGETS accel-pppd INSTALL(FILES accel-ppp.conf.5 DESTINATION share/man/man5) IF (NOT DEFINED CPACK_TYPE) - INSTALL(FILES accel-ppp.conf DESTINATION ${CMAKE_FIND_ROOT_PATH}/etc RENAME accel-ppp.conf.dist) + INSTALL(FILES accel-ppp.conf DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}" RENAME accel-ppp.conf.dist) - INSTALL(CODE "EXECUTE_PROCESS(COMMAND mkdir -p ${CMAKE_FIND_ROOT_PATH}/var/log/accel-ppp)") - INSTALL(CODE "EXECUTE_PROCESS(COMMAND mkdir -p ${CMAKE_FIND_ROOT_PATH}/var/lib/accel-ppp)") + INSTALL(DIRECTORY DESTINATION "${CMAKE_INSTALL_LOCALSTATEDIR}/log/accel-ppp") + INSTALL(DIRECTORY DESTINATION "${CMAKE_INSTALL_LOCALSTATEDIR}/lib/accel-ppp") ENDIF (NOT DEFINED CPACK_TYPE) diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index 8337ad7a..0b108734 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -824,9 +824,12 @@ Specifies IP address, port and secret of authentication RADIUS server. (obsolete .BI "acct-server=" x.x.x.x:port,secret Specifies IP address, port and secret of accounting RADIUS server. (obsolete) .TP -.BI "server=" address,secret[,auth-port=1812][,acct-port=1813][,req-limit=0][,fail-timeout=0,max-fail=0,][,weight=1][,backup] +.BI "server=" address,secret[,auth-port=1812][,acct-port=1813][,bind-device=][,req-limit=0][,fail-timeout=0,max-fail=0,][,weight=1][,backup] Specifies IP address, secret, ports of RADIUS server. .br +.B bind-device +- device name or VRF to bind the connection. By default, the device name is undefined. +.br .B req-limit - number of simultaneous requests to server (0 - unlimited). .br @@ -845,8 +848,13 @@ Specifies IP address, secret, ports of RADIUS server. If you want to specify only authentication or accounting server then set auth-port/acct-port to zero. You may specify multiple radius servers. .TP -.BI "dae-server=" x.x.x.x:port,secret +.br +.BI "dae-server=" x.x.x.x:port,secret[,bind-device=] Specifies IP address, port to bind and secret for Dynamic Authorization Extension server (DM/CoA). +.br +.B bind-device +- device name or VRF to bind the connection. By default, the device name is undefined. +.br .TP .BI "dm_coa_secret=" secret (deprecated, use dae-server instead) Specifies secret to use in DM/CoA communication. diff --git a/accel-pppd/auth/auth_chap_md5.c b/accel-pppd/auth/auth_chap_md5.c index c0d78c8d..d3982334 100644 --- a/accel-pppd/auth/auth_chap_md5.c +++ b/accel-pppd/auth/auth_chap_md5.c @@ -220,26 +220,31 @@ static void chap_send_success(struct chap_auth_data *ad, int id) static void chap_send_challenge(struct chap_auth_data *ad, int new) { - struct chap_challenge msg = { - .hdr.proto = htons(PPP_CHAP), - .hdr.code = CHAP_CHALLENGE, - .hdr.id = ad->id, - .hdr.len = htons(sizeof(msg) - 2), - .val_size = VALUE_SIZE, +#define CHAP_CHALLENGE_NAME "accel-ppp" + struct { + struct chap_challenge m; + char name[sizeof(CHAP_CHALLENGE_NAME)]; + } __attribute__((packed)) msg = { + .m.hdr.proto = htons(PPP_CHAP), + .m.hdr.code = CHAP_CHALLENGE, + .m.hdr.id = ad->id, + .m.hdr.len = htons(sizeof(struct chap_challenge) - 2 + strlen(CHAP_CHALLENGE_NAME)), + .m.val_size = VALUE_SIZE, + .name = CHAP_CHALLENGE_NAME, }; if (new) read(urandom_fd, ad->val, VALUE_SIZE); - memcpy(msg.val, ad->val, VALUE_SIZE); + memcpy(msg.m.val, ad->val, VALUE_SIZE); if (conf_ppp_verbose) { - log_ppp_info2("send [CHAP Challenge id=%x <", msg.hdr.id); - print_buf(msg.val, VALUE_SIZE); + log_ppp_info2("send [CHAP Challenge id=%x <", msg.m.hdr.id); + print_buf(msg.m.val, VALUE_SIZE); log_ppp_info2(">]\n"); } - ppp_chan_send(ad->ppp, &msg, ntohs(msg.hdr.len) + 2); + ppp_chan_send(ad->ppp, &msg, ntohs(msg.m.hdr.len) + 2); if (conf_timeout && !ad->timeout.tpd) triton_timer_add(ad->ppp->ses.ctrl->ctx, &ad->timeout, 0); diff --git a/accel-pppd/extra/ipv6pool.c b/accel-pppd/extra/ipv6pool.c index 3494a912..c5cabef5 100644 --- a/accel-pppd/extra/ipv6pool.c +++ b/accel-pppd/extra/ipv6pool.c @@ -307,6 +307,9 @@ static struct ipv6db_prefix_t *get_dp(struct ap_session *ses) else pool = def_dppool; + if (!pool) + return NULL; + start = pool; do { spin_lock(&pool->lock); diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index cc7f1f35..91b396c3 100644 --- a/accel-pppd/ipv6/dhcpv6.c +++ b/accel-pppd/ipv6/dhcpv6.c @@ -352,6 +352,10 @@ static void dhcpv6_send_reply(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, i ses->ipv6_dp = ipdb_get_ipv6_prefix(ses); if (ses->ipv6_dp) triton_event_fire(EV_FORCE_INTERIM_UPDATE, ses); + else { + dhcpv6_packet_free(reply); + return; + } } if ((req->hdr->type == D6_RENEW) && pd->dp_iaid != ia_na->iaid) { diff --git a/accel-pppd/main.c b/accel-pppd/main.c index 14e670d5..bbc36d95 100644 --- a/accel-pppd/main.c +++ b/accel-pppd/main.c @@ -282,7 +282,7 @@ static void print_help(FILE *stream) { print_usage(stream); fprintf(stream, "\n" - "\t-с, --config\t- Read config from CONFIG file \n" + "\t-c, --config\t- Read config from CONFIG file \n" "\t-p, --pid\t- Write pid to PID file\n" "\t-d, --daemon\t- Daemon mode\n" "\t-V, --version\t- Show version and exit\n" diff --git a/accel-pppd/ppp/ppp.c b/accel-pppd/ppp/ppp.c index 49b53b1a..8a4cce7c 100644 --- a/accel-pppd/ppp/ppp.c +++ b/accel-pppd/ppp/ppp.c @@ -430,6 +430,11 @@ cont: } } + list_for_each_entry(ppp_h, &ppp->unit_handlers, entry) { + if (ppp_h->proto == proto) + goto cont; + } + lcp_send_proto_rej(ppp, proto); //log_ppp_warn("ppp_chan_read: discarding unknown packet %x\n", proto); } diff --git a/accel-pppd/radius/dict.c b/accel-pppd/radius/dict.c index 4924c895..145c5da2 100644 --- a/accel-pppd/radius/dict.c +++ b/accel-pppd/radius/dict.c @@ -193,14 +193,20 @@ static int dict_load(const char *fname) attr->type = ATTR_TYPE_STRING; else if (!strcmp(ptr[2], "date")) attr->type = ATTR_TYPE_DATE; - else if (!strcmp(ptr[2], "ipaddr")) + else if (!strcmp(ptr[2], "ipaddr")) { attr->type = ATTR_TYPE_IPADDR; + attr->size = 4; /* RFC 8044 §3.8 ipv4addr */ + } else if (!strcmp(ptr[2], "octets")) attr->type = ATTR_TYPE_OCTETS; - else if (!strcmp(ptr[2], "ifid")) + else if (!strcmp(ptr[2], "ifid")) { attr->type = ATTR_TYPE_IFID; - else if (!strcmp(ptr[2], "ipv6addr")) + attr->size = 8; /* RFC 8044 §3.7 ifid */ + } + else if (!strcmp(ptr[2], "ipv6addr")) { attr->type = ATTR_TYPE_IPV6ADDR; + attr->size = 16; /* RFC 8044 §3.9 ipv6addr */ + } else if (!strcmp(ptr[2], "ipv6prefix")) attr->type = ATTR_TYPE_IPV6PREFIX; else if (!strcmp(ptr[2], "ether")) diff --git a/accel-pppd/radius/dm_coa.c b/accel-pppd/radius/dm_coa.c index b58306c5..e88cc347 100644 --- a/accel-pppd/radius/dm_coa.c +++ b/accel-pppd/radius/dm_coa.c @@ -337,6 +337,13 @@ static void init(void) return; } + if ( !conf_dm_coa_bind_default && ( 0 > setsockopt(serv.hnd.fd, SOL_SOCKET, SO_BINDTODEVICE, conf_dm_coa_bind_device, strlen(conf_dm_coa_bind_device)) ) ) + { + log_emerg("radius:dm_coa: failed set bind device '%s' in setsockopt: %s\n", conf_dm_coa_bind_device, strerror(errno)); + close(serv.hnd.fd); + return; + } + fcntl(serv.hnd.fd, F_SETFD, fcntl(serv.hnd.fd, F_GETFD) | FD_CLOEXEC); addr.sin_family = AF_INET; diff --git a/accel-pppd/radius/packet.c b/accel-pppd/radius/packet.c index 07ddf6be..79007036 100644 --- a/accel-pppd/radius/packet.c +++ b/accel-pppd/radius/packet.c @@ -258,9 +258,20 @@ int rad_packet_recv(int fd, struct rad_packet_t **p, struct sockaddr_in *addr) case ATTR_TYPE_IPADDR: case ATTR_TYPE_IFID: case ATTR_TYPE_IPV6ADDR: - memcpy(&attr->val.integer, ptr, len); + if (len == da->size) + memcpy(&attr->val.integer, ptr, len); + else + log_ppp_warn("radius:packet: attribute %s has invalid length %i (must be %i)\n", da->name, len, da->size); break; case ATTR_TYPE_IPV6PREFIX: + if (len < 2 || len > 18) { /* RFC 8044 §3.10 ipv6prefix */ + log_ppp_warn("radius:packet: attribute %s has invalid length %i (must be from 2 to 18)\n", da->name, len); + break; + } + if (ptr[1] > 128) { + log_ppp_warn("radius:packet: attribute %s has invalid prefix length %u (must be from 0 to 128)\n", da->name, ptr[1]); + break; + } attr->val.ipv6prefix.len = ptr[1]; memset(&attr->val.ipv6prefix.prefix, 0, sizeof(attr->val.ipv6prefix.prefix)); memcpy(&attr->val.ipv6prefix.prefix, ptr + 2, len - 2); diff --git a/accel-pppd/radius/radius.c b/accel-pppd/radius/radius.c index a1a94476..e074b982 100644 --- a/accel-pppd/radius/radius.c +++ b/accel-pppd/radius/radius.c @@ -38,6 +38,8 @@ int conf_interim_verbose; in_addr_t conf_dm_coa_server; int conf_dm_coa_port = 3799; char *conf_dm_coa_secret; +char conf_dm_coa_bind_device[IFNAMSIZ]; +unsigned int conf_dm_coa_bind_default; int conf_sid_in_auth; int conf_require_nas_ident; @@ -934,10 +936,10 @@ static struct pwdb_t pwdb = { .check = rad_pwdb_check, }; -static int parse_server(const char *opt, in_addr_t *addr, int *port, char **secret) +static int parse_server(const char *opt, in_addr_t *addr, int *port, char **secret, char *bind_device, unsigned int *bind_default) { char *str = _strdup(opt); - char *p1, *p2; + char *p1, *p2, *p3; p1 = strstr(str, ":"); p2 = strstr(str, ","); @@ -951,6 +953,20 @@ static int parse_server(const char *opt, in_addr_t *addr, int *port, char **secr return -1; } + p3 = strstr(p2 + 1, ",bind-device="); + if (p3) + { + *p3 = 0; + if ( strlen(p3 + 13) > IFNAMSIZ - 1 ) + { + _free(str); + return -1; + } + strcpy ( bind_device, p3 + 13); + *bind_default = 0; + } else + *bind_default = 1; + *addr = inet_addr(str); if (p1) { @@ -1019,7 +1035,7 @@ static int load_config(void) conf_bind = conf_nas_ip_address; opt = conf_get_opt("radius", "dae-server"); - if (opt && parse_server(opt, &conf_dm_coa_server, &conf_dm_coa_port, &conf_dm_coa_secret)) { + if (opt && parse_server(opt, &conf_dm_coa_server, &conf_dm_coa_port, &conf_dm_coa_secret, conf_dm_coa_bind_device, &conf_dm_coa_bind_default)) { log_emerg("radius: failed to parse dae-server\n"); return -1; } diff --git a/accel-pppd/radius/radius.h b/accel-pppd/radius/radius.h index b529acde..1925c973 100644 --- a/accel-pppd/radius/radius.h +++ b/accel-pppd/radius/radius.h @@ -5,6 +5,8 @@ #include <stdint.h> #include <sys/time.h> +#include <linux/if.h> /* For IFNAMSIZ */ + #include "ap_session.h" #include "list.h" diff --git a/accel-pppd/radius/radius_p.h b/accel-pppd/radius/radius_p.h index d992c13e..9ea54b10 100644 --- a/accel-pppd/radius/radius_p.h +++ b/accel-pppd/radius/radius_p.h @@ -128,7 +128,8 @@ struct rad_server_t { int queue_cnt; int fail_timeout; int max_fail; - + char bind_device[IFNAMSIZ]; + unsigned int bind_default:1; struct list_head req_queue[2]; int client_cnt[2]; time_t fail_time; @@ -181,6 +182,8 @@ extern in_addr_t conf_bind; extern in_addr_t conf_gw_ip_address; extern in_addr_t conf_auth_server; extern char *conf_dm_coa_secret; +extern char conf_dm_coa_bind_device[IFNAMSIZ]; +extern unsigned int conf_dm_coa_bind_default; extern int conf_sid_in_auth; extern int conf_require_nas_ident; extern in_addr_t conf_dm_coa_server; diff --git a/accel-pppd/radius/req.c b/accel-pppd/radius/req.c index 8547653e..688a6b2a 100644 --- a/accel-pppd/radius/req.c +++ b/accel-pppd/radius/req.c @@ -290,6 +290,12 @@ static int make_socket(struct rad_req_t *req) addr.sin_addr.s_addr = req->server_addr; addr.sin_port = htons(req->server_port); + if ( req->serv && !req->serv->bind_default && ( 0 > setsockopt(req->hnd.fd, SOL_SOCKET, SO_BINDTODEVICE, req->serv->bind_device, strlen(req->serv->bind_device)) ) ) + { + log_ppp_error("radius:setsockopt: %s\n", strerror(errno)); + goto out_err; + } + if (connect(req->hnd.fd, (struct sockaddr *) &addr, sizeof(addr))) { log_ppp_error("radius:connect: %s\n", strerror(errno)); goto out_err; diff --git a/accel-pppd/radius/serv.c b/accel-pppd/radius/serv.c index 6d1eb4c6..4339d301 100644 --- a/accel-pppd/radius/serv.c +++ b/accel-pppd/radius/serv.c @@ -546,6 +546,8 @@ static void __add_server(struct rad_server_t *s) s1->req_limit = s->req_limit; s1->max_fail = s->max_fail; s1->need_free = 0; + s1->bind_default = s->bind_default; + strcpy(s1->bind_device, s->bind_device); _free(s); return; } @@ -677,6 +679,7 @@ static void add_server_old(void) s->fail_timeout = conf_fail_timeout; s->req_limit = conf_req_limit; s->max_fail = conf_max_fail; + s->bind_default = 1; if (auth_addr == acct_addr && !strcmp(auth_secret, acct_secret)) { s->acct_port = acct_port; @@ -695,6 +698,7 @@ static void add_server_old(void) s->fail_timeout = conf_fail_timeout; s->req_limit = conf_req_limit; s->max_fail = conf_max_fail; + s->bind_default = 1; __add_server(s); } } @@ -745,6 +749,7 @@ static int parse_server1(const char *_opt, struct rad_server_t *s) s->fail_timeout = conf_fail_timeout; s->req_limit = conf_req_limit; s->max_fail = conf_max_fail; + s->bind_default = 1; return 0; @@ -828,6 +833,23 @@ static int parse_server2(const char *_opt, struct rad_server_t *s) } else s->weight = 1; + ptr3 = strstr(ptr2, ",bind-device="); + if (ptr3) { + endptr = strchrnul(ptr3 + 13, ','); + if (*endptr != ',' && *endptr != 0) + goto out; + if ( ( endptr - ptr3 - 13 ) > IFNAMSIZ - 1 ) { + log_error("radius: %s: too long bind device name\n", _opt); + s->bind_default = 1; + } else + { + s->bind_default = 0; + bzero(s->bind_device, sizeof(s->bind_device)); + strncpy(s->bind_device, ptr3 + 13, endptr - ptr3 - 13); + } + } else + s->bind_default = 1; + ptr3 = strstr(ptr2, ",backup"); if (ptr3) s->backup = 1; diff --git a/accel-pppd/triton/timer.c b/accel-pppd/triton/timer.c index 744b10b3..5b5d9535 100644 --- a/accel-pppd/triton/timer.c +++ b/accel-pppd/triton/timer.c @@ -108,6 +108,8 @@ void *timer_thread(void *arg) while (!list_empty(&freed_list2)) { t = list_entry(freed_list2.next, typeof(*t), entry); + epoll_ctl(epoll_fd,EPOLL_CTL_DEL, t->fd, &t->epoll_event); + close(t->fd); list_del(&t->entry); triton_context_release(t->ctx); mempool_free(t); @@ -199,8 +201,6 @@ void __export triton_timer_del(struct triton_timer_t *ud) { struct _triton_timer_t *t = (struct _triton_timer_t *)ud->tpd; - close(t->fd); - spin_lock(&t->ctx->lock); t->ud = NULL; list_del(&t->entry); |