1 /*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: src/sys/net/if_gif.c,v 1.4.2.15 2002/11/08 16:57:13 ume Exp $
30 * $KAME: if_gif.c,v 1.87 2001/10/19 08:50:27 itojun Exp $
31 */
32
33 #include "opt_inet.h"
34 #include "opt_inet6.h"
35 #include "opt_xbonehack.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/bus.h>
41 #include <sys/malloc.h>
42 #include <sys/mbuf.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/errno.h>
46 #include <sys/time.h>
47 #include <sys/sysctl.h>
48 #include <sys/syslog.h>
49 #include <sys/protosw.h>
50 #include <sys/conf.h>
51 #include <sys/thread2.h>
52
53 #include <machine/cpu.h>
54
55 #include <net/if.h>
56 #include <net/if_types.h>
57 #include <net/ifq_var.h>
58 #include <net/netisr2.h>
59 #include <net/route.h>
60 #include <net/bpf.h>
61 #include <net/if_clone.h>
62
63 #include <netinet/in.h>
64 #include <netinet/in_systm.h>
65 #include <netinet/ip.h>
66 #ifdef INET
67 #include <netinet/in_var.h>
68 #include <netinet/in_gif.h>
69 #include <netinet/ip_var.h>
70 #endif /* INET */
71
72 #ifdef INET6
73 #ifndef INET
74 #include <netinet/in.h>
75 #endif
76 #include <netinet6/in6_var.h>
77 #include <netinet/ip6.h>
78 #include <netinet6/ip6_var.h>
79 #include <netinet6/in6_gif.h>
80 #include <netinet6/ip6protosw.h>
81 #endif /* INET6 */
82
83 #include <netinet/ip_encap.h>
84 #include "if_gif.h"
85
86 #include <net/net_osdep.h>
87
88 #define GIFNAME "gif"
89
90 #define MTAG_GIF 1709048582 /* mtag cookie for nesting check */
91
92 static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
93 LIST_HEAD(, gif_softc) gif_softc_list;
94
95 int gif_clone_create(struct if_clone *, int, caddr_t, caddr_t);
96 int gif_clone_destroy(struct ifnet *);
97
98 struct if_clone gif_cloner = IF_CLONE_INITIALIZER("gif", gif_clone_create,
99 gif_clone_destroy, 0, IF_MAXUNIT);
100
101 static int gifmodevent(module_t, int, void *);
102 static void gif_clear_cache(struct gif_softc *sc);
103
104 SYSCTL_DECL(_net_link);
105 SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0,
106 "Generic Tunnel Interface");
107
108 #ifndef MAX_GIF_NEST
109 /*
110 * This macro controls the default upper limitation on nesting of gif tunnels.
111 * Since, setting a large value to this macro with a careless configuration
112 * may introduce system crash, we don't allow any nestings by default.
113 * If you need to configure nested gif tunnels, you can define this macro
114 * in your kernel configuration file. However, if you do so, please be
115 * careful to configure the tunnels so that it won't make a loop.
116 */
117 #define MAX_GIF_NEST 1
118 #endif
119 static int max_gif_nesting = MAX_GIF_NEST;
120 SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW,
121 &max_gif_nesting, 0, "Max nested tunnels");
122
123 /*
124 * By default, we disallow creation of multiple tunnels between the same
125 * pair of addresses. Some applications require this functionality so
126 * we allow control over this check here.
127 */
128 #ifdef XBONEHACK
129 static int parallel_tunnels = 1;
130 #else
131 static int parallel_tunnels = 0;
132 #endif
133 SYSCTL_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW,
134 ¶llel_tunnels, 0, "Allow parallel tunnels?");
135
136
137 int
gif_clone_create(struct if_clone * ifc,int unit,caddr_t params __unused,caddr_t data __unused)138 gif_clone_create(struct if_clone *ifc, int unit,
139 caddr_t params __unused, caddr_t data __unused)
140 {
141 struct gif_softc *sc;
142
143 sc = kmalloc (sizeof(struct gif_softc), M_GIF, M_WAITOK | M_ZERO);
144
145 sc->gif_if.if_softc = sc;
146 if_initname(&(sc->gif_if), GIFNAME, unit);
147
148 gifattach0(sc);
149
150 LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
151 return (0);
152 }
153
154 void
gifattach0(struct gif_softc * sc)155 gifattach0(struct gif_softc *sc)
156 {
157
158 sc->encap_cookie4 = sc->encap_cookie6 = NULL;
159
160 sc->gif_if.if_addrlen = 0;
161 sc->gif_if.if_mtu = GIF_MTU;
162 sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
163 #if 0
164 /* turn off ingress filter */
165 sc->gif_if.if_flags |= IFF_LINK2;
166 #endif
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 ifq_set_maxlen(&sc->gif_if.if_snd, IFQ_MAXLEN);
171 if_attach(&sc->gif_if, NULL);
172 bpfattach(&sc->gif_if, DLT_NULL, sizeof(uint32_t));
173 }
174
175 int
gif_clone_destroy(struct ifnet * ifp)176 gif_clone_destroy(struct ifnet *ifp)
177 {
178 struct gif_softc *sc = ifp->if_softc;
179 int err;
180
181 gif_delete_tunnel(&sc->gif_if);
182 LIST_REMOVE(sc, gif_list);
183 #ifdef INET6
184 if (sc->encap_cookie6 != NULL) {
185 err = encap_detach(sc->encap_cookie6);
186 KASSERT(err == 0, ("Unexpected error detaching encap_cookie6"));
187 }
188 #endif
189 #ifdef INET
190 if (sc->encap_cookie4 != NULL) {
191 err = encap_detach(sc->encap_cookie4);
192 KASSERT(err == 0, ("Unexpected error detaching encap_cookie4"));
193 }
194 #endif
195 gif_clear_cache(sc);
196
197 bpfdetach(ifp);
198 if_detach(ifp);
199
200 kfree(sc, M_GIF);
201
202 return 0;
203 }
204
205 static void
gif_clear_cache(struct gif_softc * sc)206 gif_clear_cache(struct gif_softc *sc)
207 {
208 struct rtentry *rt;
209 int n;
210
211 for (n = 0; n < netisr_ncpus; ++n) {
212 rt = sc->gif_ro[n].ro_rt;
213 if (rt != NULL) {
214 KASSERT(rt->rt_cpuid == n,
215 ("inet rt for cpu%d installed on cpu%d slot",
216 rt->rt_cpuid, n));
217 rtfree_async(rt);
218 sc->gif_ro[n].ro_rt = NULL;
219 }
220 #ifdef INET6
221 rt = sc->gif_ro6[n].ro_rt;
222 if (rt != NULL) {
223 KASSERT(rt->rt_cpuid == n,
224 ("inet6 rt for cpu%d installed on cpu%d slot",
225 rt->rt_cpuid, n));
226 rtfree_async(rt);
227 sc->gif_ro6[n].ro_rt = NULL;
228 }
229 #endif
230 }
231 }
232
233 static int
gifmodevent(module_t mod,int type,void * data)234 gifmodevent(module_t mod, int type, void *data)
235 {
236
237 switch (type) {
238 case MOD_LOAD:
239 LIST_INIT(&gif_softc_list);
240 if_clone_attach(&gif_cloner);
241
242 #ifdef INET6
243 ip6_gif_hlim = GIF_HLIM;
244 #endif
245
246 break;
247 case MOD_UNLOAD:
248 if_clone_detach(&gif_cloner);
249
250 while (!LIST_EMPTY(&gif_softc_list))
251 gif_clone_destroy(&LIST_FIRST(&gif_softc_list)->gif_if);
252
253 #ifdef INET6
254 ip6_gif_hlim = 0;
255 #endif
256 break;
257 }
258 return 0;
259 }
260
261 static moduledata_t gif_mod = {
262 "if_gif",
263 gifmodevent,
264 0
265 };
266
267 DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
268
269 int
gif_encapcheck(const struct mbuf * m,int off,int proto,void * arg)270 gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
271 {
272 struct ip ip;
273 struct gif_softc *sc;
274
275 sc = (struct gif_softc *)arg;
276 if (sc == NULL)
277 return 0;
278
279 if ((sc->gif_if.if_flags & IFF_UP) == 0)
280 return 0;
281
282 /* no physical address */
283 if (!sc->gif_psrc || !sc->gif_pdst)
284 return 0;
285
286 switch (proto) {
287 #ifdef INET
288 case IPPROTO_IPV4:
289 break;
290 #endif
291 #ifdef INET6
292 case IPPROTO_IPV6:
293 break;
294 #endif
295 default:
296 return 0;
297 }
298
299 /* Bail on short packets */
300 if (m->m_pkthdr.len < sizeof(ip))
301 return 0;
302
303 m_copydata(m, 0, sizeof(ip), &ip);
304
305 switch (ip.ip_v) {
306 #ifdef INET
307 case 4:
308 if (sc->gif_psrc->sa_family != AF_INET ||
309 sc->gif_pdst->sa_family != AF_INET)
310 return 0;
311 return gif_encapcheck4(m, off, proto, arg);
312 #endif
313 #ifdef INET6
314 case 6:
315 if (m->m_pkthdr.len < sizeof(struct ip6_hdr))
316 return 0;
317 if (sc->gif_psrc->sa_family != AF_INET6 ||
318 sc->gif_pdst->sa_family != AF_INET6)
319 return 0;
320 return gif_encapcheck6(m, off, proto, arg);
321 #endif
322 default:
323 return 0;
324 }
325 }
326
327 /*
328 * Parameters:
329 * rt: added in net2
330 */
331 static int
gif_output_serialized(struct ifnet * ifp,struct mbuf * m,struct sockaddr * dst,struct rtentry * rt)332 gif_output_serialized(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
333 struct rtentry *rt)
334 {
335 struct gif_softc *sc = (struct gif_softc *)ifp;
336 int error = 0;
337
338 error = if_tunnel_check_nesting(ifp, m, MTAG_GIF, max_gif_nesting);
339 if (error != 0) {
340 m_freem(m);
341 goto end;
342 }
343
344 m->m_flags &= ~(M_BCAST|M_MCAST);
345 if (!(ifp->if_flags & IFF_UP) ||
346 sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
347 m_freem(m);
348 error = ENETDOWN;
349 goto end;
350 }
351
352 if (ifp->if_bpf) {
353 bpf_gettoken();
354 if (ifp->if_bpf) {
355 /*
356 * We need to prepend the address family as
357 * a four byte field.
358 */
359 uint32_t af = dst->sa_family;
360
361 bpf_ptap(ifp->if_bpf, m, &af, sizeof(af));
362 }
363 bpf_reltoken();
364 }
365 IFNET_STAT_INC(ifp, opackets, 1);
366 IFNET_STAT_INC(ifp, obytes, m->m_pkthdr.len);
367
368 /* inner AF-specific encapsulation */
369
370 /* XXX should we check if our outer source is legal? */
371
372 /* dispatch to output logic based on outer AF */
373 switch (sc->gif_psrc->sa_family) {
374 #ifdef INET
375 case AF_INET:
376 error = in_gif_output(ifp, dst->sa_family, m);
377 break;
378 #endif
379 #ifdef INET6
380 case AF_INET6:
381 error = in6_gif_output(ifp, dst->sa_family, m);
382 break;
383 #endif
384 default:
385 m_freem(m);
386 error = ENETDOWN;
387 goto end;
388 }
389
390 end:
391 if (error)
392 IFNET_STAT_INC(ifp, oerrors, 1);
393 return error;
394 }
395
396 int
gif_output(struct ifnet * ifp,struct mbuf * m,struct sockaddr * dst,struct rtentry * rt)397 gif_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
398 struct rtentry *rt)
399 {
400 struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd);
401 int error;
402
403 ASSERT_NETISR_NCPUS(mycpuid);
404
405 ifsq_serialize_hw(ifsq);
406 error = gif_output_serialized(ifp, m, dst, rt);
407 ifsq_deserialize_hw(ifsq);
408 return error;
409 }
410
411 void
gif_input(struct mbuf * m,int af,struct ifnet * ifp)412 gif_input(struct mbuf *m, int af, struct ifnet *ifp)
413 {
414 int isr;
415
416 if (ifp == NULL) {
417 /* just in case */
418 m_freem(m);
419 return;
420 }
421
422 m->m_pkthdr.rcvif = ifp;
423
424 if (ifp->if_bpf) {
425 bpf_gettoken();
426 if (ifp->if_bpf) {
427 /*
428 * We need to prepend the address family as
429 * a four byte field.
430 */
431 uint32_t af1 = af;
432
433 bpf_ptap(ifp->if_bpf, m, &af1, sizeof(af1));
434 }
435 bpf_reltoken();
436 }
437
438 /*
439 * Put the packet to the network layer input queue according to the
440 * specified address family.
441 * Note: older versions of gif_input directly called network layer
442 * input functions, e.g. ip6_input, here. We changed the policy to
443 * prevent too many recursive calls of such input functions, which
444 * might cause kernel panic. But the change may introduce another
445 * problem; if the input queue is full, packets are discarded.
446 * The kernel stack overflow really happened, and we believed
447 * queue-full rarely occurs, so we changed the policy.
448 */
449 switch (af) {
450 #ifdef INET
451 case AF_INET:
452 isr = NETISR_IP;
453 break;
454 #endif
455 #ifdef INET6
456 case AF_INET6:
457 isr = NETISR_IPV6;
458 break;
459 #endif
460 default:
461 m_freem(m);
462 return;
463 }
464
465 IFNET_STAT_INC(ifp, ipackets, 1);
466 IFNET_STAT_INC(ifp, ibytes, m->m_pkthdr.len);
467 m->m_flags &= ~M_HASH;
468 netisr_queue(isr, m);
469
470 return;
471 }
472
473 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
474 int
gif_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data,struct ucred * cr)475 gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
476 {
477 struct gif_softc *sc = (struct gif_softc*)ifp;
478 struct ifreq *ifr = (struct ifreq*)data;
479 int error = 0, size;
480 struct sockaddr *dst, *src;
481 #ifdef SIOCSIFMTU /* xxx */
482 u_long mtu;
483 #endif
484
485 switch (cmd) {
486 case SIOCSIFADDR:
487 ifp->if_flags |= IFF_UP;
488 break;
489
490 case SIOCSIFDSTADDR:
491 break;
492
493 case SIOCADDMULTI:
494 case SIOCDELMULTI:
495 break;
496
497 #ifdef SIOCSIFMTU /* xxx */
498 case SIOCGIFMTU:
499 break;
500
501 case SIOCSIFMTU:
502 mtu = ifr->ifr_mtu;
503 if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX)
504 return (EINVAL);
505 ifp->if_mtu = mtu;
506 break;
507 #endif /* SIOCSIFMTU */
508
509 #ifdef INET
510 case SIOCSIFPHYADDR:
511 #endif
512 #ifdef INET6
513 case SIOCSIFPHYADDR_IN6:
514 #endif /* INET6 */
515 case SIOCSLIFPHYADDR:
516 switch (cmd) {
517 #ifdef INET
518 case SIOCSIFPHYADDR:
519 src = (struct sockaddr *)
520 &(((struct in_aliasreq *)data)->ifra_addr);
521 dst = (struct sockaddr *)
522 &(((struct in_aliasreq *)data)->ifra_dstaddr);
523 break;
524 #endif
525 #ifdef INET6
526 case SIOCSIFPHYADDR_IN6:
527 src = (struct sockaddr *)
528 &(((struct in6_aliasreq *)data)->ifra_addr);
529 dst = (struct sockaddr *)
530 &(((struct in6_aliasreq *)data)->ifra_dstaddr);
531 break;
532 #endif
533 case SIOCSLIFPHYADDR:
534 src = (struct sockaddr *)
535 &(((struct if_laddrreq *)data)->addr);
536 dst = (struct sockaddr *)
537 &(((struct if_laddrreq *)data)->dstaddr);
538 break;
539 default:
540 return EINVAL;
541 }
542
543 /* sa_family must be equal */
544 if (src->sa_family != dst->sa_family)
545 return EINVAL;
546
547 /* validate sa_len */
548 switch (src->sa_family) {
549 #ifdef INET
550 case AF_INET:
551 if (src->sa_len != sizeof(struct sockaddr_in))
552 return EINVAL;
553 break;
554 #endif
555 #ifdef INET6
556 case AF_INET6:
557 if (src->sa_len != sizeof(struct sockaddr_in6))
558 return EINVAL;
559 break;
560 #endif
561 default:
562 return EAFNOSUPPORT;
563 }
564 switch (dst->sa_family) {
565 #ifdef INET
566 case AF_INET:
567 if (dst->sa_len != sizeof(struct sockaddr_in))
568 return EINVAL;
569 break;
570 #endif
571 #ifdef INET6
572 case AF_INET6:
573 if (dst->sa_len != sizeof(struct sockaddr_in6))
574 return EINVAL;
575 break;
576 #endif
577 default:
578 return EAFNOSUPPORT;
579 }
580
581 /* check sa_family looks sane for the cmd */
582 switch (cmd) {
583 case SIOCSIFPHYADDR:
584 if (src->sa_family == AF_INET)
585 break;
586 return EAFNOSUPPORT;
587 #ifdef INET6
588 case SIOCSIFPHYADDR_IN6:
589 if (src->sa_family == AF_INET6)
590 break;
591 return EAFNOSUPPORT;
592 #endif /* INET6 */
593 case SIOCSLIFPHYADDR:
594 /* checks done in the above */
595 break;
596 }
597
598 error = gif_set_tunnel(&sc->gif_if, src, dst);
599 break;
600
601 #ifdef SIOCDIFPHYADDR
602 case SIOCDIFPHYADDR:
603 gif_delete_tunnel(&sc->gif_if);
604 break;
605 #endif
606
607 case SIOCGIFPSRCADDR:
608 #ifdef INET6
609 case SIOCGIFPSRCADDR_IN6:
610 #endif /* INET6 */
611 if (sc->gif_psrc == NULL) {
612 error = EADDRNOTAVAIL;
613 goto bad;
614 }
615 src = sc->gif_psrc;
616 switch (cmd) {
617 #ifdef INET
618 case SIOCGIFPSRCADDR:
619 dst = &ifr->ifr_addr;
620 size = sizeof(ifr->ifr_addr);
621 break;
622 #endif /* INET */
623 #ifdef INET6
624 case SIOCGIFPSRCADDR_IN6:
625 dst = (struct sockaddr *)
626 &(((struct in6_ifreq *)data)->ifr_addr);
627 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
628 break;
629 #endif /* INET6 */
630 default:
631 error = EADDRNOTAVAIL;
632 goto bad;
633 }
634 if (src->sa_len > size)
635 return EINVAL;
636 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
637 break;
638
639 case SIOCGIFPDSTADDR:
640 #ifdef INET6
641 case SIOCGIFPDSTADDR_IN6:
642 #endif /* INET6 */
643 if (sc->gif_pdst == NULL) {
644 error = EADDRNOTAVAIL;
645 goto bad;
646 }
647 src = sc->gif_pdst;
648 switch (cmd) {
649 #ifdef INET
650 case SIOCGIFPDSTADDR:
651 dst = &ifr->ifr_addr;
652 size = sizeof(ifr->ifr_addr);
653 break;
654 #endif /* INET */
655 #ifdef INET6
656 case SIOCGIFPDSTADDR_IN6:
657 dst = (struct sockaddr *)
658 &(((struct in6_ifreq *)data)->ifr_addr);
659 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
660 break;
661 #endif /* INET6 */
662 default:
663 error = EADDRNOTAVAIL;
664 goto bad;
665 }
666 if (src->sa_len > size)
667 return EINVAL;
668 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
669 break;
670
671 case SIOCGLIFPHYADDR:
672 if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
673 error = EADDRNOTAVAIL;
674 goto bad;
675 }
676
677 /* copy src */
678 src = sc->gif_psrc;
679 dst = (struct sockaddr *)
680 &(((struct if_laddrreq *)data)->addr);
681 size = sizeof(((struct if_laddrreq *)data)->addr);
682 if (src->sa_len > size)
683 return EINVAL;
684 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
685
686 /* copy dst */
687 src = sc->gif_pdst;
688 dst = (struct sockaddr *)
689 &(((struct if_laddrreq *)data)->dstaddr);
690 size = sizeof(((struct if_laddrreq *)data)->dstaddr);
691 if (src->sa_len > size)
692 return EINVAL;
693 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
694 break;
695
696 case SIOCSIFFLAGS:
697 /* if_ioctl() takes care of it */
698 break;
699
700 default:
701 error = EINVAL;
702 break;
703 }
704 bad:
705 return error;
706 }
707
708 int
gif_set_tunnel(struct ifnet * ifp,struct sockaddr * src,struct sockaddr * dst)709 gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
710 {
711 struct gif_softc *sc = (struct gif_softc *)ifp;
712 struct gif_softc *sc2;
713 struct sockaddr *osrc, *odst, *sa;
714 int error = 0;
715
716 crit_enter();
717
718 LIST_FOREACH(sc2, &gif_softc_list, gif_list) {
719 if (sc2 == sc)
720 continue;
721 if (!sc2->gif_pdst || !sc2->gif_psrc)
722 continue;
723 if (sc2->gif_pdst->sa_family != dst->sa_family ||
724 sc2->gif_pdst->sa_len != dst->sa_len ||
725 sc2->gif_psrc->sa_family != src->sa_family ||
726 sc2->gif_psrc->sa_len != src->sa_len)
727 continue;
728
729 /*
730 * Disallow parallel tunnels unless instructed
731 * otherwise.
732 */
733 if (!parallel_tunnels &&
734 bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
735 bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
736 error = EADDRNOTAVAIL;
737 goto bad;
738 }
739
740 /* XXX both end must be valid? (I mean, not 0.0.0.0) */
741 }
742
743 /* XXX we can detach from both, but be polite just in case */
744 if (sc->gif_psrc) {
745 switch (sc->gif_psrc->sa_family) {
746 #ifdef INET
747 case AF_INET:
748 in_gif_detach(sc);
749 break;
750 #endif
751 #ifdef INET6
752 case AF_INET6:
753 in6_gif_detach(sc);
754 break;
755 #endif
756 }
757 gif_clear_cache(sc);
758 }
759
760 osrc = sc->gif_psrc;
761 sa = (struct sockaddr *)kmalloc(src->sa_len, M_IFADDR, M_WAITOK);
762 bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
763 sc->gif_psrc = sa;
764
765 odst = sc->gif_pdst;
766 sa = (struct sockaddr *)kmalloc(dst->sa_len, M_IFADDR, M_WAITOK);
767 bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
768 sc->gif_pdst = sa;
769
770 switch (sc->gif_psrc->sa_family) {
771 #ifdef INET
772 case AF_INET:
773 error = in_gif_attach(sc);
774 break;
775 #endif
776 #ifdef INET6
777 case AF_INET6:
778 error = in6_gif_attach(sc);
779 break;
780 #endif
781 }
782 if (error) {
783 /* rollback */
784 kfree((caddr_t)sc->gif_psrc, M_IFADDR);
785 kfree((caddr_t)sc->gif_pdst, M_IFADDR);
786 sc->gif_psrc = osrc;
787 sc->gif_pdst = odst;
788 goto bad;
789 }
790
791 if (osrc)
792 kfree((caddr_t)osrc, M_IFADDR);
793 if (odst)
794 kfree((caddr_t)odst, M_IFADDR);
795
796 if (sc->gif_psrc && sc->gif_pdst)
797 ifp->if_flags |= IFF_RUNNING;
798 else
799 ifp->if_flags &= ~IFF_RUNNING;
800 crit_exit();
801
802 return 0;
803
804 bad:
805 if (sc->gif_psrc && sc->gif_pdst)
806 ifp->if_flags |= IFF_RUNNING;
807 else
808 ifp->if_flags &= ~IFF_RUNNING;
809 crit_exit();
810
811 return error;
812 }
813
814 void
gif_delete_tunnel(struct ifnet * ifp)815 gif_delete_tunnel(struct ifnet *ifp)
816 {
817 struct gif_softc *sc = (struct gif_softc *)ifp;
818
819 crit_enter();
820
821 if (sc->gif_psrc) {
822 kfree((caddr_t)sc->gif_psrc, M_IFADDR);
823 sc->gif_psrc = NULL;
824 }
825 if (sc->gif_pdst) {
826 kfree((caddr_t)sc->gif_pdst, M_IFADDR);
827 sc->gif_pdst = NULL;
828 }
829 /* it is safe to detach from both */
830 #ifdef INET
831 in_gif_detach(sc);
832 #endif
833 #ifdef INET6
834 in6_gif_detach(sc);
835 #endif
836 gif_clear_cache(sc);
837
838 if (sc->gif_psrc && sc->gif_pdst)
839 ifp->if_flags |= IFF_RUNNING;
840 else
841 ifp->if_flags &= ~IFF_RUNNING;
842 crit_exit();
843 }
844