Annotation of sys/netinet6/in6_gif.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: in6_gif.c,v 1.25 2007/06/01 00:52:38 henning Exp $ */
2: /* $KAME: in6_gif.c,v 1.43 2001/01/22 07:27:17 itojun Exp $ */
3:
4: /*
5: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
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.
19: *
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
30: * SUCH DAMAGE.
31: */
32:
33: #include <sys/param.h>
34: #include <sys/systm.h>
35: #include <sys/socket.h>
36: #include <sys/sockio.h>
37: #include <sys/mbuf.h>
38: #include <sys/errno.h>
39: #include <sys/ioctl.h>
40: #include <sys/protosw.h>
41:
42: #include <net/if.h>
43: #include <net/route.h>
44:
45: #include <netinet/in.h>
46: #include <netinet/in_systm.h>
47: #include <netinet/ip_ipsp.h>
48:
49: #ifdef INET
50: #include <netinet/ip.h>
51: #endif
52:
53: #include <netinet/ip6.h>
54: #include <netinet6/ip6_var.h>
55: #include <netinet6/in6_gif.h>
56:
57: #ifdef INET6
58: #include <netinet/ip6.h>
59: #endif
60:
61: #include <netinet/ip_ecn.h>
62:
63: #include <net/if_gif.h>
64:
65: #include "bridge.h"
66:
67: #ifndef offsetof
68: #define offsetof(s, e) ((int)&((s *)0)->e)
69: #endif
70:
71: int
72: in6_gif_output(ifp, family, m)
73: struct ifnet *ifp;
74: int family; /* family of the packet to be encapsulate. */
75: struct mbuf *m;
76: {
77: struct gif_softc *sc = (struct gif_softc*)ifp;
78: struct sockaddr_in6 *dst = (struct sockaddr_in6 *)&sc->gif_ro6.ro_dst;
79: struct sockaddr_in6 *sin6_src = (struct sockaddr_in6 *)sc->gif_psrc;
80: struct sockaddr_in6 *sin6_dst = (struct sockaddr_in6 *)sc->gif_pdst;
81: struct tdb tdb;
82: struct xformsw xfs;
83: int error;
84: struct mbuf *mp;
85:
86: if (sin6_src == NULL || sin6_dst == NULL ||
87: sin6_src->sin6_family != AF_INET6 ||
88: sin6_dst->sin6_family != AF_INET6) {
89: m_freem(m);
90: return EAFNOSUPPORT;
91: }
92:
93: /* setup dummy tdb. it highly depends on ipip_output() code. */
94: bzero(&tdb, sizeof(tdb));
95: bzero(&xfs, sizeof(xfs));
96: tdb.tdb_src.sin6.sin6_family = AF_INET6;
97: tdb.tdb_src.sin6.sin6_len = sizeof(struct sockaddr_in6);
98: tdb.tdb_src.sin6.sin6_addr = sin6_src->sin6_addr;
99: tdb.tdb_dst.sin6.sin6_family = AF_INET6;
100: tdb.tdb_dst.sin6.sin6_len = sizeof(struct sockaddr_in6);
101: tdb.tdb_dst.sin6.sin6_addr = sin6_dst->sin6_addr;
102: tdb.tdb_xform = &xfs;
103: xfs.xf_type = -1; /* not XF_IP4 */
104:
105: switch (family) {
106: #ifdef INET
107: case AF_INET:
108: break;
109: #endif
110: #ifdef INET6
111: case AF_INET6:
112: break;
113: #endif
114: #if NBRIDGE > 0
115: case AF_LINK:
116: break;
117: #endif /* NBRIDGE */
118: default:
119: #ifdef DEBUG
120: printf("in6_gif_output: warning: unknown family %d passed\n",
121: family);
122: #endif
123: m_freem(m);
124: return EAFNOSUPPORT;
125: }
126:
127: /* encapsulate into IPv6 packet */
128: mp = NULL;
129: #if NBRIDGE > 0
130: if (family == AF_LINK)
131: error = etherip_output(m, &tdb, &mp, 0, 0);
132: else
133: #endif /* NBRIDGE */
134: error = ipip_output(m, &tdb, &mp, 0, 0);
135: if (error)
136: return error;
137: else if (mp == NULL)
138: return EFAULT;
139:
140: m = mp;
141:
142: /* See if out cached route remains the same */
143: if (dst->sin6_family != sin6_dst->sin6_family ||
144: !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &sin6_dst->sin6_addr)) {
145: /* cache route doesn't match */
146: bzero(dst, sizeof(*dst));
147: dst->sin6_family = sin6_dst->sin6_family;
148: dst->sin6_len = sizeof(struct sockaddr_in6);
149: dst->sin6_addr = sin6_dst->sin6_addr;
150: if (sc->gif_ro6.ro_rt) {
151: RTFREE(sc->gif_ro6.ro_rt);
152: sc->gif_ro6.ro_rt = NULL;
153: }
154: }
155:
156: if (sc->gif_ro6.ro_rt == NULL) {
157: rtalloc((struct route *)&sc->gif_ro6);
158: if (sc->gif_ro6.ro_rt == NULL) {
159: m_freem(m);
160: return ENETUNREACH;
161: }
162: }
163:
164: /*
165: * force fragmentation to minimum MTU, to avoid path MTU discovery.
166: * it is too painful to ask for resend of inner packet, to achieve
167: * path MTU discovery for encapsulated packets.
168: */
169: error = ip6_output(m, 0, &sc->gif_ro6, IPV6_MINMTU, 0, NULL, NULL);
170:
171: return error;
172: }
173:
174: int in6_gif_input(mp, offp, proto)
175: struct mbuf **mp;
176: int *offp, proto;
177: {
178: struct mbuf *m = *mp;
179: struct gif_softc *sc;
180: struct ifnet *gifp = NULL;
181: struct ip6_hdr *ip6;
182:
183: /* XXX What if we run transport-mode IPsec to protect gif tunnel ? */
184: if (m->m_flags & (M_AUTH | M_CONF))
185: goto inject;
186:
187: ip6 = mtod(m, struct ip6_hdr *);
188:
189: #define satoin6(sa) (((struct sockaddr_in6 *)(sa))->sin6_addr)
190: LIST_FOREACH(sc, &gif_softc_list, gif_list) {
191: if (sc->gif_psrc == NULL || sc->gif_pdst == NULL ||
192: sc->gif_psrc->sa_family != AF_INET6 ||
193: sc->gif_pdst->sa_family != AF_INET6) {
194: continue;
195: }
196:
197: if ((sc->gif_if.if_flags & IFF_UP) == 0)
198: continue;
199:
200: if (IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_psrc), &ip6->ip6_dst) &&
201: IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_pdst), &ip6->ip6_src)) {
202: gifp = &sc->gif_if;
203: break;
204: }
205: }
206:
207: if (gifp) {
208: m->m_pkthdr.rcvif = gifp;
209: gifp->if_ipackets++;
210: gifp->if_ibytes += m->m_pkthdr.len;
211: ipip_input(m, *offp, gifp);
212: return IPPROTO_DONE;
213: }
214:
215: inject:
216: /* No GIF tunnel configured */
217: ip4_input6(&m, offp, 0); /* XXX last argument ignored */
218: return IPPROTO_DONE;
219: }
CVSweb