This source file includes following definitions.
- gre_input2
- gre_input
- gre_mobile_input
- gre_lookup
- gre_sysctl
- ipmobile_sysctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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 NETATALK
73 #include <netatalk/at.h>
74 #include <netatalk/at_var.h>
75 #include <netatalk/at_extern.h>
76 #endif
77
78 #include "bpfilter.h"
79
80
81 #include <net/if_gre.h>
82
83 struct gre_softc *gre_lookup(struct mbuf *, u_int8_t);
84 int gre_input2(struct mbuf *, int, u_char);
85
86
87
88
89
90
91
92
93
94
95 int
96 gre_input2(m , hlen, proto)
97 struct mbuf *m;
98 int hlen;
99 u_char proto;
100 {
101 struct greip *gip;
102 int s;
103 struct ifqueue *ifq;
104 struct gre_softc *sc;
105 u_short flags;
106 u_int af;
107
108 if ((sc = gre_lookup(m, proto)) == NULL) {
109
110 return (0);
111 }
112
113 if (m->m_len < sizeof(*gip)) {
114 m = m_pullup(m, sizeof(*gip));
115 if (m == NULL)
116 return (ENOBUFS);
117 }
118 gip = mtod(m, struct greip *);
119
120 m->m_pkthdr.rcvif = &sc->sc_if;
121
122 sc->sc_if.if_ipackets++;
123 sc->sc_if.if_ibytes += m->m_pkthdr.len;
124
125 switch (proto) {
126 case IPPROTO_GRE:
127 hlen += sizeof (struct gre_h);
128
129
130 flags = ntohs(gip->gi_flags);
131
132
133 if ((flags & GRE_CP) | (flags & GRE_RP))
134 hlen += 4;
135
136
137 if (flags & GRE_RP)
138 return (0);
139
140 if (flags & GRE_KP)
141 hlen += 4;
142
143 if (flags & GRE_SP)
144 hlen += 4;
145
146 switch (ntohs(gip->gi_ptype)) {
147 case GREPROTO_WCCP:
148
149
150
151
152
153
154
155
156
157
158
159 if (!gre_wccp)
160 return (0);
161 case ETHERTYPE_IP:
162 ifq = &ipintrq;
163 af = AF_INET;
164 break;
165 #ifdef NETATALK
166 case ETHERTYPE_AT:
167 ifq = &atintrq1;
168 schednetisr(NETISR_ATALK);
169 af = AF_APPLETALK;
170 break;
171 #endif
172 #ifdef INET6
173 case ETHERTYPE_IPV6:
174 ifq = &ip6intrq;
175 schednetisr(NETISR_IPV6);
176 af = AF_INET6;
177 break;
178 #endif
179 default:
180 return (0);
181 }
182 break;
183 default:
184
185 return (0);
186 }
187
188 if (hlen > m->m_pkthdr.len) {
189 m_freem(m);
190 return (EINVAL);
191 }
192 m_adj(m, hlen);
193
194 #if NBPFILTER > 0
195 if (sc->sc_if.if_bpf)
196 bpf_mtap_af(sc->sc_if.if_bpf, af, m, BPF_DIRECTION_IN);
197 #endif
198
199 s = splnet();
200 IF_INPUT_ENQUEUE(ifq, m);
201 splx(s);
202
203 return (1);
204 }
205
206
207
208
209
210
211 void
212 gre_input(struct mbuf *m, ...)
213 {
214 int hlen, ret;
215 va_list ap;
216
217 va_start(ap, m);
218 hlen = va_arg(ap, int);
219 va_end(ap);
220
221 if (!gre_allow) {
222 m_freem(m);
223 return;
224 }
225
226 ret = gre_input2(m, hlen, IPPROTO_GRE);
227
228
229
230
231
232
233
234 if (!ret)
235 rip_input(m, hlen, IPPROTO_GRE);
236 }
237
238
239
240
241
242
243
244
245 void
246 gre_mobile_input(struct mbuf *m, ...)
247 {
248 struct ip *ip;
249 struct mobip_h *mip;
250 struct ifqueue *ifq;
251 struct gre_softc *sc;
252 int hlen, s;
253 va_list ap;
254 u_char osrc = 0;
255 int msiz;
256
257 va_start(ap, m);
258 hlen = va_arg(ap, int);
259 va_end(ap);
260
261 if (!ip_mobile_allow) {
262 m_freem(m);
263 return;
264 }
265
266 if ((sc = gre_lookup(m, IPPROTO_MOBILE)) == NULL) {
267
268 m_freem(m);
269 return;
270 }
271
272 if (m->m_len < sizeof(*mip)) {
273 m = m_pullup(m, sizeof(*mip));
274 if (m == NULL)
275 return;
276 }
277 ip = mtod(m, struct ip *);
278 mip = mtod(m, struct mobip_h *);
279
280 m->m_pkthdr.rcvif = &sc->sc_if;
281
282 sc->sc_if.if_ipackets++;
283 sc->sc_if.if_ibytes += m->m_pkthdr.len;
284
285 if (ntohs(mip->mh.proto) & MOB_H_SBIT) {
286 osrc = 1;
287 msiz = MOB_H_SIZ_L;
288 mip->mi.ip_src.s_addr = mip->mh.osrc;
289 } else
290 msiz = MOB_H_SIZ_S;
291
292 if (m->m_len < (ip->ip_hl << 2) + msiz) {
293 m = m_pullup(m, (ip->ip_hl << 2) + msiz);
294 if (m == NULL)
295 return;
296 ip = mtod(m, struct ip *);
297 mip = mtod(m, struct mobip_h *);
298 }
299
300 mip->mi.ip_dst.s_addr = mip->mh.odst;
301 mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8);
302
303 if (gre_in_cksum((u_short *) &mip->mh, msiz) != 0) {
304 m_freem(m);
305 return;
306 }
307
308 bcopy(ip + (ip->ip_hl << 2) + msiz, ip + (ip->ip_hl << 2),
309 m->m_len - msiz - (ip->ip_hl << 2));
310
311 m->m_len -= msiz;
312 ip->ip_len = htons(ntohs(ip->ip_len) - msiz);
313 m->m_pkthdr.len -= msiz;
314
315 ip->ip_sum = 0;
316 ip->ip_sum = in_cksum(m,(ip->ip_hl << 2));
317
318 ifq = &ipintrq;
319
320 #if NBPFILTER > 0
321 if (sc->sc_if.if_bpf)
322 bpf_mtap_af(sc->sc_if.if_bpf, AF_INET, m, BPF_DIRECTION_IN);
323 #endif
324
325 s = splnet();
326 IF_INPUT_ENQUEUE(ifq, m);
327 splx(s);
328 }
329
330
331
332
333 struct gre_softc *
334 gre_lookup(m, proto)
335 struct mbuf *m;
336 u_int8_t proto;
337 {
338 struct ip *ip = mtod(m, struct ip *);
339 struct gre_softc *sc;
340
341 LIST_FOREACH(sc, &gre_softc_list, sc_list) {
342 if ((sc->g_dst.s_addr == ip->ip_src.s_addr) &&
343 (sc->g_src.s_addr == ip->ip_dst.s_addr) &&
344 (sc->g_proto == proto) &&
345 ((sc->sc_if.if_flags & IFF_UP) != 0))
346 return (sc);
347 }
348
349 return (NULL);
350 }
351
352 int
353 gre_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
354 int *name;
355 u_int namelen;
356 void *oldp;
357 size_t *oldlenp;
358 void *newp;
359 size_t newlen;
360 {
361
362 if (namelen != 1)
363 return (ENOTDIR);
364
365 switch (name[0]) {
366 case GRECTL_ALLOW:
367 return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_allow));
368 case GRECTL_WCCP:
369 return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp));
370 default:
371 return (ENOPROTOOPT);
372 }
373
374 }
375
376 int
377 ipmobile_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
378 int *name;
379 u_int namelen;
380 void *oldp;
381 size_t *oldlenp;
382 void *newp;
383 size_t newlen;
384 {
385
386 if (namelen != 1)
387 return (ENOTDIR);
388
389 switch (name[0]) {
390 case MOBILEIPCTL_ALLOW:
391 return (sysctl_int(oldp, oldlenp, newp, newlen,
392 &ip_mobile_allow));
393 default:
394 return (ENOPROTOOPT);
395 }
396
397 }
398 #endif