diff --git a/docs/src/html/manual.md b/docs/src/html/manual.md
index 6fbccf7..cff4b6a 100644
--- a/docs/src/html/manual.md
+++ b/docs/src/html/manual.md
@@ -159,18 +159,6 @@ should be set by a line like: set configstring \"value\" set ipaddress
: PPP counter and timer values, as described in ยง4.1 of
[RFC1661](ftp://ftp.rfc-editor.org/in-notes/rfc1661.txt).
-`lcp_renegotiation` (string)
-
-: By default (`always`), we renegotiate LCP even if the LAC already did with
- the client.
-
- We can avoid the LCP renegotiation (proxy LCP negotiation), unless what was
- already negotiated is not fine for us (`on-mismatch`). To be noted: we will
- accept not using our preferred RADIUS authentication method.
- This is notably useful when the LAC cannot pass LCP configuration through,
- and thus we have to try to accept what was already negotiated by the LAC
- with the client.
-
`primary_dns` (ip address); `econdary_dns` (ip address)
: Whenever a PPP connection is established, DNS servers will be sent
diff --git a/l2tplac.c b/l2tplac.c
index 8347d55..2af1570 100644
--- a/l2tplac.c
+++ b/l2tplac.c
@@ -60,11 +60,11 @@
* LNS1 --------------------> LNS2 (Session Open)
* ZLB
* LNS1 <-------------------- LNS2 (Session Open)
- * LCP Renegotiation (unless proxied)
+ * LCP Negotiation
* Client <------------------------------------------------------------------------> LNS2
- * PAP (Ack only if proxied) / CHAP Authentification
+ * PAP/CHAP Authentification
* Client <------------------------------------------------------------------------> LNS2
- * DATA (ppp)
+ * DATA (ppp)
* Client <------------------------------------------------------------------------> LNS2
* */
diff --git a/l2tpns.c b/l2tpns.c
index 4423df8..203fc40 100644
--- a/l2tpns.c
+++ b/l2tpns.c
@@ -159,7 +159,6 @@ config_descriptt config_values[] = {
CONFIG("ppp_max_configure", ppp_max_configure, INT),
CONFIG("ppp_max_failure", ppp_max_failure, INT),
CONFIG("ppp_keepalive", ppp_keepalive, BOOL),
- CONFIG("lcp_renegotiation", lcp_renegotiation, STRING),
CONFIG("primary_dns", default_dns1, IPv4),
CONFIG("secondary_dns", default_dns2, IPv4),
CONFIG("primary_radius", radiusserver[0], IPv4),
@@ -4185,18 +4184,9 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
uint16_t message = 0xFFFF; // message type
uint8_t fatal = 0;
uint8_t mandatory = 0;
- uint8_t *last_sent_lcp_confreq = 0;
- uint16_t last_sent_lcp_confreq_n = 0;
- uint8_t *last_received_lcp_confreq = 0;
- uint16_t last_received_lcp_confreq_n = 0;
- uint16_t atype = 0;
- uint16_t authid = 0;
- char authname[MAXUSER] = "";
- char authchall[MAXPASS] = "";
- size_t authchalln = 0;
- char authresp[MAXPASS] = "";
- size_t authrespn = 0;
uint16_t asession = 0; // assigned session
+ uint32_t amagic = 0; // magic number
+ uint8_t aflags = 0; // flags from last LCF
uint16_t version = 0x0100; // protocol version (we handle 0.0 as well and send that back just in case)
char called[MAXTEL] = ""; // called number
char calling[MAXTEL] = ""; // calling number
@@ -4673,70 +4663,50 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
}
case 29: // Proxy Authentication Type
{
- atype = ntohs(*(uint16_t *)b);
+ uint16_t atype = ntohs(*(uint16_t *)b);
LOG(4, s, t, " Proxy Auth Type %u (%s)\n", atype, ppp_auth_type(atype));
break;
}
case 30: // Proxy Authentication Name
{
+ char authname[64];
memset(authname, 0, sizeof(authname));
memcpy(authname, b, (n < sizeof(authname)) ? n : sizeof(authname) - 1);
- if (n < sizeof(authname))
- {
- LOG(4, s, t, " Proxy Auth Name (%s)\n", authname);
- }
- else
- {
- LOG(2, s, t, " Proxy Auth Name too long (%s)\n", authname);
- }
+ LOG(4, s, t, " Proxy Auth Name (%s)\n",
+ authname);
break;
}
case 31: // Proxy Authentication Challenge
{
- if (n <= sizeof(authchall))
- {
- memcpy(authchall, b, n);
- authchalln = n;
- LOG(4, s, t, " Proxy Auth Challenge\n");
- }
- else
- {
- LOG(2, s, t, " Proxy Auth Challenge too long\n");
- }
+ LOG(4, s, t, " Proxy Auth Challenge\n");
break;
}
case 32: // Proxy Authentication ID
{
- authid = ntohs(*(uint16_t *)(b));
+ uint16_t authid = ntohs(*(uint16_t *)(b));
LOG(4, s, t, " Proxy Auth ID (%u)\n", authid);
break;
}
case 33: // Proxy Authentication Response
- {
- if (n <= sizeof(authresp))
- {
- memcpy(authresp, b, n);
- authrespn = n;
- LOG(4, s, t, " Proxy Auth Response\n");
- }
- else
- {
- LOG(2, s, t, " Proxy Auth Response too long\n");
- }
- break;
- }
+ LOG(4, s, t, " Proxy Auth Response\n");
+ break;
case 27: // last sent lcp
- {
- last_sent_lcp_confreq = b;
- last_sent_lcp_confreq_n = n;
- break;
+ { // find magic number
+ uint8_t *p = b, *e = p + n;
+ while (p + 1 < e && p[1] && p + p[1] <= e)
+ {
+ if (*p == 5 && p[1] == 6) // Magic-Number
+ amagic = ntohl(*(uint32_t *) (p + 2));
+ else if (*p == 7) // Protocol-Field-Compression
+ aflags |= SESSION_PFC;
+ else if (*p == 8) // Address-and-Control-Field-Compression
+ aflags |= SESSION_ACFC;
+ p += p[1];
+ }
}
+ break;
case 28: // last recv lcp confreq
- {
- last_received_lcp_confreq = b;
- last_received_lcp_confreq_n = n;
- break;
- }
+ break;
case 26: // Initial Received LCP CONFREQ
break;
case 39: // seq required - we control it as an LNS anyway...
@@ -5047,8 +5017,9 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
break;
case 12: // ICCN
LOG(3, s, t, "Received ICCN\n");
-
- session[s].magic = time_now; // set magic number
+ if (amagic == 0) amagic = time_now;
+ session[s].magic = amagic; // set magic number
+ session[s].flags = aflags; // set flags received
session[s].mru = PPPoE_MRU; // default
controlnull(t); // ack
@@ -5063,39 +5034,8 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
else
sess_local[s].mp_epdis = 0;
- if (last_sent_lcp_confreq_n && last_received_lcp_confreq_n &&
- processlcpproxy(s, t, last_sent_lcp_confreq, last_sent_lcp_confreq_n,
- last_received_lcp_confreq, last_received_lcp_confreq_n)
- && ( (sess_local[s].lcp_authtype == 0)
- || (sess_local[s].lcp_authtype == AUTHPAP && authrespn)
- || (sess_local[s].lcp_authtype == AUTHCHAP && authchalln == 16 && authrespn == 16)))
- {
- // Could reuse the LCP negotiation and don't have empty proxy auth response or unknown challenge size, don't renegotiate
- LOG(3, s, t, "Reusing LCP negotiation\n");
- // Start with proxy auth id to avoid client caching challenge responses
- sess_local[s].auth_id = authid;
-
- if (!sess_local[s].lcp_authtype)
- {
- // No auth, open immediately
- lcp_open(s, t);
- }
- else
- {
- // Process auth
- session[s].ppp.phase = Authenticate;
- change_state(s, lcp, Opened);
- processauthproxy(s, t, atype, authname, authchalln, authchall, authrespn, authresp);
- }
- }
- else
- {
- // Have to renegotiate LCP
- LOG(3, s, t, "Renegotiating LCP\n");
- sendlcp(s, t);
- change_state(s, lcp, RequestSent);
- }
-
+ sendlcp(s, t);
+ change_state(s, lcp, RequestSent);
break;
case 14: // CDN
@@ -7506,16 +7446,6 @@ static void update_config()
MSS = MRU - TCP_HDRS;
MSS6 = MRU - TCP6_HDRS;
- if (!config->lcp_renegotiation[0])
- strcpy(config->lcp_renegotiation, "always");
-
- if (strcmp(config->lcp_renegotiation, "always") &&
- strcmp(config->lcp_renegotiation, "on-mismatch"))
- {
- LOG(0, 0, 0, "Invalid LCP renegotiation type %s, assuming 'always'\n", config->lcp_renegotiation);
- strcpy(config->lcp_renegotiation, "always");
- }
-
// Update radius
config->numradiusservers = 0;
for (i = 0; i < MAXRADSERVER; i++)
diff --git a/l2tpns.h b/l2tpns.h
index 04a6f11..39cdb3c 100644
--- a/l2tpns.h
+++ b/l2tpns.h
@@ -756,7 +756,6 @@ typedef struct
int ppp_max_configure; // max lcp configure requests to send
int ppp_max_failure; // max lcp configure naks to send
int ppp_keepalive; // send echoes regardless
- char lcp_renegotiation[12]; // LCP renegotiation (always or on-mismatch)
char radiussecret[64];
char radius_require_message_authenticator[5];
@@ -993,8 +992,6 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
void lcp_open(sessionidt s, tunnelidt t);
void lcp_restart(sessionidt s);
void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
-int processlcpproxy(sessionidt s, tunnelidt t, uint8_t *sent_lcp, uint16_t sent_lcp_n, uint8_t *received_lcp, uint16_t received_lcp_n);
-int processauthproxy(sessionidt s, tunnelidt t, uint16_t authtype, const char *authname, size_t authchalln, const char authchall[authchalln], size_t authrespn, const char authresp[authrespn]);
void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
diff --git a/ppp.c b/ppp.c
index eed07b6..a7d8a2b 100644
--- a/ppp.c
+++ b/ppp.c
@@ -556,437 +556,6 @@ 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 sent LCP options from o
-// Set changed to 1 if we changed configuration that should be sent to cluster slaves
-static int processsentlcpconfreq(sessionidt s, tunnelidt t, uint8_t *p, uint8_t *o, uint16_t x, int *changed)
-{
- int auth = 0;
- int ok = 1;
-
- 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)
- {
- sess_local[s].ppp_mru = mru;
- break;
- }
-
- ok = 0;
- break;
- }
-
- case 2: // Async-Control-Character-Map
- if (ntohl(*(uint32_t *)(o + 2)))
- ok = 0;
- break;
-
- case 3: // Authentication-Protocol
- {
- int proto = ntohs(*(uint16_t *)(o + 2));
-
- if (proto == PPPPAP)
- {
- if (config->radius_authtypes & AUTHPAP)
- {
- auth = sess_local[s].lcp_authtype = AUTHPAP;
- break;
- }
- ok = 0;
- }
- else if (proto == PPPCHAP)
- {
- if (config->radius_authtypes & AUTHCHAP
- && *(o + 4) == 5) // MD5
- {
- auth = sess_local[s].lcp_authtype = AUTHCHAP;
- break;
- }
- ok = 0;
- }
- else
- ok = 0;
- }
- break;
-
- case 4: // Quality-Protocol
- break;
-
- case 5: // Magic-Number
- if (length < 6) break;
- session[s].magic = ntohl(*(uint32_t *)(o + 2));
- *changed = 1;
- break;
-
- case 7: // Protocol-Field-Compression
- session[s].flags |= SESSION_PFC;
- *changed = 1;
- break;
- case 8: // Address-And-Control-Field-Compression
- session[s].flags |= SESSION_ACFC;
- *changed = 1;
- break;
-
- case 17: // Multilink Max-Receive-Reconstructed-Unit
- sess_local[s].mp_mrru = ntohs(*(uint16_t *)(o + 2));
- break;
-
- case 18: // Multilink Short Sequence Number Header Format
- sess_local[s].mp_mssf = 1;
- break;
-
- case 19: // Multilink Endpoint Discriminator
- ok = 0;
- break;
-
- default: // Reject any unknown options
- ok = 0;
- break;
- }
- x -= length;
- o += length;
- }
-
- if (!ok)
- // Return after taking note of magic and flags
- return 0;
-
- if (sess_local[s].lcp_authtype && !auth)
- // We do want authentication, we have to check with client
- return 0;
-
- if (sess_local[s].mp_epdis)
- // We do want Endpoint Discriminator
- return 0;
-
- return 1;
-}
-
-// Try to use LCP proxy to avoid renegotiating it (in case the LAC doesn't support passing LCP through)
-int processlcpproxy(sessionidt s, tunnelidt t, uint8_t *sent_lcp, uint16_t sent_lcp_n, uint8_t *received_lcp, uint16_t received_lcp_n)
-{
- uint8_t *response = 0;
- int changed = 0;
-
- if (!strcmp(config->lcp_renegotiation, "always"))
- /* We always renegotiate */
- return 0;
-
- LOG(3, s, t, "Trying to reuse the LAC sent and received LCP configuration:\n");
- if (config->debug >= 3)
- {
- dumplcp(sent_lcp, sent_lcp_n);
- dumplcp(received_lcp, received_lcp_n);
- }
-
- /* Check what configuration the LAC sent */
- if (!processsentlcpconfreq(s, t, NULL, sent_lcp, sent_lcp_n, &changed))
- {
- LOG(3, s, t, "Sent LCP conf does not match\n");
- return 0;
- }
-
- /* Check what configuration the LAC received */
- processreceivedlcpconfreq(s, t, NULL, received_lcp, received_lcp_n, &changed, &response);
- if (response)
- {
- LOG(3, s, t, "Received LCP conf does not match\n");
- /* Mismatch, renegotiate */
- return 0;
- }
- LOG(3, s, t, "LCP conf match\n");
-
- if (changed)
- cluster_send_session(s);
-
- // Ok!
- return 1;
-}
-
-// Try to use auth proxy to avoid renegotiating it (in case the LAC forces PAP)
-int processauthproxy(sessionidt s, tunnelidt t,
- uint16_t authtype, const char *authname,
- size_t authchalln, const char authchall[authchalln],
- size_t authrespn, const char authresp[authrespn])
-{
- uint16_t r;
-
- if ((sess_local[s].lcp_authtype == 0 && authtype != 0)
- || (sess_local[s].lcp_authtype == AUTHPAP && authtype != 3) // PAP
- || (sess_local[s].lcp_authtype == AUTHCHAP && authtype != 2)) // CHAP
- {
- LOG(3, s, t, "Authentication proxy mismatch: got %u (%s) while expecting %u\n",
- authtype, ppp_auth_type(authtype), sess_local[s].lcp_authtype);
- return 0;
- }
-
- if (session[s].ppp.phase != Authenticate)
- {
- LOG(3, s, t, "Already authenticated\n");
- return 1;
- }
-
- if (sess_local[s].lcp_authtype == 0)
- {
- LOG(4, s, t, "No auth needed\n");
- return 1;
- }
-
- if ((!config->disable_lac_func) && lac_conf_forwardtoremotelns(s, authname))
- {
- // Creating a tunnel/session has been started
- return 1;
- }
-
- if (!(r = radiusnew(s)))
- {
- LOG(1, s, t, "No RADIUS session available to authenticate session...\n");
- sessionshutdown(s, "No free RADIUS sessions.", CDN_UNAVAILABLE, TERM_SERVICE_UNAVAILABLE);
- return 1;
- }
-
- // Run PRE_AUTH plugins
- struct param_pre_auth packet = { &tunnel[t], &session[s], strdup(authname), NULL, 0, 1 };
-
- if (sess_local[s].lcp_authtype == AUTHPAP)
- {
- packet.password = strndup(authresp, authrespn);
- packet.protocol = PPPPAP;
- }
- else if (sess_local[s].lcp_authtype == AUTHCHAP)
- {
- if (authchalln != 16)
- {
- LOG(1, s, t, "CHAP challenge size different from 16: %zu\n", authchalln);
- return 0;
- }
- if (authrespn != 16)
- {
- LOG(1, s, t, "CHAP response size different from 16: %zu\n", authrespn);
- return 0;
- }
- packet.password = calloc(17, 1);
- memcpy(packet.password, authresp, 16);
- packet.protocol = PPPCHAP;
- }
- else
- // Not PAP or CHAP??
- return 0;
-
- run_plugins(PLUGIN_PRE_AUTH, &packet);
- if (!packet.continue_auth)
- {
- LOG(3, s, t, "A plugin rejected PRE_AUTH\n");
- if (packet.username) free(packet.username);
- if (packet.password) free(packet.password);
- return 1;
- }
-
- // Take all authentication information from proxy, and record for possibly proxying ourself
- strncpy(session[s].user, packet.username, sizeof(session[s].user) - 1);
- strncpy((char *) sess_local[s].auth_name, packet.username, sizeof(sess_local[s].auth_name) - 1);
-
- if (sess_local[s].lcp_authtype == AUTHPAP)
- {
- strncpy(radius[r].pass, packet.password, sizeof(radius[r].pass) - 1);
- strncpy((char *) sess_local[s].auth_resp, packet.password, sizeof(sess_local[s].auth_resp) - 1);
- }
- else
- {
- memcpy(radius[r].auth, authchall, 16);
- memcpy(sess_local[s].auth_chall, authchall, 16);
-
- memcpy(radius[r].pass, packet.password, 16);
- memcpy(sess_local[s].auth_resp, packet.password, 16);
-
- radius[r].chap = 1;
- }
- radius[r].id = sess_local[s].auth_id;
-
- LOG(3, s, t, "Sending login for %s to RADIUS\n", packet.username);
-
- free(packet.username);
- free(packet.password);
-
- if ((session[s].mrru) && (!first_session_in_bundle(s)))
- radiussend(r, RADIUSJUSTAUTH);
- else
- radiussend(r, RADIUSAUTH);
-
- return 1;
-}
-
// Process LCP messages
void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
{
@@ -1079,10 +648,165 @@ 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;
- processreceivedlcpconfreq(s, t, p, p + 4, l - 4, &changed, &response);
+ 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;
+ }
if (changed)
cluster_send_session(s);