X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/b3f40f41f7de7a383c6f1170e546d0b09cc57338..refs/heads/infinite-loop-protection:/l2tpns.c?ds=sidebyside diff --git a/l2tpns.c b/l2tpns.c index 07a45f7..0838607 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), @@ -162,6 +163,7 @@ config_descriptt config_values[] = { CONFIG("icmp_rate", icmp_rate, INT), CONFIG("packet_limit", max_packets, INT), CONFIG("cluster_address", cluster_address, IPv4), + CONFIG("cluster_port", cluster_port, INT), CONFIG("cluster_interface", cluster_interface, STRING), CONFIG("cluster_mcast_ttl", cluster_mcast_ttl, INT), CONFIG("cluster_hb_interval", cluster_hb_interval, INT), @@ -194,6 +196,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 +985,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 +1043,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 +1095,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 +1124,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 +1181,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 +1717,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 +1755,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? @@ -2128,8 +2151,11 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e free_ip_address(s); // unroute IPv6, if setup - if (session[s].ipv6route.s6_addr[0] && session[s].ipv6prefixlen && del_routes) - route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0); + for (r = 0; r < MAXROUTE6 && session[s].route6[r].ipv6route.s6_addr[0] && session[s].route6[r].ipv6prefixlen; r++) + { + if (del_routes) route6set(s, session[s].route6[r].ipv6route, session[s].route6[r].ipv6prefixlen, 0); + memset(&session[s].route6[r], 0, sizeof(session[s].route6[r])); + } if (session[s].ipv6address.s6_addr[0] && del_routes) { @@ -2189,8 +2215,10 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e cache_ipmap(session[new_s].ip, new_s); // IPV6 route - if (session[new_s].ipv6prefixlen) - cache_ipv6map(session[new_s].ipv6route, session[new_s].ipv6prefixlen, new_s); + for (r = 0; r < MAXROUTE6 && session[new_s].route6[r].ipv6prefixlen; r++) + { + cache_ipv6map(session[new_s].route6[r].ipv6route, session[new_s].route6[r].ipv6prefixlen, new_s); + } if (session[new_s].ipv6address.s6_addr[0]) { @@ -2688,7 +2716,14 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu result = 2; // general error error = 3; // reserved field non-zero msg = 0; - continue; // next + if (n == 0) + { + // if continue a infinity loop is created. + LOG(1, s, t, "It's infinite loop protection %02X\n", *b); + return; + } + else + continue; // next } b += 2; if (*(uint16_t *) (b)) @@ -2698,7 +2733,14 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu result = 2; // general error error = 6; // generic vendor-specific error msg = "unsupported vendor-specific"; - continue; // next + if (n == 0) + { + // if continue a infinity loop is created. + LOG(1, s, t, "It's infinite loop protection %02X\n", *b); + return; + } + else + continue; // next } b += 2; mtype = ntohs(*(uint16_t *) (b)); @@ -2758,7 +2800,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu n = orig_len; } - LOG(4, s, t, " AVP %u (%s) len %d%s%s\n", mtype, l2tp_avp_name(mtype), n, + LOG(3, s, t, " AVP %u (%s) len %d%s%s\n", mtype, l2tp_avp_name(mtype), n, flags & 0x40 ? ", hidden" : "", flags & 0x80 ? ", mandatory" : ""); switch (mtype) @@ -2766,7 +2808,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu case 0: // message type message = ntohs(*(uint16_t *) b); mandatory = flags & 0x80; - LOG(4, s, t, " Message type = %u (%s)\n", message, l2tp_code(message)); + LOG(3, s, t, " Message type = %u (%s)\n", message, l2tp_code(message)); break; case 1: // result code { @@ -2789,15 +2831,15 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu cause = TERM_ADMIN_RESET; } - LOG(4, s, t, " Result Code %u: %s\n", rescode, resdesc); + LOG(3, s, t, " Result Code %u: %s\n", rescode, resdesc); if (n >= 4) { uint16_t errcode = ntohs(*(uint16_t *)(b + 2)); errdesc = l2tp_error_code(errcode); - LOG(4, s, t, " Error Code %u: %s\n", errcode, errdesc); + LOG(3, s, t, " Error Code %u: %s\n", errcode, errdesc); } if (n > 4) - LOG(4, s, t, " Error String: %.*s\n", n-4, b+4); + LOG(3, s, t, " Error String: %.*s\n", n-4, b+4); if (cause && disc_cause_set < mtype) // take cause from attrib 46 in preference { @@ -2812,7 +2854,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu case 2: // protocol version { version = ntohs(*(uint16_t *) (b)); - LOG(4, s, t, " Protocol version = %u\n", version); + LOG(3, s, t, " Protocol version = %u\n", version); if (version && version != 0x0100) { // allow 0.0 and 1.0 LOG(1, s, t, " Bad protocol version %04X\n", version); @@ -2836,27 +2878,27 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu case 7: // host name memset(tunnel[t].hostname, 0, sizeof(tunnel[t].hostname)); memcpy(tunnel[t].hostname, b, (n < sizeof(tunnel[t].hostname)) ? n : sizeof(tunnel[t].hostname) - 1); - LOG(4, s, t, " Tunnel hostname = \"%s\"\n", tunnel[t].hostname); + LOG(3, s, t, " Tunnel hostname = \"%s\"\n", tunnel[t].hostname); // TBA - to send to RADIUS break; case 8: // vendor name memset(tunnel[t].vendor, 0, sizeof(tunnel[t].vendor)); memcpy(tunnel[t].vendor, b, (n < sizeof(tunnel[t].vendor)) ? n : sizeof(tunnel[t].vendor) - 1); - LOG(4, s, t, " Vendor name = \"%s\"\n", tunnel[t].vendor); + LOG(3, s, t, " Vendor name = \"%s\"\n", tunnel[t].vendor); break; case 9: // assigned tunnel tunnel[t].far = ntohs(*(uint16_t *) (b)); - LOG(4, s, t, " Remote tunnel id = %u\n", tunnel[t].far); + LOG(3, s, t, " Remote tunnel id = %u\n", tunnel[t].far); break; case 10: // rx window tunnel[t].window = ntohs(*(uint16_t *) (b)); if (!tunnel[t].window) tunnel[t].window = 1; // window of 0 is silly - LOG(4, s, t, " rx window = %u\n", tunnel[t].window); + LOG(3, s, t, " rx window = %u\n", tunnel[t].window); break; case 11: // Request Challenge { - LOG(4, s, t, " LAC requested CHAP authentication for tunnel\n"); + LOG(3, s, t, " LAC requested CHAP authentication for tunnel\n"); if (message == 1) build_chap_response(b, 2, n, &sendchalresponse); else if (message == 2) @@ -2877,28 +2919,28 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu case 14: // assigned session asession = session[s].far = ntohs(*(uint16_t *) (b)); - LOG(4, s, t, " assigned session = %u\n", asession); + LOG(3, s, t, " assigned session = %u\n", asession); break; case 15: // call serial number - LOG(4, s, t, " call serial number = %u\n", ntohl(*(uint32_t *)b)); + LOG(3, s, t, " call serial number = %u\n", ntohl(*(uint32_t *)b)); break; case 18: // bearer type - LOG(4, s, t, " bearer type = %u\n", ntohl(*(uint32_t *)b)); + LOG(3, s, t, " bearer type = %u\n", ntohl(*(uint32_t *)b)); // TBA - for RADIUS break; case 19: // framing type - LOG(4, s, t, " framing type = %u\n", ntohl(*(uint32_t *)b)); + LOG(3, s, t, " framing type = %u\n", ntohl(*(uint32_t *)b)); // TBA break; case 21: // called number memset(called, 0, sizeof(called)); memcpy(called, b, (n < sizeof(called)) ? n : sizeof(called) - 1); - LOG(4, s, t, " Called <%s>\n", called); + LOG(3, s, t, " Called <%s>\n", called); break; case 22: // calling number memset(calling, 0, sizeof(calling)); memcpy(calling, b, (n < sizeof(calling)) ? n : sizeof(calling) - 1); - LOG(4, s, t, " Calling <%s>\n", calling); + LOG(3, s, t, " Calling <%s>\n", calling); break; case 23: // subtype break; @@ -2915,7 +2957,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu memcpy(tmp, b, (n < sizeof(tmp)) ? n : sizeof(tmp) - 1); session[s].tx_connect_speed = atol(tmp); } - LOG(4, s, t, " TX connect speed <%u>\n", session[s].tx_connect_speed); + LOG(3, s, t, " TX connect speed <%u>\n", session[s].tx_connect_speed); break; case 38: // rx connect speed if (n == 4) @@ -2930,18 +2972,18 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu memcpy(tmp, b, (n < sizeof(tmp)) ? n : sizeof(tmp) - 1); session[s].rx_connect_speed = atol(tmp); } - LOG(4, s, t, " RX connect speed <%u>\n", session[s].rx_connect_speed); + LOG(3, s, t, " RX connect speed <%u>\n", session[s].rx_connect_speed); break; case 25: // Physical Channel ID { uint32_t tmp = ntohl(*(uint32_t *) b); - LOG(4, s, t, " Physical Channel ID <%X>\n", tmp); + LOG(3, s, t, " Physical Channel ID <%X>\n", tmp); break; } case 29: // Proxy Authentication Type { uint16_t atype = ntohs(*(uint16_t *)b); - LOG(4, s, t, " Proxy Auth Type %u (%s)\n", atype, ppp_auth_type(atype)); + LOG(3, s, t, " Proxy Auth Type %u (%s)\n", atype, ppp_auth_type(atype)); break; } case 30: // Proxy Authentication Name @@ -2949,23 +2991,23 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu char authname[64]; memset(authname, 0, sizeof(authname)); memcpy(authname, b, (n < sizeof(authname)) ? n : sizeof(authname) - 1); - LOG(4, s, t, " Proxy Auth Name (%s)\n", + LOG(3, s, t, " Proxy Auth Name (%s)\n", authname); break; } case 31: // Proxy Authentication Challenge { - LOG(4, s, t, " Proxy Auth Challenge\n"); + LOG(3, s, t, " Proxy Auth Challenge\n"); break; } case 32: // Proxy Authentication ID { uint16_t authid = ntohs(*(uint16_t *)(b)); - LOG(4, s, t, " Proxy Auth ID (%u)\n", authid); + LOG(3, s, t, " Proxy Auth ID (%u)\n", authid); break; } case 33: // Proxy Authentication Response - LOG(4, s, t, " Proxy Auth Response\n"); + LOG(3, s, t, " Proxy Auth Response\n"); break; case 27: // last sent lcp { // find magic number @@ -2989,7 +3031,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu case 39: // seq required - we control it as an LNS anyway... break; case 36: // Random Vector - LOG(4, s, t, " Random Vector received. Enabled AVP Hiding.\n"); + LOG(3, s, t, " Random Vector received. Enabled AVP Hiding.\n"); memset(session[s].random_vector, 0, sizeof(session[s].random_vector)); if (n > sizeof(session[s].random_vector)) n = sizeof(session[s].random_vector); @@ -3003,7 +3045,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu uint16_t proto = ntohs(*(uint16_t *) (b + 2)); uint8_t dir = *(b + 4); - LOG(4, s, t, " PPP disconnect cause " + LOG(3, s, t, " PPP disconnect cause " "(code=%u, proto=%04X, dir=%u, msg=\"%.*s\")\n", code, proto, dir, n - 5, b + 5); @@ -3754,8 +3796,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]; @@ -4574,6 +4618,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; @@ -5596,6 +5643,7 @@ static void update_config() memcpy(config->old_plugins, config->plugins, sizeof(config->plugins)); if (!config->multi_read_count) config->multi_read_count = 10; if (!config->cluster_address) config->cluster_address = inet_addr(DEFAULT_MCAST_ADDR); + if (!config->cluster_port) config->cluster_port = CLUSTERPORT; if (!*config->cluster_interface) strncpy(config->cluster_interface, DEFAULT_MCAST_INTERFACE, sizeof(config->cluster_interface) - 1); @@ -5830,7 +5878,7 @@ int load_session(sessionidt s, sessiont *new) // needs update if (newip) { - int routed = 0; + int routed = 0; // remove old routes... for (i = 0; i < MAXROUTE && session[s].route[i].ip; i++) @@ -5854,8 +5902,10 @@ int load_session(sessionidt s, sessiont *new) } // remove old IPV6 routes... - if (session[s].ipv6route.s6_addr[0] && session[s].ipv6prefixlen) - route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0); + for (i = 0; i < MAXROUTE6 && session[s].route6[i].ipv6route.s6_addr[0] && session[s].route6[i].ipv6prefixlen; i++) + { + route6set(s, session[s].route6[i].ipv6route, session[s].route6[i].ipv6prefixlen, 0); + } if (session[s].ipv6address.s6_addr[0]) { @@ -5888,12 +5938,19 @@ int load_session(sessionidt s, sessiont *new) } // check v6 routing - if (new->ipv6prefixlen && new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened) - route6set(s, new->ipv6route, new->ipv6prefixlen, 1); + if (new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened) + { + 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) { - route6set(s, new->ipv6address, 128, 1); + // Check if included in prefix + if (sessionbyipv6(new->ipv6address) != s) + route6set(s, new->ipv6address, 128, 1); } // check filters