diff --git a/l2tpns.h b/l2tpns.h index 74c6a02..3e7f4a6 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -441,6 +441,9 @@ typedef struct // last LCP Echo time_t last_echo; + // Whether we tried to suggest the IPV6CP identifier option. + int tried_identifier; + // last unsolicited RA sent to user time_t last_ra; diff --git a/ppp.c b/ppp.c index 1f5791f..7f5a5d2 100644 --- a/ppp.c +++ b/ppp.c @@ -1560,6 +1560,17 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) int gotip = 0; uint32_t ident[2]; + if (session[s].ipv6address.s6_addr[0]) + { + // LSB 64bits of assigned IPv6 address to user (see radius attribut Framed-IPv6-Address) + memcpy(&ident[0], &session[s].ipv6address.s6_addr[8], 8); + } + else + { + ident[0] = htonl(session[s].ip); + ident[1] = 0; + } + while (length > 2) { if (!o[1] || o[1] > length) return; @@ -1570,17 +1581,6 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) gotip++; // seen address if (o[1] != 10) return; - if (session[s].ipv6address.s6_addr[0]) - { - // LSB 64bits of assigned IPv6 address to user (see radius attribut Framed-IPv6-Address) - memcpy(&ident[0], &session[s].ipv6address.s6_addr[8], 8); - } - else - { - ident[0] = htonl(session[s].ip); - ident[1] = 0; - } - if (memcmp(o + 2, ident, sizeof(ident))) { q = ppp_conf_nak(s, b, sizeof(b), PPPIPV6CP, &response, q, p, o, (uint8_t *)ident, sizeof(ident)); @@ -1599,24 +1599,30 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) o += o[1]; } + if (!response && !gotip && sess_local[s].tried_identifier++ < 2) + { + uint8_t identifier_option[6] = { 1, 6 }; + + // No interface identifier option, try to suggest one + q = ppp_conf_nak(s, b, sizeof(b), PPPIPV6CP, &response, q, p, identifier_option, (uint8_t *)ident, sizeof(ident)); + if (!q) return; + } + if (response) { l = q - response; // IPV6CP packet length *((uint16_t *) (response + 2)) = htons(l); // update header } - else if (gotip) + else { + if (!gotip) + LOG(2, s, t, "No interface identifier in IPV6CP request, hoping for the best\n"); + // Send packet back as ConfigAck response = makeppp(b, sizeof(b), p, l, s, t, PPPIPV6CP, 0, 0, 0); if (!response) return; *response = ConfigAck; } - else - { - LOG(3, s, t, "No interface identifier in IPV6CP request\n"); - STAT(tunnel_rx_errors); - return; - } switch (session[s].ppp.ipv6cp) {