xref: /freebsd/sys/net/if_gif.c (revision db612abe8df3355d1eb23bb3b50fdd97bc21e979)
1 /*	$FreeBSD$	*/
2 /*	$KAME: if_gif.c,v 1.87 2001/10/19 08:50:27 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 #include "opt_mac.h"
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/module.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 <machine/cpu.h>
52 
53 #include <net/if.h>
54 #include <net/if_clone.h>
55 #include <net/if_types.h>
56 #include <net/netisr.h>
57 #include <net/route.h>
58 #include <net/bpf.h>
59 
60 #include <netinet/in.h>
61 #include <netinet/in_systm.h>
62 #include <netinet/ip.h>
63 #ifdef	INET
64 #include <netinet/in_var.h>
65 #include <netinet/in_gif.h>
66 #include <netinet/ip_var.h>
67 #endif	/* INET */
68 
69 #ifdef INET6
70 #ifndef INET
71 #include <netinet/in.h>
72 #endif
73 #include <netinet6/in6_var.h>
74 #include <netinet/ip6.h>
75 #include <netinet6/ip6_var.h>
76 #include <netinet6/scope6_var.h>
77 #include <netinet6/in6_gif.h>
78 #include <netinet6/ip6protosw.h>
79 #endif /* INET6 */
80 
81 #include <netinet/ip_encap.h>
82 #include <net/ethernet.h>
83 #include <net/if_bridgevar.h>
84 #include <net/if_gif.h>
85 
86 #include <security/mac/mac_framework.h>
87 
88 #define GIFNAME		"gif"
89 
90 /*
91  * gif_mtx protects the global gif_softc_list.
92  */
93 static struct mtx gif_mtx;
94 static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
95 static LIST_HEAD(, gif_softc) gif_softc_list;
96 
97 void	(*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af);
98 void	(*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
99 void	(*ng_gif_attach_p)(struct ifnet *ifp);
100 void	(*ng_gif_detach_p)(struct ifnet *ifp);
101 
102 static void	gif_start(struct ifnet *);
103 static int	gif_clone_create(struct if_clone *, int, caddr_t);
104 static void	gif_clone_destroy(struct ifnet *);
105 
106 IFC_SIMPLE_DECLARE(gif, 0);
107 
108 static int gifmodevent(module_t, int, void *);
109 
110 SYSCTL_DECL(_net_link);
111 SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0,
112     "Generic Tunnel Interface");
113 #ifndef MAX_GIF_NEST
114 /*
115  * This macro controls the default upper limitation on nesting of gif tunnels.
116  * Since, setting a large value to this macro with a careless configuration
117  * may introduce system crash, we don't allow any nestings by default.
118  * If you need to configure nested gif tunnels, you can define this macro
119  * in your kernel configuration file.  However, if you do so, please be
120  * careful to configure the tunnels so that it won't make a loop.
121  */
122 #define MAX_GIF_NEST 1
123 #endif
124 static int max_gif_nesting = MAX_GIF_NEST;
125 SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW,
126     &max_gif_nesting, 0, "Max nested tunnels");
127 
128 /*
129  * By default, we disallow creation of multiple tunnels between the same
130  * pair of addresses.  Some applications require this functionality so
131  * we allow control over this check here.
132  */
133 #ifdef XBONEHACK
134 static int parallel_tunnels = 1;
135 #else
136 static int parallel_tunnels = 0;
137 #endif
138 SYSCTL_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW,
139     &parallel_tunnels, 0, "Allow parallel tunnels?");
140 
141 /* copy from src/sys/net/if_ethersubr.c */
142 static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] =
143 			{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
144 #ifndef ETHER_IS_BROADCAST
145 #define ETHER_IS_BROADCAST(addr) \
146 	(bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0)
147 #endif
148 
149 static int
150 gif_clone_create(ifc, unit, params)
151 	struct if_clone *ifc;
152 	int unit;
153 	caddr_t params;
154 {
155 	struct gif_softc *sc;
156 
157 	sc = malloc(sizeof(struct gif_softc), M_GIF, M_WAITOK | M_ZERO);
158 	GIF2IFP(sc) = if_alloc(IFT_GIF);
159 	if (GIF2IFP(sc) == NULL) {
160 		free(sc, M_GIF);
161 		return (ENOSPC);
162 	}
163 
164 	GIF_LOCK_INIT(sc);
165 
166 	GIF2IFP(sc)->if_softc = sc;
167 	if_initname(GIF2IFP(sc), ifc->ifc_name, unit);
168 
169 	sc->encap_cookie4 = sc->encap_cookie6 = NULL;
170 
171 	GIF2IFP(sc)->if_addrlen = 0;
172 	GIF2IFP(sc)->if_mtu    = GIF_MTU;
173 	GIF2IFP(sc)->if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
174 #if 0
175 	/* turn off ingress filter */
176 	GIF2IFP(sc)->if_flags  |= IFF_LINK2;
177 #endif
178 	GIF2IFP(sc)->if_ioctl  = gif_ioctl;
179 	GIF2IFP(sc)->if_start  = gif_start;
180 	GIF2IFP(sc)->if_output = gif_output;
181 	GIF2IFP(sc)->if_snd.ifq_maxlen = IFQ_MAXLEN;
182 	if_attach(GIF2IFP(sc));
183 	bpfattach(GIF2IFP(sc), DLT_NULL, sizeof(u_int32_t));
184 	if (ng_gif_attach_p != NULL)
185 		(*ng_gif_attach_p)(GIF2IFP(sc));
186 
187 	mtx_lock(&gif_mtx);
188 	LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
189 	mtx_unlock(&gif_mtx);
190 
191 	return (0);
192 }
193 
194 static void
195 gif_clone_destroy(ifp)
196 	struct ifnet *ifp;
197 {
198 	int err;
199 	struct gif_softc *sc = ifp->if_softc;
200 
201 	mtx_lock(&gif_mtx);
202 	LIST_REMOVE(sc, gif_list);
203 	mtx_unlock(&gif_mtx);
204 
205 	gif_delete_tunnel(ifp);
206 #ifdef INET6
207 	if (sc->encap_cookie6 != NULL) {
208 		err = encap_detach(sc->encap_cookie6);
209 		KASSERT(err == 0, ("Unexpected error detaching encap_cookie6"));
210 	}
211 #endif
212 #ifdef INET
213 	if (sc->encap_cookie4 != NULL) {
214 		err = encap_detach(sc->encap_cookie4);
215 		KASSERT(err == 0, ("Unexpected error detaching encap_cookie4"));
216 	}
217 #endif
218 
219 	if (ng_gif_detach_p != NULL)
220 		(*ng_gif_detach_p)(ifp);
221 	bpfdetach(ifp);
222 	if_detach(ifp);
223 	if_free(ifp);
224 
225 	GIF_LOCK_DESTROY(sc);
226 
227 	free(sc, M_GIF);
228 }
229 
230 static int
231 gifmodevent(mod, type, data)
232 	module_t mod;
233 	int type;
234 	void *data;
235 {
236 
237 	switch (type) {
238 	case MOD_LOAD:
239 		mtx_init(&gif_mtx, "gif_mtx", NULL, MTX_DEF);
240 		LIST_INIT(&gif_softc_list);
241 		if_clone_attach(&gif_cloner);
242 
243 #ifdef INET6
244 		ip6_gif_hlim = GIF_HLIM;
245 #endif
246 
247 		break;
248 	case MOD_UNLOAD:
249 		if_clone_detach(&gif_cloner);
250 		mtx_destroy(&gif_mtx);
251 #ifdef INET6
252 		ip6_gif_hlim = 0;
253 #endif
254 		break;
255 	default:
256 		return EOPNOTSUPP;
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 MODULE_VERSION(if_gif, 1);
269 
270 int
271 gif_encapcheck(m, off, proto, arg)
272 	const struct mbuf *m;
273 	int off;
274 	int proto;
275 	void *arg;
276 {
277 	struct ip ip;
278 	struct gif_softc *sc;
279 
280 	sc = (struct gif_softc *)arg;
281 	if (sc == NULL)
282 		return 0;
283 
284 	if ((GIF2IFP(sc)->if_flags & IFF_UP) == 0)
285 		return 0;
286 
287 	/* no physical address */
288 	if (!sc->gif_psrc || !sc->gif_pdst)
289 		return 0;
290 
291 	switch (proto) {
292 #ifdef INET
293 	case IPPROTO_IPV4:
294 		break;
295 #endif
296 #ifdef INET6
297 	case IPPROTO_IPV6:
298 		break;
299 #endif
300 	case IPPROTO_ETHERIP:
301 		break;
302 
303 	default:
304 		return 0;
305 	}
306 
307 	/* Bail on short packets */
308 	if (m->m_pkthdr.len < sizeof(ip))
309 		return 0;
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 (m->m_pkthdr.len < sizeof(struct ip6_hdr))
324 			return 0;
325 		if (sc->gif_psrc->sa_family != AF_INET6 ||
326 		    sc->gif_pdst->sa_family != AF_INET6)
327 			return 0;
328 		return gif_encapcheck6(m, off, proto, arg);
329 #endif
330 	default:
331 		return 0;
332 	}
333 }
334 
335 static void
336 gif_start(struct ifnet *ifp)
337 {
338 	struct gif_softc *sc;
339 	struct mbuf *m;
340 
341 	sc = ifp->if_softc;
342 
343 	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
344 	for (;;) {
345 		IFQ_DEQUEUE(&ifp->if_snd, m);
346 		if (m == 0)
347 			break;
348 
349 		gif_output(ifp, m, sc->gif_pdst, NULL);
350 
351 	}
352 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
353 
354 	return;
355 }
356 
357 int
358 gif_output(ifp, m, dst, rt)
359 	struct ifnet *ifp;
360 	struct mbuf *m;
361 	struct sockaddr *dst;
362 	struct rtentry *rt;	/* added in net2 */
363 {
364 	struct gif_softc *sc = ifp->if_softc;
365 	struct m_tag *mtag;
366 	int error = 0;
367 	int gif_called;
368 	u_int32_t af;
369 
370 #ifdef MAC
371 	error = mac_ifnet_check_transmit(ifp, m);
372 	if (error) {
373 		m_freem(m);
374 		goto end;
375 	}
376 #endif
377 
378 	/*
379 	 * gif may cause infinite recursion calls when misconfigured.
380 	 * We'll prevent this by detecting loops.
381 	 *
382 	 * High nesting level may cause stack exhaustion.
383 	 * We'll prevent this by introducing upper limit.
384 	 */
385 	gif_called = 1;
386 	mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, NULL);
387 	while (mtag != NULL) {
388 		if (*(struct ifnet **)(mtag + 1) == ifp) {
389 			log(LOG_NOTICE,
390 			    "gif_output: loop detected on %s\n",
391 			    (*(struct ifnet **)(mtag + 1))->if_xname);
392 			m_freem(m);
393 			error = EIO;	/* is there better errno? */
394 			goto end;
395 		}
396 		mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, mtag);
397 		gif_called++;
398 	}
399 	if (gif_called > max_gif_nesting) {
400 		log(LOG_NOTICE,
401 		    "gif_output: recursively called too many times(%d)\n",
402 		    gif_called);
403 		m_freem(m);
404 		error = EIO;	/* is there better errno? */
405 		goto end;
406 	}
407 	mtag = m_tag_alloc(MTAG_GIF, MTAG_GIF_CALLED, sizeof(struct ifnet *),
408 	    M_NOWAIT);
409 	if (mtag == NULL) {
410 		m_freem(m);
411 		error = ENOMEM;
412 		goto end;
413 	}
414 	*(struct ifnet **)(mtag + 1) = ifp;
415 	m_tag_prepend(m, mtag);
416 
417 	m->m_flags &= ~(M_BCAST|M_MCAST);
418 
419 	GIF_LOCK(sc);
420 
421 	if (!(ifp->if_flags & IFF_UP) ||
422 	    sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
423 		GIF_UNLOCK(sc);
424 		m_freem(m);
425 		error = ENETDOWN;
426 		goto end;
427 	}
428 
429 	/* BPF writes need to be handled specially. */
430 	if (dst->sa_family == AF_UNSPEC) {
431 		bcopy(dst->sa_data, &af, sizeof(af));
432 		dst->sa_family = af;
433 	}
434 
435 	af = dst->sa_family;
436 	BPF_MTAP2(ifp, &af, sizeof(af), m);
437 	ifp->if_opackets++;
438 	ifp->if_obytes += m->m_pkthdr.len;
439 
440 	/* override to IPPROTO_ETHERIP for bridged traffic */
441 	if (ifp->if_bridge)
442 		af = AF_LINK;
443 
444 	/* inner AF-specific encapsulation */
445 
446 	/* XXX should we check if our outer source is legal? */
447 
448 	/* dispatch to output logic based on outer AF */
449 	switch (sc->gif_psrc->sa_family) {
450 #ifdef INET
451 	case AF_INET:
452 		error = in_gif_output(ifp, af, m);
453 		break;
454 #endif
455 #ifdef INET6
456 	case AF_INET6:
457 		error = in6_gif_output(ifp, af, m);
458 		break;
459 #endif
460 	default:
461 		m_freem(m);
462 		error = ENETDOWN;
463 	}
464 
465 	GIF_UNLOCK(sc);
466   end:
467 	if (error)
468 		ifp->if_oerrors++;
469 	return (error);
470 }
471 
472 void
473 gif_input(m, af, ifp)
474 	struct mbuf *m;
475 	int af;
476 	struct ifnet *ifp;
477 {
478 	int isr, n;
479 	struct etherip_header *eip;
480 	struct ether_header *eh;
481 	struct ifnet *oldifp;
482 
483 	if (ifp == NULL) {
484 		/* just in case */
485 		m_freem(m);
486 		return;
487 	}
488 
489 	m->m_pkthdr.rcvif = ifp;
490 
491 #ifdef MAC
492 	mac_ifnet_create_mbuf(ifp, m);
493 #endif
494 
495 	if (bpf_peers_present(ifp->if_bpf)) {
496 		u_int32_t af1 = af;
497 		bpf_mtap2(ifp->if_bpf, &af1, sizeof(af1), m);
498 	}
499 
500 	if (ng_gif_input_p != NULL) {
501 		(*ng_gif_input_p)(ifp, &m, af);
502 		if (m == NULL)
503 			return;
504 	}
505 
506 	/*
507 	 * Put the packet to the network layer input queue according to the
508 	 * specified address family.
509 	 * Note: older versions of gif_input directly called network layer
510 	 * input functions, e.g. ip6_input, here.  We changed the policy to
511 	 * prevent too many recursive calls of such input functions, which
512 	 * might cause kernel panic.  But the change may introduce another
513 	 * problem; if the input queue is full, packets are discarded.
514 	 * The kernel stack overflow really happened, and we believed
515 	 * queue-full rarely occurs, so we changed the policy.
516 	 */
517 	switch (af) {
518 #ifdef INET
519 	case AF_INET:
520 		isr = NETISR_IP;
521 		break;
522 #endif
523 #ifdef INET6
524 	case AF_INET6:
525 		isr = NETISR_IPV6;
526 		break;
527 #endif
528 	case AF_LINK:
529 		n = sizeof(struct etherip_header) + sizeof(struct ether_header);
530 		if (n > m->m_len) {
531 			m = m_pullup(m, n);
532 			if (m == NULL) {
533 				ifp->if_ierrors++;
534 				return;
535 			}
536 		}
537 
538 		eip = mtod(m, struct etherip_header *);
539  		if (eip->eip_ver !=
540 		    (ETHERIP_VERSION & ETHERIP_VER_VERS_MASK)) {
541 			/* discard unknown versions */
542 			m_freem(m);
543 			return;
544 		}
545 		m_adj(m, sizeof(struct etherip_header));
546 
547 		m->m_flags &= ~(M_BCAST|M_MCAST);
548 		m->m_pkthdr.rcvif = ifp;
549 
550 		if (ifp->if_bridge) {
551 			oldifp = ifp;
552 			eh = mtod(m, struct ether_header *);
553 			if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
554 				if (ETHER_IS_BROADCAST(eh->ether_dhost))
555 					m->m_flags |= M_BCAST;
556 				else
557 					m->m_flags |= M_MCAST;
558 				ifp->if_imcasts++;
559 			}
560 			BRIDGE_INPUT(ifp, m);
561 
562 			if (m != NULL && ifp != oldifp) {
563 				/*
564 				 * The bridge gave us back itself or one of the
565 				 * members for which the frame is addressed.
566 				 */
567 				ether_demux(ifp, m);
568 				return;
569 			}
570 		}
571 		if (m != NULL)
572 			m_freem(m);
573 		return;
574 
575 	default:
576 		if (ng_gif_input_orphan_p != NULL)
577 			(*ng_gif_input_orphan_p)(ifp, m, af);
578 		else
579 			m_freem(m);
580 		return;
581 	}
582 
583 	ifp->if_ipackets++;
584 	ifp->if_ibytes += m->m_pkthdr.len;
585 	netisr_dispatch(isr, m);
586 }
587 
588 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
589 int
590 gif_ioctl(ifp, cmd, data)
591 	struct ifnet *ifp;
592 	u_long cmd;
593 	caddr_t data;
594 {
595 	struct gif_softc *sc  = ifp->if_softc;
596 	struct ifreq     *ifr = (struct ifreq*)data;
597 	int error = 0, size;
598 	struct sockaddr *dst, *src;
599 #ifdef	SIOCSIFMTU /* xxx */
600 	u_long mtu;
601 #endif
602 
603 	switch (cmd) {
604 	case SIOCSIFADDR:
605 		ifp->if_flags |= IFF_UP;
606 		break;
607 
608 	case SIOCSIFDSTADDR:
609 		break;
610 
611 	case SIOCADDMULTI:
612 	case SIOCDELMULTI:
613 		break;
614 
615 #ifdef	SIOCSIFMTU /* xxx */
616 	case SIOCGIFMTU:
617 		break;
618 
619 	case SIOCSIFMTU:
620 		mtu = ifr->ifr_mtu;
621 		if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX)
622 			return (EINVAL);
623 		ifp->if_mtu = mtu;
624 		break;
625 #endif /* SIOCSIFMTU */
626 
627 #ifdef INET
628 	case SIOCSIFPHYADDR:
629 #endif
630 #ifdef INET6
631 	case SIOCSIFPHYADDR_IN6:
632 #endif /* INET6 */
633 	case SIOCSLIFPHYADDR:
634 		switch (cmd) {
635 #ifdef INET
636 		case SIOCSIFPHYADDR:
637 			src = (struct sockaddr *)
638 				&(((struct in_aliasreq *)data)->ifra_addr);
639 			dst = (struct sockaddr *)
640 				&(((struct in_aliasreq *)data)->ifra_dstaddr);
641 			break;
642 #endif
643 #ifdef INET6
644 		case SIOCSIFPHYADDR_IN6:
645 			src = (struct sockaddr *)
646 				&(((struct in6_aliasreq *)data)->ifra_addr);
647 			dst = (struct sockaddr *)
648 				&(((struct in6_aliasreq *)data)->ifra_dstaddr);
649 			break;
650 #endif
651 		case SIOCSLIFPHYADDR:
652 			src = (struct sockaddr *)
653 				&(((struct if_laddrreq *)data)->addr);
654 			dst = (struct sockaddr *)
655 				&(((struct if_laddrreq *)data)->dstaddr);
656 			break;
657 		default:
658 			return EINVAL;
659 		}
660 
661 		/* sa_family must be equal */
662 		if (src->sa_family != dst->sa_family)
663 			return EINVAL;
664 
665 		/* validate sa_len */
666 		switch (src->sa_family) {
667 #ifdef INET
668 		case AF_INET:
669 			if (src->sa_len != sizeof(struct sockaddr_in))
670 				return EINVAL;
671 			break;
672 #endif
673 #ifdef INET6
674 		case AF_INET6:
675 			if (src->sa_len != sizeof(struct sockaddr_in6))
676 				return EINVAL;
677 			break;
678 #endif
679 		default:
680 			return EAFNOSUPPORT;
681 		}
682 		switch (dst->sa_family) {
683 #ifdef INET
684 		case AF_INET:
685 			if (dst->sa_len != sizeof(struct sockaddr_in))
686 				return EINVAL;
687 			break;
688 #endif
689 #ifdef INET6
690 		case AF_INET6:
691 			if (dst->sa_len != sizeof(struct sockaddr_in6))
692 				return EINVAL;
693 			break;
694 #endif
695 		default:
696 			return EAFNOSUPPORT;
697 		}
698 
699 		/* check sa_family looks sane for the cmd */
700 		switch (cmd) {
701 		case SIOCSIFPHYADDR:
702 			if (src->sa_family == AF_INET)
703 				break;
704 			return EAFNOSUPPORT;
705 #ifdef INET6
706 		case SIOCSIFPHYADDR_IN6:
707 			if (src->sa_family == AF_INET6)
708 				break;
709 			return EAFNOSUPPORT;
710 #endif /* INET6 */
711 		case SIOCSLIFPHYADDR:
712 			/* checks done in the above */
713 			break;
714 		}
715 
716 		error = gif_set_tunnel(GIF2IFP(sc), src, dst);
717 		break;
718 
719 #ifdef SIOCDIFPHYADDR
720 	case SIOCDIFPHYADDR:
721 		gif_delete_tunnel(GIF2IFP(sc));
722 		break;
723 #endif
724 
725 	case SIOCGIFPSRCADDR:
726 #ifdef INET6
727 	case SIOCGIFPSRCADDR_IN6:
728 #endif /* INET6 */
729 		if (sc->gif_psrc == NULL) {
730 			error = EADDRNOTAVAIL;
731 			goto bad;
732 		}
733 		src = sc->gif_psrc;
734 		switch (cmd) {
735 #ifdef INET
736 		case SIOCGIFPSRCADDR:
737 			dst = &ifr->ifr_addr;
738 			size = sizeof(ifr->ifr_addr);
739 			break;
740 #endif /* INET */
741 #ifdef INET6
742 		case SIOCGIFPSRCADDR_IN6:
743 			dst = (struct sockaddr *)
744 				&(((struct in6_ifreq *)data)->ifr_addr);
745 			size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
746 			break;
747 #endif /* INET6 */
748 		default:
749 			error = EADDRNOTAVAIL;
750 			goto bad;
751 		}
752 		if (src->sa_len > size)
753 			return EINVAL;
754 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
755 #ifdef INET6
756 		if (dst->sa_family == AF_INET6) {
757 			error = sa6_recoverscope((struct sockaddr_in6 *)dst);
758 			if (error != 0)
759 				return (error);
760 		}
761 #endif
762 		break;
763 
764 	case SIOCGIFPDSTADDR:
765 #ifdef INET6
766 	case SIOCGIFPDSTADDR_IN6:
767 #endif /* INET6 */
768 		if (sc->gif_pdst == NULL) {
769 			error = EADDRNOTAVAIL;
770 			goto bad;
771 		}
772 		src = sc->gif_pdst;
773 		switch (cmd) {
774 #ifdef INET
775 		case SIOCGIFPDSTADDR:
776 			dst = &ifr->ifr_addr;
777 			size = sizeof(ifr->ifr_addr);
778 			break;
779 #endif /* INET */
780 #ifdef INET6
781 		case SIOCGIFPDSTADDR_IN6:
782 			dst = (struct sockaddr *)
783 				&(((struct in6_ifreq *)data)->ifr_addr);
784 			size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
785 			break;
786 #endif /* INET6 */
787 		default:
788 			error = EADDRNOTAVAIL;
789 			goto bad;
790 		}
791 		if (src->sa_len > size)
792 			return EINVAL;
793 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
794 #ifdef INET6
795 		if (dst->sa_family == AF_INET6) {
796 			error = sa6_recoverscope((struct sockaddr_in6 *)dst);
797 			if (error != 0)
798 				return (error);
799 		}
800 #endif
801 		break;
802 
803 	case SIOCGLIFPHYADDR:
804 		if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
805 			error = EADDRNOTAVAIL;
806 			goto bad;
807 		}
808 
809 		/* copy src */
810 		src = sc->gif_psrc;
811 		dst = (struct sockaddr *)
812 			&(((struct if_laddrreq *)data)->addr);
813 		size = sizeof(((struct if_laddrreq *)data)->addr);
814 		if (src->sa_len > size)
815 			return EINVAL;
816 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
817 
818 		/* copy dst */
819 		src = sc->gif_pdst;
820 		dst = (struct sockaddr *)
821 			&(((struct if_laddrreq *)data)->dstaddr);
822 		size = sizeof(((struct if_laddrreq *)data)->dstaddr);
823 		if (src->sa_len > size)
824 			return EINVAL;
825 		bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
826 		break;
827 
828 	case SIOCSIFFLAGS:
829 		/* if_ioctl() takes care of it */
830 		break;
831 
832 	default:
833 		error = EINVAL;
834 		break;
835 	}
836  bad:
837 	return error;
838 }
839 
840 /*
841  * XXXRW: There's a general event-ordering issue here: the code to check
842  * if a given tunnel is already present happens before we perform a
843  * potentially blocking setup of the tunnel.  This code needs to be
844  * re-ordered so that the check and replacement can be atomic using
845  * a mutex.
846  */
847 int
848 gif_set_tunnel(ifp, src, dst)
849 	struct ifnet *ifp;
850 	struct sockaddr *src;
851 	struct sockaddr *dst;
852 {
853 	struct gif_softc *sc = ifp->if_softc;
854 	struct gif_softc *sc2;
855 	struct sockaddr *osrc, *odst, *sa;
856 	int error = 0;
857 
858 	mtx_lock(&gif_mtx);
859 	LIST_FOREACH(sc2, &gif_softc_list, gif_list) {
860 		if (sc2 == sc)
861 			continue;
862 		if (!sc2->gif_pdst || !sc2->gif_psrc)
863 			continue;
864 		if (sc2->gif_pdst->sa_family != dst->sa_family ||
865 		    sc2->gif_pdst->sa_len != dst->sa_len ||
866 		    sc2->gif_psrc->sa_family != src->sa_family ||
867 		    sc2->gif_psrc->sa_len != src->sa_len)
868 			continue;
869 
870 		/*
871 		 * Disallow parallel tunnels unless instructed
872 		 * otherwise.
873 		 */
874 		if (!parallel_tunnels &&
875 		    bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
876 		    bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
877 			error = EADDRNOTAVAIL;
878 			mtx_unlock(&gif_mtx);
879 			goto bad;
880 		}
881 
882 		/* XXX both end must be valid? (I mean, not 0.0.0.0) */
883 	}
884 	mtx_unlock(&gif_mtx);
885 
886 	/* XXX we can detach from both, but be polite just in case */
887 	if (sc->gif_psrc)
888 		switch (sc->gif_psrc->sa_family) {
889 #ifdef INET
890 		case AF_INET:
891 			(void)in_gif_detach(sc);
892 			break;
893 #endif
894 #ifdef INET6
895 		case AF_INET6:
896 			(void)in6_gif_detach(sc);
897 			break;
898 #endif
899 		}
900 
901 	osrc = sc->gif_psrc;
902 	sa = (struct sockaddr *)malloc(src->sa_len, M_IFADDR, M_WAITOK);
903 	bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
904 	sc->gif_psrc = sa;
905 
906 	odst = sc->gif_pdst;
907 	sa = (struct sockaddr *)malloc(dst->sa_len, M_IFADDR, M_WAITOK);
908 	bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
909 	sc->gif_pdst = sa;
910 
911 	switch (sc->gif_psrc->sa_family) {
912 #ifdef INET
913 	case AF_INET:
914 		error = in_gif_attach(sc);
915 		break;
916 #endif
917 #ifdef INET6
918 	case AF_INET6:
919 		/*
920 		 * Check validity of the scope zone ID of the addresses, and
921 		 * convert it into the kernel internal form if necessary.
922 		 */
923 		error = sa6_embedscope((struct sockaddr_in6 *)sc->gif_psrc, 0);
924 		if (error != 0)
925 			break;
926 		error = sa6_embedscope((struct sockaddr_in6 *)sc->gif_pdst, 0);
927 		if (error != 0)
928 			break;
929 		error = in6_gif_attach(sc);
930 		break;
931 #endif
932 	}
933 	if (error) {
934 		/* rollback */
935 		free((caddr_t)sc->gif_psrc, M_IFADDR);
936 		free((caddr_t)sc->gif_pdst, M_IFADDR);
937 		sc->gif_psrc = osrc;
938 		sc->gif_pdst = odst;
939 		goto bad;
940 	}
941 
942 	if (osrc)
943 		free((caddr_t)osrc, M_IFADDR);
944 	if (odst)
945 		free((caddr_t)odst, M_IFADDR);
946 
947  bad:
948 	if (sc->gif_psrc && sc->gif_pdst)
949 		ifp->if_drv_flags |= IFF_DRV_RUNNING;
950 	else
951 		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
952 
953 	return error;
954 }
955 
956 void
957 gif_delete_tunnel(ifp)
958 	struct ifnet *ifp;
959 {
960 	struct gif_softc *sc = ifp->if_softc;
961 
962 	if (sc->gif_psrc) {
963 		free((caddr_t)sc->gif_psrc, M_IFADDR);
964 		sc->gif_psrc = NULL;
965 	}
966 	if (sc->gif_pdst) {
967 		free((caddr_t)sc->gif_pdst, M_IFADDR);
968 		sc->gif_pdst = NULL;
969 	}
970 	/* it is safe to detach from both */
971 #ifdef INET
972 	(void)in_gif_detach(sc);
973 #endif
974 #ifdef INET6
975 	(void)in6_gif_detach(sc);
976 #endif
977 	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
978 }
979