]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/in_gif.c
f57a3ea283a323f0e18d93d746fd8431be3a909f
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* $KAME: in_gif.c,v 1.27 2000/03/30 01:29:05 jinmei Exp $ */
25 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
26 * All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. Neither the name of the project nor the names of its contributors
37 * may be used to endorse or promote products derived from this software
38 * without specific prior written permission.
40 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 #include "opt_mrouting.h"
58 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/socket.h>
66 #include <sys/sockio.h>
67 #include <sys/sysctl.h>
69 #include <sys/errno.h>
71 #include <sys/kernel.h>
72 #include <sys/sysctl.h>
74 #if !defined(__FreeBSD__) || __FreeBSD__ < 3
75 #include <sys/ioctl.h>
77 #include <sys/protosw.h>
79 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
80 #include <sys/malloc.h>
84 #include <net/route.h>
85 #include <net/if_gif.h>
87 #include <netinet/in.h>
88 #include <netinet/in_systm.h>
89 #include <netinet/ip.h>
90 #include <netinet/ip_var.h>
91 #include <netinet/in_gif.h>
92 #include <netinet/in_var.h>
93 #include <netinet/ip_encap.h>
94 #include <netinet/ip_ecn.h>
97 #include <netinet/ip6.h>
101 #include <netinet/ip_mroute.h>
102 #endif /* MROUTING */
104 #include <net/if_gif.h>
108 #include <net/net_osdep.h>
111 int ip_gif_ttl
= GIF_TTL
;
116 extern struct protosw in_gif_protosw
;
118 SYSCTL_INT(_net_inet_ip
, IPCTL_GIF_TTL
, gifttl
,
119 CTLFLAG_RW
, &ip_gif_ttl
, 0, "");
122 in_gif_output(ifp
, family
, m
, rt
)
128 register struct gif_softc
*sc
= (struct gif_softc
*)ifp
;
129 struct sockaddr_in
*dst
= (struct sockaddr_in
*)&sc
->gif_ro
.ro_dst
;
130 struct sockaddr_in
*sin_src
= (struct sockaddr_in
*)sc
->gif_psrc
;
131 struct sockaddr_in
*sin_dst
= (struct sockaddr_in
*)sc
->gif_pdst
;
132 struct ip iphdr
; /* capsule IP header, host byte ordered */
136 if (sin_src
== NULL
|| sin_dst
== NULL
||
137 sin_src
->sin_family
!= AF_INET
||
138 sin_dst
->sin_family
!= AF_INET
) {
139 printf("in_gif_output: unknown family src=%x dst=%x\n", sin_src
->sin_family
, sin_dst
->sin_family
);
150 proto
= IPPROTO_IPV4
;
151 if (m
->m_len
< sizeof(*ip
)) {
152 m
= m_pullup(m
, sizeof(*ip
));
156 ip
= mtod(m
, struct ip
*);
165 proto
= IPPROTO_IPV6
;
166 if (m
->m_len
< sizeof(*ip6
)) {
167 m
= m_pullup(m
, sizeof(*ip6
));
171 ip6
= mtod(m
, struct ip6_hdr
*);
172 tos
= (ntohl(ip6
->ip6_flow
) >> 20) & 0xff;
178 printf("in_gif_output: warning: unknown family %d passed\n",
185 bzero(&iphdr
, sizeof(iphdr
));
186 iphdr
.ip_src
= sin_src
->sin_addr
;
187 if (ifp
->if_flags
& IFF_LINK0
) {
188 /* multi-destination mode */
189 if (sin_dst
->sin_addr
.s_addr
!= INADDR_ANY
)
190 iphdr
.ip_dst
= sin_dst
->sin_addr
;
192 if (family
!= AF_INET
) {
194 return EINVAL
; /*XXX*/
196 iphdr
.ip_dst
= ((struct sockaddr_in
*)
197 (rt
->rt_gateway
))->sin_addr
;
203 /* bidirectional configured tunnel mode */
204 if (sin_dst
->sin_addr
.s_addr
!= INADDR_ANY
)
205 iphdr
.ip_dst
= sin_dst
->sin_addr
;
212 /* version will be set in ip_output() */
213 iphdr
.ip_ttl
= ip_gif_ttl
;
214 iphdr
.ip_len
= m
->m_pkthdr
.len
+ sizeof(struct ip
);
215 if (ifp
->if_flags
& IFF_LINK1
)
216 ip_ecn_ingress(ECN_ALLOWED
, &iphdr
.ip_tos
, &tos
);
218 /* prepend new IP header */
219 M_PREPEND(m
, sizeof(struct ip
), M_DONTWAIT
);
220 if (m
&& m
->m_len
< sizeof(struct ip
))
221 m
= m_pullup(m
, sizeof(struct ip
));
223 printf("ENOBUFS in in_gif_output %d\n", __LINE__
);
227 *(mtod(m
, struct ip
*)) = iphdr
;
229 if (dst
->sin_family
!= sin_dst
->sin_family
||
230 dst
->sin_addr
.s_addr
!= sin_dst
->sin_addr
.s_addr
) {
231 /* cache route doesn't match */
232 dst
->sin_family
= sin_dst
->sin_family
;
233 dst
->sin_len
= sizeof(struct sockaddr_in
);
234 dst
->sin_addr
= sin_dst
->sin_addr
;
235 if (sc
->gif_ro
.ro_rt
) {
236 RTFREE(sc
->gif_ro
.ro_rt
);
237 sc
->gif_ro
.ro_rt
= NULL
;
240 sc
->gif_if
.if_mtu
= GIF_MTU
;
244 if (sc
->gif_ro
.ro_rt
== NULL
) {
245 rtalloc(&sc
->gif_ro
);
246 if (sc
->gif_ro
.ro_rt
== NULL
) {
251 ifp
->if_mtu
= sc
->gif_ro
.ro_rt
->rt_ifp
->if_mtu
257 error
= ip_output(m
, NULL
, &sc
->gif_ro
, 0, NULL
);
259 error
= ip_output(m
, NULL
, &sc
->gif_ro
, 0, NULL
, NULL
);
269 struct gif_softc
*sc
;
270 struct ifnet
*gifp
= NULL
;
280 ip
= mtod(m
, struct ip
*);
284 /* this code will be soon improved. */
285 #define satosin(sa) ((struct sockaddr_in *)(sa))
286 for (i
= 0, sc
= gif
; i
< ngif
; i
++, sc
++) {
287 if (sc
->gif_psrc
== NULL
288 || sc
->gif_pdst
== NULL
289 || sc
->gif_psrc
->sa_family
!= AF_INET
290 || sc
->gif_pdst
->sa_family
!= AF_INET
) {
294 if ((sc
->gif_if
.if_flags
& IFF_UP
) == 0)
297 if ((sc
->gif_if
.if_flags
& IFF_LINK0
)
298 && satosin(sc
->gif_psrc
)->sin_addr
.s_addr
== ip
->ip_dst
.s_addr
299 && satosin(sc
->gif_pdst
)->sin_addr
.s_addr
== INADDR_ANY
) {
304 if (satosin(sc
->gif_psrc
)->sin_addr
.s_addr
== ip
->ip_dst
.s_addr
305 && satosin(sc
->gif_pdst
)->sin_addr
.s_addr
== ip
->ip_src
.s_addr
)
312 gifp
= (struct ifnet
*)encap_getarg(m
);
316 /* for backward compatibility */
317 if (proto
== IPPROTO_IPV4
) {
319 #if defined(MROUTING) || defined(IPSEC)
320 ip4_input(m
, off
, proto
);
335 if ((gifp
->if_flags
& IFF_UP
) == 0) {
350 if (m
->m_len
< sizeof(*ip
)) {
351 m
= m_pullup(m
, sizeof(*ip
));
355 ip
= mtod(m
, struct ip
*);
356 if (gifp
->if_flags
& IFF_LINK1
)
357 ip_ecn_egress(ECN_ALLOWED
, &otos
, &ip
->ip_tos
);
367 if (m
->m_len
< sizeof(*ip6
)) {
368 m
= m_pullup(m
, sizeof(*ip6
));
372 ip6
= mtod(m
, struct ip6_hdr
*);
373 itos
= (ntohl(ip6
->ip6_flow
) >> 20) & 0xff;
374 if (gifp
->if_flags
& IFF_LINK1
)
375 ip_ecn_egress(ECN_ALLOWED
, &otos
, &itos
);
376 ip6
->ip6_flow
&= ~htonl(0xff << 20);
377 ip6
->ip6_flow
|= htonl((u_int32_t
)itos
<< 20);
386 gif_input(m
, af
, gifp
);
391 in_gif_ioctl(ifp
, cmd
, data
)
393 #if defined(__FreeBSD__) && __FreeBSD__ < 3
400 struct gif_softc
*sc
= (struct gif_softc
*)ifp
;
401 struct ifreq
*ifr
= (struct ifreq
*)data
;
403 struct sockaddr
*sa
, *dst
, *src
;
404 const struct encaptab
*p
;
405 struct sockaddr_in smask4
, dmask4
;
410 * whenever we change our idea about multi-destination mode
411 * we need to update encap attachment.
413 if (((ifp
->if_flags
^ sc
->gif_oflags
) & IFF_LINK0
) == 0)
415 if (sc
->gif_psrc
== NULL
|| sc
->gif_pdst
== NULL
||
416 sc
->gif_psrc
->sa_family
!= sc
->gif_pdst
->sa_family
)
418 bzero(&smask4
, sizeof(smask4
));
419 smask4
.sin_addr
.s_addr
= ~0;
421 if ((ifp
->if_flags
& IFF_LINK0
) != 0 &&
422 ((struct sockaddr_in
*)dst
)->sin_addr
.s_addr
==
424 bzero(&dmask4
, sizeof(dmask4
));
426 p
= encap_attach(sc
->gif_psrc
->sa_family
, -1, sc
->gif_psrc
,
427 (struct sockaddr
*)&smask4
, sc
->gif_pdst
,
428 (struct sockaddr
*)&dmask4
,
429 (struct protosw
*)&in_gif_protosw
, &sc
->gif_if
);
434 if (sc
->encap_cookie
!= NULL
)
435 (void)encap_detach(sc
->encap_cookie
);
436 sc
->encap_cookie
= p
;
437 sc
->gif_oflags
= ifp
->if_flags
;
442 switch (ifr
->ifr_addr
.sa_family
) {
444 src
= (struct sockaddr
*)
445 &(((struct in_aliasreq
*)data
)->ifra_addr
);
446 dst
= (struct sockaddr
*)
447 &(((struct in_aliasreq
*)data
)->ifra_dstaddr
);
449 bzero(&smask4
, sizeof(smask4
));
450 smask4
.sin_addr
.s_addr
= ~0;
452 if ((ifp
->if_flags
& IFF_LINK0
) != 0 &&
453 ((struct sockaddr_in
*)dst
)->sin_addr
.s_addr
==
455 bzero(&dmask4
, sizeof(dmask4
));
457 size
= sizeof(struct sockaddr_in
);
460 error
= EAFNOSUPPORT
;
464 if (sc
->encap_cookie
)
465 (void)encap_detach(sc
->encap_cookie
);
466 if (sc
->gif_psrc
!= NULL
) {
467 _FREE((caddr_t
)sc
->gif_psrc
, M_IFADDR
);
470 if (sc
->gif_pdst
!= NULL
) {
471 _FREE((caddr_t
)sc
->gif_pdst
, M_IFADDR
);
475 p
= encap_attach(ifr
->ifr_addr
.sa_family
, -1, src
,
476 (struct sockaddr
*)&smask4
, dst
,
477 (struct sockaddr
*)&dmask4
,
478 (struct protosw
*)&in_gif_protosw
, &sc
->gif_if
);
483 sc
->encap_cookie
= p
;
484 sc
->gif_oflags
= ifp
->if_flags
;
486 sa
= (struct sockaddr
*)_MALLOC(size
, M_IFADDR
, M_WAITOK
);
487 bcopy((caddr_t
)src
, (caddr_t
)sa
, size
);
490 sa
= (struct sockaddr
*)_MALLOC(size
, M_IFADDR
, M_WAITOK
);
491 bcopy((caddr_t
)dst
, (caddr_t
)sa
, size
);
494 ifp
->if_flags
|= IFF_UP
;
495 if_up(ifp
); /* send up RTM_IFINFO */