struct ipv6radix {
sessionidt sess;
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.
static uint32_t udp_rx = 0, udp_rx_pkt = 0, udp_tx = 0;
char ipv6addr[INET6_ADDRSTRLEN];
curnode = &ipv6_hash[ip.s6_addr[0]];
+ curnode = &ipv6_hash[((ip.s6_addr[0]) & 0xF0)>>4];
i = 1;
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;
i++;
}
LOG(4, s, session[s].tunnel, "Looking up address %s and got %d\n",
- inet_ntop(AF_INET6, &ip, ipv6addr,
- INET6_ADDRSTRLEN),
+ inet_ntop(AF_INET6, &ip, ipv6addr,
+ INET6_ADDRSTRLEN),
s);
return s;
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
// add it to the sessionid by IP cache.
static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s)
{
int i;
- int bytes;
+ int niblles;
struct ipv6radix *curnode;
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;
- while (i < bytes) {
+
+ while (i < niblles)
+ {
if (curnode->branch == NULL)
{
- if (!(curnode->branch = calloc(256,
- sizeof (struct ipv6radix))))
+ if (!(curnode->branch = calloc(16, sizeof (struct ipv6radix))))
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++;
}
if (s > 0)
LOG(4, s, session[s].tunnel, "Caching ip address %s/%d\n",
- inet_ntop(AF_INET6, &ip, ipv6addr,
- INET6_ADDRSTRLEN),
+ inet_ntop(AF_INET6, &ip, ipv6addr,
+ INET6_ADDRSTRLEN),
prefixlen);
else if (s == 0)
LOG(4, 0, 0, "Un-caching ip address %s/%d\n",
- inet_ntop(AF_INET6, &ip, ipv6addr,
- INET6_ADDRSTRLEN),
+ inet_ntop(AF_INET6, &ip, ipv6addr,
+ INET6_ADDRSTRLEN),
prefixlen);
}
return CLI_OK;
}
-
// Find session by username, 0 for not found
// walled garden users aren't authenticated, so the username is
// reasonably useless. Ignore them to avoid incorrect actions
sessionidt s;
sessiont *sp;
tunnelidt t;
- in_addr_t ip;
struct in6_addr ip6;
uint8_t *data = buf; // Keep a copy of the originals.
if (s == 0)
{
- ip = *(uint32_t *)(buf + 32);
- s = sessionbyip(ip);
+ s = sessionbyipv6new(ip6);
}
-
+
if (s == 0)
{
// Is this a packet for a session that doesn't exist?