new feature: If the user attribute "Framed-IPv6-Address" is defined then the ICMPv6_RA advertise this IPv6 address.
Fix: Incorrect delegation of IPv6 prefixes when multiple of 4 bits (nibble) (eg: /44, /52 ...).
This commit is contained in:
parent
e98fe68174
commit
8d94f2020d
4 changed files with 73 additions and 25 deletions
8
icmp.c
8
icmp.c
|
|
@ -143,7 +143,13 @@ void send_ipv6_ra(sessionidt s, tunnelidt t, struct in6_addr *ip)
|
||||||
pinfo->nd_opt_pi_preferred_time = htonl(604800);
|
pinfo->nd_opt_pi_preferred_time = htonl(604800);
|
||||||
pinfo->nd_opt_pi_reserved2 = 0;
|
pinfo->nd_opt_pi_reserved2 = 0;
|
||||||
pinfo->nd_opt_pi_prefix_len = 64; // prefix length
|
pinfo->nd_opt_pi_prefix_len = 64; // prefix length
|
||||||
pinfo->nd_opt_pi_prefix = config->ipv6_prefix;
|
if (session[s].ipv6address.s6_addr[0])
|
||||||
|
{
|
||||||
|
// MSB 64bits of assigned IPv6 address to user (see radius attribut Framed-IPv6-Address)
|
||||||
|
memcpy(&pinfo->nd_opt_pi_prefix, &session[s].ipv6address.s6_addr[0], 8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pinfo->nd_opt_pi_prefix = config->ipv6_prefix;
|
||||||
|
|
||||||
// // Length of payload (not header)
|
// // Length of payload (not header)
|
||||||
p_ip6_hdr->ip6_plen = htons(sizeof(*pinfo) + sizeof(*p_nra));
|
p_ip6_hdr->ip6_plen = htons(sizeof(*pinfo) + sizeof(*p_nra));
|
||||||
|
|
|
||||||
61
l2tpns.c
61
l2tpns.c
|
|
@ -102,7 +102,7 @@ union iphash {
|
||||||
struct ipv6radix {
|
struct ipv6radix {
|
||||||
sessionidt sess;
|
sessionidt sess;
|
||||||
struct ipv6radix *branch;
|
struct ipv6radix *branch;
|
||||||
} ipv6_hash[256]; // Mapping from IPv6 address to session structures.
|
} ipv6_hash[16]; // Mapping from IPv6 address to session structures.
|
||||||
|
|
||||||
// Traffic counters.
|
// Traffic counters.
|
||||||
static uint32_t udp_rx = 0, udp_rx_pkt = 0, udp_tx = 0;
|
static uint32_t udp_rx = 0, udp_rx_pkt = 0, udp_tx = 0;
|
||||||
|
|
@ -983,19 +983,24 @@ static sessionidt lookup_ipv6map(struct in6_addr ip)
|
||||||
char ipv6addr[INET6_ADDRSTRLEN];
|
char ipv6addr[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
curnode = &ipv6_hash[ip.s6_addr[0]];
|
curnode = &ipv6_hash[ip.s6_addr[0]];
|
||||||
|
curnode = &ipv6_hash[((ip.s6_addr[0]) & 0xF0)>>4];
|
||||||
i = 1;
|
i = 1;
|
||||||
s = curnode->sess;
|
s = curnode->sess;
|
||||||
|
|
||||||
while (s == 0 && i < 15 && curnode->branch != NULL)
|
while (s == 0 && i < 32 && curnode->branch != NULL)
|
||||||
{
|
{
|
||||||
curnode = &curnode->branch[ip.s6_addr[i]];
|
if (i & 1)
|
||||||
|
curnode = &curnode->branch[ip.s6_addr[i>>1] & 0x0F];
|
||||||
|
else
|
||||||
|
curnode = &curnode->branch[(ip.s6_addr[i>>1] & 0xF0)>>4];
|
||||||
|
|
||||||
s = curnode->sess;
|
s = curnode->sess;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(4, s, session[s].tunnel, "Looking up address %s and got %d\n",
|
LOG(4, s, session[s].tunnel, "Looking up address %s and got %d\n",
|
||||||
inet_ntop(AF_INET6, &ip, ipv6addr,
|
inet_ntop(AF_INET6, &ip, ipv6addr,
|
||||||
INET6_ADDRSTRLEN),
|
INET6_ADDRSTRLEN),
|
||||||
s);
|
s);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
@ -1036,6 +1041,19 @@ sessionidt sessionbyipv6(struct in6_addr ip)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sessionidt sessionbyipv6new(struct in6_addr ip)
|
||||||
|
{
|
||||||
|
sessionidt s;
|
||||||
|
CSTAT(sessionbyipv6new);
|
||||||
|
|
||||||
|
s = lookup_ipv6map(ip);
|
||||||
|
|
||||||
|
if (s > 0 && s < MAXSESSION && session[s].opened)
|
||||||
|
return s;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Take an IP address in HOST byte order and
|
// Take an IP address in HOST byte order and
|
||||||
// add it to the sessionid by IP cache.
|
// add it to the sessionid by IP cache.
|
||||||
|
|
@ -1075,22 +1093,28 @@ static void uncache_ipmap(in_addr_t ip)
|
||||||
static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s)
|
static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int bytes;
|
int niblles;
|
||||||
struct ipv6radix *curnode;
|
struct ipv6radix *curnode;
|
||||||
char ipv6addr[INET6_ADDRSTRLEN];
|
char ipv6addr[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
curnode = &ipv6_hash[ip.s6_addr[0]];
|
curnode = &ipv6_hash[((ip.s6_addr[0]) & 0xF0)>>4];
|
||||||
|
|
||||||
bytes = prefixlen >> 3;
|
niblles = prefixlen >> 2;
|
||||||
i = 1;
|
i = 1;
|
||||||
while (i < bytes) {
|
|
||||||
|
while (i < niblles)
|
||||||
|
{
|
||||||
if (curnode->branch == NULL)
|
if (curnode->branch == NULL)
|
||||||
{
|
{
|
||||||
if (!(curnode->branch = calloc(256,
|
if (!(curnode->branch = calloc(16, sizeof (struct ipv6radix))))
|
||||||
sizeof (struct ipv6radix))))
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
curnode = &curnode->branch[ip.s6_addr[i]];
|
|
||||||
|
if (i & 1)
|
||||||
|
curnode = &curnode->branch[ip.s6_addr[i>>1] & 0x0F];
|
||||||
|
else
|
||||||
|
curnode = &curnode->branch[(ip.s6_addr[i>>1] & 0xF0)>>4];
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1098,13 +1122,13 @@ static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s)
|
||||||
|
|
||||||
if (s > 0)
|
if (s > 0)
|
||||||
LOG(4, s, session[s].tunnel, "Caching ip address %s/%d\n",
|
LOG(4, s, session[s].tunnel, "Caching ip address %s/%d\n",
|
||||||
inet_ntop(AF_INET6, &ip, ipv6addr,
|
inet_ntop(AF_INET6, &ip, ipv6addr,
|
||||||
INET6_ADDRSTRLEN),
|
INET6_ADDRSTRLEN),
|
||||||
prefixlen);
|
prefixlen);
|
||||||
else if (s == 0)
|
else if (s == 0)
|
||||||
LOG(4, 0, 0, "Un-caching ip address %s/%d\n",
|
LOG(4, 0, 0, "Un-caching ip address %s/%d\n",
|
||||||
inet_ntop(AF_INET6, &ip, ipv6addr,
|
inet_ntop(AF_INET6, &ip, ipv6addr,
|
||||||
INET6_ADDRSTRLEN),
|
INET6_ADDRSTRLEN),
|
||||||
prefixlen);
|
prefixlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1155,7 +1179,6 @@ int cmd_show_ipcache(struct cli_def *cli, const char *command, char **argv, int
|
||||||
return CLI_OK;
|
return CLI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Find session by username, 0 for not found
|
// Find session by username, 0 for not found
|
||||||
// walled garden users aren't authenticated, so the username is
|
// walled garden users aren't authenticated, so the username is
|
||||||
// reasonably useless. Ignore them to avoid incorrect actions
|
// reasonably useless. Ignore them to avoid incorrect actions
|
||||||
|
|
@ -1692,7 +1715,6 @@ static void processipv6out(uint8_t * buf, int len)
|
||||||
sessionidt s;
|
sessionidt s;
|
||||||
sessiont *sp;
|
sessiont *sp;
|
||||||
tunnelidt t;
|
tunnelidt t;
|
||||||
in_addr_t ip;
|
|
||||||
struct in6_addr ip6;
|
struct in6_addr ip6;
|
||||||
|
|
||||||
uint8_t *data = buf; // Keep a copy of the originals.
|
uint8_t *data = buf; // Keep a copy of the originals.
|
||||||
|
|
@ -1731,8 +1753,7 @@ static void processipv6out(uint8_t * buf, int len)
|
||||||
|
|
||||||
if (s == 0)
|
if (s == 0)
|
||||||
{
|
{
|
||||||
ip = *(uint32_t *)(buf + 32);
|
s = sessionbyipv6new(ip6);
|
||||||
s = sessionbyip(ip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s == 0)
|
if (s == 0)
|
||||||
|
|
|
||||||
2
l2tpns.h
2
l2tpns.h
|
|
@ -606,6 +606,7 @@ struct Tstats
|
||||||
uint32_t call_processudp;
|
uint32_t call_processudp;
|
||||||
uint32_t call_sessionbyip;
|
uint32_t call_sessionbyip;
|
||||||
uint32_t call_sessionbyipv6;
|
uint32_t call_sessionbyipv6;
|
||||||
|
uint32_t call_sessionbyipv6new;
|
||||||
uint32_t call_sessionbyuser;
|
uint32_t call_sessionbyuser;
|
||||||
uint32_t call_sendarp;
|
uint32_t call_sendarp;
|
||||||
uint32_t call_sendipcp;
|
uint32_t call_sendipcp;
|
||||||
|
|
@ -951,6 +952,7 @@ void send_ipv6_ra(sessionidt s, tunnelidt t, struct in6_addr *ip);
|
||||||
void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add);
|
void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add);
|
||||||
sessionidt sessionbyip(in_addr_t ip);
|
sessionidt sessionbyip(in_addr_t ip);
|
||||||
sessionidt sessionbyipv6(struct in6_addr ip);
|
sessionidt sessionbyipv6(struct in6_addr ip);
|
||||||
|
sessionidt sessionbyipv6new(struct in6_addr ip);
|
||||||
sessionidt sessionbyuser(char *username);
|
sessionidt sessionbyuser(char *username);
|
||||||
void increment_counter(uint32_t *counter, uint32_t *wrap, uint32_t delta);
|
void increment_counter(uint32_t *counter, uint32_t *wrap, uint32_t delta);
|
||||||
void random_data(uint8_t *buf, int len);
|
void random_data(uint8_t *buf, int len);
|
||||||
|
|
|
||||||
25
ppp.c
25
ppp.c
|
|
@ -1580,8 +1580,16 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
gotip++; // seen address
|
gotip++; // seen address
|
||||||
if (o[1] != 10) return;
|
if (o[1] != 10) return;
|
||||||
|
|
||||||
ident[0] = htonl(session[s].ip);
|
if (session[s].ipv6address.s6_addr[0])
|
||||||
ident[1] = 0;
|
{
|
||||||
|
// LSB 64bits of assigned IPv6 address to user (see radius attribut Framed-IPv6-Address)
|
||||||
|
memcpy(&ident[0], &session[s].ipv6address.s6_addr[8], 8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ident[0] = htonl(session[s].ip);
|
||||||
|
ident[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (memcmp(o + 2, ident, sizeof(ident)))
|
if (memcmp(o + 2, ident, sizeof(ident)))
|
||||||
{
|
{
|
||||||
|
|
@ -2254,7 +2262,18 @@ void processipv6in(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// no spoof
|
// no spoof
|
||||||
if ((ipv4 != session[s].ip || memcmp(&config->ipv6_prefix, &ip, 8)) && sessionbyipv6(ip) != s)
|
if (session[s].ipv6address.s6_addr[0])
|
||||||
|
{
|
||||||
|
if ((sessionbyipv6new(ip) != s) &&
|
||||||
|
(ip.s6_addr[0] != 0xFE || ip.s6_addr[1] != 0x80 || ip.s6_addr16[1] != 0 || ip.s6_addr16[2] != 0 || ip.s6_addr16[3] != 0))
|
||||||
|
{
|
||||||
|
char str[INET6_ADDRSTRLEN];
|
||||||
|
LOG(5, s, t, "Dropping packet with spoofed IP %s\n",
|
||||||
|
inet_ntop(AF_INET6, &ip, str, INET6_ADDRSTRLEN));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((ipv4 != session[s].ip || memcmp(&config->ipv6_prefix, &ip, 8)) && sessionbyipv6(ip) != s)
|
||||||
{
|
{
|
||||||
char str[INET6_ADDRSTRLEN];
|
char str[INET6_ADDRSTRLEN];
|
||||||
LOG(5, s, t, "Dropping packet with spoofed IP %s\n",
|
LOG(5, s, t, "Dropping packet with spoofed IP %s\n",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue