From 1db43fc51dd91e6944cfd1ee1a8dd8c69e2386be Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 23 Apr 2023 15:48:02 +0200 Subject: [PATCH] Separate out PPP processing So we can later call it on frames obtained from kernel ppp interface. Better seen with diff -w --- l2tpns.c | 326 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 167 insertions(+), 159 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index 4787d87..4cd1a28 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -282,6 +282,7 @@ static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int 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); +static void processppp(sessionidt s, uint8_t *buf, int len, uint8_t *p, int l, struct sockaddr_in *addr, uint16_t indexudpfd); // return internal time (10ths since process startup), set f if given // as a side-effect sets time_now, and time_changed @@ -4179,180 +4180,187 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu } } else - { // data - uint16_t proto; + // data + processppp(s, buf, len, p, l, addr, indexudpfd); +} - LOG_HEX(5, "Receive Tunnel Data", p, l); - if (l > 2 && p[0] == 0xFF && p[1] == 0x03) - { // HDLC address header, discard - p += 2; - l -= 2; - } - if (l < 2) - { - LOG(1, s, t, "Short ppp length %d\n", l); - STAT(tunnel_rx_errors); - return; - } - if (*p & 1) - { - proto = *p++; - l--; - } - else - { - proto = ntohs(*(uint16_t *) p); - p += 2; - l -= 2; - } +// +// process a ppp frame coming from tunnel +static void processppp(sessionidt s, uint8_t *buf, int len, uint8_t *p, int l, struct sockaddr_in *addr, uint16_t indexudpfd) +{ // data + int t = session[s].tunnel; + uint16_t proto; - if (session[s].forwardtosession) + LOG_HEX(5, "Receive Tunnel Data", p, l); + if (l > 2 && p[0] == 0xFF && p[1] == 0x03) + { // HDLC address header, discard + p += 2; + l -= 2; + } + if (l < 2) + { + LOG(1, s, t, "Short ppp length %d\n", l); + STAT(tunnel_rx_errors); + return; + } + if (*p & 1) + { + proto = *p++; + l--; + } + else + { + proto = ntohs(*(uint16_t *) p); + p += 2; + l -= 2; + } + + 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, indexudpfd); + 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)) { - 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, indexudpfd); - return; + // 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); } - else if (config->auth_tunnel_change_addr_src) + } + + if (s && !session[s].opened) // Is something wrong?? + { + if (!config->cluster_iam_master) { - if (tunnel[t].ip != ntohl(addr->sin_addr.s_addr) && - tunnel[t].port == ntohs(addr->sin_port)) - { - // The remotes BAS are a clustered l2tpns server and the source IP has changed - LOG(5, s, t, "The tunnel IP source (%s) has changed by new IP (%s)\n", - fmtaddr(htonl(tunnel[t].ip), 0), fmtaddr(addr->sin_addr.s_addr, 0)); - - tunnel[t].ip = ntohl(addr->sin_addr.s_addr); - } - } - - if (s && !session[s].opened) // Is something wrong?? - { - if (!config->cluster_iam_master) - { - // Pass it off to the master to deal with.. - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); - return; - } - - LOG(1, s, t, "UDP packet contains session which is not opened. Dropping packet.\n"); - STAT(tunnel_rx_errors); + // Pass it off to the master to deal with.. + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } - 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, indexudpfd); return; } - processpap(s, t, p, l); - } - else if (proto == PPPCHAP) - { - session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } - processchap(s, t, p, l); - } - else if (proto == PPPLCP) - { - session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } - processlcp(s, t, p, l); - } - else if (proto == PPPIPCP) - { - session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } - processipcp(s, t, p, l); - } - else if (proto == PPPIPV6CP && config->ipv6_prefix.s6_addr[0]) - { - session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } - processipv6cp(s, t, p, l); - } - else if (proto == PPPCCP) - { - session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } - processccp(s, t, p, l); - } - else if (proto == PPPIP) - { - if (session[s].die) - { - LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s); - return; // closing session, PPP not processed - } + LOG(1, s, t, "UDP packet contains session which is not opened. Dropping packet.\n"); + STAT(tunnel_rx_errors); + return; + } - session[s].last_packet = session[s].last_data = time_now; - if (session[s].walled_garden && !config->cluster_iam_master) + 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, indexudpfd); return; } + processpap(s, t, p, l); + } + else if (proto == PPPCHAP) + { + session[s].last_packet = time_now; + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } + processchap(s, t, p, l); + } + else if (proto == PPPLCP) + { + session[s].last_packet = time_now; + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } + processlcp(s, t, p, l); + } + else if (proto == PPPIPCP) + { + session[s].last_packet = time_now; + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } + processipcp(s, t, p, l); + } + else if (proto == PPPIPV6CP && config->ipv6_prefix.s6_addr[0]) + { + session[s].last_packet = time_now; + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } + processipv6cp(s, t, p, l); + } + else if (proto == PPPCCP) + { + session[s].last_packet = time_now; + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } + processccp(s, t, p, l); + } + else if (proto == PPPIP) + { + if (session[s].die) + { + LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s); + return; // closing session, PPP not processed + } + + session[s].last_packet = session[s].last_data = time_now; + if (session[s].walled_garden && !config->cluster_iam_master) + { + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); + return; + } + + processipin(s, t, p, l); + } + else if (proto == PPPMP) + { + if (session[s].die) + { + LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s); + return; // closing session, PPP not processed + } + + session[s].last_packet = session[s].last_data = time_now; + if (!config->cluster_iam_master) + { + // The fragments reconstruction is managed by the Master. + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); + return; + } + + processmpin(s, t, p, l); + } + else if (proto == PPPIPV6 && config->ipv6_prefix.s6_addr[0]) + { + if (session[s].die) + { + LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s); + return; // closing session, PPP not processed + } + + session[s].last_packet = session[s].last_data = time_now; + if (session[s].walled_garden && !config->cluster_iam_master) + { + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); + return; + } + + if (!config->cluster_iam_master) + { + // Check if DhcpV6, IP dst: FF02::1:2, Src Port 0x0222 (546), Dst Port 0x0223 (547) + if (*(p + 6) == 17 && *(p + 24) == 0xFF && *(p + 25) == 2 && + *(uint32_t *)(p + 26) == 0 && *(uint32_t *)(p + 30) == 0 && + *(uint16_t *)(p + 34) == 0 && *(p + 36) == 0 && *(p + 37) == 1 && *(p + 38) == 0 && *(p + 39) == 2 && + *(p + 40) == 2 && *(p + 41) == 0x22 && *(p + 42) == 2 && *(p + 43) == 0x23) { + // DHCPV6 must be managed by the Master. master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } - - processipin(s, t, p, l); } - else if (proto == PPPMP) - { - if (session[s].die) - { - LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s); - return; // closing session, PPP not processed - } - session[s].last_packet = session[s].last_data = time_now; - if (!config->cluster_iam_master) - { - // The fragments reconstruction is managed by the Master. - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); - return; - } - - processmpin(s, t, p, l); - } - else if (proto == PPPIPV6 && config->ipv6_prefix.s6_addr[0]) - { - if (session[s].die) - { - LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s); - return; // closing session, PPP not processed - } - - session[s].last_packet = session[s].last_data = time_now; - if (session[s].walled_garden && !config->cluster_iam_master) - { - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); - return; - } - - if (!config->cluster_iam_master) - { - // Check if DhcpV6, IP dst: FF02::1:2, Src Port 0x0222 (546), Dst Port 0x0223 (547) - if (*(p + 6) == 17 && *(p + 24) == 0xFF && *(p + 25) == 2 && - *(uint32_t *)(p + 26) == 0 && *(uint32_t *)(p + 30) == 0 && - *(uint16_t *)(p + 34) == 0 && *(p + 36) == 0 && *(p + 37) == 1 && *(p + 38) == 0 && *(p + 39) == 2 && - *(p + 40) == 2 && *(p + 41) == 0x22 && *(p + 42) == 2 && *(p + 43) == 0x23) - { - // DHCPV6 must be managed by the Master. - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); - return; - } - } - - processipv6in(s, t, p, l); - } - else if (session[s].ppp.lcp == Opened) - { - session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } - protoreject(s, t, p, l, proto); - } - else - { - LOG(2, s, t, "Unknown PPP protocol 0x%04X received in LCP %s state\n", - proto, ppp_state(session[s].ppp.lcp)); - } + processipv6in(s, t, p, l); + } + else if (session[s].ppp.lcp == Opened) + { + session[s].last_packet = time_now; + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } + protoreject(s, t, p, l, proto); + } + else + { + LOG(2, s, t, "Unknown PPP protocol 0x%04X received in LCP %s state\n", + proto, ppp_state(session[s].ppp.lcp)); } }