2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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 $ */
32 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
33 * All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
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.
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
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,
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/kernel.h>
69 #include <sys/malloc.h>
71 #include <sys/socket.h>
72 #include <sys/sockio.h>
73 #include <sys/errno.h>
75 #include <sys/syslog.h>
76 #include <sys/protosw.h>
77 #include <kern/cpu_number.h>
80 #include <net/if_types.h>
81 #include <net/route.h>
83 #include <net/kpi_protocol.h>
84 #include <net/kpi_interface.h>
86 #include <netinet/in.h>
87 #include <netinet/in_systm.h>
88 #include <netinet/ip.h>
90 #include <netinet/in_var.h>
91 #include <netinet/in_gif.h>
92 #include <netinet/ip_var.h>
96 #include <netinet6/in6_var.h>
97 #include <netinet/ip6.h>
98 #include <netinet6/ip6_var.h>
99 #include <netinet6/in6_gif.h>
100 #include <netinet6/ip6protosw.h>
103 #include <netinet/ip_encap.h>
104 #include <net/dlil.h>
105 #include <net/if_gif.h>
107 #include <net/net_osdep.h>
110 #include <security/mac_framework.h>
113 #define GIFNAME "gif"
114 #define GIFDEV "if_gif"
115 #define GIF_MAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */
118 static MALLOC_DEFINE(M_GIF
, "gif", "Generic Tunnel Interface");
121 TAILQ_HEAD(gifhead
, gif_softc
) gifs
= TAILQ_HEAD_INITIALIZER(gifs
);
124 void gifattach(void);
125 static void gif_create_dev(void);
126 static int gif_encapcheck(const struct mbuf
*, int, int, void*);
127 static errno_t
gif_output(ifnet_t ifp
, mbuf_t m
);
128 static errno_t
gif_input(ifnet_t ifp
, protocol_family_t protocol_family
,
129 mbuf_t m
, char *frame_header
);
130 static errno_t
gif_ioctl(ifnet_t ifp
, u_int32_t cmd
, void *data
);
132 int ngif
= 0; /* number of interfaces */
136 struct protosw in_gif_protosw
=
137 { SOCK_RAW
, 0, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC
|PR_ADDR
,
138 in_gif_input
, 0, 0, 0,
143 0, rip_unlock
, 0, {0, 0}, 0, {0}
147 struct ip6protosw in6_gif_protosw
=
148 { SOCK_RAW
, 0, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC
|PR_ADDR
,
149 in6_gif_input
, 0, 0, 0,
154 0, rip_unlock
, 0, {0, 0}, 0, {0}
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
167 * We have some extra glue to support DLIL.
170 /* GIF interface module support */
171 static int gif_demux(
174 __unused
char *frame_header
,
175 protocol_family_t
*protocol_family
)
177 /* Only one protocol may be attached to a gif interface. */
178 *protocol_family
= ((struct gif_softc
*)ifnet_softc(ifp
))->gif_proto
;
186 protocol_family_t protocol_family
,
187 __unused
const struct ifnet_demux_desc
*demux_array
,
188 __unused u_int32_t demux_count
)
190 /* Only one protocol may be attached at a time */
191 struct gif_softc
* gif
= ifnet_softc(ifp
);
193 if (gif
->gif_proto
!= 0)
194 printf("gif_add_proto: request add_proto for gif%d\n", ifnet_unit(ifp
));
196 gif
->gif_proto
= protocol_family
;
204 protocol_family_t protocol_family
)
206 if (((struct gif_softc
*)ifnet_softc(ifp
))->gif_proto
== protocol_family
)
207 ((struct gif_softc
*)ifnet_softc(ifp
))->gif_proto
= 0;
212 /* Glue code to attach inet to a gif interface through DLIL */
214 gif_attach_proto_family(
216 protocol_family_t protocol_family
)
218 struct ifnet_attach_proto_param reg
;
221 bzero(®
, sizeof(reg
));
222 reg
.input
= gif_input
;
224 stat
= ifnet_attach_protocol(ifp
, protocol_family
, ®
);
225 if (stat
&& stat
!= EEXIST
) {
226 printf("gif_attach_proto_family can't attach interface fam=%d\n",
235 /* Function to setup the first gif interface */
236 __private_extern__
void
241 /* Init the list of interfaces */
244 /* Register protocol registration functions */
245 result
= proto_register_plumber(PF_INET
, APPLE_IF_FAM_GIF
,
246 gif_attach_proto_family
, NULL
);
248 printf("proto_register_plumber failed for AF_INET error=%d\n", result
);
250 result
= proto_register_plumber(PF_INET6
, APPLE_IF_FAM_GIF
,
251 gif_attach_proto_family
, NULL
);
253 printf("proto_register_plumber failed for AF_INET6 error=%d\n", result
);
255 /* Create first device */
263 bpf_packet_func callback
)
265 struct gif_softc
*sc
= ifnet_softc(ifp
);
268 sc
->tap_callback
= callback
;
273 /* Creates another gif device if there are none free */
277 struct gif_softc
*sc
;
278 struct ifnet_init_params gif_init
;
282 /* Can't create more than GIF_MAXUNIT */
283 if (ngif
>= GIF_MAXUNIT
)
286 /* Check for unused gif interface */
287 TAILQ_FOREACH(sc
, &gifs
, gif_link
) {
288 /* If unused, return, no need to create a new interface */
289 if ((ifnet_flags(sc
->gif_if
) & IFF_RUNNING
) == 0)
293 sc
= _MALLOC(sizeof(struct gif_softc
), M_DEVBUF
, M_WAITOK
);
295 log(LOG_ERR
, "gifattach: failed to allocate gif%d\n", ngif
);
299 bzero(&gif_init
, sizeof(gif_init
));
300 gif_init
.name
= GIFNAME
;
301 gif_init
.unit
= ngif
;
302 gif_init
.type
= IFT_GIF
;
303 gif_init
.family
= IFNET_FAMILY_GIF
;
304 gif_init
.output
= gif_output
;
305 gif_init
.demux
= gif_demux
;
306 gif_init
.add_proto
= gif_add_proto
;
307 gif_init
.del_proto
= gif_del_proto
;
309 gif_init
.ioctl
= gif_ioctl
;
310 gif_init
.set_bpf_tap
= gif_set_bpf_tap
;
312 bzero(sc
, sizeof(struct gif_softc
));
313 result
= ifnet_allocate(&gif_init
, &sc
->gif_if
);
315 printf("gif_create_dev, ifnet_allocate failed - %d\n", result
);
319 sc
->encap_cookie4
= sc
->encap_cookie6
= NULL
;
321 sc
->encap_cookie4
= encap_attach_func(AF_INET
, -1,
322 gif_encapcheck
, &in_gif_protosw
, sc
);
323 if (sc
->encap_cookie4
== NULL
) {
324 printf("%s: unable to attach encap4\n", if_name(sc
->gif_if
));
325 ifnet_release(sc
->gif_if
);
331 sc
->encap_cookie6
= encap_attach_func(AF_INET6
, -1,
332 gif_encapcheck
, (struct protosw
*)&in6_gif_protosw
, sc
);
333 if (sc
->encap_cookie6
== NULL
) {
334 if (sc
->encap_cookie4
) {
335 encap_detach(sc
->encap_cookie4
);
336 sc
->encap_cookie4
= NULL
;
338 printf("%s: unable to attach encap6\n", if_name(sc
->gif_if
));
339 ifnet_release(sc
->gif_if
);
345 ifnet_set_mtu(sc
->gif_if
, GIF_MTU
);
346 ifnet_set_flags(sc
->gif_if
, IFF_POINTOPOINT
| IFF_MULTICAST
, 0xffff);
348 /* turn off ingress filter */
349 sc
->gif_if
.if_flags
|= IFF_LINK2
;
351 result
= ifnet_attach(sc
->gif_if
, NULL
);
353 printf("gif_create_dev - ifnet_attach failed - %d\n", result
);
354 ifnet_release(sc
->gif_if
);
359 mac_ifnet_label_init(&sc
->gif_if
);
361 bpfattach(sc
->gif_if
, DLT_NULL
, sizeof(u_int
));
362 TAILQ_INSERT_TAIL(&gifs
, sc
, gif_link
);
368 const struct mbuf
*m
,
374 struct gif_softc
*sc
;
376 sc
= (struct gif_softc
*)arg
;
380 if ((ifnet_flags(sc
->gif_if
) & IFF_UP
) == 0)
383 /* no physical address */
384 if (!sc
->gif_psrc
|| !sc
->gif_pdst
)
400 mbuf_copydata(m
, 0, sizeof(ip
), &ip
);
405 if (sc
->gif_psrc
->sa_family
!= AF_INET
||
406 sc
->gif_pdst
->sa_family
!= AF_INET
)
408 return gif_encapcheck4(m
, off
, proto
, arg
);
412 if (sc
->gif_psrc
->sa_family
!= AF_INET6
||
413 sc
->gif_pdst
->sa_family
!= AF_INET6
)
415 return gif_encapcheck6(m
, off
, proto
, arg
);
427 struct gif_softc
*sc
= ifnet_softc(ifp
);
431 max_gif_nesting check used to live here. It doesn't anymore
432 because there is no guaruntee that we won't be called
433 concurrently from more than one thread.
436 m
->m_flags
&= ~(M_BCAST
|M_MCAST
);
437 if (!(ifnet_flags(ifp
) & IFF_UP
) ||
438 sc
->gif_psrc
== NULL
|| sc
->gif_pdst
== NULL
) {
439 ifnet_touch_lastchange(ifp
);
440 m_freem(m
); /* free it here not in dlil_output */
445 bpf_tap_out(ifp
, 0, m
, &sc
->gif_proto
, sizeof(sc
->gif_proto
));
447 /* inner AF-specific encapsulation */
449 /* XXX should we check if our outer source is legal? */
451 /* dispatch to output logic based on outer AF */
452 switch (sc
->gif_psrc
->sa_family
) {
455 error
= in_gif_output(ifp
, sc
->gif_proto
, m
, NULL
);
460 error
= in6_gif_output(ifp
, sc
->gif_proto
, m
, NULL
);
470 /* the mbuf was freed either by in_gif_output or in here */
471 ifnet_stat_increment_out(ifp
, 0, 0, 1);
474 ifnet_stat_increment_out(ifp
, 1, m
->m_pkthdr
.len
, 0);
477 error
= EJUSTRETURN
; /* if no error, packet got sent already */
482 * gif_input is the input handler for IP and IPv6 attached to gif
487 protocol_family_t protocol_family
,
489 __unused
char *frame_header
)
492 struct gif_softc
*sc
= ifnet_softc(ifp
);
494 bpf_tap_in(ifp
, 0, m
, &sc
->gif_proto
, sizeof(sc
->gif_proto
));
497 * Put the packet to the network layer input queue according to the
498 * specified address family.
499 * Note: older versions of gif_input directly called network layer
500 * input functions, e.g. ip6_input, here. We changed the policy to
501 * prevent too many recursive calls of such input functions, which
502 * might cause kernel panic. But the change may introduce another
503 * problem; if the input queue is full, packets are discarded.
504 * We believed it rarely occurs and changed the policy. If we find
505 * it occurs more times than we thought, we may change the policy
508 error
= proto_input(protocol_family
, m
);
509 ifnet_stat_increment_in(ifp
, 1, m
->m_pkthdr
.len
, 0);
514 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
521 struct gif_softc
*sc
= ifnet_softc(ifp
);
522 struct ifreq
*ifr
= (struct ifreq
*)data
;
524 struct sockaddr
*dst
= NULL
, *src
= NULL
;
527 struct gif_softc
*sc2
;
540 #ifdef SIOCSIFMTU /* xxx */
548 if (mtu
< GIF_MTU_MIN
|| mtu
> GIF_MTU_MAX
) {
551 ifnet_set_mtu(ifp
, mtu
);
554 #endif /* SIOCSIFMTU */
558 case SIOCSIFPHYADDR_IN6
:
560 case SIOCSLIFPHYADDR
:
564 src
= (struct sockaddr
*)
565 &(((struct in_aliasreq
*)data
)->ifra_addr
);
566 dst
= (struct sockaddr
*)
567 &(((struct in_aliasreq
*)data
)->ifra_dstaddr
);
571 case SIOCSIFPHYADDR_IN6
:
572 src
= (struct sockaddr
*)
573 &(((struct in6_aliasreq
*)data
)->ifra_addr
);
574 dst
= (struct sockaddr
*)
575 &(((struct in6_aliasreq
*)data
)->ifra_dstaddr
);
578 case SIOCSLIFPHYADDR
:
579 src
= (struct sockaddr
*)
580 &(((struct if_laddrreq
*)data
)->addr
);
581 dst
= (struct sockaddr
*)
582 &(((struct if_laddrreq
*)data
)->dstaddr
);
585 /* sa_family must be equal */
586 if (src
->sa_family
!= dst
->sa_family
)
589 /* validate sa_len */
590 switch (src
->sa_family
) {
593 if (src
->sa_len
!= sizeof(struct sockaddr_in
))
599 if (src
->sa_len
!= sizeof(struct sockaddr_in6
))
606 switch (dst
->sa_family
) {
609 if (dst
->sa_len
!= sizeof(struct sockaddr_in
))
615 if (dst
->sa_len
!= sizeof(struct sockaddr_in6
))
623 /* check sa_family looks sane for the cmd */
626 if (src
->sa_family
== AF_INET
)
630 case SIOCSIFPHYADDR_IN6
:
631 if (src
->sa_family
== AF_INET6
)
635 case SIOCSLIFPHYADDR
:
636 /* checks done in the above */
640 ifnet_head_lock_shared();
641 TAILQ_FOREACH(ifp2
, &ifnet_head
, if_link
) {
642 if (strcmp(ifnet_name(ifp2
), GIFNAME
) != 0)
644 sc2
= ifnet_softc(ifp2
);
647 if (!sc2
->gif_pdst
|| !sc2
->gif_psrc
)
649 if (sc2
->gif_pdst
->sa_family
!= dst
->sa_family
||
650 sc2
->gif_pdst
->sa_len
!= dst
->sa_len
||
651 sc2
->gif_psrc
->sa_family
!= src
->sa_family
||
652 sc2
->gif_psrc
->sa_len
!= src
->sa_len
)
655 /* can't configure same pair of address onto two gifs */
656 if (bcmp(sc2
->gif_pdst
, dst
, dst
->sa_len
) == 0 &&
657 bcmp(sc2
->gif_psrc
, src
, src
->sa_len
) == 0) {
658 error
= EADDRNOTAVAIL
;
664 /* can't configure multiple multi-dest interfaces */
665 #define multidest(x) \
666 (((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY)
668 #define multidest6(x) \
669 (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr))
671 if (dst
->sa_family
== AF_INET
&&
672 multidest(dst
) && multidest(sc2
->gif_pdst
)) {
673 error
= EADDRNOTAVAIL
;
678 if (dst
->sa_family
== AF_INET6
&&
679 multidest6(dst
) && multidest6(sc2
->gif_pdst
)) {
680 error
= EADDRNOTAVAIL
;
689 FREE((caddr_t
)sc
->gif_psrc
, M_IFADDR
);
690 sa
= (struct sockaddr
*)_MALLOC(src
->sa_len
, M_IFADDR
, M_WAITOK
);
691 bcopy((caddr_t
)src
, (caddr_t
)sa
, src
->sa_len
);
695 FREE((caddr_t
)sc
->gif_pdst
, M_IFADDR
);
696 sa
= (struct sockaddr
*)_MALLOC(dst
->sa_len
, M_IFADDR
, M_WAITOK
);
697 bcopy((caddr_t
)dst
, (caddr_t
)sa
, dst
->sa_len
);
700 ifnet_set_flags(ifp
, IFF_RUNNING
| IFF_UP
, IFF_RUNNING
| IFF_UP
);
703 /* Make sure at least one unused device is still available */
710 #ifdef SIOCDIFPHYADDR
713 FREE((caddr_t
)sc
->gif_psrc
, M_IFADDR
);
717 FREE((caddr_t
)sc
->gif_pdst
, M_IFADDR
);
720 /* change the IFF_{UP, RUNNING} flag as well? */
724 case SIOCGIFPSRCADDR
:
726 case SIOCGIFPSRCADDR_IN6
:
728 if (sc
->gif_psrc
== NULL
) {
729 error
= EADDRNOTAVAIL
;
735 case SIOCGIFPSRCADDR
:
736 dst
= &ifr
->ifr_addr
;
737 size
= sizeof(ifr
->ifr_addr
);
741 case SIOCGIFPSRCADDR_IN6
:
742 dst
= (struct sockaddr
*)
743 &(((struct in6_ifreq
*)data
)->ifr_addr
);
744 size
= sizeof(((struct in6_ifreq
*)data
)->ifr_addr
);
748 error
= EADDRNOTAVAIL
;
751 if (src
->sa_len
> size
)
753 bcopy((caddr_t
)src
, (caddr_t
)dst
, src
->sa_len
);
756 case SIOCGIFPDSTADDR
:
758 case SIOCGIFPDSTADDR_IN6
:
760 if (sc
->gif_pdst
== NULL
) {
761 error
= EADDRNOTAVAIL
;
767 case SIOCGIFPDSTADDR
:
768 dst
= &ifr
->ifr_addr
;
769 size
= sizeof(ifr
->ifr_addr
);
773 case SIOCGIFPDSTADDR_IN6
:
774 dst
= (struct sockaddr
*)
775 &(((struct in6_ifreq
*)data
)->ifr_addr
);
776 size
= sizeof(((struct in6_ifreq
*)data
)->ifr_addr
);
780 error
= EADDRNOTAVAIL
;
783 if (src
->sa_len
> size
)
785 bcopy((caddr_t
)src
, (caddr_t
)dst
, src
->sa_len
);
788 case SIOCGLIFPHYADDR
:
789 if (sc
->gif_psrc
== NULL
|| sc
->gif_pdst
== NULL
) {
790 error
= EADDRNOTAVAIL
;
796 dst
= (struct sockaddr
*)
797 &(((struct if_laddrreq
*)data
)->addr
);
798 size
= sizeof(((struct if_laddrreq
*)data
)->addr
);
799 if (src
->sa_len
> size
)
801 bcopy((caddr_t
)src
, (caddr_t
)dst
, src
->sa_len
);
805 dst
= (struct sockaddr
*)
806 &(((struct if_laddrreq
*)data
)->dstaddr
);
807 size
= sizeof(((struct if_laddrreq
*)data
)->dstaddr
);
808 if (src
->sa_len
> size
)
810 bcopy((caddr_t
)src
, (caddr_t
)dst
, src
->sa_len
);
814 /* if_ioctl() takes care of it */
826 /* This function is not used in our stack */
828 gif_delete_tunnel(sc
)
829 struct gif_softc
*sc
;
831 /* XXX: NetBSD protects this function with splsoftnet() */
834 FREE((caddr_t
)sc
->gif_psrc
, M_IFADDR
);
838 FREE((caddr_t
)sc
->gif_pdst
, M_IFADDR
);
841 /* change the IFF_UP flag as well? */