summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel-pppd/accel-ppp.conf.512
-rw-r--r--accel-pppd/radius/dm_coa.c7
-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
7 files changed, 70 insertions, 6 deletions
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/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/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;