Deleted Added
full compact
in6_gif.c (55009) in6_gif.c (62587)
1/* $FreeBSD: head/sys/netinet6/in6_gif.c 62587 2000-07-04 16:35:15Z itojun $ */
2/* $KAME: in6_gif.c,v 1.37 2000/06/17 20:34:25 itojun Exp $ */
3
1/*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
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

--- 11 unchanged lines hidden (view full) ---

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.
28 *
29 * $FreeBSD: head/sys/netinet6/in6_gif.c 55009 1999-12-22 19:13:38Z shin $
30 */
31
32/*
33 * in6_gif.c
34 */
35
36#include "opt_inet.h"
31 */
32
33/*
34 * in6_gif.c
35 */
36
37#include "opt_inet.h"
38#include "opt_inet6.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/socket.h>
41#include <sys/sockio.h>
42#include <sys/mbuf.h>
43#include <sys/errno.h>
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/socket.h>
43#include <sys/sockio.h>
44#include <sys/mbuf.h>
45#include <sys/errno.h>
44#include <sys/protosw.h>
45
46#include <net/if.h>
47#include <net/route.h>
48
49#include <netinet/in.h>
50#include <netinet/in_systm.h>
51#ifdef INET
52#include <netinet/ip.h>
53#endif
46
47#include <net/if.h>
48#include <net/route.h>
49
50#include <netinet/in.h>
51#include <netinet/in_systm.h>
52#ifdef INET
53#include <netinet/ip.h>
54#endif
54#include <netinet6/ip6.h>
55#include <netinet/ip_encap.h>
56#ifdef INET6
57#include <netinet/ip6.h>
55#include <netinet6/ip6_var.h>
56#include <netinet6/in6_gif.h>
58#include <netinet6/ip6_var.h>
59#include <netinet6/in6_gif.h>
57#include <netinet6/ip6.h>
60#include <netinet6/in6_var.h>
61#endif
58#include <netinet/ip_ecn.h>
62#include <netinet/ip_ecn.h>
63#ifdef INET6
59#include <netinet6/ip6_ecn.h>
64#include <netinet6/ip6_ecn.h>
65#endif
60
61#include <net/if_gif.h>
62
63#include <net/net_osdep.h>
64
66
67#include <net/if_gif.h>
68
69#include <net/net_osdep.h>
70
71#ifndef offsetof
72#define offsetof(s, e) ((int)&((s *)0)->e)
73#endif
74
65int
66in6_gif_output(ifp, family, m, rt)
67 struct ifnet *ifp;
68 int family; /* family of the packet to be encapsulate. */
69 struct mbuf *m;
70 struct rtentry *rt;
71{
72 struct gif_softc *sc = (struct gif_softc*)ifp;

--- 23 unchanged lines hidden (view full) ---

96 if (!m)
97 return ENOBUFS;
98 }
99 ip = mtod(m, struct ip *);
100 itos = ip->ip_tos;
101 break;
102 }
103#endif
75int
76in6_gif_output(ifp, family, m, rt)
77 struct ifnet *ifp;
78 int family; /* family of the packet to be encapsulate. */
79 struct mbuf *m;
80 struct rtentry *rt;
81{
82 struct gif_softc *sc = (struct gif_softc*)ifp;

--- 23 unchanged lines hidden (view full) ---

106 if (!m)
107 return ENOBUFS;
108 }
109 ip = mtod(m, struct ip *);
110 itos = ip->ip_tos;
111 break;
112 }
113#endif
114#ifdef INET6
104 case AF_INET6:
105 {
106 struct ip6_hdr *ip6;
107 proto = IPPROTO_IPV6;
108 if (m->m_len < sizeof(*ip6)) {
109 m = m_pullup(m, sizeof(*ip6));
110 if (!m)
111 return ENOBUFS;
112 }
113 ip6 = mtod(m, struct ip6_hdr *);
114 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
115 break;
116 }
115 case AF_INET6:
116 {
117 struct ip6_hdr *ip6;
118 proto = IPPROTO_IPV6;
119 if (m->m_len < sizeof(*ip6)) {
120 m = m_pullup(m, sizeof(*ip6));
121 if (!m)
122 return ENOBUFS;
123 }
124 ip6 = mtod(m, struct ip6_hdr *);
125 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
126 break;
127 }
128#endif
117 default:
129 default:
118#ifdef DIAGNOSTIC
130#ifdef DEBUG
119 printf("in6_gif_output: warning: unknown family %d passed\n",
120 family);
121#endif
122 m_freem(m);
123 return EAFNOSUPPORT;
124 }
131 printf("in6_gif_output: warning: unknown family %d passed\n",
132 family);
133#endif
134 m_freem(m);
135 return EAFNOSUPPORT;
136 }
125
137
126 /* prepend new IP header */
127 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
128 if (m && m->m_len < sizeof(struct ip6_hdr))
129 m = m_pullup(m, sizeof(struct ip6_hdr));
130 if (m == NULL) {
131 printf("ENOBUFS in in6_gif_output %d\n", __LINE__);
132 return ENOBUFS;
133 }
134
135 ip6 = mtod(m, struct ip6_hdr *);
136 ip6->ip6_flow = 0;
138 /* prepend new IP header */
139 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
140 if (m && m->m_len < sizeof(struct ip6_hdr))
141 m = m_pullup(m, sizeof(struct ip6_hdr));
142 if (m == NULL) {
143 printf("ENOBUFS in in6_gif_output %d\n", __LINE__);
144 return ENOBUFS;
145 }
146
147 ip6 = mtod(m, struct ip6_hdr *);
148 ip6->ip6_flow = 0;
137 ip6->ip6_vfc = IPV6_VERSION;
149 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
150 ip6->ip6_vfc |= IPV6_VERSION;
138 ip6->ip6_plen = htons((u_short)m->m_pkthdr.len);
139 ip6->ip6_nxt = proto;
140 ip6->ip6_hlim = ip6_gif_hlim;
141 ip6->ip6_src = sin6_src->sin6_addr;
142 if (ifp->if_flags & IFF_LINK0) {
143 /* multi-destination mode */
144 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))
145 ip6->ip6_dst = sin6_dst->sin6_addr;
146 else if (rt) {
151 ip6->ip6_plen = htons((u_short)m->m_pkthdr.len);
152 ip6->ip6_nxt = proto;
153 ip6->ip6_hlim = ip6_gif_hlim;
154 ip6->ip6_src = sin6_src->sin6_addr;
155 if (ifp->if_flags & IFF_LINK0) {
156 /* multi-destination mode */
157 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))
158 ip6->ip6_dst = sin6_dst->sin6_addr;
159 else if (rt) {
160 if (family != AF_INET6) {
161 m_freem(m);
162 return EINVAL; /*XXX*/
163 }
147 ip6->ip6_dst = ((struct sockaddr_in6 *)(rt->rt_gateway))->sin6_addr;
148 } else {
149 m_freem(m);
150 return ENETUNREACH;
151 }
152 } else {
153 /* bidirectional configured tunnel mode */
154 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))

