Skip to content

Commit

Permalink
Adding support to Radius IPV6 address
Browse files Browse the repository at this point in the history
This change enables ipv6 connections between accel-ppp and radius server
  • Loading branch information
leonardomeres committed Nov 30, 2023
1 parent 9669bcb commit 962070c
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 35 deletions.
4 changes: 4 additions & 0 deletions accel-pppd/radius/radius_p.h
Expand Up @@ -95,6 +95,7 @@ struct rad_req_t {
struct rad_server_t *serv;

in_addr_t server_addr;
struct in6_addr server_ipv6_addr;

int server_port;
int type;
Expand All @@ -120,6 +121,7 @@ struct rad_server_t {
struct triton_timer_t timer;
int id;
in_addr_t addr;
struct in6_addr addr6;
char *secret;
int auth_port;
int acct_port;
Expand Down Expand Up @@ -165,6 +167,8 @@ struct rad_server_t {
unsigned int acct_on:1;
unsigned int need_free:1;
unsigned int need_close:1;
//Flag to set radius ip version
unsigned int ipv4:1;
};

#define RAD_SERV_AUTH 0
Expand Down
85 changes: 55 additions & 30 deletions accel-pppd/radius/req.c
Expand Up @@ -53,6 +53,7 @@ static struct rad_req_t *__rad_req_alloc(struct radius_pd_t *rpd, int code, cons
goto out_err;

req->server_addr = req->serv->addr;
req->server_ipv6_addr = req->serv->addr6;
req->server_port = req->serv->auth_port;

while (1) {
Expand Down Expand Up @@ -268,47 +269,71 @@ void rad_req_free(struct rad_req_t *req)

static int make_socket(struct rad_req_t *req)
{
struct sockaddr_in addr;
if (req->serv->ipv4) {
struct sockaddr_in addr;

req->hnd.fd = socket(PF_INET, SOCK_DGRAM, 0);
if (req->hnd.fd < 0) {
log_ppp_error("radius:socket: %s\n", strerror(errno));
return -1;
}
req->hnd.fd = socket(PF_INET, SOCK_DGRAM, 0);
if (req->hnd.fd < 0) {
log_ppp_error("radius:socket: %s\n", strerror(errno));
return -1;
}

fcntl(req->hnd.fd, F_SETFD, fcntl(req->hnd.fd, F_GETFD) | FD_CLOEXEC);
fcntl(req->hnd.fd, F_SETFD, fcntl(req->hnd.fd, F_GETFD) | FD_CLOEXEC);

memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;

if (conf_bind) {
addr.sin_addr.s_addr = conf_bind;
if (bind(req->hnd.fd, (struct sockaddr *) &addr, sizeof(addr))) {
log_ppp_error("radius:bind: %s\n", strerror(errno));
goto out_err;
}
}

memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = req->server_addr;
addr.sin_port = htons(req->server_port);

if (conf_bind) {
addr.sin_addr.s_addr = conf_bind;
if (bind(req->hnd.fd, (struct sockaddr *) &addr, sizeof(addr))) {
log_ppp_error("radius:bind: %s\n", strerror(errno));
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;
}
}

addr.sin_addr.s_addr = req->server_addr;
addr.sin_port = htons(req->server_port);
if (connect(req->hnd.fd, (struct sockaddr *) &addr, sizeof(addr))) {
log_ppp_error("radius:connect: %s\n", strerror(errno));
goto out_err;
}

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 (fcntl(req->hnd.fd, F_SETFL, O_NONBLOCK)) {
log_ppp_error("radius: failed to set nonblocking mode: %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;
}
return 0;

if (fcntl(req->hnd.fd, F_SETFL, O_NONBLOCK)) {
log_ppp_error("radius: failed to set nonblocking mode: %s\n", strerror(errno));
goto out_err;
}
}else {//ipv6 address
struct sockaddr_in6 addr6;

return 0;
req->hnd.fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (req->hnd.fd < 0) {
log_ppp_error("radius:socket: %s\n", strerror(errno));
return -1;
}

fcntl(req->hnd.fd, F_SETFD, fcntl(req->hnd.fd, F_GETFD) | FD_CLOEXEC);

memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_addr = req->server_ipv6_addr;
addr6.sin6_port = htons(req->server_port);

if (connect(req->hnd.fd, (struct sockaddr *) &addr6, sizeof(addr6))) {
log_ppp_error("radius:connect: %s\n", strerror(errno));
goto out_err;
}
return 0;
}

out_err:
if (req->hnd.tpd)
Expand Down
40 changes: 35 additions & 5 deletions accel-pppd/radius/serv.c
Expand Up @@ -485,10 +485,15 @@ static void serv_ctx_close(struct triton_context_t *ctx)

static void show_stat(struct rad_server_t *s, void *client)
{
char addr[17];
char addr[INET6_ADDRSTRLEN]; // Sufficient size for both IPv4 and IPv6 addresses
struct timespec ts;

u_inet_ntoa(s->addr, addr);
if (s->ipv4) {
u_inet_ntoa(s->addr, addr);
} else {
inet_ntop(AF_INET6, &s->addr6, addr, sizeof(addr));
}

clock_gettime(CLOCK_MONOTONIC, &ts);

cli_sendv(client, "radius(%i, %s):\r\n", s->id, addr);
Expand Down Expand Up @@ -725,7 +730,20 @@ static int parse_server1(const char *_opt, struct rad_server_t *s)
if (ptr3)
*ptr3 = 0;

s->addr = inet_addr(opt);
struct in_addr addr4;
if (inet_pton(AF_INET, opt, &addr4) == 1) {
s->ipv4 = 1;
s->addr = addr4.s_addr;
}else {
struct in6_addr addr6;
if (inet_pton(AF_INET6, opt, &addr6) == 1) {
s->ipv4 = 0;
s->addr6 = addr6;
} else {
log_error("Invalid server address");
goto out;
}
}

if (ptr2) {
if (ptr2[1]) {
Expand Down Expand Up @@ -774,8 +792,20 @@ static int parse_server2(const char *_opt, struct rad_server_t *s)

*ptr1 = 0;

s->addr = inet_addr(opt);

struct in_addr addr4;
if (inet_pton(AF_INET, opt, &addr4) == 1) {
s->ipv4 = 1;
s->addr = addr4.s_addr;
}else {
struct in6_addr addr6;
if (inet_pton(AF_INET6, opt, &addr6) == 1) {
s->ipv4 = 0;
s->addr6 = addr6;
} else {
log_error("Invalid server address");
goto out;
}
}
ptr3 = strstr(ptr2, ",auth-port=");
if (ptr3) {
s->auth_port = strtol(ptr3 + 11, &endptr, 10);
Expand Down

0 comments on commit 962070c

Please sign in to comment.