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