diff --git a/l2tpns.c b/l2tpns.c index 7fcfba4..b7fd51b 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -162,8 +162,8 @@ config_descriptt config_values[] = { CONFIG("lcp_renegotiation", lcp_renegotiation, STRING), CONFIG("primary_dns", default_dns1, IPv4), CONFIG("secondary_dns", default_dns2, IPv4), - CONFIG("primary_radius", radiusserver[0], IPv4), - CONFIG("secondary_radius", radiusserver[1], IPv4), + CONFIG("primary_radius", radiusserver[0], IPv6), + CONFIG("secondary_radius", radiusserver[1], IPv6), CONFIG("primary_radius_port", radiusport[0], SHORT), CONFIG("secondary_radius_port", radiusport[1], SHORT), CONFIG("radius_accounting", radius_accounting, BOOL), @@ -231,6 +231,7 @@ config_descriptt config_values[] = { CONFIG("secondary_ipv6_dns", default_ipv6_dns2, IPv6), CONFIG("default_ipv6_domain_list", default_ipv6_domain_list, STRING), CONFIG("kernel_accel", kernel_accel, BOOL), + CONFIG("radius_nas_addr", radius_nas_addr, IPv6), { 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) #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 static void mainloop(void) { @@ -6121,6 +6138,7 @@ static void mainloop(void) if (n) { struct sockaddr_in addr; + struct sockaddr_in6 addr6; struct in_addr local; socklen_t alen; int c, s; @@ -6188,16 +6206,16 @@ static void mainloop(void) break; case FD_TYPE_RADIUS: // RADIUS response - alen = sizeof(addr); - s = recvfrom(radfds[d->index], p, size_bufp, MSG_WAITALL, (struct sockaddr *) &addr, &alen); + alen = sizeof(addr6); + s = recvfrom(radfds[d->index], p, size_bufp, MSG_WAITALL, (struct sockaddr *) &addr6, &alen); if (s >= 0 && config->cluster_iam_master) { - if (addr.sin_addr.s_addr == config->radiusserver[0] || - addr.sin_addr.s_addr == config->radiusserver[1]) - processrad(p, s, d->index); - else - LOG(3, 0, 0, "Dropping RADIUS packet from unknown source %s\n", - fmtaddr(addr.sin_addr.s_addr, 0)); + if (compare_ipv6_sockaddr(&addr6, config->radiusserver[0]) || + compare_ipv6_sockaddr(&addr6, config->radiusserver[1])) + processrad(p, s, d->index); + else + LOG(3, 0, 0, "Dropping RADIUS packet from unknown source %s\n", + fmtaddr6(&addr6.sin6_addr, 0)); } n--; @@ -7541,7 +7559,7 @@ static void update_config() // Update radius config->numradiusservers = 0; for (i = 0; i < MAXRADSERVER; i++) - if (config->radiusserver[i]) + if (!compare_ipv6_sockaddr(&config->radiusserver[i], in6addr_any)) { config->numradiusservers++; // Set radius port: if not set, take the port from the diff --git a/l2tpns.h b/l2tpns.h index 04a6f11..fac8f1b 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -762,7 +762,7 @@ typedef struct char radius_require_message_authenticator[5]; int radius_accounting; int radius_interim; - in_addr_t radiusserver[MAXRADSERVER]; // radius servers + struct in6_addr radiusserver[MAXRADSERVER]; // radius servers uint16_t radiusport[MAXRADSERVER]; // radius base ports 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) char default_ipv6_domain_list[255]; int kernel_accel; // Enable kernel-accelerated support + struct in6_addr radius_nas_addr; } configt; enum config_typet { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IPv4, IPv6 }; diff --git a/radius.c b/radius.c index 04a39fc..326fb64 100644 --- a/radius.c +++ b/radius.c @@ -56,7 +56,7 @@ void initrad(void) uint16_t min = config->radius_bind_min; uint16_t max = config->radius_bind_max; int inc = 1; - struct sockaddr_in addr; + struct sockaddr_in6 addr; if (min) { @@ -76,7 +76,7 @@ void initrad(void) for (i = 0; i < RADIUS_FDS; i++) { 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); fcntl(radfds[i], F_SETFL, flags | O_NONBLOCK); @@ -85,11 +85,11 @@ void initrad(void) int b; memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; + addr.sin6_family = AF_INET6; + addr.sin6_addr = in6addr_any; do { - addr.sin_port = htons(port); + addr.sin6_port = htons(port); if ((b = bind(radfds[i], (struct sockaddr *) &addr, sizeof(addr))) < 0) { if ((port += inc) < min || port > max) @@ -163,7 +163,7 @@ uint16_t radiusnew(sessionidt s) // Send a RADIUS request void radiussend(uint16_t r, uint8_t state) { - struct sockaddr_in addr; + struct sockaddr_in6 addr; uint8_t b[4096]; // RADIUS packet char pass[129]; int pl; @@ -471,9 +471,16 @@ void radiussend(uint16_t r, uint8_t state) } // NAS-IP-Address - *p = 4; - p[1] = 6; - *(uint32_t *)(p + 2) = config->bind_address; + //*p = 4; + //p[1] = 6; + //*(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]; // 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)); memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - *(uint32_t *) & addr.sin_addr = config->radiusserver[(radius[r].try - 1) % config->numradiusservers]; + addr.sin6_family = AF_INET6; + addr.sin6_addr = config->radiusserver[(radius[r].try - 1) % config->numradiusservers]; { // get radius port uint16_t port = config->radiusport[(radius[r].try - 1) % config->numradiusservers]; // 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));