This source file includes following definitions.
- gifattach
- gif_clone_create
- gif_clone_destroy
- gif_start
- gif_output
- gif_ioctl
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 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/mbuf.h>
37 #include <sys/socket.h>
38 #include <sys/sockio.h>
39 #include <sys/syslog.h>
40
41 #include <net/if.h>
42 #include <net/if_types.h>
43 #include <net/route.h>
44 #include <net/bpf.h>
45
46 #ifdef INET
47 #include <netinet/in.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/in_var.h>
50 #include <netinet/in_gif.h>
51 #include <netinet/ip.h>
52 #endif
53
54 #ifdef INET6
55 #ifndef INET
56 #include <netinet/in.h>
57 #endif
58 #include <netinet/ip6.h>
59 #include <netinet6/in6_gif.h>
60 #endif
61
62 #include <net/if_gif.h>
63
64 #include "bpfilter.h"
65 #include "bridge.h"
66
67 void gifattach(int);
68 int gif_clone_create(struct if_clone *, int);
69 int gif_clone_destroy(struct ifnet *);
70
71
72
73
74 struct gif_softc_head gif_softc_list;
75 struct if_clone gif_cloner =
76 IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy);
77
78
79 void
80 gifattach(count)
81 int count;
82 {
83 LIST_INIT(&gif_softc_list);
84 if_clone_attach(&gif_cloner);
85 }
86
87 int
88 gif_clone_create(ifc, unit)
89 struct if_clone *ifc;
90 int unit;
91 {
92 struct gif_softc *sc;
93 int s;
94
95 sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
96 if (!sc)
97 return (ENOMEM);
98 bzero(sc, sizeof(*sc));
99
100 snprintf(sc->gif_if.if_xname, sizeof sc->gif_if.if_xname,
101 "%s%d", ifc->ifc_name, unit);
102 sc->gif_if.if_mtu = GIF_MTU;
103 sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
104 sc->gif_if.if_ioctl = gif_ioctl;
105 sc->gif_if.if_start = gif_start;
106 sc->gif_if.if_output = gif_output;
107 sc->gif_if.if_type = IFT_GIF;
108 IFQ_SET_MAXLEN(&sc->gif_if.if_snd, ifqmaxlen);
109 IFQ_SET_READY(&sc->gif_if.if_snd);
110 sc->gif_if.if_softc = sc;
111 if_attach(&sc->gif_if);
112 if_alloc_sadl(&sc->gif_if);
113
114 #if NBPFILTER > 0
115 bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL,
116 sizeof(u_int));
117 #endif
118 s = splnet();
119 LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
120 splx(s);
121
122 return (0);
123 }
124
125 int
126 gif_clone_destroy(ifp)
127 struct ifnet *ifp;
128 {
129 struct gif_softc *sc = ifp->if_softc;
130 int s;
131
132 s = splnet();
133 LIST_REMOVE(sc, gif_list);
134 splx(s);
135
136 if_detach(ifp);
137
138 if (sc->gif_psrc)
139 free((caddr_t)sc->gif_psrc, M_IFADDR);
140 sc->gif_psrc = NULL;
141 if (sc->gif_pdst)
142 free((caddr_t)sc->gif_pdst, M_IFADDR);
143 sc->gif_pdst = NULL;
144 free(sc, M_DEVBUF);
145 return (0);
146 }
147
148 void
149 gif_start(ifp)
150 struct ifnet *ifp;
151 {
152 struct gif_softc *sc = (struct gif_softc*)ifp;
153 struct mbuf *m;
154 struct m_tag *mtag;
155 int family;
156 int s;
157 u_int8_t tp;
158
159
160 if ((ifp->if_flags & (IFF_OACTIVE | IFF_UP)) != IFF_UP ||
161 sc->gif_psrc == NULL || sc->gif_pdst == NULL)
162 return;
163
164
165 #ifdef INET
166 if (sc->gif_psrc->sa_family != AF_INET)
167 #endif
168 #ifdef INET6
169 if (sc->gif_psrc->sa_family != AF_INET6)
170 #endif
171 return;
172
173 s = splnet();
174 ifp->if_flags |= IFF_OACTIVE;
175 splx(s);
176
177 while (1) {
178 s = splnet();
179 IFQ_DEQUEUE(&ifp->if_snd, m);
180 splx(s);
181
182 if (m == NULL)
183 break;
184
185
186
187
188
189 for (mtag = m_tag_find(m, PACKET_TAG_GIF, NULL); mtag;
190 mtag = m_tag_find(m, PACKET_TAG_GIF, mtag)) {
191 if (!bcmp((caddr_t)(mtag + 1), &ifp,
192 sizeof(struct ifnet *))) {
193 IF_DROP(&ifp->if_snd);
194 log(LOG_NOTICE, "gif_output: "
195 "recursively called too many times\n");
196 m_freem(m);
197 break;
198 }
199 }
200 if (mtag)
201 continue;
202
203 mtag = m_tag_get(PACKET_TAG_GIF, sizeof(caddr_t), M_NOWAIT);
204 if (mtag == NULL) {
205 m_freem(m);
206 break;
207 }
208 bcopy(&ifp, mtag + 1, sizeof(caddr_t));
209 m_tag_prepend(m, mtag);
210
211
212
213
214
215 m->m_flags &= ~(M_BCAST|M_MCAST);
216
217
218 family = AF_UNSPEC;
219 tp = *mtod(m, u_int8_t *);
220 tp = (tp >> 4) & 0xff;
221 #ifdef INET
222 if (tp == IPVERSION)
223 family = AF_INET;
224 #endif
225 #ifdef INET6
226 if (tp == (IPV6_VERSION >> 4))
227 family = AF_INET6;
228 #endif
229
230 #if NBRIDGE > 0
231
232
233
234
235 if (ifp->if_bridge && (m->m_flags & M_PROTO1)) {
236 m->m_flags &= ~M_PROTO1;
237 family = AF_LINK;
238 }
239 #endif
240
241 #if NBPFILTER > 0
242 if (ifp->if_bpf)
243 bpf_mtap_af(ifp->if_bpf, family, m, BPF_DIRECTION_OUT);
244 #endif
245 ifp->if_opackets++;
246 ifp->if_obytes += m->m_pkthdr.len;
247
248 switch (sc->gif_psrc->sa_family) {
249 #ifdef INET
250 case AF_INET:
251 in_gif_output(ifp, family, m);
252 break;
253 #endif
254 #ifdef INET6
255 case AF_INET6:
256 in6_gif_output(ifp, family, m);
257 break;
258 #endif
259 default:
260 m_freem(m);
261 break;
262 }
263 }
264
265 ifp->if_flags &= ~IFF_OACTIVE;
266 }
267
268 int
269 gif_output(ifp, m, dst, rt)
270 struct ifnet *ifp;
271 struct mbuf *m;
272 struct sockaddr *dst;
273 struct rtentry *rt;
274 {
275 struct gif_softc *sc = (struct gif_softc*)ifp;
276 int error = 0;
277 int s;
278
279 if (!(ifp->if_flags & IFF_UP) ||
280 sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
281 m_freem(m);
282 error = ENETDOWN;
283 goto end;
284 }
285
286 switch (sc->gif_psrc->sa_family) {
287 #ifdef INET
288 case AF_INET:
289 break;
290 #endif
291 #ifdef INET6
292 case AF_INET6:
293 break;
294 #endif
295 default:
296 m_freem(m);
297 error = ENETDOWN;
298 goto end;
299 }
300
301 s = splnet();
302
303
304
305
306 IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
307 if (error) {
308
309 splx(s);
310 return (error);
311 }
312 if ((ifp->if_flags & IFF_OACTIVE) == 0)
313 (*ifp->if_start)(ifp);
314 splx(s);
315 return (error);
316
317 end:
318 if (error)
319 ifp->if_oerrors++;
320 return (error);
321 }
322
323 int
324 gif_ioctl(ifp, cmd, data)
325 struct ifnet *ifp;
326 u_long cmd;
327 caddr_t data;
328 {
329 struct gif_softc *sc = (struct gif_softc*)ifp;
330 struct ifreq *ifr = (struct ifreq*)data;
331 int error = 0, size;
332 struct sockaddr *dst, *src;
333 struct sockaddr *sa;
334 int s;
335 struct gif_softc *sc2;
336
337 switch (cmd) {
338 case SIOCSIFADDR:
339 break;
340
341 case SIOCSIFDSTADDR:
342 break;
343
344 case SIOCADDMULTI:
345 case SIOCDELMULTI:
346 switch (ifr->ifr_addr.sa_family) {
347 #ifdef INET
348 case AF_INET:
349 break;
350 #endif
351 #ifdef INET6
352 case AF_INET6:
353 break;
354 #endif
355 default:
356 error = EAFNOSUPPORT;
357 break;
358 }
359 break;
360
361 case SIOCSIFPHYADDR:
362 #ifdef INET6
363 case SIOCSIFPHYADDR_IN6:
364 #endif
365 case SIOCSLIFPHYADDR:
366 switch (cmd) {
367 #ifdef INET
368 case SIOCSIFPHYADDR:
369 src = (struct sockaddr *)
370 &(((struct in_aliasreq *)data)->ifra_addr);
371 dst = (struct sockaddr *)
372 &(((struct in_aliasreq *)data)->ifra_dstaddr);
373 break;
374 #endif
375 #ifdef INET6
376 case SIOCSIFPHYADDR_IN6:
377 src = (struct sockaddr *)
378 &(((struct in6_aliasreq *)data)->ifra_addr);
379 dst = (struct sockaddr *)
380 &(((struct in6_aliasreq *)data)->ifra_dstaddr);
381 break;
382 #endif
383 case SIOCSLIFPHYADDR:
384 src = (struct sockaddr *)
385 &(((struct if_laddrreq *)data)->addr);
386 dst = (struct sockaddr *)
387 &(((struct if_laddrreq *)data)->dstaddr);
388 break;
389 default:
390 return (EINVAL);
391 }
392
393
394 if (src->sa_family != dst->sa_family)
395 return (EINVAL);
396
397
398 switch (src->sa_family) {
399 #ifdef INET
400 case AF_INET:
401 if (src->sa_len != sizeof(struct sockaddr_in))
402 return (EINVAL);
403 break;
404 #endif
405 #ifdef INET6
406 case AF_INET6:
407 if (src->sa_len != sizeof(struct sockaddr_in6))
408 return (EINVAL);
409 break;
410 #endif
411 default:
412 return (EAFNOSUPPORT);
413 }
414 switch (dst->sa_family) {
415 #ifdef INET
416 case AF_INET:
417 if (dst->sa_len != sizeof(struct sockaddr_in))
418 return (EINVAL);
419 break;
420 #endif
421 #ifdef INET6
422 case AF_INET6:
423 if (dst->sa_len != sizeof(struct sockaddr_in6))
424 return (EINVAL);
425 break;
426 #endif
427 default:
428 return (EAFNOSUPPORT);
429 }
430
431
432 switch (cmd) {
433 case SIOCSIFPHYADDR:
434 if (src->sa_family == AF_INET)
435 break;
436 return (EAFNOSUPPORT);
437 #ifdef INET6
438 case SIOCSIFPHYADDR_IN6:
439 if (src->sa_family == AF_INET6)
440 break;
441 return (EAFNOSUPPORT);
442 #endif
443 case SIOCSLIFPHYADDR:
444
445 break;
446 }
447
448 LIST_FOREACH(sc2, &gif_softc_list, gif_list) {
449 if (sc2 == sc)
450 continue;
451 if (!sc2->gif_pdst || !sc2->gif_psrc)
452 continue;
453 if (sc2->gif_pdst->sa_family != dst->sa_family ||
454 sc2->gif_pdst->sa_len != dst->sa_len ||
455 sc2->gif_psrc->sa_family != src->sa_family ||
456 sc2->gif_psrc->sa_len != src->sa_len)
457 continue;
458
459 if (bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
460 bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
461 error = EADDRNOTAVAIL;
462 goto bad;
463 }
464
465
466 #define multidest(x) \
467 (((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY)
468 #ifdef INET6
469 #define multidest6(x) \
470 (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr))
471 #endif
472 if (dst->sa_family == AF_INET &&
473 multidest(dst) && multidest(sc2->gif_pdst)) {
474 error = EADDRNOTAVAIL;
475 goto bad;
476 }
477 #ifdef INET6
478 if (dst->sa_family == AF_INET6 &&
479 multidest6(dst) && multidest6(sc2->gif_pdst)) {
480 error = EADDRNOTAVAIL;
481 goto bad;
482 }
483 #endif
484 }
485
486 if (sc->gif_psrc)
487 free((caddr_t)sc->gif_psrc, M_IFADDR);
488 sa = (struct sockaddr *)malloc(src->sa_len, M_IFADDR, M_WAITOK);
489 bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
490 sc->gif_psrc = sa;
491
492 if (sc->gif_pdst)
493 free((caddr_t)sc->gif_pdst, M_IFADDR);
494 sa = (struct sockaddr *)malloc(dst->sa_len, M_IFADDR, M_WAITOK);
495 bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
496 sc->gif_pdst = sa;
497
498 s = splnet();
499 ifp->if_flags |= IFF_RUNNING;
500 if_up(ifp);
501 splx(s);
502
503 error = 0;
504 break;
505
506 #ifdef SIOCDIFPHYADDR
507 case SIOCDIFPHYADDR:
508 if (sc->gif_psrc) {
509 free((caddr_t)sc->gif_psrc, M_IFADDR);
510 sc->gif_psrc = NULL;
511 }
512 if (sc->gif_pdst) {
513 free((caddr_t)sc->gif_pdst, M_IFADDR);
514 sc->gif_pdst = NULL;
515 }
516
517 break;
518 #endif
519
520 case SIOCGIFPSRCADDR:
521 #ifdef INET6
522 case SIOCGIFPSRCADDR_IN6:
523 #endif
524 if (sc->gif_psrc == NULL) {
525 error = EADDRNOTAVAIL;
526 goto bad;
527 }
528 src = sc->gif_psrc;
529 switch (cmd) {
530 #ifdef INET
531 case SIOCGIFPSRCADDR:
532 dst = &ifr->ifr_addr;
533 size = sizeof(ifr->ifr_addr);
534 break;
535 #endif
536 #ifdef INET6
537 case SIOCGIFPSRCADDR_IN6:
538 dst = (struct sockaddr *)
539 &(((struct in6_ifreq *)data)->ifr_addr);
540 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
541 break;
542 #endif
543 default:
544 error = EADDRNOTAVAIL;
545 goto bad;
546 }
547 if (src->sa_len > size)
548 return (EINVAL);
549 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
550 break;
551
552 case SIOCGIFPDSTADDR:
553 #ifdef INET6
554 case SIOCGIFPDSTADDR_IN6:
555 #endif
556 if (sc->gif_pdst == NULL) {
557 error = EADDRNOTAVAIL;
558 goto bad;
559 }
560 src = sc->gif_pdst;
561 switch (cmd) {
562 #ifdef INET
563 case SIOCGIFPDSTADDR:
564 dst = &ifr->ifr_addr;
565 size = sizeof(ifr->ifr_addr);
566 break;
567 #endif
568 #ifdef INET6
569 case SIOCGIFPDSTADDR_IN6:
570 dst = (struct sockaddr *)
571 &(((struct in6_ifreq *)data)->ifr_addr);
572 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
573 break;
574 #endif
575 default:
576 error = EADDRNOTAVAIL;
577 goto bad;
578 }
579 if (src->sa_len > size)
580 return (EINVAL);
581 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
582 break;
583
584 case SIOCGLIFPHYADDR:
585 if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
586 error = EADDRNOTAVAIL;
587 goto bad;
588 }
589
590
591 src = sc->gif_psrc;
592 dst = (struct sockaddr *)
593 &(((struct if_laddrreq *)data)->addr);
594 size = sizeof(((struct if_laddrreq *)data)->addr);
595 if (src->sa_len > size)
596 return (EINVAL);
597 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
598
599
600 src = sc->gif_pdst;
601 dst = (struct sockaddr *)
602 &(((struct if_laddrreq *)data)->dstaddr);
603 size = sizeof(((struct if_laddrreq *)data)->dstaddr);
604 if (src->sa_len > size)
605 return (EINVAL);
606 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
607 break;
608
609 case SIOCSIFFLAGS:
610
611 break;
612
613 case SIOCSIFMTU:
614 if (ifr->ifr_mtu < GIF_MTU_MIN || ifr->ifr_mtu > GIF_MTU_MAX)
615 error = EINVAL;
616 else
617 ifp->if_mtu = ifr->ifr_mtu;
618 break;
619
620 default:
621 error = EINVAL;
622 break;
623 }
624 bad:
625 return (error);
626 }