Home | History | Annotate | Line # | Download | only in net
if_gre.c revision 1.105
      1  1.105    dyoung /*	$NetBSD: if_gre.c,v 1.105 2007/08/30 05:54:07 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.105    dyoung __KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1.105 2007/08/30 05:54:07 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.105    dyoung 	if (sc->sc_soparm.sp_fp != NULL) {
    433  1.102    dyoung 		gre_upcall_remove(so);
    434  1.105    dyoung 		gre_closef(&sc->sc_soparm.sp_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.105    dyoung 	else if (sc->sc_newsoparm.sp_fp != NULL) {
    446  1.105    dyoung 		sc->sc_soparm.sp_fp = sc->sc_newsoparm.sp_fp;
    447  1.105    dyoung 		sc->sc_newsoparm.sp_fp = NULL;
    448  1.105    dyoung 		so = (struct socket *)sc->sc_soparm.sp_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.105    dyoung 		    sc->sc_newsoparm.sp_fp != 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 }
    497   1.62    dyoung 
    498   1.62    dyoung static void
    499   1.62    dyoung gre_thread(void *arg)
    500   1.62    dyoung {
    501   1.62    dyoung 	struct gre_softc *sc = (struct gre_softc *)arg;
    502   1.62    dyoung 
    503  1.103    dyoung 	mutex_enter(&sc->sc_mtx);
    504   1.62    dyoung 	gre_thread1(sc, curlwp);
    505  1.103    dyoung 	mutex_exit(&sc->sc_mtx);
    506  1.103    dyoung 
    507   1.62    dyoung 	/* must not touch sc after this! */
    508   1.62    dyoung 	kthread_exit(0);
    509   1.62    dyoung }
    510   1.62    dyoung 
    511   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    512   1.62    dyoung int
    513   1.89    dyoung gre_input3(struct gre_softc *sc, struct mbuf *m, int hlen,
    514   1.93    dyoung     const struct gre_h *gh, int mtx_held)
    515   1.62    dyoung {
    516   1.62    dyoung 	u_int16_t flags;
    517   1.62    dyoung #if NBPFILTER > 0
    518   1.62    dyoung 	u_int32_t af = AF_INET;		/* af passed to BPF tap */
    519   1.62    dyoung #endif
    520   1.93    dyoung 	int isr;
    521   1.62    dyoung 	struct ifqueue *ifq;
    522   1.62    dyoung 
    523   1.62    dyoung 	sc->sc_if.if_ipackets++;
    524   1.62    dyoung 	sc->sc_if.if_ibytes += m->m_pkthdr.len;
    525   1.62    dyoung 
    526   1.89    dyoung 	hlen += sizeof(struct gre_h);
    527   1.62    dyoung 
    528   1.89    dyoung 	/* process GRE flags as packet can be of variable len */
    529   1.89    dyoung 	flags = ntohs(gh->flags);
    530   1.62    dyoung 
    531   1.89    dyoung 	/* Checksum & Offset are present */
    532   1.89    dyoung 	if ((flags & GRE_CP) | (flags & GRE_RP))
    533   1.89    dyoung 		hlen += 4;
    534   1.89    dyoung 	/* We don't support routing fields (variable length) */
    535   1.89    dyoung 	if (flags & GRE_RP) {
    536   1.89    dyoung 		sc->sc_if.if_ierrors++;
    537   1.89    dyoung 		return 0;
    538   1.89    dyoung 	}
    539   1.89    dyoung 	if (flags & GRE_KP)
    540   1.89    dyoung 		hlen += 4;
    541   1.89    dyoung 	if (flags & GRE_SP)
    542   1.89    dyoung 		hlen += 4;
    543   1.89    dyoung 
    544   1.89    dyoung 	switch (ntohs(gh->ptype)) { /* ethertypes */
    545   1.89    dyoung 	case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */
    546   1.89    dyoung 		ifq = &ipintrq;          /* we are in ip_input */
    547   1.89    dyoung 		isr = NETISR_IP;
    548   1.89    dyoung 		break;
    549   1.62    dyoung #ifdef NETATALK
    550   1.89    dyoung 	case ETHERTYPE_ATALK:
    551   1.89    dyoung 		ifq = &atintrq1;
    552   1.89    dyoung 		isr = NETISR_ATALK;
    553   1.62    dyoung #if NBPFILTER > 0
    554   1.89    dyoung 		af = AF_APPLETALK;
    555   1.62    dyoung #endif
    556   1.89    dyoung 		break;
    557   1.62    dyoung #endif
    558   1.62    dyoung #ifdef INET6
    559   1.89    dyoung 	case ETHERTYPE_IPV6:
    560   1.89    dyoung 		GRE_DPRINTF(sc, "%s: IPv6 packet\n", __func__);
    561   1.89    dyoung 		ifq = &ip6intrq;
    562   1.89    dyoung 		isr = NETISR_IPV6;
    563   1.62    dyoung #if NBPFILTER > 0
    564   1.89    dyoung 		af = AF_INET6;
    565   1.62    dyoung #endif
    566   1.89    dyoung 		break;
    567   1.62    dyoung #endif
    568   1.89    dyoung 	default:	   /* others not yet supported */
    569   1.90    dyoung 		GRE_DPRINTF(sc, "%s: unhandled ethertype 0x%04x\n", __func__,
    570   1.89    dyoung 		    ntohs(gh->ptype));
    571   1.89    dyoung 		sc->sc_if.if_noproto++;
    572   1.87    dyoung 		return 0;
    573   1.62    dyoung 	}
    574   1.62    dyoung 
    575   1.62    dyoung 	if (hlen > m->m_pkthdr.len) {
    576   1.62    dyoung 		m_freem(m);
    577   1.62    dyoung 		sc->sc_if.if_ierrors++;
    578   1.87    dyoung 		return EINVAL;
    579   1.62    dyoung 	}
    580   1.62    dyoung 	m_adj(m, hlen);
    581   1.62    dyoung 
    582   1.62    dyoung #if NBPFILTER > 0
    583   1.62    dyoung 	if (sc->sc_if.if_bpf != NULL)
    584   1.62    dyoung 		bpf_mtap_af(sc->sc_if.if_bpf, af, m);
    585   1.62    dyoung #endif /*NBPFILTER > 0*/
    586   1.62    dyoung 
    587   1.62    dyoung 	m->m_pkthdr.rcvif = &sc->sc_if;
    588   1.62    dyoung 
    589   1.93    dyoung 	if (!mtx_held)
    590   1.93    dyoung 		mutex_enter(&sc->sc_mtx);
    591   1.62    dyoung 	if (IF_QFULL(ifq)) {
    592   1.62    dyoung 		IF_DROP(ifq);
    593   1.62    dyoung 		m_freem(m);
    594   1.62    dyoung 	} else {
    595   1.62    dyoung 		IF_ENQUEUE(ifq, m);
    596   1.62    dyoung 	}
    597   1.62    dyoung 	/* we need schednetisr since the address family may change */
    598   1.62    dyoung 	schednetisr(isr);
    599   1.93    dyoung 	if (!mtx_held)
    600   1.93    dyoung 		mutex_exit(&sc->sc_mtx);
    601   1.62    dyoung 
    602   1.87    dyoung 	return 1;	/* packet is done, no further processing needed */
    603   1.62    dyoung }
    604   1.62    dyoung 
    605   1.20    itojun /*
    606    1.1       hwr  * The output routine. Takes a packet and encapsulates it in the protocol
    607   1.75    dyoung  * given by sc->sc_proto. See also RFC 1701 and RFC 2004
    608    1.1       hwr  */
    609   1.59   thorpej static int
    610   1.84    dyoung gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
    611   1.74  christos 	   struct rtentry *rt)
    612    1.1       hwr {
    613   1.89    dyoung 	int error = 0, hlen, msiz;
    614   1.10   thorpej 	struct gre_softc *sc = ifp->if_softc;
    615   1.62    dyoung 	struct greip *gi;
    616   1.62    dyoung 	struct gre_h *gh;
    617   1.62    dyoung 	struct ip *eip, *ip;
    618   1.56        is 	u_int8_t ip_tos = 0;
    619   1.48    itojun 	u_int16_t etype = 0;
    620   1.20    itojun 	struct mobile_h mob_h;
    621   1.24    martin 
    622   1.99     seanb 	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
    623   1.99     seanb 	    (IFF_UP | IFF_RUNNING) ||
    624   1.37    itojun 	    sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY) {
    625   1.37    itojun 		m_freem(m);
    626   1.38    itojun 		error = ENETDOWN;
    627   1.38    itojun 		goto end;
    628   1.37    itojun 	}
    629    1.1       hwr 
    630   1.62    dyoung 	gi = NULL;
    631   1.41    itojun 	ip = NULL;
    632    1.1       hwr 
    633    1.1       hwr #if NBPFILTER >0
    634   1.52  christos 	if (ifp->if_bpf)
    635   1.52  christos 		bpf_mtap_af(ifp->if_bpf, dst->sa_family, m);
    636    1.1       hwr #endif
    637    1.1       hwr 
    638   1.26    martin 	m->m_flags &= ~(M_BCAST|M_MCAST);
    639    1.1       hwr 
    640   1.75    dyoung 	switch (sc->sc_proto) {
    641   1.62    dyoung 	case IPPROTO_MOBILE:
    642   1.89    dyoung 		if (dst->sa_family != AF_INET) {
    643   1.89    dyoung 			IF_DROP(&ifp->if_snd);
    644   1.89    dyoung 			m_freem(m);
    645   1.89    dyoung 			error = EINVAL;
    646   1.89    dyoung 			goto end;
    647   1.89    dyoung 		}
    648   1.89    dyoung 
    649   1.89    dyoung 		if (M_UNWRITABLE(m, sizeof(*ip)) &&
    650   1.89    dyoung 		    (m = m_pullup(m, sizeof(*ip))) == NULL) {
    651   1.89    dyoung 			error = ENOBUFS;
    652   1.89    dyoung 			goto end;
    653   1.89    dyoung 		}
    654   1.89    dyoung 		ip = mtod(m, struct ip *);
    655    1.3       hwr 
    656   1.89    dyoung 		memset(&mob_h, 0, MOB_H_SIZ_L);
    657   1.89    dyoung 		mob_h.proto = (ip->ip_p) << 8;
    658   1.89    dyoung 		mob_h.odst = ip->ip_dst.s_addr;
    659   1.89    dyoung 		ip->ip_dst.s_addr = sc->g_dst.s_addr;
    660    1.3       hwr 
    661   1.89    dyoung 		/*
    662   1.89    dyoung 		 * If the packet comes from our host, we only change
    663   1.89    dyoung 		 * the destination address in the IP header.
    664   1.89    dyoung 		 * Else we also need to save and change the source
    665   1.89    dyoung 		 */
    666  1.103    dyoung 		if (in_hosteq(ip->ip_src, sc->g_src))
    667   1.89    dyoung 			msiz = MOB_H_SIZ_S;
    668  1.103    dyoung 		else {
    669   1.89    dyoung 			mob_h.proto |= MOB_H_SBIT;
    670   1.89    dyoung 			mob_h.osrc = ip->ip_src.s_addr;
    671   1.89    dyoung 			ip->ip_src.s_addr = sc->g_src.s_addr;
    672   1.89    dyoung 			msiz = MOB_H_SIZ_L;
    673   1.89    dyoung 		}
    674   1.89    dyoung 		HTONS(mob_h.proto);
    675   1.89    dyoung 		mob_h.hcrc = gre_in_cksum((u_int16_t *)&mob_h, msiz);
    676    1.3       hwr 
    677   1.89    dyoung 		M_PREPEND(m, msiz, M_DONTWAIT);
    678   1.89    dyoung 		if (m == NULL) {
    679   1.89    dyoung 			error = ENOBUFS;
    680   1.38    itojun 			goto end;
    681    1.3       hwr 		}
    682   1.89    dyoung 		/* XXX Assuming that ip does not dangle after
    683   1.89    dyoung 		 * M_PREPEND.  In practice, that's true, but
    684   1.90    dyoung 		 * that's not in M_PREPEND's contract.
    685   1.89    dyoung 		 */
    686   1.89    dyoung 		memmove(mtod(m, void *), ip, sizeof(*ip));
    687   1.89    dyoung 		ip = mtod(m, struct ip *);
    688   1.90    dyoung 		memcpy(ip + 1, &mob_h, (size_t)msiz);
    689   1.89    dyoung 		ip->ip_len = htons(ntohs(ip->ip_len) + msiz);
    690   1.62    dyoung 		break;
    691   1.62    dyoung 	case IPPROTO_UDP:
    692   1.62    dyoung 	case IPPROTO_GRE:
    693   1.62    dyoung 		GRE_DPRINTF(sc, "%s: dst->sa_family=%d\n", __func__,
    694   1.62    dyoung 		    dst->sa_family);
    695   1.20    itojun 		switch (dst->sa_family) {
    696    1.1       hwr 		case AF_INET:
    697   1.41    itojun 			ip = mtod(m, struct ip *);
    698   1.56        is 			ip_tos = ip->ip_tos;
    699    1.8  explorer 			etype = ETHERTYPE_IP;
    700    1.1       hwr 			break;
    701    1.1       hwr #ifdef NETATALK
    702    1.1       hwr 		case AF_APPLETALK:
    703    1.8  explorer 			etype = ETHERTYPE_ATALK;
    704    1.1       hwr 			break;
    705    1.1       hwr #endif
    706   1.56        is #ifdef INET6
    707   1.56        is 		case AF_INET6:
    708   1.56        is 			etype = ETHERTYPE_IPV6;
    709   1.56        is 			break;
    710   1.56        is #endif
    711    1.1       hwr 		default:
    712    1.1       hwr 			IF_DROP(&ifp->if_snd);
    713    1.1       hwr 			m_freem(m);
    714   1.38    itojun 			error = EAFNOSUPPORT;
    715   1.38    itojun 			goto end;
    716    1.1       hwr 		}
    717   1.62    dyoung 		break;
    718   1.62    dyoung 	default:
    719    1.1       hwr 		IF_DROP(&ifp->if_snd);
    720    1.1       hwr 		m_freem(m);
    721   1.38    itojun 		error = EINVAL;
    722   1.38    itojun 		goto end;
    723    1.1       hwr 	}
    724    1.1       hwr 
    725   1.75    dyoung 	switch (sc->sc_proto) {
    726   1.62    dyoung 	case IPPROTO_GRE:
    727   1.62    dyoung 		hlen = sizeof(struct greip);
    728   1.62    dyoung 		break;
    729   1.62    dyoung 	case IPPROTO_UDP:
    730   1.62    dyoung 		hlen = sizeof(struct gre_h);
    731   1.62    dyoung 		break;
    732   1.62    dyoung 	default:
    733   1.62    dyoung 		hlen = 0;
    734   1.62    dyoung 		break;
    735   1.62    dyoung 	}
    736   1.62    dyoung 
    737   1.62    dyoung 	M_PREPEND(m, hlen, M_DONTWAIT);
    738   1.62    dyoung 
    739   1.62    dyoung 	if (m == NULL) {
    740    1.1       hwr 		IF_DROP(&ifp->if_snd);
    741   1.38    itojun 		error = ENOBUFS;
    742   1.38    itojun 		goto end;
    743    1.1       hwr 	}
    744    1.1       hwr 
    745   1.75    dyoung 	switch (sc->sc_proto) {
    746   1.62    dyoung 	case IPPROTO_UDP:
    747   1.62    dyoung 		gh = mtod(m, struct gre_h *);
    748   1.62    dyoung 		memset(gh, 0, sizeof(*gh));
    749   1.62    dyoung 		gh->ptype = htons(etype);
    750   1.62    dyoung 		/* XXX Need to handle IP ToS.  Look at how I handle IP TTL. */
    751   1.62    dyoung 		break;
    752   1.62    dyoung 	case IPPROTO_GRE:
    753   1.62    dyoung 		gi = mtod(m, struct greip *);
    754   1.62    dyoung 		gh = &gi->gi_g;
    755   1.62    dyoung 		eip = &gi->gi_i;
    756    1.1       hwr 		/* we don't have any GRE flags for now */
    757   1.62    dyoung 		memset(gh, 0, sizeof(*gh));
    758   1.62    dyoung 		gh->ptype = htons(etype);
    759   1.62    dyoung 		eip->ip_src = sc->g_src;
    760   1.62    dyoung 		eip->ip_dst = sc->g_dst;
    761   1.62    dyoung 		eip->ip_hl = (sizeof(struct ip)) >> 2;
    762   1.62    dyoung 		eip->ip_ttl = ip_gre_ttl;
    763   1.62    dyoung 		eip->ip_tos = ip_tos;
    764   1.62    dyoung 		eip->ip_len = htons(m->m_pkthdr.len);
    765   1.75    dyoung 		eip->ip_p = sc->sc_proto;
    766   1.62    dyoung 		break;
    767   1.62    dyoung 	case IPPROTO_MOBILE:
    768   1.62    dyoung 		eip = mtod(m, struct ip *);
    769   1.75    dyoung 		eip->ip_p = sc->sc_proto;
    770   1.62    dyoung 		break;
    771   1.62    dyoung 	default:
    772   1.62    dyoung 		error = EPROTONOSUPPORT;
    773   1.62    dyoung 		m_freem(m);
    774   1.62    dyoung 		goto end;
    775    1.3       hwr 	}
    776    1.1       hwr 
    777    1.1       hwr 	ifp->if_opackets++;
    778    1.8  explorer 	ifp->if_obytes += m->m_pkthdr.len;
    779   1.62    dyoung 
    780    1.1       hwr 	/* send it off */
    781   1.75    dyoung 	if (sc->sc_proto == IPPROTO_UDP) {
    782   1.62    dyoung 		if (IF_QFULL(&sc->sc_snd)) {
    783   1.62    dyoung 			IF_DROP(&sc->sc_snd);
    784   1.62    dyoung 			error = ENOBUFS;
    785   1.62    dyoung 			m_freem(m);
    786   1.62    dyoung 		} else {
    787   1.62    dyoung 			IF_ENQUEUE(&sc->sc_snd, m);
    788   1.62    dyoung 			gre_wakeup(sc);
    789   1.62    dyoung 			error = 0;
    790   1.62    dyoung 		}
    791   1.81     joerg 		goto end;
    792   1.81     joerg 	}
    793   1.86    dyoung 	if (sc->route.ro_rt == NULL)
    794   1.86    dyoung 		rtcache_init(&sc->route);
    795   1.86    dyoung 	else
    796   1.86    dyoung 		rtcache_check(&sc->route);
    797   1.91    dyoung 	if (sc->route.ro_rt == NULL) {
    798   1.91    dyoung 		m_freem(m);
    799   1.81     joerg 		goto end;
    800   1.91    dyoung 	}
    801   1.91    dyoung 	if (sc->route.ro_rt->rt_ifp->if_softc == sc) {
    802   1.92    dyoung 		rtcache_clear(&sc->route);
    803   1.91    dyoung 		m_freem(m);
    804   1.91    dyoung 	} else
    805   1.92    dyoung 		error = ip_output(m, NULL, &sc->route, 0, NULL, NULL);
    806   1.38    itojun   end:
    807    1.8  explorer 	if (error)
    808    1.1       hwr 		ifp->if_oerrors++;
    809   1.87    dyoung 	return error;
    810    1.1       hwr }
    811    1.1       hwr 
    812   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    813   1.62    dyoung static int
    814   1.62    dyoung gre_kick(struct gre_softc *sc)
    815   1.62    dyoung {
    816   1.62    dyoung 	struct ifnet *ifp = &sc->sc_if;
    817   1.62    dyoung 
    818   1.75    dyoung 	if (sc->sc_proto == IPPROTO_UDP && (ifp->if_flags & IFF_UP) == IFF_UP &&
    819  1.102    dyoung 	    !sc->sc_running)
    820  1.102    dyoung 		return EBUSY;
    821  1.102    dyoung 	gre_wakeup(sc);
    822  1.102    dyoung 	return 0;
    823   1.62    dyoung }
    824   1.62    dyoung 
    825   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    826   1.62    dyoung static int
    827   1.62    dyoung gre_getname(struct socket *so, int req, struct mbuf *nam, struct lwp *l)
    828   1.62    dyoung {
    829   1.93    dyoung 	return (*so->so_proto->pr_usrreq)(so, req, NULL, nam, NULL, l);
    830   1.62    dyoung }
    831   1.62    dyoung 
    832   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    833   1.62    dyoung static int
    834   1.62    dyoung gre_getsockname(struct socket *so, struct mbuf *nam, struct lwp *l)
    835   1.62    dyoung {
    836   1.62    dyoung 	return gre_getname(so, PRU_SOCKADDR, nam, l);
    837   1.62    dyoung }
    838   1.62    dyoung 
    839   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    840   1.62    dyoung static int
    841   1.62    dyoung gre_getpeername(struct socket *so, struct mbuf *nam, struct lwp *l)
    842   1.62    dyoung {
    843   1.62    dyoung 	return gre_getname(so, PRU_PEERADDR, nam, l);
    844   1.62    dyoung }
    845   1.62    dyoung 
    846   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    847   1.62    dyoung static int
    848   1.62    dyoung gre_getnames(struct socket *so, struct lwp *l, struct sockaddr_in *src,
    849   1.62    dyoung     struct sockaddr_in *dst)
    850   1.62    dyoung {
    851   1.62    dyoung 	struct mbuf *m;
    852   1.62    dyoung 	struct sockaddr_in *sin;
    853   1.62    dyoung 	int rc;
    854   1.62    dyoung 
    855   1.62    dyoung 	if ((m = gre_getsockmbuf(so)) == NULL)
    856   1.62    dyoung 		return ENOBUFS;
    857   1.62    dyoung 
    858   1.62    dyoung 	sin = mtod(m, struct sockaddr_in *);
    859   1.62    dyoung 
    860   1.62    dyoung 	if ((rc = gre_getsockname(so, m, l)) != 0)
    861   1.62    dyoung 		goto out;
    862   1.62    dyoung 	if (sin->sin_family != AF_INET) {
    863   1.62    dyoung 		rc = EAFNOSUPPORT;
    864   1.62    dyoung 		goto out;
    865   1.62    dyoung 	}
    866   1.62    dyoung 	*src = *sin;
    867   1.62    dyoung 
    868   1.62    dyoung 	if ((rc = gre_getpeername(so, m, l)) != 0)
    869   1.62    dyoung 		goto out;
    870   1.62    dyoung 	if (sin->sin_family != AF_INET) {
    871   1.62    dyoung 		rc = EAFNOSUPPORT;
    872   1.62    dyoung 		goto out;
    873   1.62    dyoung 	}
    874   1.62    dyoung 	*dst = *sin;
    875   1.62    dyoung 
    876   1.62    dyoung out:
    877   1.62    dyoung 	m_freem(m);
    878   1.62    dyoung 	return rc;
    879   1.62    dyoung }
    880   1.62    dyoung 
    881   1.93    dyoung static void
    882   1.93    dyoung gre_closef(struct file **fpp, struct lwp *l)
    883   1.93    dyoung {
    884   1.93    dyoung 	struct file *fp = *fpp;
    885   1.93    dyoung 
    886   1.93    dyoung 	simple_lock(&fp->f_slock);
    887   1.93    dyoung 	FILE_USE(fp);
    888   1.93    dyoung 	closef(fp, l);
    889   1.93    dyoung 	*fpp = NULL;
    890   1.93    dyoung }
    891   1.93    dyoung 
    892   1.59   thorpej static int
    893   1.88  christos gre_ioctl(struct ifnet *ifp, u_long cmd, void *data)
    894    1.1       hwr {
    895   1.62    dyoung 	u_char oproto;
    896   1.93    dyoung 	struct file *fp;
    897   1.62    dyoung 	struct socket *so;
    898   1.62    dyoung 	struct sockaddr_in dst, src;
    899   1.62    dyoung 	struct proc *p = curproc;	/* XXX */
    900   1.61        ad 	struct lwp *l = curlwp;	/* XXX */
    901   1.94  christos 	struct ifreq *ifr;
    902   1.28    itojun 	struct if_laddrreq *lifr = (struct if_laddrreq *)data;
    903    1.8  explorer 	struct gre_softc *sc = ifp->if_softc;
    904    1.1       hwr 	struct sockaddr_in si;
    905    1.8  explorer 	struct sockaddr *sa = NULL;
    906   1.80  christos 	int error = 0;
    907   1.96  christos #ifdef COMPAT_OIFREQ
    908   1.94  christos 	u_long ocmd = cmd;
    909   1.95   xtraeme 	struct oifreq *oifr = NULL;
    910   1.94  christos 	struct ifreq ifrb;
    911   1.94  christos 
    912  1.101       skd 	cmd = compat_cvtcmd(cmd);
    913   1.94  christos 	if (cmd != ocmd) {
    914   1.94  christos 		oifr = data;
    915   1.94  christos 		data = ifr = &ifrb;
    916   1.94  christos 		ifreqo2n(oifr, ifr);
    917   1.94  christos 	} else
    918   1.94  christos #endif
    919   1.94  christos 		ifr = data;
    920   1.94  christos 
    921   1.61        ad 	switch (cmd) {
    922   1.61        ad 	case SIOCSIFFLAGS:
    923   1.61        ad 	case SIOCSIFMTU:
    924   1.61        ad 	case GRESPROTO:
    925   1.61        ad 	case GRESADDRD:
    926   1.61        ad 	case GRESADDRS:
    927   1.62    dyoung 	case GRESSOCK:
    928   1.62    dyoung 	case GREDSOCK:
    929   1.61        ad 	case SIOCSLIFPHYADDR:
    930   1.61        ad 	case SIOCDIFPHYADDR:
    931   1.70      elad 		if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
    932   1.70      elad 		    KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
    933   1.70      elad 		    NULL) != 0)
    934   1.87    dyoung 			return EPERM;
    935   1.61        ad 		break;
    936   1.61        ad 	default:
    937   1.61        ad 		break;
    938   1.61        ad 	}
    939    1.1       hwr 
    940   1.93    dyoung 	mutex_enter(&sc->sc_mtx);
    941   1.20    itojun 	switch (cmd) {
    942   1.20    itojun 	case SIOCSIFADDR:
    943   1.36    itojun 		ifp->if_flags |= IFF_UP;
    944   1.78    dyoung 		if ((error = gre_kick(sc)) != 0)
    945   1.78    dyoung 			ifp->if_flags &= ~IFF_UP;
    946   1.36    itojun 		break;
    947   1.55     perry 	case SIOCSIFDSTADDR:
    948    1.1       hwr 		break;
    949    1.1       hwr 	case SIOCSIFFLAGS:
    950   1.75    dyoung 		oproto = sc->sc_proto;
    951   1.62    dyoung 		switch (ifr->ifr_flags & (IFF_LINK0|IFF_LINK2)) {
    952   1.62    dyoung 		case IFF_LINK0|IFF_LINK2:
    953   1.75    dyoung 			sc->sc_proto = IPPROTO_UDP;
    954   1.62    dyoung 			if (oproto != IPPROTO_UDP)
    955   1.62    dyoung 				ifp->if_flags &= ~IFF_RUNNING;
    956   1.62    dyoung 			error = gre_kick(sc);
    957   1.62    dyoung 			break;
    958   1.62    dyoung 		case IFF_LINK0:
    959   1.75    dyoung 			sc->sc_proto = IPPROTO_GRE;
    960   1.62    dyoung 			gre_wakeup(sc);
    961   1.62    dyoung 			goto recompute;
    962   1.62    dyoung 		case 0:
    963   1.75    dyoung 			sc->sc_proto = IPPROTO_MOBILE;
    964   1.62    dyoung 			gre_wakeup(sc);
    965   1.62    dyoung 			goto recompute;
    966   1.62    dyoung 		}
    967    1.1       hwr 		break;
    968   1.20    itojun 	case SIOCSIFMTU:
    969   1.27    martin 		if (ifr->ifr_mtu < 576) {
    970    1.1       hwr 			error = EINVAL;
    971    1.1       hwr 			break;
    972    1.1       hwr 		}
    973    1.1       hwr 		ifp->if_mtu = ifr->ifr_mtu;
    974    1.1       hwr 		break;
    975    1.1       hwr 	case SIOCGIFMTU:
    976    1.1       hwr 		ifr->ifr_mtu = sc->sc_if.if_mtu;
    977    1.1       hwr 		break;
    978    1.1       hwr 	case SIOCADDMULTI:
    979    1.1       hwr 	case SIOCDELMULTI:
    980    1.8  explorer 		if (ifr == 0) {
    981    1.1       hwr 			error = EAFNOSUPPORT;
    982    1.1       hwr 			break;
    983    1.1       hwr 		}
    984    1.8  explorer 		switch (ifr->ifr_addr.sa_family) {
    985    1.1       hwr #ifdef INET
    986    1.1       hwr 		case AF_INET:
    987    1.1       hwr 			break;
    988    1.1       hwr #endif
    989   1.56        is #ifdef INET6
    990   1.56        is 		case AF_INET6:
    991   1.56        is 			break;
    992   1.56        is #endif
    993    1.1       hwr 		default:
    994    1.1       hwr 			error = EAFNOSUPPORT;
    995    1.1       hwr 			break;
    996    1.1       hwr 		}
    997    1.1       hwr 		break;
    998    1.1       hwr 	case GRESPROTO:
    999   1.75    dyoung 		oproto = sc->sc_proto;
   1000   1.75    dyoung 		sc->sc_proto = ifr->ifr_flags;
   1001   1.75    dyoung 		switch (sc->sc_proto) {
   1002   1.62    dyoung 		case IPPROTO_UDP:
   1003   1.62    dyoung 			ifp->if_flags |= IFF_LINK0|IFF_LINK2;
   1004   1.62    dyoung 			if (oproto != IPPROTO_UDP)
   1005   1.62    dyoung 				ifp->if_flags &= ~IFF_RUNNING;
   1006   1.62    dyoung 			error = gre_kick(sc);
   1007   1.62    dyoung 			break;
   1008   1.40    itojun 		case IPPROTO_GRE:
   1009    1.3       hwr 			ifp->if_flags |= IFF_LINK0;
   1010   1.62    dyoung 			ifp->if_flags &= ~IFF_LINK2;
   1011   1.62    dyoung 			goto recompute;
   1012   1.40    itojun 		case IPPROTO_MOBILE:
   1013   1.62    dyoung 			ifp->if_flags &= ~(IFF_LINK0|IFF_LINK2);
   1014   1.62    dyoung 			goto recompute;
   1015    1.1       hwr 		default:
   1016   1.40    itojun 			error = EPROTONOSUPPORT;
   1017   1.35    itojun 			break;
   1018    1.1       hwr 		}
   1019    1.1       hwr 		break;
   1020    1.1       hwr 	case GREGPROTO:
   1021   1.75    dyoung 		ifr->ifr_flags = sc->sc_proto;
   1022    1.1       hwr 		break;
   1023    1.1       hwr 	case GRESADDRS:
   1024    1.1       hwr 	case GRESADDRD:
   1025    1.1       hwr 		/*
   1026   1.20    itojun 		 * set tunnel endpoints, compute a less specific route
   1027   1.20    itojun 		 * to the remote end and mark if as up
   1028   1.20    itojun 		 */
   1029    1.1       hwr 		sa = &ifr->ifr_addr;
   1030   1.62    dyoung 		if (cmd == GRESADDRS) {
   1031    1.1       hwr 			sc->g_src = (satosin(sa))->sin_addr;
   1032   1.62    dyoung 			sc->g_srcport = satosin(sa)->sin_port;
   1033   1.62    dyoung 		}
   1034   1.62    dyoung 		if (cmd == GRESADDRD) {
   1035   1.75    dyoung 			if (sc->sc_proto == IPPROTO_UDP &&
   1036   1.62    dyoung 			    satosin(sa)->sin_port == 0) {
   1037   1.62    dyoung 				error = EINVAL;
   1038   1.62    dyoung 				break;
   1039   1.62    dyoung 			}
   1040    1.1       hwr 			sc->g_dst = (satosin(sa))->sin_addr;
   1041   1.62    dyoung 			sc->g_dstport = satosin(sa)->sin_port;
   1042   1.62    dyoung 		}
   1043   1.30    itojun 	recompute:
   1044   1.75    dyoung 		if (sc->sc_proto == IPPROTO_UDP ||
   1045   1.62    dyoung 		    (sc->g_src.s_addr != INADDR_ANY &&
   1046   1.62    dyoung 		     sc->g_dst.s_addr != INADDR_ANY)) {
   1047   1.81     joerg 			rtcache_free(&sc->route);
   1048  1.102    dyoung 			if (sc->sc_proto == IPPROTO_UDP) {
   1049  1.102    dyoung 				if ((error = gre_kick(sc)) == 0)
   1050  1.102    dyoung 					ifp->if_flags |= IFF_RUNNING;
   1051  1.102    dyoung 				else
   1052  1.102    dyoung 					ifp->if_flags &= ~IFF_RUNNING;
   1053  1.102    dyoung 			}
   1054   1.62    dyoung 			else if (gre_compute_route(sc) == 0)
   1055   1.39    itojun 				ifp->if_flags |= IFF_RUNNING;
   1056   1.39    itojun 			else
   1057   1.39    itojun 				ifp->if_flags &= ~IFF_RUNNING;
   1058    1.1       hwr 		}
   1059    1.1       hwr 		break;
   1060    1.1       hwr 	case GREGADDRS:
   1061  1.102    dyoung 		sockaddr_in_init(&si, &sc->g_src,
   1062  1.102    dyoung 		    (sc->sc_proto == IPPROTO_UDP) ? sc->g_srcport : 0);
   1063  1.102    dyoung 		ifr->ifr_addr = *sintosa(&si);
   1064    1.1       hwr 		break;
   1065    1.1       hwr 	case GREGADDRD:
   1066  1.102    dyoung 		sockaddr_in_init(&si, &sc->g_dst,
   1067  1.102    dyoung 		    (sc->sc_proto == IPPROTO_UDP) ? sc->g_dstport : 0);
   1068  1.102    dyoung 		ifr->ifr_addr = *sintosa(&si);
   1069   1.28    itojun 		break;
   1070   1.62    dyoung 	case GREDSOCK:
   1071   1.93    dyoung 		if (sc->sc_proto != IPPROTO_UDP) {
   1072   1.93    dyoung 			error = EINVAL;
   1073   1.93    dyoung 			break;
   1074   1.63    dyoung 		}
   1075   1.93    dyoung 		ifp->if_flags &= ~IFF_UP;
   1076   1.93    dyoung 		gre_wakeup(sc);
   1077   1.62    dyoung 		break;
   1078   1.62    dyoung 	case GRESSOCK:
   1079   1.93    dyoung 		if (sc->sc_proto != IPPROTO_UDP) {
   1080  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   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.102    dyoung 		if ((error = getsock(p->p_fd, (int)ifr->ifr_value, &fp)) != 0) {
   1086  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1087  1.102    dyoung 			error = EINVAL;
   1088   1.62    dyoung 			break;
   1089  1.102    dyoung 		}
   1090   1.62    dyoung 		so = (struct socket *)fp->f_data;
   1091   1.62    dyoung 		if (so->so_type != SOCK_DGRAM) {
   1092  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1093   1.62    dyoung 			FILE_UNUSE(fp, NULL);
   1094   1.62    dyoung 			error = EINVAL;
   1095   1.62    dyoung 			break;
   1096   1.62    dyoung 		}
   1097   1.62    dyoung 		/* check address */
   1098   1.62    dyoung 		if ((error = gre_getnames(so, curlwp, &src, &dst)) != 0) {
   1099  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1100   1.62    dyoung 			FILE_UNUSE(fp, NULL);
   1101   1.62    dyoung 			break;
   1102   1.62    dyoung 		}
   1103   1.62    dyoung 
   1104   1.93    dyoung                 /* Increase reference count.  Now that our reference
   1105   1.93    dyoung                  * to the file descriptor is counted, this thread
   1106   1.93    dyoung                  * can release our "use" of the descriptor, but it
   1107   1.93    dyoung                  * will not be destroyed by some other thread's
   1108   1.93    dyoung                  * action.  This thread needs to release its use,
   1109   1.93    dyoung                  * too, because one and only one thread can have
   1110   1.93    dyoung                  * use of the descriptor at once.  The kernel thread
   1111   1.93    dyoung                  * will pick up the use if it needs it.
   1112   1.93    dyoung 		 */
   1113   1.93    dyoung 
   1114   1.62    dyoung 		fp->f_count++;
   1115   1.93    dyoung 		FILE_UNUSE(fp, NULL);
   1116   1.93    dyoung 
   1117  1.105    dyoung 		while (sc->sc_newsoparm.sp_fp != NULL && error == 0) {
   1118  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1119   1.93    dyoung 			error = cv_timedwait_sig(&sc->sc_soparm_cv, &sc->sc_mtx,
   1120   1.93    dyoung 					         MAX(1, hz / 2));
   1121   1.93    dyoung 		}
   1122   1.93    dyoung 		if (error == 0) {
   1123  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1124  1.105    dyoung 			sc->sc_newsoparm.sp_fp = fp;
   1125   1.93    dyoung 			ifp->if_flags |= IFF_UP;
   1126   1.93    dyoung 		}
   1127   1.62    dyoung 
   1128   1.93    dyoung 		if (error != 0 || (error = gre_kick(sc)) != 0) {
   1129  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1130   1.93    dyoung 			gre_closef(&fp, l);
   1131   1.62    dyoung 			break;
   1132   1.62    dyoung 		}
   1133   1.93    dyoung 		/* fp does not any longer belong to this thread. */
   1134   1.62    dyoung 		sc->g_src = src.sin_addr;
   1135   1.62    dyoung 		sc->g_srcport = src.sin_port;
   1136   1.62    dyoung 		sc->g_dst = dst.sin_addr;
   1137   1.62    dyoung 		sc->g_dstport = dst.sin_port;
   1138  1.102    dyoung 		GRE_DPRINTF(sc, "%s: sock 0x%08" PRIx32 " port %d -> "
   1139  1.102    dyoung 		    "0x%08" PRIx32 " port %d\n", __func__,
   1140  1.102    dyoung 		    src.sin_addr.s_addr, ntohs(src.sin_port),
   1141  1.102    dyoung 		    dst.sin_addr.s_addr, ntohs(dst.sin_port));
   1142   1.62    dyoung 		break;
   1143   1.28    itojun 	case SIOCSLIFPHYADDR:
   1144   1.28    itojun 		if (lifr->addr.ss_family != AF_INET ||
   1145   1.31    itojun 		    lifr->dstaddr.ss_family != AF_INET) {
   1146   1.31    itojun 			error = EAFNOSUPPORT;
   1147   1.31    itojun 			break;
   1148   1.31    itojun 		}
   1149   1.28    itojun 		if (lifr->addr.ss_len != sizeof(si) ||
   1150   1.31    itojun 		    lifr->dstaddr.ss_len != sizeof(si)) {
   1151   1.31    itojun 			error = EINVAL;
   1152   1.31    itojun 			break;
   1153   1.31    itojun 		}
   1154   1.62    dyoung 		sc->g_src = satosin(&lifr->addr)->sin_addr;
   1155   1.62    dyoung 		sc->g_dst = satosin(&lifr->dstaddr)->sin_addr;
   1156   1.62    dyoung 		sc->g_srcport = satosin(&lifr->addr)->sin_port;
   1157   1.62    dyoung 		sc->g_dstport = satosin(&lifr->dstaddr)->sin_port;
   1158   1.30    itojun 		goto recompute;
   1159   1.28    itojun 	case SIOCDIFPHYADDR:
   1160   1.28    itojun 		sc->g_src.s_addr = INADDR_ANY;
   1161   1.28    itojun 		sc->g_dst.s_addr = INADDR_ANY;
   1162   1.62    dyoung 		sc->g_srcport = 0;
   1163   1.62    dyoung 		sc->g_dstport = 0;
   1164   1.62    dyoung 		goto recompute;
   1165   1.28    itojun 	case SIOCGLIFPHYADDR:
   1166   1.28    itojun 		if (sc->g_src.s_addr == INADDR_ANY ||
   1167   1.28    itojun 		    sc->g_dst.s_addr == INADDR_ANY) {
   1168   1.28    itojun 			error = EADDRNOTAVAIL;
   1169   1.28    itojun 			break;
   1170   1.28    itojun 		}
   1171  1.102    dyoung 		sockaddr_in_init(satosin(&lifr->addr), &sc->g_src,
   1172  1.102    dyoung 		    (sc->sc_proto == IPPROTO_UDP) ? sc->g_srcport : 0);
   1173  1.102    dyoung 		sockaddr_in_init(satosin(&lifr->dstaddr), &sc->g_dst,
   1174  1.102    dyoung 		    (sc->sc_proto == IPPROTO_UDP) ? sc->g_dstport : 0);
   1175    1.1       hwr 		break;
   1176    1.1       hwr 	default:
   1177    1.1       hwr 		error = EINVAL;
   1178   1.31    itojun 		break;
   1179    1.1       hwr 	}
   1180   1.94  christos #ifdef COMPAT_OIFREQ
   1181   1.94  christos 	if (cmd != ocmd)
   1182   1.94  christos 		ifreqn2o(oifr, ifr);
   1183   1.94  christos #endif
   1184   1.93    dyoung 	mutex_exit(&sc->sc_mtx);
   1185   1.87    dyoung 	return error;
   1186    1.1       hwr }
   1187    1.1       hwr 
   1188   1.20    itojun /*
   1189   1.78    dyoung  * Compute a route to our destination.
   1190    1.1       hwr  */
   1191   1.59   thorpej static int
   1192    1.8  explorer gre_compute_route(struct gre_softc *sc)
   1193    1.1       hwr {
   1194    1.1       hwr 	struct route *ro;
   1195   1.92    dyoung 	union {
   1196   1.92    dyoung 		struct sockaddr		dst;
   1197   1.92    dyoung 		struct sockaddr_in	dst4;
   1198   1.92    dyoung 	} u;
   1199    1.1       hwr 
   1200    1.8  explorer 	ro = &sc->route;
   1201   1.20    itojun 
   1202   1.92    dyoung 	memset(ro, 0, sizeof(*ro));
   1203   1.92    dyoung 	sockaddr_in_init(&u.dst4, &sc->g_dst, 0);
   1204   1.92    dyoung 	rtcache_setdst(ro, &u.dst);
   1205    1.8  explorer 
   1206   1.81     joerg 	rtcache_init(ro);
   1207   1.81     joerg 
   1208   1.81     joerg 	if (ro->ro_rt == NULL || ro->ro_rt->rt_ifp->if_softc == sc) {
   1209   1.90    dyoung 		GRE_DPRINTF(sc, "%s: route to %s %s\n", sc->sc_if.if_xname,
   1210   1.92    dyoung 		    inet_ntoa(u.dst4.sin_addr),
   1211   1.90    dyoung 		    (ro->ro_rt == NULL)
   1212   1.90    dyoung 		        ?  "does not exist"
   1213   1.90    dyoung 			: "loops back to ourself");
   1214   1.81     joerg 		rtcache_free(ro);
   1215   1.81     joerg 		return EADDRNOTAVAIL;
   1216   1.25    martin 	}
   1217   1.25    martin 
   1218   1.25    martin 	return 0;
   1219    1.1       hwr }
   1220    1.1       hwr 
   1221    1.3       hwr /*
   1222   1.20    itojun  * do a checksum of a buffer - much like in_cksum, which operates on
   1223   1.20    itojun  * mbufs.
   1224    1.3       hwr  */
   1225   1.48    itojun u_int16_t
   1226   1.48    itojun gre_in_cksum(u_int16_t *p, u_int len)
   1227    1.3       hwr {
   1228   1.48    itojun 	u_int32_t sum = 0;
   1229    1.3       hwr 	int nwords = len >> 1;
   1230   1.20    itojun 
   1231    1.3       hwr 	while (nwords-- != 0)
   1232    1.3       hwr 		sum += *p++;
   1233   1.20    itojun 
   1234   1.20    itojun 	if (len & 1) {
   1235   1.20    itojun 		union {
   1236   1.20    itojun 			u_short w;
   1237   1.20    itojun 			u_char c[2];
   1238   1.20    itojun 		} u;
   1239   1.20    itojun 		u.c[0] = *(u_char *)p;
   1240   1.20    itojun 		u.c[1] = 0;
   1241   1.20    itojun 		sum += u.w;
   1242   1.20    itojun 	}
   1243   1.20    itojun 
   1244   1.20    itojun 	/* end-around-carry */
   1245   1.20    itojun 	sum = (sum >> 16) + (sum & 0xffff);
   1246   1.20    itojun 	sum += (sum >> 16);
   1247   1.87    dyoung 	return ~sum;
   1248    1.3       hwr }
   1249   1.54  christos #endif
   1250   1.54  christos 
   1251   1.59   thorpej void	greattach(int);
   1252   1.54  christos 
   1253   1.54  christos /* ARGSUSED */
   1254   1.54  christos void
   1255   1.74  christos greattach(int count)
   1256   1.54  christos {
   1257   1.54  christos #ifdef INET
   1258   1.54  christos 	LIST_INIT(&gre_softc_list);
   1259   1.54  christos 	if_clone_attach(&gre_cloner);
   1260   1.54  christos #endif
   1261   1.54  christos }
   1262