From 6f04a5c390b7a47a30c4ccc96b3dfe9dddfcd1e6 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 8 Mar 2025 23:13:23 +0100 Subject: [PATCH] l2tp: Add Last Sent/Received LCP ConfReq in ICCN To support proxy LCP negotiation. --- l2tpns.c | 14 ++++++++++++++ l2tpns.h | 10 ++++++++++ ppp.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/l2tpns.c b/l2tpns.c index 941e81e..a001823 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -4841,6 +4841,8 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu session[s].ppp.phase = Establish; session[s].ppp.lcp = Starting; + sess_local[s].lcp_last_received_confreq_n = 0; + sess_local[s].lcp_last_sent_confreq_n = 0; STAT(session_created); break; @@ -4867,6 +4869,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu LOG(3, s, t, "Received ICRP\n"); if (session[s].forwardtosession) { + sessionidt fs = session[s].forwardtosession; controlt *c = controlnew(12); // ICCN session[s].opened = time_now; @@ -4879,6 +4882,17 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu control32(c, 19, 1, 1); // Framing Type control32(c, 24, 10000000, 1); // Tx Connect Speed + + if (sess_local[fs].lcp_last_sent_confreq_n) + // Last Sent LCP ConfReq + controlb(c, 27, sess_local[fs].lcp_last_sent_confreq, + sess_local[fs].lcp_last_sent_confreq_n, 0); + + if (sess_local[fs].lcp_last_received_confreq_n) + // Last Received LCP ConfReq + controlb(c, 28, sess_local[fs].lcp_last_received_confreq, + sess_local[fs].lcp_last_received_confreq_n, 0); + controladd(c, asession, t); // send the message LOG(3, s, t, "Sending ICCN\n"); } diff --git a/l2tpns.h b/l2tpns.h index 8a54fc5..0ca23be 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -393,6 +393,9 @@ fragmentationt; #define AUTHPAP 1 // allow PAP #define AUTHCHAP 2 // allow CHAP +#define MAXLCPLENGTH 128 // Arbitrary, not too large to avoid consuming too + // much memory, but not too short for actual uses + typedef struct { // packet counters @@ -416,6 +419,13 @@ typedef struct // authentication to use int lcp_authtype; + // Last Received LCP ConfReq and its length + uint8_t lcp_last_received_confreq[MAXLCPLENGTH]; + int lcp_last_received_confreq_n; + // Last Sent LCP ConfReq and its length + uint8_t lcp_last_sent_confreq[MAXLCPLENGTH]; + int lcp_last_sent_confreq_n; + // our MRU uint16_t ppp_mru; diff --git a/ppp.c b/ppp.c index 57b4340..c40b858 100644 --- a/ppp.c +++ b/ppp.c @@ -425,6 +425,8 @@ void lcp_open(sessionidt s, tunnelidt t) void lcp_restart(sessionidt s) { session[s].ppp.phase = Establish; + sess_local[s].lcp_last_received_confreq_n = 0; + sess_local[s].lcp_last_sent_confreq_n = 0; // This-Layer-Down change_state(s, ipcp, Initial); change_state(s, ipv6cp, Initial); @@ -851,6 +853,18 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) LOG(3, s, t, "LCP: send %s\n", ppp_code(*response)); if (config->debug > 3) dumplcp(response, l); + if (*response == ConfigAck && l - 4 <= sizeof(sess_local[s].lcp_last_received_confreq)) + { + memcpy(sess_local[s].lcp_last_received_confreq, p + 4, l - 4); + sess_local[s].lcp_last_received_confreq_n = l - 4; + } + else + { + LOG(3, s, t, "their LCP ConfigReq is too long for proxying\n"); + dumplcp(p, l); + sess_local[s].lcp_last_received_confreq_n = 0; + } + tunnelsend(b, l + (response - b), t); } else if (*p == ConfigNak || *p == ConfigRej) @@ -859,6 +873,10 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) uint8_t *o = (p + 4); int authtype = -1; + // They didn't like our config + + sess_local[s].lcp_last_sent_confreq_n = 0; + while (x > 2) { int type = o[0]; @@ -2800,6 +2818,18 @@ void sendlcp(sessionidt s, tunnelidt t) LOG_HEX(5, "PPPLCP", q, l - q); if (config->debug > 3) dumplcp(q, l - q); + if (l - (q + 4) <= sizeof(sess_local[s].lcp_last_sent_confreq)) + { + memcpy(sess_local[s].lcp_last_sent_confreq, q + 4, l - (q + 4)); + sess_local[s].lcp_last_sent_confreq_n = l - (q + 4); + } + else + { + LOG(3, s, t, "our LCP ConfigReq is too long for proxying\n"); + dumplcp(q, l - q); + sess_local[s].lcp_last_sent_confreq_n = 0; + } + tunnelsend(b, (l - b), t); restart_timer(s, lcp); }