diff --git a/accel-pppd/radius/radius_p.h b/accel-pppd/radius/radius_p.h index cd9a0ab4..87613624 100644 --- a/accel-pppd/radius/radius_p.h +++ b/accel-pppd/radius/radius_p.h @@ -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; @@ -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; @@ -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 diff --git a/accel-pppd/radius/req.c b/accel-pppd/radius/req.c index 11abf8cb..be74f047 100644 --- a/accel-pppd/radius/req.c +++ b/accel-pppd/radius/req.c @@ -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) { @@ -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) diff --git a/accel-pppd/radius/serv.c b/accel-pppd/radius/serv.c index 4339d301..4af6a67a 100644 --- a/accel-pppd/radius/serv.c +++ b/accel-pppd/radius/serv.c @@ -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); @@ -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]) { @@ -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);