Index | Thread | Search

From:
"Peter J. Philipp" <pjp@delphinusdns.org>
Subject:
an update to the bridge(4) inspection of pppoe patch
To:
tech@openbsd.org
Cc:
pjp@delphinusdns.org
Date:
Fri, 2 Feb 2024 11:45:28 +0100

Download raw body.

Thread
A slight update, after visually spotting a bug and then testing it again.

bridge0: flags=41<UP,RUNNING> mtu 1500
        index 4 llprio 3
        groups: bridge
        priority 32768 hellotime 2 fwddelay 15 maxage 20 holdcnt 6 proto rstp
        designated: id 00:00:00:00:00:00 priority 0
                port 5 ifpriority 0 ifcost 0
        bse0 flags=3<LEARNING,DISCOVER>
                port 1 ifpriority 0 ifcost 0
        pass in on bse0 src 00:11:22:33:44:55 dst 00:11:ff:ff:00:01 tag PPPOE pppoe sessid 1
        Addresses (max cache: 100, timeout: 240):
                fe:e1:ba:d0:eb:58 bse0 1 flags=0<>
                00:11:22:33:44:55 bse0 1 flags=0<>

....

root@vega# tcpdump -v -n -i pflog0 -s 1000 -X -c1 -e
tcpdump: listening on pflog0, link-type PFLOG
11:41:29.976376 rule 18/(match) [uid 0, pid 53550] block in on bse0: 192.168.177.99.1212 > 192.168.177.255.22: [udp sum ok] udp 10 (DF) (ttl 255, id 23233, len 38)
  0000: 4500 0026 5ac1 4000 ff11 3c51 c0a8 b163  E..&Z.@...<Q...c
  0010: c0a8 b1ff 04bc 0016 0012 7345 4869 2053  ..........sEHi S
  0020: 6e69 6666 6572                           niffer

root@vega# 

This new patch includes provision for not just Ethernet-2 frames but also
LLC headers for ARP (is this legal to have ARP on LLC?).  So that fixes the
shortcomings of the ARP filters in bridge(4).

-peter


Index: sbin/ifconfig/brconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/brconfig.c,v
retrieving revision 1.32
diff -u -p -u -r1.32 brconfig.c
--- sbin/ifconfig/brconfig.c	23 Nov 2023 03:38:34 -0000	1.32
+++ sbin/ifconfig/brconfig.c	2 Feb 2024 10:30:07 -0000
@@ -57,6 +57,7 @@ void bridge_cfg(const char *);
 void bridge_badrule(int, char **, int);
 void bridge_showrule(struct ifbrlreq *);
 int bridge_arprule(struct ifbrlreq *, int *, char ***);
+int bridge_pppoerule(struct ifbrlreq *, int *, char ***);
 
 #define	IFBAFBITS	"\020\1STATIC"
 #define	IFBIFBITS	\
@@ -907,6 +908,13 @@ bridge_showrule(struct ifbrlreq *r)
 	if (r->ifbr_arpf.brla_flags & BRLA_TPA)
 		printf(" tpa %s", inet_ntoa(r->ifbr_arpf.brla_tpa));
 
+	if (r->ifbr_pppoef.brla_flags & BRLA_PPPOE) {
+		printf(" pppoe");
+	
+		if (r->ifbr_pppoef.brla_flags & BRLA_PPPOESESS)
+			printf(" sessid %u", r->ifbr_pppoef.brla_session);
+	}
+
 	printf("\n");
 }
 
@@ -1005,6 +1013,11 @@ bridge_rule(int targc, char **targv, int
 			argc--; argv++;
 			if (bridge_arprule(&rule, &argc, &argv) == -1)
 				goto bad_rule;
+		} else if (strcmp(argv[0], "pppoe") == 0) {
+			rule.ifbr_pppoef.brla_flags |= BRLA_PPPOE;
+			argc--; argv++;
+			if (bridge_pppoerule(&rule, &argc, &argv) == -1)
+				goto bad_rule;
 		} else
 			goto bad_rule;
 
