2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* $FreeBSD: src/sys/net/if_gif.c,v 1.4.2.6 2001/07/24 19:10:18 brooks Exp $ */
26 /* $KAME: if_gif.c,v 1.47 2001/05/01 05:28:42 itojun Exp $ */
29 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
30 * All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. Neither the name of the project nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/kernel.h>
60 #include <sys/malloc.h>
62 #include <sys/socket.h>
63 #include <sys/sockio.h>
64 #include <sys/errno.h>
66 #include <sys/syslog.h>
67 #include <sys/protosw.h>
68 #include <kern/cpu_number.h>
71 #include <net/if_types.h>
72 #include <net/netisr.h>
73 #include <net/route.h>
76 #include <netinet/in.h>
77 #include <netinet/in_systm.h>
78 #include <netinet/ip.h>
80 #include <netinet/in_var.h>
81 #include <netinet/in_gif.h>
82 #include <netinet/ip_var.h>
86 #include <netinet6/in6_var.h>
87 #include <netinet/ip6.h>
88 #include <netinet6/ip6_var.h>
89 #include <netinet6/in6_gif.h>
90 #include <netinet6/ip6protosw.h>
93 #include <netinet/ip_encap.h>
95 #include <net/if_gif.h>
97 #include <net/net_osdep.h>
100 #define GIFDEV "if_gif"
101 #define GIF_MAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */
104 static MALLOC_DEFINE(M_GIF
, "gif", "Generic Tunnel Interface");
107 TAILQ_HEAD(gifhead
, gif_softc
) gifs
= TAILQ_HEAD_INITIALIZER(gifs
);
110 void gifattach
__P((void));
111 int gif_pre_output
__P((struct ifnet
*, register struct mbuf
**, struct sockaddr
*,
112 caddr_t
, char *, char *, u_long
));
113 static void gif_create_dev(void);
114 static int gif_encapcheck(const struct mbuf
*, int, int, void*);
117 int ngif
= 0; /* number of interfaces */
121 struct protosw in_gif_protosw
=
122 { SOCK_RAW
, 0, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC
|PR_ADDR
,
123 in_gif_input
, 0, 0, 0,
131 struct ip6protosw in6_gif_protosw
=
132 { SOCK_RAW
, 0, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC
|PR_ADDR
,
144 * This macro controls the upper limitation on nesting of gif tunnels.
145 * Since, setting a large value to this macro with a careless configuration
146 * may introduce system crash, we don't allow any nestings by default.
147 * If you need to configure nested gif tunnels, you can define this macro
148 * in your kernel configuration file. However, if you do so, please be
149 * careful to configure the tunnels so that it won't make a loop.
151 #define MAX_GIF_NEST 1
153 static int max_gif_nesting
= MAX_GIF_NEST
;
159 * Theory of operation: initially, one gif interface is created.
160 * Any time a gif interface is configured, if there are no other
161 * unconfigured gif interfaces, a new gif interface is created.
162 * BSD uses the clone mechanism to dynamically create more
165 * We have some extra glue to support DLIL.
168 /* GIF interface module support */
169 int gif_demux(ifp
, m
, frame_header
, proto
)
173 struct if_proto
**proto
;
175 struct gif_softc
* gif
= (struct gif_softc
*)ifp
->if_softc
;
177 /* Only one protocol may be attached to a gif interface. */
178 *proto
= gif
->gif_proto
;
184 int gif_add_if(struct ifnet
*ifp
)
186 ifp
->if_demux
= gif_demux
;
192 int gif_del_if(struct ifnet
*ifp
)
198 int gif_add_proto(struct ddesc_head_str
*desc_head
, struct if_proto
*proto
, u_long dl_tag
)
200 /* Only one protocol may be attached at a time */
201 struct gif_softc
* gif
= (struct gif_softc
*)proto
->ifp
;
203 if (gif
->gif_proto
!= NULL
)
204 printf("gif_add_proto: request add_proto for gif%d\n", gif
->gif_if
.if_unit
);
206 gif
->gif_proto
= proto
;
212 int gif_del_proto(struct if_proto
*proto
, u_long dl_tag
)
214 if (((struct gif_softc
*)proto
->ifp
)->gif_proto
== proto
)
215 ((struct gif_softc
*)proto
->ifp
)->gif_proto
= NULL
;
227 void gif_reg_if_mods()
229 struct dlil_ifmod_reg_str gif_ifmod
;
231 bzero(&gif_ifmod
, sizeof(gif_ifmod
));
232 gif_ifmod
.add_if
= gif_add_if
;
233 gif_ifmod
.del_if
= gif_del_if
;
234 gif_ifmod
.add_proto
= gif_add_proto
;
235 gif_ifmod
.del_proto
= gif_del_proto
;
236 gif_ifmod
.ifmod_ioctl
= 0;
237 gif_ifmod
.shutdown
= gif_shutdown
;
239 if (dlil_reg_if_modules(APPLE_IF_FAM_GIF
, &gif_ifmod
))
240 panic("Couldn't register gif modules\n");
244 /* Glue code to attach inet to a gif interface through DLIL */
246 u_long
gif_attach_proto_family(struct ifnet
*ifp
, int af
)
248 struct dlil_proto_reg_str reg
;
249 struct dlil_demux_desc desc
;
254 /* Check if we're already attached */
255 stat
= dlil_find_dltag(ifp
->if_family
, ifp
->if_unit
, af
, &dl_tag
);
259 TAILQ_INIT(®
.demux_desc_head
);
260 desc
.type
= DLIL_DESC_RAW
;
261 desc
.variants
.bitmask
.proto_id_length
= 0;
262 desc
.variants
.bitmask
.proto_id
= 0;
263 desc
.variants
.bitmask
.proto_id_mask
= 0;
264 desc
.native_type
= (char *) &native
;
265 TAILQ_INSERT_TAIL(®
.demux_desc_head
, &desc
, next
);
266 reg
.interface_family
= ifp
->if_family
;
267 reg
.unit_number
= ifp
->if_unit
;
268 reg
.input
= gif_input
;
269 reg
.pre_output
= gif_pre_output
;
273 reg
.default_proto
= 0;
274 reg
.protocol_family
= af
;
276 stat
= dlil_attach_protocol(®
, &dl_tag
);
278 panic("gif_attach_proto_family can't attach interface fam=%d\n", af
);
284 u_long
gif_detach_proto_family(struct ifnet
*ifp
, int af
)
286 u_long ip_dl_tag
= 0;
289 stat
= dlil_find_dltag(ifp
->if_family
, ifp
->if_unit
, af
, &ip_dl_tag
);
291 stat
= dlil_detach_protocol(ip_dl_tag
);
293 printf("WARNING: gif_detach can't detach IP fam=%d from interface\n", af
);
299 int gif_attach_inet(struct ifnet
*ifp
, u_long
*dl_tag
) {
300 *dl_tag
= gif_attach_proto_family(ifp
, AF_INET
);
304 int gif_detach_inet(struct ifnet
*ifp
, u_long dl_tag
) {
305 gif_detach_proto_family(ifp
, AF_INET
);
309 int gif_attach_inet6(struct ifnet
*ifp
, u_long
*dl_tag
) {
310 *dl_tag
= gif_attach_proto_family(ifp
, AF_INET6
);
314 int gif_detach_inet6(struct ifnet
*ifp
, u_long dl_tag
) {
315 gif_detach_proto_family(ifp
, AF_INET6
);
320 /* Function to setup the first gif interface */
324 struct dlil_protomod_reg_str gif_protoreg
;
327 /* Init the list of interfaces */
330 gif_reg_if_mods(); /* DLIL modules */
332 /* Register protocol registration functions */
334 bzero(&gif_protoreg
, sizeof(gif_protoreg
));
335 gif_protoreg
.attach_proto
= gif_attach_inet
;
336 gif_protoreg
.detach_proto
= gif_detach_inet
;
338 if ( error
= dlil_reg_proto_module(AF_INET
, APPLE_IF_FAM_GIF
, &gif_protoreg
) != 0)
339 printf("dlil_reg_proto_module failed for AF_INET error=%d\n", error
);
341 gif_protoreg
.attach_proto
= gif_attach_inet6
;
342 gif_protoreg
.detach_proto
= gif_detach_inet6
;
344 if ( error
= dlil_reg_proto_module(AF_INET6
, APPLE_IF_FAM_GIF
, &gif_protoreg
) != 0)
345 printf("dlil_reg_proto_module failed for AF_INET6 error=%d\n", error
);
348 /* Create first device */
352 /* Creates another gif device if there are none free */
356 struct gif_softc
*sc
;
359 /* Can't create more than GIF_MAXUNIT */
360 if (ngif
>= GIF_MAXUNIT
)
363 /* Check for unused gif interface */
364 TAILQ_FOREACH(sc
, &gifs
, gif_link
) {
365 /* If unused, return, no need to create a new interface */
366 if ((sc
->gif_if
.if_flags
& IFF_RUNNING
) == 0)
370 sc
= _MALLOC(sizeof(struct gif_softc
), M_DEVBUF
, M_WAITOK
);
372 log(LOG_ERR
, "gifattach: failed to allocate gif%d\n", ngif
);
376 bzero(sc
, sizeof(struct gif_softc
));
377 sc
->gif_if
.if_softc
= sc
;
378 sc
->gif_if
.if_name
= GIFNAME
;
379 sc
->gif_if
.if_unit
= ngif
;
381 sc
->encap_cookie4
= sc
->encap_cookie6
= NULL
;
383 sc
->encap_cookie4
= encap_attach_func(AF_INET
, -1,
384 gif_encapcheck
, &in_gif_protosw
, sc
);
385 if (sc
->encap_cookie4
== NULL
) {
386 printf("%s: unable to attach encap4\n", if_name(&sc
->gif_if
));
392 sc
->encap_cookie6
= encap_attach_func(AF_INET6
, -1,
393 gif_encapcheck
, (struct protosw
*)&in6_gif_protosw
, sc
);
394 if (sc
->encap_cookie6
== NULL
) {
395 if (sc
->encap_cookie4
) {
396 encap_detach(sc
->encap_cookie4
);
397 sc
->encap_cookie4
= NULL
;
399 printf("%s: unable to attach encap6\n", if_name(&sc
->gif_if
));
405 sc
->gif_if
.if_family
= APPLE_IF_FAM_GIF
;
406 sc
->gif_if
.if_mtu
= GIF_MTU
;
407 sc
->gif_if
.if_flags
= IFF_POINTOPOINT
| IFF_MULTICAST
;
409 /* turn off ingress filter */
410 sc
->gif_if
.if_flags
|= IFF_LINK2
;
412 sc
->gif_if
.if_ioctl
= gif_ioctl
;
413 sc
->gif_if
.if_output
= NULL
; /* pre_output returns error or EJUSTRETURN */
414 sc
->gif_if
.if_type
= IFT_GIF
;
415 dlil_if_attach(&sc
->gif_if
);
416 bpfattach(&sc
->gif_if
, DLT_NULL
, sizeof(u_int
));
417 TAILQ_INSERT_TAIL(&gifs
, sc
, gif_link
);
422 gif_encapcheck(m
, off
, proto
, arg
)
423 const struct mbuf
*m
;
429 struct gif_softc
*sc
;
431 sc
= (struct gif_softc
*)arg
;
435 if ((sc
->gif_if
.if_flags
& IFF_UP
) == 0)
438 /* no physical address */
439 if (!sc
->gif_psrc
|| !sc
->gif_pdst
)
455 /* LINTED const cast */
456 m_copydata((struct mbuf
*)m
, 0, sizeof(ip
), (caddr_t
)&ip
);
461 if (sc
->gif_psrc
->sa_family
!= AF_INET
||
462 sc
->gif_pdst
->sa_family
!= AF_INET
)
464 return gif_encapcheck4(m
, off
, proto
, arg
);
468 if (sc
->gif_psrc
->sa_family
!= AF_INET6
||
469 sc
->gif_pdst
->sa_family
!= AF_INET6
)
471 return gif_encapcheck6(m
, off
, proto
, arg
);
479 gif_pre_output(ifp
, m0
, dst
, rt
, frame
, address
, dl_tag
)
482 struct sockaddr
*dst
;
488 struct gif_softc
*sc
= (struct gif_softc
*)ifp
;
489 register struct mbuf
* m
= *m0
;
491 static int called
= 0; /* XXX: MUTEX */
494 * gif may cause infinite recursion calls when misconfigured.
495 * We'll prevent this by introducing upper limit.
496 * XXX: this mechanism may introduce another problem about
497 * mutual exclusion of the variable CALLED, especially if we
500 if (++called
> max_gif_nesting
) {
502 "gif_output: recursively called too many times(%d)\n",
504 m_freem(m
); /* free it here not in dlil_output*/
505 error
= EIO
; /* is there better errno? */
509 getmicrotime(&ifp
->if_lastchange
);
510 m
->m_flags
&= ~(M_BCAST
|M_MCAST
);
511 if (!(ifp
->if_flags
& IFF_UP
) ||
512 sc
->gif_psrc
== NULL
|| sc
->gif_pdst
== NULL
) {
513 m_freem(m
); /* free it here not in dlil_output */
520 * We need to prepend the address family as
521 * a four byte field. Cons up a dummy header
522 * to pacify bpf. This is safe because bpf
523 * will only read from the mbuf (i.e., it won't
524 * try to free it or keep a pointer a to it).
527 u_int32_t af
= dst
->sa_family
;
531 m0
.m_data
= (char *)&af
;
536 ifp
->if_obytes
+= m
->m_pkthdr
.len
;
538 /* inner AF-specific encapsulation */
540 /* XXX should we check if our outer source is legal? */
542 /* dispatch to output logic based on outer AF */
543 switch (sc
->gif_psrc
->sa_family
) {
546 error
= in_gif_output(ifp
, dst
->sa_family
, m
, (struct rtentry
*)rt
);
551 error
= in6_gif_output(ifp
, dst
->sa_family
, m
, (struct rtentry
*)rt
);
560 called
= 0; /* reset recursion counter */
562 /* the mbuf was freed either by in_gif_output or in here */
563 *m0
= NULL
; /* avoid getting dlil_output freeing it */
567 error
= EJUSTRETURN
; /* if no error, packet got sent already */
572 gif_input(m
, frame_header
, gifp
, dl_tag
, sync_ok
)
580 struct ifqueue
*ifq
= 0;
589 /* Assume packet is of type of protocol attached to this interface */
590 af
= ((struct gif_softc
*)(gifp
->if_softc
))->gif_proto
->protocol_family
;
592 if (m
->m_pkthdr
.rcvif
)
593 m
->m_pkthdr
.rcvif
= gifp
;
597 * We need to prepend the address family as
598 * a four byte field. Cons up a dummy header
599 * to pacify bpf. This is safe because bpf
600 * will only read from the mbuf (i.e., it won't
601 * try to free it or keep a pointer a to it).
608 m0
.m_data
= (char *)&af1
;
614 * Put the packet to the network layer input queue according to the
615 * specified address family.
616 * Note: older versions of gif_input directly called network layer
617 * input functions, e.g. ip6_input, here. We changed the policy to
618 * prevent too many recursive calls of such input functions, which
619 * might cause kernel panic. But the change may introduce another
620 * problem; if the input queue is full, packets are discarded.
621 * We believed it rarely occurs and changed the policy. If we find
622 * it occurs more times than we thought, we may change the policy
640 return (EJUSTRETURN
);
645 IF_DROP(ifq
); /* update statistics */
648 return (EJUSTRETURN
);
651 /* we need schednetisr since the address family may change */
654 gifp
->if_ibytes
+= m
->m_pkthdr
.len
;
660 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
662 gif_ioctl(ifp
, cmd
, data
)
667 struct gif_softc
*sc
= (struct gif_softc
*)ifp
;
668 struct ifreq
*ifr
= (struct ifreq
*)data
;
670 struct sockaddr
*dst
, *src
;
674 struct gif_softc
*sc2
;
687 #ifdef SIOCSIFMTU /* xxx */
695 if (mtu
< GIF_MTU_MIN
|| mtu
> GIF_MTU_MAX
) {
701 #endif /* SIOCSIFMTU */
705 case SIOCSIFPHYADDR_IN6
:
707 case SIOCSLIFPHYADDR
:
711 src
= (struct sockaddr
*)
712 &(((struct in_aliasreq
*)data
)->ifra_addr
);
713 dst
= (struct sockaddr
*)
714 &(((struct in_aliasreq
*)data
)->ifra_dstaddr
);
718 case SIOCSIFPHYADDR_IN6
:
719 src
= (struct sockaddr
*)
720 &(((struct in6_aliasreq
*)data
)->ifra_addr
);
721 dst
= (struct sockaddr
*)
722 &(((struct in6_aliasreq
*)data
)->ifra_dstaddr
);
725 case SIOCSLIFPHYADDR
:
726 src
= (struct sockaddr
*)
727 &(((struct if_laddrreq
*)data
)->addr
);
728 dst
= (struct sockaddr
*)
729 &(((struct if_laddrreq
*)data
)->dstaddr
);
732 /* sa_family must be equal */
733 if (src
->sa_family
!= dst
->sa_family
)
736 /* validate sa_len */
737 switch (src
->sa_family
) {
740 if (src
->sa_len
!= sizeof(struct sockaddr_in
))
746 if (src
->sa_len
!= sizeof(struct sockaddr_in6
))
753 switch (dst
->sa_family
) {
756 if (dst
->sa_len
!= sizeof(struct sockaddr_in
))
762 if (dst
->sa_len
!= sizeof(struct sockaddr_in6
))
770 /* check sa_family looks sane for the cmd */
773 if (src
->sa_family
== AF_INET
)
777 case SIOCSIFPHYADDR_IN6
:
778 if (src
->sa_family
== AF_INET6
)
782 case SIOCSLIFPHYADDR
:
783 /* checks done in the above */
787 TAILQ_FOREACH(ifp2
, &ifnet
, if_link
) {
788 if (strcmp(ifp2
->if_name
, GIFNAME
) != 0)
790 sc2
= ifp2
->if_softc
;
793 if (!sc2
->gif_pdst
|| !sc2
->gif_psrc
)
795 if (sc2
->gif_pdst
->sa_family
!= dst
->sa_family
||
796 sc2
->gif_pdst
->sa_len
!= dst
->sa_len
||
797 sc2
->gif_psrc
->sa_family
!= src
->sa_family
||
798 sc2
->gif_psrc
->sa_len
!= src
->sa_len
)
801 /* can't configure same pair of address onto two gifs */
802 if (bcmp(sc2
->gif_pdst
, dst
, dst
->sa_len
) == 0 &&
803 bcmp(sc2
->gif_psrc
, src
, src
->sa_len
) == 0) {
804 error
= EADDRNOTAVAIL
;
809 /* can't configure multiple multi-dest interfaces */
810 #define multidest(x) \
811 (((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY)
813 #define multidest6(x) \
814 (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr))
816 if (dst
->sa_family
== AF_INET
&&
817 multidest(dst
) && multidest(sc2
->gif_pdst
)) {
818 error
= EADDRNOTAVAIL
;
822 if (dst
->sa_family
== AF_INET6
&&
823 multidest6(dst
) && multidest6(sc2
->gif_pdst
)) {
824 error
= EADDRNOTAVAIL
;
831 FREE((caddr_t
)sc
->gif_psrc
, M_IFADDR
);
832 sa
= (struct sockaddr
*)_MALLOC(src
->sa_len
, M_IFADDR
, M_WAITOK
);
833 bcopy((caddr_t
)src
, (caddr_t
)sa
, src
->sa_len
);
837 FREE((caddr_t
)sc
->gif_pdst
, M_IFADDR
);
838 sa
= (struct sockaddr
*)_MALLOC(dst
->sa_len
, M_IFADDR
, M_WAITOK
);
839 bcopy((caddr_t
)dst
, (caddr_t
)sa
, dst
->sa_len
);
842 ifp
->if_flags
|= IFF_RUNNING
;
844 gif_attach_proto_family(ifp
, src
->sa_family
);
847 if_up(ifp
); /* mark interface UP and send up RTM_IFINFO */
849 /* Make sure at least one unused device is still available */
857 #ifdef SIOCDIFPHYADDR
860 FREE((caddr_t
)sc
->gif_psrc
, M_IFADDR
);
864 FREE((caddr_t
)sc
->gif_pdst
, M_IFADDR
);
867 /* change the IFF_{UP, RUNNING} flag as well? */
871 case SIOCGIFPSRCADDR
:
873 case SIOCGIFPSRCADDR_IN6
:
875 if (sc
->gif_psrc
== NULL
) {
876 error
= EADDRNOTAVAIL
;
882 case SIOCGIFPSRCADDR
:
883 dst
= &ifr
->ifr_addr
;
884 size
= sizeof(ifr
->ifr_addr
);
888 case SIOCGIFPSRCADDR_IN6
:
889 dst
= (struct sockaddr
*)
890 &(((struct in6_ifreq
*)data
)->ifr_addr
);
891 size
= sizeof(((struct in6_ifreq
*)data
)->ifr_addr
);
895 error
= EADDRNOTAVAIL
;
898 if (src
->sa_len
> size
)
900 bcopy((caddr_t
)src
, (caddr_t
)dst
, src
->sa_len
);
903 case SIOCGIFPDSTADDR
:
905 case SIOCGIFPDSTADDR_IN6
:
907 if (sc
->gif_pdst
== NULL
) {
908 error
= EADDRNOTAVAIL
;
914 case SIOCGIFPDSTADDR
:
915 dst
= &ifr
->ifr_addr
;
916 size
= sizeof(ifr
->ifr_addr
);
920 case SIOCGIFPDSTADDR_IN6
:
921 dst
= (struct sockaddr
*)
922 &(((struct in6_ifreq
*)data
)->ifr_addr
);
923 size
= sizeof(((struct in6_ifreq
*)data
)->ifr_addr
);
927 error
= EADDRNOTAVAIL
;
930 if (src
->sa_len
> size
)
932 bcopy((caddr_t
)src
, (caddr_t
)dst
, src
->sa_len
);
935 case SIOCGLIFPHYADDR
:
936 if (sc
->gif_psrc
== NULL
|| sc
->gif_pdst
== NULL
) {
937 error
= EADDRNOTAVAIL
;
943 dst
= (struct sockaddr
*)
944 &(((struct if_laddrreq
*)data
)->addr
);
945 size
= sizeof(((struct if_laddrreq
*)data
)->addr
);
946 if (src
->sa_len
> size
)
948 bcopy((caddr_t
)src
, (caddr_t
)dst
, src
->sa_len
);
952 dst
= (struct sockaddr
*)
953 &(((struct if_laddrreq
*)data
)->dstaddr
);
954 size
= sizeof(((struct if_laddrreq
*)data
)->dstaddr
);
955 if (src
->sa_len
> size
)
957 bcopy((caddr_t
)src
, (caddr_t
)dst
, src
->sa_len
);
961 /* if_ioctl() takes care of it */
973 gif_delete_tunnel(sc
)
974 struct gif_softc
*sc
;
976 /* XXX: NetBSD protects this function with splsoftnet() */
979 FREE((caddr_t
)sc
->gif_psrc
, M_IFADDR
);
983 FREE((caddr_t
)sc
->gif_pdst
, M_IFADDR
);
986 /* change the IFF_UP flag as well? */