X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/91fc2ec13bb4bf58770085375a91a75f2413fa71..92bfbe46e854e7ff40d6d4297c8df74f1efcf10f:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index c41b502..5445013 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; @@ -75,7 +77,7 @@ int cluster_sockfd = -1; // Intra-cluster communications socket. int epollfd = -1; // event polling time_t basetime = 0; // base clock char hostname[MAXHOSTNAME] = ""; // us. -static int tunidx; // ifr_ifindex of tun device +int tunidx; // ifr_ifindex of tun device int nlseqnum = 0; // netlink sequence number int min_initok_nlseqnum = 0; // minimun seq number for messages after init is ok static int syslog_log = 0; // are we logging to syslog @@ -92,15 +94,16 @@ uint16_t MSS = 0; // TCP MSS struct cli_session_actions *cli_session_actions = NULL; // Pending session changes requested by CLI struct cli_tunnel_actions *cli_tunnel_actions = NULL; // Pending tunnel changes required by CLI -union iphash { +union iphash +{ sessionidt sess; union iphash *idx; -} ip_hash[256]; // Mapping from IP address to session structures. +}ip_hash[256]; // Mapping from IP address to session structures. 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; @@ -186,8 +189,16 @@ config_descriptt config_values[] = { CONFIG("disable_sending_hello", disable_sending_hello, BOOL), CONFIG("disable_no_spoof", disable_no_spoof, BOOL), CONFIG("bind_multi_address", bind_multi_address, STRING), + 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 } }; @@ -216,6 +227,7 @@ tunnelt *tunnel = NULL; // Array of tunnel structures. bundlet *bundle = NULL; // Array of bundle structures. fragmentationt *frag = NULL; // Array of fragmentation structures. sessiont *session = NULL; // Array of session structures. +groupsesst *grpsession = NULL; // Array of groupsesst structures. sessionlocalt *sess_local = NULL; // Array of local per-session counters. radiust *radius = NULL; // Array of radius structures. ippoolt *ip_address_pool = NULL; // Array of dynamic IP addresses. @@ -226,9 +238,6 @@ struct Tstats *_statistics = NULL; struct Tringbuffer *ringbuffer = NULL; #endif -static ssize_t netlink_send(struct nlmsghdr *nh); -static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen); -static void cache_ipmap(in_addr_t ip, sessionidt s); static void uncache_ipmap(in_addr_t ip); static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s); static void free_ip_address(sessionidt s); @@ -257,8 +266,9 @@ static clockt now(double *f) if (f) *f = t.tv_sec + t.tv_usec / 1000000.0; if (t.tv_sec != time_now) { - time_now = t.tv_sec; - time_changed++; + time_now = t.tv_sec; + time_changed++; + grp_time_changed(); } // Time in milliseconds @@ -617,7 +627,7 @@ static void initnetlink(void) } } -static ssize_t netlink_send(struct nlmsghdr *nh) +ssize_t netlink_send(struct nlmsghdr *nh) { struct sockaddr_nl nladdr; struct iovec iov; @@ -653,7 +663,7 @@ static ssize_t netlink_recv(void *buf, ssize_t len) } /* adapted from iproute2 */ -static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) +void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) { int len = RTA_LENGTH(alen); struct rtattr *rta; @@ -973,20 +983,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; @@ -1013,8 +1027,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); } @@ -1025,13 +1041,26 @@ 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. // // (It's actually cached in network order) // -static void cache_ipmap(in_addr_t ip, sessionidt s) +void cache_ipmap(in_addr_t ip, sessionidt s) { in_addr_t nip = htonl(ip); // MUST be in network order. I.e. MSB must in be ((char *) (&ip))[0] uint8_t *a = (uint8_t *) &nip; @@ -1050,7 +1079,6 @@ static void cache_ipmap(in_addr_t ip, sessionidt s) if (s > 0) LOG(4, s, session[s].tunnel, "Caching ip address %s\n", fmtaddr(nip, 0)); - else if (s == 0) LOG(4, 0, 0, "Un-caching ip address %s\n", fmtaddr(nip, 0)); // else a map to an ip pool index. @@ -1064,22 +1092,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++; } @@ -1087,20 +1121,20 @@ 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); } // // 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; @@ -1144,7 +1178,6 @@ int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc) 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 @@ -1413,9 +1446,10 @@ static void update_session_out_stat(sessionidt s, sessiont *sp, int len) void processipout(uint8_t *buf, int len) { sessionidt s; + 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; @@ -1448,8 +1482,33 @@ void processipout(uint8_t *buf, int len) return; } + ip_src = *(uint32_t *)(buf + 12); ip = *(uint32_t *)(buf + 16); - if (!(s = sessionbyip(ip))) + if ((g = grp_groupbyip(ip))) + { + s = grp_getnextsession(g, &ip, &ip_src, 0); + if (!s) + { + // Is this a packet for a session that doesn't exist? + static int rate = 0; // Number of ICMP packets we've sent this second. + static int last = 0; // Last time we reset the ICMP packet counter 'rate'. + + if (last != time_now) + { + last = time_now; + rate = 0; + } + + if (rate++ < config->icmp_rate) // Only send a max of icmp_rate per second. + { + LOG(4, 0, 0, "IP: Sending ICMP host unreachable to %s\n", fmtaddr(*(in_addr_t *)(buf + 12), 0)); + host_unreachable(*(in_addr_t *)(buf + 12), *(uint16_t *)(buf + 4), + config->bind_address ? config->bind_address : my_address, buf, len); + } + return; + } + } + else if (!(s = sessionbyip(ip))) { // Is this a packet for a session that doesn't exist? static int rate = 0; // Number of ICMP packets we've sent this second. @@ -1532,12 +1591,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) @@ -1675,10 +1737,11 @@ void processipout(uint8_t *buf, int len) static void processipv6out(uint8_t * buf, int len) { sessionidt s; + groupidt g; sessiont *sp; tunnelidt t; - in_addr_t ip; - struct in6_addr ip6; + struct in6_addr *p_ip6; + struct in6_addr *p_ip6_src; uint8_t *data = buf; // Keep a copy of the originals. int size = len; @@ -1711,15 +1774,18 @@ static void processipv6out(uint8_t * buf, int len) return; } - ip6 = *(struct in6_addr *)(buf+24); - s = sessionbyipv6(ip6); + p_ip6_src = (struct in6_addr *)(buf+8); + p_ip6 = (struct in6_addr *)(buf+24); - if (s == 0) + if ((g = grp_groupbyipv6(*p_ip6))) { - ip = *(uint32_t *)(buf + 32); - s = sessionbyip(ip); + s = grp_getnextsession(g, p_ip6, p_ip6_src, 1); } - + else if (!(s = sessionbyipv6(*p_ip6))) + { + s = sessionbyipv6new(*p_ip6); + } + if (s == 0) { // Is this a packet for a session that doesn't exist? @@ -1799,6 +1865,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]; @@ -1821,11 +1889,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) @@ -1844,10 +1915,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; } @@ -1855,10 +1927,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; } @@ -1866,9 +1940,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); } @@ -1877,9 +1952,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; } @@ -1924,10 +2000,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) @@ -2080,7 +2157,7 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e session[s].die = TIME + 150; // Clean up in 15 seconds if (session[s].ip) - { // IP allocated, clear and unroute + { // IP allocated, clear and unroute int r; int routed = 0; for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++) @@ -2102,9 +2179,17 @@ 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) - 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) + { + route6set(s, session[s].ipv6address, 128, 0); + } + if (b) { // This session was part of a bundle @@ -2158,8 +2243,15 @@ 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]) + { + cache_ipv6map(session[new_s].ipv6address, 128, new_s); + } } } } @@ -2280,6 +2372,8 @@ static void sessionclear(sessionidt s) // kill a session now void sessionkill(sessionidt s, char *reason) { + groupidt g; + CSTAT(sessionkill); if (!session[s].opened) // not alive @@ -2308,6 +2402,12 @@ void sessionkill(sessionidt s, char *reason) } LOG(2, s, session[s].tunnel, "Kill session %d (%s): %s\n", s, session[s].user, reason); + + if ((g = grp_groupbysession(s))) + { + grp_removesession(g, s); + } + sessionclear(s); cluster_send_session(s); } @@ -3218,7 +3318,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu // Set multilink options before sending initial LCP packet sess_local[s].mp_mrru = 1614; - sess_local[s].mp_epdis = ntohl(config->iftun_n_address[tunnel[t].indexudp] ? config->iftun_n_address[tunnel[t].indexudp] : my_address); + sess_local[s].mp_epdis = ntohl(config->iftun_address ? config->iftun_address : my_address); sendlcp(s, t); change_state(s, lcp, RequestSent); @@ -3397,6 +3497,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) @@ -3705,7 +3819,7 @@ 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)) + (time_now - sess_local[s].last_echo >= config->echo_timeout)) { uint8_t b[MAXETHER]; @@ -4642,6 +4756,8 @@ static void initdata(int optdebug, char *optconfig) #endif /* BGP */ lac_initremotelnsdata(); + + grp_initdata(); } static int assign_ip_address(sessionidt s) @@ -5042,9 +5158,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++; @@ -5084,6 +5200,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"); { @@ -5095,7 +5212,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) @@ -5159,6 +5276,7 @@ int main(int argc, char *argv[]) initrad(); initippool(); + dhcpv6_init(); // seed prng { @@ -5182,6 +5300,9 @@ int main(int argc, char *argv[]) LOG(0, 0, 0, "Can't lock pages: %s\n", strerror(errno)); } + //LOG(3, 0, 0, "Debug sizeof struct: sessiont %lu, tunnelt %lu, bundlet %lu, groupsesst %lu\n", + // sizeof(sessiont), sizeof(tunnelt), sizeof(bundlet), sizeof(groupsesst)); + mainloop(); /* remove plugins (so cleanup code gets run) */ @@ -5693,6 +5814,7 @@ int sessionsetup(sessionidt s, tunnelidt t) if (!session[s].bundle || (bundle[session[s].bundle].num_of_links == 1)) { int routed = 0; + groupidt g; // Add the route for this session. for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++) @@ -5715,6 +5837,12 @@ int sessionsetup(sessionidt s, tunnelidt t) } else cache_ipmap(session[s].ip, s); + + if ((g = grp_groupbysession(s))) + { + grp_setgrouproute(g, 1); + cluster_send_groupe(g); + } } sess_local[s].lcp_authtype = 0; // RADIUS authentication complete @@ -5778,7 +5906,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++) @@ -5801,6 +5929,17 @@ int load_session(sessionidt s, sessiont *new) uncache_ipmap(session[s].ip); } + // remove old IPV6 routes... + 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]) + { + route6set(s, session[s].ipv6address, 128, 0); + } + routed = 0; // add new routes... @@ -5827,8 +5966,20 @@ 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) + { + // 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])) @@ -6275,7 +6426,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; @@ -6313,7 +6464,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;