xref: /xnu-10002.1.13/bsd/net/if_gif.c (revision 1031c584a5e37aff177559b9f69dbd3c8c3fd30a)
1 /*
2  * Copyright (c) 2000-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /* $FreeBSD: src/sys/net/if_gif.c,v 1.4.2.6 2001/07/24 19:10:18 brooks Exp $ */
29 /* $KAME: if_gif.c,v 1.47 2001/05/01 05:28:42 itojun Exp $ */
30 
31 /*
32  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  * 3. Neither the name of the project nor the names of its contributors
44  *    may be used to endorse or promote products derived from this software
45  *    without specific prior written permission.
46  *
47  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57  * SUCH DAMAGE.
58  */
59 /*
60  * NOTICE: This file was modified by SPARTA, Inc. in 2006 to introduce
61  * support for mandatory and extensible security protections.  This notice
62  * is included in support of clause 2.2 (b) of the Apple Public License,
63  * Version 2.0.
64  */
65 
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/kernel.h>
69 #include <sys/malloc.h>
70 #include <sys/mbuf.h>
71 #include <sys/socket.h>
72 #include <sys/sockio.h>
73 #include <sys/errno.h>
74 #include <sys/time.h>
75 #include <sys/syslog.h>
76 #include <sys/protosw.h>
77 #include <kern/cpu_number.h>
78 #include <kern/zalloc.h>
79 
80 #include <net/if.h>
81 #include <net/if_types.h>
82 #include <net/route.h>
83 #include <net/bpf.h>
84 #include <net/kpi_protocol.h>
85 #include <net/kpi_interface.h>
86 #include <net/init.h>
87 
88 #include <netinet/in.h>
89 #include <netinet/in_systm.h>
90 #include <netinet/ip.h>
91 #if     INET
92 #include <netinet/in_var.h>
93 #include <netinet/in_gif.h>
94 #include <netinet/ip_var.h>
95 #endif  /* INET */
96 
97 #include <netinet6/in6_var.h>
98 #include <netinet/ip6.h>
99 #include <netinet6/ip6_var.h>
100 #include <netinet6/in6_gif.h>
101 #include <netinet6/ip6protosw.h>
102 
103 #include <netinet/ip_encap.h>
104 #include <net/dlil.h>
105 #include <net/if_gif.h>
106 
107 #include <net/net_osdep.h>
108 
109 #define GIFNAME         "gif"
110 #define GIFDEV          "if_gif"
111 
112 #define GIF_MAXUNIT     IF_MAXUNIT
113 #define GIF_ZONE_MAX_ELEM       MIN(IFNETS_MAX, GIF_MAXUNIT)
114 
115 /* gif lock variables */
116 static LCK_GRP_DECLARE(gif_mtx_grp, "gif");
117 static LCK_ATTR_DECLARE(gif_mtx_attr, 0, 0);
118 static LCK_MTX_DECLARE_ATTR(gif_mtx, &gif_mtx_grp, &gif_mtx_attr);
119 
120 TAILQ_HEAD(gifhead, gif_softc) gifs = TAILQ_HEAD_INITIALIZER(gifs);
121 
122 static int gif_encapcheck(const struct mbuf *, int, int, void *);
123 static errno_t gif_output(ifnet_t ifp, mbuf_t m);
124 static errno_t gif_input(ifnet_t ifp, protocol_family_t protocol_family,
125     mbuf_t m, char *frame_header);
126 static errno_t gif_ioctl(ifnet_t ifp, u_long cmd, void *data);
127 
128 static int ngif = 0;            /* number of interfaces */
129 
130 #if INET
131 static struct protosw in_gif_protosw =
132 {
133 	.pr_type =              SOCK_RAW,
134 	.pr_protocol =          0, /* IPPROTO_IPV[46] */
135 	.pr_flags =             PR_ATOMIC | PR_ADDR,
136 	.pr_input =             in_gif_input,
137 	.pr_usrreqs =           &rip_usrreqs,
138 	.pr_unlock =            rip_unlock,
139 };
140 #endif
141 static struct ip6protosw in6_gif_protosw =
142 {
143 	.pr_type =              SOCK_RAW,
144 	.pr_protocol =          0, /* IPPROTO_IPV[46] */
145 	.pr_flags =             PR_ATOMIC | PR_ADDR,
146 	.pr_input =             in6_gif_input,
147 	.pr_usrreqs =           &rip6_usrreqs,
148 	.pr_unlock =            rip_unlock,
149 };
150 
151 static int gif_remove(struct ifnet *);
152 static int gif_clone_create(struct if_clone *, uint32_t, void *);
153 static int gif_clone_destroy(struct ifnet *);
154 static void gif_delete_tunnel(struct gif_softc *);
155 static void gif_detach(struct ifnet *);
156 
157 static struct if_clone gif_cloner =
158     IF_CLONE_INITIALIZER(GIFNAME, gif_clone_create, gif_clone_destroy,
159     0, GIF_MAXUNIT);
160 /*
161  * Theory of operation: initially, one gif interface is created.
162  * Any time a gif interface is configured, if there are no other
163  * unconfigured gif interfaces, a new gif interface is created.
164  * BSD uses the clone mechanism to dynamically create more
165  * gif interfaces.
166  *
167  * We have some extra glue to support DLIL.
168  */
169 
170 /* GIF interface module support */
171 static int
gif_demux(ifnet_t ifp,__unused mbuf_t m,__unused char * frame_header,protocol_family_t * protocol_family)172 gif_demux(
173 	ifnet_t ifp,
174 	__unused mbuf_t m,
175 	__unused char *frame_header,
176 	protocol_family_t *protocol_family)
177 {
178 	struct gif_softc *sc = ifnet_softc(ifp);
179 
180 	GIF_LOCK(sc);
181 	/* Only one protocol may be attached to a gif interface. */
182 	*protocol_family = sc->gif_proto;
183 	GIF_UNLOCK(sc);
184 
185 	return 0;
186 }
187 
188 static errno_t
gif_add_proto(ifnet_t ifp,protocol_family_t protocol_family,__unused const struct ifnet_demux_desc * demux_array,__unused u_int32_t demux_count)189 gif_add_proto(
190 	ifnet_t ifp,
191 	protocol_family_t protocol_family,
192 	__unused const struct ifnet_demux_desc *demux_array,
193 	__unused u_int32_t demux_count)
194 {
195 	/* Only one protocol may be attached at a time */
196 	struct gif_softc *sc = ifnet_softc(ifp);
197 
198 	GIF_LOCK(sc);
199 	if (sc->gif_proto != 0) {
200 		printf("gif_add_proto: request add_proto for gif%d\n",
201 		    ifnet_unit(ifp));
202 	}
203 
204 	sc->gif_proto = protocol_family;
205 	GIF_UNLOCK(sc);
206 
207 	return 0;
208 }
209 
210 static errno_t
gif_del_proto(ifnet_t ifp,protocol_family_t protocol_family)211 gif_del_proto(
212 	ifnet_t ifp,
213 	protocol_family_t protocol_family)
214 {
215 	struct gif_softc *sc = ifnet_softc(ifp);
216 
217 	GIF_LOCK(sc);
218 	if (sc->gif_proto == protocol_family) {
219 		sc->gif_proto = 0;
220 	}
221 	GIF_UNLOCK(sc);
222 
223 	return 0;
224 }
225 
226 /* Glue code to attach inet to a gif interface through DLIL */
227 static errno_t
gif_attach_proto_family(ifnet_t ifp,protocol_family_t protocol_family)228 gif_attach_proto_family(
229 	ifnet_t ifp,
230 	protocol_family_t protocol_family)
231 {
232 	struct ifnet_attach_proto_param reg;
233 	errno_t stat;
234 
235 	bzero(&reg, sizeof(reg));
236 	reg.input = gif_input;
237 
238 	stat = ifnet_attach_protocol(ifp, protocol_family, &reg);
239 	if (stat && stat != EEXIST) {
240 		printf("gif_attach_proto_family can't attach interface	\
241 		    fam=%d\n", protocol_family);
242 	}
243 
244 	return stat;
245 }
246 
247 /* Function to setup the first gif interface */
248 void
gif_init(void)249 gif_init(void)
250 {
251 	errno_t result;
252 
253 	/* Initialize the list of interfaces */
254 	TAILQ_INIT(&gifs);
255 
256 	/* Register protocol registration functions */
257 	result = proto_register_plumber(PF_INET, APPLE_IF_FAM_GIF,
258 	    gif_attach_proto_family, NULL);
259 	if (result != 0) {
260 		printf("proto_register_plumber failed for AF_INET error=%d\n",
261 		    result);
262 	}
263 
264 	result = proto_register_plumber(PF_INET6, APPLE_IF_FAM_GIF,
265 	    gif_attach_proto_family, NULL);
266 	if (result != 0) {
267 		printf("proto_register_plumber failed for AF_INET6 error=%d\n",
268 		    result);
269 	}
270 
271 	result = if_clone_attach(&gif_cloner);
272 	if (result != 0) {
273 		panic("%s: if_clone_attach() failed, error %d", __func__, result);
274 	}
275 
276 	gif_clone_create(&gif_cloner, 0, NULL);
277 }
278 
279 static errno_t
gif_set_bpf_tap(ifnet_t ifp,bpf_tap_mode mode,bpf_packet_func callback)280 gif_set_bpf_tap(
281 	ifnet_t ifp,
282 	bpf_tap_mode mode,
283 	bpf_packet_func callback)
284 {
285 	struct gif_softc *sc = ifnet_softc(ifp);
286 
287 	GIF_LOCK(sc);
288 	sc->tap_mode = mode;
289 	sc->tap_callback = callback;
290 	GIF_UNLOCK(sc);
291 
292 	return 0;
293 }
294 
295 static void
gif_detach(struct ifnet * ifp)296 gif_detach(struct ifnet *ifp)
297 {
298 	struct gif_softc *sc = ifp->if_softc;
299 	lck_mtx_destroy(&sc->gif_lock, &gif_mtx_grp);
300 	kfree_type(struct gif_softc, sc);
301 	ifp->if_softc = NULL;
302 	(void) ifnet_release(ifp);
303 }
304 
305 static int
gif_clone_create(struct if_clone * ifc,uint32_t unit,__unused void * params)306 gif_clone_create(struct if_clone *ifc, uint32_t unit, __unused void *params)
307 {
308 	struct gif_softc *sc = NULL;
309 	struct ifnet_init_eparams gif_init_params;
310 	errno_t error = 0;
311 
312 	lck_mtx_lock(&gif_mtx);
313 
314 	/* Can't create more than GIF_MAXUNIT */
315 	if (ngif >= GIF_MAXUNIT) {
316 		error = ENXIO;
317 		goto done;
318 	}
319 
320 	sc = kalloc_type(struct gif_softc, Z_WAITOK_ZERO_NOFAIL);
321 
322 	/* use the interface name as the unique id for ifp recycle */
323 	snprintf(sc->gif_ifname, sizeof(sc->gif_ifname), "%s%d",
324 	    ifc->ifc_name, unit);
325 
326 	lck_mtx_init(&sc->gif_lock, &gif_mtx_grp, &gif_mtx_attr);
327 
328 	bzero(&gif_init_params, sizeof(gif_init_params));
329 	gif_init_params.ver = IFNET_INIT_CURRENT_VERSION;
330 	gif_init_params.len = sizeof(gif_init_params);
331 	gif_init_params.flags = IFNET_INIT_LEGACY;
332 	gif_init_params.uniqueid = sc->gif_ifname;
333 	gif_init_params.uniqueid_len = strlen(sc->gif_ifname);
334 	gif_init_params.name = GIFNAME;
335 	gif_init_params.unit = unit;
336 	gif_init_params.type = IFT_GIF;
337 	gif_init_params.family = IFNET_FAMILY_GIF;
338 	gif_init_params.output = gif_output;
339 	gif_init_params.demux = gif_demux;
340 	gif_init_params.add_proto = gif_add_proto;
341 	gif_init_params.del_proto = gif_del_proto;
342 	gif_init_params.softc = sc;
343 	gif_init_params.ioctl = gif_ioctl;
344 	gif_init_params.set_bpf_tap = gif_set_bpf_tap;
345 	gif_init_params.detach = gif_detach;
346 
347 	error = ifnet_allocate_extended(&gif_init_params, &sc->gif_if);
348 	if (error != 0) {
349 		printf("gif_clone_create, ifnet_allocate failed - %d\n", error);
350 		kfree_type(struct gif_softc, sc);
351 		error = ENOBUFS;
352 		goto done;
353 	}
354 
355 	sc->encap_cookie4 = sc->encap_cookie6 = NULL;
356 #if INET
357 	sc->encap_cookie4 = encap_attach_func(AF_INET, -1,
358 	    gif_encapcheck, &in_gif_protosw, sc);
359 	if (sc->encap_cookie4 == NULL) {
360 		printf("%s: unable to attach encap4\n", if_name(sc->gif_if));
361 		ifnet_release(sc->gif_if);
362 		kfree_type(struct gif_softc, sc);
363 		error = ENOBUFS;
364 		goto done;
365 	}
366 #endif
367 	sc->encap_cookie6 = encap_attach_func(AF_INET6, -1,
368 	    gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc);
369 	if (sc->encap_cookie6 == NULL) {
370 		if (sc->encap_cookie4) {
371 			encap_detach(sc->encap_cookie4);
372 			sc->encap_cookie4 = NULL;
373 		}
374 		printf("%s: unable to attach encap6\n", if_name(sc->gif_if));
375 		ifnet_release(sc->gif_if);
376 		kfree_type(struct gif_softc, sc);
377 		error = ENOBUFS;
378 		goto done;
379 	}
380 	sc->gif_called = 0;
381 	ifnet_set_mtu(sc->gif_if, GIF_MTU);
382 	ifnet_set_flags(sc->gif_if, IFF_POINTOPOINT | IFF_MULTICAST, 0xffff);
383 	sc->gif_flags |= IFGIF_DETACHING;
384 	error = ifnet_attach(sc->gif_if, NULL);
385 	if (error != 0) {
386 		printf("gif_clone_create - ifnet_attach failed - %d\n", error);
387 		ifnet_release(sc->gif_if);
388 		if (sc->encap_cookie4) {
389 			encap_detach(sc->encap_cookie4);
390 			sc->encap_cookie4 = NULL;
391 		}
392 		if (sc->encap_cookie6) {
393 			encap_detach(sc->encap_cookie6);
394 			sc->encap_cookie6 = NULL;
395 		}
396 		kfree_type(struct gif_softc, sc);
397 		goto done;
398 	}
399 	bpfattach(sc->gif_if, DLT_NULL, sizeof(u_int));
400 	sc->gif_flags &= ~IFGIF_DETACHING;
401 	TAILQ_INSERT_TAIL(&gifs, sc, gif_link);
402 	ngif++;
403 done:
404 	lck_mtx_unlock(&gif_mtx);
405 
406 	return error;
407 }
408 
409 static int
gif_remove(struct ifnet * ifp)410 gif_remove(struct ifnet *ifp)
411 {
412 	int error = 0;
413 	struct gif_softc *sc = NULL;
414 	const struct encaptab *encap_cookie4 = NULL;
415 	const struct encaptab *encap_cookie6 = NULL;
416 
417 	lck_mtx_lock(&gif_mtx);
418 	sc = ifp->if_softc;
419 
420 	if (sc == NULL) {
421 		error = EINVAL;
422 		goto done;
423 	}
424 
425 	GIF_LOCK(sc);
426 	if (sc->gif_flags & IFGIF_DETACHING) {
427 		error = EINVAL;
428 		goto done;
429 	}
430 
431 	sc->gif_flags |= IFGIF_DETACHING;
432 	TAILQ_REMOVE(&gifs, sc, gif_link);
433 	ngif--;
434 
435 	gif_delete_tunnel(sc);
436 	encap_cookie6 = sc->encap_cookie6;
437 #ifdef INET
438 	encap_cookie4 = sc->encap_cookie4;
439 #endif
440 done:
441 	if (sc != NULL) {
442 		GIF_UNLOCK(sc);
443 	}
444 	lck_mtx_unlock(&gif_mtx);
445 
446 	if (encap_cookie6 != NULL) {
447 		error = encap_detach(encap_cookie6);
448 		KASSERT(error == 0, ("gif_clone_destroy: Unexpected "
449 		    "error detaching encap_cookie6"));
450 	}
451 
452 	if (encap_cookie4 != NULL) {
453 		error = encap_detach(encap_cookie4);
454 		KASSERT(error == 0, ("gif_clone_destroy: Unexpected "
455 		    "error detaching encap_cookie4"));
456 	}
457 
458 	return error;
459 }
460 
461 static int
gif_clone_destroy(struct ifnet * ifp)462 gif_clone_destroy(struct ifnet *ifp)
463 {
464 	int error = 0;
465 
466 	error = gif_remove(ifp);
467 	if (error != 0) {
468 		printf("gif_clone_destroy: gif remove failed %d\n", error);
469 		return error;
470 	}
471 
472 	error = ifnet_set_flags(ifp, 0, IFF_UP);
473 	if (error != 0) {
474 		printf("gif_clone_destroy: ifnet_set_flags failed %d\n", error);
475 	}
476 
477 	error = ifnet_detach(ifp);
478 	if (error != 0) {
479 		panic("gif_clone_destroy: ifnet_detach(%p) failed %d", ifp,
480 		    error);
481 	}
482 	return 0;
483 }
484 
485 static int
gif_encapcheck(const struct mbuf * m,int off,int proto,void * arg)486 gif_encapcheck(
487 	const struct mbuf *m,
488 	int off,
489 	int proto,
490 	void *arg)
491 {
492 	int error = 0;
493 	struct ip ip;
494 	struct gif_softc *sc;
495 
496 	sc = (struct gif_softc *)arg;
497 	if (sc == NULL) {
498 		return error;
499 	}
500 
501 	GIF_LOCK(sc);
502 	if ((ifnet_flags(sc->gif_if) & IFF_UP) == 0) {
503 		goto done;
504 	}
505 
506 	/* no physical address */
507 	if (!sc->gif_psrc || !sc->gif_pdst) {
508 		goto done;
509 	}
510 
511 	switch (proto) {
512 #if INET
513 	case IPPROTO_IPV4:
514 		break;
515 #endif
516 	case IPPROTO_IPV6:
517 		break;
518 	default:
519 		goto done;
520 	}
521 
522 	mbuf_copydata((struct mbuf *)(size_t)m, 0, sizeof(ip), &ip);
523 
524 	switch (ip.ip_v) {
525 #if INET
526 	case 4:
527 		if (sc->gif_psrc->sa_family != AF_INET ||
528 		    sc->gif_pdst->sa_family != AF_INET) {
529 			goto done;
530 		}
531 		error = gif_encapcheck4(m, off, proto, arg);
532 #endif
533 		OS_FALLTHROUGH;
534 	case 6:
535 		if (sc->gif_psrc->sa_family != AF_INET6 ||
536 		    sc->gif_pdst->sa_family != AF_INET6) {
537 			goto done;
538 		}
539 		error = gif_encapcheck6(m, off, proto, arg);
540 		OS_FALLTHROUGH;
541 	default:
542 		goto done;
543 	}
544 done:
545 	GIF_UNLOCK(sc);
546 	return error;
547 }
548 
549 static errno_t
gif_output(ifnet_t ifp,mbuf_t m)550 gif_output(
551 	ifnet_t ifp,
552 	mbuf_t m)
553 {
554 	struct gif_softc *sc = ifnet_softc(ifp);
555 	struct sockaddr *gif_psrc;
556 	struct sockaddr *gif_pdst;
557 	int error = 0;
558 
559 	GIF_LOCK(sc);
560 	gif_psrc = sc->gif_psrc;
561 	gif_pdst = sc->gif_pdst;
562 	GIF_UNLOCK(sc);
563 
564 	/*
565 	 * max_gif_nesting check used to live here. It doesn't anymore
566 	 * because there is no guaruntee that we won't be called
567 	 * concurrently from more than one thread.
568 	 */
569 	m->m_flags &= ~(M_BCAST | M_MCAST);
570 	if (!(ifnet_flags(ifp) & IFF_UP) ||
571 	    gif_psrc == NULL || gif_pdst == NULL) {
572 		ifnet_touch_lastchange(ifp);
573 		m_freem(m);     /* free it here not in dlil_output */
574 		error = ENETDOWN;
575 		goto end;
576 	}
577 
578 	bpf_tap_out(ifp, 0, m, &sc->gif_proto, sizeof(sc->gif_proto));
579 
580 	GIF_LOCK(sc);
581 
582 	/* inner AF-specific encapsulation */
583 
584 	/* XXX should we check if our outer source is legal? */
585 
586 	/*
587 	 * Save the length as m may be free by the output functions
588 	 * as they call m_pullup
589 	 */
590 	u_int32_t bytes_out = m->m_pkthdr.len;
591 
592 	/* dispatch to output logic based on outer AF */
593 	switch (sc->gif_psrc->sa_family) {
594 #if INET
595 	case AF_INET:
596 		error = in_gif_output(ifp, sc->gif_proto, m, NULL);
597 		break;
598 #endif
599 	case AF_INET6:
600 		error = in6_gif_output(ifp, sc->gif_proto, m, NULL);
601 		break;
602 	default:
603 		error = ENETDOWN;
604 		break;
605 	}
606 
607 	GIF_UNLOCK(sc);
608 end:
609 	if (error) {
610 		/* the mbuf was freed either by in_gif_output or in here */
611 		ifnet_stat_increment_out(ifp, 0, 0, 1);
612 	} else {
613 		ifnet_stat_increment_out(ifp, 1, bytes_out, 0);
614 	}
615 	if (error == 0) {
616 		error = EJUSTRETURN; /* if no error, packet got sent already */
617 	}
618 	return error;
619 }
620 
621 /*
622  * gif_input is the input handler for IP and IPv6 attached to gif
623  */
624 static errno_t
gif_input(ifnet_t ifp,protocol_family_t protocol_family,mbuf_t m,__unused char * frame_header)625 gif_input(
626 	ifnet_t ifp,
627 	protocol_family_t protocol_family,
628 	mbuf_t m,
629 	__unused char *frame_header)
630 {
631 	struct gif_softc *sc = ifnet_softc(ifp);
632 
633 	bpf_tap_in(ifp, 0, m, &sc->gif_proto, sizeof(sc->gif_proto));
634 
635 	/*
636 	 * Put the packet to the network layer input queue according to the
637 	 * specified address family.
638 	 * Note: older versions of gif_input directly called network layer
639 	 * input functions, e.g. ip6_input, here. We changed the policy to
640 	 * prevent too many recursive calls of such input functions, which
641 	 * might cause kernel panic. But the change may introduce another
642 	 * problem; if the input queue is full, packets are discarded.
643 	 * We believed it rarely occurs and changed the policy. If we find
644 	 * it occurs more times than we thought, we may change the policy
645 	 * again.
646 	 */
647 	int32_t pktlen = m->m_pkthdr.len;
648 	if (proto_input(protocol_family, m) != 0) {
649 		ifnet_stat_increment_in(ifp, 0, 0, 1);
650 		m_freem(m);
651 	} else {
652 		ifnet_stat_increment_in(ifp, 1, pktlen, 0);
653 	}
654 
655 	return 0;
656 }
657 
658 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
659 static errno_t
gif_ioctl(ifnet_t ifp,u_long cmd,void * data)660 gif_ioctl(
661 	ifnet_t                 ifp,
662 	u_long                  cmd,
663 	void                    *data)
664 {
665 	struct gif_softc *sc  = ifnet_softc(ifp);
666 	struct ifreq *ifr = (struct ifreq *)data;
667 	int error = 0, size;
668 	struct sockaddr *dst = NULL, *src = NULL;
669 	struct sockaddr *sa;
670 	struct ifnet *ifp2;
671 	struct gif_softc *sc2;
672 
673 	switch (cmd) {
674 	case SIOCSIFADDR:
675 		break;
676 
677 	case SIOCSIFDSTADDR:
678 		break;
679 
680 	case SIOCADDMULTI:
681 	case SIOCDELMULTI:
682 		break;
683 
684 #ifdef  SIOCSIFMTU /* xxx */
685 	case SIOCGIFMTU:
686 		break;
687 
688 	case SIOCSIFMTU:
689 	{
690 		u_int32_t mtu;
691 		mtu = ifr->ifr_mtu;
692 		if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
693 			return EINVAL;
694 		}
695 		ifnet_set_mtu(ifp, mtu);
696 	}
697 	break;
698 #endif /* SIOCSIFMTU */
699 
700 	case SIOCSIFPHYADDR:
701 	case SIOCSIFPHYADDR_IN6_32:
702 	case SIOCSIFPHYADDR_IN6_64:
703 		switch (cmd) {
704 #if INET
705 		case SIOCSIFPHYADDR:
706 			src = (struct sockaddr *)
707 			    &(((struct in_aliasreq *)data)->ifra_addr);
708 			dst = (struct sockaddr *)
709 			    &(((struct in_aliasreq *)data)->ifra_dstaddr);
710 			break;
711 #endif
712 		case SIOCSIFPHYADDR_IN6_32: {
713 			struct in6_aliasreq_32 *ifra_32 =
714 			    (struct in6_aliasreq_32 *)data;
715 
716 			src = (struct sockaddr *)&ifra_32->ifra_addr;
717 			dst = (struct sockaddr *)&ifra_32->ifra_dstaddr;
718 			break;
719 		}
720 
721 		case SIOCSIFPHYADDR_IN6_64: {
722 			struct in6_aliasreq_64 *ifra_64 =
723 			    (struct in6_aliasreq_64 *)data;
724 
725 			src = (struct sockaddr *)&ifra_64->ifra_addr;
726 			dst = (struct sockaddr *)&ifra_64->ifra_dstaddr;
727 			break;
728 		}
729 		}
730 
731 		/* sa_family must be equal */
732 		if (src->sa_family != dst->sa_family) {
733 			return EINVAL;
734 		}
735 
736 		/* validate sa_len */
737 		switch (src->sa_family) {
738 #if INET
739 		case AF_INET:
740 			if (src->sa_len != sizeof(struct sockaddr_in)) {
741 				return EINVAL;
742 			}
743 			break;
744 #endif
745 		case AF_INET6:
746 			if (src->sa_len != sizeof(struct sockaddr_in6)) {
747 				return EINVAL;
748 			}
749 			break;
750 		default:
751 			return EAFNOSUPPORT;
752 		}
753 		switch (dst->sa_family) {
754 #if INET
755 		case AF_INET:
756 			if (dst->sa_len != sizeof(struct sockaddr_in)) {
757 				return EINVAL;
758 			}
759 			break;
760 #endif
761 		case AF_INET6:
762 			if (dst->sa_len != sizeof(struct sockaddr_in6)) {
763 				return EINVAL;
764 			}
765 			break;
766 		default:
767 			return EAFNOSUPPORT;
768 		}
769 
770 		/* check sa_family looks sane for the cmd */
771 		switch (cmd) {
772 		case SIOCSIFPHYADDR:
773 			if (src->sa_family == AF_INET) {
774 				break;
775 			}
776 			return EAFNOSUPPORT;
777 		case SIOCSIFPHYADDR_IN6_32:
778 		case SIOCSIFPHYADDR_IN6_64:
779 			if (src->sa_family == AF_INET6) {
780 				break;
781 			}
782 			return EAFNOSUPPORT;
783 		}
784 
785 #define GIF_ORDERED_LOCK(sc, sc2)       \
786 	if (sc < sc2) {                 \
787 	        GIF_LOCK(sc);           \
788 	        GIF_LOCK(sc2);          \
789 	} else {                        \
790 	        GIF_LOCK(sc2);          \
791 	        GIF_LOCK(sc);           \
792 	}
793 
794 #define GIF_ORDERED_UNLOCK(sc, sc2)     \
795 	if (sc > sc2) {                 \
796 	        GIF_UNLOCK(sc);         \
797 	        GIF_UNLOCK(sc2);        \
798 	} else {                        \
799 	        GIF_UNLOCK(sc2);        \
800 	        GIF_UNLOCK(sc);         \
801 	}
802 
803 		ifnet_head_lock_shared();
804 		TAILQ_FOREACH(ifp2, &ifnet_head, if_link) {
805 			if (strcmp(ifnet_name(ifp2), GIFNAME) != 0) {
806 				continue;
807 			}
808 			sc2 = ifnet_softc(ifp2);
809 			if (sc2 == sc) {
810 				continue;
811 			}
812 			/* lock sc and sc2 in increasing order of ifnet index */
813 			GIF_ORDERED_LOCK(sc, sc2);
814 			if (!sc2->gif_pdst || !sc2->gif_psrc) {
815 				GIF_ORDERED_UNLOCK(sc, sc2);
816 				continue;
817 			}
818 			if (sc2->gif_pdst->sa_family != dst->sa_family ||
819 			    sc2->gif_pdst->sa_len != dst->sa_len ||
820 			    sc2->gif_psrc->sa_family != src->sa_family ||
821 			    sc2->gif_psrc->sa_len != src->sa_len) {
822 				GIF_ORDERED_UNLOCK(sc, sc2);
823 				continue;
824 			}
825 #ifndef XBONEHACK
826 			/* can't configure same pair of address onto two gifs */
827 			if (bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
828 			    bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
829 				GIF_ORDERED_UNLOCK(sc, sc2);
830 				error = EADDRNOTAVAIL;
831 				ifnet_head_done();
832 				goto bad;
833 			}
834 #endif
835 
836 			/* can't configure multiple multi-dest interfaces */
837 #define multidest(x) \
838 	(((struct sockaddr_in *)(void *)(x))->sin_addr.s_addr == INADDR_ANY)
839 #define multidest6(x) \
840 	(IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)      \
841 	    (void *)(x))->sin6_addr))
842 			if (dst->sa_family == AF_INET &&
843 			    multidest(dst) && multidest(sc2->gif_pdst)) {
844 				GIF_ORDERED_UNLOCK(sc, sc2);
845 				error = EADDRNOTAVAIL;
846 				ifnet_head_done();
847 				goto bad;
848 			}
849 			if (dst->sa_family == AF_INET6 &&
850 			    multidest6(dst) && multidest6(sc2->gif_pdst)) {
851 				GIF_ORDERED_UNLOCK(sc, sc2);
852 				error = EADDRNOTAVAIL;
853 				ifnet_head_done();
854 				goto bad;
855 			}
856 			GIF_ORDERED_UNLOCK(sc, sc2);
857 		}
858 		ifnet_head_done();
859 
860 		GIF_LOCK(sc);
861 		if (sc->gif_psrc) {
862 			kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
863 		}
864 		sa = (struct sockaddr *)kalloc_data(src->sa_len, Z_WAITOK);
865 		if (sa == NULL) {
866 			GIF_UNLOCK(sc);
867 			return ENOBUFS;
868 		}
869 		bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
870 		sc->gif_psrc = sa;
871 
872 		if (sc->gif_pdst) {
873 			kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
874 		}
875 		sa = (struct sockaddr *)kalloc_data(dst->sa_len, Z_WAITOK);
876 		if (sa == NULL) {
877 			GIF_UNLOCK(sc);
878 			return ENOBUFS;
879 		}
880 		bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
881 		sc->gif_pdst = sa;
882 		GIF_UNLOCK(sc);
883 
884 		ifnet_set_flags(ifp, IFF_RUNNING | IFF_UP, IFF_RUNNING |
885 		    IFF_UP);
886 
887 		error = 0;
888 		break;
889 
890 #ifdef SIOCDIFPHYADDR
891 	case SIOCDIFPHYADDR:
892 		GIF_LOCK(sc);
893 		if (sc->gif_psrc) {
894 			kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
895 			sc->gif_psrc = NULL;
896 		}
897 		if (sc->gif_pdst) {
898 			kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
899 			sc->gif_pdst = NULL;
900 		}
901 		GIF_UNLOCK(sc);
902 		/* change the IFF_{UP, RUNNING} flag as well? */
903 		break;
904 #endif
905 
906 	case SIOCGIFPSRCADDR:
907 	case SIOCGIFPSRCADDR_IN6:
908 		GIF_LOCK(sc);
909 		if (sc->gif_psrc == NULL) {
910 			GIF_UNLOCK(sc);
911 			error = EADDRNOTAVAIL;
912 			goto bad;
913 		}
914 		src = sc->gif_psrc;
915 		switch (cmd) {
916 #if INET
917 		case SIOCGIFPSRCADDR:
918 			dst = &ifr->ifr_addr;
919 			size = sizeof(ifr->ifr_addr);
920 			break;
921 #endif /* INET */
922 		case SIOCGIFPSRCADDR_IN6:
923 			dst = (struct sockaddr *)
924 			    &(((struct in6_ifreq *)data)->ifr_addr);
925 			size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
926 			break;
927 		default:
928 			GIF_UNLOCK(sc);
929 			error = EADDRNOTAVAIL;
930 			goto bad;
931 		}
932 		if (src->sa_len > size) {
933 			GIF_UNLOCK(sc);
934 			return EINVAL;
935 		}
936 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
937 		GIF_UNLOCK(sc);
938 		break;
939 
940 	case SIOCGIFPDSTADDR:
941 	case SIOCGIFPDSTADDR_IN6:
942 		GIF_LOCK(sc);
943 		if (sc->gif_pdst == NULL) {
944 			GIF_UNLOCK(sc);
945 			error = EADDRNOTAVAIL;
946 			goto bad;
947 		}
948 		src = sc->gif_pdst;
949 		switch (cmd) {
950 #if INET
951 		case SIOCGIFPDSTADDR:
952 			dst = &ifr->ifr_addr;
953 			size = sizeof(ifr->ifr_addr);
954 			break;
955 #endif /* INET */
956 		case SIOCGIFPDSTADDR_IN6:
957 			dst = (struct sockaddr *)
958 			    &(((struct in6_ifreq *)data)->ifr_addr);
959 			size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
960 			break;
961 		default:
962 			error = EADDRNOTAVAIL;
963 			GIF_UNLOCK(sc);
964 			goto bad;
965 		}
966 		if (src->sa_len > size) {
967 			GIF_UNLOCK(sc);
968 			return EINVAL;
969 		}
970 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
971 		GIF_UNLOCK(sc);
972 		break;
973 
974 	case SIOCSIFFLAGS:
975 		/* if_ioctl() takes care of it */
976 		break;
977 
978 	default:
979 		error = EOPNOTSUPP;
980 		break;
981 	}
982 bad:
983 	return error;
984 }
985 
986 static void
gif_delete_tunnel(struct gif_softc * sc)987 gif_delete_tunnel(struct gif_softc *sc)
988 {
989 	GIF_LOCK_ASSERT(sc);
990 	if (sc->gif_psrc) {
991 		kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
992 		sc->gif_psrc = NULL;
993 	}
994 	if (sc->gif_pdst) {
995 		kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
996 		sc->gif_pdst = NULL;
997 	}
998 	ROUTE_RELEASE(&sc->gif_ro);
999 	/* change the IFF_UP flag as well? */
1000 }
1001