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

          Line data    Source code
       1             : /*      $OpenBSD: rtsock.c,v 1.279 2018/07/10 20:28:34 claudio Exp $    */
       2             : /*      $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $  */
       3             : 
       4             : /*
       5             :  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
       6             :  * All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  * 1. Redistributions of source code must retain the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer.
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  * 3. Neither the name of the project nor the names of its contributors
      17             :  *    may be used to endorse or promote products derived from this software
      18             :  *    without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
      21             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      22             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      23             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
      24             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      25             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      26             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      27             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      28             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      29             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      30             :  * SUCH DAMAGE.
      31             :  */
      32             : 
      33             : /*
      34             :  * Copyright (c) 1988, 1991, 1993
      35             :  *      The Regents of the University of California.  All rights reserved.
      36             :  *
      37             :  * Redistribution and use in source and binary forms, with or without
      38             :  * modification, are permitted provided that the following conditions
      39             :  * are met:
      40             :  * 1. Redistributions of source code must retain the above copyright
      41             :  *    notice, this list of conditions and the following disclaimer.
      42             :  * 2. Redistributions in binary form must reproduce the above copyright
      43             :  *    notice, this list of conditions and the following disclaimer in the
      44             :  *    documentation and/or other materials provided with the distribution.
      45             :  * 3. Neither the name of the University nor the names of its contributors
      46             :  *    may be used to endorse or promote products derived from this software
      47             :  *    without specific prior written permission.
      48             :  *
      49             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      50             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      51             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      52             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      53             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      54             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      55             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      56             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      57             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      58             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      59             :  * SUCH DAMAGE.
      60             :  *
      61             :  *      @(#)rtsock.c    8.6 (Berkeley) 2/11/95
      62             :  */
      63             : 
      64             : #include <sys/param.h>
      65             : #include <sys/systm.h>
      66             : #include <sys/proc.h>
      67             : #include <sys/sysctl.h>
      68             : #include <sys/mbuf.h>
      69             : #include <sys/socket.h>
      70             : #include <sys/socketvar.h>
      71             : #include <sys/domain.h>
      72             : #include <sys/protosw.h>
      73             : #include <sys/srp.h>
      74             : 
      75             : #include <net/if.h>
      76             : #include <net/if_dl.h>
      77             : #include <net/if_var.h>
      78             : #include <net/route.h>
      79             : 
      80             : #include <netinet/in.h>
      81             : 
      82             : #ifdef MPLS
      83             : #include <netmpls/mpls.h>
      84             : #endif
      85             : #ifdef IPSEC
      86             : #include <netinet/ip_ipsp.h>
      87             : #include <net/if_enc.h>
      88             : #endif
      89             : #ifdef BFD
      90             : #include <net/bfd.h>
      91             : #endif
      92             : 
      93             : #include <sys/stdarg.h>
      94             : #include <sys/kernel.h>
      95             : #include <sys/timeout.h>
      96             : 
      97             : #define ROUTESNDQ       8192
      98             : #define ROUTERCVQ       8192
      99             : 
     100             : const struct sockaddr route_src = { 2, PF_ROUTE, };
     101             : 
     102             : struct walkarg {
     103             :         int     w_op, w_arg, w_given, w_needed, w_tmemsize;
     104             :         caddr_t w_where, w_tmem;
     105             : };
     106             : 
     107             : void    route_prinit(void);
     108             : void    rcb_ref(void *, void *);
     109             : void    rcb_unref(void *, void *);
     110             : int     route_output(struct mbuf *, struct socket *, struct sockaddr *,
     111             :             struct mbuf *);
     112             : int     route_ctloutput(int, struct socket *, int, int, struct mbuf *);
     113             : int     route_usrreq(struct socket *, int, struct mbuf *, struct mbuf *,
     114             :             struct mbuf *, struct proc *);
     115             : void    route_input(struct mbuf *m0, struct socket *, sa_family_t);
     116             : int     route_arp_conflict(struct rtentry *, struct rt_addrinfo *);
     117             : int     route_cleargateway(struct rtentry *, void *, unsigned int);
     118             : void    rtm_senddesync_timer(void *);
     119             : void    rtm_senddesync(struct socket *);
     120             : int     rtm_sendup(struct socket *, struct mbuf *, int);
     121             : 
     122             : int     rtm_getifa(struct rt_addrinfo *, unsigned int);
     123             : int     rtm_output(struct rt_msghdr *, struct rtentry **, struct rt_addrinfo *,
     124             :             uint8_t, unsigned int);
     125             : struct rt_msghdr *rtm_report(struct rtentry *, u_char, int, int);
     126             : struct mbuf     *rtm_msg1(int, struct rt_addrinfo *);
     127             : int              rtm_msg2(int, int, struct rt_addrinfo *, caddr_t,
     128             :                      struct walkarg *);
     129             : void             rtm_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
     130             : int              rtm_validate_proposal(struct rt_addrinfo *);
     131             : void             rtm_setmetrics(u_long, const struct rt_metrics *,
     132             :                      struct rt_kmetrics *);
     133             : void             rtm_getmetrics(const struct rt_kmetrics *,
     134             :                      struct rt_metrics *);
     135             : 
     136             : int              sysctl_iflist(int, struct walkarg *);
     137             : int              sysctl_ifnames(struct walkarg *);
     138             : int              sysctl_rtable_rtstat(void *, size_t *, void *);
     139             : 
     140             : struct rtpcb {
     141             :         struct socket           *rop_socket;
     142             : 
     143             :         SRPL_ENTRY(rtpcb)       rop_list;
     144             :         struct refcnt           rop_refcnt;
     145             :         struct timeout          rop_timeout;
     146             :         unsigned int            rop_msgfilter;
     147             :         unsigned int            rop_flags;
     148             :         u_int                   rop_rtableid;
     149             :         unsigned short          rop_proto;
     150             :         u_char                  rop_priority;
     151             : };
     152             : #define sotortpcb(so)   ((struct rtpcb *)(so)->so_pcb)
     153             : 
     154             : struct rtptable {
     155             :         SRPL_HEAD(, rtpcb)      rtp_list;
     156             :         struct srpl_rc          rtp_rc;
     157             :         struct rwlock           rtp_lk;
     158             :         unsigned int            rtp_count;
     159             : };
     160             : 
     161             : struct rtptable rtptable;
     162             : 
     163             : /*
     164             :  * These flags and timeout are used for indicating to userland (via a
     165             :  * RTM_DESYNC msg) when the route socket has overflowed and messages
     166             :  * have been lost.
     167             :  */
     168             : #define ROUTECB_FLAG_DESYNC     0x1     /* Route socket out of memory */
     169             : #define ROUTECB_FLAG_FLUSH      0x2     /* Wait until socket is empty before
     170             :                                            queueing more packets */
     171             : 
     172             : #define ROUTE_DESYNC_RESEND_TIMEOUT     (hz / 5)        /* In hz */
     173             : 
     174             : void
     175           0 : route_prinit(void)
     176             : {
     177           0 :         srpl_rc_init(&rtptable.rtp_rc, rcb_ref, rcb_unref, NULL);
     178           0 :         rw_init(&rtptable.rtp_lk, "rtsock");
     179           0 :         SRPL_INIT(&rtptable.rtp_list);
     180           0 : }
     181             : 
     182             : void
     183           0 : rcb_ref(void *null, void *v)
     184             : {
     185           0 :         struct rtpcb *rop = v;
     186             : 
     187           0 :         refcnt_take(&rop->rop_refcnt);
     188           0 : }
     189             : 
     190             : void
     191           0 : rcb_unref(void *null, void *v)
     192             : {
     193           0 :         struct rtpcb *rop = v;
     194             : 
     195           0 :         refcnt_rele_wake(&rop->rop_refcnt);
     196           0 : }
     197             : 
     198             : int
     199           0 : route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
     200             :     struct mbuf *control, struct proc *p)
     201             : {
     202             :         struct rtpcb    *rop;
     203             :         int              error = 0;
     204             : 
     205           0 :         if (req == PRU_CONTROL)
     206           0 :                 return (EOPNOTSUPP);
     207             : 
     208           0 :         soassertlocked(so);
     209             : 
     210           0 :         if (control && control->m_len) {
     211             :                 error = EOPNOTSUPP;
     212           0 :                 goto release;
     213             :         }
     214             : 
     215           0 :         rop = sotortpcb(so);
     216           0 :         if (rop == NULL) {
     217             :                 error = EINVAL;
     218           0 :                 goto release;
     219             :         }
     220             : 
     221           0 :         switch (req) {
     222             :         /* no connect, bind, accept. Socket is connected from the start */
     223             :         case PRU_CONNECT:
     224             :         case PRU_BIND:
     225             :         case PRU_CONNECT2:
     226             :         case PRU_LISTEN:
     227             :         case PRU_ACCEPT:
     228             :                 error = EOPNOTSUPP;
     229           0 :                 break;
     230             : 
     231             :         case PRU_DISCONNECT:
     232             :         case PRU_ABORT:
     233           0 :                 soisdisconnected(so);
     234           0 :                 break;
     235             :         case PRU_SHUTDOWN:
     236           0 :                 socantsendmore(so);
     237           0 :                 break;
     238             :         case PRU_SENSE:
     239             :                 /* stat: don't bother with a blocksize. */
     240           0 :                 return (0);
     241             : 
     242             :         /* minimal support, just implement a fake peer address */
     243             :         case PRU_SOCKADDR:
     244             :                 error = EINVAL;
     245           0 :                 break;
     246             :         case PRU_PEERADDR:
     247           0 :                 bcopy(&route_src, mtod(nam, caddr_t), route_src.sa_len);
     248           0 :                 nam->m_len = route_src.sa_len;
     249           0 :                 break;
     250             : 
     251             :         case PRU_RCVOOB:
     252           0 :                 return (EOPNOTSUPP);
     253             :         case PRU_RCVD:
     254             :                 /*
     255             :                  * If we are in a FLUSH state, check if the buffer is
     256             :                  * empty so that we can clear the flag.
     257             :                  */
     258           0 :                 if (((rop->rop_flags & ROUTECB_FLAG_FLUSH) != 0) &&
     259           0 :                     ((sbspace(rop->rop_socket, &rop->rop_socket->so_rcv) ==
     260           0 :                     rop->rop_socket->so_rcv.sb_hiwat)))
     261           0 :                         rop->rop_flags &= ~ROUTECB_FLAG_FLUSH;
     262           0 :                 return (0);
     263             : 
     264             :         case PRU_SENDOOB:
     265             :                 error = EOPNOTSUPP;
     266           0 :                 break;
     267             :         case PRU_SEND:
     268           0 :                 if (nam) {
     269             :                         error = EISCONN;
     270           0 :                         break;
     271             :                 }
     272           0 :                 error = (*so->so_proto->pr_output)(m, so, NULL, NULL);
     273             :                 m = NULL;
     274           0 :                 break;
     275             :         default:
     276           0 :                 panic("route_usrreq");
     277             :         }
     278             : 
     279             :  release:
     280           0 :         m_freem(control);
     281           0 :         m_freem(m);
     282           0 :         return (error);
     283           0 : }
     284             : 
     285             : int
     286           0 : route_attach(struct socket *so, int proto)
     287             : {
     288             :         struct rtpcb    *rop;
     289             :         int              error;
     290             : 
     291             :         /*
     292             :          * use the rawcb but allocate a rtpcb, this
     293             :          * code does not care about the additional fields
     294             :          * and works directly on the raw socket.
     295             :          */
     296           0 :         rop = malloc(sizeof(struct rtpcb), M_PCB, M_WAITOK|M_ZERO);
     297           0 :         so->so_pcb = rop;
     298             :         /* Init the timeout structure */
     299           0 :         timeout_set(&rop->rop_timeout, rtm_senddesync_timer, so);
     300           0 :         refcnt_init(&rop->rop_refcnt);
     301             : 
     302           0 :         if (curproc == NULL)
     303           0 :                 error = EACCES;
     304             :         else
     305           0 :                 error = soreserve(so, ROUTESNDQ, ROUTERCVQ);
     306           0 :         if (error) {
     307           0 :                 free(rop, M_PCB, sizeof(struct rtpcb));
     308           0 :                 return (error);
     309             :         }
     310             : 
     311           0 :         rop->rop_socket = so;
     312           0 :         rop->rop_proto = proto;
     313             : 
     314           0 :         rop->rop_rtableid = curproc->p_p->ps_rtableid;
     315             : 
     316           0 :         soisconnected(so);
     317           0 :         so->so_options |= SO_USELOOPBACK;
     318             : 
     319           0 :         rw_enter(&rtptable.rtp_lk, RW_WRITE);
     320           0 :         SRPL_INSERT_HEAD_LOCKED(&rtptable.rtp_rc, &rtptable.rtp_list, rop, rop_list);
     321           0 :         rtptable.rtp_count++;
     322           0 :         rw_exit(&rtptable.rtp_lk);
     323             : 
     324           0 :         return (0);
     325           0 : }
     326             : 
     327             : int
     328           0 : route_detach(struct socket *so)
     329             : {
     330             :         struct rtpcb    *rop;
     331             : 
     332           0 :         soassertlocked(so);
     333             : 
     334           0 :         rop = sotortpcb(so);
     335           0 :         if (rop == NULL)
     336           0 :                 return (EINVAL);
     337             : 
     338           0 :         rw_enter(&rtptable.rtp_lk, RW_WRITE);
     339             : 
     340           0 :         timeout_del(&rop->rop_timeout);
     341           0 :         rtptable.rtp_count--;
     342             : 
     343           0 :         SRPL_REMOVE_LOCKED(&rtptable.rtp_rc, &rtptable.rtp_list, rop, rtpcb,
     344             :             rop_list);
     345           0 :         rw_exit(&rtptable.rtp_lk);
     346             : 
     347             :         /* wait for all references to drop */
     348           0 :         refcnt_finalize(&rop->rop_refcnt, "rtsockrefs");
     349             : 
     350           0 :         so->so_pcb = NULL;
     351           0 :         KASSERT((so->so_state & SS_NOFDREF) == 0);
     352           0 :         free(rop, M_PCB, sizeof(struct rtpcb));
     353             : 
     354           0 :         return (0);
     355           0 : }
     356             : 
     357             : int
     358           0 : route_ctloutput(int op, struct socket *so, int level, int optname,
     359             :     struct mbuf *m)
     360             : {
     361           0 :         struct rtpcb *rop = sotortpcb(so);
     362             :         int error = 0;
     363             :         unsigned int tid, prio;
     364             : 
     365           0 :         if (level != AF_ROUTE)
     366           0 :                 return (EINVAL);
     367             : 
     368           0 :         switch (op) {
     369             :         case PRCO_SETOPT:
     370           0 :                 switch (optname) {
     371             :                 case ROUTE_MSGFILTER:
     372           0 :                         if (m == NULL || m->m_len != sizeof(unsigned int))
     373           0 :                                 error = EINVAL;
     374             :                         else
     375           0 :                                 rop->rop_msgfilter = *mtod(m, unsigned int *);
     376             :                         break;
     377             :                 case ROUTE_TABLEFILTER:
     378           0 :                         if (m == NULL || m->m_len != sizeof(unsigned int)) {
     379             :                                 error = EINVAL;
     380           0 :                                 break;
     381             :                         }
     382           0 :                         tid = *mtod(m, unsigned int *);
     383           0 :                         if (tid != RTABLE_ANY && !rtable_exists(tid))
     384           0 :                                 error = ENOENT;
     385             :                         else
     386           0 :                                 rop->rop_rtableid = tid;
     387             :                         break;
     388             :                 case ROUTE_PRIOFILTER:
     389           0 :                         if (m == NULL || m->m_len != sizeof(unsigned int)) {
     390             :                                 error = EINVAL;
     391           0 :                                 break;
     392             :                         }
     393           0 :                         prio = *mtod(m, unsigned int *);
     394           0 :                         if (prio > RTP_MAX)
     395           0 :                                 error = EINVAL;
     396             :                         else
     397           0 :                                 rop->rop_priority = prio;
     398             :                         break;
     399             :                 default:
     400             :                         error = ENOPROTOOPT;
     401           0 :                         break;
     402             :                 }
     403             :                 break;
     404             :         case PRCO_GETOPT:
     405           0 :                 switch (optname) {
     406             :                 case ROUTE_MSGFILTER:
     407           0 :                         m->m_len = sizeof(unsigned int);
     408           0 :                         *mtod(m, unsigned int *) = rop->rop_msgfilter;
     409           0 :                         break;
     410             :                 case ROUTE_TABLEFILTER:
     411           0 :                         m->m_len = sizeof(unsigned int);
     412           0 :                         *mtod(m, unsigned int *) = rop->rop_rtableid;
     413           0 :                         break;
     414             :                 case ROUTE_PRIOFILTER:
     415           0 :                         m->m_len = sizeof(unsigned int);
     416           0 :                         *mtod(m, unsigned int *) = rop->rop_priority;
     417           0 :                         break;
     418             :                 default:
     419             :                         error = ENOPROTOOPT;
     420           0 :                         break;
     421             :                 }
     422             :         }
     423           0 :         return (error);
     424           0 : }
     425             : 
     426             : void
     427           0 : rtm_senddesync_timer(void *xso)
     428             : {
     429           0 :         struct socket   *so = xso;
     430             :         int              s;
     431             : 
     432           0 :         s = solock(so);
     433           0 :         rtm_senddesync(so);
     434           0 :         sounlock(so, s);
     435           0 : }
     436             : 
     437             : void
     438           0 : rtm_senddesync(struct socket *so)
     439             : {
     440           0 :         struct rtpcb    *rop = sotortpcb(so);
     441             :         struct mbuf     *desync_mbuf;
     442             : 
     443           0 :         soassertlocked(so);
     444             : 
     445             :         /* If we are in a DESYNC state, try to send a RTM_DESYNC packet */
     446           0 :         if ((rop->rop_flags & ROUTECB_FLAG_DESYNC) == 0)
     447           0 :                 return;
     448             : 
     449             :         /*
     450             :          * If we fail to alloc memory or if sbappendaddr()
     451             :          * fails, re-add timeout and try again.
     452             :          */
     453           0 :         desync_mbuf = rtm_msg1(RTM_DESYNC, NULL);
     454           0 :         if (desync_mbuf != NULL) {
     455           0 :                 if (sbappendaddr(so, &so->so_rcv, &route_src,
     456           0 :                     desync_mbuf, NULL) != 0) {
     457           0 :                         rop->rop_flags &= ~ROUTECB_FLAG_DESYNC;
     458           0 :                         sorwakeup(rop->rop_socket);
     459           0 :                         return;
     460             :                 }
     461           0 :                 m_freem(desync_mbuf);
     462           0 :         }
     463             :         /* Re-add timeout to try sending msg again */
     464           0 :         timeout_add(&rop->rop_timeout, ROUTE_DESYNC_RESEND_TIMEOUT);
     465           0 : }
     466             : 
     467             : void
     468           0 : route_input(struct mbuf *m0, struct socket *so0, sa_family_t sa_family)
     469             : {
     470             :         struct socket *so;
     471             :         struct rtpcb *rop;
     472             :         struct rt_msghdr *rtm;
     473             :         struct mbuf *m = m0;
     474             :         struct socket *last = NULL;
     475           0 :         struct srp_ref sr;
     476             :         int s;
     477             : 
     478             :         /* ensure that we can access the rtm_type via mtod() */
     479           0 :         if (m->m_len < offsetof(struct rt_msghdr, rtm_type) + 1) {
     480           0 :                 m_freem(m);
     481           0 :                 return;
     482             :         }
     483             : 
     484           0 :         SRPL_FOREACH(rop, &sr, &rtptable.rtp_list, rop_list) {
     485             :                 /*
     486             :                  * If route socket is bound to an address family only send
     487             :                  * messages that match the address family. Address family
     488             :                  * agnostic messages are always sent.
     489             :                  */
     490           0 :                 if (sa_family != AF_UNSPEC && rop->rop_proto != AF_UNSPEC &&
     491           0 :                     rop->rop_proto != sa_family)
     492             :                         continue;
     493             : 
     494             : 
     495           0 :                 so = rop->rop_socket;
     496           0 :                 s = solock(so);
     497             : 
     498             :                 /*
     499             :                  * Check to see if we don't want our own messages and
     500             :                  * if we can receive anything.
     501             :                  */
     502           0 :                 if ((so0 == so && !(so0->so_options & SO_USELOOPBACK)) ||
     503           0 :                     !(so->so_state & SS_ISCONNECTED) ||
     504           0 :                     (so->so_state & SS_CANTRCVMORE)) {
     505             : next:
     506           0 :                         sounlock(so, s);
     507           0 :                         continue;
     508             :                 }
     509             : 
     510             :                 /* filter messages that the process does not want */
     511           0 :                 rtm = mtod(m, struct rt_msghdr *);
     512             :                 /* but RTM_DESYNC can't be filtered */
     513           0 :                 if (rtm->rtm_type != RTM_DESYNC && rop->rop_msgfilter != 0 &&
     514           0 :                     !(rop->rop_msgfilter & (1 << rtm->rtm_type)))
     515             :                         goto next;
     516           0 :                 switch (rtm->rtm_type) {
     517             :                 case RTM_IFANNOUNCE:
     518             :                 case RTM_DESYNC:
     519             :                         /* no tableid */
     520             :                         break;
     521             :                 case RTM_RESOLVE:
     522             :                 case RTM_NEWADDR:
     523             :                 case RTM_DELADDR:
     524             :                 case RTM_IFINFO:
     525             :                 case RTM_BFD:
     526             :                         /* check against rdomain id */
     527           0 :                         if (rop->rop_rtableid != RTABLE_ANY &&
     528           0 :                             rtable_l2(rop->rop_rtableid) != rtm->rtm_tableid)
     529             :                                 goto next;
     530             :                         break;
     531             :                 default:
     532           0 :                         if (rop->rop_priority != 0 &&
     533           0 :                             rop->rop_priority < rtm->rtm_priority)
     534             :                                 goto next;
     535             :                         /* check against rtable id */
     536           0 :                         if (rop->rop_rtableid != RTABLE_ANY &&
     537           0 :                             rop->rop_rtableid != rtm->rtm_tableid)
     538             :                                 goto next;
     539             :                         break;
     540             :                 }
     541             : 
     542             :                 /*
     543             :                  * Check to see if the flush flag is set. If so, don't queue
     544             :                  * any more messages until the flag is cleared.
     545             :                  */
     546           0 :                 if ((rop->rop_flags & ROUTECB_FLAG_FLUSH) != 0)
     547             :                         goto next;
     548           0 :                 sounlock(so, s);
     549             : 
     550           0 :                 if (last) {
     551           0 :                         s = solock(last);
     552           0 :                         rtm_sendup(last, m, 1);
     553           0 :                         sounlock(last, s);
     554           0 :                         refcnt_rele_wake(&sotortpcb(last)->rop_refcnt);
     555           0 :                 }
     556             :                 /* keep a reference for last */
     557           0 :                 refcnt_take(&rop->rop_refcnt);
     558           0 :                 last = rop->rop_socket;
     559           0 :         }
     560           0 :         SRPL_LEAVE(&sr);
     561             : 
     562           0 :         if (last) {
     563           0 :                 s = solock(last);
     564           0 :                 rtm_sendup(last, m, 0);
     565           0 :                 sounlock(last, s);
     566           0 :                 refcnt_rele_wake(&sotortpcb(last)->rop_refcnt);
     567           0 :         } else
     568           0 :                 m_freem(m);
     569           0 : }
     570             : 
     571             : int
     572           0 : rtm_sendup(struct socket *so, struct mbuf *m0, int more)
     573             : {
     574           0 :         struct rtpcb *rop = sotortpcb(so);
     575             :         struct mbuf *m;
     576             : 
     577           0 :         soassertlocked(so);
     578             : 
     579           0 :         if (more) {
     580           0 :                 m = m_copym(m0, 0, M_COPYALL, M_NOWAIT);
     581           0 :                 if (m == NULL)
     582           0 :                         return (ENOMEM);
     583             :         } else
     584             :                 m = m0;
     585             : 
     586           0 :         if (sbspace(so, &so->so_rcv) < (2 * MSIZE) ||
     587           0 :             sbappendaddr(so, &so->so_rcv, &route_src, m, NULL) == 0) {
     588             :                 /* Flag socket as desync'ed and flush required */
     589           0 :                 rop->rop_flags |= ROUTECB_FLAG_DESYNC | ROUTECB_FLAG_FLUSH;
     590           0 :                 rtm_senddesync(so);
     591           0 :                 m_freem(m);
     592           0 :                 return (ENOBUFS);
     593             :         }
     594             : 
     595           0 :         sorwakeup(so);
     596           0 :         return (0);
     597           0 : }
     598             : 
     599             : struct rt_msghdr *
     600           0 : rtm_report(struct rtentry *rt, u_char type, int seq, int tableid)
     601             : {
     602             :         struct rt_msghdr        *rtm;
     603           0 :         struct rt_addrinfo       info;
     604           0 :         struct sockaddr_rtlabel  sa_rl;
     605           0 :         struct sockaddr_in6      sa_mask;
     606             : #ifdef BFD
     607             :         struct sockaddr_bfd      sa_bfd;
     608             : #endif
     609             :         struct ifnet            *ifp = NULL;
     610             :         int                      len;
     611             : 
     612           0 :         bzero(&info, sizeof(info));
     613           0 :         info.rti_info[RTAX_DST] = rt_key(rt);
     614           0 :         info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
     615           0 :         info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask);
     616           0 :         info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
     617             : #ifdef BFD
     618             :         if (rt->rt_flags & RTF_BFD)
     619             :                 info.rti_info[RTAX_BFD] = bfd2sa(rt, &sa_bfd);
     620             : #endif
     621             : #ifdef MPLS
     622           0 :         if (rt->rt_flags & RTF_MPLS) {
     623           0 :                 struct sockaddr_mpls     sa_mpls;
     624             : 
     625           0 :                 bzero(&sa_mpls, sizeof(sa_mpls));
     626           0 :                 sa_mpls.smpls_family = AF_MPLS;
     627           0 :                 sa_mpls.smpls_len = sizeof(sa_mpls);
     628           0 :                 sa_mpls.smpls_label = ((struct rt_mpls *)
     629           0 :                     rt->rt_llinfo)->mpls_label;
     630           0 :                 info.rti_info[RTAX_SRC] = (struct sockaddr *)&sa_mpls;
     631           0 :                 info.rti_mpls = ((struct rt_mpls *)
     632           0 :                     rt->rt_llinfo)->mpls_operation;
     633           0 :         }
     634             : #endif
     635           0 :         ifp = if_get(rt->rt_ifidx);
     636           0 :         if (ifp != NULL) {
     637           0 :                 info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl);
     638           0 :                 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
     639           0 :                 if (ifp->if_flags & IFF_POINTOPOINT)
     640           0 :                         info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr;
     641             :         }
     642           0 :         if_put(ifp);
     643             :         /* RTAX_GENMASK, RTAX_AUTHOR, RTAX_SRCMASK ignored */
     644             : 
     645             :         /* build new route message */
     646           0 :         len = rtm_msg2(type, RTM_VERSION, &info, NULL, NULL);
     647           0 :         rtm = malloc(len, M_RTABLE, M_WAITOK | M_ZERO);
     648             : 
     649           0 :         rtm_msg2(type, RTM_VERSION, &info, (caddr_t)rtm, NULL);
     650           0 :         rtm->rtm_type = type;
     651           0 :         rtm->rtm_index = rt->rt_ifidx;
     652           0 :         rtm->rtm_tableid = tableid;
     653           0 :         rtm->rtm_priority = rt->rt_priority & RTP_MASK;
     654           0 :         rtm->rtm_flags = rt->rt_flags;
     655           0 :         rtm->rtm_pid = curproc->p_p->ps_pid;
     656           0 :         rtm->rtm_seq = seq;
     657           0 :         rtm_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
     658           0 :         rtm->rtm_addrs = info.rti_addrs;
     659             : #ifdef MPLS
     660           0 :         rtm->rtm_mpls = info.rti_mpls;
     661             : #endif
     662           0 :         return rtm;
     663           0 : }
     664             : 
     665             : int
     666           0 : route_output(struct mbuf *m, struct socket *so, struct sockaddr *dstaddr,
     667             :     struct mbuf *control)
     668             : {
     669             :         struct rt_msghdr        *rtm = NULL;
     670           0 :         struct rtentry          *rt = NULL;
     671           0 :         struct rt_addrinfo       info;
     672             :         int                      len, seq, error = 0;
     673             :         u_int                    tableid;
     674             :         u_int8_t                 prio;
     675             :         u_char                   vers, type;
     676             : 
     677           0 :         if (m == NULL || ((m->m_len < sizeof(int32_t)) &&
     678           0 :             (m = m_pullup(m, sizeof(int32_t))) == 0))
     679           0 :                 return (ENOBUFS);
     680           0 :         if ((m->m_flags & M_PKTHDR) == 0)
     681           0 :                 panic("route_output");
     682           0 :         len = m->m_pkthdr.len;
     683           0 :         if (len < offsetof(struct rt_msghdr, rtm_type) + 1 ||
     684           0 :             len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
     685             :                 error = EINVAL;
     686           0 :                 goto fail;
     687             :         }
     688           0 :         vers = mtod(m, struct rt_msghdr *)->rtm_version;
     689           0 :         switch (vers) {
     690             :         case RTM_VERSION:
     691           0 :                 if (len < sizeof(struct rt_msghdr)) {
     692             :                         error = EINVAL;
     693           0 :                         goto fail;
     694             :                 }
     695           0 :                 if (len > RTM_MAXSIZE) {
     696             :                         error = EMSGSIZE;
     697           0 :                         goto fail;
     698             :                 }
     699           0 :                 rtm = malloc(len, M_RTABLE, M_WAITOK);
     700           0 :                 m_copydata(m, 0, len, (caddr_t)rtm);
     701             :                 break;
     702             :         default:
     703             :                 error = EPROTONOSUPPORT;
     704           0 :                 goto fail;
     705             :         }
     706           0 :         rtm->rtm_pid = curproc->p_p->ps_pid;
     707           0 :         if (rtm->rtm_hdrlen == 0)    /* old client */
     708           0 :                 rtm->rtm_hdrlen = sizeof(struct rt_msghdr);
     709           0 :         if (len < rtm->rtm_hdrlen) {
     710             :                 error = EINVAL;
     711           0 :                 goto fail;
     712             :         }
     713             : 
     714             :         /* Verify that the caller is sending an appropriate message early */
     715           0 :         switch (rtm->rtm_type) {
     716             :         case RTM_ADD:
     717             :         case RTM_DELETE:
     718             :         case RTM_GET:
     719             :         case RTM_CHANGE:
     720             :         case RTM_PROPOSAL:
     721             :                 break;
     722             :         default:
     723             :                 error = EOPNOTSUPP;
     724           0 :                 goto fail;
     725             :         }
     726             : 
     727             :         /*
     728             :          * Verify that the caller has the appropriate privilege; RTM_GET
     729             :          * is the only operation the non-superuser is allowed.
     730             :          */
     731           0 :         if (rtm->rtm_type != RTM_GET && suser(curproc) != 0) {
     732             :                 error = EACCES;
     733           0 :                 goto fail;
     734             :         }
     735           0 :         tableid = rtm->rtm_tableid;
     736           0 :         if (!rtable_exists(tableid)) {
     737           0 :                 if (rtm->rtm_type == RTM_ADD) {
     738           0 :                         if ((error = rtable_add(tableid)) != 0)
     739             :                                 goto fail;
     740             :                 } else {
     741             :                         error = EINVAL;
     742           0 :                         goto fail;
     743             :                 }
     744             :         }
     745             : 
     746             : 
     747             :         /* Do not let userland play with kernel-only flags. */
     748           0 :         if ((rtm->rtm_flags & (RTF_LOCAL|RTF_BROADCAST)) != 0) {
     749             :                 error = EINVAL;
     750           0 :                 goto fail;
     751             :         }
     752             : 
     753             :         /* make sure that kernel-only bits are not set */
     754           0 :         rtm->rtm_priority &= RTP_MASK;
     755           0 :         rtm->rtm_flags &= ~(RTF_DONE|RTF_CLONED|RTF_CACHED);
     756           0 :         rtm->rtm_fmask &= RTF_FMASK;
     757             : 
     758           0 :         if (rtm->rtm_priority != 0) {
     759           0 :                 if (rtm->rtm_priority > RTP_MAX ||
     760           0 :                     rtm->rtm_priority == RTP_LOCAL) {
     761             :                         error = EINVAL;
     762           0 :                         goto fail;
     763             :                 }
     764             :                 prio = rtm->rtm_priority;
     765           0 :         } else if (rtm->rtm_type != RTM_ADD)
     766           0 :                 prio = RTP_ANY;
     767           0 :         else if (rtm->rtm_flags & RTF_STATIC)
     768           0 :                 prio = 0;
     769             :         else
     770             :                 prio = RTP_DEFAULT;
     771             : 
     772           0 :         bzero(&info, sizeof(info));
     773           0 :         info.rti_addrs = rtm->rtm_addrs;
     774           0 :         rtm_xaddrs(rtm->rtm_hdrlen + (caddr_t)rtm, len + (caddr_t)rtm, &info);
     775           0 :         info.rti_flags = rtm->rtm_flags;
     776           0 :         if (rtm->rtm_type != RTM_PROPOSAL &&
     777           0 :            (info.rti_info[RTAX_DST] == NULL ||
     778           0 :             info.rti_info[RTAX_DST]->sa_family >= AF_MAX ||
     779           0 :             (info.rti_info[RTAX_GATEWAY] != NULL &&
     780           0 :             info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX) ||
     781           0 :             info.rti_info[RTAX_GENMASK] != NULL)) {
     782             :                 error = EINVAL;
     783           0 :                 goto fail;
     784             :         }
     785             : #ifdef MPLS
     786           0 :         info.rti_mpls = rtm->rtm_mpls;
     787             : #endif
     788             : 
     789           0 :         if (info.rti_info[RTAX_GATEWAY] != NULL &&
     790           0 :             info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK &&
     791           0 :             (info.rti_flags & RTF_CLONING) == 0) {
     792           0 :                 info.rti_flags |= RTF_LLINFO;
     793           0 :         }
     794             : 
     795             :         /*
     796             :          * Validate RTM_PROPOSAL and pass it along or error out.
     797             :          */
     798           0 :         if (rtm->rtm_type == RTM_PROPOSAL) {
     799           0 :                 if (rtm_validate_proposal(&info) == -1) {
     800             :                         error = EINVAL;
     801           0 :                         goto fail;
     802             :                 }
     803             :         } else {
     804           0 :                 error = rtm_output(rtm, &rt, &info, prio, tableid);
     805           0 :                 if (!error) {
     806           0 :                         type = rtm->rtm_type;
     807           0 :                         seq = rtm->rtm_seq;
     808           0 :                         free(rtm, M_RTABLE, len);
     809           0 :                         rtm = rtm_report(rt, type, seq, tableid);
     810           0 :                         len = rtm->rtm_msglen;
     811           0 :                 }
     812             :         }
     813             : 
     814           0 :         rtfree(rt);
     815           0 :         if (error) {
     816           0 :                 rtm->rtm_errno = error;
     817           0 :         } else {
     818           0 :                 rtm->rtm_flags |= RTF_DONE;
     819             :         }
     820             : 
     821             :         /*
     822             :          * Check to see if we don't want our own messages.
     823             :          */
     824           0 :         if (!(so->so_options & SO_USELOOPBACK)) {
     825           0 :                 if (rtptable.rtp_count <= 1) {
     826             :                         /* no other listener and no loopback of messages */
     827             : fail:
     828           0 :                         free(rtm, M_RTABLE, len);
     829           0 :                         m_freem(m);
     830           0 :                         return (error);
     831             :                 }
     832             :         }
     833           0 :         if (rtm) {
     834           0 :                 if (m_copyback(m, 0, len, rtm, M_NOWAIT)) {
     835           0 :                         m_freem(m);
     836             :                         m = NULL;
     837           0 :                 } else if (m->m_pkthdr.len > len)
     838           0 :                         m_adj(m, len - m->m_pkthdr.len);
     839           0 :                 free(rtm, M_RTABLE, len);
     840           0 :         }
     841           0 :         if (m)
     842           0 :                 route_input(m, so, info.rti_info[RTAX_DST] ?
     843           0 :                     info.rti_info[RTAX_DST]->sa_family : AF_UNSPEC);
     844             : 
     845           0 :         return (error);
     846           0 : }
     847             : 
     848             : int
     849           0 : rtm_output(struct rt_msghdr *rtm, struct rtentry **prt,
     850             :     struct rt_addrinfo *info, uint8_t prio, unsigned int tableid)
     851             : {
     852           0 :         struct rtentry          *rt = *prt;
     853             :         struct ifnet            *ifp = NULL;
     854             :         int                      plen, newgate = 0, error = 0;
     855             : 
     856           0 :         switch (rtm->rtm_type) {
     857             :         case RTM_ADD:
     858           0 :                 if (info->rti_info[RTAX_GATEWAY] == NULL) {
     859             :                         error = EINVAL;
     860           0 :                         break;
     861             :                 }
     862             : 
     863           0 :                 rt = rtable_match(tableid, info->rti_info[RTAX_DST], NULL);
     864           0 :                 if ((error = route_arp_conflict(rt, info))) {
     865           0 :                         rtfree(rt);
     866           0 :                         rt = NULL;
     867           0 :                         break;
     868             :                 }
     869             : 
     870             :                 /*
     871             :                  * We cannot go through a delete/create/insert cycle for
     872             :                  * cached route because this can lead to races in the
     873             :                  * receive path.  Instead we update the L2 cache.
     874             :                  */
     875           0 :                 if ((rt != NULL) && ISSET(rt->rt_flags, RTF_CACHED))
     876             :                         goto change;
     877             : 
     878           0 :                 rtfree(rt);
     879           0 :                 rt = NULL;
     880             : 
     881           0 :                 NET_LOCK();
     882           0 :                 if ((error = rtm_getifa(info, tableid)) != 0) {
     883           0 :                         NET_UNLOCK();
     884           0 :                         break;
     885             :                 }
     886           0 :                 error = rtrequest(RTM_ADD, info, prio, &rt, tableid);
     887           0 :                 NET_UNLOCK();
     888           0 :                 if (error == 0)
     889           0 :                         rtm_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
     890           0 :                             &rt->rt_rmx);
     891             :                 break;
     892             :         case RTM_DELETE:
     893           0 :                 rt = rtable_lookup(tableid, info->rti_info[RTAX_DST],
     894           0 :                     info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY],
     895             :                     prio);
     896           0 :                 if (rt == NULL) {
     897             :                         error = ESRCH;
     898           0 :                         break;
     899             :                 }
     900             : 
     901             :                 /*
     902             :                  * If we got multipath routes, we require users to specify
     903             :                  * a matching gateway.
     904             :                  */
     905           0 :                 if (ISSET(rt->rt_flags, RTF_MPATH) &&
     906           0 :                     info->rti_info[RTAX_GATEWAY] == NULL) {
     907             :                         error = ESRCH;
     908           0 :                         break;
     909             :                 }
     910             : 
     911             :                 /* Detaching an interface requires the KERNEL_LOCK(). */
     912           0 :                 ifp = if_get(rt->rt_ifidx);
     913           0 :                 KASSERT(ifp != NULL);
     914             : 
     915             :                 /*
     916             :                  * Invalidate the cache of automagically created and
     917             :                  * referenced L2 entries to make sure that ``rt_gwroute''
     918             :                  * pointer stays valid for other CPUs.
     919             :                  */
     920           0 :                 if ((ISSET(rt->rt_flags, RTF_CACHED))) {
     921           0 :                         NET_LOCK();
     922           0 :                         ifp->if_rtrequest(ifp, RTM_INVALIDATE, rt);
     923             :                         /* Reset the MTU of the gateway route. */
     924           0 :                         rtable_walk(tableid, rt_key(rt)->sa_family,
     925           0 :                             route_cleargateway, rt);
     926           0 :                         NET_UNLOCK();
     927           0 :                         if_put(ifp);
     928           0 :                         break;
     929             :                 }
     930             : 
     931             :                 /*
     932             :                  * Make sure that local routes are only modified by the
     933             :                  * kernel.
     934             :                  */
     935           0 :                 if (ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)) {
     936           0 :                         if_put(ifp);
     937             :                         error = EINVAL;
     938           0 :                         break;
     939             :                 }
     940             : 
     941           0 :                 rtfree(rt);
     942           0 :                 rt = NULL;
     943             : 
     944           0 :                 NET_LOCK();
     945           0 :                 error = rtrequest_delete(info, prio, ifp, &rt, tableid);
     946           0 :                 NET_UNLOCK();
     947           0 :                 if_put(ifp);
     948           0 :                 break;
     949             :         case RTM_CHANGE:
     950           0 :                 rt = rtable_lookup(tableid, info->rti_info[RTAX_DST],
     951           0 :                     info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY],
     952             :                     prio);
     953             :                 /*
     954             :                  * If we got multipath routes, we require users to specify
     955             :                  * a matching gateway.
     956             :                  */
     957           0 :                 if ((rt != NULL) && ISSET(rt->rt_flags, RTF_MPATH) &&
     958           0 :                     (info->rti_info[RTAX_GATEWAY] == NULL)) {
     959           0 :                         rtfree(rt);
     960           0 :                         rt = NULL;
     961           0 :                 }
     962             :                 /*
     963             :                  * If RTAX_GATEWAY is the argument we're trying to
     964             :                  * change, try to find a compatible route.
     965             :                  */
     966           0 :                 if ((rt == NULL) && (info->rti_info[RTAX_GATEWAY] != NULL) &&
     967           0 :                     (rtm->rtm_type == RTM_CHANGE)) {
     968           0 :                         rt = rtable_lookup(tableid, info->rti_info[RTAX_DST],
     969           0 :                             info->rti_info[RTAX_NETMASK], NULL, prio);
     970             :                         /* Ensure we don't pick a multipath one. */
     971           0 :                         if ((rt != NULL) && ISSET(rt->rt_flags, RTF_MPATH)) {
     972           0 :                                 rtfree(rt);
     973           0 :                                 rt = NULL;
     974           0 :                         }
     975             :                 }
     976             : 
     977           0 :                 if (rt == NULL) {
     978             :                         error = ESRCH;
     979           0 :                         break;
     980             :                 }
     981             : 
     982             :                 /*
     983             :                  * Make sure that local routes are only modified by the
     984             :                  * kernel.
     985             :                  */
     986           0 :                 if (ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)) {
     987             :                         error = EINVAL;
     988           0 :                         break;
     989             :                 }
     990             : 
     991             :                 /*
     992             :                  * RTM_CHANGE/LOCK need a perfect match.
     993             :                  */
     994           0 :                 plen = rtable_satoplen(info->rti_info[RTAX_DST]->sa_family,
     995           0 :                     info->rti_info[RTAX_NETMASK]);
     996           0 :                 if (rt_plen(rt) != plen) {
     997             :                         error = ESRCH;
     998           0 :                         break;
     999             :                 }
    1000             : 
    1001           0 :                 switch (rtm->rtm_type) {
    1002             :                 case RTM_CHANGE:
    1003           0 :                         if (info->rti_info[RTAX_GATEWAY] != NULL)
    1004           0 :                                 if (rt->rt_gateway == NULL ||
    1005           0 :                                     bcmp(rt->rt_gateway,
    1006           0 :                                     info->rti_info[RTAX_GATEWAY],
    1007           0 :                                     info->rti_info[RTAX_GATEWAY]->sa_len)) {
    1008             :                                         newgate = 1;
    1009           0 :                                 }
    1010             :                         /*
    1011             :                          * Check reachable gateway before changing the route.
    1012             :                          * New gateway could require new ifaddr, ifp;
    1013             :                          * flags may also be different; ifp may be specified
    1014             :                          * by ll sockaddr when protocol address is ambiguous.
    1015             :                          */
    1016           0 :                         if (newgate || info->rti_info[RTAX_IFP] != NULL ||
    1017           0 :                             info->rti_info[RTAX_IFA] != NULL) {
    1018             :                                 struct ifaddr   *ifa = NULL;
    1019             : 
    1020           0 :                                 NET_LOCK();
    1021           0 :                                 if ((error = rtm_getifa(info, tableid)) != 0) {
    1022           0 :                                         NET_UNLOCK();
    1023           0 :                                         break;
    1024             :                                 }
    1025           0 :                                 ifa = info->rti_ifa;
    1026           0 :                                 if (rt->rt_ifa != ifa) {
    1027           0 :                                         ifp = if_get(rt->rt_ifidx);
    1028           0 :                                         KASSERT(ifp != NULL);
    1029           0 :                                         ifp->if_rtrequest(ifp, RTM_DELETE, rt);
    1030           0 :                                         ifafree(rt->rt_ifa);
    1031           0 :                                         if_put(ifp);
    1032             : 
    1033           0 :                                         ifa->ifa_refcnt++;
    1034           0 :                                         rt->rt_ifa = ifa;
    1035           0 :                                         rt->rt_ifidx = ifa->ifa_ifp->if_index;
    1036             :                                         /* recheck link state after ifp change*/
    1037           0 :                                         rt_if_linkstate_change(rt, ifa->ifa_ifp,
    1038             :                                             tableid);
    1039           0 :                                 }
    1040           0 :                                 NET_UNLOCK();
    1041           0 :                         }
    1042             : change:
    1043           0 :                         if (info->rti_info[RTAX_GATEWAY] != NULL) {
    1044             :                                 /*
    1045             :                                  * When updating the gateway, make sure it's
    1046             :                                  * valid.
    1047             :                                  */
    1048           0 :                                 if (!newgate && rt->rt_gateway->sa_family !=
    1049           0 :                                     info->rti_info[RTAX_GATEWAY]->sa_family) {
    1050             :                                         error = EINVAL;
    1051           0 :                                         break;
    1052             :                                 }
    1053             : 
    1054           0 :                                 NET_LOCK();
    1055           0 :                                 error = rt_setgate(rt,
    1056           0 :                                     info->rti_info[RTAX_GATEWAY], tableid);
    1057           0 :                                 NET_UNLOCK();
    1058           0 :                                 if (error)
    1059             :                                         break;
    1060             :                         }
    1061             : #ifdef MPLS
    1062           0 :                         if ((rtm->rtm_flags & RTF_MPLS) &&
    1063           0 :                             info->rti_info[RTAX_SRC] != NULL) {
    1064           0 :                                 NET_LOCK();
    1065           0 :                                 error = rt_mpls_set(rt,
    1066           0 :                                     info->rti_info[RTAX_SRC], info->rti_mpls);
    1067           0 :                                 NET_UNLOCK();
    1068           0 :                                 if (error)
    1069             :                                         break;
    1070           0 :                         } else if (newgate || ((rtm->rtm_fmask & RTF_MPLS) &&
    1071           0 :                             !(rtm->rtm_flags & RTF_MPLS))) {
    1072           0 :                                 NET_LOCK();
    1073             :                                 /* if gateway changed remove MPLS information */
    1074           0 :                                 rt_mpls_clear(rt);
    1075           0 :                                 NET_UNLOCK();
    1076           0 :                         }
    1077             : #endif
    1078             : 
    1079             : #ifdef BFD
    1080             :                         if (ISSET(rtm->rtm_flags, RTF_BFD)) {
    1081             :                                 if ((error = bfdset(rt)))
    1082             :                                         break;
    1083             :                         } else if (!ISSET(rtm->rtm_flags, RTF_BFD) &&
    1084             :                             ISSET(rtm->rtm_fmask, RTF_BFD)) {
    1085             :                                 bfdclear(rt);
    1086             :                         }
    1087             : #endif
    1088             : 
    1089           0 :                         NET_LOCK();
    1090             :                         /* Hack to allow some flags to be toggled */
    1091           0 :                         if (rtm->rtm_fmask)
    1092           0 :                                 rt->rt_flags =
    1093           0 :                                     (rt->rt_flags & ~rtm->rtm_fmask) |
    1094           0 :                                     (rtm->rtm_flags & rtm->rtm_fmask);
    1095             : 
    1096           0 :                         rtm_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
    1097           0 :                             &rt->rt_rmx);
    1098             : 
    1099           0 :                         ifp = if_get(rt->rt_ifidx);
    1100           0 :                         KASSERT(ifp != NULL);
    1101           0 :                         ifp->if_rtrequest(ifp, RTM_ADD, rt);
    1102           0 :                         if_put(ifp);
    1103             : 
    1104           0 :                         if (info->rti_info[RTAX_LABEL] != NULL) {
    1105           0 :                                 char *rtlabel = ((struct sockaddr_rtlabel *)
    1106           0 :                                     info->rti_info[RTAX_LABEL])->sr_label;
    1107           0 :                                 rtlabel_unref(rt->rt_labelid);
    1108           0 :                                 rt->rt_labelid = rtlabel_name2id(rtlabel);
    1109           0 :                         }
    1110           0 :                         if_group_routechange(info->rti_info[RTAX_DST],
    1111           0 :                             info->rti_info[RTAX_NETMASK]);
    1112           0 :                         rt->rt_locks &= ~(rtm->rtm_inits);
    1113           0 :                         rt->rt_locks |=
    1114           0 :                             (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
    1115           0 :                         NET_UNLOCK();
    1116           0 :                         break;
    1117             :                 }
    1118             :                 break;
    1119             :         case RTM_GET:
    1120           0 :                 rt = rtable_lookup(tableid, info->rti_info[RTAX_DST],
    1121           0 :                     info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY],
    1122             :                     prio);
    1123           0 :                 if (rt == NULL)
    1124           0 :                         error = ESRCH;
    1125             :                 break;
    1126             :         }
    1127             : 
    1128           0 :         *prt = rt;
    1129           0 :         return (error);
    1130           0 : }
    1131             : 
    1132             : struct ifaddr *
    1133           0 : ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway,
    1134             :     unsigned int rtableid)
    1135             : {
    1136             :         struct ifaddr   *ifa;
    1137             : 
    1138           0 :         if ((flags & RTF_GATEWAY) == 0) {
    1139             :                 /*
    1140             :                  * If we are adding a route to an interface,
    1141             :                  * and the interface is a pt to pt link
    1142             :                  * we should search for the destination
    1143             :                  * as our clue to the interface.  Otherwise
    1144             :                  * we can use the local address.
    1145             :                  */
    1146             :                 ifa = NULL;
    1147           0 :                 if (flags & RTF_HOST)
    1148           0 :                         ifa = ifa_ifwithdstaddr(dst, rtableid);
    1149           0 :                 if (ifa == NULL)
    1150           0 :                         ifa = ifa_ifwithaddr(gateway, rtableid);
    1151             :         } else {
    1152             :                 /*
    1153             :                  * If we are adding a route to a remote net
    1154             :                  * or host, the gateway may still be on the
    1155             :                  * other end of a pt to pt link.
    1156             :                  */
    1157           0 :                 ifa = ifa_ifwithdstaddr(gateway, rtableid);
    1158             :         }
    1159           0 :         if (ifa == NULL) {
    1160           0 :                 if (gateway->sa_family == AF_LINK) {
    1161           0 :                         struct sockaddr_dl *sdl = satosdl(gateway);
    1162           0 :                         struct ifnet *ifp = if_get(sdl->sdl_index);
    1163             : 
    1164           0 :                         if (ifp != NULL)
    1165           0 :                                 ifa = ifaof_ifpforaddr(dst, ifp);
    1166           0 :                         if_put(ifp);
    1167           0 :                 } else {
    1168             :                         struct rtentry *rt;
    1169             : 
    1170           0 :                         rt = rtalloc(gateway, RT_RESOLVE, rtable_l2(rtableid));
    1171           0 :                         if (rt != NULL)
    1172           0 :                                 ifa = rt->rt_ifa;
    1173           0 :                         rtfree(rt);
    1174             :                 }
    1175             :         }
    1176           0 :         if (ifa == NULL)
    1177           0 :                 return (NULL);
    1178           0 :         if (ifa->ifa_addr->sa_family != dst->sa_family) {
    1179             :                 struct ifaddr   *oifa = ifa;
    1180           0 :                 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
    1181           0 :                 if (ifa == NULL)
    1182           0 :                         ifa = oifa;
    1183           0 :         }
    1184           0 :         return (ifa);
    1185           0 : }
    1186             : 
    1187             : int
    1188           0 : rtm_getifa(struct rt_addrinfo *info, unsigned int rtid)
    1189             : {
    1190             :         struct ifnet    *ifp = NULL;
    1191             : 
    1192             :         /*
    1193             :          * The "returned" `ifa' is guaranteed to be alive only if
    1194             :          * the NET_LOCK() is held.
    1195             :          */
    1196           0 :         NET_ASSERT_LOCKED();
    1197             : 
    1198             :         /*
    1199             :          * ifp may be specified by sockaddr_dl when protocol address
    1200             :          * is ambiguous
    1201             :          */
    1202           0 :         if (info->rti_info[RTAX_IFP] != NULL) {
    1203             :                 struct sockaddr_dl *sdl;
    1204             : 
    1205           0 :                 sdl = satosdl(info->rti_info[RTAX_IFP]);
    1206           0 :                 ifp = if_get(sdl->sdl_index);
    1207           0 :         }
    1208             : 
    1209             : #ifdef IPSEC
    1210             :         /*
    1211             :          * If the destination is a PF_KEY address, we'll look
    1212             :          * for the existence of a encap interface number or address
    1213             :          * in the options list of the gateway. By default, we'll return
    1214             :          * enc0.
    1215             :          */
    1216           0 :         if (info->rti_info[RTAX_DST] &&
    1217           0 :             info->rti_info[RTAX_DST]->sa_family == PF_KEY)
    1218           0 :                 info->rti_ifa = enc_getifa(rtid, 0);
    1219             : #endif
    1220             : 
    1221           0 :         if (info->rti_ifa == NULL && info->rti_info[RTAX_IFA] != NULL)
    1222           0 :                 info->rti_ifa = ifa_ifwithaddr(info->rti_info[RTAX_IFA], rtid);
    1223             : 
    1224           0 :         if (info->rti_ifa == NULL) {
    1225             :                 struct sockaddr *sa;
    1226             : 
    1227           0 :                 if ((sa = info->rti_info[RTAX_IFA]) == NULL)
    1228           0 :                         if ((sa = info->rti_info[RTAX_GATEWAY]) == NULL)
    1229           0 :                                 sa = info->rti_info[RTAX_DST];
    1230             : 
    1231           0 :                 if (sa != NULL && ifp != NULL)
    1232           0 :                         info->rti_ifa = ifaof_ifpforaddr(sa, ifp);
    1233           0 :                 else if (info->rti_info[RTAX_DST] != NULL &&
    1234           0 :                     info->rti_info[RTAX_GATEWAY] != NULL)
    1235           0 :                         info->rti_ifa = ifa_ifwithroute(info->rti_flags,
    1236             :                             info->rti_info[RTAX_DST],
    1237             :                             info->rti_info[RTAX_GATEWAY],
    1238             :                             rtid);
    1239           0 :                 else if (sa != NULL)
    1240           0 :                         info->rti_ifa = ifa_ifwithroute(info->rti_flags,
    1241             :                             sa, sa, rtid);
    1242           0 :         }
    1243             : 
    1244           0 :         if_put(ifp);
    1245             : 
    1246           0 :         if (info->rti_ifa == NULL)
    1247           0 :                 return (ENETUNREACH);
    1248             : 
    1249           0 :         return (0);
    1250           0 : }
    1251             : 
    1252             : int
    1253           0 : route_cleargateway(struct rtentry *rt, void *arg, unsigned int rtableid)
    1254             : {
    1255           0 :         struct rtentry *nhrt = arg;
    1256             : 
    1257           0 :         if (ISSET(rt->rt_flags, RTF_GATEWAY) && rt->rt_gwroute == nhrt &&
    1258           0 :             !ISSET(rt->rt_locks, RTV_MTU))
    1259           0 :                 rt->rt_mtu = 0;
    1260             : 
    1261           0 :         return (0);
    1262             : }
    1263             : 
    1264             : /*
    1265             :  * Check if the user request to insert an ARP entry does not conflict
    1266             :  * with existing ones.
    1267             :  *
    1268             :  * Only two entries are allowed for a given IP address: a private one
    1269             :  * (priv) and a public one (pub).
    1270             :  */
    1271             : int
    1272           0 : route_arp_conflict(struct rtentry *rt, struct rt_addrinfo *info)
    1273             : {
    1274           0 :         int              proxy = (info->rti_flags & RTF_ANNOUNCE);
    1275             : 
    1276           0 :         if ((info->rti_flags & RTF_LLINFO) == 0 ||
    1277           0 :             (info->rti_info[RTAX_DST]->sa_family != AF_INET))
    1278           0 :                 return (0);
    1279             : 
    1280           0 :         if (rt == NULL || !ISSET(rt->rt_flags, RTF_LLINFO))
    1281           0 :                 return (0);
    1282             : 
    1283             :         /* If the entry is cached, it can be updated. */
    1284           0 :         if (ISSET(rt->rt_flags, RTF_CACHED))
    1285           0 :                 return (0);
    1286             : 
    1287             :         /*
    1288             :          * Same destination, not cached and both "priv" or "pub" conflict.
    1289             :          * If a second entry exists, it always conflict.
    1290             :          */
    1291           0 :         if ((ISSET(rt->rt_flags, RTF_ANNOUNCE) == proxy) ||
    1292           0 :             ISSET(rt->rt_flags, RTF_MPATH))
    1293           0 :                 return (EEXIST);
    1294             : 
    1295             :         /* No conflict but an entry exist so we need to force mpath. */
    1296           0 :         info->rti_flags |= RTF_MPATH;
    1297           0 :         return (0);
    1298           0 : }
    1299             : 
    1300             : void
    1301           0 : rtm_setmetrics(u_long which, const struct rt_metrics *in,
    1302             :     struct rt_kmetrics *out)
    1303             : {
    1304             :         int64_t expire;
    1305             : 
    1306           0 :         if (which & RTV_MTU)
    1307           0 :                 out->rmx_mtu = in->rmx_mtu;
    1308           0 :         if (which & RTV_EXPIRE) {
    1309           0 :                 expire = in->rmx_expire;
    1310           0 :                 if (expire != 0) {
    1311           0 :                         expire -= time_second;
    1312           0 :                         expire += time_uptime;
    1313           0 :                 }
    1314             : 
    1315           0 :                 out->rmx_expire = expire;
    1316           0 :         }
    1317           0 : }
    1318             : 
    1319             : void
    1320           0 : rtm_getmetrics(const struct rt_kmetrics *in, struct rt_metrics *out)
    1321             : {
    1322             :         int64_t expire;
    1323             : 
    1324           0 :         expire = in->rmx_expire;
    1325           0 :         if (expire != 0) {
    1326           0 :                 expire -= time_uptime;
    1327           0 :                 expire += time_second;
    1328           0 :         }
    1329             : 
    1330           0 :         bzero(out, sizeof(*out));
    1331           0 :         out->rmx_locks = in->rmx_locks;
    1332           0 :         out->rmx_mtu = in->rmx_mtu;
    1333           0 :         out->rmx_expire = expire;
    1334           0 :         out->rmx_pksent = in->rmx_pksent;
    1335           0 : }
    1336             : 
    1337             : #define ROUNDUP(a) \
    1338             :         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
    1339             : #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
    1340             : 
    1341             : void
    1342           0 : rtm_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
    1343             : {
    1344             :         struct sockaddr *sa;
    1345             :         int              i;
    1346             : 
    1347           0 :         bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
    1348           0 :         for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
    1349           0 :                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
    1350             :                         continue;
    1351           0 :                 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
    1352           0 :                 ADVANCE(cp, sa);
    1353           0 :         }
    1354           0 : }
    1355             : 
    1356             : struct mbuf *
    1357           0 : rtm_msg1(int type, struct rt_addrinfo *rtinfo)
    1358             : {
    1359             :         struct rt_msghdr        *rtm;
    1360             :         struct mbuf             *m;
    1361             :         int                      i;
    1362             :         struct sockaddr         *sa;
    1363             :         int                      len, dlen, hlen;
    1364             : 
    1365           0 :         switch (type) {
    1366             :         case RTM_DELADDR:
    1367             :         case RTM_NEWADDR:
    1368             :                 len = sizeof(struct ifa_msghdr);
    1369           0 :                 break;
    1370             :         case RTM_IFINFO:
    1371             :                 len = sizeof(struct if_msghdr);
    1372           0 :                 break;
    1373             :         case RTM_IFANNOUNCE:
    1374             :                 len = sizeof(struct if_announcemsghdr);
    1375           0 :                 break;
    1376             : #ifdef BFD
    1377             :         case RTM_BFD:
    1378             :                 len = sizeof(struct bfd_msghdr);
    1379             :                 break;
    1380             : #endif
    1381             :         default:
    1382             :                 len = sizeof(struct rt_msghdr);
    1383           0 :                 break;
    1384             :         }
    1385           0 :         if (len > MCLBYTES)
    1386           0 :                 panic("rtm_msg1");
    1387           0 :         m = m_gethdr(M_DONTWAIT, MT_DATA);
    1388           0 :         if (m && len > MHLEN) {
    1389           0 :                 MCLGET(m, M_DONTWAIT);
    1390           0 :                 if ((m->m_flags & M_EXT) == 0) {
    1391           0 :                         m_free(m);
    1392             :                         m = NULL;
    1393           0 :                 }
    1394             :         }
    1395           0 :         if (m == NULL)
    1396           0 :                 return (m);
    1397           0 :         m->m_pkthdr.len = m->m_len = hlen = len;
    1398           0 :         m->m_pkthdr.ph_ifidx = 0;
    1399           0 :         rtm = mtod(m, struct rt_msghdr *);
    1400           0 :         bzero(rtm, len);
    1401           0 :         for (i = 0; i < RTAX_MAX; i++) {
    1402           0 :                 if (rtinfo == NULL || (sa = rtinfo->rti_info[i]) == NULL)
    1403             :                         continue;
    1404           0 :                 rtinfo->rti_addrs |= (1 << i);
    1405           0 :                 dlen = ROUNDUP(sa->sa_len);
    1406           0 :                 if (m_copyback(m, len, dlen, sa, M_NOWAIT)) {
    1407           0 :                         m_freem(m);
    1408           0 :                         return (NULL);
    1409             :                 }
    1410           0 :                 len += dlen;
    1411           0 :         }
    1412           0 :         rtm->rtm_msglen = len;
    1413           0 :         rtm->rtm_hdrlen = hlen;
    1414           0 :         rtm->rtm_version = RTM_VERSION;
    1415           0 :         rtm->rtm_type = type;
    1416           0 :         return (m);
    1417           0 : }
    1418             : 
    1419             : int
    1420           0 : rtm_msg2(int type, int vers, struct rt_addrinfo *rtinfo, caddr_t cp,
    1421             :     struct walkarg *w)
    1422             : {
    1423             :         int             i;
    1424             :         int             len, dlen, hlen, second_time = 0;
    1425             :         caddr_t         cp0;
    1426             : 
    1427           0 :         rtinfo->rti_addrs = 0;
    1428             : again:
    1429           0 :         switch (type) {
    1430             :         case RTM_DELADDR:
    1431             :         case RTM_NEWADDR:
    1432             :                 len = sizeof(struct ifa_msghdr);
    1433           0 :                 break;
    1434             :         case RTM_IFINFO:
    1435             :                 len = sizeof(struct if_msghdr);
    1436           0 :                 break;
    1437             :         default:
    1438             :                 len = sizeof(struct rt_msghdr);
    1439           0 :                 break;
    1440             :         }
    1441             :         hlen = len;
    1442           0 :         if ((cp0 = cp) != NULL)
    1443           0 :                 cp += len;
    1444           0 :         for (i = 0; i < RTAX_MAX; i++) {
    1445             :                 struct sockaddr *sa;
    1446             : 
    1447           0 :                 if ((sa = rtinfo->rti_info[i]) == NULL)
    1448           0 :                         continue;
    1449           0 :                 rtinfo->rti_addrs |= (1 << i);
    1450           0 :                 dlen = ROUNDUP(sa->sa_len);
    1451           0 :                 if (cp) {
    1452           0 :                         bcopy(sa, cp, (size_t)dlen);
    1453           0 :                         cp += dlen;
    1454           0 :                 }
    1455           0 :                 len += dlen;
    1456           0 :         }
    1457             :         /* align message length to the next natural boundary */
    1458           0 :         len = ALIGN(len);
    1459           0 :         if (cp == 0 && w != NULL && !second_time) {
    1460           0 :                 w->w_needed += len;
    1461           0 :                 if (w->w_needed <= 0 && w->w_where) {
    1462           0 :                         if (w->w_tmemsize < len) {
    1463           0 :                                 free(w->w_tmem, M_RTABLE, w->w_tmemsize);
    1464           0 :                                 w->w_tmem = malloc(len, M_RTABLE, M_NOWAIT);
    1465           0 :                                 if (w->w_tmem)
    1466           0 :                                         w->w_tmemsize = len;
    1467             :                         }
    1468           0 :                         if (w->w_tmem) {
    1469             :                                 cp = w->w_tmem;
    1470             :                                 second_time = 1;
    1471           0 :                                 goto again;
    1472             :                         } else
    1473           0 :                                 w->w_where = 0;
    1474           0 :                 }
    1475             :         }
    1476           0 :         if (cp && w)            /* clear the message header */
    1477           0 :                 bzero(cp0, hlen);
    1478             : 
    1479           0 :         if (cp) {
    1480           0 :                 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
    1481             : 
    1482           0 :                 rtm->rtm_version = RTM_VERSION;
    1483           0 :                 rtm->rtm_type = type;
    1484           0 :                 rtm->rtm_msglen = len;
    1485           0 :                 rtm->rtm_hdrlen = hlen;
    1486           0 :         }
    1487           0 :         return (len);
    1488             : }
    1489             : 
    1490             : void
    1491           0 : rtm_send(struct rtentry *rt, int cmd, int error, unsigned int rtableid)
    1492             : {
    1493           0 :         struct rt_addrinfo       info;
    1494             :         struct ifnet            *ifp;
    1495           0 :         struct sockaddr_rtlabel  sa_rl;
    1496           0 :         struct sockaddr_in6      sa_mask;
    1497             : 
    1498           0 :         memset(&info, 0, sizeof(info));
    1499           0 :         info.rti_info[RTAX_DST] = rt_key(rt);
    1500           0 :         info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
    1501           0 :         if (!ISSET(rt->rt_flags, RTF_HOST))
    1502           0 :                 info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask);
    1503           0 :         info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
    1504           0 :         ifp = if_get(rt->rt_ifidx);
    1505           0 :         if (ifp != NULL) {
    1506           0 :                 info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl);
    1507           0 :                 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
    1508           0 :         }
    1509             : 
    1510           0 :         rtm_miss(cmd, &info, rt->rt_flags, rt->rt_priority, rt->rt_ifidx, error,
    1511             :             rtableid);
    1512           0 :         if_put(ifp);
    1513           0 : }
    1514             : 
    1515             : /*
    1516             :  * This routine is called to generate a message from the routing
    1517             :  * socket indicating that a redirect has occurred, a routing lookup
    1518             :  * has failed, or that a protocol has detected timeouts to a particular
    1519             :  * destination.
    1520             :  */
    1521             : void
    1522           0 : rtm_miss(int type, struct rt_addrinfo *rtinfo, int flags, uint8_t prio,
    1523             :     u_int ifidx, int error, u_int tableid)
    1524             : {
    1525             :         struct rt_msghdr        *rtm;
    1526             :         struct mbuf             *m;
    1527           0 :         struct sockaddr         *sa = rtinfo->rti_info[RTAX_DST];
    1528             : 
    1529           0 :         if (rtptable.rtp_count == 0)
    1530           0 :                 return;
    1531           0 :         m = rtm_msg1(type, rtinfo);
    1532           0 :         if (m == NULL)
    1533           0 :                 return;
    1534           0 :         rtm = mtod(m, struct rt_msghdr *);
    1535           0 :         rtm->rtm_flags = RTF_DONE | flags;
    1536           0 :         rtm->rtm_priority = prio;
    1537           0 :         rtm->rtm_errno = error;
    1538           0 :         rtm->rtm_tableid = tableid;
    1539           0 :         rtm->rtm_addrs = rtinfo->rti_addrs;
    1540           0 :         rtm->rtm_index = ifidx;
    1541           0 :         route_input(m, NULL, sa ? sa->sa_family : AF_UNSPEC);
    1542           0 : }
    1543             : 
    1544             : /*
    1545             :  * This routine is called to generate a message from the routing
    1546             :  * socket indicating that the status of a network interface has changed.
    1547             :  */
    1548             : void
    1549           0 : rtm_ifchg(struct ifnet *ifp)
    1550             : {
    1551             :         struct if_msghdr        *ifm;
    1552             :         struct mbuf             *m;
    1553             : 
    1554           0 :         if (rtptable.rtp_count == 0)
    1555           0 :                 return;
    1556           0 :         m = rtm_msg1(RTM_IFINFO, NULL);
    1557           0 :         if (m == NULL)
    1558           0 :                 return;
    1559           0 :         ifm = mtod(m, struct if_msghdr *);
    1560           0 :         ifm->ifm_index = ifp->if_index;
    1561           0 :         ifm->ifm_tableid = ifp->if_rdomain;
    1562           0 :         ifm->ifm_flags = ifp->if_flags;
    1563           0 :         ifm->ifm_xflags = ifp->if_xflags;
    1564           0 :         if_getdata(ifp, &ifm->ifm_data);
    1565           0 :         ifm->ifm_addrs = 0;
    1566           0 :         route_input(m, NULL, AF_UNSPEC);
    1567           0 : }
    1568             : 
    1569             : /*
    1570             :  * This is called to generate messages from the routing socket
    1571             :  * indicating a network interface has had addresses associated with it.
    1572             :  * if we ever reverse the logic and replace messages TO the routing
    1573             :  * socket indicate a request to configure interfaces, then it will
    1574             :  * be unnecessary as the routing socket will automatically generate
    1575             :  * copies of it.
    1576             :  */
    1577             : void
    1578           0 : rtm_addr(int cmd, struct ifaddr *ifa)
    1579             : {
    1580           0 :         struct ifnet            *ifp = ifa->ifa_ifp;
    1581             :         struct mbuf             *m;
    1582           0 :         struct rt_addrinfo       info;
    1583             :         struct ifa_msghdr       *ifam;
    1584             : 
    1585           0 :         if (rtptable.rtp_count == 0)
    1586           0 :                 return;
    1587             : 
    1588           0 :         memset(&info, 0, sizeof(info));
    1589           0 :         info.rti_info[RTAX_IFA] = ifa->ifa_addr;
    1590           0 :         info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl);
    1591           0 :         info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
    1592           0 :         info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
    1593           0 :         if ((m = rtm_msg1(cmd, &info)) == NULL)
    1594           0 :                 return;
    1595           0 :         ifam = mtod(m, struct ifa_msghdr *);
    1596           0 :         ifam->ifam_index = ifp->if_index;
    1597           0 :         ifam->ifam_metric = ifa->ifa_metric;
    1598           0 :         ifam->ifam_flags = ifa->ifa_flags;
    1599           0 :         ifam->ifam_addrs = info.rti_addrs;
    1600           0 :         ifam->ifam_tableid = ifp->if_rdomain;
    1601             : 
    1602           0 :         route_input(m, NULL,
    1603           0 :             ifa->ifa_addr ? ifa->ifa_addr->sa_family : AF_UNSPEC);
    1604           0 : }
    1605             : 
    1606             : /*
    1607             :  * This is called to generate routing socket messages indicating
    1608             :  * network interface arrival and departure.
    1609             :  */
    1610             : void
    1611           0 : rtm_ifannounce(struct ifnet *ifp, int what)
    1612             : {
    1613             :         struct if_announcemsghdr        *ifan;
    1614             :         struct mbuf                     *m;
    1615             : 
    1616           0 :         if (rtptable.rtp_count == 0)
    1617           0 :                 return;
    1618           0 :         m = rtm_msg1(RTM_IFANNOUNCE, NULL);
    1619           0 :         if (m == NULL)
    1620           0 :                 return;
    1621           0 :         ifan = mtod(m, struct if_announcemsghdr *);
    1622           0 :         ifan->ifan_index = ifp->if_index;
    1623           0 :         strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name));
    1624           0 :         ifan->ifan_what = what;
    1625           0 :         route_input(m, NULL, AF_UNSPEC);
    1626           0 : }
    1627             : 
    1628             : #ifdef BFD
    1629             : /*
    1630             :  * This is used to generate routing socket messages indicating
    1631             :  * the state of a BFD session.
    1632             :  */
    1633             : void
    1634             : rtm_bfd(struct bfd_config *bfd)
    1635             : {
    1636             :         struct bfd_msghdr       *bfdm;
    1637             :         struct sockaddr_bfd      sa_bfd;
    1638             :         struct mbuf             *m;
    1639             :         struct rt_addrinfo       info;
    1640             : 
    1641             :         if (rtptable.rtp_count == 0)
    1642             :                 return;
    1643             :         memset(&info, 0, sizeof(info));
    1644             :         info.rti_info[RTAX_DST] = rt_key(bfd->bc_rt);
    1645             :         info.rti_info[RTAX_IFA] = bfd->bc_rt->rt_ifa->ifa_addr;
    1646             : 
    1647             :         m = rtm_msg1(RTM_BFD, &info);
    1648             :         if (m == NULL)
    1649             :                 return;
    1650             :         bfdm = mtod(m, struct bfd_msghdr *);
    1651             :         bfdm->bm_addrs = info.rti_addrs;
    1652             : 
    1653             :         bfd2sa(bfd->bc_rt, &sa_bfd);
    1654             :         memcpy(&bfdm->bm_sa, &sa_bfd, sizeof(sa_bfd));
    1655             : 
    1656             :         route_input(m, NULL, info.rti_info[RTAX_DST]->sa_family);
    1657             : }
    1658             : #endif /* BFD */
    1659             : 
    1660             : /*
    1661             :  * This is used in dumping the kernel table via sysctl().
    1662             :  */
    1663             : int
    1664           0 : sysctl_dumpentry(struct rtentry *rt, void *v, unsigned int id)
    1665             : {
    1666           0 :         struct walkarg          *w = v;
    1667             :         int                      error = 0, size;
    1668           0 :         struct rt_addrinfo       info;
    1669             :         struct ifnet            *ifp;
    1670             : #ifdef BFD
    1671             :         struct sockaddr_bfd      sa_bfd;
    1672             : #endif
    1673           0 :         struct sockaddr_rtlabel  sa_rl;
    1674           0 :         struct sockaddr_in6      sa_mask;
    1675             : 
    1676           0 :         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
    1677           0 :                 return 0;
    1678           0 :         if (w->w_op == NET_RT_DUMP && w->w_arg) {
    1679           0 :                 u_int8_t prio = w->w_arg & RTP_MASK;
    1680           0 :                 if (w->w_arg < 0) {
    1681           0 :                         prio = (-w->w_arg) & RTP_MASK;
    1682             :                         /* Show all routes that are not this priority */
    1683           0 :                         if (prio == (rt->rt_priority & RTP_MASK))
    1684           0 :                                 return 0;
    1685             :                 } else {
    1686           0 :                         if (prio != (rt->rt_priority & RTP_MASK) &&
    1687           0 :                             prio != RTP_ANY)
    1688           0 :                                 return 0;
    1689             :                 }
    1690           0 :         }
    1691           0 :         bzero(&info, sizeof(info));
    1692           0 :         info.rti_info[RTAX_DST] = rt_key(rt);
    1693           0 :         info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
    1694           0 :         info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask);
    1695           0 :         ifp = if_get(rt->rt_ifidx);
    1696           0 :         if (ifp != NULL) {
    1697           0 :                 info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl);
    1698           0 :                 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
    1699           0 :                 if (ifp->if_flags & IFF_POINTOPOINT)
    1700           0 :                         info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr;
    1701             :         }
    1702           0 :         if_put(ifp);
    1703           0 :         info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
    1704             : #ifdef BFD
    1705             :         if (rt->rt_flags & RTF_BFD)
    1706             :                 info.rti_info[RTAX_BFD] = bfd2sa(rt, &sa_bfd);
    1707             : #endif
    1708             : #ifdef MPLS
    1709           0 :         if (rt->rt_flags & RTF_MPLS) {
    1710           0 :                 struct sockaddr_mpls     sa_mpls;
    1711             : 
    1712           0 :                 bzero(&sa_mpls, sizeof(sa_mpls));
    1713           0 :                 sa_mpls.smpls_family = AF_MPLS;
    1714           0 :                 sa_mpls.smpls_len = sizeof(sa_mpls);
    1715           0 :                 sa_mpls.smpls_label = ((struct rt_mpls *)
    1716           0 :                     rt->rt_llinfo)->mpls_label;
    1717           0 :                 info.rti_info[RTAX_SRC] = (struct sockaddr *)&sa_mpls;
    1718           0 :                 info.rti_mpls = ((struct rt_mpls *)
    1719           0 :                     rt->rt_llinfo)->mpls_operation;
    1720           0 :         }
    1721             : #endif
    1722             : 
    1723           0 :         size = rtm_msg2(RTM_GET, RTM_VERSION, &info, NULL, w);
    1724           0 :         if (w->w_where && w->w_tmem && w->w_needed <= 0) {
    1725           0 :                 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
    1726             : 
    1727           0 :                 rtm->rtm_pid = curproc->p_p->ps_pid;
    1728           0 :                 rtm->rtm_flags = rt->rt_flags;
    1729           0 :                 rtm->rtm_priority = rt->rt_priority & RTP_MASK;
    1730           0 :                 rtm_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
    1731             :                 /* Do not account the routing table's reference. */
    1732           0 :                 rtm->rtm_rmx.rmx_refcnt = rt->rt_refcnt - 1;
    1733           0 :                 rtm->rtm_index = rt->rt_ifidx;
    1734           0 :                 rtm->rtm_addrs = info.rti_addrs;
    1735           0 :                 rtm->rtm_tableid = id;
    1736             : #ifdef MPLS
    1737           0 :                 rtm->rtm_mpls = info.rti_mpls;
    1738             : #endif
    1739           0 :                 if ((error = copyout(rtm, w->w_where, size)) != 0)
    1740           0 :                         w->w_where = NULL;
    1741             :                 else
    1742           0 :                         w->w_where += size;
    1743           0 :         }
    1744           0 :         return (error);
    1745           0 : }
    1746             : 
    1747             : int
    1748           0 : sysctl_iflist(int af, struct walkarg *w)
    1749             : {
    1750             :         struct ifnet            *ifp;
    1751             :         struct ifaddr           *ifa;
    1752           0 :         struct rt_addrinfo       info;
    1753             :         int                      len, error = 0;
    1754             : 
    1755           0 :         bzero(&info, sizeof(info));
    1756           0 :         TAILQ_FOREACH(ifp, &ifnet, if_list) {
    1757           0 :                 if (w->w_arg && w->w_arg != ifp->if_index)
    1758             :                         continue;
    1759             :                 /* Copy the link-layer address first */
    1760           0 :                 info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl);
    1761           0 :                 len = rtm_msg2(RTM_IFINFO, RTM_VERSION, &info, 0, w);
    1762           0 :                 if (w->w_where && w->w_tmem && w->w_needed <= 0) {
    1763             :                         struct if_msghdr *ifm;
    1764             : 
    1765           0 :                         ifm = (struct if_msghdr *)w->w_tmem;
    1766           0 :                         ifm->ifm_index = ifp->if_index;
    1767           0 :                         ifm->ifm_tableid = ifp->if_rdomain;
    1768           0 :                         ifm->ifm_flags = ifp->if_flags;
    1769           0 :                         if_getdata(ifp, &ifm->ifm_data);
    1770           0 :                         ifm->ifm_addrs = info.rti_addrs;
    1771           0 :                         error = copyout(ifm, w->w_where, len);
    1772           0 :                         if (error)
    1773           0 :                                 return (error);
    1774           0 :                         w->w_where += len;
    1775           0 :                 }
    1776           0 :                 info.rti_info[RTAX_IFP] = NULL;
    1777           0 :                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
    1778           0 :                         KASSERT(ifa->ifa_addr->sa_family != AF_LINK);
    1779           0 :                         if (af && af != ifa->ifa_addr->sa_family)
    1780             :                                 continue;
    1781           0 :                         info.rti_info[RTAX_IFA] = ifa->ifa_addr;
    1782           0 :                         info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
    1783           0 :                         info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
    1784           0 :                         len = rtm_msg2(RTM_NEWADDR, RTM_VERSION, &info, 0, w);
    1785           0 :                         if (w->w_where && w->w_tmem && w->w_needed <= 0) {
    1786             :                                 struct ifa_msghdr *ifam;
    1787             : 
    1788           0 :                                 ifam = (struct ifa_msghdr *)w->w_tmem;
    1789           0 :                                 ifam->ifam_index = ifa->ifa_ifp->if_index;
    1790           0 :                                 ifam->ifam_flags = ifa->ifa_flags;
    1791           0 :                                 ifam->ifam_metric = ifa->ifa_metric;
    1792           0 :                                 ifam->ifam_addrs = info.rti_addrs;
    1793           0 :                                 error = copyout(w->w_tmem, w->w_where, len);
    1794           0 :                                 if (error)
    1795           0 :                                         return (error);
    1796           0 :                                 w->w_where += len;
    1797           0 :                         }
    1798             :                 }
    1799           0 :                 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
    1800           0 :                     info.rti_info[RTAX_BRD] = NULL;
    1801           0 :         }
    1802           0 :         return (0);
    1803           0 : }
    1804             : 
    1805             : int
    1806           0 : sysctl_ifnames(struct walkarg *w)
    1807             : {
    1808           0 :         struct if_nameindex_msg ifn;
    1809             :         struct ifnet *ifp;
    1810             :         int error = 0;
    1811             : 
    1812             :         /* XXX ignore tableid for now */
    1813           0 :         TAILQ_FOREACH(ifp, &ifnet, if_list) {
    1814           0 :                 if (w->w_arg && w->w_arg != ifp->if_index)
    1815             :                         continue;
    1816           0 :                 w->w_needed += sizeof(ifn);
    1817           0 :                 if (w->w_where && w->w_needed <= 0) {
    1818             : 
    1819           0 :                         memset(&ifn, 0, sizeof(ifn));
    1820           0 :                         ifn.if_index = ifp->if_index;
    1821           0 :                         strlcpy(ifn.if_name, ifp->if_xname,
    1822             :                             sizeof(ifn.if_name));
    1823           0 :                         error = copyout(&ifn, w->w_where, sizeof(ifn));
    1824           0 :                         if (error)
    1825           0 :                                 return (error);
    1826           0 :                         w->w_where += sizeof(ifn);
    1827           0 :                 }
    1828             :         }
    1829             : 
    1830           0 :         return (0);
    1831           0 : }
    1832             : 
    1833             : int
    1834           0 : sysctl_rtable(int *name, u_int namelen, void *where, size_t *given, void *new,
    1835             :     size_t newlen)
    1836             : {
    1837             :         int                      i, error = EINVAL;
    1838             :         u_char                   af;
    1839           0 :         struct walkarg           w;
    1840           0 :         struct rt_tableinfo      tableinfo;
    1841             :         u_int                    tableid = 0;
    1842             : 
    1843           0 :         if (new)
    1844           0 :                 return (EPERM);
    1845           0 :         if (namelen < 3 || namelen > 4)
    1846           0 :                 return (EINVAL);
    1847           0 :         af = name[0];
    1848           0 :         bzero(&w, sizeof(w));
    1849           0 :         w.w_where = where;
    1850           0 :         w.w_given = *given;
    1851           0 :         w.w_needed = 0 - w.w_given;
    1852           0 :         w.w_op = name[1];
    1853           0 :         w.w_arg = name[2];
    1854             : 
    1855           0 :         if (namelen == 4) {
    1856           0 :                 tableid = name[3];
    1857           0 :                 if (!rtable_exists(tableid))
    1858           0 :                         return (ENOENT);
    1859             :         } else
    1860           0 :                 tableid = curproc->p_p->ps_rtableid;
    1861             : 
    1862           0 :         switch (w.w_op) {
    1863             :         case NET_RT_DUMP:
    1864             :         case NET_RT_FLAGS:
    1865           0 :                 NET_LOCK();
    1866           0 :                 for (i = 1; i <= AF_MAX; i++) {
    1867           0 :                         if (af != 0 && af != i)
    1868             :                                 continue;
    1869             : 
    1870           0 :                         error = rtable_walk(tableid, i, sysctl_dumpentry, &w);
    1871           0 :                         if (error == EAFNOSUPPORT)
    1872             :                                 error = 0;
    1873           0 :                         if (error)
    1874             :                                 break;
    1875             :                 }
    1876           0 :                 NET_UNLOCK();
    1877           0 :                 break;
    1878             : 
    1879             :         case NET_RT_IFLIST:
    1880           0 :                 NET_LOCK();
    1881           0 :                 error = sysctl_iflist(af, &w);
    1882           0 :                 NET_UNLOCK();
    1883           0 :                 break;
    1884             : 
    1885             :         case NET_RT_STATS:
    1886           0 :                 return (sysctl_rtable_rtstat(where, given, new));
    1887             :         case NET_RT_TABLE:
    1888           0 :                 tableid = w.w_arg;
    1889           0 :                 if (!rtable_exists(tableid))
    1890           0 :                         return (ENOENT);
    1891           0 :                 memset(&tableinfo, 0, sizeof tableinfo);
    1892           0 :                 tableinfo.rti_tableid = tableid;
    1893           0 :                 tableinfo.rti_domainid = rtable_l2(tableid);
    1894           0 :                 error = sysctl_rdstruct(where, given, new,
    1895             :                     &tableinfo, sizeof(tableinfo));
    1896           0 :                 return (error);
    1897             :         case NET_RT_IFNAMES:
    1898           0 :                 NET_LOCK();
    1899           0 :                 error = sysctl_ifnames(&w);
    1900           0 :                 NET_UNLOCK();
    1901           0 :                 break;
    1902             :         }
    1903           0 :         free(w.w_tmem, M_RTABLE, w.w_tmemsize);
    1904           0 :         w.w_needed += w.w_given;
    1905           0 :         if (where) {
    1906           0 :                 *given = w.w_where - (caddr_t)where;
    1907           0 :                 if (*given < w.w_needed)
    1908           0 :                         return (ENOMEM);
    1909             :         } else
    1910           0 :                 *given = (11 * w.w_needed) / 10;
    1911             : 
    1912           0 :         return (error);
    1913           0 : }
    1914             : 
    1915             : int
    1916           0 : sysctl_rtable_rtstat(void *oldp, size_t *oldlenp, void *newp)
    1917             : {
    1918             :         extern struct cpumem *rtcounters;
    1919           0 :         uint64_t counters[rts_ncounters];
    1920           0 :         struct rtstat rtstat;
    1921           0 :         uint32_t *words = (uint32_t *)&rtstat;
    1922             :         int i;
    1923             : 
    1924             :         CTASSERT(sizeof(rtstat) == (nitems(counters) * sizeof(uint32_t)));
    1925           0 :         memset(&rtstat, 0, sizeof rtstat);
    1926           0 :         counters_read(rtcounters, counters, nitems(counters));
    1927             : 
    1928           0 :         for (i = 0; i < nitems(counters); i++)
    1929           0 :                 words[i] = (uint32_t)counters[i];
    1930             : 
    1931           0 :         return (sysctl_rdstruct(oldp, oldlenp, newp, &rtstat, sizeof(rtstat)));
    1932           0 : }
    1933             : 
    1934             : int
    1935           0 : rtm_validate_proposal(struct rt_addrinfo *info)
    1936             : {
    1937           0 :         if (info->rti_addrs & ~(RTA_NETMASK | RTA_IFA | RTA_DNS | RTA_STATIC |
    1938             :             RTA_SEARCH)) {
    1939           0 :                 return -1;
    1940             :         }
    1941             : 
    1942           0 :         if (ISSET(info->rti_addrs, RTA_NETMASK)) {
    1943           0 :                 struct sockaddr *sa = info->rti_info[RTAX_NETMASK];
    1944           0 :                 if (sa == NULL)
    1945           0 :                         return -1;
    1946           0 :                 switch (sa->sa_family) {
    1947             :                 case AF_INET:
    1948           0 :                         if (sa->sa_len != sizeof(struct sockaddr_in))
    1949           0 :                                 return -1;
    1950             :                         break;
    1951             :                 case AF_INET6:
    1952           0 :                         if (sa->sa_len != sizeof(struct sockaddr_in6))
    1953           0 :                                 return -1;
    1954             :                         break;
    1955             :                 default:
    1956           0 :                         return -1;
    1957             :                 }
    1958           0 :         }
    1959             : 
    1960           0 :         if (ISSET(info->rti_addrs, RTA_IFA)) {
    1961           0 :                 struct sockaddr *sa = info->rti_info[RTAX_IFA];
    1962           0 :                 if (sa == NULL)
    1963           0 :                         return -1;
    1964           0 :                 switch (sa->sa_family) {
    1965             :                 case AF_INET:
    1966           0 :                         if (sa->sa_len != sizeof(struct sockaddr_in))
    1967           0 :                                 return -1;
    1968             :                         break;
    1969             :                 case AF_INET6:
    1970           0 :                         if (sa->sa_len != sizeof(struct sockaddr_in6))
    1971           0 :                                 return -1;
    1972             :                         break;
    1973             :                 default:
    1974           0 :                         return -1;
    1975             :                 }
    1976           0 :         }
    1977             : 
    1978           0 :         if (ISSET(info->rti_addrs, RTA_DNS)) {
    1979             :                 struct sockaddr_rtdns *rtdns =
    1980           0 :                     (struct sockaddr_rtdns *)info->rti_info[RTAX_DNS];
    1981           0 :                 if (rtdns == NULL)
    1982           0 :                         return -1;
    1983           0 :                 if (rtdns->sr_len > sizeof(*rtdns))
    1984           0 :                         return -1;
    1985           0 :                 if (rtdns->sr_len <=
    1986             :                     offsetof(struct sockaddr_rtdns, sr_dns))
    1987           0 :                         return -1;
    1988           0 :         }
    1989             : 
    1990           0 :         if (ISSET(info->rti_addrs, RTA_STATIC)) {
    1991             :                 struct sockaddr_rtstatic *rtstatic =
    1992           0 :                     (struct sockaddr_rtstatic *)info->rti_info[RTAX_STATIC];
    1993           0 :                 if (rtstatic == NULL)
    1994           0 :                         return -1;
    1995           0 :                 if (rtstatic->sr_len > sizeof(*rtstatic))
    1996           0 :                         return -1;
    1997           0 :                 if (rtstatic->sr_len <=
    1998             :                     offsetof(struct sockaddr_rtstatic, sr_static))
    1999           0 :                         return -1;
    2000           0 :         }
    2001             : 
    2002           0 :         if (ISSET(info->rti_addrs, RTA_SEARCH)) {
    2003             :                 struct sockaddr_rtsearch *rtsearch =
    2004           0 :                     (struct sockaddr_rtsearch *)info->rti_info[RTAX_SEARCH];
    2005           0 :                 if (rtsearch == NULL)
    2006           0 :                         return -1;
    2007           0 :                 if (rtsearch->sr_len > sizeof(*rtsearch))
    2008           0 :                         return -1;
    2009           0 :                 if (rtsearch->sr_len <=
    2010             :                     offsetof(struct sockaddr_rtsearch, sr_search))
    2011           0 :                         return -1;
    2012           0 :         }
    2013             : 
    2014           0 :         return 0;
    2015           0 : }
    2016             : 
    2017             : /*
    2018             :  * Definitions of protocols supported in the ROUTE domain.
    2019             :  */
    2020             : 
    2021             : extern  struct domain routedomain;              /* or at least forward */
    2022             : 
    2023             : struct protosw routesw[] = {
    2024             : {
    2025             :   .pr_type      = SOCK_RAW,
    2026             :   .pr_domain    = &routedomain,
    2027             :   .pr_flags     = PR_ATOMIC|PR_ADDR|PR_WANTRCVD,
    2028             :   .pr_output    = route_output,
    2029             :   .pr_ctloutput = route_ctloutput,
    2030             :   .pr_usrreq    = route_usrreq,
    2031             :   .pr_attach    = route_attach,
    2032             :   .pr_detach    = route_detach,
    2033             :   .pr_init      = route_prinit,
    2034             :   .pr_sysctl    = sysctl_rtable
    2035             : }
    2036             : };
    2037             : 
    2038             : struct domain routedomain = {
    2039             :   .dom_family = PF_ROUTE,
    2040             :   .dom_name = "route",
    2041             :   .dom_init = route_init,
    2042             :   .dom_protosw = routesw,
    2043             :   .dom_protoswNPROTOSW = &routesw[nitems(routesw)]
    2044             : };

Generated by: LCOV version 1.13