X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/14031c41a5c8e4e2513c6bfd65d5019da7611156..ba1c3362c6dc0d65eb3d06368c47b75aa135456b:/l2tpns.c?ds=sidebyside diff --git a/l2tpns.c b/l2tpns.c index 9ac6bfd..5403364 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -10,6 +10,7 @@ #include #include #define SYSLOG_NAMES +#include #include #include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -40,6 +40,7 @@ #include #include "md5.h" +#include "dhcp6.h" #include "l2tpns.h" #include "cluster.h" #include "plugin.h" @@ -55,6 +56,7 @@ #include "l2tplac.h" #include "pppoe.h" +#include "dhcp6.h" char * Vendor_name = "Linux L2TPNS"; uint32_t call_serial_number = 0; @@ -186,6 +188,13 @@ config_descriptt config_values[] = { CONFIG("grp_txrate_average_time", grp_txrate_average_time, INT), CONFIG("pppoe_only_equal_svc_name", pppoe_only_equal_svc_name, BOOL), CONFIG("multi_hostname", multi_hostname, STRING), + CONFIG("no_throttle_local_IP", no_throttle_local_IP, BOOL), + 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("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), { NULL, 0, 0, 0 } }; @@ -1010,8 +1019,10 @@ sessionidt sessionbyipv6(struct in6_addr ip) ip.s6_addr[1] == 0x80 && ip.s6_addr16[1] == 0 && ip.s6_addr16[2] == 0 && - ip.s6_addr16[3] == 0)) { - s = lookup_ipmap(*(in_addr_t *) &ip.s6_addr[8]); + ip.s6_addr16[3] == 0)) + { + in_addr_t *pipv4 = (in_addr_t *) &ip.s6_addr[8]; + s = lookup_ipmap(*pipv4); } else { s = lookup_ipv6map(ip); } @@ -1097,7 +1108,7 @@ static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s) // // CLI list to dump current ipcache. // -int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc) +int cmd_show_ipcache(struct cli_def *cli, const char *command, char **argv, int argc) { union iphash *d = ip_hash, *e, *f, *g; int i, j, k, l; @@ -1413,7 +1424,7 @@ void processipout(uint8_t *buf, int len) groupidt g; sessiont *sp; tunnelidt t; - in_addr_t ip; + in_addr_t ip, ip_src; uint8_t *data = buf; // Keep a copy of the originals. int size = len; @@ -1446,10 +1457,11 @@ void processipout(uint8_t *buf, int len) return; } + ip_src = *(uint32_t *)(buf + 12); ip = *(uint32_t *)(buf + 16); if ((g = grp_groupbyip(ip))) { - s = grp_getnextsession(g, ip); + s = grp_getnextsession(g, ip, ip_src); if (!s) { // Is this a packet for a session that doesn't exist? @@ -1554,12 +1566,15 @@ void processipout(uint8_t *buf, int len) if (sp->tbf_out) { - // Are we throttling this session? - if (config->cluster_iam_master) - tbf_queue_packet(sp->tbf_out, data, size); - else - master_throttle_packet(sp->tbf_out, data, size); - return; + if (!config->no_throttle_local_IP || !sessionbyip(ip_src)) + { + // Are we throttling this session? + if (config->cluster_iam_master) + tbf_queue_packet(sp->tbf_out, data, size); + else + master_throttle_packet(sp->tbf_out, data, size); + return; + } } if (sp->walled_garden && !config->cluster_iam_master) @@ -1821,6 +1836,8 @@ static void send_ipout(sessionidt s, uint8_t *buf, int len) { sessiont *sp; tunnelidt t; + uint8_t *p; + uint8_t *data = buf; // Keep a copy of the originals. uint8_t b[MAXETHER + 20]; @@ -1843,11 +1860,14 @@ static void send_ipout(sessionidt s, uint8_t *buf, int len) LOG(5, s, t, "Ethernet -> Tunnel (%d bytes)\n", len); // Add on L2TP header - { - uint8_t *p = makeppp(b, sizeof(b), buf, len, s, t, PPPIP, 0, 0, 0); - if (!p) return; - tunnelsend(b, len + (p-b), t); // send it... - } + if (*(uint16_t *) (data + 2) == htons(PKTIPV6)) + p = makeppp(b, sizeof(b), buf, len, s, t, PPPIPV6, 0, 0, 0); // IPV6 + else + p = makeppp(b, sizeof(b), buf, len, s, t, PPPIP, 0, 0, 0); // IPV4 + + if (!p) return; + + tunnelsend(b, len + (p-b), t); // send it... // Snooping this session. if (sp->snoop_ip && sp->snoop_port) @@ -1866,10 +1886,11 @@ static void send_ipout(sessionidt s, uint8_t *buf, int len) static void control16(controlt * c, uint16_t avp, uint16_t val, uint8_t m) { uint16_t l = (m ? 0x8008 : 0x0008); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); - *(uint16_t *) (c->buf + c->length + 6) = htons(val); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); + pint16[3] = htons(val); c->length += 8; } @@ -1877,10 +1898,12 @@ static void control16(controlt * c, uint16_t avp, uint16_t val, uint8_t m) static void control32(controlt * c, uint16_t avp, uint32_t val, uint8_t m) { uint16_t l = (m ? 0x800A : 0x000A); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); - *(uint32_t *) (c->buf + c->length + 6) = htonl(val); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + uint32_t *pint32 = (uint32_t *) (c->buf + c->length + 6); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); + pint32[0] = htonl(val); c->length += 10; } @@ -1888,9 +1911,10 @@ static void control32(controlt * c, uint16_t avp, uint32_t val, uint8_t m) static void controls(controlt * c, uint16_t avp, char *val, uint8_t m) { uint16_t l = ((m ? 0x8000 : 0) + strlen(val) + 6); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); memcpy(c->buf + c->length + 6, val, strlen(val)); c->length += 6 + strlen(val); } @@ -1899,9 +1923,10 @@ static void controls(controlt * c, uint16_t avp, char *val, uint8_t m) static void controlb(controlt * c, uint16_t avp, uint8_t *val, unsigned int len, uint8_t m) { uint16_t l = ((m ? 0x8000 : 0) + len + 6); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); memcpy(c->buf + c->length + 6, val, len); c->length += 6 + len; } @@ -1946,10 +1971,11 @@ static void controlnull(tunnelidt t) // add a control message to a tunnel, and send if within window static void controladd(controlt *c, sessionidt far, tunnelidt t) { - *(uint16_t *) (c->buf + 2) = htons(c->length); // length - *(uint16_t *) (c->buf + 4) = htons(tunnel[t].far); // tunnel - *(uint16_t *) (c->buf + 6) = htons(far); // session - *(uint16_t *) (c->buf + 8) = htons(tunnel[t].ns); // sequence + uint16_t *pint16 = (uint16_t *) (c->buf + 2); + pint16[0] = htons(c->length); // length + pint16[1] = htons(tunnel[t].far); // tunnel + pint16[2] = htons(far); // session + pint16[3] = htons(tunnel[t].ns); // sequence tunnel[t].ns++; // advance sequence // link in message in to queue if (tunnel[t].controlc) @@ -2124,9 +2150,14 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e free_ip_address(s); // unroute IPv6, if setup - if (session[s].ppp.ipv6cp == Opened && session[s].ipv6prefixlen && del_routes) + if (session[s].ipv6route.s6_addr[0] && session[s].ipv6prefixlen && del_routes) route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0); - + + if (session[s].ipv6address.s6_addr[0] && del_routes) + { + route6set(s, session[s].ipv6address, 128, 0); + } + if (b) { // This session was part of a bundle @@ -2182,6 +2213,11 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e // IPV6 route if (session[new_s].ipv6prefixlen) cache_ipv6map(session[new_s].ipv6route, session[new_s].ipv6prefixlen, new_s); + + if (session[new_s].ipv6address.s6_addr[0]) + { + cache_ipv6map(session[new_s].ipv6address, 128, new_s); + } } } } @@ -3427,6 +3463,20 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu return; } + if (!config->cluster_iam_master) + { + // Check if DhcpV6, IP dst: FF02::1:2, Src Port 0x0222 (546), Dst Port 0x0223 (547) + if (*(p + 6) == 17 && *(p + 24) == 0xFF && *(p + 25) == 2 && + *(uint32_t *)(p + 26) == 0 && *(uint32_t *)(p + 30) == 0 && + *(uint16_t *)(p + 34) == 0 && *(p + 36) == 0 && *(p + 37) == 1 && *(p + 38) == 0 && *(p + 39) == 2 && + *(p + 40) == 2 && *(p + 41) == 0x22 && *(p + 42) == 2 && *(p + 43) == 0x23) + { + // DHCPV6 must be managed by the Master. + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); + return; + } + } + processipv6in(s, t, p, l); } else if (session[s].ppp.lcp == Opened) @@ -5074,9 +5124,9 @@ int main(int argc, char *argv[]) case 'd': if (fork()) exit(0); setsid(); - freopen("/dev/null", "r", stdin); - freopen("/dev/null", "w", stdout); - freopen("/dev/null", "w", stderr); + if(!freopen("/dev/null", "r", stdin)) LOG(0, 0, 0, "Error freopen stdin: %s\n", strerror(errno)); + if(!freopen("/dev/null", "w", stdout)) LOG(0, 0, 0, "Error freopen stdout: %s\n", strerror(errno)); + if(!freopen("/dev/null", "w", stderr)) LOG(0, 0, 0, "Error freopen stderr: %s\n", strerror(errno)); break; case 'v': optdebug++; @@ -5116,6 +5166,7 @@ int main(int argc, char *argv[]) init_tbf(config->num_tbfs); LOG(0, 0, 0, "L2TPNS version " VERSION "\n"); + LOG(0, 0, 0, "Copyright (c) 2012, 2013, 2014 ISP FDN & SAMESWIRELESS\n"); LOG(0, 0, 0, "Copyright (c) 2003, 2004, 2005, 2006 Optus Internet Engineering\n"); LOG(0, 0, 0, "Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced\n"); { @@ -5127,7 +5178,7 @@ int main(int argc, char *argv[]) LOG(0, 0, 0, "Can't set ulimit: %s\n", strerror(errno)); // Make core dumps go to /tmp - chdir("/tmp"); + if(chdir("/tmp")) LOG(0, 0, 0, "Error chdir /tmp: %s\n", strerror(errno)); } if (config->scheduler_fifo) @@ -5191,6 +5242,7 @@ int main(int argc, char *argv[]) initrad(); initippool(); + dhcpv6_init(); // seed prng { @@ -5843,6 +5895,15 @@ int load_session(sessionidt s, sessiont *new) uncache_ipmap(session[s].ip); } + // remove old IPV6 routes... + if (session[s].ipv6route.s6_addr[0] && session[s].ipv6prefixlen) + route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0); + + if (session[s].ipv6address.s6_addr[0]) + { + route6set(s, session[s].ipv6address, 128, 0); + } + routed = 0; // add new routes... @@ -5870,7 +5931,14 @@ 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); + route6set(s, new->ipv6route, new->ipv6prefixlen, 1); + + if (new->ipv6address.s6_addr[0] && new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened) + { + // Check if included in prefix + if (sessionbyipv6(new->ipv6address) != s) + route6set(s, new->ipv6address, 128, 1); + } // check filters if (new->filter_in && (new->filter_in > MAXFILTER || !ip_filters[new->filter_in - 1].name[0])) @@ -6317,7 +6385,7 @@ void become_master(void) } } -int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc) +int cmd_show_hist_idle(struct cli_def *cli, const char *command, char **argv, int argc) { int s, i; int count = 0; @@ -6355,7 +6423,7 @@ int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc return CLI_OK; } -int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc) +int cmd_show_hist_open(struct cli_def *cli, const char *command, char **argv, int argc) { int s, i; int count = 0;