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