Home | History | Annotate | Line # | Download | only in net
if_gif.c revision 1.2
      1 /*
      2  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. Neither the name of the project nor the names of its contributors
     14  *    may be used to endorse or promote products derived from this software
     15  *    without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 /*
     31  * gif.c
     32  */
     33 
     34 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
     35 #include "opt_inet.h"
     36 #endif
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/kernel.h>
     41 #include <sys/mbuf.h>
     42 #include <sys/socket.h>
     43 #include <sys/sockio.h>
     44 #include <sys/errno.h>
     45 #if !defined(__FreeBSD__) || __FreeBSD__ < 3
     46 #include <sys/ioctl.h>
     47 #endif
     48 #include <sys/time.h>
     49 #include <sys/syslog.h>
     50 #include <machine/cpu.h>
     51 
     52 #include <net/if.h>
     53 #include <net/if_types.h>
     54 #include <net/netisr.h>
     55 #include <net/route.h>
     56 #include <net/bpf.h>
     57 
     58 #ifdef	INET
     59 #include <netinet/in.h>
     60 #include <netinet/in_systm.h>
     61 #include <netinet/in_var.h>
     62 #include <netinet/ip.h>
     63 #include <netinet/in_gif.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/in6_ifattach.h>
     75 #endif /* INET6 */
     76 
     77 #include <net/if_gif.h>
     78 
     79 #include "gif.h"
     80 #include "bpfilter.h"
     81 
     82 #if NGIF > 0
     83 
     84 void gifattach __P((void *));
     85 
     86 /*
     87  * gif global variable definitions
     88  */
     89 int ngif = NGIF;		/* number of interfaces */
     90 struct gif_softc *gif = 0;
     91 
     92 void
     93 gifattach(dummy)
     94 	void *dummy;
     95 {
     96 	register struct gif_softc *sc;
     97 	register int i;
     98 
     99 	gif = sc = malloc (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAIT);
    100 	bzero(sc, ngif * sizeof(struct gif_softc));
    101 	for (i = 0; i < ngif; sc++, i++) {
    102 		sprintf(sc->gif_if.if_xname, "gif%d", i);
    103 		sc->gif_if.if_mtu    = GIF_MTU;
    104 		sc->gif_if.if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
    105 		sc->gif_if.if_ioctl  = gif_ioctl;
    106 		sc->gif_if.if_output = gif_output;
    107 		sc->gif_if.if_type   = IFT_GIF;
    108 		if_attach(&sc->gif_if);
    109 #if NBPFILTER > 0
    110 		bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL, sizeof(u_int));
    111 #endif
    112 	}
    113 }
    114 
    115 #ifdef __FreeBSD__
    116 PSEUDO_SET(gifattach, if_gif);
    117 #endif
    118 
    119 int
    120 gif_output(ifp, m, dst, rt)
    121 	struct ifnet *ifp;
    122 	struct mbuf *m;
    123 	struct sockaddr *dst;
    124 	struct rtentry *rt;	/* added in net2 */
    125 {
    126 	register struct gif_softc *sc = (struct gif_softc*)ifp;
    127 	int error = 0;
    128 	static int called = 0;	/* XXX: MUTEX */
    129 	int calllimit = 10;	/* XXX: adhoc */
    130 
    131 	/*
    132 	 * gif may cause infinite recursion calls when misconfigured.
    133 	 * We'll prevent this by introducing upper limit.
    134 	 * XXX: this mechanism may introduce another problem about
    135 	 *      mutual exclusion of the variable CALLED, especially if we
    136 	 *      use kernel thread.
    137 	 */
    138 	if (++called >= calllimit) {
    139 		log(LOG_NOTICE,
    140 		    "gif_output: recursively called too many times(%d)\n",
    141 		    called);
    142 		m_freem(m);
    143 		error = EIO;	/* is there better errno? */
    144 		goto end;
    145 	}
    146 
    147 	ifp->if_lastchange = time;
    148 	m->m_flags &= ~(M_BCAST|M_MCAST);
    149 	if (!(ifp->if_flags & IFF_UP) ||
    150 #if 0
    151 	    sc->gif_flags & GIFF_INUSE ||
    152 #endif
    153 	    sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
    154 		m_freem(m);
    155 		error = ENETDOWN;
    156 		goto end;
    157 	}
    158 
    159 #if NBPFILTER > 0
    160 	if (ifp->if_bpf) {
    161 		/*
    162 		 * We need to prepend the address family as
    163 		 * a four byte field.  Cons up a dummy header
    164 		 * to pacify bpf.  This is safe because bpf
    165 		 * will only read from the mbuf (i.e., it won't
    166 		 * try to free it or keep a pointer a to it).
    167 		 */
    168 		struct mbuf m0;
    169 		u_int af = dst->sa_family;
    170 
    171 		m0.m_next = m;
    172 		m0.m_len = 4;
    173 		m0.m_data = (char *)&af;
    174 
    175 		bpf_mtap(ifp->if_bpf, &m0);
    176 	}
    177 #endif
    178 	ifp->if_opackets++;
    179 	ifp->if_obytes += m->m_pkthdr.len;
    180 #if 0
    181 	s = splnet();
    182 	sc->gif_flags |= GIFF_INUSE;
    183 #endif
    184 
    185 	switch (sc->gif_psrc->sa_family) {
    186 #ifdef INET
    187 	case AF_INET:
    188 		error = in_gif_output(ifp, dst->sa_family, m, rt);
    189 		break;
    190 #endif
    191 #ifdef INET6
    192 	case AF_INET6:
    193 		error = in6_gif_output(ifp, dst->sa_family, m, rt);
    194 		break;
    195 #endif
    196 	default:
    197 		m_freem(m);
    198 		error = ENETDOWN;
    199 	}
    200 #if 0
    201 	sc->gif_flags &= ~GIFF_INUSE;
    202 	splx(s);
    203 #endif
    204 
    205   end:
    206 	called = 0;		/* reset recursion counter */
    207 	if (error) ifp->if_oerrors++;
    208 	return error;
    209 }
    210 
    211 void
    212 gif_input(m, af, gifp)
    213 	struct mbuf *m;
    214 	int af;
    215 	struct ifnet *gifp;
    216 {
    217 	int s, isr;
    218 	register struct ifqueue *ifq = 0;
    219 
    220 	if (gifp == NULL) {
    221 		/* just in case */
    222 		m_freem(m);
    223 		return;
    224 	}
    225 
    226 	if (m->m_pkthdr.rcvif)
    227 		m->m_pkthdr.rcvif = gifp;
    228 
    229 #if NBPFILTER > 0
    230 	if (gifp->if_bpf) {
    231 		/*
    232 		 * We need to prepend the address family as
    233 		 * a four byte field.  Cons up a dummy header
    234 		 * to pacify bpf.  This is safe because bpf
    235 		 * will only read from the mbuf (i.e., it won't
    236 		 * try to free it or keep a pointer a to it).
    237 		 */
    238 		struct mbuf m0;
    239 		u_int af = AF_INET6;
    240 
    241 		m0.m_next = m;
    242 		m0.m_len = 4;
    243 		m0.m_data = (char *)&af;
    244 
    245 		bpf_mtap(gifp->if_bpf, &m0);
    246 	}
    247 #endif /*NBPFILTER > 0*/
    248 
    249 	/*
    250 	 * Put the packet to the network layer input queue according to the
    251 	 * specified address family.
    252 	 * Note: older versions of gif_input directly called network layer
    253 	 * input functions, e.g. ip6_input, here. We changed the policy to
    254 	 * prevent too many recursive calls of such input functions, which
    255 	 * might cause kernel panic. But the change may introduce another
    256 	 * problem; if the input queue is full, packets are discarded.
    257 	 * We believed it rarely occurs and changed the policy. If we find
    258 	 * it occurs more times than we thought, we may change the policy
    259 	 * again.
    260 	 */
    261 	switch (af) {
    262 #ifdef INET
    263 	case AF_INET:
    264 		ifq = &ipintrq;
    265 		isr = NETISR_IP;
    266 		break;
    267 #endif
    268 #ifdef INET6
    269 	case AF_INET6:
    270 		ifq = &ip6intrq;
    271 		isr = NETISR_IPV6;
    272 		break;
    273 #endif
    274 	default:
    275 		m_freem(m);
    276 		return;
    277 	}
    278 
    279 	s = splimp();
    280 	if (IF_QFULL(ifq)) {
    281 		IF_DROP(ifq);	/* update statistics */
    282 		m_freem(m);
    283 		splx(s);
    284 		return;
    285 	}
    286 	IF_ENQUEUE(ifq, m);
    287 	/* we need schednetisr since the address family may change */
    288 	schednetisr(isr);
    289 	gifp->if_ipackets++;
    290 	gifp->if_ibytes += m->m_pkthdr.len;
    291 	splx(s);
    292 
    293 	return;
    294 }
    295 
    296 
    297 int
    298 gif_ioctl(ifp, cmd, data)
    299 	struct ifnet *ifp;
    300 	u_long cmd;
    301 	caddr_t data;
    302 {
    303 	struct gif_softc *sc  = (struct gif_softc*)ifp;
    304 	struct ifreq     *ifr = (struct ifreq*)data;
    305 	int error = 0, size;
    306 	struct sockaddr *sa, *dst, *src;
    307 
    308 	switch (cmd) {
    309 	case SIOCSIFADDR:
    310 		break;
    311 
    312 	case SIOCSIFDSTADDR:
    313 		break;
    314 
    315 	case SIOCADDMULTI:
    316 	case SIOCDELMULTI:
    317 		switch (ifr->ifr_addr.sa_family) {
    318 #ifdef INET
    319 		case AF_INET:	/* IP supports Multicast */
    320 			break;
    321 #endif /* INET */
    322 #ifdef INET6
    323 		case AF_INET6:	/* IP6 supports Multicast */
    324 			break;
    325 #endif /* INET6 */
    326 		default:  /* Other protocols doesn't support Multicast */
    327 			error = EAFNOSUPPORT;
    328 			break;
    329 		}
    330 		break;
    331 
    332 #ifdef	SIOCSIFMTU /* xxx */
    333 	case SIOCGIFMTU:
    334 		break;
    335 	case SIOCSIFMTU:
    336 		{
    337 #ifdef __bsdi__
    338 			short mtu;
    339 			mtu = *(short *)ifr->ifr_data;
    340 #else
    341 			u_long mtu;
    342 			mtu = ifr->ifr_mtu;
    343 #endif
    344 			if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
    345 				return (EINVAL);
    346 			}
    347 			ifp->if_mtu = mtu;
    348 		}
    349 		break;
    350 #endif /* SIOCSIFMTU */
    351 
    352 	case SIOCSIFPHYADDR:
    353 #ifdef INET6
    354 	case SIOCSIFPHYADDR_IN6:
    355 #endif /* INET6 */
    356 #ifdef INET6
    357 		if (found_first_ifid)
    358 			in6_ifattach(ifp, IN6_IFT_P2P, NULL, 1);
    359 		else {
    360 			error = ENXIO; /* xxx */
    361 			goto bad;
    362 		}
    363 #endif /* INET6 */
    364 
    365 		switch (ifr->ifr_addr.sa_family) {
    366 #ifdef INET
    367 		case AF_INET:
    368 			src = (struct sockaddr *)
    369 				&(((struct in_aliasreq *)data)->ifra_addr);
    370 			dst = (struct sockaddr *)
    371 				&(((struct in_aliasreq *)data)->ifra_dstaddr);
    372 
    373 			/* only one gif can have dst = INADDR_ANY */
    374 #define satosaddr(sa) (((struct sockaddr_in *)(sa))->sin_addr.s_addr)
    375 
    376 			if (satosaddr(dst) == INADDR_ANY) {
    377 				int i;
    378 				struct gif_softc *sc2;
    379 
    380 			  	for (i = 0, sc2 = gif; i < ngif; i++, sc2++) {
    381 					if (sc2 == sc) continue;
    382 					if (sc2->gif_pdst &&
    383 					    satosaddr(sc2->gif_pdst)
    384 						== INADDR_ANY) {
    385 					    error = EADDRNOTAVAIL;
    386 					    goto bad;
    387 					}
    388 				}
    389 			}
    390 			size = sizeof(struct sockaddr_in);
    391 			break;
    392 #endif /* INET */
    393 #ifdef INET6
    394 		case AF_INET6:
    395 			src = (struct sockaddr *)
    396 				&(((struct in6_aliasreq *)data)->ifra_addr);
    397 			dst = (struct sockaddr *)
    398 				&(((struct in6_aliasreq *)data)->ifra_dstaddr);
    399 
    400 			/* only one gif can have dst = in6addr_any */
    401 #define satoin6(sa) (&((struct sockaddr_in6 *)(sa))->sin6_addr)
    402 
    403 			if (IN6_IS_ADDR_UNSPECIFIED(satoin6(dst))) {
    404 				int i;
    405 				struct gif_softc *sc2;
    406 
    407 			  	for (i = 0, sc2 = gif; i < ngif; i++, sc2++) {
    408 					if (sc2 == sc) continue;
    409 					if (sc2->gif_pdst &&
    410 					    IN6_IS_ADDR_UNSPECIFIED(
    411 						satoin6(sc2->gif_pdst)
    412 								    )) {
    413 					    error = EADDRNOTAVAIL;
    414 					    goto bad;
    415 					}
    416 				}
    417 			}
    418 			size = sizeof(struct sockaddr_in6);
    419 			break;
    420 #endif /* INET6 */
    421 		default:
    422 			error = EPROTOTYPE;
    423 			goto bad;
    424 			break;
    425 		}
    426 		if (sc->gif_psrc != NULL)
    427 			free((caddr_t)sc->gif_psrc, M_IFADDR);
    428 		if (sc->gif_pdst != NULL)
    429 			free((caddr_t)sc->gif_pdst, M_IFADDR);
    430 
    431 		sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK);
    432 		bzero((caddr_t)sa, size);
    433 		bcopy((caddr_t)src, (caddr_t)sa, size);
    434 		sc->gif_psrc = sa;
    435 
    436 		sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK);
    437 		bzero((caddr_t)sa, size);
    438 		bcopy((caddr_t)dst, (caddr_t)sa, size);
    439 		sc->gif_pdst = sa;
    440 
    441 		ifp->if_flags |= (IFF_UP|IFF_RUNNING);
    442 		if_up(ifp);		/* send up RTM_IFINFO */
    443 
    444 		break;
    445 
    446 	case SIOCGIFPSRCADDR:
    447 #ifdef INET6
    448 	case SIOCGIFPSRCADDR_IN6:
    449 #endif /* INET6 */
    450 		if (sc->gif_psrc == NULL) {
    451 			error = EADDRNOTAVAIL;
    452 			goto bad;
    453 		}
    454 		src = sc->gif_psrc;
    455 		switch (sc->gif_psrc->sa_family) {
    456 #ifdef INET
    457 		case AF_INET:
    458 			dst = &ifr->ifr_addr;
    459 			size = sizeof(struct sockaddr_in);
    460 			break;
    461 #endif /* INET */
    462 #ifdef INET6
    463 		case AF_INET6:
    464 			dst = (struct sockaddr *)
    465 				&(((struct in6_ifreq *)data)->ifr_addr);
    466 			size = sizeof(struct sockaddr_in6);
    467 			break;
    468 #endif /* INET6 */
    469 		default:
    470 			error = EADDRNOTAVAIL;
    471 			goto bad;
    472 		}
    473 		bcopy((caddr_t)src, (caddr_t)dst, size);
    474 		break;
    475 
    476 	case SIOCGIFPDSTADDR:
    477 #ifdef INET6
    478 	case SIOCGIFPDSTADDR_IN6:
    479 #endif /* INET6 */
    480 		if (sc->gif_pdst == NULL) {
    481 			error = EADDRNOTAVAIL;
    482 			goto bad;
    483 		}
    484 		src = sc->gif_pdst;
    485 		switch (sc->gif_pdst->sa_family) {
    486 #ifdef INET
    487 		case AF_INET:
    488 			dst = &ifr->ifr_addr;
    489 			size = sizeof(struct sockaddr_in);
    490 			break;
    491 #endif /* INET */
    492 #ifdef INET6
    493 		case AF_INET6:
    494 			dst = (struct sockaddr *)
    495 				&(((struct in6_ifreq *)data)->ifr_addr);
    496 			size = sizeof(struct sockaddr_in6);
    497 			break;
    498 #endif /* INET6 */
    499 		default:
    500 			error = EADDRNOTAVAIL;
    501 			goto bad;
    502 		}
    503 		bcopy((caddr_t)src, (caddr_t)dst, size);
    504 		break;
    505 
    506 	case SIOCSIFFLAGS:
    507 		break;
    508 
    509 	default:
    510 		error = EINVAL;
    511 		break;
    512 	}
    513  bad:
    514 	return error;
    515 }
    516 #endif /*NGIF > 0*/
    517