Home | History | Annotate | Line # | Download | only in net
if_gre.c revision 1.108
      1  1.108    dyoung /*	$NetBSD: if_gre.c,v 1.108 2007/09/02 07:01:41 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.108    dyoung __KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1.108 2007/09/02 07:01:41 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.106    dyoung 	sc->sc_dst.s_addr = sc->sc_src.s_addr = INADDR_ANY;
    195  1.106    dyoung 	sc->sc_dstport = sc->sc_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.62    dyoung 	struct mbuf *m;
    292   1.62    dyoung 	struct sockaddr_in *sin;
    293   1.62    dyoung 	struct socket *so;
    294   1.62    dyoung 
    295   1.62    dyoung 	GRE_DPRINTF(sc, "%s: enter\n", __func__);
    296   1.62    dyoung 	rc = socreate(AF_INET, sop, SOCK_DGRAM, IPPROTO_UDP, l);
    297   1.62    dyoung 	if (rc != 0) {
    298   1.62    dyoung 		GRE_DPRINTF(sc, "%s: socreate failed\n", __func__);
    299   1.62    dyoung 		return rc;
    300   1.62    dyoung 	}
    301   1.62    dyoung 
    302   1.62    dyoung 	so = *sop;
    303   1.62    dyoung 
    304   1.90    dyoung 	gre_upcall_add(so, sc);
    305   1.62    dyoung 	if ((m = gre_getsockmbuf(so)) == NULL) {
    306   1.62    dyoung 		rc = ENOBUFS;
    307   1.62    dyoung 		goto out;
    308   1.62    dyoung 	}
    309   1.62    dyoung 	sin = mtod(m, struct sockaddr_in *);
    310  1.106    dyoung 	sockaddr_in_init(sin, &sc->sc_src, sc->sc_srcport);
    311  1.102    dyoung 	m->m_len = sin->sin_len;
    312   1.62    dyoung 
    313   1.62    dyoung 	GRE_DPRINTF(sc, "%s: bind 0x%08" PRIx32 " port %d\n", __func__,
    314   1.62    dyoung 	    sin->sin_addr.s_addr, ntohs(sin->sin_port));
    315   1.62    dyoung 	if ((rc = sobind(so, m, l)) != 0) {
    316   1.62    dyoung 		GRE_DPRINTF(sc, "%s: sobind failed\n", __func__);
    317   1.62    dyoung 		goto out;
    318   1.62    dyoung 	}
    319   1.62    dyoung 
    320  1.106    dyoung 	if (sc->sc_srcport == 0) {
    321   1.69    dyoung 		if ((rc = gre_getsockname(so, m, l)) != 0) {
    322  1.103    dyoung 			GRE_DPRINTF(sc, "%s: gre_getsockname\n", __func__);
    323   1.62    dyoung 			goto out;
    324   1.62    dyoung 		}
    325  1.106    dyoung 		sc->sc_srcport = sin->sin_port;
    326   1.62    dyoung 	}
    327   1.62    dyoung 
    328  1.106    dyoung 	sockaddr_in_init(sin, &sc->sc_dst, sc->sc_dstport);
    329  1.102    dyoung 	m->m_len = sin->sin_len;
    330   1.62    dyoung 
    331   1.68    dyoung 	if ((rc = soconnect(so, m, l)) != 0) {
    332   1.62    dyoung 		GRE_DPRINTF(sc, "%s: soconnect failed\n", __func__);
    333   1.62    dyoung 		goto out;
    334   1.62    dyoung 	}
    335   1.62    dyoung 
    336   1.62    dyoung 	*mtod(m, int *) = ip_gre_ttl;
    337   1.76    dyoung 	m->m_len = sizeof(int);
    338  1.100     joerg 	KASSERT(so->so_proto && so->so_proto->pr_ctloutput);
    339   1.62    dyoung 	rc = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so, IPPROTO_IP, IP_TTL,
    340   1.62    dyoung 	    &m);
    341   1.62    dyoung 	m = NULL;
    342   1.62    dyoung 	if (rc != 0) {
    343  1.103    dyoung 		GRE_DPRINTF(sc, "%s: setopt ttl failed\n", __func__);
    344   1.62    dyoung 		rc = 0;
    345   1.62    dyoung 	}
    346   1.62    dyoung out:
    347   1.62    dyoung 	m_freem(m);
    348   1.62    dyoung 
    349   1.62    dyoung 	if (rc != 0)
    350   1.62    dyoung 		gre_sodestroy(sop);
    351  1.102    dyoung 	else {
    352  1.102    dyoung 		sc->sc_if.if_flags |= IFF_RUNNING;
    353  1.108    dyoung 		sc->sc_soparm = sc->sc_newsoparm;
    354  1.102    dyoung 	}
    355   1.62    dyoung 
    356   1.62    dyoung 	return rc;
    357   1.62    dyoung }
    358   1.62    dyoung 
    359   1.62    dyoung static void
    360  1.102    dyoung gre_do_recv(struct gre_softc *sc, struct socket *so, lwp_t *l)
    361  1.102    dyoung {
    362  1.102    dyoung 	for (;;) {
    363  1.102    dyoung 		int flags, rc;
    364  1.102    dyoung 		const struct gre_h *gh;
    365  1.102    dyoung 		struct mbuf *m;
    366  1.102    dyoung 
    367  1.102    dyoung 		flags = MSG_DONTWAIT;
    368  1.102    dyoung 		sc->sc_uio.uio_resid = 1000000;
    369  1.103    dyoung 		rc = (*so->so_receive)(so, NULL, &sc->sc_uio, &m, NULL, &flags);
    370  1.102    dyoung 		/* TBD Back off if ECONNREFUSED (indicates
    371  1.102    dyoung 		 * ICMP Port Unreachable)?
    372  1.102    dyoung 		 */
    373  1.102    dyoung 		if (rc == EWOULDBLOCK) {
    374  1.102    dyoung 			GRE_DPRINTF(sc, "%s: so_receive EWOULDBLOCK\n",
    375  1.102    dyoung 			    __func__);
    376  1.102    dyoung 			break;
    377  1.102    dyoung 		} else if (rc != 0 || m == NULL) {
    378  1.102    dyoung 			GRE_DPRINTF(sc, "%s: rc %d m %p\n",
    379  1.102    dyoung 			    sc->sc_if.if_xname, rc, (void *)m);
    380  1.102    dyoung 			continue;
    381  1.102    dyoung 		} else
    382  1.103    dyoung 			GRE_DPRINTF(sc, "%s: so_receive ok\n", __func__);
    383  1.102    dyoung 		if (m->m_len < sizeof(*gh) &&
    384  1.102    dyoung 		    (m = m_pullup(m, sizeof(*gh))) == NULL) {
    385  1.103    dyoung 			GRE_DPRINTF(sc, "%s: m_pullup failed\n", __func__);
    386  1.102    dyoung 			continue;
    387  1.102    dyoung 		}
    388  1.102    dyoung 		gh = mtod(m, const struct gre_h *);
    389  1.102    dyoung 
    390  1.103    dyoung 		if (gre_input3(sc, m, 0, gh, 0) == 0) {
    391  1.103    dyoung 			GRE_DPRINTF(sc, "%s: dropping unsupported\n", __func__);
    392  1.102    dyoung 			m_freem(m);
    393  1.102    dyoung 		}
    394  1.102    dyoung 	}
    395  1.102    dyoung }
    396  1.102    dyoung 
    397  1.102    dyoung static void
    398  1.102    dyoung gre_do_send(struct gre_softc *sc, struct socket *so, lwp_t *l)
    399  1.102    dyoung {
    400  1.102    dyoung 	for (;;) {
    401  1.102    dyoung 		int rc;
    402  1.102    dyoung 		struct mbuf *m;
    403  1.102    dyoung 
    404  1.103    dyoung 		mutex_enter(&sc->sc_mtx);
    405  1.102    dyoung 		IF_DEQUEUE(&sc->sc_snd, m);
    406  1.103    dyoung 		mutex_exit(&sc->sc_mtx);
    407  1.102    dyoung 		if (m == NULL)
    408  1.102    dyoung 			break;
    409  1.102    dyoung 		GRE_DPRINTF(sc, "%s: dequeue\n", __func__);
    410  1.102    dyoung 		if ((so->so_state & SS_ISCONNECTED) == 0) {
    411  1.103    dyoung 			GRE_DPRINTF(sc, "%s: not connected\n", __func__);
    412  1.102    dyoung 			m_freem(m);
    413  1.102    dyoung 			continue;
    414  1.102    dyoung 		}
    415  1.102    dyoung 		rc = (*so->so_send)(so, NULL, NULL, m, NULL, 0, l);
    416  1.102    dyoung 		/* XXX handle ENOBUFS? */
    417  1.102    dyoung 		if (rc != 0)
    418  1.102    dyoung 			GRE_DPRINTF(sc, "%s: so_send failed\n",
    419  1.102    dyoung 			    __func__);
    420  1.102    dyoung 	}
    421  1.102    dyoung }
    422  1.102    dyoung 
    423  1.102    dyoung static struct socket *
    424  1.102    dyoung gre_reconf(struct gre_softc *sc, struct socket *so, lwp_t *l)
    425  1.102    dyoung {
    426  1.102    dyoung 	struct ifnet *ifp = &sc->sc_if;
    427  1.102    dyoung 
    428  1.102    dyoung 	GRE_DPRINTF(sc, "%s: enter\n", __func__);
    429  1.102    dyoung 
    430  1.102    dyoung shutdown:
    431  1.105    dyoung 	if (sc->sc_soparm.sp_fp != NULL) {
    432  1.108    dyoung 		GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
    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.108    dyoung 		sc->sc_soparm = sc->sc_newsoparm;
    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 	} else if (gre_socreate1(sc, l, &so) != 0) {
    451  1.102    dyoung 		sc->sc_dying = 1;
    452  1.102    dyoung 		goto shutdown;
    453  1.102    dyoung 	}
    454  1.102    dyoung 	cv_signal(&sc->sc_soparm_cv);
    455  1.102    dyoung 	if (so != NULL)
    456  1.102    dyoung 		sc->sc_if.if_flags |= IFF_RUNNING;
    457  1.103    dyoung 	else if (sc->sc_proto == IPPROTO_UDP)
    458  1.102    dyoung 		sc->sc_if.if_flags &= ~IFF_RUNNING;
    459  1.102    dyoung 	return so;
    460  1.102    dyoung }
    461  1.102    dyoung 
    462  1.102    dyoung static void
    463   1.62    dyoung gre_thread1(struct gre_softc *sc, struct lwp *l)
    464   1.62    dyoung {
    465   1.62    dyoung 	struct ifnet *ifp = &sc->sc_if;
    466   1.62    dyoung 	struct socket *so = NULL;
    467   1.62    dyoung 
    468   1.62    dyoung 	GRE_DPRINTF(sc, "%s: enter\n", __func__);
    469   1.62    dyoung 
    470  1.102    dyoung 	while (!sc->sc_dying) {
    471   1.93    dyoung 		while (sc->sc_haswork == 0) {
    472   1.62    dyoung 			GRE_DPRINTF(sc, "%s: sleeping\n", __func__);
    473   1.93    dyoung 			cv_wait(&sc->sc_work_cv, &sc->sc_mtx);
    474   1.62    dyoung 		}
    475   1.93    dyoung 		sc->sc_haswork = 0;
    476  1.103    dyoung 
    477   1.62    dyoung 		GRE_DPRINTF(sc, "%s: awake\n", __func__);
    478  1.103    dyoung 
    479   1.62    dyoung 		/* XXX optimize */
    480  1.102    dyoung 		if ((ifp->if_flags & IFF_UP) != IFF_UP ||
    481  1.102    dyoung 		    sc->sc_proto != IPPROTO_UDP || so == NULL ||
    482  1.105    dyoung 		    sc->sc_newsoparm.sp_fp != NULL ||
    483  1.103    dyoung 		    memcmp(&sc->sc_soparm, &sc->sc_newsoparm,
    484  1.108    dyoung 		           offsetof(struct gre_soparm, sp_fp)) != 0)
    485  1.102    dyoung 			so = gre_reconf(sc, so, l);
    486  1.103    dyoung 		mutex_exit(&sc->sc_mtx);
    487  1.103    dyoung 		if (so != NULL) {
    488  1.103    dyoung 			gre_do_recv(sc, so, l);
    489  1.103    dyoung 			gre_do_send(sc, so, l);
    490  1.103    dyoung 		}
    491  1.103    dyoung 		mutex_enter(&sc->sc_mtx);
    492   1.62    dyoung 	}
    493  1.102    dyoung 	sc->sc_running = 0;
    494  1.102    dyoung 	cv_signal(&sc->sc_join_cv);
    495   1.62    dyoung }
    496   1.62    dyoung 
    497   1.62    dyoung static void
    498   1.62    dyoung gre_thread(void *arg)
    499   1.62    dyoung {
    500   1.62    dyoung 	struct gre_softc *sc = (struct gre_softc *)arg;
    501   1.62    dyoung 
    502  1.103    dyoung 	mutex_enter(&sc->sc_mtx);
    503   1.62    dyoung 	gre_thread1(sc, curlwp);
    504  1.103    dyoung 	mutex_exit(&sc->sc_mtx);
    505  1.103    dyoung 
    506   1.62    dyoung 	/* must not touch sc after this! */
    507   1.62    dyoung 	kthread_exit(0);
    508   1.62    dyoung }
    509   1.62    dyoung 
    510   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    511   1.62    dyoung int
    512   1.89    dyoung gre_input3(struct gre_softc *sc, struct mbuf *m, int hlen,
    513   1.93    dyoung     const struct gre_h *gh, int mtx_held)
    514   1.62    dyoung {
    515   1.62    dyoung 	u_int16_t flags;
    516   1.62    dyoung #if NBPFILTER > 0
    517   1.62    dyoung 	u_int32_t af = AF_INET;		/* af passed to BPF tap */
    518   1.62    dyoung #endif
    519   1.93    dyoung 	int isr;
    520   1.62    dyoung 	struct ifqueue *ifq;
    521   1.62    dyoung 
    522   1.62    dyoung 	sc->sc_if.if_ipackets++;
    523   1.62    dyoung 	sc->sc_if.if_ibytes += m->m_pkthdr.len;
    524   1.62    dyoung 
    525   1.89    dyoung 	hlen += sizeof(struct gre_h);
    526   1.62    dyoung 
    527   1.89    dyoung 	/* process GRE flags as packet can be of variable len */
    528   1.89    dyoung 	flags = ntohs(gh->flags);
    529   1.62    dyoung 
    530   1.89    dyoung 	/* Checksum & Offset are present */
    531   1.89    dyoung 	if ((flags & GRE_CP) | (flags & GRE_RP))
    532   1.89    dyoung 		hlen += 4;
    533   1.89    dyoung 	/* We don't support routing fields (variable length) */
    534   1.89    dyoung 	if (flags & GRE_RP) {
    535   1.89    dyoung 		sc->sc_if.if_ierrors++;
    536   1.89    dyoung 		return 0;
    537   1.89    dyoung 	}
    538   1.89    dyoung 	if (flags & GRE_KP)
    539   1.89    dyoung 		hlen += 4;
    540   1.89    dyoung 	if (flags & GRE_SP)
    541   1.89    dyoung 		hlen += 4;
    542   1.89    dyoung 
    543   1.89    dyoung 	switch (ntohs(gh->ptype)) { /* ethertypes */
    544   1.89    dyoung 	case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */
    545   1.89    dyoung 		ifq = &ipintrq;          /* we are in ip_input */
    546   1.89    dyoung 		isr = NETISR_IP;
    547   1.89    dyoung 		break;
    548   1.62    dyoung #ifdef NETATALK
    549   1.89    dyoung 	case ETHERTYPE_ATALK:
    550   1.89    dyoung 		ifq = &atintrq1;
    551   1.89    dyoung 		isr = NETISR_ATALK;
    552   1.62    dyoung #if NBPFILTER > 0
    553   1.89    dyoung 		af = AF_APPLETALK;
    554   1.62    dyoung #endif
    555   1.89    dyoung 		break;
    556   1.62    dyoung #endif
    557   1.62    dyoung #ifdef INET6
    558   1.89    dyoung 	case ETHERTYPE_IPV6:
    559   1.89    dyoung 		GRE_DPRINTF(sc, "%s: IPv6 packet\n", __func__);
    560   1.89    dyoung 		ifq = &ip6intrq;
    561   1.89    dyoung 		isr = NETISR_IPV6;
    562   1.62    dyoung #if NBPFILTER > 0
    563   1.89    dyoung 		af = AF_INET6;
    564   1.62    dyoung #endif
    565   1.89    dyoung 		break;
    566   1.62    dyoung #endif
    567   1.89    dyoung 	default:	   /* others not yet supported */
    568   1.90    dyoung 		GRE_DPRINTF(sc, "%s: unhandled ethertype 0x%04x\n", __func__,
    569   1.89    dyoung 		    ntohs(gh->ptype));
    570   1.89    dyoung 		sc->sc_if.if_noproto++;
    571   1.87    dyoung 		return 0;
    572   1.62    dyoung 	}
    573   1.62    dyoung 
    574   1.62    dyoung 	if (hlen > m->m_pkthdr.len) {
    575   1.62    dyoung 		m_freem(m);
    576   1.62    dyoung 		sc->sc_if.if_ierrors++;
    577   1.87    dyoung 		return EINVAL;
    578   1.62    dyoung 	}
    579   1.62    dyoung 	m_adj(m, hlen);
    580   1.62    dyoung 
    581   1.62    dyoung #if NBPFILTER > 0
    582   1.62    dyoung 	if (sc->sc_if.if_bpf != NULL)
    583   1.62    dyoung 		bpf_mtap_af(sc->sc_if.if_bpf, af, m);
    584   1.62    dyoung #endif /*NBPFILTER > 0*/
    585   1.62    dyoung 
    586   1.62    dyoung 	m->m_pkthdr.rcvif = &sc->sc_if;
    587   1.62    dyoung 
    588   1.93    dyoung 	if (!mtx_held)
    589   1.93    dyoung 		mutex_enter(&sc->sc_mtx);
    590   1.62    dyoung 	if (IF_QFULL(ifq)) {
    591   1.62    dyoung 		IF_DROP(ifq);
    592   1.62    dyoung 		m_freem(m);
    593   1.62    dyoung 	} else {
    594   1.62    dyoung 		IF_ENQUEUE(ifq, m);
    595   1.62    dyoung 	}
    596   1.62    dyoung 	/* we need schednetisr since the address family may change */
    597   1.62    dyoung 	schednetisr(isr);
    598   1.93    dyoung 	if (!mtx_held)
    599   1.93    dyoung 		mutex_exit(&sc->sc_mtx);
    600   1.62    dyoung 
    601   1.87    dyoung 	return 1;	/* packet is done, no further processing needed */
    602   1.62    dyoung }
    603   1.62    dyoung 
    604   1.20    itojun /*
    605    1.1       hwr  * The output routine. Takes a packet and encapsulates it in the protocol
    606   1.75    dyoung  * given by sc->sc_proto. See also RFC 1701 and RFC 2004
    607    1.1       hwr  */
    608   1.59   thorpej static int
    609   1.84    dyoung gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
    610   1.74  christos 	   struct rtentry *rt)
    611    1.1       hwr {
    612   1.89    dyoung 	int error = 0, hlen, msiz;
    613   1.10   thorpej 	struct gre_softc *sc = ifp->if_softc;
    614   1.62    dyoung 	struct greip *gi;
    615   1.62    dyoung 	struct gre_h *gh;
    616   1.62    dyoung 	struct ip *eip, *ip;
    617   1.56        is 	u_int8_t ip_tos = 0;
    618   1.48    itojun 	u_int16_t etype = 0;
    619   1.20    itojun 	struct mobile_h mob_h;
    620   1.24    martin 
    621   1.99     seanb 	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
    622   1.99     seanb 	    (IFF_UP | IFF_RUNNING) ||
    623  1.106    dyoung 	    sc->sc_src.s_addr == INADDR_ANY ||
    624  1.106    dyoung 	    sc->sc_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.106    dyoung 		ip->ip_dst.s_addr = sc->sc_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.106    dyoung 		if (in_hosteq(ip->ip_src, sc->sc_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.106    dyoung 			ip->ip_src.s_addr = sc->sc_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.106    dyoung 		eip->ip_src = sc->sc_src;
    760  1.106    dyoung 		eip->ip_dst = sc->sc_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.108    dyoung 	if (!sc->sc_running)
    819  1.102    dyoung 		return EBUSY;
    820  1.102    dyoung 	gre_wakeup(sc);
    821  1.102    dyoung 	return 0;
    822   1.62    dyoung }
    823   1.62    dyoung 
    824   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    825   1.62    dyoung static int
    826   1.62    dyoung gre_getname(struct socket *so, int req, struct mbuf *nam, struct lwp *l)
    827   1.62    dyoung {
    828   1.93    dyoung 	return (*so->so_proto->pr_usrreq)(so, req, NULL, nam, NULL, l);
    829   1.62    dyoung }
    830   1.62    dyoung 
    831   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    832   1.62    dyoung static int
    833   1.62    dyoung gre_getsockname(struct socket *so, struct mbuf *nam, struct lwp *l)
    834   1.62    dyoung {
    835   1.62    dyoung 	return gre_getname(so, PRU_SOCKADDR, nam, l);
    836   1.62    dyoung }
    837   1.62    dyoung 
    838   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    839   1.62    dyoung static int
    840   1.62    dyoung gre_getpeername(struct socket *so, struct mbuf *nam, struct lwp *l)
    841   1.62    dyoung {
    842   1.62    dyoung 	return gre_getname(so, PRU_PEERADDR, nam, l);
    843   1.62    dyoung }
    844   1.62    dyoung 
    845   1.93    dyoung /* Calling thread must hold sc->sc_mtx. */
    846   1.62    dyoung static int
    847   1.62    dyoung gre_getnames(struct socket *so, struct lwp *l, struct sockaddr_in *src,
    848   1.62    dyoung     struct sockaddr_in *dst)
    849   1.62    dyoung {
    850   1.62    dyoung 	struct mbuf *m;
    851   1.62    dyoung 	struct sockaddr_in *sin;
    852   1.62    dyoung 	int rc;
    853   1.62    dyoung 
    854   1.62    dyoung 	if ((m = gre_getsockmbuf(so)) == NULL)
    855   1.62    dyoung 		return ENOBUFS;
    856   1.62    dyoung 
    857   1.62    dyoung 	sin = mtod(m, struct sockaddr_in *);
    858   1.62    dyoung 
    859   1.62    dyoung 	if ((rc = gre_getsockname(so, m, l)) != 0)
    860   1.62    dyoung 		goto out;
    861   1.62    dyoung 	if (sin->sin_family != AF_INET) {
    862   1.62    dyoung 		rc = EAFNOSUPPORT;
    863   1.62    dyoung 		goto out;
    864   1.62    dyoung 	}
    865   1.62    dyoung 	*src = *sin;
    866   1.62    dyoung 
    867   1.62    dyoung 	if ((rc = gre_getpeername(so, m, l)) != 0)
    868   1.62    dyoung 		goto out;
    869   1.62    dyoung 	if (sin->sin_family != AF_INET) {
    870   1.62    dyoung 		rc = EAFNOSUPPORT;
    871   1.62    dyoung 		goto out;
    872   1.62    dyoung 	}
    873   1.62    dyoung 	*dst = *sin;
    874   1.62    dyoung 
    875   1.62    dyoung out:
    876   1.62    dyoung 	m_freem(m);
    877   1.62    dyoung 	return rc;
    878   1.62    dyoung }
    879   1.62    dyoung 
    880   1.93    dyoung static void
    881   1.93    dyoung gre_closef(struct file **fpp, struct lwp *l)
    882   1.93    dyoung {
    883   1.93    dyoung 	struct file *fp = *fpp;
    884   1.93    dyoung 
    885   1.93    dyoung 	simple_lock(&fp->f_slock);
    886   1.93    dyoung 	FILE_USE(fp);
    887   1.93    dyoung 	closef(fp, l);
    888   1.93    dyoung 	*fpp = NULL;
    889   1.93    dyoung }
    890   1.93    dyoung 
    891   1.59   thorpej static int
    892  1.107    dyoung gre_ioctl(struct ifnet *ifp, const u_long cmd, void *data)
    893    1.1       hwr {
    894   1.62    dyoung 	u_char oproto;
    895   1.93    dyoung 	struct file *fp;
    896   1.62    dyoung 	struct socket *so;
    897   1.62    dyoung 	struct sockaddr_in dst, src;
    898   1.62    dyoung 	struct proc *p = curproc;	/* XXX */
    899   1.61        ad 	struct lwp *l = curlwp;	/* XXX */
    900   1.94  christos 	struct ifreq *ifr;
    901   1.28    itojun 	struct if_laddrreq *lifr = (struct if_laddrreq *)data;
    902    1.8  explorer 	struct gre_softc *sc = ifp->if_softc;
    903    1.1       hwr 	struct sockaddr_in si;
    904  1.106    dyoung 	const struct sockaddr *sa;
    905   1.80  christos 	int error = 0;
    906  1.107    dyoung 
    907  1.107    dyoung 	ifr = data;
    908  1.107    dyoung 
    909   1.61        ad 	switch (cmd) {
    910   1.61        ad 	case SIOCSIFFLAGS:
    911   1.61        ad 	case SIOCSIFMTU:
    912   1.61        ad 	case GRESPROTO:
    913   1.61        ad 	case GRESADDRD:
    914   1.61        ad 	case GRESADDRS:
    915   1.62    dyoung 	case GRESSOCK:
    916   1.62    dyoung 	case GREDSOCK:
    917   1.61        ad 	case SIOCSLIFPHYADDR:
    918   1.61        ad 	case SIOCDIFPHYADDR:
    919   1.70      elad 		if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
    920   1.70      elad 		    KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
    921   1.70      elad 		    NULL) != 0)
    922   1.87    dyoung 			return EPERM;
    923   1.61        ad 		break;
    924   1.61        ad 	default:
    925   1.61        ad 		break;
    926   1.61        ad 	}
    927    1.1       hwr 
    928   1.93    dyoung 	mutex_enter(&sc->sc_mtx);
    929   1.20    itojun 	switch (cmd) {
    930   1.20    itojun 	case SIOCSIFADDR:
    931   1.36    itojun 		ifp->if_flags |= IFF_UP;
    932   1.78    dyoung 		if ((error = gre_kick(sc)) != 0)
    933   1.78    dyoung 			ifp->if_flags &= ~IFF_UP;
    934   1.36    itojun 		break;
    935   1.55     perry 	case SIOCSIFDSTADDR:
    936    1.1       hwr 		break;
    937    1.1       hwr 	case SIOCSIFFLAGS:
    938   1.75    dyoung 		oproto = sc->sc_proto;
    939   1.62    dyoung 		switch (ifr->ifr_flags & (IFF_LINK0|IFF_LINK2)) {
    940   1.62    dyoung 		case IFF_LINK0|IFF_LINK2:
    941   1.75    dyoung 			sc->sc_proto = IPPROTO_UDP;
    942   1.62    dyoung 			if (oproto != IPPROTO_UDP)
    943   1.62    dyoung 				ifp->if_flags &= ~IFF_RUNNING;
    944   1.62    dyoung 			error = gre_kick(sc);
    945   1.62    dyoung 			break;
    946   1.62    dyoung 		case IFF_LINK0:
    947   1.75    dyoung 			sc->sc_proto = IPPROTO_GRE;
    948   1.62    dyoung 			gre_wakeup(sc);
    949   1.62    dyoung 			goto recompute;
    950   1.62    dyoung 		case 0:
    951   1.75    dyoung 			sc->sc_proto = IPPROTO_MOBILE;
    952   1.62    dyoung 			gre_wakeup(sc);
    953   1.62    dyoung 			goto recompute;
    954   1.62    dyoung 		}
    955    1.1       hwr 		break;
    956   1.20    itojun 	case SIOCSIFMTU:
    957   1.27    martin 		if (ifr->ifr_mtu < 576) {
    958    1.1       hwr 			error = EINVAL;
    959    1.1       hwr 			break;
    960    1.1       hwr 		}
    961    1.1       hwr 		ifp->if_mtu = ifr->ifr_mtu;
    962    1.1       hwr 		break;
    963    1.1       hwr 	case SIOCGIFMTU:
    964    1.1       hwr 		ifr->ifr_mtu = sc->sc_if.if_mtu;
    965    1.1       hwr 		break;
    966    1.1       hwr 	case SIOCADDMULTI:
    967    1.1       hwr 	case SIOCDELMULTI:
    968  1.106    dyoung 		if (ifr == NULL) {
    969    1.1       hwr 			error = EAFNOSUPPORT;
    970    1.1       hwr 			break;
    971    1.1       hwr 		}
    972  1.106    dyoung 		switch (ifreq_getaddr(cmd, ifr)->sa_family) {
    973    1.1       hwr #ifdef INET
    974    1.1       hwr 		case AF_INET:
    975    1.1       hwr 			break;
    976    1.1       hwr #endif
    977   1.56        is #ifdef INET6
    978   1.56        is 		case AF_INET6:
    979   1.56        is 			break;
    980   1.56        is #endif
    981    1.1       hwr 		default:
    982    1.1       hwr 			error = EAFNOSUPPORT;
    983    1.1       hwr 			break;
    984    1.1       hwr 		}
    985    1.1       hwr 		break;
    986    1.1       hwr 	case GRESPROTO:
    987   1.75    dyoung 		oproto = sc->sc_proto;
    988   1.75    dyoung 		sc->sc_proto = ifr->ifr_flags;
    989   1.75    dyoung 		switch (sc->sc_proto) {
    990   1.62    dyoung 		case IPPROTO_UDP:
    991   1.62    dyoung 			ifp->if_flags |= IFF_LINK0|IFF_LINK2;
    992   1.62    dyoung 			if (oproto != IPPROTO_UDP)
    993   1.62    dyoung 				ifp->if_flags &= ~IFF_RUNNING;
    994   1.62    dyoung 			error = gre_kick(sc);
    995   1.62    dyoung 			break;
    996   1.40    itojun 		case IPPROTO_GRE:
    997    1.3       hwr 			ifp->if_flags |= IFF_LINK0;
    998   1.62    dyoung 			ifp->if_flags &= ~IFF_LINK2;
    999   1.62    dyoung 			goto recompute;
   1000   1.40    itojun 		case IPPROTO_MOBILE:
   1001   1.62    dyoung 			ifp->if_flags &= ~(IFF_LINK0|IFF_LINK2);
   1002   1.62    dyoung 			goto recompute;
   1003    1.1       hwr 		default:
   1004   1.40    itojun 			error = EPROTONOSUPPORT;
   1005   1.35    itojun 			break;
   1006    1.1       hwr 		}
   1007    1.1       hwr 		break;
   1008    1.1       hwr 	case GREGPROTO:
   1009   1.75    dyoung 		ifr->ifr_flags = sc->sc_proto;
   1010    1.1       hwr 		break;
   1011    1.1       hwr 	case GRESADDRS:
   1012    1.1       hwr 	case GRESADDRD:
   1013    1.1       hwr 		/*
   1014   1.20    itojun 		 * set tunnel endpoints, compute a less specific route
   1015   1.20    itojun 		 * to the remote end and mark if as up
   1016   1.20    itojun 		 */
   1017    1.1       hwr 		sa = &ifr->ifr_addr;
   1018   1.62    dyoung 		if (cmd == GRESADDRS) {
   1019  1.106    dyoung 			sc->sc_src = satocsin(sa)->sin_addr;
   1020  1.106    dyoung 			sc->sc_srcport = satocsin(sa)->sin_port;
   1021   1.62    dyoung 		}
   1022   1.62    dyoung 		if (cmd == GRESADDRD) {
   1023   1.75    dyoung 			if (sc->sc_proto == IPPROTO_UDP &&
   1024  1.106    dyoung 			    satocsin(sa)->sin_port == 0) {
   1025   1.62    dyoung 				error = EINVAL;
   1026   1.62    dyoung 				break;
   1027   1.62    dyoung 			}
   1028  1.106    dyoung 			sc->sc_dst = satocsin(sa)->sin_addr;
   1029  1.106    dyoung 			sc->sc_dstport = satocsin(sa)->sin_port;
   1030   1.62    dyoung 		}
   1031   1.30    itojun 	recompute:
   1032   1.75    dyoung 		if (sc->sc_proto == IPPROTO_UDP ||
   1033  1.106    dyoung 		    (sc->sc_src.s_addr != INADDR_ANY &&
   1034  1.106    dyoung 		     sc->sc_dst.s_addr != INADDR_ANY)) {
   1035   1.81     joerg 			rtcache_free(&sc->route);
   1036  1.102    dyoung 			if (sc->sc_proto == IPPROTO_UDP) {
   1037  1.102    dyoung 				if ((error = gre_kick(sc)) == 0)
   1038  1.102    dyoung 					ifp->if_flags |= IFF_RUNNING;
   1039  1.102    dyoung 				else
   1040  1.102    dyoung 					ifp->if_flags &= ~IFF_RUNNING;
   1041  1.102    dyoung 			}
   1042   1.62    dyoung 			else if (gre_compute_route(sc) == 0)
   1043   1.39    itojun 				ifp->if_flags |= IFF_RUNNING;
   1044   1.39    itojun 			else
   1045   1.39    itojun 				ifp->if_flags &= ~IFF_RUNNING;
   1046    1.1       hwr 		}
   1047    1.1       hwr 		break;
   1048    1.1       hwr 	case GREGADDRS:
   1049  1.106    dyoung 		sockaddr_in_init(&si, &sc->sc_src,
   1050  1.106    dyoung 		    (sc->sc_proto == IPPROTO_UDP) ? sc->sc_srcport : 0);
   1051  1.102    dyoung 		ifr->ifr_addr = *sintosa(&si);
   1052    1.1       hwr 		break;
   1053    1.1       hwr 	case GREGADDRD:
   1054  1.106    dyoung 		sockaddr_in_init(&si, &sc->sc_dst,
   1055  1.106    dyoung 		    (sc->sc_proto == IPPROTO_UDP) ? sc->sc_dstport : 0);
   1056  1.102    dyoung 		ifr->ifr_addr = *sintosa(&si);
   1057   1.28    itojun 		break;
   1058   1.62    dyoung 	case GREDSOCK:
   1059   1.93    dyoung 		if (sc->sc_proto != IPPROTO_UDP) {
   1060   1.93    dyoung 			error = EINVAL;
   1061   1.93    dyoung 			break;
   1062   1.63    dyoung 		}
   1063   1.93    dyoung 		ifp->if_flags &= ~IFF_UP;
   1064   1.93    dyoung 		gre_wakeup(sc);
   1065   1.62    dyoung 		break;
   1066   1.62    dyoung 	case GRESSOCK:
   1067   1.93    dyoung 		if (sc->sc_proto != IPPROTO_UDP) {
   1068  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1069   1.93    dyoung 			error = EINVAL;
   1070   1.93    dyoung 			break;
   1071   1.93    dyoung 		}
   1072   1.93    dyoung 		/* getsock() will FILE_USE() and unlock the descriptor for us */
   1073  1.102    dyoung 		if ((error = getsock(p->p_fd, (int)ifr->ifr_value, &fp)) != 0) {
   1074  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1075  1.102    dyoung 			error = EINVAL;
   1076   1.62    dyoung 			break;
   1077  1.102    dyoung 		}
   1078   1.62    dyoung 		so = (struct socket *)fp->f_data;
   1079   1.62    dyoung 		if (so->so_type != SOCK_DGRAM) {
   1080  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1081   1.62    dyoung 			FILE_UNUSE(fp, NULL);
   1082   1.62    dyoung 			error = EINVAL;
   1083   1.62    dyoung 			break;
   1084   1.62    dyoung 		}
   1085   1.62    dyoung 		/* check address */
   1086   1.62    dyoung 		if ((error = gre_getnames(so, curlwp, &src, &dst)) != 0) {
   1087  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1088   1.62    dyoung 			FILE_UNUSE(fp, NULL);
   1089   1.62    dyoung 			break;
   1090   1.62    dyoung 		}
   1091   1.62    dyoung 
   1092   1.93    dyoung                 /* Increase reference count.  Now that our reference
   1093   1.93    dyoung                  * to the file descriptor is counted, this thread
   1094   1.93    dyoung                  * can release our "use" of the descriptor, but it
   1095   1.93    dyoung                  * will not be destroyed by some other thread's
   1096   1.93    dyoung                  * action.  This thread needs to release its use,
   1097   1.93    dyoung                  * too, because one and only one thread can have
   1098   1.93    dyoung                  * use of the descriptor at once.  The kernel thread
   1099   1.93    dyoung                  * will pick up the use if it needs it.
   1100   1.93    dyoung 		 */
   1101   1.93    dyoung 
   1102   1.62    dyoung 		fp->f_count++;
   1103  1.108    dyoung 		GRE_DPRINTF(sc, "%s: l.%d f_count %d\n", __func__, __LINE__,
   1104  1.108    dyoung 		    fp->f_count);
   1105   1.93    dyoung 		FILE_UNUSE(fp, NULL);
   1106   1.93    dyoung 
   1107  1.105    dyoung 		while (sc->sc_newsoparm.sp_fp != NULL && error == 0) {
   1108  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1109   1.93    dyoung 			error = cv_timedwait_sig(&sc->sc_soparm_cv, &sc->sc_mtx,
   1110   1.93    dyoung 					         MAX(1, hz / 2));
   1111   1.93    dyoung 		}
   1112   1.93    dyoung 		if (error == 0) {
   1113  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1114  1.105    dyoung 			sc->sc_newsoparm.sp_fp = fp;
   1115   1.93    dyoung 			ifp->if_flags |= IFF_UP;
   1116   1.93    dyoung 		}
   1117   1.62    dyoung 
   1118   1.93    dyoung 		if (error != 0 || (error = gre_kick(sc)) != 0) {
   1119  1.102    dyoung 			GRE_DPRINTF(sc, "%s: l.%d\n", __func__, __LINE__);
   1120   1.93    dyoung 			gre_closef(&fp, l);
   1121   1.62    dyoung 			break;
   1122   1.62    dyoung 		}
   1123   1.93    dyoung 		/* fp does not any longer belong to this thread. */
   1124  1.106    dyoung 		sc->sc_src = src.sin_addr;
   1125  1.106    dyoung 		sc->sc_srcport = src.sin_port;
   1126  1.106    dyoung 		sc->sc_dst = dst.sin_addr;
   1127  1.106    dyoung 		sc->sc_dstport = dst.sin_port;
   1128  1.102    dyoung 		GRE_DPRINTF(sc, "%s: sock 0x%08" PRIx32 " port %d -> "
   1129  1.102    dyoung 		    "0x%08" PRIx32 " port %d\n", __func__,
   1130  1.102    dyoung 		    src.sin_addr.s_addr, ntohs(src.sin_port),
   1131  1.102    dyoung 		    dst.sin_addr.s_addr, ntohs(dst.sin_port));
   1132   1.62    dyoung 		break;
   1133   1.28    itojun 	case SIOCSLIFPHYADDR:
   1134   1.28    itojun 		if (lifr->addr.ss_family != AF_INET ||
   1135   1.31    itojun 		    lifr->dstaddr.ss_family != AF_INET) {
   1136   1.31    itojun 			error = EAFNOSUPPORT;
   1137   1.31    itojun 			break;
   1138   1.31    itojun 		}
   1139   1.28    itojun 		if (lifr->addr.ss_len != sizeof(si) ||
   1140   1.31    itojun 		    lifr->dstaddr.ss_len != sizeof(si)) {
   1141   1.31    itojun 			error = EINVAL;
   1142   1.31    itojun 			break;
   1143   1.31    itojun 		}
   1144  1.106    dyoung 		sc->sc_src = satocsin(&lifr->addr)->sin_addr;
   1145  1.106    dyoung 		sc->sc_dst = satocsin(&lifr->dstaddr)->sin_addr;
   1146  1.106    dyoung 		sc->sc_srcport = satocsin(&lifr->addr)->sin_port;
   1147  1.106    dyoung 		sc->sc_dstport = satocsin(&lifr->dstaddr)->sin_port;
   1148   1.30    itojun 		goto recompute;
   1149   1.28    itojun 	case SIOCDIFPHYADDR:
   1150  1.106    dyoung 		sc->sc_src.s_addr = INADDR_ANY;
   1151  1.106    dyoung 		sc->sc_dst.s_addr = INADDR_ANY;
   1152  1.106    dyoung 		sc->sc_srcport = 0;
   1153  1.106    dyoung 		sc->sc_dstport = 0;
   1154   1.62    dyoung 		goto recompute;
   1155   1.28    itojun 	case SIOCGLIFPHYADDR:
   1156  1.106    dyoung 		if (sc->sc_src.s_addr == INADDR_ANY ||
   1157  1.106    dyoung 		    sc->sc_dst.s_addr == INADDR_ANY) {
   1158   1.28    itojun 			error = EADDRNOTAVAIL;
   1159   1.28    itojun 			break;
   1160   1.28    itojun 		}
   1161  1.106    dyoung 		sockaddr_in_init(satosin(&lifr->addr), &sc->sc_src,
   1162  1.106    dyoung 		    (sc->sc_proto == IPPROTO_UDP) ? sc->sc_srcport : 0);
   1163  1.106    dyoung 		sockaddr_in_init(satosin(&lifr->dstaddr), &sc->sc_dst,
   1164  1.106    dyoung 		    (sc->sc_proto == IPPROTO_UDP) ? sc->sc_dstport : 0);
   1165    1.1       hwr 		break;
   1166    1.1       hwr 	default:
   1167    1.1       hwr 		error = EINVAL;
   1168   1.31    itojun 		break;
   1169    1.1       hwr 	}
   1170   1.93    dyoung 	mutex_exit(&sc->sc_mtx);
   1171   1.87    dyoung 	return error;
   1172    1.1       hwr }
   1173    1.1       hwr 
   1174   1.20    itojun /*
   1175   1.78    dyoung  * Compute a route to our destination.
   1176    1.1       hwr  */
   1177   1.59   thorpej static int
   1178    1.8  explorer gre_compute_route(struct gre_softc *sc)
   1179    1.1       hwr {
   1180    1.1       hwr 	struct route *ro;
   1181   1.92    dyoung 	union {
   1182   1.92    dyoung 		struct sockaddr		dst;
   1183   1.92    dyoung 		struct sockaddr_in	dst4;
   1184   1.92    dyoung 	} u;
   1185    1.1       hwr 
   1186    1.8  explorer 	ro = &sc->route;
   1187   1.20    itojun 
   1188   1.92    dyoung 	memset(ro, 0, sizeof(*ro));
   1189  1.106    dyoung 	sockaddr_in_init(&u.dst4, &sc->sc_dst, 0);
   1190   1.92    dyoung 	rtcache_setdst(ro, &u.dst);
   1191    1.8  explorer 
   1192   1.81     joerg 	rtcache_init(ro);
   1193   1.81     joerg 
   1194   1.81     joerg 	if (ro->ro_rt == NULL || ro->ro_rt->rt_ifp->if_softc == sc) {
   1195   1.90    dyoung 		GRE_DPRINTF(sc, "%s: route to %s %s\n", sc->sc_if.if_xname,
   1196   1.92    dyoung 		    inet_ntoa(u.dst4.sin_addr),
   1197   1.90    dyoung 		    (ro->ro_rt == NULL)
   1198   1.90    dyoung 		        ?  "does not exist"
   1199   1.90    dyoung 			: "loops back to ourself");
   1200   1.81     joerg 		rtcache_free(ro);
   1201   1.81     joerg 		return EADDRNOTAVAIL;
   1202   1.25    martin 	}
   1203   1.25    martin 
   1204   1.25    martin 	return 0;
   1205    1.1       hwr }
   1206    1.1       hwr 
   1207    1.3       hwr /*
   1208   1.20    itojun  * do a checksum of a buffer - much like in_cksum, which operates on
   1209   1.20    itojun  * mbufs.
   1210    1.3       hwr  */
   1211   1.48    itojun u_int16_t
   1212   1.48    itojun gre_in_cksum(u_int16_t *p, u_int len)
   1213    1.3       hwr {
   1214   1.48    itojun 	u_int32_t sum = 0;
   1215    1.3       hwr 	int nwords = len >> 1;
   1216   1.20    itojun 
   1217    1.3       hwr 	while (nwords-- != 0)
   1218    1.3       hwr 		sum += *p++;
   1219   1.20    itojun 
   1220   1.20    itojun 	if (len & 1) {
   1221   1.20    itojun 		union {
   1222   1.20    itojun 			u_short w;
   1223   1.20    itojun 			u_char c[2];
   1224   1.20    itojun 		} u;
   1225   1.20    itojun 		u.c[0] = *(u_char *)p;
   1226   1.20    itojun 		u.c[1] = 0;
   1227   1.20    itojun 		sum += u.w;
   1228   1.20    itojun 	}
   1229   1.20    itojun 
   1230   1.20    itojun 	/* end-around-carry */
   1231   1.20    itojun 	sum = (sum >> 16) + (sum & 0xffff);
   1232   1.20    itojun 	sum += (sum >> 16);
   1233   1.87    dyoung 	return ~sum;
   1234    1.3       hwr }
   1235   1.54  christos #endif
   1236   1.54  christos 
   1237   1.59   thorpej void	greattach(int);
   1238   1.54  christos 
   1239   1.54  christos /* ARGSUSED */
   1240   1.54  christos void
   1241   1.74  christos greattach(int count)
   1242   1.54  christos {
   1243   1.54  christos #ifdef INET
   1244   1.54  christos 	LIST_INIT(&gre_softc_list);
   1245   1.54  christos 	if_clone_attach(&gre_cloner);
   1246   1.54  christos #endif
   1247   1.54  christos }
   1248