This source file includes following definitions.
- greattach
- gre_clone_create
- gre_clone_destroy
- gre_output
- gre_ioctl
- gre_compute_route
- gre_in_cksum
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
48 #include "gre.h"
49 #if NGRE > 0
50
51 #include "bpfilter.h"
52
53 #include <sys/param.h>
54 #include <sys/proc.h>
55 #include <sys/mbuf.h>
56 #include <sys/socket.h>
57 #include <sys/sockio.h>
58 #include <sys/kernel.h>
59 #include <sys/systm.h>
60
61 #include <net/if.h>
62 #include <net/if_types.h>
63 #include <net/netisr.h>
64 #include <net/route.h>
65
66 #ifdef INET
67 #include <netinet/in.h>
68 #include <netinet/in_systm.h>
69 #include <netinet/in_var.h>
70 #include <netinet/ip.h>
71 #include <netinet/ip_var.h>
72 #include <netinet/if_ether.h>
73 #else
74 #error "if_gre used without inet"
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 #if NBPFILTER > 0
84 #include <net/bpf.h>
85 #endif
86
87 #include <net/if_gre.h>
88
89 #ifndef GRE_RECURSION_LIMIT
90 #define GRE_RECURSION_LIMIT 3
91 #endif
92
93
94
95
96
97
98 #define GREMTU 1476
99
100 int gre_clone_create(struct if_clone *, int);
101 int gre_clone_destroy(struct ifnet *);
102
103 struct gre_softc_head gre_softc_list;
104 struct if_clone gre_cloner =
105 IF_CLONE_INITIALIZER("gre", gre_clone_create, gre_clone_destroy);
106
107
108
109
110
111
112
113
114
115
116 int gre_allow = 0;
117 int gre_wccp = 0;
118 int ip_mobile_allow = 0;
119
120 static void gre_compute_route(struct gre_softc *sc);
121
122 void
123 greattach(int n)
124 {
125 LIST_INIT(&gre_softc_list);
126 if_clone_attach(&gre_cloner);
127 }
128
129 int
130 gre_clone_create(struct if_clone *ifc, int unit)
131 {
132 struct gre_softc *sc;
133 int s;
134
135 sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
136 if (!sc)
137 return (ENOMEM);
138 bzero(sc, sizeof(*sc));
139 snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname, "%s%d",
140 ifc->ifc_name, unit);
141 sc->sc_if.if_softc = sc;
142 sc->sc_if.if_type = IFT_TUNNEL;
143 sc->sc_if.if_addrlen = 0;
144 sc->sc_if.if_hdrlen = 24;
145 sc->sc_if.if_mtu = GREMTU;
146 sc->sc_if.if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
147 sc->sc_if.if_output = gre_output;
148 sc->sc_if.if_ioctl = gre_ioctl;
149 sc->sc_if.if_collisions = 0;
150 sc->sc_if.if_ierrors = 0;
151 sc->sc_if.if_oerrors = 0;
152 sc->sc_if.if_ipackets = 0;
153 sc->sc_if.if_opackets = 0;
154 sc->g_dst.s_addr = sc->g_src.s_addr = INADDR_ANY;
155 sc->g_proto = IPPROTO_GRE;
156 sc->sc_if.if_flags |= IFF_LINK0;
157
158 if_attach(&sc->sc_if);
159 if_alloc_sadl(&sc->sc_if);
160
161 #if NBPFILTER > 0
162 bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_NULL,
163 sizeof(u_int32_t));
164 #endif
165 s = splnet();
166 LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list);
167 splx(s);
168
169 return (0);
170 }
171
172 int
173 gre_clone_destroy(struct ifnet *ifp)
174 {
175 struct gre_softc *sc = ifp->if_softc;
176 int s;
177
178 s = splnet();
179 LIST_REMOVE(sc, sc_list);
180 splx(s);
181
182 if_detach(ifp);
183
184 free(sc, M_DEVBUF);
185 return (0);
186 }
187
188
189
190
191
192
193 int
194 gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
195 struct rtentry *rt)
196 {
197 int error = 0;
198 struct gre_softc *sc = (struct gre_softc *) (ifp->if_softc);
199 struct greip *gh = NULL;
200 struct ip *inp = NULL;
201 u_int8_t ip_tos = 0;
202 u_int16_t etype = 0;
203 struct mobile_h mob_h;
204 struct m_tag *mtag;
205
206 if ((ifp->if_flags & IFF_UP) == 0 ||
207 sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY) {
208 m_freem(m);
209 error = ENETDOWN;
210 goto end;
211 }
212
213
214 for (mtag = m_tag_find(m, PACKET_TAG_GRE, NULL); mtag;
215 mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) {
216 if (!bcmp((caddr_t)(mtag + 1), &ifp, sizeof(struct ifnet *))) {
217 IF_DROP(&ifp->if_snd);
218 m_freem(m);
219 error = EIO;
220 goto end;
221 }
222 }
223
224 mtag = m_tag_get(PACKET_TAG_GRE, sizeof(struct ifnet *), M_NOWAIT);
225 if (mtag == NULL) {
226 IF_DROP(&ifp->if_snd);
227 m_freem(m);
228 error = ENOBUFS;
229 goto end;
230 }
231 bcopy(&ifp, (caddr_t)(mtag + 1), sizeof(struct ifnet *));
232 m_tag_prepend(m, mtag);
233
234 m->m_flags &= ~(M_BCAST|M_MCAST);
235
236 #if NBPFILTER >0
237 if (ifp->if_bpf)
238 bpf_mtap_af(ifp->if_bpf, dst->sa_family, m, BPF_DIRECTION_OUT);
239 #endif
240
241 if (sc->g_proto == IPPROTO_MOBILE) {
242 if (ip_mobile_allow == 0) {
243 IF_DROP(&ifp->if_snd);
244 m_freem(m);
245 error = EACCES;
246 goto end;
247 }
248
249 if (dst->sa_family == AF_INET) {
250 struct mbuf *m0;
251 int msiz;
252
253
254
255
256
257 if (m->m_len < sizeof(struct ip)) {
258 m = m_pullup(m, sizeof(struct ip));
259 if (m == NULL) {
260 IF_DROP(&ifp->if_snd);
261 error = ENOBUFS;
262 goto end;
263 } else
264 inp = mtod(m, struct ip *);
265
266 if (m->m_len < inp->ip_hl << 2) {
267 m = m_pullup(m, inp->ip_hl << 2);
268 if (m == NULL) {
269 IF_DROP(&ifp->if_snd);
270 error = ENOBUFS;
271 goto end;
272 }
273 }
274 }
275
276 inp = mtod(m, struct ip *);
277
278 bzero(&mob_h, MOB_H_SIZ_L);
279 mob_h.proto = (inp->ip_p) << 8;
280 mob_h.odst = inp->ip_dst.s_addr;
281 inp->ip_dst.s_addr = sc->g_dst.s_addr;
282
283
284
285
286
287
288 if (inp->ip_src.s_addr == sc->g_src.s_addr) {
289 msiz = MOB_H_SIZ_S;
290 } else {
291 mob_h.proto |= MOB_H_SBIT;
292 mob_h.osrc = inp->ip_src.s_addr;
293 inp->ip_src.s_addr = sc->g_src.s_addr;
294 msiz = MOB_H_SIZ_L;
295 }
296
297 HTONS(mob_h.proto);
298 mob_h.hcrc = gre_in_cksum((u_int16_t *) &mob_h, msiz);
299
300
301 if ((m->m_data - msiz) < m->m_pktdat) {
302
303 MGETHDR(m0, M_DONTWAIT, MT_HEADER);
304 if (m0 == NULL) {
305 IF_DROP(&ifp->if_snd);
306 m_freem(m);
307 error = ENOBUFS;
308 goto end;
309 }
310 M_MOVE_HDR(m0, m);
311
312 m0->m_len = msiz + (inp->ip_hl << 2);
313 m0->m_data += max_linkhdr;
314 m0->m_pkthdr.len = m->m_pkthdr.len + msiz;
315 m->m_data += inp->ip_hl << 2;
316 m->m_len -= inp->ip_hl << 2;
317
318 bcopy((caddr_t) inp, mtod(m0, caddr_t),
319 sizeof(struct ip));
320
321 m0->m_next = m;
322 m = m0;
323 } else {
324 m->m_data -= msiz;
325 m->m_len += msiz;
326 m->m_pkthdr.len += msiz;
327 bcopy(inp, mtod(m, caddr_t),
328 inp->ip_hl << 2);
329 }
330
331
332 inp = mtod(m, struct ip *);
333 bcopy(&mob_h, (caddr_t)(inp + 1), (unsigned) msiz);
334 inp->ip_len = htons(ntohs(inp->ip_len) + msiz);
335 } else {
336 IF_DROP(&ifp->if_snd);
337 m_freem(m);
338 error = EINVAL;
339 goto end;
340 }
341 } else if (sc->g_proto == IPPROTO_GRE) {
342 if (gre_allow == 0) {
343 IF_DROP(&ifp->if_snd);
344 m_freem(m);
345 error = EACCES;
346 goto end;
347 }
348
349 switch(dst->sa_family) {
350 case AF_INET:
351 if (m->m_len < sizeof(struct ip)) {
352 m = m_pullup(m, sizeof(struct ip));
353 if (m == NULL) {
354 IF_DROP(&ifp->if_snd);
355 error = ENOBUFS;
356 goto end;
357 }
358 }
359
360 inp = mtod(m, struct ip *);
361 ip_tos = inp->ip_tos;
362 etype = ETHERTYPE_IP;
363 break;
364 #ifdef NETATALK
365 case AF_APPLETALK:
366 etype = ETHERTYPE_AT;
367 break;
368 #endif
369 #ifdef INET6
370 case AF_INET6:
371 etype = ETHERTYPE_IPV6;
372 break;
373 #endif
374 default:
375 IF_DROP(&ifp->if_snd);
376 m_freem(m);
377 error = EAFNOSUPPORT;
378 goto end;
379 }
380
381 M_PREPEND(m, sizeof(struct greip), M_DONTWAIT);
382 } else {
383 IF_DROP(&ifp->if_snd);
384 m_freem(m);
385 error = EINVAL;
386 goto end;
387 }
388
389 if (m == NULL) {
390 IF_DROP(&ifp->if_snd);
391 error = ENOBUFS;
392 goto end;
393 }
394
395 gh = mtod(m, struct greip *);
396 if (sc->g_proto == IPPROTO_GRE) {
397
398
399 bzero((void *) &gh->gi_g, sizeof(struct gre_h));
400 gh->gi_ptype = htons(etype);
401 }
402
403 gh->gi_pr = sc->g_proto;
404 if (sc->g_proto != IPPROTO_MOBILE) {
405 gh->gi_src = sc->g_src;
406 gh->gi_dst = sc->g_dst;
407 ((struct ip *) gh)->ip_hl = (sizeof(struct ip)) >> 2;
408 ((struct ip *) gh)->ip_ttl = ip_defttl;
409 ((struct ip *) gh)->ip_tos = ip_tos;
410 gh->gi_len = htons(m->m_pkthdr.len);
411 }
412
413 ifp->if_opackets++;
414 ifp->if_obytes += m->m_pkthdr.len;
415
416
417 error = ip_output(m, (void *)NULL, &sc->route, 0, (void *)NULL, (void *)NULL);
418 end:
419 if (error)
420 ifp->if_oerrors++;
421 return (error);
422 }
423
424 int
425 gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
426 {
427
428 struct ifreq *ifr = (struct ifreq *) data;
429 struct if_laddrreq *lifr = (struct if_laddrreq *)data;
430 struct gre_softc *sc = ifp->if_softc;
431 int s;
432 struct sockaddr_in si;
433 struct sockaddr *sa = NULL;
434 int error = 0;
435 struct proc *prc = curproc;
436
437 s = splnet();
438 switch(cmd) {
439 case SIOCSIFADDR:
440 ifp->if_flags |= IFF_UP;
441 break;
442 case SIOCSIFDSTADDR:
443 break;
444 case SIOCSIFFLAGS:
445 if ((ifr->ifr_flags & IFF_LINK0) != 0)
446 sc->g_proto = IPPROTO_GRE;
447 else
448 sc->g_proto = IPPROTO_MOBILE;
449 break;
450 case SIOCSIFMTU:
451 if (ifr->ifr_mtu < 576) {
452 error = EINVAL;
453 break;
454 }
455 ifp->if_mtu = ifr->ifr_mtu;
456 break;
457 case SIOCGIFMTU:
458 ifr->ifr_mtu = sc->sc_if.if_mtu;
459 break;
460 case SIOCADDMULTI:
461 case SIOCDELMULTI:
462 if (ifr == 0) {
463 error = EAFNOSUPPORT;
464 break;
465 }
466 switch (ifr->ifr_addr.sa_family) {
467 #ifdef INET
468 case AF_INET:
469 break;
470 #endif
471 #ifdef INET6
472 case AF_INET6:
473 break;
474 #endif
475 default:
476 error = EAFNOSUPPORT;
477 break;
478 }
479 break;
480 case GRESPROTO:
481
482 if ((error = suser(prc, 0)) != 0)
483 break;
484
485 sc->g_proto = ifr->ifr_flags;
486 switch (sc->g_proto) {
487 case IPPROTO_GRE:
488 ifp->if_flags |= IFF_LINK0;
489 break;
490 case IPPROTO_MOBILE:
491 ifp->if_flags &= ~IFF_LINK0;
492 break;
493 default:
494 error = EPROTONOSUPPORT;
495 break;
496 }
497 break;
498 case GREGPROTO:
499 ifr->ifr_flags = sc->g_proto;
500 break;
501 case GRESADDRS:
502 case GRESADDRD:
503
504 if ((error = suser(prc, 0)) != 0)
505 break;
506
507
508
509
510
511 sa = &ifr->ifr_addr;
512 if (cmd == GRESADDRS )
513 sc->g_src = (satosin(sa))->sin_addr;
514 if (cmd == GRESADDRD )
515 sc->g_dst = (satosin(sa))->sin_addr;
516 recompute:
517 if ((sc->g_src.s_addr != INADDR_ANY) &&
518 (sc->g_dst.s_addr != INADDR_ANY)) {
519 if (sc->route.ro_rt != 0) {
520
521 RTFREE(sc->route.ro_rt);
522 sc->route.ro_rt = (struct rtentry *) 0;
523 }
524 gre_compute_route(sc);
525 ifp->if_flags |= IFF_UP;
526 }
527 break;
528 case GREGADDRS:
529 bzero(&si, sizeof(si));
530 si.sin_family = AF_INET;
531 si.sin_len = sizeof(struct sockaddr_in);
532 si.sin_addr.s_addr = sc->g_src.s_addr;
533 sa = sintosa(&si);
534 ifr->ifr_addr = *sa;
535 break;
536 case GREGADDRD:
537 bzero(&si, sizeof(si));
538 si.sin_family = AF_INET;
539 si.sin_len = sizeof(struct sockaddr_in);
540 si.sin_addr.s_addr = sc->g_dst.s_addr;
541 sa = sintosa(&si);
542 ifr->ifr_addr = *sa;
543 break;
544 case SIOCSLIFPHYADDR:
545 if ((error = suser(prc, 0)) != 0)
546 break;
547 if (lifr->addr.ss_family != AF_INET ||
548 lifr->dstaddr.ss_family != AF_INET) {
549 error = EAFNOSUPPORT;
550 break;
551 }
552 if (lifr->addr.ss_len != sizeof(si) ||
553 lifr->dstaddr.ss_len != sizeof(si)) {
554 error = EINVAL;
555 break;
556 }
557 sc->g_src = (satosin((struct sockadrr *)&lifr->addr))->sin_addr;
558 sc->g_dst =
559 (satosin((struct sockadrr *)&lifr->dstaddr))->sin_addr;
560 goto recompute;
561 case SIOCDIFPHYADDR:
562 if ((error = suser(prc, 0)) != 0)
563 break;
564 sc->g_src.s_addr = INADDR_ANY;
565 sc->g_dst.s_addr = INADDR_ANY;
566 break;
567 case SIOCGLIFPHYADDR:
568 if (sc->g_src.s_addr == INADDR_ANY ||
569 sc->g_dst.s_addr == INADDR_ANY) {
570 error = EADDRNOTAVAIL;
571 break;
572 }
573 bzero(&si, sizeof(si));
574 si.sin_family = AF_INET;
575 si.sin_len = sizeof(struct sockaddr_in);
576 si.sin_addr.s_addr = sc->g_src.s_addr;
577 memcpy(&lifr->addr, &si, sizeof(si));
578 si.sin_addr.s_addr = sc->g_dst.s_addr;
579 memcpy(&lifr->dstaddr, &si, sizeof(si));
580 break;
581 default:
582 error = EINVAL;
583 }
584
585 splx(s);
586 return (error);
587 }
588
589
590
591
592
593
594
595
596
597
598
599
600
601 static void
602 gre_compute_route(struct gre_softc *sc)
603 {
604 struct route *ro;
605 u_int32_t a, b, c;
606
607 ro = &sc->route;
608
609 bzero(ro, sizeof(struct route));
610 ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = sc->g_dst;
611 ro->ro_dst.sa_family = AF_INET;
612 ro->ro_dst.sa_len = sizeof(ro->ro_dst);
613
614
615
616
617
618
619
620 if ((sc->sc_if.if_flags & IFF_LINK1) == 0) {
621 a = ntohl(sc->g_dst.s_addr);
622 b = a & 0x01;
623 c = a & 0xfffffffe;
624 b = b ^ 0x01;
625 a = b | c;
626 ((struct sockaddr_in *) &ro->ro_dst)->sin_addr.s_addr = htonl(a);
627 }
628
629 rtalloc(ro);
630 if (ro->ro_rt == 0)
631 return;
632
633
634
635
636
637
638 if (ro->ro_rt->rt_ifp == &sc->sc_if) {
639 RTFREE(ro->ro_rt);
640 ro->ro_rt = (struct rtentry *) 0;
641 return;
642 }
643
644
645
646
647
648 if ((sc->sc_if.if_flags & IFF_LINK1) == 0)
649 ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = sc->g_dst;
650 }
651
652
653
654
655
656 u_int16_t
657 gre_in_cksum(u_int16_t *p, u_int len)
658 {
659 u_int32_t sum = 0;
660 int nwords = len >> 1;
661
662 while (nwords-- != 0)
663 sum += *p++;
664
665 if (len & 1) {
666 union {
667 u_short w;
668 u_char c[2];
669 } u;
670 u.c[0] = *(u_char *) p;
671 u.c[1] = 0;
672 sum += u.w;
673 }
674
675
676 sum = (sum >> 16) + (sum & 0xffff);
677 sum += (sum >> 16);
678 return (~sum);
679 }
680 #endif