xref: /openbsd/sys/net/if_ethersubr.c (revision ac5f541a)
1 /*	$OpenBSD: if_ethersubr.c,v 1.293 2024/02/14 22:41:48 bluhm Exp $	*/
2 /*	$NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 /*
34  * Copyright (c) 1982, 1989, 1993
35  *	The Regents of the University of California.  All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. Neither the name of the University nor the names of its contributors
46  *    may be used to endorse or promote products derived from this software
47  *    without specific prior written permission.
48  *
49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59  * SUCH DAMAGE.
60  *
61  *	@(#)if_ethersubr.c	8.1 (Berkeley) 6/10/93
62  */
63 
64 /*
65 %%% portions-copyright-nrl-95
66 Portions of this software are Copyright 1995-1998 by Randall Atkinson,
67 Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
68 Reserved. All rights under this copyright have been assigned to the US
69 Naval Research Laboratory (NRL). The NRL Copyright Notice and License
70 Agreement Version 1.1 (January 17, 1995) applies to these portions of the
71 software.
72 You should have received a copy of the license with this software. If you
73 didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
74 */
75 
76 #include "bpfilter.h"
77 
78 #include <sys/param.h>
79 #include <sys/systm.h>
80 #include <sys/kernel.h>
81 #include <sys/malloc.h>
82 #include <sys/mbuf.h>
83 #include <sys/socket.h>
84 #include <sys/ioctl.h>
85 #include <sys/errno.h>
86 #include <sys/syslog.h>
87 #include <sys/timeout.h>
88 #include <sys/smr.h>
89 
90 #include <net/if.h>
91 #include <net/netisr.h>
92 #include <net/route.h>
93 #include <net/if_llc.h>
94 #include <net/if_dl.h>
95 #include <net/if_media.h>
96 #include <net/if_types.h>
97 
98 #include <netinet/in.h>
99 #include <netinet/if_ether.h>
100 #include <netinet/ip_ipsp.h>
101 #include <netinet/ip.h>
102 #include <netinet/ip6.h>
103 #include <netinet/tcp.h>
104 #include <netinet/udp.h>
105 
106 #if NBPFILTER > 0
107 #include <net/bpf.h>
108 #endif
109 
110 #include "vlan.h"
111 #if NVLAN > 0
112 #include <net/if_vlan_var.h>
113 #endif
114 
115 #include "carp.h"
116 #if NCARP > 0
117 #include <netinet/ip_carp.h>
118 #endif
119 
120 #include "pppoe.h"
121 #if NPPPOE > 0
122 #include <net/if_pppoe.h>
123 #endif
124 
125 #include "bpe.h"
126 #if NBPE > 0
127 #include <net/if_bpe.h>
128 #endif
129 
130 #ifdef INET6
131 #include <netinet6/in6_var.h>
132 #include <netinet6/nd6.h>
133 #endif
134 
135 #ifdef PIPEX
136 #include <net/pipex.h>
137 #endif
138 
139 #ifdef MPLS
140 #include <netmpls/mpls.h>
141 #endif /* MPLS */
142 
143 /* #define ETHERDEBUG 1 */
144 #ifdef ETHERDEBUG
145 int etherdebug = ETHERDEBUG;
146 #define DNPRINTF(level, fmt, args...)					\
147 	do {								\
148 		if (etherdebug >= level)				\
149 			printf("%s: " fmt "\n", __func__, ## args);	\
150 	} while (0)
151 #else
152 #define DNPRINTF(level, fmt, args...)					\
153 	do { } while (0)
154 #endif
155 #define DPRINTF(fmt, args...)	DNPRINTF(1, fmt, args)
156 
157 u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] =
158     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
159 u_int8_t etheranyaddr[ETHER_ADDR_LEN] =
160     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
161 #define senderr(e) { error = (e); goto bad;}
162 
163 int
ether_ioctl(struct ifnet * ifp,struct arpcom * arp,u_long cmd,caddr_t data)164 ether_ioctl(struct ifnet *ifp, struct arpcom *arp, u_long cmd, caddr_t data)
165 {
166 	struct ifreq *ifr = (struct ifreq *)data;
167 	int error = 0;
168 
169 	switch (cmd) {
170 	case SIOCSIFADDR:
171 		break;
172 
173 	case SIOCSIFMTU:
174 		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
175 			error = EINVAL;
176 		else
177 			ifp->if_mtu = ifr->ifr_mtu;
178 		break;
179 
180 	case SIOCADDMULTI:
181 	case SIOCDELMULTI:
182 		if (ifp->if_flags & IFF_MULTICAST) {
183 			error = (cmd == SIOCADDMULTI) ?
184 			    ether_addmulti(ifr, arp) :
185 			    ether_delmulti(ifr, arp);
186 		} else
187 			error = ENOTTY;
188 		break;
189 
190 	default:
191 		error = ENOTTY;
192 	}
193 
194 	return (error);
195 }
196 
197 
198 void
ether_rtrequest(struct ifnet * ifp,int req,struct rtentry * rt)199 ether_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
200 {
201 	if (rt == NULL)
202 		return;
203 
204 	switch (rt_key(rt)->sa_family) {
205 	case AF_INET:
206 		arp_rtrequest(ifp, req, rt);
207 		break;
208 #ifdef INET6
209 	case AF_INET6:
210 		nd6_rtrequest(ifp, req, rt);
211 		break;
212 #endif
213 	default:
214 		break;
215 	}
216 }
217 
218 int
ether_resolve(struct ifnet * ifp,struct mbuf * m,struct sockaddr * dst,struct rtentry * rt,struct ether_header * eh)219 ether_resolve(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
220     struct rtentry *rt, struct ether_header *eh)
221 {
222 	struct arpcom *ac = (struct arpcom *)ifp;
223 	sa_family_t af = dst->sa_family;
224 	int error = 0;
225 
226 	if (!ISSET(ifp->if_flags, IFF_RUNNING))
227 		senderr(ENETDOWN);
228 
229 	KASSERT(rt != NULL || ISSET(m->m_flags, M_MCAST|M_BCAST) ||
230 		af == AF_UNSPEC || af == pseudo_AF_HDRCMPLT);
231 
232 #ifdef DIAGNOSTIC
233 	if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) {
234 		printf("%s: trying to send packet on wrong domain. "
235 		    "if %d vs. mbuf %d\n", ifp->if_xname,
236 		    ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid));
237 	}
238 #endif
239 
240 	switch (af) {
241 	case AF_INET:
242 		error = arpresolve(ifp, rt, m, dst, eh->ether_dhost);
243 		if (error)
244 			return (error);
245 		eh->ether_type = htons(ETHERTYPE_IP);
246 
247 		/*
248 		 * If broadcasting on a simplex interface, loopback a copy.
249 		 * The checksum must be calculated in software.  Keep the
250 		 * condition in sync with in_ifcap_cksum().
251 		 */
252 		if (ISSET(m->m_flags, M_BCAST) &&
253 		    ISSET(ifp->if_flags, IFF_SIMPLEX) &&
254 		    !m->m_pkthdr.pf.routed) {
255 			struct mbuf *mcopy;
256 
257 			/* XXX Should we input an unencrypted IPsec packet? */
258 			mcopy = m_copym(m, 0, M_COPYALL, M_NOWAIT);
259 			if (mcopy != NULL)
260 				if_input_local(ifp, mcopy, af);
261 		}
262 		break;
263 #ifdef INET6
264 	case AF_INET6:
265 		error = nd6_resolve(ifp, rt, m, dst, eh->ether_dhost);
266 		if (error)
267 			return (error);
268 		eh->ether_type = htons(ETHERTYPE_IPV6);
269 		break;
270 #endif
271 #ifdef MPLS
272 	case AF_MPLS:
273 		if (rt == NULL)
274 			senderr(EHOSTUNREACH);
275 
276 		if (!ISSET(ifp->if_xflags, IFXF_MPLS))
277 			senderr(ENETUNREACH);
278 
279 		dst = ISSET(rt->rt_flags, RTF_GATEWAY) ?
280 		    rt->rt_gateway : rt_key(rt);
281 
282 		switch (dst->sa_family) {
283 		case AF_LINK:
284 			if (satosdl(dst)->sdl_alen < sizeof(eh->ether_dhost))
285 				senderr(EHOSTUNREACH);
286 			memcpy(eh->ether_dhost, LLADDR(satosdl(dst)),
287 			    sizeof(eh->ether_dhost));
288 			break;
289 #ifdef INET6
290 		case AF_INET6:
291 			error = nd6_resolve(ifp, rt, m, dst, eh->ether_dhost);
292 			if (error)
293 				return (error);
294 			break;
295 #endif
296 		case AF_INET:
297 			error = arpresolve(ifp, rt, m, dst, eh->ether_dhost);
298 			if (error)
299 				return (error);
300 			break;
301 		default:
302 			senderr(EHOSTUNREACH);
303 		}
304 		/* XXX handling for simplex devices in case of M/BCAST ?? */
305 		if (m->m_flags & (M_BCAST | M_MCAST))
306 			eh->ether_type = htons(ETHERTYPE_MPLS_MCAST);
307 		else
308 			eh->ether_type = htons(ETHERTYPE_MPLS);
309 		break;
310 #endif /* MPLS */
311 	case pseudo_AF_HDRCMPLT:
312 		/* take the whole header from the sa */
313 		memcpy(eh, dst->sa_data, sizeof(*eh));
314 		return (0);
315 
316 	case AF_UNSPEC:
317 		/* take the dst and type from the sa, but get src below */
318 		memcpy(eh, dst->sa_data, sizeof(*eh));
319 		break;
320 
321 	default:
322 		printf("%s: can't handle af%d\n", ifp->if_xname, af);
323 		senderr(EAFNOSUPPORT);
324 	}
325 
326 	memcpy(eh->ether_shost, ac->ac_enaddr, sizeof(eh->ether_shost));
327 
328 	return (0);
329 
330 bad:
331 	m_freem(m);
332 	return (error);
333 }
334 
335 struct mbuf*
ether_encap(struct ifnet * ifp,struct mbuf * m,struct sockaddr * dst,struct rtentry * rt,int * errorp)336 ether_encap(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
337     struct rtentry *rt, int *errorp)
338 {
339 	struct ether_header eh;
340 	int error;
341 
342 	error = ether_resolve(ifp, m, dst, rt, &eh);
343 	switch (error) {
344 	case 0:
345 		break;
346 	case EAGAIN:
347 		error = 0;
348 	default:
349 		*errorp = error;
350 		return (NULL);
351 	}
352 
353 	m = m_prepend(m, ETHER_ALIGN + sizeof(eh), M_DONTWAIT);
354 	if (m == NULL) {
355 		*errorp = ENOBUFS;
356 		return (NULL);
357 	}
358 
359 	m_adj(m, ETHER_ALIGN);
360 	memcpy(mtod(m, struct ether_header *), &eh, sizeof(eh));
361 
362 	return (m);
363 }
364 
365 int
ether_output(struct ifnet * ifp,struct mbuf * m,struct sockaddr * dst,struct rtentry * rt)366 ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
367     struct rtentry *rt)
368 {
369 	int error;
370 
371 	m = ether_encap(ifp, m, dst, rt, &error);
372 	if (m == NULL)
373 		return (error);
374 
375 	return (if_enqueue(ifp, m));
376 }
377 
378 /*
379  * Process a received Ethernet packet.
380  *
381  * Ethernet input has several "phases" of filtering packets to
382  * support virtual/pseudo interfaces before actual layer 3 protocol
383  * handling.
384  *
385  * First phase:
386  *
387  * The first phase supports drivers that aggregate multiple Ethernet
388  * ports into a single logical interface, ie, aggr(4) and trunk(4).
389  * These drivers intercept packets by swapping out the if_input handler
390  * on the "port" interfaces to steal the packets before they get here
391  * to ether_input().
392  */
393 void
ether_input(struct ifnet * ifp,struct mbuf * m)394 ether_input(struct ifnet *ifp, struct mbuf *m)
395 {
396 	struct ether_header *eh;
397 	void (*input)(struct ifnet *, struct mbuf *);
398 	u_int16_t etype;
399 	struct arpcom *ac;
400 	const struct ether_brport *eb;
401 	unsigned int sdelim = 0;
402 	uint64_t dst, self;
403 
404 	/* Drop short frames */
405 	if (m->m_len < ETHER_HDR_LEN)
406 		goto dropanyway;
407 
408 	/*
409 	 * Second phase: service delimited packet filtering.
410 	 *
411 	 * Let vlan(4) and svlan(4) look at "service delimited"
412 	 * packets. If a virtual interface does not exist to take
413 	 * those packets, they're returned to ether_input() so a
414 	 * bridge can have a go at forwarding them.
415 	 */
416 
417 	eh = mtod(m, struct ether_header *);
418 	dst = ether_addr_to_e64((struct ether_addr *)eh->ether_dhost);
419 	etype = ntohs(eh->ether_type);
420 
421 	if (ISSET(m->m_flags, M_VLANTAG) ||
422 	    etype == ETHERTYPE_VLAN || etype == ETHERTYPE_QINQ) {
423 #if NVLAN > 0
424 		m = vlan_input(ifp, m, &sdelim);
425 		if (m == NULL)
426 			return;
427 #else
428 		sdelim = 1;
429 #endif
430 	}
431 
432 	/*
433 	 * Third phase: bridge processing.
434 	 *
435 	 * Give the packet to a bridge interface, ie, bridge(4),
436 	 * veb(4), or tpmr(4), if it is configured. A bridge
437 	 * may take the packet and forward it to another port, or it
438 	 * may return it here to ether_input() to support local
439 	 * delivery to this port.
440 	 */
441 
442 	ac = (struct arpcom *)ifp;
443 
444 	smr_read_enter();
445 	eb = SMR_PTR_GET(&ac->ac_brport);
446 	if (eb != NULL)
447 		eb->eb_port_take(eb->eb_port);
448 	smr_read_leave();
449 	if (eb != NULL) {
450 		m = (*eb->eb_input)(ifp, m, dst, eb->eb_port);
451 		eb->eb_port_rele(eb->eb_port);
452 		if (m == NULL) {
453 			return;
454 		}
455 	}
456 
457 	/*
458 	 * Fourth phase: drop service delimited packets.
459 	 *
460 	 * If the packet has a tag, and a bridge didn't want it,
461 	 * it's not for this port.
462 	 */
463 
464 	if (sdelim)
465 		goto dropanyway;
466 
467 	/*
468 	 * Fifth phase: destination address check.
469 	 *
470 	 * Is the packet specifically addressed to this port?
471 	 */
472 
473 	eh = mtod(m, struct ether_header *);
474 	self = ether_addr_to_e64((struct ether_addr *)ac->ac_enaddr);
475 	if (dst != self) {
476 #if NCARP > 0
477 		/*
478 		 * If it's not for this port, it could be for carp(4).
479 		 */
480 		if (ifp->if_type != IFT_CARP &&
481 		    !SRPL_EMPTY_LOCKED(&ifp->if_carp)) {
482 			m = carp_input(ifp, m, dst);
483 			if (m == NULL)
484 				return;
485 
486 			eh = mtod(m, struct ether_header *);
487 		}
488 #endif
489 
490 		/*
491 		 * If not, it must be multicast or broadcast to go further.
492 		 */
493 		if (!ETH64_IS_MULTICAST(dst))
494 			goto dropanyway;
495 
496 		/*
497 		 * If this is not a simplex interface, drop the packet
498 		 * if it came from us.
499 		 */
500 		if ((ifp->if_flags & IFF_SIMPLEX) == 0) {
501 			uint64_t src = ether_addr_to_e64(
502 			    (struct ether_addr *)eh->ether_shost);
503 			if (self == src)
504 				goto dropanyway;
505 		}
506 
507 		SET(m->m_flags, ETH64_IS_BROADCAST(dst) ? M_BCAST : M_MCAST);
508 		ifp->if_imcasts++;
509 	}
510 
511 	/*
512 	 * Sixth phase: protocol demux.
513 	 *
514 	 * At this point it is known that the packet is destined
515 	 * for layer 3 protocol handling on the local port.
516 	 */
517 	etype = ntohs(eh->ether_type);
518 
519 	switch (etype) {
520 	case ETHERTYPE_IP:
521 		input = ipv4_input;
522 		break;
523 
524 	case ETHERTYPE_ARP:
525 		if (ifp->if_flags & IFF_NOARP)
526 			goto dropanyway;
527 		input = arpinput;
528 		break;
529 
530 	case ETHERTYPE_REVARP:
531 		if (ifp->if_flags & IFF_NOARP)
532 			goto dropanyway;
533 		input = revarpinput;
534 		break;
535 
536 #ifdef INET6
537 	/*
538 	 * Schedule IPv6 software interrupt for incoming IPv6 packet.
539 	 */
540 	case ETHERTYPE_IPV6:
541 		input = ipv6_input;
542 		break;
543 #endif /* INET6 */
544 #if NPPPOE > 0 || defined(PIPEX)
545 	case ETHERTYPE_PPPOEDISC:
546 	case ETHERTYPE_PPPOE:
547 		if (m->m_flags & (M_MCAST | M_BCAST))
548 			goto dropanyway;
549 #ifdef PIPEX
550 		if (pipex_enable) {
551 			struct pipex_session *session;
552 
553 			if ((session = pipex_pppoe_lookup_session(m)) != NULL) {
554 				pipex_pppoe_input(m, session);
555 				pipex_rele_session(session);
556 				return;
557 			}
558 		}
559 #endif
560 		if (etype == ETHERTYPE_PPPOEDISC) {
561 			if (mq_enqueue(&pppoediscinq, m) == 0)
562 				schednetisr(NETISR_PPPOE);
563 		} else {
564 			if (mq_enqueue(&pppoeinq, m) == 0)
565 				schednetisr(NETISR_PPPOE);
566 		}
567 		return;
568 #endif
569 #ifdef MPLS
570 	case ETHERTYPE_MPLS:
571 	case ETHERTYPE_MPLS_MCAST:
572 		input = mpls_input;
573 		break;
574 #endif
575 #if NBPE > 0
576 	case ETHERTYPE_PBB:
577 		bpe_input(ifp, m);
578 		return;
579 #endif
580 	default:
581 		goto dropanyway;
582 	}
583 
584 	m_adj(m, sizeof(*eh));
585 	(*input)(ifp, m);
586 	return;
587 dropanyway:
588 	m_freem(m);
589 	return;
590 }
591 
592 int
ether_brport_isset(struct ifnet * ifp)593 ether_brport_isset(struct ifnet *ifp)
594 {
595 	struct arpcom *ac = (struct arpcom *)ifp;
596 
597 	KERNEL_ASSERT_LOCKED();
598 	if (SMR_PTR_GET_LOCKED(&ac->ac_brport) != NULL)
599 		return (EBUSY);
600 
601 	return (0);
602 }
603 
604 void
ether_brport_set(struct ifnet * ifp,const struct ether_brport * eb)605 ether_brport_set(struct ifnet *ifp, const struct ether_brport *eb)
606 {
607 	struct arpcom *ac = (struct arpcom *)ifp;
608 
609 	KERNEL_ASSERT_LOCKED();
610 	KASSERTMSG(SMR_PTR_GET_LOCKED(&ac->ac_brport) == NULL,
611 	    "%s setting an already set brport", ifp->if_xname);
612 
613 	SMR_PTR_SET_LOCKED(&ac->ac_brport, eb);
614 }
615 
616 void
ether_brport_clr(struct ifnet * ifp)617 ether_brport_clr(struct ifnet *ifp)
618 {
619 	struct arpcom *ac = (struct arpcom *)ifp;
620 
621 	KERNEL_ASSERT_LOCKED();
622 	KASSERTMSG(SMR_PTR_GET_LOCKED(&ac->ac_brport) != NULL,
623 	    "%s clearing an already clear brport", ifp->if_xname);
624 
625 	SMR_PTR_SET_LOCKED(&ac->ac_brport, NULL);
626 }
627 
628 const struct ether_brport *
ether_brport_get(struct ifnet * ifp)629 ether_brport_get(struct ifnet *ifp)
630 {
631 	struct arpcom *ac = (struct arpcom *)ifp;
632 	SMR_ASSERT_CRITICAL();
633 	return (SMR_PTR_GET(&ac->ac_brport));
634 }
635 
636 const struct ether_brport *
ether_brport_get_locked(struct ifnet * ifp)637 ether_brport_get_locked(struct ifnet *ifp)
638 {
639 	struct arpcom *ac = (struct arpcom *)ifp;
640 	KERNEL_ASSERT_LOCKED();
641 	return (SMR_PTR_GET_LOCKED(&ac->ac_brport));
642 }
643 
644 /*
645  * Convert Ethernet address to printable (loggable) representation.
646  */
647 static char digits[] = "0123456789abcdef";
648 char *
ether_sprintf(u_char * ap)649 ether_sprintf(u_char *ap)
650 {
651 	int i;
652 	static char etherbuf[ETHER_ADDR_LEN * 3];
653 	char *cp = etherbuf;
654 
655 	for (i = 0; i < ETHER_ADDR_LEN; i++) {
656 		*cp++ = digits[*ap >> 4];
657 		*cp++ = digits[*ap++ & 0xf];
658 		*cp++ = ':';
659 	}
660 	*--cp = 0;
661 	return (etherbuf);
662 }
663 
664 /*
665  * Generate a (hopefully) acceptable MAC address, if asked.
666  */
667 void
ether_fakeaddr(struct ifnet * ifp)668 ether_fakeaddr(struct ifnet *ifp)
669 {
670 	static int unit;
671 	int rng = arc4random();
672 
673 	/* Non-multicast; locally administered address */
674 	((struct arpcom *)ifp)->ac_enaddr[0] = 0xfe;
675 	((struct arpcom *)ifp)->ac_enaddr[1] = 0xe1;
676 	((struct arpcom *)ifp)->ac_enaddr[2] = 0xba;
677 	((struct arpcom *)ifp)->ac_enaddr[3] = 0xd0 | (unit++ & 0xf);
678 	((struct arpcom *)ifp)->ac_enaddr[4] = rng;
679 	((struct arpcom *)ifp)->ac_enaddr[5] = rng >> 8;
680 }
681 
682 /*
683  * Perform common duties while attaching to interface list
684  */
685 void
ether_ifattach(struct ifnet * ifp)686 ether_ifattach(struct ifnet *ifp)
687 {
688 	struct arpcom *ac = (struct arpcom *)ifp;
689 
690 	/*
691 	 * Any interface which provides a MAC address which is obviously
692 	 * invalid gets whacked, so that users will notice.
693 	 */
694 	if (ETHER_IS_MULTICAST(((struct arpcom *)ifp)->ac_enaddr))
695 		ether_fakeaddr(ifp);
696 
697 	ifp->if_type = IFT_ETHER;
698 	ifp->if_addrlen = ETHER_ADDR_LEN;
699 	ifp->if_hdrlen = ETHER_HDR_LEN;
700 	ifp->if_mtu = ETHERMTU;
701 	ifp->if_input = ether_input;
702 	if (ifp->if_output == NULL)
703 		ifp->if_output = ether_output;
704 	ifp->if_rtrequest = ether_rtrequest;
705 
706 	if (ifp->if_hardmtu == 0)
707 		ifp->if_hardmtu = ETHERMTU;
708 
709 	if_alloc_sadl(ifp);
710 	memcpy(LLADDR(ifp->if_sadl), ac->ac_enaddr, ifp->if_addrlen);
711 	LIST_INIT(&ac->ac_multiaddrs);
712 #if NBPFILTER > 0
713 	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN);
714 #endif
715 }
716 
717 void
ether_ifdetach(struct ifnet * ifp)718 ether_ifdetach(struct ifnet *ifp)
719 {
720 	struct arpcom *ac = (struct arpcom *)ifp;
721 	struct ether_multi *enm;
722 
723 	/* Undo pseudo-driver changes. */
724 	if_deactivate(ifp);
725 
726 	while (!LIST_EMPTY(&ac->ac_multiaddrs)) {
727 		enm = LIST_FIRST(&ac->ac_multiaddrs);
728 		LIST_REMOVE(enm, enm_list);
729 		free(enm, M_IFMADDR, sizeof *enm);
730 	}
731 }
732 
733 #if 0
734 /*
735  * This is for reference.  We have table-driven versions of the
736  * crc32 generators, which are faster than the double-loop.
737  */
738 u_int32_t __pure
739 ether_crc32_le_update(u_int_32_t crc, const u_int8_t *buf, size_t len)
740 {
741 	u_int32_t c, carry;
742 	size_t i, j;
743 
744 	for (i = 0; i < len; i++) {
745 		c = buf[i];
746 		for (j = 0; j < 8; j++) {
747 			carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
748 			crc >>= 1;
749 			c >>= 1;
750 			if (carry)
751 				crc = (crc ^ ETHER_CRC_POLY_LE);
752 		}
753 	}
754 
755 	return (crc);
756 }
757 
758 u_int32_t __pure
759 ether_crc32_be_update(u_int_32_t crc, const u_int8_t *buf, size_t len)
760 {
761 	u_int32_t c, carry;
762 	size_t i, j;
763 
764 	for (i = 0; i < len; i++) {
765 		c = buf[i];
766 		for (j = 0; j < 8; j++) {
767 			carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
768 			crc <<= 1;
769 			c >>= 1;
770 			if (carry)
771 				crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
772 		}
773 	}
774 
775 	return (crc);
776 }
777 #else
778 u_int32_t __pure
ether_crc32_le_update(u_int32_t crc,const u_int8_t * buf,size_t len)779 ether_crc32_le_update(u_int32_t crc, const u_int8_t *buf, size_t len)
780 {
781 	static const u_int32_t crctab[] = {
782 		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
783 		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
784 		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
785 		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
786 	};
787 	size_t i;
788 
789 	for (i = 0; i < len; i++) {
790 		crc ^= buf[i];
791 		crc = (crc >> 4) ^ crctab[crc & 0xf];
792 		crc = (crc >> 4) ^ crctab[crc & 0xf];
793 	}
794 
795 	return (crc);
796 }
797 
798 u_int32_t __pure
ether_crc32_be_update(u_int32_t crc,const u_int8_t * buf,size_t len)799 ether_crc32_be_update(u_int32_t crc, const u_int8_t *buf, size_t len)
800 {
801 	static const u_int8_t rev[] = {
802 		0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
803 		0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
804 	};
805 	static const u_int32_t crctab[] = {
806 		0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
807 		0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
808 		0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
809 		0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd
810 	};
811 	size_t i;
812 	u_int8_t data;
813 
814 	for (i = 0; i < len; i++) {
815 		data = buf[i];
816 		crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data & 0xf]];
817 		crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data >> 4]];
818 	}
819 
820 	return (crc);
821 }
822 #endif
823 
824 u_int32_t
ether_crc32_le(const u_int8_t * buf,size_t len)825 ether_crc32_le(const u_int8_t *buf, size_t len)
826 {
827 	return ether_crc32_le_update(0xffffffff, buf, len);
828 }
829 
830 u_int32_t
ether_crc32_be(const u_int8_t * buf,size_t len)831 ether_crc32_be(const u_int8_t *buf, size_t len)
832 {
833 	return ether_crc32_be_update(0xffffffff, buf, len);
834 }
835 
836 u_char	ether_ipmulticast_min[ETHER_ADDR_LEN] =
837     { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
838 u_char	ether_ipmulticast_max[ETHER_ADDR_LEN] =
839     { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
840 
841 #ifdef INET6
842 u_char	ether_ip6multicast_min[ETHER_ADDR_LEN] =
843     { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
844 u_char	ether_ip6multicast_max[ETHER_ADDR_LEN] =
845     { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
846 #endif
847 
848 /*
849  * Convert a sockaddr into an Ethernet address or range of Ethernet
850  * addresses.
851  */
852 int
ether_multiaddr(struct sockaddr * sa,u_int8_t addrlo[ETHER_ADDR_LEN],u_int8_t addrhi[ETHER_ADDR_LEN])853 ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN],
854     u_int8_t addrhi[ETHER_ADDR_LEN])
855 {
856 	struct sockaddr_in *sin;
857 #ifdef INET6
858 	struct sockaddr_in6 *sin6;
859 #endif /* INET6 */
860 
861 	switch (sa->sa_family) {
862 
863 	case AF_UNSPEC:
864 		memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN);
865 		memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
866 		break;
867 
868 	case AF_INET:
869 		sin = satosin(sa);
870 		if (sin->sin_addr.s_addr == INADDR_ANY) {
871 			/*
872 			 * An IP address of INADDR_ANY means listen to
873 			 * or stop listening to all of the Ethernet
874 			 * multicast addresses used for IP.
875 			 * (This is for the sake of IP multicast routers.)
876 			 */
877 			memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN);
878 			memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN);
879 		} else {
880 			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
881 			memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
882 		}
883 		break;
884 #ifdef INET6
885 	case AF_INET6:
886 		sin6 = satosin6(sa);
887 		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
888 			/*
889 			 * An IP6 address of 0 means listen to or stop
890 			 * listening to all of the Ethernet multicast
891 			 * address used for IP6.
892 			 *
893 			 * (This might not be healthy, given IPv6's reliance on
894 			 * multicast for things like neighbor discovery.
895 			 * Perhaps initializing all-nodes, solicited nodes, and
896 			 * possibly all-routers for this interface afterwards
897 			 * is not a bad idea.)
898 			 */
899 
900 			memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN);
901 			memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN);
902 		} else {
903 			ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
904 			memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
905 		}
906 		break;
907 #endif
908 
909 	default:
910 		return (EAFNOSUPPORT);
911 	}
912 	return (0);
913 }
914 
915 /*
916  * Add an Ethernet multicast address or range of addresses to the list for a
917  * given interface.
918  */
919 int
ether_addmulti(struct ifreq * ifr,struct arpcom * ac)920 ether_addmulti(struct ifreq *ifr, struct arpcom *ac)
921 {
922 	struct ether_multi *enm;
923 	u_char addrlo[ETHER_ADDR_LEN];
924 	u_char addrhi[ETHER_ADDR_LEN];
925 	int s = splnet(), error;
926 
927 	error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
928 	if (error != 0) {
929 		splx(s);
930 		return (error);
931 	}
932 
933 	/*
934 	 * Verify that we have valid Ethernet multicast addresses.
935 	 */
936 	if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
937 		splx(s);
938 		return (EINVAL);
939 	}
940 	/*
941 	 * See if the address range is already in the list.
942 	 */
943 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
944 	if (enm != NULL) {
945 		/*
946 		 * Found it; just increment the reference count.
947 		 */
948 		refcnt_take(&enm->enm_refcnt);
949 		splx(s);
950 		return (0);
951 	}
952 	/*
953 	 * New address or range; malloc a new multicast record
954 	 * and link it into the interface's multicast list.
955 	 */
956 	enm = malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
957 	if (enm == NULL) {
958 		splx(s);
959 		return (ENOBUFS);
960 	}
961 	memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN);
962 	memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN);
963 	refcnt_init_trace(&enm->enm_refcnt, DT_REFCNT_IDX_ETHMULTI);
964 	LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list);
965 	ac->ac_multicnt++;
966 	if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
967 		ac->ac_multirangecnt++;
968 	splx(s);
969 	/*
970 	 * Return ENETRESET to inform the driver that the list has changed
971 	 * and its reception filter should be adjusted accordingly.
972 	 */
973 	return (ENETRESET);
974 }
975 
976 /*
977  * Delete a multicast address record.
978  */
979 int
ether_delmulti(struct ifreq * ifr,struct arpcom * ac)980 ether_delmulti(struct ifreq *ifr, struct arpcom *ac)
981 {
982 	struct ether_multi *enm;
983 	u_char addrlo[ETHER_ADDR_LEN];
984 	u_char addrhi[ETHER_ADDR_LEN];
985 	int s = splnet(), error;
986 
987 	error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
988 	if (error != 0) {
989 		splx(s);
990 		return (error);
991 	}
992 
993 	/*
994 	 * Look up the address in our list.
995 	 */
996 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
997 	if (enm == NULL) {
998 		splx(s);
999 		return (ENXIO);
1000 	}
1001 	if (refcnt_rele(&enm->enm_refcnt) == 0) {
1002 		/*
1003 		 * Still some claims to this record.
1004 		 */
1005 		splx(s);
1006 		return (0);
1007 	}
1008 	/*
1009 	 * No remaining claims to this record; unlink and free it.
1010 	 */
1011 	LIST_REMOVE(enm, enm_list);
1012 	free(enm, M_IFMADDR, sizeof *enm);
1013 	ac->ac_multicnt--;
1014 	if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0)
1015 		ac->ac_multirangecnt--;
1016 	splx(s);
1017 	/*
1018 	 * Return ENETRESET to inform the driver that the list has changed
1019 	 * and its reception filter should be adjusted accordingly.
1020 	 */
1021 	return (ENETRESET);
1022 }
1023 
1024 uint64_t
ether_addr_to_e64(const struct ether_addr * ea)1025 ether_addr_to_e64(const struct ether_addr *ea)
1026 {
1027 	uint64_t e64 = 0;
1028 	size_t i;
1029 
1030 	for (i = 0; i < nitems(ea->ether_addr_octet); i++) {
1031 		e64 <<= 8;
1032 		e64 |= ea->ether_addr_octet[i];
1033 	}
1034 
1035 	return (e64);
1036 }
1037 
1038 void
ether_e64_to_addr(struct ether_addr * ea,uint64_t e64)1039 ether_e64_to_addr(struct ether_addr *ea, uint64_t e64)
1040 {
1041 	size_t i = nitems(ea->ether_addr_octet);
1042 
1043 	do {
1044 		ea->ether_addr_octet[--i] = e64;
1045 		e64 >>= 8;
1046 	} while (i > 0);
1047 }
1048 
1049 /* Parse different TCP/IP protocol headers for a quick view inside an mbuf. */
1050 void
ether_extract_headers(struct mbuf * m0,struct ether_extracted * ext)1051 ether_extract_headers(struct mbuf *m0, struct ether_extracted *ext)
1052 {
1053 	struct mbuf	*m;
1054 	size_t		 hlen, iplen;
1055 	int		 hoff;
1056 	uint8_t		 ipproto;
1057 	uint16_t	 ether_type;
1058 	/* gcc 4.2.1 on sparc64 may create 32 bit loads on unaligned mbuf */
1059 	union {
1060 		u_char	hc_data;
1061 #if _BYTE_ORDER == _LITTLE_ENDIAN
1062 		struct {
1063 			u_int	hl:4,	/* header length */
1064 				v:4;	/* version */
1065 		} hc_ip;
1066 		struct {
1067 			u_int	x2:4,	/* (unused) */
1068 				off:4;	/* data offset */
1069 		} hc_th;
1070 #endif
1071 #if _BYTE_ORDER == _BIG_ENDIAN
1072 		struct {
1073 			u_int	v:4,	/* version */
1074 				hl:4;	/* header length */
1075 		} hc_ip;
1076 		struct {
1077 			u_int	off:4,	/* data offset */
1078 				x2:4;	/* (unused) */
1079 		} hc_th;
1080 #endif
1081 	} hdrcpy;
1082 
1083 	/* Return NULL if header was not recognized. */
1084 	memset(ext, 0, sizeof(*ext));
1085 
1086 	KASSERT(ISSET(m0->m_flags, M_PKTHDR));
1087 	ext->paylen = m0->m_pkthdr.len;
1088 
1089 	if (m0->m_len < sizeof(*ext->eh)) {
1090 		DPRINTF("m_len %d, eh %zu", m0->m_len, sizeof(*ext->eh));
1091 		return;
1092 	}
1093 	ext->eh = mtod(m0, struct ether_header *);
1094 	ether_type = ntohs(ext->eh->ether_type);
1095 	hlen = sizeof(*ext->eh);
1096 	if (ext->paylen < hlen) {
1097 		DPRINTF("paylen %u, ehlen %zu", ext->paylen, hlen);
1098 		ext->eh = NULL;
1099 		return;
1100 	}
1101 	ext->paylen -= hlen;
1102 
1103 #if NVLAN > 0
1104 	if (ether_type == ETHERTYPE_VLAN) {
1105 		if (m0->m_len < sizeof(*ext->evh)) {
1106 			DPRINTF("m_len %d, evh %zu",
1107 			    m0->m_len, sizeof(*ext->evh));
1108 			return;
1109 		}
1110 		ext->evh = mtod(m0, struct ether_vlan_header *);
1111 		ether_type = ntohs(ext->evh->evl_proto);
1112 		hlen = sizeof(*ext->evh);
1113 		if (sizeof(*ext->eh) + ext->paylen < hlen) {
1114 			DPRINTF("paylen %zu, evhlen %zu",
1115 			    sizeof(*ext->eh) + ext->paylen, hlen);
1116 			ext->evh = NULL;
1117 			return;
1118 		}
1119 		ext->paylen = sizeof(*ext->eh) + ext->paylen - hlen;
1120 	}
1121 #endif
1122 
1123 	switch (ether_type) {
1124 	case ETHERTYPE_IP:
1125 		m = m_getptr(m0, hlen, &hoff);
1126 		if (m == NULL || m->m_len - hoff < sizeof(*ext->ip4)) {
1127 			DPRINTF("m_len %d, hoff %d, ip4 %zu",
1128 			    m ? m->m_len : -1, hoff, sizeof(*ext->ip4));
1129 			return;
1130 		}
1131 		ext->ip4 = (struct ip *)(mtod(m, caddr_t) + hoff);
1132 
1133 		memcpy(&hdrcpy.hc_data, ext->ip4, 1);
1134 		hlen = hdrcpy.hc_ip.hl << 2;
1135 		if (m->m_len - hoff < hlen) {
1136 			DPRINTF("m_len %d, hoff %d, iphl %zu",
1137 			    m ? m->m_len : -1, hoff, hlen);
1138 			ext->ip4 = NULL;
1139 			return;
1140 		}
1141 		if (ext->paylen < hlen) {
1142 			DPRINTF("paylen %u, ip4hlen %zu", ext->paylen, hlen);
1143 			ext->ip4 = NULL;
1144 			return;
1145 		}
1146 		iplen = ntohs(ext->ip4->ip_len);
1147 		if (ext->paylen < iplen) {
1148 			DPRINTF("paylen %u, ip4len %zu", ext->paylen, iplen);
1149 			ext->ip4 = NULL;
1150 			return;
1151 		}
1152 		if (iplen < hlen) {
1153 			DPRINTF("ip4len %zu, ip4hlen %zu", iplen, hlen);
1154 			ext->ip4 = NULL;
1155 			return;
1156 		}
1157 		ext->iplen = iplen;
1158 		ext->iphlen = hlen;
1159 		ext->paylen -= hlen;
1160 		ipproto = ext->ip4->ip_p;
1161 
1162 		if (ISSET(ntohs(ext->ip4->ip_off), IP_MF|IP_OFFMASK))
1163 			return;
1164 		break;
1165 #ifdef INET6
1166 	case ETHERTYPE_IPV6:
1167 		m = m_getptr(m0, hlen, &hoff);
1168 		if (m == NULL || m->m_len - hoff < sizeof(*ext->ip6)) {
1169 			DPRINTF("m_len %d, hoff %d, ip6 %zu",
1170 			    m ? m->m_len : -1, hoff, sizeof(*ext->ip6));
1171 			return;
1172 		}
1173 		ext->ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + hoff);
1174 
1175 		hlen = sizeof(*ext->ip6);
1176 		if (ext->paylen < hlen) {
1177 			DPRINTF("paylen %u, ip6hlen %zu", ext->paylen, hlen);
1178 			ext->ip6 = NULL;
1179 			return;
1180 		}
1181 		iplen = hlen + ntohs(ext->ip6->ip6_plen);
1182 		if (ext->paylen < iplen) {
1183 			DPRINTF("paylen %u, ip6len %zu", ext->paylen, iplen);
1184 			ext->ip6 = NULL;
1185 			return;
1186 		}
1187 		ext->iplen = iplen;
1188 		ext->iphlen = hlen;
1189 		ext->paylen -= hlen;
1190 		ipproto = ext->ip6->ip6_nxt;
1191 		break;
1192 #endif
1193 	default:
1194 		return;
1195 	}
1196 
1197 	switch (ipproto) {
1198 	case IPPROTO_TCP:
1199 		m = m_getptr(m, hoff + hlen, &hoff);
1200 		if (m == NULL || m->m_len - hoff < sizeof(*ext->tcp)) {
1201 			DPRINTF("m_len %d, hoff %d, tcp %zu",
1202 			    m ? m->m_len : -1, hoff, sizeof(*ext->tcp));
1203 			return;
1204 		}
1205 		ext->tcp = (struct tcphdr *)(mtod(m, caddr_t) + hoff);
1206 
1207 		memcpy(&hdrcpy.hc_data, &ext->tcp->th_flags - 1, 1);
1208 		hlen = hdrcpy.hc_th.off << 2;
1209 		if (m->m_len - hoff < hlen) {
1210 			DPRINTF("m_len %d, hoff %d, thoff %zu",
1211 			    m ? m->m_len : -1, hoff, hlen);
1212 			ext->tcp = NULL;
1213 			return;
1214 		}
1215 		if (ext->iplen - ext->iphlen < hlen) {
1216 			DPRINTF("iplen %u, iphlen %u, tcphlen %zu",
1217 			    ext->iplen, ext->iphlen, hlen);
1218 			ext->tcp = NULL;
1219 			return;
1220 		}
1221 		ext->tcphlen = hlen;
1222 		ext->paylen -= hlen;
1223 		break;
1224 
1225 	case IPPROTO_UDP:
1226 		m = m_getptr(m, hoff + hlen, &hoff);
1227 		if (m == NULL || m->m_len - hoff < sizeof(*ext->udp)) {
1228 			DPRINTF("m_len %d, hoff %d, tcp %zu",
1229 			    m ? m->m_len : -1, hoff, sizeof(*ext->tcp));
1230 			return;
1231 		}
1232 		ext->udp = (struct udphdr *)(mtod(m, caddr_t) + hoff);
1233 
1234 		hlen = sizeof(*ext->udp);
1235 		if (ext->iplen - ext->iphlen < hlen) {
1236 			DPRINTF("iplen %u, iphlen %u, udphlen %zu",
1237 			    ext->iplen, ext->iphlen, hlen);
1238 			ext->udp = NULL;
1239 			return;
1240 		}
1241 		break;
1242 	}
1243 
1244 	DNPRINTF(2, "%s%s%s%s%s%s ip %u, iph %u, tcph %u, payl %u",
1245 	    ext->eh ? "eh," : "", ext->evh ? "evh," : "",
1246 	    ext->ip4 ? "ip4," : "", ext->ip6 ? "ip6," : "",
1247 	    ext->tcp ? "tcp," : "", ext->udp ? "udp," : "",
1248 	    ext->iplen, ext->iphlen, ext->tcphlen, ext->paylen);
1249 }
1250