From 817ce3574889f3d1745e0e1ae9ef18d9a684fbad Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 8 Mar 2025 20:05:56 -0500 Subject: [PATCH] ppp: Move LCP received configuration parsing to a separate function So it can be reused for proxy LCP negotiation. --- ppp.c | 320 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 164 insertions(+), 156 deletions(-) diff --git a/ppp.c b/ppp.c index 5687524..b5bc5dd 100644 --- a/ppp.c +++ b/ppp.c @@ -556,6 +556,169 @@ static void ppp_code_rej(sessionidt s, tunnelidt t, uint16_t proto, tunnelsend(buf, l + (q - buf), t); } +// Process received LCP options from o from packet p. +// Set changed to 1 if we changed configuration that should be sent to cluster slaves, fill response on nak or rej +static void processreceivedlcpconfreq(sessionidt s, tunnelidt t, uint8_t *p, uint8_t *o, uint16_t x, int *changed, uint8_t **response) +{ + static uint8_t asyncmap[4] = { 0, 0, 0, 0 }; // all zero + static uint8_t authproto[5]; + uint8_t b[MAXETHER]; + uint8_t *q = NULL; + + while (x > 2) + { + int type = o[0]; + int length = o[1]; + + if (length == 0 || length == 1 || type == 0 || x < length) break; + switch (type) + { + case 1: // Maximum-Receive-Unit + { + uint16_t mru = ntohs(*(uint16_t *)(o + 2)); + if (mru >= MINMTU) + { + session[s].mru = mru; + (*changed)++; + break; + } + + LOG(3, s, t, " Remote requesting MRU of %u. Rejecting.\n", mru); + mru = htons(MRU); + q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, response, q, p, o, (uint8_t *) &mru, sizeof(mru)); + } + break; + + case 2: // Async-Control-Character-Map + if (!ntohl(*(uint32_t *)(o + 2))) // all bits zero is OK + break; + + LOG(3, s, t, " Remote requesting asyncmap. Rejecting.\n"); + q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, response, q, p, o, asyncmap, sizeof(asyncmap)); + break; + + case 3: // Authentication-Protocol + { + int proto = ntohs(*(uint16_t *)(o + 2)); + char proto_name[] = "0x0000"; + int alen; + + if (proto == PPPPAP) + { + if (config->radius_authtypes & AUTHPAP) + { + sess_local[s].lcp_authtype = AUTHPAP; + break; + } + + strcpy(proto_name, "PAP"); + } + else if (proto == PPPCHAP) + { + if (config->radius_authtypes & AUTHCHAP + && *(o + 4) == 5) // MD5 + { + sess_local[s].lcp_authtype = AUTHCHAP; + break; + } + + strcpy(proto_name, "CHAP"); + } + else + sprintf(proto_name, "%#4.4x", proto); + + LOG(3, s, t, " Remote requesting %s authentication. Rejecting.\n", proto_name); + + alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authprefer); + if (alen < 2) break; // paranoia + + q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, response, q, p, o, authproto + 2, alen - 2); + if (q && **response == ConfigNak && + config->radius_authtypes != config->radius_authprefer) + { + // alternate type + alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authtypes & ~config->radius_authprefer); + if (alen < 2) break; + q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, response, q, p, o, authproto + 2, alen - 2); + } + + break; + } + break; + + case 4: // Quality-Protocol + case 5: // Magic-Number + case 7: // Protocol-Field-Compression + case 8: // Address-And-Control-Field-Compression + break; + + case 17: // Multilink Max-Receive-Reconstructed-Unit + { + uint16_t mrru = ntohs(*(uint16_t *)(o + 2)); + session[s].mrru = mrru; + (*changed)++; + LOG(3, s, t, " Received PPP LCP option MRRU: %d\n",mrru); + } + break; + + case 18: // Multilink Short Sequence Number Header Format + { + session[s].mssf = 1; + (*changed)++; + LOG(3, s, t, " Received PPP LCP option MSSN format\n"); + } + break; + + case 19: // Multilink Endpoint Discriminator + { + uint8_t epdis_class = o[2]; + int addr; + + session[s].epdis.addr_class = epdis_class; + session[s].epdis.length = length - 3; + if (session[s].epdis.length > 20) + { + LOG(1, s, t, "Error: received EndDis Address Length more than 20: %d\n", session[s].epdis.length); + session[s].epdis.length = 20; + } + + for (addr = 0; addr < session[s].epdis.length; addr++) + session[s].epdis.address[addr] = o[3+addr]; + + (*changed)++; + + switch (epdis_class) + { + case LOCALADDR: + LOG(3, s, t, " Received PPP LCP option Multilink EndDis Local Address Class: %d\n",epdis_class); + break; + case IPADDR: + LOG(3, s, t, " Received PPP LCP option Multilink EndDis IP Address Class: %d\n",epdis_class); + break; + case IEEEMACADDR: + LOG(3, s, t, " Received PPP LCP option Multilink EndDis IEEE MAC Address Class: %d\n",epdis_class); + break; + case PPPMAGIC: + LOG(3, s, t, " Received PPP LCP option Multilink EndDis PPP Magic No Class: %d\n",epdis_class); + break; + case PSNDN: + LOG(3, s, t, " Received PPP LCP option Multilink EndDis PSND No Class: %d\n",epdis_class); + break; + default: + LOG(3, s, t, " Received PPP LCP option Multilink EndDis NULL Class %d\n",epdis_class); + } + } + break; + + default: // Reject any unknown options + LOG(3, s, t, " Rejecting unknown PPP LCP option %d\n", type); + q = ppp_conf_rej(s, b, sizeof(b), PPPLCP, response, q, p, o); + } + x -= length; + o += length; + } +} + // Process LCP messages void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) { @@ -648,165 +811,10 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) } else if (*p == ConfigReq) { - int x = l - 4; - uint8_t *o = (p + 4); uint8_t *response = 0; - static uint8_t asyncmap[4] = { 0, 0, 0, 0 }; // all zero - static uint8_t authproto[5]; int changed = 0; - while (x > 2) - { - int type = o[0]; - int length = o[1]; - - if (length == 0 || length == 1 || type == 0 || x < length) break; - switch (type) - { - case 1: // Maximum-Receive-Unit - { - uint16_t mru = ntohs(*(uint16_t *)(o + 2)); - if (mru >= MINMTU) - { - session[s].mru = mru; - changed++; - break; - } - - LOG(3, s, t, " Remote requesting MRU of %u. Rejecting.\n", mru); - mru = htons(MRU); - q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, (uint8_t *) &mru, sizeof(mru)); - } - break; - - case 2: // Async-Control-Character-Map - if (!ntohl(*(uint32_t *)(o + 2))) // all bits zero is OK - break; - - LOG(3, s, t, " Remote requesting asyncmap. Rejecting.\n"); - q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, asyncmap, sizeof(asyncmap)); - break; - - case 3: // Authentication-Protocol - { - int proto = ntohs(*(uint16_t *)(o + 2)); - char proto_name[] = "0x0000"; - int alen; - - if (proto == PPPPAP) - { - if (config->radius_authtypes & AUTHPAP) - { - sess_local[s].lcp_authtype = AUTHPAP; - break; - } - - strcpy(proto_name, "PAP"); - } - else if (proto == PPPCHAP) - { - if (config->radius_authtypes & AUTHCHAP - && *(o + 4) == 5) // MD5 - { - sess_local[s].lcp_authtype = AUTHCHAP; - break; - } - - strcpy(proto_name, "CHAP"); - } - else - sprintf(proto_name, "%#4.4x", proto); - - LOG(3, s, t, " Remote requesting %s authentication. Rejecting.\n", proto_name); - - alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authprefer); - if (alen < 2) break; // paranoia - - q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, authproto + 2, alen - 2); - if (q && *response == ConfigNak && - config->radius_authtypes != config->radius_authprefer) - { - // alternate type - alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authtypes & ~config->radius_authprefer); - if (alen < 2) break; - q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, authproto + 2, alen - 2); - } - - break; - } - break; - - case 4: // Quality-Protocol - case 5: // Magic-Number - case 7: // Protocol-Field-Compression - case 8: // Address-And-Control-Field-Compression - break; - - case 17: // Multilink Max-Receive-Reconstructed-Unit - { - uint16_t mrru = ntohs(*(uint16_t *)(o + 2)); - session[s].mrru = mrru; - changed++; - LOG(3, s, t, " Received PPP LCP option MRRU: %d\n",mrru); - } - break; - - case 18: // Multilink Short Sequence Number Header Format - { - session[s].mssf = 1; - changed++; - LOG(3, s, t, " Received PPP LCP option MSSN format\n"); - } - break; - - case 19: // Multilink Endpoint Discriminator - { - uint8_t epdis_class = o[2]; - int addr; - - session[s].epdis.addr_class = epdis_class; - session[s].epdis.length = length - 3; - if (session[s].epdis.length > 20) - { - LOG(1, s, t, "Error: received EndDis Address Length more than 20: %d\n", session[s].epdis.length); - session[s].epdis.length = 20; - } - - for (addr = 0; addr < session[s].epdis.length; addr++) - session[s].epdis.address[addr] = o[3+addr]; - - changed++; - - switch (epdis_class) - { - case LOCALADDR: - LOG(3, s, t, " Received PPP LCP option Multilink EndDis Local Address Class: %d\n",epdis_class); - break; - case IPADDR: - LOG(3, s, t, " Received PPP LCP option Multilink EndDis IP Address Class: %d\n",epdis_class); - break; - case IEEEMACADDR: - LOG(3, s, t, " Received PPP LCP option Multilink EndDis IEEE MAC Address Class: %d\n",epdis_class); - break; - case PPPMAGIC: - LOG(3, s, t, " Received PPP LCP option Multilink EndDis PPP Magic No Class: %d\n",epdis_class); - break; - case PSNDN: - LOG(3, s, t, " Received PPP LCP option Multilink EndDis PSND No Class: %d\n",epdis_class); - break; - default: - LOG(3, s, t, " Received PPP LCP option Multilink EndDis NULL Class %d\n",epdis_class); - } - } - break; - - default: // Reject any unknown options - LOG(3, s, t, " Rejecting unknown PPP LCP option %d\n", type); - q = ppp_conf_rej(s, b, sizeof(b), PPPLCP, &response, q, p, o); - } - x -= length; - o += length; - } + processreceivedlcpconfreq(s, t, p, p + 4, l - 4, &changed, &response); if (changed) cluster_send_session(s);