Home | History | Annotate | Line # | Download | only in net
if_gre.c revision 1.101
      1  1.101       skd /*	$NetBSD: if_gre.c,v 1.101 2007/08/20 04:49:41 skd Exp $ */
      2    1.4   thorpej 
      3    1.1       hwr /*
      4    1.4   thorpej  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5    1.1       hwr  * All rights reserved.
      6    1.1       hwr  *
      7    1.1       hwr  * This code is derived from software contributed to The NetBSD Foundation
      8    1.1       hwr  * by Heiko W.Rupp <hwr (at) pilhuhn.de>
      9    1.1       hwr  *
     10   1.56        is  * IPv6-over-GRE contributed by Gert Doering <gert (at) greenie.muc.de>
     11   1.56        is  *
     12    1.1       hwr  * Redistribution and use in source and binary forms, with or without
     13    1.1       hwr  * modification, are permitted provided that the following conditions
     14    1.1       hwr  * are met:
     15    1.1       hwr  * 1. Redistributions of source code must retain the above copyright
     16    1.1       hwr  *    notice, this list of conditions and the following disclaimer.
     17    1.1       hwr  * 2. Redistributions in binary form must reproduce the above copyright
     18    1.1       hwr  *    notice, this list of conditions and the following disclaimer in the
     19    1.1       hwr  *    documentation and/or other materials provided with the distribution.
     20    1.1       hwr  * 3. All advertising materials mentioning features or use of this software
     21    1.1       hwr  *    must display the following acknowledgement:
     22    1.1       hwr  *        This product includes software developed by the NetBSD
     23    1.1       hwr  *        Foundation, Inc. and its contributors.
     24    1.1       hwr  * 4. Neither the name of The NetBSD Foundation nor the names of its
     25    1.1       hwr  *    contributors may be used to endorse or promote products derived
     26    1.1       hwr  *    from this software without specific prior written permission.
     27    1.1       hwr  *
     28    1.1       hwr  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     29    1.1       hwr  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     30    1.1       hwr  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     31    1.1       hwr  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     32    1.1       hwr  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     33    1.1       hwr  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     34    1.1       hwr  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     35    1.1       hwr  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     36    1.1       hwr  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     37    1.1       hwr  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     38    1.1       hwr  * POSSIBILITY OF SUCH DAMAGE.
     39    1.1       hwr  */
     40    1.1       hwr 
     41    1.1       hwr /*
     42    1.1       hwr  * Encapsulate L3 protocols into IP
     43    1.1       hwr  * See RFC 1701 and 1702 for more details.
     44    1.1       hwr  * If_gre is compatible with Cisco GRE tunnels, so you can
     45    1.1       hwr  * have a NetBSD box as the other end of a tunnel interface of a Cisco
     46    1.1       hwr  * router. See gre(4) for more details.
     47    1.6       hwr  * Also supported:  IP in IP encaps (proto 55) as of RFC 2004
     48    1.1       hwr  */
     49   1.22     lukem 
     50   1.22     lukem #include <sys/cdefs.h>
     51  1.101       skd __KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1.101 2007/08/20 04:49:41 skd Exp $");
     52    1.1       hwr 
     53   1.62    dyoung #include "opt_gre.h"
     54    1.1       hwr #include "opt_inet.h"
     55    1.1       hwr #include "bpfilter.h"
     56    1.1       hwr 
     57   1.54  christos #ifdef INET
     58    1.1       hwr #include <sys/param.h>
     59   1.62    dyoung #include <sys/file.h>
     60   1.62    dyoung #include <sys/filedesc.h>
     61    1.1       hwr #include <sys/malloc.h>
     62    1.1       hwr #include <sys/mbuf.h>
     63   1.13    martin #include <sys/proc.h>
     64    1.1       hwr #include <sys/protosw.h>
     65    1.1       hwr #include <sys/socket.h>
     66   1.62    dyoung #include <sys/socketvar.h>
     67    1.1       hwr #include <sys/ioctl.h>
     68   1.10   thorpej #include <sys/queue.h>
     69    1.1       hwr #if __NetBSD__
     70    1.1       hwr #include <sys/systm.h>
     71   1.62    dyoung #include <sys/sysctl.h>
     72   1.60      elad #include <sys/kauth.h>
     73    1.1       hwr #endif
     74    1.1       hwr 
     75   1.93    dyoung #include <sys/kernel.h>
     76   1.93    dyoung #include <sys/mutex.h>
     77   1.93    dyoung #include <sys/condvar.h>
     78   1.62    dyoung #include <sys/kthread.h>
     79   1.62    dyoung 
     80    1.1       hwr #include <machine/cpu.h>
     81    1.1       hwr 
     82    1.1       hwr #include <net/ethertypes.h>
     83    1.1       hwr #include <net/if.h>
     84    1.1       hwr #include <net/if_types.h>
     85    1.1       hwr #include <net/netisr.h>
     86    1.1       hwr #include <net/route.h>
     87    1.1       hwr 
     88    1.1       hwr #ifdef INET
     89    1.1       hwr #include <netinet/in.h>
     90    1.1       hwr #include <netinet/in_systm.h>
     91    1.1       hwr #include <netinet/in_var.h>
     92    1.1       hwr #include <netinet/ip.h>
     93    1.1       hwr #include <netinet/ip_var.h>
     94    1.1       hwr #else
     95    1.4   thorpej #error "Huh? if_gre without inet?"
     96    1.1       hwr #endif
     97    1.1       hwr 
     98    1.1       hwr 
     99    1.1       hwr #ifdef NETATALK
    100    1.1       hwr #include <netatalk/at.h>
    101    1.1       hwr #include <netatalk/at_var.h>
    102    1.1       hwr #include <netatalk/at_extern.h>
    103    1.1       hwr #endif
    104    1.1       hwr 
    105    1.1       hwr #if NBPFILTER > 0
    106    1.1       hwr #include <sys/time.h>
    107    1.1       hwr #include <net/bpf.h>
    108    1.1       hwr #endif
    109    1.1       hwr 
    110    1.1       hwr #include <net/if_gre.h>
    111    1.1       hwr 
    112  1.101       skd #include <compat/sys/socket.h>
    113   1.94  christos #include <compat/sys/sockio.h>
    114   1.20    itojun /*
    115   1.27    martin  * It is not easy to calculate the right value for a GRE MTU.
    116   1.27    martin  * We leave this task to the admin and use the same default that
    117   1.27    martin  * other vendors use.
    118   1.20    itojun  */
    119   1.27    martin #define GREMTU 1476
    120    1.1       hwr 
    121   1.62    dyoung #ifdef GRE_DEBUG
    122   1.62    dyoung #define	GRE_DPRINTF(__sc, __fmt, ...)				\
    123   1.62    dyoung 	do {							\
    124   1.62    dyoung 		if (((__sc)->sc_if.if_flags & IFF_DEBUG) != 0)	\
    125   1.62    dyoung 			printf(__fmt, __VA_ARGS__);		\
    126   1.62    dyoung 	} while (/*CONSTCOND*/0)
    127   1.62    dyoung #else
    128   1.62    dyoung #define	GRE_DPRINTF(__sc, __fmt, ...)	do { } while (/*CONSTCOND*/0)
    129   1.62    dyoung #endif /* GRE_DEBUG */
    130   1.62    dyoung 
    131   1.11   thorpej struct gre_softc_head gre_softc_list;
    132   1.26    martin int ip_gre_ttl = GRE_TTL;
    133    1.1       hwr 
    134   1.59   thorpej static int	gre_clone_create(struct if_clone *, int);
    135   1.59   thorpej static int	gre_clone_destroy(struct ifnet *);
    136   1.10   thorpej 
    137   1.59   thorpej static struct if_clone gre_cloner =
    138   1.10   thorpej     IF_CLONE_INITIALIZER("gre", gre_clone_create, gre_clone_destroy);
    139    1.1       hwr 
    140   1.84    dyoung static int	gre_output(struct ifnet *, struct mbuf *,
    141   1.84    dyoung 			   const struct sockaddr *, struct rtentry *);
    142   1.88  christos static int	gre_ioctl(struct ifnet *, u_long, void *);
    143    1.1       hwr 
    144   1.59   thorpej static int	gre_compute_route(struct gre_softc *sc);
    145   1.59   thorpej 
    146   1.93    dyoung static void gre_closef(struct file **, struct lwp *);
    147   1.62    dyoung static int gre_getsockname(struct socket *, struct mbuf *, struct lwp *);
    148   1.62    dyoung static int gre_getpeername(struct socket *, struct mbuf *, struct lwp *);
    149   1.62    dyoung static int gre_getnames(struct socket *, struct lwp *, struct sockaddr_in *,
    150   1.62    dyoung     struct sockaddr_in *);
    151   1.62    dyoung 
    152   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    153   1.62    dyoung static void
    154   1.93    dyoung gre_stop(struct gre_softc *sc)
    155   1.62    dyoung {
    156   1.93    dyoung 	sc->sc_running = 0;
    157   1.93    dyoung 	cv_signal(&sc->sc_join_cv);
    158   1.62    dyoung }
    159   1.62    dyoung 
    160   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    161   1.62    dyoung static void
    162   1.93    dyoung gre_join(struct gre_softc *sc)
    163   1.62    dyoung {
    164   1.93    dyoung 	while (sc->sc_running != 0)
    165   1.93    dyoung 		cv_wait(&sc->sc_join_cv, &sc->sc_mtx);
    166   1.62    dyoung }
    167   1.62    dyoung 
    168   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    169   1.62    dyoung static void
    170   1.62    dyoung gre_wakeup(struct gre_softc *sc)
    171   1.62    dyoung {
    172   1.62    dyoung 	GRE_DPRINTF(sc, "%s: enter\n", __func__);
    173   1.93    dyoung 	sc->sc_haswork = 1;
    174   1.93    dyoung 	cv_signal(&sc->sc_work_cv);
    175   1.62    dyoung }
    176   1.62    dyoung 
    177   1.59   thorpej static int
    178   1.59   thorpej gre_clone_create(struct if_clone *ifc, int unit)
    179    1.1       hwr {
    180    1.8  explorer 	struct gre_softc *sc;
    181    1.1       hwr 
    182   1.10   thorpej 	sc = malloc(sizeof(struct gre_softc), M_DEVBUF, M_WAITOK);
    183   1.10   thorpej 	memset(sc, 0, sizeof(struct gre_softc));
    184   1.93    dyoung 	mutex_init(&sc->sc_mtx, MUTEX_DRIVER, IPL_NET);
    185   1.93    dyoung 	cv_init(&sc->sc_work_cv, "gre work");
    186   1.93    dyoung 	cv_init(&sc->sc_join_cv, "gre join");
    187   1.93    dyoung 	cv_init(&sc->sc_soparm_cv, "gre soparm");
    188   1.10   thorpej 
    189   1.50    itojun 	snprintf(sc->sc_if.if_xname, sizeof(sc->sc_if.if_xname), "%s%d",
    190   1.50    itojun 	    ifc->ifc_name, unit);
    191   1.10   thorpej 	sc->sc_if.if_softc = sc;
    192   1.51      tron 	sc->sc_if.if_type = IFT_TUNNEL;
    193   1.34    itojun 	sc->sc_if.if_addrlen = 0;
    194   1.10   thorpej 	sc->sc_if.if_hdrlen = 24; /* IP + GRE */
    195   1.15   thorpej 	sc->sc_if.if_dlt = DLT_NULL;
    196   1.20    itojun 	sc->sc_if.if_mtu = GREMTU;
    197   1.10   thorpej 	sc->sc_if.if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
    198   1.10   thorpej 	sc->sc_if.if_output = gre_output;
    199   1.10   thorpej 	sc->sc_if.if_ioctl = gre_ioctl;
    200   1.10   thorpej 	sc->g_dst.s_addr = sc->g_src.s_addr = INADDR_ANY;
    201   1.62    dyoung 	sc->g_dstport = sc->g_srcport = 0;
    202   1.75    dyoung 	sc->sc_proto = IPPROTO_GRE;
    203   1.64    dyoung 	sc->sc_snd.ifq_maxlen = 256;
    204   1.35    itojun 	sc->sc_if.if_flags |= IFF_LINK0;
    205   1.10   thorpej 	if_attach(&sc->sc_if);
    206   1.16   thorpej 	if_alloc_sadl(&sc->sc_if);
    207    1.1       hwr #if NBPFILTER > 0
    208   1.14   thorpej 	bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int32_t));
    209    1.1       hwr #endif
    210   1.10   thorpej 	LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list);
    211   1.87    dyoung 	return 0;
    212   1.10   thorpej }
    213    1.1       hwr 
    214   1.59   thorpej static int
    215   1.59   thorpej gre_clone_destroy(struct ifnet *ifp)
    216   1.10   thorpej {
    217   1.10   thorpej 	struct gre_softc *sc = ifp->if_softc;
    218   1.10   thorpej 
    219   1.10   thorpej 	LIST_REMOVE(sc, sc_list);
    220   1.10   thorpej #if NBPFILTER > 0
    221   1.10   thorpej 	bpfdetach(ifp);
    222   1.10   thorpej #endif
    223   1.93    dyoung 	if_detach(ifp);
    224   1.93    dyoung 	mutex_enter(&sc->sc_mtx);
    225   1.62    dyoung 	gre_wakeup(sc);
    226   1.93    dyoung 	gre_join(sc);
    227   1.93    dyoung 	mutex_exit(&sc->sc_mtx);
    228   1.85    dyoung 	rtcache_free(&sc->route);
    229   1.93    dyoung 
    230   1.93    dyoung 	cv_destroy(&sc->sc_soparm_cv);
    231   1.93    dyoung 	cv_destroy(&sc->sc_join_cv);
    232   1.93    dyoung 	cv_destroy(&sc->sc_work_cv);
    233   1.93    dyoung 	mutex_destroy(&sc->sc_mtx);
    234   1.10   thorpej 	free(sc, M_DEVBUF);
    235   1.53     peter 
    236   1.87    dyoung 	return 0;
    237    1.1       hwr }
    238    1.1       hwr 
    239   1.62    dyoung static void
    240   1.88  christos gre_receive(struct socket *so, void *arg, int waitflag)
    241   1.62    dyoung {
    242   1.62    dyoung 	struct gre_softc *sc = (struct gre_softc *)arg;
    243   1.62    dyoung 
    244   1.62    dyoung 	GRE_DPRINTF(sc, "%s: enter\n", __func__);
    245   1.62    dyoung 
    246   1.62    dyoung 	gre_wakeup(sc);
    247   1.62    dyoung }
    248   1.62    dyoung 
    249   1.62    dyoung static void
    250   1.88  christos gre_upcall_add(struct socket *so, void *arg)
    251   1.62    dyoung {
    252   1.62    dyoung 	/* XXX What if the kernel already set an upcall? */
    253   1.62    dyoung 	so->so_upcallarg = arg;
    254   1.62    dyoung 	so->so_upcall = gre_receive;
    255   1.62    dyoung 	so->so_rcv.sb_flags |= SB_UPCALL;
    256   1.62    dyoung }
    257   1.62    dyoung 
    258   1.62    dyoung static void
    259   1.62    dyoung gre_upcall_remove(struct socket *so)
    260   1.62    dyoung {
    261   1.62    dyoung 	/* XXX What if the kernel already set an upcall? */
    262   1.62    dyoung 	so->so_rcv.sb_flags &= ~SB_UPCALL;
    263   1.62    dyoung 	so->so_upcallarg = NULL;
    264   1.62    dyoung 	so->so_upcall = NULL;
    265   1.62    dyoung }
    266   1.62    dyoung 
    267   1.62    dyoung static void
    268   1.62    dyoung gre_sodestroy(struct socket **sop)
    269   1.62    dyoung {
    270   1.62    dyoung 	gre_upcall_remove(*sop);
    271   1.62    dyoung 	soshutdown(*sop, SHUT_RDWR);
    272   1.62    dyoung 	soclose(*sop);
    273   1.62    dyoung 	*sop = NULL;
    274   1.62    dyoung }
    275   1.62    dyoung 
    276   1.62    dyoung static struct mbuf *
    277   1.74  christos gre_getsockmbuf(struct socket *so)
    278   1.62    dyoung {
    279   1.62    dyoung 	struct mbuf *m;
    280   1.62    dyoung 
    281   1.62    dyoung 	m = m_get(M_WAIT, MT_SONAME);
    282   1.62    dyoung 	if (m != NULL)
    283   1.62    dyoung 		MCLAIM(m, so->so_mowner);
    284   1.62    dyoung 	return m;
    285   1.62    dyoung }
    286   1.62    dyoung 
    287   1.62    dyoung static int
    288   1.62    dyoung gre_socreate1(struct gre_softc *sc, struct lwp *l, struct gre_soparm *sp,
    289   1.62    dyoung     struct socket **sop)
    290   1.62    dyoung {
    291   1.62    dyoung 	int rc;
    292   1.62    dyoung 	struct mbuf *m;
    293   1.62    dyoung 	struct sockaddr_in *sin;
    294   1.62    dyoung 	struct socket *so;
    295   1.62    dyoung 
    296   1.62    dyoung 	GRE_DPRINTF(sc, "%s: enter\n", __func__);
    297   1.62    dyoung 	rc = socreate(AF_INET, sop, SOCK_DGRAM, IPPROTO_UDP, l);
    298   1.62    dyoung 	if (rc != 0) {
    299   1.62    dyoung 		GRE_DPRINTF(sc, "%s: socreate failed\n", __func__);
    300   1.62    dyoung 		return rc;
    301   1.62    dyoung 	}
    302   1.62    dyoung 
    303   1.62    dyoung 	so = *sop;
    304   1.62    dyoung 
    305   1.90    dyoung 	gre_upcall_add(so, sc);
    306   1.62    dyoung 	if ((m = gre_getsockmbuf(so)) == NULL) {
    307   1.62    dyoung 		rc = ENOBUFS;
    308   1.62    dyoung 		goto out;
    309   1.62    dyoung 	}
    310   1.62    dyoung 	sin = mtod(m, struct sockaddr_in *);
    311   1.62    dyoung 	sin->sin_len = m->m_len = sizeof(struct sockaddr_in);
    312   1.62    dyoung 	sin->sin_family = AF_INET;
    313   1.62    dyoung 	sin->sin_addr = sc->g_src;
    314   1.62    dyoung 	sin->sin_port = sc->g_srcport;
    315   1.62    dyoung 
    316   1.62    dyoung 	GRE_DPRINTF(sc, "%s: bind 0x%08" PRIx32 " port %d\n", __func__,
    317   1.62    dyoung 	    sin->sin_addr.s_addr, ntohs(sin->sin_port));
    318   1.62    dyoung 	if ((rc = sobind(so, m, l)) != 0) {
    319   1.62    dyoung 		GRE_DPRINTF(sc, "%s: sobind failed\n", __func__);
    320   1.62    dyoung 		goto out;
    321   1.62    dyoung 	}
    322   1.62    dyoung 
    323   1.62    dyoung 	if (sc->g_srcport == 0) {
    324   1.69    dyoung 		if ((rc = gre_getsockname(so, m, l)) != 0) {
    325   1.62    dyoung 			GRE_DPRINTF(sc, "%s: gre_getsockname failed\n",
    326   1.62    dyoung 			    __func__);
    327   1.62    dyoung 			goto out;
    328   1.62    dyoung 		}
    329   1.62    dyoung 		sc->g_srcport = sin->sin_port;
    330   1.62    dyoung 	}
    331   1.62    dyoung 
    332   1.62    dyoung 	sin->sin_addr = sc->g_dst;
    333   1.62    dyoung 	sin->sin_port = sc->g_dstport;
    334   1.62    dyoung 
    335   1.68    dyoung 	if ((rc = soconnect(so, m, l)) != 0) {
    336   1.62    dyoung 		GRE_DPRINTF(sc, "%s: soconnect failed\n", __func__);
    337   1.62    dyoung 		goto out;
    338   1.62    dyoung 	}
    339   1.62    dyoung 
    340   1.62    dyoung 	*mtod(m, int *) = ip_gre_ttl;
    341   1.76    dyoung 	m->m_len = sizeof(int);
    342  1.100     joerg 	KASSERT(so->so_proto && so->so_proto->pr_ctloutput);
    343   1.62    dyoung 	rc = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so, IPPROTO_IP, IP_TTL,
    344   1.62    dyoung 	    &m);
    345   1.62    dyoung 	m = NULL;
    346   1.62    dyoung 	if (rc != 0) {
    347   1.62    dyoung 		printf("%s: setopt ttl failed\n", __func__);
    348   1.62    dyoung 		rc = 0;
    349   1.62    dyoung 	}
    350   1.62    dyoung out:
    351   1.62    dyoung 	m_freem(m);
    352   1.62    dyoung 
    353   1.62    dyoung 	if (rc != 0)
    354   1.62    dyoung 		gre_sodestroy(sop);
    355   1.62    dyoung 	else
    356   1.63    dyoung 		*sp = sc->sc_soparm;
    357   1.62    dyoung 
    358   1.62    dyoung 	return rc;
    359   1.62    dyoung }
    360   1.62    dyoung 
    361   1.62    dyoung static void
    362   1.62    dyoung gre_thread1(struct gre_softc *sc, struct lwp *l)
    363   1.62    dyoung {
    364   1.93    dyoung 	int flags, rc;
    365   1.62    dyoung 	const struct gre_h *gh;
    366   1.62    dyoung 	struct ifnet *ifp = &sc->sc_if;
    367   1.62    dyoung 	struct mbuf *m;
    368   1.62    dyoung 	struct socket *so = NULL;
    369   1.62    dyoung 	struct uio uio;
    370   1.62    dyoung 	struct gre_soparm sp;
    371   1.93    dyoung 	struct file *fp = NULL;
    372   1.62    dyoung 
    373   1.62    dyoung 	GRE_DPRINTF(sc, "%s: enter\n", __func__);
    374   1.93    dyoung 	mutex_enter(&sc->sc_mtx);
    375   1.62    dyoung 
    376   1.93    dyoung 	sc->sc_haswork = 1;
    377   1.62    dyoung 
    378   1.62    dyoung 	memset(&sp, 0, sizeof(sp));
    379   1.62    dyoung 	memset(&uio, 0, sizeof(uio));
    380   1.62    dyoung 
    381   1.62    dyoung 	ifp->if_flags |= IFF_RUNNING;
    382   1.62    dyoung 
    383   1.62    dyoung 	for (;;) {
    384   1.93    dyoung 		while (sc->sc_haswork == 0) {
    385   1.62    dyoung 			GRE_DPRINTF(sc, "%s: sleeping\n", __func__);
    386   1.93    dyoung 			cv_wait(&sc->sc_work_cv, &sc->sc_mtx);
    387   1.62    dyoung 		}
    388   1.93    dyoung 		sc->sc_haswork = 0;
    389   1.62    dyoung 		GRE_DPRINTF(sc, "%s: awake\n", __func__);
    390   1.62    dyoung 		if ((ifp->if_flags & IFF_UP) != IFF_UP) {
    391   1.62    dyoung 			GRE_DPRINTF(sc, "%s: not up & running; exiting\n",
    392   1.62    dyoung 			    __func__);
    393   1.62    dyoung 			break;
    394   1.62    dyoung 		}
    395   1.75    dyoung 		if (sc->sc_proto != IPPROTO_UDP) {
    396   1.62    dyoung 			GRE_DPRINTF(sc, "%s: not udp; exiting\n", __func__);
    397   1.62    dyoung 			break;
    398   1.62    dyoung 		}
    399   1.62    dyoung 		/* XXX optimize */
    400   1.93    dyoung 		if (so == NULL || sc->sc_fp != NULL ||
    401   1.93    dyoung 		    memcmp(&sp, &sc->sc_soparm, sizeof(sp)) != 0) {
    402   1.62    dyoung 			GRE_DPRINTF(sc, "%s: parameters changed\n", __func__);
    403   1.62    dyoung 
    404   1.93    dyoung 			if (fp != NULL) {
    405   1.93    dyoung 				gre_closef(&fp, curlwp);
    406   1.62    dyoung 				so = NULL;
    407   1.62    dyoung 			} else if (so != NULL)
    408   1.62    dyoung 				gre_sodestroy(&so);
    409   1.62    dyoung 
    410   1.62    dyoung 			if (sc->sc_fp != NULL) {
    411   1.93    dyoung 				fp = sc->sc_fp;
    412   1.93    dyoung 				sc->sc_fp = NULL;
    413   1.93    dyoung 				so = (struct socket *)fp->f_data;
    414   1.90    dyoung 				gre_upcall_add(so, sc);
    415   1.63    dyoung 				sp = sc->sc_soparm;
    416   1.62    dyoung 			} else if (gre_socreate1(sc, l, &sp, &so) != 0)
    417   1.62    dyoung 				goto out;
    418   1.62    dyoung 		}
    419   1.93    dyoung 		cv_signal(&sc->sc_soparm_cv);
    420   1.62    dyoung 		for (;;) {
    421   1.62    dyoung 			flags = MSG_DONTWAIT;
    422   1.62    dyoung 			uio.uio_resid = 1000000;
    423   1.62    dyoung 			rc = (*so->so_receive)(so, NULL, &uio, &m, NULL,
    424   1.62    dyoung 			    &flags);
    425   1.62    dyoung 			/* TBD Back off if ECONNREFUSED (indicates
    426   1.62    dyoung 			 * ICMP Port Unreachable)?
    427   1.62    dyoung 			 */
    428   1.62    dyoung 			if (rc == EWOULDBLOCK) {
    429   1.62    dyoung 				GRE_DPRINTF(sc, "%s: so_receive EWOULDBLOCK\n",
    430   1.62    dyoung 				    __func__);
    431   1.62    dyoung 				break;
    432   1.62    dyoung 			} else if (rc != 0 || m == NULL) {
    433   1.62    dyoung 				GRE_DPRINTF(sc, "%s: rc %d m %p\n",
    434   1.62    dyoung 				    ifp->if_xname, rc, (void *)m);
    435   1.62    dyoung 				continue;
    436   1.62    dyoung 			} else
    437   1.62    dyoung 				GRE_DPRINTF(sc, "%s: so_receive ok\n",
    438   1.62    dyoung 				    __func__);
    439   1.62    dyoung 			if (m->m_len < sizeof(*gh) &&
    440   1.62    dyoung 			    (m = m_pullup(m, sizeof(*gh))) == NULL) {
    441   1.62    dyoung 				GRE_DPRINTF(sc, "%s: m_pullup failed\n",
    442   1.62    dyoung 				    __func__);
    443   1.62    dyoung 				continue;
    444   1.62    dyoung 			}
    445   1.62    dyoung 			gh = mtod(m, const struct gre_h *);
    446   1.62    dyoung 
    447   1.93    dyoung 			if (gre_input3(sc, m, 0, gh, 1) == 0) {
    448   1.62    dyoung 				GRE_DPRINTF(sc, "%s: dropping unsupported\n",
    449   1.62    dyoung 				    __func__);
    450   1.62    dyoung 				m_freem(m);
    451   1.62    dyoung 			}
    452   1.62    dyoung 		}
    453   1.62    dyoung 		for (;;) {
    454   1.62    dyoung 			IF_DEQUEUE(&sc->sc_snd, m);
    455   1.62    dyoung 			if (m == NULL)
    456   1.62    dyoung 				break;
    457   1.62    dyoung 			GRE_DPRINTF(sc, "%s: dequeue\n", __func__);
    458   1.62    dyoung 			if ((so->so_state & SS_ISCONNECTED) == 0) {
    459   1.62    dyoung 				GRE_DPRINTF(sc, "%s: not connected\n",
    460   1.62    dyoung 				    __func__);
    461   1.62    dyoung 				m_freem(m);
    462   1.62    dyoung 				continue;
    463   1.62    dyoung 			}
    464   1.62    dyoung 			rc = (*so->so_send)(so, NULL, NULL, m, NULL, 0, l);
    465   1.62    dyoung 			/* XXX handle ENOBUFS? */
    466   1.62    dyoung 			if (rc != 0)
    467   1.62    dyoung 				GRE_DPRINTF(sc, "%s: so_send failed\n",
    468   1.62    dyoung 				    __func__);
    469   1.62    dyoung 		}
    470   1.62    dyoung 	}
    471   1.93    dyoung 	if (fp != NULL) {
    472   1.62    dyoung 		GRE_DPRINTF(sc, "%s: removing upcall\n", __func__);
    473   1.62    dyoung 		gre_upcall_remove(so);
    474   1.66    dyoung 	} else if (so != NULL)
    475   1.62    dyoung 		gre_sodestroy(&so);
    476   1.62    dyoung out:
    477   1.62    dyoung 	GRE_DPRINTF(sc, "%s: stopping\n", __func__);
    478   1.93    dyoung 	if (fp != NULL)
    479   1.93    dyoung 		gre_closef(&fp, curlwp);
    480   1.75    dyoung 	if (sc->sc_proto == IPPROTO_UDP)
    481   1.62    dyoung 		ifp->if_flags &= ~IFF_RUNNING;
    482   1.64    dyoung 	while (!IF_IS_EMPTY(&sc->sc_snd)) {
    483   1.64    dyoung 		IF_DEQUEUE(&sc->sc_snd, m);
    484   1.64    dyoung 		m_freem(m);
    485   1.64    dyoung 	}
    486   1.93    dyoung 	gre_stop(sc);
    487   1.62    dyoung 	/* must not touch sc after this! */
    488   1.62    dyoung 	GRE_DPRINTF(sc, "%s: restore ipl\n", __func__);
    489   1.93    dyoung 	mutex_exit(&sc->sc_mtx);
    490   1.62    dyoung }
    491   1.62    dyoung 
    492   1.62    dyoung static void
    493   1.62    dyoung gre_thread(void *arg)
    494   1.62    dyoung {
    495   1.62    dyoung 	struct gre_softc *sc = (struct gre_softc *)arg;
    496   1.62    dyoung 
    497   1.62    dyoung 	gre_thread1(sc, curlwp);
    498   1.62    dyoung 	/* must not touch sc after this! */
    499   1.62    dyoung 	kthread_exit(0);
    500   1.62    dyoung }
    501   1.62    dyoung 
    502   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    503   1.62    dyoung int
    504   1.89    dyoung gre_input3(struct gre_softc *sc, struct mbuf *m, int hlen,
    505   1.93    dyoung     const struct gre_h *gh, int mtx_held)
    506   1.62    dyoung {
    507   1.62    dyoung 	u_int16_t flags;
    508   1.62    dyoung #if NBPFILTER > 0
    509   1.62    dyoung 	u_int32_t af = AF_INET;		/* af passed to BPF tap */
    510   1.62    dyoung #endif
    511   1.93    dyoung 	int isr;
    512   1.62    dyoung 	struct ifqueue *ifq;
    513   1.62    dyoung 
    514   1.62    dyoung 	sc->sc_if.if_ipackets++;
    515   1.62    dyoung 	sc->sc_if.if_ibytes += m->m_pkthdr.len;
    516   1.62    dyoung 
    517   1.89    dyoung 	hlen += sizeof(struct gre_h);
    518   1.62    dyoung 
    519   1.89    dyoung 	/* process GRE flags as packet can be of variable len */
    520   1.89    dyoung 	flags = ntohs(gh->flags);
    521   1.62    dyoung 
    522   1.89    dyoung 	/* Checksum & Offset are present */
    523   1.89    dyoung 	if ((flags & GRE_CP) | (flags & GRE_RP))
    524   1.89    dyoung 		hlen += 4;
    525   1.89    dyoung 	/* We don't support routing fields (variable length) */
    526   1.89    dyoung 	if (flags & GRE_RP) {
    527   1.89    dyoung 		sc->sc_if.if_ierrors++;
    528   1.89    dyoung 		return 0;
    529   1.89    dyoung 	}
    530   1.89    dyoung 	if (flags & GRE_KP)
    531   1.89    dyoung 		hlen += 4;
    532   1.89    dyoung 	if (flags & GRE_SP)
    533   1.89    dyoung 		hlen += 4;
    534   1.89    dyoung 
    535   1.89    dyoung 	switch (ntohs(gh->ptype)) { /* ethertypes */
    536   1.89    dyoung 	case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */
    537   1.89    dyoung 		ifq = &ipintrq;          /* we are in ip_input */
    538   1.89    dyoung 		isr = NETISR_IP;
    539   1.89    dyoung 		break;
    540   1.62    dyoung #ifdef NETATALK
    541   1.89    dyoung 	case ETHERTYPE_ATALK:
    542   1.89    dyoung 		ifq = &atintrq1;
    543   1.89    dyoung 		isr = NETISR_ATALK;
    544   1.62    dyoung #if NBPFILTER > 0
    545   1.89    dyoung 		af = AF_APPLETALK;
    546   1.62    dyoung #endif
    547   1.89    dyoung 		break;
    548   1.62    dyoung #endif
    549   1.62    dyoung #ifdef INET6
    550   1.89    dyoung 	case ETHERTYPE_IPV6:
    551   1.89    dyoung 		GRE_DPRINTF(sc, "%s: IPv6 packet\n", __func__);
    552   1.89    dyoung 		ifq = &ip6intrq;
    553   1.89    dyoung 		isr = NETISR_IPV6;
    554   1.62    dyoung #if NBPFILTER > 0
    555   1.89    dyoung 		af = AF_INET6;
    556   1.62    dyoung #endif
    557   1.89    dyoung 		break;
    558   1.62    dyoung #endif
    559   1.89    dyoung 	default:	   /* others not yet supported */
    560   1.90    dyoung 		GRE_DPRINTF(sc, "%s: unhandled ethertype 0x%04x\n", __func__,
    561   1.89    dyoung 		    ntohs(gh->ptype));
    562   1.89    dyoung 		sc->sc_if.if_noproto++;
    563   1.87    dyoung 		return 0;
    564   1.62    dyoung 	}
    565   1.62    dyoung 
    566   1.62    dyoung 	if (hlen > m->m_pkthdr.len) {
    567   1.62    dyoung 		m_freem(m);
    568   1.62    dyoung 		sc->sc_if.if_ierrors++;
    569   1.87    dyoung 		return EINVAL;
    570   1.62    dyoung 	}
    571   1.62    dyoung 	m_adj(m, hlen);
    572   1.62    dyoung 
    573   1.62    dyoung #if NBPFILTER > 0
    574   1.62    dyoung 	if (sc->sc_if.if_bpf != NULL)
    575   1.62    dyoung 		bpf_mtap_af(sc->sc_if.if_bpf, af, m);
    576   1.62    dyoung #endif /*NBPFILTER > 0*/
    577   1.62    dyoung 
    578   1.62    dyoung 	m->m_pkthdr.rcvif = &sc->sc_if;
    579   1.62    dyoung 
    580   1.93    dyoung 	if (!mtx_held)
    581   1.93    dyoung 		mutex_enter(&sc->sc_mtx);
    582   1.62    dyoung 	if (IF_QFULL(ifq)) {
    583   1.62    dyoung 		IF_DROP(ifq);
    584   1.62    dyoung 		m_freem(m);
    585   1.62    dyoung 	} else {
    586   1.62    dyoung 		IF_ENQUEUE(ifq, m);
    587   1.62    dyoung 	}
    588   1.62    dyoung 	/* we need schednetisr since the address family may change */
    589   1.62    dyoung 	schednetisr(isr);
    590   1.93    dyoung 	if (!mtx_held)
    591   1.93    dyoung 		mutex_exit(&sc->sc_mtx);
    592   1.62    dyoung 
    593   1.87    dyoung 	return 1;	/* packet is done, no further processing needed */
    594   1.62    dyoung }
    595   1.62    dyoung 
    596   1.20    itojun /*
    597    1.1       hwr  * The output routine. Takes a packet and encapsulates it in the protocol
    598   1.75    dyoung  * given by sc->sc_proto. See also RFC 1701 and RFC 2004
    599    1.1       hwr  */
    600   1.59   thorpej static int
    601   1.84    dyoung gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
    602   1.74  christos 	   struct rtentry *rt)
    603    1.1       hwr {
    604   1.89    dyoung 	int error = 0, hlen, msiz;
    605   1.10   thorpej 	struct gre_softc *sc = ifp->if_softc;
    606   1.62    dyoung 	struct greip *gi;
    607   1.62    dyoung 	struct gre_h *gh;
    608   1.62    dyoung 	struct ip *eip, *ip;
    609   1.56        is 	u_int8_t ip_tos = 0;
    610   1.48    itojun 	u_int16_t etype = 0;
    611   1.20    itojun 	struct mobile_h mob_h;
    612   1.24    martin 
    613   1.99     seanb 	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
    614   1.99     seanb 	    (IFF_UP | IFF_RUNNING) ||
    615   1.37    itojun 	    sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY) {
    616   1.37    itojun 		m_freem(m);
    617   1.38    itojun 		error = ENETDOWN;
    618   1.38    itojun 		goto end;
    619   1.37    itojun 	}
    620    1.1       hwr 
    621   1.62    dyoung 	gi = NULL;
    622   1.41    itojun 	ip = NULL;
    623    1.1       hwr 
    624    1.1       hwr #if NBPFILTER >0
    625   1.52  christos 	if (ifp->if_bpf)
    626   1.52  christos 		bpf_mtap_af(ifp->if_bpf, dst->sa_family, m);
    627    1.1       hwr #endif
    628    1.1       hwr 
    629   1.26    martin 	m->m_flags &= ~(M_BCAST|M_MCAST);
    630    1.1       hwr 
    631   1.75    dyoung 	switch (sc->sc_proto) {
    632   1.62    dyoung 	case IPPROTO_MOBILE:
    633   1.89    dyoung 		if (dst->sa_family != AF_INET) {
    634   1.89    dyoung 			IF_DROP(&ifp->if_snd);
    635   1.89    dyoung 			m_freem(m);
    636   1.89    dyoung 			error = EINVAL;
    637   1.89    dyoung 			goto end;
    638   1.89    dyoung 		}
    639   1.89    dyoung 
    640   1.89    dyoung 		if (M_UNWRITABLE(m, sizeof(*ip)) &&
    641   1.89    dyoung 		    (m = m_pullup(m, sizeof(*ip))) == NULL) {
    642   1.89    dyoung 			error = ENOBUFS;
    643   1.89    dyoung 			goto end;
    644   1.89    dyoung 		}
    645   1.89    dyoung 		ip = mtod(m, struct ip *);
    646    1.3       hwr 
    647   1.89    dyoung 		memset(&mob_h, 0, MOB_H_SIZ_L);
    648   1.89    dyoung 		mob_h.proto = (ip->ip_p) << 8;
    649   1.89    dyoung 		mob_h.odst = ip->ip_dst.s_addr;
    650   1.89    dyoung 		ip->ip_dst.s_addr = sc->g_dst.s_addr;
    651    1.3       hwr 
    652   1.89    dyoung 		/*
    653   1.89    dyoung 		 * If the packet comes from our host, we only change
    654   1.89    dyoung 		 * the destination address in the IP header.
    655   1.89    dyoung 		 * Else we also need to save and change the source
    656   1.89    dyoung 		 */
    657   1.89    dyoung 		if (in_hosteq(ip->ip_src, sc->g_src)) {
    658   1.89    dyoung 			msiz = MOB_H_SIZ_S;
    659   1.89    dyoung 		} else {
    660   1.89    dyoung 			mob_h.proto |= MOB_H_SBIT;
    661   1.89    dyoung 			mob_h.osrc = ip->ip_src.s_addr;
    662   1.89    dyoung 			ip->ip_src.s_addr = sc->g_src.s_addr;
    663   1.89    dyoung 			msiz = MOB_H_SIZ_L;
    664   1.89    dyoung 		}
    665   1.89    dyoung 		HTONS(mob_h.proto);
    666   1.89    dyoung 		mob_h.hcrc = gre_in_cksum((u_int16_t *)&mob_h, msiz);
    667    1.3       hwr 
    668   1.89    dyoung 		M_PREPEND(m, msiz, M_DONTWAIT);
    669   1.89    dyoung 		if (m == NULL) {
    670   1.89    dyoung 			error = ENOBUFS;
    671   1.38    itojun 			goto end;
    672    1.3       hwr 		}
    673   1.89    dyoung 		/* XXX Assuming that ip does not dangle after
    674   1.89    dyoung 		 * M_PREPEND.  In practice, that's true, but
    675   1.90    dyoung 		 * that's not in M_PREPEND's contract.
    676   1.89    dyoung 		 */
    677   1.89    dyoung 		memmove(mtod(m, void *), ip, sizeof(*ip));
    678   1.89    dyoung 		ip = mtod(m, struct ip *);
    679   1.90    dyoung 		memcpy(ip + 1, &mob_h, (size_t)msiz);
    680   1.89    dyoung 		ip->ip_len = htons(ntohs(ip->ip_len) + msiz);
    681   1.62    dyoung 		break;
    682   1.62    dyoung 	case IPPROTO_UDP:
    683   1.62    dyoung 	case IPPROTO_GRE:
    684   1.62    dyoung 		GRE_DPRINTF(sc, "%s: dst->sa_family=%d\n", __func__,
    685   1.62    dyoung 		    dst->sa_family);
    686   1.20    itojun 		switch (dst->sa_family) {
    687    1.1       hwr 		case AF_INET:
    688   1.41    itojun 			ip = mtod(m, struct ip *);
    689   1.56        is 			ip_tos = ip->ip_tos;
    690    1.8  explorer 			etype = ETHERTYPE_IP;
    691    1.1       hwr 			break;
    692    1.1       hwr #ifdef NETATALK
    693    1.1       hwr 		case AF_APPLETALK:
    694    1.8  explorer 			etype = ETHERTYPE_ATALK;
    695    1.1       hwr 			break;
    696    1.1       hwr #endif
    697   1.56        is #ifdef INET6
    698   1.56        is 		case AF_INET6:
    699   1.56        is 			etype = ETHERTYPE_IPV6;
    700   1.56        is 			break;
    701   1.56        is #endif
    702    1.1       hwr 		default:
    703    1.1       hwr 			IF_DROP(&ifp->if_snd);
    704    1.1       hwr 			m_freem(m);
    705   1.38    itojun 			error = EAFNOSUPPORT;
    706   1.38    itojun 			goto end;
    707    1.1       hwr 		}
    708   1.62    dyoung 		break;
    709   1.62    dyoung 	default:
    710    1.1       hwr 		IF_DROP(&ifp->if_snd);
    711    1.1       hwr 		m_freem(m);
    712   1.38    itojun 		error = EINVAL;
    713   1.38    itojun 		goto end;
    714    1.1       hwr 	}
    715    1.1       hwr 
    716   1.75    dyoung 	switch (sc->sc_proto) {
    717   1.62    dyoung 	case IPPROTO_GRE:
    718   1.62    dyoung 		hlen = sizeof(struct greip);
    719   1.62    dyoung 		break;
    720   1.62    dyoung 	case IPPROTO_UDP:
    721   1.62    dyoung 		hlen = sizeof(struct gre_h);
    722   1.62    dyoung 		break;
    723   1.62    dyoung 	default:
    724   1.62    dyoung 		hlen = 0;
    725   1.62    dyoung 		break;
    726   1.62    dyoung 	}
    727   1.62    dyoung 
    728   1.62    dyoung 	M_PREPEND(m, hlen, M_DONTWAIT);
    729   1.62    dyoung 
    730   1.62    dyoung 	if (m == NULL) {
    731    1.1       hwr 		IF_DROP(&ifp->if_snd);
    732   1.38    itojun 		error = ENOBUFS;
    733   1.38    itojun 		goto end;
    734    1.1       hwr 	}
    735    1.1       hwr 
    736   1.75    dyoung 	switch (sc->sc_proto) {
    737   1.62    dyoung 	case IPPROTO_UDP:
    738   1.62    dyoung 		gh = mtod(m, struct gre_h *);
    739   1.62    dyoung 		memset(gh, 0, sizeof(*gh));
    740   1.62    dyoung 		gh->ptype = htons(etype);
    741   1.62    dyoung 		/* XXX Need to handle IP ToS.  Look at how I handle IP TTL. */
    742   1.62    dyoung 		break;
    743   1.62    dyoung 	case IPPROTO_GRE:
    744   1.62    dyoung 		gi = mtod(m, struct greip *);
    745   1.62    dyoung 		gh = &gi->gi_g;
    746   1.62    dyoung 		eip = &gi->gi_i;
    747    1.1       hwr 		/* we don't have any GRE flags for now */
    748   1.62    dyoung 		memset(gh, 0, sizeof(*gh));
    749   1.62    dyoung 		gh->ptype = htons(etype);
    750   1.62    dyoung 		eip->ip_src = sc->g_src;
    751   1.62    dyoung 		eip->ip_dst = sc->g_dst;
    752   1.62    dyoung 		eip->ip_hl = (sizeof(struct ip)) >> 2;
    753   1.62    dyoung 		eip->ip_ttl = ip_gre_ttl;
    754   1.62    dyoung 		eip->ip_tos = ip_tos;
    755   1.62    dyoung 		eip->ip_len = htons(m->m_pkthdr.len);
    756   1.75    dyoung 		eip->ip_p = sc->sc_proto;
    757   1.62    dyoung 		break;
    758   1.62    dyoung 	case IPPROTO_MOBILE:
    759   1.62    dyoung 		eip = mtod(m, struct ip *);
    760   1.75    dyoung 		eip->ip_p = sc->sc_proto;
    761   1.62    dyoung 		break;
    762   1.62    dyoung 	default:
    763   1.62    dyoung 		error = EPROTONOSUPPORT;
    764   1.62    dyoung 		m_freem(m);
    765   1.62    dyoung 		goto end;
    766    1.3       hwr 	}
    767    1.1       hwr 
    768    1.1       hwr 	ifp->if_opackets++;
    769    1.8  explorer 	ifp->if_obytes += m->m_pkthdr.len;
    770   1.62    dyoung 
    771    1.1       hwr 	/* send it off */
    772   1.75    dyoung 	if (sc->sc_proto == IPPROTO_UDP) {
    773   1.62    dyoung 		if (IF_QFULL(&sc->sc_snd)) {
    774   1.62    dyoung 			IF_DROP(&sc->sc_snd);
    775   1.62    dyoung 			error = ENOBUFS;
    776   1.62    dyoung 			m_freem(m);
    777   1.62    dyoung 		} else {
    778   1.62    dyoung 			IF_ENQUEUE(&sc->sc_snd, m);
    779   1.62    dyoung 			gre_wakeup(sc);
    780   1.62    dyoung 			error = 0;
    781   1.62    dyoung 		}
    782   1.81     joerg 		goto end;
    783   1.81     joerg 	}
    784   1.86    dyoung 	if (sc->route.ro_rt == NULL)
    785   1.86    dyoung 		rtcache_init(&sc->route);
    786   1.86    dyoung 	else
    787   1.86    dyoung 		rtcache_check(&sc->route);
    788   1.91    dyoung 	if (sc->route.ro_rt == NULL) {
    789   1.91    dyoung 		m_freem(m);
    790   1.81     joerg 		goto end;
    791   1.91    dyoung 	}
    792   1.91    dyoung 	if (sc->route.ro_rt->rt_ifp->if_softc == sc) {
    793   1.92    dyoung 		rtcache_clear(&sc->route);
    794   1.91    dyoung 		m_freem(m);
    795   1.91    dyoung 	} else
    796   1.92    dyoung 		error = ip_output(m, NULL, &sc->route, 0, NULL, NULL);
    797   1.38    itojun   end:
    798    1.8  explorer 	if (error)
    799    1.1       hwr 		ifp->if_oerrors++;
    800   1.87    dyoung 	return error;
    801    1.1       hwr }
    802    1.1       hwr 
    803   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    804   1.62    dyoung static int
    805   1.62    dyoung gre_kick(struct gre_softc *sc)
    806   1.62    dyoung {
    807   1.62    dyoung 	int rc;
    808   1.62    dyoung 	struct ifnet *ifp = &sc->sc_if;
    809   1.62    dyoung 
    810   1.75    dyoung 	if (sc->sc_proto == IPPROTO_UDP && (ifp->if_flags & IFF_UP) == IFF_UP &&
    811   1.93    dyoung 	    !sc->sc_running) {
    812   1.93    dyoung 		sc->sc_running = 1;
    813   1.98        ad 		rc = kthread_create(PRI_NONE, 0, NULL, gre_thread, sc,
    814   1.98        ad 		    NULL, ifp->if_xname);
    815   1.62    dyoung 		if (rc != 0)
    816   1.93    dyoung 			gre_stop(sc);
    817   1.62    dyoung 		return rc;
    818   1.62    dyoung 	} else {
    819   1.62    dyoung 		gre_wakeup(sc);
    820   1.62    dyoung 		return 0;
    821   1.62    dyoung 	}
    822   1.62    dyoung }
    823   1.62    dyoung 
    824   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    825   1.62    dyoung static int
    826   1.62    dyoung gre_getname(struct socket *so, int req, struct mbuf *nam, struct lwp *l)
    827   1.62    dyoung {
    828   1.93    dyoung 	return (*so->so_proto->pr_usrreq)(so, req, NULL, nam, NULL, l);
    829   1.62    dyoung }
    830   1.62    dyoung 
    831   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    832   1.62    dyoung static int
    833   1.62    dyoung gre_getsockname(struct socket *so, struct mbuf *nam, struct lwp *l)
    834   1.62    dyoung {
    835   1.62    dyoung 	return gre_getname(so, PRU_SOCKADDR, nam, l);
    836   1.62    dyoung }
    837   1.62    dyoung 
    838   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    839   1.62    dyoung static int
    840   1.62    dyoung gre_getpeername(struct socket *so, struct mbuf *nam, struct lwp *l)
    841   1.62    dyoung {
    842   1.62    dyoung 	return gre_getname(so, PRU_PEERADDR, nam, l);
    843   1.62    dyoung }
    844   1.62    dyoung 
    845   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    846   1.62    dyoung static int
    847   1.62    dyoung gre_getnames(struct socket *so, struct lwp *l, struct sockaddr_in *src,
    848   1.62    dyoung     struct sockaddr_in *dst)
    849   1.62    dyoung {
    850   1.62    dyoung 	struct mbuf *m;
    851   1.62    dyoung 	struct sockaddr_in *sin;
    852   1.62    dyoung 	int rc;
    853   1.62    dyoung 
    854   1.62    dyoung 	if ((m = gre_getsockmbuf(so)) == NULL)
    855   1.62    dyoung 		return ENOBUFS;
    856   1.62    dyoung 
    857   1.62    dyoung 	sin = mtod(m, struct sockaddr_in *);
    858   1.62    dyoung 
    859   1.62    dyoung 	if ((rc = gre_getsockname(so, m, l)) != 0)
    860   1.62    dyoung 		goto out;
    861   1.62    dyoung 	if (sin->sin_family != AF_INET) {
    862   1.62    dyoung 		rc = EAFNOSUPPORT;
    863   1.62    dyoung 		goto out;
    864   1.62    dyoung 	}
    865   1.62    dyoung 	*src = *sin;
    866   1.62    dyoung 
    867   1.62    dyoung 	if ((rc = gre_getpeername(so, m, l)) != 0)
    868   1.62    dyoung 		goto out;
    869   1.62    dyoung 	if (sin->sin_family != AF_INET) {
    870   1.62    dyoung 		rc = EAFNOSUPPORT;
    871   1.62    dyoung 		goto out;
    872   1.62    dyoung 	}
    873   1.62    dyoung 	*dst = *sin;
    874   1.62    dyoung 
    875   1.62    dyoung out:
    876   1.62    dyoung 	m_freem(m);
    877   1.62    dyoung 	return rc;
    878   1.62    dyoung }
    879   1.62    dyoung 
    880   1.93    dyoung static void
    881   1.93    dyoung gre_closef(struct file **fpp, struct lwp *l)
    882   1.93    dyoung {
    883   1.93    dyoung 	struct file *fp = *fpp;
    884   1.93    dyoung 
    885   1.93    dyoung 	simple_lock(&fp->f_slock);
    886   1.93    dyoung 	FILE_USE(fp);
    887   1.93    dyoung 	closef(fp, l);
    888   1.93    dyoung 	*fpp = NULL;
    889   1.93    dyoung }
    890   1.93    dyoung 
    891   1.59   thorpej static int
    892   1.88  christos gre_ioctl(struct ifnet *ifp, u_long cmd, void *data)
    893    1.1       hwr {
    894   1.62    dyoung 	u_char oproto;
    895   1.93    dyoung 	struct file *fp;
    896   1.62    dyoung 	struct socket *so;
    897   1.62    dyoung 	struct sockaddr_in dst, src;
    898   1.62    dyoung 	struct proc *p = curproc;	/* XXX */
    899   1.61        ad 	struct lwp *l = curlwp;	/* XXX */
    900   1.94  christos 	struct ifreq *ifr;
    901   1.28    itojun 	struct if_laddrreq *lifr = (struct if_laddrreq *)data;
    902    1.8  explorer 	struct gre_softc *sc = ifp->if_softc;
    903    1.1       hwr 	struct sockaddr_in si;
    904    1.8  explorer 	struct sockaddr *sa = NULL;
    905   1.80  christos 	int error = 0;
    906   1.96  christos #ifdef COMPAT_OIFREQ
    907   1.94  christos 	u_long ocmd = cmd;
    908   1.95   xtraeme 	struct oifreq *oifr = NULL;
    909   1.94  christos 	struct ifreq ifrb;
    910   1.94  christos 
    911  1.101       skd 	cmd = compat_cvtcmd(cmd);
    912   1.94  christos 	if (cmd != ocmd) {
    913   1.94  christos 		oifr = data;
    914   1.94  christos 		data = ifr = &ifrb;
    915   1.94  christos 		ifreqo2n(oifr, ifr);
    916   1.94  christos 	} else
    917   1.94  christos #endif
    918   1.94  christos 		ifr = data;
    919   1.94  christos 
    920   1.61        ad 	switch (cmd) {
    921   1.61        ad 	case SIOCSIFFLAGS:
    922   1.61        ad 	case SIOCSIFMTU:
    923   1.61        ad 	case GRESPROTO:
    924   1.61        ad 	case GRESADDRD:
    925   1.61        ad 	case GRESADDRS:
    926   1.62    dyoung 	case GRESSOCK:
    927   1.62    dyoung 	case GREDSOCK:
    928   1.61        ad 	case SIOCSLIFPHYADDR:
    929   1.61        ad 	case SIOCDIFPHYADDR:
    930   1.70      elad 		if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
    931   1.70      elad 		    KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
    932   1.70      elad 		    NULL) != 0)
    933   1.87    dyoung 			return EPERM;
    934   1.61        ad 		break;
    935   1.61        ad 	default:
    936   1.61        ad 		break;
    937   1.61        ad 	}
    938    1.1       hwr 
    939   1.93    dyoung 	mutex_enter(&sc->sc_mtx);
    940   1.20    itojun 	switch (cmd) {
    941   1.20    itojun 	case SIOCSIFADDR:
    942   1.36    itojun 		ifp->if_flags |= IFF_UP;
    943   1.78    dyoung 		if ((error = gre_kick(sc)) != 0)
    944   1.78    dyoung 			ifp->if_flags &= ~IFF_UP;
    945   1.36    itojun 		break;
    946   1.55     perry 	case SIOCSIFDSTADDR:
    947    1.1       hwr 		break;
    948    1.1       hwr 	case SIOCSIFFLAGS:
    949   1.75    dyoung 		oproto = sc->sc_proto;
    950   1.62    dyoung 		switch (ifr->ifr_flags & (IFF_LINK0|IFF_LINK2)) {
    951   1.62    dyoung 		case IFF_LINK0|IFF_LINK2:
    952   1.75    dyoung 			sc->sc_proto = IPPROTO_UDP;
    953   1.62    dyoung 			if (oproto != IPPROTO_UDP)
    954   1.62    dyoung 				ifp->if_flags &= ~IFF_RUNNING;
    955   1.62    dyoung 			error = gre_kick(sc);
    956   1.62    dyoung 			break;
    957   1.62    dyoung 		case IFF_LINK0:
    958   1.75    dyoung 			sc->sc_proto = IPPROTO_GRE;
    959   1.62    dyoung 			gre_wakeup(sc);
    960   1.62    dyoung 			goto recompute;
    961   1.62    dyoung 		case 0:
    962   1.75    dyoung 			sc->sc_proto = IPPROTO_MOBILE;
    963   1.62    dyoung 			gre_wakeup(sc);
    964   1.62    dyoung 			goto recompute;
    965   1.62    dyoung 		}
    966    1.1       hwr 		break;
    967   1.20    itojun 	case SIOCSIFMTU:
    968   1.27    martin 		if (ifr->ifr_mtu < 576) {
    969    1.1       hwr 			error = EINVAL;
    970    1.1       hwr 			break;
    971    1.1       hwr 		}
    972    1.1       hwr 		ifp->if_mtu = ifr->ifr_mtu;
    973    1.1       hwr 		break;
    974    1.1       hwr 	case SIOCGIFMTU:
    975    1.1       hwr 		ifr->ifr_mtu = sc->sc_if.if_mtu;
    976    1.1       hwr 		break;
    977    1.1       hwr 	case SIOCADDMULTI:
    978    1.1       hwr 	case SIOCDELMULTI:
    979    1.8  explorer 		if (ifr == 0) {
    980    1.1       hwr 			error = EAFNOSUPPORT;
    981    1.1       hwr 			break;
    982    1.1       hwr 		}
    983    1.8  explorer 		switch (ifr->ifr_addr.sa_family) {
    984    1.1       hwr #ifdef INET
    985    1.1       hwr 		case AF_INET:
    986    1.1       hwr 			break;
    987    1.1       hwr #endif
    988   1.56        is #ifdef INET6
    989   1.56        is 		case AF_INET6:
    990   1.56        is 			break;
    991   1.56        is #endif
    992    1.1       hwr 		default:
    993    1.1       hwr 			error = EAFNOSUPPORT;
    994    1.1       hwr 			break;
    995    1.1       hwr 		}
    996    1.1       hwr 		break;
    997    1.1       hwr 	case GRESPROTO:
    998   1.75    dyoung 		oproto = sc->sc_proto;
    999   1.75    dyoung 		sc->sc_proto = ifr->ifr_flags;
   1000   1.75    dyoung 		switch (sc->sc_proto) {
   1001   1.62    dyoung 		case IPPROTO_UDP:
   1002   1.62    dyoung 			ifp->if_flags |= IFF_LINK0|IFF_LINK2;
   1003   1.62    dyoung 			if (oproto != IPPROTO_UDP)
   1004   1.62    dyoung 				ifp->if_flags &= ~IFF_RUNNING;
   1005   1.62    dyoung 			error = gre_kick(sc);
   1006   1.62    dyoung 			break;
   1007   1.40    itojun 		case IPPROTO_GRE:
   1008    1.3       hwr 			ifp->if_flags |= IFF_LINK0;
   1009   1.62    dyoung 			ifp->if_flags &= ~IFF_LINK2;
   1010   1.62    dyoung 			goto recompute;
   1011   1.40    itojun 		case IPPROTO_MOBILE:
   1012   1.62    dyoung 			ifp->if_flags &= ~(IFF_LINK0|IFF_LINK2);
   1013   1.62    dyoung 			goto recompute;
   1014    1.1       hwr 		default:
   1015   1.40    itojun 			error = EPROTONOSUPPORT;
   1016   1.35    itojun 			break;
   1017    1.1       hwr 		}
   1018    1.1       hwr 		break;
   1019    1.1       hwr 	case GREGPROTO:
   1020   1.75    dyoung 		ifr->ifr_flags = sc->sc_proto;
   1021    1.1       hwr 		break;
   1022    1.1       hwr 	case GRESADDRS:
   1023    1.1       hwr 	case GRESADDRD:
   1024    1.1       hwr 		/*
   1025   1.20    itojun 		 * set tunnel endpoints, compute a less specific route
   1026   1.20    itojun 		 * to the remote end and mark if as up
   1027   1.20    itojun 		 */
   1028    1.1       hwr 		sa = &ifr->ifr_addr;
   1029   1.62    dyoung 		if (cmd == GRESADDRS) {
   1030    1.1       hwr 			sc->g_src = (satosin(sa))->sin_addr;
   1031   1.62    dyoung 			sc->g_srcport = satosin(sa)->sin_port;
   1032   1.62    dyoung 		}
   1033   1.62    dyoung 		if (cmd == GRESADDRD) {
   1034   1.75    dyoung 			if (sc->sc_proto == IPPROTO_UDP &&
   1035   1.62    dyoung 			    satosin(sa)->sin_port == 0) {
   1036   1.62    dyoung 				error = EINVAL;
   1037   1.62    dyoung 				break;
   1038   1.62    dyoung 			}
   1039    1.1       hwr 			sc->g_dst = (satosin(sa))->sin_addr;
   1040   1.62    dyoung 			sc->g_dstport = satosin(sa)->sin_port;
   1041   1.62    dyoung 		}
   1042   1.30    itojun 	recompute:
   1043   1.75    dyoung 		if (sc->sc_proto == IPPROTO_UDP ||
   1044   1.62    dyoung 		    (sc->g_src.s_addr != INADDR_ANY &&
   1045   1.62    dyoung 		     sc->g_dst.s_addr != INADDR_ANY)) {
   1046   1.81     joerg 			rtcache_free(&sc->route);
   1047   1.75    dyoung 			if (sc->sc_proto == IPPROTO_UDP)
   1048   1.62    dyoung 				error = gre_kick(sc);
   1049   1.62    dyoung 			else if (gre_compute_route(sc) == 0)
   1050   1.39    itojun 				ifp->if_flags |= IFF_RUNNING;
   1051   1.39    itojun 			else
   1052   1.39    itojun 				ifp->if_flags &= ~IFF_RUNNING;
   1053    1.1       hwr 		}
   1054    1.1       hwr 		break;
   1055    1.1       hwr 	case GREGADDRS:
   1056   1.33    itojun 		memset(&si, 0, sizeof(si));
   1057   1.28    itojun 		si.sin_family = AF_INET;
   1058   1.28    itojun 		si.sin_len = sizeof(struct sockaddr_in);
   1059    1.1       hwr 		si.sin_addr.s_addr = sc->g_src.s_addr;
   1060    1.8  explorer 		sa = sintosa(&si);
   1061    1.1       hwr 		ifr->ifr_addr = *sa;
   1062    1.1       hwr 		break;
   1063    1.1       hwr 	case GREGADDRD:
   1064   1.33    itojun 		memset(&si, 0, sizeof(si));
   1065   1.28    itojun 		si.sin_family = AF_INET;
   1066   1.28    itojun 		si.sin_len = sizeof(struct sockaddr_in);
   1067    1.1       hwr 		si.sin_addr.s_addr = sc->g_dst.s_addr;
   1068    1.8  explorer 		sa = sintosa(&si);
   1069    1.1       hwr 		ifr->ifr_addr = *sa;
   1070   1.28    itojun 		break;
   1071   1.62    dyoung 	case GREDSOCK:
   1072   1.93    dyoung 		if (sc->sc_proto != IPPROTO_UDP) {
   1073   1.93    dyoung 			error = EINVAL;
   1074   1.93    dyoung 			break;
   1075   1.63    dyoung 		}
   1076   1.93    dyoung 		ifp->if_flags &= ~IFF_UP;
   1077   1.93    dyoung 		gre_wakeup(sc);
   1078   1.62    dyoung 		break;
   1079   1.62    dyoung 	case GRESSOCK:
   1080   1.93    dyoung 		if (sc->sc_proto != IPPROTO_UDP) {
   1081   1.93    dyoung 			error = EINVAL;
   1082   1.93    dyoung 			break;
   1083   1.93    dyoung 		}
   1084   1.93    dyoung 		/* getsock() will FILE_USE() and unlock the descriptor for us */
   1085   1.62    dyoung 		if ((error = getsock(p->p_fd, (int)ifr->ifr_value, &fp)) != 0)
   1086   1.62    dyoung 			break;
   1087   1.62    dyoung 		so = (struct socket *)fp->f_data;
   1088   1.62    dyoung 		if (so->so_type != SOCK_DGRAM) {
   1089   1.62    dyoung 			FILE_UNUSE(fp, NULL);
   1090   1.62    dyoung 			error = EINVAL;
   1091   1.62    dyoung 			break;
   1092   1.62    dyoung 		}
   1093   1.62    dyoung 		/* check address */
   1094   1.62    dyoung 		if ((error = gre_getnames(so, curlwp, &src, &dst)) != 0) {
   1095   1.62    dyoung 			FILE_UNUSE(fp, NULL);
   1096   1.62    dyoung 			break;
   1097   1.62    dyoung 		}
   1098   1.62    dyoung 
   1099   1.93    dyoung                 /* Increase reference count.  Now that our reference
   1100   1.93    dyoung                  * to the file descriptor is counted, this thread
   1101   1.93    dyoung                  * can release our "use" of the descriptor, but it
   1102   1.93    dyoung                  * will not be destroyed by some other thread's
   1103   1.93    dyoung                  * action.  This thread needs to release its use,
   1104   1.93    dyoung                  * too, because one and only one thread can have
   1105   1.93    dyoung                  * use of the descriptor at once.  The kernel thread
   1106   1.93    dyoung                  * will pick up the use if it needs it.
   1107   1.93    dyoung 		 */
   1108   1.93    dyoung 
   1109   1.62    dyoung 		fp->f_count++;
   1110   1.93    dyoung 		FILE_UNUSE(fp, NULL);
   1111   1.93    dyoung 
   1112   1.93    dyoung 		while (sc->sc_fp != NULL && error == 0) {
   1113   1.93    dyoung 			error = cv_timedwait_sig(&sc->sc_soparm_cv, &sc->sc_mtx,
   1114   1.93    dyoung 					         MAX(1, hz / 2));
   1115   1.93    dyoung 		}
   1116   1.93    dyoung 		if (error == 0) {
   1117   1.93    dyoung 			sc->sc_fp = fp;
   1118   1.93    dyoung 			ifp->if_flags |= IFF_UP;
   1119   1.93    dyoung 		}
   1120   1.62    dyoung 
   1121   1.93    dyoung 		if (error != 0 || (error = gre_kick(sc)) != 0) {
   1122   1.93    dyoung 			gre_closef(&fp, l);
   1123   1.62    dyoung 			break;
   1124   1.62    dyoung 		}
   1125   1.93    dyoung 		/* fp does not any longer belong to this thread. */
   1126   1.62    dyoung 		sc->g_src = src.sin_addr;
   1127   1.62    dyoung 		sc->g_srcport = src.sin_port;
   1128   1.62    dyoung 		sc->g_dst = dst.sin_addr;
   1129   1.62    dyoung 		sc->g_dstport = dst.sin_port;
   1130   1.62    dyoung 		break;
   1131   1.28    itojun 	case SIOCSLIFPHYADDR:
   1132   1.28    itojun 		if (lifr->addr.ss_family != AF_INET ||
   1133   1.31    itojun 		    lifr->dstaddr.ss_family != AF_INET) {
   1134   1.31    itojun 			error = EAFNOSUPPORT;
   1135   1.31    itojun 			break;
   1136   1.31    itojun 		}
   1137   1.28    itojun 		if (lifr->addr.ss_len != sizeof(si) ||
   1138   1.31    itojun 		    lifr->dstaddr.ss_len != sizeof(si)) {
   1139   1.31    itojun 			error = EINVAL;
   1140   1.31    itojun 			break;
   1141   1.31    itojun 		}
   1142   1.62    dyoung 		sc->g_src = satosin(&lifr->addr)->sin_addr;
   1143   1.62    dyoung 		sc->g_dst = satosin(&lifr->dstaddr)->sin_addr;
   1144   1.62    dyoung 		sc->g_srcport = satosin(&lifr->addr)->sin_port;
   1145   1.62    dyoung 		sc->g_dstport = satosin(&lifr->dstaddr)->sin_port;
   1146   1.30    itojun 		goto recompute;
   1147   1.28    itojun 	case SIOCDIFPHYADDR:
   1148   1.28    itojun 		sc->g_src.s_addr = INADDR_ANY;
   1149   1.28    itojun 		sc->g_dst.s_addr = INADDR_ANY;
   1150   1.62    dyoung 		sc->g_srcport = 0;
   1151   1.62    dyoung 		sc->g_dstport = 0;
   1152   1.62    dyoung 		goto recompute;
   1153   1.28    itojun 	case SIOCGLIFPHYADDR:
   1154   1.28    itojun 		if (sc->g_src.s_addr == INADDR_ANY ||
   1155   1.28    itojun 		    sc->g_dst.s_addr == INADDR_ANY) {
   1156   1.28    itojun 			error = EADDRNOTAVAIL;
   1157   1.28    itojun 			break;
   1158   1.28    itojun 		}
   1159   1.33    itojun 		memset(&si, 0, sizeof(si));
   1160   1.28    itojun 		si.sin_family = AF_INET;
   1161   1.28    itojun 		si.sin_len = sizeof(struct sockaddr_in);
   1162   1.62    dyoung 		si.sin_addr = sc->g_src;
   1163   1.75    dyoung 		if (sc->sc_proto == IPPROTO_UDP)
   1164   1.62    dyoung 			si.sin_port = sc->g_srcport;
   1165   1.33    itojun 		memcpy(&lifr->addr, &si, sizeof(si));
   1166   1.62    dyoung 		si.sin_addr = sc->g_dst;
   1167   1.75    dyoung 		if (sc->sc_proto == IPPROTO_UDP)
   1168   1.62    dyoung 			si.sin_port = sc->g_dstport;
   1169   1.33    itojun 		memcpy(&lifr->dstaddr, &si, sizeof(si));
   1170    1.1       hwr 		break;
   1171    1.1       hwr 	default:
   1172    1.1       hwr 		error = EINVAL;
   1173   1.31    itojun 		break;
   1174    1.1       hwr 	}
   1175   1.94  christos #ifdef COMPAT_OIFREQ
   1176   1.94  christos 	if (cmd != ocmd)
   1177   1.94  christos 		ifreqn2o(oifr, ifr);
   1178   1.94  christos #endif
   1179   1.93    dyoung 	mutex_exit(&sc->sc_mtx);
   1180   1.87    dyoung 	return error;
   1181    1.1       hwr }
   1182    1.1       hwr 
   1183   1.20    itojun /*
   1184   1.78    dyoung  * Compute a route to our destination.
   1185    1.1       hwr  */
   1186   1.59   thorpej static int
   1187    1.8  explorer gre_compute_route(struct gre_softc *sc)
   1188    1.1       hwr {
   1189    1.1       hwr 	struct route *ro;
   1190   1.92    dyoung 	union {
   1191   1.92    dyoung 		struct sockaddr		dst;
   1192   1.92    dyoung 		struct sockaddr_in	dst4;
   1193   1.92    dyoung 	} u;
   1194    1.1       hwr 
   1195    1.8  explorer 	ro = &sc->route;
   1196   1.20    itojun 
   1197   1.92    dyoung 	memset(ro, 0, sizeof(*ro));
   1198   1.92    dyoung 	sockaddr_in_init(&u.dst4, &sc->g_dst, 0);
   1199   1.92    dyoung 	rtcache_setdst(ro, &u.dst);
   1200    1.8  explorer 
   1201   1.81     joerg 	rtcache_init(ro);
   1202   1.81     joerg 
   1203   1.81     joerg 	if (ro->ro_rt == NULL || ro->ro_rt->rt_ifp->if_softc == sc) {
   1204   1.90    dyoung 		GRE_DPRINTF(sc, "%s: route to %s %s\n", sc->sc_if.if_xname,
   1205   1.92    dyoung 		    inet_ntoa(u.dst4.sin_addr),
   1206   1.90    dyoung 		    (ro->ro_rt == NULL)
   1207   1.90    dyoung 		        ?  "does not exist"
   1208   1.90    dyoung 			: "loops back to ourself");
   1209   1.81     joerg 		rtcache_free(ro);
   1210   1.81     joerg 		return EADDRNOTAVAIL;
   1211   1.25    martin 	}
   1212   1.25    martin 
   1213   1.25    martin 	return 0;
   1214    1.1       hwr }
   1215    1.1       hwr 
   1216    1.3       hwr /*
   1217   1.20    itojun  * do a checksum of a buffer - much like in_cksum, which operates on
   1218   1.20    itojun  * mbufs.
   1219    1.3       hwr  */
   1220   1.48    itojun u_int16_t
   1221   1.48    itojun gre_in_cksum(u_int16_t *p, u_int len)
   1222    1.3       hwr {
   1223   1.48    itojun 	u_int32_t sum = 0;
   1224    1.3       hwr 	int nwords = len >> 1;
   1225   1.20    itojun 
   1226    1.3       hwr 	while (nwords-- != 0)
   1227    1.3       hwr 		sum += *p++;
   1228   1.20    itojun 
   1229   1.20    itojun 	if (len & 1) {
   1230   1.20    itojun 		union {
   1231   1.20    itojun 			u_short w;
   1232   1.20    itojun 			u_char c[2];
   1233   1.20    itojun 		} u;
   1234   1.20    itojun 		u.c[0] = *(u_char *)p;
   1235   1.20    itojun 		u.c[1] = 0;
   1236   1.20    itojun 		sum += u.w;
   1237   1.20    itojun 	}
   1238   1.20    itojun 
   1239   1.20    itojun 	/* end-around-carry */
   1240   1.20    itojun 	sum = (sum >> 16) + (sum & 0xffff);
   1241   1.20    itojun 	sum += (sum >> 16);
   1242   1.87    dyoung 	return ~sum;
   1243    1.3       hwr }
   1244   1.54  christos #endif
   1245   1.54  christos 
   1246   1.59   thorpej void	greattach(int);
   1247   1.54  christos 
   1248   1.54  christos /* ARGSUSED */
   1249   1.54  christos void
   1250   1.74  christos greattach(int count)
   1251   1.54  christos {
   1252   1.54  christos #ifdef INET
   1253   1.54  christos 	LIST_INIT(&gre_softc_list);
   1254   1.54  christos 	if_clone_attach(&gre_cloner);
   1255   1.54  christos #endif
   1256   1.54  christos }
   1257