radius: Use IPv6 for communication
IPv4 now only supported via IPv6-mapped addresses.
This commit is contained in:
parent
e9c8c172b9
commit
7081b7aaac
3 changed files with 50 additions and 24 deletions
40
l2tpns.c
40
l2tpns.c
|
|
@ -162,8 +162,8 @@ config_descriptt config_values[] = {
|
||||||
CONFIG("lcp_renegotiation", lcp_renegotiation, STRING),
|
CONFIG("lcp_renegotiation", lcp_renegotiation, STRING),
|
||||||
CONFIG("primary_dns", default_dns1, IPv4),
|
CONFIG("primary_dns", default_dns1, IPv4),
|
||||||
CONFIG("secondary_dns", default_dns2, IPv4),
|
CONFIG("secondary_dns", default_dns2, IPv4),
|
||||||
CONFIG("primary_radius", radiusserver[0], IPv4),
|
CONFIG("primary_radius", radiusserver[0], IPv6),
|
||||||
CONFIG("secondary_radius", radiusserver[1], IPv4),
|
CONFIG("secondary_radius", radiusserver[1], IPv6),
|
||||||
CONFIG("primary_radius_port", radiusport[0], SHORT),
|
CONFIG("primary_radius_port", radiusport[0], SHORT),
|
||||||
CONFIG("secondary_radius_port", radiusport[1], SHORT),
|
CONFIG("secondary_radius_port", radiusport[1], SHORT),
|
||||||
CONFIG("radius_accounting", radius_accounting, BOOL),
|
CONFIG("radius_accounting", radius_accounting, BOOL),
|
||||||
|
|
@ -231,6 +231,7 @@ config_descriptt config_values[] = {
|
||||||
CONFIG("secondary_ipv6_dns", default_ipv6_dns2, IPv6),
|
CONFIG("secondary_ipv6_dns", default_ipv6_dns2, IPv6),
|
||||||
CONFIG("default_ipv6_domain_list", default_ipv6_domain_list, STRING),
|
CONFIG("default_ipv6_domain_list", default_ipv6_domain_list, STRING),
|
||||||
CONFIG("kernel_accel", kernel_accel, BOOL),
|
CONFIG("kernel_accel", kernel_accel, BOOL),
|
||||||
|
CONFIG("radius_nas_addr", radius_nas_addr, IPv6),
|
||||||
{ NULL, 0, 0, 0 }
|
{ NULL, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -5980,6 +5981,22 @@ static int still_busy(void)
|
||||||
// for the header of the forwarded MPPP/DHCP packet (see C_MPPP_FORWARD)
|
// for the header of the forwarded MPPP/DHCP packet (see C_MPPP_FORWARD)
|
||||||
#define SLACK 56
|
#define SLACK 56
|
||||||
|
|
||||||
|
|
||||||
|
int compare_ipv6_sockaddr(const struct sockaddr_in6 * sa, const struct in6_addr b) {
|
||||||
|
if (sa->sin6_family != AF_INET6)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int c = (memcmp((char *) &(sa->sin6_addr),
|
||||||
|
(char *) &(b),
|
||||||
|
sizeof(struct in6_addr)));
|
||||||
|
if (c==0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// main loop - gets packets on tun or udp and processes them
|
// main loop - gets packets on tun or udp and processes them
|
||||||
static void mainloop(void)
|
static void mainloop(void)
|
||||||
{
|
{
|
||||||
|
|
@ -6121,6 +6138,7 @@ static void mainloop(void)
|
||||||
if (n)
|
if (n)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
|
struct sockaddr_in6 addr6;
|
||||||
struct in_addr local;
|
struct in_addr local;
|
||||||
socklen_t alen;
|
socklen_t alen;
|
||||||
int c, s;
|
int c, s;
|
||||||
|
|
@ -6188,16 +6206,16 @@ static void mainloop(void)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FD_TYPE_RADIUS: // RADIUS response
|
case FD_TYPE_RADIUS: // RADIUS response
|
||||||
alen = sizeof(addr);
|
alen = sizeof(addr6);
|
||||||
s = recvfrom(radfds[d->index], p, size_bufp, MSG_WAITALL, (struct sockaddr *) &addr, &alen);
|
s = recvfrom(radfds[d->index], p, size_bufp, MSG_WAITALL, (struct sockaddr *) &addr6, &alen);
|
||||||
if (s >= 0 && config->cluster_iam_master)
|
if (s >= 0 && config->cluster_iam_master)
|
||||||
{
|
{
|
||||||
if (addr.sin_addr.s_addr == config->radiusserver[0] ||
|
if (compare_ipv6_sockaddr(&addr6, config->radiusserver[0]) ||
|
||||||
addr.sin_addr.s_addr == config->radiusserver[1])
|
compare_ipv6_sockaddr(&addr6, config->radiusserver[1]))
|
||||||
processrad(p, s, d->index);
|
processrad(p, s, d->index);
|
||||||
else
|
else
|
||||||
LOG(3, 0, 0, "Dropping RADIUS packet from unknown source %s\n",
|
LOG(3, 0, 0, "Dropping RADIUS packet from unknown source %s\n",
|
||||||
fmtaddr(addr.sin_addr.s_addr, 0));
|
fmtaddr6(&addr6.sin6_addr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
n--;
|
n--;
|
||||||
|
|
@ -7541,7 +7559,7 @@ static void update_config()
|
||||||
// Update radius
|
// Update radius
|
||||||
config->numradiusservers = 0;
|
config->numradiusservers = 0;
|
||||||
for (i = 0; i < MAXRADSERVER; i++)
|
for (i = 0; i < MAXRADSERVER; i++)
|
||||||
if (config->radiusserver[i])
|
if (!compare_ipv6_sockaddr(&config->radiusserver[i], in6addr_any))
|
||||||
{
|
{
|
||||||
config->numradiusservers++;
|
config->numradiusservers++;
|
||||||
// Set radius port: if not set, take the port from the
|
// Set radius port: if not set, take the port from the
|
||||||
|
|
|
||||||
3
l2tpns.h
3
l2tpns.h
|
|
@ -762,7 +762,7 @@ typedef struct
|
||||||
char radius_require_message_authenticator[5];
|
char radius_require_message_authenticator[5];
|
||||||
int radius_accounting;
|
int radius_accounting;
|
||||||
int radius_interim;
|
int radius_interim;
|
||||||
in_addr_t radiusserver[MAXRADSERVER]; // radius servers
|
struct in6_addr radiusserver[MAXRADSERVER]; // radius servers
|
||||||
uint16_t radiusport[MAXRADSERVER]; // radius base ports
|
uint16_t radiusport[MAXRADSERVER]; // radius base ports
|
||||||
uint8_t numradiusservers; // radius server count
|
uint8_t numradiusservers; // radius server count
|
||||||
|
|
||||||
|
|
@ -883,6 +883,7 @@ typedef struct
|
||||||
uint32_t dns6_lifetime; // RDNSS lifetime default 1200 (see rfc6106, rfc4861) (MaxRtrAdvInterval <= Lifetime <= 2*MaxRtrAdvInterval)
|
uint32_t dns6_lifetime; // RDNSS lifetime default 1200 (see rfc6106, rfc4861) (MaxRtrAdvInterval <= Lifetime <= 2*MaxRtrAdvInterval)
|
||||||
char default_ipv6_domain_list[255];
|
char default_ipv6_domain_list[255];
|
||||||
int kernel_accel; // Enable kernel-accelerated support
|
int kernel_accel; // Enable kernel-accelerated support
|
||||||
|
struct in6_addr radius_nas_addr;
|
||||||
} configt;
|
} configt;
|
||||||
|
|
||||||
enum config_typet { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IPv4, IPv6 };
|
enum config_typet { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IPv4, IPv6 };
|
||||||
|
|
|
||||||
31
radius.c
31
radius.c
|
|
@ -56,7 +56,7 @@ void initrad(void)
|
||||||
uint16_t min = config->radius_bind_min;
|
uint16_t min = config->radius_bind_min;
|
||||||
uint16_t max = config->radius_bind_max;
|
uint16_t max = config->radius_bind_max;
|
||||||
int inc = 1;
|
int inc = 1;
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in6 addr;
|
||||||
|
|
||||||
if (min)
|
if (min)
|
||||||
{
|
{
|
||||||
|
|
@ -76,7 +76,7 @@ void initrad(void)
|
||||||
for (i = 0; i < RADIUS_FDS; i++)
|
for (i = 0; i < RADIUS_FDS; i++)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
radfds[i] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
radfds[i] = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
flags = fcntl(radfds[i], F_GETFL, 0);
|
flags = fcntl(radfds[i], F_GETFL, 0);
|
||||||
fcntl(radfds[i], F_SETFL, flags | O_NONBLOCK);
|
fcntl(radfds[i], F_SETFL, flags | O_NONBLOCK);
|
||||||
|
|
||||||
|
|
@ -85,11 +85,11 @@ void initrad(void)
|
||||||
int b;
|
int b;
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin6_family = AF_INET6;
|
||||||
addr.sin_addr.s_addr = INADDR_ANY;
|
addr.sin6_addr = in6addr_any;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
addr.sin_port = htons(port);
|
addr.sin6_port = htons(port);
|
||||||
if ((b = bind(radfds[i], (struct sockaddr *) &addr, sizeof(addr))) < 0)
|
if ((b = bind(radfds[i], (struct sockaddr *) &addr, sizeof(addr))) < 0)
|
||||||
{
|
{
|
||||||
if ((port += inc) < min || port > max)
|
if ((port += inc) < min || port > max)
|
||||||
|
|
@ -163,7 +163,7 @@ uint16_t radiusnew(sessionidt s)
|
||||||
// Send a RADIUS request
|
// Send a RADIUS request
|
||||||
void radiussend(uint16_t r, uint8_t state)
|
void radiussend(uint16_t r, uint8_t state)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in6 addr;
|
||||||
uint8_t b[4096]; // RADIUS packet
|
uint8_t b[4096]; // RADIUS packet
|
||||||
char pass[129];
|
char pass[129];
|
||||||
int pl;
|
int pl;
|
||||||
|
|
@ -471,9 +471,16 @@ void radiussend(uint16_t r, uint8_t state)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NAS-IP-Address
|
// NAS-IP-Address
|
||||||
*p = 4;
|
//*p = 4;
|
||||||
p[1] = 6;
|
//p[1] = 6;
|
||||||
*(uint32_t *)(p + 2) = config->bind_address;
|
//*(uint32_t *)(p + 2) = config->bind_address;
|
||||||
|
//p += p[1];
|
||||||
|
|
||||||
|
// NAS-IPv6-Address
|
||||||
|
*p = 95;
|
||||||
|
p[1] = 18;
|
||||||
|
//*(uint32_t *)(p + 2) = config->bind_address;
|
||||||
|
memcpy(&p[2], (char*) &config->radius_nas_addr, 16);
|
||||||
p += p[1];
|
p += p[1];
|
||||||
|
|
||||||
// All AVpairs added
|
// All AVpairs added
|
||||||
|
|
@ -491,13 +498,13 @@ void radiussend(uint16_t r, uint8_t state)
|
||||||
MD5_Hmac(ma, b, p-b, config->radiussecret, strlen(config->radiussecret));
|
MD5_Hmac(ma, b, p-b, config->radiussecret, strlen(config->radiussecret));
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin6_family = AF_INET6;
|
||||||
*(uint32_t *) & addr.sin_addr = config->radiusserver[(radius[r].try - 1) % config->numradiusservers];
|
addr.sin6_addr = config->radiusserver[(radius[r].try - 1) % config->numradiusservers];
|
||||||
{
|
{
|
||||||
// get radius port
|
// get radius port
|
||||||
uint16_t port = config->radiusport[(radius[r].try - 1) % config->numradiusservers];
|
uint16_t port = config->radiusport[(radius[r].try - 1) % config->numradiusservers];
|
||||||
// assume RADIUS accounting port is the authentication port +1
|
// assume RADIUS accounting port is the authentication port +1
|
||||||
addr.sin_port = htons((state == RADIUSAUTH || state == RADIUSJUSTAUTH) ? port : port+1);
|
addr.sin6_port = htons((state == RADIUSAUTH || state == RADIUSJUSTAUTH) ? port : port+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_HEX(5, "RADIUS Send", b, (p - b));
|
LOG_HEX(5, "RADIUS Send", b, (p - b));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue