summaryrefslogtreecommitdiff
path: root/accel-pppd/radius
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/radius')
-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.h4
-rw-r--r--accel-pppd/radius/req.c6
-rw-r--r--accel-pppd/radius/serv.c22
6 files changed, 60 insertions, 3 deletions
diff --git a/accel-pppd/radius/dm_coa.c b/accel-pppd/radius/dm_coa.c
index b58306c..a838671 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_vrf_default && ( 0 > setsockopt(serv.hnd.fd, SOL_SOCKET, SO_BINDTODEVICE, conf_dm_coa_vrf_name, strlen(conf_dm_coa_vrf_name)) ) )
+ {
+ log_emerg("radius:dm_coa: failed set vrf '%s' in setsockopt: %s\n", conf_dm_coa_vrf_name, 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 a1a9447..edeb560 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_vrf_name[IFNAMSIZ];
+unsigned int conf_dm_coa_vrf_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 *vrf_name, unsigned int *vrf_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, ",vrf=");
+ if (p3)
+ {
+ *p3 = 0;
+ if ( strlen(p3 + 5) > IFNAMSIZ - 1 )
+ {
+ _free(str);
+ return -1;
+ }
+ strcpy ( vrf_name, p3 + 5);
+ *vrf_default = 0;
+ } else
+ *vrf_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_vrf_name, &conf_dm_coa_vrf_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 b529acd..1925c97 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 d992c13..7d034a0 100644
--- a/accel-pppd/radius/radius_p.h
+++ b/accel-pppd/radius/radius_p.h
@@ -128,6 +128,8 @@ struct rad_server_t {
int queue_cnt;
int fail_timeout;
int max_fail;
+ char vrf_name[IFNAMSIZ];
+ unsigned int vrf_default:1;
struct list_head req_queue[2];
int client_cnt[2];
@@ -181,6 +183,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_vrf_name[IFNAMSIZ];
+extern unsigned int conf_dm_coa_vrf_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 8547653..716bb75 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->vrf_default && ( 0 > setsockopt(req->hnd.fd, SOL_SOCKET, SO_BINDTODEVICE, req->serv->vrf_name, strlen(req->serv->vrf_name)) ) )
+ {
+ 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 6d1eb4c..47fdcc6 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->vrf_default = s->vrf_default;
+ strcpy(s1->vrf_name, s->vrf_name);
_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->vrf_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->vrf_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->vrf_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, ",vrf=");
+ if (ptr3) {
+ endptr = strchrnul(ptr3 + 5, ',');
+ if (*endptr != ',' && *endptr != 0)
+ goto out;
+ if ( ( endptr - ptr3 - 5 ) > IFNAMSIZ - 1 ) {
+ log_error("radius: %s: too long vrf name, set vrf to default\n", _opt);
+ s->vrf_default = 1;
+ } else
+ {
+ s->vrf_default = 0;
+ bzero(s->vrf_name, sizeof(s->vrf_name));
+ strncpy(s->vrf_name, ptr3 + 5, endptr - ptr3 - 5);
+ }
+ } else
+ s->vrf_default = 1;
+
ptr3 = strstr(ptr2, ",backup");
if (ptr3)
s->backup = 1;