diff --git a/l2tpns.c b/l2tpns.c index e64210c..9b343de 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -5488,6 +5488,11 @@ static void regular_cleanups(double period) if (sess_local[s].ipcp.conf_sent < config->ppp_max_configure) { LOG(3, s, session[s].tunnel, "No ACK for IPCP ConfigReq... resending\n"); + if (sess_local[s].lcp_authtype == AUTHCHAP && sess_local[s].ipcp.conf_sent % 3 == 2) + { + LOG(3, s, session[s].tunnel, "Trying to re-send CHAP ack\n"); + resendchapack(s, session[s].tunnel, sess_local[s].auth_id); + } sendipcp(s, session[s].tunnel); change_state(s, ipcp, next_state); } @@ -7780,7 +7785,7 @@ int sessionsetup(sessionidt s, tunnelidt t) // Add the route for this session. routesset(s, &session[s], 1); - sess_local[s].lcp_authtype = 0; // RADIUS authentication complete + sess_local[s].lcp_authdone = 1; // RADIUS authentication complete lcp_open(s, t); // transition to Network phase and send initial IPCP // Run the plugin's against this new session. diff --git a/l2tpns.h b/l2tpns.h index dd97491..4affa5c 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -419,6 +419,8 @@ typedef struct // authentication to use int lcp_authtype; + // whether authentication is over + int lcp_authdone; // Last Received LCP ConfReq and its length uint8_t lcp_last_received_confreq[MAXLCPLENGTH]; @@ -998,6 +1000,7 @@ void processmpframe(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l, uint8_t e void processipv6in(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l); void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l); void sendchap(sessionidt s, tunnelidt t); +void resendchapack(sessionidt s, tunnelidt t, uint16_t auth_id); uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, sessionidt s, tunnelidt t, uint16_t mtype, uint8_t prio, bundleidt bid, uint8_t mp_bits); uint8_t *opt_makeppp(uint8_t *p, int l, sessionidt s, tunnelidt t, uint16_t mtype, uint8_t prio, bundleidt bid, uint8_t mp_bits); void sendlcp(sessionidt s, tunnelidt t); diff --git a/ppp.c b/ppp.c index 80ffb17..5687524 100644 --- a/ppp.c +++ b/ppp.c @@ -170,6 +170,19 @@ void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) } } +// Re-send a CHAP ack, in case it was previously lost +void resendchapack(sessionidt s, tunnelidt t, uint16_t auth_id) +{ + uint8_t b[MAXETHER]; + uint8_t *p; + p = makeppp(b, sizeof(b), 0, 0, s, t, PPPCHAP, 0, 0, 0); + if (!p) return; + *p = 3; // ack + p[1] = auth_id; + *(uint16_t *) (p + 2) = ntohs(4); // no message + tunnelsend(b, (p - b) + 4, t); // send it +} + // Process CHAP messages void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) { @@ -209,15 +222,8 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) { if (session[s].ppp.phase == Network) { - uint8_t b[MAXETHER]; - uint8_t *p2; LOG(2, s, t, "CHAP in Network phase, peer probably missed our ack, confirming it\n"); - p2 = makeppp(b, sizeof(b), 0, 0, s, t, PPPCHAP, 0, 0, 0); - if (!p2) return; - *p2 = 3; // ack - p2[1] = p[1]; - *(uint16_t *) (p2 + 2) = ntohs(4); // no message - tunnelsend(b, (p2 - b) + 4, t); // send it + resendchapack(s, t, p[1]); } else LOG(2, s, t, "CHAP ignored in %s phase\n", ppp_phase(session[s].ppp.phase)); @@ -405,7 +411,7 @@ static void dumplcp(uint8_t *p, int l) void lcp_open(sessionidt s, tunnelidt t) { // transition to Authentication or Network phase: - session[s].ppp.phase = sess_local[s].lcp_authtype ? Authenticate : Network; + session[s].ppp.phase = sess_local[s].lcp_authtype && !sess_local[s].lcp_authdone ? Authenticate : Network; LOG(3, s, t, "LCP: Opened, phase %s\n", ppp_phase(session[s].ppp.phase));