diff options
37 files changed, 534 insertions, 79 deletions
diff --git a/accel-pppd/CMakeLists.txt b/accel-pppd/CMakeLists.txt index d7eaf1db..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) @@ -64,6 +66,14 @@ CHECK_INCLUDE_FILE("linux/netfilter/ipset/ip_set.h" HAVE_IPSET) INCLUDE(CheckFunctionExists) CHECK_FUNCTION_EXISTS(setns HAVE_SETNS) +INCLUDE (CheckCSourceCompiles) +CHECK_C_SOURCE_COMPILES(" +#include <linux/if_link.h> +int main(void) +{ + return IFLA_VRF_UNSPEC+IFLA_VRF_TABLE; +}" HAVE_VRF) + ADD_EXECUTABLE(accel-pppd memdebug.c session.c @@ -126,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 b/accel-pppd/accel-ppp.conf index 8ea405bc..d5c69bf8 100644 --- a/accel-pppd/accel-ppp.conf +++ b/accel-pppd/accel-ppp.conf @@ -43,6 +43,8 @@ thread-count=4 #max-sessions=1000 #max-starting=0 #check-ip=0 +#nl-snd-buffer=32768 +#nl-rcv-buffer=1048576 [ppp] verbose=1 @@ -65,8 +67,12 @@ unit-cache=1 #unit-preallocate=1 [auth] +#timeout=5 +#interval=0 +#max-failure=3 #any-login=0 #noauth=0 +#challenge-name=accel-ppp [pptp] verbose=1 @@ -217,6 +223,7 @@ verbose=1 #default-realm= #strip-realm=0 #attr-tunnel-type=My-Tunnel-Type +#nas-port-id-in-req=1 [client-ip-range] 10.0.0.0/8 diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index 51612ca9..f951325c 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -131,6 +131,17 @@ Specifies maximum concurrent session attempts which server may processed (defaul .TP .BI "check-ip=" 0|1 Specifies whether accel-ppp should check if IP already assigned to other client interface (default 0). +.TP +.BI "nl-snd-buffer=" n +Specifies netlink maximum send buffer size (SO_SNDBUF option) (default 32768). +.TP +.BI "nl-rcv-buffer=" n +Specifies netlink maximum receive buffer size (SO_RCVBUF option) (default 1048576). +.TP +.BI "session-timeout=" n +Specifies max sessions time in seconds, after this time session will be terminated. +.br +This timeout can be redefined with radius attribute Session-Timeout. 0 value means infinite timeout. .SH [ppp] .br PPP module configuration. @@ -233,6 +244,27 @@ This should reduce kernel-level interface creation/deletion rate lack. .TP .BI "unit-preallocate=" 0|1 If set to 1 then allocate ppp unit (interface) before authorization, so Nas-Port and Nas-Port-Id would be defined in Access-Request phase. +.SH [auth] +.br +Contains authentication params +.TP +.BI "timeout=" n +If n is not zero specifies timeout in seconds to wait for PAP, CHAP, Microsoft CHAP v1/v2 authentication. +.TP +.BI "interval=" n +If n is not zero specifies timeout in seconds to restart CHAP and Microsoft CHAP v1/v2 authentication. +.TP +.BI "max-failure=" n +If n is not zero specifies maximum number of CHAP and Microsoft CHAP v1/v2 authentication failures. +.TP +.BI "any-login=" 0|1 +If set to 1 allows pass PAP, CHAP and Microsoft CHAP v1 authentication with any login. +.TP +.BI "noauth=" 0|1 +If set to 1 skips any PPP and IPOE authentication. +.TP +.BI "challenge-name=" name +Specifies challenge name for CHAP authentication. .SH [ipoe] .TP .BI "verbose=" n @@ -532,6 +564,11 @@ as a template, i.e pptp%d => pptp0. .BI "ppp-max-mtu=" n Set the maximum MTU value that can be negotiated for PPP over PPTP sessions. Default value is 1436. +.TP +.BI "session-timeout=" n +Specifies max sessions time in seconds, after this time session will be terminated. +.br +This timeout can be redefined with radius attribute Session-Timeout. 0 value means infinite timeout. .SH [pppoe] .br Configuration of PPPoE module. @@ -601,6 +638,11 @@ Specifies overall limit of PADI packets to reply in 1 second period (default 0 - If this option is given ppp interface will be renamed using .B ifname as a template, i.e pppoe%d => pppoe0. +.TP +.BI "session-timeout=" n +Specifies max sessions time in seconds, after this time session will be terminated. +.br +This timeout can be redefined with radius attribute Session-Timeout. 0 value means infinite timeout. .SH [l2tp] .br Configuration of L2TP module. @@ -692,6 +734,11 @@ sessions. Default value is 1420. If this option is given ppp interface will be renamed using .B ifname as a template, i.e l2tp%d => l2tp0. +.TP +.BI "session-timeout=" n +Specifies max sessions time in seconds, after this time session will be terminated. +.br +This timeout can be redefined with radius attribute Session-Timeout. 0 value means infinite timeout. .SH [sstp] .br Configuration of SSTP module. @@ -798,6 +845,11 @@ as a template, i.e sstp%d => sstp0. .BI "ppp-max-mtu=" n Set the maximum MTU value that can be negotiated for PPP over SSTP sessions. Default value is 1452, maximum is 4087. +.TP +.BI "session-timeout=" n +Specifies max sessions time in seconds, after this time session will be terminated. +.br +This timeout can be redefined with radius attribute Session-Timeout. 0 value means infinite timeout. .SH [radius] .br Configuration of RADIUS module. @@ -818,9 +870,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 @@ -839,8 +894,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. @@ -890,6 +950,9 @@ option for realm substitution. .TP .BI "sid-in-auth=0|1" Specifies should accel-ppp generate and send Acct-Session-Id on Access-Request packet. +.TP +.BI "nas-port-id-in-req=" 0|1 +Specifies should accel-ppp send NAS-Port-Id on Access-Request and Accounting-Request packets (default 1). .SH [log] .br Configuration of log and log_file modules. diff --git a/accel-pppd/auth/auth_chap_md5.c b/accel-pppd/auth/auth_chap_md5.c index c0d78c8d..3ff685e6 100644 --- a/accel-pppd/auth/auth_chap_md5.c +++ b/accel-pppd/auth/auth_chap_md5.c @@ -36,6 +36,7 @@ static int conf_timeout = 5; static int conf_interval = 0; static int conf_max_failure = 3; static int conf_any_login = 0; +static const char *conf_challenge_name = "accel-ppp"; struct chap_hdr { uint16_t proto; @@ -220,26 +221,36 @@ 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, - }; + struct chap_challenge *msg; + int name_len; + + name_len = conf_challenge_name ? strlen(conf_challenge_name) : 0; + msg = alloca(sizeof(*msg) + name_len); + memset(msg, 0, sizeof(*msg) + name_len); + + msg->hdr.proto = htons(PPP_CHAP); + msg->hdr.code = CHAP_CHALLENGE; + msg->hdr.id = ad->id; + msg->hdr.len = htons(sizeof(*msg) + name_len - 2); if (new) read(urandom_fd, ad->val, VALUE_SIZE); - memcpy(msg.val, ad->val, VALUE_SIZE); + memcpy(msg->val, ad->val, VALUE_SIZE); + msg->val_size = VALUE_SIZE; + + if (name_len) + memcpy(msg->name, conf_challenge_name, name_len); if (conf_ppp_verbose) { - log_ppp_info2("send [CHAP Challenge id=%x <", msg.hdr.id); - print_buf(msg.val, VALUE_SIZE); - log_ppp_info2(">]\n"); + log_ppp_info2("send [CHAP Challenge id=%x <", msg->hdr.id); + print_buf(msg->val, VALUE_SIZE); + log_ppp_info2("> name=\""); + print_str(msg->name, ntohs(msg->hdr.len) - sizeof(*msg) + 2); + log_ppp_info2("\"]\n"); } - ppp_chan_send(ad->ppp, &msg, ntohs(msg.hdr.len) + 2); + ppp_chan_send(ad->ppp, msg, ntohs(msg->hdr.len) + 2); if (conf_timeout && !ad->timeout.tpd) triton_timer_add(ad->ppp->ses.ctrl->ctx, &ad->timeout, 0); @@ -476,6 +487,10 @@ static void load_config(void) opt = conf_get_opt("auth", "any-login"); if (opt) conf_any_login = atoi(opt); + + opt = conf_get_opt("auth", "challenge-name"); + if (opt) + conf_challenge_name = opt; } static void auth_chap_md5_init() diff --git a/accel-pppd/auth/auth_pap.c b/accel-pppd/auth/auth_pap.c index 40921019..f31be8b4 100644 --- a/accel-pppd/auth/auth_pap.c +++ b/accel-pppd/auth/auth_pap.c @@ -43,6 +43,7 @@ struct pap_auth_data { char *peer_id; int req_id; unsigned int started:1; + unsigned int active:1; }; struct pap_hdr { @@ -76,6 +77,10 @@ static struct auth_data_t* auth_data_init(struct ppp_t *ppp) d->auth.len = 0; d->ppp = ppp; + d->h.proto = PPP_PAP; + d->h.recv = pap_recv; + ppp_register_chan_handler(ppp, &d->h); + return &d->auth; } @@ -83,6 +88,11 @@ static void auth_data_free(struct ppp_t *ppp, struct auth_data_t *auth) { struct pap_auth_data *d = container_of(auth, typeof(*d), auth); + if (d->timeout.tpd) + triton_timer_del(&d->timeout); + + ppp_unregister_handler(ppp, &d->h); + _free(d); } @@ -90,14 +100,12 @@ static int pap_start(struct ppp_t *ppp, struct auth_data_t *auth) { struct pap_auth_data *d = container_of(auth, typeof(*d), auth); - d->h.proto = PPP_PAP; - d->h.recv = pap_recv; d->timeout.expire = pap_timeout; d->timeout.period = conf_timeout * 1000; triton_timer_add(ppp->ses.ctrl->ctx, &d->timeout, 0); - ppp_register_chan_handler(ppp, &d->h); + d->active = 1; return 0; } @@ -105,14 +113,14 @@ static int pap_finish(struct ppp_t *ppp, struct auth_data_t *auth) { struct pap_auth_data *d = container_of(auth, typeof(*d), auth); + d->active = 0; + if (d->timeout.tpd) triton_timer_del(&d->timeout); if (d->peer_id) _free(d->peer_id); - ppp_unregister_handler(ppp, &d->h); - return 0; } @@ -200,6 +208,11 @@ static int pap_recv_req(struct pap_auth_data *p, struct pap_hdr *hdr) int passwd_len; uint8_t *ptr = (uint8_t*)(hdr + 1); + if (!p->active) { + log_ppp_debug("PAP: unexpected packet received\n"); + return 0; + } + if (p->timeout.tpd) triton_timer_del(&p->timeout); diff --git a/accel-pppd/cli/show_sessions.c b/accel-pppd/cli/show_sessions.c index 6ef60595..fb3ff527 100644 --- a/accel-pppd/cli/show_sessions.c +++ b/accel-pppd/cli/show_sessions.c @@ -384,6 +384,14 @@ static void print_netns(struct ap_session *ses, char *buf) snprintf(buf, CELL_SIZE, "%s", ses->net->name); } +static void print_vrf(struct ap_session *ses, char *buf) +{ + if (ses->vrf_name) + snprintf(buf, CELL_SIZE, "%s", ses->vrf_name); + else + *buf = 0; +} + static void print_ifname(struct ap_session *ses, char *buf) { snprintf(buf, CELL_SIZE, "%s", ses->ifname); @@ -557,10 +565,19 @@ static void format_bytes(char *buf, unsigned long long bytes) sprintf(buf, "%.1f %s", d, suffix); } +static void get_stats(struct ap_session *ses) { + if(ap_session_read_stats(ses, &stats) == -1) { + stats.rx_bytes = 0; + stats.tx_bytes = 0; + stats.rx_packets = 0; + stats.tx_packets = 0; + } +} + static void print_rx_bytes(struct ap_session *ses, char *buf) { if (!stats_set) { - ap_session_read_stats(ses, &stats); + get_stats(ses); stats_set = 1; } format_bytes(buf, 4294967296ll*ses->acct_input_gigawords + stats.rx_bytes); @@ -569,7 +586,7 @@ static void print_rx_bytes(struct ap_session *ses, char *buf) static void print_tx_bytes(struct ap_session *ses, char *buf) { if (!stats_set) { - ap_session_read_stats(ses, &stats); + get_stats(ses); stats_set = 1; } format_bytes(buf, 4294967296ll*ses->acct_output_gigawords + stats.tx_bytes); @@ -578,7 +595,7 @@ static void print_tx_bytes(struct ap_session *ses, char *buf) static void print_rx_bytes_raw(struct ap_session *ses, char *buf) { if (!stats_set) { - ap_session_read_stats(ses, &stats); + get_stats(ses); stats_set = 1; } sprintf(buf, "%llu", 4294967296ll*ses->acct_input_gigawords + stats.rx_bytes); @@ -587,7 +604,7 @@ static void print_rx_bytes_raw(struct ap_session *ses, char *buf) static void print_tx_bytes_raw(struct ap_session *ses, char *buf) { if (!stats_set) { - ap_session_read_stats(ses, &stats); + get_stats(ses); stats_set = 1; } sprintf(buf, "%llu", 4294967296ll*ses->acct_output_gigawords + stats.tx_bytes); @@ -596,7 +613,7 @@ static void print_tx_bytes_raw(struct ap_session *ses, char *buf) static void print_rx_pkts(struct ap_session *ses, char *buf) { if (!stats_set) { - ap_session_read_stats(ses, &stats); + get_stats(ses); stats_set = 1; } sprintf(buf, "%u", stats.rx_packets); @@ -605,7 +622,7 @@ static void print_rx_pkts(struct ap_session *ses, char *buf) static void print_tx_pkts(struct ap_session *ses, char *buf) { if (!stats_set) { - ap_session_read_stats(ses, &stats); + get_stats(ses); stats_set = 1; } sprintf(buf, "%u", stats.tx_packets); @@ -639,6 +656,7 @@ static void init(void) cli_register_simple_cmd2(show_ses_exec, show_ses_help, 2, "show", "sessions"); cli_show_ses_register("netns", "network namespace name", print_netns); + cli_show_ses_register("vrf", "vrf name", print_vrf); cli_show_ses_register("ifname", "interface name", print_ifname); cli_show_ses_register("username", "user name", print_username); cli_show_ses_register("ip", "IP address", print_ip); diff --git a/accel-pppd/ctrl/ipoe/arp.c b/accel-pppd/ctrl/ipoe/arp.c index fa6858d2..e94d61a0 100644 --- a/accel-pppd/ctrl/ipoe/arp.c +++ b/accel-pppd/ctrl/ipoe/arp.c @@ -109,13 +109,8 @@ static void arp_ctx_read(struct _arphdr *ah) pthread_mutex_unlock(&ipoe->lock); goto out; } - - if (ipoe->opt_arp == 2) - memcpy(ah2.ar_sha, ses2->hwaddr, ETH_ALEN); - else - memcpy(ah2.ar_sha, ipoe->hwaddr, ETH_ALEN); - } else - memcpy(ah2.ar_sha, ipoe->hwaddr, ETH_ALEN); + } + memcpy(ah2.ar_sha, ipoe->hwaddr, ETH_ALEN); pthread_mutex_unlock(&ipoe->lock); diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index dbc3f19f..b6ca46c4 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -2081,7 +2081,7 @@ static struct ipoe_session *ipoe_session_create_up(struct ipoe_serv *serv, struc if (conf_max_sessions && ap_session_stat.active + ap_session_stat.starting >= conf_max_sessions) return NULL; - if (connlimit_loaded && connlimit_check(cl_key_from_ipv4(saddr))) + if (connlimit_loaded && connlimit_check(serv->opt_shared ? cl_key_from_ipv4(saddr) : serv->ifindex)) return NULL; if (l4_redirect_list_check(saddr)) diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c index 8567027d..027d7100 100644 --- a/accel-pppd/ctrl/l2tp/l2tp.c +++ b/accel-pppd/ctrl/l2tp/l2tp.c @@ -93,6 +93,7 @@ static size_t conf_secret_len = 0; static int conf_mppe = MPPE_UNSET; static int conf_dataseq = L2TP_DATASEQ_ALLOW; static int conf_reorder_timeout = 0; +static int conf_session_timeout; static const char *conf_ip_pool; static const char *conf_ipv6_pool; static const char *conf_dpv6_pool; @@ -1813,6 +1814,9 @@ static int l2tp_session_start_data_channel(struct l2tp_sess_t *sess) if (conf_ifname) sess->ppp.ses.ifname_rename = _strdup(conf_ifname); + if (conf_session_timeout) + sess->ppp.ses.session_timeout = conf_session_timeout; + sess->ppp.ses.ctrl = &sess->ctrl; sess->apses_state = APSTATE_INIT; @@ -4972,6 +4976,12 @@ static void load_config(void) conf_dpv6_pool = conf_get_opt("l2tp", "ipv6-pool-delegate"); conf_ifname = conf_get_opt("l2tp", "ifname"); + opt = conf_get_opt("l2tp", "session-timeout"); + if (opt) + conf_session_timeout = atoi(opt); + else + conf_session_timeout = 0; + switch (iprange_check_activation()) { case IPRANGE_DISABLED: log_warn("l2tp: iprange module disabled, improper IP configuration of PPP interfaces may cause kernel soft lockup\n"); diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c index 415dd7c0..43163f16 100644 --- a/accel-pppd/ctrl/pppoe/pppoe.c +++ b/accel-pppd/ctrl/pppoe/pppoe.c @@ -127,6 +127,7 @@ unsigned long stat_filtered; pthread_rwlock_t serv_lock = PTHREAD_RWLOCK_INITIALIZER; LIST_HEAD(serv_list); static int connlimit_loaded; +static int conf_session_timeout; static pthread_mutex_t sid_lock = PTHREAD_MUTEX_INITIALIZER; static unsigned long *sid_map; @@ -417,6 +418,8 @@ static struct pppoe_conn_t *allocate_channel(struct pppoe_serv_t *serv, const ui conn->ppp.ses.dpv6_pool_name = _strdup(conf_dpv6_pool); if (conf_ifname) conn->ppp.ses.ifname_rename = _strdup(conf_ifname); + if (conf_session_timeout) + conn->ppp.ses.session_timeout = conf_session_timeout; triton_context_register(&conn->ctx, conn); @@ -2027,6 +2030,11 @@ static void load_config(void) else conf_cookie_timeout = 5; + opt = conf_get_opt("pppoe", "session-timeout"); + if (opt) + conf_session_timeout = atoi(opt); + else + conf_session_timeout = 0; conf_mppe = MPPE_UNSET; opt = conf_get_opt("pppoe", "mppe"); diff --git a/accel-pppd/ctrl/pptp/pptp.c b/accel-pppd/ctrl/pptp/pptp.c index a5bcaca8..a95fe8ae 100644 --- a/accel-pppd/ctrl/pptp/pptp.c +++ b/accel-pppd/ctrl/pptp/pptp.c @@ -60,6 +60,7 @@ static int conf_timeout = 5; static int conf_echo_interval = 0; static int conf_echo_failure = 3; static int conf_verbose = 0; +static int conf_session_timeout; static int conf_mppe = MPPE_UNSET; static const char *conf_ip_pool; static const char *conf_ipv6_pool; @@ -721,6 +722,8 @@ static int pptp_connect(struct triton_md_handler_t *h) conn->ppp.ses.dpv6_pool_name = _strdup(conf_dpv6_pool); if (conf_ifname) conn->ppp.ses.ifname_rename = _strdup(conf_ifname); + if (conf_session_timeout) + conn->ppp.ses.session_timeout = conf_session_timeout; triton_context_register(&conn->ctx, &conn->ppp.ses); triton_md_register_handler(&conn->ctx, &conn->hnd); @@ -807,6 +810,12 @@ static void load_config(void) conf_dpv6_pool = conf_get_opt("pptp", "ipv6-pool-delegate"); conf_ifname = conf_get_opt("pptp", "ifname"); + opt = conf_get_opt("pptp", "session-timeout"); + if (opt) + conf_session_timeout = atoi(opt); + else + conf_session_timeout = 0; + switch (iprange_check_activation()) { case IPRANGE_DISABLED: log_warn("pptp: iprange module disabled, improper IP configuration of PPP interfaces may cause kernel soft lockup\n"); diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c index 4b154005..f17db433 100644 --- a/accel-pppd/ctrl/sstp/sstp.c +++ b/accel-pppd/ctrl/sstp/sstp.c @@ -169,6 +169,7 @@ static const char *conf_ifname; static int conf_proxyproto = 0; static int conf_sndbuf = 0; static int conf_rcvbuf = 0; +static int conf_session_timeout; static int conf_hash_protocol = CERT_HASH_PROTOCOL_SHA1 | CERT_HASH_PROTOCOL_SHA256; static struct hash_t conf_hash_sha1 = { .len = 0 }; @@ -2401,6 +2402,8 @@ static int sstp_connect(struct triton_md_handler_t *h) conn->ppp.ses.dpv6_pool_name = _strdup(conf_dpv6_pool); if (conf_ifname) conn->ppp.ses.ifname_rename = _strdup(conf_ifname); + if (conf_session_timeout) + conn->ppp.ses.session_timeout = conf_session_timeout; sockaddr_ntop(&addr, addr_buf, sizeof(addr_buf), FLAG_NOPORT); conn->ctrl.calling_station_id = _strdup(addr_buf); @@ -2843,6 +2846,12 @@ static void load_config(void) if (opt && atoi(opt) > 0) conf_rcvbuf = atoi(opt); + opt = conf_get_opt("sstp", "session-timeout"); + if (opt) + conf_session_timeout = atoi(opt); + else + conf_session_timeout = 0; + ipmode = (serv.addr.u.sa.sa_family == AF_INET && !conf_proxyproto) ? iprange_check_activation() : -1; switch (ipmode) { 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/ifcfg.c b/accel-pppd/ifcfg.c index 6ab55051..3750060b 100644 --- a/accel-pppd/ifcfg.c +++ b/accel-pppd/ifcfg.c @@ -19,8 +19,11 @@ #include "ipdb.h" #include "log.h" #include "backup.h" +#include "config.h" #include "memdebug.h" +#define VRF_DEFAULT_NAME "default" + // from /usr/include/linux/ipv6.h struct in6_ifreq { struct in6_addr ifr6_addr; @@ -56,6 +59,15 @@ void ap_session_ifup(struct ap_session *ses) ses->ifname_rename = NULL; } +#ifdef HAVE_VRF + if (ses->vrf_name) { + if (ap_session_vrf(ses, ses->vrf_name, -1)) { + ap_session_terminate(ses, TERM_NAS_ERROR, 0); + return; + } + } +#endif + triton_event_fire(EV_SES_ACCT_START, ses); if (ses->stop_time) @@ -334,3 +346,34 @@ int __export ap_session_rename(struct ap_session *ses, const char *ifname, int l return 0; } +#ifdef HAVE_VRF +int __export ap_session_vrf(struct ap_session *ses, const char *vrf_name, int len) +{ + if (len == -1) + len = strlen(vrf_name); + + int vrf_ifindex = 0; + + if (len) { + vrf_ifindex = ses->net->get_ifindex(vrf_name); + if (vrf_ifindex < 0) { + log_ppp_error("vrf '%s' not found\n", vrf_name); + return -1; + } + } else + vrf_name = VRF_DEFAULT_NAME; + + if (ses->net->set_vrf(ses->ifindex, vrf_ifindex)) { + log_ppp_error("set vrf %s failed ifindex=%d, vrf_ifindex=%d\n", vrf_name, ses->ifindex, vrf_ifindex); + return -1; + } else + log_ppp_info2("set vrf %s\n", vrf_name); + + if (!len) { + _free(ses->vrf_name); + ses->vrf_name = NULL; + } + + return 0; +} +#endif
\ No newline at end of file diff --git a/accel-pppd/include/ap_net.h b/accel-pppd/include/ap_net.h index 984c6c18..063b8933 100644 --- a/accel-pppd/include/ap_net.h +++ b/accel-pppd/include/ap_net.h @@ -6,6 +6,7 @@ #include "libnetlink.h" #include "list.h" +#include "config.h" struct ap_net { struct list_head entry; @@ -33,6 +34,10 @@ struct ap_net { int (*move_link)(struct ap_net *net, int ifindex); int (*get_ifindex)(const char * ifname); void (*release)(struct ap_net *net); +#ifdef HAVE_VRF + int (*set_vrf)(int ifindex, int vrf_ifindex); +#endif + }; extern __thread struct ap_net *net; diff --git a/accel-pppd/include/ap_session.h b/accel-pppd/include/ap_session.h index 7efa1105..12277185 100644 --- a/accel-pppd/include/ap_session.h +++ b/accel-pppd/include/ap_session.h @@ -73,6 +73,7 @@ struct ap_session char *chan_name; char ifname[AP_IFNAME_LEN]; char *ifname_rename; + char *vrf_name; int unit_idx; int ifindex; char sessionid[AP_SESSIONID_LEN+1]; @@ -151,6 +152,9 @@ int ap_check_username(const char *username); void ap_session_ifup(struct ap_session *ses); void ap_session_ifdown(struct ap_session *ses); int ap_session_rename(struct ap_session *ses, const char *ifname, int len); +#ifdef HAVE_VRF +int ap_session_vrf(struct ap_session *ses, const char *vrf_name, int len); +#endif int ap_session_read_stats(struct ap_session *ses, struct rtnl_link_stats *stats); diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index 12701ce3..cefbcfd8 100644 --- a/accel-pppd/ipv6/dhcpv6.c +++ b/accel-pppd/ipv6/dhcpv6.c @@ -355,6 +355,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/libnetlink/libnetlink.c b/accel-pppd/libnetlink/libnetlink.c index 0ab83a3c..a0ea103e 100644 --- a/accel-pppd/libnetlink/libnetlink.c +++ b/accel-pppd/libnetlink/libnetlink.c @@ -28,7 +28,8 @@ #define __export __attribute__((visibility("default"))) -int rcvbuf = 1024 * 1024; +extern int conf_nl_rcvbuf; +extern int conf_nl_sndbuf; void __export rtnl_close(struct rtnl_handle *rth) { @@ -52,12 +53,22 @@ int __export rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, return -1; } - if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { - log_debug("libnetlink: ""SO_SNDBUF: %s\n", strerror(errno)); - return -1; + if (conf_nl_sndbuf > 0) { + if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&conf_nl_sndbuf,sizeof(conf_nl_sndbuf)) < 0) { + log_debug("libnetlink: ""SO_SNDBUF: %s\n", strerror(errno)); + log_debug("libnetlink: unable to set custom sndbuf. Default value %d will be used", sndbuf); + conf_nl_sndbuf = -1; + } + } + + if (conf_nl_sndbuf <= 0) { + if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { + log_debug("libnetlink: ""SO_SNDBUF: %s\n", strerror(errno)); + return -1; + } } - if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) { + if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&conf_nl_rcvbuf,sizeof(conf_nl_rcvbuf)) < 0) { log_debug("libnetlink: ""SO_RCVBUF: %s\n", strerror(errno)); return -1; } diff --git a/accel-pppd/main.c b/accel-pppd/main.c index 4af14f0f..bbc36d95 100644 --- a/accel-pppd/main.c +++ b/accel-pppd/main.c @@ -162,7 +162,7 @@ static void __core_restart(int soft) readlink(exe, exe_buf, PATH_MAX); while (1) { - execv(exe, argv); + execv(exe_buf, argv); sleep(3); } } @@ -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/net.c b/accel-pppd/net.c index 809dfaaa..c619deed 100644 --- a/accel-pppd/net.c +++ b/accel-pppd/net.c @@ -45,6 +45,9 @@ __export __thread struct ap_net *net; __export struct ap_net *def_net; static int def_ns_fd; +__export int conf_nl_rcvbuf = 1024 * 1024; +__export int conf_nl_sndbuf = -1; + static int def_socket(int domain, int type, int proto) { return socket(domain, type, proto); @@ -231,6 +234,44 @@ static int def_get_ifindex(const char *ifname) return ifr.ifr_ifindex; } +#ifdef HAVE_VRF +static int def_set_vrf(int ifindex, int vrf_ifindex) +{ + struct iplink_req { + struct nlmsghdr n; + struct ifinfomsg i; + char buf[1024]; + } req; + + struct rtnl_handle *rth = net->rtnl_get(); + + int r = 0; + + if (!rth) { + log_ppp_error("def_set_vrf rtnl_get failed\n"); + return -1; + } + + memset(&req, 0, sizeof(req) - 1024); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_NEWLINK; + req.i.ifi_family = AF_UNSPEC; + req.i.ifi_index = ifindex; + + addattr_l(&req.n, sizeof(req), IFLA_MASTER, &vrf_ifindex, sizeof(vrf_ifindex)); + + if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) { + log_ppp_error("def_set_vrf rtnl_talk failed\n"); + r = -1; + } + + net->rtnl_put(rth); + + return r; +} +#endif static void def_release(struct ap_net *d) { @@ -318,6 +359,9 @@ static struct ap_net *alloc_net(const char *name) net->move_link = def_move_link; net->get_ifindex = def_get_ifindex; net->release = def_release; +#ifdef HAVE_VRF + net->set_vrf = def_set_vrf; +#endif n->sock = socket(AF_INET, SOCK_DGRAM, 0); n->sock6 = socket(AF_INET6, SOCK_DGRAM, 0); @@ -391,6 +435,14 @@ static void __init init() { const char *opt; + opt = conf_get_opt("common", "nl-rcv-buffer"); + if (opt) + conf_nl_rcvbuf = atoi(opt); + + opt = conf_get_opt("common", "nl-snd-buffer"); + if (opt) + conf_nl_sndbuf = atoi(opt); + opt = conf_get_opt("common", "netns-run-dir"); if (opt) conf_netns_run_dir = opt; 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/attr_defs.h b/accel-pppd/radius/attr_defs.h index 8e5bf9b8..39fd0c05 100644 --- a/accel-pppd/radius/attr_defs.h +++ b/accel-pppd/radius/attr_defs.h @@ -1,6 +1,8 @@ #define VENDOR_Microsoft 311 #define VENDOR_Accel_PPP 55999 +#define Accel_VRF_Name 1 + #define User_Name 1 #define User_Password 2 #define CHAP_Password 3 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/dict/dictionary b/accel-pppd/radius/dict/dictionary index cf9e367c..2afd26fc 100644 --- a/accel-pppd/radius/dict/dictionary +++ b/accel-pppd/radius/dict/dictionary @@ -76,6 +76,7 @@ $INCLUDE dictionary.rfc4818 $INCLUDE dictionary.rfc5176 $INCLUDE dictionary.rfc6911 +$INCLUDE dictionary.accel $INCLUDE dictionary.microsoft $INCLUDE dictionary.cisco $INCLUDE dictionary.alcatel diff --git a/accel-pppd/radius/dict/dictionary.accel b/accel-pppd/radius/dict/dictionary.accel new file mode 100644 index 00000000..849cc42c --- /dev/null +++ b/accel-pppd/radius/dict/dictionary.accel @@ -0,0 +1,7 @@ +VENDOR Accel-PPP 55999 + +BEGIN-VENDOR Accel-PPP + +ATTRIBUTE Accel-VRF-Name 1 string + +END-VENDOR Accel-PPP diff --git a/accel-pppd/radius/dm_coa.c b/accel-pppd/radius/dm_coa.c index 003a691d..e88cc347 100644 --- a/accel-pppd/radius/dm_coa.c +++ b/accel-pppd/radius/dm_coa.c @@ -17,6 +17,7 @@ #include "log.h" #include "radius_p.h" +#include "attr_defs.h" #include "memdebug.h" @@ -143,6 +144,24 @@ static void disconnect_request(struct radius_pd_t *rpd) ap_session_terminate(rpd->ses, TERM_ADMIN_RESET, 0); } +#ifdef HAVE_VRF +int rad_update_vrf(struct radius_pd_t *rpd, const char *vrf_name) +{ + if (*vrf_name == '0') { + // Delete interface from VRF + if (!ap_session_vrf(rpd->ses, NULL, 0)) + return 1; + } + else { + // Add interface to VRF + if(!ap_session_vrf(rpd->ses, vrf_name, -1)) + return 1; + } + + return 0; +} +#endif + static void coa_request(struct radius_pd_t *rpd) { struct rad_attr_t *class; @@ -153,6 +172,8 @@ static void coa_request(struct radius_pd_t *rpd) .request = rpd->dm_coa_req, }; + int send_ack = 0; + if (conf_verbose) { log_ppp_info2("recv "); rad_packet_print(rpd->dm_coa_req, NULL, log_ppp_info2); @@ -161,7 +182,7 @@ static void coa_request(struct radius_pd_t *rpd) triton_event_fire(EV_RADIUS_COA, &ev); if (ev.res) - dm_coa_send_nak(serv.hnd.fd, rpd->dm_coa_req, &rpd->dm_coa_addr, 0); + goto out; else { class = rad_packet_find_attr(rpd->dm_coa_req, NULL, "Class"); if (class) { @@ -180,14 +201,32 @@ static void coa_request(struct radius_pd_t *rpd) else rad_packet_add_octets(rpd->acct_req->pack, NULL, "Class", rpd->attr_class, rpd->attr_class_len); } + send_ack = 1; + goto out; } attr = rad_packet_find_attr(rpd->dm_coa_req, NULL, "Session-Timeout"); - if (attr) + if (attr){ rad_update_session_timeout(rpd, attr->val.integer); + send_ack = 1; + goto out; + } +#ifdef HAVE_VRF + attr = rad_packet_find_attr(rpd->dm_coa_req, "Accel-PPP", "Accel-VRF-Name"); + if (attr){ + if(!rad_update_vrf(rpd, attr->val.string)){ + goto out; + } + } +#endif + send_ack = 1; + } +out: + if (send_ack) dm_coa_send_ack(serv.hnd.fd, rpd->dm_coa_req, &rpd->dm_coa_addr); - } + else + dm_coa_send_nak(serv.hnd.fd, rpd->dm_coa_req, &rpd->dm_coa_addr, 0); rad_packet_free(rpd->dm_coa_req); @@ -298,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 9137f610..786faa56 100644 --- a/accel-pppd/radius/radius.c +++ b/accel-pppd/radius/radius.c @@ -20,6 +20,7 @@ #include "radius_p.h" #include "attr_defs.h" +#include "config.h" #include "memdebug.h" @@ -37,8 +38,11 @@ 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_nas_port_id_in_req = 1; int conf_require_nas_ident; int conf_acct_interim_interval; int conf_acct_interim_jitter; @@ -282,28 +286,43 @@ int rad_proc_attrs(struct rad_req_t *req) req->rpd->acct_interim_jitter = conf_acct_interim_jitter; list_for_each_entry(attr, &req->reply->attrs, entry) { - if (attr->vendor && attr->vendor->id == VENDOR_Microsoft) { - switch (attr->attr->id) { - case MS_Primary_DNS_Server: - dns.ses = rpd->ses; - dns.dns1 = attr->val.ipaddr; - break; - case MS_Secondary_DNS_Server: - dns.ses = rpd->ses; - dns.dns2 = attr->val.ipaddr; - break; - case MS_Primary_NBNS_Server: - wins.ses = rpd->ses; - wins.wins1 = attr->val.ipaddr; - break; - case MS_Secondary_NBNS_Server: - wins.ses = rpd->ses; - wins.wins2 = attr->val.ipaddr; - break; + if (attr->vendor) { + if (attr->vendor->id == VENDOR_Microsoft) { + switch (attr->attr->id) { + case MS_Primary_DNS_Server: + dns.ses = rpd->ses; + dns.dns1 = attr->val.ipaddr; + break; + case MS_Secondary_DNS_Server: + dns.ses = rpd->ses; + dns.dns2 = attr->val.ipaddr; + break; + case MS_Primary_NBNS_Server: + wins.ses = rpd->ses; + wins.wins1 = attr->val.ipaddr; + break; + case MS_Secondary_NBNS_Server: + wins.ses = rpd->ses; + wins.wins2 = attr->val.ipaddr; + break; + } + continue; +#ifdef HAVE_VRF + } else if (attr->vendor->id == VENDOR_Accel_PPP) { + switch (attr->attr->id) { + case Accel_VRF_Name: + if (rpd->ses->vrf_name) + _free(rpd->ses->vrf_name); + rpd->ses->vrf_name = _malloc(attr->len + 1); + memcpy(rpd->ses->vrf_name, attr->val.string, attr->len); + rpd->ses->vrf_name[attr->len] = 0; + break; + } + continue; +#endif } continue; - } else if (attr->vendor) - continue; + } switch(attr->attr->id) { case User_Name: @@ -918,10 +937,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, ","); @@ -935,6 +954,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) { @@ -1003,7 +1036,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; } @@ -1038,6 +1071,10 @@ static int load_config(void) if (opt && atoi(opt) >= 0) conf_strip_realm = atoi(opt) > 0; + opt = conf_get_opt("radius", "nas-port-id-in-req"); + if (opt) + conf_nas_port_id_in_req = atoi(opt); + return 0; } 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..988f154f 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,7 +182,10 @@ 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_nas_port_id_in_req; extern int conf_require_nas_ident; extern in_addr_t conf_dm_coa_server; extern int conf_dm_coa_port; diff --git a/accel-pppd/radius/req.c b/accel-pppd/radius/req.c index 8547653e..11abf8cb 100644 --- a/accel-pppd/radius/req.c +++ b/accel-pppd/radius/req.c @@ -89,8 +89,10 @@ static struct rad_req_t *__rad_req_alloc(struct radius_pd_t *rpd, int code, cons if (rpd->ses->unit_idx != -1 && rad_packet_add_int(req->pack, NULL, "NAS-Port", rpd->ses->unit_idx)) goto out_err; - if (*rpd->ses->ifname && rad_packet_add_str(req->pack, NULL, "NAS-Port-Id", rpd->ses->ifname)) - goto out_err; + if (conf_nas_port_id_in_req) { + if (*rpd->ses->ifname && rad_packet_add_str(req->pack, NULL, "NAS-Port-Id", rpd->ses->ifname)) + goto out_err; + } if (req->rpd->ses->ctrl->type == CTRL_TYPE_IPOE) { if (rad_packet_add_val(req->pack, NULL, "NAS-Port-Type", "Ethernet")) @@ -290,6 +292,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/session.c b/accel-pppd/session.c index 78d12f95..81ac271b 100644 --- a/accel-pppd/session.c +++ b/accel-pppd/session.c @@ -24,6 +24,7 @@ #include "iputils.h" #include "spinlock.h" #include "mempool.h" +#include "config.h" #include "memdebug.h" #define SID_SOURCE_SEQ 0 @@ -34,6 +35,7 @@ static int conf_single_session = -1; static int conf_single_session_ignore_case; static int conf_sid_source; static int conf_seq_save_timeout = 10; +static int conf_session_timeout; static const char *conf_seq_file; int __export conf_max_sessions; int __export conf_max_starting; @@ -151,6 +153,9 @@ void __export ap_session_activate(struct ap_session *ses) __sync_sub_and_fetch(&ap_session_stat.starting, 1); __sync_add_and_fetch(&ap_session_stat.active, 1); + if (!ses->session_timeout && conf_session_timeout) + ses->session_timeout = conf_session_timeout; + if (ses->idle_timeout) { ses->timer.expire = ap_session_timer; ses->timer.period = 60000; @@ -240,6 +245,11 @@ void __export ap_session_finished(struct ap_session *ses) ses->ifname_rename = NULL; } +#ifdef HAVE_VRF + if (ses->vrf_name) + ap_session_vrf(ses, NULL, 0); +#endif + if (ses->net) ses->net->release(ses->net); @@ -541,6 +551,12 @@ static void load_config(void) conf_max_starting = atoi(opt); else conf_max_starting = 0; + + opt = conf_get_opt("common", "session-timeout"); + if (opt) + conf_session_timeout = atoi(opt); + else + conf_session_timeout = 0; } static void init(void) 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); diff --git a/config.h.in b/config.h.in index 46fca37d..e2186a03 100644 --- a/config.h.in +++ b/config.h.in @@ -2,3 +2,4 @@ //#cmakedefine RADIUS #cmakedefine HAVE_IPSET #cmakedefine HAVE_SETNS +#cmakedefine HAVE_VRF diff --git a/contrib/accel-ppp.service b/contrib/accel-ppp.service index f25a66d5..ca7986f8 100644 --- a/contrib/accel-ppp.service +++ b/contrib/accel-ppp.service @@ -8,7 +8,7 @@ StandardOutput=null ExecReload=/bin/kill -SIGUSR1 $MAINPID PIDFile=/var/run/accel-pppd.pid Type=forking -Restart=always +Restart=on-failure [Install] WantedBy=multi-user.target diff --git a/drivers/ipoe/ipoe.c b/drivers/ipoe/ipoe.c index 5e220e94..5a5f68b8 100644 --- a/drivers/ipoe/ipoe.c +++ b/drivers/ipoe/ipoe.c @@ -1154,7 +1154,11 @@ static int ipoe_create(__be32 peer_addr, __be32 addr, __be32 gw, int ifindex, co if (link_dev) { dev->features = link_dev->features & ~(NETIF_F_HW_VLAN_FILTER | NETIF_F_LRO); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) + dev_addr_mod(dev, 0, link_dev->dev_addr, ETH_ALEN); +#else memcpy(dev->dev_addr, link_dev->dev_addr, ETH_ALEN); +#endif memcpy(dev->broadcast, link_dev->broadcast, ETH_ALEN); } @@ -1446,7 +1450,11 @@ static int ipoe_nl_cmd_modify(struct sk_buff *skb, struct genl_info *info) if (link_dev) { ses->dev->features = link_dev->features & ~(NETIF_F_HW_VLAN_FILTER | NETIF_F_LRO); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) + dev_addr_mod(dev, 0, link_dev->dev_addr, ETH_ALEN); +#else memcpy(dev->dev_addr, link_dev->dev_addr, ETH_ALEN); +#endif memcpy(dev->broadcast, link_dev->broadcast, ETH_ALEN); } } |