X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/5e65215ed4758c8fcd26ecaadc4b6121b93dab1c..91fc2ec13bb4bf58770085375a91a75f2413fa71:/l2tpns.c?ds=sidebyside diff --git a/l2tpns.c b/l2tpns.c index 694726d..c41b502 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -53,23 +53,18 @@ #include "bgp.h" #endif -#ifdef LAC #include "l2tplac.h" -#endif +#include "pppoe.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. @@ -157,6 +152,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), @@ -178,11 +174,21 @@ config_descriptt config_values[] = { #endif CONFIG("echo_timeout", echo_timeout, INT), CONFIG("idle_echo_timeout", idle_echo_timeout, INT), -#ifdef LAC + CONFIG("iftun_address", iftun_address, IPv4), + CONFIG("tundevicename", tundevicename, STRING), 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 - { NULL, 0, 0, 0 }, + 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("pppoe_only_equal_svc_name", pppoe_only_equal_svc_name, BOOL), + CONFIG("multi_hostname", multi_hostname, STRING), + { NULL, 0, 0, 0 } }; static char *plugin_functions[] = { @@ -256,7 +262,8 @@ static clockt now(double *f) } // Time in milliseconds - time_now_ms = (t.tv_sec * 1000) + (t.tv_usec/1000); + // TODO FOR MLPPP DEV + //time_now_ms = (t.tv_sec * 1000) + (t.tv_usec/1000); return (t.tv_sec - basetime) * 10 + t.tv_usec / 100000 + 1; } @@ -292,7 +299,7 @@ void _log(int level, sessionidt s, tunnelidt t, const char *format, ...) ringbuffer->buffer[ringbuffer->tail].session = s; ringbuffer->buffer[ringbuffer->tail].tunnel = t; va_start(ap, format); - vsnprintf(ringbuffer->buffer[ringbuffer->tail].message, 4095, format, ap); + vsnprintf(ringbuffer->buffer[ringbuffer->tail].message, MAX_LOG_LENGTH, format, ap); va_end(ap); } #endif @@ -687,15 +694,19 @@ static void inittun(void) int flags = fcntl(tunfd, F_GETFL, 0); fcntl(tunfd, F_SETFL, flags | O_NONBLOCK); } + + if (*config->tundevicename) + strncpy(ifr.ifr_name, config->tundevicename, IFNAMSIZ); + if (ioctl(tunfd, TUNSETIFF, (void *) &ifr) < 0) { LOG(0, 0, 0, "Can't set tun interface: %s\n", strerror(errno)); exit(1); } - assert(strlen(ifr.ifr_name) < sizeof(config->tundevice) - 1); - strncpy(config->tundevice, ifr.ifr_name, sizeof(config->tundevice)); + assert(strlen(ifr.ifr_name) < sizeof(config->tundevicename) - 1); + strncpy(config->tundevicename, ifr.ifr_name, sizeof(config->tundevicename)); - tunidx = if_nametoindex(config->tundevice); + tunidx = if_nametoindex(config->tundevicename); if (tunidx == 0) { LOG(0, 0, 0, "Can't get tun interface index\n"); @@ -747,14 +758,30 @@ static void inittun(void) req.ifmsg.ifaddr.ifa_scope = RT_SCOPE_UNIVERSE; req.ifmsg.ifaddr.ifa_index = tunidx; - if (config->bind_address) - ip = config->bind_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]) { @@ -824,28 +851,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)); @@ -859,6 +893,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)); @@ -872,27 +913,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); - 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); } // @@ -1185,6 +1229,12 @@ void tunnelsend(uint8_t * buf, uint16_t l, tunnelidt t) return; } + if (t == TUNNEL_ID_PPPOE) + { + pppoe_sess_send(buf, l, t); + return; + } + if (!tunnel[t].ip) { LOG(1, 0, t, "Error sending data out tunnel: no remote endpoint (tunnel not set up)\n"); @@ -1211,14 +1261,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; } @@ -1604,17 +1651,15 @@ void processipout(uint8_t *buf, int len) else { // Send it as one frame (NO MPPP Frame) - uint8_t *p = makeppp(fragbuf, sizeof(fragbuf), buf, len, s, t, PPPIP, 0, 0, 0); - if (!p) return; - tunnelsend(fragbuf, len + (p-fragbuf), t); // send it... + uint8_t *p = opt_makeppp(buf, len, s, t, PPPIP, 0, 0, 0); + tunnelsend(p, len + (buf-p), t); // send it... update_session_out_stat(s, sp, len); } } else { - uint8_t *p = makeppp(fragbuf, sizeof(fragbuf), buf, len, s, t, PPPIP, 0, 0, 0); - if (!p) return; - tunnelsend(fragbuf, len + (p-fragbuf), t); // send it... + uint8_t *p = opt_makeppp(buf, len, s, t, PPPIP, 0, 0, 0); + tunnelsend(p, len + (buf-p), t); // send it... update_session_out_stat(s, sp, len); } @@ -1799,10 +1844,10 @@ 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); - c->buf16[c->length/2 + 0] = htons(l); - c->buf16[c->length/2 + 1] = htons(0); - c->buf16[c->length/2 + 2] = htons(avp); - c->buf16[c->length/2 + 3] = htons(val); + *(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); c->length += 8; } @@ -1810,10 +1855,10 @@ 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); - c->buf16[c->length/2 + 0] = htons(l); - c->buf16[c->length/2 + 1] = htons(0); - c->buf16[c->length/2 + 2] = htons(avp); - *(uint32_t *) &c->buf[c->length + 6] = htonl(val); + *(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); c->length += 10; } @@ -1821,10 +1866,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); - c->buf16[c->length/2 + 0] = htons(l); - c->buf16[c->length/2 + 1] = htons(0); - c->buf16[c->length/2 + 2] = htons(avp); - memcpy(&c->buf[c->length + 6], val, strlen(val)); + *(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); + memcpy(c->buf + c->length + 6, val, strlen(val)); c->length += 6 + strlen(val); } @@ -1832,10 +1877,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); - c->buf16[c->length/2 + 0] = htons(l); - c->buf16[c->length/2 + 1] = htons(0); - c->buf16[c->length/2 + 2] = htons(avp); - memcpy(&c->buf[c->length + 6], val, len); + *(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); + memcpy(c->buf + c->length + 6, val, len); c->length += 6 + len; } @@ -1852,7 +1897,8 @@ static controlt *controlnew(uint16_t mtype) } assert(c); c->next = 0; - c->buf16[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; @@ -1878,10 +1924,10 @@ 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) { - c->buf16[1] = htons(c->length); // length - c->buf16[2] = htons(tunnel[t].far); // tunnel - c->buf16[3] = htons(far); // session - c->buf16[4] = htons(tunnel[t].ns); // sequence + *(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 tunnel[t].ns++; // advance sequence // link in message in to queue if (tunnel[t].controlc) @@ -2006,7 +2052,6 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e struct param_kill_session data = { &tunnel[session[s].tunnel], &session[s] }; LOG(2, s, session[s].tunnel, "Shutting down session %u: %s\n", s, reason); run_plugins(PLUGIN_KILL_SESSION, &data); - session[s].die = TIME + 150; // Clean up in 15 seconds } if (session[s].ip && !walled_garden && !session[s].die) @@ -2031,6 +2076,9 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e memcpy(&shut_acct[shut_acct_n++], &session[s], sizeof(session[s])); } + if (!session[s].die) + session[s].die = TIME + 150; // Clean up in 15 seconds + if (session[s].ip) { // IP allocated, clear and unroute int r; @@ -2124,20 +2172,28 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e throttle_session(s, 0, 0); if (cdn_result) - { // Send CDN - controlt *c = controlnew(14); // sending CDN - if (cdn_error) + { + if (session[s].tunnel == TUNNEL_ID_PPPOE) { - uint16_t buf[2]; - buf[0] = htons(cdn_result); - buf[1] = htons(cdn_error); - controlb(c, 1, (uint8_t *)buf, 4, 1); + pppoe_shutdown_session(s); } else - control16(c, 1, cdn_result, 1); + { + // Send CDN + controlt *c = controlnew(14); // sending CDN + if (cdn_error) + { + 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); - control16(c, 14, s, 1); // assigned session (our end) - controladd(c, session[s].far, session[s].tunnel); // send the message + control16(c, 14, s, 1); // assigned session (our end) + controladd(c, session[s].far, session[s].tunnel); // send the message + } } // update filter refcounts @@ -2177,7 +2233,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->bind_address ? config->bind_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 @@ -2241,7 +2297,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; @@ -2251,7 +2306,6 @@ 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); sessionclear(s); @@ -2357,9 +2411,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; @@ -2404,6 +2459,12 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) STAT(tunnel_rx_errors); return; } + if (t == TUNNEL_ID_PPPOE) + { + LOG(1, s, t, "Received UDP packet with tunnel ID reserved for pppoe\n"); + STAT(tunnel_rx_errors); + return; + } if (*buf & 0x08) { // ns/nr ns = ntohs(*(uint16_t *) p); @@ -2442,7 +2503,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; } @@ -2492,6 +2553,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); @@ -2756,22 +2818,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; @@ -3004,8 +3067,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 } @@ -3017,24 +3080,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 } @@ -3048,7 +3111,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"); @@ -3062,6 +3124,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) tunnelshutdown(t, "Stopped", 0, 0, 0); // Shut down cleanly break; case 6: // HELLO + LOG(3, s, t, "Received HELLO\n"); controlnull(t); // simply ACK break; case 7: // OCRQ @@ -3125,7 +3188,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) { @@ -3141,7 +3203,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"); @@ -3157,7 +3218,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) // Set multilink options before sending initial LCP packet sess_local[s].mp_mrru = 1614; - sess_local[s].mp_epdis = ntohl(config->bind_address ? config->bind_address : my_address); + sess_local[s].mp_epdis = ntohl(config->iftun_n_address[tunnel[t].indexudp] ? config->iftun_n_address[tunnel[t].indexudp] : my_address); sendlcp(s, t); change_state(s, lcp, RequestSent); @@ -3179,7 +3240,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 @@ -3215,22 +3277,32 @@ 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 or Remote LNS session - lac_session_forward(buf, len, s, proto); + // Forward to LAC/BAS or Remote LNS session + lac_session_forward(buf, len, s, proto, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } -#endif /* LAC */ + else if (config->auth_tunnel_change_addr_src) + { + if (tunnel[t].ip != ntohl(addr->sin_addr.s_addr) && + tunnel[t].port == ntohs(addr->sin_port)) + { + // The remotes BAS are a clustered l2tpns server and the source IP has changed + LOG(5, s, t, "The tunnel IP source (%s) has changed by new IP (%s)\n", + fmtaddr(htonl(tunnel[t].ip), 0), fmtaddr(addr->sin_addr.s_addr, 0)); + + tunnel[t].ip = ntohl(addr->sin_addr.s_addr); + } + } 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; } @@ -3242,37 +3314,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) @@ -3286,7 +3358,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; } @@ -3304,7 +3376,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; } @@ -3321,7 +3393,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; } @@ -3330,7 +3402,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) 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 @@ -3418,6 +3490,9 @@ static void regular_cleanups(double period) if (t > config->cluster_highest_tunnelid) t = 1; + if (t == TUNNEL_ID_PPPOE) + continue; + // check for expired tunnels if (tunnel[t].die && tunnel[t].die <= TIME) { @@ -3450,10 +3525,13 @@ static void regular_cleanups(double period) // Send hello if (tunnel[t].state == TUNNELOPEN && !tunnel[t].controlc && (time_now - tunnel[t].lastrec) > 60) { - controlt *c = controlnew(6); // sending HELLO - controladd(c, 0, t); // send the message - LOG(3, 0, t, "Sending HELLO message\n"); - t_actions++; + if (!config->disable_sending_hello) + { + controlt *c = controlnew(6); // sending HELLO + controladd(c, 0, t); // send the message + LOG(3, 0, t, "Sending HELLO message\n"); + t_actions++; + } } // Check for tunnel changes requested from the CLI @@ -3641,7 +3719,8 @@ static void regular_cleanups(double period) LOG(4, s, session[s].tunnel, "No data in %d seconds, sending LCP ECHO\n", (int)(time_now - session[s].last_packet)); - tunnelsend(b, 24, session[s].tunnel); // send it + + tunnelsend(b, (q - b) + 8, session[s].tunnel); // send it sess_local[s].last_echo = time_now; s_actions++; } @@ -3892,13 +3971,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 -#define BASE_FDS 8 -#else -// the base set of fds polled: cli, cluster, tun, udp, control, dae, netlink -#define BASE_FDS 7 -#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 @@ -3910,10 +3984,11 @@ 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 + 8; // for the hearder of the forwarded MPPP packet (see C_MPPP_FORWARD) - int size_bufp = sizeof(buf) - 8; + uint8_t *p = buf + 32; // for the hearder of the forwarded MPPP packet (see C_MPPP_FORWARD) + // and the forwarded pppoe session + int size_bufp = sizeof(buf) - 32; clockt next_cluster_ping = 0; // send initial ping immediately struct epoll_event events[BASE_FDS + RADIUS_FDS + EXTRA_FDS]; int maxevent = sizeof(events)/sizeof(*events); @@ -3924,13 +3999,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\n", - clifd, cluster_sockfd, tunfd, udpfd, controlfd, daefd, nlfd, udplacfd); -#else - LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d, nlfd=%d\n", - clifd, cluster_sockfd, tunfd, udpfd, controlfd, daefd, nlfd); -#endif + 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[0], controlfd, daefd, nlfd, udplacfd, pppoediscfd, pppoesessfd); /* setup our fds to poll for input */ { @@ -3955,10 +4025,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); @@ -3971,11 +4037,21 @@ 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; + d[i].type = FD_TYPE_PPPOEDISC; e.data.ptr = &d[i++]; - epoll_ctl(epollfd, EPOLL_CTL_ADD, udplacfd, &e); -#endif + epoll_ctl(epollfd, EPOLL_CTL_ADD, pppoediscfd, &e); + + 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 @@ -4037,14 +4113,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 @@ -4078,32 +4152,37 @@ 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 + s = read(pppoediscfd, p, size_bufp); + if (s > 0) process_pppoe_disc(p, s); + n--; + break; + case FD_TYPE_CONTROL: // nsctl commands alen = sizeof(addr); - s = recvfromto(controlfd, buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local); - if (s > 0) processcontrol(buf, s, &addr, alen, &local); + s = recvfromto(controlfd, p, size_bufp, MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local); + if (s > 0) processcontrol(p, s, &addr, alen, &local); n--; break; case FD_TYPE_DAE: // DAE requests alen = sizeof(addr); - s = recvfromto(daefd, buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local); - if (s > 0) processdae(buf, s, &addr, alen, &local); + s = recvfromto(daefd, p, size_bufp, MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local); + if (s > 0) processdae(p, s, &addr, alen, &local); n--; break; case FD_TYPE_RADIUS: // RADIUS response alen = sizeof(addr); - s = recvfrom(radfds[d->index], buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen); + s = recvfrom(radfds[d->index], p, size_bufp, MSG_WAITALL, (struct sockaddr *) &addr, &alen); if (s >= 0 && config->cluster_iam_master) { if (addr.sin_addr.s_addr == config->radiusserver[0] || addr.sin_addr.s_addr == config->radiusserver[1]) - processrad(buf, s, d->index); + processrad(p, s, d->index); else LOG(3, 0, 0, "Dropping RADIUS packet from unknown source %s\n", fmtaddr(addr.sin_addr.s_addr, 0)); @@ -4114,15 +4193,15 @@ 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 */ case FD_TYPE_NETLINK: { - struct nlmsghdr *nh = (struct nlmsghdr *)buf; - s = netlink_recv(buf, sizeof(buf)); + struct nlmsghdr *nh = (struct nlmsghdr *)p; + s = netlink_recv(p, size_bufp); if (nh->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *errmsg = NLMSG_DATA(nh); @@ -4134,7 +4213,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 @@ -4146,7 +4224,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); } } @@ -4156,51 +4234,51 @@ 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, buf, sizeof(buf), 0, (void *) &addr, &alen)) > 0) + // L2TP and L2TP REMOTE LNS + if (udp_ready[j]) { - processudp(buf, s, &addr); - udp_pkts++; - } - else - { - 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) + + // incoming IP + if (tun_ready) { - alen = sizeof(addr); - if ((s = recvfrom(udplacfd, buf, sizeof(buf), 0, (void *) &addr, &alen)) > 0) + if ((s = read(tunfd, p, size_bufp)) > 0) { - if (!config->disable_lac_func) - processudp(buf, s, &addr); - - udplac_pkts++; + processtun(p, s); + tun_pkts++; } else { - udplac_ready = 0; + tun_ready = 0; n--; } } -#endif - // incoming IP - if (tun_ready) + + // pppoe session + if (pppoesess_ready) { - if ((s = read(tunfd, p, size_bufp)) > 0) + if ((s = read(pppoesessfd, p, size_bufp)) > 0) { - processtun(p, s); - tun_pkts++; + process_pppoe_sess(p, s); + pppoesess_pkts++; } else { - tun_ready = 0; + pppoesess_ready = 0; n--; } } @@ -4209,9 +4287,9 @@ static void mainloop(void) if (cluster_ready) { alen = sizeof(addr); - if ((s = recvfrom(cluster_sockfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen)) > 0) + if ((s = recvfrom(cluster_sockfd, p, size_bufp, MSG_WAITALL, (void *) &addr, &alen)) > 0) { - processcluster(buf, s, addr.sin_addr.s_addr); + processcluster(p, s, addr.sin_addr.s_addr); cluster_pkts++; } else @@ -4222,18 +4300,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 and %d cluster %d rmlns packets\n", - config->multi_read_count, udp_pkts, tun_pkts, cluster_pkts, udplac_pkts); -#else - LOG(3, 0, 0, "Reached multi_read_count (%d); processed %d udp, %d tun and %d cluster packets\n", - config->multi_read_count, udp_pkts, tun_pkts, cluster_pkts); -#endif + 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[0], tun_pkts, cluster_pkts, pppoesess_pkts); STAT(multi_read_exceeded); more++; } @@ -4568,9 +4641,7 @@ static void initdata(int optdebug, char *optconfig) } #endif /* BGP */ -#ifdef LAC lac_initremotelnsdata(); -#endif } static int assign_ip_address(sessionidt s) @@ -4857,11 +4928,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) @@ -4880,6 +4947,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" @@ -4887,18 +4969,32 @@ static int dump_session(FILE **f, sessiont *s) "# uptime: %ld\n" "# format: username ip qos uptxoctets downrxoctets\n", hostname, - fmtaddr(config->bind_address ? config->bind_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; @@ -5034,9 +5130,33 @@ int main(int argc, char *argv[]) exit(1); inittun(); - LOG(1, 0, 0, "Set up on interface %s\n", config->tundevice); + LOG(1, 0, 0, "Set up on interface %s\n", config->tundevicename); + + if (*config->pppoe_if_to_bind) + { + init_pppoe(); + LOG(1, 0, 0, "Set up on pppoe interface %s\n", config->pppoe_if_to_bind); + } + + 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); - initudp(); initrad(); initippool(); @@ -5268,10 +5388,103 @@ static void update_config() if (!config->radius_dae_port) config->radius_dae_port = DAEPORT; -#ifdef LAC if(!config->bind_portremotelns) config->bind_portremotelns = L2TPLACPORT; -#endif + if(!config->bind_address_remotelns) + config->bind_address_remotelns = INADDR_ANY; + + 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); // re-initialise the random number source initrandom(config->random_device); @@ -5451,8 +5664,7 @@ int sessionsetup(sessionidt s, tunnelidt t) if (ip == session[i].ip) { - sessionkill(i, "Duplicate IP address"); - cluster_listinvert_session(s, i); + sessionshutdown(i, "Duplicate IP address", CDN_ADMIN_DISC, TERM_ADMIN_RESET); // close radius/routes, etc. continue; } @@ -5473,7 +5685,7 @@ int sessionsetup(sessionidt s, tunnelidt t) // Drop the new session in case of duplicate sessionss, not the old one. if (!strcasecmp(user, session[i].user)) - sessionkill(i, "Duplicate session for users"); + sessionshutdown(i, "Duplicate session for users", CDN_ADMIN_DISC, TERM_ADMIN_RESET); // close radius/routes, etc. } } @@ -6009,7 +6221,7 @@ static tunnelidt new_tunnel() tunnelidt i; for (i = 1; i < MAXTUNNEL; i++) { - if (tunnel[i].state == TUNNELFREE) + if ((tunnel[i].state == TUNNELFREE) && (i != TUNNEL_ID_PPPOE)) { LOG(4, 0, i, "Assigning tunnel ID %u\n", i); if (i > config->cluster_highest_tunnelid) @@ -6327,8 +6539,6 @@ int ip_filter(uint8_t *buf, int len, uint8_t filter) return 0; } -#ifdef LAC - tunnelidt lac_new_tunnel() { return new_tunnel(); @@ -6347,7 +6557,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 @@ -6374,4 +6584,3 @@ void lac_tunnelshutdown(tunnelidt t, char *reason, int result, int error, char * tunnelshutdown(t, reason, result, error, msg); } -#endif