X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/b8cd61ce5a3796ef4d9f5a5a63fb49e5fa43aaec..e6208f516d2437f7effeee7305bd3ecae93e4c11:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index 4e2a079..8af4eb2 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -4,7 +4,7 @@ // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced // vim: sw=8 ts=8 -char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.117 2005/08/10 08:04:26 bodea Exp $"; +char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.147 2005/11/14 08:38:02 bodea Exp $"; #include #include @@ -75,6 +75,10 @@ static int syslog_log = 0; // are we logging to syslog static FILE *log_stream = 0; // file handle for direct logging (i.e. direct into file, not via syslog). uint32_t last_id = 0; // Unique ID for radius accounting +// calculated from config->l2tp_mtu +uint16_t MRU = 0; // PPP MRU +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 @@ -92,7 +96,9 @@ uint32_t eth_tx = 0; static uint32_t ip_pool_size = 1; // Size of the pool of addresses used for dynamic address allocation. time_t time_now = 0; // Current time in seconds since epoch. static char time_now_string[64] = {0}; // Current time as a string. +int time_changed = 0; // time_now changed char main_quit = 0; // True if we're in the process of exiting. +char main_reload = 0; // Re-load pending linked_list *loaded_plugins; linked_list *plugins[MAX_PLUGIN_TYPES]; @@ -104,7 +110,8 @@ config_descriptt config_values[] = { CONFIG("log_file", log_filename, STRING), CONFIG("pid_file", pid_file, STRING), CONFIG("random_device", random_device, STRING), - CONFIG("l2tp_secret", l2tpsecret, STRING), + CONFIG("l2tp_secret", l2tp_secret, STRING), + CONFIG("l2tp_mtu", l2tp_mtu, INT), CONFIG("ppp_restart_time", ppp_restart_time, INT), CONFIG("ppp_max_configure", ppp_max_configure, INT), CONFIG("ppp_max_failure", ppp_max_failure, INT), @@ -135,6 +142,7 @@ config_descriptt config_values[] = { CONFIG("packet_limit", max_packets, INT), CONFIG("cluster_address", cluster_address, IPv4), CONFIG("cluster_interface", cluster_interface, STRING), + CONFIG("cluster_mcast_ttl", cluster_mcast_ttl, INT), CONFIG("cluster_hb_interval", cluster_hb_interval, INT), CONFIG("cluster_hb_timeout", cluster_hb_timeout, INT), CONFIG("cluster_master_min_adv", cluster_master_min_adv, INT), @@ -154,6 +162,7 @@ static char *plugin_functions[] = { "plugin_control", "plugin_radius_response", "plugin_radius_reset", + "plugin_radius_account", "plugin_become_master", "plugin_new_session_master", }; @@ -182,7 +191,6 @@ static void cache_ipv6map(struct in6_addr ip, int prefixlen, int s); static void free_ip_address(sessionidt s); static void dump_acct_info(int all); static void sighup_handler(int sig); -static void sigalrm_handler(int sig); static void shutdown_handler(int sig); static void sigchild_handler(int sig); static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challenge_length, uint8_t **challenge_response); @@ -204,11 +212,17 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec #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) { struct timeval t; gettimeofday(&t, 0); if (f) *f = t.tv_sec + t.tv_usec / 1000000.0; + if (t.tv_sec != time_now) + { + time_now = t.tv_sec; + time_changed++; + } return (t.tv_sec - basetime) * 10 + t.tv_usec / 100000 + 1; } @@ -948,7 +962,7 @@ void tunnelsend(uint8_t * buf, uint16_t l, tunnelidt t) { tunnel[t].last = time_now; // control message sent tunnel[t].retry = backoff(tunnel[t].try); // when to resend - if (tunnel[t].try > 1) + if (tunnel[t].try) { STAT(tunnel_retries); LOG(3, 0, t, "Control message resend try %d\n", tunnel[t].try); @@ -977,6 +991,61 @@ int tun_write(uint8_t * data, int size) return write(tunfd, data, size); } +// adjust tcp mss to avoid fragmentation (called only for tcp packets with syn set) +void adjust_tcp_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp) +{ + int d = (tcp[12] >> 4) * 4; + uint8_t *mss = 0; + uint8_t *opts; + uint8_t *data; + uint16_t orig; + uint32_t sum; + + if ((tcp[13] & 0x3f) & ~(TCP_FLAG_SYN|TCP_FLAG_ACK)) // only want SYN and SYN,ACK + return; + + if (tcp + d > buf + len) // short? + return; + + opts = tcp + 20; + data = tcp + d; + + while (opts < data) + { + if (*opts == 2 && opts[1] == 4) // mss option (2), length 4 + { + mss = opts + 2; + if (mss + 2 > data) return; // short? + break; + } + + if (*opts == 0) return; // end of options + if (*opts == 1 || !opts[1]) // no op (one byte), or no length (prevent loop) + opts++; + else + opts += opts[1]; // skip over option + } + + if (!mss) return; // not found + orig = ntohs(*(uint16_t *) mss); + + if (orig <= MSS) return; // mss OK + + LOG(5, s, t, "TCP: %s:%u -> %s:%u SYN%s: adjusted mss from %u to %u\n", + fmtaddr(*(in_addr_t *) (buf + 12), 0), ntohs(*(uint16_t *) tcp), + fmtaddr(*(in_addr_t *) (buf + 16), 1), ntohs(*(uint16_t *) (tcp + 2)), + (tcp[13] & TCP_FLAG_ACK) ? ",ACK" : "", orig, MSS); + + // set mss + *(int16_t *) mss = htons(MSS); + + // adjust checksum (see rfc1141) + sum = orig + (~MSS & 0xffff); + sum += ntohs(*(uint16_t *) (tcp + 16)); + sum = (sum & 0xffff) + (sum >> 16); + *(uint16_t *) (tcp + 16) = htons(sum); +} + // process outgoing (to tunnel) IP // static void processipout(uint8_t *buf, int len) @@ -1084,6 +1153,14 @@ static void processipout(uint8_t *buf, int len) if (session[s].filter_out && !ip_filter(buf, len, session[s].filter_out - 1)) return; + // adjust MSS on SYN and SYN,ACK packets with options + if ((ntohs(*(uint16_t *) (buf + 6)) & 0x1fff) == 0 && buf[9] == IPPROTO_TCP) // first tcp fragment + { + int ihl = (buf[0] & 0xf) * 4; // length of IP header + if (len >= ihl + 20 && (buf[ihl + 13] & TCP_FLAG_SYN) && ((buf[ihl + 12] >> 4) > 5)) + adjust_tcp_mss(s, t, buf, len, buf + ihl); + } + if (sp->tbf_out) { // Are we throttling this session? @@ -1104,7 +1181,7 @@ static void processipout(uint8_t *buf, int len) // Add on L2TP header { - uint8_t *p = makeppp(b, sizeof(b), buf, len, t, s, PPPIP); + uint8_t *p = makeppp(b, sizeof(b), buf, len, s, t, PPPIP); if (!p) return; tunnelsend(b, len + (p-b), t); // send it... } @@ -1215,7 +1292,7 @@ static void processipv6out(uint8_t * buf, int len) // Add on L2TP header { - uint8_t *p = makeppp(b, sizeof(b), buf, len, t, s, PPPIPV6); + uint8_t *p = makeppp(b, sizeof(b), buf, len, s, t, PPPIPV6); if (!p) return; tunnelsend(b, len + (p-b), t); // send it... } @@ -1267,7 +1344,7 @@ static void send_ipout(sessionidt s, uint8_t *buf, int len) // Add on L2TP header { - uint8_t *p = makeppp(b, sizeof(b), buf, len, t, s, PPPIP); + uint8_t *p = makeppp(b, sizeof(b), buf, len, s, t, PPPIP); if (!p) return; tunnelsend(b, len + (p-b), t); // send it... } @@ -1366,7 +1443,7 @@ static void controlnull(tunnelidt t) } // add a control message to a tunnel, and send if within window -static void controladd(controlt * c, tunnelidt t, sessionidt far) +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 @@ -1558,7 +1635,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error) control16(c, 1, result, 1); control16(c, 14, s, 1); // assigned session (our end) - controladd(c, session[s].tunnel, session[s].far); // send the message + controladd(c, session[s].far, session[s].tunnel); // send the message } if (!session[s].die) @@ -1578,12 +1655,13 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error) cluster_send_session(s); } -void sendipcp(tunnelidt t, sessionidt s) +void sendipcp(sessionidt s, tunnelidt t) { - uint8_t buf[MAXCONTROL]; + uint8_t buf[MAXETHER]; uint8_t *q; CSTAT(sendipcp); + LOG(3, s, t, "IPCP: send ConfigReq\n"); if (!session[s].unique_id) { @@ -1591,7 +1669,7 @@ void sendipcp(tunnelidt t, sessionidt s) session[s].unique_id = last_id; } - q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPCP); + q = makeppp(buf, sizeof(buf), 0, 0, s, t, PPPIPCP); if (!q) return; *q = ConfigReq; @@ -1604,16 +1682,18 @@ void sendipcp(tunnelidt t, sessionidt s) my_address; // send my IP tunnelsend(buf, 10 + (q - buf), t); // send it + restart_timer(s, ipcp); } -void sendipv6cp(tunnelidt t, sessionidt s) +void sendipv6cp(sessionidt s, tunnelidt t) { - uint8_t buf[MAXCONTROL]; + uint8_t buf[MAXETHER]; uint8_t *q; CSTAT(sendipv6cp); + LOG(3, s, t, "IPV6CP: send ConfigReq\n"); - q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPV6CP); + q = makeppp(buf, sizeof(buf), 0, 0, s, t, PPPIPV6CP); if (!q) return; *q = ConfigReq; @@ -1628,6 +1708,7 @@ void sendipv6cp(tunnelidt t, sessionidt s) q[13] = 1; tunnelsend(buf, 14 + (q - buf), t); // send it + restart_timer(s, ipv6cp); } static void sessionclear(sessionidt s) @@ -1753,7 +1834,7 @@ static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, cha control16(c, 1, result, 1); control16(c, 9, t, 1); // assigned tunnel (our end) - controladd(c, t, 0); // send the message + controladd(c, 0, t); // send the message } } @@ -1824,12 +1905,16 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) return; } l -= (p - buf); + + // used to time out old tunnels + if (t && tunnel[t].state == TUNNELOPEN) + tunnel[t].lastrec = time_now; + if (*buf & 0x80) { // control uint16_t message = 0xFFFF; // message type uint8_t fatal = 0; uint8_t mandatory = 0; - uint8_t authtype = 0; // proxy auth type uint16_t asession = 0; // assigned session uint32_t amagic = 0; // magic number uint8_t aflags = 0; // flags from last LCF @@ -1912,9 +1997,6 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) return; } - // This is used to time out old tunnels - tunnel[t].lastrec = time_now; - // check sequence of this message { int skip = tunnel[t].window; // track how many in-window packets are still in queue @@ -2004,7 +2086,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) uint16_t orig_len; // handle hidden AVPs - if (!*config->l2tpsecret) + if (!*config->l2tp_secret) { LOG(1, s, t, "Hidden AVP requested, but no L2TP secret.\n"); fatal = flags; @@ -2214,11 +2296,6 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) { uint16_t atype = ntohs(*(uint16_t *)b); LOG(4, s, t, " Proxy Auth Type %d (%s)\n", atype, ppp_auth_type(atype)); - if (atype == 2) - authtype = AUTHCHAP; - else if (atype == 3) - authtype = AUTHPAP; - break; } case 30: // Proxy Authentication Name @@ -2251,14 +2328,10 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) { if (*p == 5 && p[1] == 6) // Magic-Number amagic = ntohl(*(uint32_t *) (p + 2)); - else if (*p == 3 && p[1] == 4 && *(uint16_t *) (p + 2) == htons(PPPPAP)) // Authentication-Protocol (PAP) - authtype = AUTHPAP; - else if (*p == 3 && p[1] == 5 && *(uint16_t *) (p + 2) == htons(PPPCHAP) && p[4] == 5) // Authentication-Protocol (CHAP) - authtype = AUTHCHAP; else if (*p == 7) // Protocol-Field-Compression - aflags |= SESSIONPFC; + aflags |= SESSION_PFC; else if (*p == 8) // Address-and-Control-Field-Compression - aflags |= SESSIONACFC; + aflags |= SESSION_ACFC; p += p[1]; } } @@ -2302,10 +2375,10 @@ 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, tunnel[t].hostname, 1); // host name (TBA) + controls(c, 7, hostname, 1); // host name if (chapresponse) controlb(c, 13, chapresponse, 16, 1); // Challenge response control16(c, 9, t, 1); // assigned tunnel - controladd(c, t, 0); // send the resply + controladd(c, 0, t); // send the resply } else { @@ -2353,7 +2426,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) session[s].last_packet = time_now; LOG(3, s, t, "New session (%d/%d)\n", tunnel[t].far, session[s].far); control16(c, 14, s, 1); // assigned session - controladd(c, t, asession); // send the reply + controladd(c, asession, t); // send the reply strncpy(session[s].called, called, sizeof(session[s].called) - 1); strncpy(session[s].calling, calling, sizeof(session[s].calling) - 1); @@ -2376,7 +2449,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) else control16(c, 1, 2, 7); // shutting down, try another - controladd(c, t, asession); // send the message + controladd(c, asession, t); // send the message } return; case 11: // ICRP @@ -2385,23 +2458,17 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) case 12: // ICCN if (amagic == 0) amagic = time_now; session[s].magic = amagic; // set magic number - session[s].l2tp_flags = aflags; // set flags received - LOG(3, s, t, "Magic %X Flags %X\n", amagic, aflags); + session[s].flags = aflags; // set flags received + session[s].mru = PPPMTU; // default controlnull(t); // ack - // proxy authentication type is not supported - if (!(config->radius_authtypes & authtype)) - authtype = config->radius_authprefer; - // start LCP - sendlcp(t, s, authtype); - sess_local[s].lcp.restart = time_now + config->ppp_restart_time; - sess_local[s].lcp.conf_sent = 1; - sess_local[s].lcp.nak_sent = 0; - sess_local[s].lcp_authtype = authtype; - session[s].ppp.lcp = RequestSent; - + sess_local[s].lcp_authtype = config->radius_authprefer; + sess_local[s].ppp_mru = MRU; + sendlcp(s, t); + change_state(s, lcp, RequestSent); break; + case 14: // CDN controlnull(t); // ack sessionshutdown(s, "Closed (Received CDN).", 0, 0); @@ -2427,7 +2494,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) } else { // data - uint16_t prot; + uint16_t proto; LOG_HEX(5, "Receive Tunnel Data", p, l); if (l > 2 && p[0] == 0xFF && p[1] == 0x03) @@ -2443,12 +2510,12 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) } if (*p & 1) { - prot = *p++; + proto = *p++; l--; } else { - prot = ntohs(*(uint16_t *) p); + proto = ntohs(*(uint16_t *) p); p += 2; l -= 2; } @@ -2468,43 +2535,43 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) return; } - if (prot == PPPPAP) + 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; } - processpap(t, s, p, l); + processpap(s, t, p, l); } - else if (prot == PPPCHAP) + 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; } - processchap(t, s, p, l); + processchap(s, t, p, l); } - else if (prot == PPPLCP) + 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; } - processlcp(t, s, p, l); + processlcp(s, t, p, l); } - else if (prot == PPPIPCP) + 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; } - processipcp(t, s, p, l); + processipcp(s, t, p, l); } - else if (prot == PPPIPV6CP) + 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; } - processipv6cp(t, s, p, l); + processipv6cp(s, t, p, l); } - else if (prot == PPPCCP) + 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; } - processccp(t, s, p, l); + processccp(s, t, p, l); } - else if (prot == PPPIP) + else if (proto == PPPIP) { if (session[s].die) { @@ -2519,15 +2586,10 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) return; } - processipin(t, s, p, l); + processipin(s, t, p, l); } - else if (prot == PPPIPV6) + else if (proto == PPPIPV6 && config->ipv6_prefix.s6_addr[0]) { - if (!config->ipv6_prefix.s6_addr[0]) - { - LOG(1, s, t, "IPv6 not configured; yet received IPv6 packet. Ignoring.\n"); - return; - } if (session[s].die) { LOG(4, s, t, "Session %d is closing. Don't process PPP packets\n", s); @@ -2541,12 +2603,38 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) return; } - processipv6in(t, s, p, l); + processipv6in(s, t, p, l); + } + else if (session[s].ppp.lcp == Opened) + { + uint8_t buf[MAXETHER]; + uint8_t *q; + int mru = session[s].mru; + if (mru > sizeof(buf)) mru = sizeof(buf); + + l += 6; + if (l > mru) l = mru; + + q = makeppp(buf, sizeof(buf), 0, 0, s, t, PPPLCP); + if (!q) return; + + *q = ProtocolRej; + *(q + 1) = ++sess_local[s].lcp_ident; + *(uint16_t *)(q + 2) = htons(l); + *(uint16_t *)(q + 4) = htons(proto); + memcpy(q + 6, p, l - 6); + + if (proto == PPPIPV6CP) + LOG(3, s, t, "LCP: send ProtocolRej (IPV6CP: not configured)\n"); + else + LOG(2, s, t, "LCP: sent ProtocolRej (0x%04X: unsupported)\n", proto); + + tunnelsend(buf, l + (q - buf), t); } else { - STAT(tunnel_rx_errors); - LOG(1, s, t, "Unknown PPP protocol %04X\n", prot); + LOG(2, s, t, "Unknown PPP protocol 0x%04X received in LCP %s state\n", + proto, ppp_state(session[s].ppp.lcp)); } } } @@ -2657,10 +2745,10 @@ static void regular_cleanups(double period) } } // Send hello - if (tunnel[t].state == TUNNELOPEN && tunnel[t].lastrec < TIME + 600) + if (tunnel[t].state == TUNNELOPEN && !tunnel[t].controlc && (time_now - tunnel[t].lastrec) > 60) { controlt *c = controlnew(6); // sending HELLO - controladd(c, t, 0); // send the message + controladd(c, 0, t); // send the message LOG(3, 0, t, "Sending HELLO message\n"); t_actions++; } @@ -2715,7 +2803,7 @@ static void regular_cleanups(double period) } // PPP timeouts - if (sess_local[s].lcp.restart >= time_now) + if (sess_local[s].lcp.restart <= time_now) { int next_state = session[s].ppp.lcp; switch (session[s].ppp.lcp) @@ -2728,9 +2816,7 @@ static void regular_cleanups(double period) if (sess_local[s].lcp.conf_sent < config->ppp_max_configure) { LOG(3, s, session[s].tunnel, "No ACK for LCP ConfigReq... resending\n"); - sess_local[s].lcp.restart = time_now + config->ppp_restart_time; - sess_local[s].lcp.conf_sent++; - sendlcp(t, s, sess_local[s].lcp_authtype); + sendlcp(s, session[s].tunnel); change_state(s, lcp, next_state); } else @@ -2746,7 +2832,7 @@ static void regular_cleanups(double period) continue; } - if (sess_local[s].ipcp.restart >= time_now) + if (sess_local[s].ipcp.restart <= time_now) { int next_state = session[s].ppp.ipcp; switch (session[s].ppp.ipcp) @@ -2759,9 +2845,7 @@ static void regular_cleanups(double period) if (sess_local[s].ipcp.conf_sent < config->ppp_max_configure) { LOG(3, s, session[s].tunnel, "No ACK for IPCP ConfigReq... resending\n"); - sess_local[s].ipcp.restart = time_now + config->ppp_restart_time; - sess_local[s].ipcp.conf_sent++; - sendipcp(t, s); + sendipcp(s, session[s].tunnel); change_state(s, ipcp, next_state); } else @@ -2777,7 +2861,7 @@ static void regular_cleanups(double period) continue; } - if (sess_local[s].ipv6cp.restart >= time_now) + if (sess_local[s].ipv6cp.restart <= time_now) { int next_state = session[s].ppp.ipv6cp; switch (session[s].ppp.ipv6cp) @@ -2790,9 +2874,7 @@ static void regular_cleanups(double period) if (sess_local[s].ipv6cp.conf_sent < config->ppp_max_configure) { LOG(3, s, session[s].tunnel, "No ACK for IPV6CP ConfigReq... resending\n"); - sess_local[s].ipv6cp.restart = time_now + config->ppp_restart_time; - sess_local[s].ipv6cp.conf_sent++; - sendipv6cp(t, s); + sendipv6cp(s, session[s].tunnel); change_state(s, ipv6cp, next_state); } else @@ -2805,7 +2887,7 @@ static void regular_cleanups(double period) } } - if (sess_local[s].ccp.restart >= time_now) + if (sess_local[s].ccp.restart <= time_now) { int next_state = session[s].ppp.ccp; switch (session[s].ppp.ccp) @@ -2818,9 +2900,7 @@ static void regular_cleanups(double period) if (sess_local[s].ccp.conf_sent < config->ppp_max_configure) { LOG(3, s, session[s].tunnel, "No ACK for CCP ConfigReq... resending\n"); - sess_local[s].ccp.restart = time_now + config->ppp_restart_time; - sess_local[s].ccp.conf_sent++; - sendccp(t, s); + sendccp(s, session[s].tunnel); change_state(s, ccp, next_state); } else @@ -2843,11 +2923,12 @@ 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 >= ECHO_TIMEOUT)) + if (session[s].ppp.phase >= Establish && (time_now - session[s].last_packet >= ECHO_TIMEOUT) && + (time_now - sess_local[s].last_echo >= ECHO_TIMEOUT)) { - uint8_t b[MAXCONTROL] = {0}; + uint8_t b[MAXETHER]; - uint8_t *q = makeppp(b, sizeof(b), 0, 0, session[s].tunnel, s, PPPLCP); + uint8_t *q = makeppp(b, sizeof(b), 0, 0, s, session[s].tunnel, PPPLCP); if (!q) continue; *q = EchoReq; @@ -2858,6 +2939,7 @@ 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 + sess_local[s].last_echo = time_now; s_actions++; } @@ -3147,9 +3229,17 @@ static void mainloop(void) int more = 0; int n; + + if (main_reload) + { + main_reload = 0; + read_config_file(); + config->reload_config++; + } + if (config->reload_config) { - // Update the config state based on config settings + config->reload_config = 0; update_config(); } @@ -3313,6 +3403,35 @@ static void mainloop(void) } } + if (time_changed) + { + double Mbps = 1024.0 * 1024.0 / 8 * time_changed; + + // Log current traffic stats + snprintf(config->bandwidth, sizeof(config->bandwidth), + "UDP-ETH:%1.0f/%1.0f ETH-UDP:%1.0f/%1.0f TOTAL:%0.1f IN:%u OUT:%u", + (udp_rx / Mbps), (eth_tx / Mbps), (eth_rx / Mbps), (udp_tx / Mbps), + ((udp_tx + udp_rx + eth_tx + eth_rx) / Mbps), + udp_rx_pkt / time_changed, eth_rx_pkt / time_changed); + + udp_tx = udp_rx = 0; + udp_rx_pkt = eth_rx_pkt = 0; + eth_tx = eth_rx = 0; + time_changed = 0; + + if (config->dump_speed) + printf("%s\n", config->bandwidth); + + // Update the internal time counter + strftime(time_now_string, sizeof(time_now_string), "%Y-%m-%d %H:%M:%S", localtime(&time_now)); + + { + // Run timer hooks + struct param_timer p = { time_now }; + run_plugins(PLUGIN_TIMER, &p); + } + } + // Runs on every machine (master and slaves). if (next_cluster_ping <= TIME) { @@ -3481,6 +3600,7 @@ static void initdata(int optdebug, char *optconfig) config->debug = optdebug; config->num_tbfs = MAXTBFS; config->rl_rate = 28; // 28kbps + config->cluster_mcast_ttl = 1; config->cluster_master_min_adv = 1; config->ppp_restart_time = 3; config->ppp_max_configure = 10; @@ -3987,14 +4107,13 @@ int main(int argc, char *argv[]) // Start the timer routine off time(&time_now); strftime(time_now_string, sizeof(time_now_string), "%Y-%m-%d %H:%M:%S", localtime(&time_now)); - signal(SIGALRM, sigalrm_handler); - siginterrupt(SIGALRM, 0); initplugins(); initdata(optdebug, optconfig); init_cli(hostname); read_config_file(); + update_config(); init_tbf(config->num_tbfs); LOG(0, 0, 0, "L2TPNS version " VERSION "\n"); @@ -4070,8 +4189,6 @@ int main(int argc, char *argv[]) LOG(0, 0, 0, "Can't lock pages: %s\n", strerror(errno)); } - alarm(1); - // Drop privileges here if (config->target_uid > 0 && geteuid() == 0) setuid(config->target_uid); @@ -4093,53 +4210,11 @@ int main(int argc, char *argv[]) static void sighup_handler(int sig) { - if (log_stream) - { - if (log_stream != stderr) - fclose(log_stream); - - log_stream = NULL; - } - - read_config_file(); -} - -static void sigalrm_handler(int sig) -{ - // Log current traffic stats - - snprintf(config->bandwidth, sizeof(config->bandwidth), - "UDP-ETH:%1.0f/%1.0f ETH-UDP:%1.0f/%1.0f TOTAL:%0.1f IN:%u OUT:%u", - (udp_rx / 1024.0 / 1024.0 * 8), - (eth_tx / 1024.0 / 1024.0 * 8), - (eth_rx / 1024.0 / 1024.0 * 8), - (udp_tx / 1024.0 / 1024.0 * 8), - ((udp_tx + udp_rx + eth_tx + eth_rx) / 1024.0 / 1024.0 * 8), - udp_rx_pkt, eth_rx_pkt); - - udp_tx = udp_rx = 0; - udp_rx_pkt = eth_rx_pkt = 0; - eth_tx = eth_rx = 0; - - if (config->dump_speed) - printf("%s\n", config->bandwidth); - - // Update the internal time counter - time(&time_now); - strftime(time_now_string, sizeof(time_now_string), "%Y-%m-%d %H:%M:%S", localtime(&time_now)); - alarm(1); - - { - // Run timer hooks - struct param_timer p = { time_now }; - run_plugins(PLUGIN_TIMER, &p); - } - + main_reload++; } static void shutdown_handler(int sig) { - LOG(1, 0, 0, "Shutting down\n"); main_quit = (sig == SIGQUIT) ? QUIT_SHUTDOWN : QUIT_FAILOVER; } @@ -4154,7 +4229,7 @@ static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challen MD5_CTX ctx; *challenge_response = NULL; - if (!*config->l2tpsecret) + if (!*config->l2tp_secret) { LOG(0, 0, 0, "LNS requested CHAP authentication, but no l2tp secret is defined\n"); return; @@ -4166,7 +4241,7 @@ static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challen MD5_Init(&ctx); MD5_Update(&ctx, &id, 1); - MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret)); + MD5_Update(&ctx, config->l2tp_secret, strlen(config->l2tp_secret)); MD5_Update(&ctx, challenge, challenge_length); MD5_Final(*challenge_response, &ctx); @@ -4233,6 +4308,17 @@ static void update_config() setbuf(log_stream, NULL); } +#define L2TP_HDRS (20+8+6+4) // L2TP data encaptulation: ip + udp + l2tp (data) + ppp (inc hdlc) +#define TCP_HDRS (20+20) // TCP encapsulation: ip + tcp + + if (config->l2tp_mtu <= 0) config->l2tp_mtu = PPPMTU; + else if (config->l2tp_mtu < MINMTU) config->l2tp_mtu = MINMTU; + else if (config->l2tp_mtu > MAXMTU) config->l2tp_mtu = MAXMTU; + + // reset MRU/MSS globals + MRU = config->l2tp_mtu - L2TP_HDRS; + MSS = MRU - TCP_HDRS; + // Update radius config->numradiusservers = 0; for (i = 0; i < MAXRADSERVER; i++) @@ -4378,8 +4464,6 @@ static void update_config() LOG(0, 0, 0, "Can't write to PID file %s: %s\n", config->pid_file, strerror(errno)); } } - - config->reload_config = 0; } static void read_config_file() @@ -4397,10 +4481,9 @@ static void read_config_file() cli_do_file(f); LOG(3, 0, 0, "Done reading config file\n"); fclose(f); - update_config(); } -int sessionsetup(tunnelidt t, sessionidt s) +int sessionsetup(sessionidt s, tunnelidt t) { // A session now exists, set it up in_addr_t ip; @@ -4479,7 +4562,7 @@ int sessionsetup(tunnelidt t, sessionidt s) } sess_local[s].lcp_authtype = 0; // RADIUS authentication complete - lcp_open(t, s); // transition to Network phase and send initial IPCP + lcp_open(s, t); // transition to Network phase and send initial IPCP // Run the plugin's against this new session. { @@ -5131,7 +5214,7 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec // Compute initial pad MD5_Init(&ctx); MD5_Update(&ctx, (unsigned char *) &m, 2); - MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret)); + MD5_Update(&ctx, config->l2tp_secret, strlen(config->l2tp_secret)); MD5_Update(&ctx, vector, vec_len); MD5_Final(digest, &ctx); @@ -5144,7 +5227,7 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec if (d >= sizeof(digest)) { MD5_Init(&ctx); - MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret)); + MD5_Update(&ctx, config->l2tp_secret, strlen(config->l2tp_secret)); MD5_Update(&ctx, last, sizeof(digest)); MD5_Final(digest, &ctx); @@ -5267,7 +5350,10 @@ int ip_filter(uint8_t *buf, int len, uint8_t filter) if (frag_offset) { - if (!rule->frag || rule->action == FILTER_ACTION_DENY) + // non-fragmented deny rules are skipped if containing L4 matches + if (!rule->frag && + (rule->src_ports.op || rule->dst_ports.op || rule->tcp_flag_op) && + rule->action == FILTER_ACTION_DENY) continue; } else