xref: /xnu-8020.101.4/bsd/net/if_gif.c (revision e7776783b89a353188416a9a346c6cdb4928faad)
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, GIF_ZONE_MAX_ELEM, sizeof(struct gif_softc));
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 	if_clone_softc_deallocate(&gif_cloner, 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 = if_clone_softc_allocate(&gif_cloner);
321 	if (sc == NULL) {
322 		log(LOG_ERR, "gif_clone_create: failed to allocate gif%d\n",
323 		    unit);
324 		error = ENOBUFS;
325 		goto done;
326 	}
327 
328 	/* use the interface name as the unique id for ifp recycle */
329 	snprintf(sc->gif_ifname, sizeof(sc->gif_ifname), "%s%d",
330 	    ifc->ifc_name, unit);
331 
332 	lck_mtx_init(&sc->gif_lock, &gif_mtx_grp, &gif_mtx_attr);
333 
334 	bzero(&gif_init_params, sizeof(gif_init_params));
335 	gif_init_params.ver = IFNET_INIT_CURRENT_VERSION;
336 	gif_init_params.len = sizeof(gif_init_params);
337 	gif_init_params.flags = IFNET_INIT_LEGACY;
338 	gif_init_params.uniqueid = sc->gif_ifname;
339 	gif_init_params.uniqueid_len = strlen(sc->gif_ifname);
340 	gif_init_params.name = GIFNAME;
341 	gif_init_params.unit = unit;
342 	gif_init_params.type = IFT_GIF;
343 	gif_init_params.family = IFNET_FAMILY_GIF;
344 	gif_init_params.output = gif_output;
345 	gif_init_params.demux = gif_demux;
346 	gif_init_params.add_proto = gif_add_proto;
347 	gif_init_params.del_proto = gif_del_proto;
348 	gif_init_params.softc = sc;
349 	gif_init_params.ioctl = gif_ioctl;
350 	gif_init_params.set_bpf_tap = gif_set_bpf_tap;
351 	gif_init_params.detach = gif_detach;
352 
353 	error = ifnet_allocate_extended(&gif_init_params, &sc->gif_if);
354 	if (error != 0) {
355 		printf("gif_clone_create, ifnet_allocate failed - %d\n", error);
356 		if_clone_softc_deallocate(&gif_cloner, sc);
357 		error = ENOBUFS;
358 		goto done;
359 	}
360 
361 	sc->encap_cookie4 = sc->encap_cookie6 = NULL;
362 #if INET
363 	sc->encap_cookie4 = encap_attach_func(AF_INET, -1,
364 	    gif_encapcheck, &in_gif_protosw, sc);
365 	if (sc->encap_cookie4 == NULL) {
366 		printf("%s: unable to attach encap4\n", if_name(sc->gif_if));
367 		ifnet_release(sc->gif_if);
368 		if_clone_softc_deallocate(&gif_cloner, sc);
369 		error = ENOBUFS;
370 		goto done;
371 	}
372 #endif
373 	sc->encap_cookie6 = encap_attach_func(AF_INET6, -1,
374 	    gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc);
375 	if (sc->encap_cookie6 == NULL) {
376 		if (sc->encap_cookie4) {
377 			encap_detach(sc->encap_cookie4);
378 			sc->encap_cookie4 = NULL;
379 		}
380 		printf("%s: unable to attach encap6\n", if_name(sc->gif_if));
381 		ifnet_release(sc->gif_if);
382 		if_clone_softc_deallocate(&gif_cloner, sc);
383 		error = ENOBUFS;
384 		goto done;
385 	}
386 	sc->gif_called = 0;
387 	ifnet_set_mtu(sc->gif_if, GIF_MTU);
388 	ifnet_set_flags(sc->gif_if, IFF_POINTOPOINT | IFF_MULTICAST, 0xffff);
389 	sc->gif_flags |= IFGIF_DETACHING;
390 	error = ifnet_attach(sc->gif_if, NULL);
391 	if (error != 0) {
392 		printf("gif_clone_create - ifnet_attach failed - %d\n", error);
393 		ifnet_release(sc->gif_if);
394 		if (sc->encap_cookie4) {
395 			encap_detach(sc->encap_cookie4);
396 			sc->encap_cookie4 = NULL;
397 		}
398 		if (sc->encap_cookie6) {
399 			encap_detach(sc->encap_cookie6);
400 			sc->encap_cookie6 = NULL;
401 		}
402 		if_clone_softc_deallocate(&gif_cloner, sc);
403 		goto done;
404 	}
405 	bpfattach(sc->gif_if, DLT_NULL, sizeof(u_int));
406 	sc->gif_flags &= ~IFGIF_DETACHING;
407 	TAILQ_INSERT_TAIL(&gifs, sc, gif_link);
408 	ngif++;
409 done:
410 	lck_mtx_unlock(&gif_mtx);
411 
412 	return error;
413 }
414 
415 static int
gif_remove(struct ifnet * ifp)416 gif_remove(struct ifnet *ifp)
417 {
418 	int error = 0;
419 	struct gif_softc *sc = NULL;
420 	const struct encaptab *encap_cookie4 = NULL;
421 	const struct encaptab *encap_cookie6 = NULL;
422 
423 	lck_mtx_lock(&gif_mtx);
424 	sc = ifp->if_softc;
425 
426 	if (sc == NULL) {
427 		error = EINVAL;
428 		goto done;
429 	}
430 
431 	GIF_LOCK(sc);
432 	if (sc->gif_flags & IFGIF_DETACHING) {
433 		error = EINVAL;
434 		goto done;
435 	}
436 
437 	sc->gif_flags |= IFGIF_DETACHING;
438 	TAILQ_REMOVE(&gifs, sc, gif_link);
439 	ngif--;
440 
441 	gif_delete_tunnel(sc);
442 	encap_cookie6 = sc->encap_cookie6;
443 #ifdef INET
444 	encap_cookie4 = sc->encap_cookie4;
445 #endif
446 done:
447 	if (sc != NULL) {
448 		GIF_UNLOCK(sc);
449 	}
450 	lck_mtx_unlock(&gif_mtx);
451 
452 	if (encap_cookie6 != NULL) {
453 		error = encap_detach(encap_cookie6);
454 		KASSERT(error == 0, ("gif_clone_destroy: Unexpected "
455 		    "error detaching encap_cookie6"));
456 	}
457 
458 	if (encap_cookie4 != NULL) {
459 		error = encap_detach(encap_cookie4);
460 		KASSERT(error == 0, ("gif_clone_destroy: Unexpected "
461 		    "error detaching encap_cookie4"));
462 	}
463 
464 	return error;
465 }
466 
467 static int
gif_clone_destroy(struct ifnet * ifp)468 gif_clone_destroy(struct ifnet *ifp)
469 {
470 	int error = 0;
471 
472 	error = gif_remove(ifp);
473 	if (error != 0) {
474 		printf("gif_clone_destroy: gif remove failed %d\n", error);
475 		return error;
476 	}
477 
478 	error = ifnet_set_flags(ifp, 0, IFF_UP);
479 	if (error != 0) {
480 		printf("gif_clone_destroy: ifnet_set_flags failed %d\n", error);
481 	}
482 
483 	error = ifnet_detach(ifp);
484 	if (error != 0) {
485 		panic("gif_clone_destroy: ifnet_detach(%p) failed %d", ifp,
486 		    error);
487 	}
488 	return 0;
489 }
490 
491 static int
gif_encapcheck(const struct mbuf * m,int off,int proto,void * arg)492 gif_encapcheck(
493 	const struct mbuf *m,
494 	int off,
495 	int proto,
496 	void *arg)
497 {
498 	int error = 0;
499 	struct ip ip;
500 	struct gif_softc *sc;
501 
502 	sc = (struct gif_softc *)arg;
503 	if (sc == NULL) {
504 		return error;
505 	}
506 
507 	GIF_LOCK(sc);
508 	if ((ifnet_flags(sc->gif_if) & IFF_UP) == 0) {
509 		goto done;
510 	}
511 
512 	/* no physical address */
513 	if (!sc->gif_psrc || !sc->gif_pdst) {
514 		goto done;
515 	}
516 
517 	switch (proto) {
518 #if INET
519 	case IPPROTO_IPV4:
520 		break;
521 #endif
522 	case IPPROTO_IPV6:
523 		break;
524 	default:
525 		goto done;
526 	}
527 
528 	mbuf_copydata((struct mbuf *)(size_t)m, 0, sizeof(ip), &ip);
529 
530 	switch (ip.ip_v) {
531 #if INET
532 	case 4:
533 		if (sc->gif_psrc->sa_family != AF_INET ||
534 		    sc->gif_pdst->sa_family != AF_INET) {
535 			goto done;
536 		}
537 		error = gif_encapcheck4(m, off, proto, arg);
538 #endif
539 		OS_FALLTHROUGH;
540 	case 6:
541 		if (sc->gif_psrc->sa_family != AF_INET6 ||
542 		    sc->gif_pdst->sa_family != AF_INET6) {
543 			goto done;
544 		}
545 		error = gif_encapcheck6(m, off, proto, arg);
546 		OS_FALLTHROUGH;
547 	default:
548 		goto done;
549 	}
550 done:
551 	GIF_UNLOCK(sc);
552 	return error;
553 }
554 
555 static errno_t
gif_output(ifnet_t ifp,mbuf_t m)556 gif_output(
557 	ifnet_t ifp,
558 	mbuf_t m)
559 {
560 	struct gif_softc *sc = ifnet_softc(ifp);
561 	struct sockaddr *gif_psrc;
562 	struct sockaddr *gif_pdst;
563 	int error = 0;
564 
565 	GIF_LOCK(sc);
566 	gif_psrc = sc->gif_psrc;
567 	gif_pdst = sc->gif_pdst;
568 	GIF_UNLOCK(sc);
569 
570 	/*
571 	 * max_gif_nesting check used to live here. It doesn't anymore
572 	 * because there is no guaruntee that we won't be called
573 	 * concurrently from more than one thread.
574 	 */
575 	m->m_flags &= ~(M_BCAST | M_MCAST);
576 	if (!(ifnet_flags(ifp) & IFF_UP) ||
577 	    gif_psrc == NULL || gif_pdst == NULL) {
578 		ifnet_touch_lastchange(ifp);
579 		m_freem(m);     /* free it here not in dlil_output */
580 		error = ENETDOWN;
581 		goto end;
582 	}
583 
584 	bpf_tap_out(ifp, 0, m, &sc->gif_proto, sizeof(sc->gif_proto));
585 
586 	GIF_LOCK(sc);
587 
588 	/* inner AF-specific encapsulation */
589 
590 	/* XXX should we check if our outer source is legal? */
591 
592 	/*
593 	 * Save the length as m may be free by the output functions
594 	 * as they call m_pullup
595 	 */
596 	u_int32_t bytes_out = m->m_pkthdr.len;
597 
598 	/* dispatch to output logic based on outer AF */
599 	switch (sc->gif_psrc->sa_family) {
600 #if INET
601 	case AF_INET:
602 		error = in_gif_output(ifp, sc->gif_proto, m, NULL);
603 		break;
604 #endif
605 	case AF_INET6:
606 		error = in6_gif_output(ifp, sc->gif_proto, m, NULL);
607 		break;
608 	default:
609 		error = ENETDOWN;
610 		break;
611 	}
612 
613 	GIF_UNLOCK(sc);
614 end:
615 	if (error) {
616 		/* the mbuf was freed either by in_gif_output or in here */
617 		ifnet_stat_increment_out(ifp, 0, 0, 1);
618 	} else {
619 		ifnet_stat_increment_out(ifp, 1, bytes_out, 0);
620 	}
621 	if (error == 0) {
622 		error = EJUSTRETURN; /* if no error, packet got sent already */
623 	}
624 	return error;
625 }
626 
627 /*
628  * gif_input is the input handler for IP and IPv6 attached to gif
629  */
630 static errno_t
gif_input(ifnet_t ifp,protocol_family_t protocol_family,mbuf_t m,__unused char * frame_header)631 gif_input(
632 	ifnet_t ifp,
633 	protocol_family_t protocol_family,
634 	mbuf_t m,
635 	__unused char *frame_header)
636 {
637 	struct gif_softc *sc = ifnet_softc(ifp);
638 
639 	bpf_tap_in(ifp, 0, m, &sc->gif_proto, sizeof(sc->gif_proto));
640 
641 	/*
642 	 * Put the packet to the network layer input queue according to the
643 	 * specified address family.
644 	 * Note: older versions of gif_input directly called network layer
645 	 * input functions, e.g. ip6_input, here. We changed the policy to
646 	 * prevent too many recursive calls of such input functions, which
647 	 * might cause kernel panic. But the change may introduce another
648 	 * problem; if the input queue is full, packets are discarded.
649 	 * We believed it rarely occurs and changed the policy. If we find
650 	 * it occurs more times than we thought, we may change the policy
651 	 * again.
652 	 */
653 	int32_t pktlen = m->m_pkthdr.len;
654 	if (proto_input(protocol_family, m) != 0) {
655 		ifnet_stat_increment_in(ifp, 0, 0, 1);
656 		m_freem(m);
657 	} else {
658 		ifnet_stat_increment_in(ifp, 1, pktlen, 0);
659 	}
660 
661 	return 0;
662 }
663 
664 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
665 static errno_t
gif_ioctl(ifnet_t ifp,u_long cmd,void * data)666 gif_ioctl(
667 	ifnet_t                 ifp,
668 	u_long                  cmd,
669 	void                    *data)
670 {
671 	struct gif_softc *sc  = ifnet_softc(ifp);
672 	struct ifreq *ifr = (struct ifreq *)data;
673 	int error = 0, size;
674 	struct sockaddr *dst = NULL, *src = NULL;
675 	struct sockaddr *sa;
676 	struct ifnet *ifp2;
677 	struct gif_softc *sc2;
678 
679 	switch (cmd) {
680 	case SIOCSIFADDR:
681 		break;
682 
683 	case SIOCSIFDSTADDR:
684 		break;
685 
686 	case SIOCADDMULTI:
687 	case SIOCDELMULTI:
688 		break;
689 
690 #ifdef  SIOCSIFMTU /* xxx */
691 	case SIOCGIFMTU:
692 		break;
693 
694 	case SIOCSIFMTU:
695 	{
696 		u_int32_t mtu;
697 		mtu = ifr->ifr_mtu;
698 		if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
699 			return EINVAL;
700 		}
701 		ifnet_set_mtu(ifp, mtu);
702 	}
703 	break;
704 #endif /* SIOCSIFMTU */
705 
706 	case SIOCSIFPHYADDR:
707 	case SIOCSIFPHYADDR_IN6_32:
708 	case SIOCSIFPHYADDR_IN6_64:
709 		switch (cmd) {
710 #if INET
711 		case SIOCSIFPHYADDR:
712 			src = (struct sockaddr *)
713 			    &(((struct in_aliasreq *)data)->ifra_addr);
714 			dst = (struct sockaddr *)
715 			    &(((struct in_aliasreq *)data)->ifra_dstaddr);
716 			break;
717 #endif
718 		case SIOCSIFPHYADDR_IN6_32: {
719 			struct in6_aliasreq_32 *ifra_32 =
720 			    (struct in6_aliasreq_32 *)data;
721 
722 			src = (struct sockaddr *)&ifra_32->ifra_addr;
723 			dst = (struct sockaddr *)&ifra_32->ifra_dstaddr;
724 			break;
725 		}
726 
727 		case SIOCSIFPHYADDR_IN6_64: {
728 			struct in6_aliasreq_64 *ifra_64 =
729 			    (struct in6_aliasreq_64 *)data;
730 
731 			src = (struct sockaddr *)&ifra_64->ifra_addr;
732 			dst = (struct sockaddr *)&ifra_64->ifra_dstaddr;
733 			break;
734 		}
735 		}
736 
737 		/* sa_family must be equal */
738 		if (src->sa_family != dst->sa_family) {
739 			return EINVAL;
740 		}
741 
742 		/* validate sa_len */
743 		switch (src->sa_family) {
744 #if INET
745 		case AF_INET:
746 			if (src->sa_len != sizeof(struct sockaddr_in)) {
747 				return EINVAL;
748 			}
749 			break;
750 #endif
751 		case AF_INET6:
752 			if (src->sa_len != sizeof(struct sockaddr_in6)) {
753 				return EINVAL;
754 			}
755 			break;
756 		default:
757 			return EAFNOSUPPORT;
758 		}
759 		switch (dst->sa_family) {
760 #if INET
761 		case AF_INET:
762 			if (dst->sa_len != sizeof(struct sockaddr_in)) {
763 				return EINVAL;
764 			}
765 			break;
766 #endif
767 		case AF_INET6:
768 			if (dst->sa_len != sizeof(struct sockaddr_in6)) {
769 				return EINVAL;
770 			}
771 			break;
772 		default:
773 			return EAFNOSUPPORT;
774 		}
775 
776 		/* check sa_family looks sane for the cmd */
777 		switch (cmd) {
778 		case SIOCSIFPHYADDR:
779 			if (src->sa_family == AF_INET) {
780 				break;
781 			}
782 			return EAFNOSUPPORT;
783 		case SIOCSIFPHYADDR_IN6_32:
784 		case SIOCSIFPHYADDR_IN6_64:
785 			if (src->sa_family == AF_INET6) {
786 				break;
787 			}
788 			return EAFNOSUPPORT;
789 		}
790 
791 #define GIF_ORDERED_LOCK(sc, sc2)       \
792 	if (sc < sc2) {                 \
793 	        GIF_LOCK(sc);           \
794 	        GIF_LOCK(sc2);          \
795 	} else {                        \
796 	        GIF_LOCK(sc2);          \
797 	        GIF_LOCK(sc);           \
798 	}
799 
800 #define GIF_ORDERED_UNLOCK(sc, sc2)     \
801 	if (sc > sc2) {                 \
802 	        GIF_UNLOCK(sc);         \
803 	        GIF_UNLOCK(sc2);        \
804 	} else {                        \
805 	        GIF_UNLOCK(sc2);        \
806 	        GIF_UNLOCK(sc);         \
807 	}
808 
809 		ifnet_head_lock_shared();
810 		TAILQ_FOREACH(ifp2, &ifnet_head, if_link) {
811 			if (strcmp(ifnet_name(ifp2), GIFNAME) != 0) {
812 				continue;
813 			}
814 			sc2 = ifnet_softc(ifp2);
815 			if (sc2 == sc) {
816 				continue;
817 			}
818 			/* lock sc and sc2 in increasing order of ifnet index */
819 			GIF_ORDERED_LOCK(sc, sc2);
820 			if (!sc2->gif_pdst || !sc2->gif_psrc) {
821 				GIF_ORDERED_UNLOCK(sc, sc2);
822 				continue;
823 			}
824 			if (sc2->gif_pdst->sa_family != dst->sa_family ||
825 			    sc2->gif_pdst->sa_len != dst->sa_len ||
826 			    sc2->gif_psrc->sa_family != src->sa_family ||
827 			    sc2->gif_psrc->sa_len != src->sa_len) {
828 				GIF_ORDERED_UNLOCK(sc, sc2);
829 				continue;
830 			}
831 #ifndef XBONEHACK
832 			/* can't configure same pair of address onto two gifs */
833 			if (bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
834 			    bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
835 				GIF_ORDERED_UNLOCK(sc, sc2);
836 				error = EADDRNOTAVAIL;
837 				ifnet_head_done();
838 				goto bad;
839 			}
840 #endif
841 
842 			/* can't configure multiple multi-dest interfaces */
843 #define multidest(x) \
844 	(((struct sockaddr_in *)(void *)(x))->sin_addr.s_addr == INADDR_ANY)
845 #define multidest6(x) \
846 	(IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)      \
847 	    (void *)(x))->sin6_addr))
848 			if (dst->sa_family == AF_INET &&
849 			    multidest(dst) && multidest(sc2->gif_pdst)) {
850 				GIF_ORDERED_UNLOCK(sc, sc2);
851 				error = EADDRNOTAVAIL;
852 				ifnet_head_done();
853 				goto bad;
854 			}
855 			if (dst->sa_family == AF_INET6 &&
856 			    multidest6(dst) && multidest6(sc2->gif_pdst)) {
857 				GIF_ORDERED_UNLOCK(sc, sc2);
858 				error = EADDRNOTAVAIL;
859 				ifnet_head_done();
860 				goto bad;
861 			}
862 			GIF_ORDERED_UNLOCK(sc, sc2);
863 		}
864 		ifnet_head_done();
865 
866 		GIF_LOCK(sc);
867 		if (sc->gif_psrc) {
868 			kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
869 		}
870 		sa = (struct sockaddr *)kalloc_data(src->sa_len, Z_WAITOK);
871 		if (sa == NULL) {
872 			GIF_UNLOCK(sc);
873 			return ENOBUFS;
874 		}
875 		bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
876 		sc->gif_psrc = sa;
877 
878 		if (sc->gif_pdst) {
879 			kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
880 		}
881 		sa = (struct sockaddr *)kalloc_data(dst->sa_len, Z_WAITOK);
882 		if (sa == NULL) {
883 			GIF_UNLOCK(sc);
884 			return ENOBUFS;
885 		}
886 		bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
887 		sc->gif_pdst = sa;
888 		GIF_UNLOCK(sc);
889 
890 		ifnet_set_flags(ifp, IFF_RUNNING | IFF_UP, IFF_RUNNING |
891 		    IFF_UP);
892 
893 		error = 0;
894 		break;
895 
896 #ifdef SIOCDIFPHYADDR
897 	case SIOCDIFPHYADDR:
898 		GIF_LOCK(sc);
899 		if (sc->gif_psrc) {
900 			kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
901 			sc->gif_psrc = NULL;
902 		}
903 		if (sc->gif_pdst) {
904 			kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
905 			sc->gif_pdst = NULL;
906 		}
907 		GIF_UNLOCK(sc);
908 		/* change the IFF_{UP, RUNNING} flag as well? */
909 		break;
910 #endif
911 
912 	case SIOCGIFPSRCADDR:
913 	case SIOCGIFPSRCADDR_IN6:
914 		GIF_LOCK(sc);
915 		if (sc->gif_psrc == NULL) {
916 			GIF_UNLOCK(sc);
917 			error = EADDRNOTAVAIL;
918 			goto bad;
919 		}
920 		src = sc->gif_psrc;
921 		switch (cmd) {
922 #if INET
923 		case SIOCGIFPSRCADDR:
924 			dst = &ifr->ifr_addr;
925 			size = sizeof(ifr->ifr_addr);
926 			break;
927 #endif /* INET */
928 		case SIOCGIFPSRCADDR_IN6:
929 			dst = (struct sockaddr *)
930 			    &(((struct in6_ifreq *)data)->ifr_addr);
931 			size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
932 			break;
933 		default:
934 			GIF_UNLOCK(sc);
935 			error = EADDRNOTAVAIL;
936 			goto bad;
937 		}
938 		if (src->sa_len > size) {
939 			GIF_UNLOCK(sc);
940 			return EINVAL;
941 		}
942 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
943 		GIF_UNLOCK(sc);
944 		break;
945 
946 	case SIOCGIFPDSTADDR:
947 	case SIOCGIFPDSTADDR_IN6:
948 		GIF_LOCK(sc);
949 		if (sc->gif_pdst == NULL) {
950 			GIF_UNLOCK(sc);
951 			error = EADDRNOTAVAIL;
952 			goto bad;
953 		}
954 		src = sc->gif_pdst;
955 		switch (cmd) {
956 #if INET
957 		case SIOCGIFPDSTADDR:
958 			dst = &ifr->ifr_addr;
959 			size = sizeof(ifr->ifr_addr);
960 			break;
961 #endif /* INET */
962 		case SIOCGIFPDSTADDR_IN6:
963 			dst = (struct sockaddr *)
964 			    &(((struct in6_ifreq *)data)->ifr_addr);
965 			size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
966 			break;
967 		default:
968 			error = EADDRNOTAVAIL;
969 			GIF_UNLOCK(sc);
970 			goto bad;
971 		}
972 		if (src->sa_len > size) {
973 			GIF_UNLOCK(sc);
974 			return EINVAL;
975 		}
976 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
977 		GIF_UNLOCK(sc);
978 		break;
979 
980 	case SIOCSIFFLAGS:
981 		/* if_ioctl() takes care of it */
982 		break;
983 
984 	default:
985 		error = EOPNOTSUPP;
986 		break;
987 	}
988 bad:
989 	return error;
990 }
991 
992 static void
gif_delete_tunnel(struct gif_softc * sc)993 gif_delete_tunnel(struct gif_softc *sc)
994 {
995 	GIF_LOCK_ASSERT(sc);
996 	if (sc->gif_psrc) {
997 		kfree_data(sc->gif_psrc, sc->gif_psrc->sa_len);
998 		sc->gif_psrc = NULL;
999 	}
1000 	if (sc->gif_pdst) {
1001 		kfree_data(sc->gif_pdst, sc->gif_pdst->sa_len);
1002 		sc->gif_pdst = NULL;
1003 	}
1004 	ROUTE_RELEASE(&sc->gif_ro);
1005 	/* change the IFF_UP flag as well? */
1006 }
1007