The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if_gre.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: if_gre.c,v 1.184 2022/09/03 02:47:59 thorpej Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Heiko W.Rupp <hwr@pilhuhn.de>
    9  *
   10  * IPv6-over-GRE contributed by Gert Doering <gert@greenie.muc.de>
   11  *
   12  * GRE over UDP/IPv4/IPv6 sockets contributed by David Young <dyoung@NetBSD.org>
   13  *
   14  * Redistribution and use in source and binary forms, with or without
   15  * modification, are permitted provided that the following conditions
   16  * are met:
   17  * 1. Redistributions of source code must retain the above copyright
   18  *    notice, this list of conditions and the following disclaimer.
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   27  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   33  * POSSIBILITY OF SUCH DAMAGE.
   34  *
   35  * This material is based upon work partially supported by NSF
   36  * under Contract No. NSF CNS-0626584.
   37  */
   38 
   39 /*
   40  * Encapsulate L3 protocols into IP
   41  * See RFC 1701 and 1702 for more details.
   42  * If_gre is compatible with Cisco GRE tunnels, so you can
   43  * have a NetBSD box as the other end of a tunnel interface of a Cisco
   44  * router. See gre(4) for more details.
   45  */
   46 
   47 #include <sys/cdefs.h>
   48 __KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1.184 2022/09/03 02:47:59 thorpej Exp $");
   49 
   50 #ifdef _KERNEL_OPT
   51 #include "opt_atalk.h"
   52 #include "opt_gre.h"
   53 #include "opt_inet.h"
   54 #include "opt_mpls.h"
   55 #endif
   56 
   57 #include <sys/param.h>
   58 #include <sys/file.h>
   59 #include <sys/filedesc.h>
   60 #include <sys/malloc.h>
   61 #include <sys/mallocvar.h>
   62 #include <sys/mbuf.h>
   63 #include <sys/proc.h>
   64 #include <sys/domain.h>
   65 #include <sys/protosw.h>
   66 #include <sys/socket.h>
   67 #include <sys/socketvar.h>
   68 #include <sys/ioctl.h>
   69 #include <sys/queue.h>
   70 #include <sys/intr.h>
   71 #include <sys/systm.h>
   72 #include <sys/sysctl.h>
   73 #include <sys/kauth.h>
   74 #include <sys/device.h>
   75 #include <sys/module.h>
   76 
   77 #include <sys/kernel.h>
   78 #include <sys/mutex.h>
   79 #include <sys/condvar.h>
   80 #include <sys/kthread.h>
   81 
   82 #include <sys/cpu.h>
   83 
   84 #include <net/ethertypes.h>
   85 #include <net/if.h>
   86 #include <net/if_types.h>
   87 #include <net/route.h>
   88 #include <sys/device.h>
   89 #include <sys/module.h>
   90 #include <sys/atomic.h>
   91 
   92 #include <netinet/in_systm.h>
   93 #include <netinet/in.h>
   94 #include <netinet/ip.h> /* we always need this for sizeof(struct ip) */
   95 
   96 #ifdef INET
   97 #include <netinet/in_var.h>
   98 #include <netinet/ip_var.h>
   99 #endif
  100 
  101 #ifdef INET6
  102 #include <netinet6/in6_var.h>
  103 #endif
  104 
  105 #ifdef MPLS
  106 #include <netmpls/mpls.h>
  107 #include <netmpls/mpls_var.h>
  108 #endif
  109 
  110 #ifdef NETATALK
  111 #include <netatalk/at.h>
  112 #include <netatalk/at_var.h>
  113 #include <netatalk/at_extern.h>
  114 #endif
  115 
  116 #include <sys/time.h>
  117 #include <net/bpf.h>
  118 
  119 #include <net/if_gre.h>
  120 
  121 #include "ioconf.h"
  122 
  123 /*
  124  * It is not easy to calculate the right value for a GRE MTU.
  125  * We leave this task to the admin and use the same default that
  126  * other vendors use.
  127  */
  128 #define GREMTU 1476
  129 
  130 #ifdef GRE_DEBUG
  131 int gre_debug = 0;
  132 #define GRE_DPRINTF(__sc, ...)                                          \
  133         do {                                                            \
  134                 if (__predict_false(gre_debug ||                        \
  135                     ((__sc)->sc_if.if_flags & IFF_DEBUG) != 0)) {       \
  136                         printf("%s.%d: ", __func__, __LINE__);          \
  137                         printf(__VA_ARGS__);                            \
  138                 }                                                       \
  139         } while (/*CONSTCOND*/0)
  140 #else
  141 #define GRE_DPRINTF(__sc, __fmt, ...)   do { } while (/*CONSTCOND*/0)
  142 #endif /* GRE_DEBUG */
  143 
  144 CTASSERT(sizeof(struct gre_h) == 4);
  145 
  146 int ip_gre_ttl = GRE_TTL;
  147 
  148 static u_int gre_count;
  149 
  150 static int gre_clone_create(struct if_clone *, int);
  151 static int gre_clone_destroy(struct ifnet *);
  152 
  153 static struct if_clone gre_cloner =
  154     IF_CLONE_INITIALIZER("gre", gre_clone_create, gre_clone_destroy);
  155 
  156 static int gre_input(struct gre_softc *, struct mbuf *, const struct gre_h *);
  157 static bool gre_is_nullconf(const struct gre_soparm *);
  158 static int gre_output(struct ifnet *, struct mbuf *,
  159                            const struct sockaddr *, const struct rtentry *);
  160 static int gre_ioctl(struct ifnet *, u_long, void *);
  161 static int gre_getsockname(struct socket *, struct sockaddr *);
  162 static int gre_getpeername(struct socket *, struct sockaddr *);
  163 static int gre_getnames(struct socket *, struct lwp *,
  164     struct sockaddr_storage *, struct sockaddr_storage *);
  165 static void gre_clearconf(struct gre_soparm *, bool);
  166 static int gre_soreceive(struct socket *, struct mbuf **);
  167 static int gre_sosend(struct socket *, struct mbuf *);
  168 static struct socket *gre_reconf(struct gre_softc *, const struct gre_soparm *);
  169 
  170 static bool gre_fp_send(struct gre_softc *, enum gre_msg, file_t *);
  171 static bool gre_fp_recv(struct gre_softc *);
  172 static void gre_fp_recvloop(void *);
  173 
  174 static void
  175 gre_bufq_init(struct gre_bufq *bq, size_t len0)
  176 {
  177         memset(bq, 0, sizeof(*bq));
  178         bq->bq_q = pcq_create(len0, KM_SLEEP);
  179         KASSERT(bq->bq_q != NULL);
  180 }
  181 
  182 static struct mbuf *
  183 gre_bufq_dequeue(struct gre_bufq *bq)
  184 {
  185         return pcq_get(bq->bq_q);
  186 }
  187 
  188 static void
  189 gre_bufq_purge(struct gre_bufq *bq)
  190 {
  191         struct mbuf *m;
  192 
  193         while ((m = gre_bufq_dequeue(bq)) != NULL)
  194                 m_freem(m);
  195 }
  196 
  197 static void
  198 gre_bufq_destroy(struct gre_bufq *bq)
  199 {
  200         gre_bufq_purge(bq);
  201         pcq_destroy(bq->bq_q);
  202 }
  203 
  204 static int
  205 gre_bufq_enqueue(struct gre_bufq *bq, struct mbuf *m)
  206 {
  207         KASSERT(bq->bq_q != NULL);
  208 
  209         if (!pcq_put(bq->bq_q, m)) {
  210                 bq->bq_drops++;
  211                 return ENOBUFS;
  212         }
  213         return 0;
  214 }
  215 
  216 static void
  217 greintr(void *arg)
  218 {
  219         struct gre_softc *sc = (struct gre_softc *)arg;
  220         struct socket *so = sc->sc_soparm.sp_so;
  221         int rc;
  222         struct mbuf *m;
  223 
  224         KASSERT(so != NULL);
  225 
  226         sc->sc_send_ev.ev_count++;
  227         GRE_DPRINTF(sc, "enter\n");
  228         while ((m = gre_bufq_dequeue(&sc->sc_snd)) != NULL) {
  229                 /* XXX handle ENOBUFS? */
  230                 if ((rc = gre_sosend(so, m)) != 0)
  231                         GRE_DPRINTF(sc, "gre_sosend failed %d\n", rc);
  232         }
  233 }
  234 
  235 /* Caller must hold sc->sc_mtx. */
  236 static void
  237 gre_fp_wait(struct gre_softc *sc)
  238 {
  239         sc->sc_fp_waiters++;
  240         cv_wait(&sc->sc_fp_condvar, &sc->sc_mtx);
  241         sc->sc_fp_waiters--;
  242 }
  243 
  244 static void
  245 gre_evcnt_detach(struct gre_softc *sc)
  246 {
  247         evcnt_detach(&sc->sc_recv_ev);
  248         evcnt_detach(&sc->sc_block_ev);
  249         evcnt_detach(&sc->sc_error_ev);
  250         evcnt_detach(&sc->sc_pullup_ev);
  251         evcnt_detach(&sc->sc_unsupp_ev);
  252 
  253         evcnt_detach(&sc->sc_send_ev);
  254         evcnt_detach(&sc->sc_oflow_ev);
  255 }
  256 
  257 static void
  258 gre_evcnt_attach(struct gre_softc *sc)
  259 {
  260         evcnt_attach_dynamic(&sc->sc_recv_ev, EVCNT_TYPE_MISC,
  261             NULL, sc->sc_if.if_xname, "recv");
  262         evcnt_attach_dynamic(&sc->sc_block_ev, EVCNT_TYPE_MISC,
  263             &sc->sc_recv_ev, sc->sc_if.if_xname, "would block");
  264         evcnt_attach_dynamic(&sc->sc_error_ev, EVCNT_TYPE_MISC,
  265             &sc->sc_recv_ev, sc->sc_if.if_xname, "error");
  266         evcnt_attach_dynamic(&sc->sc_pullup_ev, EVCNT_TYPE_MISC,
  267             &sc->sc_recv_ev, sc->sc_if.if_xname, "pullup failed");
  268         evcnt_attach_dynamic(&sc->sc_unsupp_ev, EVCNT_TYPE_MISC,
  269             &sc->sc_recv_ev, sc->sc_if.if_xname, "unsupported");
  270 
  271         evcnt_attach_dynamic(&sc->sc_send_ev, EVCNT_TYPE_MISC,
  272             NULL, sc->sc_if.if_xname, "send");
  273         evcnt_attach_dynamic(&sc->sc_oflow_ev, EVCNT_TYPE_MISC,
  274             &sc->sc_send_ev, sc->sc_if.if_xname, "overflow");
  275 }
  276 
  277 static int
  278 gre_clone_create(struct if_clone *ifc, int unit)
  279 {
  280         int rc;
  281         struct gre_softc *sc;
  282         struct gre_soparm *sp;
  283         const struct sockaddr *any;
  284 
  285         if ((any = sockaddr_any_by_family(AF_INET)) == NULL &&
  286             (any = sockaddr_any_by_family(AF_INET6)) == NULL)
  287                 goto fail0;
  288 
  289         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
  290         mutex_init(&sc->sc_mtx, MUTEX_DRIVER, IPL_SOFTNET);
  291         cv_init(&sc->sc_condvar, "gre wait");
  292         cv_init(&sc->sc_fp_condvar, "gre fp");
  293 
  294         if_initname(&sc->sc_if, ifc->ifc_name, unit);
  295         sc->sc_if.if_softc = sc;
  296         sc->sc_if.if_type = IFT_TUNNEL;
  297         sc->sc_if.if_addrlen = 0;
  298         sc->sc_if.if_hdrlen = sizeof(struct ip) + sizeof(struct gre_h);
  299         sc->sc_if.if_dlt = DLT_NULL;
  300         sc->sc_if.if_mtu = GREMTU;
  301         sc->sc_if.if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
  302         sc->sc_if.if_output = gre_output;
  303         sc->sc_if.if_ioctl = gre_ioctl;
  304         sp = &sc->sc_soparm;
  305         sockaddr_copy(sstosa(&sp->sp_dst), sizeof(sp->sp_dst), any);
  306         sockaddr_copy(sstosa(&sp->sp_src), sizeof(sp->sp_src), any);
  307         sp->sp_proto = IPPROTO_GRE;
  308         sp->sp_type = SOCK_RAW;
  309 
  310         sc->sc_fd = -1;
  311 
  312         rc = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, gre_fp_recvloop, sc,
  313             NULL, "%s", sc->sc_if.if_xname);
  314         if (rc)
  315                 goto fail1;
  316 
  317         gre_evcnt_attach(sc);
  318 
  319         gre_bufq_init(&sc->sc_snd, 17);
  320         sc->sc_if.if_flags |= IFF_LINK0;
  321         if_attach(&sc->sc_if);
  322         if_alloc_sadl(&sc->sc_if);
  323         bpf_attach(&sc->sc_if, DLT_NULL, sizeof(uint32_t));
  324         atomic_inc_uint(&gre_count);
  325         return 0;
  326 
  327 fail1:
  328         cv_destroy(&sc->sc_fp_condvar);
  329         cv_destroy(&sc->sc_condvar);
  330         mutex_destroy(&sc->sc_mtx);
  331         free(sc, M_DEVBUF);
  332 
  333 fail0:
  334         return -1;
  335 }
  336 
  337 static int
  338 gre_clone_destroy(struct ifnet *ifp)
  339 {
  340         int s;
  341         struct gre_softc *sc = ifp->if_softc;
  342 
  343         GRE_DPRINTF(sc, "\n");
  344 
  345         bpf_detach(ifp);
  346         s = splnet();
  347         if_detach(ifp);
  348 
  349         GRE_DPRINTF(sc, "\n");
  350         /* Note that we must not hold the mutex while we call gre_reconf(). */
  351         gre_reconf(sc, NULL);
  352 
  353         mutex_enter(&sc->sc_mtx);
  354         sc->sc_msg = GRE_M_STOP;
  355         cv_signal(&sc->sc_fp_condvar);
  356         while (sc->sc_fp_waiters > 0)
  357                 cv_wait(&sc->sc_fp_condvar, &sc->sc_mtx);
  358         mutex_exit(&sc->sc_mtx);
  359 
  360         splx(s);
  361 
  362         cv_destroy(&sc->sc_condvar);
  363         cv_destroy(&sc->sc_fp_condvar);
  364         mutex_destroy(&sc->sc_mtx);
  365         gre_bufq_destroy(&sc->sc_snd);
  366         gre_evcnt_detach(sc);
  367         free(sc, M_DEVBUF);
  368 
  369         atomic_dec_uint(&gre_count);
  370         return 0;
  371 }
  372 
  373 static void
  374 gre_receive(struct socket *so, void *arg, int events, int waitflag)
  375 {
  376         struct gre_softc *sc = (struct gre_softc *)arg;
  377         int rc;
  378         struct gre_h gh;
  379         struct mbuf *m;
  380 
  381         GRE_DPRINTF(sc, "enter\n");
  382 
  383         sc->sc_recv_ev.ev_count++;
  384 
  385         rc = gre_soreceive(so, &m);
  386         /* TBD Back off if ECONNREFUSED (indicates
  387          * ICMP Port Unreachable)?
  388          */
  389         if (rc == EWOULDBLOCK) {
  390                 GRE_DPRINTF(sc, "EWOULDBLOCK\n");
  391                 sc->sc_block_ev.ev_count++;
  392                 return;
  393         } else if (rc != 0 || m == NULL) {
  394                 GRE_DPRINTF(sc, "%s: rc %d m %p\n",
  395                     sc->sc_if.if_xname, rc, (void *)m);
  396                 sc->sc_error_ev.ev_count++;
  397                 return;
  398         }
  399 
  400         if (__predict_false(m->m_len < sizeof(gh))) {
  401                 if ((m = m_pullup(m, sizeof(gh))) == NULL) {
  402                         GRE_DPRINTF(sc, "m_pullup failed\n");
  403                         sc->sc_pullup_ev.ev_count++;
  404                         return;
  405                 }
  406         }
  407         memcpy(&gh, mtod(m, void *), sizeof(gh));
  408 
  409         if (gre_input(sc, m, &gh) == 0) {
  410                 sc->sc_unsupp_ev.ev_count++;
  411                 GRE_DPRINTF(sc, "dropping unsupported\n");
  412                 m_freem(m);
  413         }
  414 }
  415 
  416 static void
  417 gre_upcall_add(struct socket *so, void *arg)
  418 {
  419         /* XXX What if the kernel already set an upcall? */
  420         KASSERT((so->so_rcv.sb_flags & SB_UPCALL) == 0);
  421         so->so_upcallarg = arg;
  422         so->so_upcall = gre_receive;
  423         so->so_rcv.sb_flags |= SB_UPCALL;
  424 }
  425 
  426 static void
  427 gre_upcall_remove(struct socket *so)
  428 {
  429         so->so_rcv.sb_flags &= ~SB_UPCALL;
  430         so->so_upcallarg = NULL;
  431         so->so_upcall = NULL;
  432 }
  433 
  434 static int
  435 gre_socreate(struct gre_softc *sc, const struct gre_soparm *sp, int *fdout)
  436 {
  437         int fd, rc;
  438         struct socket *so;
  439         struct sockaddr_big sbig;
  440         sa_family_t af;
  441         int val;
  442 
  443         GRE_DPRINTF(sc, "enter\n");
  444 
  445         af = sp->sp_src.ss_family;
  446         rc = fsocreate(af, NULL, sp->sp_type, sp->sp_proto, &fd);
  447         if (rc != 0) {
  448                 GRE_DPRINTF(sc, "fsocreate failed\n");
  449                 return rc;
  450         }
  451 
  452         if ((rc = fd_getsock(fd, &so)) != 0)
  453                 return rc;
  454 
  455         memcpy(&sbig, &sp->sp_src, sizeof(sp->sp_src));
  456         if ((rc = sobind(so, (struct sockaddr *)&sbig, curlwp)) != 0) {
  457                 GRE_DPRINTF(sc, "sobind failed\n");
  458                 goto out;
  459         }
  460 
  461         memcpy(&sbig, &sp->sp_dst, sizeof(sp->sp_dst));
  462         solock(so);
  463         if ((rc = soconnect(so, (struct sockaddr *)&sbig, curlwp)) != 0) {
  464                 GRE_DPRINTF(sc, "soconnect failed\n");
  465                 sounlock(so);
  466                 goto out;
  467         }
  468         sounlock(so);
  469 
  470         /* XXX convert to a (new) SOL_SOCKET call */
  471         KASSERT(so->so_proto != NULL);
  472         rc = so_setsockopt(curlwp, so, IPPROTO_IP, IP_TTL,
  473             &ip_gre_ttl, sizeof(ip_gre_ttl));
  474         if (rc != 0) {
  475                 GRE_DPRINTF(sc, "so_setsockopt ttl failed\n");
  476                 rc = 0;
  477         }
  478 
  479         val = 1;
  480         rc = so_setsockopt(curlwp, so, SOL_SOCKET, SO_NOHEADER,
  481             &val, sizeof(val));
  482         if (rc != 0) {
  483                 GRE_DPRINTF(sc, "so_setsockopt SO_NOHEADER failed\n");
  484                 rc = 0;
  485         }
  486 out:
  487         if (rc != 0)
  488                 fd_close(fd);
  489         else  {
  490                 fd_putfile(fd);
  491                 *fdout = fd;
  492         }
  493 
  494         return rc;
  495 }
  496 
  497 static int
  498 gre_sosend(struct socket *so, struct mbuf *top)
  499 {
  500         struct proc     *p;
  501         long            space, resid;
  502         int             error;
  503         struct lwp * const l = curlwp;
  504 
  505         p = l->l_proc;
  506 
  507         resid = top->m_pkthdr.len;
  508         if (p)
  509                 l->l_ru.ru_msgsnd++;
  510 #define snderr(errno)   { error = errno; goto release; }
  511 
  512         solock(so);
  513         if ((error = sblock(&so->so_snd, M_NOWAIT)) != 0)
  514                 goto out;
  515         if (so->so_state & SS_CANTSENDMORE)
  516                 snderr(EPIPE);
  517         if (so->so_error) {
  518                 error = so->so_error;
  519                 so->so_error = 0;
  520                 goto release;
  521         }
  522         if ((so->so_state & SS_ISCONNECTED) == 0) {
  523                 if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
  524                         snderr(ENOTCONN);
  525                 } else {
  526                         snderr(EDESTADDRREQ);
  527                 }
  528         }
  529         space = sbspace(&so->so_snd);
  530         if (resid > so->so_snd.sb_hiwat)
  531                 snderr(EMSGSIZE);
  532         if (space < resid)
  533                 snderr(EWOULDBLOCK);
  534         /*
  535          * Data is prepackaged in "top".
  536          */
  537         if (so->so_state & SS_CANTSENDMORE)
  538                 snderr(EPIPE);
  539         error = (*so->so_proto->pr_usrreqs->pr_send)(so,
  540             top, NULL, NULL, l);
  541         top = NULL;
  542  release:
  543         sbunlock(&so->so_snd);
  544  out:
  545         sounlock(so);
  546         if (top != NULL)
  547                 m_freem(top);
  548         return error;
  549 }
  550 
  551 /* This is a stripped-down version of soreceive() that will never
  552  * block.  It will support SOCK_DGRAM sockets.  It may also support
  553  * SOCK_SEQPACKET sockets.
  554  */
  555 static int
  556 gre_soreceive(struct socket *so, struct mbuf **mp0)
  557 {
  558         struct mbuf *m, **mp;
  559         int flags, len, error, type;
  560         const struct protosw    *pr;
  561         struct mbuf *nextrecord;
  562 
  563         KASSERT(mp0 != NULL);
  564 
  565         flags = MSG_DONTWAIT;
  566         pr = so->so_proto;
  567         mp = mp0;
  568         type = 0;
  569 
  570         *mp = NULL;
  571 
  572         KASSERT(pr->pr_flags & PR_ATOMIC);
  573  restart:
  574         if ((error = sblock(&so->so_rcv, M_NOWAIT)) != 0) {
  575                 return error;
  576         }
  577         m = so->so_rcv.sb_mb;
  578         /*
  579          * If we have less data than requested, do not block awaiting more.
  580          */
  581         if (m == NULL) {
  582 #ifdef DIAGNOSTIC
  583                 if (so->so_rcv.sb_cc)
  584                         panic("receive 1");
  585 #endif
  586                 if (so->so_error) {
  587                         error = so->so_error;
  588                         so->so_error = 0;
  589                 } else if (so->so_state & SS_CANTRCVMORE)
  590                         ;
  591                 else if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0
  592                       && (so->so_proto->pr_flags & PR_CONNREQUIRED))
  593                         error = ENOTCONN;
  594                 else
  595                         error = EWOULDBLOCK;
  596                 goto release;
  597         }
  598         /*
  599          * On entry here, m points to the first record of the socket buffer.
  600          * While we process the initial mbufs containing address and control
  601          * info, we save a copy of m->m_nextpkt into nextrecord.
  602          */
  603         if (curlwp != NULL)
  604                 curlwp->l_ru.ru_msgrcv++;
  605         KASSERT(m == so->so_rcv.sb_mb);
  606         SBLASTRECORDCHK(&so->so_rcv, "soreceive 1");
  607         SBLASTMBUFCHK(&so->so_rcv, "soreceive 1");
  608         nextrecord = m->m_nextpkt;
  609         if (pr->pr_flags & PR_ADDR) {
  610 #ifdef DIAGNOSTIC
  611                 if (m->m_type != MT_SONAME)
  612                         panic("receive 1a");
  613 #endif
  614                 sbfree(&so->so_rcv, m);
  615                 m = so->so_rcv.sb_mb = m_free(m);
  616         }
  617         while (m != NULL && m->m_type == MT_CONTROL && error == 0) {
  618                 sbfree(&so->so_rcv, m);
  619                 /*
  620                  * Dispose of any SCM_RIGHTS message that went
  621                  * through the read path rather than recv.
  622                  */
  623                 if (pr->pr_domain->dom_dispose &&
  624                     mtod(m, struct cmsghdr *)->cmsg_type == SCM_RIGHTS)
  625                         (*pr->pr_domain->dom_dispose)(m);
  626                 m = so->so_rcv.sb_mb = m_free(m);
  627         }
  628 
  629         /*
  630          * If m is non-NULL, we have some data to read.  From now on,
  631          * make sure to keep sb_lastrecord consistent when working on
  632          * the last packet on the chain (nextrecord == NULL) and we
  633          * change m->m_nextpkt.
  634          */
  635         if (m != NULL) {
  636                 m->m_nextpkt = nextrecord;
  637                 /*
  638                  * If nextrecord == NULL (this is a single chain),
  639                  * then sb_lastrecord may not be valid here if m
  640                  * was changed earlier.
  641                  */
  642                 if (nextrecord == NULL) {
  643                         KASSERT(so->so_rcv.sb_mb == m);
  644                         so->so_rcv.sb_lastrecord = m;
  645                 }
  646                 type = m->m_type;
  647                 if (type == MT_OOBDATA)
  648                         flags |= MSG_OOB;
  649         } else {
  650                 KASSERT(so->so_rcv.sb_mb == m);
  651                 so->so_rcv.sb_mb = nextrecord;
  652                 SB_EMPTY_FIXUP(&so->so_rcv);
  653         }
  654         SBLASTRECORDCHK(&so->so_rcv, "soreceive 2");
  655         SBLASTMBUFCHK(&so->so_rcv, "soreceive 2");
  656 
  657         while (m != NULL) {
  658                 if (m->m_type == MT_OOBDATA) {
  659                         if (type != MT_OOBDATA)
  660                                 break;
  661                 } else if (type == MT_OOBDATA)
  662                         break;
  663 #ifdef DIAGNOSTIC
  664                 else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
  665                         panic("receive 3");
  666 #endif
  667                 so->so_state &= ~SS_RCVATMARK;
  668                 if (so->so_oobmark != 0 && so->so_oobmark < m->m_len)
  669                         break;
  670                 len = m->m_len;
  671                 /*
  672                  * mp is set, just pass back the mbufs.
  673                  * Sockbuf must be consistent here (points to current mbuf,
  674                  * it points to next record) when we drop priority;
  675                  * we must note any additions to the sockbuf when we
  676                  * block interrupts again.
  677                  */
  678                 if (m->m_flags & M_EOR)
  679                         flags |= MSG_EOR;
  680                 nextrecord = m->m_nextpkt;
  681                 sbfree(&so->so_rcv, m);
  682                 *mp = m;
  683                 mp = &m->m_next;
  684                 so->so_rcv.sb_mb = m = m->m_next;
  685                 *mp = NULL;
  686                 /*
  687                  * If m != NULL, we also know that
  688                  * so->so_rcv.sb_mb != NULL.
  689                  */
  690                 KASSERT(so->so_rcv.sb_mb == m);
  691                 if (m) {
  692                         m->m_nextpkt = nextrecord;
  693                         if (nextrecord == NULL)
  694                                 so->so_rcv.sb_lastrecord = m;
  695                 } else {
  696                         so->so_rcv.sb_mb = nextrecord;
  697                         SB_EMPTY_FIXUP(&so->so_rcv);
  698                 }
  699                 SBLASTRECORDCHK(&so->so_rcv, "soreceive 3");
  700                 SBLASTMBUFCHK(&so->so_rcv, "soreceive 3");
  701                 if (so->so_oobmark) {
  702                         so->so_oobmark -= len;
  703                         if (so->so_oobmark == 0) {
  704                                 so->so_state |= SS_RCVATMARK;
  705                                 break;
  706                         }
  707                 }
  708                 if (flags & MSG_EOR)
  709                         break;
  710         }
  711 
  712         if (m != NULL) {
  713                 m_freem(*mp);
  714                 *mp = NULL;
  715                 error = ENOMEM;
  716                 (void) sbdroprecord(&so->so_rcv);
  717         } else {
  718                 /*
  719                  * First part is an inline SB_EMPTY_FIXUP().  Second
  720                  * part makes sure sb_lastrecord is up-to-date if
  721                  * there is still data in the socket buffer.
  722                  */
  723                 so->so_rcv.sb_mb = nextrecord;
  724                 if (so->so_rcv.sb_mb == NULL) {
  725                         so->so_rcv.sb_mbtail = NULL;
  726                         so->so_rcv.sb_lastrecord = NULL;
  727                 } else if (nextrecord->m_nextpkt == NULL)
  728                         so->so_rcv.sb_lastrecord = nextrecord;
  729         }
  730         SBLASTRECORDCHK(&so->so_rcv, "soreceive 4");
  731         SBLASTMBUFCHK(&so->so_rcv, "soreceive 4");
  732         if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
  733                 (*pr->pr_usrreqs->pr_rcvd)(so, flags, curlwp);
  734         if (*mp0 == NULL && (flags & MSG_EOR) == 0 &&
  735             (so->so_state & SS_CANTRCVMORE) == 0) {
  736                 sbunlock(&so->so_rcv);
  737                 goto restart;
  738         }
  739 
  740  release:
  741         sbunlock(&so->so_rcv);
  742         return error;
  743 }
  744 
  745 static struct socket *
  746 gre_reconf(struct gre_softc *sc, const struct gre_soparm *newsoparm)
  747 {
  748         struct ifnet *ifp = &sc->sc_if;
  749 
  750         GRE_DPRINTF(sc, "enter\n");
  751 
  752 shutdown:
  753         if (sc->sc_soparm.sp_so != NULL) {
  754                 GRE_DPRINTF(sc, "\n");
  755                 gre_upcall_remove(sc->sc_soparm.sp_so);
  756                 softint_disestablish(sc->sc_si);
  757                 sc->sc_si = NULL;
  758                 gre_fp_send(sc, GRE_M_DELFP, NULL);
  759                 gre_clearconf(&sc->sc_soparm, false);
  760         }
  761 
  762         if (newsoparm != NULL) {
  763                 GRE_DPRINTF(sc, "\n");
  764                 sc->sc_soparm = *newsoparm;
  765                 newsoparm = NULL;
  766         }
  767 
  768         if (sc->sc_soparm.sp_so != NULL) {
  769                 GRE_DPRINTF(sc, "\n");
  770                 sc->sc_si = softint_establish(SOFTINT_NET, greintr, sc);
  771                 gre_upcall_add(sc->sc_soparm.sp_so, sc);
  772                 if ((ifp->if_flags & IFF_UP) == 0) {
  773                         GRE_DPRINTF(sc, "down\n");
  774                         goto shutdown;
  775                 }
  776         }
  777 
  778         GRE_DPRINTF(sc, "\n");
  779         if (sc->sc_soparm.sp_so != NULL)
  780                 sc->sc_if.if_flags |= IFF_RUNNING;
  781         else {
  782                 gre_bufq_purge(&sc->sc_snd);
  783                 sc->sc_if.if_flags &= ~IFF_RUNNING;
  784         }
  785         return sc->sc_soparm.sp_so;
  786 }
  787 
  788 static int
  789 gre_input(struct gre_softc *sc, struct mbuf *m, const struct gre_h *gh)
  790 {
  791         pktqueue_t *pktq = NULL;
  792         uint16_t flags;
  793         uint32_t af;            /* af passed to BPF tap */
  794         int hlen;
  795 
  796         if_statadd2(&sc->sc_if, if_ipackets, 1, if_ibytes, m->m_pkthdr.len);
  797 
  798         hlen = sizeof(struct gre_h);
  799 
  800         /* process GRE flags as packet can be of variable len */
  801         flags = ntohs(gh->flags);
  802 
  803         /* Checksum & Offset are present */
  804         if ((flags & GRE_CP) | (flags & GRE_RP))
  805                 hlen += 4;
  806         /* We don't support routing fields (variable length) */
  807         if (flags & GRE_RP) {
  808                 if_statinc(&sc->sc_if, if_ierrors);
  809                 return 0;
  810         }
  811         if (flags & GRE_KP)
  812                 hlen += 4;
  813         if (flags & GRE_SP)
  814                 hlen += 4;
  815 
  816         switch (ntohs(gh->ptype)) { /* ethertypes */
  817 #ifdef INET
  818         case ETHERTYPE_IP:
  819                 pktq = ip_pktq;
  820                 af = AF_INET;
  821                 break;
  822 #endif
  823 #ifdef NETATALK
  824         case ETHERTYPE_ATALK:
  825                 pktq = at_pktq1;
  826                 af = AF_APPLETALK;
  827                 break;
  828 #endif
  829 #ifdef INET6
  830         case ETHERTYPE_IPV6:
  831                 pktq = ip6_pktq;
  832                 af = AF_INET6;
  833                 break;
  834 #endif
  835 #ifdef MPLS
  836         case ETHERTYPE_MPLS:
  837                 pktq = mpls_pktq;
  838                 af = AF_MPLS;
  839                 break;
  840 #endif
  841         default:           /* others not yet supported */
  842                 GRE_DPRINTF(sc, "unhandled ethertype 0x%04x\n",
  843                     ntohs(gh->ptype));
  844                 if_statinc(&sc->sc_if, if_noproto);
  845                 return 0;
  846         }
  847 
  848         if (hlen > m->m_pkthdr.len) {
  849                 m_freem(m);
  850                 if_statinc(&sc->sc_if, if_ierrors);
  851                 return 1;
  852         }
  853         m_adj(m, hlen);
  854 
  855         bpf_mtap_af(&sc->sc_if, af, m, BPF_D_IN);
  856 
  857         m_set_rcvif(m, &sc->sc_if);
  858 
  859         KASSERT(pktq != NULL);
  860         if (__predict_false(!pktq_enqueue(pktq, m, 0))) {
  861                 m_freem(m);
  862         }
  863         return 1;       /* packet is done, no further processing needed */
  864 }
  865 
  866 /*
  867  * The output routine. Takes a packet and encapsulates it in the protocol
  868  * given by sc->sc_soparm.sp_proto. See also RFC 1701 and RFC 2004
  869  */
  870 static int
  871 gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
  872     const struct rtentry *rt)
  873 {
  874         int error = 0;
  875         struct gre_softc *sc = ifp->if_softc;
  876         struct gre_h gh = { .flags = 0 };
  877         uint16_t etype = 0;
  878 
  879         KASSERT((m->m_flags & M_PKTHDR) != 0);
  880 
  881         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
  882                 m_freem(m);
  883                 error = ENETDOWN;
  884                 goto end;
  885         }
  886 
  887         bpf_mtap_af(ifp, dst->sa_family, m, BPF_D_OUT);
  888 
  889         m->m_flags &= ~(M_BCAST|M_MCAST);
  890 
  891         GRE_DPRINTF(sc, "dst->sa_family=%d\n", dst->sa_family);
  892         switch (dst->sa_family) {
  893 #ifdef INET
  894         case AF_INET:
  895                 /*
  896                  * TBD Extract the IP ToS field and set the
  897                  * encapsulating protocol's ToS to suit.
  898                  */
  899                 etype = htons(ETHERTYPE_IP);
  900                 break;
  901 #endif
  902 #ifdef NETATALK
  903         case AF_APPLETALK:
  904                 etype = htons(ETHERTYPE_ATALK);
  905                 break;
  906 #endif
  907 #ifdef INET6
  908         case AF_INET6:
  909                 etype = htons(ETHERTYPE_IPV6);
  910                 break;
  911 #endif
  912         default:
  913                 IF_DROP(&ifp->if_snd);
  914                 m_freem(m);
  915                 error = EAFNOSUPPORT;
  916                 goto end;
  917         }
  918 
  919 #ifdef MPLS
  920         if (rt != NULL && rt_gettag(rt) != NULL) {
  921                 union mpls_shim msh;
  922                 msh.s_addr = MPLS_GETSADDR(rt);
  923                 if (msh.shim.label != MPLS_LABEL_IMPLNULL)
  924                         etype = htons(ETHERTYPE_MPLS);
  925         }
  926 #endif
  927 
  928         M_PREPEND(m, sizeof(gh), M_DONTWAIT);
  929         if (m == NULL) {
  930                 IF_DROP(&ifp->if_snd);
  931                 error = ENOBUFS;
  932                 goto end;
  933         }
  934 
  935         gh.ptype = etype;
  936         memcpy(mtod(m, void *), &gh, sizeof(gh));
  937         /* XXX Need to handle IP ToS.  Look at how I handle IP TTL. */
  938 
  939         if_statadd2(ifp, if_opackets, 1, if_obytes, m->m_pkthdr.len);
  940 
  941         /* Clear checksum-offload flags. */
  942         m->m_pkthdr.csum_flags = 0;
  943         m->m_pkthdr.csum_data = 0;
  944 
  945         /* send it off */
  946         if ((error = gre_bufq_enqueue(&sc->sc_snd, m)) != 0) {
  947                 sc->sc_oflow_ev.ev_count++;
  948                 m_freem(m);
  949         } else {
  950                 kpreempt_disable();
  951                 softint_schedule(sc->sc_si);
  952                 kpreempt_enable();
  953         }
  954 
  955 end:
  956         if (error)
  957                 if_statinc(ifp, if_oerrors);
  958         return error;
  959 }
  960 
  961 static int
  962 gre_getsockname(struct socket *so, struct sockaddr *nam)
  963 {
  964         return (*so->so_proto->pr_usrreqs->pr_sockaddr)(so, nam);
  965 }
  966 
  967 static int
  968 gre_getpeername(struct socket *so, struct sockaddr *nam)
  969 {
  970         return (*so->so_proto->pr_usrreqs->pr_peeraddr)(so, nam);
  971 }
  972 
  973 static int
  974 gre_getnames(struct socket *so, struct lwp *l, struct sockaddr_storage *src,
  975     struct sockaddr_storage *dst)
  976 {
  977         struct sockaddr_storage ss;
  978         int rc;
  979 
  980         solock(so);
  981         if ((rc = gre_getsockname(so, (struct sockaddr *)&ss)) != 0)
  982                 goto out;
  983         *src = ss;
  984 
  985         if ((rc = gre_getpeername(so, (struct sockaddr *)&ss)) != 0)
  986                 goto out;
  987         *dst = ss;
  988 out:
  989         sounlock(so);
  990         return rc;
  991 }
  992 
  993 static void
  994 gre_fp_recvloop(void *arg)
  995 {
  996         struct gre_softc *sc = arg;
  997 
  998         mutex_enter(&sc->sc_mtx);
  999         while (gre_fp_recv(sc))
 1000                 ;
 1001         mutex_exit(&sc->sc_mtx);
 1002         kthread_exit(0);
 1003 }
 1004 
 1005 static bool
 1006 gre_fp_recv(struct gre_softc *sc)
 1007 {
 1008         int fd, ofd, rc;
 1009         file_t *fp;
 1010 
 1011         fp = sc->sc_fp;
 1012         ofd = sc->sc_fd;
 1013         fd = -1;
 1014 
 1015         switch (sc->sc_msg) {
 1016         case GRE_M_STOP:
 1017                 cv_signal(&sc->sc_fp_condvar);
 1018                 return false;
 1019         case GRE_M_SETFP:
 1020                 mutex_exit(&sc->sc_mtx);
 1021                 rc = fd_dup(fp, 0, &fd, 0);
 1022                 mutex_enter(&sc->sc_mtx);
 1023                 if (rc != 0) {
 1024                         sc->sc_msg = GRE_M_ERR;
 1025                         break;
 1026                 }
 1027                 /*FALLTHROUGH*/
 1028         case GRE_M_DELFP:
 1029                 mutex_exit(&sc->sc_mtx);
 1030                 if (ofd != -1 && fd_getfile(ofd) != NULL)
 1031                         fd_close(ofd);
 1032                 mutex_enter(&sc->sc_mtx);
 1033                 sc->sc_fd = fd;
 1034                 sc->sc_msg = GRE_M_OK;
 1035                 break;
 1036         default:
 1037                 gre_fp_wait(sc);
 1038                 return true;
 1039         }
 1040         cv_signal(&sc->sc_fp_condvar);
 1041         return true;
 1042 }
 1043 
 1044 static bool
 1045 gre_fp_send(struct gre_softc *sc, enum gre_msg msg, file_t *fp)
 1046 {
 1047         bool rc;
 1048 
 1049         mutex_enter(&sc->sc_mtx);
 1050         while (sc->sc_msg != GRE_M_NONE)
 1051                 gre_fp_wait(sc);
 1052         sc->sc_fp = fp;
 1053         sc->sc_msg = msg;
 1054         cv_signal(&sc->sc_fp_condvar);
 1055         while (sc->sc_msg != GRE_M_STOP && sc->sc_msg != GRE_M_OK &&
 1056                     sc->sc_msg != GRE_M_ERR)
 1057                 gre_fp_wait(sc);
 1058         rc = (sc->sc_msg != GRE_M_ERR);
 1059         sc->sc_msg = GRE_M_NONE;
 1060         cv_signal(&sc->sc_fp_condvar);
 1061         mutex_exit(&sc->sc_mtx);
 1062         return rc;
 1063 }
 1064 
 1065 static int
 1066 gre_ssock(struct ifnet *ifp, struct gre_soparm *sp, int fd)
 1067 {
 1068         int error = 0;
 1069         const struct protosw *pr;
 1070         file_t *fp;
 1071         struct gre_softc *sc = ifp->if_softc;
 1072         struct socket *so;
 1073         struct sockaddr_storage dst, src;
 1074 
 1075         if ((fp = fd_getfile(fd)) == NULL)
 1076                 return EBADF;
 1077         if (fp->f_type != DTYPE_SOCKET) {
 1078                 fd_putfile(fd);
 1079                 return ENOTSOCK;
 1080         }
 1081 
 1082         GRE_DPRINTF(sc, "\n");
 1083 
 1084         so = fp->f_socket;
 1085         pr = so->so_proto;
 1086 
 1087         GRE_DPRINTF(sc, "type %d, proto %d\n", pr->pr_type, pr->pr_protocol);
 1088 
 1089         if ((pr->pr_flags & PR_ATOMIC) == 0 ||
 1090             (sp->sp_type != 0 && pr->pr_type != sp->sp_type) ||
 1091             (sp->sp_proto != 0 && pr->pr_protocol != 0 &&
 1092              pr->pr_protocol != sp->sp_proto)) {
 1093                 error = EINVAL;
 1094                 goto err;
 1095         }
 1096 
 1097         GRE_DPRINTF(sc, "\n");
 1098 
 1099         /* check address */
 1100         if ((error = gre_getnames(so, curlwp, &src, &dst)) != 0)
 1101                 goto err;
 1102 
 1103         GRE_DPRINTF(sc, "\n");
 1104 
 1105         if (!gre_fp_send(sc, GRE_M_SETFP, fp)) {
 1106                 error = EBUSY;
 1107                 goto err;
 1108         }
 1109 
 1110         GRE_DPRINTF(sc, "\n");
 1111 
 1112         sp->sp_src = src;
 1113         sp->sp_dst = dst;
 1114 
 1115         sp->sp_so = so;
 1116 
 1117 err:
 1118         fd_putfile(fd);
 1119         return error;
 1120 }
 1121 
 1122 static bool
 1123 sockaddr_is_anyaddr(const struct sockaddr *sa)
 1124 {
 1125         socklen_t anylen, salen;
 1126         const void *anyaddr, *addr;
 1127 
 1128         if ((anyaddr = sockaddr_anyaddr(sa, &anylen)) == NULL ||
 1129             (addr = sockaddr_const_addr(sa, &salen)) == NULL)
 1130                 return false;
 1131 
 1132         if (salen > anylen)
 1133                 return false;
 1134 
 1135         return memcmp(anyaddr, addr, MIN(anylen, salen)) == 0;
 1136 }
 1137 
 1138 static bool
 1139 gre_is_nullconf(const struct gre_soparm *sp)
 1140 {
 1141         return sockaddr_is_anyaddr(sstocsa(&sp->sp_src)) ||
 1142                sockaddr_is_anyaddr(sstocsa(&sp->sp_dst));
 1143 }
 1144 
 1145 static void
 1146 gre_clearconf(struct gre_soparm *sp, bool force)
 1147 {
 1148         if (sp->sp_bysock || force) {
 1149                 sockaddr_copy(sstosa(&sp->sp_src), sizeof(sp->sp_src),
 1150                     sockaddr_any(sstosa(&sp->sp_src)));
 1151                 sockaddr_copy(sstosa(&sp->sp_dst), sizeof(sp->sp_dst),
 1152                     sockaddr_any(sstosa(&sp->sp_dst)));
 1153                 sp->sp_bysock = false;
 1154         }
 1155         sp->sp_so = NULL; /* XXX */
 1156 }
 1157 
 1158 static int
 1159 gre_ioctl(struct ifnet *ifp, const u_long cmd, void *data)
 1160 {
 1161         struct ifreq *ifr;
 1162         struct ifaddr *ifa = (struct ifaddr *)data;
 1163         struct if_laddrreq *lifr = (struct if_laddrreq *)data;
 1164         struct gre_softc *sc = ifp->if_softc;
 1165         struct gre_soparm *sp;
 1166         int fd, error = 0, oproto, otype, s;
 1167         struct gre_soparm sp0;
 1168 
 1169         ifr = data;
 1170 
 1171         GRE_DPRINTF(sc, "cmd %lu\n", cmd);
 1172 
 1173         switch (cmd) {
 1174         case GRESPROTO:
 1175         case GRESADDRD:
 1176         case GRESADDRS:
 1177         case GRESSOCK:
 1178         case GREDSOCK:
 1179                 if (kauth_authorize_network(kauth_cred_get(),
 1180                     KAUTH_NETWORK_INTERFACE,
 1181                     KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
 1182                     NULL) != 0)
 1183                         return EPERM;
 1184                 break;
 1185         default:
 1186                 break;
 1187         }
 1188 
 1189         s = splnet();
 1190 
 1191         sp0 = sc->sc_soparm;
 1192         sp0.sp_so = NULL;
 1193         sp = &sp0;
 1194 
 1195         GRE_DPRINTF(sc, "\n");
 1196 
 1197         switch (cmd) {
 1198         case SIOCINITIFADDR:
 1199                 GRE_DPRINTF(sc, "\n");
 1200                 if ((ifp->if_flags & IFF_UP) != 0)
 1201                         break;
 1202                 gre_clearconf(sp, false);
 1203                 ifp->if_flags |= IFF_UP;
 1204                 ifa->ifa_rtrequest = p2p_rtrequest;
 1205                 goto mksocket;
 1206         case SIOCSIFFLAGS:
 1207                 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
 1208                         break;
 1209                 oproto = sp->sp_proto;
 1210                 otype = sp->sp_type;
 1211                 switch (ifr->ifr_flags & (IFF_LINK0|IFF_LINK2)) {
 1212                 case IFF_LINK0|IFF_LINK2:
 1213                         sp->sp_proto = IPPROTO_UDP;
 1214                         sp->sp_type = SOCK_DGRAM;
 1215                         break;
 1216                 case IFF_LINK2:
 1217                         sp->sp_proto = 0;
 1218                         sp->sp_type = 0;
 1219                         break;
 1220                 case IFF_LINK0:
 1221                         sp->sp_proto = IPPROTO_GRE;
 1222                         sp->sp_type = SOCK_RAW;
 1223                         break;
 1224                 default:
 1225                         GRE_DPRINTF(sc, "\n");
 1226                         error = EINVAL;
 1227                         goto out;
 1228                 }
 1229                 GRE_DPRINTF(sc, "\n");
 1230                 gre_clearconf(sp, false);
 1231                 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==
 1232                     (IFF_UP|IFF_RUNNING) &&
 1233                     (oproto == sp->sp_proto || sp->sp_proto == 0) &&
 1234                     (otype == sp->sp_type || sp->sp_type == 0))
 1235                         break;
 1236                 switch (sp->sp_proto) {
 1237                 case IPPROTO_UDP:
 1238                 case IPPROTO_GRE:
 1239                         goto mksocket;
 1240                 default:
 1241                         break;
 1242                 }
 1243                 break;
 1244         case SIOCSIFMTU:
 1245                 /* XXX determine MTU automatically by probing w/
 1246                  * XXX do-not-fragment packets?
 1247                  */
 1248                 if (ifr->ifr_mtu < 576) {
 1249                         error = EINVAL;
 1250                         break;
 1251                 }
 1252                 /*FALLTHROUGH*/
 1253         case SIOCGIFMTU:
 1254                 if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET)
 1255                         error = 0;
 1256                 break;
 1257         case SIOCADDMULTI:
 1258         case SIOCDELMULTI:
 1259                 if (ifr == NULL) {
 1260                         error = EAFNOSUPPORT;
 1261                         break;
 1262                 }
 1263                 switch (ifreq_getaddr(cmd, ifr)->sa_family) {
 1264 #ifdef INET
 1265                 case AF_INET:
 1266                         break;
 1267 #endif
 1268 #ifdef INET6
 1269                 case AF_INET6:
 1270                         break;
 1271 #endif
 1272                 default:
 1273                         error = EAFNOSUPPORT;
 1274                         break;
 1275                 }
 1276                 break;
 1277         case GRESPROTO:
 1278                 gre_clearconf(sp, false);
 1279                 oproto = sp->sp_proto;
 1280                 otype = sp->sp_type;
 1281                 sp->sp_proto = ifr->ifr_flags;
 1282                 switch (sp->sp_proto) {
 1283                 case IPPROTO_UDP:
 1284                         ifp->if_flags |= IFF_LINK0|IFF_LINK2;
 1285                         sp->sp_type = SOCK_DGRAM;
 1286                         break;
 1287                 case IPPROTO_GRE:
 1288                         ifp->if_flags |= IFF_LINK0;
 1289                         ifp->if_flags &= ~IFF_LINK2;
 1290                         sp->sp_type = SOCK_RAW;
 1291                         break;
 1292                 case 0:
 1293                         ifp->if_flags &= ~IFF_LINK0;
 1294                         ifp->if_flags |= IFF_LINK2;
 1295                         sp->sp_type = 0;
 1296                         break;
 1297                 default:
 1298                         error = EPROTONOSUPPORT;
 1299                         break;
 1300                 }
 1301                 if ((oproto == sp->sp_proto || sp->sp_proto == 0) &&
 1302                     (otype == sp->sp_type || sp->sp_type == 0))
 1303                         break;
 1304                 switch (sp->sp_proto) {
 1305                 case IPPROTO_UDP:
 1306                 case IPPROTO_GRE:
 1307                         goto mksocket;
 1308                 default:
 1309                         break;
 1310                 }
 1311                 break;
 1312         case GREGPROTO:
 1313                 ifr->ifr_flags = sp->sp_proto;
 1314                 break;
 1315         case GRESADDRS:
 1316         case GRESADDRD:
 1317                 gre_clearconf(sp, false);
 1318                 /* set tunnel endpoints and mark interface as up */
 1319                 switch (cmd) {
 1320                 case GRESADDRS:
 1321                         sockaddr_copy(sstosa(&sp->sp_src),
 1322                             sizeof(sp->sp_src), ifreq_getaddr(cmd, ifr));
 1323                         break;
 1324                 case GRESADDRD:
 1325                         sockaddr_copy(sstosa(&sp->sp_dst),
 1326                             sizeof(sp->sp_dst), ifreq_getaddr(cmd, ifr));
 1327                         break;
 1328                 }
 1329         checkaddr:
 1330                 if (sockaddr_any(sstosa(&sp->sp_src)) == NULL ||
 1331                     sockaddr_any(sstosa(&sp->sp_dst)) == NULL) {
 1332                         error = EINVAL;
 1333                         break;
 1334                 }
 1335                 /* let gre_socreate() check the rest */
 1336         mksocket:
 1337                 GRE_DPRINTF(sc, "\n");
 1338                 /* If we're administratively down, or the configuration
 1339                  * is empty, there's no use creating a socket.
 1340                  */
 1341                 if ((ifp->if_flags & IFF_UP) == 0 || gre_is_nullconf(sp))
 1342                         goto sendconf;
 1343 
 1344                 GRE_DPRINTF(sc, "\n");
 1345                 fd = 0;
 1346                 error = gre_socreate(sc, sp, &fd);
 1347                 if (error != 0)
 1348                         break;
 1349 
 1350         setsock:
 1351                 GRE_DPRINTF(sc, "\n");
 1352 
 1353                 error = gre_ssock(ifp, sp, fd);
 1354 
 1355                 if (cmd != GRESSOCK) {
 1356                         GRE_DPRINTF(sc, "\n");
 1357                         /* XXX v. dodgy */
 1358                         if (fd_getfile(fd) != NULL)
 1359                                 fd_close(fd);
 1360                 }
 1361 
 1362                 if (error == 0) {
 1363         sendconf:
 1364                         GRE_DPRINTF(sc, "\n");
 1365                         ifp->if_flags &= ~IFF_RUNNING;
 1366                         gre_reconf(sc, sp);
 1367                 }
 1368 
 1369                 break;
 1370         case GREGADDRS:
 1371                 ifreq_setaddr(cmd, ifr, sstosa(&sp->sp_src));
 1372                 break;
 1373         case GREGADDRD:
 1374                 ifreq_setaddr(cmd, ifr, sstosa(&sp->sp_dst));
 1375                 break;
 1376         case GREDSOCK:
 1377                 GRE_DPRINTF(sc, "\n");
 1378                 if (sp->sp_bysock)
 1379                         ifp->if_flags &= ~IFF_UP;
 1380                 gre_clearconf(sp, false);
 1381                 goto mksocket;
 1382         case GRESSOCK:
 1383                 GRE_DPRINTF(sc, "\n");
 1384                 gre_clearconf(sp, true);
 1385                 fd = (int)ifr->ifr_value;
 1386                 sp->sp_bysock = true;
 1387                 ifp->if_flags |= IFF_UP;
 1388                 goto setsock;
 1389         case SIOCSLIFPHYADDR:
 1390                 GRE_DPRINTF(sc, "\n");
 1391                 if (lifr->addr.ss_family != lifr->dstaddr.ss_family) {
 1392                         error = EAFNOSUPPORT;
 1393                         break;
 1394                 }
 1395                 sockaddr_copy(sstosa(&sp->sp_src), sizeof(sp->sp_src),
 1396                     sstosa(&lifr->addr));
 1397                 sockaddr_copy(sstosa(&sp->sp_dst), sizeof(sp->sp_dst),
 1398                     sstosa(&lifr->dstaddr));
 1399                 GRE_DPRINTF(sc, "\n");
 1400                 goto checkaddr;
 1401         case SIOCDIFPHYADDR:
 1402                 GRE_DPRINTF(sc, "\n");
 1403                 gre_clearconf(sp, true);
 1404                 ifp->if_flags &= ~IFF_UP;
 1405                 goto mksocket;
 1406         case SIOCGLIFPHYADDR:
 1407                 GRE_DPRINTF(sc, "\n");
 1408                 if (gre_is_nullconf(sp)) {
 1409                         error = EADDRNOTAVAIL;
 1410                         break;
 1411                 }
 1412                 sockaddr_copy(sstosa(&lifr->addr), sizeof(lifr->addr),
 1413                     sstosa(&sp->sp_src));
 1414                 sockaddr_copy(sstosa(&lifr->dstaddr), sizeof(lifr->dstaddr),
 1415                     sstosa(&sp->sp_dst));
 1416                 GRE_DPRINTF(sc, "\n");
 1417                 break;
 1418         default:
 1419                 error = ifioctl_common(ifp, cmd, data);
 1420                 break;
 1421         }
 1422 out:
 1423         GRE_DPRINTF(sc, "\n");
 1424         splx(s);
 1425         return error;
 1426 }
 1427 
 1428 /* ARGSUSED */
 1429 void
 1430 greattach(int count)
 1431 {
 1432 
 1433         /*
 1434          * Nothing to do here, initialization is handled by the
 1435          * module initialization code in greinit() below.
 1436          */
 1437 }
 1438 
 1439 static void
 1440 greinit(void)
 1441 {
 1442         if_clone_attach(&gre_cloner);
 1443 }
 1444 
 1445 static int
 1446 gredetach(void)
 1447 {
 1448         int error = 0;
 1449 
 1450         if (gre_count != 0)
 1451                 error = EBUSY;
 1452 
 1453         if (error == 0)
 1454                 if_clone_detach(&gre_cloner);
 1455 
 1456         return error;
 1457 }
 1458 
 1459 /*
 1460  * Module infrastructure
 1461  */
 1462 #include "if_module.h"
 1463 
 1464 IF_MODULE(MODULE_CLASS_DRIVER, gre, NULL)

Cache object: 7c1d432ab09dda5d74cce5885eb2cf64


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.