--- 15 unchanged lines hidden (view full) ---

170 bzero(dst, sizeof(*dst));
171 dst->sin6_family = sin6_dst->sin6_family;
172 dst->sin6_len = sizeof(struct sockaddr_in6);
173 dst->sin6_addr = sin6_dst->sin6_addr;
174 if (sc->gif_ro6.ro_rt) {
175 RTFREE(sc->gif_ro6.ro_rt);
176 sc->gif_ro6.ro_rt = NULL;
177 }
164 ip6->ip6_dst = ((struct sockaddr_in6 *)(rt->rt_gateway))->sin6_addr;
165 } else {
166 m_freem(m);
167 return ENETUNREACH;
168 }
169 } else {
170 /* bidirectional configured tunnel mode */
171 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))

--- 15 unchanged lines hidden (view full) ---

187 bzero(dst, sizeof(*dst));
188 dst->sin6_family = sin6_dst->sin6_family;
189 dst->sin6_len = sizeof(struct sockaddr_in6);
190 dst->sin6_addr = sin6_dst->sin6_addr;
191 if (sc->gif_ro6.ro_rt) {
192 RTFREE(sc->gif_ro6.ro_rt);
193 sc->gif_ro6.ro_rt = NULL;
194 }
195#if 0
196 sc->gif_if.if_mtu = GIF_MTU;
197#endif
178 }
179
180 if (sc->gif_ro6.ro_rt == NULL) {
181 rtalloc((struct route *)&sc->gif_ro6);
182 if (sc->gif_ro6.ro_rt == NULL) {
183 m_freem(m);
184 return ENETUNREACH;
185 }
198 }
199
200 if (sc->gif_ro6.ro_rt == NULL) {
201 rtalloc((struct route *)&sc->gif_ro6);
202 if (sc->gif_ro6.ro_rt == NULL) {
203 m_freem(m);
204 return ENETUNREACH;
205 }
186 }
187
206
207 /* if it constitutes infinite encapsulation, punt. */
208 if (sc->gif_ro.ro_rt->rt_ifp == ifp) {
209 m_freem(m);
210 return ENETUNREACH; /*XXX*/
211 }
212#if 0
213 ifp->if_mtu = sc->gif_ro6.ro_rt->rt_ifp->if_mtu
214 - sizeof(struct ip6_hdr);
215#endif
216 }
217
218#ifdef IPV6_MINMTU
219 /*
220 * force fragmentation to minimum MTU, to avoid path MTU discovery.
221 * it is too painful to ask for resend of inner packet, to achieve
222 * path MTU discovery for encapsulated packets.
223 */
224 return(ip6_output(m, 0, &sc->gif_ro6, IPV6_MINMTU, 0, NULL));
225#else
188 return(ip6_output(m, 0, &sc->gif_ro6, 0, 0, NULL));
226 return(ip6_output(m, 0, &sc->gif_ro6, 0, 0, NULL));
227#endif
189}
190
191int in6_gif_input(mp, offp, proto)
192 struct mbuf **mp;
193 int *offp, proto;
194{
195 struct mbuf *m = *mp;
228}
229
230int in6_gif_input(mp, offp, proto)
231 struct mbuf **mp;
232 int *offp, proto;
233{
234 struct mbuf *m = *mp;
196 struct gif_softc *sc;
197 struct ifnet *gifp = NULL;
198 struct ip6_hdr *ip6;
235 struct ifnet *gifp = NULL;
236 struct ip6_hdr *ip6;
199 int i;
200 int af = 0;
201 u_int32_t otos;
202
203 ip6 = mtod(m, struct ip6_hdr *);
204
237 int af = 0;
238 u_int32_t otos;
239
240 ip6 = mtod(m, struct ip6_hdr *);
241
205#define satoin6(sa) (((struct sockaddr_in6 *)(sa))->sin6_addr)
206 for (i = 0, sc = gif; i < ngif; i++, sc++) {
207 if (sc->gif_psrc == NULL ||
208 sc->gif_pdst == NULL ||
209 sc->gif_psrc->sa_family != AF_INET6 ||
210 sc->gif_pdst->sa_family != AF_INET6) {
211 continue;
212 }
213 if ((sc->gif_if.if_flags & IFF_UP) == 0)
214 continue;
215 if ((sc->gif_if.if_flags & IFF_LINK0) &&
216 IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_psrc), &ip6->ip6_dst) &&
217 IN6_IS_ADDR_UNSPECIFIED(&satoin6(sc->gif_pdst))) {
218 gifp = &sc->gif_if;
219 continue;
220 }
221 if (IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_psrc), &ip6->ip6_dst) &&
222 IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_pdst), &ip6->ip6_src)) {
223 gifp = &sc->gif_if;
224 break;
225 }
226 }
242 gifp = (struct ifnet *)encap_getarg(m);
227
243
228 if (gifp == NULL) {
244 if (gifp == NULL || (gifp->if_flags & IFF_UP) == 0) {
229 m_freem(m);
230 ip6stat.ip6s_nogif++;
231 return IPPROTO_DONE;
232 }
245 m_freem(m);
246 ip6stat.ip6s_nogif++;
247 return IPPROTO_DONE;
248 }
233
249
234 otos = ip6->ip6_flow;
235 m_adj(m, *offp);
236
237 switch (proto) {
238#ifdef INET
239 case IPPROTO_IPV4:
240 {
241 struct ip *ip;

--- 6 unchanged lines hidden (view full) ---

248 return IPPROTO_DONE;
249 }
250 ip = mtod(m, struct ip *);
251 if (gifp->if_flags & IFF_LINK1)
252 ip_ecn_egress(ECN_ALLOWED, &otos8, &ip->ip_tos);
253 break;
254 }
255#endif /* INET */
250 otos = ip6->ip6_flow;
251 m_adj(m, *offp);
252
253 switch (proto) {
254#ifdef INET
255 case IPPROTO_IPV4:
256 {
257 struct ip *ip;

--- 6 unchanged lines hidden (view full) ---

264 return IPPROTO_DONE;
265 }
266 ip = mtod(m, struct ip *);
267 if (gifp->if_flags & IFF_LINK1)
268 ip_ecn_egress(ECN_ALLOWED, &otos8, &ip->ip_tos);
269 break;
270 }
271#endif /* INET */
272#ifdef INET6
256 case IPPROTO_IPV6:
257 {
258 struct ip6_hdr *ip6;
259 af = AF_INET6;
260 if (m->m_len < sizeof(*ip6)) {
261 m = m_pullup(m, sizeof(*ip6));
262 if (!m)
263 return IPPROTO_DONE;
264 }
265 ip6 = mtod(m, struct ip6_hdr *);
266 if (gifp->if_flags & IFF_LINK1)
267 ip6_ecn_egress(ECN_ALLOWED, &otos, &ip6->ip6_flow);
268 break;
269 }
273 case IPPROTO_IPV6:
274 {
275 struct ip6_hdr *ip6;
276 af = AF_INET6;
277 if (m->m_len < sizeof(*ip6)) {
278 m = m_pullup(m, sizeof(*ip6));
279 if (!m)
280 return IPPROTO_DONE;
281 }
282 ip6 = mtod(m, struct ip6_hdr *);
283 if (gifp->if_flags & IFF_LINK1)
284 ip6_ecn_egress(ECN_ALLOWED, &otos, &ip6->ip6_flow);
285 break;
286 }
287#endif
270 default:
271 ip6stat.ip6s_nogif++;
272 m_freem(m);
273 return IPPROTO_DONE;
274 }
288 default:
289 ip6stat.ip6s_nogif++;
290 m_freem(m);
291 return IPPROTO_DONE;
292 }
275
293
276 gif_input(m, af, gifp);
277 return IPPROTO_DONE;
278}
294 gif_input(m, af, gifp);
295 return IPPROTO_DONE;
296}
297
298/*
299 * we know that we are in IFF_UP, outer address available, and outer family
300 * matched the physical addr family. see gif_encapcheck().
301 */
302int
303gif_encapcheck6(m, off, proto, arg)
304 const struct mbuf *m;
305 int off;
306 int proto;
307 void *arg;
308{
309 struct ip6_hdr ip6;
310 struct gif_softc *sc;
311 struct sockaddr_in6 *src, *dst;
312 int addrmatch;
313
314 /* sanity check done in caller */
315 sc = (struct gif_softc *)arg;
316 src = (struct sockaddr_in6 *)sc->gif_psrc;
317 dst = (struct sockaddr_in6 *)sc->gif_pdst;
318
319 /* LINTED const cast */
320 m_copydata((struct mbuf *)m, 0, sizeof(ip6), (caddr_t)&ip6);
321
322 /* check for address match */
323 addrmatch = 0;
324 if (IN6_ARE_ADDR_EQUAL(&src->sin6_addr, &ip6.ip6_dst))
325 addrmatch |= 1;
326 if (IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6.ip6_src))
327 addrmatch |= 2;
328 else if ((sc->gif_if.if_flags & IFF_LINK0) != 0 &&
329 IN6_IS_ADDR_UNSPECIFIED(&dst->sin6_addr)) {
330 addrmatch |= 2; /* we accept any source */
331 }
332 if (addrmatch != 3)
333 return 0;
334
335 /* martian filters on outer source - done in ip6_input */
336
337 /* ingress filters on outer source */
338 if ((m->m_flags & M_PKTHDR) != 0 && m->m_pkthdr.rcvif) {
339 struct sockaddr_in6 sin6;
340 struct rtentry *rt;
341
342 bzero(&sin6, sizeof(sin6));
343 sin6.sin6_family = AF_INET6;
344 sin6.sin6_len = sizeof(struct sockaddr_in6);
345 sin6.sin6_addr = ip6.ip6_src;
346 /* XXX scopeid */
347 rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
348 if (!rt)
349 return 0;
350 if (rt->rt_ifp != m->m_pkthdr.rcvif) {
351 rtfree(rt);
352 return 0;
353 }
354 rtfree(rt);
355 }
356
357 /* prioritize: IFF_LINK0 mode is less preferred */
358 return (sc->gif_if.if_flags & IFF_LINK0) ? 128 : 128 * 2;
359}