1 /* $OpenBSD: ip_gre.c,v 1.24 2003/12/10 07:22:43 itojun Exp $ */
2 /* $NetBSD: ip_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */
3
4 /*
5 * Copyright (c) 1998 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Heiko W.Rupp <hwr@pilhuhn.de>
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * decapsulate tunneled packets and send them on
42 * output half is in net/if_gre.[ch]
43 * This currently handles IPPROTO_GRE, IPPROTO_MOBILE
44 */
45
46
47 #include "gre.h"
48 #if NGRE > 0
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/mbuf.h>
53 #include <sys/socket.h>
54 #include <sys/sysctl.h>
55 #include <net/if.h>
56 #include <net/netisr.h>
57 #include <net/route.h>
58 #include <net/bpf.h>
59
60 #ifdef INET
61 #include <netinet/in.h>
62 #include <netinet/in_var.h>
63 #include <netinet/in_systm.h>
64 #include <netinet/ip.h>
65 #include <netinet/ip_var.h>
66 #include <netinet/ip_gre.h>
67 #include <netinet/if_ether.h>
68 #else
69 #error "ip_gre used without inet"
70 #endif
71
72 #ifdef NS
73 #include <netns/ns.h>
74 #include <netns/ns_if.h>
75 #endif
76
77 #ifdef NETATALK
78 #include <netatalk/at.h>
79 #include <netatalk/at_var.h>
80 #include <netatalk/at_extern.h>
81 #endif
82
83 #include "bpfilter.h"
84
85 /* Needs IP headers. */
86 #include <net/if_gre.h>
87
88 struct gre_softc *gre_lookup(struct mbuf *, u_int8_t);
89 static int gre_input2(struct mbuf *, int, u_char);
90
91 /*
92 * Decapsulate.
93 * Does the real work and is called from gre_input() (above)
94 * returns 0 if packet is not yet processed
95 * and 1 if it needs no further processing
96 * proto is the protocol number of the "calling" foo_input()
97 * routine.
98 */
99
100 static int
gre_input2(m,hlen,proto)101 gre_input2(m , hlen, proto)
102 struct mbuf *m;
103 int hlen;
104 u_char proto;
105 {
106 struct greip *gip;
107 int s;
108 struct ifqueue *ifq;
109 struct gre_softc *sc;
110 u_short flags;
111 u_int af;
112
113 if ((sc = gre_lookup(m, proto)) == NULL) {
114 /* No matching tunnel or tunnel is down. */
115 return (0);
116 }
117
118 if (m->m_len < sizeof(*gip)) {
119 m = m_pullup(m, sizeof(*gip));
120 if (m == NULL)
121 return (ENOBUFS);
122 }
123 gip = mtod(m, struct greip *);
124
125 m->m_pkthdr.rcvif = &sc->sc_if;
126
127 sc->sc_if.if_ipackets++;
128 sc->sc_if.if_ibytes += m->m_pkthdr.len;
129
130 switch (proto) {
131 case IPPROTO_GRE:
132 hlen += sizeof (struct gre_h);
133
134 /* process GRE flags as packet can be of variable len */
135 flags = ntohs(gip->gi_flags);
136
137 /* Checksum & Offset are present */
138 if ((flags & GRE_CP) | (flags & GRE_RP))
139 hlen += 4;
140
141 /* We don't support routing fields (variable length) */
142 if (flags & GRE_RP)
143 return (0);
144
145 if (flags & GRE_KP)
146 hlen += 4;
147
148 if (flags & GRE_SP)
149 hlen += 4;
150
151 switch (ntohs(gip->gi_ptype)) { /* ethertypes */
152 case GREPROTO_WCCP:
153 /* WCCP/GRE:
154 * So far as I can see (and test) it seems that Cisco's WCCP
155 * GRE tunnel is precisely a IP-in-GRE tunnel that differs
156 * only in it's protocol number. At least, it works for me.
157 *
158 * The Internet Draft can be found if you look for
159 * draft-forster-wrec-wccp-v1-00.txt
160 *
161 * So yes, we're doing a fall-through (unless, of course,
162 * net.inet.gre.wccp is 0).
163 */
164 if (!gre_wccp)
165 return (0);
166 case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */
167 ifq = &ipintrq; /* we are in ip_input */
168 af = AF_INET;
169 break;
170 #ifdef NS
171 case ETHERTYPE_NS:
172 ifq = &nsintrq;
173 schednetisr_virtual(NETISR_NS);
174 af = AF_NS;
175 break;
176 #endif
177 #ifdef NETATALK
178 case ETHERTYPE_AT:
179 ifq = &atintrq1;
180 schednetisr_virtual(NETISR_ATALK);
181 af = AF_APPLETALK;
182 break;
183 #endif
184 #ifdef INET6
185 case ETHERTYPE_IPV6:
186 ifq = &ip6intrq;
187 schednetisr_virtual(NETISR_IPV6);
188 af = AF_INET6;
189 break;
190 #endif /* INET6 */
191 default: /* others not yet supported */
192 return (0);
193 }
194 break;
195 default:
196 /* others not yet supported */
197 return (0);
198 }
199
200 if (hlen > m->m_pkthdr.len) {
201 m_freem(m);
202 return (EINVAL);
203 }
204 m_adj(m, hlen);
205
206 #if NBPFILTER > 0
207 if (sc->sc_if.if_bpf) {
208 /*
209 * We need to prepend the address family as
210 * a four byte field. Cons up a fake header
211 * to pacify bpf. This is safe because bpf
212 * will only read from the mbuf (i.e., it won't
213 * try to free it or keep a pointer a to it).
214 */
215 struct mbuf m0;
216
217 m0.m_flags = 0;
218 m0.m_next = m;
219 m0.m_len = 4;
220 m0.m_data = (char *) ⁡
221
222 bpf_mtap(sc->sc_if.if_bpf, &m0);
223 }
224 #endif
225
226 s = splimp(); /* possible */
227 if (IF_QFULL(ifq)) {
228 IF_DROP(ifq);
229 m_freem(m);
230 } else {
231 IF_ENQUEUE(ifq, m);
232 }
233 splx(s);
234
235 return (1); /* packet is done, no further processing needed */
236 }
237
238 /*
239 * Decapsulate a packet and feed it back through ip_input (this
240 * routine is called whenever IP gets a packet with proto type
241 * IPPROTO_GRE and a local destination address).
242 */
243 void
gre_input(struct mbuf * m,...)244 gre_input(struct mbuf *m, ...)
245 {
246 int hlen, ret;
247 va_list ap;
248
249 va_start(ap, m);
250 hlen = va_arg(ap, int);
251 va_end(ap);
252
253 if (!gre_allow) {
254 m_freem(m);
255 return;
256 }
257
258 ret = gre_input2(m, hlen, IPPROTO_GRE);
259 /*
260 * ret == 0: packet not processed, but input from here
261 * means no matching tunnel that is up is found.
262 * we inject it to raw ip socket to see if anyone picks it up.
263 * possible that we received a WCCPv1-style GRE packet
264 * but we're not set to accept them.
265 */
266 if (!ret)
267 rip_input(m, hlen, IPPROTO_GRE);
268 }
269
270 /*
271 * Input routine for IPPRPOTO_MOBILE.
272 * This is a little bit diffrent from the other modes, as the
273 * encapsulating header was not prepended, but instead inserted
274 * between IP header and payload.
275 */
276
277 void
gre_mobile_input(struct mbuf * m,...)278 gre_mobile_input(struct mbuf *m, ...)
279 {
280 struct ip *ip;
281 struct mobip_h *mip;
282 struct ifqueue *ifq;
283 struct gre_softc *sc;
284 int hlen, s;
285 va_list ap;
286 u_char osrc = 0;
287 int msiz;
288
289 va_start(ap, m);
290 hlen = va_arg(ap, int);
291 va_end(ap);
292
293 if (!ip_mobile_allow) {
294 m_freem(m);
295 return;
296 }
297
298 if ((sc = gre_lookup(m, IPPROTO_MOBILE)) == NULL) {
299 /* No matching tunnel or tunnel is down. */
300 m_freem(m);
301 return;
302 }
303
304 if (m->m_len < sizeof(*mip)) {
305 m = m_pullup(m, sizeof(*mip));
306 if (m == NULL)
307 return;
308 }
309 ip = mtod(m, struct ip *);
310 mip = mtod(m, struct mobip_h *);
311
312 m->m_pkthdr.rcvif = &sc->sc_if;
313
314 sc->sc_if.if_ipackets++;
315 sc->sc_if.if_ibytes += m->m_pkthdr.len;
316
317 if (ntohs(mip->mh.proto) & MOB_H_SBIT) {
318 osrc = 1;
319 msiz = MOB_H_SIZ_L;
320 mip->mi.ip_src.s_addr = mip->mh.osrc;
321 } else
322 msiz = MOB_H_SIZ_S;
323
324 if (m->m_len < (ip->ip_hl << 2) + msiz) {
325 m = m_pullup(m, (ip->ip_hl << 2) + msiz);
326 if (m == NULL)
327 return;
328 ip = mtod(m, struct ip *);
329 mip = mtod(m, struct mobip_h *);
330 }
331
332 mip->mi.ip_dst.s_addr = mip->mh.odst;
333 mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8);
334
335 if (gre_in_cksum((u_short *) &mip->mh, msiz) != 0) {
336 m_freem(m);
337 return;
338 }
339
340 bcopy(ip + (ip->ip_hl << 2) + msiz, ip + (ip->ip_hl << 2),
341 m->m_len - msiz - (ip->ip_hl << 2));
342
343 m->m_len -= msiz;
344 ip->ip_len = htons(ntohs(ip->ip_len) - msiz);
345 m->m_pkthdr.len -= msiz;
346
347 ip->ip_sum = 0;
348 ip->ip_sum = in_cksum(m,(ip->ip_hl << 2));
349
350 ifq = &ipintrq;
351
352 #if NBPFILTER > 0
353 if (sc->sc_if.if_bpf) {
354 /*
355 * We need to prepend the address family as
356 * a four byte field. Cons up a fake header
357 * to pacify bpf. This is safe because bpf
358 * will only read from the mbuf (i.e., it won't
359 * try to free it or keep a pointer a to it).
360 */
361 struct mbuf m0;
362 u_int af = AF_INET;
363
364 m0.m_flags = 0;
365 m0.m_next = m;
366 m0.m_len = 4;
367 m0.m_data = (char *) ⁡
368
369 bpf_mtap(sc->sc_if.if_bpf, &m0);
370 }
371 #endif
372
373 s = splimp(); /* possible */
374 if (IF_QFULL(ifq)) {
375 IF_DROP(ifq);
376 m_freem(m);
377 } else {
378 IF_ENQUEUE(ifq, m);
379 }
380 splx(s);
381 }
382
383 /*
384 * Find the gre interface associated with our src/dst/proto set.
385 */
386 struct gre_softc *
gre_lookup(m,proto)387 gre_lookup(m, proto)
388 struct mbuf *m;
389 u_int8_t proto;
390 {
391 struct ip *ip = mtod(m, struct ip *);
392 struct gre_softc *sc;
393
394 LIST_FOREACH(sc, &gre_softc_list, sc_list) {
395 if ((sc->g_dst.s_addr == ip->ip_src.s_addr) &&
396 (sc->g_src.s_addr == ip->ip_dst.s_addr) &&
397 (sc->g_proto == proto) &&
398 ((sc->sc_if.if_flags & IFF_UP) != 0))
399 return (sc);
400 }
401
402 return (NULL);
403 }
404
405 int
gre_sysctl(name,namelen,oldp,oldlenp,newp,newlen)406 gre_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
407 int *name;
408 u_int namelen;
409 void *oldp;
410 size_t *oldlenp;
411 void *newp;
412 size_t newlen;
413 {
414 /* All sysctl names at this level are terminal. */
415 if (namelen != 1)
416 return (ENOTDIR);
417
418 switch (name[0]) {
419 case GRECTL_ALLOW:
420 return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_allow));
421 case GRECTL_WCCP:
422 return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp));
423 default:
424 return (ENOPROTOOPT);
425 }
426 /* NOTREACHED */
427 }
428
429 int
ipmobile_sysctl(name,namelen,oldp,oldlenp,newp,newlen)430 ipmobile_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
431 int *name;
432 u_int namelen;
433 void *oldp;
434 size_t *oldlenp;
435 void *newp;
436 size_t newlen;
437 {
438 /* All sysctl names at this level are terminal. */
439 if (namelen != 1)
440 return (ENOTDIR);
441
442 switch (name[0]) {
443 case MOBILEIPCTL_ALLOW:
444 return (sysctl_int(oldp, oldlenp, newp, newlen,
445 &ip_mobile_allow));
446 default:
447 return (ENOPROTOOPT);
448 }
449 /* NOTREACHED */
450 }
451 #endif /* if NGRE > 0 */
452