X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/76ae461853c7ac6e101704f6e6fd41dc520e9921..d547c00f76be21289a5ba403b3d94818d8696360:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index 8640c8b..0da9a24 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -53,11 +53,24 @@ #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 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. @@ -160,10 +173,23 @@ config_descriptt config_values[] = { CONFIG("ipv6_prefix", ipv6_prefix, IPv6), CONFIG("cli_bind_address", cli_bind_address, IPv4), CONFIG("hostname", hostname, STRING), +#ifdef BGP CONFIG("nexthop_address", nexthop_address, IPv4), CONFIG("nexthop6_address", nexthop6_address, IPv6), +#endif CONFIG("echo_timeout", echo_timeout, INT), 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), { NULL, 0, 0, 0 }, }; @@ -224,13 +250,6 @@ static tunnelidt new_tunnel(void); static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vector, size_t vec_len); static void bundleclear(bundleidt b); -// on slaves, alow BGP to withdraw cleanly before exiting -#define QUIT_DELAY 5 - -// quit actions (master) -#define QUIT_FAILOVER 1 // SIGTERM: exit when all control messages have been acked (for cluster failover) -#define QUIT_SHUTDOWN 2 // SIGQUIT: shutdown sessions/tunnels, reject new connections - // return internal time (10ths since process startup), set f if given // as a side-effect sets time_now, and time_changed static clockt now(double *f) @@ -245,7 +264,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; } @@ -281,7 +301,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 @@ -676,15 +696,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"); @@ -736,8 +760,8 @@ 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->iftun_address) + ip = config->iftun_address; else ip = 0x01010101; // 1.1.1.1 netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); @@ -862,6 +886,25 @@ static void initudp(void) exit(1); } +#ifdef LAC + // Tunnel to Remote LNS + 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)); + { + int flags = fcntl(udplacfd, F_GETFL, 0); + fcntl(udplacfd, F_SETFL, flags | O_NONBLOCK); + } + if (bind(udplacfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) + { + LOG(0, 0, 0, "Error in UDP REMOTE LNS bind: %s\n", strerror(errno)); + exit(1); + } +#endif + // Intercept snoopfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); } @@ -1156,6 +1199,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"); @@ -1182,8 +1231,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 { 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)); @@ -1330,7 +1382,8 @@ static void update_session_out_stat(sessionidt s, sessiont *sp, int len) // process outgoing (to tunnel) IP // -static void processipout(uint8_t *buf, int len) +// (i.e. this routine writes to data[-8]). +void processipout(uint8_t *buf, int len) { sessionidt s; sessiont *sp; @@ -1469,6 +1522,14 @@ static void processipout(uint8_t *buf, int len) if(session[s].bundle != 0 && bundle[session[s].bundle].num_of_links > 1) { + + if (!config->cluster_iam_master) + { + // The MPPP packets must be managed by the Master. + master_forward_mppp_packet(s, data, size); + return; + } + // Add on L2TP header sessionidt members[MAXBUNDLESES]; bundleidt bid = session[s].bundle; @@ -1490,7 +1551,7 @@ static void processipout(uint8_t *buf, int len) if (nb_opened < 1) { - LOG(2, s, t, "MPPP: PROCESSIPOUT ERROR, no session opened in bundle:%d\n", bid); + LOG(3, s, t, "MPPP: PROCESSIPOUT ERROR, no session opened in bundle:%d\n", bid); return; } @@ -2035,11 +2096,11 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e { uint8_t ml; for(ml = 0; mlpeer_address ? config->peer_address : - config->bind_address ? config->bind_address : + config->iftun_address ? config->iftun_address : my_address; // send my IP tunnelsend(buf, 10 + (q - buf), t); // send it @@ -2200,6 +2269,18 @@ 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; + if (session[sess].forwardtosession == s) + { + // Shutdown the linked session also. + 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); cluster_send_session(s); @@ -2351,6 +2432,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); @@ -2615,7 +2702,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) case 0: // message type message = ntohs(*(uint16_t *) b); mandatory = flags & 0x80; - LOG(4, s, t, " Message type = %u (%s)\n", *b, l2tp_code(message)); + LOG(4, s, t, " Message type = %u (%s)\n", message, l2tp_code(message)); break; case 1: // result code { @@ -2710,6 +2797,15 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) } break; case 13: // Response +#ifdef LAC + if (tunnel[t].isremotelns) + { + chapresponse = calloc(17, 1); + memcpy(chapresponse, 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; @@ -2935,8 +3031,10 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) { case 1: // SCCRQ - Start Control Connection Request tunnel[t].state = TUNNELOPENING; + LOG(3, s, t, "Received SCCRQ\n"); if (main_quit != QUIT_SHUTDOWN) { + LOG(3, s, t, "sending SCCRP\n"); controlt *c = controlnew(2); // sending SCCRP control16(c, 2, version, 1); // protocol version control32(c, 3, 3, 1); // framing @@ -2953,33 +3051,74 @@ 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) + { + hasht hash; + + lac_calc_rlns_auth(t, 2, hash); // id = 2 (SCCRP) + // check authenticator + if (memcmp(hash, chapresponse, 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, 8, Vendor_name, 1); // Vendor name + control16(c, 2, version, 1); // protocol version + control32(c, 3, 3, 1); // framing Capabilities + control16(c, 9, t, 1); // assigned tunnel + controladd(c, 0, t); // send + } + else + { + tunnelshutdown(t, "Bad chap response from REMOTE LNS", 4, 0, 0); + } + } + } + else + { + tunnelshutdown(t, "Shutting down", 6, 0, 0); + } +#endif /* LAC */ break; case 3: // SCCN + LOG(3, s, t, "Received SCCN\n"); tunnel[t].state = TUNNELOPEN; tunnel[t].lastrec = time_now; controlnull(t); // ack break; case 4: // StopCCN + LOG(3, s, t, "Received StopCCN\n"); controlnull(t); // ack 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 // TBA + LOG(3, s, t, "Received OCRQ\n"); break; case 8: // OCRO // TBA + LOG(3, s, t, "Received OCRO\n"); break; case 9: // OCCN // TBA + LOG(3, s, t, "Received OCCN\n"); break; case 10: // ICRQ + LOG(3, s, t, "Received ICRQ\n"); if (sessionfree && main_quit != QUIT_SHUTDOWN) { controlt *c = controlnew(11); // ICRP + LOG(3, s, t, "Sending ICRP\n"); + s = sessionfree; sessionfree = session[s].next; memset(&session[s], 0, sizeof(session[s])); @@ -3007,6 +3146,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) { controlt *c = controlnew(14); // CDN + LOG(3, s, t, "Sending CDN\n"); if (!sessionfree) { STAT(session_overflow); @@ -3020,9 +3160,26 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) } return; case 11: // ICRP - // TBA +#ifdef LAC + LOG(3, s, t, "Received ICRP\n"); + if (session[s].forwardtosession) + { + controlt *c = controlnew(12); // ICCN + + session[s].opened = time_now; + session[s].tunnel = t; + session[s].far = asession; + session[s].last_packet = session[s].last_data = time_now; + + control32(c, 19, 1, 1); // Framing Type + control32(c, 24, 10000000, 1); // Tx Connect Speed + 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"); if (amagic == 0) amagic = time_now; session[s].magic = amagic; // set magic number session[s].flags = aflags; // set flags received @@ -3035,13 +3192,14 @@ 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_address ? config->iftun_address : my_address); sendlcp(s, t); change_state(s, lcp, RequestSent); break; case 14: // CDN + LOG(3, s, t, "Received CDN\n"); controlnull(t); // ack sessionshutdown(s, disc_reason, CDN_NONE, disc_cause); break; @@ -3092,6 +3250,28 @@ 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); + return; + } + 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); + } + } +#endif /* LAC */ + if (s && !session[s].opened) // Is something wrong?? { if (!config->cluster_iam_master) @@ -3101,7 +3281,6 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) return; } - LOG(1, s, t, "UDP packet contains session which is not opened. Dropping packet.\n"); STAT(tunnel_rx_errors); return; @@ -3210,6 +3389,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) } // read and process packet on tun +// (i.e. this routine writes to buf[-8]). static void processtun(uint8_t * buf, int len) { LOG_HEX(5, "Receive TUN Data", buf, len); @@ -3285,6 +3465,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) { @@ -3508,7 +3691,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++; } @@ -3759,8 +3943,13 @@ static int still_busy(void) # include "fake_epoll.h" #endif -// the base set of fds polled: cli, cluster, tun, udp, control, dae, netlink -#define BASE_FDS 7 +#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 // additional polled fds #ifdef BGP @@ -3774,6 +3963,9 @@ static void mainloop(void) { int i; uint8_t buf[65536]; + uint8_t *p = buf + 24; // for the hearder of the forwarded MPPP packet (see C_MPPP_FORWARD) + // and the forwarded pppoe session + int size_bufp = sizeof(buf) - 24; 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); @@ -3784,8 +3976,13 @@ static void mainloop(void) exit(1); } - 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); +#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 /* setup our fds to poll for input */ { @@ -3825,6 +4022,20 @@ static void mainloop(void) d[i].type = FD_TYPE_NETLINK; 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); + + d[i].type = FD_TYPE_PPPOESESS; + e.data.ptr = &d[i++]; + epoll_ctl(epollfd, EPOLL_CTL_ADD, pppoesessfd, &e); } #ifdef BGP @@ -3887,6 +4098,12 @@ static void mainloop(void) socklen_t alen; int c, s; int udp_ready = 0; +#ifdef LAC + int udplac_ready = 0; + int udplac_pkts = 0; +#endif + int pppoesess_ready = 0; + int pppoesess_pkts = 0; int tun_ready = 0; int cluster_ready = 0; int udp_pkts = 0; @@ -3924,6 +4141,16 @@ static void mainloop(void) 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_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); @@ -4003,9 +4230,9 @@ static void mainloop(void) if (udp_ready) { alen = sizeof(addr); - if ((s = recvfrom(udpfd, buf, sizeof(buf), 0, (void *) &addr, &alen)) > 0) + if ((s = recvfrom(udpfd, p, size_bufp, 0, (void *) &addr, &alen)) > 0) { - processudp(buf, s, &addr); + processudp(p, s, &addr); udp_pkts++; } else @@ -4014,14 +4241,32 @@ static void mainloop(void) 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) { - if ((s = read(tunfd, buf, sizeof(buf))) > 0) + if ((s = read(tunfd, p, size_bufp)) > 0) { - processtun(buf, s); - tun_pkts++; + processtun(p, s); + tun_pkts++; } else { @@ -4030,13 +4275,28 @@ static void mainloop(void) } } + // pppoe session + if (pppoesess_ready) + { + if ((s = read(pppoesessfd, p, size_bufp)) > 0) + { + process_pppoe_sess(p, s); + pppoesess_pkts++; + } + else + { + pppoesess_ready = 0; + n--; + } + } + // cluster 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 @@ -4052,9 +4312,13 @@ static void mainloop(void) if (c >= config->multi_read_count) { +#ifdef LAC + LOG(3, 0, 0, "Reached multi_read_count (%d); processed %d udp, %d tun %d cluster and %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 STAT(multi_read_exceeded); more++; } @@ -4388,6 +4652,10 @@ static void initdata(int optdebug, char *optconfig) exit(1); } #endif /* BGP */ + +#ifdef LAC + lac_initremotelnsdata(); +#endif } static int assign_ip_address(sessionidt s) @@ -4674,7 +4942,11 @@ 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) @@ -4700,7 +4972,7 @@ 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_address ? config->iftun_address : my_address, 0), now, now - basetime); } @@ -4847,8 +5119,13 @@ 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); + } initudp(); initrad(); initippool(); @@ -5081,6 +5358,18 @@ 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->iftun_address) + config->iftun_address = config->bind_address; + + 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); @@ -5215,18 +5504,18 @@ int sessionsetup(sessionidt s, tunnelidt t) LOG(3, s, t, "Doing session setup for session\n"); // Join a bundle if the MRRU option is accepted - if(session[s].mrru > 0 && session[s].bundle == 0) - { - LOG(3, s, t, "This session can be part of multilink bundle\n"); - if (join_bundle(s) > 0) - cluster_send_bundle(session[s].bundle); + if(session[s].mrru > 0 && session[s].bundle == 0) + { + LOG(3, s, t, "This session can be part of multilink bundle\n"); + if (join_bundle(s) > 0) + cluster_send_bundle(session[s].bundle); else { LOG(0, s, t, "MPPP: Mismaching mssf option with other sessions in bundle\n"); sessionshutdown(s, "Mismaching mssf option.", CDN_NONE, TERM_SERVICE_UNAVAILABLE); return 0; } - } + } if (!session[s].ip) { @@ -5241,7 +5530,6 @@ int sessionsetup(sessionidt s, tunnelidt t) fmtaddr(htonl(session[s].ip), 0)); } - // Make sure this is right session[s].tunnel = t; @@ -5254,13 +5542,14 @@ int sessionsetup(sessionidt s, tunnelidt t) for (i = 1; i <= config->cluster_highest_sessionid; i++) { if (i == s) continue; - if (!session[s].opened) continue; + if (!session[s].opened) break; // Allow duplicate sessions for multilink ones of the same bundle. - if (session[s].bundle && session[i].bundle && session[s].bundle == session[i].bundle) - continue; + if (session[s].bundle && session[i].bundle && session[s].bundle == session[i].bundle) continue; + if (ip == session[i].ip) { sessionkill(i, "Duplicate IP address"); + cluster_listinvert_session(s, i); continue; } @@ -5268,16 +5557,16 @@ int sessionsetup(sessionidt s, tunnelidt t) if (session[s].walled_garden || session[i].walled_garden) continue; // Guest change int found = 0; - int gu; - for (gu = 0; gu < guest_accounts_num; gu++) - { - if (!strcasecmp(user, guest_users[gu])) - { - found = 1; - break; - } - } - if (found) continue; + int gu; + for (gu = 0; gu < guest_accounts_num; gu++) + { + if (!strcasecmp(user, guest_users[gu])) + { + found = 1; + break; + } + } + if (found) continue; // Drop the new session in case of duplicate sessionss, not the old one. if (!strcasecmp(user, session[i].user)) @@ -5288,7 +5577,7 @@ int sessionsetup(sessionidt s, tunnelidt t) // no need to set a route for the same IP address of the bundle if (!session[s].bundle || (bundle[session[s].bundle].num_of_links == 1)) { - int routed = 0; + int routed = 0; // Add the route for this session. for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++) @@ -5817,7 +6106,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) @@ -6134,3 +6423,52 @@ int ip_filter(uint8_t *buf, int len, uint8_t filter) // default deny return 0; } + +#ifdef LAC + +tunnelidt lac_new_tunnel() +{ + return new_tunnel(); +} + +void lac_tunnelclear(tunnelidt t) +{ + tunnelclear(t); +} + +void lac_send_SCCRQ(tunnelidt t, uint8_t * auth, unsigned int auth_len) +{ + uint16_t version = 0x0100; // protocol version + + tunnel[t].state = TUNNELOPENING; + + // Sent SCCRQ - Start Control Connection Request + controlt *c = controlnew(1); // sending SCCRQ + controls(c, 7, 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 + control16(c, 9, t, 1); // assigned tunnel + controlb(c, 11, (uint8_t *) auth, auth_len, 1); // CHAP Challenge + LOG(3, 0, t, "Sent SCCRQ to REMOTE LNS\n"); + controladd(c, 0, t); // send +} + +void lac_send_ICRQ(tunnelidt t, sessionidt s) +{ + // Sent ICRQ Incoming-call-request + controlt *c = controlnew(10); // ICRQ + + control16(c, 14, s, 1); // assigned sesion + call_serial_number++; + control32(c, 15, call_serial_number, 1); // call serial number + LOG(3, s, t, "Sent ICRQ to REMOTE LNS (far ID %u)\n", tunnel[t].far); + controladd(c, 0, t); // send +} + +void lac_tunnelshutdown(tunnelidt t, char *reason, int result, int error, char *msg) +{ + tunnelshutdown(t, reason, result, error, msg); +} + +#endif