X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/e98fe681743394f8a5c1434d1909b202eac9ad0a..b1cd5081631f84c89823dba802aa023c80865a79:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index cc69c2d..1c50a3e 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -102,7 +102,7 @@ union iphash { 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; @@ -132,6 +132,7 @@ config_descriptt config_values[] = { CONFIG("ppp_restart_time", ppp_restart_time, INT), CONFIG("ppp_max_configure", ppp_max_configure, INT), CONFIG("ppp_max_failure", ppp_max_failure, INT), + CONFIG("ppp_keepalive", ppp_keepalive, BOOL), CONFIG("primary_dns", default_dns1, IPv4), CONFIG("secondary_dns", default_dns2, IPv4), CONFIG("primary_radius", radiusserver[0], IPv4), @@ -194,6 +195,7 @@ config_descriptt config_values[] = { CONFIG("dhcp6_preferred_lifetime", dhcp6_preferred_lifetime, INT), CONFIG("dhcp6_valid_lifetime", dhcp6_valid_lifetime, INT), CONFIG("dhcp6_server_duid", dhcp6_server_duid, INT), + CONFIG("dns6_lifetime", dns6_lifetime, INT), CONFIG("primary_ipv6_dns", default_ipv6_dns1, IPv6), CONFIG("secondary_ipv6_dns", default_ipv6_dns2, IPv6), CONFIG("default_ipv6_domain_list", default_ipv6_domain_list, STRING), @@ -982,20 +984,24 @@ static sessionidt lookup_ipv6map(struct in6_addr ip) int s; 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; @@ -1036,6 +1042,19 @@ sessionidt sessionbyipv6(struct in6_addr ip) 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. @@ -1075,22 +1094,28 @@ static void uncache_ipmap(in_addr_t ip) 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++; } @@ -1098,13 +1123,13 @@ static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s) 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); } @@ -1155,7 +1180,6 @@ int cmd_show_ipcache(struct cli_def *cli, const char *command, char **argv, int 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 @@ -1692,7 +1716,6 @@ static void processipv6out(uint8_t * buf, int len) sessionidt s; sessiont *sp; tunnelidt t; - in_addr_t ip; struct in6_addr ip6; uint8_t *data = buf; // Keep a copy of the originals. @@ -1731,10 +1754,9 @@ static void processipv6out(uint8_t * buf, int len) 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? @@ -3759,8 +3781,10 @@ static void regular_cleanups(double period) } // No data in ECHO_TIMEOUT seconds, send LCP ECHO - if (session[s].ppp.phase >= Establish && (time_now - session[s].last_packet >= config->echo_timeout) && - (time_now - sess_local[s].last_echo >= ECHO_TIMEOUT)) + if (session[s].ppp.phase >= Establish && + ((!config->ppp_keepalive) || + (time_now - session[s].last_packet >= config->echo_timeout)) && + (time_now - sess_local[s].last_echo >= ECHO_TIMEOUT)) { uint8_t b[MAXETHER]; @@ -4579,6 +4603,9 @@ static void initdata(int optdebug, char *optconfig) // Set default value echo_timeout and idle_echo_timeout config->echo_timeout = ECHO_TIMEOUT; config->idle_echo_timeout = IDLE_ECHO_TIMEOUT; + config->ppp_keepalive = 1; + // Set default RDNSS lifetime + config->dns6_lifetime = 1200; log_stream = stderr; @@ -5895,9 +5922,12 @@ int load_session(sessionidt s, sessiont *new) } // check v6 routing - for (i = 0; i < MAXROUTE6 && new->route6[i].ipv6prefixlen; i++) + if (new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened) { - route6set(s, new->route6[i].ipv6route, new->route6[i].ipv6prefixlen, 1); + for (i = 0; i < MAXROUTE6 && new->route6[i].ipv6prefixlen; i++) + { + route6set(s, new->route6[i].ipv6route, new->route6[i].ipv6prefixlen, 1); + } } if (new->ipv6address.s6_addr[0] && new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened)