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