LCOV - code coverage report
Current view: top level - net - if_gre.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1840 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 123 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if_gre.c,v 1.124 2018/07/24 07:40:35 yasuoka Exp $ */
       2             : /*      $NetBSD: if_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1998 The NetBSD Foundation, Inc.
       6             :  * All rights reserved.
       7             :  *
       8             :  * This code is derived from software contributed to The NetBSD Foundation
       9             :  * by Heiko W.Rupp <hwr@pilhuhn.de>
      10             :  *
      11             :  * IPv6-over-GRE contributed by Gert Doering <gert@greenie.muc.de>
      12             :  *
      13             :  * Redistribution and use in source and binary forms, with or without
      14             :  * modification, are permitted provided that the following conditions
      15             :  * are met:
      16             :  * 1. Redistributions of source code must retain the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer.
      18             :  * 2. Redistributions in binary form must reproduce the above copyright
      19             :  *    notice, this list of conditions and the following disclaimer in the
      20             :  *    documentation and/or other materials provided with the distribution.
      21             :  *
      22             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      23             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      24             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      25             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      26             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      27             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      28             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      29             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      30             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      31             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      32             :  * POSSIBILITY OF SUCH DAMAGE.
      33             :  */
      34             : 
      35             : /*
      36             :  * Encapsulate L3 protocols into IP, per RFC 1701 and 1702.
      37             :  * See gre(4) for more details.
      38             :  * Also supported: IP in IP encapsulation (proto 55) per RFC 2004.
      39             :  */
      40             : 
      41             : #include "bpfilter.h"
      42             : #include "pf.h"
      43             : 
      44             : #include <sys/param.h>
      45             : #include <sys/mbuf.h>
      46             : #include <sys/socket.h>
      47             : #include <sys/sockio.h>
      48             : #include <sys/kernel.h>
      49             : #include <sys/systm.h>
      50             : #include <sys/errno.h>
      51             : #include <sys/timeout.h>
      52             : #include <sys/queue.h>
      53             : #include <sys/tree.h>
      54             : #include <sys/pool.h>
      55             : #include <sys/rwlock.h>
      56             : 
      57             : #include <crypto/siphash.h>
      58             : 
      59             : #include <net/if.h>
      60             : #include <net/if_var.h>
      61             : #include <net/if_types.h>
      62             : #include <net/if_media.h>
      63             : #include <net/route.h>
      64             : 
      65             : #include <netinet/in.h>
      66             : #include <netinet/in_var.h>
      67             : #include <netinet/if_ether.h>
      68             : #include <netinet/ip.h>
      69             : #include <netinet/ip_var.h>
      70             : 
      71             : #ifdef INET6
      72             : #include <netinet/ip6.h>
      73             : #include <netinet6/ip6_var.h>
      74             : #include <netinet6/in6_var.h>
      75             : #endif
      76             : 
      77             : #ifdef PIPEX
      78             : #include <net/pipex.h>
      79             : #endif
      80             : 
      81             : #ifdef MPLS
      82             : #include <netmpls/mpls.h>
      83             : #endif /* MPLS */
      84             : 
      85             : #if NBPFILTER > 0
      86             : #include <net/bpf.h>
      87             : #endif
      88             : 
      89             : #if NPF > 0
      90             : #include <net/pfvar.h>
      91             : #endif
      92             : 
      93             : #include <net/if_gre.h>
      94             : 
      95             : #include <netinet/ip_gre.h>
      96             : #include <sys/sysctl.h>
      97             : 
      98             : /* for nvgre bridge shizz */
      99             : #include <sys/socket.h>
     100             : #include <net/if_bridge.h>
     101             : 
     102             : /*
     103             :  * packet formats
     104             :  */
     105             : struct gre_header {
     106             :         uint16_t                gre_flags;
     107             : #define GRE_CP                          0x8000  /* Checksum Present */
     108             : #define GRE_KP                          0x2000  /* Key Present */
     109             : #define GRE_SP                          0x1000  /* Sequence Present */
     110             : 
     111             : #define GRE_VERS_MASK                   0x0007
     112             : #define GRE_VERS_0                      0x0000
     113             : #define GRE_VERS_1                      0x0001
     114             : 
     115             :         uint16_t                gre_proto;
     116             : } __packed __aligned(4);
     117             : 
     118             : struct gre_h_cksum {
     119             :         uint16_t                gre_cksum;
     120             :         uint16_t                gre_reserved1;
     121             : } __packed __aligned(4);
     122             : 
     123             : struct gre_h_key {
     124             :         uint32_t                gre_key;
     125             : } __packed __aligned(4);
     126             : 
     127             : #define GRE_EOIP                0x6400
     128             : 
     129             : struct gre_h_key_eoip {
     130             :         uint16_t                eoip_len;       /* network order */
     131             :         uint16_t                eoip_tunnel_id; /* little endian */
     132             : } __packed __aligned(4);
     133             : 
     134             : #define NVGRE_VSID_RES_MIN      0x000000 /* reserved for future use */
     135             : #define NVGRE_VSID_RES_MAX      0x000fff
     136             : #define NVGRE_VSID_NVE2NVE      0xffffff /* vendor specific NVE-to-NVE comms */
     137             : 
     138             : struct gre_h_seq {
     139             :         uint32_t                gre_seq;
     140             : } __packed __aligned(4);
     141             : 
     142             : struct gre_h_wccp {
     143             :         uint8_t                 wccp_flags;
     144             :         uint8_t                 service_id;
     145             :         uint8_t                 alt_bucket;
     146             :         uint8_t                 pri_bucket;
     147             : } __packed __aligned(4);
     148             : 
     149             : #define GRE_WCCP 0x883e
     150             : 
     151             : #define GRE_HDRLEN (sizeof(struct ip) + sizeof(struct gre_header))
     152             : 
     153             : /*
     154             :  * GRE tunnel metadata
     155             :  */
     156             : 
     157             : #define GRE_KA_NONE             0
     158             : #define GRE_KA_DOWN             1
     159             : #define GRE_KA_HOLD             2
     160             : #define GRE_KA_UP               3
     161             : 
     162             : union gre_addr {
     163             :         struct in_addr          in4;
     164             :         struct in6_addr         in6;
     165             : };
     166             : 
     167             : static inline int
     168             :                 gre_ip_cmp(int, const union gre_addr *,
     169             :                     const union gre_addr *);
     170             : 
     171             : #define GRE_KEY_MIN             0x00000000U
     172             : #define GRE_KEY_MAX             0xffffffffU
     173             : #define GRE_KEY_SHIFT           0
     174             : 
     175             : #define GRE_KEY_ENTROPY_MIN     0x00000000U
     176             : #define GRE_KEY_ENTROPY_MAX     0x00ffffffU
     177             : #define GRE_KEY_ENTROPY_SHIFT   8
     178             : 
     179             : struct gre_tunnel {
     180             :         uint32_t                t_key_mask;
     181             : #define GRE_KEY_NONE                    htonl(0x00000000U)
     182             : #define GRE_KEY_ENTROPY                 htonl(0xffffff00U)
     183             : #define GRE_KEY_MASK                    htonl(0xffffffffU)
     184             :         uint32_t                t_key;
     185             : 
     186             :         u_int                   t_rtableid;
     187             :         union gre_addr          t_src;
     188             : #define t_src4  t_src.in4
     189             : #define t_src6  t_src.in6
     190             :         union gre_addr          t_dst;
     191             : #define t_dst4  t_dst.in4
     192             : #define t_dst6  t_dst.in6
     193             :         int                     t_ttl;
     194             :         uint16_t                t_df;
     195             :         sa_family_t             t_af;
     196             : };
     197             : 
     198             : static int
     199             :                 gre_cmp_src(const struct gre_tunnel *,
     200             :                     const struct gre_tunnel *);
     201             : static int
     202             :                 gre_cmp(const struct gre_tunnel *, const struct gre_tunnel *);
     203             : 
     204             : static int      gre_set_tunnel(struct gre_tunnel *, struct if_laddrreq *, int);
     205             : static int      gre_get_tunnel(struct gre_tunnel *, struct if_laddrreq *);
     206             : static int      gre_del_tunnel(struct gre_tunnel *);
     207             : 
     208             : static int      gre_set_vnetid(struct gre_tunnel *, struct ifreq *);
     209             : static int      gre_get_vnetid(struct gre_tunnel *, struct ifreq *);
     210             : static int      gre_del_vnetid(struct gre_tunnel *);
     211             : 
     212             : static int      gre_set_vnetflowid(struct gre_tunnel *, struct ifreq *);
     213             : static int      gre_get_vnetflowid(struct gre_tunnel *, struct ifreq *);
     214             : 
     215             : static struct mbuf *
     216             :                 gre_encap_dst(const struct gre_tunnel *, const union gre_addr *,
     217             :                     struct mbuf *, uint16_t, uint8_t, uint8_t);
     218             : #define gre_encap(_t, _m, _p, _ttl, _tos) \
     219             :                 gre_encap_dst((_t), &(_t)->t_dst, (_m), (_p), (_ttl), (_tos))
     220             : 
     221             : static struct mbuf *
     222             :                 gre_encap_dst_ip(const struct gre_tunnel *,
     223             :                     const union gre_addr *, struct mbuf *, uint8_t, uint8_t);
     224             : #define gre_encap_ip(_t, _m, _ttl, _tos) \
     225             :                 gre_encap_dst_ip((_t), &(_t)->t_dst, (_m), (_ttl), (_tos))
     226             : 
     227             : static int
     228             :                 gre_ip_output(const struct gre_tunnel *, struct mbuf *);
     229             : 
     230             : static int      gre_tunnel_ioctl(struct ifnet *, struct gre_tunnel *,
     231             :                     u_long, void *);
     232             : 
     233             : /*
     234             :  * layer 3 GRE tunnels
     235             :  */
     236             : 
     237             : struct gre_softc {
     238             :         struct gre_tunnel       sc_tunnel; /* must be first */
     239             :         TAILQ_ENTRY(gre_softc)  sc_entry;
     240             : 
     241             :         struct ifnet            sc_if;
     242             : 
     243             :         struct timeout          sc_ka_send;
     244             :         struct timeout          sc_ka_hold;
     245             : 
     246             :         unsigned int            sc_ka_state;
     247             :         unsigned int            sc_ka_timeo;
     248             :         unsigned int            sc_ka_count;
     249             : 
     250             :         unsigned int            sc_ka_holdmax;
     251             :         unsigned int            sc_ka_holdcnt;
     252             : 
     253             :         SIPHASH_KEY             sc_ka_key;
     254             :         uint32_t                sc_ka_bias;
     255             :         int                     sc_ka_recvtm;
     256             : };
     257             : 
     258             : TAILQ_HEAD(gre_list, gre_softc);
     259             : 
     260             : struct gre_keepalive {
     261             :         uint32_t                gk_uptime;
     262             :         uint32_t                gk_random;
     263             :         uint8_t                 gk_digest[SIPHASH_DIGEST_LENGTH];
     264             : } __packed __aligned(4);
     265             : 
     266             : static int      gre_clone_create(struct if_clone *, int);
     267             : static int      gre_clone_destroy(struct ifnet *);
     268             : 
     269             : struct if_clone gre_cloner =
     270             :     IF_CLONE_INITIALIZER("gre", gre_clone_create, gre_clone_destroy);
     271             : 
     272             : /* protected by NET_LOCK */
     273             : struct gre_list gre_list = TAILQ_HEAD_INITIALIZER(gre_list);
     274             : 
     275             : static int      gre_output(struct ifnet *, struct mbuf *, struct sockaddr *,
     276             :                     struct rtentry *);
     277             : static void     gre_start(struct ifnet *);
     278             : static int      gre_ioctl(struct ifnet *, u_long, caddr_t);
     279             : 
     280             : static int      gre_up(struct gre_softc *);
     281             : static int      gre_down(struct gre_softc *);
     282             : static void     gre_link_state(struct ifnet *, unsigned int);
     283             : 
     284             : static int      gre_input_key(struct mbuf **, int *, int, int,
     285             :                     struct gre_tunnel *);
     286             : 
     287             : static void     gre_keepalive_send(void *);
     288             : static void     gre_keepalive_recv(struct ifnet *ifp, struct mbuf *);
     289             : static void     gre_keepalive_hold(void *);
     290             : 
     291             : static struct mbuf *
     292             :                 gre_l3_encap_dst(const struct gre_tunnel *, const void *,
     293             :                     struct mbuf *m, sa_family_t);
     294             : 
     295             : #define gre_l3_encap(_t, _m, _af) \
     296             :                 gre_l3_encap_dst((_t), &(_t)->t_dst, (_m), (_af))
     297             : 
     298             : struct mgre_softc {
     299             :         struct gre_tunnel       sc_tunnel; /* must be first */
     300             :         RBT_ENTRY(mgre_softc)   sc_entry;
     301             : 
     302             :         struct ifnet            sc_if;
     303             : };
     304             : 
     305             : RBT_HEAD(mgre_tree, mgre_softc);
     306             : 
     307             : static inline int
     308             :                 mgre_cmp(const struct mgre_softc *, const struct mgre_softc *);
     309             : 
     310           0 : RBT_PROTOTYPE(mgre_tree, mgre_softc, sc_entry, mgre_cmp);
     311             : 
     312             : static int      mgre_clone_create(struct if_clone *, int);
     313             : static int      mgre_clone_destroy(struct ifnet *);
     314             : 
     315             : struct if_clone mgre_cloner =
     316             :     IF_CLONE_INITIALIZER("mgre", mgre_clone_create, mgre_clone_destroy);
     317             : 
     318             : static void     mgre_rtrequest(struct ifnet *, int, struct rtentry *);
     319             : static int      mgre_output(struct ifnet *, struct mbuf *, struct sockaddr *,
     320             :                     struct rtentry *);
     321             : static void     mgre_start(struct ifnet *);
     322             : static int      mgre_ioctl(struct ifnet *, u_long, caddr_t);
     323             : 
     324             : static int      mgre_set_tunnel(struct mgre_softc *, struct if_laddrreq *);
     325             : static int      mgre_get_tunnel(struct mgre_softc *, struct if_laddrreq *);
     326             : static int      mgre_up(struct mgre_softc *);
     327             : static int      mgre_down(struct mgre_softc *);
     328             : 
     329             : /* protected by NET_LOCK */
     330             : struct mgre_tree mgre_tree = RBT_INITIALIZER();
     331             : 
     332             : /*
     333             :  * Ethernet GRE tunnels
     334             :  */
     335             : #define ether_cmp(_a, _b)       memcmp((_a), (_b), ETHER_ADDR_LEN)
     336             : #define ether_isequal(_a, _b)   (ether_cmp((_a), (_b)) == 0)
     337             : #define ether_isbcast(_e)       ether_isequal((_e), etherbroadcastaddr)
     338             : 
     339             : static struct mbuf *
     340             :                 gre_ether_align(struct mbuf *, int);
     341             : 
     342             : struct egre_softc {
     343             :         struct gre_tunnel       sc_tunnel; /* must be first */
     344             :         RBT_ENTRY(egre_softc)   sc_entry;
     345             : 
     346             :         struct arpcom           sc_ac;
     347             :         struct ifmedia          sc_media;
     348             : };
     349             : 
     350             : RBT_HEAD(egre_tree, egre_softc);
     351             : 
     352             : static inline int
     353             :                 egre_cmp(const struct egre_softc *, const struct egre_softc *);
     354             : 
     355           0 : RBT_PROTOTYPE(egre_tree, egre_softc, sc_entry, egre_cmp);
     356             : 
     357             : static int      egre_clone_create(struct if_clone *, int);
     358             : static int      egre_clone_destroy(struct ifnet *);
     359             : 
     360             : static void     egre_start(struct ifnet *);
     361             : static int      egre_ioctl(struct ifnet *, u_long, caddr_t);
     362             : static int      egre_media_change(struct ifnet *);
     363             : static void     egre_media_status(struct ifnet *, struct ifmediareq *);
     364             : 
     365             : static int      egre_up(struct egre_softc *);
     366             : static int      egre_down(struct egre_softc *);
     367             : 
     368             : static int      egre_input(const struct gre_tunnel *, struct mbuf *, int);
     369             : struct if_clone egre_cloner =
     370             :     IF_CLONE_INITIALIZER("egre", egre_clone_create, egre_clone_destroy);
     371             :  
     372             : /* protected by NET_LOCK */
     373             : struct egre_tree egre_tree = RBT_INITIALIZER();
     374             : 
     375             : /*
     376             :  * Network Virtualisation Using Generic Routing Encapsulation (NVGRE)
     377             :  */
     378             : 
     379             : #define NVGRE_AGE_TMO           100     /* seconds */
     380             : 
     381             : struct nvgre_entry {
     382             :         RB_ENTRY(nvgre_entry)    nv_entry;
     383             :         struct ether_addr        nv_dst;
     384             :         uint8_t                  nv_type;
     385             : #define NVGRE_ENTRY_DYNAMIC             0
     386             : #define NVGRE_ENTRY_STATIC              1
     387             :         union gre_addr           nv_gateway;
     388             :         struct refcnt            nv_refs;
     389             :         int                      nv_age;
     390             : };
     391             : 
     392             : RBT_HEAD(nvgre_map, nvgre_entry);
     393             : 
     394             : static inline int
     395             :                 nvgre_entry_cmp(const struct nvgre_entry *,
     396             :                     const struct nvgre_entry *);
     397             : 
     398           0 : RBT_PROTOTYPE(nvgre_map, nvgre_entry, nv_entry, nvgre_entry_cmp);
     399             : 
     400             : struct nvgre_softc {
     401             :         struct gre_tunnel        sc_tunnel; /* must be first */
     402             :         unsigned int             sc_ifp0;
     403             :         RBT_ENTRY(nvgre_softc)   sc_uentry;
     404             :         RBT_ENTRY(nvgre_softc)   sc_mentry;
     405             : 
     406             :         struct arpcom            sc_ac;
     407             :         struct ifmedia           sc_media;
     408             : 
     409             :         struct mbuf_queue        sc_send_list;
     410             :         struct task              sc_send_task;
     411             : 
     412             :         void                    *sc_inm;
     413             :         void                    *sc_lhcookie;
     414             :         void                    *sc_dhcookie;
     415             : 
     416             :         struct rwlock            sc_ether_lock;
     417             :         struct nvgre_map         sc_ether_map;
     418             :         unsigned int             sc_ether_num;
     419             :         unsigned int             sc_ether_max;
     420             :         int                      sc_ether_tmo;
     421             :         struct timeout           sc_ether_age;
     422             : };
     423             : 
     424             : RBT_HEAD(nvgre_ucast_tree, nvgre_softc);
     425             : RBT_HEAD(nvgre_mcast_tree, nvgre_softc);
     426             : 
     427             : static inline int
     428             :                 nvgre_cmp_ucast(const struct nvgre_softc *,
     429             :                     const struct nvgre_softc *);
     430             : static int
     431             :                 nvgre_cmp_mcast(const struct gre_tunnel *,
     432             :                     const union gre_addr *, unsigned int,
     433             :                     const struct gre_tunnel *, const union gre_addr *,
     434             :                     unsigned int);
     435             : static inline int
     436             :                 nvgre_cmp_mcast_sc(const struct nvgre_softc *,
     437             :                     const struct nvgre_softc *);
     438             : 
     439           0 : RBT_PROTOTYPE(nvgre_ucast_tree, nvgre_softc, sc_uentry, nvgre_cmp_ucast);
     440           0 : RBT_PROTOTYPE(nvgre_mcast_tree, nvgre_softc, sc_mentry, nvgre_cmp_mcast_sc);
     441             : 
     442             : static int      nvgre_clone_create(struct if_clone *, int);
     443             : static int      nvgre_clone_destroy(struct ifnet *);
     444             : 
     445             : static void     nvgre_start(struct ifnet *);
     446             : static int      nvgre_ioctl(struct ifnet *, u_long, caddr_t);
     447             : 
     448             : static int      nvgre_up(struct nvgre_softc *);
     449             : static int      nvgre_down(struct nvgre_softc *);
     450             : static int      nvgre_set_parent(struct nvgre_softc *, const char *);
     451             : static void     nvgre_link_change(void *);
     452             : static void     nvgre_detach(void *);
     453             : 
     454             : static int      nvgre_input(const struct gre_tunnel *, struct mbuf *, int);
     455             : static void     nvgre_send(void *);
     456             : 
     457             : static int      nvgre_rtfind(struct nvgre_softc *, struct ifbaconf *);
     458             : static void     nvgre_flush_map(struct nvgre_softc *);
     459             : static void     nvgre_input_map(struct nvgre_softc *,
     460             :                     const struct gre_tunnel *, const struct ether_header *);
     461             : static void     nvgre_age(void *);
     462             : 
     463             : struct if_clone nvgre_cloner =
     464             :     IF_CLONE_INITIALIZER("nvgre", nvgre_clone_create, nvgre_clone_destroy);
     465             : 
     466             : struct pool nvgre_pool;
     467             : 
     468             : /* protected by NET_LOCK */
     469             : struct nvgre_ucast_tree nvgre_ucast_tree = RBT_INITIALIZER();
     470             : struct nvgre_mcast_tree nvgre_mcast_tree = RBT_INITIALIZER();
     471             : 
     472             : /*
     473             :  * MikroTik Ethernet over IP protocol (eoip)
     474             :  */
     475             : 
     476             : struct eoip_softc {
     477             :         struct gre_tunnel       sc_tunnel; /* must be first */
     478             :         uint16_t                sc_tunnel_id;
     479             :         RBT_ENTRY(eoip_softc)   sc_entry;
     480             : 
     481             :         struct arpcom           sc_ac;
     482             :         struct ifmedia          sc_media;
     483             : 
     484             :         struct timeout          sc_ka_send;
     485             :         struct timeout          sc_ka_hold;
     486             : 
     487             :         unsigned int            sc_ka_state;
     488             :         unsigned int            sc_ka_timeo;
     489             :         unsigned int            sc_ka_count;
     490             : 
     491             :         unsigned int            sc_ka_holdmax;
     492             :         unsigned int            sc_ka_holdcnt;
     493             : };
     494             : 
     495             : RBT_HEAD(eoip_tree, eoip_softc);
     496             : 
     497             : static inline int
     498             :                 eoip_cmp(const struct eoip_softc *, const struct eoip_softc *);
     499             : 
     500           0 : RBT_PROTOTYPE(eoip_tree, eoip_softc, sc_entry, eoip_cmp);
     501             : 
     502             : static int      eoip_clone_create(struct if_clone *, int);
     503             : static int      eoip_clone_destroy(struct ifnet *);
     504             : 
     505             : static void     eoip_start(struct ifnet *);
     506             : static int      eoip_ioctl(struct ifnet *, u_long, caddr_t);
     507             : 
     508             : static void     eoip_keepalive_send(void *);
     509             : static void     eoip_keepalive_recv(struct eoip_softc *);
     510             : static void     eoip_keepalive_hold(void *);
     511             : 
     512             : static int      eoip_up(struct eoip_softc *);
     513             : static int      eoip_down(struct eoip_softc *);
     514             : 
     515             : static struct mbuf *
     516             :                 eoip_encap(struct eoip_softc *, struct mbuf *, uint8_t);
     517             : 
     518             : static struct mbuf *
     519             :                 eoip_input(struct gre_tunnel *, struct mbuf *,
     520             :                     const struct gre_header *, int);
     521             : struct if_clone eoip_cloner =
     522             :     IF_CLONE_INITIALIZER("eoip", eoip_clone_create, eoip_clone_destroy);
     523             :  
     524             : /* protected by NET_LOCK */
     525             : struct eoip_tree eoip_tree = RBT_INITIALIZER();
     526             : 
     527             : /*
     528             :  * It is not easy to calculate the right value for a GRE MTU.
     529             :  * We leave this task to the admin and use the same default that
     530             :  * other vendors use.
     531             :  */
     532             : #define GREMTU 1476
     533             : 
     534             : /*
     535             :  * We can control the acceptance of GRE and MobileIP packets by
     536             :  * altering the sysctl net.inet.gre.allow values
     537             :  * respectively. Zero means drop them, all else is acceptance.  We can also
     538             :  * control acceptance of WCCPv1-style GRE packets through the
     539             :  * net.inet.gre.wccp value, but be aware it depends upon normal GRE being
     540             :  * allowed as well.
     541             :  *
     542             :  */
     543             : int gre_allow = 0;
     544             : int gre_wccp = 0;
     545             : 
     546             : void
     547           0 : greattach(int n)
     548             : {
     549           0 :         if_clone_attach(&gre_cloner);
     550           0 :         if_clone_attach(&mgre_cloner);
     551           0 :         if_clone_attach(&egre_cloner);
     552           0 :         if_clone_attach(&nvgre_cloner);
     553           0 :         if_clone_attach(&eoip_cloner);
     554           0 : }
     555             : 
     556             : static int
     557           0 : gre_clone_create(struct if_clone *ifc, int unit)
     558             : {
     559             :         struct gre_softc *sc;
     560             :         struct ifnet *ifp;
     561             : 
     562           0 :         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
     563           0 :         snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname, "%s%d",
     564           0 :             ifc->ifc_name, unit);
     565             : 
     566             :         ifp = &sc->sc_if;
     567           0 :         ifp->if_softc = sc;
     568           0 :         ifp->if_type = IFT_TUNNEL;
     569           0 :         ifp->if_hdrlen = GRE_HDRLEN;
     570           0 :         ifp->if_mtu = GREMTU;
     571           0 :         ifp->if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
     572           0 :         ifp->if_xflags = IFXF_CLONED;
     573           0 :         ifp->if_output = gre_output;
     574           0 :         ifp->if_start = gre_start;
     575           0 :         ifp->if_ioctl = gre_ioctl;
     576           0 :         ifp->if_rtrequest = p2p_rtrequest;
     577             : 
     578           0 :         sc->sc_tunnel.t_ttl = ip_defttl;
     579           0 :         sc->sc_tunnel.t_df = htons(0);
     580             : 
     581           0 :         timeout_set(&sc->sc_ka_send, gre_keepalive_send, sc);
     582           0 :         timeout_set_proc(&sc->sc_ka_hold, gre_keepalive_hold, sc);
     583           0 :         sc->sc_ka_state = GRE_KA_NONE;
     584             : 
     585           0 :         if_attach(ifp);
     586           0 :         if_alloc_sadl(ifp);
     587             : 
     588             : #if NBPFILTER > 0
     589           0 :         bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t));
     590             : #endif
     591             : 
     592           0 :         NET_LOCK();
     593           0 :         TAILQ_INSERT_TAIL(&gre_list, sc, sc_entry);
     594           0 :         NET_UNLOCK();
     595             : 
     596           0 :         return (0);
     597             : }
     598             : 
     599             : static int
     600           0 : gre_clone_destroy(struct ifnet *ifp)
     601             : {
     602           0 :         struct gre_softc *sc = ifp->if_softc;
     603             : 
     604           0 :         NET_LOCK();
     605           0 :         if (ISSET(ifp->if_flags, IFF_RUNNING))
     606           0 :                 gre_down(sc);
     607             : 
     608           0 :         TAILQ_REMOVE(&gre_list, sc, sc_entry);
     609           0 :         NET_UNLOCK();
     610             : 
     611           0 :         if_detach(ifp);
     612             : 
     613           0 :         free(sc, M_DEVBUF, sizeof(*sc));
     614             : 
     615           0 :         return (0);
     616             : }
     617             : 
     618             : static int
     619           0 : mgre_clone_create(struct if_clone *ifc, int unit)
     620             : {
     621             :         struct mgre_softc *sc;
     622             :         struct ifnet *ifp;
     623             : 
     624           0 :         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
     625           0 :         ifp = &sc->sc_if;
     626             : 
     627           0 :         snprintf(ifp->if_xname, sizeof(ifp->if_xname),
     628           0 :             "%s%d", ifc->ifc_name, unit);
     629             : 
     630           0 :         ifp->if_softc = sc;
     631           0 :         ifp->if_type = IFT_L3IPVLAN;
     632           0 :         ifp->if_hdrlen = GRE_HDRLEN;
     633           0 :         ifp->if_mtu = GREMTU;
     634           0 :         ifp->if_flags = IFF_MULTICAST|IFF_SIMPLEX;
     635           0 :         ifp->if_xflags = IFXF_CLONED;
     636           0 :         ifp->if_rtrequest = mgre_rtrequest;
     637           0 :         ifp->if_output = mgre_output;
     638           0 :         ifp->if_start = mgre_start;
     639           0 :         ifp->if_ioctl = mgre_ioctl;
     640             : 
     641           0 :         sc->sc_tunnel.t_ttl = ip_defttl;
     642           0 :         sc->sc_tunnel.t_df = htons(0);
     643             : 
     644           0 :         if_attach(ifp);
     645           0 :         if_alloc_sadl(ifp);
     646             : 
     647             : #if NBPFILTER > 0
     648           0 :         bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t));
     649             : #endif
     650             : 
     651           0 :         return (0);
     652             : }
     653             : 
     654             : static int
     655           0 : mgre_clone_destroy(struct ifnet *ifp)
     656             : {
     657           0 :         struct mgre_softc *sc = ifp->if_softc;
     658             : 
     659           0 :         NET_LOCK();
     660           0 :         if (ISSET(ifp->if_flags, IFF_RUNNING))
     661           0 :                 mgre_down(sc);
     662           0 :         NET_UNLOCK();
     663             : 
     664           0 :         if_detach(ifp);
     665             : 
     666           0 :         free(sc, M_DEVBUF, sizeof(*sc));
     667             : 
     668           0 :         return (0);
     669             : }
     670             : 
     671             : static int
     672           0 : egre_clone_create(struct if_clone *ifc, int unit)
     673             : {
     674             :         struct egre_softc *sc;
     675             :         struct ifnet *ifp;
     676             : 
     677           0 :         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
     678           0 :         ifp = &sc->sc_ac.ac_if;
     679             : 
     680           0 :         snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d",
     681           0 :             ifc->ifc_name, unit);
     682             : 
     683           0 :         ifp->if_softc = sc;
     684           0 :         ifp->if_mtu = 1500; /* XXX */
     685           0 :         ifp->if_ioctl = egre_ioctl;
     686           0 :         ifp->if_start = egre_start;
     687           0 :         ifp->if_xflags = IFXF_CLONED;
     688           0 :         IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
     689           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     690           0 :         ether_fakeaddr(ifp);
     691             : 
     692           0 :         sc->sc_tunnel.t_ttl = ip_defttl;
     693           0 :         sc->sc_tunnel.t_df = htons(0);
     694             : 
     695           0 :         ifmedia_init(&sc->sc_media, 0, egre_media_change, egre_media_status);
     696           0 :         ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
     697           0 :         ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
     698             : 
     699           0 :         if_attach(ifp);
     700           0 :         ether_ifattach(ifp);
     701             : 
     702           0 :         return (0);
     703             : }
     704             : 
     705             : static int
     706           0 : egre_clone_destroy(struct ifnet *ifp)
     707             : {
     708           0 :         struct egre_softc *sc = ifp->if_softc;
     709             : 
     710           0 :         NET_LOCK();
     711           0 :         if (ISSET(ifp->if_flags, IFF_RUNNING))
     712           0 :                 egre_down(sc);
     713           0 :         NET_UNLOCK();
     714             : 
     715           0 :         ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
     716           0 :         ether_ifdetach(ifp);
     717           0 :         if_detach(ifp);
     718             : 
     719           0 :         free(sc, M_DEVBUF, sizeof(*sc));
     720             : 
     721           0 :         return (0);
     722             : }
     723             : 
     724             : static int
     725           0 : nvgre_clone_create(struct if_clone *ifc, int unit)
     726             : {
     727             :         struct nvgre_softc *sc;
     728             :         struct ifnet *ifp;
     729             :         struct gre_tunnel *tunnel;
     730             : 
     731           0 :         if (nvgre_pool.pr_size == 0) {
     732           0 :                 pool_init(&nvgre_pool, sizeof(struct nvgre_entry), 0,
     733             :                     IPL_SOFTNET, 0, "nvgren", NULL);
     734           0 :         }
     735             : 
     736           0 :         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
     737           0 :         ifp = &sc->sc_ac.ac_if;
     738             : 
     739           0 :         snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d",
     740           0 :             ifc->ifc_name, unit);
     741             : 
     742           0 :         ifp->if_softc = sc;
     743           0 :         ifp->if_mtu = 1500; /* XXX */
     744           0 :         ifp->if_ioctl = nvgre_ioctl;
     745           0 :         ifp->if_start = nvgre_start;
     746           0 :         ifp->if_xflags = IFXF_CLONED;
     747           0 :         IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
     748           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     749           0 :         ether_fakeaddr(ifp);
     750             : 
     751           0 :         tunnel = &sc->sc_tunnel;
     752           0 :         tunnel->t_ttl = IP_DEFAULT_MULTICAST_TTL;
     753           0 :         tunnel->t_df = htons(IP_DF);
     754           0 :         tunnel->t_key_mask = GRE_KEY_ENTROPY;
     755           0 :         tunnel->t_key = htonl((NVGRE_VSID_RES_MAX + 1) <<
     756             :             GRE_KEY_ENTROPY_SHIFT);
     757             : 
     758           0 :         mq_init(&sc->sc_send_list, IFQ_MAXLEN * 2, IPL_SOFTNET);
     759           0 :         task_set(&sc->sc_send_task, nvgre_send, sc);
     760             : 
     761           0 :         rw_init(&sc->sc_ether_lock, "nvgrelk");
     762           0 :         RBT_INIT(nvgre_map, &sc->sc_ether_map);
     763           0 :         sc->sc_ether_num = 0;
     764           0 :         sc->sc_ether_max = 100;
     765           0 :         sc->sc_ether_tmo = 240 * hz;
     766           0 :         timeout_set_proc(&sc->sc_ether_age, nvgre_age, sc); /* ugh */
     767             : 
     768           0 :         ifmedia_init(&sc->sc_media, 0, egre_media_change, egre_media_status);
     769           0 :         ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
     770           0 :         ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
     771             : 
     772           0 :         if_attach(ifp);
     773           0 :         ether_ifattach(ifp);
     774             : 
     775           0 :         return (0);
     776             : }
     777             : 
     778             : static int
     779           0 : nvgre_clone_destroy(struct ifnet *ifp)
     780             : {
     781           0 :         struct nvgre_softc *sc = ifp->if_softc;
     782             : 
     783           0 :         NET_LOCK();
     784           0 :         if (ISSET(ifp->if_flags, IFF_RUNNING))
     785           0 :                 nvgre_down(sc);
     786           0 :         NET_UNLOCK();
     787             : 
     788           0 :         ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
     789           0 :         ether_ifdetach(ifp);
     790           0 :         if_detach(ifp);
     791             : 
     792           0 :         free(sc, M_DEVBUF, sizeof(*sc));
     793             : 
     794           0 :         return (0);
     795             : }
     796             : 
     797             : static int
     798           0 : eoip_clone_create(struct if_clone *ifc, int unit)
     799             : {
     800             :         struct eoip_softc *sc;
     801             :         struct ifnet *ifp;
     802             : 
     803           0 :         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
     804           0 :         ifp = &sc->sc_ac.ac_if;
     805             : 
     806           0 :         snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d",
     807           0 :             ifc->ifc_name, unit);
     808             : 
     809           0 :         ifp->if_softc = sc;
     810           0 :         ifp->if_ioctl = eoip_ioctl;
     811           0 :         ifp->if_start = eoip_start;
     812           0 :         ifp->if_xflags = IFXF_CLONED;
     813           0 :         IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
     814           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     815           0 :         ether_fakeaddr(ifp);
     816             : 
     817           0 :         sc->sc_tunnel.t_ttl = ip_defttl;
     818           0 :         sc->sc_tunnel.t_df = htons(0);
     819             : 
     820           0 :         sc->sc_ka_timeo = 10;
     821           0 :         sc->sc_ka_count = 10;
     822             : 
     823           0 :         timeout_set(&sc->sc_ka_send, eoip_keepalive_send, sc);
     824           0 :         timeout_set_proc(&sc->sc_ka_hold, eoip_keepalive_hold, sc);
     825           0 :         sc->sc_ka_state = GRE_KA_DOWN;
     826             : 
     827           0 :         ifmedia_init(&sc->sc_media, 0, egre_media_change, egre_media_status);
     828           0 :         ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
     829           0 :         ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
     830             : 
     831           0 :         if_attach(ifp);
     832           0 :         ether_ifattach(ifp);
     833             : 
     834           0 :         return (0);
     835             : }
     836             : 
     837             : static int
     838           0 : eoip_clone_destroy(struct ifnet *ifp)
     839             : {
     840           0 :         struct eoip_softc *sc = ifp->if_softc;
     841             : 
     842           0 :         NET_LOCK();
     843           0 :         if (ISSET(ifp->if_flags, IFF_RUNNING))
     844           0 :                 eoip_down(sc);
     845           0 :         NET_UNLOCK();
     846             : 
     847           0 :         ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
     848           0 :         ether_ifdetach(ifp);
     849           0 :         if_detach(ifp);
     850             : 
     851           0 :         free(sc, M_DEVBUF, sizeof(*sc));
     852             : 
     853           0 :         return (0);
     854             : }
     855             : 
     856             : int
     857           0 : gre_input(struct mbuf **mp, int *offp, int type, int af)
     858             : {
     859           0 :         struct mbuf *m = *mp;
     860           0 :         struct gre_tunnel key;
     861             :         struct ip *ip;
     862             : 
     863           0 :         ip = mtod(m, struct ip *);
     864             : 
     865             :         /* XXX check if ip_src is sane for nvgre? */
     866             : 
     867           0 :         key.t_af = AF_INET;
     868           0 :         key.t_ttl = ip->ip_ttl;
     869           0 :         key.t_src4 = ip->ip_dst;
     870           0 :         key.t_dst4 = ip->ip_src;
     871             : 
     872           0 :         if (gre_input_key(mp, offp, type, af, &key) == -1)
     873           0 :                 return (rip_input(mp, offp, type, af));
     874             : 
     875           0 :         return (IPPROTO_DONE);
     876           0 : }
     877             : 
     878             : #ifdef INET6
     879             : int
     880           0 : gre_input6(struct mbuf **mp, int *offp, int type, int af)
     881             : {
     882           0 :         struct mbuf *m = *mp;
     883           0 :         struct gre_tunnel key;
     884             :         struct ip6_hdr *ip6;
     885             : 
     886           0 :         ip6 = mtod(m, struct ip6_hdr *);
     887             : 
     888             :         /* XXX check if ip6_src is sane for nvgre? */
     889             : 
     890           0 :         key.t_af = AF_INET6;
     891           0 :         key.t_ttl = ip6->ip6_hlim;
     892           0 :         key.t_src6 = ip6->ip6_dst;
     893           0 :         key.t_dst6 = ip6->ip6_src;
     894             : 
     895           0 :         if (gre_input_key(mp, offp, type, af, &key) == -1)
     896           0 :                 return (rip6_input(mp, offp, type, af));
     897             : 
     898           0 :         return (IPPROTO_DONE);
     899           0 : }
     900             : #endif /* INET6 */
     901             : 
     902             : static inline struct ifnet *
     903           0 : gre_find(const struct gre_tunnel *key)
     904             : {
     905             :         struct gre_softc *sc;
     906             : 
     907           0 :         TAILQ_FOREACH(sc, &gre_list, sc_entry) {
     908           0 :                 if (gre_cmp(key, &sc->sc_tunnel) != 0)
     909             :                         continue;
     910             : 
     911           0 :                 if (!ISSET(sc->sc_if.if_flags, IFF_RUNNING))
     912             :                         continue;
     913             : 
     914           0 :                 return (&sc->sc_if);
     915             :         }
     916             : 
     917           0 :         return (NULL);
     918           0 : }
     919             : 
     920             : static inline struct ifnet *
     921           0 : mgre_find(const struct gre_tunnel *key)
     922             : {
     923             :         struct mgre_softc *sc;
     924             : 
     925           0 :         NET_ASSERT_LOCKED();
     926           0 :         sc = RBT_FIND(mgre_tree, &mgre_tree, (const struct mgre_softc *)key);
     927           0 :         if (sc != NULL)
     928           0 :                 return (&sc->sc_if);
     929             : 
     930           0 :         return (NULL);
     931           0 : }
     932             : 
     933             : static struct mbuf *
     934           0 : gre_input_1(struct gre_tunnel *key, struct mbuf *m,
     935             :     const struct gre_header *gh, int iphlen)
     936             : {
     937           0 :         switch (gh->gre_proto) {
     938             :         case htons(ETHERTYPE_PPP):
     939             : #ifdef PIPEX
     940           0 :                 if (pipex_enable) {
     941             :                         struct pipex_session *session;
     942             : 
     943           0 :                         session = pipex_pptp_lookup_session(m);
     944           0 :                         if (session != NULL &&
     945           0 :                             pipex_pptp_input(m, session) == NULL)
     946           0 :                                 return (NULL);
     947           0 :                 }
     948             : #endif
     949             :                 break;
     950             :         case htons(GRE_EOIP):
     951           0 :                 return (eoip_input(key, m, gh, iphlen));
     952             :                 break;
     953             :         }
     954             : 
     955           0 :         return (m);
     956           0 : }
     957             : 
     958             : static int
     959           0 : gre_input_key(struct mbuf **mp, int *offp, int type, int af,
     960             :     struct gre_tunnel *key)
     961             : {
     962           0 :         struct mbuf *m = *mp;
     963           0 :         int iphlen = *offp, hlen;
     964             :         struct ifnet *ifp;
     965             :         const struct gre_tunnel *tunnel;
     966             :         caddr_t buf;
     967             :         struct gre_header *gh;
     968             :         struct gre_h_key *gkh;
     969             :         void (*input)(struct ifnet *, struct mbuf *);
     970             :         int bpf_af = AF_UNSPEC; /* bpf */
     971             :         int mcast = 0;
     972             :         int ttloff;
     973             : 
     974           0 :         if (!gre_allow)
     975             :                 goto decline;
     976             : 
     977           0 :         key->t_rtableid = m->m_pkthdr.ph_rtableid;
     978             : 
     979           0 :         hlen = iphlen + sizeof(*gh);
     980           0 :         if (m->m_pkthdr.len < hlen)
     981             :                 goto decline;
     982             : 
     983           0 :         m = m_pullup(m, hlen);
     984           0 :         if (m == NULL)
     985           0 :                 return (IPPROTO_DONE);
     986             : 
     987           0 :         buf = mtod(m, caddr_t);
     988           0 :         gh = (struct gre_header *)(buf + iphlen);
     989             : 
     990             :         /* check the version */
     991           0 :         switch (gh->gre_flags & htons(GRE_VERS_MASK)) {
     992             :         case htons(GRE_VERS_0):
     993             :                 break;
     994             : 
     995             :         case htons(GRE_VERS_1):
     996           0 :                 m = gre_input_1(key, m, gh, iphlen);
     997           0 :                 if (m == NULL)
     998           0 :                         return (IPPROTO_DONE);
     999             :                 /* FALLTHROUGH */
    1000             :         default:
    1001             :                 goto decline;
    1002             :         }
    1003             : 
    1004             :         /* the only optional bit in the header is K flag */
    1005           0 :         if ((gh->gre_flags & htons(~(GRE_KP|GRE_VERS_MASK))) != htons(0))
    1006             :                 goto decline;
    1007             : 
    1008           0 :         if (gh->gre_flags & htons(GRE_KP)) {
    1009           0 :                 hlen += sizeof(*gkh);
    1010           0 :                 if (m->m_pkthdr.len < hlen)
    1011             :                         goto decline;
    1012             : 
    1013           0 :                 m = m_pullup(m, hlen);
    1014           0 :                 if (m == NULL)
    1015           0 :                         return (IPPROTO_DONE);
    1016             : 
    1017           0 :                 buf = mtod(m, caddr_t);
    1018           0 :                 gh = (struct gre_header *)(buf + iphlen);
    1019           0 :                 gkh = (struct gre_h_key *)(gh + 1);
    1020             : 
    1021           0 :                 key->t_key_mask = GRE_KEY_MASK;
    1022           0 :                 key->t_key = gkh->gre_key;
    1023           0 :         } else
    1024           0 :                 key->t_key_mask = GRE_KEY_NONE;
    1025             : 
    1026           0 :         if (gh->gre_proto == htons(ETHERTYPE_TRANSETHER)) {
    1027           0 :                 if (egre_input(key, m, hlen) == -1 &&
    1028           0 :                     nvgre_input(key, m, hlen) == -1)
    1029             :                         goto decline;
    1030             : 
    1031           0 :                 return (IPPROTO_DONE);
    1032             :         }
    1033             : 
    1034           0 :         ifp = gre_find(key);
    1035           0 :         if (ifp == NULL) {
    1036           0 :                 ifp = mgre_find(key);
    1037           0 :                 if (ifp == NULL)
    1038             :                         goto decline;
    1039             :         }
    1040             : 
    1041           0 :         switch (gh->gre_proto) {
    1042             :         case htons(GRE_WCCP): {
    1043             :                 struct mbuf *n;
    1044           0 :                 int off;
    1045             : 
    1046             :                 /* WCCP/GRE:
    1047             :                  *   So far as I can see (and test) it seems that Cisco's WCCP
    1048             :                  *   GRE tunnel is precisely a IP-in-GRE tunnel that differs
    1049             :                  *   only in its protocol number.  At least, it works for me.
    1050             :                  *
    1051             :                  *   The Internet Drafts can be found if you look for
    1052             :                  *   the following:
    1053             :                  *     draft-forster-wrec-wccp-v1-00.txt
    1054             :                  *     draft-wilson-wrec-wccp-v2-01.txt
    1055             :                  */
    1056             : 
    1057           0 :                 if (!gre_wccp && !ISSET(ifp->if_flags, IFF_LINK0))
    1058           0 :                         goto decline;
    1059             : 
    1060             :                 /*
    1061             :                  * If the first nibble of the payload does not look like
    1062             :                  * IPv4, assume it is WCCP v2.
    1063             :                  */
    1064           0 :                 n = m_getptr(m, hlen, &off);
    1065           0 :                 if (n == NULL)
    1066           0 :                         goto decline;
    1067           0 :                 if (n->m_data[off] >> 4 != IPVERSION)
    1068           0 :                         hlen += sizeof(gre_wccp);
    1069             : 
    1070             :                 /* FALLTHROUGH */
    1071           0 :         }
    1072             :         case htons(ETHERTYPE_IP):
    1073             : #if NBPFILTER > 0
    1074             :                 bpf_af = AF_INET;
    1075             : #endif
    1076             :                 ttloff = offsetof(struct ip, ip_ttl);
    1077             :                 input = ipv4_input;
    1078           0 :                 break;
    1079             : #ifdef INET6
    1080             :         case htons(ETHERTYPE_IPV6):
    1081             : #if NBPFILTER > 0
    1082             :                 bpf_af = AF_INET6;
    1083             : #endif
    1084             :                 ttloff = offsetof(struct ip6_hdr, ip6_hlim);
    1085             :                 input = ipv6_input;
    1086           0 :                 break;
    1087             : #endif
    1088             : #ifdef MPLS
    1089             :         case htons(ETHERTYPE_MPLS_MCAST):
    1090           0 :                 mcast = M_MCAST|M_BCAST;
    1091             :                 /* fallthrough */
    1092             :         case htons(ETHERTYPE_MPLS):
    1093             : #if NBPFILTER > 0
    1094             :                 bpf_af = AF_MPLS;
    1095             : #endif
    1096             :                 ttloff = 3; /* XXX */
    1097             :                 input = mpls_input;
    1098           0 :                 break;
    1099             : #endif
    1100             :         case htons(0):
    1101           0 :                 if (ifp->if_type != IFT_TUNNEL) {
    1102             :                         /* keepalives dont make sense for mgre */
    1103             :                         goto decline;
    1104             :                 }
    1105             : 
    1106             : #if NBPFILTER > 0
    1107             :                 bpf_af = AF_UNSPEC;
    1108             : #endif
    1109             :                 input = gre_keepalive_recv;
    1110           0 :                 break;
    1111             : 
    1112             :         default:
    1113             :                 goto decline;
    1114             :         }
    1115             : 
    1116             :         /* it's ours now */
    1117             : 
    1118           0 :         m_adj(m, hlen);
    1119             : 
    1120           0 :         tunnel = ifp->if_softc; /* gre and mgre tunnel info is at the front */
    1121             : 
    1122           0 :         if (tunnel->t_ttl == -1) {
    1123           0 :                 m = m_pullup(m, ttloff + 1);
    1124           0 :                 if (m == NULL)
    1125           0 :                         return (IPPROTO_DONE);
    1126             : 
    1127           0 :                 *(m->m_data + ttloff) = key->t_ttl;
    1128           0 :         }
    1129             : 
    1130           0 :         if (tunnel->t_key_mask == GRE_KEY_ENTROPY) {
    1131           0 :                 m->m_pkthdr.ph_flowid = M_FLOWID_VALID |
    1132           0 :                     (bemtoh32(&key->t_key) & ~GRE_KEY_ENTROPY);
    1133           0 :         }
    1134             : 
    1135           0 :         m->m_flags &= ~(M_MCAST|M_BCAST);
    1136           0 :         m->m_flags |= mcast;
    1137           0 :         m->m_pkthdr.ph_ifidx = ifp->if_index;
    1138           0 :         m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
    1139             : 
    1140             : #if NPF > 0
    1141           0 :         pf_pkt_addr_changed(m);
    1142             : #endif
    1143             : 
    1144           0 :         ifp->if_ipackets++;
    1145           0 :         ifp->if_ibytes += m->m_pkthdr.len;
    1146             : 
    1147             : #if NBPFILTER > 0
    1148           0 :         if (ifp->if_bpf)
    1149           0 :                 bpf_mtap_af(ifp->if_bpf, bpf_af, m, BPF_DIRECTION_IN);
    1150             : #endif
    1151             : 
    1152           0 :         (*input)(ifp, m);
    1153           0 :         return (IPPROTO_DONE);
    1154             : decline:
    1155           0 :         *mp = m;
    1156           0 :         return (-1);
    1157           0 : }
    1158             : 
    1159             : static int
    1160           0 : egre_input(const struct gre_tunnel *key, struct mbuf *m, int hlen)
    1161             : {
    1162             :         struct egre_softc *sc;
    1163           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
    1164             : 
    1165           0 :         NET_ASSERT_LOCKED();
    1166           0 :         sc = RBT_FIND(egre_tree, &egre_tree, (const struct egre_softc *)key);
    1167           0 :         if (sc == NULL)
    1168           0 :                 return (-1);
    1169             : 
    1170             :         /* it's ours now */
    1171           0 :         m = gre_ether_align(m, hlen);
    1172           0 :         if (m == NULL)
    1173           0 :                 return (0);
    1174             : 
    1175           0 :         if (sc->sc_tunnel.t_key_mask == GRE_KEY_ENTROPY) {
    1176           0 :                 m->m_pkthdr.ph_flowid = M_FLOWID_VALID |
    1177           0 :                     (bemtoh32(&key->t_key) & ~GRE_KEY_ENTROPY);
    1178           0 :         }
    1179             : 
    1180           0 :         m->m_flags &= ~(M_MCAST|M_BCAST);
    1181             : 
    1182             : #if NPF > 0
    1183           0 :         pf_pkt_addr_changed(m);
    1184             : #endif
    1185             : 
    1186           0 :         ml_enqueue(&ml, m);
    1187           0 :         if_input(&sc->sc_ac.ac_if, &ml);
    1188             : 
    1189           0 :         return (0);
    1190           0 : }
    1191             : 
    1192             : static int
    1193           0 : nvgre_rtfind(struct nvgre_softc *sc, struct ifbaconf *baconf)
    1194             : {
    1195           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
    1196             :         struct nvgre_entry *nv;
    1197           0 :         struct ifbareq bareq;
    1198             :         caddr_t uaddr, end;
    1199             :         int error;
    1200             :         int age;
    1201             : 
    1202           0 :         if (baconf->ifbac_len == 0) {
    1203             :                 /* single read is atomic */
    1204           0 :                 baconf->ifbac_len = sc->sc_ether_num * sizeof(bareq);
    1205           0 :                 return (0);
    1206             :         }
    1207             : 
    1208           0 :         uaddr = baconf->ifbac_buf;
    1209           0 :         end = uaddr + baconf->ifbac_len;
    1210             : 
    1211           0 :         rw_enter_read(&sc->sc_ether_lock);
    1212           0 :         RBT_FOREACH(nv, nvgre_map, &sc->sc_ether_map) {
    1213           0 :                 if (uaddr >= end)
    1214             :                         break;
    1215             : 
    1216           0 :                 memcpy(bareq.ifba_name, ifp->if_xname,
    1217             :                     sizeof(bareq.ifba_name));
    1218           0 :                 memcpy(bareq.ifba_ifsname, ifp->if_xname,
    1219             :                     sizeof(bareq.ifba_ifsname));
    1220           0 :                 memcpy(&bareq.ifba_dst, &nv->nv_dst,
    1221             :                     sizeof(bareq.ifba_dst));
    1222             : 
    1223           0 :                 memset(&bareq.ifba_dstsa, 0, sizeof(bareq.ifba_dstsa));
    1224           0 :                 switch (sc->sc_tunnel.t_af) {
    1225             :                 case AF_INET: {
    1226             :                         struct sockaddr_in *sin;
    1227             : 
    1228           0 :                         sin = (struct sockaddr_in *)&bareq.ifba_dstsa;
    1229           0 :                         sin->sin_len = sizeof(*sin);
    1230           0 :                         sin->sin_family = AF_INET;
    1231           0 :                         sin->sin_addr = nv->nv_gateway.in4;
    1232             : 
    1233             :                         break;
    1234             :                 }
    1235             : #ifdef INET6
    1236             :                 case AF_INET6: {
    1237             :                         struct sockaddr_in6 *sin6;
    1238             : 
    1239           0 :                         sin6 = (struct sockaddr_in6 *)&bareq.ifba_dstsa;
    1240           0 :                         sin6->sin6_len = sizeof(*sin6);
    1241           0 :                         sin6->sin6_family = AF_INET6;
    1242           0 :                         sin6->sin6_addr = nv->nv_gateway.in6;
    1243             : 
    1244             :                         break;
    1245             :                 }
    1246             : #endif /* INET6 */
    1247             :                 default:
    1248           0 :                         unhandled_af(sc->sc_tunnel.t_af);
    1249             :                 }
    1250             : 
    1251           0 :                 switch (nv->nv_type) {
    1252             :                 case NVGRE_ENTRY_DYNAMIC:
    1253           0 :                         age = (ticks - nv->nv_age) / hz;
    1254           0 :                         bareq.ifba_age = MIN(age, 0xff);
    1255           0 :                         bareq.ifba_flags = IFBAF_DYNAMIC;
    1256           0 :                         break;
    1257             :                 case NVGRE_ENTRY_STATIC:
    1258           0 :                         bareq.ifba_age = 0;
    1259           0 :                         bareq.ifba_flags = IFBAF_STATIC;
    1260           0 :                         break;
    1261             :                 }
    1262             : 
    1263           0 :                 error = copyout(&bareq, uaddr, sizeof(bareq));
    1264           0 :                 if (error != 0) {
    1265           0 :                         rw_exit_read(&sc->sc_ether_lock);
    1266           0 :                         return (error);
    1267             :                 }
    1268             : 
    1269           0 :                 uaddr += sizeof(bareq);
    1270             :         }
    1271           0 :         baconf->ifbac_len = sc->sc_ether_num * sizeof(bareq);
    1272           0 :         rw_exit_read(&sc->sc_ether_lock);
    1273             : 
    1274           0 :         return (0);
    1275           0 : }
    1276             : 
    1277             : static void
    1278           0 : nvgre_flush_map(struct nvgre_softc *sc)
    1279             : {
    1280           0 :         struct nvgre_map map;
    1281             :         struct nvgre_entry *nv, *nnv;
    1282             : 
    1283           0 :         rw_enter_write(&sc->sc_ether_lock);
    1284           0 :         map = sc->sc_ether_map;
    1285           0 :         RBT_INIT(nvgre_map, &sc->sc_ether_map);
    1286           0 :         sc->sc_ether_num = 0;
    1287           0 :         rw_exit_write(&sc->sc_ether_lock);
    1288             : 
    1289           0 :         RBT_FOREACH_SAFE(nv, nvgre_map, &map, nnv) {
    1290           0 :                 RBT_REMOVE(nvgre_map, &map, nv);
    1291           0 :                 if (refcnt_rele(&nv->nv_refs))
    1292           0 :                         pool_put(&nvgre_pool, nv);
    1293             :         }
    1294           0 : }
    1295             : 
    1296             : static void
    1297           0 : nvgre_input_map(struct nvgre_softc *sc, const struct gre_tunnel *key,
    1298             :     const struct ether_header *eh)
    1299             : {
    1300           0 :         struct nvgre_entry *nv, nkey;
    1301             :         int new = 0;
    1302             : 
    1303           0 :         if (ether_isbcast(eh->ether_shost) ||
    1304           0 :             ETHER_IS_MULTICAST(eh->ether_shost))
    1305           0 :                 return;
    1306             : 
    1307           0 :         memcpy(&nkey.nv_dst, eh->ether_shost, ETHER_ADDR_LEN);
    1308             : 
    1309             :         /* remember where it came from */
    1310           0 :         rw_enter_read(&sc->sc_ether_lock);
    1311           0 :         nv = RBT_FIND(nvgre_map, &sc->sc_ether_map, &nkey);
    1312           0 :         if (nv == NULL)
    1313           0 :                 new = 1;
    1314             :         else {
    1315           0 :                 nv->nv_age = ticks;
    1316             : 
    1317           0 :                 if (nv->nv_type != NVGRE_ENTRY_DYNAMIC ||
    1318           0 :                     gre_ip_cmp(key->t_af, &key->t_dst, &nv->nv_gateway))
    1319           0 :                         nv = NULL;
    1320             :                 else
    1321           0 :                         refcnt_take(&nv->nv_refs);
    1322             :         }
    1323           0 :         rw_exit_read(&sc->sc_ether_lock);
    1324             : 
    1325           0 :         if (new) {
    1326             :                 struct nvgre_entry *onv;
    1327             :                 unsigned int num;
    1328             : 
    1329           0 :                 nv = pool_get(&nvgre_pool, PR_NOWAIT);
    1330           0 :                 if (nv == NULL) {
    1331             :                         /* oh well */
    1332           0 :                         return;
    1333             :                 }
    1334             : 
    1335           0 :                 memcpy(&nv->nv_dst, eh->ether_shost, ETHER_ADDR_LEN);
    1336           0 :                 nv->nv_type = NVGRE_ENTRY_DYNAMIC;
    1337           0 :                 nv->nv_gateway = key->t_dst;
    1338           0 :                 refcnt_init(&nv->nv_refs);
    1339           0 :                 nv->nv_age = ticks;
    1340             : 
    1341           0 :                 rw_enter_write(&sc->sc_ether_lock);
    1342           0 :                 num = sc->sc_ether_num;
    1343           0 :                 if (++num > sc->sc_ether_max)
    1344           0 :                         onv = nv;
    1345             :                 else {
    1346             :                         /* try to give the ref to the map */
    1347           0 :                         onv = RBT_INSERT(nvgre_map, &sc->sc_ether_map, nv);
    1348           0 :                         if (onv == NULL) {
    1349             :                                 /* count the successful insert */
    1350           0 :                                 sc->sc_ether_num = num;
    1351           0 :                         }
    1352             :                 }
    1353           0 :                 rw_exit_write(&sc->sc_ether_lock);
    1354             : 
    1355           0 :                 if (onv != NULL)
    1356           0 :                         pool_put(&nvgre_pool, nv);
    1357           0 :         } else if (nv != NULL) {
    1358           0 :                 rw_enter_write(&sc->sc_ether_lock);
    1359           0 :                 nv->nv_gateway = key->t_dst;
    1360           0 :                 rw_exit_write(&sc->sc_ether_lock);
    1361             : 
    1362           0 :                 if (refcnt_rele(&nv->nv_refs)) {
    1363             :                         /* ioctl may have deleted the entry */
    1364           0 :                         pool_put(&nvgre_pool, nv);
    1365           0 :                 }
    1366             :         }
    1367           0 : }
    1368             : 
    1369             : static inline struct nvgre_softc *
    1370           0 : nvgre_mcast_find(const struct gre_tunnel *key, unsigned int if0idx)
    1371             : {
    1372             :         struct nvgre_softc *sc;
    1373             :         int rv;
    1374             : 
    1375             :         /*
    1376             :          * building an nvgre_softc to use with RBT_FIND is expensive, and
    1377             :          * would need to swap the src and dst addresses in the key. so do the
    1378             :          * find by hand.
    1379             :          */
    1380             : 
    1381           0 :         NET_ASSERT_LOCKED();
    1382           0 :         sc = RBT_ROOT(nvgre_mcast_tree, &nvgre_mcast_tree);
    1383           0 :         while (sc != NULL) {
    1384           0 :                 rv = nvgre_cmp_mcast(key, &key->t_src, if0idx,
    1385           0 :                     &sc->sc_tunnel, &sc->sc_tunnel.t_dst, sc->sc_ifp0);
    1386           0 :                 if (rv == 0)
    1387           0 :                         return (sc);
    1388           0 :                 if (rv < 0)
    1389           0 :                         sc = RBT_LEFT(nvgre_mcast_tree, sc);
    1390             :                 else
    1391           0 :                         sc = RBT_RIGHT(nvgre_mcast_tree, sc);
    1392             :         }
    1393             : 
    1394           0 :         return (NULL);
    1395           0 : }
    1396             : 
    1397             : static inline struct nvgre_softc *
    1398           0 : nvgre_ucast_find(const struct gre_tunnel *key)
    1399             : {
    1400           0 :         NET_ASSERT_LOCKED();
    1401           0 :         return (RBT_FIND(nvgre_ucast_tree, &nvgre_ucast_tree,
    1402             :             (struct nvgre_softc *)key));
    1403             : }
    1404             : 
    1405             : static int
    1406           0 : nvgre_input(const struct gre_tunnel *key, struct mbuf *m, int hlen)
    1407             : {
    1408             :         struct nvgre_softc *sc;
    1409           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
    1410             : 
    1411           0 :         if (ISSET(m->m_flags, M_MCAST|M_BCAST))
    1412           0 :                 sc = nvgre_mcast_find(key, m->m_pkthdr.ph_ifidx);
    1413             :         else
    1414           0 :                 sc = nvgre_ucast_find(key);
    1415             : 
    1416           0 :         if (sc == NULL)
    1417           0 :                 return (-1);
    1418             : 
    1419             :         /* it's ours now */
    1420           0 :         m = gre_ether_align(m, hlen);
    1421           0 :         if (m == NULL)
    1422           0 :                 return (0);
    1423             : 
    1424           0 :         nvgre_input_map(sc, key, mtod(m, struct ether_header *));
    1425             : 
    1426           0 :         m->m_pkthdr.ph_flowid = M_FLOWID_VALID |
    1427           0 :             (bemtoh32(&key->t_key) & ~GRE_KEY_ENTROPY);
    1428             : 
    1429           0 :         m->m_flags &= ~(M_MCAST|M_BCAST);
    1430             : 
    1431             : #if NPF > 0
    1432           0 :         pf_pkt_addr_changed(m);
    1433             : #endif
    1434             : 
    1435           0 :         ml_enqueue(&ml, m);
    1436           0 :         if_input(&sc->sc_ac.ac_if, &ml);
    1437             : 
    1438           0 :         return (0);
    1439           0 : }
    1440             : 
    1441             : static struct mbuf *
    1442           0 : gre_ether_align(struct mbuf *m, int hlen)
    1443             : {
    1444             :         struct mbuf *n;
    1445           0 :         int off;
    1446             : 
    1447           0 :         m_adj(m, hlen);
    1448             : 
    1449           0 :         if (m->m_pkthdr.len < sizeof(struct ether_header)) {
    1450           0 :                 m_freem(m);
    1451           0 :                 return (NULL);
    1452             :         }
    1453             : 
    1454           0 :         m = m_pullup(m, sizeof(struct ether_header));
    1455           0 :         if (m == NULL)
    1456           0 :                 return (NULL);
    1457             : 
    1458           0 :         n = m_getptr(m, sizeof(struct ether_header), &off);
    1459           0 :         if (n == NULL) {
    1460           0 :                 m_freem(m);
    1461           0 :                 return (NULL);
    1462             :         }
    1463             : 
    1464             :         if (!ALIGNED_POINTER(mtod(n, caddr_t) + off, uint32_t)) {
    1465             :                 n = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT);
    1466             :                 m_freem(m);
    1467             :                 if (n == NULL)
    1468             :                         return (NULL);
    1469             :                 m = n;
    1470             :         }
    1471             : 
    1472           0 :         return (m);
    1473           0 : }
    1474             : 
    1475             : static void
    1476           0 : gre_keepalive_recv(struct ifnet *ifp, struct mbuf *m)
    1477             : {
    1478           0 :         struct gre_softc *sc = ifp->if_softc;
    1479             :         struct gre_keepalive *gk;
    1480           0 :         SIPHASH_CTX ctx;
    1481           0 :         uint8_t digest[SIPHASH_DIGEST_LENGTH];
    1482             :         int uptime, delta;
    1483           0 :         int tick = ticks;
    1484             : 
    1485           0 :         if (sc->sc_ka_state == GRE_KA_NONE ||
    1486           0 :             sc->sc_tunnel.t_rtableid != sc->sc_if.if_rdomain)
    1487             :                 goto drop;
    1488             : 
    1489           0 :         if (m->m_pkthdr.len < sizeof(*gk))
    1490             :                 goto drop;
    1491           0 :         m = m_pullup(m, sizeof(*gk));
    1492           0 :         if (m == NULL)
    1493           0 :                 return;
    1494             : 
    1495           0 :         gk = mtod(m, struct gre_keepalive *);
    1496           0 :         uptime = bemtoh32(&gk->gk_uptime) - sc->sc_ka_bias;
    1497           0 :         delta = tick - uptime;
    1498           0 :         if (delta < 0)
    1499             :                 goto drop;
    1500           0 :         if (delta > hz * 10) /* magic */
    1501             :                 goto drop;
    1502             : 
    1503             :         /* avoid too much siphash work */
    1504           0 :         delta = tick - sc->sc_ka_recvtm;
    1505           0 :         if (delta > 0 && delta < (hz / 10))
    1506             :                 goto drop;
    1507             : 
    1508           0 :         SipHash24_Init(&ctx, &sc->sc_ka_key);
    1509           0 :         SipHash24_Update(&ctx, &gk->gk_uptime, sizeof(gk->gk_uptime));
    1510           0 :         SipHash24_Update(&ctx, &gk->gk_random, sizeof(gk->gk_random));
    1511           0 :         SipHash24_Final(digest, &ctx);
    1512             : 
    1513           0 :         if (memcmp(digest, gk->gk_digest, sizeof(digest)) != 0)
    1514             :                 goto drop;
    1515             : 
    1516           0 :         sc->sc_ka_recvtm = tick;
    1517             : 
    1518           0 :         switch (sc->sc_ka_state) {
    1519             :         case GRE_KA_DOWN:
    1520           0 :                 sc->sc_ka_state = GRE_KA_HOLD;
    1521           0 :                 sc->sc_ka_holdcnt = sc->sc_ka_holdmax;
    1522           0 :                 sc->sc_ka_holdmax = MIN(sc->sc_ka_holdmax * 2,
    1523             :                     16 * sc->sc_ka_count);
    1524           0 :                 break;
    1525             :         case GRE_KA_HOLD:
    1526           0 :                 if (--sc->sc_ka_holdcnt > 0)
    1527             :                         break;
    1528             : 
    1529           0 :                 sc->sc_ka_state = GRE_KA_UP;
    1530           0 :                 gre_link_state(&sc->sc_if, sc->sc_ka_state);
    1531           0 :                 break;
    1532             : 
    1533             :         case GRE_KA_UP:
    1534           0 :                 sc->sc_ka_holdmax--;
    1535           0 :                 sc->sc_ka_holdmax = MAX(sc->sc_ka_holdmax, sc->sc_ka_count);
    1536           0 :                 break;
    1537             :         }
    1538             : 
    1539           0 :         timeout_add_sec(&sc->sc_ka_hold, sc->sc_ka_timeo * sc->sc_ka_count);
    1540             : 
    1541             : drop:
    1542           0 :         m_freem(m);
    1543           0 : }
    1544             : 
    1545             : static int
    1546           0 : gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
    1547             :     struct rtentry *rt)
    1548             : {
    1549             :         struct m_tag *mtag;
    1550             :         int error = 0;
    1551             : 
    1552           0 :         if (!gre_allow) {
    1553             :                 error = EACCES;
    1554           0 :                 goto drop;
    1555             :         }
    1556             : 
    1557           0 :         if (!ISSET(ifp->if_flags, IFF_RUNNING)) {
    1558             :                 error = ENETDOWN;
    1559           0 :                 goto drop;
    1560             :         }
    1561             : 
    1562           0 :         switch (dst->sa_family) {
    1563             :         case AF_INET:
    1564             : #ifdef INET6
    1565             :         case AF_INET6:
    1566             : #endif
    1567             : #ifdef MPLS
    1568             :         case AF_MPLS:
    1569             : #endif
    1570             :                 break;
    1571             :         default:
    1572             :                 error = EAFNOSUPPORT;
    1573           0 :                 goto drop;
    1574             :         }
    1575             : 
    1576             :         /* Try to limit infinite recursion through misconfiguration. */
    1577           0 :         for (mtag = m_tag_find(m, PACKET_TAG_GRE, NULL); mtag;
    1578           0 :              mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) {
    1579           0 :                 if (memcmp((caddr_t)(mtag + 1), &ifp->if_index,
    1580           0 :                     sizeof(ifp->if_index)) == 0) {
    1581           0 :                         m_freem(m);
    1582             :                         error = EIO;
    1583           0 :                         goto end;
    1584             :                 }
    1585             :         }
    1586             : 
    1587           0 :         mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT);
    1588           0 :         if (mtag == NULL) {
    1589           0 :                 m_freem(m);
    1590             :                 error = ENOBUFS;
    1591           0 :                 goto end;
    1592             :         }
    1593           0 :         memcpy((caddr_t)(mtag + 1), &ifp->if_index, sizeof(ifp->if_index));
    1594           0 :         m_tag_prepend(m, mtag);
    1595             : 
    1596           0 :         m->m_pkthdr.ph_family = dst->sa_family;
    1597             : 
    1598           0 :         error = if_enqueue(ifp, m);
    1599             : end:
    1600           0 :         if (error)
    1601           0 :                 ifp->if_oerrors++;
    1602           0 :         return (error);
    1603             : 
    1604             : drop:
    1605           0 :         m_freem(m);
    1606           0 :         return (error);
    1607           0 : }
    1608             : 
    1609             : void
    1610           0 : gre_start(struct ifnet *ifp)
    1611             : {
    1612           0 :         struct gre_softc *sc = ifp->if_softc;
    1613             :         struct mbuf *m;
    1614             :         int af;
    1615             : #if NBPFILTER > 0
    1616             :         caddr_t if_bpf;
    1617             : #endif
    1618             : 
    1619           0 :         while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) {
    1620           0 :                 af = m->m_pkthdr.ph_family;
    1621             : 
    1622             : #if NBPFILTER > 0
    1623           0 :                 if_bpf = ifp->if_bpf;
    1624           0 :                 if (if_bpf)
    1625           0 :                         bpf_mtap_af(if_bpf, af, m, BPF_DIRECTION_OUT);
    1626             : #endif
    1627             : 
    1628           0 :                 m = gre_l3_encap(&sc->sc_tunnel, m, af);
    1629           0 :                 if (m == NULL || gre_ip_output(&sc->sc_tunnel, m) != 0) {
    1630           0 :                         ifp->if_oerrors++;
    1631           0 :                         continue;
    1632             :                 }
    1633             :         }
    1634           0 : }
    1635             : 
    1636             : void
    1637           0 : mgre_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
    1638             : {
    1639             :         struct ifnet *lo0ifp;
    1640             :         struct ifaddr *ifa, *lo0ifa;
    1641             : 
    1642           0 :         switch (req) {
    1643             :         case RTM_ADD:
    1644           0 :                 if (!ISSET(rt->rt_flags, RTF_LOCAL))
    1645             :                         break;
    1646             : 
    1647           0 :                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
    1648           0 :                         if (memcmp(rt_key(rt), ifa->ifa_addr,
    1649           0 :                             rt_key(rt)->sa_len) == 0)
    1650             :                                 break;
    1651             :                 }
    1652             : 
    1653           0 :                 if (ifa == NULL)
    1654             :                         break;
    1655             : 
    1656           0 :                 KASSERT(ifa == rt->rt_ifa);
    1657             : 
    1658           0 :                 lo0ifp = if_get(rtable_loindex(ifp->if_rdomain));
    1659           0 :                 KASSERT(lo0ifp != NULL);
    1660           0 :                 TAILQ_FOREACH(lo0ifa, &lo0ifp->if_addrlist, ifa_list) {
    1661           0 :                         if (lo0ifa->ifa_addr->sa_family ==
    1662           0 :                             ifa->ifa_addr->sa_family)
    1663             :                                 break;
    1664             :                 }
    1665           0 :                 if_put(lo0ifp);
    1666             : 
    1667           0 :                 if (lo0ifa == NULL)
    1668             :                         break;
    1669             : 
    1670           0 :                 rt->rt_flags &= ~RTF_LLINFO;
    1671           0 :                 break;
    1672             :         case RTM_DELETE:
    1673             :         case RTM_RESOLVE:
    1674             :         default:
    1675             :                 break;
    1676             :         }
    1677           0 : }
    1678             : 
    1679             : static int
    1680           0 : mgre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dest,
    1681             :     struct rtentry *rt0)
    1682             : {
    1683           0 :         struct mgre_softc *sc = ifp->if_softc;
    1684             :         struct sockaddr *gate;
    1685             :         struct rtentry *rt;
    1686             :         struct m_tag *mtag;
    1687             :         int error = 0;
    1688             :         sa_family_t af;
    1689             :         const void *addr;
    1690             : 
    1691           0 :         if (!gre_allow) {
    1692             :                 error = EACCES;
    1693           0 :                 goto drop;
    1694             :         }
    1695             : 
    1696           0 :         if (!ISSET(ifp->if_flags, IFF_RUNNING)) {
    1697             :                 error = ENETDOWN;
    1698           0 :                 goto drop;
    1699             :         }
    1700             : 
    1701           0 :         switch (dest->sa_family) {
    1702             :         case AF_INET:
    1703             : #ifdef INET6
    1704             :         case AF_INET6:
    1705             : #endif
    1706             : #ifdef MPLS
    1707             :         case AF_MPLS:
    1708             : #endif
    1709             :                 break;
    1710             :         default:
    1711             :                 error = EAFNOSUPPORT;
    1712           0 :                 goto drop;
    1713             :         }
    1714             : 
    1715           0 :         if (ISSET(m->m_flags, M_MCAST|M_BCAST)) {
    1716             :                 error = ENETUNREACH;
    1717           0 :                 goto drop;
    1718             :         }
    1719             : 
    1720           0 :         rt = rt_getll(rt0);
    1721             : 
    1722             :         /* chech rt_expire? */
    1723           0 :         if (ISSET(rt->rt_flags, RTF_REJECT)) {
    1724           0 :                 error = (rt == rt0) ? EHOSTDOWN : EHOSTUNREACH;
    1725           0 :                 goto drop;
    1726             :         }
    1727           0 :         if (!ISSET(rt->rt_flags, RTF_HOST)) {
    1728             :                 error = EHOSTUNREACH;
    1729           0 :                 goto drop;
    1730             :         }
    1731           0 :         if (ISSET(rt->rt_flags, RTF_GATEWAY)) {
    1732             :                 error = EINVAL;
    1733           0 :                 goto drop;
    1734             :         }
    1735             : 
    1736           0 :         gate = rt->rt_gateway;
    1737           0 :         af = gate->sa_family;
    1738           0 :         if (af != sc->sc_tunnel.t_af) {
    1739             :                 error = EAGAIN;
    1740           0 :                 goto drop;
    1741             :         }
    1742             :  
    1743             :         /* Try to limit infinite recursion through misconfiguration. */
    1744           0 :         for (mtag = m_tag_find(m, PACKET_TAG_GRE, NULL); mtag;
    1745           0 :              mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) {
    1746           0 :                 if (memcmp((caddr_t)(mtag + 1), &ifp->if_index,
    1747           0 :                     sizeof(ifp->if_index)) == 0) {
    1748             :                         error = EIO;
    1749           0 :                         goto drop;
    1750             :                 }
    1751             :         }
    1752             : 
    1753           0 :         mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT);
    1754           0 :         if (mtag == NULL) {
    1755             :                 error = ENOBUFS;
    1756           0 :                 goto drop;
    1757             :         }
    1758           0 :         memcpy((caddr_t)(mtag + 1), &ifp->if_index, sizeof(ifp->if_index));
    1759           0 :         m_tag_prepend(m, mtag);
    1760             : 
    1761           0 :         switch (af) {
    1762             :         case AF_INET: {
    1763           0 :                 struct sockaddr_in *sin = (struct sockaddr_in *)gate;
    1764           0 :                 addr = &sin->sin_addr;
    1765             :                 break;
    1766             :         }
    1767             : #ifdef INET6
    1768             :         case AF_INET6: {
    1769           0 :                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)gate;
    1770           0 :                 addr = &sin6->sin6_addr;
    1771             :                 break;
    1772             :         }
    1773             :  #endif
    1774             :         default:
    1775           0 :                 unhandled_af(af);
    1776             :                 /* NOTREACHED */
    1777             :         }
    1778             : 
    1779           0 :         m = gre_l3_encap_dst(&sc->sc_tunnel, addr, m, dest->sa_family);
    1780           0 :         if (m == NULL)
    1781           0 :                 return (ENOBUFS);
    1782             : 
    1783           0 :         m->m_pkthdr.ph_family = dest->sa_family;
    1784             : 
    1785           0 :         error = if_enqueue(ifp, m);
    1786           0 :         if (error)
    1787           0 :                 ifp->if_oerrors++;
    1788           0 :         return (error);
    1789             : 
    1790             : drop:
    1791           0 :         m_freem(m);
    1792           0 :         return (error);
    1793           0 : }
    1794             : 
    1795             : static void
    1796           0 : mgre_start(struct ifnet *ifp)
    1797             : {
    1798           0 :         struct mgre_softc *sc = ifp->if_softc;
    1799             :         struct mbuf *m;
    1800             : #if NBPFILTER > 0
    1801             :         caddr_t if_bpf;
    1802             : #endif
    1803             : 
    1804           0 :         while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) {
    1805             : #if NBPFILTER > 0
    1806           0 :                 if_bpf = ifp->if_bpf;
    1807           0 :                 if (if_bpf) {
    1808           0 :                         struct m_hdr mh;
    1809             :                         struct mbuf *n;
    1810           0 :                         int off;
    1811             : 
    1812           0 :                         n = m_getptr(m, ifp->if_hdrlen, &off);
    1813           0 :                         KASSERT(n != NULL);
    1814             : 
    1815           0 :                         mh.mh_flags = 0;
    1816           0 :                         mh.mh_next = n->m_next;
    1817           0 :                         mh.mh_len = n->m_len - off;
    1818           0 :                         mh.mh_data = n->m_data + off;
    1819             : 
    1820           0 :                         bpf_mtap_af(if_bpf, m->m_pkthdr.ph_family,
    1821           0 :                             (struct mbuf *)&mh, BPF_DIRECTION_OUT);
    1822           0 :                 }
    1823             : #endif
    1824             : 
    1825           0 :                 if (m == NULL || gre_ip_output(&sc->sc_tunnel, m) != 0) {
    1826           0 :                         ifp->if_oerrors++;
    1827           0 :                         continue;
    1828             :                 }
    1829             :         }
    1830           0 : }
    1831             : 
    1832             : static void
    1833           0 : egre_start(struct ifnet *ifp)
    1834             : {
    1835           0 :         struct egre_softc *sc = ifp->if_softc;
    1836             :         struct mbuf *m0, *m;
    1837             : #if NBPFILTER > 0
    1838             :         caddr_t if_bpf;
    1839             : #endif
    1840             : 
    1841           0 :         if (!gre_allow) {
    1842           0 :                 ifq_purge(&ifp->if_snd);
    1843           0 :                 return;
    1844             :         }
    1845             : 
    1846           0 :         while ((m0 = ifq_dequeue(&ifp->if_snd)) != NULL) {
    1847             : #if NBPFILTER > 0
    1848           0 :                 if_bpf = ifp->if_bpf;
    1849           0 :                 if (if_bpf)
    1850           0 :                         bpf_mtap_ether(if_bpf, m0, BPF_DIRECTION_OUT);
    1851             : #endif
    1852             : 
    1853           0 :                 m = m_gethdr(M_DONTWAIT, m0->m_type);
    1854           0 :                 if (m == NULL) {
    1855           0 :                         m_freem(m0);
    1856           0 :                         continue;
    1857             :                 }
    1858             : 
    1859           0 :                 M_MOVE_PKTHDR(m, m0);
    1860           0 :                 m->m_next = m0;
    1861             : 
    1862           0 :                 MH_ALIGN(m, 0);
    1863           0 :                 m->m_len = 0;
    1864             : 
    1865           0 :                 m = gre_encap(&sc->sc_tunnel, m, htons(ETHERTYPE_TRANSETHER),
    1866             :                     sc->sc_tunnel.t_ttl, 0);
    1867           0 :                 if (m == NULL || gre_ip_output(&sc->sc_tunnel, m) != 0) {
    1868           0 :                         ifp->if_oerrors++;
    1869           0 :                         continue;
    1870             :                 }
    1871             :         }
    1872           0 : }
    1873             : 
    1874             : static struct mbuf *
    1875           0 : gre_l3_encap_dst(const struct gre_tunnel *tunnel, const void *dst,
    1876             :     struct mbuf *m, sa_family_t af)
    1877             : {
    1878             :         uint16_t proto;
    1879             :         uint8_t ttl, tos;
    1880           0 :         int tttl = tunnel->t_ttl;
    1881             :         int ttloff;
    1882             : 
    1883           0 :         switch (af) {
    1884             :         case AF_INET: {
    1885             :                 struct ip *ip;
    1886             : 
    1887           0 :                 m = m_pullup(m, sizeof(*ip));
    1888           0 :                 if (m == NULL)
    1889           0 :                         return (NULL);
    1890             : 
    1891           0 :                 ip = mtod(m, struct ip *);
    1892           0 :                 tos = ip->ip_tos;
    1893             : 
    1894             :                 ttloff = offsetof(struct ip, ip_ttl);
    1895             :                 proto = htons(ETHERTYPE_IP);
    1896           0 :                 break;
    1897             :         }
    1898             : #ifdef INET6
    1899             :         case AF_INET6:
    1900             :                 tos = 0;
    1901             :                 ttloff = offsetof(struct ip6_hdr, ip6_hlim);
    1902             :                 proto = htons(ETHERTYPE_IPV6);
    1903           0 :                 break;
    1904             :  #endif
    1905             : #ifdef MPLS
    1906             :         case AF_MPLS:
    1907             :                 ttloff = 3;
    1908             :                 tos = 0;
    1909             :  
    1910           0 :                 if (m->m_flags & (M_BCAST | M_MCAST))
    1911           0 :                         proto = htons(ETHERTYPE_MPLS_MCAST);
    1912             :                 else
    1913             :                         proto = htons(ETHERTYPE_MPLS);
    1914             :                 break;
    1915             : #endif
    1916             :         default:
    1917           0 :                 unhandled_af(af);
    1918             :         }
    1919             :  
    1920           0 :         if (tttl == -1) {
    1921           0 :                 m = m_pullup(m, ttloff + 1);
    1922           0 :                 if (m == NULL)
    1923           0 :                         return (NULL);
    1924             :  
    1925           0 :                 ttl = *(m->m_data + ttloff);
    1926           0 :         } else
    1927           0 :                 ttl = tttl;
    1928             : 
    1929           0 :         return (gre_encap_dst(tunnel, dst, m, proto, ttl, tos));
    1930           0 : }
    1931             : 
    1932             : static struct mbuf *
    1933           0 : gre_encap_dst(const struct gre_tunnel *tunnel, const union gre_addr *dst,
    1934             :     struct mbuf *m, uint16_t proto, uint8_t ttl, uint8_t tos)
    1935             : {
    1936             :         struct gre_header *gh;
    1937             :         struct gre_h_key *gkh;
    1938             :         int hlen;
    1939             : 
    1940             :         hlen = sizeof(*gh);
    1941           0 :         if (tunnel->t_key_mask != GRE_KEY_NONE)
    1942           0 :                 hlen += sizeof(*gkh);
    1943             : 
    1944           0 :         m = m_prepend(m, hlen, M_DONTWAIT);
    1945           0 :         if (m == NULL)
    1946           0 :                 return (NULL);
    1947             : 
    1948           0 :         gh = mtod(m, struct gre_header *);
    1949           0 :         gh->gre_flags = GRE_VERS_0;
    1950           0 :         gh->gre_proto = proto;
    1951           0 :         if (tunnel->t_key_mask != GRE_KEY_NONE) {
    1952           0 :                 gh->gre_flags |= htons(GRE_KP);
    1953             : 
    1954           0 :                 gkh = (struct gre_h_key *)(gh + 1);
    1955           0 :                 gkh->gre_key = tunnel->t_key;
    1956             : 
    1957           0 :                 if (tunnel->t_key_mask == GRE_KEY_ENTROPY &&
    1958           0 :                     ISSET(m->m_pkthdr.ph_flowid, M_FLOWID_VALID)) {
    1959           0 :                         gkh->gre_key |= htonl(~GRE_KEY_ENTROPY &
    1960             :                             (m->m_pkthdr.ph_flowid & M_FLOWID_MASK));
    1961           0 :                 }
    1962             :         }
    1963             : 
    1964           0 :         return (gre_encap_dst_ip(tunnel, dst, m, ttl, tos));
    1965           0 : }
    1966             : 
    1967             : static struct mbuf *
    1968           0 : gre_encap_dst_ip(const struct gre_tunnel *tunnel, const union gre_addr *dst,
    1969             :     struct mbuf *m, uint8_t ttl, uint8_t tos)
    1970             : {
    1971           0 :         switch (tunnel->t_af) {
    1972             :         case AF_INET: {
    1973             :                 struct ip *ip;
    1974             : 
    1975           0 :                 m = m_prepend(m, sizeof(*ip), M_DONTWAIT);
    1976           0 :                 if (m == NULL)
    1977           0 :                         return (NULL);
    1978             : 
    1979           0 :                 ip = mtod(m, struct ip *);
    1980           0 :                 ip->ip_v = IPVERSION;
    1981           0 :                 ip->ip_hl = sizeof(*ip) >> 2;
    1982           0 :                 ip->ip_off = tunnel->t_df;
    1983           0 :                 ip->ip_tos = tos;
    1984           0 :                 ip->ip_len = htons(m->m_pkthdr.len);
    1985           0 :                 ip->ip_ttl = ttl;
    1986           0 :                 ip->ip_p = IPPROTO_GRE;
    1987           0 :                 ip->ip_src = tunnel->t_src4;
    1988           0 :                 ip->ip_dst = dst->in4;
    1989           0 :                 break;
    1990             :         }
    1991             : #ifdef INET6
    1992             :         case AF_INET6: {
    1993             :                 struct ip6_hdr *ip6;
    1994           0 :                 int len = m->m_pkthdr.len;
    1995             : 
    1996           0 :                 m = m_prepend(m, sizeof(*ip6), M_DONTWAIT);
    1997           0 :                 if (m == NULL)
    1998           0 :                         return (NULL);
    1999             : 
    2000           0 :                 ip6 = mtod(m, struct ip6_hdr *);
    2001           0 :                 ip6->ip6_flow = ISSET(m->m_pkthdr.ph_flowid, M_FLOWID_VALID) ?
    2002           0 :                     htonl(m->m_pkthdr.ph_flowid & M_FLOWID_MASK) : 0;
    2003           0 :                 ip6->ip6_vfc |= IPV6_VERSION;
    2004           0 :                 ip6->ip6_plen = htons(len);
    2005           0 :                 ip6->ip6_nxt = IPPROTO_GRE;
    2006           0 :                 ip6->ip6_hlim = ttl;
    2007           0 :                 ip6->ip6_src = tunnel->t_src6;
    2008           0 :                 ip6->ip6_dst = dst->in6;
    2009             : 
    2010           0 :                 if (tunnel->t_df)
    2011           0 :                         SET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT);
    2012             : 
    2013           0 :                 break;
    2014             :         }
    2015             : #endif /* INET6 */
    2016             :         default:
    2017           0 :                 panic("%s: unsupported af %d in %p", __func__, tunnel->t_af,
    2018             :                     tunnel);
    2019             :         }
    2020             : 
    2021           0 :         return (m);
    2022           0 : }
    2023             : 
    2024             : static int
    2025           0 : gre_ip_output(const struct gre_tunnel *tunnel, struct mbuf *m)
    2026             : {
    2027           0 :         m->m_flags &= ~(M_BCAST|M_MCAST);
    2028           0 :         m->m_pkthdr.ph_rtableid = tunnel->t_rtableid;
    2029             : 
    2030             : #if NPF > 0
    2031           0 :         pf_pkt_addr_changed(m);
    2032             : #endif
    2033             : 
    2034           0 :         switch (tunnel->t_af) {
    2035             :         case AF_INET:
    2036           0 :                 ip_send(m);
    2037           0 :                 break;
    2038             : #ifdef INET6
    2039             :         case AF_INET6:
    2040           0 :                 ip6_send(m);
    2041           0 :                 break;
    2042             : #endif
    2043             :         default:
    2044           0 :                 panic("%s: unsupported af %d in %p", __func__, tunnel->t_af,
    2045             :                     tunnel);
    2046             :         }
    2047             : 
    2048           0 :         return (0);
    2049             : }
    2050             : 
    2051             : static int
    2052           0 : gre_tunnel_ioctl(struct ifnet *ifp, struct gre_tunnel *tunnel,
    2053             :     u_long cmd, void *data)
    2054             : {
    2055           0 :         struct ifreq *ifr = (struct ifreq *)data;
    2056             :         int error = 0;
    2057             : 
    2058           0 :         switch(cmd) {
    2059             :         case SIOCSIFMTU:
    2060           0 :                 if (ifr->ifr_mtu < 576) {
    2061             :                         error = EINVAL;
    2062           0 :                         break;
    2063             :                 }
    2064           0 :                 ifp->if_mtu = ifr->ifr_mtu;
    2065           0 :                 break;
    2066             :         case SIOCADDMULTI:
    2067             :         case SIOCDELMULTI:
    2068             :                 break;
    2069             : 
    2070             :         case SIOCSVNETID:
    2071           0 :                 error = gre_set_vnetid(tunnel, ifr);
    2072           0 :                 break;
    2073             : 
    2074             :         case SIOCGVNETID:
    2075           0 :                 error = gre_get_vnetid(tunnel, ifr);
    2076           0 :                 break;
    2077             :         case SIOCDVNETID:
    2078           0 :                 error = gre_del_vnetid(tunnel);
    2079           0 :                 break;
    2080             : 
    2081             :         case SIOCSVNETFLOWID:
    2082           0 :                 error = gre_set_vnetflowid(tunnel, ifr);
    2083           0 :                 break;
    2084             : 
    2085             :         case SIOCGVNETFLOWID:
    2086           0 :                 error = gre_get_vnetflowid(tunnel, ifr);
    2087           0 :                 break;
    2088             : 
    2089             :         case SIOCSLIFPHYADDR:
    2090           0 :                 error = gre_set_tunnel(tunnel, (struct if_laddrreq *)data, 1);
    2091           0 :                 break;
    2092             :         case SIOCGLIFPHYADDR:
    2093           0 :                 error = gre_get_tunnel(tunnel, (struct if_laddrreq *)data);
    2094           0 :                 break;
    2095             :         case SIOCDIFPHYADDR:
    2096           0 :                 error = gre_del_tunnel(tunnel);
    2097           0 :                 break;
    2098             : 
    2099             :         case SIOCSLIFPHYRTABLE:
    2100           0 :                 if (ifr->ifr_rdomainid < 0 ||
    2101           0 :                     ifr->ifr_rdomainid > RT_TABLEID_MAX ||
    2102           0 :                     !rtable_exists(ifr->ifr_rdomainid)) {
    2103             :                         error = EINVAL;
    2104           0 :                         break;
    2105             :                 }
    2106           0 :                 tunnel->t_rtableid = ifr->ifr_rdomainid;
    2107           0 :                 break;
    2108             :         case SIOCGLIFPHYRTABLE:
    2109           0 :                 ifr->ifr_rdomainid = tunnel->t_rtableid;
    2110           0 :                 break;
    2111             : 
    2112             :         case SIOCSLIFPHYDF:
    2113             :                 /* commit */
    2114           0 :                 tunnel->t_df = ifr->ifr_df ? htons(IP_DF) : htons(0);
    2115           0 :                 break;
    2116             :         case SIOCGLIFPHYDF:
    2117           0 :                 ifr->ifr_df = tunnel->t_df ? 1 : 0;
    2118           0 :                 break;
    2119             : 
    2120             :         default:
    2121             :                 error = ENOTTY;
    2122           0 :                 break;
    2123             :         }
    2124             : 
    2125           0 :         return (error);
    2126             : }
    2127             : 
    2128             : static int
    2129           0 : gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    2130             : {
    2131           0 :         struct gre_softc *sc = ifp->if_softc;
    2132           0 :         struct ifreq *ifr = (struct ifreq *)data;
    2133           0 :         struct ifkalivereq *ikar = (struct ifkalivereq *)data;
    2134             :         int error = 0;
    2135             : 
    2136           0 :         switch(cmd) {
    2137             :         case SIOCSIFADDR:
    2138           0 :                 ifp->if_flags |= IFF_UP;
    2139             :                 /* FALLTHROUGH */
    2140             :         case SIOCSIFFLAGS:
    2141           0 :                 if (ISSET(ifp->if_flags, IFF_UP)) {
    2142           0 :                         if (!ISSET(ifp->if_flags, IFF_RUNNING))
    2143           0 :                                 error = gre_up(sc);
    2144             :                         else
    2145             :                                 error = 0;
    2146             :                 } else {
    2147           0 :                         if (ISSET(ifp->if_flags, IFF_RUNNING))
    2148           0 :                                 error = gre_down(sc);
    2149             :                 }
    2150             :                 break;
    2151             :         case SIOCSIFRDOMAIN:
    2152             :                 /* let if_rdomain do its thing */
    2153             :                 error = ENOTTY;
    2154           0 :                 break;
    2155             : 
    2156             :         case SIOCSETKALIVE:
    2157           0 :                 if (ikar->ikar_timeo < 0 || ikar->ikar_timeo > 86400 ||
    2158           0 :                     ikar->ikar_cnt < 0 || ikar->ikar_cnt > 256)
    2159           0 :                         return (EINVAL);
    2160             : 
    2161           0 :                 if (ikar->ikar_timeo == 0 || ikar->ikar_cnt == 0) {
    2162           0 :                         sc->sc_ka_count = 0;
    2163           0 :                         sc->sc_ka_timeo = 0;
    2164           0 :                         sc->sc_ka_state = GRE_KA_NONE;
    2165           0 :                 } else {
    2166           0 :                         sc->sc_ka_count = ikar->ikar_cnt;
    2167           0 :                         sc->sc_ka_timeo = ikar->ikar_timeo;
    2168           0 :                         sc->sc_ka_state = GRE_KA_DOWN;
    2169             :                 }
    2170             :                 break;
    2171             : 
    2172             :         case SIOCGETKALIVE:
    2173           0 :                 ikar->ikar_cnt = sc->sc_ka_count;
    2174           0 :                 ikar->ikar_timeo = sc->sc_ka_timeo;
    2175           0 :                 break;
    2176             : 
    2177             :         case SIOCSLIFPHYTTL:
    2178           0 :                 if (ifr->ifr_ttl != -1 &&
    2179           0 :                     (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff)) {
    2180             :                         error = EINVAL;
    2181           0 :                         break;
    2182             :                 }
    2183             : 
    2184             :                 /* commit */
    2185           0 :                 sc->sc_tunnel.t_ttl = ifr->ifr_ttl;
    2186           0 :                 break;
    2187             : 
    2188             :         case SIOCGLIFPHYTTL:
    2189           0 :                 ifr->ifr_ttl = sc->sc_tunnel.t_ttl;
    2190           0 :                 break;
    2191             : 
    2192             :         default:
    2193           0 :                 error = gre_tunnel_ioctl(ifp, &sc->sc_tunnel, cmd, data);
    2194           0 :                 break;
    2195             :         }
    2196             : 
    2197           0 :         return (error);
    2198           0 : }
    2199             : 
    2200             : static int
    2201           0 : mgre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    2202             : {
    2203           0 :         struct mgre_softc *sc = ifp->if_softc;
    2204           0 :         struct ifreq *ifr = (struct ifreq *)data;
    2205             :         int error = 0;
    2206             : 
    2207           0 :         switch(cmd) {
    2208             :         case SIOCSIFADDR:
    2209             :                 break;
    2210             :         case SIOCSIFFLAGS:
    2211           0 :                 if (ISSET(ifp->if_flags, IFF_UP)) {
    2212           0 :                         if (!ISSET(ifp->if_flags, IFF_RUNNING))
    2213           0 :                                 error = mgre_up(sc);
    2214             :                         else
    2215             :                                 error = 0;
    2216             :                 } else {
    2217           0 :                         if (ISSET(ifp->if_flags, IFF_RUNNING))
    2218           0 :                                 error = mgre_down(sc);
    2219             :                 }
    2220             :                 break;
    2221             : 
    2222             :         case SIOCSLIFPHYTTL:
    2223           0 :                 if (ifr->ifr_ttl != -1 &&
    2224           0 :                     (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff)) {
    2225             :                         error = EINVAL;
    2226           0 :                         break;
    2227             :                 }
    2228             : 
    2229             :                 /* commit */
    2230           0 :                 sc->sc_tunnel.t_ttl = ifr->ifr_ttl;
    2231           0 :                 break;
    2232             : 
    2233             :         case SIOCGLIFPHYTTL:
    2234           0 :                 ifr->ifr_ttl = sc->sc_tunnel.t_ttl;
    2235           0 :                 break;
    2236             : 
    2237             :         case SIOCSLIFPHYADDR:
    2238           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2239             :                         error = EBUSY;
    2240           0 :                         break;
    2241             :                 }
    2242           0 :                 error = mgre_set_tunnel(sc, (struct if_laddrreq *)data);
    2243           0 :                 break;
    2244             :         case SIOCGLIFPHYADDR:
    2245           0 :                 error = mgre_get_tunnel(sc, (struct if_laddrreq *)data);
    2246           0 :                 break;
    2247             : 
    2248             :         case SIOCSVNETID:
    2249             :         case SIOCDVNETID:
    2250             :         case SIOCDIFPHYADDR:
    2251             :         case SIOCSLIFPHYRTABLE:
    2252           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2253             :                         error = EBUSY;
    2254           0 :                         break;
    2255             :                 }
    2256             : 
    2257             :                 /* FALLTHROUGH */
    2258             :         default:
    2259           0 :                 error = gre_tunnel_ioctl(ifp, &sc->sc_tunnel, cmd, data);
    2260           0 :                 break;
    2261             :         }
    2262             : 
    2263           0 :         return (error);
    2264             : }
    2265             : 
    2266             : static int
    2267           0 : mgre_set_tunnel(struct mgre_softc *sc, struct if_laddrreq *req)
    2268             : {
    2269           0 :         struct gre_tunnel *tunnel = &sc->sc_tunnel;
    2270           0 :         struct sockaddr *addr = (struct sockaddr *)&req->addr;
    2271           0 :         struct sockaddr *dstaddr = (struct sockaddr *)&req->dstaddr;
    2272             :         struct sockaddr_in *addr4;
    2273             : #ifdef INET6
    2274             :         struct sockaddr_in6 *addr6;
    2275             :         int error;
    2276             : #endif
    2277             : 
    2278           0 :         if (dstaddr->sa_family != AF_UNSPEC)
    2279           0 :                 return (EINVAL);
    2280             : 
    2281             :         /* validate */
    2282           0 :         switch (addr->sa_family) {
    2283             :         case AF_INET:
    2284           0 :                 if (addr->sa_len != sizeof(*addr4))
    2285           0 :                         return (EINVAL);
    2286             : 
    2287           0 :                 addr4 = (struct sockaddr_in *)addr;
    2288           0 :                 if (in_nullhost(addr4->sin_addr) ||
    2289           0 :                     IN_MULTICAST(addr4->sin_addr.s_addr))
    2290           0 :                         return (EINVAL);
    2291             : 
    2292           0 :                 tunnel->t_src4 = addr4->sin_addr;
    2293           0 :                 tunnel->t_dst4.s_addr = INADDR_ANY;
    2294             : 
    2295           0 :                 break;
    2296             : #ifdef INET6
    2297             :         case AF_INET6:
    2298           0 :                 if (addr->sa_len != sizeof(*addr6))
    2299           0 :                         return (EINVAL);
    2300             : 
    2301           0 :                 addr6 = (struct sockaddr_in6 *)addr;
    2302           0 :                 if (IN6_IS_ADDR_UNSPECIFIED(&addr6->sin6_addr) ||
    2303           0 :                     IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr))
    2304           0 :                         return (EINVAL);
    2305             : 
    2306           0 :                 error = in6_embedscope(&tunnel->t_src6, addr6, NULL);
    2307           0 :                 if (error != 0)
    2308           0 :                         return (error);
    2309             : 
    2310           0 :                 memset(&tunnel->t_dst6, 0, sizeof(tunnel->t_dst6));
    2311             : 
    2312           0 :                 break;
    2313             : #endif
    2314             :         default:
    2315           0 :                 return (EAFNOSUPPORT);
    2316             :         }
    2317             : 
    2318             :         /* commit */
    2319           0 :         tunnel->t_af = addr->sa_family;
    2320             : 
    2321           0 :         return (0);
    2322           0 : }
    2323             : 
    2324             : static int
    2325           0 : mgre_get_tunnel(struct mgre_softc *sc, struct if_laddrreq *req)
    2326             : {
    2327           0 :         struct gre_tunnel *tunnel = &sc->sc_tunnel;
    2328           0 :         struct sockaddr *dstaddr = (struct sockaddr *)&req->dstaddr;
    2329             :         struct sockaddr_in *sin;
    2330             : #ifdef INET6
    2331             :         struct sockaddr_in6 *sin6;
    2332             : #endif
    2333             : 
    2334           0 :         switch (tunnel->t_af) {
    2335             :         case AF_UNSPEC:
    2336           0 :                 return (EADDRNOTAVAIL);
    2337             :         case AF_INET:
    2338           0 :                 sin = (struct sockaddr_in *)&req->addr;
    2339           0 :                 memset(sin, 0, sizeof(*sin));
    2340           0 :                 sin->sin_family = AF_INET;
    2341           0 :                 sin->sin_len = sizeof(*sin);
    2342           0 :                 sin->sin_addr = tunnel->t_src4;
    2343           0 :                 break;
    2344             : 
    2345             : #ifdef INET6
    2346             :         case AF_INET6:
    2347           0 :                 sin6 = (struct sockaddr_in6 *)&req->addr;
    2348           0 :                 memset(sin6, 0, sizeof(*sin6));
    2349           0 :                 sin6->sin6_family = AF_INET6;
    2350           0 :                 sin6->sin6_len = sizeof(*sin6);
    2351           0 :                 in6_recoverscope(sin6, &tunnel->t_src6);
    2352           0 :                 break;
    2353             : #endif
    2354             :         default:
    2355           0 :                 unhandled_af(tunnel->t_af);
    2356             :         }
    2357             : 
    2358           0 :         dstaddr->sa_len = 2;
    2359           0 :         dstaddr->sa_family = AF_UNSPEC;
    2360             : 
    2361           0 :         return (0);
    2362           0 : }
    2363             : 
    2364             : static int
    2365           0 : egre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    2366             : {
    2367           0 :         struct egre_softc *sc = ifp->if_softc;
    2368           0 :         struct ifreq *ifr = (struct ifreq *)data;
    2369             :         int error = 0;
    2370             : 
    2371           0 :         switch(cmd) {
    2372             :         case SIOCSIFADDR:
    2373             :                 break;
    2374             :         case SIOCSIFFLAGS:
    2375           0 :                 if (ISSET(ifp->if_flags, IFF_UP)) {
    2376           0 :                         if (!ISSET(ifp->if_flags, IFF_RUNNING))
    2377           0 :                                 error = egre_up(sc);
    2378             :                         else
    2379             :                                 error = 0;
    2380             :                 } else {
    2381           0 :                         if (ISSET(ifp->if_flags, IFF_RUNNING))
    2382           0 :                                 error = egre_down(sc);
    2383             :                 }
    2384             :                 break;
    2385             : 
    2386             :         case SIOCSLIFPHYTTL:
    2387           0 :                 if (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff) {
    2388             :                         error = EINVAL;
    2389           0 :                         break;
    2390             :                 }
    2391             : 
    2392             :                 /* commit */
    2393           0 :                 sc->sc_tunnel.t_ttl = (uint8_t)ifr->ifr_ttl;
    2394           0 :                 break;
    2395             : 
    2396             :         case SIOCGLIFPHYTTL:
    2397           0 :                 ifr->ifr_ttl = (int)sc->sc_tunnel.t_ttl;
    2398           0 :                 break;
    2399             : 
    2400             :         case SIOCSVNETID:
    2401             :         case SIOCDVNETID:
    2402             :         case SIOCSVNETFLOWID:
    2403             :         case SIOCSLIFPHYADDR:
    2404             :         case SIOCDIFPHYADDR:
    2405             :         case SIOCSLIFPHYRTABLE:
    2406           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2407             :                         error = EBUSY;
    2408           0 :                         break;
    2409             :                 }
    2410             : 
    2411             :                 /* FALLTHROUGH */
    2412             :         default:
    2413           0 :                 error = gre_tunnel_ioctl(ifp, &sc->sc_tunnel, cmd, data);
    2414           0 :                 if (error == ENOTTY)
    2415           0 :                         error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
    2416             :                 break;
    2417             :         }
    2418             : 
    2419           0 :         return (error);
    2420             : }
    2421             : 
    2422             : static int
    2423           0 : nvgre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    2424             : {
    2425           0 :         struct nvgre_softc *sc = ifp->if_softc;
    2426           0 :         struct gre_tunnel *tunnel = &sc->sc_tunnel;
    2427             : 
    2428           0 :         struct ifreq *ifr = (struct ifreq *)data;
    2429           0 :         struct if_parent *parent = (struct if_parent *)data;
    2430           0 :         struct ifbrparam *bparam = (struct ifbrparam *)data;
    2431             :         struct ifnet *ifp0;
    2432             : 
    2433             :         int error = 0;
    2434             : 
    2435           0 :         switch (cmd) {
    2436             :         case SIOCSIFADDR:
    2437             :                 break;
    2438             :         case SIOCSIFFLAGS:
    2439           0 :                 if (ISSET(ifp->if_flags, IFF_UP)) {
    2440           0 :                         if (!ISSET(ifp->if_flags, IFF_RUNNING))
    2441           0 :                                 error = nvgre_up(sc);
    2442             :                         else
    2443             :                                 error = ENETRESET;
    2444             :                 } else {
    2445           0 :                         if (ISSET(ifp->if_flags, IFF_RUNNING))
    2446           0 :                                 error = nvgre_down(sc);
    2447             :                 }
    2448             :                 break;
    2449             : 
    2450             :         case SIOCSLIFPHYADDR:
    2451           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2452             :                         error = EBUSY;
    2453           0 :                         break;
    2454             :                 }
    2455           0 :                 error = gre_set_tunnel(tunnel, (struct if_laddrreq *)data, 0);
    2456           0 :                 if (error == 0)
    2457           0 :                         nvgre_flush_map(sc);
    2458             :                 break;
    2459             :         case SIOCGLIFPHYADDR:
    2460           0 :                 error = gre_get_tunnel(tunnel, (struct if_laddrreq *)data);
    2461           0 :                 break;
    2462             :         case SIOCDIFPHYADDR:
    2463           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2464             :                         error = EBUSY;
    2465           0 :                         break;
    2466             :                 }
    2467           0 :                 error = gre_del_tunnel(tunnel);
    2468           0 :                 if (error == 0)
    2469           0 :                         nvgre_flush_map(sc);
    2470             :                 break;
    2471             : 
    2472             :         case SIOCSIFPARENT:
    2473           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2474             :                         error = EBUSY;
    2475           0 :                         break;
    2476             :                 }
    2477           0 :                 error = nvgre_set_parent(sc, parent->ifp_parent);
    2478           0 :                 if (error == 0)
    2479           0 :                         nvgre_flush_map(sc);
    2480             :                 break;
    2481             :         case SIOCGIFPARENT:
    2482           0 :                 ifp0 = if_get(sc->sc_ifp0);
    2483           0 :                 if (ifp0 == NULL)
    2484           0 :                         error = EADDRNOTAVAIL;
    2485             :                 else {
    2486           0 :                         memcpy(parent->ifp_parent, ifp0->if_xname,
    2487             :                             sizeof(parent->ifp_parent));
    2488             :                 }
    2489           0 :                 if_put(ifp0);
    2490           0 :                 break;
    2491             :         case SIOCDIFPARENT:
    2492           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2493             :                         error = EBUSY;
    2494           0 :                         break;
    2495             :                 }
    2496             :                 /* commit */
    2497           0 :                 sc->sc_ifp0 = 0;
    2498           0 :                 nvgre_flush_map(sc);
    2499           0 :                 break;
    2500             : 
    2501             :         case SIOCSVNETID:
    2502           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2503             :                         error = EBUSY;
    2504           0 :                         break;
    2505             :                 }
    2506           0 :                 if (ifr->ifr_vnetid < GRE_KEY_ENTROPY_MIN ||
    2507           0 :                     ifr->ifr_vnetid > GRE_KEY_ENTROPY_MAX) {
    2508             :                         error = EINVAL;
    2509           0 :                         break;
    2510             :                 }
    2511             : 
    2512             :                 /* commit */
    2513           0 :                 tunnel->t_key = htonl(ifr->ifr_vnetid << GRE_KEY_ENTROPY_SHIFT);
    2514           0 :                 nvgre_flush_map(sc);
    2515           0 :                 break;
    2516             :         case SIOCGVNETID:
    2517           0 :                 error = gre_get_vnetid(tunnel, ifr);
    2518           0 :                 break;
    2519             : 
    2520             :         case SIOCSLIFPHYRTABLE:
    2521           0 :                 if (ifr->ifr_rdomainid < 0 ||
    2522           0 :                     ifr->ifr_rdomainid > RT_TABLEID_MAX ||
    2523           0 :                     !rtable_exists(ifr->ifr_rdomainid)) {
    2524             :                         error = EINVAL;
    2525           0 :                         break;
    2526             :                 }
    2527           0 :                 tunnel->t_rtableid = ifr->ifr_rdomainid;
    2528           0 :                 nvgre_flush_map(sc);
    2529           0 :                 break;
    2530             :         case SIOCGLIFPHYRTABLE:
    2531           0 :                 ifr->ifr_rdomainid = tunnel->t_rtableid;
    2532           0 :                 break;
    2533             : 
    2534             :         case SIOCSLIFPHYDF:
    2535             :                 /* commit */
    2536           0 :                 tunnel->t_df = ifr->ifr_df ? htons(IP_DF) : htons(0);
    2537           0 :                 break;
    2538             :         case SIOCGLIFPHYDF:
    2539           0 :                 ifr->ifr_df = tunnel->t_df ? 1 : 0;
    2540           0 :                 break;
    2541             : 
    2542             :         case SIOCSLIFPHYTTL:
    2543           0 :                 if (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff) {
    2544             :                         error = EINVAL;
    2545           0 :                         break;
    2546             :                 }
    2547             : 
    2548             :                 /* commit */
    2549           0 :                 tunnel->t_ttl = ifr->ifr_ttl;
    2550           0 :                 break;
    2551             : 
    2552             :         case SIOCGLIFPHYTTL:
    2553           0 :                 ifr->ifr_ttl = tunnel->t_ttl;
    2554           0 :                 break;
    2555             : 
    2556             :         case SIOCBRDGSCACHE:
    2557           0 :                 if (bparam->ifbrp_csize < 1) {
    2558             :                         error = EINVAL;
    2559           0 :                         break;
    2560             :                 }
    2561             : 
    2562             :                 /* commit */
    2563           0 :                 sc->sc_ether_max = bparam->ifbrp_csize;
    2564           0 :                 break;
    2565             :         case SIOCBRDGGCACHE:
    2566           0 :                 bparam->ifbrp_csize = sc->sc_ether_max;
    2567           0 :                 break;
    2568             : 
    2569             :         case SIOCBRDGSTO:
    2570           0 :                 if (bparam->ifbrp_ctime < 0 ||
    2571           0 :                     bparam->ifbrp_ctime > INT_MAX / hz) {
    2572             :                         error = EINVAL;
    2573           0 :                         break;
    2574             :                 }
    2575           0 :                 sc->sc_ether_tmo = bparam->ifbrp_ctime * hz;
    2576           0 :                 break;
    2577             :         case SIOCBRDGGTO:
    2578           0 :                 bparam->ifbrp_ctime = sc->sc_ether_tmo / hz;
    2579           0 :                 break;
    2580             : 
    2581             :         case SIOCBRDGRTS:
    2582           0 :                 error = nvgre_rtfind(sc, (struct ifbaconf *)data);
    2583           0 :                 break;
    2584             :         case SIOCBRDGFLUSH:
    2585           0 :                 nvgre_flush_map(sc);
    2586           0 :                 break;
    2587             : 
    2588             :         default:
    2589           0 :                 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
    2590           0 :                 break;
    2591             :         }
    2592             : 
    2593           0 :         if (error == ENETRESET) {
    2594             :                 /* no hardware to program */
    2595             :                 error = 0;
    2596           0 :         }
    2597             : 
    2598           0 :         return (error);
    2599             : }
    2600             : 
    2601             : static int
    2602           0 : eoip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    2603             : {
    2604           0 :         struct eoip_softc *sc = ifp->if_softc;
    2605           0 :         struct ifreq *ifr = (struct ifreq *)data;
    2606           0 :         struct ifkalivereq *ikar = (struct ifkalivereq *)data;
    2607             :         int error = 0;
    2608             : 
    2609           0 :         switch(cmd) {
    2610             :         case SIOCSIFADDR:
    2611             :                 break;
    2612             :         case SIOCSIFFLAGS:
    2613           0 :                 if (ISSET(ifp->if_flags, IFF_UP)) {
    2614           0 :                         if (!ISSET(ifp->if_flags, IFF_RUNNING))
    2615           0 :                                 error = eoip_up(sc);
    2616             :                         else
    2617             :                                 error = 0;
    2618             :                 } else {
    2619           0 :                         if (ISSET(ifp->if_flags, IFF_RUNNING))
    2620           0 :                                 error = eoip_down(sc);
    2621             :                 }
    2622             :                 break;
    2623             : 
    2624             :         case SIOCSETKALIVE:
    2625           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2626             :                         error = EBUSY;
    2627           0 :                         break;
    2628             :                 }
    2629             : 
    2630           0 :                 if (ikar->ikar_timeo < 0 || ikar->ikar_timeo > 86400 ||
    2631           0 :                     ikar->ikar_cnt < 0 || ikar->ikar_cnt > 256)
    2632           0 :                         return (EINVAL);
    2633             : 
    2634           0 :                 if (ikar->ikar_timeo == 0 || ikar->ikar_cnt == 0) {
    2635           0 :                         sc->sc_ka_count = 0;
    2636           0 :                         sc->sc_ka_timeo = 0;
    2637           0 :                         sc->sc_ka_state = GRE_KA_NONE;
    2638           0 :                 } else {
    2639           0 :                         sc->sc_ka_count = ikar->ikar_cnt;
    2640           0 :                         sc->sc_ka_timeo = ikar->ikar_timeo;
    2641           0 :                         sc->sc_ka_state = GRE_KA_DOWN;
    2642             :                 }
    2643             :                 break;
    2644             : 
    2645             :         case SIOCGETKALIVE:
    2646           0 :                 ikar->ikar_cnt = sc->sc_ka_count;
    2647           0 :                 ikar->ikar_timeo = sc->sc_ka_timeo;
    2648           0 :                 break;
    2649             : 
    2650             :         case SIOCSVNETID:
    2651           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2652             :                         error = EBUSY;
    2653           0 :                         break;
    2654             :                 }
    2655           0 :                 if (ifr->ifr_vnetid < 0 || ifr->ifr_vnetid > 0xffff)
    2656           0 :                         return (EINVAL);
    2657             : 
    2658           0 :                 sc->sc_tunnel.t_key = htole16(ifr->ifr_vnetid); /* for cmp */
    2659           0 :                 sc->sc_tunnel_id = htole16(ifr->ifr_vnetid);
    2660           0 :                 break;
    2661             : 
    2662             :         case SIOCGVNETID:
    2663           0 :                 ifr->ifr_vnetid = letoh16(sc->sc_tunnel_id);
    2664           0 :                 break;
    2665             : 
    2666             :         case SIOCSLIFPHYADDR:
    2667           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2668             :                         error = EBUSY;
    2669           0 :                         break;
    2670             :                 }
    2671             : 
    2672           0 :                 error = gre_set_tunnel(&sc->sc_tunnel,
    2673           0 :                     (struct if_laddrreq *)data, 1);
    2674           0 :                 break;
    2675             :         case SIOCGLIFPHYADDR:
    2676           0 :                 error = gre_get_tunnel(&sc->sc_tunnel,
    2677           0 :                     (struct if_laddrreq *)data);
    2678           0 :                 break;
    2679             :         case SIOCDIFPHYADDR:
    2680           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2681             :                         error = EBUSY;
    2682           0 :                         break;
    2683             :                 }
    2684             : 
    2685           0 :                 error = gre_del_tunnel(&sc->sc_tunnel);
    2686           0 :                 break;
    2687             : 
    2688             :         case SIOCSLIFPHYRTABLE:
    2689           0 :                 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2690             :                         error = EBUSY;
    2691           0 :                         break;
    2692             :                 }
    2693             : 
    2694           0 :                 if (ifr->ifr_rdomainid < 0 ||
    2695           0 :                     ifr->ifr_rdomainid > RT_TABLEID_MAX ||
    2696           0 :                     !rtable_exists(ifr->ifr_rdomainid)) {
    2697             :                         error = EINVAL;
    2698           0 :                         break;
    2699             :                 }
    2700           0 :                 sc->sc_tunnel.t_rtableid = ifr->ifr_rdomainid;
    2701           0 :                 break;
    2702             :         case SIOCGLIFPHYRTABLE:
    2703           0 :                 ifr->ifr_rdomainid = sc->sc_tunnel.t_rtableid;
    2704           0 :                 break;
    2705             : 
    2706             :         case SIOCSLIFPHYTTL:
    2707           0 :                 if (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff) {
    2708             :                         error = EINVAL;
    2709           0 :                         break;
    2710             :                 }
    2711             : 
    2712             :                 /* commit */
    2713           0 :                 sc->sc_tunnel.t_ttl = (uint8_t)ifr->ifr_ttl;
    2714           0 :                 break;
    2715             :         case SIOCGLIFPHYTTL:
    2716           0 :                 ifr->ifr_ttl = (int)sc->sc_tunnel.t_ttl;
    2717           0 :                 break;
    2718             : 
    2719             :         case SIOCSLIFPHYDF:
    2720             :                 /* commit */
    2721           0 :                 sc->sc_tunnel.t_df = ifr->ifr_df ? htons(IP_DF) : htons(0);
    2722           0 :                 break;
    2723             :         case SIOCGLIFPHYDF:
    2724           0 :                 ifr->ifr_df = sc->sc_tunnel.t_df ? 1 : 0;
    2725           0 :                 break;
    2726             : 
    2727             :         default:
    2728           0 :                 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
    2729           0 :                 break;
    2730             :         }
    2731             : 
    2732           0 :         return (error);
    2733           0 : }
    2734             : 
    2735             : static int
    2736           0 : gre_up(struct gre_softc *sc)
    2737             : {
    2738           0 :         NET_ASSERT_LOCKED();
    2739           0 :         SET(sc->sc_if.if_flags, IFF_RUNNING);
    2740             : 
    2741           0 :         if (sc->sc_ka_state != GRE_KA_NONE) {
    2742           0 :                 arc4random_buf(&sc->sc_ka_key, sizeof(sc->sc_ka_key));
    2743           0 :                 sc->sc_ka_bias = arc4random();
    2744             : 
    2745           0 :                 sc->sc_ka_recvtm = ticks - hz;
    2746           0 :                 sc->sc_ka_holdmax = sc->sc_ka_count;
    2747             : 
    2748           0 :                 gre_keepalive_send(sc);
    2749           0 :         }
    2750             : 
    2751           0 :         return (0);
    2752             : }
    2753             : 
    2754             : static int
    2755           0 : gre_down(struct gre_softc *sc)
    2756             : {
    2757           0 :         NET_ASSERT_LOCKED();
    2758           0 :         CLR(sc->sc_if.if_flags, IFF_RUNNING);
    2759             : 
    2760           0 :         if (sc->sc_ka_state != GRE_KA_NONE) {
    2761           0 :                 if (!timeout_del(&sc->sc_ka_hold))
    2762           0 :                         timeout_barrier(&sc->sc_ka_hold);
    2763           0 :                 if (!timeout_del(&sc->sc_ka_send))
    2764           0 :                         timeout_barrier(&sc->sc_ka_send);
    2765             : 
    2766           0 :                 sc->sc_ka_state = GRE_KA_DOWN;
    2767           0 :                 gre_link_state(&sc->sc_if, sc->sc_ka_state);
    2768           0 :         }
    2769             : 
    2770           0 :         return (0);
    2771             : }
    2772             : 
    2773             : static void
    2774           0 : gre_link_state(struct ifnet *ifp, unsigned int state)
    2775             : {
    2776             :         int link_state = LINK_STATE_UNKNOWN;
    2777             : 
    2778           0 :         if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    2779           0 :                 switch (state) {
    2780             :                 case GRE_KA_NONE:
    2781             :                         /* maybe up? or down? it's unknown, really */
    2782             :                         break;
    2783             :                 case GRE_KA_UP:
    2784             :                         link_state = LINK_STATE_UP;
    2785           0 :                         break;
    2786             :                 default:
    2787             :                         link_state = LINK_STATE_KALIVE_DOWN;
    2788           0 :                         break;
    2789             :                 }
    2790             :         }
    2791             : 
    2792           0 :         if (ifp->if_link_state != link_state) {
    2793           0 :                 ifp->if_link_state = link_state;
    2794           0 :                 if_link_state_change(ifp);
    2795           0 :         }
    2796           0 : }
    2797             : 
    2798             : static void
    2799           0 : gre_keepalive_send(void *arg)
    2800             : {
    2801           0 :         struct gre_tunnel t;
    2802           0 :         struct gre_softc *sc = arg;
    2803             :         struct mbuf *m;
    2804             :         struct gre_keepalive *gk;
    2805           0 :         SIPHASH_CTX ctx;
    2806             :         int linkhdr, len;
    2807             :         uint16_t proto;
    2808             :         uint8_t ttl;
    2809             : 
    2810           0 :         if (!ISSET(sc->sc_if.if_flags, IFF_RUNNING) ||
    2811           0 :             sc->sc_ka_state == GRE_KA_NONE ||
    2812           0 :             sc->sc_tunnel.t_rtableid != sc->sc_if.if_rdomain)
    2813           0 :                 return;
    2814             : 
    2815             :         /* this is really conservative */
    2816             : #ifdef INET6
    2817           0 :         linkhdr = max_linkhdr + MAX(sizeof(struct ip), sizeof(struct ip6_hdr)) +
    2818           0 :             sizeof(struct gre_header) + sizeof(struct gre_h_key);
    2819             : #else
    2820             :         linkhdr = max_linkhdr + sizeof(struct ip) +
    2821             :             sizeof(struct gre_header) + sizeof(struct gre_h_key);
    2822             : #endif
    2823           0 :         len = linkhdr + sizeof(*gk);
    2824             : 
    2825           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
    2826           0 :         if (m == NULL)
    2827           0 :                 return;
    2828             : 
    2829           0 :         if (len > MHLEN) {
    2830           0 :                 MCLGETI(m, M_DONTWAIT, NULL, len);
    2831           0 :                 if (!ISSET(m->m_flags, M_EXT)) {
    2832           0 :                         m_freem(m);
    2833           0 :                         return;
    2834             :                 }
    2835             :         }
    2836             : 
    2837           0 :         m->m_pkthdr.len = m->m_len = len;
    2838           0 :         m_adj(m, linkhdr);
    2839             : 
    2840             :         /*
    2841             :          * build the inside packet
    2842             :          */
    2843           0 :         gk = mtod(m, struct gre_keepalive *);
    2844           0 :         htobem32(&gk->gk_uptime, sc->sc_ka_bias + ticks);
    2845           0 :         htobem32(&gk->gk_random, arc4random());
    2846             : 
    2847           0 :         SipHash24_Init(&ctx, &sc->sc_ka_key);
    2848           0 :         SipHash24_Update(&ctx, &gk->gk_uptime, sizeof(gk->gk_uptime));
    2849           0 :         SipHash24_Update(&ctx, &gk->gk_random, sizeof(gk->gk_random));
    2850           0 :         SipHash24_Final(gk->gk_digest, &ctx);
    2851             : 
    2852           0 :         ttl = sc->sc_tunnel.t_ttl == -1 ? ip_defttl : sc->sc_tunnel.t_ttl;
    2853             : 
    2854           0 :         t.t_af = sc->sc_tunnel.t_af;
    2855           0 :         t.t_df = sc->sc_tunnel.t_df;
    2856           0 :         t.t_src = sc->sc_tunnel.t_dst;
    2857           0 :         t.t_dst = sc->sc_tunnel.t_src;
    2858           0 :         t.t_key = sc->sc_tunnel.t_key;
    2859           0 :         t.t_key_mask = sc->sc_tunnel.t_key_mask;
    2860             : 
    2861           0 :         m = gre_encap(&t, m, htons(0), ttl, IPTOS_PREC_INTERNETCONTROL);
    2862           0 :         if (m == NULL)
    2863           0 :                 return;
    2864             : 
    2865           0 :         switch (sc->sc_tunnel.t_af) {
    2866             :         case AF_INET: {
    2867             :                 struct ip *ip;
    2868             : 
    2869           0 :                 ip = mtod(m, struct ip *);
    2870           0 :                 ip->ip_id = htons(ip_randomid());
    2871           0 :                 ip->ip_sum = 0;
    2872           0 :                 ip->ip_sum = in_cksum(m, sizeof(*ip));
    2873             : 
    2874             :                 proto = htons(ETHERTYPE_IP);
    2875             :                 break;
    2876             :         }
    2877             : #ifdef INET6
    2878             :         case AF_INET6:
    2879             :                 proto = htons(ETHERTYPE_IPV6);
    2880           0 :                 break;
    2881             : #endif
    2882             :         }
    2883             : 
    2884             :         /*
    2885             :          * put it in the tunnel
    2886             :          */
    2887           0 :         m = gre_encap(&sc->sc_tunnel, m, proto, ttl,
    2888             :             IPTOS_PREC_INTERNETCONTROL);
    2889           0 :         if (m == NULL)
    2890           0 :                 return;
    2891             : 
    2892           0 :         gre_ip_output(&sc->sc_tunnel, m);
    2893             : 
    2894           0 :         timeout_add_sec(&sc->sc_ka_send, sc->sc_ka_timeo);
    2895           0 : }
    2896             : 
    2897             : static void
    2898           0 : gre_keepalive_hold(void *arg)
    2899             : {
    2900           0 :         struct gre_softc *sc = arg;
    2901           0 :         struct ifnet *ifp = &sc->sc_if;
    2902             : 
    2903           0 :         if (!ISSET(ifp->if_flags, IFF_RUNNING) ||
    2904           0 :             sc->sc_ka_state == GRE_KA_NONE)
    2905           0 :                 return;
    2906             : 
    2907           0 :         NET_LOCK();
    2908           0 :         sc->sc_ka_state = GRE_KA_DOWN;
    2909           0 :         gre_link_state(ifp, sc->sc_ka_state);
    2910           0 :         NET_UNLOCK();
    2911           0 : }
    2912             : 
    2913             : static int
    2914           0 : gre_set_tunnel(struct gre_tunnel *tunnel, struct if_laddrreq *req, int ucast)
    2915             : {
    2916           0 :         struct sockaddr *src = (struct sockaddr *)&req->addr;
    2917           0 :         struct sockaddr *dst = (struct sockaddr *)&req->dstaddr;
    2918             :         struct sockaddr_in *src4, *dst4;
    2919             : #ifdef INET6
    2920             :         struct sockaddr_in6 *src6, *dst6;
    2921             :         int error;
    2922             : #endif
    2923             : 
    2924             :         /* sa_family and sa_len must be equal */
    2925           0 :         if (src->sa_family != dst->sa_family || src->sa_len != dst->sa_len)
    2926           0 :                 return (EINVAL);
    2927             : 
    2928             :         /* validate */
    2929           0 :         switch (dst->sa_family) {
    2930             :         case AF_INET:
    2931           0 :                 if (dst->sa_len != sizeof(*dst4))
    2932           0 :                         return (EINVAL);
    2933             : 
    2934           0 :                 src4 = (struct sockaddr_in *)src;
    2935           0 :                 if (in_nullhost(src4->sin_addr) ||
    2936           0 :                     IN_MULTICAST(src4->sin_addr.s_addr))
    2937           0 :                         return (EINVAL);
    2938             : 
    2939           0 :                 dst4 = (struct sockaddr_in *)dst;
    2940           0 :                 if (in_nullhost(dst4->sin_addr) ||
    2941           0 :                     (IN_MULTICAST(dst4->sin_addr.s_addr) != !ucast))
    2942           0 :                         return (EINVAL);
    2943             : 
    2944           0 :                 tunnel->t_src4 = src4->sin_addr;
    2945           0 :                 tunnel->t_dst4 = dst4->sin_addr;
    2946             : 
    2947           0 :                 break;
    2948             : #ifdef INET6
    2949             :         case AF_INET6:
    2950           0 :                 if (dst->sa_len != sizeof(*dst6))
    2951           0 :                         return (EINVAL);
    2952             : 
    2953           0 :                 src6 = (struct sockaddr_in6 *)src;
    2954           0 :                 if (IN6_IS_ADDR_UNSPECIFIED(&src6->sin6_addr) ||
    2955           0 :                     IN6_IS_ADDR_MULTICAST(&src6->sin6_addr))
    2956           0 :                         return (EINVAL);
    2957             : 
    2958           0 :                 dst6 = (struct sockaddr_in6 *)dst;
    2959           0 :                 if (IN6_IS_ADDR_UNSPECIFIED(&dst6->sin6_addr) ||
    2960           0 :                     IN6_IS_ADDR_MULTICAST(&dst6->sin6_addr) != !ucast)
    2961           0 :                         return (EINVAL);
    2962             : 
    2963           0 :                 if (src6->sin6_scope_id != dst6->sin6_scope_id)
    2964           0 :                         return (EINVAL);
    2965             : 
    2966           0 :                 error = in6_embedscope(&tunnel->t_src6, src6, NULL);
    2967           0 :                 if (error != 0)
    2968           0 :                         return (error);
    2969             : 
    2970           0 :                 error = in6_embedscope(&tunnel->t_dst6, dst6, NULL);
    2971           0 :                 if (error != 0)
    2972           0 :                         return (error);
    2973             : 
    2974             :                 break;
    2975             : #endif
    2976             :         default:
    2977           0 :                 return (EAFNOSUPPORT);
    2978             :         }
    2979             : 
    2980             :         /* commit */
    2981           0 :         tunnel->t_af = dst->sa_family;
    2982             : 
    2983           0 :         return (0);
    2984           0 : }
    2985             : 
    2986             : static int
    2987           0 : gre_get_tunnel(struct gre_tunnel *tunnel, struct if_laddrreq *req)
    2988             : {
    2989           0 :         struct sockaddr *src = (struct sockaddr *)&req->addr;
    2990           0 :         struct sockaddr *dst = (struct sockaddr *)&req->dstaddr;
    2991             :         struct sockaddr_in *sin;
    2992             : #ifdef INET6 /* ifconfig already embeds the scopeid */
    2993             :         struct sockaddr_in6 *sin6;
    2994             : #endif
    2995             : 
    2996           0 :         switch (tunnel->t_af) {
    2997             :         case AF_UNSPEC:
    2998           0 :                 return (EADDRNOTAVAIL);
    2999             :         case AF_INET:
    3000           0 :                 sin = (struct sockaddr_in *)src;
    3001           0 :                 memset(sin, 0, sizeof(*sin));
    3002           0 :                 sin->sin_family = AF_INET;
    3003           0 :                 sin->sin_len = sizeof(*sin);
    3004           0 :                 sin->sin_addr = tunnel->t_src4;
    3005             : 
    3006           0 :                 sin = (struct sockaddr_in *)dst;
    3007           0 :                 memset(sin, 0, sizeof(*sin));
    3008           0 :                 sin->sin_family = AF_INET;
    3009           0 :                 sin->sin_len = sizeof(*sin);
    3010           0 :                 sin->sin_addr = tunnel->t_dst4;
    3011             : 
    3012           0 :                 break;
    3013             : 
    3014             : #ifdef INET6
    3015             :         case AF_INET6:
    3016           0 :                 sin6 = (struct sockaddr_in6 *)src;
    3017           0 :                 memset(sin6, 0, sizeof(*sin6));
    3018           0 :                 sin6->sin6_family = AF_INET6;
    3019           0 :                 sin6->sin6_len = sizeof(*sin6);
    3020           0 :                 in6_recoverscope(sin6, &tunnel->t_src6);
    3021             : 
    3022           0 :                 sin6 = (struct sockaddr_in6 *)dst;
    3023           0 :                 memset(sin6, 0, sizeof(*sin6));
    3024           0 :                 sin6->sin6_family = AF_INET6;
    3025           0 :                 sin6->sin6_len = sizeof(*sin6);
    3026           0 :                 in6_recoverscope(sin6, &tunnel->t_dst6);
    3027             : 
    3028           0 :                 break;
    3029             : #endif
    3030             :         default:
    3031           0 :                 return (EAFNOSUPPORT);
    3032             :         }
    3033             : 
    3034           0 :         return (0);
    3035           0 : }
    3036             : 
    3037             : static int
    3038           0 : gre_del_tunnel(struct gre_tunnel *tunnel)
    3039             : {
    3040             :         /* commit */
    3041           0 :         tunnel->t_af = AF_UNSPEC;
    3042             : 
    3043           0 :         return (0);
    3044             : }
    3045             : 
    3046             : static int
    3047           0 : gre_set_vnetid(struct gre_tunnel *tunnel, struct ifreq *ifr)
    3048             : {
    3049             :         uint32_t key;
    3050             :         uint32_t min = GRE_KEY_MIN;
    3051             :         uint32_t max = GRE_KEY_MAX;
    3052             :         unsigned int shift = GRE_KEY_SHIFT;
    3053             :         uint32_t mask = GRE_KEY_MASK;
    3054             : 
    3055           0 :         if (tunnel->t_key_mask == GRE_KEY_ENTROPY) {
    3056             :                 min = GRE_KEY_ENTROPY_MIN;
    3057             :                 max = GRE_KEY_ENTROPY_MAX;
    3058             :                 shift = GRE_KEY_ENTROPY_SHIFT;
    3059             :                 mask = GRE_KEY_ENTROPY;
    3060           0 :         }
    3061             : 
    3062           0 :         if (ifr->ifr_vnetid < min || ifr->ifr_vnetid > max)
    3063           0 :                 return (EINVAL);
    3064             : 
    3065           0 :         key = htonl(ifr->ifr_vnetid << shift);
    3066             : 
    3067             :         /* commit */
    3068           0 :         tunnel->t_key_mask = mask;
    3069           0 :         tunnel->t_key = key;
    3070             : 
    3071           0 :         return (0);
    3072           0 : }
    3073             : 
    3074             : static int
    3075           0 : gre_get_vnetid(struct gre_tunnel *tunnel, struct ifreq *ifr)
    3076             : {
    3077             :         int shift;
    3078             : 
    3079           0 :         switch (tunnel->t_key_mask) {
    3080             :         case GRE_KEY_NONE:
    3081           0 :                 return (EADDRNOTAVAIL);
    3082             :         case GRE_KEY_ENTROPY:
    3083             :                 shift = GRE_KEY_ENTROPY_SHIFT;
    3084           0 :                 break;
    3085             :         case GRE_KEY_MASK:
    3086             :                 shift = GRE_KEY_SHIFT;
    3087           0 :                 break;
    3088             :         }
    3089             : 
    3090           0 :         ifr->ifr_vnetid = ntohl(tunnel->t_key) >> shift;
    3091             : 
    3092           0 :         return (0);
    3093           0 : }
    3094             : 
    3095             : static int
    3096           0 : gre_del_vnetid(struct gre_tunnel *tunnel)
    3097             : {
    3098           0 :         tunnel->t_key_mask = GRE_KEY_NONE;
    3099             : 
    3100           0 :         return (0);
    3101             : }
    3102             : 
    3103             : static int
    3104           0 : gre_set_vnetflowid(struct gre_tunnel *tunnel, struct ifreq *ifr)
    3105             : {
    3106             :         uint32_t mask, key;
    3107             : 
    3108           0 :         if (tunnel->t_key_mask == GRE_KEY_NONE)
    3109           0 :                 return (EADDRNOTAVAIL);
    3110             : 
    3111           0 :         mask = ifr->ifr_vnetid ? GRE_KEY_ENTROPY : GRE_KEY_MASK;
    3112           0 :         if (tunnel->t_key_mask == mask) {
    3113             :                 /* nop */
    3114           0 :                 return (0);
    3115             :         }
    3116             : 
    3117           0 :         key = ntohl(tunnel->t_key);
    3118           0 :         if (mask == GRE_KEY_ENTROPY) {
    3119           0 :                 if (key > GRE_KEY_ENTROPY_MAX)
    3120           0 :                         return (ERANGE);
    3121             : 
    3122           0 :                 key = htonl(key << GRE_KEY_ENTROPY_SHIFT);
    3123           0 :         } else
    3124           0 :                 key = htonl(key >> GRE_KEY_ENTROPY_SHIFT);
    3125             : 
    3126             :         /* commit */
    3127           0 :         tunnel->t_key_mask = mask;
    3128           0 :         tunnel->t_key = key;
    3129             : 
    3130           0 :         return (0);
    3131           0 : }
    3132             : 
    3133             : static int
    3134           0 : gre_get_vnetflowid(struct gre_tunnel *tunnel, struct ifreq *ifr)
    3135             : {
    3136           0 :         if (tunnel->t_key_mask == GRE_KEY_NONE)
    3137           0 :                 return (EADDRNOTAVAIL);
    3138             : 
    3139           0 :         ifr->ifr_vnetid = tunnel->t_key_mask == GRE_KEY_ENTROPY;
    3140             : 
    3141           0 :         return (0);
    3142           0 : }
    3143             : 
    3144             : static int
    3145           0 : mgre_up(struct mgre_softc *sc)
    3146             : {
    3147             :         unsigned int hlen;
    3148             : 
    3149           0 :         switch (sc->sc_tunnel.t_af) {
    3150             :         case AF_UNSPEC:
    3151           0 :                 return (EDESTADDRREQ);
    3152             :         case AF_INET:
    3153             :                 hlen = sizeof(struct ip);
    3154           0 :                 break;
    3155             : #ifdef INET6
    3156             :         case AF_INET6:
    3157             :                 hlen = sizeof(struct ip6_hdr);
    3158           0 :                 break;
    3159             : #endif /* INET6 */
    3160             :         }
    3161             : 
    3162           0 :         hlen += sizeof(struct gre_header);
    3163           0 :         if (sc->sc_tunnel.t_key_mask != GRE_KEY_NONE)
    3164           0 :                 hlen += sizeof(struct gre_h_key);
    3165             : 
    3166           0 :         NET_ASSERT_LOCKED();
    3167             : 
    3168           0 :         if (RBT_INSERT(mgre_tree, &mgre_tree, sc) != NULL)
    3169           0 :                 return (EADDRINUSE);
    3170             : 
    3171           0 :         sc->sc_if.if_hdrlen = hlen;
    3172           0 :         SET(sc->sc_if.if_flags, IFF_RUNNING);
    3173             : 
    3174           0 :         return (0);
    3175           0 : }
    3176             : 
    3177             : static int
    3178           0 : mgre_down(struct mgre_softc *sc)
    3179             : {
    3180           0 :         NET_ASSERT_LOCKED();
    3181             : 
    3182           0 :         CLR(sc->sc_if.if_flags, IFF_RUNNING);
    3183           0 :         sc->sc_if.if_hdrlen = GRE_HDRLEN; /* symmetry */
    3184             : 
    3185           0 :         RBT_REMOVE(mgre_tree, &mgre_tree, sc);
    3186             : 
    3187             :         /* barrier? */
    3188             : 
    3189           0 :         return (0);
    3190             : }
    3191             : 
    3192             : static int
    3193           0 : egre_up(struct egre_softc *sc)
    3194             : {
    3195           0 :         if (sc->sc_tunnel.t_af == AF_UNSPEC)
    3196           0 :                 return (EDESTADDRREQ);
    3197             : 
    3198           0 :         NET_ASSERT_LOCKED();
    3199             : 
    3200           0 :         if (RBT_INSERT(egre_tree, &egre_tree, sc) != NULL)
    3201           0 :                 return (EADDRINUSE);
    3202             : 
    3203           0 :         SET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING);
    3204             : 
    3205           0 :         return (0);
    3206           0 : }
    3207             : 
    3208             : static int
    3209           0 : egre_down(struct egre_softc *sc)
    3210             : {
    3211           0 :         NET_ASSERT_LOCKED();
    3212             : 
    3213           0 :         CLR(sc->sc_ac.ac_if.if_flags, IFF_RUNNING);
    3214             : 
    3215           0 :         RBT_REMOVE(egre_tree, &egre_tree, sc);
    3216             : 
    3217             :         /* barrier? */
    3218             : 
    3219           0 :         return (0);
    3220             : }
    3221             : 
    3222             : static int
    3223           0 : egre_media_change(struct ifnet *ifp)
    3224             : {
    3225           0 :         return (ENOTTY);
    3226             : }
    3227             : 
    3228             : static void
    3229           0 : egre_media_status(struct ifnet *ifp, struct ifmediareq *imr)
    3230             : {
    3231           0 :         imr->ifm_active = IFM_ETHER | IFM_AUTO;
    3232           0 :         imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
    3233           0 : }
    3234             : 
    3235             : static int
    3236           0 : nvgre_up(struct nvgre_softc *sc)
    3237             : {
    3238           0 :         struct gre_tunnel *tunnel = &sc->sc_tunnel;
    3239             :         struct ifnet *ifp0;
    3240             :         void *inm;
    3241           0 :         int error;
    3242             : 
    3243           0 :         if (tunnel->t_af == AF_UNSPEC)
    3244           0 :                 return (EDESTADDRREQ);
    3245             : 
    3246           0 :         ifp0 = if_get(sc->sc_ifp0);
    3247           0 :         if (ifp0 == NULL)
    3248           0 :                 return (ENXIO);
    3249           0 :         if (!ISSET(ifp0->if_flags, IFF_MULTICAST)) {
    3250           0 :                 error = ENODEV;
    3251           0 :                 goto put;
    3252             :         }
    3253             : 
    3254           0 :         NET_ASSERT_LOCKED();
    3255             : 
    3256           0 :         if (RBT_INSERT(nvgre_mcast_tree, &nvgre_mcast_tree, sc) != NULL) {
    3257           0 :                 error = EADDRINUSE;
    3258           0 :                 goto put;
    3259             :         }
    3260           0 :         if (RBT_INSERT(nvgre_ucast_tree, &nvgre_ucast_tree, sc) != NULL) {
    3261           0 :                 error = EADDRINUSE;
    3262           0 :                 goto remove_mcast;
    3263             :         }
    3264             : 
    3265           0 :         switch (tunnel->t_af) {
    3266             :         case AF_INET:
    3267           0 :                 inm = in_addmulti(&tunnel->t_dst4, ifp0);
    3268           0 :                 if (inm == NULL) {
    3269           0 :                         error = ECONNABORTED;
    3270           0 :                         goto remove_ucast;
    3271             :                 }
    3272             :                 break;
    3273             : #ifdef INET6
    3274             :         case AF_INET6:
    3275           0 :                 inm = in6_addmulti(&tunnel->t_dst6, ifp0, &error);
    3276           0 :                 if (inm == NULL) {
    3277             :                         /* error is already set */
    3278             :                         goto remove_ucast;
    3279             :                 }
    3280             :                 break;
    3281             : #endif /* INET6 */
    3282             :         default:
    3283           0 :                 unhandled_af(tunnel->t_af);
    3284             :         }
    3285             : 
    3286           0 :         sc->sc_lhcookie = hook_establish(ifp0->if_linkstatehooks, 0,
    3287           0 :             nvgre_link_change, sc);
    3288           0 :         if (sc->sc_lhcookie == NULL) {
    3289           0 :                 error = ENOMEM;
    3290           0 :                 goto delmulti;
    3291             :         }
    3292             : 
    3293           0 :         sc->sc_dhcookie = hook_establish(ifp0->if_detachhooks, 0,
    3294             :             nvgre_detach, sc);
    3295           0 :         if (sc->sc_dhcookie == NULL) {
    3296           0 :                 error = ENOMEM;
    3297             :                 goto dislh;
    3298             :         }
    3299             : 
    3300           0 :         if_put(ifp0);
    3301             : 
    3302           0 :         sc->sc_inm = inm;
    3303           0 :         SET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING);
    3304             : 
    3305           0 :         timeout_add_sec(&sc->sc_ether_age, NVGRE_AGE_TMO);
    3306             : 
    3307           0 :         return (0);
    3308             : 
    3309             : dislh:
    3310           0 :         hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lhcookie);
    3311             : delmulti:
    3312           0 :         switch (tunnel->t_af) {
    3313             :         case AF_INET:
    3314           0 :                 in_delmulti(inm);
    3315           0 :                 break;
    3316             : #ifdef INET6
    3317             :         case AF_INET6:
    3318           0 :                 in6_delmulti(inm);
    3319           0 :                 break;
    3320             : #endif
    3321             :         }
    3322             : remove_ucast:
    3323           0 :         RBT_REMOVE(nvgre_ucast_tree, &nvgre_ucast_tree, sc);
    3324             : remove_mcast:
    3325           0 :         RBT_REMOVE(nvgre_mcast_tree, &nvgre_mcast_tree, sc);
    3326             : put:
    3327           0 :         if_put(ifp0);
    3328           0 :         return (error);
    3329           0 : }
    3330             : 
    3331             : static int
    3332           0 : nvgre_down(struct nvgre_softc *sc)
    3333             : {
    3334           0 :         struct gre_tunnel *tunnel = &sc->sc_tunnel;
    3335           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
    3336           0 :         struct taskq *softnet = net_tq(ifp->if_index);
    3337             :         struct ifnet *ifp0;
    3338             : 
    3339           0 :         NET_ASSERT_LOCKED();
    3340             : 
    3341           0 :         CLR(ifp->if_flags, IFF_RUNNING);
    3342             : 
    3343           0 :         NET_UNLOCK();
    3344           0 :         if (!timeout_del(&sc->sc_ether_age))
    3345           0 :                 timeout_barrier(&sc->sc_ether_age);
    3346           0 :         ifq_barrier(&ifp->if_snd);
    3347           0 :         if (!task_del(softnet, &sc->sc_send_task))
    3348           0 :                 taskq_barrier(softnet);
    3349           0 :         NET_LOCK();
    3350             : 
    3351           0 :         mq_purge(&sc->sc_send_list);
    3352             : 
    3353           0 :         ifp0 = if_get(sc->sc_ifp0);
    3354           0 :         if (ifp0 != NULL) {
    3355           0 :                 hook_disestablish(ifp0->if_detachhooks, sc->sc_dhcookie);
    3356           0 :                 hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lhcookie);
    3357           0 :         }
    3358           0 :         if_put(ifp0);
    3359             : 
    3360           0 :         switch (tunnel->t_af) {
    3361             :         case AF_INET:
    3362           0 :                 in_delmulti(sc->sc_inm);
    3363           0 :                 break;
    3364             : 
    3365             : #ifdef INET6
    3366             :         case AF_INET6:
    3367           0 :                 in6_delmulti(sc->sc_inm);
    3368           0 :                 break;
    3369             : #endif
    3370             :         }
    3371             : 
    3372           0 :         RBT_REMOVE(nvgre_ucast_tree, &nvgre_ucast_tree, sc);
    3373           0 :         RBT_REMOVE(nvgre_mcast_tree, &nvgre_mcast_tree, sc);
    3374             : 
    3375           0 :         return (0);
    3376             : }
    3377             : 
    3378             : static void
    3379           0 : nvgre_link_change(void *arg)
    3380             : {
    3381             :         /* nop */
    3382           0 : }
    3383             : 
    3384             : static void
    3385           0 : nvgre_detach(void *arg)
    3386             : {
    3387           0 :         struct nvgre_softc *sc = arg;
    3388           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
    3389             : 
    3390           0 :         if (ISSET(ifp->if_flags, IFF_RUNNING)) {
    3391           0 :                 nvgre_down(sc);
    3392           0 :                 if_down(ifp);
    3393           0 :         }
    3394             : 
    3395           0 :         sc->sc_ifp0 = 0;
    3396           0 : }
    3397             : 
    3398             : static int
    3399           0 : nvgre_set_parent(struct nvgre_softc *sc, const char *parent)
    3400             : {
    3401             :         struct ifnet *ifp0;
    3402             : 
    3403           0 :         ifp0 = ifunit(parent); /* doesn't need an if_put */
    3404           0 :         if (ifp0 == NULL)
    3405           0 :                 return (EINVAL);
    3406             : 
    3407           0 :         if (!ISSET(ifp0->if_flags, IFF_MULTICAST))
    3408           0 :                 return (EPROTONOSUPPORT);
    3409             : 
    3410             :         /* commit */
    3411           0 :         sc->sc_ifp0 = ifp0->if_index;
    3412             : 
    3413           0 :         return (0);
    3414           0 : }
    3415             : 
    3416             : static void
    3417           0 : nvgre_age(void *arg)
    3418             : {
    3419           0 :         struct nvgre_softc *sc = arg;
    3420             :         struct nvgre_entry *nv, *nnv;
    3421           0 :         int tmo = sc->sc_ether_tmo * 2;
    3422             :         int diff;
    3423             : 
    3424           0 :         if (!ISSET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING))
    3425           0 :                 return;
    3426             : 
    3427           0 :         rw_enter_write(&sc->sc_ether_lock); /* XXX */
    3428           0 :         RBT_FOREACH_SAFE(nv, nvgre_map, &sc->sc_ether_map, nnv) {
    3429           0 :                 if (nv->nv_type != NVGRE_ENTRY_DYNAMIC)
    3430             :                         continue;
    3431             : 
    3432           0 :                 diff = ticks - nv->nv_age;
    3433           0 :                 if (diff < tmo)
    3434             :                         continue;
    3435             : 
    3436           0 :                 sc->sc_ether_num--;
    3437           0 :                 RBT_REMOVE(nvgre_map, &sc->sc_ether_map, nv);
    3438           0 :                 if (refcnt_rele(&nv->nv_refs))
    3439           0 :                         pool_put(&nvgre_pool, nv);
    3440             :         }
    3441           0 :         rw_exit_write(&sc->sc_ether_lock);
    3442             : 
    3443           0 :         timeout_add_sec(&sc->sc_ether_age, NVGRE_AGE_TMO);
    3444           0 : }
    3445             : 
    3446             : static inline int
    3447           0 : nvgre_entry_valid(struct nvgre_softc *sc, const struct nvgre_entry *nv)
    3448             : {
    3449             :         int diff;
    3450             : 
    3451           0 :         if (nv == NULL)
    3452           0 :                 return (0);
    3453             : 
    3454           0 :         if (nv->nv_type == NVGRE_ENTRY_STATIC)
    3455           0 :                 return (1);
    3456             : 
    3457           0 :         diff = ticks - nv->nv_age;
    3458           0 :         if (diff < sc->sc_ether_tmo)
    3459           0 :                 return (1);
    3460             : 
    3461           0 :         return (0);
    3462           0 : }
    3463             : 
    3464             : static void
    3465           0 : nvgre_start(struct ifnet *ifp)
    3466             : {
    3467           0 :         struct nvgre_softc *sc = ifp->if_softc;
    3468           0 :         const struct gre_tunnel *tunnel = &sc->sc_tunnel;
    3469           0 :         union gre_addr gateway;
    3470           0 :         struct nvgre_entry *nv, key;
    3471           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
    3472             :         struct ether_header *eh;
    3473             :         struct mbuf *m, *m0;
    3474             : #if NBPFILTER > 0
    3475             :         caddr_t if_bpf;
    3476             : #endif
    3477             : 
    3478           0 :         if (!gre_allow) {
    3479           0 :                 ifq_purge(&ifp->if_snd);
    3480           0 :                 return;
    3481             :         }
    3482             : 
    3483           0 :         while ((m0 = ifq_dequeue(&ifp->if_snd)) != NULL) {
    3484             : #if NBPFILTER > 0
    3485           0 :                 if_bpf = ifp->if_bpf;
    3486           0 :                 if (if_bpf)
    3487           0 :                         bpf_mtap_ether(if_bpf, m0, BPF_DIRECTION_OUT);
    3488             : #endif
    3489             : 
    3490           0 :                 eh = mtod(m0, struct ether_header *);
    3491           0 :                 if (ether_isbcast(eh->ether_dhost))
    3492           0 :                         gateway = tunnel->t_dst;
    3493             :                 else {
    3494           0 :                         memcpy(&key.nv_dst, eh->ether_dhost,
    3495             :                             sizeof(key.nv_dst));
    3496             : 
    3497           0 :                         rw_enter_read(&sc->sc_ether_lock);
    3498           0 :                         nv = RBT_FIND(nvgre_map, &sc->sc_ether_map, &key);
    3499           0 :                         if (nvgre_entry_valid(sc, nv))
    3500           0 :                                 gateway = nv->nv_gateway;
    3501             :                         else {
    3502             :                                 /* "flood" to unknown hosts */
    3503           0 :                                 gateway = tunnel->t_dst;
    3504             :                         }
    3505           0 :                         rw_exit_read(&sc->sc_ether_lock);
    3506             :                 }
    3507             : 
    3508           0 :                 m = m_gethdr(M_DONTWAIT, m0->m_type);
    3509           0 :                 if (m == NULL) {
    3510           0 :                         m_freem(m0);
    3511           0 :                         continue;
    3512             :                 }
    3513             : 
    3514           0 :                 M_MOVE_PKTHDR(m, m0);
    3515           0 :                 m->m_next = m0;
    3516             : 
    3517           0 :                 MH_ALIGN(m, 0);
    3518           0 :                 m->m_len = 0;
    3519             : 
    3520           0 :                 m = gre_encap_dst(tunnel, &gateway, m,
    3521           0 :                     htons(ETHERTYPE_TRANSETHER), tunnel->t_ttl, 0);
    3522           0 :                 if (m == NULL)
    3523           0 :                         continue;
    3524             : 
    3525           0 :                 m->m_flags &= ~(M_BCAST|M_MCAST);
    3526           0 :                 m->m_pkthdr.ph_rtableid = tunnel->t_rtableid;
    3527             : 
    3528             : #if NPF > 0
    3529           0 :                 pf_pkt_addr_changed(m);
    3530             : #endif
    3531             : 
    3532           0 :                 ml_enqueue(&ml, m);
    3533             :         }
    3534             : 
    3535           0 :         if (!ml_empty(&ml)) {
    3536           0 :                 if (mq_enlist(&sc->sc_send_list, &ml) == 0)
    3537           0 :                         task_add(net_tq(ifp->if_index), &sc->sc_send_task);
    3538             :                 /* else set OACTIVE? */
    3539             :         }
    3540           0 : }
    3541             : 
    3542             : static uint64_t
    3543           0 : nvgre_send4(struct nvgre_softc *sc, struct mbuf_list *ml)
    3544             : {
    3545           0 :         struct ip_moptions imo;
    3546             :         struct mbuf *m;
    3547             :         uint64_t oerrors = 0;
    3548             : 
    3549           0 :         imo.imo_ifidx = sc->sc_ifp0;
    3550           0 :         imo.imo_ttl = sc->sc_tunnel.t_ttl;
    3551           0 :         imo.imo_loop = 0;
    3552             : 
    3553           0 :         NET_RLOCK();
    3554           0 :         while ((m = ml_dequeue(ml)) != NULL) {
    3555           0 :                 if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &imo, NULL, 0) != 0)
    3556           0 :                         oerrors++;
    3557             :         }
    3558           0 :         NET_RUNLOCK();
    3559             : 
    3560           0 :         return (oerrors);
    3561           0 : }
    3562             : 
    3563             : #ifdef INET6
    3564             : static uint64_t
    3565           0 : nvgre_send6(struct nvgre_softc *sc, struct mbuf_list *ml)
    3566             : {
    3567           0 :         struct ip6_moptions im6o;
    3568             :         struct mbuf *m;
    3569             :         uint64_t oerrors = 0;
    3570             : 
    3571           0 :         im6o.im6o_ifidx = sc->sc_ifp0;
    3572           0 :         im6o.im6o_hlim = sc->sc_tunnel.t_ttl;
    3573           0 :         im6o.im6o_loop = 0;
    3574             : 
    3575           0 :         NET_RLOCK();
    3576           0 :         while ((m = ml_dequeue(ml)) != NULL) {
    3577           0 :                 if (ip6_output(m, NULL, NULL, 0, &im6o, NULL) != 0)
    3578           0 :                         oerrors++;
    3579             :         }
    3580           0 :         NET_RUNLOCK();
    3581             : 
    3582           0 :         return (oerrors);
    3583           0 : }
    3584             : #endif /* INET6 */
    3585             : 
    3586             : static void
    3587           0 : nvgre_send(void *arg)
    3588             : {
    3589           0 :         struct nvgre_softc *sc = arg;
    3590           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
    3591           0 :         sa_family_t af = sc->sc_tunnel.t_af;
    3592           0 :         struct mbuf_list ml;
    3593             :         uint64_t oerrors;
    3594             : 
    3595           0 :         if (!ISSET(ifp->if_flags, IFF_RUNNING))
    3596           0 :                 return;
    3597             : 
    3598           0 :         mq_delist(&sc->sc_send_list, &ml);
    3599           0 :         if (ml_empty(&ml))
    3600           0 :                 return;
    3601             : 
    3602           0 :         switch (af) {
    3603             :         case AF_INET:
    3604           0 :                 oerrors = nvgre_send4(sc, &ml);
    3605           0 :                 break;
    3606             : #ifdef INET6
    3607             :         case AF_INET6:
    3608           0 :                 oerrors = nvgre_send6(sc, &ml);
    3609           0 :                 break;
    3610             : #endif
    3611             :         default:
    3612           0 :                 unhandled_af(af);
    3613             :                 /* NOTREACHED */
    3614             :         }
    3615             : 
    3616           0 :         ifp->if_oerrors += oerrors; /* XXX should be ifq_oerrors */
    3617           0 : }
    3618             : 
    3619             : static int
    3620           0 : eoip_up(struct eoip_softc *sc)
    3621             : {
    3622           0 :         if (sc->sc_tunnel.t_af == AF_UNSPEC)
    3623           0 :                 return (EDESTADDRREQ);
    3624             : 
    3625           0 :         NET_ASSERT_LOCKED();
    3626             : 
    3627           0 :         if (RBT_INSERT(eoip_tree, &eoip_tree, sc) != NULL)
    3628           0 :                 return (EADDRINUSE);
    3629             : 
    3630           0 :         SET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING);
    3631             : 
    3632           0 :         if (sc->sc_ka_state != GRE_KA_NONE) {
    3633           0 :                 sc->sc_ka_holdmax = sc->sc_ka_count;
    3634           0 :                 eoip_keepalive_send(sc);
    3635           0 :         }
    3636             : 
    3637           0 :         return (0);
    3638           0 : }
    3639             : 
    3640             : static int
    3641           0 : eoip_down(struct eoip_softc *sc)
    3642             : {
    3643           0 :         NET_ASSERT_LOCKED();
    3644           0 :         CLR(sc->sc_ac.ac_if.if_flags, IFF_RUNNING);
    3645             : 
    3646           0 :         if (sc->sc_ka_state != GRE_KA_NONE) {
    3647           0 :                 if (!timeout_del(&sc->sc_ka_hold))
    3648           0 :                         timeout_barrier(&sc->sc_ka_hold);
    3649           0 :                 if (!timeout_del(&sc->sc_ka_send))
    3650           0 :                         timeout_barrier(&sc->sc_ka_send);
    3651             : 
    3652           0 :                 sc->sc_ka_state = GRE_KA_DOWN;
    3653           0 :                 gre_link_state(&sc->sc_ac.ac_if, sc->sc_ka_state);
    3654           0 :         }
    3655             : 
    3656           0 :         RBT_REMOVE(eoip_tree, &eoip_tree, sc);
    3657             : 
    3658           0 :         return (0);
    3659             : }
    3660             : 
    3661             : static void
    3662           0 : eoip_start(struct ifnet *ifp)
    3663             : {
    3664           0 :         struct eoip_softc *sc = ifp->if_softc;
    3665             :         struct mbuf *m0, *m;
    3666             : #if NBPFILTER > 0
    3667             :         caddr_t if_bpf;
    3668             : #endif
    3669             : 
    3670           0 :         if (!gre_allow) {
    3671           0 :                 ifq_purge(&ifp->if_snd);
    3672           0 :                 return;
    3673             :         }
    3674             : 
    3675           0 :         while ((m0 = ifq_dequeue(&ifp->if_snd)) != NULL) {
    3676             : #if NBPFILTER > 0
    3677           0 :                 if_bpf = ifp->if_bpf;
    3678           0 :                 if (if_bpf)
    3679           0 :                         bpf_mtap_ether(if_bpf, m0, BPF_DIRECTION_OUT);
    3680             : #endif
    3681             : 
    3682           0 :                 m = m_gethdr(M_DONTWAIT, m0->m_type);
    3683           0 :                 if (m == NULL) {
    3684           0 :                         m_freem(m0);
    3685           0 :                         continue;
    3686             :                 }
    3687             : 
    3688           0 :                 M_MOVE_PKTHDR(m, m0);
    3689           0 :                 m->m_next = m0;
    3690             : 
    3691           0 :                 MH_ALIGN(m, 0);
    3692           0 :                 m->m_len = 0;
    3693             : 
    3694           0 :                 m = eoip_encap(sc, m, 0);
    3695           0 :                 if (m == NULL || gre_ip_output(&sc->sc_tunnel, m) != 0) {
    3696           0 :                         ifp->if_oerrors++;
    3697           0 :                         continue;
    3698             :                 }
    3699             :         }
    3700           0 : }
    3701             : 
    3702             : static struct mbuf *
    3703           0 : eoip_encap(struct eoip_softc *sc, struct mbuf *m, uint8_t tos)
    3704             : {
    3705             :         struct gre_header *gh;
    3706             :         struct gre_h_key_eoip *eoiph;
    3707           0 :         int len = m->m_pkthdr.len;
    3708             : 
    3709           0 :         m = m_prepend(m, sizeof(*gh) + sizeof(*eoiph), M_DONTWAIT);
    3710           0 :         if (m == NULL)
    3711           0 :                 return (NULL);
    3712             : 
    3713           0 :         gh = mtod(m, struct gre_header *);
    3714           0 :         gh->gre_flags = htons(GRE_VERS_1 | GRE_KP);
    3715           0 :         gh->gre_proto = htons(GRE_EOIP);
    3716             : 
    3717           0 :         eoiph = (struct gre_h_key_eoip *)(gh + 1);
    3718           0 :         htobem16(&eoiph->eoip_len, len);
    3719           0 :         eoiph->eoip_tunnel_id = sc->sc_tunnel_id;
    3720             : 
    3721           0 :         return (gre_encap_ip(&sc->sc_tunnel, m, sc->sc_tunnel.t_ttl, tos));
    3722           0 : }
    3723             : 
    3724             : static void
    3725           0 : eoip_keepalive_send(void *arg)
    3726             : {
    3727           0 :         struct eoip_softc *sc = arg;
    3728             :         struct mbuf *m;
    3729             :         int linkhdr;
    3730             : 
    3731           0 :         if (!ISSET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING))
    3732           0 :                 return;
    3733             : 
    3734             :         /* this is really conservative */
    3735             : #ifdef INET6
    3736           0 :         linkhdr = max_linkhdr + MAX(sizeof(struct ip), sizeof(struct ip6_hdr)) +
    3737           0 :             sizeof(struct gre_header) + sizeof(struct gre_h_key_eoip);
    3738             : #else
    3739             :         linkhdr = max_linkhdr + sizeof(struct ip) +
    3740             :             sizeof(struct gre_header) + sizeof(struct gre_h_key_eoip);
    3741             : #endif
    3742           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
    3743           0 :         if (m == NULL)
    3744           0 :                 return;
    3745             : 
    3746           0 :         if (linkhdr > MHLEN) {
    3747           0 :                 MCLGETI(m, M_DONTWAIT, NULL, linkhdr);
    3748           0 :                 if (!ISSET(m->m_flags, M_EXT)) {
    3749           0 :                         m_freem(m);
    3750           0 :                         return;
    3751             :                 }
    3752             :         }
    3753             : 
    3754           0 :         m->m_pkthdr.len = m->m_len = linkhdr;
    3755           0 :         m_adj(m, linkhdr);
    3756             : 
    3757           0 :         m = eoip_encap(sc, m, IPTOS_PREC_INTERNETCONTROL);
    3758           0 :         if (m == NULL)
    3759           0 :                 return;
    3760             : 
    3761           0 :         gre_ip_output(&sc->sc_tunnel, m);
    3762             : 
    3763           0 :         timeout_add_sec(&sc->sc_ka_send, sc->sc_ka_timeo);
    3764           0 : }
    3765             : 
    3766             : static void
    3767           0 : eoip_keepalive_hold(void *arg)
    3768             : {
    3769           0 :         struct eoip_softc *sc = arg;
    3770           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
    3771             : 
    3772           0 :         if (!ISSET(ifp->if_flags, IFF_RUNNING))
    3773           0 :                 return;
    3774             : 
    3775           0 :         NET_LOCK();
    3776           0 :         sc->sc_ka_state = GRE_KA_DOWN;
    3777           0 :         gre_link_state(ifp, sc->sc_ka_state);
    3778           0 :         NET_UNLOCK();
    3779           0 : }
    3780             : 
    3781             : static void
    3782           0 : eoip_keepalive_recv(struct eoip_softc *sc)
    3783             : {
    3784           0 :         switch (sc->sc_ka_state) {
    3785             :         case GRE_KA_NONE:
    3786             :                 return;
    3787             :         case GRE_KA_DOWN:
    3788           0 :                 sc->sc_ka_state = GRE_KA_HOLD;
    3789           0 :                 sc->sc_ka_holdcnt = sc->sc_ka_holdmax;
    3790           0 :                 sc->sc_ka_holdmax = MIN(sc->sc_ka_holdmax * 2,
    3791             :                     16 * sc->sc_ka_count);
    3792           0 :                 break;
    3793             :         case GRE_KA_HOLD:
    3794           0 :                 if (--sc->sc_ka_holdcnt > 0)
    3795             :                         break;
    3796             : 
    3797           0 :                 sc->sc_ka_state = GRE_KA_UP;
    3798           0 :                 gre_link_state(&sc->sc_ac.ac_if, sc->sc_ka_state);
    3799           0 :                 break;
    3800             : 
    3801             :         case GRE_KA_UP:
    3802           0 :                 sc->sc_ka_holdmax--;
    3803           0 :                 sc->sc_ka_holdmax = MAX(sc->sc_ka_holdmax, sc->sc_ka_count);
    3804           0 :                 break;
    3805             :         }
    3806             : 
    3807           0 :         timeout_add_sec(&sc->sc_ka_hold, sc->sc_ka_timeo * sc->sc_ka_count);
    3808           0 : }
    3809             : 
    3810             : static struct mbuf *
    3811           0 : eoip_input(struct gre_tunnel *key, struct mbuf *m,
    3812             :     const struct gre_header *gh, int iphlen)
    3813             : {
    3814           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
    3815             :         struct eoip_softc *sc;
    3816             :         struct gre_h_key_eoip *eoiph;
    3817             :         int hlen, len;
    3818             :         caddr_t buf;
    3819             : 
    3820           0 :         if (gh->gre_flags != htons(GRE_KP | GRE_VERS_1))
    3821             :                 goto decline;
    3822             : 
    3823           0 :         hlen = iphlen + sizeof(*gh) + sizeof(*eoiph);
    3824           0 :         if (m->m_pkthdr.len < hlen)
    3825             :                 goto decline;
    3826             : 
    3827           0 :         m = m_pullup(m, hlen);
    3828           0 :         if (m == NULL)
    3829           0 :                 return (NULL);
    3830             : 
    3831           0 :         buf = mtod(m, caddr_t);
    3832           0 :         gh = (struct gre_header *)(buf + iphlen);
    3833           0 :         eoiph = (struct gre_h_key_eoip *)(gh + 1);
    3834             : 
    3835           0 :         key->t_key = eoiph->eoip_tunnel_id;
    3836             : 
    3837           0 :         NET_ASSERT_LOCKED();
    3838           0 :         sc = RBT_FIND(eoip_tree, &eoip_tree, (const struct eoip_softc *)key);
    3839           0 :         if (sc == NULL)
    3840             :                 goto decline;
    3841             : 
    3842             :         /* it's ours now */
    3843           0 :         len = bemtoh16(&eoiph->eoip_len);
    3844           0 :         if (len == 0) {
    3845           0 :                 eoip_keepalive_recv(sc);
    3846           0 :                 goto drop;
    3847             :         }
    3848             : 
    3849           0 :         m = gre_ether_align(m, hlen);
    3850           0 :         if (m == NULL)
    3851           0 :                 return (NULL);
    3852             : 
    3853           0 :         if (m->m_pkthdr.len < len)
    3854             :                 goto drop;
    3855           0 :         if (m->m_pkthdr.len != len)
    3856           0 :                 m_adj(m, len - m->m_pkthdr.len);
    3857             : 
    3858           0 :         m->m_flags &= ~(M_MCAST|M_BCAST);
    3859             : 
    3860             : #if NPF > 0
    3861           0 :         pf_pkt_addr_changed(m);
    3862             : #endif
    3863             : 
    3864           0 :         ml_enqueue(&ml, m);
    3865           0 :         if_input(&sc->sc_ac.ac_if, &ml);
    3866             : 
    3867           0 :         return (NULL);
    3868             : 
    3869             : decline:
    3870           0 :         return (m);
    3871             : drop:
    3872           0 :         m_freem(m);
    3873           0 :         return (NULL);
    3874           0 : }
    3875             : 
    3876             : int
    3877           0 : gre_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
    3878             :     size_t newlen)
    3879             : {
    3880             :         int error;
    3881             : 
    3882             :         /* All sysctl names at this level are terminal. */
    3883           0 :         if (namelen != 1)
    3884           0 :                 return (ENOTDIR);
    3885             : 
    3886           0 :         switch (name[0]) {
    3887             :         case GRECTL_ALLOW:
    3888           0 :                 NET_LOCK();
    3889           0 :                 error = sysctl_int(oldp, oldlenp, newp, newlen, &gre_allow);
    3890           0 :                 NET_UNLOCK();
    3891           0 :                 return (error);
    3892             :         case GRECTL_WCCP:
    3893           0 :                 NET_LOCK();
    3894           0 :                 error = sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp);
    3895           0 :                 NET_UNLOCK();
    3896           0 :                 return (error);
    3897             :         default:
    3898           0 :                 return (ENOPROTOOPT);
    3899             :         }
    3900             :         /* NOTREACHED */
    3901           0 : }
    3902             : 
    3903             : static inline int
    3904           0 : gre_ip_cmp(int af, const union gre_addr *a, const union gre_addr *b)
    3905             : {
    3906           0 :         switch (af) {
    3907             : #ifdef INET6
    3908             :         case AF_INET6:
    3909           0 :                 return (memcmp(&a->in6, &b->in6, sizeof(a->in6)));
    3910             : #endif /* INET6 */
    3911             :         case AF_INET:
    3912           0 :                 return (memcmp(&a->in4, &b->in4, sizeof(a->in4)));
    3913             :         default:
    3914           0 :                 panic("%s: unsupported af %d\n", __func__, af);
    3915             :         }
    3916             : 
    3917             :         return (0);
    3918           0 : }
    3919             : 
    3920             : static int
    3921           0 : gre_cmp_src(const struct gre_tunnel *a, const struct gre_tunnel *b)
    3922             : {
    3923             :         uint32_t ka, kb;
    3924             :         uint32_t mask;
    3925             :         int rv;
    3926             : 
    3927             :         /* is K set at all? */
    3928           0 :         ka = a->t_key_mask & GRE_KEY_ENTROPY;
    3929           0 :         kb = b->t_key_mask & GRE_KEY_ENTROPY;
    3930             : 
    3931             :         /* sort by whether K is set */
    3932           0 :         if (ka > kb)
    3933           0 :                 return (1);
    3934           0 :         if (ka < kb)
    3935           0 :                 return (-1);
    3936             : 
    3937             :         /* is K set on both? */
    3938           0 :         if (ka != GRE_KEY_NONE) {
    3939             :                 /* get common prefix */
    3940           0 :                 mask = a->t_key_mask & b->t_key_mask;
    3941             : 
    3942           0 :                 ka = a->t_key & mask;
    3943           0 :                 kb = b->t_key & mask;
    3944             : 
    3945             :                 /* sort by common prefix */
    3946           0 :                 if (ka > kb)
    3947           0 :                         return (1);
    3948           0 :                 if (ka < kb)
    3949           0 :                         return (-1);
    3950             :         }
    3951             : 
    3952             :         /* sort by routing table */
    3953           0 :         if (a->t_rtableid > b->t_rtableid)
    3954           0 :                 return (1);
    3955           0 :         if (a->t_rtableid < b->t_rtableid)
    3956           0 :                 return (-1);
    3957             : 
    3958             :         /* sort by address */
    3959           0 :         if (a->t_af > b->t_af)
    3960           0 :                 return (1);
    3961           0 :         if (a->t_af < b->t_af)
    3962           0 :                 return (-1);
    3963             : 
    3964           0 :         rv = gre_ip_cmp(a->t_af, &a->t_src, &b->t_src);
    3965           0 :         if (rv != 0)
    3966           0 :                 return (rv);
    3967             : 
    3968           0 :         return (0);
    3969           0 : }
    3970             : 
    3971             : static int
    3972           0 : gre_cmp(const struct gre_tunnel *a, const struct gre_tunnel *b)
    3973             : {
    3974             :         int rv;
    3975             : 
    3976           0 :         rv = gre_cmp_src(a, b);
    3977           0 :         if (rv != 0)
    3978           0 :                 return (rv);
    3979             : 
    3980           0 :         return (gre_ip_cmp(a->t_af, &a->t_dst, &b->t_dst));
    3981           0 : }
    3982             : 
    3983             : static inline int
    3984           0 : mgre_cmp(const struct mgre_softc *a, const struct mgre_softc *b)
    3985             : {
    3986           0 :         return (gre_cmp_src(&a->sc_tunnel, &b->sc_tunnel));
    3987             : }
    3988             : 
    3989           0 : RBT_GENERATE(mgre_tree, mgre_softc, sc_entry, mgre_cmp);
    3990             : 
    3991             : static inline int
    3992           0 : egre_cmp(const struct egre_softc *a, const struct egre_softc *b)
    3993             : {
    3994           0 :         return (gre_cmp(&a->sc_tunnel, &b->sc_tunnel));
    3995             : }
    3996             : 
    3997           0 : RBT_GENERATE(egre_tree, egre_softc, sc_entry, egre_cmp);
    3998             : 
    3999             : static inline int
    4000           0 : nvgre_entry_cmp(const struct nvgre_entry *a, const struct nvgre_entry *b)
    4001             : {
    4002           0 :         return (memcmp(&a->nv_dst, &b->nv_dst, sizeof(a->nv_dst)));
    4003             : }
    4004             : 
    4005           0 : RBT_GENERATE(nvgre_map, nvgre_entry, nv_entry, nvgre_entry_cmp);
    4006             : 
    4007             : static int
    4008           0 : nvgre_cmp_tunnel(const struct gre_tunnel *a, const struct gre_tunnel *b)
    4009             : {
    4010             :         uint32_t ka, kb;
    4011             : 
    4012           0 :         ka = a->t_key & GRE_KEY_ENTROPY;
    4013           0 :         kb = b->t_key & GRE_KEY_ENTROPY;
    4014             : 
    4015             :         /* sort by common prefix */
    4016           0 :         if (ka > kb)
    4017           0 :                 return (1);
    4018           0 :         if (ka < kb)
    4019           0 :                 return (-1);
    4020             : 
    4021             :         /* sort by routing table */
    4022           0 :         if (a->t_rtableid > b->t_rtableid)
    4023           0 :                 return (1);
    4024           0 :         if (a->t_rtableid < b->t_rtableid)
    4025           0 :                 return (-1);
    4026             : 
    4027             :         /* sort by address */
    4028           0 :         if (a->t_af > b->t_af)
    4029           0 :                 return (1);
    4030           0 :         if (a->t_af < b->t_af)
    4031           0 :                 return (-1);
    4032             : 
    4033           0 :         return (0);
    4034           0 : }
    4035             : 
    4036             : static inline int
    4037           0 : nvgre_cmp_ucast(const struct nvgre_softc *na, const struct nvgre_softc *nb)
    4038             : {
    4039           0 :         const struct gre_tunnel *a = &na->sc_tunnel;
    4040           0 :         const struct gre_tunnel *b = &nb->sc_tunnel;
    4041             :         int rv;
    4042             : 
    4043           0 :         rv = nvgre_cmp_tunnel(a, b);
    4044           0 :         if (rv != 0)
    4045           0 :                 return (rv);
    4046             : 
    4047           0 :         rv = gre_ip_cmp(a->t_af, &a->t_src, &b->t_src);
    4048           0 :         if (rv != 0)
    4049           0 :                 return (rv);
    4050             : 
    4051           0 :         return (0);
    4052           0 : }
    4053             : 
    4054             : static int
    4055           0 : nvgre_cmp_mcast(const struct gre_tunnel *a, const union gre_addr *aa,
    4056             :     unsigned int if0idxa, const struct gre_tunnel *b,
    4057             :     const union gre_addr *ab,unsigned int if0idxb)
    4058             : {
    4059             :         int rv;
    4060             : 
    4061           0 :         rv = nvgre_cmp_tunnel(a, b);
    4062           0 :         if (rv != 0)
    4063           0 :                 return (rv);
    4064             : 
    4065           0 :         rv = gre_ip_cmp(a->t_af, aa, ab);
    4066           0 :         if (rv != 0)
    4067           0 :                 return (rv);
    4068             : 
    4069           0 :         if (if0idxa > if0idxb)
    4070           0 :                 return (1);
    4071           0 :         if (if0idxa < if0idxb)
    4072           0 :                 return (-1);
    4073             : 
    4074           0 :         return (0);
    4075           0 : }
    4076             : 
    4077             : static inline int
    4078           0 : nvgre_cmp_mcast_sc(const struct nvgre_softc *na, const struct nvgre_softc *nb)
    4079             : {
    4080           0 :         const struct gre_tunnel *a = &na->sc_tunnel;
    4081           0 :         const struct gre_tunnel *b = &nb->sc_tunnel;
    4082             : 
    4083           0 :         return (nvgre_cmp_mcast(a, &a->t_dst, na->sc_ifp0,
    4084           0 :             b, &b->t_dst, nb->sc_ifp0));
    4085             : }
    4086             : 
    4087           0 : RBT_GENERATE(nvgre_ucast_tree, nvgre_softc, sc_uentry, nvgre_cmp_ucast);
    4088           0 : RBT_GENERATE(nvgre_mcast_tree, nvgre_softc, sc_mentry, nvgre_cmp_mcast_sc);
    4089             : 
    4090             : static inline int
    4091           0 : eoip_cmp(const struct eoip_softc *ea, const struct eoip_softc *eb)
    4092             : {
    4093           0 :         const struct gre_tunnel *a = &ea->sc_tunnel;
    4094           0 :         const struct gre_tunnel *b = &eb->sc_tunnel;
    4095             :         int rv;
    4096             : 
    4097           0 :         if (a->t_key > b->t_key)
    4098           0 :                 return (1);
    4099           0 :         if (a->t_key < b->t_key)
    4100           0 :                 return (-1);
    4101             : 
    4102             :         /* sort by routing table */
    4103           0 :         if (a->t_rtableid > b->t_rtableid)
    4104           0 :                 return (1);
    4105           0 :         if (a->t_rtableid < b->t_rtableid)
    4106           0 :                 return (-1);
    4107             : 
    4108             :         /* sort by address */
    4109           0 :         if (a->t_af > b->t_af)
    4110           0 :                 return (1);
    4111           0 :         if (a->t_af < b->t_af)
    4112           0 :                 return (-1);
    4113             : 
    4114           0 :         rv = gre_ip_cmp(a->t_af, &a->t_src, &b->t_src);
    4115           0 :         if (rv != 0)
    4116           0 :                 return (rv);
    4117             : 
    4118           0 :         rv = gre_ip_cmp(a->t_af, &a->t_dst, &b->t_dst);
    4119           0 :         if (rv != 0)
    4120           0 :                 return (rv);
    4121             : 
    4122           0 :         return (0);
    4123           0 : }
    4124             : 
    4125           0 : RBT_GENERATE(eoip_tree, eoip_softc, sc_entry, eoip_cmp);

Generated by: LCOV version 1.13