Index | Thread | Search

From:
Bjorn Ketelaars <bket@openbsd.org>
Subject:
pppoe(4): replace PPPOE_TERM_UNKNOWN_SESSIONS with ifconfig knob
To:
tech@openbsd.org
Date:
Fri, 27 Dec 2024 20:32:01 +0100

Download raw body.

Thread
The pppoe(4) manpage describes the kernel option
PPPOE_TERM_UNKNOWN_SESSIONS, which addresses an issue with
re-establishing a connection after a power failure. Rather than
requiring a kernel recompile, the proposal is to make this fix
configurable via an ifconfig(8) knob.
This fix provides a convenient solution for resolving issues I encounter
with reconnecting to my ISP.

The diff below includes the necessary changes to implement this and
updates to relevant manpages.

Comments/tests/OK?


diff --git share/man/man4/options.4 share/man/man4/options.4
index a6ed33cc497..f84807ab181 100644
--- share/man/man4/options.4
+++ share/man/man4/options.4
@@ -412,10 +412,6 @@ Enables BSD compressor for PPP connections.
 .It Cd option PPP_DEFLATE
 For use in conjunction with PPP_BSDCOMP; provides an interface to zlib for PPP
 for deflate compression/decompression.
-.It Cd option PPPOE_TERM_UNKNOWN_SESSIONS
-Send PADT to terminate open sessions before connecting.
-See
-.Xr pppoe 4 .
 .It Cd option SOCKET_SPLICE
 Enables zero-copy socket splicing in the kernel.
 See
diff --git share/man/man4/pppoe.4 share/man/man4/pppoe.4
index ca0cd209d5d..a5684fee726 100644
--- share/man/man4/pppoe.4
+++ share/man/man4/pppoe.4
@@ -126,7 +126,7 @@ the gateway will be changed to the suggested address as well.
 .Pp
 Otherwise, PPP negotiation will only agree to exactly the IPv4 addresses
 which are configured on the interface.
-.Sh KERNEL OPTIONS
+.Pp
 .Nm
 does not interfere with other PPPoE implementations
 running on the same machine.
@@ -138,12 +138,11 @@ because there is already an open session.
 This would be indicated by the client sending a high number of PADI packets
 before successfully connecting.
 The
+.Em link2
+switch lets the
 .Nm
-driver can be told to kill all unknown PPPoE sessions
-by sending a PADT packet to explicitly terminate the old session.
-Add the following to the kernel config file:
-.Pp
-.Dl option PPPOE_TERM_UNKNOWN_SESSIONS
+driver terminate unknown sessions on its parent interface with a PADT
+packet.
 .Sh PPPOE AND MTU/MSS
 PPPoE has an 8-byte header.
 When run over a network interface with the
diff --git sys/net/if_pppoe.c sys/net/if_pppoe.c
index ba194a5fec4..c5005788583 100644
--- sys/net/if_pppoe.c
+++ sys/net/if_pppoe.c
@@ -684,17 +684,15 @@ pppoe_data_input(struct mbuf *m)
 	struct pppoe_softc *sc;
 	struct pppoehdr *ph;
 	u_int16_t session, plen;
-#ifdef PPPOE_TERM_UNKNOWN_SESSIONS
 	u_int8_t shost[ETHER_ADDR_LEN];
-#endif
+
 	if (LIST_EMPTY(&pppoe_softc_list))
 		goto drop;
 
 	KASSERT(m->m_flags & M_PKTHDR);
 
-#ifdef PPPOE_TERM_UNKNOWN_SESSIONS
 	memcpy(shost, mtod(m, struct ether_header*)->ether_shost, ETHER_ADDR_LEN);
-#endif
+
 	m_adj(m, sizeof(struct ether_header));
 	if (m->m_pkthdr.len <= PPPOE_HEADERLEN) {
 		printf("pppoe (data): dropping too short packet: %d bytes\n",
@@ -720,11 +718,22 @@ pppoe_data_input(struct mbuf *m)
 	session = ntohs(ph->session);
 	sc = pppoe_find_softc_by_session(session, m->m_pkthdr.ph_ifidx);
 	if (sc == NULL) {
-#ifdef PPPOE_TERM_UNKNOWN_SESSIONS
-		printf("pppoe (data): input for unknown session 0x%x, sending PADT\n",
-		    session);
-		pppoe_send_padt(m->m_pkthdr.ph_ifidx, session, shost, 0);
-#endif
+		/*
+		 * Using a data packet from an unknown session, iterate through
+		 * the pppoe_softc_list to find a matching parent interface. If
+		 * IFF_LINK2 is set on a PPPoE interface on that parent
+		 * interface, send a PADT packet to terminate the unknown PPPoE
+		 * session.
+		 */
+		LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
+			if (ISSET(sc->sc_sppp.pp_if.if_flags, IFF_LINK2) &&
+			    sc->sc_eth_ifidx == m->m_pkthdr.ph_ifidx) {
+				printf("pppoe (data): input for unknown "
+				    "session 0x%x, sending PADT\n", session);
+				pppoe_send_padt(m->m_pkthdr.ph_ifidx, session,
+				    shost, 0);
+			}
+		}
 		goto drop;
 	}