Deleted Added
full compact
if_gif.c (92081) if_gif.c (92725)
1/* $FreeBSD: head/sys/net/if_gif.c 92081 2002-03-11 09:26:07Z mux $ */
1/* $FreeBSD: head/sys/net/if_gif.c 92725 2002-03-19 21:54:18Z alfred $ */
2/* $KAME: if_gif.c,v 1.47 2001/05/01 05:28:42 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#include "opt_inet6.h"
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/kernel.h>
39#include <sys/malloc.h>
40#include <sys/mbuf.h>
41#include <sys/socket.h>
42#include <sys/sockio.h>
43#include <sys/errno.h>
44#include <sys/time.h>
45#include <sys/sysctl.h>
46#include <sys/syslog.h>
47#include <sys/protosw.h>
48#include <sys/conf.h>
49#include <machine/cpu.h>
50
51#include <net/if.h>
52#include <net/if_types.h>
53#include <net/netisr.h>
54#include <net/route.h>
55#include <net/bpf.h>
56
57#include <netinet/in.h>
58#include <netinet/in_systm.h>
59#include <netinet/ip.h>
60#ifdef INET
61#include <netinet/in_var.h>
62#include <netinet/in_gif.h>
63#include <netinet/ip_var.h>
64#endif /* INET */
65
66#ifdef INET6
67#ifndef INET
68#include <netinet/in.h>
69#endif
70#include <netinet6/in6_var.h>
71#include <netinet/ip6.h>
72#include <netinet6/ip6_var.h>
73#include <netinet6/in6_gif.h>
74#include <netinet6/ip6protosw.h>
75#endif /* INET6 */
76
77#include <netinet/ip_encap.h>
78#include <net/if_gif.h>
79
80#include <net/net_osdep.h>
81
82#define GIFNAME "gif"
83
84static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
85static LIST_HEAD(, gif_softc) gif_softc_list;
86
87void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af);
88void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
89void (*ng_gif_attach_p)(struct ifnet *ifp);
90void (*ng_gif_detach_p)(struct ifnet *ifp);
91
2/* $KAME: if_gif.c,v 1.47 2001/05/01 05:28:42 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#include "opt_inet6.h"
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/kernel.h>
39#include <sys/malloc.h>
40#include <sys/mbuf.h>
41#include <sys/socket.h>
42#include <sys/sockio.h>
43#include <sys/errno.h>
44#include <sys/time.h>
45#include <sys/sysctl.h>
46#include <sys/syslog.h>
47#include <sys/protosw.h>
48#include <sys/conf.h>
49#include <machine/cpu.h>
50
51#include <net/if.h>
52#include <net/if_types.h>
53#include <net/netisr.h>
54#include <net/route.h>
55#include <net/bpf.h>
56
57#include <netinet/in.h>
58#include <netinet/in_systm.h>
59#include <netinet/ip.h>
60#ifdef INET
61#include <netinet/in_var.h>
62#include <netinet/in_gif.h>
63#include <netinet/ip_var.h>
64#endif /* INET */
65
66#ifdef INET6
67#ifndef INET
68#include <netinet/in.h>
69#endif
70#include <netinet6/in6_var.h>
71#include <netinet/ip6.h>
72#include <netinet6/ip6_var.h>
73#include <netinet6/in6_gif.h>
74#include <netinet6/ip6protosw.h>
75#endif /* INET6 */
76
77#include <netinet/ip_encap.h>
78#include <net/if_gif.h>
79
80#include <net/net_osdep.h>
81
82#define GIFNAME "gif"
83
84static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
85static LIST_HEAD(, gif_softc) gif_softc_list;
86
87void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af);
88void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
89void (*ng_gif_attach_p)(struct ifnet *ifp);
90void (*ng_gif_detach_p)(struct ifnet *ifp);
91
92int gif_clone_create __P((struct if_clone *, int));
93int gif_clone_destroy __P((struct ifnet *));
92int gif_clone_create(struct if_clone *, int);
93int gif_clone_destroy(struct ifnet *);
94
95struct if_clone gif_cloner = IF_CLONE_INITIALIZER("gif",
96 gif_clone_create, gif_clone_destroy, IF_MAXUNIT);
97
94
95struct if_clone gif_cloner = IF_CLONE_INITIALIZER("gif",
96 gif_clone_create, gif_clone_destroy, IF_MAXUNIT);
97
98static int gifmodevent __P((module_t, int, void *));
99void gif_delete_tunnel __P((struct gif_softc *));
100static int gif_encapcheck __P((const struct mbuf *, int, int, void *));
98static int gifmodevent(module_t, int, void *);
99void gif_delete_tunnel(struct gif_softc *);
100static int gif_encapcheck(const struct mbuf *, int, int, void *);
101
102#ifdef INET
103extern struct domain inetdomain;
104struct protosw in_gif_protosw =
105{ SOCK_RAW, &inetdomain, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC|PR_ADDR,
106 in_gif_input, (pr_output_t*)rip_output, 0, rip_ctloutput,
107 0,
108 0, 0, 0, 0,
109 &rip_usrreqs
110};
111#endif
112#ifdef INET6
113extern struct domain inet6domain;
114struct ip6protosw in6_gif_protosw =
115{ SOCK_RAW, &inet6domain, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC|PR_ADDR,
116 in6_gif_input, rip6_output, 0, rip6_ctloutput,
117 0,
118 0, 0, 0, 0,
119 &rip6_usrreqs
120};
121#endif
122
123SYSCTL_DECL(_net_link);
124SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0,
125 "Generic Tunnel Interface");
126#ifndef MAX_GIF_NEST
127/*
128 * This macro controls the default upper limitation on nesting of gif tunnels.
129 * Since, setting a large value to this macro with a careless configuration
130 * may introduce system crash, we don't allow any nestings by default.
131 * If you need to configure nested gif tunnels, you can define this macro
132 * in your kernel configuration file. However, if you do so, please be
133 * careful to configure the tunnels so that it won't make a loop.
134 */
135#define MAX_GIF_NEST 1
136#endif
137static int max_gif_nesting = MAX_GIF_NEST;
138SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW,
139 &max_gif_nesting, 0, "Max nested tunnels");
140
141/*
142 * By default, we disallow creation of multiple tunnels between the same
143 * pair of addresses. Some applications require this functionality so
144 * we allow control over this check here.
145 */
146#ifdef XBONEHACK
147static int parallel_tunnels = 1;
148#else
149static int parallel_tunnels = 0;
150#endif
151SYSCTL_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW,
152 &parallel_tunnels, 0, "Allow parallel tunnels?");
153
154int
155gif_clone_create(ifc, unit)
156 struct if_clone *ifc;
157 int unit;
158{
159 struct gif_softc *sc;
160
161 sc = malloc (sizeof(struct gif_softc), M_GIF, M_WAITOK);
162 bzero(sc, sizeof(struct gif_softc));
163
164 sc->gif_if.if_softc = sc;
165 sc->gif_if.if_name = GIFNAME;
166 sc->gif_if.if_unit = unit;
167
168 sc->encap_cookie4 = sc->encap_cookie6 = NULL;
169#ifdef INET
170 sc->encap_cookie4 = encap_attach_func(AF_INET, -1,
171 gif_encapcheck, (struct protosw*)&in_gif_protosw, sc);
172 if (sc->encap_cookie4 == NULL) {
173 printf("%s: unable to attach encap4\n", if_name(&sc->gif_if));
174 free(sc, M_GIF);
175 return (EIO); /* XXX */
176 }
177#endif
178#ifdef INET6
179 sc->encap_cookie6 = encap_attach_func(AF_INET6, -1,
180 gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc);
181 if (sc->encap_cookie6 == NULL) {
182 if (sc->encap_cookie4) {
183 encap_detach(sc->encap_cookie4);
184 sc->encap_cookie4 = NULL;
185 }
186 printf("%s: unable to attach encap6\n", if_name(&sc->gif_if));
187 free(sc, M_GIF);
188 return (EIO); /* XXX */
189 }
190#endif
191
192 sc->gif_if.if_mtu = GIF_MTU;
193 sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
194#if 0
195 /* turn off ingress filter */
196 sc->gif_if.if_flags |= IFF_LINK2;
197#endif
198 sc->gif_if.if_ioctl = gif_ioctl;
199 sc->gif_if.if_output = gif_output;
200 sc->gif_if.if_type = IFT_GIF;
201 sc->gif_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
202 if_attach(&sc->gif_if);
203 bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
204 if (ng_gif_attach_p != NULL)
205 (*ng_gif_attach_p)(&sc->gif_if);
206 LIST_INSERT_HEAD(&gif_softc_list, sc, gif_link);
207 return (0);
208}
209
210int
211gif_clone_destroy(ifp)
212 struct ifnet *ifp;
213{
214 int err;
215 struct gif_softc *sc = ifp->if_softc;
216
217 gif_delete_tunnel(sc);
218 LIST_REMOVE(sc, gif_link);
219 if (sc->encap_cookie4 != NULL) {
220 err = encap_detach(sc->encap_cookie4);
221 KASSERT(err == 0, ("Unexpected error detaching encap_cookie4"));
222 }
223 if (sc->encap_cookie6 != NULL) {
224 err = encap_detach(sc->encap_cookie6);
225 KASSERT(err == 0, ("Unexpected error detaching encap_cookie6"));
226 }
227
228 if (ng_gif_detach_p != NULL)
229 (*ng_gif_detach_p)(ifp);
230 bpfdetach(ifp);
231 if_detach(ifp);
232
233 free(sc, M_GIF);
234 return (0);
235}
236
237static int
238gifmodevent(mod, type, data)
239 module_t mod;
240 int type;
241 void *data;
242{
243
244 switch (type) {
245 case MOD_LOAD:
246 LIST_INIT(&gif_softc_list);
247 if_clone_attach(&gif_cloner);
248
249#ifdef INET6
250 ip6_gif_hlim = GIF_HLIM;
251#endif
252
253 break;
254 case MOD_UNLOAD:
255 if_clone_detach(&gif_cloner);
256
257 while (!LIST_EMPTY(&gif_softc_list))
258 gif_clone_destroy(&LIST_FIRST(&gif_softc_list)->gif_if);
259
260#ifdef INET6
261 ip6_gif_hlim = 0;
262#endif
263 break;
264 }
265 return 0;
266}
267
268static moduledata_t gif_mod = {
269 "if_gif",
270 gifmodevent,
271 0
272};
273
274DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
275MODULE_VERSION(if_gif, 1);
276
277static int
278gif_encapcheck(m, off, proto, arg)
279 const struct mbuf *m;
280 int off;
281 int proto;
282 void *arg;
283{
284 struct ip ip;
285 struct gif_softc *sc;
286
287 sc = (struct gif_softc *)arg;
288 if (sc == NULL)
289 return 0;
290
291 if ((sc->gif_if.if_flags & IFF_UP) == 0)
292 return 0;
293
294 /* no physical address */
295 if (!sc->gif_psrc || !sc->gif_pdst)
296 return 0;
297
298 switch (proto) {
299#ifdef INET
300 case IPPROTO_IPV4:
301 break;
302#endif
303#ifdef INET6
304 case IPPROTO_IPV6:
305 break;
306#endif
307 default:
308 return 0;
309 }
310
311 m_copydata(m, 0, sizeof(ip), (caddr_t)&ip);
312
313 switch (ip.ip_v) {
314#ifdef INET
315 case 4:
316 if (sc->gif_psrc->sa_family != AF_INET ||
317 sc->gif_pdst->sa_family != AF_INET)
318 return 0;
319 return gif_encapcheck4(m, off, proto, arg);
320#endif
321#ifdef INET6
322 case 6:
323 if (sc->gif_psrc->sa_family != AF_INET6 ||
324 sc->gif_pdst->sa_family != AF_INET6)
325 return 0;
326 return gif_encapcheck6(m, off, proto, arg);
327#endif
328 default:
329 return 0;
330 }
331}
332
333int
334gif_output(ifp, m, dst, rt)
335 struct ifnet *ifp;
336 struct mbuf *m;
337 struct sockaddr *dst;
338 struct rtentry *rt; /* added in net2 */
339{
340 struct gif_softc *sc = (struct gif_softc*)ifp;
341 int error = 0;
342 static int called = 0; /* XXX: MUTEX */
343
344 /*
345 * gif may cause infinite recursion calls when misconfigured.
346 * We'll prevent this by introducing upper limit.
347 * XXX: this mechanism may introduce another problem about
348 * mutual exclusion of the variable CALLED, especially if we
349 * use kernel thread.
350 */
351 if (++called > max_gif_nesting) {
352 log(LOG_NOTICE,
353 "gif_output: recursively called too many times(%d)\n",
354 called);
355 m_freem(m);
356 error = EIO; /* is there better errno? */
357 goto end;
358 }
359
360 m->m_flags &= ~(M_BCAST|M_MCAST);
361 if (!(ifp->if_flags & IFF_UP) ||
362 sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
363 m_freem(m);
364 error = ENETDOWN;
365 goto end;
366 }
367
368 if (ifp->if_bpf) {
369 /*
370 * We need to prepend the address family as
371 * a four byte field. Cons up a dummy header
372 * to pacify bpf. This is safe because bpf
373 * will only read from the mbuf (i.e., it won't
374 * try to free it or keep a pointer a to it).
375 */
376 struct mbuf m0;
377 u_int32_t af = dst->sa_family;
378
379 m0.m_next = m;
380 m0.m_len = 4;
381 m0.m_data = (char *)&af;
382
383 bpf_mtap(ifp, &m0);
384 }
385 ifp->if_opackets++;
386 ifp->if_obytes += m->m_pkthdr.len;
387
388 /* inner AF-specific encapsulation */
389
390 /* XXX should we check if our outer source is legal? */
391
392 /* dispatch to output logic based on outer AF */
393 switch (sc->gif_psrc->sa_family) {
394#ifdef INET
395 case AF_INET:
396 error = in_gif_output(ifp, dst->sa_family, m, rt);
397 break;
398#endif
399#ifdef INET6
400 case AF_INET6:
401 error = in6_gif_output(ifp, dst->sa_family, m, rt);
402 break;
403#endif
404 default:
405 m_freem(m);
406 error = ENETDOWN;
407 goto end;
408 }
409
410 end:
411 called = 0; /* reset recursion counter */
412 if (error)
413 ifp->if_oerrors++;
414 return error;
415}
416
417void
418gif_input(m, af, gifp)
419 struct mbuf *m;
420 int af;
421 struct ifnet *gifp;
422{
423 int isr;
424 struct ifqueue *ifq = 0;
425
426 if (gifp == NULL) {
427 /* just in case */
428 m_freem(m);
429 return;
430 }
431
432 m->m_pkthdr.rcvif = gifp;
433
434 if (gifp->if_bpf) {
435 /*
436 * We need to prepend the address family as
437 * a four byte field. Cons up a dummy header
438 * to pacify bpf. This is safe because bpf
439 * will only read from the mbuf (i.e., it won't
440 * try to free it or keep a pointer a to it).
441 */
442 struct mbuf m0;
443 u_int32_t af1 = af;
444
445 m0.m_next = m;
446 m0.m_len = 4;
447 m0.m_data = (char *)&af1;
448
449 bpf_mtap(gifp, &m0);
450 }
451
452 if (ng_gif_input_p != NULL) {
453 (*ng_gif_input_p)(gifp, &m, af);
454 if (m == NULL)
455 return;
456 }
457
458 /*
459 * Put the packet to the network layer input queue according to the
460 * specified address family.
461 * Note: older versions of gif_input directly called network layer
462 * input functions, e.g. ip6_input, here. We changed the policy to
463 * prevent too many recursive calls of such input functions, which
464 * might cause kernel panic. But the change may introduce another
465 * problem; if the input queue is full, packets are discarded.
466 * We believed it rarely occurs and changed the policy. If we find
467 * it occurs more times than we thought, we may change the policy
468 * again.
469 */
470 switch (af) {
471#ifdef INET
472 case AF_INET:
473 ifq = &ipintrq;
474 isr = NETISR_IP;
475 break;
476#endif
477#ifdef INET6
478 case AF_INET6:
479 ifq = &ip6intrq;
480 isr = NETISR_IPV6;
481 break;
482#endif
483 default:
484 if (ng_gif_input_orphan_p != NULL)
485 (*ng_gif_input_orphan_p)(gifp, m, af);
486 else
487 m_freem(m);
488 return;
489 }
490
491 gifp->if_ipackets++;
492 gifp->if_ibytes += m->m_pkthdr.len;
493 (void) IF_HANDOFF(ifq, m, NULL);
494 /* we need schednetisr since the address family may change */
495 schednetisr(isr);
496
497 return;
498}
499
500/* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
501int
502gif_ioctl(ifp, cmd, data)
503 struct ifnet *ifp;
504 u_long cmd;
505 caddr_t data;
506{
507 struct gif_softc *sc = (struct gif_softc*)ifp;
508 struct ifreq *ifr = (struct ifreq*)data;
509 int error = 0, size;
510 struct sockaddr *dst, *src;
511 struct sockaddr *sa;
512 int s;
513 struct ifnet *ifp2;
514 struct gif_softc *sc2;
515
516 switch (cmd) {
517 case SIOCSIFADDR:
518 break;
519
520 case SIOCSIFDSTADDR:
521 break;
522
523 case SIOCADDMULTI:
524 case SIOCDELMULTI:
525 break;
526
527#ifdef SIOCSIFMTU /* xxx */
528 case SIOCGIFMTU:
529 break;
530
531 case SIOCSIFMTU:
532 {
533 u_long mtu;
534 mtu = ifr->ifr_mtu;
535 if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
536 return (EINVAL);
537 }
538 ifp->if_mtu = mtu;
539 }
540 break;
541#endif /* SIOCSIFMTU */
542
543 case SIOCSIFPHYADDR:
544#ifdef INET6
545 case SIOCSIFPHYADDR_IN6:
546#endif /* INET6 */
547 case SIOCSLIFPHYADDR:
548 switch (cmd) {
549#ifdef INET
550 case SIOCSIFPHYADDR:
551 src = (struct sockaddr *)
552 &(((struct in_aliasreq *)data)->ifra_addr);
553 dst = (struct sockaddr *)
554 &(((struct in_aliasreq *)data)->ifra_dstaddr);
555 break;
556#endif
557#ifdef INET6
558 case SIOCSIFPHYADDR_IN6:
559 src = (struct sockaddr *)
560 &(((struct in6_aliasreq *)data)->ifra_addr);
561 dst = (struct sockaddr *)
562 &(((struct in6_aliasreq *)data)->ifra_dstaddr);
563 break;
564#endif
565 case SIOCSLIFPHYADDR:
566 src = (struct sockaddr *)
567 &(((struct if_laddrreq *)data)->addr);
568 dst = (struct sockaddr *)
569 &(((struct if_laddrreq *)data)->dstaddr);
570 default:
571 error = EADDRNOTAVAIL;
572 goto bad;
573 }
574
575 /* sa_family must be equal */
576 if (src->sa_family != dst->sa_family)
577 return EINVAL;
578
579 /* validate sa_len */
580 switch (src->sa_family) {
581#ifdef INET
582 case AF_INET:
583 if (src->sa_len != sizeof(struct sockaddr_in))
584 return EINVAL;
585 break;
586#endif
587#ifdef INET6
588 case AF_INET6:
589 if (src->sa_len != sizeof(struct sockaddr_in6))
590 return EINVAL;
591 break;
592#endif
593 default:
594 return EAFNOSUPPORT;
595 }
596 switch (dst->sa_family) {
597#ifdef INET
598 case AF_INET:
599 if (dst->sa_len != sizeof(struct sockaddr_in))
600 return EINVAL;
601 break;
602#endif
603#ifdef INET6
604 case AF_INET6:
605 if (dst->sa_len != sizeof(struct sockaddr_in6))
606 return EINVAL;
607 break;
608#endif
609 default:
610 return EAFNOSUPPORT;
611 }
612
613 /* check sa_family looks sane for the cmd */
614 switch (cmd) {
615 case SIOCSIFPHYADDR:
616 if (src->sa_family == AF_INET)
617 break;
618 return EAFNOSUPPORT;
619#ifdef INET6
620 case SIOCSIFPHYADDR_IN6:
621 if (src->sa_family == AF_INET6)
622 break;
623 return EAFNOSUPPORT;
624#endif /* INET6 */
625 case SIOCSLIFPHYADDR:
626 /* checks done in the above */
627 break;
628 }
629
630 TAILQ_FOREACH(ifp2, &ifnet, if_link) {
631 if (strcmp(ifp2->if_name, GIFNAME) != 0)
632 continue;
633 sc2 = ifp2->if_softc;
634 if (sc2 == sc)
635 continue;
636 if (!sc2->gif_pdst || !sc2->gif_psrc)
637 continue;
638 if (sc2->gif_pdst->sa_family != dst->sa_family ||
639 sc2->gif_pdst->sa_len != dst->sa_len ||
640 sc2->gif_psrc->sa_family != src->sa_family ||
641 sc2->gif_psrc->sa_len != src->sa_len)
642 continue;
643
644 /*
645 * Disallow parallel tunnels unless instructed
646 * otherwise.
647 */
648 if (!parallel_tunnels &&
649 bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
650 bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
651 error = EADDRNOTAVAIL;
652 goto bad;
653 }
654
655 /* can't configure multiple multi-dest interfaces */
656#define multidest(x) \
657 (((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY)
658#ifdef INET6
659#define multidest6(x) \
660 (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr))
661#endif
662 if (dst->sa_family == AF_INET &&
663 multidest(dst) && multidest(sc2->gif_pdst)) {
664 error = EADDRNOTAVAIL;
665 goto bad;
666 }
667#ifdef INET6
668 if (dst->sa_family == AF_INET6 &&
669 multidest6(dst) && multidest6(sc2->gif_pdst)) {
670 error = EADDRNOTAVAIL;
671 goto bad;
672 }
673#endif
674 }
675
676 if (sc->gif_psrc)
677 free((caddr_t)sc->gif_psrc, M_IFADDR);
678 sa = (struct sockaddr *)malloc(src->sa_len, M_IFADDR, M_WAITOK);
679 bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
680 sc->gif_psrc = sa;
681
682 if (sc->gif_pdst)
683 free((caddr_t)sc->gif_pdst, M_IFADDR);
684 sa = (struct sockaddr *)malloc(dst->sa_len, M_IFADDR, M_WAITOK);
685 bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
686 sc->gif_pdst = sa;
687
688 ifp->if_flags |= IFF_RUNNING;
689 s = splimp();
690 if_up(ifp); /* mark interface UP and send up RTM_IFINFO */
691 splx(s);
692
693 error = 0;
694 break;
695
696#ifdef SIOCDIFPHYADDR
697 case SIOCDIFPHYADDR:
698 if (sc->gif_psrc) {
699 free((caddr_t)sc->gif_psrc, M_IFADDR);
700 sc->gif_psrc = NULL;
701 }
702 if (sc->gif_pdst) {
703 free((caddr_t)sc->gif_pdst, M_IFADDR);
704 sc->gif_pdst = NULL;
705 }
706 /* change the IFF_{UP, RUNNING} flag as well? */
707 break;
708#endif
709
710 case SIOCGIFPSRCADDR:
711#ifdef INET6
712 case SIOCGIFPSRCADDR_IN6:
713#endif /* INET6 */
714 if (sc->gif_psrc == NULL) {
715 error = EADDRNOTAVAIL;
716 goto bad;
717 }
718 src = sc->gif_psrc;
719 switch (cmd) {
720#ifdef INET
721 case SIOCGIFPSRCADDR:
722 dst = &ifr->ifr_addr;
723 size = sizeof(ifr->ifr_addr);
724 break;
725#endif /* INET */
726#ifdef INET6
727 case SIOCGIFPSRCADDR_IN6:
728 dst = (struct sockaddr *)
729 &(((struct in6_ifreq *)data)->ifr_addr);
730 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
731 break;
732#endif /* INET6 */
733 default:
734 error = EADDRNOTAVAIL;
735 goto bad;
736 }
737 if (src->sa_len > size)
738 return EINVAL;
739 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
740 break;
741
742 case SIOCGIFPDSTADDR:
743#ifdef INET6
744 case SIOCGIFPDSTADDR_IN6:
745#endif /* INET6 */
746 if (sc->gif_pdst == NULL) {
747 error = EADDRNOTAVAIL;
748 goto bad;
749 }
750 src = sc->gif_pdst;
751 switch (cmd) {
752#ifdef INET
753 case SIOCGIFPDSTADDR:
754 dst = &ifr->ifr_addr;
755 size = sizeof(ifr->ifr_addr);
756 break;
757#endif /* INET */
758#ifdef INET6
759 case SIOCGIFPDSTADDR_IN6:
760 dst = (struct sockaddr *)
761 &(((struct in6_ifreq *)data)->ifr_addr);
762 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
763 break;
764#endif /* INET6 */
765 default:
766 error = EADDRNOTAVAIL;
767 goto bad;
768 }
769 if (src->sa_len > size)
770 return EINVAL;
771 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
772 break;
773
774 case SIOCGLIFPHYADDR:
775 if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
776 error = EADDRNOTAVAIL;
777 goto bad;
778 }
779
780 /* copy src */
781 src = sc->gif_psrc;
782 dst = (struct sockaddr *)
783 &(((struct if_laddrreq *)data)->addr);
784 size = sizeof(((struct if_laddrreq *)data)->addr);
785 if (src->sa_len > size)
786 return EINVAL;
787 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
788
789 /* copy dst */
790 src = sc->gif_pdst;
791 dst = (struct sockaddr *)
792 &(((struct if_laddrreq *)data)->dstaddr);
793 size = sizeof(((struct if_laddrreq *)data)->dstaddr);
794 if (src->sa_len > size)
795 return EINVAL;
796 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
797 break;
798
799 case SIOCSIFFLAGS:
800 /* if_ioctl() takes care of it */
801 break;
802
803 default:
804 error = EINVAL;
805 break;
806 }
807 bad:
808 return error;
809}
810
811void
812gif_delete_tunnel(sc)
813 struct gif_softc *sc;
814{
815 /* XXX: NetBSD protects this function with splsoftnet() */
816
817 if (sc->gif_psrc) {
818 free((caddr_t)sc->gif_psrc, M_IFADDR);
819 sc->gif_psrc = NULL;
820 }
821 if (sc->gif_pdst) {
822 free((caddr_t)sc->gif_pdst, M_IFADDR);
823 sc->gif_pdst = NULL;
824 }
825 /* change the IFF_UP flag as well? */
826}
101
102#ifdef INET
103extern struct domain inetdomain;
104struct protosw in_gif_protosw =
105{ SOCK_RAW, &inetdomain, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC|PR_ADDR,
106 in_gif_input, (pr_output_t*)rip_output, 0, rip_ctloutput,
107 0,
108 0, 0, 0, 0,
109 &rip_usrreqs
110};
111#endif
112#ifdef INET6
113extern struct domain inet6domain;
114struct ip6protosw in6_gif_protosw =
115{ SOCK_RAW, &inet6domain, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC|PR_ADDR,
116 in6_gif_input, rip6_output, 0, rip6_ctloutput,
117 0,
118 0, 0, 0, 0,
119 &rip6_usrreqs
120};
121#endif
122
123SYSCTL_DECL(_net_link);
124SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0,
125 "Generic Tunnel Interface");
126#ifndef MAX_GIF_NEST
127/*
128 * This macro controls the default upper limitation on nesting of gif tunnels.
129 * Since, setting a large value to this macro with a careless configuration
130 * may introduce system crash, we don't allow any nestings by default.
131 * If you need to configure nested gif tunnels, you can define this macro
132 * in your kernel configuration file. However, if you do so, please be
133 * careful to configure the tunnels so that it won't make a loop.
134 */
135#define MAX_GIF_NEST 1
136#endif
137static int max_gif_nesting = MAX_GIF_NEST;
138SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW,
139 &max_gif_nesting, 0, "Max nested tunnels");
140
141/*
142 * By default, we disallow creation of multiple tunnels between the same
143 * pair of addresses. Some applications require this functionality so
144 * we allow control over this check here.
145 */
146#ifdef XBONEHACK
147static int parallel_tunnels = 1;
148#else
149static int parallel_tunnels = 0;
150#endif
151SYSCTL_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW,
152 &parallel_tunnels, 0, "Allow parallel tunnels?");
153
154int
155gif_clone_create(ifc, unit)
156 struct if_clone *ifc;
157 int unit;
158{
159 struct gif_softc *sc;
160
161 sc = malloc (sizeof(struct gif_softc), M_GIF, M_WAITOK);
162 bzero(sc, sizeof(struct gif_softc));
163
164 sc->gif_if.if_softc = sc;
165 sc->gif_if.if_name = GIFNAME;
166 sc->gif_if.if_unit = unit;
167
168 sc->encap_cookie4 = sc->encap_cookie6 = NULL;
169#ifdef INET
170 sc->encap_cookie4 = encap_attach_func(AF_INET, -1,
171 gif_encapcheck, (struct protosw*)&in_gif_protosw, sc);
172 if (sc->encap_cookie4 == NULL) {
173 printf("%s: unable to attach encap4\n", if_name(&sc->gif_if));
174 free(sc, M_GIF);
175 return (EIO); /* XXX */
176 }
177#endif
178#ifdef INET6
179 sc->encap_cookie6 = encap_attach_func(AF_INET6, -1,
180 gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc);
181 if (sc->encap_cookie6 == NULL) {
182 if (sc->encap_cookie4) {
183 encap_detach(sc->encap_cookie4);
184 sc->encap_cookie4 = NULL;
185 }
186 printf("%s: unable to attach encap6\n", if_name(&sc->gif_if));
187 free(sc, M_GIF);
188 return (EIO); /* XXX */
189 }
190#endif
191
192 sc->gif_if.if_mtu = GIF_MTU;
193 sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
194#if 0
195 /* turn off ingress filter */
196 sc->gif_if.if_flags |= IFF_LINK2;
197#endif
198 sc->gif_if.if_ioctl = gif_ioctl;
199 sc->gif_if.if_output = gif_output;
200 sc->gif_if.if_type = IFT_GIF;
201 sc->gif_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
202 if_attach(&sc->gif_if);
203 bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
204 if (ng_gif_attach_p != NULL)
205 (*ng_gif_attach_p)(&sc->gif_if);
206 LIST_INSERT_HEAD(&gif_softc_list, sc, gif_link);
207 return (0);
208}
209
210int
211gif_clone_destroy(ifp)
212 struct ifnet *ifp;
213{
214 int err;
215 struct gif_softc *sc = ifp->if_softc;
216
217 gif_delete_tunnel(sc);
218 LIST_REMOVE(sc, gif_link);
219 if (sc->encap_cookie4 != NULL) {
220 err = encap_detach(sc->encap_cookie4);
221 KASSERT(err == 0, ("Unexpected error detaching encap_cookie4"));
222 }
223 if (sc->encap_cookie6 != NULL) {
224 err = encap_detach(sc->encap_cookie6);
225 KASSERT(err == 0, ("Unexpected error detaching encap_cookie6"));
226 }
227
228 if (ng_gif_detach_p != NULL)
229 (*ng_gif_detach_p)(ifp);
230 bpfdetach(ifp);
231 if_detach(ifp);
232
233 free(sc, M_GIF);
234 return (0);
235}
236
237static int
238gifmodevent(mod, type, data)
239 module_t mod;
240 int type;
241 void *data;
242{
243
244 switch (type) {
245 case MOD_LOAD:
246 LIST_INIT(&gif_softc_list);
247 if_clone_attach(&gif_cloner);
248
249#ifdef INET6
250 ip6_gif_hlim = GIF_HLIM;
251#endif
252
253 break;
254 case MOD_UNLOAD:
255 if_clone_detach(&gif_cloner);
256
257 while (!LIST_EMPTY(&gif_softc_list))
258 gif_clone_destroy(&LIST_FIRST(&gif_softc_list)->gif_if);
259
260#ifdef INET6
261 ip6_gif_hlim = 0;
262#endif
263 break;
264 }
265 return 0;
266}
267
268static moduledata_t gif_mod = {
269 "if_gif",
270 gifmodevent,
271 0
272};
273
274DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
275MODULE_VERSION(if_gif, 1);
276
277static int
278gif_encapcheck(m, off, proto, arg)
279 const struct mbuf *m;
280 int off;
281 int proto;
282 void *arg;
283{
284 struct ip ip;
285 struct gif_softc *sc;
286
287 sc = (struct gif_softc *)arg;
288 if (sc == NULL)
289 return 0;
290
291 if ((sc->gif_if.if_flags & IFF_UP) == 0)
292 return 0;
293
294 /* no physical address */
295 if (!sc->gif_psrc || !sc->gif_pdst)
296 return 0;
297
298 switch (proto) {
299#ifdef INET
300 case IPPROTO_IPV4:
301 break;
302#endif
303#ifdef INET6
304 case IPPROTO_IPV6:
305 break;
306#endif
307 default:
308 return 0;
309 }
310
311 m_copydata(m, 0, sizeof(ip), (caddr_t)&ip);
312
313 switch (ip.ip_v) {
314#ifdef INET
315 case 4:
316 if (sc->gif_psrc->sa_family != AF_INET ||
317 sc->gif_pdst->sa_family != AF_INET)
318 return 0;
319 return gif_encapcheck4(m, off, proto, arg);
320#endif
321#ifdef INET6
322 case 6:
323 if (sc->gif_psrc->sa_family != AF_INET6 ||
324 sc->gif_pdst->sa_family != AF_INET6)
325 return 0;
326 return gif_encapcheck6(m, off, proto, arg);
327#endif
328 default:
329 return 0;
330 }
331}
332
333int
334gif_output(ifp, m, dst, rt)
335 struct ifnet *ifp;
336 struct mbuf *m;
337 struct sockaddr *dst;
338 struct rtentry *rt; /* added in net2 */
339{
340 struct gif_softc *sc = (struct gif_softc*)ifp;
341 int error = 0;
342 static int called = 0; /* XXX: MUTEX */
343
344 /*
345 * gif may cause infinite recursion calls when misconfigured.
346 * We'll prevent this by introducing upper limit.
347 * XXX: this mechanism may introduce another problem about
348 * mutual exclusion of the variable CALLED, especially if we
349 * use kernel thread.
350 */
351 if (++called > max_gif_nesting) {
352 log(LOG_NOTICE,
353 "gif_output: recursively called too many times(%d)\n",
354 called);
355 m_freem(m);
356 error = EIO; /* is there better errno? */
357 goto end;
358 }
359
360 m->m_flags &= ~(M_BCAST|M_MCAST);
361 if (!(ifp->if_flags & IFF_UP) ||
362 sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
363 m_freem(m);
364 error = ENETDOWN;
365 goto end;
366 }
367
368 if (ifp->if_bpf) {
369 /*
370 * We need to prepend the address family as
371 * a four byte field. Cons up a dummy header
372 * to pacify bpf. This is safe because bpf
373 * will only read from the mbuf (i.e., it won't
374 * try to free it or keep a pointer a to it).
375 */
376 struct mbuf m0;
377 u_int32_t af = dst->sa_family;
378
379 m0.m_next = m;
380 m0.m_len = 4;
381 m0.m_data = (char *)&af;
382
383 bpf_mtap(ifp, &m0);
384 }
385 ifp->if_opackets++;
386 ifp->if_obytes += m->m_pkthdr.len;
387
388 /* inner AF-specific encapsulation */
389
390 /* XXX should we check if our outer source is legal? */
391
392 /* dispatch to output logic based on outer AF */
393 switch (sc->gif_psrc->sa_family) {
394#ifdef INET
395 case AF_INET:
396 error = in_gif_output(ifp, dst->sa_family, m, rt);
397 break;
398#endif
399#ifdef INET6
400 case AF_INET6:
401 error = in6_gif_output(ifp, dst->sa_family, m, rt);
402 break;
403#endif
404 default:
405 m_freem(m);
406 error = ENETDOWN;
407 goto end;
408 }
409
410 end:
411 called = 0; /* reset recursion counter */
412 if (error)
413 ifp->if_oerrors++;
414 return error;
415}
416
417void
418gif_input(m, af, gifp)
419 struct mbuf *m;
420 int af;
421 struct ifnet *gifp;
422{
423 int isr;
424 struct ifqueue *ifq = 0;
425
426 if (gifp == NULL) {
427 /* just in case */
428 m_freem(m);
429 return;
430 }
431
432 m->m_pkthdr.rcvif = gifp;
433
434 if (gifp->if_bpf) {
435 /*
436 * We need to prepend the address family as
437 * a four byte field. Cons up a dummy header
438 * to pacify bpf. This is safe because bpf
439 * will only read from the mbuf (i.e., it won't
440 * try to free it or keep a pointer a to it).
441 */
442 struct mbuf m0;
443 u_int32_t af1 = af;
444
445 m0.m_next = m;
446 m0.m_len = 4;
447 m0.m_data = (char *)&af1;
448
449 bpf_mtap(gifp, &m0);
450 }
451
452 if (ng_gif_input_p != NULL) {
453 (*ng_gif_input_p)(gifp, &m, af);
454 if (m == NULL)
455 return;
456 }
457
458 /*
459 * Put the packet to the network layer input queue according to the
460 * specified address family.
461 * Note: older versions of gif_input directly called network layer
462 * input functions, e.g. ip6_input, here. We changed the policy to
463 * prevent too many recursive calls of such input functions, which
464 * might cause kernel panic. But the change may introduce another
465 * problem; if the input queue is full, packets are discarded.
466 * We believed it rarely occurs and changed the policy. If we find
467 * it occurs more times than we thought, we may change the policy
468 * again.
469 */
470 switch (af) {
471#ifdef INET
472 case AF_INET:
473 ifq = &ipintrq;
474 isr = NETISR_IP;
475 break;
476#endif
477#ifdef INET6
478 case AF_INET6:
479 ifq = &ip6intrq;
480 isr = NETISR_IPV6;
481 break;
482#endif
483 default:
484 if (ng_gif_input_orphan_p != NULL)
485 (*ng_gif_input_orphan_p)(gifp, m, af);
486 else
487 m_freem(m);
488 return;
489 }
490
491 gifp->if_ipackets++;
492 gifp->if_ibytes += m->m_pkthdr.len;
493 (void) IF_HANDOFF(ifq, m, NULL);
494 /* we need schednetisr since the address family may change */
495 schednetisr(isr);
496
497 return;
498}
499
500/* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
501int
502gif_ioctl(ifp, cmd, data)
503 struct ifnet *ifp;
504 u_long cmd;
505 caddr_t data;
506{
507 struct gif_softc *sc = (struct gif_softc*)ifp;
508 struct ifreq *ifr = (struct ifreq*)data;
509 int error = 0, size;
510 struct sockaddr *dst, *src;
511 struct sockaddr *sa;
512 int s;
513 struct ifnet *ifp2;
514 struct gif_softc *sc2;
515
516 switch (cmd) {
517 case SIOCSIFADDR:
518 break;
519
520 case SIOCSIFDSTADDR:
521 break;
522
523 case SIOCADDMULTI:
524 case SIOCDELMULTI:
525 break;
526
527#ifdef SIOCSIFMTU /* xxx */
528 case SIOCGIFMTU:
529 break;
530
531 case SIOCSIFMTU:
532 {
533 u_long mtu;
534 mtu = ifr->ifr_mtu;
535 if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
536 return (EINVAL);
537 }
538 ifp->if_mtu = mtu;
539 }
540 break;
541#endif /* SIOCSIFMTU */
542
543 case SIOCSIFPHYADDR:
544#ifdef INET6
545 case SIOCSIFPHYADDR_IN6:
546#endif /* INET6 */
547 case SIOCSLIFPHYADDR:
548 switch (cmd) {
549#ifdef INET
550 case SIOCSIFPHYADDR:
551 src = (struct sockaddr *)
552 &(((struct in_aliasreq *)data)->ifra_addr);
553 dst = (struct sockaddr *)
554 &(((struct in_aliasreq *)data)->ifra_dstaddr);
555 break;
556#endif
557#ifdef INET6
558 case SIOCSIFPHYADDR_IN6:
559 src = (struct sockaddr *)
560 &(((struct in6_aliasreq *)data)->ifra_addr);
561 dst = (struct sockaddr *)
562 &(((struct in6_aliasreq *)data)->ifra_dstaddr);
563 break;
564#endif
565 case SIOCSLIFPHYADDR:
566 src = (struct sockaddr *)
567 &(((struct if_laddrreq *)data)->addr);
568 dst = (struct sockaddr *)
569 &(((struct if_laddrreq *)data)->dstaddr);
570 default:
571 error = EADDRNOTAVAIL;
572 goto bad;
573 }
574
575 /* sa_family must be equal */
576 if (src->sa_family != dst->sa_family)
577 return EINVAL;
578
579 /* validate sa_len */
580 switch (src->sa_family) {
581#ifdef INET
582 case AF_INET:
583 if (src->sa_len != sizeof(struct sockaddr_in))
584 return EINVAL;
585 break;
586#endif
587#ifdef INET6
588 case AF_INET6:
589 if (src->sa_len != sizeof(struct sockaddr_in6))
590 return EINVAL;
591 break;
592#endif
593 default:
594 return EAFNOSUPPORT;
595 }
596 switch (dst->sa_family) {
597#ifdef INET
598 case AF_INET:
599 if (dst->sa_len != sizeof(struct sockaddr_in))
600 return EINVAL;
601 break;
602#endif
603#ifdef INET6
604 case AF_INET6:
605 if (dst->sa_len != sizeof(struct sockaddr_in6))
606 return EINVAL;
607 break;
608#endif
609 default:
610 return EAFNOSUPPORT;
611 }
612
613 /* check sa_family looks sane for the cmd */
614 switch (cmd) {
615 case SIOCSIFPHYADDR:
616 if (src->sa_family == AF_INET)
617 break;
618 return EAFNOSUPPORT;
619#ifdef INET6
620 case SIOCSIFPHYADDR_IN6:
621 if (src->sa_family == AF_INET6)
622 break;
623 return EAFNOSUPPORT;
624#endif /* INET6 */
625 case SIOCSLIFPHYADDR:
626 /* checks done in the above */
627 break;
628 }
629
630 TAILQ_FOREACH(ifp2, &ifnet, if_link) {
631 if (strcmp(ifp2->if_name, GIFNAME) != 0)
632 continue;
633 sc2 = ifp2->if_softc;
634 if (sc2 == sc)
635 continue;
636 if (!sc2->gif_pdst || !sc2->gif_psrc)
637 continue;
638 if (sc2->gif_pdst->sa_family != dst->sa_family ||
639 sc2->gif_pdst->sa_len != dst->sa_len ||
640 sc2->gif_psrc->sa_family != src->sa_family ||
641 sc2->gif_psrc->sa_len != src->sa_len)
642 continue;
643
644 /*
645 * Disallow parallel tunnels unless instructed
646 * otherwise.
647 */
648 if (!parallel_tunnels &&
649 bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
650 bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
651 error = EADDRNOTAVAIL;
652 goto bad;
653 }
654
655 /* can't configure multiple multi-dest interfaces */
656#define multidest(x) \
657 (((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY)
658#ifdef INET6
659#define multidest6(x) \
660 (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr))
661#endif
662 if (dst->sa_family == AF_INET &&
663 multidest(dst) && multidest(sc2->gif_pdst)) {
664 error = EADDRNOTAVAIL;
665 goto bad;
666 }
667#ifdef INET6
668 if (dst->sa_family == AF_INET6 &&
669 multidest6(dst) && multidest6(sc2->gif_pdst)) {
670 error = EADDRNOTAVAIL;
671 goto bad;
672 }
673#endif
674 }
675
676 if (sc->gif_psrc)
677 free((caddr_t)sc->gif_psrc, M_IFADDR);
678 sa = (struct sockaddr *)malloc(src->sa_len, M_IFADDR, M_WAITOK);
679 bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
680 sc->gif_psrc = sa;
681
682 if (sc->gif_pdst)
683 free((caddr_t)sc->gif_pdst, M_IFADDR);
684 sa = (struct sockaddr *)malloc(dst->sa_len, M_IFADDR, M_WAITOK);
685 bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
686 sc->gif_pdst = sa;
687
688 ifp->if_flags |= IFF_RUNNING;
689 s = splimp();
690 if_up(ifp); /* mark interface UP and send up RTM_IFINFO */
691 splx(s);
692
693 error = 0;
694 break;
695
696#ifdef SIOCDIFPHYADDR
697 case SIOCDIFPHYADDR:
698 if (sc->gif_psrc) {
699 free((caddr_t)sc->gif_psrc, M_IFADDR);
700 sc->gif_psrc = NULL;
701 }
702 if (sc->gif_pdst) {
703 free((caddr_t)sc->gif_pdst, M_IFADDR);
704 sc->gif_pdst = NULL;
705 }
706 /* change the IFF_{UP, RUNNING} flag as well? */
707 break;
708#endif
709
710 case SIOCGIFPSRCADDR:
711#ifdef INET6
712 case SIOCGIFPSRCADDR_IN6:
713#endif /* INET6 */
714 if (sc->gif_psrc == NULL) {
715 error = EADDRNOTAVAIL;
716 goto bad;
717 }
718 src = sc->gif_psrc;
719 switch (cmd) {
720#ifdef INET
721 case SIOCGIFPSRCADDR:
722 dst = &ifr->ifr_addr;
723 size = sizeof(ifr->ifr_addr);
724 break;
725#endif /* INET */
726#ifdef INET6
727 case SIOCGIFPSRCADDR_IN6:
728 dst = (struct sockaddr *)
729 &(((struct in6_ifreq *)data)->ifr_addr);
730 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
731 break;
732#endif /* INET6 */
733 default:
734 error = EADDRNOTAVAIL;
735 goto bad;
736 }
737 if (src->sa_len > size)
738 return EINVAL;
739 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
740 break;
741
742 case SIOCGIFPDSTADDR:
743#ifdef INET6
744 case SIOCGIFPDSTADDR_IN6:
745#endif /* INET6 */
746 if (sc->gif_pdst == NULL) {
747 error = EADDRNOTAVAIL;
748 goto bad;
749 }
750 src = sc->gif_pdst;
751 switch (cmd) {
752#ifdef INET
753 case SIOCGIFPDSTADDR:
754 dst = &ifr->ifr_addr;
755 size = sizeof(ifr->ifr_addr);
756 break;
757#endif /* INET */
758#ifdef INET6
759 case SIOCGIFPDSTADDR_IN6:
760 dst = (struct sockaddr *)
761 &(((struct in6_ifreq *)data)->ifr_addr);
762 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
763 break;
764#endif /* INET6 */
765 default:
766 error = EADDRNOTAVAIL;
767 goto bad;
768 }
769 if (src->sa_len > size)
770 return EINVAL;
771 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
772 break;
773
774 case SIOCGLIFPHYADDR:
775 if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
776 error = EADDRNOTAVAIL;
777 goto bad;
778 }
779
780 /* copy src */
781 src = sc->gif_psrc;
782 dst = (struct sockaddr *)
783 &(((struct if_laddrreq *)data)->addr);
784 size = sizeof(((struct if_laddrreq *)data)->addr);
785 if (src->sa_len > size)
786 return EINVAL;
787 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
788
789 /* copy dst */
790 src = sc->gif_pdst;
791 dst = (struct sockaddr *)
792 &(((struct if_laddrreq *)data)->dstaddr);
793 size = sizeof(((struct if_laddrreq *)data)->dstaddr);
794 if (src->sa_len > size)
795 return EINVAL;
796 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
797 break;
798
799 case SIOCSIFFLAGS:
800 /* if_ioctl() takes care of it */
801 break;
802
803 default:
804 error = EINVAL;
805 break;
806 }
807 bad:
808 return error;
809}
810
811void
812gif_delete_tunnel(sc)
813 struct gif_softc *sc;
814{
815 /* XXX: NetBSD protects this function with splsoftnet() */
816
817 if (sc->gif_psrc) {
818 free((caddr_t)sc->gif_psrc, M_IFADDR);
819 sc->gif_psrc = NULL;
820 }
821 if (sc->gif_pdst) {
822 free((caddr_t)sc->gif_pdst, M_IFADDR);
823 sc->gif_pdst = NULL;
824 }
825 /* change the IFF_UP flag as well? */
826}