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