1 /* $NetBSD: if_gif.c,v 1.75 2008/06/15 16:37:21 christos Exp $ */
2 /* $KAME: if_gif.c,v 1.76 2001/08/20 02:01:02 kjc Exp $ */
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.75 2008/06/15 16:37:21 christos Exp $");
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/errno.h>
46 #include <sys/ioctl.h>
48 #include <sys/syslog.h>
50 #include <sys/protosw.h>
51 #include <sys/kauth.h>
56 #include <net/if_types.h>
57 #include <net/netisr.h>
58 #include <net/route.h>
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/ip.h>
65 #include <netinet/in_var.h>
67 #include <netinet/in_gif.h>
71 #include <netinet/in.h>
73 #include <netinet6/in6_var.h>
74 #include <netinet/ip6.h>
75 #include <netinet6/ip6_var.h>
76 #include <netinet6/in6_gif.h>
77 #include <netinet6/ip6protosw.h>
81 #include <netiso/iso.h>
82 #include <netiso/iso_var.h>
85 #include <netinet/ip_encap.h>
86 #include <net/if_gif.h>
90 #include <net/net_osdep.h>
93 static void gifintr(void *);
95 static struct mbuf
*gif_eon_encap(struct mbuf
*);
96 static struct mbuf
*gif_eon_decap(struct ifnet
*, struct mbuf
*);
100 * gif global variable definitions
102 LIST_HEAD(, gif_softc
) gif_softc_list
; /* XXX should be static */
104 static int gif_clone_create(struct if_clone
*, int);
105 static int gif_clone_destroy(struct ifnet
*);
107 static struct if_clone gif_cloner
=
108 IF_CLONE_INITIALIZER("gif", gif_clone_create
, gif_clone_destroy
);
112 * This macro controls the upper limitation on nesting of gif tunnels.
113 * Since, setting a large value to this macro with a careless configuration
114 * may introduce system crash, we don't allow any nestings by default.
115 * If you need to configure nested gif tunnels, you can define this macro
116 * in your kernel configuration file. However, if you do so, please be
117 * careful to configure the tunnels so that it won't make a loop.
119 #define MAX_GIF_NEST 1
121 static int max_gif_nesting
= MAX_GIF_NEST
;
128 LIST_INIT(&gif_softc_list
);
129 if_clone_attach(&gif_cloner
);
133 gif_clone_create(struct if_clone
*ifc
, int unit
)
135 struct gif_softc
*sc
;
137 sc
= malloc(sizeof(struct gif_softc
), M_DEVBUF
, M_WAITOK
|M_ZERO
);
139 if_initname(&sc
->gif_if
, ifc
->ifc_name
, unit
);
143 LIST_INSERT_HEAD(&gif_softc_list
, sc
, gif_list
);
148 gifattach0(struct gif_softc
*sc
)
151 sc
->encap_cookie4
= sc
->encap_cookie6
= NULL
;
153 sc
->gif_if
.if_addrlen
= 0;
154 sc
->gif_if
.if_mtu
= GIF_MTU
;
155 sc
->gif_if
.if_flags
= IFF_POINTOPOINT
| IFF_MULTICAST
;
156 sc
->gif_if
.if_ioctl
= gif_ioctl
;
157 sc
->gif_if
.if_output
= gif_output
;
158 sc
->gif_if
.if_type
= IFT_GIF
;
159 sc
->gif_if
.if_dlt
= DLT_NULL
;
160 sc
->gif_if
.if_softc
= sc
;
161 IFQ_SET_READY(&sc
->gif_if
.if_snd
);
162 if_attach(&sc
->gif_if
);
163 if_alloc_sadl(&sc
->gif_if
);
165 bpfattach(&sc
->gif_if
, DLT_NULL
, sizeof(u_int
));
170 gif_clone_destroy(struct ifnet
*ifp
)
172 struct gif_softc
*sc
= (void *) ifp
;
174 gif_delete_tunnel(&sc
->gif_if
);
175 LIST_REMOVE(sc
, gif_list
);
177 encap_detach(sc
->encap_cookie6
);
180 encap_detach(sc
->encap_cookie4
);
187 rtcache_free(&sc
->gif_ro
);
194 #ifdef GIF_ENCAPCHECK
196 gif_encapcheck(struct mbuf
*m
, int off
, int proto
, void *arg
)
199 struct gif_softc
*sc
;
205 if ((sc
->gif_if
.if_flags
& IFF_UP
) == 0)
208 /* no physical address */
209 if (!sc
->gif_psrc
|| !sc
->gif_pdst
)
229 /* Bail on short packets */
230 KASSERT(m
->m_flags
& M_PKTHDR
);
231 if (m
->m_pkthdr
.len
< sizeof(ip
))
234 m_copydata(m
, 0, sizeof(ip
), &ip
);
239 if (sc
->gif_psrc
->sa_family
!= AF_INET
||
240 sc
->gif_pdst
->sa_family
!= AF_INET
)
242 return gif_encapcheck4(m
, off
, proto
, arg
);
246 if (m
->m_pkthdr
.len
< sizeof(struct ip6_hdr
))
248 if (sc
->gif_psrc
->sa_family
!= AF_INET6
||
249 sc
->gif_pdst
->sa_family
!= AF_INET6
)
251 return gif_encapcheck6(m
, off
, proto
, arg
);
260 gif_output(struct ifnet
*ifp
, struct mbuf
*m
, const struct sockaddr
*dst
,
263 struct gif_softc
*sc
= ifp
->if_softc
;
265 static int called
= 0; /* XXX: MUTEX */
266 ALTQ_DECL(struct altq_pktattr pktattr
;)
269 IFQ_CLASSIFY(&ifp
->if_snd
, m
, dst
->sa_family
, &pktattr
);
272 * gif may cause infinite recursion calls when misconfigured.
273 * We'll prevent this by introducing upper limit.
274 * XXX: this mechanism may introduce another problem about
275 * mutual exclusion of the variable CALLED, especially if we
278 if (++called
> max_gif_nesting
) {
280 "gif_output: recursively called too many times(%d)\n",
283 error
= EIO
; /* is there better errno? */
287 m
->m_flags
&= ~(M_BCAST
|M_MCAST
);
288 if (!(ifp
->if_flags
& IFF_UP
) ||
289 sc
->gif_psrc
== NULL
|| sc
->gif_pdst
== NULL
) {
295 /* inner AF-specific encapsulation */
296 switch (dst
->sa_family
) {
299 m
= gif_eon_encap(m
);
310 /* XXX should we check if our outer source is legal? */
312 /* use DLT_NULL encapsulation here to pass inner af type */
313 M_PREPEND(m
, sizeof(int), M_DONTWAIT
);
318 *mtod(m
, int *) = dst
->sa_family
;
321 IFQ_ENQUEUE(&ifp
->if_snd
, m
, &pktattr
, error
);
328 softint_schedule(sc
->gif_si
);
332 called
= 0; /* reset recursion counter */
341 struct gif_softc
*sc
;
352 /* output processing */
355 IFQ_DEQUEUE(&sc
->gif_if
.if_snd
, m
);
360 /* grab and chop off inner af type */
361 if (sizeof(int) > m
->m_len
) {
362 m
= m_pullup(m
, sizeof(int));
368 family
= *mtod(m
, int *);
371 bpf_mtap(ifp
->if_bpf
, m
);
373 m_adj(m
, sizeof(int));
375 len
= m
->m_pkthdr
.len
;
377 /* dispatch to output logic based on outer AF */
378 switch (sc
->gif_psrc
->sa_family
) {
381 error
= in_gif_output(ifp
, family
, m
);
386 error
= in6_gif_output(ifp
, family
, m
);
399 ifp
->if_obytes
+= len
;
405 gif_input(struct mbuf
*m
, int af
, struct ifnet
*ifp
)
408 struct ifqueue
*ifq
= NULL
;
416 m
->m_pkthdr
.rcvif
= ifp
;
420 bpf_mtap_af(ifp
->if_bpf
, af
, m
);
421 #endif /*NBPFILTER > 0*/
424 * Put the packet to the network layer input queue according to the
425 * specified address family.
426 * Note: older versions of gif_input directly called network layer
427 * input functions, e.g. ip6_input, here. We changed the policy to
428 * prevent too many recursive calls of such input functions, which
429 * might cause kernel panic. But the change may introduce another
430 * problem; if the input queue is full, packets are discarded.
431 * The kernel stack overflow really happened, and we believed
432 * queue-full rarely occurs, so we changed the policy.
449 m
= gif_eon_decap(ifp
, m
);
463 IF_DROP(ifq
); /* update statistics */
469 ifp
->if_ibytes
+= m
->m_pkthdr
.len
;
471 /* we need schednetisr since the address family may change */
476 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
478 gif_ioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
480 struct lwp
*l
= curlwp
; /* XXX */
481 struct gif_softc
*sc
= ifp
->if_softc
;
482 struct ifreq
*ifr
= (struct ifreq
*)data
;
484 struct sockaddr
*dst
, *src
;
488 case SIOCSLIFPHYADDR
:
489 #ifdef SIOCDIFPHYADDR
492 if ((error
= kauth_authorize_network(l
->l_cred
,
493 KAUTH_NETWORK_INTERFACE
,
494 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV
, ifp
, (void *)cmd
,
504 ifp
->if_flags
|= IFF_UP
;
512 switch (ifr
->ifr_addr
.sa_family
) {
514 case AF_INET
: /* IP supports Multicast */
518 case AF_INET6
: /* IP6 supports Multicast */
521 default: /* Other protocols doesn't support Multicast */
522 error
= EAFNOSUPPORT
;
531 if (ifr
->ifr_mtu
< GIF_MTU_MIN
|| ifr
->ifr_mtu
> GIF_MTU_MAX
)
533 else if ((error
= ifioctl_common(ifp
, cmd
, data
)) == ENETRESET
)
541 case SIOCSIFPHYADDR_IN6
:
543 case SIOCSLIFPHYADDR
:
547 src
= (struct sockaddr
*)
548 &(((struct in_aliasreq
*)data
)->ifra_addr
);
549 dst
= (struct sockaddr
*)
550 &(((struct in_aliasreq
*)data
)->ifra_dstaddr
);
554 case SIOCSIFPHYADDR_IN6
:
555 src
= (struct sockaddr
*)
556 &(((struct in6_aliasreq
*)data
)->ifra_addr
);
557 dst
= (struct sockaddr
*)
558 &(((struct in6_aliasreq
*)data
)->ifra_dstaddr
);
561 case SIOCSLIFPHYADDR
:
562 src
= (struct sockaddr
*)
563 &(((struct if_laddrreq
*)data
)->addr
);
564 dst
= (struct sockaddr
*)
565 &(((struct if_laddrreq
*)data
)->dstaddr
);
571 /* sa_family must be equal */
572 if (src
->sa_family
!= dst
->sa_family
)
575 /* validate sa_len */
576 switch (src
->sa_family
) {
579 if (src
->sa_len
!= sizeof(struct sockaddr_in
))
585 if (src
->sa_len
!= sizeof(struct sockaddr_in6
))
592 switch (dst
->sa_family
) {
595 if (dst
->sa_len
!= sizeof(struct sockaddr_in
))
601 if (dst
->sa_len
!= sizeof(struct sockaddr_in6
))
609 /* check sa_family looks sane for the cmd */
612 if (src
->sa_family
== AF_INET
)
616 case SIOCSIFPHYADDR_IN6
:
617 if (src
->sa_family
== AF_INET6
)
621 case SIOCSLIFPHYADDR
:
622 /* checks done in the above */
626 error
= gif_set_tunnel(&sc
->gif_if
, src
, dst
);
629 #ifdef SIOCDIFPHYADDR
631 gif_delete_tunnel(&sc
->gif_if
);
635 case SIOCGIFPSRCADDR
:
637 case SIOCGIFPSRCADDR_IN6
:
639 if (sc
->gif_psrc
== NULL
) {
640 error
= EADDRNOTAVAIL
;
646 case SIOCGIFPSRCADDR
:
647 dst
= &ifr
->ifr_addr
;
648 size
= sizeof(ifr
->ifr_addr
);
652 case SIOCGIFPSRCADDR_IN6
:
653 dst
= (struct sockaddr
*)
654 &(((struct in6_ifreq
*)data
)->ifr_addr
);
655 size
= sizeof(((struct in6_ifreq
*)data
)->ifr_addr
);
659 error
= EADDRNOTAVAIL
;
662 if (src
->sa_len
> size
)
664 memcpy(dst
, src
, src
->sa_len
);
667 case SIOCGIFPDSTADDR
:
669 case SIOCGIFPDSTADDR_IN6
:
671 if (sc
->gif_pdst
== NULL
) {
672 error
= EADDRNOTAVAIL
;
678 case SIOCGIFPDSTADDR
:
679 dst
= &ifr
->ifr_addr
;
680 size
= sizeof(ifr
->ifr_addr
);
684 case SIOCGIFPDSTADDR_IN6
:
685 dst
= (struct sockaddr
*)
686 &(((struct in6_ifreq
*)data
)->ifr_addr
);
687 size
= sizeof(((struct in6_ifreq
*)data
)->ifr_addr
);
691 error
= EADDRNOTAVAIL
;
694 if (src
->sa_len
> size
)
696 memcpy(dst
, src
, src
->sa_len
);
699 case SIOCGLIFPHYADDR
:
700 if (sc
->gif_psrc
== NULL
|| sc
->gif_pdst
== NULL
) {
701 error
= EADDRNOTAVAIL
;
707 dst
= (struct sockaddr
*)
708 &(((struct if_laddrreq
*)data
)->addr
);
709 size
= sizeof(((struct if_laddrreq
*)data
)->addr
);
710 if (src
->sa_len
> size
)
712 memcpy(dst
, src
, src
->sa_len
);
716 dst
= (struct sockaddr
*)
717 &(((struct if_laddrreq
*)data
)->dstaddr
);
718 size
= sizeof(((struct if_laddrreq
*)data
)->dstaddr
);
719 if (src
->sa_len
> size
)
721 memcpy(dst
, src
, src
->sa_len
);
725 return ifioctl_common(ifp
, cmd
, data
);
732 gif_set_tunnel(struct ifnet
*ifp
, struct sockaddr
*src
, struct sockaddr
*dst
)
734 struct gif_softc
*sc
= ifp
->if_softc
;
735 struct gif_softc
*sc2
;
736 struct sockaddr
*osrc
, *odst
;
742 LIST_FOREACH(sc2
, &gif_softc_list
, gif_list
) {
745 if (!sc2
->gif_pdst
|| !sc2
->gif_psrc
)
747 /* can't configure same pair of address onto two gifs */
748 if (sockaddr_cmp(sc2
->gif_pdst
, dst
) == 0 &&
749 sockaddr_cmp(sc2
->gif_psrc
, src
) == 0) {
750 error
= EADDRNOTAVAIL
;
754 /* XXX both end must be valid? (I mean, not 0.0.0.0) */
758 softint_disestablish(sc
->gif_si
);
762 /* XXX we can detach from both, but be polite just in case */
764 switch (sc
->gif_psrc
->sa_family
) {
767 (void)in_gif_detach(sc
);
772 (void)in6_gif_detach(sc
);
777 sc
->gif_si
= softint_establish(SOFTINT_NET
, gifintr
, sc
);
778 if (sc
->gif_si
== NULL
) {
784 sc
->gif_psrc
= sockaddr_dup(src
, M_WAITOK
);
787 sc
->gif_pdst
= sockaddr_dup(dst
, M_WAITOK
);
789 switch (sc
->gif_psrc
->sa_family
) {
792 error
= in_gif_attach(sc
);
797 error
= in6_gif_attach(sc
);
806 sockaddr_free(sc
->gif_psrc
);
807 sockaddr_free(sc
->gif_pdst
);
818 if (sc
->gif_psrc
&& sc
->gif_pdst
)
819 ifp
->if_flags
|= IFF_RUNNING
;
821 ifp
->if_flags
&= ~IFF_RUNNING
;
828 softint_disestablish(sc
->gif_si
);
831 if (sc
->gif_psrc
&& sc
->gif_pdst
)
832 ifp
->if_flags
|= IFF_RUNNING
;
834 ifp
->if_flags
&= ~IFF_RUNNING
;
841 gif_delete_tunnel(struct ifnet
*ifp
)
843 struct gif_softc
*sc
= ifp
->if_softc
;
849 softint_disestablish(sc
->gif_si
);
853 sockaddr_free(sc
->gif_psrc
);
857 sockaddr_free(sc
->gif_pdst
);
860 /* it is safe to detach from both */
862 (void)in_gif_detach(sc
);
865 (void)in6_gif_detach(sc
);
868 if (sc
->gif_psrc
&& sc
->gif_pdst
)
869 ifp
->if_flags
|= IFF_RUNNING
;
871 ifp
->if_flags
&= ~IFF_RUNNING
;
883 * prepend EON header to ISO PDU
886 gif_eon_encap(struct mbuf
*m
)
890 M_PREPEND(m
, sizeof(*ehdr
), M_DONTWAIT
);
891 if (m
&& m
->m_len
< sizeof(*ehdr
))
892 m
= m_pullup(m
, sizeof(*ehdr
));
895 ehdr
= mtod(m
, struct eonhdr
*);
897 ehdr
->class = 0; /* always unicast */
899 /* calculate the checksum of the eonhdr */
902 memset(&mhead
, 0, sizeof(mhead
));
904 mhead
.m_data
= (void *)ehdr
;
905 mhead
.m_len
= sizeof(*ehdr
);
907 iso_gen_csum(&mhead
, offsetof(struct eonhdr
, cksum
),
911 /* since the data is always constant we'll just plug the value in */
912 ehdr
->cksum
= htons(0xfc02);
918 * remove EON header and check checksum
921 gif_eon_decap(struct ifnet
*ifp
, struct mbuf
*m
)
925 if (m
->m_len
< sizeof(*ehdr
) &&
926 (m
= m_pullup(m
, sizeof(*ehdr
))) == NULL
) {
930 if (iso_check_csum(m
, sizeof(struct eonhdr
))) {
934 m_adj(m
, sizeof(*ehdr
));