@@ -1030,6 +1043,30 @@ bridge_rule(int targc, char **targv, int
 bad_rule:
 	bridge_badrule(targc, targv, ln);
 	return (1);
+}
+
+
+int
+bridge_pppoerule(struct ifbrlreq *rule, int *argc, char ***argv)
+{
+	while (*argc) {
+		u_short			*sess;
+
+		if (strcmp((*argv)[0], "sessid") == 0) {
+			sess = &rule->ifbr_pppoef.brla_session;
+		} else
+			return (0);
+
+		(*argc)--; (*argv)++;
+		if (sess != NULL) {
+			if (*argc == 0)
+				return (-1);
+			*sess = atoi((*argv)[0]);
+			rule->ifbr_pppoef.brla_flags |= BRLA_PPPOESESS;
+			(*argc)--; (*argv)++;
+		}
+	}
+	return (0);
 }
 
 int
Index: sbin/ifconfig/ifconfig.8
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.399
diff -u -p -u -r1.399 ifconfig.8
--- sbin/ifconfig/ifconfig.8	11 Jan 2024 17:22:04 -0000	1.399
+++ sbin/ifconfig/ifconfig.8	2 Feb 2024 10:30:07 -0000
@@ -801,6 +801,12 @@ like a hub or a wireless network.
 .Op Cm tpa Ar ipaddr
 .Oc
 .Ek
+.Bk -words
+.Oo
+.Cm pppoe
+.Op Cm sessid Ar integer
+.Oc
+.Ek
 .Xc
 Add a filtering rule to an interface.
 Rules have a similar syntax to those in
Index: sys/net/bridgectl.c
===================================================================
RCS file: /cvs/src/sys/net/bridgectl.c,v
retrieving revision 1.25
diff -u -p -u -r1.25 bridgectl.c
--- sys/net/bridgectl.c	25 Feb 2021 02:48:21 -0000	1.25
+++ sys/net/bridgectl.c	2 Feb 2024 10:30:15 -0000
@@ -48,6 +48,9 @@
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 
+#include <net/if_llc.h>
+#include <net/if_pppoe.h>
+
 #include <net/if_bridge.h>
 
 
