xref: /openbsd-src/sys/net/if_etherip.c (revision c7e8ea31cd41a963f06f0a8ba93948b06aa6b4a4)
1 /*	$OpenBSD: if_etherip.c,v 1.19 2017/06/06 11:51:13 mpi 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 #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 struct etherip_softc {
58 	struct arpcom sc_ac;
59 	struct ifmedia sc_media;
60 	unsigned int sc_rdomain;
61 	struct sockaddr_storage sc_src;
62 	struct sockaddr_storage sc_dst;
63 	LIST_ENTRY(etherip_softc) sc_entry;
64 };
65 
66 LIST_HEAD(, etherip_softc) etherip_softc_list;
67 
68 #if 0
69 /*
70  * TODO:
71  *   At this stage, etherip_allow and etheripstat are defined
72  *   at netinet/ip_ether.c. When implementation of etherip is
73  *   removed from gif(4), there are moved here.
74  */
75 
76 /*
77  * We can control the acceptance of EtherIP packets by altering the sysctl
78  * net.inet.etherip.allow value. Zero means drop them, all else is acceptance.
79  */
80 int etherip_allow = 0;
81 
82 struct etheripstat etheripstat;
83 #endif
84 
85 void etheripattach(int);
86 int etherip_clone_create(struct if_clone *, int);
87 int etherip_clone_destroy(struct ifnet *);
88 int etherip_ioctl(struct ifnet *, u_long, caddr_t);
89 void etherip_start(struct ifnet *);
90 int etherip_media_change(struct ifnet *);
91 void etherip_media_status(struct ifnet *, struct ifmediareq *);
92 int etherip_set_tunnel_addr(struct ifnet *, struct sockaddr_storage *,
93    struct sockaddr_storage *);
94 
95 struct if_clone	etherip_cloner = IF_CLONE_INITIALIZER("etherip",
96     etherip_clone_create, etherip_clone_destroy);
97 
98 
99 void
100 etheripattach(int count)
101 {
102 	if_clone_attach(&etherip_cloner);
103 }
104 
105 int
106 etherip_clone_create(struct if_clone *ifc, int unit)
107 {
108 	struct ifnet *ifp;
109 	struct etherip_softc *sc;
110 
111 	if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
112 		return ENOMEM;
113 
114 	ifp = &sc->sc_ac.ac_if;
115 	snprintf(ifp->if_xname, sizeof ifp->if_xname, "etherip%d", unit);
116 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
117 	ether_fakeaddr(ifp);
118 
119 	ifp->if_softc = sc;
120 	ifp->if_ioctl = etherip_ioctl;
121 	ifp->if_start = etherip_start;
122 	ifp->if_xflags = IFXF_CLONED;
123 	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
124 
125 	ifp->if_capabilities = IFCAP_VLAN_MTU;
126 
127 	ifmedia_init(&sc->sc_media, 0, etherip_media_change,
128 	    etherip_media_status);
129 	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
130 	ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
131 
132 	if_attach(ifp);
133 	ether_ifattach(ifp);
134 
135 	LIST_INSERT_HEAD(&etherip_softc_list, sc, sc_entry);
136 
137 	return 0;
138 }
139 
140 int
141 etherip_clone_destroy(struct ifnet *ifp)
142 {
143 	struct etherip_softc *sc = ifp->if_softc;
144 
145 	LIST_REMOVE(sc, sc_entry);
146 
147 	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
148 	ether_ifdetach(ifp);
149 	if_detach(ifp);
150 	free(sc, M_DEVBUF, sizeof(*sc));
151 
152 	return 0;
153 }
154 
155 int
156 etherip_media_change(struct ifnet *ifp)
157 {
158 	return 0;
159 }
160 
161 void
162 etherip_media_status(struct ifnet *ifp, struct ifmediareq *imr)
163 {
164 	imr->ifm_active = IFM_ETHER | IFM_AUTO;
165 	imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
166 }
167 
168 void
169 etherip_start(struct ifnet *ifp)
170 {
171 	struct etherip_softc *sc = ifp->if_softc;
172 	struct mbuf *m;
173 	int error;
174 
175 	for (;;) {
176 		IFQ_DEQUEUE(&ifp->if_snd, m);
177 		if (m == NULL)
178 			break;
179 
180 #if NBPFILTER > 0
181 		if (ifp->if_bpf)
182 			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
183 #endif
184 		if (sc->sc_src.ss_family == AF_UNSPEC ||
185 		    sc->sc_dst.ss_family == AF_UNSPEC) {
186 			m_freem(m);
187 			continue;
188 		}
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.etherips_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.etherips_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.etherips_opackets++;
402 	etheripstat.etherips_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 int
409 ip_etherip_input(struct mbuf **mp, int *offp, int proto, int af)
410 {
411 	struct mbuf *m = *mp;
412 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
413 	struct etherip_softc *sc;
414 	const struct ip *ip;
415 	struct etherip_header *eip;
416 	struct sockaddr_in *src, *dst;
417 	struct ifnet *ifp = NULL;
418 
419 	ip = mtod(m, struct ip *);
420 
421 	if (ip->ip_p != IPPROTO_ETHERIP) {
422 		m_freem(m);
423 		ipstat_inc(ips_noproto);
424 		return IPPROTO_DONE;
425 	}
426 
427 	if (!etherip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0) {
428 		m_freem(m);
429 		etheripstat.etherips_pdrops++;
430 		return IPPROTO_DONE;
431 	}
432 
433 	LIST_FOREACH(sc, &etherip_softc_list, sc_entry) {
434 		if (sc->sc_src.ss_family != AF_INET ||
435 		    sc->sc_dst.ss_family != AF_INET)
436 			continue;
437 
438 		src = (struct sockaddr_in *)&sc->sc_src;
439 		dst = (struct sockaddr_in *)&sc->sc_dst;
440 
441 		if (sc->sc_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid) ||
442 		    src->sin_addr.s_addr != ip->ip_dst.s_addr ||
443 		    dst->sin_addr.s_addr != ip->ip_src.s_addr)
444 			continue;
445 
446 		ifp = &sc->sc_ac.ac_if;
447 		break;
448 	}
449 
450 	if (ifp == NULL) {
451 #if NGIF > 0
452 		/*
453 		 * This path is nessesary for gif(4) and etherip(4) coexistence.
454 		 * This is tricky but the path will be removed soon when
455 		 * implementation of etherip is removed from gif(4).
456 		 */
457 		return etherip_input(mp, offp, proto, af);
458 #else
459 		etheripstat.etherips_noifdrops++;
460 		m_freem(m);
461 		return IPPROTO_DONE;
462 #endif /* NGIF */
463 	}
464 
465 	m_adj(m, *offp);
466 	m = *mp = m_pullup(m, sizeof(struct etherip_header));
467 	if (m == NULL) {
468 		etheripstat.etherips_adrops++;
469 		return IPPROTO_DONE;
470 	}
471 
472 	eip = mtod(m, struct etherip_header *);
473 	if (eip->eip_ver != ETHERIP_VERSION || eip->eip_pad) {
474 		etheripstat.etherips_adrops++;
475 		m_freem(m);
476 		return IPPROTO_DONE;
477 	}
478 
479 	etheripstat.etherips_ipackets++;
480 	etheripstat.etherips_ibytes += (m->m_pkthdr.len -
481 	    sizeof(struct etherip_header));
482 
483 	m_adj(m, sizeof(struct etherip_header));
484 	m = *mp = m_pullup(m, sizeof(struct ether_header));
485 	if (m == NULL) {
486 		etheripstat.etherips_adrops++;
487 		return IPPROTO_DONE;
488 	}
489 	m->m_flags &= ~(M_BCAST|M_MCAST);
490 
491 #if NPF > 0
492 	pf_pkt_addr_changed(m);
493 #endif
494 
495 	ml_enqueue(&ml, m);
496 	if_input(ifp, &ml);
497 	return IPPROTO_DONE;
498 }
499 
500 #ifdef INET6
501 int
502 ip6_etherip_output(struct ifnet *ifp, struct mbuf *m)
503 {
504 	struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
505 	struct sockaddr_in6 *src, *dst;
506 	struct etherip_header *eip;
507 	struct ip6_hdr *ip6;
508 	int error;
509 
510 	src = (struct sockaddr_in6 *)&sc->sc_src;
511 	dst = (struct sockaddr_in6 *)&sc->sc_dst;
512 
513 	if (src == NULL || dst == NULL ||
514 	    src->sin6_family != AF_INET6 || dst->sin6_family != AF_INET6) {
515 		error = EAFNOSUPPORT;
516 		goto drop;
517 	}
518 	if (IN6_IS_ADDR_UNSPECIFIED(&dst->sin6_addr)) {
519 		error = ENETUNREACH;
520 		goto drop;
521 	}
522 
523 	m->m_flags &= ~(M_BCAST|M_MCAST);
524 
525 	M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
526 	if (m == NULL) {
527 		etheripstat.etherips_adrops++;
528 		return ENOBUFS;
529 	}
530 	eip = mtod(m, struct etherip_header *);
531 	eip->eip_ver = ETHERIP_VERSION;
532 	eip->eip_res = 0;
533 	eip->eip_pad = 0;
534 
535 	M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
536 	if (m == NULL) {
537 		etheripstat.etherips_adrops++;
538 		return ENOBUFS;
539 	}
540 	ip6 = mtod(m, struct ip6_hdr *);
541 	ip6->ip6_flow = 0;
542 	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
543 	ip6->ip6_vfc |= IPV6_VERSION;
544 	ip6->ip6_nxt  = IPPROTO_ETHERIP;
545 	ip6->ip6_hlim = ip6_defhlim;
546 	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
547 	error = in6_embedscope(&ip6->ip6_src, src, NULL);
548 	if (error != 0)
549 		goto drop;
550 	error = in6_embedscope(&ip6->ip6_dst, dst, NULL);
551 	if (error != 0)
552 		goto drop;
553 
554 	m->m_pkthdr.ph_rtableid = sc->sc_rdomain;
555 
556 #if NPF > 0
557 	pf_pkt_addr_changed(m);
558 #endif
559 	etheripstat.etherips_opackets++;
560 	etheripstat.etherips_obytes += (m->m_pkthdr.len -
561 	    (sizeof(struct ip6_hdr) + sizeof(struct etherip_header)));
562 
563 	return ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL);
564 
565 drop:
566 	m_freem(m);
567 	return (error);
568 }
569 
570 int
571 ip6_etherip_input(struct mbuf **mp, int *offp, int proto, int af)
572 {
573 	struct mbuf *m = *mp;
574 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
575 	struct etherip_softc *sc;
576 	const struct ip6_hdr *ip6;
577 	struct etherip_header *eip;
578 	struct sockaddr_in6 ipsrc, ipdst;
579 	struct sockaddr_in6 *src6, *dst6;
580 	struct ifnet *ifp = NULL;
581 
582 
583 	if (!etherip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0) {
584 		m_freem(m);
585 		etheripstat.etherips_pdrops++;
586 		return IPPROTO_NONE;
587 	}
588 
589 	ip6 = mtod(m, const struct ip6_hdr *);
590 	in6_recoverscope(&ipsrc, &ip6->ip6_src);
591 	in6_recoverscope(&ipdst, &ip6->ip6_dst);
592 
593 	LIST_FOREACH(sc, &etherip_softc_list, sc_entry) {
594 		if (sc->sc_src.ss_family != AF_INET6 ||
595 		    sc->sc_dst.ss_family != AF_INET6)
596 			continue;
597 
598 		src6 = (struct sockaddr_in6 *)&sc->sc_src;
599 		dst6 = (struct sockaddr_in6 *)&sc->sc_dst;
600 
601 		if (IN6_ARE_ADDR_EQUAL(&src6->sin6_addr, &ipdst.sin6_addr) &&
602 		    src6->sin6_scope_id == ipdst.sin6_scope_id &&
603 		    IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ipsrc.sin6_addr) &&
604 		    dst6->sin6_scope_id == ipsrc.sin6_scope_id) {
605 			ifp = &sc->sc_ac.ac_if;
606 			break;
607 		}
608 	}
609 
610 	if (ifp == NULL) {
611 #if NGIF > 0
612 		/*
613 		 * This path is nessesary for gif(4) and etherip(4) coexistence.
614 		 * This is tricky but the path will be removed soon when
615 		 * implementation of etherip is removed from gif(4).
616 		 */
617 		return etherip_input(mp, offp, proto, af);
618 #else
619 		etheripstat.etherips_noifdrops++;
620 		m_freem(m);
621 		return IPPROTO_DONE;
622 #endif /* NGIF */
623 	}
624 
625 	m_adj(m, *offp);
626 	m = *mp = m_pullup(m, sizeof(struct etherip_header));
627 	if (m == NULL) {
628 		etheripstat.etherips_adrops++;
629 		return IPPROTO_DONE;
630 	}
631 
632 	eip = mtod(m, struct etherip_header *);
633 	if ((eip->eip_ver != ETHERIP_VERSION) || eip->eip_pad) {
634 		etheripstat.etherips_adrops++;
635 		m_freem(m);
636 		return IPPROTO_DONE;
637 	}
638 	etheripstat.etherips_ipackets++;
639 	etheripstat.etherips_ibytes += (m->m_pkthdr.len -
640 	    sizeof(struct etherip_header));
641 
642 	m_adj(m, sizeof(struct etherip_header));
643 	m = *mp = m_pullup(m, sizeof(struct ether_header));
644 	if (m == NULL) {
645 		etheripstat.etherips_adrops++;
646 		return IPPROTO_DONE;
647 	}
648 
649 	m->m_flags &= ~(M_BCAST|M_MCAST);
650 
651 #if NPF > 0
652 	pf_pkt_addr_changed(m);
653 #endif
654 
655 	ml_enqueue(&ml, m);
656 	if_input(ifp, &ml);
657 	return IPPROTO_DONE;
658 }
659 #endif /* INET6 */
660 
661 int
662 ip_etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
663     void *newp, size_t newlen)
664 {
665 	/* All sysctl names at this level are terminal. */
666 	if (namelen != 1)
667 		return ENOTDIR;
668 
669 	switch (name[0]) {
670 	case ETHERIPCTL_ALLOW:
671 		return sysctl_int(oldp, oldlenp, newp, newlen, &etherip_allow);
672 	case ETHERIPCTL_STATS:
673 		if (newp != NULL)
674 			return EPERM;
675 		return sysctl_struct(oldp, oldlenp, newp, newlen,
676 		    &etheripstat, sizeof(etheripstat));
677 	default:
678 		break;
679 	}
680 
681 	return ENOPROTOOPT;
682 }
683