X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/17b2ce31a692b0a82ab22e7d2aad1691eba0188c..5a24a99c3836f1447e42617e7d67cd750c64109d:/l2tpns.c?ds=inline diff --git a/l2tpns.c b/l2tpns.c index 67fc844..39f72d7 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.114 2005/07/04 05:49:46 bodea Exp $"; +char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.150 2005/11/17 07:35:35 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,11 @@ 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), CONFIG("primary_dns", default_dns1, IPv4), CONFIG("secondary_dns", default_dns2, IPv4), CONFIG("primary_radius", radiusserver[0], IPv4), @@ -132,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), @@ -151,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", }; @@ -179,10 +191,9 @@ 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(char *challenge, uint8_t id, uint16_t challenge_length, char **challenge_response); +static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challenge_length, uint8_t **challenge_response); static void update_config(void); static void read_config_file(void); static void initplugins(void); @@ -201,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; } @@ -258,10 +275,10 @@ void _log(int level, sessionidt s, tunnelidt t, const char *format, ...) va_end(ap); } -void _log_hex(int level, const char *title, const char *data, int maxsize) +void _log_hex(int level, const char *title, const uint8_t *data, int maxsize) { int i, j; - const uint8_t *d = (const uint8_t *) data; + const uint8_t *d = data; if (config->debug < level) return; @@ -537,6 +554,13 @@ static void inittun(void) LOG(0, 0, 0, "Error setting tun queue length: %s\n", strerror(errno)); exit(1); } + /* set MTU to modem MRU + 4 (tun header) */ + ifr.ifr_mtu = MRU + 4; + if (ioctl(ifrfd, SIOCSIFMTU, (void *) &ifr) < 0) + { + LOG(0, 0, 0, "Error setting tun MTU: %s\n", strerror(errno)); + exit(1); + } ifr.ifr_flags = IFF_UP; if (ioctl(ifrfd, SIOCSIFFLAGS, (void *) &ifr) < 0) { @@ -551,7 +575,7 @@ static void inittun(void) tunidx = ifr.ifr_ifindex; // Only setup IPv6 on the tun device if we have a configured prefix - if (config->ipv6_prefix.s6_addr[0] > 0) { + if (config->ipv6_prefix.s6_addr[0]) { ifr6fd = socket(PF_INET6, SOCK_DGRAM, 0); // Link local address is FE80::1 @@ -702,8 +726,11 @@ sessionidt sessionbyipv6(struct in6_addr ip) CSTAT(sessionbyipv6); if (!memcmp(&config->ipv6_prefix, &ip, 8) || - (ip.s6_addr[0] == 0xFE && ip.s6_addr[1] == 0x80 && - (ip.s6_addr16[1] == ip.s6_addr16[2] == ip.s6_addr16[3] == 0))) { + (ip.s6_addr[0] == 0xFE && + ip.s6_addr[1] == 0x80 && + ip.s6_addr16[1] == 0 && + ip.s6_addr16[2] == 0 && + ip.s6_addr16[3] == 0)) { s = lookup_ipmap(*(in_addr_t *) &ip.s6_addr[8]); } else { s = lookup_ipv6map(ip); @@ -942,7 +969,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); @@ -971,16 +998,71 @@ 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 + (sum >> 16)); +} + // process outgoing (to tunnel) IP // -static void processipout(uint8_t * buf, int len) +static void processipout(uint8_t *buf, int len) { sessionidt s; sessiont *sp; tunnelidt t; in_addr_t ip; - char *data = buf; // Keep a copy of the originals. + uint8_t *data = buf; // Keep a copy of the originals. int size = len; uint8_t b[MAXETHER + 20]; @@ -1078,6 +1160,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? @@ -1087,7 +1177,8 @@ static void processipout(uint8_t * buf, int len) master_throttle_packet(sp->tbf_out, data, size); return; } - else if (sp->walled_garden && !config->cluster_iam_master) + + if (sp->walled_garden && !config->cluster_iam_master) { // We are walled-gardening this master_garden_packet(s, data, size); @@ -1098,7 +1189,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... } @@ -1126,7 +1217,7 @@ static void processipv6out(uint8_t * buf, int len) in_addr_t ip; struct in6_addr ip6; - char *data = buf; // Keep a copy of the originals. + uint8_t *data = buf; // Keep a copy of the originals. int size = len; uint8_t b[MAXETHER + 20]; @@ -1209,7 +1300,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... } @@ -1261,7 +1352,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... } @@ -1313,7 +1404,7 @@ static void controls(controlt * c, uint16_t avp, char *val, uint8_t m) } // add a binary AVP -static void controlb(controlt * c, uint16_t avp, char *val, unsigned int len, uint8_t m) +static void controlb(controlt * c, uint16_t avp, uint8_t *val, unsigned int len, uint8_t m) { uint16_t l = ((m ? 0x8000 : 0) + len + 6); *(uint16_t *) (c->buf + c->length + 0) = htons(l); @@ -1360,7 +1451,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 @@ -1493,10 +1584,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error) if (session[s].ip && !walled_garden && !session[s].die) { // RADIUS Stop message - uint16_t r = sess_local[s].radius; - if (!r) - r = radiusnew(s); - + uint16_t r = radiusnew(s); if (r) { // stop, if not already trying @@ -1534,7 +1622,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error) free_ip_address(s); // unroute IPv6, if setup - if (session[s].flags & SF_IPV6_ROUTED) + if (session[s].ppp.ipv6cp == Opened && session[s].ipv6prefixlen) route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0); } @@ -1546,7 +1634,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error) controlt *c = controlnew(14); // sending CDN if (error) { - char buf[4]; + uint8_t buf[4]; *(uint16_t *) buf = htons(result); *(uint16_t *) (buf+2) = htons(error); controlb(c, 1, buf, 4, 1); @@ -1555,7 +1643,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) @@ -1565,78 +1653,70 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error) if (session[s].filter_in) ip_filters[session[s].filter_in - 1].used--; if (session[s].filter_out) ip_filters[session[s].filter_out - 1].used--; + // clear PPP state + memset(&session[s].ppp, 0, sizeof(session[s].ppp)); + sess_local[s].lcp.restart = 0; + sess_local[s].ipcp.restart = 0; + sess_local[s].ipv6cp.restart = 0; + sess_local[s].ccp.restart = 0; + cluster_send_session(s); } -void sendipcp(tunnelidt t, sessionidt s) +void sendipcp(sessionidt s, tunnelidt t) { - uint8_t buf[MAXCONTROL]; - uint16_t r = sess_local[s].radius; + uint8_t buf[MAXETHER]; uint8_t *q; CSTAT(sendipcp); + LOG(3, s, t, "IPCP: send ConfigReq\n"); - if (!r) - r = radiusnew(s); - - if (!r) - { - sessionshutdown(s, "No free RADIUS sessions for IPCP", 3, 0); - return; - } - - if (radius[r].state != RADIUSIPCP) + if (!session[s].unique_id) { - radius[r].state = RADIUSIPCP; - radius[r].try = 0; + if (!++last_id) ++last_id; // skip zero + session[s].unique_id = last_id; } - radius[r].retry = backoff(radius[r].try++); - if (radius[r].try > 10) - { - radiusclear(r, s); // Clear radius session. - sessionshutdown(s, "No reply to IPCP.", 3, 0); - return; - } - - 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; - q[1] = r >> RADIUS_SHIFT; // ID, dont care, we only send one type of request - *(uint16_t *) (q + 2) = htons(10); - q[4] = 3; - q[5] = 6; + q[1] = session[s].unique_id & 0xf; // ID, dont care, we only send one type of request + *(uint16_t *) (q + 2) = htons(10); // packet length + 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 : my_address; // send my IP tunnelsend(buf, 10 + (q - buf), t); // send it - session[s].flags &= ~SF_IPCP_ACKED; // Clear flag. - - // If we have an IPv6 prefix length configured, assume we should - // try to negotiate an IPv6 session as well. Unless we've had a - // (N)ACK for IPV6CP. - if (config->ipv6_prefix.s6_addr[0] > 0 && - !(session[s].flags & SF_IPV6CP_ACKED) && - !(session[s].flags & SF_IPV6_NACKED)) - { - q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPV6CP); - if (!q) return; - - *q = ConfigReq; - q[1] = r >> RADIUS_SHIFT; // ID, don't care, we - // only send one type - // of request - *(uint16_t *) (q + 2) = htons(14); - q[4] = 1; - q[5] = 10; - *(uint32_t *) (q + 6) = 0; // We'll be prefix::1 - *(uint32_t *) (q + 10) = 0; - q[13] = 1; - - tunnelsend(buf, 14 + (q - buf), t); // send it - } + restart_timer(s, ipcp); +} + +void sendipv6cp(sessionidt s, tunnelidt t) +{ + uint8_t buf[MAXETHER]; + uint8_t *q; + + CSTAT(sendipv6cp); + LOG(3, s, t, "IPV6CP: send ConfigReq\n"); + + q = makeppp(buf, sizeof(buf), 0, 0, s, t, PPPIPV6CP); + if (!q) return; + + *q = ConfigReq; + q[1] = session[s].unique_id & 0xf; // ID, don't care, we + // only send one type + // of request + *(uint16_t *) (q + 2) = htons(14); + q[4] = 1; // interface identifier option + q[5] = 10; // option length + *(uint32_t *) (q + 6) = 0; // We'll be prefix::1 + *(uint32_t *) (q + 10) = 0; + q[13] = 1; + + tunnelsend(buf, 14 + (q - buf), t); // send it + restart_timer(s, ipv6cp); } static void sessionclear(sessionidt s) @@ -1742,7 +1822,7 @@ static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, cha controlt *c = controlnew(4); // sending StopCCN if (error) { - char buf[64]; + uint8_t buf[64]; int l = 4; *(uint16_t *) buf = htons(result); *(uint16_t *) (buf+2) = htons(error); @@ -1762,14 +1842,14 @@ 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 } } // 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) { - char *chapresponse = NULL; + uint8_t *chapresponse = NULL; uint16_t l = len, t = 0, s = 0, ns = 0, nr = 0; uint8_t *p = buf + 2; @@ -1833,12 +1913,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 @@ -1921,9 +2005,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 @@ -2013,7 +2094,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; @@ -2061,7 +2142,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) n = orig_len; } - LOG(4, s, t, " AVP %d (%s) len %d%s%s\n", mtype, avp_name(mtype), n, + LOG(4, s, t, " AVP %d (%s) len %d%s%s\n", mtype, l2tp_avp_name(mtype), n, flags & 0x40 ? ", hidden" : "", flags & 0x80 ? ", mandatory" : ""); switch (mtype) @@ -2069,7 +2150,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 = %d (%s)\n", *b, l2tp_message_type(message)); + LOG(4, s, t, " Message type = %d (%s)\n", *b, l2tp_code(message)); break; case 1: // result code { @@ -2077,18 +2158,18 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) const char* resdesc = "(unknown)"; if (message == 4) { /* StopCCN */ - resdesc = stopccn_result_code(rescode); + resdesc = l2tp_stopccn_result_code(rescode); } else if (message == 14) { /* CDN */ - resdesc = cdn_result_code(rescode); + resdesc = l2tp_cdn_result_code(rescode); } LOG(4, s, t, " Result Code %d: %s\n", rescode, resdesc); if (n >= 4) { uint16_t errcode = ntohs(*(uint16_t *)(b + 2)); - LOG(4, s, t, " Error Code %d: %s\n", errcode, error_code(errcode)); + LOG(4, s, t, " Error Code %d: %s\n", errcode, l2tp_error_code(errcode)); } if (n > 4) LOG(4, s, t, " Error String: %.*s\n", n-4, b+4); @@ -2222,12 +2303,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) case 29: // Proxy Authentication Type { uint16_t atype = ntohs(*(uint16_t *)b); - LOG(4, s, t, " Proxy Auth Type %d (%s)\n", atype, auth_type(atype)); - if (atype == 2) - authtype = AUTHCHAP; - else if (atype == 3) - authtype = AUTHPAP; - + LOG(4, s, t, " Proxy Auth Type %d (%s)\n", atype, ppp_auth_type(atype)); break; } case 30: // Proxy Authentication Name @@ -2242,16 +2318,12 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) case 31: // Proxy Authentication Challenge { LOG(4, s, t, " Proxy Auth Challenge\n"); - if (sess_local[s].radius) - memcpy(radius[sess_local[s].radius].auth, b, 16); break; } case 32: // Proxy Authentication ID { uint16_t authid = ntohs(*(uint16_t *)(b)); LOG(4, s, t, " Proxy Auth ID (%d)\n", authid); - if (sess_local[s].radius) - radius[sess_local[s].radius].id = authid; break; } case 33: // Proxy Authentication Response @@ -2264,14 +2336,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]; } } @@ -2315,10 +2383,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 { @@ -2351,7 +2419,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) case 10: // ICRQ if (sessionfree && main_quit != QUIT_SHUTDOWN) { - uint16_t r; + controlt *c = controlnew(11); // ICRP s = sessionfree; sessionfree = session[s].next; @@ -2360,43 +2428,36 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) if (s > config->cluster_highest_sessionid) config->cluster_highest_sessionid = s; - // make a RADIUS session - if ((r = radiusnew(s))) - { - controlt *c = controlnew(11); // sending ICRP - session[s].opened = time_now; - session[s].tunnel = t; - session[s].far = asession; - 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 - - strncpy(radius[r].calling, calling, sizeof(radius[r].calling) - 1); - strncpy(session[s].called, called, sizeof(session[s].called) - 1); - strncpy(session[s].calling, calling, sizeof(session[s].calling) - 1); - STAT(session_created); - break; - } + session[s].opened = time_now; + session[s].tunnel = t; + session[s].far = asession; + 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, 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); - LOG(1, s, t, "No free RADIUS sessions for ICRQ\n"); - sessionclear(s); - } - else - { - STAT(session_overflow); - LOG(1, 0, t, "No free sessions\n"); + session[s].ppp.phase = Establish; + session[s].ppp.lcp = Starting; + + STAT(session_created); + break; } { controlt *c = controlnew(14); // CDN - if (main_quit == QUIT_SHUTDOWN) - control16(c, 1, 2, 7); // try another - else + if (!sessionfree) + { + STAT(session_overflow); + LOG(1, 0, t, "No free sessions\n"); control16(c, 1, 4, 0); // temporary lack of resources + } + 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 @@ -2405,16 +2466,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_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); @@ -2440,7 +2502,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) @@ -2456,12 +2518,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; } @@ -2481,50 +2543,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]) { - if (config->ipv6_prefix.s6_addr[0] > 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); - } - else - { - LOG(1, s, t, "IPv6 not configured; ignoring IPv6CP\n"); - } + 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(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) { @@ -2539,15 +2594,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] > 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); @@ -2561,12 +2611,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)); } } } @@ -2592,7 +2668,7 @@ static void processtun(uint8_t * buf, int len) if (*(uint16_t *) (buf + 2) == htons(PKTIP)) // IPv4 processipout(buf, len); else if (*(uint16_t *) (buf + 2) == htons(PKTIPV6) // IPV6 - && config->ipv6_prefix.s6_addr[0] > 0) + && config->ipv6_prefix.s6_addr[0]) processipv6out(buf, len); // Else discard. @@ -2677,10 +2753,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++; } @@ -2734,13 +2810,115 @@ static void regular_cleanups(double period) continue; } - if (session[s].ip && !(session[s].flags & SF_IPCP_ACKED) - && !(sess_local[s].radius && radius[sess_local[s].radius].state == RADIUSIPCP)) + // PPP timeouts + if (sess_local[s].lcp.restart <= time_now) { - // IPCP has not completed yet. Resend - LOG(3, s, session[s].tunnel, "No ACK for initial IPCP ConfigReq... resending\n"); - sendipcp(session[s].tunnel, s); - s_actions++; + int next_state = session[s].ppp.lcp; + switch (session[s].ppp.lcp) + { + case RequestSent: + case AckReceived: + next_state = RequestSent; + + case AckSent: + if (sess_local[s].lcp.conf_sent < config->ppp_max_configure) + { + LOG(3, s, session[s].tunnel, "No ACK for LCP ConfigReq... resending\n"); + sendlcp(s, session[s].tunnel); + change_state(s, lcp, next_state); + } + else + { + sessionshutdown(s, "No response to LCP ConfigReq.", 3, 0); + STAT(session_timeout); + } + + s_actions++; + } + + if (session[s].die) + continue; + } + + if (sess_local[s].ipcp.restart <= time_now) + { + int next_state = session[s].ppp.ipcp; + switch (session[s].ppp.ipcp) + { + case RequestSent: + case AckReceived: + next_state = RequestSent; + + case AckSent: + if (sess_local[s].ipcp.conf_sent < config->ppp_max_configure) + { + LOG(3, s, session[s].tunnel, "No ACK for IPCP ConfigReq... resending\n"); + sendipcp(s, session[s].tunnel); + change_state(s, ipcp, next_state); + } + else + { + sessionshutdown(s, "No response to IPCP ConfigReq.", 3, 0); + STAT(session_timeout); + } + + s_actions++; + } + + if (session[s].die) + continue; + } + + if (sess_local[s].ipv6cp.restart <= time_now) + { + int next_state = session[s].ppp.ipv6cp; + switch (session[s].ppp.ipv6cp) + { + case RequestSent: + case AckReceived: + next_state = RequestSent; + + case AckSent: + if (sess_local[s].ipv6cp.conf_sent < config->ppp_max_configure) + { + LOG(3, s, session[s].tunnel, "No ACK for IPV6CP ConfigReq... resending\n"); + sendipv6cp(s, session[s].tunnel); + change_state(s, ipv6cp, next_state); + } + else + { + LOG(3, s, session[s].tunnel, "No ACK for IPV6CP ConfigReq\n"); + change_state(s, ipv6cp, Stopped); + } + + s_actions++; + } + } + + if (sess_local[s].ccp.restart <= time_now) + { + int next_state = session[s].ppp.ccp; + switch (session[s].ppp.ccp) + { + case RequestSent: + case AckReceived: + next_state = RequestSent; + + case AckSent: + if (sess_local[s].ccp.conf_sent < config->ppp_max_configure) + { + LOG(3, s, session[s].tunnel, "No ACK for CCP ConfigReq... resending\n"); + sendccp(s, session[s].tunnel); + change_state(s, ccp, next_state); + } + else + { + LOG(3, s, session[s].tunnel, "No ACK for CCP ConfigReq\n"); + change_state(s, ccp, Stopped); + } + + s_actions++; + } } // Drop sessions who have not responded within IDLE_TIMEOUT seconds @@ -2753,11 +2931,12 @@ static void regular_cleanups(double period) } // No data in ECHO_TIMEOUT seconds, send LCP ECHO - if (session[s].user[0] && (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; @@ -2768,6 +2947,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++; } @@ -3057,9 +3237,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(); } @@ -3084,7 +3272,8 @@ static void mainloop(void) if (n) { struct sockaddr_in addr; - int alen, c, s; + socklen_t alen; + int c, s; int udp_ready = 0; int tun_ready = 0; int cluster_ready = 0; @@ -3222,6 +3411,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) { @@ -3390,7 +3608,11 @@ 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; + config->ppp_max_failure = 5; strcpy(config->random_device, RANDOMDEVICE); log_stream = stderr; @@ -3758,7 +3980,7 @@ static void initippool() LOG(1, 0, 0, "IP address pool is %d addresses\n", ip_pool_size - 1); } -void snoop_send_packet(char *packet, uint16_t size, in_addr_t destination, uint16_t port) +void snoop_send_packet(uint8_t *packet, uint16_t size, in_addr_t destination, uint16_t port) { struct sockaddr_in snoop_addr = {0}; if (!destination || !port || snoopfd <= 0 || size <= 0 || !packet) @@ -3893,14 +4115,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"); @@ -3976,8 +4197,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); @@ -3999,53 +4218,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; } @@ -4055,12 +4232,12 @@ static void sigchild_handler(int sig) ; } -static void build_chap_response(char *challenge, uint8_t id, uint16_t challenge_length, char **challenge_response) +static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challenge_length, uint8_t **challenge_response) { 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; @@ -4068,13 +4245,13 @@ static void build_chap_response(char *challenge, uint8_t id, uint16_t challenge_ LOG(4, 0, 0, " Building challenge response for CHAP request\n"); - *challenge_response = (char *)calloc(17, 1); + *challenge_response = calloc(17, 1); - MD5Init(&ctx); - MD5Update(&ctx, &id, 1); - MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret)); - MD5Update(&ctx, challenge, challenge_length); - MD5Final(*challenge_response, &ctx); + MD5_Init(&ctx); + MD5_Update(&ctx, &id, 1); + MD5_Update(&ctx, config->l2tp_secret, strlen(config->l2tp_secret)); + MD5_Update(&ctx, challenge, challenge_length); + MD5_Final(*challenge_response, &ctx); return; } @@ -4139,6 +4316,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++) @@ -4284,8 +4472,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() @@ -4303,10 +4489,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; @@ -4384,13 +4569,8 @@ int sessionsetup(tunnelidt t, sessionidt s) cache_ipmap(session[s].ip, s); } - if (!session[s].unique_id) - { - // did this session just finish radius? - LOG(3, s, t, "Sending initial IPCP to client\n"); - sendipcp(t, s); - session[s].unique_id = ++last_id; - } + sess_local[s].lcp_authtype = 0; // RADIUS authentication complete + lcp_open(s, t); // transition to Network phase and send initial IPCP // Run the plugin's against this new session. { @@ -4499,7 +4679,7 @@ int load_session(sessionidt s, sessiont *new) } // check v6 routing - if (new->flags & SF_IPV6_ROUTED && !(session[s].flags & SF_IPV6_ROUTED)) + if (new->ipv6prefixlen && new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened) route6set(s, new->ipv6route, new->ipv6prefixlen, 1); // check filters @@ -4716,7 +4896,7 @@ static void plugins_done() run_plugin_done(p); } -static void processcontrol(uint8_t * buf, int len, struct sockaddr_in *addr, int alen) +static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen) { struct nsctl request; struct nsctl response; @@ -5040,11 +5220,11 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec uint16_t m = htons(type); // Compute initial pad - MD5Init(&ctx); - MD5Update(&ctx, (unsigned char *) &m, 2); - MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret)); - MD5Update(&ctx, vector, vec_len); - MD5Final(digest, &ctx); + MD5_Init(&ctx); + MD5_Update(&ctx, (unsigned char *) &m, 2); + MD5_Update(&ctx, config->l2tp_secret, strlen(config->l2tp_secret)); + MD5_Update(&ctx, vector, vec_len); + MD5_Final(digest, &ctx); // pointer to last decoded 16 octets last = value; @@ -5054,10 +5234,10 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec // calculate a new pad based on the last decoded block if (d >= sizeof(digest)) { - MD5Init(&ctx); - MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret)); - MD5Update(&ctx, last, sizeof(digest)); - MD5Final(digest, &ctx); + MD5_Init(&ctx); + MD5_Update(&ctx, config->l2tp_secret, strlen(config->l2tp_secret)); + MD5_Update(&ctx, last, sizeof(digest)); + MD5_Final(digest, &ctx); d = 0; last = value; @@ -5178,7 +5358,9 @@ int ip_filter(uint8_t *buf, int len, uint8_t filter) if (frag_offset) { - if (!rule->frag || rule->action == FILTER_ACTION_DENY) + // layer 4 deny rules are skipped + if (rule->action == FILTER_ACTION_DENY && + (rule->src_ports.op || rule->dst_ports.op || rule->tcp_flag_op)) continue; } else