xref: /openbsd-src/sys/net/if_etherip.c (revision 8ead0783a05eee83ab02af2c7b14b10fbcdce47d)
1 /*	$OpenBSD: if_etherip.c,v 1.21 2017/10/25 09:24:09 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 	/*
367 	 * Remove multicast and broadcast flags or encapsulated packet
368 	 * ends up as multicast or broadcast packet.
369 	 */
370 	m->m_flags &= ~(M_BCAST|M_MCAST);
371 
372 	M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
373 	if (m == NULL) {
374 		etheripstat.etherips_adrops++;
375 		return ENOBUFS;
376 	}
377 	eip = mtod(m, struct etherip_header *);
378 	eip->eip_ver = ETHERIP_VERSION;
379 	eip->eip_res = 0;
380 	eip->eip_pad = 0;
381 
382 	M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
383 	if (m == NULL) {
384 		etheripstat.etherips_adrops++;
385 		return ENOBUFS;
386 	}
387 	ip = mtod(m, struct ip *);
388 	memset(ip, 0, sizeof(struct ip));
389 
390 	ip->ip_v = IPVERSION;
391 	ip->ip_hl = sizeof(struct ip) >> 2;
392 	ip->ip_id = htons(ip_randomid());
393 	ip->ip_tos = IPTOS_LOWDELAY;
394 	ip->ip_p = IPPROTO_ETHERIP;
395 	ip->ip_len = htons(m->m_pkthdr.len);
396 	ip->ip_ttl = IPDEFTTL;
397 	ip->ip_src = src->sin_addr;
398 	ip->ip_dst = dst->sin_addr;
399 
400 	m->m_pkthdr.ph_rtableid = sc->sc_rdomain;
401 
402 #if NPF > 0
403 	pf_pkt_addr_changed(m);
404 #endif
405 	etheripstat.etherips_opackets++;
406 	etheripstat.etherips_obytes += (m->m_pkthdr.len -
407 	    (sizeof(struct ip) + sizeof(struct etherip_header)));
408 
409 	return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL, 0);
410 }
411 
412 int
413 ip_etherip_input(struct mbuf **mp, int *offp, int proto, int af)
414 {
415 	struct mbuf *m = *mp;
416 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
417 	struct etherip_softc *sc;
418 	const struct ip *ip;
419 	struct etherip_header *eip;
420 	struct sockaddr_in *src, *dst;
421 	struct ifnet *ifp = NULL;
422 
423 	ip = mtod(m, struct ip *);
424 
425 	if (ip->ip_p != IPPROTO_ETHERIP) {
426 		m_freem(m);
427 		ipstat_inc(ips_noproto);
428 		return IPPROTO_DONE;
429 	}
430 
431 	if (!etherip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0) {
432 		m_freem(m);
433 		etheripstat.etherips_pdrops++;
434 		return IPPROTO_DONE;
435 	}
436 
437 	LIST_FOREACH(sc, &etherip_softc_list, sc_entry) {
438 		if (sc->sc_src.ss_family != AF_INET ||
439 		    sc->sc_dst.ss_family != AF_INET)
440 			continue;
441 
442 		src = (struct sockaddr_in *)&sc->sc_src;
443 		dst = (struct sockaddr_in *)&sc->sc_dst;
444 
445 		if (sc->sc_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid) ||
446 		    src->sin_addr.s_addr != ip->ip_dst.s_addr ||
447 		    dst->sin_addr.s_addr != ip->ip_src.s_addr)
448 			continue;
449 
450 		ifp = &sc->sc_ac.ac_if;
451 		break;
452 	}
453 
454 	if (ifp == NULL) {
455 #if NGIF > 0
456 		/*
457 		 * This path is nessesary for gif(4) and etherip(4) coexistence.
458 		 * This is tricky but the path will be removed soon when
459 		 * implementation of etherip is removed from gif(4).
460 		 */
461 		return etherip_input(mp, offp, proto, af);
462 #else
463 		etheripstat.etherips_noifdrops++;
464 		m_freem(m);
465 		return IPPROTO_DONE;
466 #endif /* NGIF */
467 	}
468 
469 	m_adj(m, *offp);
470 	m = *mp = m_pullup(m, sizeof(struct etherip_header));
471 	if (m == NULL) {
472 		etheripstat.etherips_adrops++;
473 		return IPPROTO_DONE;
474 	}
475 
476 	eip = mtod(m, struct etherip_header *);
477 	if (eip->eip_ver != ETHERIP_VERSION || eip->eip_pad) {
478 		etheripstat.etherips_adrops++;
479 		m_freem(m);
480 		return IPPROTO_DONE;
481 	}
482 
483 	etheripstat.etherips_ipackets++;
484 	etheripstat.etherips_ibytes += (m->m_pkthdr.len -
485 	    sizeof(struct etherip_header));
486 
487 	m_adj(m, sizeof(struct etherip_header));
488 	m = *mp = m_pullup(m, sizeof(struct ether_header));
489 	if (m == NULL) {
490 		etheripstat.etherips_adrops++;
491 		return IPPROTO_DONE;
492 	}
493 	m->m_flags &= ~(M_BCAST|M_MCAST);
494 
495 #if NPF > 0
496 	pf_pkt_addr_changed(m);
497 #endif
498 
499 	ml_enqueue(&ml, m);
500 	if_input(ifp, &ml);
501 	return IPPROTO_DONE;
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 	/*
528 	 * Remove multicast and broadcast flags or encapsulated packet
529 	 * ends up as multicast or broadcast packet.
530 	 */
531 	m->m_flags &= ~(M_BCAST|M_MCAST);
532 
533 	M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
534 	if (m == NULL) {
535 		etheripstat.etherips_adrops++;
536 		return ENOBUFS;
537 	}
538 	eip = mtod(m, struct etherip_header *);
539 	eip->eip_ver = ETHERIP_VERSION;
540 	eip->eip_res = 0;
541 	eip->eip_pad = 0;
542 
543 	M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
544 	if (m == NULL) {
545 		etheripstat.etherips_adrops++;
546 		return ENOBUFS;
547 	}
548 	ip6 = mtod(m, struct ip6_hdr *);
549 	ip6->ip6_flow = 0;
550 	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
551 	ip6->ip6_vfc |= IPV6_VERSION;
552 	ip6->ip6_nxt  = IPPROTO_ETHERIP;
553 	ip6->ip6_hlim = ip6_defhlim;
554 	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
555 	error = in6_embedscope(&ip6->ip6_src, src, NULL);
556 	if (error != 0)
557 		goto drop;
558 	error = in6_embedscope(&ip6->ip6_dst, dst, NULL);
559 	if (error != 0)
560 		goto drop;
561 
562 	m->m_pkthdr.ph_rtableid = sc->sc_rdomain;
563 
564 #if NPF > 0
565 	pf_pkt_addr_changed(m);
566 #endif
567 	etheripstat.etherips_opackets++;
568 	etheripstat.etherips_obytes += (m->m_pkthdr.len -
569 	    (sizeof(struct ip6_hdr) + sizeof(struct etherip_header)));
570 
571 	return ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL);
572 
573 drop:
574 	m_freem(m);
575 	return (error);
576 }
577 
578 int
579 ip6_etherip_input(struct mbuf **mp, int *offp, int proto, int af)
580 {
581 	struct mbuf *m = *mp;
582 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
583 	struct etherip_softc *sc;
584 	const struct ip6_hdr *ip6;
585 	struct etherip_header *eip;
586 	struct sockaddr_in6 ipsrc, ipdst;
587 	struct sockaddr_in6 *src6, *dst6;
588 	struct ifnet *ifp = NULL;
589 
590 
591 	if (!etherip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0) {
592 		m_freem(m);
593 		etheripstat.etherips_pdrops++;
594 		return IPPROTO_NONE;
595 	}
596 
597 	ip6 = mtod(m, const struct ip6_hdr *);
598 	in6_recoverscope(&ipsrc, &ip6->ip6_src);
599 	in6_recoverscope(&ipdst, &ip6->ip6_dst);
600 
601 	LIST_FOREACH(sc, &etherip_softc_list, sc_entry) {
602 		if (sc->sc_src.ss_family != AF_INET6 ||
603 		    sc->sc_dst.ss_family != AF_INET6)
604 			continue;
605 
606 		src6 = (struct sockaddr_in6 *)&sc->sc_src;
607 		dst6 = (struct sockaddr_in6 *)&sc->sc_dst;
608 
609 		if (IN6_ARE_ADDR_EQUAL(&src6->sin6_addr, &ipdst.sin6_addr) &&
610 		    src6->sin6_scope_id == ipdst.sin6_scope_id &&
611 		    IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ipsrc.sin6_addr) &&
612 		    dst6->sin6_scope_id == ipsrc.sin6_scope_id) {
613 			ifp = &sc->sc_ac.ac_if;
614 			break;
615 		}
616 	}
617 
618 	if (ifp == NULL) {
619 #if NGIF > 0
620 		/*
621 		 * This path is nessesary for gif(4) and etherip(4) coexistence.
622 		 * This is tricky but the path will be removed soon when
623 		 * implementation of etherip is removed from gif(4).
624 		 */
625 		return etherip_input(mp, offp, proto, af);
626 #else
627 		etheripstat.etherips_noifdrops++;
628 		m_freem(m);
629 		return IPPROTO_DONE;
630 #endif /* NGIF */
631 	}
632 
633 	m_adj(m, *offp);
634 	m = *mp = m_pullup(m, sizeof(struct etherip_header));
635 	if (m == NULL) {
636 		etheripstat.etherips_adrops++;
637 		return IPPROTO_DONE;
638 	}
639 
640 	eip = mtod(m, struct etherip_header *);
641 	if ((eip->eip_ver != ETHERIP_VERSION) || eip->eip_pad) {
642 		etheripstat.etherips_adrops++;
643 		m_freem(m);
644 		return IPPROTO_DONE;
645 	}
646 	etheripstat.etherips_ipackets++;
647 	etheripstat.etherips_ibytes += (m->m_pkthdr.len -
648 	    sizeof(struct etherip_header));
649 
650 	m_adj(m, sizeof(struct etherip_header));
651 	m = *mp = m_pullup(m, sizeof(struct ether_header));
652 	if (m == NULL) {
653 		etheripstat.etherips_adrops++;
654 		return IPPROTO_DONE;
655 	}
656 
657 	m->m_flags &= ~(M_BCAST|M_MCAST);
658 
659 #if NPF > 0
660 	pf_pkt_addr_changed(m);
661 #endif
662 
663 	ml_enqueue(&ml, m);
664 	if_input(ifp, &ml);
665 	return IPPROTO_DONE;
666 }
667 #endif /* INET6 */
668 
669 int
670 ip_etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
671     void *newp, size_t newlen)
672 {
673 	int error;
674 
675 	/* All sysctl names at this level are terminal. */
676 	if (namelen != 1)
677 		return ENOTDIR;
678 
679 	switch (name[0]) {
680 	case ETHERIPCTL_ALLOW:
681 		NET_LOCK();
682 		error = sysctl_int(oldp, oldlenp, newp, newlen, &etherip_allow);
683 		NET_UNLOCK();
684 		return (error);
685 	case ETHERIPCTL_STATS:
686 		if (newp != NULL)
687 			return EPERM;
688 		NET_LOCK();
689 		error = sysctl_struct(oldp, oldlenp, newp, newlen,
690 		    &etheripstat, sizeof(etheripstat));
691 		NET_UNLOCK();
692 		return (error);
693 	default:
694 		break;
695 	}
696 
697 	return ENOPROTOOPT;
698 }
699