summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel-pppd/CMakeLists.txt16
-rw-r--r--accel-pppd/accel-ppp.conf7
-rw-r--r--accel-pppd/accel-ppp.conf.567
-rw-r--r--accel-pppd/auth/auth_chap_md5.c39
-rw-r--r--accel-pppd/auth/auth_pap.c23
-rw-r--r--accel-pppd/cli/show_sessions.c30
-rw-r--r--accel-pppd/ctrl/ipoe/arp.c9
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.c2
-rw-r--r--accel-pppd/ctrl/l2tp/l2tp.c10
-rw-r--r--accel-pppd/ctrl/pppoe/pppoe.c8
-rw-r--r--accel-pppd/ctrl/pptp/pptp.c9
-rw-r--r--accel-pppd/ctrl/sstp/sstp.c9
-rw-r--r--accel-pppd/extra/ipv6pool.c3
-rw-r--r--accel-pppd/ifcfg.c43
-rw-r--r--accel-pppd/include/ap_net.h5
-rw-r--r--accel-pppd/include/ap_session.h4
-rw-r--r--accel-pppd/ipv6/dhcpv6.c4
-rw-r--r--accel-pppd/libnetlink/libnetlink.c21
-rw-r--r--accel-pppd/main.c4
-rw-r--r--accel-pppd/net.c52
-rw-r--r--accel-pppd/ppp/ppp.c5
-rw-r--r--accel-pppd/radius/attr_defs.h2
-rw-r--r--accel-pppd/radius/dict.c12
-rw-r--r--accel-pppd/radius/dict/dictionary1
-rw-r--r--accel-pppd/radius/dict/dictionary.accel7
-rw-r--r--accel-pppd/radius/dm_coa.c52
-rw-r--r--accel-pppd/radius/packet.c13
-rw-r--r--accel-pppd/radius/radius.c83
-rw-r--r--accel-pppd/radius/radius.h2
-rw-r--r--accel-pppd/radius/radius_p.h6
-rw-r--r--accel-pppd/radius/req.c12
-rw-r--r--accel-pppd/radius/serv.c22
-rw-r--r--accel-pppd/session.c16
-rw-r--r--accel-pppd/triton/timer.c4
-rw-r--r--config.h.in1
-rw-r--r--contrib/accel-ppp.service2
-rw-r--r--drivers/ipoe/ipoe.c8
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);
}
}