xref: /openbsd-src/sys/net/if_etherip.c (revision 6a13ef69787db04ae501a22e92fa10865b44fd7c)
1 /*	$OpenBSD: if_etherip.c,v 1.11 2017/01/22 10:17:39 dlg 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 #include "gif.h"
21 
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/mbuf.h>
25 #include <sys/socket.h>
26 #include <sys/ioctl.h>
27 #include <sys/device.h>
28 #include <sys/sysctl.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 
35 #include <netinet/in.h>
36 #include <netinet/ip.h>
37 #include <netinet/ip_var.h>
38 #include <netinet/if_ether.h>
39 #include <netinet/ip_ether.h>
40 
41 #ifdef INET6
42 #include <netinet/ip6.h>
43 #include <netinet6/ip6_var.h>
44 #endif
45 
46 #if NBPFILTER > 0
47 #include <net/bpf.h>
48 #endif
49 
50 #if NPF > 0
51 #include <net/pfvar.h>
52 #endif
53 
54 #include <net/if_etherip.h>
55 
56 struct etherip_softc {
57 	struct arpcom sc_ac;
58 	struct ifmedia sc_media;
59 	unsigned int sc_rdomain;
60 	struct sockaddr_storage sc_src;
61 	struct sockaddr_storage sc_dst;
62 	LIST_ENTRY(etherip_softc) sc_entry;
63 };
64 
65 LIST_HEAD(, etherip_softc) etherip_softc_list;
66 
67 #if 0
68 /*
69  * TODO:
70  *   At this stage, etherip_allow and etheripstat are defined
71  *   at netinet/ip_ether.c. When implementation of etherip is
72  *   removed from gif(4), there are moved here.
73  */
74 
75 /*
76  * We can control the acceptance of EtherIP packets by altering the sysctl
77  * net.inet.etherip.allow value. Zero means drop them, all else is acceptance.
78  */
79 int etherip_allow = 0;
80 
81 struct etheripstat etheripstat;
82 #endif
83 
84 void etheripattach(int);
85 int etherip_clone_create(struct if_clone *, int);
86 int etherip_clone_destroy(struct ifnet *);
87 int etherip_ioctl(struct ifnet *, u_long, caddr_t);
88 void etherip_start(struct ifnet *);
89 int etherip_media_change(struct ifnet *);
90 void etherip_media_status(struct ifnet *, struct ifmediareq *);
91 int etherip_set_tunnel_addr(struct ifnet *, struct sockaddr_storage *,
92    struct sockaddr_storage *);
93 
94 struct if_clone	etherip_cloner = IF_CLONE_INITIALIZER("etherip",
95     etherip_clone_create, etherip_clone_destroy);
96 
97 
98 void
99 etheripattach(int count)
100 {
101 	if_clone_attach(&etherip_cloner);
102 }
103 
104 int
105 etherip_clone_create(struct if_clone *ifc, int unit)
106 {
107 	struct ifnet *ifp;
108 	struct etherip_softc *sc;
109 
110 	if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
111 		return ENOMEM;
112 
113 	ifp = &sc->sc_ac.ac_if;
114 	snprintf(ifp->if_xname, sizeof ifp->if_xname, "etherip%d", unit);
115 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
116 	ether_fakeaddr(ifp);
117 
118 	ifp->if_softc = sc;
119 	ifp->if_ioctl = etherip_ioctl;
120 	ifp->if_start = etherip_start;
121 	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
122 
123 	ifp->if_capabilities = IFCAP_VLAN_MTU;
124 
125 	ifmedia_init(&sc->sc_media, 0, etherip_media_change,
126 	    etherip_media_status);
127 	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
128 	ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
129 
130 	if_attach(ifp);
131 	ether_ifattach(ifp);
132 
133 	LIST_INSERT_HEAD(&etherip_softc_list, sc, sc_entry);
134 
135 	return 0;
136 }
137 
138 int
139 etherip_clone_destroy(struct ifnet *ifp)
140 {
141 	struct etherip_softc *sc = ifp->if_softc;
142 
143 	LIST_REMOVE(sc, sc_entry);
144 
145 	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
146 	ether_ifdetach(ifp);
147 	if_detach(ifp);
148 	free(sc, M_DEVBUF, sizeof(*sc));
149 
150 	return 0;
151 }
152 
153 int
154 etherip_media_change(struct ifnet *ifp)
155 {
156 	return 0;
157 }
158 
159 void
160 etherip_media_status(struct ifnet *ifp, struct ifmediareq *imr)
161 {
162 	imr->ifm_active = IFM_ETHER | IFM_AUTO;
163 	imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
164 }
165 
166 void
167 etherip_start(struct ifnet *ifp)
168 {
169 	struct etherip_softc *sc = ifp->if_softc;
170 	struct mbuf *m;
171 	int error;
172 
173 	for (;;) {
174 		IFQ_DEQUEUE(&ifp->if_snd, m);
175 		if (m == NULL)
176 			break;
177 
178 #if NBPFILTER > 0
179 		if (ifp->if_bpf)
180 			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
181 #endif
182 		if (sc->sc_src.ss_family == AF_UNSPEC ||
183 		    sc->sc_dst.ss_family == AF_UNSPEC) {
184 			m_freem(m);
185 			continue;
186 		}
187 
188 		switch (sc->sc_src.ss_family) {
189 		case AF_INET:
190 			error = ip_etherip_output(ifp, m);
191 			break;
192 #ifdef INET6
193 		case AF_INET6:
194 			error = ip6_etherip_output(ifp, m);
195 			break;
196 #endif
197 		default:
198 			unhandled_af(sc->sc_src.ss_family);
199 		}
200 
201 		if (error)
202 			ifp->if_oerrors++;
203 	}
204 
205 }
206 
207 
208 int
209 etherip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
210 {
211 	struct etherip_softc *sc = ifp->if_softc;
212 	struct if_laddrreq *lifr = (struct if_laddrreq *)data;
213 	struct ifreq *ifr = (struct ifreq *)data;
214 	struct sockaddr_storage *src, *dst;
215 	struct proc *p = curproc;
216 	int error = 0;
217 
218 	switch (cmd) {
219 	case SIOCSIFADDR:
220 		ifp->if_flags |= IFF_UP;
221 		/* FALLTHROUGH */
222 
223 	case SIOCSIFFLAGS:
224 		if (ifp->if_flags & IFF_UP)
225 			ifp->if_flags |= IFF_RUNNING;
226 		else
227 			ifp->if_flags &= ~IFF_RUNNING;
228 
229 		break;
230 
231 	case SIOCSLIFPHYRTABLE:
232 		if ((error = suser(p, 0)) != 0)
233 			break;
234 
235 		if (ifr->ifr_rdomainid < 0 ||
236 		    ifr->ifr_rdomainid > RT_TABLEID_MAX ||
237 		    !rtable_exists(ifr->ifr_rdomainid)) {
238 			error = EINVAL;
239 			break;
240 		}
241 		sc->sc_rdomain = ifr->ifr_rdomainid;
242 		break;
243 
244 	case SIOCGLIFPHYRTABLE:
245 		ifr->ifr_rdomainid = sc->sc_rdomain;
246 		break;
247 
248 	case SIOCSLIFPHYADDR:
249 		if ((error = suser(p, 0)) != 0)
250 			break;
251 
252 		src = &lifr->addr;
253 		dst = &lifr->dstaddr;
254 		if (src->ss_family == AF_UNSPEC || dst->ss_family == AF_UNSPEC)
255 			return EADDRNOTAVAIL;
256 
257 		switch (src->ss_family) {
258 		case AF_INET:
259 			if (src->ss_len != sizeof(struct sockaddr_in) ||
260 			    dst->ss_len != sizeof(struct sockaddr_in))
261 				return EINVAL;
262 			break;
263 #ifdef INET6
264 		case AF_INET6:
265 			if (src->ss_len != sizeof(struct sockaddr_in6) ||
266 			    dst->ss_len != sizeof(struct sockaddr_in6))
267 				return EINVAL;
268 			break;
269 #endif
270 		default:
271 			return EAFNOSUPPORT;
272 		}
273 
274 		error = etherip_set_tunnel_addr(ifp, src, dst);
275 		break;
276 
277 	case SIOCDIFPHYADDR:
278 		if ((error = suser(p, 0)) != 0)
279 			break;
280 
281 		ifp->if_flags &= ~IFF_RUNNING;
282 		memset(&sc->sc_src, 0, sizeof(sc->sc_src));
283 		memset(&sc->sc_dst, 0, sizeof(sc->sc_dst));
284 		break;
285 
286 	case SIOCGLIFPHYADDR:
287 		if (sc->sc_dst.ss_family == AF_UNSPEC)
288 			return EADDRNOTAVAIL;
289 
290 		memset(&lifr->addr, 0, sizeof(lifr->addr));
291 		memset(&lifr->dstaddr, 0, sizeof(lifr->dstaddr));
292 		memcpy(&lifr->addr, &sc->sc_src, sc->sc_src.ss_len);
293 		memcpy(&lifr->dstaddr, &sc->sc_dst, sc->sc_dst.ss_len);
294 
295 		break;
296 
297 	case SIOCSIFMEDIA:
298 	case SIOCGIFMEDIA:
299 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
300 		break;
301 
302 	default:
303 		error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
304 		break;
305 	}
306 
307 	return error;
308 }
309 
310 int
311 etherip_set_tunnel_addr(struct ifnet *ifp, struct sockaddr_storage *src,
312     struct sockaddr_storage *dst)
313 {
314 	struct etherip_softc *sc, *tsc;
315 	int error = 0;
316 
317 	sc  = ifp->if_softc;
318 
319 	LIST_FOREACH(tsc, &etherip_softc_list, sc_entry) {
320 		if (tsc == sc)
321 			continue;
322 
323 		if (tsc->sc_src.ss_family != src->ss_family ||
324 		    tsc->sc_dst.ss_family != dst->ss_family ||
325 		    tsc->sc_src.ss_len != src->ss_len ||
326 		    tsc->sc_dst.ss_len != dst->ss_len)
327 			continue;
328 
329 		if (tsc->sc_rdomain == sc->sc_rdomain &&
330 		    memcmp(&tsc->sc_dst, dst, dst->ss_len) == 0 &&
331 		    memcmp(&tsc->sc_src, src, src->ss_len) == 0) {
332 			error = EADDRNOTAVAIL;
333 			goto out;
334 		}
335 	}
336 
337 	memcpy(&sc->sc_src, src, src->ss_len);
338 	memcpy(&sc->sc_dst, dst, dst->ss_len);
339 out:
340 	return error;
341 }
342 
343 int
344 ip_etherip_output(struct ifnet *ifp, struct mbuf *m)
345 {
346 	struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
347 	struct sockaddr_in *src, *dst;
348 	struct etherip_header *eip;
349 	struct ip *ip;
350 
351 	src = (struct sockaddr_in *)&sc->sc_src;
352 	dst = (struct sockaddr_in *)&sc->sc_dst;
353 
354 	if (src == NULL || dst == NULL ||
355 	    src->sin_family != AF_INET || dst->sin_family != AF_INET) {
356 		m_freem(m);
357 		return EAFNOSUPPORT;
358 	}
359 	if (dst->sin_addr.s_addr == INADDR_ANY) {
360 		m_freem(m);
361 		return ENETUNREACH;
362 	}
363 
364 	m->m_flags &= ~(M_BCAST|M_MCAST);
365 
366 	M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
367 	if (m == NULL) {
368 		etheripstat.etherip_adrops++;
369 		return ENOBUFS;
370 	}
371 	eip = mtod(m, struct etherip_header *);
372 	eip->eip_ver = ETHERIP_VERSION;
373 	eip->eip_res = 0;
374 	eip->eip_pad = 0;
375 
376 	M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
377 	if (m == NULL) {
378 		etheripstat.etherip_adrops++;
379 		return ENOBUFS;
380 	}
381 	ip = mtod(m, struct ip *);
382 	memset(ip, 0, sizeof(struct ip));
383 
384 	ip->ip_v = IPVERSION;
385 	ip->ip_hl = sizeof(struct ip) >> 2;
386 	ip->ip_id = htons(ip_randomid());
387 	ip->ip_tos = IPTOS_LOWDELAY;
388 	ip->ip_p = IPPROTO_ETHERIP;
389 	ip->ip_len = htons(m->m_pkthdr.len);
390 	ip->ip_ttl = IPDEFTTL;
391 	ip->ip_src = src->sin_addr;
392 	ip->ip_dst = dst->sin_addr;
393 
394 	m->m_pkthdr.ph_rtableid = sc->sc_rdomain;
395 
396 #if NPF > 0
397 	pf_pkt_addr_changed(m);
398 #endif
399 	etheripstat.etherip_opackets++;
400 	etheripstat.etherip_obytes += (m->m_pkthdr.len -
401 	    (sizeof(struct ip) + sizeof(struct etherip_header)));
402 
403 	return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL, 0);
404 }
405 
406 void
407 ip_etherip_input(struct mbuf *m, ...)
408 {
409 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
410 	struct etherip_softc *sc;
411 	const struct ip *ip;
412 	struct etherip_header *eip;
413 	struct sockaddr_in *src, *dst;
414 	struct ifnet *ifp = NULL;
415 	int off;
416 	va_list ap;
417 
418 	va_start(ap, m);
419 	off = va_arg(ap, int);
420 	va_end(ap);
421 
422 	ip = mtod(m, struct ip *);
423 
424 	if (ip->ip_p != IPPROTO_ETHERIP) {
425 		m_freem(m);
426 		ipstat_inc(ips_noproto);
427 		return;
428 	}
429 
430 	if (!etherip_allow) {
431 		m_freem(m);
432 		etheripstat.etherip_pdrops++;
433 		return;
434 	}
435 
436 	LIST_FOREACH(sc, &etherip_softc_list, sc_entry) {
437 		if (sc->sc_src.ss_family != AF_INET ||
438 		    sc->sc_dst.ss_family != AF_INET)
439 			continue;
440 
441 		src = (struct sockaddr_in *)&sc->sc_src;
442 		dst = (struct sockaddr_in *)&sc->sc_dst;
443 
444 		if (sc->sc_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid) ||
445 		    src->sin_addr.s_addr != ip->ip_dst.s_addr ||
446 		    dst->sin_addr.s_addr != ip->ip_src.s_addr)
447 			continue;
448 
449 		ifp = &sc->sc_ac.ac_if;
450 		break;
451 	}
452 
453 	if (ifp == NULL) {
454 #if NGIF > 0
455 		/*
456 		 * This path is nessesary for gif(4) and etherip(4) coexistence.
457 		 * This is tricky but the path will be removed soon when
458 		 * implementation of etherip is removed from gif(4).
459 		 */
460 		etherip_input(m, off);
461 #else
462 		etheripstat.etherip_noifdrops++;
463 		m_freem(m);
464 #endif /* NGIF */
465 		return;
466 	}
467 
468 	m_adj(m, off);
469 	m = m_pullup(m, sizeof(struct etherip_header));
470 	if (m == NULL) {
471 		etheripstat.etherip_adrops++;
472 		return;
473 	}
474 
475 	eip = mtod(m, struct etherip_header *);
476 	if (eip->eip_ver != ETHERIP_VERSION || eip->eip_pad) {
477 		etheripstat.etherip_adrops++;
478 		m_freem(m);
479 		return;
480 	}
481 
482 	etheripstat.etherip_ipackets++;
483 	etheripstat.etherip_ibytes += (m->m_pkthdr.len -
484 	    sizeof(struct etherip_header));
485 
486 	m_adj(m, sizeof(struct etherip_header));
487 	m = m_pullup(m, sizeof(struct ether_header));
488 	if (m == NULL) {
489 		etheripstat.etherip_adrops++;
490 		return;
491 	}
492 	m->m_flags &= ~(M_BCAST|M_MCAST);
493 
494 #if NPF > 0
495 	pf_pkt_addr_changed(m);
496 #endif
497 
498 	ml_enqueue(&ml, m);
499 	if_input(ifp, &ml);
500 }
501 
502 #ifdef INET6
503 int
504 ip6_etherip_output(struct ifnet *ifp, struct mbuf *m)
505 {
506 	struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
507 	struct sockaddr_in6 *src, *dst;
508 	struct etherip_header *eip;
509 	struct ip6_hdr *ip6;
510 	int error;
511 
512 	src = (struct sockaddr_in6 *)&sc->sc_src;
513 	dst = (struct sockaddr_in6 *)&sc->sc_dst;
514 
515 	if (src == NULL || dst == NULL ||
516 	    src->sin6_family != AF_INET6 || dst->sin6_family != AF_INET6) {
517 		error = EAFNOSUPPORT;
518 		goto drop;
519 	}
520 	if (IN6_IS_ADDR_UNSPECIFIED(&dst->sin6_addr)) {
521 		error = ENETUNREACH;
522 		goto drop;
523 	}
524 
525 	m->m_flags &= ~(M_BCAST|M_MCAST);
526 
527 	M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
528 	if (m == NULL) {
529 		etheripstat.etherip_adrops++;
530 		return ENOBUFS;
531 	}
532 	eip = mtod(m, struct etherip_header *);
533 	eip->eip_ver = ETHERIP_VERSION;
534 	eip->eip_res = 0;
535 	eip->eip_pad = 0;
536 
537 	M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
538 	if (m == NULL) {
539 		etheripstat.etherip_adrops++;
540 		return ENOBUFS;
541 	}
542 	ip6 = mtod(m, struct ip6_hdr *);
543 	ip6->ip6_flow = 0;
544 	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
545 	ip6->ip6_vfc |= IPV6_VERSION;
546 	ip6->ip6_nxt  = IPPROTO_ETHERIP;
547 	ip6->ip6_hlim = ip6_defhlim;
548 	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
549 	error = in6_embedscope(&ip6->ip6_src, src, NULL);
550 	if (error != 0)
551 		goto drop;
552 	error = in6_embedscope(&ip6->ip6_dst, dst, NULL);
553 	if (error != 0)
554 		goto drop;
555 
556 	m->m_pkthdr.ph_rtableid = sc->sc_rdomain;
557 
558 #if NPF > 0
559 	pf_pkt_addr_changed(m);
560 #endif
561 	etheripstat.etherip_opackets++;
562 	etheripstat.etherip_obytes += (m->m_pkthdr.len -
563 	    (sizeof(struct ip6_hdr) + sizeof(struct etherip_header)));
564 
565 	return ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL);
566 
567 drop:
568 	m_freem(m);
569 	return (error);
570 }
571 
572 int
573 ip6_etherip_input(struct mbuf **mp, int *offp, int proto)
574 {
575 	struct mbuf *m = *mp;
576 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
577 	int off = *offp;
578 	struct etherip_softc *sc;
579 	const struct ip6_hdr *ip6;
580 	struct etherip_header *eip;
581 	struct sockaddr_in6 ipsrc, ipdst;
582 	struct sockaddr_in6 *src6, *dst6;
583 	struct ifnet *ifp = NULL;
584 
585 
586 	if (!etherip_allow) {
587 		m_freem(m);
588 		etheripstat.etherip_pdrops++;
589 		return IPPROTO_NONE;
590 	}
591 
592 	ip6 = mtod(m, const struct ip6_hdr *);
593 	in6_recoverscope(&ipsrc, &ip6->ip6_src);
594 	in6_recoverscope(&ipdst, &ip6->ip6_dst);
595 
596 	LIST_FOREACH(sc, &etherip_softc_list, sc_entry) {
597 		if (sc->sc_src.ss_family != AF_INET6 ||
598 		    sc->sc_dst.ss_family != AF_INET6)
599 			continue;
600 
601 		src6 = (struct sockaddr_in6 *)&sc->sc_src;
602 		dst6 = (struct sockaddr_in6 *)&sc->sc_dst;
603 
604 		if (IN6_ARE_ADDR_EQUAL(&src6->sin6_addr, &ipdst.sin6_addr) &&
605 		    src6->sin6_scope_id == ipdst.sin6_scope_id &&
606 		    IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ipsrc.sin6_addr) &&
607 		    dst6->sin6_scope_id == ipsrc.sin6_scope_id) {
608 			ifp = &sc->sc_ac.ac_if;
609 			break;
610 		}
611 	}
612 
613 	if (ifp == NULL) {
614 #if NGIF > 0
615 		/*
616 		 * This path is nessesary for gif(4) and etherip(4) coexistence.
617 		 * This is tricky but the path will be removed soon when
618 		 * implementation of etherip is removed from gif(4).
619 		 */
620 		return etherip_input6(mp, offp, proto);
621 #else
622 		etheripstat.etherip_noifdrops++;
623 		m_freem(m);
624 		return IPPROTO_DONE;
625 #endif /* NGIF */
626 	}
627 
628 	m_adj(m, off);
629 	m = m_pullup(m, sizeof(struct etherip_header));
630 	if (m == NULL) {
631 		etheripstat.etherip_adrops++;
632 		return IPPROTO_DONE;
633 	}
634 
635 	eip = mtod(m, struct etherip_header *);
636 	if ((eip->eip_ver != ETHERIP_VERSION) || eip->eip_pad) {
637 		etheripstat.etherip_adrops++;
638 		m_freem(m);
639 		return IPPROTO_DONE;
640 	}
641 	etheripstat.etherip_ipackets++;
642 	etheripstat.etherip_ibytes += (m->m_pkthdr.len -
643 	    sizeof(struct etherip_header));
644 
645 	m_adj(m, sizeof(struct etherip_header));
646 	m = m_pullup(m, sizeof(struct ether_header));
647 	if (m == NULL) {
648 		etheripstat.etherip_adrops++;
649 		return IPPROTO_DONE;
650 	}
651 
652 	m->m_flags &= ~(M_BCAST|M_MCAST);
653 
654 #if NPF > 0
655 	pf_pkt_addr_changed(m);
656 #endif
657 
658 	ml_enqueue(&ml, m);
659 	if_input(ifp, &ml);
660 
661 	return IPPROTO_DONE;
662 }
663 
664 #endif /* INET6 */
665 
666 int
667 ip_etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
668     void *newp, size_t newlen)
669 {
670 	/* All sysctl names at this level are terminal. */
671 	if (namelen != 1)
672 		return ENOTDIR;
673 
674 	switch (name[0]) {
675 	case ETHERIPCTL_ALLOW:
676 		return sysctl_int(oldp, oldlenp, newp, newlen, &etherip_allow);
677 	case ETHERIPCTL_STATS:
678 		if (newp != NULL)
679 			return EPERM;
680 		return sysctl_struct(oldp, oldlenp, newp, newlen,
681 		    &etheripstat, sizeof(etheripstat));
682 	default:
683 		break;
684 	}
685 
686 	return ENOPROTOOPT;
687 }
688