X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/9e78f1af54f2c8b7abfbe6ffe2dfbd26e98672c2..ba1c3362c6dc0d65eb3d06368c47b75aa135456b:/l2tpns.c?ds=sidebyside diff --git a/l2tpns.c b/l2tpns.c index 8fca167..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" @@ -53,24 +54,19 @@ #include "bgp.h" #endif -#ifdef LAC #include "l2tplac.h" -#endif #include "pppoe.h" +#include "dhcp6.h" -#ifdef LAC char * Vendor_name = "Linux L2TPNS"; uint32_t call_serial_number = 0; -#endif // Globals configt *config = NULL; // all configuration int nlfd = -1; // netlink socket int tunfd = -1; // tun interface file handle. (network device) -int udpfd = -1; // UDP file handle -#ifdef LAC +int udpfd[MAX_UDPFD + 1] = INIT_TABUDPFD; // array UDP file handle + 1 for lac udp int udplacfd = -1; // UDP LAC file handle -#endif int controlfd = -1; // Control signal handle int clifd = -1; // Socket listening for CLI connections. int daefd = -1; // Socket listening for DAE connections. @@ -81,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 @@ -98,10 +94,7 @@ 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 { - sessionidt sess; - union iphash *idx; -} ip_hash[256]; // Mapping from IP address to session structures. +union iphash ip_hash[256]; // Mapping from IP address to session structures. struct ipv6radix { sessionidt sess; @@ -158,6 +151,7 @@ config_descriptt config_values[] = { CONFIG("throttle_speed", rl_rate, UNSIGNED_LONG), CONFIG("throttle_buckets", num_tbfs, INT), CONFIG("accounting_dir", accounting_dir, STRING), + CONFIG("account_all_origin", account_all_origin, BOOL), CONFIG("dump_speed", dump_speed, BOOL), CONFIG("multi_read_count", multi_read_count, INT), CONFIG("scheduler_fifo", scheduler_fifo, BOOL), @@ -181,17 +175,26 @@ config_descriptt config_values[] = { CONFIG("idle_echo_timeout", idle_echo_timeout, INT), CONFIG("iftun_address", iftun_address, IPv4), CONFIG("tundevicename", tundevicename, STRING), -#ifdef LAC CONFIG("disable_lac_func", disable_lac_func, BOOL), CONFIG("auth_tunnel_change_addr_src", auth_tunnel_change_addr_src, BOOL), CONFIG("bind_address_remotelns", bind_address_remotelns, IPv4), CONFIG("bind_portremotelns", bind_portremotelns, SHORT), -#endif CONFIG("pppoe_if_to_bind", pppoe_if_to_bind, STRING), CONFIG("pppoe_service_name", pppoe_service_name, STRING), CONFIG("pppoe_ac_name", pppoe_ac_name, STRING), 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 } }; @@ -220,6 +223,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. @@ -230,9 +234,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); @@ -261,8 +262,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 @@ -621,7 +623,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; @@ -657,7 +659,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; @@ -700,7 +702,7 @@ static void inittun(void) } if (*config->tundevicename) - strncpy(ifr.ifr_name, config->tundevicename, IFNAMSIZ); + strncpy(ifr.ifr_name, config->tundevicename, IFNAMSIZ); if (ioctl(tunfd, TUNSETIFF, (void *) &ifr) < 0) { @@ -762,14 +764,30 @@ static void inittun(void) req.ifmsg.ifaddr.ifa_scope = RT_SCOPE_UNIVERSE; req.ifmsg.ifaddr.ifa_index = tunidx; - if (config->iftun_address) - ip = config->iftun_address; + if (config->nbmultiaddress > 1) + { + int i; + for (i = 0; i < config->nbmultiaddress ; i++) + { + ip = config->iftun_n_address[i]; + netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); + if (netlink_send(&req.nh) < 0) + goto senderror; + } + } else - ip = 0x01010101; // 1.1.1.1 - netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); + { + if (config->iftun_address) + ip = config->iftun_address; + else + ip = 0x01010101; // 1.1.1.1 + netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); + + if (netlink_send(&req.nh) < 0) + goto senderror; + } + - if (netlink_send(&req.nh) < 0) - goto senderror; // Only setup IPv6 on the tun device if we have a configured prefix if (config->ipv6_prefix.s6_addr[0]) { @@ -839,28 +857,35 @@ senderror: exit(1); } -// set up UDP ports -static void initudp(void) +// set up LAC UDP ports +static void initlacudp(void) { int on = 1; struct sockaddr_in addr; - // Tunnel + // Tunnel to Remote LNS memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_port = htons(L2TPPORT); - addr.sin_addr.s_addr = config->bind_address; - udpfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - setsockopt(udpfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + addr.sin_port = htons(config->bind_portremotelns); + addr.sin_addr.s_addr = config->bind_address_remotelns; + udplacfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + setsockopt(udplacfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); { - int flags = fcntl(udpfd, F_GETFL, 0); - fcntl(udpfd, F_SETFL, flags | O_NONBLOCK); + int flags = fcntl(udplacfd, F_GETFL, 0); + fcntl(udplacfd, F_SETFL, flags | O_NONBLOCK); } - if (bind(udpfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) + if (bind(udplacfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - LOG(0, 0, 0, "Error in UDP bind: %s\n", strerror(errno)); + LOG(0, 0, 0, "Error in UDP REMOTE LNS bind: %s\n", strerror(errno)); exit(1); } +} + +// set up control ports +static void initcontrol(void) +{ + int on = 1; + struct sockaddr_in addr; // Control memset(&addr, 0, sizeof(addr)); @@ -874,6 +899,13 @@ static void initudp(void) LOG(0, 0, 0, "Error in control bind: %s\n", strerror(errno)); exit(1); } +} + +// set up Dynamic Authorization Extensions to RADIUS port +static void initdae(void) +{ + int on = 1; + struct sockaddr_in addr; // Dynamic Authorization Extensions to RADIUS memset(&addr, 0, sizeof(addr)); @@ -887,28 +919,30 @@ static void initudp(void) LOG(0, 0, 0, "Error in DAE bind: %s\n", strerror(errno)); exit(1); } +} -#ifdef LAC - // Tunnel to Remote LNS +// set up UDP ports +static void initudp(int * pudpfd, in_addr_t ip_bind) +{ + int on = 1; + struct sockaddr_in addr; + + // Tunnel memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_port = htons(config->bind_portremotelns); - addr.sin_addr.s_addr = config->bind_address_remotelns; - udplacfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - setsockopt(udplacfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + addr.sin_port = htons(L2TPPORT); + addr.sin_addr.s_addr = ip_bind; + (*pudpfd) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + setsockopt((*pudpfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); { - int flags = fcntl(udplacfd, F_GETFL, 0); - fcntl(udplacfd, F_SETFL, flags | O_NONBLOCK); + int flags = fcntl((*pudpfd), F_GETFL, 0); + fcntl((*pudpfd), F_SETFL, flags | O_NONBLOCK); } - if (bind(udplacfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) + if (bind((*pudpfd), (struct sockaddr *) &addr, sizeof(addr)) < 0) { - LOG(0, 0, 0, "Error in UDP REMOTE LNS bind: %s\n", strerror(errno)); + LOG(0, 0, 0, "Error in UDP bind: %s\n", strerror(errno)); exit(1); } -#endif - - // Intercept - snoopfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); } // @@ -985,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); } @@ -1003,7 +1039,7 @@ sessionidt sessionbyipv6(struct in6_addr ip) // // (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; @@ -1072,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; @@ -1233,14 +1269,11 @@ void tunnelsend(uint8_t * buf, uint16_t l, tunnelidt t) LOG(3, 0, t, "Control message resend try %d\n", tunnel[t].try); } } -#ifdef LAC - if (sendto((tunnel[t].isremotelns?udplacfd:udpfd), buf, l, 0, (void *) &addr, sizeof(addr)) < 0) -#else - if (sendto(udpfd, buf, l, 0, (void *) &addr, sizeof(addr)) < 0) -#endif + + if (sendto(udpfd[tunnel[t].indexudp], buf, l, 0, (void *) &addr, sizeof(addr)) < 0) { LOG(0, ntohs((*(uint16_t *) (buf + 6))), t, "Error sending data out tunnel: %s (udpfd=%d, buf=%p, len=%d, dest=%s)\n", - strerror(errno), udpfd, buf, l, inet_ntoa(addr.sin_addr)); + strerror(errno), udpfd[tunnel[t].indexudp], buf, l, inet_ntoa(addr.sin_addr)); STAT(tunnel_tx_errors); return; } @@ -1388,9 +1421,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; @@ -1423,8 +1457,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); + 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. @@ -1507,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) @@ -1774,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]; @@ -1796,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) @@ -1819,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; } @@ -1830,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; } @@ -1841,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); } @@ -1852,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; } @@ -1872,7 +1944,8 @@ static controlt *controlnew(uint16_t mtype) } assert(c); c->next = 0; - *(uint16_t *) (c->buf + 0) = htons(0xC802); // flags/ver + c->buf[0] = 0xC8; // flags + c->buf[1] = 0x02; // ver c->length = 12; control16(c, 0, mtype, 1); return c; @@ -1882,26 +1955,27 @@ static controlt *controlnew(uint16_t mtype) // (ZLB send). static void controlnull(tunnelidt t) { - uint8_t buf[12]; + uint16_t buf[6]; if (tunnel[t].controlc) // Messages queued; They will carry the ack. return; - *(uint16_t *) (buf + 0) = htons(0xC802); // flags/ver - *(uint16_t *) (buf + 2) = htons(12); // length - *(uint16_t *) (buf + 4) = htons(tunnel[t].far); // tunnel - *(uint16_t *) (buf + 6) = htons(0); // session - *(uint16_t *) (buf + 8) = htons(tunnel[t].ns); // sequence - *(uint16_t *) (buf + 10) = htons(tunnel[t].nr); // sequence - tunnelsend(buf, 12, t); + buf[0] = htons(0xC802); // flags/ver + buf[1] = htons(12); // length + buf[2] = htons(tunnel[t].far); // tunnel + buf[3] = htons(0); // session + buf[4] = htons(tunnel[t].ns); // sequence + buf[5] = htons(tunnel[t].nr); // sequence + tunnelsend((uint8_t *)buf, 12, 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) @@ -2054,7 +2128,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++) @@ -2076,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 @@ -2134,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); + } } } } @@ -2152,14 +2236,15 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e pppoe_shutdown_session(s); } else - { // Send CDN + { + // Send CDN controlt *c = controlnew(14); // sending CDN if (cdn_error) { - uint8_t buf[4]; - *(uint16_t *) buf = htons(cdn_result); - *(uint16_t *) (buf+2) = htons(cdn_error); - controlb(c, 1, buf, 4, 1); + uint16_t buf[2]; + buf[0] = htons(cdn_result); + buf[1] = htons(cdn_error); + controlb(c, 1, (uint8_t *)buf, 4, 1); } else control16(c, 1, cdn_result, 1); @@ -2206,7 +2291,7 @@ void sendipcp(sessionidt s, tunnelidt t) q[4] = 3; // ip address option q[5] = 6; // option length *(in_addr_t *) (q + 6) = config->peer_address ? config->peer_address : - config->iftun_address ? config->iftun_address : + config->iftun_n_address[tunnel[t].indexudp] ? config->iftun_n_address[tunnel[t].indexudp] : my_address; // send my IP tunnelsend(buf, 10 + (q - buf), t); // send it @@ -2253,6 +2338,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 @@ -2270,7 +2357,6 @@ void sessionkill(sessionidt s, char *reason) if (sess_local[s].radius) radiusclear(sess_local[s].radius, s); // cant send clean accounting data, session is killed -#ifdef LAC if (session[s].forwardtosession) { sessionidt sess = session[s].forwardtosession; @@ -2280,9 +2366,14 @@ void sessionkill(sessionidt s, char *reason) sessionshutdown(sess, reason, CDN_ADMIN_DISC, TERM_ADMIN_RESET); } } -#endif 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); } @@ -2361,21 +2452,21 @@ static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, cha controlt *c = controlnew(4); // sending StopCCN if (error) { - uint8_t buf[64]; + uint16_t buf[32]; int l = 4; - *(uint16_t *) buf = htons(result); - *(uint16_t *) (buf+2) = htons(error); + buf[0] = htons(result); + buf[1] = htons(error); if (msg) { int m = strlen(msg); if (m + 4 > sizeof(buf)) m = sizeof(buf) - 4; - memcpy(buf+4, msg, m); + memcpy(buf+2, msg, m); l += m; } - controlb(c, 1, buf, l, 1); + controlb(c, 1, (uint8_t *)buf, l, 1); } else control16(c, 1, result, 1); @@ -2386,9 +2477,10 @@ static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, cha } // read and process packet on tunnel (UDP) -void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) +void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexudpfd) { - uint8_t *chapresponse = NULL; + uint8_t *sendchalresponse = NULL; + uint8_t *recvchalresponse = NULL; uint16_t l = len, t = 0, s = 0, ns = 0, nr = 0; uint8_t *p = buf + 2; @@ -2477,7 +2569,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) if (!config->cluster_iam_master) { - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } @@ -2527,6 +2619,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) tunnel[t].ip = ntohl(*(in_addr_t *) & addr->sin_addr); tunnel[t].port = ntohs(addr->sin_port); tunnel[t].window = 4; // default window + tunnel[t].indexudp = indexudpfd; STAT(tunnel_created); LOG(1, 0, t, " New tunnel from %s:%u ID %u\n", fmtaddr(htonl(tunnel[t].ip), 0), tunnel[t].port, t); @@ -2791,22 +2884,23 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) tunnel[t].window = 1; // window of 0 is silly LOG(4, s, t, " rx window = %u\n", tunnel[t].window); break; - case 11: // Challenge + case 11: // Request Challenge { LOG(4, s, t, " LAC requested CHAP authentication for tunnel\n"); - build_chap_response(b, 2, n, &chapresponse); + if (message == 1) + build_chap_response(b, 2, n, &sendchalresponse); + else if (message == 2) + build_chap_response(b, 3, n, &sendchalresponse); } break; - case 13: // Response -#ifdef LAC + case 13: // receive challenge Response if (tunnel[t].isremotelns) { - chapresponse = calloc(17, 1); - memcpy(chapresponse, b, (n < 17) ? n : 16); + recvchalresponse = calloc(17, 1); + memcpy(recvchalresponse, b, (n < 17) ? n : 16); LOG(3, s, t, "received challenge response from REMOTE LNS\n"); } else -#endif /* LAC */ // Why did they send a response? We never challenge. LOG(2, s, t, " received unexpected challenge response\n"); break; @@ -3039,8 +3133,8 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) controlt *c = controlnew(2); // sending SCCRP control16(c, 2, version, 1); // protocol version control32(c, 3, 3, 1); // framing - controls(c, 7, hostname, 1); // host name - if (chapresponse) controlb(c, 13, chapresponse, 16, 1); // Challenge response + controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name + if (sendchalresponse) controlb(c, 13, sendchalresponse, 16, 1); // Send Challenge response control16(c, 9, t, 1); // assigned tunnel controladd(c, 0, t); // send the resply } @@ -3052,24 +3146,24 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) case 2: // SCCRP tunnel[t].state = TUNNELOPEN; tunnel[t].lastrec = time_now; -#ifdef LAC LOG(3, s, t, "Received SCCRP\n"); if (main_quit != QUIT_SHUTDOWN) { - if (tunnel[t].isremotelns && chapresponse) + if (tunnel[t].isremotelns && recvchalresponse) { hasht hash; lac_calc_rlns_auth(t, 2, hash); // id = 2 (SCCRP) // check authenticator - if (memcmp(hash, chapresponse, 16) == 0) + if (memcmp(hash, recvchalresponse, 16) == 0) { LOG(3, s, t, "sending SCCCN to REMOTE LNS\n"); controlt *c = controlnew(3); // sending SCCCN - controls(c, 7, hostname, 1); // host name + controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name controls(c, 8, Vendor_name, 1); // Vendor name control16(c, 2, version, 1); // protocol version control32(c, 3, 3, 1); // framing Capabilities + if (sendchalresponse) controlb(c, 13, sendchalresponse, 16, 1); // Challenge response control16(c, 9, t, 1); // assigned tunnel controladd(c, 0, t); // send } @@ -3083,7 +3177,6 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) { tunnelshutdown(t, "Shutting down", 6, 0, 0); } -#endif /* LAC */ break; case 3: // SCCN LOG(3, s, t, "Received SCCN\n"); @@ -3161,7 +3254,6 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) } return; case 11: // ICRP -#ifdef LAC LOG(3, s, t, "Received ICRP\n"); if (session[s].forwardtosession) { @@ -3177,7 +3269,6 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) controladd(c, asession, t); // send the message LOG(3, s, t, "Sending ICCN\n"); } -#endif /* LAC */ break; case 12: // ICCN LOG(3, s, t, "Received ICCN\n"); @@ -3215,7 +3306,8 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) LOG(1, s, t, "Unknown message type %u\n", message); break; } - if (chapresponse) free(chapresponse); + if (sendchalresponse) free(sendchalresponse); + if (recvchalresponse) free(recvchalresponse); cluster_send_tunnel(t); } else @@ -3251,12 +3343,11 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) l -= 2; } -#ifdef LAC if (session[s].forwardtosession) { LOG(5, s, t, "Forwarding data session to session %u\n", session[s].forwardtosession); // Forward to LAC/BAS or Remote LNS session - lac_session_forward(buf, len, s, proto, addr->sin_addr.s_addr, addr->sin_port); + lac_session_forward(buf, len, s, proto, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } else if (config->auth_tunnel_change_addr_src) @@ -3271,14 +3362,13 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) tunnel[t].ip = ntohl(addr->sin_addr.s_addr); } } -#endif /* LAC */ if (s && !session[s].opened) // Is something wrong?? { if (!config->cluster_iam_master) { // Pass it off to the master to deal with.. - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } @@ -3290,37 +3380,37 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) if (proto == PPPPAP) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processpap(s, t, p, l); } else if (proto == PPPCHAP) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processchap(s, t, p, l); } else if (proto == PPPLCP) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processlcp(s, t, p, l); } else if (proto == PPPIPCP) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processipcp(s, t, p, l); } else if (proto == PPPIPV6CP && config->ipv6_prefix.s6_addr[0]) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processipv6cp(s, t, p, l); } else if (proto == PPPCCP) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processccp(s, t, p, l); } else if (proto == PPPIP) @@ -3334,7 +3424,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) session[s].last_packet = session[s].last_data = time_now; if (session[s].walled_garden && !config->cluster_iam_master) { - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } @@ -3352,7 +3442,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) if (!config->cluster_iam_master) { // The fragments reconstruction is managed by the Master. - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } @@ -3369,16 +3459,30 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) session[s].last_packet = session[s].last_data = time_now; if (session[s].walled_garden && !config->cluster_iam_master) { - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); 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) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } protoreject(s, t, p, l, proto); } else @@ -3681,7 +3785,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]; @@ -3947,13 +4051,8 @@ static int still_busy(void) # include "fake_epoll.h" #endif -#ifdef LAC -// the base set of fds polled: cli, cluster, tun, udp, control, dae, netlink, udplac, pppoedisc, pppoesess -#define BASE_FDS 10 -#else -// the base set of fds polled: cli, cluster, tun, udp, control, dae, netlink, pppoedisc, pppoesess -#define BASE_FDS 9 -#endif +// the base set of fds polled: cli, cluster, tun, udp (MAX_UDPFD), control, dae, netlink, udplac, pppoedisc, pppoesess +#define BASE_FDS (9 + MAX_UDPFD) // additional polled fds #ifdef BGP @@ -3965,7 +4064,7 @@ static int still_busy(void) // main loop - gets packets on tun or udp and processes them static void mainloop(void) { - int i; + int i, j; uint8_t buf[65536]; uint8_t *p = buf + 32; // for the hearder of the forwarded MPPP packet (see C_MPPP_FORWARD) // and the forwarded pppoe session @@ -3980,13 +4079,8 @@ static void mainloop(void) exit(1); } -#ifdef LAC LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d, nlfd=%d , udplacfd=%d, pppoefd=%d, pppoesessfd=%d\n", - clifd, cluster_sockfd, tunfd, udpfd, controlfd, daefd, nlfd, udplacfd, pppoediscfd, pppoesessfd); -#else - LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d, nlfd=%d, pppoefd=%d, pppoesessfd=%d\n", - clifd, cluster_sockfd, tunfd, udpfd, controlfd, daefd, nlfd, pppoediscfd, pppoesessfd); -#endif + clifd, cluster_sockfd, tunfd, udpfd[0], controlfd, daefd, nlfd, udplacfd, pppoediscfd, pppoesessfd); /* setup our fds to poll for input */ { @@ -4011,10 +4105,6 @@ static void mainloop(void) e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, tunfd, &e); - d[i].type = FD_TYPE_UDP; - e.data.ptr = &d[i++]; - epoll_ctl(epollfd, EPOLL_CTL_ADD, udpfd, &e); - d[i].type = FD_TYPE_CONTROL; e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, controlfd, &e); @@ -4027,12 +4117,6 @@ static void mainloop(void) e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, nlfd, &e); -#ifdef LAC - d[i].type = FD_TYPE_UDPLAC; - e.data.ptr = &d[i++]; - epoll_ctl(epollfd, EPOLL_CTL_ADD, udplacfd, &e); -#endif - d[i].type = FD_TYPE_PPPOEDISC; e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, pppoediscfd, &e); @@ -4040,6 +4124,14 @@ static void mainloop(void) d[i].type = FD_TYPE_PPPOESESS; e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, pppoesessfd, &e); + + for (j = 0; j < config->nbudpfd; j++) + { + d[i].type = FD_TYPE_UDP; + d[i].index = j; + e.data.ptr = &d[i++]; + epoll_ctl(epollfd, EPOLL_CTL_ADD, udpfd[j], &e); + } } #ifdef BGP @@ -4101,16 +4193,12 @@ static void mainloop(void) struct in_addr local; socklen_t alen; int c, s; - int udp_ready = 0; -#ifdef LAC - int udplac_ready = 0; - int udplac_pkts = 0; -#endif + int udp_ready[MAX_UDPFD + 1] = INIT_TABUDPVAR; int pppoesess_ready = 0; int pppoesess_pkts = 0; int tun_ready = 0; int cluster_ready = 0; - int udp_pkts = 0; + int udp_pkts[MAX_UDPFD + 1] = INIT_TABUDPVAR; int tun_pkts = 0; int cluster_pkts = 0; #ifdef BGP @@ -4144,10 +4232,7 @@ static void mainloop(void) // these are handled below, with multiple interleaved reads case FD_TYPE_CLUSTER: cluster_ready++; break; case FD_TYPE_TUN: tun_ready++; break; - case FD_TYPE_UDP: udp_ready++; break; -#ifdef LAC - case FD_TYPE_UDPLAC: udplac_ready++; break; -#endif + case FD_TYPE_UDP: udp_ready[d->index]++; break; case FD_TYPE_PPPOESESS: pppoesess_ready++; break; case FD_TYPE_PPPOEDISC: // pppoe discovery @@ -4188,8 +4273,8 @@ static void mainloop(void) #ifdef BGP case FD_TYPE_BGP: - bgp_events[d->index] = events[i].events; - n--; + bgp_events[d->index] = events[i].events; + n--; break; #endif /* BGP */ @@ -4208,7 +4293,6 @@ static void mainloop(void) exit(1); } else - LOG(0, 0, 0, "Got a netlink error: %s\n", strerror(-errmsg->error)); } // else it's a ack @@ -4220,7 +4304,7 @@ static void mainloop(void) } default: - LOG(0, 0, 0, "Unexpected fd type returned from epoll_wait: %d\n", d->type); + LOG(0, 0, 0, "Unexpected fd type returned from epoll_wait: %d\n", d->type); } } @@ -4230,40 +4314,25 @@ static void mainloop(void) for (c = 0; n && c < config->multi_read_count; c++) { - // L2TP - if (udp_ready) + for (j = 0; j < config->nbudpfd; j++) { - alen = sizeof(addr); - if ((s = recvfrom(udpfd, p, size_bufp, 0, (void *) &addr, &alen)) > 0) - { - processudp(p, s, &addr); - udp_pkts++; - } - else + // L2TP and L2TP REMOTE LNS + if (udp_ready[j]) { - udp_ready = 0; - n--; + alen = sizeof(addr); + if ((s = recvfrom(udpfd[j], p, size_bufp, 0, (void *) &addr, &alen)) > 0) + { + processudp(p, s, &addr, j); + udp_pkts[j]++; + } + else + { + udp_ready[j] = 0; + n--; + } } } -#ifdef LAC - // L2TP REMOTE LNS - if (udplac_ready) - { - alen = sizeof(addr); - if ((s = recvfrom(udplacfd, p, size_bufp, 0, (void *) &addr, &alen)) > 0) - { - if (!config->disable_lac_func) - processudp(p, s, &addr); - udplac_pkts++; - } - else - { - udplac_ready = 0; - n--; - } - } -#endif // incoming IP if (tun_ready) { @@ -4311,18 +4380,13 @@ static void mainloop(void) } } - if (udp_pkts > 1 || tun_pkts > 1 || cluster_pkts > 1) + if (udp_pkts[0] > 1 || tun_pkts > 1 || cluster_pkts > 1) STAT(multi_read_used); if (c >= config->multi_read_count) { -#ifdef LAC - LOG(3, 0, 0, "Reached multi_read_count (%d); processed %d udp, %d tun %d cluster %d rmlns and %d pppoe packets\n", - config->multi_read_count, udp_pkts, tun_pkts, cluster_pkts, udplac_pkts, pppoesess_pkts); -#else LOG(3, 0, 0, "Reached multi_read_count (%d); processed %d udp, %d tun %d cluster and %d pppoe packets\n", - config->multi_read_count, udp_pkts, tun_pkts, cluster_pkts, pppoesess_pkts); -#endif + config->multi_read_count, udp_pkts[0], tun_pkts, cluster_pkts, pppoesess_pkts); STAT(multi_read_exceeded); more++; } @@ -4657,9 +4721,9 @@ static void initdata(int optdebug, char *optconfig) } #endif /* BGP */ -#ifdef LAC lac_initremotelnsdata(); -#endif + + grp_initdata(); } static int assign_ip_address(sessionidt s) @@ -4946,11 +5010,7 @@ void snoop_send_packet(uint8_t *packet, uint16_t size, in_addr_t destination, ui static int dump_session(FILE **f, sessiont *s) { -#ifdef LAC if (!s->opened || (!s->ip && !s->forwardtosession) || !(s->cin_delta || s->cout_delta) || !*s->user || s->walled_garden) -#else - if (!s->opened || !s->ip || !(s->cin_delta || s->cout_delta) || !*s->user || s->walled_garden) -#endif return 1; if (!*f) @@ -4969,6 +5029,21 @@ static int dump_session(FILE **f, sessiont *s) } LOG(3, 0, 0, "Dumping accounting information to %s\n", filename); + if(config->account_all_origin) + { + fprintf(*f, "# dslwatch.pl dump file V1.01\n" + "# host: %s\n" + "# endpoint: %s\n" + "# time: %ld\n" + "# uptime: %ld\n" + "# format: username ip qos uptxoctets downrxoctets origin(L=LAC, R=Remote LNS, P=PPPOE)\n", + hostname, + fmtaddr(config->iftun_n_address[tunnel[s->tunnel].indexudp] ? config->iftun_n_address[tunnel[s->tunnel].indexudp] : my_address, 0), + now, + now - basetime); + } + else + { fprintf(*f, "# dslwatch.pl dump file V1.01\n" "# host: %s\n" "# endpoint: %s\n" @@ -4976,18 +5051,32 @@ static int dump_session(FILE **f, sessiont *s) "# uptime: %ld\n" "# format: username ip qos uptxoctets downrxoctets\n", hostname, - fmtaddr(config->iftun_address ? config->iftun_address : my_address, 0), + fmtaddr(config->iftun_n_address[tunnel[s->tunnel].indexudp] ? config->iftun_n_address[tunnel[s->tunnel].indexudp] : my_address, 0), now, now - basetime); + } } LOG(4, 0, 0, "Dumping accounting information for %s\n", s->user); + if(config->account_all_origin) + { + fprintf(*f, "%s %s %d %u %u %s\n", + s->user, // username + fmtaddr(htonl(s->ip), 0), // ip + (s->throttle_in || s->throttle_out) ? 2 : 1, // qos + (uint32_t) s->cin_delta, // uptxoctets + (uint32_t) s->cout_delta, // downrxoctets + (s->tunnel == TUNNEL_ID_PPPOE)?"P":(tunnel[s->tunnel].isremotelns?"R":"L")); // Origin + } + else if (!tunnel[s->tunnel].isremotelns && (s->tunnel != TUNNEL_ID_PPPOE)) + { fprintf(*f, "%s %s %d %u %u\n", s->user, // username fmtaddr(htonl(s->ip), 0), // ip (s->throttle_in || s->throttle_out) ? 2 : 1, // qos (uint32_t) s->cin_delta, // uptxoctets (uint32_t) s->cout_delta); // downrxoctets + } s->cin_delta = s->cout_delta = 0; @@ -5035,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++; @@ -5077,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"); { @@ -5088,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) @@ -5130,9 +5220,29 @@ int main(int argc, char *argv[]) init_pppoe(); LOG(1, 0, 0, "Set up on pppoe interface %s\n", config->pppoe_if_to_bind); } - initudp(); + + if (!config->nbmultiaddress) + { + config->bind_n_address[0] = config->bind_address; + config->nbmultiaddress++; + } + config->nbudpfd = config->nbmultiaddress; + for (i = 0; i < config->nbudpfd; i++) + initudp(&udpfd[i], config->bind_n_address[i]); + initlacudp(); + config->indexlacudpfd = config->nbudpfd; + udpfd[config->indexlacudpfd] = udplacfd; + config->nbudpfd++; + + initcontrol(); + initdae(); + + // Intercept + snoopfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + initrad(); initippool(); + dhcpv6_init(); // seed prng { @@ -5156,6 +5266,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) */ @@ -5362,14 +5475,100 @@ static void update_config() if (!config->radius_dae_port) config->radius_dae_port = DAEPORT; -#ifdef LAC if(!config->bind_portremotelns) config->bind_portremotelns = L2TPLACPORT; if(!config->bind_address_remotelns) config->bind_address_remotelns = INADDR_ANY; -#endif + + if (*config->bind_multi_address) + { + char *sip = config->bind_multi_address; + char *n = sip; + char *e = config->bind_multi_address + strlen(config->bind_multi_address); + config->nbmultiaddress = 0; + + while (*sip && (sip < e)) + { + in_addr_t ip = 0; + uint8_t u = 0; + + while (n < e && (*n == ',' || *n == ' ')) n++; + + while (n < e && (isdigit(*n) || *n == '.')) + { + if (*n == '.') + { + ip = (ip << 8) + u; + u = 0; + } + else + u = u * 10 + *n - '0'; + n++; + } + ip = (ip << 8) + u; + n++; + + if (ip) + { + config->bind_n_address[config->nbmultiaddress] = htonl(ip); + config->iftun_n_address[config->nbmultiaddress] = htonl(ip); + config->nbmultiaddress++; + LOG(1, 0, 0, "Bind address %s\n", fmtaddr(htonl(ip), 0)); + + if (config->nbmultiaddress >= MAX_BINDADDR) break; + } + + sip = n; + } + + if (config->nbmultiaddress >= 1) + { + config->bind_address = config->bind_n_address[0]; + config->iftun_address = config->bind_address; + } + } + if(!config->iftun_address) + { config->iftun_address = config->bind_address; + config->iftun_n_address[0] = config->iftun_address; + } + + if (*config->multi_hostname) + { + char *shost = config->multi_hostname; + char *n = shost; + char *e = config->multi_hostname + strlen(config->multi_hostname); + config->nbmultihostname = 0; + + while (*shost && (shost < e)) + { + while ((n < e) && (*n == ' ' || *n == ',' || *n == '\t')) n++; + + i = 0; + while (n < e && (*n != ',') && (*n != '\t')) + { + config->multi_n_hostname[config->nbmultihostname][i] = *n; + n++;i++; + } + + if (i > 0) + { + config->multi_n_hostname[config->nbmultihostname][i] = 0; + LOG(1, 0, 0, "Bind Hostname %s\n", config->multi_n_hostname[config->nbmultihostname]); + config->nbmultihostname++; + if (config->nbmultihostname >= MAX_NBHOSTNAME) break; + } + + shost = n; + } + + if (config->nbmultihostname >= 1) + { + strcpy(hostname, config->multi_n_hostname[0]); + strcpy(config->hostname, hostname); + } + } if (!*config->pppoe_ac_name) strncpy(config->pppoe_ac_name, DEFAULT_PPPOE_AC_NAME, sizeof(config->pppoe_ac_name) - 1); @@ -5581,6 +5780,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++) @@ -5603,6 +5803,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 @@ -5689,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... @@ -5716,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])) @@ -6163,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; @@ -6201,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; @@ -6427,8 +6649,6 @@ int ip_filter(uint8_t *buf, int len, uint8_t filter) return 0; } -#ifdef LAC - tunnelidt lac_new_tunnel() { return new_tunnel(); @@ -6447,7 +6667,7 @@ void lac_send_SCCRQ(tunnelidt t, uint8_t * auth, unsigned int auth_len) // Sent SCCRQ - Start Control Connection Request controlt *c = controlnew(1); // sending SCCRQ - controls(c, 7, hostname, 1); // host name + controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name controls(c, 8, Vendor_name, 1); // Vendor name control16(c, 2, version, 1); // protocol version control32(c, 3, 3, 1); // framing Capabilities @@ -6474,4 +6694,3 @@ void lac_tunnelshutdown(tunnelidt t, char *reason, int result, int error, char * tunnelshutdown(t, reason, result, error, msg); } -#endif