Download raw body.
question regarding pppoe(4) inspection in a bridge(4) or veb(4)
an update to the bridge(4) inspection of pppoe patch
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;
question regarding pppoe(4) inspection in a bridge(4) or veb(4)
an update to the bridge(4) inspection of pppoe patch