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