xref: /openbsd-src/sys/net/if_etherip.c (revision d4741794dd2f512d997014f8bd85fbb24d935059)
1 /*	$OpenBSD: if_etherip.c,v 1.10 2016/12/13 06:51:11 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 		ifp->if_opackets++;
189 
190 		switch (sc->sc_src.ss_family) {
191 		case AF_INET:
192 			error = ip_etherip_output(ifp, m);
193 			break;
194 #ifdef INET6
195 		case AF_INET6:
196 			error = ip6_etherip_output(ifp, m);
197 			break;
198 #endif
199 		default:
200 			unhandled_af(sc->sc_src.ss_family);
201 		}
202 
203 		if (error)
204 			ifp->if_oerrors++;
205 	}
206 
207 }
208 
209 
210 int
211 etherip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
212 {
213 	struct etherip_softc *sc = ifp->if_softc;
214 	struct if_laddrreq *lifr = (struct if_laddrreq *)data;
215 	struct ifreq *ifr = (struct ifreq *)data;
216 	struct sockaddr_storage *src, *dst;
217 	struct proc *p = curproc;
218 	int error = 0;
219 
220 	switch (cmd) {
221 	case SIOCSIFADDR:
222 		ifp->if_flags |= IFF_UP;
223 		/* FALLTHROUGH */
224 
225 	case SIOCSIFFLAGS:
226 		if (ifp->if_flags & IFF_UP)
227 			ifp->if_flags |= IFF_RUNNING;
228 		else
229 			ifp->if_flags &= ~IFF_RUNNING;
230 
231 		break;
232 
233 	case SIOCSLIFPHYRTABLE:
234 		if ((error = suser(p, 0)) != 0)
235 			break;
236 
237 		if (ifr->ifr_rdomainid < 0 ||
238 		    ifr->ifr_rdomainid > RT_TABLEID_MAX ||
239 		    !rtable_exists(ifr->ifr_rdomainid)) {
240 			error = EINVAL;
241 			break;
242 		}
243 		sc->sc_rdomain = ifr->ifr_rdomainid;
244 		break;
245 
246 	case SIOCGLIFPHYRTABLE:
247 		ifr->ifr_rdomainid = sc->sc_rdomain;
248 		break;
249 
250 	case SIOCSLIFPHYADDR:
251 		if ((error = suser(p, 0)) != 0)
252 			break;
253 
254 		src = &lifr->addr;
255 		dst = &lifr->dstaddr;
256 		if (src->ss_family == AF_UNSPEC || dst->ss_family == AF_UNSPEC)
257 			return EADDRNOTAVAIL;
258 
259 		switch (src->ss_family) {
260 		case AF_INET:
261 			if (src->ss_len != sizeof(struct sockaddr_in) ||
262 			    dst->ss_len != sizeof(struct sockaddr_in))
263 				return EINVAL;
264 			break;
265 #ifdef INET6
266 		case AF_INET6:
267 			if (src->ss_len != sizeof(struct sockaddr_in6) ||
268 			    dst->ss_len != sizeof(struct sockaddr_in6))
269 				return EINVAL;
270 			break;
271 #endif
272 		default:
273 			return EAFNOSUPPORT;
274 		}
275 
276 		error = etherip_set_tunnel_addr(ifp, src, dst);
277 		break;
278 
279 	case SIOCDIFPHYADDR:
280 		if ((error = suser(p, 0)) != 0)
281 			break;
282 
283 		ifp->if_flags &= ~IFF_RUNNING;
284 		memset(&sc->sc_src, 0, sizeof(sc->sc_src));
285 		memset(&sc->sc_dst, 0, sizeof(sc->sc_dst));
286 		break;
287 
288 	case SIOCGLIFPHYADDR:
289 		if (sc->sc_dst.ss_family == AF_UNSPEC)
290 			return EADDRNOTAVAIL;
291 
292 		memset(&lifr->addr, 0, sizeof(lifr->addr));
293 		memset(&lifr->dstaddr, 0, sizeof(lifr->dstaddr));
294 		memcpy(&lifr->addr, &sc->sc_src, sc->sc_src.ss_len);
295 		memcpy(&lifr->dstaddr, &sc->sc_dst, sc->sc_dst.ss_len);
296 
297 		break;
298 
299 	case SIOCSIFMEDIA:
300 	case SIOCGIFMEDIA:
301 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
302 		break;
303 
304 	default:
305 		error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
306 		break;
307 	}
308 
309 	return error;
310 }
311 
312 int
313 etherip_set_tunnel_addr(struct ifnet *ifp, struct sockaddr_storage *src,
314     struct sockaddr_storage *dst)
315 {
316 	struct etherip_softc *sc, *tsc;
317 	int error = 0;
318 
319 	sc  = ifp->if_softc;
320 
321 	LIST_FOREACH(tsc, &etherip_softc_list, sc_entry) {
322 		if (tsc == sc)
323 			continue;
324 
325 		if (tsc->sc_src.ss_family != src->ss_family ||
326 		    tsc->sc_dst.ss_family != dst->ss_family ||
327 		    tsc->sc_src.ss_len != src->ss_len ||
328 		    tsc->sc_dst.ss_len != dst->ss_len)
329 			continue;
330 
331 		if (tsc->sc_rdomain == sc->sc_rdomain &&
332 		    memcmp(&tsc->sc_dst, dst, dst->ss_len) == 0 &&
333 		    memcmp(&tsc->sc_src, src, src->ss_len) == 0) {
334 			error = EADDRNOTAVAIL;
335 			goto out;
336 		}
337 	}
338 
339 	memcpy(&sc->sc_src, src, src->ss_len);
340 	memcpy(&sc->sc_dst, dst, dst->ss_len);
341 out:
342 	return error;
343 }
344 
345 int
346 ip_etherip_output(struct ifnet *ifp, struct mbuf *m)
347 {
348 	struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
349 	struct sockaddr_in *src, *dst;
350 	struct etherip_header *eip;
351 	struct ip *ip;
352 
353 	src = (struct sockaddr_in *)&sc->sc_src;
354 	dst = (struct sockaddr_in *)&sc->sc_dst;
355 
356 	if (src == NULL || dst == NULL ||
357 	    src->sin_family != AF_INET || dst->sin_family != AF_INET) {
358 		m_freem(m);
359 		return EAFNOSUPPORT;
360 	}
361 	if (dst->sin_addr.s_addr == INADDR_ANY) {
362 		m_freem(m);
363 		return ENETUNREACH;
364 	}
365 
366 	m->m_flags &= ~(M_BCAST|M_MCAST);
367 
368 	M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
369 	if (m == NULL) {
370 		etheripstat.etherip_adrops++;
371 		return ENOBUFS;
372 	}
373 	eip = mtod(m, struct etherip_header *);
374 	eip->eip_ver = ETHERIP_VERSION;
375 	eip->eip_res = 0;
376 	eip->eip_pad = 0;
377 
378 	M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
379 	if (m == NULL) {
380 		etheripstat.etherip_adrops++;
381 		return ENOBUFS;
382 	}
383 	ip = mtod(m, struct ip *);
384 	memset(ip, 0, sizeof(struct ip));
385 
386 	ip->ip_v = IPVERSION;
387 	ip->ip_hl = sizeof(struct ip) >> 2;
388 	ip->ip_id = htons(ip_randomid());
389 	ip->ip_tos = IPTOS_LOWDELAY;
390 	ip->ip_p = IPPROTO_ETHERIP;
391 	ip->ip_len = htons(m->m_pkthdr.len);
392 	ip->ip_ttl = IPDEFTTL;
393 	ip->ip_src = src->sin_addr;
394 	ip->ip_dst = dst->sin_addr;
395 
396 	m->m_pkthdr.ph_rtableid = sc->sc_rdomain;
397 
398 #if NPF > 0
399 	pf_pkt_addr_changed(m);
400 #endif
401 	etheripstat.etherip_opackets++;
402 	etheripstat.etherip_obytes += (m->m_pkthdr.len -
403 	    (sizeof(struct ip) + sizeof(struct etherip_header)));
404 
405 	return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL, 0);
406 }
407 
408 void
409 ip_etherip_input(struct mbuf *m, ...)
410 {
411 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
412 	struct etherip_softc *sc;
413 	const struct ip *ip;
414 	struct etherip_header *eip;
415 	struct sockaddr_in *src, *dst;
416 	struct ifnet *ifp = NULL;
417 	int off;
418 	va_list ap;
419 
420 	va_start(ap, m);
421 	off = va_arg(ap, int);
422 	va_end(ap);
423 
424 	ip = mtod(m, struct ip *);
425 
426 	if (ip->ip_p != IPPROTO_ETHERIP) {
427 		m_freem(m);
428 		ipstat_inc(ips_noproto);
429 		return;
430 	}
431 
432 	if (!etherip_allow) {
433 		m_freem(m);
434 		etheripstat.etherip_pdrops++;
435 		return;
436 	}
437 
438 	LIST_FOREACH(sc, &etherip_softc_list, sc_entry) {
439 		if (sc->sc_src.ss_family != AF_INET ||
440 		    sc->sc_dst.ss_family != AF_INET)
441 			continue;
442 
443 		src = (struct sockaddr_in *)&sc->sc_src;
444 		dst = (struct sockaddr_in *)&sc->sc_dst;
445 
446 		if (sc->sc_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid) ||
447 		    src->sin_addr.s_addr != ip->ip_dst.s_addr ||
448 		    dst->sin_addr.s_addr != ip->ip_src.s_addr)
449 			continue;
450 
451 		ifp = &sc->sc_ac.ac_if;
452 		break;
453 	}
454 
455 	if (ifp == NULL) {
456 #if NGIF > 0
457 		/*
458 		 * This path is nessesary for gif(4) and etherip(4) coexistence.
459 		 * This is tricky but the path will be removed soon when
460 		 * implementation of etherip is removed from gif(4).
461 		 */
462 		etherip_input(m, off);
463 #else
464 		etheripstat.etherip_noifdrops++;
465 		m_freem(m);
466 #endif /* NGIF */
467 		return;
468 	}
469 
470 	m_adj(m, off);
471 	m = m_pullup(m, sizeof(struct etherip_header));
472 	if (m == NULL) {
473 		etheripstat.etherip_adrops++;
474 		return;
475 	}
476 
477 	eip = mtod(m, struct etherip_header *);
478 	if (eip->eip_ver != ETHERIP_VERSION || eip->eip_pad) {
479 		etheripstat.etherip_adrops++;
480 		m_freem(m);
481 		return;
482 	}
483 
484 	etheripstat.etherip_ipackets++;
485 	etheripstat.etherip_ibytes += (m->m_pkthdr.len -
486 	    sizeof(struct etherip_header));
487 
488 	m_adj(m, sizeof(struct etherip_header));
489 	m = m_pullup(m, sizeof(struct ether_header));
490 	if (m == NULL) {
491 		etheripstat.etherip_adrops++;
492 		return;
493 	}
494 	m->m_flags &= ~(M_BCAST|M_MCAST);
495 
496 #if NPF > 0
497 	pf_pkt_addr_changed(m);
498 #endif
499 
500 	ml_enqueue(&ml, m);
501 	if_input(ifp, &ml);
502 }
503 
504 #ifdef INET6
505 int
506 ip6_etherip_output(struct ifnet *ifp, struct mbuf *m)
507 {
508 	struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
509 	struct sockaddr_in6 *src, *dst;
510 	struct etherip_header *eip;
511 	struct ip6_hdr *ip6;
512 	int error;
513 
514 	src = (struct sockaddr_in6 *)&sc->sc_src;
515 	dst = (struct sockaddr_in6 *)&sc->sc_dst;
516 
517 	if (src == NULL || dst == NULL ||
518 	    src->sin6_family != AF_INET6 || dst->sin6_family != AF_INET6) {
519 		error = EAFNOSUPPORT;
520 		goto drop;
521 	}
522 	if (IN6_IS_ADDR_UNSPECIFIED(&dst->sin6_addr)) {
523 		error = ENETUNREACH;
524 		goto drop;
525 	}
526 
527 	m->m_flags &= ~(M_BCAST|M_MCAST);
528 
529 	M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
530 	if (m == NULL) {
531 		etheripstat.etherip_adrops++;
532 		return ENOBUFS;
533 	}
534 	eip = mtod(m, struct etherip_header *);
535 	eip->eip_ver = ETHERIP_VERSION;
536 	eip->eip_res = 0;
537 	eip->eip_pad = 0;
538 
539 	M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
540 	if (m == NULL) {
541 		etheripstat.etherip_adrops++;
542 		return ENOBUFS;
543 	}
544 	ip6 = mtod(m, struct ip6_hdr *);
545 	ip6->ip6_flow = 0;
546 	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
547 	ip6->ip6_vfc |= IPV6_VERSION;
548 	ip6->ip6_nxt  = IPPROTO_ETHERIP;
549 	ip6->ip6_hlim = ip6_defhlim;
550 	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
551 	error = in6_embedscope(&ip6->ip6_src, src, NULL);
552 	if (error != 0)
553 		goto drop;
554 	error = in6_embedscope(&ip6->ip6_dst, dst, NULL);
555 	if (error != 0)
556 		goto drop;
557 
558 	m->m_pkthdr.ph_rtableid = sc->sc_rdomain;
559 
560 #if NPF > 0
561 	pf_pkt_addr_changed(m);
562 #endif
563 	etheripstat.etherip_opackets++;
564 	etheripstat.etherip_obytes += (m->m_pkthdr.len -
565 	    (sizeof(struct ip6_hdr) + sizeof(struct etherip_header)));
566 
567 	return ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL);
568 
569 drop:
570 	m_freem(m);
571 	return (error);
572 }
573 
574 int
575 ip6_etherip_input(struct mbuf **mp, int *offp, int proto)
576 {
577 	struct mbuf *m = *mp;
578 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
579 	int off = *offp;
580 	struct etherip_softc *sc;
581 	const struct ip6_hdr *ip6;
582 	struct etherip_header *eip;
583 	struct sockaddr_in6 ipsrc, ipdst;
584 	struct sockaddr_in6 *src6, *dst6;
585 	struct ifnet *ifp = NULL;
586 
587 
588 	if (!etherip_allow) {
589 		m_freem(m);
590 		etheripstat.etherip_pdrops++;
591 		return IPPROTO_NONE;
592 	}
593 
594 	ip6 = mtod(m, const struct ip6_hdr *);
595 	in6_recoverscope(&ipsrc, &ip6->ip6_src);
596 	in6_recoverscope(&ipdst, &ip6->ip6_dst);
597 
598 	LIST_FOREACH(sc, &etherip_softc_list, sc_entry) {
599 		if (sc->sc_src.ss_family != AF_INET6 ||
600 		    sc->sc_dst.ss_family != AF_INET6)
601 			continue;
602 
603 		src6 = (struct sockaddr_in6 *)&sc->sc_src;
604 		dst6 = (struct sockaddr_in6 *)&sc->sc_dst;
605 
606 		if (IN6_ARE_ADDR_EQUAL(&src6->sin6_addr, &ipdst.sin6_addr) &&
607 		    src6->sin6_scope_id == ipdst.sin6_scope_id &&
608 		    IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ipsrc.sin6_addr) &&
609 		    dst6->sin6_scope_id == ipsrc.sin6_scope_id) {
610 			ifp = &sc->sc_ac.ac_if;
611 			break;
612 		}
613 	}
614 
615 	if (ifp == NULL) {
616 #if NGIF > 0
617 		/*
618 		 * This path is nessesary for gif(4) and etherip(4) coexistence.
619 		 * This is tricky but the path will be removed soon when
620 		 * implementation of etherip is removed from gif(4).
621 		 */
622 		return etherip_input6(mp, offp, proto);
623 #else
624 		etheripstat.etherip_noifdrops++;
625 		m_freem(m);
626 		return IPPROTO_DONE;
627 #endif /* NGIF */
628 	}
629 
630 	m_adj(m, off);
631 	m = m_pullup(m, sizeof(struct etherip_header));
632 	if (m == NULL) {
633 		etheripstat.etherip_adrops++;
634 		return IPPROTO_DONE;
635 	}
636 
637 	eip = mtod(m, struct etherip_header *);
638 	if ((eip->eip_ver != ETHERIP_VERSION) || eip->eip_pad) {
639 		etheripstat.etherip_adrops++;
640 		m_freem(m);
641 		return IPPROTO_DONE;
642 	}
643 	etheripstat.etherip_ipackets++;
644 	etheripstat.etherip_ibytes += (m->m_pkthdr.len -
645 	    sizeof(struct etherip_header));
646 
647 	m_adj(m, sizeof(struct etherip_header));
648 	m = m_pullup(m, sizeof(struct ether_header));
649 	if (m == NULL) {
650 		etheripstat.etherip_adrops++;
651 		return IPPROTO_DONE;
652 	}
653 
654 	m->m_flags &= ~(M_BCAST|M_MCAST);
655 
656 #if NPF > 0
657 	pf_pkt_addr_changed(m);
658 #endif
659 
660 	ml_enqueue(&ml, m);
661 	if_input(ifp, &ml);
662 
663 	return IPPROTO_DONE;
664 }
665 
666 #endif /* INET6 */
667 
668 int
669 ip_etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
670     void *newp, size_t newlen)
671 {
672 	/* All sysctl names at this level are terminal. */
673 	if (namelen != 1)
674 		return ENOTDIR;
675 
676 	switch (name[0]) {
677 	case ETHERIPCTL_ALLOW:
678 		return sysctl_int(oldp, oldlenp, newp, newlen, &etherip_allow);
679 	case ETHERIPCTL_STATS:
680 		if (newp != NULL)
681 			return EPERM;
682 		return sysctl_struct(oldp, oldlenp, newp, newlen,
683 		    &etheripstat, sizeof(etheripstat));
684 	default:
685 		break;
686 	}
687 
688 	return ENOPROTOOPT;
689 }
690