xref: /xnu-10063.101.15/bsd/net/if_gif.c (revision 94d3b452840153a99b38a3a9659680b2a006908e)
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 *data);
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 *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 *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 *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 *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 *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 *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 = sc->gif_ifname;
335 	gif_init_params.uniqueid_len = strlen(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 *sc = NULL;
416 	const struct encaptab *encap_cookie4 = NULL;
417 	const struct encaptab *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 *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((struct mbuf *)(size_t)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 *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 *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 * data)662 gif_ioctl(
663 	ifnet_t                 ifp,
664 	u_long                  cmd,
665 	void                    *data)
666 {
667 	struct gif_softc *sc  = ifnet_softc(ifp);
668 	struct ifreq *ifr = (struct ifreq *)data;
669 	int error = 0, size;
670 	struct sockaddr *dst = NULL, *src = NULL;
671 	struct sockaddr *sa;
672 	struct ifnet *ifp2;
673 	struct gif_softc *sc2;
674 
675 	switch (cmd) {
676 	case SIOCSIFADDR:
677 		break;
678 
679 	case SIOCSIFDSTADDR:
680 		break;
681 
682 	case SIOCADDMULTI:
683 	case SIOCDELMULTI:
684 		break;
685 
686 #ifdef  SIOCSIFMTU /* xxx */
687 	case SIOCGIFMTU:
688 		break;
689 
690 	case SIOCSIFMTU:
691 	{
692 		u_int32_t mtu;
693 		mtu = ifr->ifr_mtu;
694 		if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
695 			return EINVAL;
696 		}
697 		ifnet_set_mtu(ifp, mtu);
698 	}
699 	break;
700 #endif /* SIOCSIFMTU */
701 
702 	case SIOCSIFPHYADDR:
703 	case SIOCSIFPHYADDR_IN6_32:
704 	case SIOCSIFPHYADDR_IN6_64:
705 		switch (cmd) {
706 #if INET
707 		case SIOCSIFPHYADDR: {
708 			struct in_aliasreq *ifra =
709 			    (struct in_aliasreq*)data;
710 
711 			src = SA(&ifra->ifra_addr);
712 			dst = SA(&ifra->ifra_dstaddr);
713 			break;
714 		}
715 #endif
716 		case SIOCSIFPHYADDR_IN6_32: {
717 			struct in6_aliasreq_32 *ifra_32 =
718 			    (struct in6_aliasreq_32 *)data;
719 
720 			src = SA(&ifra_32->ifra_addr);
721 			dst = SA(&ifra_32->ifra_dstaddr);
722 			break;
723 		}
724 
725 		case SIOCSIFPHYADDR_IN6_64: {
726 			struct in6_aliasreq_64 *ifra_64 =
727 			    (struct in6_aliasreq_64 *)data;
728 
729 			src = SA(&ifra_64->ifra_addr);
730 			dst = SA(&ifra_64->ifra_dstaddr);
731 			break;
732 		}
733 		}
734 
735 		/* sa_family must be equal */
736 		if (src->sa_family != dst->sa_family) {
737 			return EINVAL;
738 		}
739 
740 		/* validate sa_len */
741 		switch (src->sa_family) {
742 #if INET
743 		case AF_INET:
744 			if (src->sa_len != sizeof(struct sockaddr_in)) {
745 				return EINVAL;
746 			}
747 			break;
748 #endif
749 		case AF_INET6:
750 			if (src->sa_len != sizeof(struct sockaddr_in6)) {
751 				return EINVAL;
752 			}
753 			break;
754 		default:
755 			return EAFNOSUPPORT;
756 		}
757 		switch (dst->sa_family) {
758 #if INET
759 		case AF_INET:
760 			if (dst->sa_len != sizeof(struct sockaddr_in)) {
761 				return EINVAL;
762 			}
763 			break;
764 #endif
765 		case AF_INET6:
766 			if (dst->sa_len != sizeof(struct sockaddr_in6)) {
767 				return EINVAL;
768 			}
769 			break;
770 		default:
771 			return EAFNOSUPPORT;
772 		}
773 
774 		/* check sa_family looks sane for the cmd */
775 		switch (cmd) {
776 		case SIOCSIFPHYADDR:
777 			if (src->sa_family == AF_INET) {
778 				break;
779 			}
780 			return EAFNOSUPPORT;
781 		case SIOCSIFPHYADDR_IN6_32:
782 		case SIOCSIFPHYADDR_IN6_64:
783 			if (src->sa_family == AF_INET6) {
784 				break;
785 			}
786 			return EAFNOSUPPORT;
787 		}
788 
789 #define GIF_ORDERED_LOCK(sc, sc2)       \
790 	if (sc < sc2) {                 \
791 	        GIF_LOCK(sc);           \
792 	        GIF_LOCK(sc2);          \
793 	} else {                        \
794 	        GIF_LOCK(sc2);          \
795 	        GIF_LOCK(sc);           \
796 	}
797 
798 #define GIF_ORDERED_UNLOCK(sc, sc2)     \
799 	if (sc > sc2) {                 \
800 	        GIF_UNLOCK(sc);         \
801 	        GIF_UNLOCK(sc2);        \
802 	} else {                        \
803 	        GIF_UNLOCK(sc2);        \
804 	        GIF_UNLOCK(sc);         \
805 	}
806 
807 		ifnet_head_lock_shared();
808 		TAILQ_FOREACH(ifp2, &ifnet_head, if_link) {
809 			if (strcmp(ifnet_name(ifp2), GIFNAME) != 0) {
810 				continue;
811 			}
812 			sc2 = ifnet_softc(ifp2);
813 			if (sc2 == sc) {
814 				continue;
815 			}
816 			/* lock sc and sc2 in increasing order of ifnet index */
817 			GIF_ORDERED_LOCK(sc, sc2);
818 			if (!sc2->gif_pdst || !sc2->gif_psrc) {
819 				GIF_ORDERED_UNLOCK(sc, sc2);
820 				continue;
821 			}
822 			if (sc2->gif_pdst->sa_family != dst->sa_family ||
823 			    sc2->gif_pdst->sa_len != dst->sa_len ||
824 			    sc2->gif_psrc->sa_family != src->sa_family ||
825 			    sc2->gif_psrc->sa_len != src->sa_len) {
826 				GIF_ORDERED_UNLOCK(sc, sc2);
827 				continue;
828 			}
829 #ifndef XBONEHACK
830 			/* can't configure same pair of address onto two gifs */
831 			if (SOCKADDR_CMP(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
832 			    SOCKADDR_CMP(sc2->gif_psrc, src, src->sa_len) == 0) {
833 				GIF_ORDERED_UNLOCK(sc, sc2);
834 				error = EADDRNOTAVAIL;
835 				ifnet_head_done();
836 				goto bad;
837 			}
838 #endif
839 
840 			/* can't configure multiple multi-dest interfaces */
841 #define multidest(x) \
842 	(((struct sockaddr_in *)(void *)(x))->sin_addr.s_addr == INADDR_ANY)
843 #define multidest6(x) \
844 	(IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)      \
845 	    (void *)(x))->sin6_addr))
846 			if (dst->sa_family == AF_INET &&
847 			    multidest(dst) && multidest(sc2->gif_pdst)) {
848 				GIF_ORDERED_UNLOCK(sc, sc2);
849 				error = EADDRNOTAVAIL;
850 				ifnet_head_done();
851 				goto bad;
852 			}
853 			if (dst->sa_family == AF_INET6 &&
854 			    multidest6(dst) && multidest6(sc2->gif_pdst)) {
855 				GIF_ORDERED_UNLOCK(sc, sc2);
856 				error = EADDRNOTAVAIL;
857 				ifnet_head_done();
858 				goto bad;
859 			}
860 			GIF_ORDERED_UNLOCK(sc, sc2);
861 		}
862 		ifnet_head_done();
863 
864 		GIF_LOCK(sc);
865 		if (sc->gif_psrc) {
866 			kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
867 		}
868 		sa = SA(kalloc_data(src->sa_len, Z_WAITOK));
869 		if (sa == NULL) {
870 			GIF_UNLOCK(sc);
871 			return ENOBUFS;
872 		}
873 		bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
874 		sc->gif_psrc = sa;
875 
876 		if (sc->gif_pdst) {
877 			kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
878 		}
879 		sa = SA(kalloc_data(dst->sa_len, Z_WAITOK));
880 		if (sa == NULL) {
881 			GIF_UNLOCK(sc);
882 			return ENOBUFS;
883 		}
884 		bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
885 		sc->gif_pdst = sa;
886 		GIF_UNLOCK(sc);
887 
888 		ifnet_set_flags(ifp, IFF_RUNNING | IFF_UP, IFF_RUNNING |
889 		    IFF_UP);
890 
891 		error = 0;
892 		break;
893 
894 #ifdef SIOCDIFPHYADDR
895 	case SIOCDIFPHYADDR:
896 		GIF_LOCK(sc);
897 		if (sc->gif_psrc) {
898 			kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
899 			sc->gif_psrc = NULL;
900 		}
901 		if (sc->gif_pdst) {
902 			kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
903 			sc->gif_pdst = NULL;
904 		}
905 		GIF_UNLOCK(sc);
906 		/* change the IFF_{UP, RUNNING} flag as well? */
907 		break;
908 #endif
909 
910 	case SIOCGIFPSRCADDR:
911 	case SIOCGIFPSRCADDR_IN6:
912 		GIF_LOCK(sc);
913 		if (sc->gif_psrc == NULL) {
914 			GIF_UNLOCK(sc);
915 			error = EADDRNOTAVAIL;
916 			goto bad;
917 		}
918 		src = sc->gif_psrc;
919 		switch (cmd) {
920 #if INET
921 		case SIOCGIFPSRCADDR:
922 			dst = &ifr->ifr_addr;
923 			size = sizeof(ifr->ifr_addr);
924 			break;
925 #endif /* INET */
926 		case SIOCGIFPSRCADDR_IN6: {
927 			struct in6_ifreq *ifreq =
928 			    (struct in6_ifreq*)data;
929 
930 			dst = SA(&ifreq->ifr_addr);
931 			size = sizeof(ifreq->ifr_addr);
932 			break;
933 		}
934 		default:
935 			GIF_UNLOCK(sc);
936 			error = EADDRNOTAVAIL;
937 			goto bad;
938 		}
939 		if (src->sa_len > size) {
940 			GIF_UNLOCK(sc);
941 			return EINVAL;
942 		}
943 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
944 		GIF_UNLOCK(sc);
945 		break;
946 
947 	case SIOCGIFPDSTADDR:
948 	case SIOCGIFPDSTADDR_IN6:
949 		GIF_LOCK(sc);
950 		if (sc->gif_pdst == NULL) {
951 			GIF_UNLOCK(sc);
952 			error = EADDRNOTAVAIL;
953 			goto bad;
954 		}
955 		src = sc->gif_pdst;
956 		switch (cmd) {
957 #if INET
958 		case SIOCGIFPDSTADDR:
959 			dst = &ifr->ifr_addr;
960 			size = sizeof(ifr->ifr_addr);
961 			break;
962 #endif /* INET */
963 		case SIOCGIFPDSTADDR_IN6: {
964 			struct in6_ifreq *ifreq =
965 			    (struct in6_ifreq*)data;
966 
967 			dst = SA(&ifreq->ifr_addr);
968 			size = sizeof(ifreq->ifr_addr);
969 			break;
970 		}
971 		default:
972 			error = EADDRNOTAVAIL;
973 			GIF_UNLOCK(sc);
974 			goto bad;
975 		}
976 		if (src->sa_len > size) {
977 			GIF_UNLOCK(sc);
978 			return EINVAL;
979 		}
980 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
981 		GIF_UNLOCK(sc);
982 		break;
983 
984 	case SIOCSIFFLAGS:
985 		/* if_ioctl() takes care of it */
986 		break;
987 
988 	default:
989 		error = EOPNOTSUPP;
990 		break;
991 	}
992 bad:
993 	return error;
994 }
995 
996 static void
gif_delete_tunnel(struct gif_softc * sc)997 gif_delete_tunnel(struct gif_softc *sc)
998 {
999 	GIF_LOCK_ASSERT(sc);
1000 	if (sc->gif_psrc) {
1001 		kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
1002 		sc->gif_psrc = NULL;
1003 	}
1004 	if (sc->gif_pdst) {
1005 		kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
1006 		sc->gif_pdst = NULL;
1007 	}
1008 	ROUTE_RELEASE(&sc->gif_ro);
1009 	/* change the IFF_UP flag as well? */
1010 }
1011