xref: /openbsd-src/sys/net/if_etherip.c (revision 68dd5bb1859285b71cb62a10bf107b8ad54064d9)
1 /*	$OpenBSD: if_etherip.c,v 1.54 2023/12/23 10:52:54 bluhm Exp $	*/
2 /*
3  * Copyright (c) 2015 Kazuya GODA <goda@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include "bpfilter.h"
19 #include "pf.h"
20 
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 #include <sys/mbuf.h>
24 #include <sys/socket.h>
25 #include <sys/ioctl.h>
26 #include <sys/device.h>
27 #include <sys/sysctl.h>
28 #include <sys/tree.h>
29 
30 #include <net/if.h>
31 #include <net/if_var.h>
32 #include <net/if_dl.h>
33 #include <net/if_media.h>
34 #include <net/rtable.h>
35 
36 #include <netinet/in.h>
37 #include <netinet/ip.h>
38 #include <netinet/ip_var.h>
39 #include <netinet/if_ether.h>
40 #include <netinet/ip_ether.h>
41 
42 #ifdef INET6
43 #include <netinet/ip6.h>
44 #include <netinet6/ip6_var.h>
45 #endif
46 
47 #if NBPFILTER > 0
48 #include <net/bpf.h>
49 #endif
50 
51 #if NPF > 0
52 #include <net/pfvar.h>
53 #endif
54 
55 #include <net/if_etherip.h>
56 
57 union etherip_addr {
58 	struct in_addr	in4;
59 	struct in6_addr	in6;
60 };
61 
62 struct etherip_tunnel {
63 	union etherip_addr
64 			_t_src;
65 #define t_src4	_t_src.in4
66 #define t_src6	_t_src.in6
67 	union etherip_addr
68 			_t_dst;
69 #define t_dst4	_t_dst.in4
70 #define t_dst6	_t_dst.in6
71 
72 	unsigned int	t_rtableid;
73 	sa_family_t	t_af;
74 	uint8_t		t_tos;
75 
76 	TAILQ_ENTRY(etherip_tunnel)
77 			t_entry;
78 };
79 
80 TAILQ_HEAD(etherip_list, etherip_tunnel);
81 
82 static inline int etherip_cmp(const struct etherip_tunnel *,
83     const struct etherip_tunnel *);
84 
85 struct etherip_softc {
86 	struct etherip_tunnel	sc_tunnel; /* must be first */
87 	struct arpcom		sc_ac;
88 	struct ifmedia		sc_media;
89 	int			sc_txhprio;
90 	int			sc_rxhprio;
91 	uint16_t		sc_df;
92 	uint8_t			sc_ttl;
93 };
94 
95 /*
96  * We can control the acceptance of EtherIP packets by altering the sysctl
97  * net.inet.etherip.allow value. Zero means drop them, all else is acceptance.
98  */
99 int etherip_allow = 0;
100 
101 struct cpumem *etheripcounters;
102 
103 void etheripattach(int);
104 int etherip_clone_create(struct if_clone *, int);
105 int etherip_clone_destroy(struct ifnet *);
106 int etherip_ioctl(struct ifnet *, u_long, caddr_t);
107 int etherip_output(struct ifnet *, struct mbuf *, struct sockaddr *,
108     struct rtentry *);
109 void etherip_start(struct ifnet *);
110 int etherip_media_change(struct ifnet *);
111 void etherip_media_status(struct ifnet *, struct ifmediareq *);
112 int etherip_set_tunnel(struct etherip_softc *, struct if_laddrreq *);
113 int etherip_get_tunnel(struct etherip_softc *, struct if_laddrreq *);
114 int etherip_del_tunnel(struct etherip_softc *);
115 int etherip_up(struct etherip_softc *);
116 int etherip_down(struct etherip_softc *);
117 struct etherip_softc *etherip_find(const struct etherip_tunnel *);
118 int etherip_input(struct etherip_tunnel *, struct mbuf *, uint8_t, int);
119 
120 struct if_clone	etherip_cloner = IF_CLONE_INITIALIZER("etherip",
121     etherip_clone_create, etherip_clone_destroy);
122 
123 struct etherip_list etherip_list = TAILQ_HEAD_INITIALIZER(etherip_list);
124 
125 void
126 etheripattach(int count)
127 {
128 	if_clone_attach(&etherip_cloner);
129 	etheripcounters = counters_alloc(etherips_ncounters);
130 }
131 
132 int
133 etherip_clone_create(struct if_clone *ifc, int unit)
134 {
135 	struct ifnet *ifp;
136 	struct etherip_softc *sc;
137 
138 	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
139 	ifp = &sc->sc_ac.ac_if;
140 
141 	snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d",
142 	    ifc->ifc_name, unit);
143 
144 	sc->sc_ttl = ip_defttl;
145 	sc->sc_txhprio = IFQ_TOS2PRIO(IPTOS_PREC_ROUTINE); /* 0 */
146 	sc->sc_rxhprio = IF_HDRPRIO_PACKET;
147 	sc->sc_df = htons(0);
148 
149 	ifp->if_softc = sc;
150 	ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN;
151 	ifp->if_ioctl = etherip_ioctl;
152 	ifp->if_output = etherip_output;
153 	ifp->if_start = etherip_start;
154 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
155 	ifp->if_xflags = IFXF_CLONED;
156 	ifp->if_capabilities = IFCAP_VLAN_MTU;
157 	ether_fakeaddr(ifp);
158 
159 	ifmedia_init(&sc->sc_media, 0, etherip_media_change,
160 	    etherip_media_status);
161 	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
162 	ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
163 
164 	if_counters_alloc(ifp);
165 	if_attach(ifp);
166 	ether_ifattach(ifp);
167 
168 	NET_LOCK();
169 	TAILQ_INSERT_TAIL(&etherip_list, &sc->sc_tunnel, t_entry);
170 	NET_UNLOCK();
171 
172 	return (0);
173 }
174 
175 int
176 etherip_clone_destroy(struct ifnet *ifp)
177 {
178 	struct etherip_softc *sc = ifp->if_softc;
179 
180 	NET_LOCK();
181 	if (ISSET(ifp->if_flags, IFF_RUNNING))
182 		etherip_down(sc);
183 
184 	TAILQ_REMOVE(&etherip_list, &sc->sc_tunnel, t_entry);
185 	NET_UNLOCK();
186 
187 	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
188 	ether_ifdetach(ifp);
189 	if_detach(ifp);
190 
191 	free(sc, M_DEVBUF, sizeof(*sc));
192 
193 	return (0);
194 }
195 
196 int
197 etherip_media_change(struct ifnet *ifp)
198 {
199 	return 0;
200 }
201 
202 void
203 etherip_media_status(struct ifnet *ifp, struct ifmediareq *imr)
204 {
205 	imr->ifm_active = IFM_ETHER | IFM_AUTO;
206 	imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
207 }
208 
209 int
210 etherip_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
211     struct rtentry *rt)
212 {
213  	struct m_tag *mtag;
214 
215 	mtag = NULL;
216 	while ((mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) != NULL) {
217 		if (*(int *)(mtag + 1) == ifp->if_index) {
218 			m_freem(m);
219 			return (EIO);
220 		}
221 	}
222 
223 	return (ether_output(ifp, m, dst, rt));
224 }
225 
226 void
227 etherip_start(struct ifnet *ifp)
228 {
229 	struct etherip_softc *sc = ifp->if_softc;
230 	struct mbuf *m;
231 	int error;
232 #if NBPFILTER > 0
233 	caddr_t if_bpf;
234 #endif
235 
236 	while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) {
237 #if NBPFILTER > 0
238 		if_bpf = ifp->if_bpf;
239 		if (if_bpf)
240 			bpf_mtap_ether(if_bpf, m, BPF_DIRECTION_OUT);
241 #endif
242 
243 		switch (sc->sc_tunnel.t_af) {
244 		case AF_INET:
245 			error = ip_etherip_output(ifp, m);
246 			break;
247 #ifdef INET6
248 		case AF_INET6:
249 			error = ip6_etherip_output(ifp, m);
250 			break;
251 #endif
252 		default:
253 			/* unhandled_af(sc->sc_tunnel.t_af); */
254 			m_freem(m);
255 			continue;
256 		}
257 
258 		if (error)
259 			ifp->if_oerrors++;
260 	}
261 }
262 
263 int
264 etherip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
265 {
266 	struct etherip_softc *sc = ifp->if_softc;
267 	struct ifreq *ifr = (struct ifreq *)data;
268 	int error = 0;
269 
270 	switch (cmd) {
271 	case SIOCSIFADDR:
272 		ifp->if_flags |= IFF_UP;
273 		/* FALLTHROUGH */
274 
275 	case SIOCSIFFLAGS:
276 		if (ISSET(ifp->if_flags, IFF_UP)) {
277 			if (!ISSET(ifp->if_flags, IFF_RUNNING))
278 				error = etherip_up(sc);
279 			else
280 				error = 0;
281 		} else {
282 			if (ISSET(ifp->if_flags, IFF_RUNNING))
283 				error = etherip_down(sc);
284 		}
285 		break;
286 
287 	case SIOCSLIFPHYRTABLE:
288 		if (ifr->ifr_rdomainid < 0 ||
289 		    ifr->ifr_rdomainid > RT_TABLEID_MAX ||
290 		    !rtable_exists(ifr->ifr_rdomainid)) {
291 			error = EINVAL;
292 			break;
293 		}
294 		sc->sc_tunnel.t_rtableid = ifr->ifr_rdomainid;
295 		break;
296 
297 	case SIOCGLIFPHYRTABLE:
298 		ifr->ifr_rdomainid = sc->sc_tunnel.t_rtableid;
299 		break;
300 
301 	case SIOCSLIFPHYADDR:
302 		error = etherip_set_tunnel(sc, (struct if_laddrreq *)data);
303 		break;
304 	case SIOCGLIFPHYADDR:
305 		error = etherip_get_tunnel(sc, (struct if_laddrreq *)data);
306 		break;
307 	case SIOCDIFPHYADDR:
308 		error = etherip_del_tunnel(sc);
309 		break;
310 
311 	case SIOCSTXHPRIO:
312 		error = if_txhprio_l2_check(ifr->ifr_hdrprio);
313 		if (error != 0)
314 			break;
315 
316 		sc->sc_txhprio = ifr->ifr_hdrprio;
317 		break;
318 	case SIOCGTXHPRIO:
319 		ifr->ifr_hdrprio = sc->sc_txhprio;
320                 break;
321 
322 	case SIOCSRXHPRIO:
323 		error = if_rxhprio_l2_check(ifr->ifr_hdrprio);
324 		if (error != 0)
325 			break;
326 
327 		sc->sc_rxhprio = ifr->ifr_hdrprio;
328 		break;
329 	case SIOCGRXHPRIO:
330 		ifr->ifr_hdrprio = sc->sc_rxhprio;
331                 break;
332 
333 	case SIOCSLIFPHYTTL:
334 		if (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff) {
335 			error = EINVAL;
336 			break;
337 		}
338 
339 		/* commit */
340 		sc->sc_ttl = (uint8_t)ifr->ifr_ttl;
341 		break;
342 	case SIOCGLIFPHYTTL:
343 		ifr->ifr_ttl = (int)sc->sc_ttl;
344 		break;
345 
346 	case SIOCSLIFPHYDF:
347 		/* commit */
348 		sc->sc_df = ifr->ifr_df ? htons(IP_DF) : htons(0);
349 		break;
350 	case SIOCGLIFPHYDF:
351 		ifr->ifr_df = sc->sc_df ? 1 : 0;
352 		break;
353 
354 	case SIOCSIFMEDIA:
355 	case SIOCGIFMEDIA:
356 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
357 		break;
358 
359 	case SIOCADDMULTI:
360 	case SIOCDELMULTI:
361 		break;
362 
363 	default:
364 		error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
365 		break;
366 	}
367 
368 	if (error == ENETRESET) {
369 		/* no hardware to program */
370 		error = 0;
371 	}
372 
373 	return (error);
374 }
375 
376 int
377 etherip_set_tunnel(struct etherip_softc *sc, struct if_laddrreq *req)
378 {
379 	struct sockaddr *src = (struct sockaddr *)&req->addr;
380 	struct sockaddr *dst = (struct sockaddr *)&req->dstaddr;
381 	struct sockaddr_in *src4, *dst4;
382 #ifdef INET6
383 	struct sockaddr_in6 *src6, *dst6;
384 	int error;
385 #endif
386 
387 	/* sa_family and sa_len must be equal */
388 	if (src->sa_family != dst->sa_family || src->sa_len != dst->sa_len)
389 		return (EINVAL);
390 
391 	/* validate */
392 	switch (dst->sa_family) {
393 	case AF_INET:
394 		if (dst->sa_len != sizeof(*dst4))
395 			return (EINVAL);
396 
397 		src4 = (struct sockaddr_in *)src;
398 		if (in_nullhost(src4->sin_addr) ||
399 		    IN_MULTICAST(src4->sin_addr.s_addr))
400 			return (EINVAL);
401 
402 		dst4 = (struct sockaddr_in *)dst;
403 		if (in_nullhost(dst4->sin_addr) ||
404 		    IN_MULTICAST(dst4->sin_addr.s_addr))
405 			return (EINVAL);
406 
407 		sc->sc_tunnel.t_src4 = src4->sin_addr;
408 		sc->sc_tunnel.t_dst4 = dst4->sin_addr;
409 		break;
410 #ifdef INET6
411 	case AF_INET6:
412 		if (dst->sa_len != sizeof(*dst6))
413 			return (EINVAL);
414 
415 		src6 = (struct sockaddr_in6 *)src;
416 		if (IN6_IS_ADDR_UNSPECIFIED(&src6->sin6_addr) ||
417 		    IN6_IS_ADDR_MULTICAST(&src6->sin6_addr))
418 			return (EINVAL);
419 
420 		dst6 = (struct sockaddr_in6 *)dst;
421 		if (IN6_IS_ADDR_UNSPECIFIED(&dst6->sin6_addr) ||
422 		    IN6_IS_ADDR_MULTICAST(&dst6->sin6_addr))
423 			return (EINVAL);
424 
425 		error = in6_embedscope(&sc->sc_tunnel.t_src6, src6, NULL, NULL);
426 		if (error != 0)
427 			return (error);
428 
429 		error = in6_embedscope(&sc->sc_tunnel.t_dst6, dst6, NULL, NULL);
430 		if (error != 0)
431 			return (error);
432 
433 		break;
434 #endif
435 	default:
436 		return (EAFNOSUPPORT);
437 	}
438 
439 	/* commit */
440 	sc->sc_tunnel.t_af = dst->sa_family;
441 
442 	return (0);
443 }
444 
445 int
446 etherip_get_tunnel(struct etherip_softc *sc, struct if_laddrreq *req)
447 {
448 	struct sockaddr *src = (struct sockaddr *)&req->addr;
449 	struct sockaddr *dst = (struct sockaddr *)&req->dstaddr;
450 	struct sockaddr_in *sin;
451 #ifdef INET6 /* ifconfig already embeds the scopeid */
452 	struct sockaddr_in6 *sin6;
453 #endif
454 
455 	switch (sc->sc_tunnel.t_af) {
456 	case AF_UNSPEC:
457 		return (EADDRNOTAVAIL);
458 	case AF_INET:
459 		sin = (struct sockaddr_in *)src;
460 		memset(sin, 0, sizeof(*sin));
461 		sin->sin_family = AF_INET;
462 		sin->sin_len = sizeof(*sin);
463 		sin->sin_addr = sc->sc_tunnel.t_src4;
464 
465 		sin = (struct sockaddr_in *)dst;
466 		memset(sin, 0, sizeof(*sin));
467 		sin->sin_family = AF_INET;
468 		sin->sin_len = sizeof(*sin);
469 		sin->sin_addr = sc->sc_tunnel.t_dst4;
470 
471 		break;
472 #ifdef INET6
473 	case AF_INET6:
474 		sin6 = (struct sockaddr_in6 *)src;
475 		memset(sin6, 0, sizeof(*sin6));
476 		sin6->sin6_family = AF_INET6;
477 		sin6->sin6_len = sizeof(*sin6);
478 		in6_recoverscope(sin6, &sc->sc_tunnel.t_src6);
479 
480 		sin6 = (struct sockaddr_in6 *)dst;
481 		memset(sin6, 0, sizeof(*sin6));
482 		sin6->sin6_family = AF_INET6;
483 		sin6->sin6_len = sizeof(*sin6);
484 		in6_recoverscope(sin6, &sc->sc_tunnel.t_dst6);
485 
486 		break;
487 #endif
488 	default:
489 		return (EAFNOSUPPORT);
490 	}
491 
492 	return (0);
493 }
494 
495 int
496 etherip_del_tunnel(struct etherip_softc *sc)
497 {
498 	/* commit */
499 	sc->sc_tunnel.t_af = AF_UNSPEC;
500 
501 	return (0);
502 }
503 
504 int
505 etherip_up(struct etherip_softc *sc)
506 {
507 	struct ifnet *ifp = &sc->sc_ac.ac_if;
508 
509 	NET_ASSERT_LOCKED();
510 
511 	SET(ifp->if_flags, IFF_RUNNING);
512 
513 	return (0);
514 }
515 
516 int
517 etherip_down(struct etherip_softc *sc)
518 {
519 	struct ifnet *ifp = &sc->sc_ac.ac_if;
520 
521 	NET_ASSERT_LOCKED();
522 
523 	CLR(ifp->if_flags, IFF_RUNNING);
524 
525 	return (0);
526 }
527 
528 int
529 ip_etherip_output(struct ifnet *ifp, struct mbuf *m)
530 {
531 	struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
532 	struct m_tag *mtag;
533 	struct etherip_header *eip;
534 	struct ip *ip;
535 
536 	M_PREPEND(m, sizeof(*ip) + sizeof(*eip), M_DONTWAIT);
537 	if (m == NULL) {
538 		etheripstat_inc(etherips_adrops);
539 		return ENOBUFS;
540 	}
541 
542 	ip = mtod(m, struct ip *);
543 	memset(ip, 0, sizeof(struct ip));
544 
545 	ip->ip_v = IPVERSION;
546 	ip->ip_hl = sizeof(*ip) >> 2;
547 	ip->ip_tos = IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ?
548 	    m->m_pkthdr.pf.prio : sc->sc_txhprio);
549 	ip->ip_len = htons(m->m_pkthdr.len);
550 	ip->ip_id = htons(ip_randomid());
551 	ip->ip_off = sc->sc_df;
552 	ip->ip_ttl = sc->sc_ttl;
553 	ip->ip_p = IPPROTO_ETHERIP;
554 	ip->ip_src = sc->sc_tunnel.t_src4;
555 	ip->ip_dst = sc->sc_tunnel.t_dst4;
556 
557 	eip = (struct etherip_header *)(ip + 1);
558 	eip->eip_ver = ETHERIP_VERSION;
559 	eip->eip_res = 0;
560 	eip->eip_pad = 0;
561 
562 	mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT);
563 	if (mtag == NULL) {
564 		m_freem(m);
565 		return (ENOMEM);
566 	}
567 
568 	*(int *)(mtag + 1) = ifp->if_index;
569 	m_tag_prepend(m, mtag);
570 
571 	m->m_flags &= ~(M_BCAST|M_MCAST);
572 	m->m_pkthdr.ph_rtableid = sc->sc_tunnel.t_rtableid;
573 
574 #if NPF > 0
575 	pf_pkt_addr_changed(m);
576 #endif
577 	etheripstat_pkt(etherips_opackets, etherips_obytes, m->m_pkthdr.len -
578 	    (sizeof(struct ip) + sizeof(struct etherip_header)));
579 
580 	ip_send(m);
581 
582 	return (0);
583 }
584 
585 int
586 ip_etherip_input(struct mbuf **mp, int *offp, int type, int af)
587 {
588 	struct mbuf *m = *mp;
589 	struct etherip_tunnel key;
590 	struct ip *ip;
591 
592 	ip = mtod(m, struct ip *);
593 
594 	key.t_af = AF_INET;
595 	key.t_src4 = ip->ip_dst;
596 	key.t_dst4 = ip->ip_src;
597 
598 	return (etherip_input(&key, m, ip->ip_tos, *offp));
599 }
600 
601 struct etherip_softc *
602 etherip_find(const struct etherip_tunnel *key)
603 {
604 	struct etherip_tunnel *t;
605 	struct etherip_softc *sc;
606 
607 	TAILQ_FOREACH(t, &etherip_list, t_entry) {
608 		if (etherip_cmp(key, t) != 0)
609 			continue;
610 
611 		sc = (struct etherip_softc *)t;
612 		if (!ISSET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING))
613 			continue;
614 
615 		return (sc);
616 	}
617 
618 	return (NULL);
619 }
620 
621 int
622 etherip_input(struct etherip_tunnel *key, struct mbuf *m, uint8_t tos,
623     int hlen)
624 {
625 	struct etherip_softc *sc;
626 	struct ifnet *ifp;
627 	struct etherip_header *eip;
628 	int rxprio;
629 
630 	if (!etherip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0) {
631 		etheripstat_inc(etherips_pdrops);
632 		goto drop;
633 	}
634 
635 	key->t_rtableid = m->m_pkthdr.ph_rtableid;
636 
637 	NET_ASSERT_LOCKED();
638 	sc = etherip_find(key);
639 	if (sc == NULL) {
640 		etheripstat_inc(etherips_noifdrops);
641 		goto drop;
642 	}
643 
644 	m_adj(m, hlen);
645 	m = m_pullup(m, sizeof(*eip));
646 	if (m == NULL) {
647 		etheripstat_inc(etherips_adrops);
648 		return IPPROTO_DONE;
649 	}
650 
651 	eip = mtod(m, struct etherip_header *);
652 	if (eip->eip_ver != ETHERIP_VERSION || eip->eip_pad) {
653 		etheripstat_inc(etherips_adrops);
654 		goto drop;
655 	}
656 
657 	m_adj(m, sizeof(struct etherip_header));
658 
659 	etheripstat_pkt(etherips_ipackets, etherips_ibytes, m->m_pkthdr.len);
660 
661 	m = m_pullup(m, sizeof(struct ether_header));
662 	if (m == NULL) {
663 		etheripstat_inc(etherips_adrops);
664 		return IPPROTO_DONE;
665 	}
666 
667 	rxprio = sc->sc_rxhprio;
668 	switch (rxprio) {
669 	case IF_HDRPRIO_PACKET:
670 		break;
671 	case IF_HDRPRIO_OUTER:
672 		m->m_pkthdr.pf.prio = IFQ_TOS2PRIO(tos);
673 		break;
674 	default:
675 		m->m_pkthdr.pf.prio = rxprio;
676 		break;
677 	}
678 
679 	ifp = &sc->sc_ac.ac_if;
680 
681 	m->m_flags &= ~(M_BCAST|M_MCAST);
682 	m->m_pkthdr.ph_ifidx = ifp->if_index;
683 	m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
684 
685 #if NPF > 0
686 	pf_pkt_addr_changed(m);
687 #endif
688 
689 	if_vinput(ifp, m);
690 	return IPPROTO_DONE;
691 
692 drop:
693 	m_freem(m);
694 	return (IPPROTO_DONE);
695 }
696 
697 #ifdef INET6
698 int
699 ip6_etherip_output(struct ifnet *ifp, struct mbuf *m)
700 {
701 	struct etherip_softc *sc = ifp->if_softc;
702 	struct m_tag *mtag;
703 	struct ip6_hdr *ip6;
704 	struct etherip_header *eip;
705 	uint16_t len;
706 	uint32_t flow;
707 
708 	if (IN6_IS_ADDR_UNSPECIFIED(&sc->sc_tunnel.t_dst6)) {
709 		m_freem(m);
710 		return (ENETUNREACH);
711 	}
712 
713 	len = m->m_pkthdr.len;
714 
715 	M_PREPEND(m, sizeof(*ip6) + sizeof(*eip), M_DONTWAIT);
716 	if (m == NULL) {
717 		etheripstat_inc(etherips_adrops);
718 		return ENOBUFS;
719 	}
720 
721 	flow = IPV6_VERSION << 24;
722 	flow |= IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ?
723 	     m->m_pkthdr.pf.prio : sc->sc_txhprio) << 20;
724 
725 	ip6 = mtod(m, struct ip6_hdr *);
726 	htobem32(&ip6->ip6_flow, flow);
727 	ip6->ip6_nxt  = IPPROTO_ETHERIP;
728 	ip6->ip6_hlim = sc->sc_ttl;
729 	ip6->ip6_plen = htons(len);
730 	memcpy(&ip6->ip6_src, &sc->sc_tunnel.t_src6, sizeof(ip6->ip6_src));
731 	memcpy(&ip6->ip6_dst, &sc->sc_tunnel.t_dst6, sizeof(ip6->ip6_dst));
732 
733 	eip = (struct etherip_header *)(ip6 + 1);
734 	eip->eip_ver = ETHERIP_VERSION;
735 	eip->eip_res = 0;
736 	eip->eip_pad = 0;
737 
738 	mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT);
739 	if (mtag == NULL) {
740 		m_freem(m);
741 		return (ENOMEM);
742 	}
743 
744 	*(int *)(mtag + 1) = ifp->if_index;
745 	m_tag_prepend(m, mtag);
746 
747 	if (sc->sc_df)
748 		SET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT);
749 
750 	m->m_flags &= ~(M_BCAST|M_MCAST);
751 	m->m_pkthdr.ph_rtableid = sc->sc_tunnel.t_rtableid;
752 
753 #if NPF > 0
754 	pf_pkt_addr_changed(m);
755 #endif
756 
757 	etheripstat_pkt(etherips_opackets, etherips_obytes, len);
758 
759 	ip6_send(m);
760 	return (0);
761 }
762 
763 int
764 ip6_etherip_input(struct mbuf **mp, int *offp, int proto, int af)
765 {
766 	struct mbuf *m = *mp;
767 	struct etherip_tunnel key;
768 	const struct ip6_hdr *ip6;
769 	uint32_t flow;
770 
771 	ip6 = mtod(m, const struct ip6_hdr *);
772 
773 	key.t_af = AF_INET6;
774 	key.t_src6 = ip6->ip6_dst;
775 	key.t_dst6 = ip6->ip6_src;
776 
777 	flow = bemtoh32(&ip6->ip6_flow);
778 
779 	return (etherip_input(&key, m, flow >> 20, *offp));
780 }
781 #endif /* INET6 */
782 
783 int
784 etherip_sysctl_etheripstat(void *oldp, size_t *oldlenp, void *newp)
785 {
786 	struct etheripstat etheripstat;
787 
788 	CTASSERT(sizeof(etheripstat) == (etherips_ncounters *
789 	    sizeof(uint64_t)));
790 	memset(&etheripstat, 0, sizeof etheripstat);
791 	counters_read(etheripcounters, (uint64_t *)&etheripstat,
792 	    etherips_ncounters, NULL);
793 	return (sysctl_rdstruct(oldp, oldlenp, newp, &etheripstat,
794 	    sizeof(etheripstat)));
795 }
796 
797 int
798 etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
799     void *newp, size_t newlen)
800 {
801 	int error;
802 
803 	/* All sysctl names at this level are terminal. */
804 	if (namelen != 1)
805 		return ENOTDIR;
806 
807 	switch (name[0]) {
808 	case ETHERIPCTL_ALLOW:
809 		NET_LOCK();
810 		error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
811 		    &etherip_allow, 0, 1);
812 		NET_UNLOCK();
813 		return (error);
814 	case ETHERIPCTL_STATS:
815 		return (etherip_sysctl_etheripstat(oldp, oldlenp, newp));
816 	default:
817 		break;
818 	}
819 
820 	return ENOPROTOOPT;
821 }
822 
823 static inline int
824 etherip_ip_cmp(int af, const union etherip_addr *a, const union etherip_addr *b)
825 {
826 	switch (af) {
827 #ifdef INET6
828 	case AF_INET6:
829 		return (memcmp(&a->in6, &b->in6, sizeof(a->in6)));
830 		/* FALLTHROUGH */
831 #endif /* INET6 */
832 	case AF_INET:
833 		return (memcmp(&a->in4, &b->in4, sizeof(a->in4)));
834 		break;
835 	default:
836 		panic("%s: unsupported af %d", __func__, af);
837 	}
838 
839 	return (0);
840 }
841 
842 static inline int
843 etherip_cmp(const struct etherip_tunnel *a, const struct etherip_tunnel *b)
844 {
845 	int rv;
846 
847 	if (a->t_rtableid > b->t_rtableid)
848 		return (1);
849 	if (a->t_rtableid < b->t_rtableid)
850 		return (-1);
851 
852 	/* sort by address */
853 	if (a->t_af > b->t_af)
854 		return (1);
855 	if (a->t_af < b->t_af)
856 		return (-1);
857 
858 	rv = etherip_ip_cmp(a->t_af, &a->_t_dst, &b->_t_dst);
859 	if (rv != 0)
860 		return (rv);
861 
862 	rv = etherip_ip_cmp(a->t_af, &a->_t_src, &b->_t_src);
863 	if (rv != 0)
864 		return (rv);
865 
866 	return (0);
867 }
868