@@ -623,6 +626,7 @@ bridge_brlconf(struct bridge_iflist *bif
 		req->ifbr_src = n->brl_src;
 		req->ifbr_dst = n->brl_dst;
 		req->ifbr_arpf = n->brl_arpf;
+		req->ifbr_pppoef = n->brl_pppoef;
 #if NPF > 0
 		req->ifbr_tagname[0] = '\0';
 		if (n->brl_tag)
@@ -642,6 +646,7 @@ bridge_brlconf(struct bridge_iflist *bif
 		req->ifbr_src = n->brl_src;
 		req->ifbr_dst = n->brl_dst;
 		req->ifbr_arpf = n->brl_arpf;
+		req->ifbr_pppoef = n->brl_pppoef;
 #if NPF > 0
 		req->ifbr_tagname[0] = '\0';
 		if (n->brl_tag)
@@ -658,6 +663,27 @@ done:
 }
 
 u_int8_t
+bridge_pppoesfilter(struct brl_node *n, struct ether_header *eh, struct mbuf *m)
+{
+	struct pppoehdr	hdr;
+
+	if (!(n->brl_pppoef.brla_flags & (BRLA_PPPOE)))
+		return (1);
+
+	if (m->m_pkthdr.len < (ETHER_HDR_LEN + sizeof(hdr) + sizeof(u_int16_t)))
+		return (0);	/* log error? */
+
+	m_copydata(m, ETHER_HDR_LEN, sizeof(hdr), &hdr);
+
+	if ((ntohs(hdr.session) != n->brl_pppoef.brla_session) &&
+		(n->brl_pppoef.brla_flags & BRLA_PPPOESESS)) {
+		return (0);
+	}
+
+	return (1);
+}
+
+u_int8_t
 bridge_arpfilter(struct brl_node *n, struct ether_header *eh, struct mbuf *m)
 {
 	struct ether_arp	 ea;
@@ -665,10 +691,9 @@ bridge_arpfilter(struct brl_node *n, str
 	if (!(n->brl_arpf.brla_flags & (BRLA_ARP|BRLA_RARP)))
 		return (1);
 
-	if (ntohs(eh->ether_type) != ETHERTYPE_ARP)
-		return (0);
 	if (m->m_pkthdr.len < ETHER_HDR_LEN + sizeof(ea))
 		return (0);	/* log error? */
+
 	m_copydata(m, ETHER_HDR_LEN, sizeof(ea), &ea);
 
 	if (ntohs(ea.arp_hrd) != ARPHRD_ETHER ||
@@ -706,15 +731,57 @@ u_int8_t
 bridge_filterrule(struct brl_head *h, struct ether_header *eh, struct mbuf *m)
 {
 	struct brl_node *n;
+	struct llc llc;
 	u_int8_t action, flags;
+	u_int16_t etype;
 
 	if (SIMPLEQ_EMPTY(h))
 		return (BRL_ACTION_PASS);
 
 	KERNEL_LOCK();
 	SIMPLEQ_FOREACH(n, h, brl_next) {
-		if (!bridge_arpfilter(n, eh, m))
-			continue;
+		switch (etype = ntohs(eh->ether_type)) {
+		case ETHERTYPE_ARP:		/* FALLTHROUGH */
+		case ETHERTYPE_REVARP:
+			if (!bridge_arpfilter(n, eh, m))
+				continue;
+			break;
+		case ETHERTYPE_PPPOE:
+			if (!bridge_pppoesfilter(n, eh, m))
+				continue;
+			break;
+		default:
+			/* check if we have a Logical Link Control header */
+			if ((etype <= ETHERMTU ||
+		    		m->m_pkthdr.len >= (LLC_SNAPFRAMELEN +
+		    		ETHER_HDR_LEN))) {
+
+				m_copydata(m, ETHER_HDR_LEN, LLC_SNAPFRAMELEN, 
+					&llc);
+
+				if (llc.llc_dsap != LLC_SNAP_LSAP ||
+			    		llc.llc_ssap != LLC_SNAP_LSAP ||
+			    		llc.llc_control != LLC_UI ||
+			    		llc.llc_snap.org_code[0] ||
+			    		llc.llc_snap.org_code[1] ||
+			    		llc.llc_snap.org_code[2])
+					continue;
+	
+				etype = ntohs(llc.llc_snap.ether_type);
+
+				if ((etype == ETHERTYPE_ARP ||
+					etype == ETHERTYPE_REVARP) && 
+					!bridge_arpfilter(n, eh, m))
+					continue;
+
+				if ((etype == ETHERTYPE_PPPOE) && 
+					!bridge_pppoesfilter(n, eh, m))
+					continue;
+			}
+
+			break;
+		}	
+
 		flags = n->brl_flags & (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID);
 		if (flags == 0)
 			goto return_action;
@@ -765,6 +832,7 @@ bridge_addrule(struct bridge_iflist *bif
 	n->brl_action = req->ifbr_action;
 	n->brl_flags = req->ifbr_flags;
 	n->brl_arpf = req->ifbr_arpf;
+	n->brl_pppoef = req->ifbr_pppoef;
 #if NPF > 0
 	if (req->ifbr_tagname[0])
 		n->brl_tag = pf_tagname2tag(req->ifbr_tagname, 1);
Index: sys/net/if_bridge.c
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.c,v
retrieving revision 1.368
diff -u -p -u -r1.368 if_bridge.c
--- sys/net/if_bridge.c	16 May 2023 14:32:54 -0000	1.368
+++ sys/net/if_bridge.c	2 Feb 2024 10:30:15 -0000
@@ -48,6 +48,8 @@
 #include <net/if_types.h>
 #include <net/if_llc.h>
 #include <net/netisr.h>
+#include <net/if_pppoe.h>
+#include <net/ppp_defs.h>
 
 #include <netinet/in.h>
 #include <netinet/ip.h>
@@ -1668,11 +1670,16 @@ struct mbuf *
 bridge_ip(struct ifnet *brifp, int dir, struct ifnet *ifp,
     struct ether_header *eh, struct mbuf *m)
 {
-	struct llc llc;
 	int hassnap = 0;
-	struct ip *ip;
+	int haspppoe = 0;
 	int hlen;
-	u_int16_t etype;
+	int llclen = ETHER_HDR_LEN;
+
+	u_int16_t etype, lcp;
+
+	struct ip *ip;
+	struct llc llc;
+	struct pppoehdr phdr;
 
 #if NVLAN > 0
 	if (m->m_flags & M_VLANTAG)
@@ -1681,7 +1688,8 @@ bridge_ip(struct ifnet *brifp, int dir, 
 
 	etype = ntohs(eh->ether_type);
 
-	if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6) {
+	if ((etype != ETHERTYPE_IP) && (etype != ETHERTYPE_IPV6) && 
+		(etype != ETHERTYPE_PPPOE)) {
 		if (etype > ETHERMTU ||
 		    m->m_pkthdr.len < (LLC_SNAPFRAMELEN +
 		    ETHER_HDR_LEN))
@@ -1698,17 +1706,42 @@ bridge_ip(struct ifnet *brifp, int dir, 
 			return (m);
 
 		etype = ntohs(llc.llc_snap.ether_type);
-		if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6)
+		if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6 &&
+			etype != ETHERTYPE_PPPOE)
 			return (m);
+
 		hassnap = 1;
 	}
 
+	if (etype == ETHERTYPE_PPPOE) {
+		if (hassnap) {
+			llclen += LLC_SNAPFRAMELEN;
+		}
+
+		m_copydata(m, llclen, sizeof(phdr), &phdr);
+		llclen += sizeof(phdr);
+
+		m_copydata(m, llclen, sizeof(u_int16_t), &lcp);
+
+		if (ntohs(lcp) == PPP_IP)
+			etype = ETHERTYPE_IP;
+		else if (ntohs(lcp) == PPP_IPV6)
+			etype = ETHERTYPE_IPV6;
+		else
+			return (m);
+
+		haspppoe = 1;
+	}
+
+
 	m_adj(m, ETHER_HDR_LEN);
+
 	if (hassnap)
 		m_adj(m, LLC_SNAPFRAMELEN);
+	if (haspppoe)
+		m_adj(m, sizeof(phdr) + sizeof(u_int16_t));
 
 	switch (etype) {
-
 	case ETHERTYPE_IP:
 		m = ipv4_check(ifp, m);
 		if (m == NULL)
@@ -1793,11 +1826,29 @@ bridge_ip(struct ifnet *brifp, int dir, 
 		break;
 	}
 
-	/* Reattach SNAP header */
+	/* Reattach PPPoE and SNAP headers */
+	if (haspppoe) {
+		u_int16_t *tmplcp;
+
+		M_PREPEND(m, sizeof(u_int16_t), M_DONTWAIT);
+		if (m == NULL)
+			goto dropit;
+
+		tmplcp = (u_int16_t *)mtod(m, caddr_t);
+		*tmplcp = lcp;
+
+		M_PREPEND(m, sizeof(phdr), M_DONTWAIT);
+		if (m == NULL)
+			goto dropit;
+
+		bcopy(&phdr, mtod(m, caddr_t), sizeof(phdr));
+	}
+
 	if (hassnap) {
 		M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
 		if (m == NULL)
 			goto dropit;
+
 		bcopy(&llc, mtod(m, caddr_t), LLC_SNAPFRAMELEN);
 	}
 
Index: sys/net/if_bridge.h
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.h,v
retrieving revision 1.73
diff -u -p -u -r1.73 if_bridge.h
--- sys/net/if_bridge.h	11 Nov 2021 10:03:10 -0000	1.73
+++ sys/net/if_bridge.h	2 Feb 2024 10:30:15 -0000
@@ -208,6 +208,14 @@ struct ifbrarpf {
 #define	BRLA_THA	0x40
 #define	BRLA_TPA	0x80
 
+struct ifbrpppoef {
+	u_int16_t		brla_flags;
+	u_int16_t		brla_session;
+};
+
+#define BRLA_PPPOE	0x100
+#define BRLA_PPPOESESS	0x200
+
 struct ifbrlreq {
 	char			ifbr_name[IFNAMSIZ];	/* bridge ifs name */
 	char			ifbr_ifsname[IFNAMSIZ];	/* member ifs name */
@@ -217,6 +225,7 @@ struct ifbrlreq {
 	struct ether_addr	ifbr_dst;		/* destination mac */
 	char			ifbr_tagname[PF_TAG_NAME_SIZE];	/* pf tagname */
 	struct ifbrarpf		ifbr_arpf;		/* arp filter */
+	struct ifbrpppoef	ifbr_pppoef;		/* pppoe ses filter */
 };
 #define	BRL_ACTION_BLOCK	0x01			/* block frame */
 #define	BRL_ACTION_PASS		0x02			/* pass frame */
@@ -286,6 +295,7 @@ struct brl_node {
 	u_int8_t		brl_action;	/* what to do with match */
 	u_int8_t		brl_flags;	/* comparison flags */
 	struct ifbrarpf		brl_arpf;	/* arp filter */
+	struct ifbrpppoef	brl_pppoef;	/* pppoe sess filter */
 };
 
 struct bstp_timer {
Index: sys/net/if_pppoe.c
===================================================================
RCS file: /cvs/src/sys/net/if_pppoe.c,v
retrieving revision 1.83
diff -u -p -u -r1.83 if_pppoe.c
--- sys/net/if_pppoe.c	14 Jul 2022 11:03:15 -0000	1.83
+++ sys/net/if_pppoe.c	2 Feb 2024 10:30:15 -0000
@@ -59,61 +59,6 @@
 
 #define PPPOEDEBUG(a)	((sc->sc_sppp.pp_if.if_flags & IFF_DEBUG) ? printf a : 0)
 
-struct pppoehdr {
-	u_int8_t vertype;
-	u_int8_t code;
-	u_int16_t session;
-	u_int16_t plen;
-} __packed;
-
-struct pppoetag {
-	u_int16_t tag;
-	u_int16_t len;
-} __packed;
-
-#define	PPPOE_HEADERLEN		sizeof(struct pppoehdr)
-#define	PPPOE_OVERHEAD		(PPPOE_HEADERLEN + 2)
-#define	PPPOE_VERTYPE		0x11		/* VER=1, TYPE = 1 */
-
-#define	PPPOE_TAG_EOL		0x0000		/* end of list */
-#define	PPPOE_TAG_SNAME		0x0101		/* service name */
-#define	PPPOE_TAG_ACNAME	0x0102		/* access concentrator name */
-#define	PPPOE_TAG_HUNIQUE	0x0103		/* host unique */
-#define	PPPOE_TAG_ACCOOKIE	0x0104		/* AC cookie */
-#define	PPPOE_TAG_VENDOR	0x0105		/* vendor specific */
-#define	PPPOE_TAG_RELAYSID	0x0110		/* relay session id */
-#define	PPPOE_TAG_MAX_PAYLOAD	0x0120		/* RFC 4638 max payload */
-#define	PPPOE_TAG_SNAME_ERR	0x0201		/* service name error */
-#define	PPPOE_TAG_ACSYS_ERR	0x0202		/* AC system error */
-#define	PPPOE_TAG_GENERIC_ERR	0x0203		/* generic error */
-
-#define	PPPOE_CODE_PADI		0x09		/* Active Discovery Initiation */
-#define	PPPOE_CODE_PADO		0x07		/* Active Discovery Offer */
-#define	PPPOE_CODE_PADR		0x19		/* Active Discovery Request */
-#define	PPPOE_CODE_PADS		0x65		/* Active Discovery Session confirmation */
-#define	PPPOE_CODE_PADT		0xA7		/* Active Discovery Terminate */
-
-/* two byte PPP protocol discriminator, then IP data */
-#define	PPPOE_MTU	(ETHERMTU - PPPOE_OVERHEAD)
-#define	PPPOE_MAXMTU	PP_MAX_MRU
-
-/* Add a 16 bit unsigned value to a buffer pointed to by PTR */
-#define	PPPOE_ADD_16(PTR, VAL)			\
-		*(PTR)++ = (VAL) / 256;		\
-		*(PTR)++ = (VAL) % 256
-
-/* Add a complete PPPoE header to the buffer pointed to by PTR */
-#define	PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN)	\
-		*(PTR)++ = PPPOE_VERTYPE;	\
-		*(PTR)++ = (CODE);		\
-		PPPOE_ADD_16(PTR, SESS);	\
-		PPPOE_ADD_16(PTR, LEN)
-
-#define	PPPOE_DISC_TIMEOUT	5	/* base for quick timeout calculation (seconds) */
-#define	PPPOE_SLOW_RETRY	60	/* persistent retry interval (seconds) */
-#define	PPPOE_DISC_MAXPADI	4	/* retry PADI four times (quickly) */
-#define	PPPOE_DISC_MAXPADR	2	/* retry PADR twice */
-
 /*
  * Locks used to protect struct members and global data
  *       I       immutable after creation
Index: sys/net/if_pppoe.h
===================================================================
RCS file: /cvs/src/sys/net/if_pppoe.h,v
retrieving revision 1.8
diff -u -p -u -r1.8 if_pppoe.h
--- sys/net/if_pppoe.h	29 Jun 2022 09:08:07 -0000	1.8
+++ sys/net/if_pppoe.h	2 Feb 2024 10:30:16 -0000
@@ -64,6 +64,61 @@ struct pppoeconnectionstate {
 
 #define PPPOEGETSESSION	_IOWR('i', 112, struct pppoeconnectionstate)
 
+struct pppoehdr {
+	u_int8_t vertype;
+	u_int8_t code;
+	u_int16_t session;
+	u_int16_t plen;
+} __packed;
+
+struct pppoetag {
+	u_int16_t tag;
+	u_int16_t len;
+} __packed;
+
+#define	PPPOE_HEADERLEN		sizeof(struct pppoehdr)
+#define	PPPOE_OVERHEAD		(PPPOE_HEADERLEN + 2)
+#define	PPPOE_VERTYPE		0x11		/* VER=1, TYPE = 1 */
+
+#define	PPPOE_TAG_EOL		0x0000		/* end of list */
+#define	PPPOE_TAG_SNAME		0x0101		/* service name */
+#define	PPPOE_TAG_ACNAME	0x0102		/* access concentrator name */
+#define	PPPOE_TAG_HUNIQUE	0x0103		/* host unique */
+#define	PPPOE_TAG_ACCOOKIE	0x0104		/* AC cookie */
+#define	PPPOE_TAG_VENDOR	0x0105		/* vendor specific */
+#define	PPPOE_TAG_RELAYSID	0x0110		/* relay session id */
+#define	PPPOE_TAG_MAX_PAYLOAD	0x0120		/* RFC 4638 max payload */
+#define	PPPOE_TAG_SNAME_ERR	0x0201		/* service name error */
+#define	PPPOE_TAG_ACSYS_ERR	0x0202		/* AC system error */
+#define	PPPOE_TAG_GENERIC_ERR	0x0203		/* generic error */
+
+#define	PPPOE_CODE_PADI		0x09		/* Active Discovery Initiation */
+#define	PPPOE_CODE_PADO		0x07		/* Active Discovery Offer */
+#define	PPPOE_CODE_PADR		0x19		/* Active Discovery Request */
+#define	PPPOE_CODE_PADS		0x65		/* Active Discovery Session confirmation */
+#define	PPPOE_CODE_PADT		0xA7		/* Active Discovery Terminate */
+
+/* two byte PPP protocol discriminator, then IP data */
+#define	PPPOE_MTU	(ETHERMTU - PPPOE_OVERHEAD)
+#define	PPPOE_MAXMTU	PP_MAX_MRU
+
+/* Add a 16 bit unsigned value to a buffer pointed to by PTR */
+#define	PPPOE_ADD_16(PTR, VAL)			\
+		*(PTR)++ = (VAL) / 256;		\
+		*(PTR)++ = (VAL) % 256
+
+/* Add a complete PPPoE header to the buffer pointed to by PTR */
+#define	PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN)	\
+		*(PTR)++ = PPPOE_VERTYPE;	\
+		*(PTR)++ = (CODE);		\
+		PPPOE_ADD_16(PTR, SESS);	\
+		PPPOE_ADD_16(PTR, LEN)
+
+#define	PPPOE_DISC_TIMEOUT	5	/* base for quick timeout calculation (seconds) */
+#define	PPPOE_SLOW_RETRY	60	/* persistent retry interval (seconds) */
+#define	PPPOE_DISC_MAXPADI	4	/* retry PADI four times (quickly) */
+#define	PPPOE_DISC_MAXPADR	2	/* retry PADR twice */
+
 #ifdef _KERNEL
 
 extern struct mbuf_queue pppoediscinq;