if_gif.c revision 1.17 1 /* $NetBSD: if_gif.c,v 1.17 2000/11/19 18:48:45 martin Exp $ */
2 /* $KAME: if_gif.c,v 1.34 2000/10/07 03:58:53 itojun Exp $ */
3
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
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
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.
31 */
32
33 #include "opt_inet.h"
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/mbuf.h>
39 #include <sys/socket.h>
40 #include <sys/sockio.h>
41 #include <sys/errno.h>
42 #include <sys/ioctl.h>
43 #include <sys/time.h>
44 #include <sys/syslog.h>
45 #include <sys/proc.h>
46 #include <sys/protosw.h>
47 #include <machine/cpu.h>
48
49 #include <net/if.h>
50 #include <net/if_types.h>
51 #include <net/netisr.h>
52 #include <net/route.h>
53 #include <net/bpf.h>
54
55 #include <netinet/in.h>
56 #include <netinet/in_systm.h>
57 #include <netinet/ip.h>
58 #ifdef INET
59 #include <netinet/in_var.h>
60 #include <netinet/in_gif.h>
61 #endif /* INET */
62
63 #ifdef INET6
64 #ifndef INET
65 #include <netinet/in.h>
66 #endif
67 #include <netinet6/in6_var.h>
68 #include <netinet/ip6.h>
69 #include <netinet6/ip6_var.h>
70 #include <netinet6/in6_gif.h>
71 #include <netinet6/ip6protosw.h>
72 #endif /* INET6 */
73
74 #include <netinet/ip_encap.h>
75 #include <net/if_gif.h>
76
77 #include "gif.h"
78 #include "bpfilter.h"
79
80 #include <net/net_osdep.h>
81
82 #if NGIF > 0
83
84 void gifattach __P((int));
85 static int gif_encapcheck __P((const struct mbuf *, int, int, void *));
86 #ifdef INET
87 extern struct protosw in_gif_protosw;
88 #endif
89 #ifdef INET6
90 extern struct ip6protosw in6_gif_protosw;
91 #endif
92
93 /*
94 * gif global variable definitions
95 */
96 LIST_HEAD(, gif_softc) gif_softc_list;
97
98 int gif_clone_create __P((struct if_clone *, int));
99 void gif_clone_destroy __P((struct ifnet *));
100
101 struct if_clone gif_cloner =
102 IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy);
103
104 void gif_delete_tunnel __P((struct gif_softc *));
105
106 #ifndef MAX_GIF_NEST
107 /*
108 * This macro controls the upper limitation on nesting of gif tunnels.
109 * Since, setting a large value to this macro with a careless configuration
110 * may introduce system crash, we don't allow any nestings by default.
111 * If you need to configure nested gif tunnels, you can define this macro
112 * in your kernel configuration file. However, if you do so, please be
113 * careful to configure the tunnels so that it won't make a loop.
114 */
115 #define MAX_GIF_NEST 1
116 #endif
117 static int max_gif_nesting = MAX_GIF_NEST;
118
119 /* ARGSUSED */
120 void
121 gifattach(count)
122 int count;
123 {
124
125 LIST_INIT(&gif_softc_list);
126 if_clone_attach(&gif_cloner);
127 }
128
129 int
130 gif_clone_create(ifc, unit)
131 struct if_clone *ifc;
132 int unit;
133 {
134 struct gif_softc *sc;
135
136 sc = malloc(sizeof(struct gif_softc), M_DEVBUF, M_WAIT);
137 bzero(sc, sizeof(struct gif_softc));
138
139 sprintf(sc->gif_if.if_xname, "%s%d", ifc->ifc_name, unit);
140
141 sc->encap_cookie4 = sc->encap_cookie6 = NULL;
142 #ifdef INET
143 sc->encap_cookie4 = encap_attach_func(AF_INET, -1,
144 gif_encapcheck, &in_gif_protosw, sc);
145 if (sc->encap_cookie4 == NULL) {
146 printf("%s: unable to attach encap4\n", if_name(&sc->gif_if));
147 free(sc, M_DEVBUF);
148 return (EIO); /* XXX */
149 }
150 #endif
151 #ifdef INET6
152 sc->encap_cookie6 = encap_attach_func(AF_INET6, -1,
153 gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc);
154 if (sc->encap_cookie6 == NULL) {
155 if (sc->encap_cookie4) {
156 encap_detach(sc->encap_cookie4);
157 sc->encap_cookie4 = NULL;
158 }
159 printf("%s: unable to attach encap6\n", if_name(&sc->gif_if));
160 free(sc, M_DEVBUF);
161 return (EIO); /* XXX */
162 }
163 #endif
164
165 sc->gif_if.if_mtu = GIF_MTU;
166 sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
167 sc->gif_if.if_ioctl = gif_ioctl;
168 sc->gif_if.if_output = gif_output;
169 sc->gif_if.if_type = IFT_GIF;
170 if_attach(&sc->gif_if);
171 #if NBPFILTER > 0
172 #ifdef HAVE_OLD_BPF
173 bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
174 #else
175 bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL, sizeof(u_int));
176 #endif
177 #endif
178 LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
179 return (0);
180 }
181
182 void
183 gif_clone_destroy(ifp)
184 struct ifnet *ifp;
185 {
186 struct gif_softc *sc = (void *) ifp;
187
188 gif_delete_tunnel(sc);
189 LIST_REMOVE(sc, gif_list);
190 #ifdef INET6
191 encap_detach(sc->encap_cookie6);
192 #endif
193 #ifdef INET
194 encap_detach(sc->encap_cookie4);
195 #endif
196
197 #if NBPFILTER > 0
198 bpfdetach(ifp);
199 #endif
200 if_detach(ifp);
201
202 free(sc, M_DEVBUF);
203 }
204
205 static int
206 gif_encapcheck(m, off, proto, arg)
207 const struct mbuf *m;
208 int off;
209 int proto;
210 void *arg;
211 {
212 struct ip ip;
213 struct gif_softc *sc;
214
215 sc = (struct gif_softc *)arg;
216 if (sc == NULL)
217 return 0;
218
219 if ((sc->gif_if.if_flags & IFF_UP) == 0)
220 return 0;
221
222 /* no physical address */
223 if (!sc->gif_psrc || !sc->gif_pdst)
224 return 0;
225
226 switch (proto) {
227 #ifdef INET
228 case IPPROTO_IPV4:
229 break;
230 #endif
231 #ifdef INET6
232 case IPPROTO_IPV6:
233 break;
234 #endif
235 default:
236 return 0;
237 }
238
239 /* LINTED const cast */
240 m_copydata((struct mbuf *)m, 0, sizeof(ip), (caddr_t)&ip);
241
242 switch (ip.ip_v) {
243 #ifdef INET
244 case 4:
245 if (sc->gif_psrc->sa_family != AF_INET ||
246 sc->gif_pdst->sa_family != AF_INET)
247 return 0;
248 return gif_encapcheck4(m, off, proto, arg);
249 #endif
250 #ifdef INET6
251 case 6:
252 if (sc->gif_psrc->sa_family != AF_INET6 ||
253 sc->gif_pdst->sa_family != AF_INET6)
254 return 0;
255 return gif_encapcheck6(m, off, proto, arg);
256 #endif
257 default:
258 return 0;
259 }
260 }
261
262 int
263 gif_output(ifp, m, dst, rt)
264 struct ifnet *ifp;
265 struct mbuf *m;
266 struct sockaddr *dst;
267 struct rtentry *rt; /* added in net2 */
268 {
269 register struct gif_softc *sc = (struct gif_softc*)ifp;
270 int error = 0;
271 static int called = 0; /* XXX: MUTEX */
272
273 /*
274 * gif may cause infinite recursion calls when misconfigured.
275 * We'll prevent this by introducing upper limit.
276 * XXX: this mechanism may introduce another problem about
277 * mutual exclusion of the variable CALLED, especially if we
278 * use kernel thread.
279 */
280 if (++called > max_gif_nesting) {
281 log(LOG_NOTICE,
282 "gif_output: recursively called too many times(%d)\n",
283 called);
284 m_freem(m);
285 error = EIO; /* is there better errno? */
286 goto end;
287 }
288
289 ifp->if_lastchange = time;
290 m->m_flags &= ~(M_BCAST|M_MCAST);
291 if (!(ifp->if_flags & IFF_UP) ||
292 sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
293 m_freem(m);
294 error = ENETDOWN;
295 goto end;
296 }
297
298 #if NBPFILTER > 0
299 if (ifp->if_bpf) {
300 /*
301 * We need to prepend the address family as
302 * a four byte field. Cons up a dummy header
303 * to pacify bpf. This is safe because bpf
304 * will only read from the mbuf (i.e., it won't
305 * try to free it or keep a pointer a to it).
306 */
307 struct mbuf m0;
308 u_int af = dst->sa_family;
309
310 m0.m_next = m;
311 m0.m_len = 4;
312 m0.m_data = (char *)⁡
313
314 #ifdef HAVE_OLD_BPF
315 bpf_mtap(ifp, &m0);
316 #else
317 bpf_mtap(ifp->if_bpf, &m0);
318 #endif
319 }
320 #endif
321 ifp->if_opackets++;
322 ifp->if_obytes += m->m_pkthdr.len;
323
324 /* XXX should we check if our outer source is legal? */
325
326 switch (sc->gif_psrc->sa_family) {
327 #ifdef INET
328 case AF_INET:
329 error = in_gif_output(ifp, dst->sa_family, m, rt);
330 break;
331 #endif
332 #ifdef INET6
333 case AF_INET6:
334 error = in6_gif_output(ifp, dst->sa_family, m, rt);
335 break;
336 #endif
337 default:
338 m_freem(m);
339 error = ENETDOWN;
340 }
341
342 end:
343 called = 0; /* reset recursion counter */
344 if (error) ifp->if_oerrors++;
345 return error;
346 }
347
348 void
349 gif_input(m, af, gifp)
350 struct mbuf *m;
351 int af;
352 struct ifnet *gifp;
353 {
354 int s, isr;
355 register struct ifqueue *ifq = 0;
356
357 if (gifp == NULL) {
358 /* just in case */
359 m_freem(m);
360 return;
361 }
362
363 m->m_pkthdr.rcvif = gifp;
364
365 #if NBPFILTER > 0
366 if (gifp->if_bpf) {
367 /*
368 * We need to prepend the address family as
369 * a four byte field. Cons up a dummy header
370 * to pacify bpf. This is safe because bpf
371 * will only read from the mbuf (i.e., it won't
372 * try to free it or keep a pointer a to it).
373 */
374 struct mbuf m0;
375 u_int af = AF_INET6;
376
377 m0.m_next = m;
378 m0.m_len = 4;
379 m0.m_data = (char *)⁡
380
381 #ifdef HAVE_OLD_BPF
382 bpf_mtap(gifp, &m0);
383 #else
384 bpf_mtap(gifp->if_bpf, &m0);
385 #endif
386 }
387 #endif /*NBPFILTER > 0*/
388
389 /*
390 * Put the packet to the network layer input queue according to the
391 * specified address family.
392 * Note: older versions of gif_input directly called network layer
393 * input functions, e.g. ip6_input, here. We changed the policy to
394 * prevent too many recursive calls of such input functions, which
395 * might cause kernel panic. But the change may introduce another
396 * problem; if the input queue is full, packets are discarded.
397 * We believed it rarely occurs and changed the policy. If we find
398 * it occurs more times than we thought, we may change the policy
399 * again.
400 */
401 switch (af) {
402 #ifdef INET
403 case AF_INET:
404 ifq = &ipintrq;
405 isr = NETISR_IP;
406 break;
407 #endif
408 #ifdef INET6
409 case AF_INET6:
410 ifq = &ip6intrq;
411 isr = NETISR_IPV6;
412 break;
413 #endif
414 default:
415 m_freem(m);
416 return;
417 }
418
419 s = splimp();
420 if (IF_QFULL(ifq)) {
421 IF_DROP(ifq); /* update statistics */
422 m_freem(m);
423 splx(s);
424 return;
425 }
426 IF_ENQUEUE(ifq, m);
427 /* we need schednetisr since the address family may change */
428 schednetisr(isr);
429 gifp->if_ipackets++;
430 gifp->if_ibytes += m->m_pkthdr.len;
431 splx(s);
432
433 return;
434 }
435
436 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
437 int
438 gif_ioctl(ifp, cmd, data)
439 struct ifnet *ifp;
440 u_long cmd;
441 caddr_t data;
442 {
443 struct proc *p = curproc; /* XXX */
444 struct gif_softc *sc = (struct gif_softc*)ifp;
445 struct ifreq *ifr = (struct ifreq*)data;
446 int error = 0, size;
447 struct sockaddr *dst, *src;
448 struct sockaddr *sa;
449 struct gif_softc *sc2;
450
451 switch (cmd) {
452 case SIOCSIFADDR:
453 break;
454
455 case SIOCSIFDSTADDR:
456 break;
457
458 case SIOCADDMULTI:
459 case SIOCDELMULTI:
460 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
461 break;
462 switch (ifr->ifr_addr.sa_family) {
463 #ifdef INET
464 case AF_INET: /* IP supports Multicast */
465 break;
466 #endif /* INET */
467 #ifdef INET6
468 case AF_INET6: /* IP6 supports Multicast */
469 break;
470 #endif /* INET6 */
471 default: /* Other protocols doesn't support Multicast */
472 error = EAFNOSUPPORT;
473 break;
474 }
475 break;
476
477 #ifdef SIOCSIFMTU /* xxx */
478 case SIOCGIFMTU:
479 break;
480
481 case SIOCSIFMTU:
482 {
483 u_long mtu;
484 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
485 break;
486 mtu = ifr->ifr_mtu;
487 if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
488 return (EINVAL);
489 }
490 ifp->if_mtu = mtu;
491 }
492 break;
493 #endif /* SIOCSIFMTU */
494
495 case SIOCSIFPHYADDR:
496 #ifdef INET6
497 case SIOCSIFPHYADDR_IN6:
498 #endif /* INET6 */
499 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
500 break;
501 switch (cmd) {
502 #ifdef INET
503 case SIOCSIFPHYADDR:
504 src = (struct sockaddr *)
505 &(((struct in_aliasreq *)data)->ifra_addr);
506 dst = (struct sockaddr *)
507 &(((struct in_aliasreq *)data)->ifra_dstaddr);
508 if (src->sa_len != sizeof(struct sockaddr_in) ||
509 dst->sa_len != sizeof(struct sockaddr_in))
510 return EINVAL;
511 if (src->sa_family != AF_INET ||
512 dst->sa_family != AF_INET)
513 return EAFNOSUPPORT;
514 break;
515 #endif
516 #ifdef INET6
517 case SIOCSIFPHYADDR_IN6:
518 src = (struct sockaddr *)
519 &(((struct in6_aliasreq *)data)->ifra_addr);
520 dst = (struct sockaddr *)
521 &(((struct in6_aliasreq *)data)->ifra_dstaddr);
522 if (src->sa_len != sizeof(struct sockaddr_in6) ||
523 dst->sa_len != sizeof(struct sockaddr_in6))
524 return EINVAL;
525 if (src->sa_family != AF_INET6 ||
526 dst->sa_family != AF_INET6)
527 return EAFNOSUPPORT;
528 break;
529 #endif
530 }
531
532 for (sc2 = LIST_FIRST(&gif_softc_list); sc2 != NULL;
533 sc2 = LIST_NEXT(sc2, gif_list)) {
534 if (sc2 == sc)
535 continue;
536 if (!sc2->gif_pdst || !sc2->gif_psrc)
537 continue;
538 if (sc2->gif_pdst->sa_family != dst->sa_family ||
539 sc2->gif_pdst->sa_len != dst->sa_len ||
540 sc2->gif_psrc->sa_family != src->sa_family ||
541 sc2->gif_psrc->sa_len != src->sa_len)
542 continue;
543
544 /* can't configure same pair of address onto two gifs */
545 if (bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
546 bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
547 error = EADDRNOTAVAIL;
548 goto bad;
549 }
550
551 /* can't configure multiple multi-dest interfaces */
552 #define multidest(x) \
553 (((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY)
554 #ifdef INET6
555 #define multidest6(x) \
556 (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr))
557 #endif
558 if (dst->sa_family == AF_INET &&
559 multidest(dst) && multidest(sc2->gif_pdst)) {
560 error = EADDRNOTAVAIL;
561 goto bad;
562 }
563 #ifdef INET6
564 if (dst->sa_family == AF_INET6 &&
565 multidest6(dst) && multidest6(sc2->gif_pdst)) {
566 error = EADDRNOTAVAIL;
567 goto bad;
568 }
569 #endif
570 }
571
572 if (src->sa_family != dst->sa_family ||
573 src->sa_len != dst->sa_len) {
574 error = EINVAL;
575 break;
576 }
577 switch (src->sa_family) {
578 #ifdef INET
579 case AF_INET:
580 size = sizeof(struct sockaddr_in);
581 break;
582 #endif
583 #ifdef INET6
584 case AF_INET6:
585 size = sizeof(struct sockaddr_in6);
586 break;
587 #endif
588 default:
589 error = EAFNOSUPPORT;
590 goto bad;
591 }
592 if (src->sa_len != size) {
593 error = EINVAL;
594 break;
595 }
596
597 if (sc->gif_psrc)
598 free((caddr_t)sc->gif_psrc, M_IFADDR);
599 sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK);
600 bcopy((caddr_t)src, (caddr_t)sa, size);
601 sc->gif_psrc = sa;
602
603 if (sc->gif_pdst)
604 free((caddr_t)sc->gif_pdst, M_IFADDR);
605 sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK);
606 bcopy((caddr_t)dst, (caddr_t)sa, size);
607 sc->gif_pdst = sa;
608
609 ifp->if_flags |= IFF_UP;
610 if_up(ifp); /* send up RTM_IFINFO */
611
612 error = 0;
613 break;
614
615 #ifdef SIOCDIFPHYADDR
616 case SIOCDIFPHYADDR:
617 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
618 break;
619 gif_delete_tunnel(sc);
620 break;
621 #endif
622
623 case SIOCGIFPSRCADDR:
624 #ifdef INET6
625 case SIOCGIFPSRCADDR_IN6:
626 #endif /* INET6 */
627 if (sc->gif_psrc == NULL) {
628 error = EADDRNOTAVAIL;
629 goto bad;
630 }
631 src = sc->gif_psrc;
632 switch (cmd) {
633 #ifdef INET
634 case SIOCGIFPSRCADDR:
635 dst = &ifr->ifr_addr;
636 size = sizeof(ifr->ifr_addr);
637 break;
638 #endif /* INET */
639 #ifdef INET6
640 case SIOCGIFPSRCADDR_IN6:
641 dst = (struct sockaddr *)
642 &(((struct in6_ifreq *)data)->ifr_addr);
643 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
644 break;
645 #endif /* INET6 */
646 default:
647 error = EADDRNOTAVAIL;
648 goto bad;
649 }
650 if (src->sa_len > size)
651 return EINVAL;
652 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
653 break;
654
655 case SIOCGIFPDSTADDR:
656 #ifdef INET6
657 case SIOCGIFPDSTADDR_IN6:
658 #endif /* INET6 */
659 if (sc->gif_pdst == NULL) {
660 error = EADDRNOTAVAIL;
661 goto bad;
662 }
663 src = sc->gif_pdst;
664 switch (cmd) {
665 #ifdef INET
666 case SIOCGIFPDSTADDR:
667 dst = &ifr->ifr_addr;
668 size = sizeof(ifr->ifr_addr);
669 break;
670 #endif /* INET */
671 #ifdef INET6
672 case SIOCGIFPDSTADDR_IN6:
673 dst = (struct sockaddr *)
674 &(((struct in6_ifreq *)data)->ifr_addr);
675 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
676 break;
677 #endif /* INET6 */
678 default:
679 error = EADDRNOTAVAIL;
680 goto bad;
681 }
682 if (src->sa_len > size)
683 return EINVAL;
684 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
685 break;
686
687 case SIOCSIFFLAGS:
688 /* if_ioctl() takes care of it */
689 break;
690
691 default:
692 error = EINVAL;
693 break;
694 }
695 bad:
696 return error;
697 }
698
699 void
700 gif_delete_tunnel(sc)
701 struct gif_softc *sc;
702 {
703 int s;
704
705 s = splsoftnet();
706
707 if (sc->gif_psrc) {
708 free((caddr_t)sc->gif_psrc, M_IFADDR);
709 sc->gif_psrc = NULL;
710 }
711 if (sc->gif_pdst) {
712 free((caddr_t)sc->gif_pdst, M_IFADDR);
713 sc->gif_pdst = NULL;
714 }
715 /* change the IFF_UP flag as well? */
716
717 splx(s);
718 }
719 #endif /*NGIF > 0*/
720