xref: /xnu-12377.81.4/bsd/net/if_gif.c (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
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 #include <net/sockaddr_utils.h>
110 
111 #define GIFNAME         "gif"
112 #define GIFDEV          "if_gif"
113 
114 #define GIF_MAXUNIT     IF_MAXUNIT
115 #define GIF_ZONE_MAX_ELEM       MIN(IFNETS_MAX, GIF_MAXUNIT)
116 
117 /* gif lock variables */
118 static LCK_GRP_DECLARE(gif_mtx_grp, "gif");
119 static LCK_ATTR_DECLARE(gif_mtx_attr, 0, 0);
120 static LCK_MTX_DECLARE_ATTR(gif_mtx, &gif_mtx_grp, &gif_mtx_attr);
121 
122 TAILQ_HEAD(gifhead, gif_softc) gifs = TAILQ_HEAD_INITIALIZER(gifs);
123 
124 static int gif_encapcheck(const struct mbuf *, int, int, void *);
125 static errno_t gif_output(ifnet_t ifp, mbuf_t m);
126 static errno_t gif_input(ifnet_t ifp, protocol_family_t protocol_family,
127     mbuf_t m, char *frame_header);
128 static errno_t gif_ioctl(ifnet_t ifp, u_long cmd, void *__sized_by(IOCPARM_LEN(cmd)));
129 
130 static int ngif = 0;            /* number of interfaces */
131 
132 #if INET
133 static struct protosw in_gif_protosw =
134 {
135 	.pr_type =              SOCK_RAW,
136 	.pr_protocol =          0, /* IPPROTO_IPV[46] */
137 	.pr_flags =             PR_ATOMIC | PR_ADDR,
138 	.pr_input =             in_gif_input,
139 	.pr_usrreqs =           &rip_usrreqs,
140 	.pr_unlock =            rip_unlock,
141 };
142 #endif
143 static struct ip6protosw in6_gif_protosw =
144 {
145 	.pr_type =              SOCK_RAW,
146 	.pr_protocol =          0, /* IPPROTO_IPV[46] */
147 	.pr_flags =             PR_ATOMIC | PR_ADDR,
148 	.pr_input =             in6_gif_input,
149 	.pr_usrreqs =           &rip6_usrreqs,
150 	.pr_unlock =            rip_unlock,
151 };
152 
153 static int gif_remove(struct ifnet *);
154 static int gif_clone_create(struct if_clone *, uint32_t, void *);
155 static int gif_clone_destroy(struct ifnet *);
156 static void gif_delete_tunnel(struct gif_softc *);
157 static void gif_detach(struct ifnet *);
158 
159 static struct if_clone gif_cloner =
160     IF_CLONE_INITIALIZER(GIFNAME, gif_clone_create, gif_clone_destroy,
161     0, GIF_MAXUNIT);
162 /*
163  * Theory of operation: initially, one gif interface is created.
164  * Any time a gif interface is configured, if there are no other
165  * unconfigured gif interfaces, a new gif interface is created.
166  * BSD uses the clone mechanism to dynamically create more
167  * gif interfaces.
168  *
169  * We have some extra glue to support DLIL.
170  */
171 
172 /* GIF interface module support */
173 static int
gif_demux(ifnet_t ifp,__unused mbuf_t m,__unused char * frame_header,protocol_family_t * protocol_family)174 gif_demux(
175 	ifnet_t ifp,
176 	__unused mbuf_t m,
177 	__unused char *frame_header,
178 	protocol_family_t *protocol_family)
179 {
180 	struct gif_softc *__single sc = ifnet_softc(ifp);
181 
182 	GIF_LOCK(sc);
183 	/* Only one protocol may be attached to a gif interface. */
184 	*protocol_family = sc->gif_proto;
185 	GIF_UNLOCK(sc);
186 
187 	return 0;
188 }
189 
190 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)191 gif_add_proto(
192 	ifnet_t ifp,
193 	protocol_family_t protocol_family,
194 	__unused const struct ifnet_demux_desc *demux_array,
195 	__unused u_int32_t demux_count)
196 {
197 	/* Only one protocol may be attached at a time */
198 	struct gif_softc *__single sc = ifnet_softc(ifp);
199 
200 	GIF_LOCK(sc);
201 	if (sc->gif_proto != 0) {
202 		printf("gif_add_proto: request add_proto for gif%d\n",
203 		    ifnet_unit(ifp));
204 	}
205 
206 	sc->gif_proto = protocol_family;
207 	GIF_UNLOCK(sc);
208 
209 	return 0;
210 }
211 
212 static errno_t
gif_del_proto(ifnet_t ifp,protocol_family_t protocol_family)213 gif_del_proto(
214 	ifnet_t ifp,
215 	protocol_family_t protocol_family)
216 {
217 	struct gif_softc *__single sc = ifnet_softc(ifp);
218 
219 	GIF_LOCK(sc);
220 	if (sc->gif_proto == protocol_family) {
221 		sc->gif_proto = 0;
222 	}
223 	GIF_UNLOCK(sc);
224 
225 	return 0;
226 }
227 
228 /* Glue code to attach inet to a gif interface through DLIL */
229 static errno_t
gif_attach_proto_family(ifnet_t ifp,protocol_family_t protocol_family)230 gif_attach_proto_family(
231 	ifnet_t ifp,
232 	protocol_family_t protocol_family)
233 {
234 	struct ifnet_attach_proto_param reg;
235 	errno_t stat;
236 
237 	bzero(&reg, sizeof(reg));
238 	reg.input = gif_input;
239 
240 	stat = ifnet_attach_protocol(ifp, protocol_family, &reg);
241 	if (stat && stat != EEXIST) {
242 		printf("gif_attach_proto_family can't attach interface	\
243 		    fam=%d\n", protocol_family);
244 	}
245 
246 	return stat;
247 }
248 
249 /* Function to setup the first gif interface */
250 void
gif_init(void)251 gif_init(void)
252 {
253 	errno_t result;
254 
255 	/* Initialize the list of interfaces */
256 	TAILQ_INIT(&gifs);
257 
258 	/* Register protocol registration functions */
259 	result = proto_register_plumber(PF_INET, APPLE_IF_FAM_GIF,
260 	    gif_attach_proto_family, NULL);
261 	if (result != 0) {
262 		printf("proto_register_plumber failed for AF_INET error=%d\n",
263 		    result);
264 	}
265 
266 	result = proto_register_plumber(PF_INET6, APPLE_IF_FAM_GIF,
267 	    gif_attach_proto_family, NULL);
268 	if (result != 0) {
269 		printf("proto_register_plumber failed for AF_INET6 error=%d\n",
270 		    result);
271 	}
272 
273 	result = if_clone_attach(&gif_cloner);
274 	if (result != 0) {
275 		panic("%s: if_clone_attach() failed, error %d", __func__, result);
276 	}
277 
278 	gif_clone_create(&gif_cloner, 0, NULL);
279 }
280 
281 static errno_t
gif_set_bpf_tap(ifnet_t ifp,bpf_tap_mode mode,bpf_packet_func callback)282 gif_set_bpf_tap(
283 	ifnet_t ifp,
284 	bpf_tap_mode mode,
285 	bpf_packet_func callback)
286 {
287 	struct gif_softc *__single sc = ifnet_softc(ifp);
288 
289 	GIF_LOCK(sc);
290 	sc->tap_mode = mode;
291 	sc->tap_callback = callback;
292 	GIF_UNLOCK(sc);
293 
294 	return 0;
295 }
296 
297 static void
gif_detach(struct ifnet * ifp)298 gif_detach(struct ifnet *ifp)
299 {
300 	struct gif_softc *__single sc = ifp->if_softc;
301 	lck_mtx_destroy(&sc->gif_lock, &gif_mtx_grp);
302 	kfree_type(struct gif_softc, sc);
303 	ifp->if_softc = NULL;
304 	(void) ifnet_release(ifp);
305 }
306 
307 static int
gif_clone_create(struct if_clone * ifc,uint32_t unit,__unused void * params)308 gif_clone_create(struct if_clone *ifc, uint32_t unit, __unused void *params)
309 {
310 	struct gif_softc *__single sc = NULL;
311 	struct ifnet_init_eparams gif_init_params;
312 	errno_t error = 0;
313 
314 	lck_mtx_lock(&gif_mtx);
315 
316 	/* Can't create more than GIF_MAXUNIT */
317 	if (ngif >= GIF_MAXUNIT) {
318 		error = ENXIO;
319 		goto done;
320 	}
321 
322 	sc = kalloc_type(struct gif_softc, Z_WAITOK_ZERO_NOFAIL);
323 
324 	/* use the interface name as the unique id for ifp recycle */
325 	snprintf(sc->gif_ifname, sizeof(sc->gif_ifname), "%s%d",
326 	    ifc->ifc_name, unit);
327 
328 	lck_mtx_init(&sc->gif_lock, &gif_mtx_grp, &gif_mtx_attr);
329 
330 	bzero(&gif_init_params, sizeof(gif_init_params));
331 	gif_init_params.ver = IFNET_INIT_CURRENT_VERSION;
332 	gif_init_params.len = sizeof(gif_init_params);
333 	gif_init_params.flags = IFNET_INIT_LEGACY;
334 	gif_init_params.uniqueid_len = strbuflen(sc->gif_ifname);
335 	gif_init_params.uniqueid = sc->gif_ifname;
336 	gif_init_params.name = GIFNAME;
337 	gif_init_params.unit = unit;
338 	gif_init_params.type = IFT_GIF;
339 	gif_init_params.family = IFNET_FAMILY_GIF;
340 	gif_init_params.output = gif_output;
341 	gif_init_params.demux = gif_demux;
342 	gif_init_params.add_proto = gif_add_proto;
343 	gif_init_params.del_proto = gif_del_proto;
344 	gif_init_params.softc = sc;
345 	gif_init_params.ioctl = gif_ioctl;
346 	gif_init_params.set_bpf_tap = gif_set_bpf_tap;
347 	gif_init_params.detach = gif_detach;
348 
349 	error = ifnet_allocate_extended(&gif_init_params, &sc->gif_if);
350 	if (error != 0) {
351 		printf("gif_clone_create, ifnet_allocate failed - %d\n", error);
352 		kfree_type(struct gif_softc, sc);
353 		error = ENOBUFS;
354 		goto done;
355 	}
356 
357 	sc->encap_cookie4 = sc->encap_cookie6 = NULL;
358 #if INET
359 	sc->encap_cookie4 = encap_attach_func(AF_INET, -1,
360 	    gif_encapcheck, &in_gif_protosw, sc);
361 	if (sc->encap_cookie4 == NULL) {
362 		printf("%s: unable to attach encap4\n", if_name(sc->gif_if));
363 		ifnet_release(sc->gif_if);
364 		kfree_type(struct gif_softc, sc);
365 		error = ENOBUFS;
366 		goto done;
367 	}
368 #endif
369 	sc->encap_cookie6 = encap_attach_func(AF_INET6, -1,
370 	    gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc);
371 	if (sc->encap_cookie6 == NULL) {
372 		if (sc->encap_cookie4) {
373 			encap_detach(sc->encap_cookie4);
374 			sc->encap_cookie4 = NULL;
375 		}
376 		printf("%s: unable to attach encap6\n", if_name(sc->gif_if));
377 		ifnet_release(sc->gif_if);
378 		kfree_type(struct gif_softc, sc);
379 		error = ENOBUFS;
380 		goto done;
381 	}
382 	sc->gif_called = 0;
383 	ifnet_set_mtu(sc->gif_if, GIF_MTU);
384 	ifnet_set_flags(sc->gif_if, IFF_POINTOPOINT | IFF_MULTICAST, 0xffff);
385 	sc->gif_flags |= IFGIF_DETACHING;
386 	error = ifnet_attach(sc->gif_if, NULL);
387 	if (error != 0) {
388 		printf("gif_clone_create - ifnet_attach failed - %d\n", error);
389 		ifnet_release(sc->gif_if);
390 		if (sc->encap_cookie4) {
391 			encap_detach(sc->encap_cookie4);
392 			sc->encap_cookie4 = NULL;
393 		}
394 		if (sc->encap_cookie6) {
395 			encap_detach(sc->encap_cookie6);
396 			sc->encap_cookie6 = NULL;
397 		}
398 		kfree_type(struct gif_softc, sc);
399 		goto done;
400 	}
401 	bpfattach(sc->gif_if, DLT_NULL, sizeof(u_int));
402 	sc->gif_flags &= ~IFGIF_DETACHING;
403 	TAILQ_INSERT_TAIL(&gifs, sc, gif_link);
404 	ngif++;
405 done:
406 	lck_mtx_unlock(&gif_mtx);
407 
408 	return error;
409 }
410 
411 static int
gif_remove(struct ifnet * ifp)412 gif_remove(struct ifnet *ifp)
413 {
414 	int error = 0;
415 	struct gif_softc *__single sc = NULL;
416 	const struct encaptab *__single encap_cookie4 = NULL;
417 	const struct encaptab *__single encap_cookie6 = NULL;
418 
419 	lck_mtx_lock(&gif_mtx);
420 	sc = ifp->if_softc;
421 
422 	if (sc == NULL) {
423 		error = EINVAL;
424 		goto done;
425 	}
426 
427 	GIF_LOCK(sc);
428 	if (sc->gif_flags & IFGIF_DETACHING) {
429 		error = EINVAL;
430 		goto done;
431 	}
432 
433 	sc->gif_flags |= IFGIF_DETACHING;
434 	TAILQ_REMOVE(&gifs, sc, gif_link);
435 	ngif--;
436 
437 	gif_delete_tunnel(sc);
438 	encap_cookie6 = sc->encap_cookie6;
439 #ifdef INET
440 	encap_cookie4 = sc->encap_cookie4;
441 #endif
442 done:
443 	if (sc != NULL) {
444 		GIF_UNLOCK(sc);
445 	}
446 	lck_mtx_unlock(&gif_mtx);
447 
448 	if (encap_cookie6 != NULL) {
449 		error = encap_detach(encap_cookie6);
450 		KASSERT(error == 0, ("gif_clone_destroy: Unexpected "
451 		    "error detaching encap_cookie6"));
452 	}
453 
454 	if (encap_cookie4 != NULL) {
455 		error = encap_detach(encap_cookie4);
456 		KASSERT(error == 0, ("gif_clone_destroy: Unexpected "
457 		    "error detaching encap_cookie4"));
458 	}
459 
460 	return error;
461 }
462 
463 static int
gif_clone_destroy(struct ifnet * ifp)464 gif_clone_destroy(struct ifnet *ifp)
465 {
466 	int error = 0;
467 
468 	error = gif_remove(ifp);
469 	if (error != 0) {
470 		printf("gif_clone_destroy: gif remove failed %d\n", error);
471 		return error;
472 	}
473 
474 	error = ifnet_set_flags(ifp, 0, IFF_UP);
475 	if (error != 0) {
476 		printf("gif_clone_destroy: ifnet_set_flags failed %d\n", error);
477 	}
478 
479 	error = ifnet_detach(ifp);
480 	if (error != 0) {
481 		panic("gif_clone_destroy: ifnet_detach(%p) failed %d", ifp,
482 		    error);
483 	}
484 	return 0;
485 }
486 
487 static int
gif_encapcheck(const struct mbuf * m,int off,int proto,void * arg)488 gif_encapcheck(
489 	const struct mbuf *m,
490 	int off,
491 	int proto,
492 	void *arg)
493 {
494 	int error = 0;
495 	struct ip ip;
496 	struct gif_softc *__single sc;
497 
498 	sc = (struct gif_softc *)arg;
499 	if (sc == NULL) {
500 		return error;
501 	}
502 
503 	GIF_LOCK(sc);
504 	if ((ifnet_flags(sc->gif_if) & IFF_UP) == 0) {
505 		goto done;
506 	}
507 
508 	/* no physical address */
509 	if (!sc->gif_psrc || !sc->gif_pdst) {
510 		goto done;
511 	}
512 
513 	switch (proto) {
514 #if INET
515 	case IPPROTO_IPV4:
516 		break;
517 #endif
518 	case IPPROTO_IPV6:
519 		break;
520 	default:
521 		goto done;
522 	}
523 
524 	mbuf_copydata(__DECONST(struct mbuf *, m), 0, sizeof(ip), &ip);
525 
526 	switch (ip.ip_v) {
527 #if INET
528 	case 4:
529 		if (sc->gif_psrc->sa_family != AF_INET ||
530 		    sc->gif_pdst->sa_family != AF_INET) {
531 			goto done;
532 		}
533 		error = gif_encapcheck4(m, off, proto, arg);
534 #endif
535 		OS_FALLTHROUGH;
536 	case 6:
537 		if (sc->gif_psrc->sa_family != AF_INET6 ||
538 		    sc->gif_pdst->sa_family != AF_INET6) {
539 			goto done;
540 		}
541 		error = gif_encapcheck6(m, off, proto, arg);
542 		OS_FALLTHROUGH;
543 	default:
544 		goto done;
545 	}
546 done:
547 	GIF_UNLOCK(sc);
548 	return error;
549 }
550 
551 static errno_t
gif_output(ifnet_t ifp,mbuf_t m)552 gif_output(
553 	ifnet_t ifp,
554 	mbuf_t m)
555 {
556 	struct gif_softc *__single sc = ifnet_softc(ifp);
557 	struct sockaddr *gif_psrc;
558 	struct sockaddr *gif_pdst;
559 	int error = 0;
560 
561 	GIF_LOCK(sc);
562 	gif_psrc = sc->gif_psrc;
563 	gif_pdst = sc->gif_pdst;
564 	GIF_UNLOCK(sc);
565 
566 	/*
567 	 * max_gif_nesting check used to live here. It doesn't anymore
568 	 * because there is no guaruntee that we won't be called
569 	 * concurrently from more than one thread.
570 	 */
571 	m->m_flags &= ~(M_BCAST | M_MCAST);
572 	if (!(ifnet_flags(ifp) & IFF_UP) ||
573 	    gif_psrc == NULL || gif_pdst == NULL) {
574 		ifnet_touch_lastchange(ifp);
575 		m_freem(m);     /* free it here not in dlil_output */
576 		error = ENETDOWN;
577 		goto end;
578 	}
579 
580 	bpf_tap_out(ifp, 0, m, &sc->gif_proto, sizeof(sc->gif_proto));
581 
582 	GIF_LOCK(sc);
583 
584 	/* inner AF-specific encapsulation */
585 
586 	/* XXX should we check if our outer source is legal? */
587 
588 	/*
589 	 * Save the length as m may be free by the output functions
590 	 * as they call m_pullup
591 	 */
592 	u_int32_t bytes_out = m->m_pkthdr.len;
593 
594 	/* dispatch to output logic based on outer AF */
595 	switch (sc->gif_psrc->sa_family) {
596 #if INET
597 	case AF_INET:
598 		error = in_gif_output(ifp, sc->gif_proto, m, NULL);
599 		break;
600 #endif
601 	case AF_INET6:
602 		error = in6_gif_output(ifp, sc->gif_proto, m, NULL);
603 		break;
604 	default:
605 		error = ENETDOWN;
606 		break;
607 	}
608 
609 	GIF_UNLOCK(sc);
610 end:
611 	if (error) {
612 		/* the mbuf was freed either by in_gif_output or in here */
613 		ifnet_stat_increment_out(ifp, 0, 0, 1);
614 	} else {
615 		ifnet_stat_increment_out(ifp, 1, bytes_out, 0);
616 	}
617 	if (error == 0) {
618 		error = EJUSTRETURN; /* if no error, packet got sent already */
619 	}
620 	return error;
621 }
622 
623 /*
624  * gif_input is the input handler for IP and IPv6 attached to gif
625  */
626 static errno_t
gif_input(ifnet_t ifp,protocol_family_t protocol_family,mbuf_t m,__unused char * frame_header)627 gif_input(
628 	ifnet_t ifp,
629 	protocol_family_t protocol_family,
630 	mbuf_t m,
631 	__unused char *frame_header)
632 {
633 	struct gif_softc *__single sc = ifnet_softc(ifp);
634 
635 	bpf_tap_in(ifp, 0, m, &sc->gif_proto, sizeof(sc->gif_proto));
636 
637 	/*
638 	 * Put the packet to the network layer input queue according to the
639 	 * specified address family.
640 	 * Note: older versions of gif_input directly called network layer
641 	 * input functions, e.g. ip6_input, here. We changed the policy to
642 	 * prevent too many recursive calls of such input functions, which
643 	 * might cause kernel panic. But the change may introduce another
644 	 * problem; if the input queue is full, packets are discarded.
645 	 * We believed it rarely occurs and changed the policy. If we find
646 	 * it occurs more times than we thought, we may change the policy
647 	 * again.
648 	 */
649 	int32_t pktlen = m->m_pkthdr.len;
650 	if (proto_input(protocol_family, m) != 0) {
651 		ifnet_stat_increment_in(ifp, 0, 0, 1);
652 		m_freem(m);
653 	} else {
654 		ifnet_stat_increment_in(ifp, 1, pktlen, 0);
655 	}
656 
657 	return 0;
658 }
659 
660 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
661 static errno_t
gif_ioctl(ifnet_t ifp,u_long cmd,void * __sized_by (IOCPARM_LEN (cmd))data)662 gif_ioctl(ifnet_t ifp, u_long cmd, void *__sized_by(IOCPARM_LEN(cmd)) data)
663 {
664 	struct gif_softc *__single sc  = ifnet_softc(ifp);
665 	struct ifreq *__single ifr = (struct ifreq *)data;
666 	int error = 0, size;
667 	struct sockaddr *dst = NULL, *src = NULL;
668 	struct sockaddr *__single sa;
669 	struct ifnet *__single ifp2;
670 	struct gif_softc *__single sc2;
671 
672 	switch (cmd) {
673 	case SIOCSIFADDR:
674 		break;
675 
676 	case SIOCSIFDSTADDR:
677 		break;
678 
679 	case SIOCADDMULTI:
680 	case SIOCDELMULTI:
681 		break;
682 
683 #ifdef  SIOCSIFMTU /* xxx */
684 	case SIOCGIFMTU:
685 		break;
686 
687 	case SIOCSIFMTU:
688 	{
689 		u_int32_t mtu;
690 		mtu = ifr->ifr_mtu;
691 		if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
692 			return EINVAL;
693 		}
694 		ifnet_set_mtu(ifp, mtu);
695 	}
696 	break;
697 #endif /* SIOCSIFMTU */
698 
699 	case SIOCSIFPHYADDR:
700 	case SIOCSIFPHYADDR_IN6_32:
701 	case SIOCSIFPHYADDR_IN6_64:
702 		switch (cmd) {
703 #if INET
704 		case SIOCSIFPHYADDR: {
705 			struct in_aliasreq *ifra =
706 			    (struct in_aliasreq*)data;
707 
708 			src = SA(&ifra->ifra_addr);
709 			dst = SA(&ifra->ifra_dstaddr);
710 			break;
711 		}
712 #endif
713 		case SIOCSIFPHYADDR_IN6_32: {
714 			struct in6_aliasreq_32 *ifra_32 =
715 			    (struct in6_aliasreq_32 *)data;
716 
717 			src = SA(&ifra_32->ifra_addr);
718 			dst = SA(&ifra_32->ifra_dstaddr);
719 			break;
720 		}
721 
722 		case SIOCSIFPHYADDR_IN6_64: {
723 			struct in6_aliasreq_64 *ifra_64 =
724 			    (struct in6_aliasreq_64 *)data;
725 
726 			src = SA(&ifra_64->ifra_addr);
727 			dst = SA(&ifra_64->ifra_dstaddr);
728 			break;
729 		}
730 		}
731 
732 		/* sa_family must be equal */
733 		if (src->sa_family != dst->sa_family) {
734 			return EINVAL;
735 		}
736 
737 		/* validate sa_len */
738 		switch (src->sa_family) {
739 #if INET
740 		case AF_INET:
741 			if (src->sa_len != sizeof(struct sockaddr_in)) {
742 				return EINVAL;
743 			}
744 			break;
745 #endif
746 		case AF_INET6:
747 			if (src->sa_len != sizeof(struct sockaddr_in6)) {
748 				return EINVAL;
749 			}
750 			break;
751 		default:
752 			return EAFNOSUPPORT;
753 		}
754 		switch (dst->sa_family) {
755 #if INET
756 		case AF_INET:
757 			if (dst->sa_len != sizeof(struct sockaddr_in)) {
758 				return EINVAL;
759 			}
760 			break;
761 #endif
762 		case AF_INET6:
763 			if (dst->sa_len != sizeof(struct sockaddr_in6)) {
764 				return EINVAL;
765 			}
766 			break;
767 		default:
768 			return EAFNOSUPPORT;
769 		}
770 
771 		/* check sa_family looks sane for the cmd */
772 		switch (cmd) {
773 		case SIOCSIFPHYADDR:
774 			if (src->sa_family == AF_INET) {
775 				break;
776 			}
777 			return EAFNOSUPPORT;
778 		case SIOCSIFPHYADDR_IN6_32:
779 		case SIOCSIFPHYADDR_IN6_64:
780 			if (src->sa_family == AF_INET6) {
781 				break;
782 			}
783 			return EAFNOSUPPORT;
784 		}
785 
786 #define GIF_ORDERED_LOCK(sc, sc2)       \
787 	if (sc < sc2) {                 \
788 	        GIF_LOCK(sc);           \
789 	        GIF_LOCK(sc2);          \
790 	} else {                        \
791 	        GIF_LOCK(sc2);          \
792 	        GIF_LOCK(sc);           \
793 	}
794 
795 #define GIF_ORDERED_UNLOCK(sc, sc2)     \
796 	if (sc > sc2) {                 \
797 	        GIF_UNLOCK(sc);         \
798 	        GIF_UNLOCK(sc2);        \
799 	} else {                        \
800 	        GIF_UNLOCK(sc2);        \
801 	        GIF_UNLOCK(sc);         \
802 	}
803 
804 		ifnet_head_lock_shared();
805 		TAILQ_FOREACH(ifp2, &ifnet_head, if_link) {
806 			if (strcmp(ifnet_name(ifp2), GIFNAME) != 0) {
807 				continue;
808 			}
809 			sc2 = ifnet_softc(ifp2);
810 			if (sc2 == sc) {
811 				continue;
812 			}
813 			/* lock sc and sc2 in increasing order of ifnet index */
814 			GIF_ORDERED_LOCK(sc, sc2);
815 			if (!sc2->gif_pdst || !sc2->gif_psrc) {
816 				GIF_ORDERED_UNLOCK(sc, sc2);
817 				continue;
818 			}
819 			if (sc2->gif_pdst->sa_family != dst->sa_family ||
820 			    sc2->gif_pdst->sa_len != dst->sa_len ||
821 			    sc2->gif_psrc->sa_family != src->sa_family ||
822 			    sc2->gif_psrc->sa_len != src->sa_len) {
823 				GIF_ORDERED_UNLOCK(sc, sc2);
824 				continue;
825 			}
826 #ifndef XBONEHACK
827 			/* can't configure same pair of address onto two gifs */
828 			if (SOCKADDR_CMP(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
829 			    SOCKADDR_CMP(sc2->gif_psrc, src, src->sa_len) == 0) {
830 				GIF_ORDERED_UNLOCK(sc, sc2);
831 				error = EADDRNOTAVAIL;
832 				ifnet_head_done();
833 				goto bad;
834 			}
835 #endif
836 
837 			/* can't configure multiple multi-dest interfaces */
838 #define multidest(x) \
839 	(((struct sockaddr_in *)(void *)(x))->sin_addr.s_addr == INADDR_ANY)
840 #define multidest6(x) \
841 	(IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)      \
842 	    (void *)(x))->sin6_addr))
843 			if (dst->sa_family == AF_INET &&
844 			    multidest(dst) && multidest(sc2->gif_pdst)) {
845 				GIF_ORDERED_UNLOCK(sc, sc2);
846 				error = EADDRNOTAVAIL;
847 				ifnet_head_done();
848 				goto bad;
849 			}
850 			if (dst->sa_family == AF_INET6 &&
851 			    multidest6(dst) && multidest6(sc2->gif_pdst)) {
852 				GIF_ORDERED_UNLOCK(sc, sc2);
853 				error = EADDRNOTAVAIL;
854 				ifnet_head_done();
855 				goto bad;
856 			}
857 			GIF_ORDERED_UNLOCK(sc, sc2);
858 		}
859 		ifnet_head_done();
860 
861 		GIF_LOCK(sc);
862 		if (sc->gif_psrc) {
863 			kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
864 		}
865 		sa = SA(kalloc_data(src->sa_len, Z_WAITOK));
866 		if (sa == NULL) {
867 			GIF_UNLOCK(sc);
868 			return ENOBUFS;
869 		}
870 		SOCKADDR_COPY(src, sa, src->sa_len);
871 		sc->gif_psrc = sa;
872 
873 		if (sc->gif_pdst) {
874 			kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
875 		}
876 		sa = SA(kalloc_data(dst->sa_len, Z_WAITOK));
877 		if (sa == NULL) {
878 			GIF_UNLOCK(sc);
879 			return ENOBUFS;
880 		}
881 		SOCKADDR_COPY(dst, sa, dst->sa_len);
882 		sc->gif_pdst = sa;
883 		GIF_UNLOCK(sc);
884 
885 		ifnet_set_flags(ifp, IFF_RUNNING | IFF_UP, IFF_RUNNING |
886 		    IFF_UP);
887 
888 		error = 0;
889 		break;
890 
891 #ifdef SIOCDIFPHYADDR
892 	case SIOCDIFPHYADDR:
893 		GIF_LOCK(sc);
894 		if (sc->gif_psrc) {
895 			kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
896 			sc->gif_psrc = NULL;
897 		}
898 		if (sc->gif_pdst) {
899 			kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
900 			sc->gif_pdst = NULL;
901 		}
902 		GIF_UNLOCK(sc);
903 		/* change the IFF_{UP, RUNNING} flag as well? */
904 		break;
905 #endif
906 
907 	case SIOCGIFPSRCADDR:
908 	case SIOCGIFPSRCADDR_IN6:
909 		GIF_LOCK(sc);
910 		if (sc->gif_psrc == NULL) {
911 			GIF_UNLOCK(sc);
912 			error = EADDRNOTAVAIL;
913 			goto bad;
914 		}
915 		src = sc->gif_psrc;
916 		switch (cmd) {
917 #if INET
918 		case SIOCGIFPSRCADDR:
919 			dst = &ifr->ifr_addr;
920 			size = sizeof(ifr->ifr_addr);
921 			break;
922 #endif /* INET */
923 		case SIOCGIFPSRCADDR_IN6: {
924 			struct in6_ifreq *ifreq =
925 			    (struct in6_ifreq*)data;
926 
927 			dst = SA(&ifreq->ifr_addr);
928 			size = sizeof(ifreq->ifr_addr);
929 			break;
930 		}
931 		default:
932 			GIF_UNLOCK(sc);
933 			error = EADDRNOTAVAIL;
934 			goto bad;
935 		}
936 		if (src->sa_len > size) {
937 			GIF_UNLOCK(sc);
938 			return EINVAL;
939 		}
940 		SOCKADDR_COPY(src, dst, src->sa_len);
941 		GIF_UNLOCK(sc);
942 		break;
943 
944 	case SIOCGIFPDSTADDR:
945 	case SIOCGIFPDSTADDR_IN6:
946 		GIF_LOCK(sc);
947 		if (sc->gif_pdst == NULL) {
948 			GIF_UNLOCK(sc);
949 			error = EADDRNOTAVAIL;
950 			goto bad;
951 		}
952 		src = sc->gif_pdst;
953 		switch (cmd) {
954 #if INET
955 		case SIOCGIFPDSTADDR:
956 			dst = &ifr->ifr_addr;
957 			size = sizeof(ifr->ifr_addr);
958 			break;
959 #endif /* INET */
960 		case SIOCGIFPDSTADDR_IN6: {
961 			struct in6_ifreq *ifreq =
962 			    (struct in6_ifreq*)data;
963 
964 			dst = SA(&ifreq->ifr_addr);
965 			size = sizeof(ifreq->ifr_addr);
966 			break;
967 		}
968 		default:
969 			error = EADDRNOTAVAIL;
970 			GIF_UNLOCK(sc);
971 			goto bad;
972 		}
973 		if (src->sa_len > size) {
974 			GIF_UNLOCK(sc);
975 			return EINVAL;
976 		}
977 		SOCKADDR_COPY(src, dst, src->sa_len);
978 		GIF_UNLOCK(sc);
979 		break;
980 
981 	case SIOCSIFFLAGS:
982 		/* if_ioctl() takes care of it */
983 		break;
984 
985 	default:
986 		error = EOPNOTSUPP;
987 		break;
988 	}
989 bad:
990 	return error;
991 }
992 
993 static void
gif_delete_tunnel(struct gif_softc * sc)994 gif_delete_tunnel(struct gif_softc *sc)
995 {
996 	GIF_LOCK_ASSERT(sc);
997 	if (sc->gif_psrc) {
998 		kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
999 		sc->gif_psrc = NULL;
1000 	}
1001 	if (sc->gif_pdst) {
1002 		kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
1003 		sc->gif_pdst = NULL;
1004 	}
1005 	ROUTE_RELEASE(&sc->gif_ro);
1006 	/* change the IFF_UP flag as well? */
1007 }
1008