2 * Copyright (c) 2000-2018 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>
78 #include <kern/zalloc.h>
81 #include <net/if_types.h>
82 #include <net/route.h>
84 #include <net/kpi_protocol.h>
85 #include <net/kpi_interface.h>
88 #include <netinet/in.h>
89 #include <netinet/in_systm.h>
90 #include <netinet/ip.h>
92 #include <netinet/in_var.h>
93 #include <netinet/in_gif.h>
94 #include <netinet/ip_var.h>
98 #include <netinet6/in6_var.h>
99 #include <netinet/ip6.h>
100 #include <netinet6/ip6_var.h>
101 #include <netinet6/in6_gif.h>
102 #include <netinet6/ip6protosw.h>
105 #include <netinet/ip_encap.h>
106 #include <net/dlil.h>
107 #include <net/if_gif.h>
109 #include <net/net_osdep.h>
112 #include <security/mac_framework.h>
115 #define GIFNAME "gif"
116 #define GIFDEV "if_gif"
118 #define GIF_MAXUNIT IF_MAXUNIT
119 #define GIF_ZONE_MAX_ELEM MIN(IFNETS_MAX, GIF_MAXUNIT)
121 /* gif lock variables */
122 static lck_grp_t
*gif_mtx_grp
;
123 static lck_grp_attr_t
*gif_mtx_grp_attr
;
124 static lck_attr_t
*gif_mtx_attr
;
125 decl_lck_mtx_data(static, gif_mtx_data
);
126 static lck_mtx_t
*gif_mtx
= &gif_mtx_data
;
128 TAILQ_HEAD(gifhead
, gif_softc
) gifs
= TAILQ_HEAD_INITIALIZER(gifs
);
130 static int gif_encapcheck(const struct mbuf
*, int, int, void *);
131 static errno_t
gif_output(ifnet_t ifp
, mbuf_t m
);
132 static errno_t
gif_input(ifnet_t ifp
, protocol_family_t protocol_family
,
133 mbuf_t m
, char *frame_header
);
134 static errno_t
gif_ioctl(ifnet_t ifp
, u_long cmd
, void *data
);
136 static int ngif
= 0; /* number of interfaces */
139 static struct protosw in_gif_protosw
=
142 .pr_protocol
= 0, /* IPPROTO_IPV[46] */
143 .pr_flags
= PR_ATOMIC
|PR_ADDR
,
144 .pr_input
= in_gif_input
,
145 .pr_usrreqs
= &rip_usrreqs
,
146 .pr_unlock
= rip_unlock
,
150 static struct ip6protosw in6_gif_protosw
=
153 .pr_protocol
= 0, /* IPPROTO_IPV[46] */
154 .pr_flags
= PR_ATOMIC
|PR_ADDR
,
155 .pr_input
= in6_gif_input
,
156 .pr_usrreqs
= &rip6_usrreqs
,
157 .pr_unlock
= rip_unlock
,
161 static int gif_remove(struct ifnet
*);
162 static int gif_clone_create(struct if_clone
*, uint32_t, void *);
163 static int gif_clone_destroy(struct ifnet
*);
164 static void gif_delete_tunnel(struct gif_softc
*);
165 static void gif_detach(struct ifnet
*);
167 static struct if_clone gif_cloner
=
168 IF_CLONE_INITIALIZER(GIFNAME
, gif_clone_create
, gif_clone_destroy
,
169 0, GIF_MAXUNIT
, GIF_ZONE_MAX_ELEM
, sizeof(struct gif_softc
));
171 * Theory of operation: initially, one gif interface is created.
172 * Any time a gif interface is configured, if there are no other
173 * unconfigured gif interfaces, a new gif interface is created.
174 * BSD uses the clone mechanism to dynamically create more
177 * We have some extra glue to support DLIL.
180 /* GIF interface module support */
185 __unused
char *frame_header
,
186 protocol_family_t
*protocol_family
)
188 struct gif_softc
*sc
= ifnet_softc(ifp
);
191 /* Only one protocol may be attached to a gif interface. */
192 *protocol_family
= sc
->gif_proto
;
201 protocol_family_t protocol_family
,
202 __unused
const struct ifnet_demux_desc
*demux_array
,
203 __unused u_int32_t demux_count
)
205 /* Only one protocol may be attached at a time */
206 struct gif_softc
*sc
= ifnet_softc(ifp
);
209 if (sc
->gif_proto
!= 0)
210 printf("gif_add_proto: request add_proto for gif%d\n",
213 sc
->gif_proto
= protocol_family
;
222 protocol_family_t protocol_family
)
224 struct gif_softc
*sc
= ifnet_softc(ifp
);
227 if (sc
->gif_proto
== protocol_family
)
234 /* Glue code to attach inet to a gif interface through DLIL */
236 gif_attach_proto_family(
238 protocol_family_t protocol_family
)
240 struct ifnet_attach_proto_param reg
;
243 bzero(®
, sizeof (reg
));
244 reg
.input
= gif_input
;
246 stat
= ifnet_attach_protocol(ifp
, protocol_family
, ®
);
247 if (stat
&& stat
!= EEXIST
) {
248 printf("gif_attach_proto_family can't attach interface \
249 fam=%d\n", protocol_family
);
255 /* Function to setup the first gif interface */
261 /* Initialize the list of interfaces */
264 /* Initialize the gif global lock */
265 gif_mtx_grp_attr
= lck_grp_attr_alloc_init();
266 gif_mtx_grp
= lck_grp_alloc_init("gif", gif_mtx_grp_attr
);
267 gif_mtx_attr
= lck_attr_alloc_init();
268 lck_mtx_init(gif_mtx
, gif_mtx_grp
, gif_mtx_attr
);
270 /* Register protocol registration functions */
271 result
= proto_register_plumber(PF_INET
, APPLE_IF_FAM_GIF
,
272 gif_attach_proto_family
, NULL
);
274 printf("proto_register_plumber failed for AF_INET error=%d\n",
277 result
= proto_register_plumber(PF_INET6
, APPLE_IF_FAM_GIF
,
278 gif_attach_proto_family
, NULL
);
280 printf("proto_register_plumber failed for AF_INET6 error=%d\n",
283 result
= if_clone_attach(&gif_cloner
);
285 panic("%s: if_clone_attach() failed, error %d\n", __func__
, result
);
287 gif_clone_create(&gif_cloner
, 0, NULL
);
294 bpf_packet_func callback
)
296 struct gif_softc
*sc
= ifnet_softc(ifp
);
300 sc
->tap_callback
= callback
;
307 gif_detach(struct ifnet
*ifp
)
309 struct gif_softc
*sc
= ifp
->if_softc
;
310 lck_mtx_destroy(&sc
->gif_lock
, gif_mtx_grp
);
311 if_clone_softc_deallocate(&gif_cloner
, sc
);
312 ifp
->if_softc
= NULL
;
313 (void) ifnet_release(ifp
);
317 gif_clone_create(struct if_clone
*ifc
, uint32_t unit
, __unused
void *params
)
319 struct gif_softc
*sc
= NULL
;
320 struct ifnet_init_eparams gif_init_params
;
323 lck_mtx_lock(gif_mtx
);
325 /* Can't create more than GIF_MAXUNIT */
326 if (ngif
>= GIF_MAXUNIT
) {
331 sc
= if_clone_softc_allocate(&gif_cloner
);
333 log(LOG_ERR
, "gif_clone_create: failed to allocate gif%d\n",
339 /* use the interface name as the unique id for ifp recycle */
340 snprintf(sc
->gif_ifname
, sizeof (sc
->gif_ifname
), "%s%d",
341 ifc
->ifc_name
, unit
);
343 lck_mtx_init(&sc
->gif_lock
, gif_mtx_grp
, gif_mtx_attr
);
345 bzero(&gif_init_params
, sizeof (gif_init_params
));
346 gif_init_params
.ver
= IFNET_INIT_CURRENT_VERSION
;
347 gif_init_params
.len
= sizeof (gif_init_params
);
348 gif_init_params
.flags
= IFNET_INIT_LEGACY
;
349 gif_init_params
.uniqueid
= sc
->gif_ifname
;
350 gif_init_params
.uniqueid_len
= strlen(sc
->gif_ifname
);
351 gif_init_params
.name
= GIFNAME
;
352 gif_init_params
.unit
= unit
;
353 gif_init_params
.type
= IFT_GIF
;
354 gif_init_params
.family
= IFNET_FAMILY_GIF
;
355 gif_init_params
.output
= gif_output
;
356 gif_init_params
.demux
= gif_demux
;
357 gif_init_params
.add_proto
= gif_add_proto
;
358 gif_init_params
.del_proto
= gif_del_proto
;
359 gif_init_params
.softc
= sc
;
360 gif_init_params
.ioctl
= gif_ioctl
;
361 gif_init_params
.set_bpf_tap
= gif_set_bpf_tap
;
362 gif_init_params
.detach
= gif_detach
;
364 error
= ifnet_allocate_extended(&gif_init_params
, &sc
->gif_if
);
366 printf("gif_clone_create, ifnet_allocate failed - %d\n", error
);
367 if_clone_softc_deallocate(&gif_cloner
, sc
);
372 sc
->encap_cookie4
= sc
->encap_cookie6
= NULL
;
374 sc
->encap_cookie4
= encap_attach_func(AF_INET
, -1,
375 gif_encapcheck
, &in_gif_protosw
, sc
);
376 if (sc
->encap_cookie4
== NULL
) {
377 printf("%s: unable to attach encap4\n", if_name(sc
->gif_if
));
378 ifnet_release(sc
->gif_if
);
379 if_clone_softc_deallocate(&gif_cloner
, sc
);
385 sc
->encap_cookie6
= encap_attach_func(AF_INET6
, -1,
386 gif_encapcheck
, (struct protosw
*)&in6_gif_protosw
, sc
);
387 if (sc
->encap_cookie6
== NULL
) {
388 if (sc
->encap_cookie4
) {
389 encap_detach(sc
->encap_cookie4
);
390 sc
->encap_cookie4
= NULL
;
392 printf("%s: unable to attach encap6\n", if_name(sc
->gif_if
));
393 ifnet_release(sc
->gif_if
);
394 if_clone_softc_deallocate(&gif_cloner
, sc
);
400 ifnet_set_mtu(sc
->gif_if
, GIF_MTU
);
401 ifnet_set_flags(sc
->gif_if
, IFF_POINTOPOINT
| IFF_MULTICAST
, 0xffff);
403 /* turn off ingress filter */
404 sc
->gif_if
.if_flags
|= IFF_LINK2
;
406 sc
->gif_flags
|= IFGIF_DETACHING
;
407 error
= ifnet_attach(sc
->gif_if
, NULL
);
409 printf("gif_clone_create - ifnet_attach failed - %d\n", error
);
410 ifnet_release(sc
->gif_if
);
411 if (sc
->encap_cookie4
) {
412 encap_detach(sc
->encap_cookie4
);
413 sc
->encap_cookie4
= NULL
;
415 if (sc
->encap_cookie6
) {
416 encap_detach(sc
->encap_cookie6
);
417 sc
->encap_cookie6
= NULL
;
419 if_clone_softc_deallocate(&gif_cloner
, sc
);
423 mac_ifnet_label_init(&sc
->gif_if
);
425 bpfattach(sc
->gif_if
, DLT_NULL
, sizeof (u_int
));
426 sc
->gif_flags
&= ~IFGIF_DETACHING
;
427 TAILQ_INSERT_TAIL(&gifs
, sc
, gif_link
);
430 lck_mtx_unlock(gif_mtx
);
436 gif_remove(struct ifnet
*ifp
)
439 struct gif_softc
*sc
= NULL
;
441 lck_mtx_lock(gif_mtx
);
450 if (sc
->gif_flags
& IFGIF_DETACHING
) {
455 sc
->gif_flags
|= IFGIF_DETACHING
;
456 TAILQ_REMOVE(&gifs
, sc
, gif_link
);
459 gif_delete_tunnel(sc
);
461 if (sc
->encap_cookie6
!= NULL
) {
462 error
= encap_detach(sc
->encap_cookie6
);
463 KASSERT(error
== 0, ("gif_clone_destroy: Unexpected "
464 "error detaching encap_cookie6"));
468 if (sc
->encap_cookie4
!= NULL
) {
469 error
= encap_detach(sc
->encap_cookie4
);
470 KASSERT(error
== 0, ("gif_clone_destroy: Unexpected "
471 "error detaching encap_cookie4"));
477 lck_mtx_unlock(gif_mtx
);
483 gif_clone_destroy(struct ifnet
*ifp
)
487 error
= gif_remove(ifp
);
489 printf("gif_clone_destroy: gif remove failed %d\n", error
);
493 error
= ifnet_set_flags(ifp
, 0, IFF_UP
);
495 printf("gif_clone_destroy: ifnet_set_flags failed %d\n", error
);
498 error
= ifnet_detach(ifp
);
500 panic("gif_clone_destroy: ifnet_detach(%p) failed %d\n", ifp
,
507 const struct mbuf
*m
,
514 struct gif_softc
*sc
;
516 sc
= (struct gif_softc
*)arg
;
521 if ((ifnet_flags(sc
->gif_if
) & IFF_UP
) == 0)
524 /* no physical address */
525 if (!sc
->gif_psrc
|| !sc
->gif_pdst
)
541 mbuf_copydata((struct mbuf
*)(size_t)m
, 0, sizeof (ip
), &ip
);
546 if (sc
->gif_psrc
->sa_family
!= AF_INET
||
547 sc
->gif_pdst
->sa_family
!= AF_INET
)
549 error
= gif_encapcheck4(m
, off
, proto
, arg
);
553 if (sc
->gif_psrc
->sa_family
!= AF_INET6
||
554 sc
->gif_pdst
->sa_family
!= AF_INET6
)
556 error
= gif_encapcheck6(m
, off
, proto
, arg
);
571 struct gif_softc
*sc
= ifnet_softc(ifp
);
572 struct sockaddr
*gif_psrc
;
573 struct sockaddr
*gif_pdst
;
577 gif_psrc
= sc
->gif_psrc
;
578 gif_pdst
= sc
->gif_pdst
;
582 * max_gif_nesting check used to live here. It doesn't anymore
583 * because there is no guaruntee that we won't be called
584 * concurrently from more than one thread.
586 m
->m_flags
&= ~(M_BCAST
|M_MCAST
);
587 if (!(ifnet_flags(ifp
) & IFF_UP
) ||
588 gif_psrc
== NULL
|| gif_pdst
== NULL
) {
589 ifnet_touch_lastchange(ifp
);
590 m_freem(m
); /* free it here not in dlil_output */
595 bpf_tap_out(ifp
, 0, m
, &sc
->gif_proto
, sizeof (sc
->gif_proto
));
599 /* inner AF-specific encapsulation */
601 /* XXX should we check if our outer source is legal? */
603 /* dispatch to output logic based on outer AF */
604 switch (sc
->gif_psrc
->sa_family
) {
607 error
= in_gif_output(ifp
, sc
->gif_proto
, m
, NULL
);
612 error
= in6_gif_output(ifp
, sc
->gif_proto
, m
, NULL
);
623 /* the mbuf was freed either by in_gif_output or in here */
624 ifnet_stat_increment_out(ifp
, 0, 0, 1);
626 ifnet_stat_increment_out(ifp
, 1, m
->m_pkthdr
.len
, 0);
629 error
= EJUSTRETURN
; /* if no error, packet got sent already */
634 * gif_input is the input handler for IP and IPv6 attached to gif
639 protocol_family_t protocol_family
,
641 __unused
char *frame_header
)
643 struct gif_softc
*sc
= ifnet_softc(ifp
);
645 bpf_tap_in(ifp
, 0, m
, &sc
->gif_proto
, sizeof (sc
->gif_proto
));
648 * Put the packet to the network layer input queue according to the
649 * specified address family.
650 * Note: older versions of gif_input directly called network layer
651 * input functions, e.g. ip6_input, here. We changed the policy to
652 * prevent too many recursive calls of such input functions, which
653 * might cause kernel panic. But the change may introduce another
654 * problem; if the input queue is full, packets are discarded.
655 * We believed it rarely occurs and changed the policy. If we find
656 * it occurs more times than we thought, we may change the policy
659 int32_t pktlen
= m
->m_pkthdr
.len
;
660 if (proto_input(protocol_family
, m
) != 0) {
661 ifnet_stat_increment_in(ifp
, 0, 0, 1);
664 ifnet_stat_increment_in(ifp
, 1, pktlen
, 0);
670 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
677 struct gif_softc
*sc
= ifnet_softc(ifp
);
678 struct ifreq
*ifr
= (struct ifreq
*)data
;
680 struct sockaddr
*dst
= NULL
, *src
= NULL
;
683 struct gif_softc
*sc2
;
696 #ifdef SIOCSIFMTU /* xxx */
704 if (mtu
< GIF_MTU_MIN
|| mtu
> GIF_MTU_MAX
) {
707 ifnet_set_mtu(ifp
, mtu
);
710 #endif /* SIOCSIFMTU */
714 case SIOCSIFPHYADDR_IN6_32
:
715 case SIOCSIFPHYADDR_IN6_64
:
720 src
= (struct sockaddr
*)
721 &(((struct in_aliasreq
*)data
)->ifra_addr
);
722 dst
= (struct sockaddr
*)
723 &(((struct in_aliasreq
*)data
)->ifra_dstaddr
);
727 case SIOCSIFPHYADDR_IN6_32
: {
728 struct in6_aliasreq_32
*ifra_32
=
729 (struct in6_aliasreq_32
*)data
;
731 src
= (struct sockaddr
*)&ifra_32
->ifra_addr
;
732 dst
= (struct sockaddr
*)&ifra_32
->ifra_dstaddr
;
736 case SIOCSIFPHYADDR_IN6_64
: {
737 struct in6_aliasreq_64
*ifra_64
=
738 (struct in6_aliasreq_64
*)data
;
740 src
= (struct sockaddr
*)&ifra_64
->ifra_addr
;
741 dst
= (struct sockaddr
*)&ifra_64
->ifra_dstaddr
;
747 /* sa_family must be equal */
748 if (src
->sa_family
!= dst
->sa_family
)
751 /* validate sa_len */
752 switch (src
->sa_family
) {
755 if (src
->sa_len
!= sizeof (struct sockaddr_in
))
761 if (src
->sa_len
!= sizeof (struct sockaddr_in6
))
766 return (EAFNOSUPPORT
);
768 switch (dst
->sa_family
) {
771 if (dst
->sa_len
!= sizeof (struct sockaddr_in
))
777 if (dst
->sa_len
!= sizeof (struct sockaddr_in6
))
782 return (EAFNOSUPPORT
);
785 /* check sa_family looks sane for the cmd */
788 if (src
->sa_family
== AF_INET
)
790 return (EAFNOSUPPORT
);
792 case SIOCSIFPHYADDR_IN6_32
:
793 case SIOCSIFPHYADDR_IN6_64
:
794 if (src
->sa_family
== AF_INET6
)
796 return (EAFNOSUPPORT
);
800 #define GIF_ORDERED_LOCK(sc, sc2) \
809 #define GIF_ORDERED_UNLOCK(sc, sc2) \
818 ifnet_head_lock_shared();
819 TAILQ_FOREACH(ifp2
, &ifnet_head
, if_link
) {
820 if (strcmp(ifnet_name(ifp2
), GIFNAME
) != 0)
822 sc2
= ifnet_softc(ifp2
);
825 /* lock sc and sc2 in increasing order of ifnet index */
826 GIF_ORDERED_LOCK(sc
, sc2
);
827 if (!sc2
->gif_pdst
|| !sc2
->gif_psrc
) {
828 GIF_ORDERED_UNLOCK(sc
, sc2
);
831 if (sc2
->gif_pdst
->sa_family
!= dst
->sa_family
||
832 sc2
->gif_pdst
->sa_len
!= dst
->sa_len
||
833 sc2
->gif_psrc
->sa_family
!= src
->sa_family
||
834 sc2
->gif_psrc
->sa_len
!= src
->sa_len
) {
835 GIF_ORDERED_UNLOCK(sc
, sc2
);
839 /* can't configure same pair of address onto two gifs */
840 if (bcmp(sc2
->gif_pdst
, dst
, dst
->sa_len
) == 0 &&
841 bcmp(sc2
->gif_psrc
, src
, src
->sa_len
) == 0) {
842 GIF_ORDERED_UNLOCK(sc
, sc2
);
843 error
= EADDRNOTAVAIL
;
849 /* can't configure multiple multi-dest interfaces */
850 #define multidest(x) \
851 (((struct sockaddr_in *)(void *)(x))->sin_addr.s_addr == INADDR_ANY)
853 #define multidest6(x) \
854 (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) \
855 (void *)(x))->sin6_addr))
857 if (dst
->sa_family
== AF_INET
&&
858 multidest(dst
) && multidest(sc2
->gif_pdst
)) {
859 GIF_ORDERED_UNLOCK(sc
, sc2
);
860 error
= EADDRNOTAVAIL
;
865 if (dst
->sa_family
== AF_INET6
&&
866 multidest6(dst
) && multidest6(sc2
->gif_pdst
)) {
867 GIF_ORDERED_UNLOCK(sc
, sc2
);
868 error
= EADDRNOTAVAIL
;
873 GIF_ORDERED_UNLOCK(sc
, sc2
);
879 FREE((caddr_t
)sc
->gif_psrc
, M_IFADDR
);
880 sa
= (struct sockaddr
*)_MALLOC(src
->sa_len
, M_IFADDR
,
886 bcopy((caddr_t
)src
, (caddr_t
)sa
, src
->sa_len
);
890 FREE((caddr_t
)sc
->gif_pdst
, M_IFADDR
);
891 sa
= (struct sockaddr
*)_MALLOC(dst
->sa_len
, M_IFADDR
,
897 bcopy((caddr_t
)dst
, (caddr_t
)sa
, dst
->sa_len
);
901 ifnet_set_flags(ifp
, IFF_RUNNING
| IFF_UP
, IFF_RUNNING
|
907 #ifdef SIOCDIFPHYADDR
911 FREE((caddr_t
)sc
->gif_psrc
, M_IFADDR
);
915 FREE((caddr_t
)sc
->gif_pdst
, M_IFADDR
);
919 /* change the IFF_{UP, RUNNING} flag as well? */
923 case SIOCGIFPSRCADDR
:
925 case SIOCGIFPSRCADDR_IN6
:
928 if (sc
->gif_psrc
== NULL
) {
930 error
= EADDRNOTAVAIL
;
936 case SIOCGIFPSRCADDR
:
937 dst
= &ifr
->ifr_addr
;
938 size
= sizeof (ifr
->ifr_addr
);
942 case SIOCGIFPSRCADDR_IN6
:
943 dst
= (struct sockaddr
*)
944 &(((struct in6_ifreq
*)data
)->ifr_addr
);
945 size
= sizeof (((struct in6_ifreq
*)data
)->ifr_addr
);
950 error
= EADDRNOTAVAIL
;
953 if (src
->sa_len
> size
) {
957 bcopy((caddr_t
)src
, (caddr_t
)dst
, src
->sa_len
);
961 case SIOCGIFPDSTADDR
:
963 case SIOCGIFPDSTADDR_IN6
:
966 if (sc
->gif_pdst
== NULL
) {
968 error
= EADDRNOTAVAIL
;
974 case SIOCGIFPDSTADDR
:
975 dst
= &ifr
->ifr_addr
;
976 size
= sizeof (ifr
->ifr_addr
);
980 case SIOCGIFPDSTADDR_IN6
:
981 dst
= (struct sockaddr
*)
982 &(((struct in6_ifreq
*)data
)->ifr_addr
);
983 size
= sizeof (((struct in6_ifreq
*)data
)->ifr_addr
);
987 error
= EADDRNOTAVAIL
;
991 if (src
->sa_len
> size
) {
995 bcopy((caddr_t
)src
, (caddr_t
)dst
, src
->sa_len
);
1000 /* if_ioctl() takes care of it */
1012 gif_delete_tunnel(struct gif_softc
*sc
)
1014 GIF_LOCK_ASSERT(sc
);
1016 FREE((caddr_t
)sc
->gif_psrc
, M_IFADDR
);
1017 sc
->gif_psrc
= NULL
;
1020 FREE((caddr_t
)sc
->gif_pdst
, M_IFADDR
);
1021 sc
->gif_pdst
= NULL
;
1023 ROUTE_RELEASE(&sc
->gif_ro
);
1024 /* change the IFF_UP flag as well? */