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