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


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

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

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

    1 /*-
    2  * Copyright (c) 1988, 1991, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 4. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      @(#)rtsock.c    8.7 (Berkeley) 10/12/95
   30  * $FreeBSD: releng/11.0/sys/net/rtsock.c 301270 2016-06-03 13:57:10Z bz $
   31  */
   32 #include "opt_compat.h"
   33 #include "opt_mpath.h"
   34 #include "opt_inet.h"
   35 #include "opt_inet6.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/jail.h>
   39 #include <sys/kernel.h>
   40 #include <sys/domain.h>
   41 #include <sys/lock.h>
   42 #include <sys/malloc.h>
   43 #include <sys/mbuf.h>
   44 #include <sys/priv.h>
   45 #include <sys/proc.h>
   46 #include <sys/protosw.h>
   47 #include <sys/rwlock.h>
   48 #include <sys/signalvar.h>
   49 #include <sys/socket.h>
   50 #include <sys/socketvar.h>
   51 #include <sys/sysctl.h>
   52 #include <sys/systm.h>
   53 
   54 #include <net/if.h>
   55 #include <net/if_var.h>
   56 #include <net/if_dl.h>
   57 #include <net/if_llatbl.h>
   58 #include <net/if_types.h>
   59 #include <net/netisr.h>
   60 #include <net/raw_cb.h>
   61 #include <net/route.h>
   62 #include <net/route_var.h>
   63 #include <net/vnet.h>
   64 
   65 #include <netinet/in.h>
   66 #include <netinet/if_ether.h>
   67 #include <netinet/ip_carp.h>
   68 #ifdef INET6
   69 #include <netinet6/ip6_var.h>
   70 #include <netinet6/scope6_var.h>
   71 #endif
   72 
   73 #ifdef COMPAT_FREEBSD32
   74 #include <sys/mount.h>
   75 #include <compat/freebsd32/freebsd32.h>
   76 
   77 struct if_msghdr32 {
   78         uint16_t ifm_msglen;
   79         uint8_t ifm_version;
   80         uint8_t ifm_type;
   81         int32_t ifm_addrs;
   82         int32_t ifm_flags;
   83         uint16_t ifm_index;
   84         struct  if_data ifm_data;
   85 };
   86 
   87 struct if_msghdrl32 {
   88         uint16_t ifm_msglen;
   89         uint8_t ifm_version;
   90         uint8_t ifm_type;
   91         int32_t ifm_addrs;
   92         int32_t ifm_flags;
   93         uint16_t ifm_index;
   94         uint16_t _ifm_spare1;
   95         uint16_t ifm_len;
   96         uint16_t ifm_data_off;
   97         struct  if_data ifm_data;
   98 };
   99 
  100 struct ifa_msghdrl32 {
  101         uint16_t ifam_msglen;
  102         uint8_t ifam_version;
  103         uint8_t ifam_type;
  104         int32_t ifam_addrs;
  105         int32_t ifam_flags;
  106         uint16_t ifam_index;
  107         uint16_t _ifam_spare1;
  108         uint16_t ifam_len;
  109         uint16_t ifam_data_off;
  110         int32_t ifam_metric;
  111         struct  if_data ifam_data;
  112 };
  113 #endif /* COMPAT_FREEBSD32 */
  114 
  115 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
  116 
  117 /* NB: these are not modified */
  118 static struct   sockaddr route_src = { 2, PF_ROUTE, };
  119 static struct   sockaddr sa_zero   = { sizeof(sa_zero), AF_INET, };
  120 
  121 /* These are external hooks for CARP. */
  122 int     (*carp_get_vhid_p)(struct ifaddr *);
  123 
  124 /*
  125  * Used by rtsock/raw_input callback code to decide whether to filter the update
  126  * notification to a socket bound to a particular FIB.
  127  */
  128 #define RTS_FILTER_FIB  M_PROTO8
  129 
  130 typedef struct {
  131         int     ip_count;       /* attached w/ AF_INET */
  132         int     ip6_count;      /* attached w/ AF_INET6 */
  133         int     any_count;      /* total attached */
  134 } route_cb_t;
  135 static VNET_DEFINE(route_cb_t, route_cb);
  136 #define V_route_cb VNET(route_cb)
  137 
  138 struct mtx rtsock_mtx;
  139 MTX_SYSINIT(rtsock, &rtsock_mtx, "rtsock route_cb lock", MTX_DEF);
  140 
  141 #define RTSOCK_LOCK()   mtx_lock(&rtsock_mtx)
  142 #define RTSOCK_UNLOCK() mtx_unlock(&rtsock_mtx)
  143 #define RTSOCK_LOCK_ASSERT()    mtx_assert(&rtsock_mtx, MA_OWNED)
  144 
  145 static SYSCTL_NODE(_net, OID_AUTO, route, CTLFLAG_RD, 0, "");
  146 
  147 struct walkarg {
  148         int     w_tmemsize;
  149         int     w_op, w_arg;
  150         caddr_t w_tmem;
  151         struct sysctl_req *w_req;
  152 };
  153 
  154 static void     rts_input(struct mbuf *m);
  155 static struct mbuf *rtsock_msg_mbuf(int type, struct rt_addrinfo *rtinfo);
  156 static int      rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo,
  157                         struct walkarg *w, int *plen);
  158 static int      rt_xaddrs(caddr_t cp, caddr_t cplim,
  159                         struct rt_addrinfo *rtinfo);
  160 static int      sysctl_dumpentry(struct radix_node *rn, void *vw);
  161 static int      sysctl_iflist(int af, struct walkarg *w);
  162 static int      sysctl_ifmalist(int af, struct walkarg *w);
  163 static int      route_output(struct mbuf *m, struct socket *so, ...);
  164 static void     rt_getmetrics(const struct rtentry *rt, struct rt_metrics *out);
  165 static void     rt_dispatch(struct mbuf *, sa_family_t);
  166 static struct sockaddr  *rtsock_fix_netmask(struct sockaddr *dst,
  167                         struct sockaddr *smask, struct sockaddr_storage *dmask);
  168 
  169 static struct netisr_handler rtsock_nh = {
  170         .nh_name = "rtsock",
  171         .nh_handler = rts_input,
  172         .nh_proto = NETISR_ROUTE,
  173         .nh_policy = NETISR_POLICY_SOURCE,
  174 };
  175 
  176 static int
  177 sysctl_route_netisr_maxqlen(SYSCTL_HANDLER_ARGS)
  178 {
  179         int error, qlimit;
  180 
  181         netisr_getqlimit(&rtsock_nh, &qlimit);
  182         error = sysctl_handle_int(oidp, &qlimit, 0, req);
  183         if (error || !req->newptr)
  184                 return (error);
  185         if (qlimit < 1)
  186                 return (EINVAL);
  187         return (netisr_setqlimit(&rtsock_nh, qlimit));
  188 }
  189 SYSCTL_PROC(_net_route, OID_AUTO, netisr_maxqlen, CTLTYPE_INT|CTLFLAG_RW,
  190     0, 0, sysctl_route_netisr_maxqlen, "I",
  191     "maximum routing socket dispatch queue length");
  192 
  193 static void
  194 vnet_rts_init(void)
  195 {
  196         int tmp;
  197 
  198         if (IS_DEFAULT_VNET(curvnet)) {
  199                 if (TUNABLE_INT_FETCH("net.route.netisr_maxqlen", &tmp))
  200                         rtsock_nh.nh_qlimit = tmp;
  201                 netisr_register(&rtsock_nh);
  202         }
  203 #ifdef VIMAGE
  204          else
  205                 netisr_register_vnet(&rtsock_nh);
  206 #endif
  207 }
  208 VNET_SYSINIT(vnet_rtsock, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
  209     vnet_rts_init, 0);
  210 
  211 #ifdef VIMAGE
  212 static void
  213 vnet_rts_uninit(void)
  214 {
  215 
  216         netisr_unregister_vnet(&rtsock_nh);
  217 }
  218 VNET_SYSUNINIT(vnet_rts_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
  219     vnet_rts_uninit, 0);
  220 #endif
  221 
  222 static int
  223 raw_input_rts_cb(struct mbuf *m, struct sockproto *proto, struct sockaddr *src,
  224     struct rawcb *rp)
  225 {
  226         int fibnum;
  227 
  228         KASSERT(m != NULL, ("%s: m is NULL", __func__));
  229         KASSERT(proto != NULL, ("%s: proto is NULL", __func__));
  230         KASSERT(rp != NULL, ("%s: rp is NULL", __func__));
  231 
  232         /* No filtering requested. */
  233         if ((m->m_flags & RTS_FILTER_FIB) == 0)
  234                 return (0);
  235 
  236         /* Check if it is a rts and the fib matches the one of the socket. */
  237         fibnum = M_GETFIB(m);
  238         if (proto->sp_family != PF_ROUTE ||
  239             rp->rcb_socket == NULL ||
  240             rp->rcb_socket->so_fibnum == fibnum)
  241                 return (0);
  242 
  243         /* Filtering requested and no match, the socket shall be skipped. */
  244         return (1);
  245 }
  246 
  247 static void
  248 rts_input(struct mbuf *m)
  249 {
  250         struct sockproto route_proto;
  251         unsigned short *family;
  252         struct m_tag *tag;
  253 
  254         route_proto.sp_family = PF_ROUTE;
  255         tag = m_tag_find(m, PACKET_TAG_RTSOCKFAM, NULL);
  256         if (tag != NULL) {
  257                 family = (unsigned short *)(tag + 1);
  258                 route_proto.sp_protocol = *family;
  259                 m_tag_delete(m, tag);
  260         } else
  261                 route_proto.sp_protocol = 0;
  262 
  263         raw_input_ext(m, &route_proto, &route_src, raw_input_rts_cb);
  264 }
  265 
  266 /*
  267  * It really doesn't make any sense at all for this code to share much
  268  * with raw_usrreq.c, since its functionality is so restricted.  XXX
  269  */
  270 static void
  271 rts_abort(struct socket *so)
  272 {
  273 
  274         raw_usrreqs.pru_abort(so);
  275 }
  276 
  277 static void
  278 rts_close(struct socket *so)
  279 {
  280 
  281         raw_usrreqs.pru_close(so);
  282 }
  283 
  284 /* pru_accept is EOPNOTSUPP */
  285 
  286 static int
  287 rts_attach(struct socket *so, int proto, struct thread *td)
  288 {
  289         struct rawcb *rp;
  290         int error;
  291 
  292         KASSERT(so->so_pcb == NULL, ("rts_attach: so_pcb != NULL"));
  293 
  294         /* XXX */
  295         rp = malloc(sizeof *rp, M_PCB, M_WAITOK | M_ZERO);
  296 
  297         so->so_pcb = (caddr_t)rp;
  298         so->so_fibnum = td->td_proc->p_fibnum;
  299         error = raw_attach(so, proto);
  300         rp = sotorawcb(so);
  301         if (error) {
  302                 so->so_pcb = NULL;
  303                 free(rp, M_PCB);
  304                 return error;
  305         }
  306         RTSOCK_LOCK();
  307         switch(rp->rcb_proto.sp_protocol) {
  308         case AF_INET:
  309                 V_route_cb.ip_count++;
  310                 break;
  311         case AF_INET6:
  312                 V_route_cb.ip6_count++;
  313                 break;
  314         }
  315         V_route_cb.any_count++;
  316         RTSOCK_UNLOCK();
  317         soisconnected(so);
  318         so->so_options |= SO_USELOOPBACK;
  319         return 0;
  320 }
  321 
  322 static int
  323 rts_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
  324 {
  325 
  326         return (raw_usrreqs.pru_bind(so, nam, td)); /* xxx just EINVAL */
  327 }
  328 
  329 static int
  330 rts_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
  331 {
  332 
  333         return (raw_usrreqs.pru_connect(so, nam, td)); /* XXX just EINVAL */
  334 }
  335 
  336 /* pru_connect2 is EOPNOTSUPP */
  337 /* pru_control is EOPNOTSUPP */
  338 
  339 static void
  340 rts_detach(struct socket *so)
  341 {
  342         struct rawcb *rp = sotorawcb(so);
  343 
  344         KASSERT(rp != NULL, ("rts_detach: rp == NULL"));
  345 
  346         RTSOCK_LOCK();
  347         switch(rp->rcb_proto.sp_protocol) {
  348         case AF_INET:
  349                 V_route_cb.ip_count--;
  350                 break;
  351         case AF_INET6:
  352                 V_route_cb.ip6_count--;
  353                 break;
  354         }
  355         V_route_cb.any_count--;
  356         RTSOCK_UNLOCK();
  357         raw_usrreqs.pru_detach(so);
  358 }
  359 
  360 static int
  361 rts_disconnect(struct socket *so)
  362 {
  363 
  364         return (raw_usrreqs.pru_disconnect(so));
  365 }
  366 
  367 /* pru_listen is EOPNOTSUPP */
  368 
  369 static int
  370 rts_peeraddr(struct socket *so, struct sockaddr **nam)
  371 {
  372 
  373         return (raw_usrreqs.pru_peeraddr(so, nam));
  374 }
  375 
  376 /* pru_rcvd is EOPNOTSUPP */
  377 /* pru_rcvoob is EOPNOTSUPP */
  378 
  379 static int
  380 rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
  381          struct mbuf *control, struct thread *td)
  382 {
  383 
  384         return (raw_usrreqs.pru_send(so, flags, m, nam, control, td));
  385 }
  386 
  387 /* pru_sense is null */
  388 
  389 static int
  390 rts_shutdown(struct socket *so)
  391 {
  392 
  393         return (raw_usrreqs.pru_shutdown(so));
  394 }
  395 
  396 static int
  397 rts_sockaddr(struct socket *so, struct sockaddr **nam)
  398 {
  399 
  400         return (raw_usrreqs.pru_sockaddr(so, nam));
  401 }
  402 
  403 static struct pr_usrreqs route_usrreqs = {
  404         .pru_abort =            rts_abort,
  405         .pru_attach =           rts_attach,
  406         .pru_bind =             rts_bind,
  407         .pru_connect =          rts_connect,
  408         .pru_detach =           rts_detach,
  409         .pru_disconnect =       rts_disconnect,
  410         .pru_peeraddr =         rts_peeraddr,
  411         .pru_send =             rts_send,
  412         .pru_shutdown =         rts_shutdown,
  413         .pru_sockaddr =         rts_sockaddr,
  414         .pru_close =            rts_close,
  415 };
  416 
  417 #ifndef _SOCKADDR_UNION_DEFINED
  418 #define _SOCKADDR_UNION_DEFINED
  419 /*
  420  * The union of all possible address formats we handle.
  421  */
  422 union sockaddr_union {
  423         struct sockaddr         sa;
  424         struct sockaddr_in      sin;
  425         struct sockaddr_in6     sin6;
  426 };
  427 #endif /* _SOCKADDR_UNION_DEFINED */
  428 
  429 static int
  430 rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
  431     struct rtentry *rt, union sockaddr_union *saun, struct ucred *cred)
  432 {
  433 
  434         /* First, see if the returned address is part of the jail. */
  435         if (prison_if(cred, rt->rt_ifa->ifa_addr) == 0) {
  436                 info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
  437                 return (0);
  438         }
  439 
  440         switch (info->rti_info[RTAX_DST]->sa_family) {
  441 #ifdef INET
  442         case AF_INET:
  443         {
  444                 struct in_addr ia;
  445                 struct ifaddr *ifa;
  446                 int found;
  447 
  448                 found = 0;
  449                 /*
  450                  * Try to find an address on the given outgoing interface
  451                  * that belongs to the jail.
  452                  */
  453                 IF_ADDR_RLOCK(ifp);
  454                 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
  455                         struct sockaddr *sa;
  456                         sa = ifa->ifa_addr;
  457                         if (sa->sa_family != AF_INET)
  458                                 continue;
  459                         ia = ((struct sockaddr_in *)sa)->sin_addr;
  460                         if (prison_check_ip4(cred, &ia) == 0) {
  461                                 found = 1;
  462                                 break;
  463                         }
  464                 }
  465                 IF_ADDR_RUNLOCK(ifp);
  466                 if (!found) {
  467                         /*
  468                          * As a last resort return the 'default' jail address.
  469                          */
  470                         ia = ((struct sockaddr_in *)rt->rt_ifa->ifa_addr)->
  471                             sin_addr;
  472                         if (prison_get_ip4(cred, &ia) != 0)
  473                                 return (ESRCH);
  474                 }
  475                 bzero(&saun->sin, sizeof(struct sockaddr_in));
  476                 saun->sin.sin_len = sizeof(struct sockaddr_in);
  477                 saun->sin.sin_family = AF_INET;
  478                 saun->sin.sin_addr.s_addr = ia.s_addr;
  479                 info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin;
  480                 break;
  481         }
  482 #endif
  483 #ifdef INET6
  484         case AF_INET6:
  485         {
  486                 struct in6_addr ia6;
  487                 struct ifaddr *ifa;
  488                 int found;
  489 
  490                 found = 0;
  491                 /*
  492                  * Try to find an address on the given outgoing interface
  493                  * that belongs to the jail.
  494                  */
  495                 IF_ADDR_RLOCK(ifp);
  496                 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
  497                         struct sockaddr *sa;
  498                         sa = ifa->ifa_addr;
  499                         if (sa->sa_family != AF_INET6)
  500                                 continue;
  501                         bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr,
  502                             &ia6, sizeof(struct in6_addr));
  503                         if (prison_check_ip6(cred, &ia6) == 0) {
  504                                 found = 1;
  505                                 break;
  506                         }
  507                 }
  508                 IF_ADDR_RUNLOCK(ifp);
  509                 if (!found) {
  510                         /*
  511                          * As a last resort return the 'default' jail address.
  512                          */
  513                         ia6 = ((struct sockaddr_in6 *)rt->rt_ifa->ifa_addr)->
  514                             sin6_addr;
  515                         if (prison_get_ip6(cred, &ia6) != 0)
  516                                 return (ESRCH);
  517                 }
  518                 bzero(&saun->sin6, sizeof(struct sockaddr_in6));
  519                 saun->sin6.sin6_len = sizeof(struct sockaddr_in6);
  520                 saun->sin6.sin6_family = AF_INET6;
  521                 bcopy(&ia6, &saun->sin6.sin6_addr, sizeof(struct in6_addr));
  522                 if (sa6_recoverscope(&saun->sin6) != 0)
  523                         return (ESRCH);
  524                 info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin6;
  525                 break;
  526         }
  527 #endif
  528         default:
  529                 return (ESRCH);
  530         }
  531         return (0);
  532 }
  533 
  534 /*ARGSUSED*/
  535 static int
  536 route_output(struct mbuf *m, struct socket *so, ...)
  537 {
  538         struct rt_msghdr *rtm = NULL;
  539         struct rtentry *rt = NULL;
  540         struct rib_head *rnh;
  541         struct rt_addrinfo info;
  542         struct sockaddr_storage ss;
  543 #ifdef INET6
  544         struct sockaddr_in6 *sin6;
  545         int i, rti_need_deembed = 0;
  546 #endif
  547         int alloc_len = 0, len, error = 0, fibnum;
  548         struct ifnet *ifp = NULL;
  549         union sockaddr_union saun;
  550         sa_family_t saf = AF_UNSPEC;
  551         struct rawcb *rp = NULL;
  552         struct walkarg w;
  553 
  554         fibnum = so->so_fibnum;
  555 
  556 #define senderr(e) { error = e; goto flush;}
  557         if (m == NULL || ((m->m_len < sizeof(long)) &&
  558                        (m = m_pullup(m, sizeof(long))) == NULL))
  559                 return (ENOBUFS);
  560         if ((m->m_flags & M_PKTHDR) == 0)
  561                 panic("route_output");
  562         len = m->m_pkthdr.len;
  563         if (len < sizeof(*rtm) ||
  564             len != mtod(m, struct rt_msghdr *)->rtm_msglen)
  565                 senderr(EINVAL);
  566 
  567         /*
  568          * Most of current messages are in range 200-240 bytes,
  569          * minimize possible re-allocation on reply using larger size
  570          * buffer aligned on 1k boundaty.
  571          */
  572         alloc_len = roundup2(len, 1024);
  573         if ((rtm = malloc(alloc_len, M_TEMP, M_NOWAIT)) == NULL)
  574                 senderr(ENOBUFS);
  575 
  576         m_copydata(m, 0, len, (caddr_t)rtm);
  577         bzero(&info, sizeof(info));
  578         bzero(&w, sizeof(w));
  579 
  580         if (rtm->rtm_version != RTM_VERSION) {
  581                 /* Do not touch message since format is unknown */
  582                 free(rtm, M_TEMP);
  583                 rtm = NULL;
  584                 senderr(EPROTONOSUPPORT);
  585         }
  586 
  587         /*
  588          * Starting from here, it is possible
  589          * to alter original message and insert
  590          * caller PID and error value.
  591          */
  592 
  593         rtm->rtm_pid = curproc->p_pid;
  594         info.rti_addrs = rtm->rtm_addrs;
  595 
  596         info.rti_mflags = rtm->rtm_inits;
  597         info.rti_rmx = &rtm->rtm_rmx;
  598 
  599         /*
  600          * rt_xaddrs() performs s6_addr[2] := sin6_scope_id for AF_INET6
  601          * link-local address because rtrequest requires addresses with
  602          * embedded scope id.
  603          */
  604         if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info))
  605                 senderr(EINVAL);
  606 
  607         info.rti_flags = rtm->rtm_flags;
  608         if (info.rti_info[RTAX_DST] == NULL ||
  609             info.rti_info[RTAX_DST]->sa_family >= AF_MAX ||
  610             (info.rti_info[RTAX_GATEWAY] != NULL &&
  611              info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
  612                 senderr(EINVAL);
  613         saf = info.rti_info[RTAX_DST]->sa_family;
  614         /*
  615          * Verify that the caller has the appropriate privilege; RTM_GET
  616          * is the only operation the non-superuser is allowed.
  617          */
  618         if (rtm->rtm_type != RTM_GET) {
  619                 error = priv_check(curthread, PRIV_NET_ROUTE);
  620                 if (error)
  621                         senderr(error);
  622         }
  623 
  624         /*
  625          * The given gateway address may be an interface address.
  626          * For example, issuing a "route change" command on a route
  627          * entry that was created from a tunnel, and the gateway
  628          * address given is the local end point. In this case the 
  629          * RTF_GATEWAY flag must be cleared or the destination will
  630          * not be reachable even though there is no error message.
  631          */
  632         if (info.rti_info[RTAX_GATEWAY] != NULL &&
  633             info.rti_info[RTAX_GATEWAY]->sa_family != AF_LINK) {
  634                 struct rt_addrinfo ginfo;
  635                 struct sockaddr *gdst;
  636 
  637                 bzero(&ginfo, sizeof(ginfo));
  638                 bzero(&ss, sizeof(ss));
  639                 ss.ss_len = sizeof(ss);
  640 
  641                 ginfo.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&ss;
  642                 gdst = info.rti_info[RTAX_GATEWAY];
  643 
  644                 /* 
  645                  * A host route through the loopback interface is 
  646                  * installed for each interface adddress. In pre 8.0
  647                  * releases the interface address of a PPP link type
  648                  * is not reachable locally. This behavior is fixed as 
  649                  * part of the new L2/L3 redesign and rewrite work. The
  650                  * signature of this interface address route is the
  651                  * AF_LINK sa_family type of the rt_gateway, and the
  652                  * rt_ifp has the IFF_LOOPBACK flag set.
  653                  */
  654                 if (rib_lookup_info(fibnum, gdst, NHR_REF, 0, &ginfo) == 0) {
  655                         if (ss.ss_family == AF_LINK &&
  656                             ginfo.rti_ifp->if_flags & IFF_LOOPBACK) {
  657                                 info.rti_flags &= ~RTF_GATEWAY;
  658                                 info.rti_flags |= RTF_GWFLAG_COMPAT;
  659                         }
  660                         rib_free_info(&ginfo);
  661                 }
  662         }
  663 
  664         switch (rtm->rtm_type) {
  665                 struct rtentry *saved_nrt;
  666 
  667         case RTM_ADD:
  668         case RTM_CHANGE:
  669                 if (info.rti_info[RTAX_GATEWAY] == NULL)
  670                         senderr(EINVAL);
  671                 saved_nrt = NULL;
  672 
  673                 /* support for new ARP code */
  674                 if (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK &&
  675                     (rtm->rtm_flags & RTF_LLDATA) != 0) {
  676                         error = lla_rt_output(rtm, &info);
  677 #ifdef INET6
  678                         if (error == 0)
  679                                 rti_need_deembed = (V_deembed_scopeid) ? 1 : 0;
  680 #endif
  681                         break;
  682                 }
  683                 error = rtrequest1_fib(rtm->rtm_type, &info, &saved_nrt,
  684                     fibnum);
  685                 if (error == 0 && saved_nrt != NULL) {
  686 #ifdef INET6
  687                         rti_need_deembed = (V_deembed_scopeid) ? 1 : 0;
  688 #endif
  689                         RT_LOCK(saved_nrt);
  690                         rtm->rtm_index = saved_nrt->rt_ifp->if_index;
  691                         RT_REMREF(saved_nrt);
  692                         RT_UNLOCK(saved_nrt);
  693                 }
  694                 break;
  695 
  696         case RTM_DELETE:
  697                 saved_nrt = NULL;
  698                 /* support for new ARP code */
  699                 if (info.rti_info[RTAX_GATEWAY] && 
  700                     (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) &&
  701                     (rtm->rtm_flags & RTF_LLDATA) != 0) {
  702                         error = lla_rt_output(rtm, &info);
  703 #ifdef INET6
  704                         if (error == 0)
  705                                 rti_need_deembed = (V_deembed_scopeid) ? 1 : 0;
  706 #endif
  707                         break;
  708                 }
  709                 error = rtrequest1_fib(RTM_DELETE, &info, &saved_nrt, fibnum);
  710                 if (error == 0) {
  711                         RT_LOCK(saved_nrt);
  712                         rt = saved_nrt;
  713                         goto report;
  714                 }
  715 #ifdef INET6
  716                 /* rt_msg2() will not be used when RTM_DELETE fails. */
  717                 rti_need_deembed = (V_deembed_scopeid) ? 1 : 0;
  718 #endif
  719                 break;
  720 
  721         case RTM_GET:
  722                 rnh = rt_tables_get_rnh(fibnum, saf);
  723                 if (rnh == NULL)
  724                         senderr(EAFNOSUPPORT);
  725 
  726                 RIB_RLOCK(rnh);
  727 
  728                 if (info.rti_info[RTAX_NETMASK] == NULL &&
  729                     rtm->rtm_type == RTM_GET) {
  730                         /*
  731                          * Provide logest prefix match for
  732                          * address lookup (no mask).
  733                          * 'route -n get addr'
  734                          */
  735                         rt = (struct rtentry *) rnh->rnh_matchaddr(
  736                             info.rti_info[RTAX_DST], &rnh->head);
  737                 } else
  738                         rt = (struct rtentry *) rnh->rnh_lookup(
  739                             info.rti_info[RTAX_DST],
  740                             info.rti_info[RTAX_NETMASK], &rnh->head);
  741 
  742                 if (rt == NULL) {
  743                         RIB_RUNLOCK(rnh);
  744                         senderr(ESRCH);
  745                 }
  746 #ifdef RADIX_MPATH
  747                 /*
  748                  * for RTM_CHANGE/LOCK, if we got multipath routes,
  749                  * we require users to specify a matching RTAX_GATEWAY.
  750                  *
  751                  * for RTM_GET, gate is optional even with multipath.
  752                  * if gate == NULL the first match is returned.
  753                  * (no need to call rt_mpath_matchgate if gate == NULL)
  754                  */
  755                 if (rt_mpath_capable(rnh) &&
  756                     (rtm->rtm_type != RTM_GET || info.rti_info[RTAX_GATEWAY])) {
  757                         rt = rt_mpath_matchgate(rt, info.rti_info[RTAX_GATEWAY]);
  758                         if (!rt) {
  759                                 RIB_RUNLOCK(rnh);
  760                                 senderr(ESRCH);
  761                         }
  762                 }
  763 #endif
  764                 /*
  765                  * If performing proxied L2 entry insertion, and
  766                  * the actual PPP host entry is found, perform
  767                  * another search to retrieve the prefix route of
  768                  * the local end point of the PPP link.
  769                  */
  770                 if (rtm->rtm_flags & RTF_ANNOUNCE) {
  771                         struct sockaddr laddr;
  772 
  773                         if (rt->rt_ifp != NULL && 
  774                             rt->rt_ifp->if_type == IFT_PROPVIRTUAL) {
  775                                 struct ifaddr *ifa;
  776 
  777                                 ifa = ifa_ifwithnet(info.rti_info[RTAX_DST], 1,
  778                                                 RT_ALL_FIBS);
  779                                 if (ifa != NULL)
  780                                         rt_maskedcopy(ifa->ifa_addr,
  781                                                       &laddr,
  782                                                       ifa->ifa_netmask);
  783                         } else
  784                                 rt_maskedcopy(rt->rt_ifa->ifa_addr,
  785                                               &laddr,
  786                                               rt->rt_ifa->ifa_netmask);
  787                         /* 
  788                          * refactor rt and no lock operation necessary
  789                          */
  790                         rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr,
  791                             &rnh->head);
  792                         if (rt == NULL) {
  793                                 RIB_RUNLOCK(rnh);
  794                                 senderr(ESRCH);
  795                         }
  796                 } 
  797                 RT_LOCK(rt);
  798                 RT_ADDREF(rt);
  799                 RIB_RUNLOCK(rnh);
  800 
  801 report:
  802                 RT_LOCK_ASSERT(rt);
  803                 if ((rt->rt_flags & RTF_HOST) == 0
  804                     ? jailed_without_vnet(curthread->td_ucred)
  805                     : prison_if(curthread->td_ucred,
  806                     rt_key(rt)) != 0) {
  807                         RT_UNLOCK(rt);
  808                         senderr(ESRCH);
  809                 }
  810                 info.rti_info[RTAX_DST] = rt_key(rt);
  811                 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
  812                 info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt),
  813                     rt_mask(rt), &ss);
  814                 info.rti_info[RTAX_GENMASK] = 0;
  815                 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
  816                         ifp = rt->rt_ifp;
  817                         if (ifp) {
  818                                 info.rti_info[RTAX_IFP] =
  819                                     ifp->if_addr->ifa_addr;
  820                                 error = rtm_get_jailed(&info, ifp, rt,
  821                                     &saun, curthread->td_ucred);
  822                                 if (error != 0) {
  823                                         RT_UNLOCK(rt);
  824                                         senderr(error);
  825                                 }
  826                                 if (ifp->if_flags & IFF_POINTOPOINT)
  827                                         info.rti_info[RTAX_BRD] =
  828                                             rt->rt_ifa->ifa_dstaddr;
  829                                 rtm->rtm_index = ifp->if_index;
  830                         } else {
  831                                 info.rti_info[RTAX_IFP] = NULL;
  832                                 info.rti_info[RTAX_IFA] = NULL;
  833                         }
  834                 } else if ((ifp = rt->rt_ifp) != NULL) {
  835                         rtm->rtm_index = ifp->if_index;
  836                 }
  837 
  838                 /* Check if we need to realloc storage */
  839                 rtsock_msg_buffer(rtm->rtm_type, &info, NULL, &len);
  840                 if (len > alloc_len) {
  841                         struct rt_msghdr *new_rtm;
  842                         new_rtm = malloc(len, M_TEMP, M_NOWAIT);
  843                         if (new_rtm == NULL) {
  844                                 RT_UNLOCK(rt);
  845                                 senderr(ENOBUFS);
  846                         }
  847                         bcopy(rtm, new_rtm, rtm->rtm_msglen);
  848                         free(rtm, M_TEMP);
  849                         rtm = new_rtm;
  850                         alloc_len = len;
  851                 }
  852 
  853                 w.w_tmem = (caddr_t)rtm;
  854                 w.w_tmemsize = alloc_len;
  855                 rtsock_msg_buffer(rtm->rtm_type, &info, &w, &len);
  856 
  857                 if (rt->rt_flags & RTF_GWFLAG_COMPAT)
  858                         rtm->rtm_flags = RTF_GATEWAY | 
  859                                 (rt->rt_flags & ~RTF_GWFLAG_COMPAT);
  860                 else
  861                         rtm->rtm_flags = rt->rt_flags;
  862                 rt_getmetrics(rt, &rtm->rtm_rmx);
  863                 rtm->rtm_addrs = info.rti_addrs;
  864 
  865                 RT_UNLOCK(rt);
  866                 break;
  867 
  868         default:
  869                 senderr(EOPNOTSUPP);
  870         }
  871 
  872 flush:
  873         if (rt != NULL)
  874                 RTFREE(rt);
  875         /*
  876          * Check to see if we don't want our own messages.
  877          */
  878         if ((so->so_options & SO_USELOOPBACK) == 0) {
  879                 if (V_route_cb.any_count <= 1) {
  880                         if (rtm != NULL)
  881                                 free(rtm, M_TEMP);
  882                         m_freem(m);
  883                         return (error);
  884                 }
  885                 /* There is another listener, so construct message */
  886                 rp = sotorawcb(so);
  887         }
  888 
  889         if (rtm != NULL) {
  890 #ifdef INET6
  891                 if (rti_need_deembed) {
  892                         /* sin6_scope_id is recovered before sending rtm. */
  893                         sin6 = (struct sockaddr_in6 *)&ss;
  894                         for (i = 0; i < RTAX_MAX; i++) {
  895                                 if (info.rti_info[i] == NULL)
  896                                         continue;
  897                                 if (info.rti_info[i]->sa_family != AF_INET6)
  898                                         continue;
  899                                 bcopy(info.rti_info[i], sin6, sizeof(*sin6));
  900                                 if (sa6_recoverscope(sin6) == 0)
  901                                         bcopy(sin6, info.rti_info[i],
  902                                                     sizeof(*sin6));
  903                         }
  904                 }
  905 #endif
  906                 if (error != 0)
  907                         rtm->rtm_errno = error;
  908                 else
  909                         rtm->rtm_flags |= RTF_DONE;
  910 
  911                 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
  912                 if (m->m_pkthdr.len < rtm->rtm_msglen) {
  913                         m_freem(m);
  914                         m = NULL;
  915                 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
  916                         m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
  917 
  918                 free(rtm, M_TEMP);
  919         }
  920         if (m != NULL) {
  921                 M_SETFIB(m, fibnum);
  922                 m->m_flags |= RTS_FILTER_FIB;
  923                 if (rp) {
  924                         /*
  925                          * XXX insure we don't get a copy by
  926                          * invalidating our protocol
  927                          */
  928                         unsigned short family = rp->rcb_proto.sp_family;
  929                         rp->rcb_proto.sp_family = 0;
  930                         rt_dispatch(m, saf);
  931                         rp->rcb_proto.sp_family = family;
  932                 } else
  933                         rt_dispatch(m, saf);
  934         }
  935 
  936         return (error);
  937 }
  938 
  939 static void
  940 rt_getmetrics(const struct rtentry *rt, struct rt_metrics *out)
  941 {
  942 
  943         bzero(out, sizeof(*out));
  944         out->rmx_mtu = rt->rt_mtu;
  945         out->rmx_weight = rt->rt_weight;
  946         out->rmx_pksent = counter_u64_fetch(rt->rt_pksent);
  947         /* Kernel -> userland timebase conversion. */
  948         out->rmx_expire = rt->rt_expire ?
  949             rt->rt_expire - time_uptime + time_second : 0;
  950 }
  951 
  952 /*
  953  * Extract the addresses of the passed sockaddrs.
  954  * Do a little sanity checking so as to avoid bad memory references.
  955  * This data is derived straight from userland.
  956  */
  957 static int
  958 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
  959 {
  960         struct sockaddr *sa;
  961         int i;
  962 
  963         for (i = 0; i < RTAX_MAX && cp < cplim; i++) {
  964                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
  965                         continue;
  966                 sa = (struct sockaddr *)cp;
  967                 /*
  968                  * It won't fit.
  969                  */
  970                 if (cp + sa->sa_len > cplim)
  971                         return (EINVAL);
  972                 /*
  973                  * there are no more.. quit now
  974                  * If there are more bits, they are in error.
  975                  * I've seen this. route(1) can evidently generate these. 
  976                  * This causes kernel to core dump.
  977                  * for compatibility, If we see this, point to a safe address.
  978                  */
  979                 if (sa->sa_len == 0) {
  980                         rtinfo->rti_info[i] = &sa_zero;
  981                         return (0); /* should be EINVAL but for compat */
  982                 }
  983                 /* accept it */
  984 #ifdef INET6
  985                 if (sa->sa_family == AF_INET6)
  986                         sa6_embedscope((struct sockaddr_in6 *)sa,
  987                             V_ip6_use_defzone);
  988 #endif
  989                 rtinfo->rti_info[i] = sa;
  990                 cp += SA_SIZE(sa);
  991         }
  992         return (0);
  993 }
  994 
  995 /*
  996  * Fill in @dmask with valid netmask leaving original @smask
  997  * intact. Mostly used with radix netmasks.
  998  */
  999 static struct sockaddr *
 1000 rtsock_fix_netmask(struct sockaddr *dst, struct sockaddr *smask,
 1001     struct sockaddr_storage *dmask)
 1002 {
 1003         if (dst == NULL || smask == NULL)
 1004                 return (NULL);
 1005 
 1006         memset(dmask, 0, dst->sa_len);
 1007         memcpy(dmask, smask, smask->sa_len);
 1008         dmask->ss_len = dst->sa_len;
 1009         dmask->ss_family = dst->sa_family;
 1010 
 1011         return ((struct sockaddr *)dmask);
 1012 }
 1013 
 1014 /*
 1015  * Writes information related to @rtinfo object to newly-allocated mbuf.
 1016  * Assumes MCLBYTES is enough to construct any message.
 1017  * Used for OS notifications of vaious events (if/ifa announces,etc)
 1018  *
 1019  * Returns allocated mbuf or NULL on failure.
 1020  */
 1021 static struct mbuf *
 1022 rtsock_msg_mbuf(int type, struct rt_addrinfo *rtinfo)
 1023 {
 1024         struct rt_msghdr *rtm;
 1025         struct mbuf *m;
 1026         int i;
 1027         struct sockaddr *sa;
 1028 #ifdef INET6
 1029         struct sockaddr_storage ss;
 1030         struct sockaddr_in6 *sin6;
 1031 #endif
 1032         int len, dlen;
 1033 
 1034         switch (type) {
 1035 
 1036         case RTM_DELADDR:
 1037         case RTM_NEWADDR:
 1038                 len = sizeof(struct ifa_msghdr);
 1039                 break;
 1040 
 1041         case RTM_DELMADDR:
 1042         case RTM_NEWMADDR:
 1043                 len = sizeof(struct ifma_msghdr);
 1044                 break;
 1045 
 1046         case RTM_IFINFO:
 1047                 len = sizeof(struct if_msghdr);
 1048                 break;
 1049 
 1050         case RTM_IFANNOUNCE:
 1051         case RTM_IEEE80211:
 1052                 len = sizeof(struct if_announcemsghdr);
 1053                 break;
 1054 
 1055         default:
 1056                 len = sizeof(struct rt_msghdr);
 1057         }
 1058 
 1059         /* XXXGL: can we use MJUMPAGESIZE cluster here? */
 1060         KASSERT(len <= MCLBYTES, ("%s: message too big", __func__));
 1061         if (len > MHLEN)
 1062                 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
 1063         else
 1064                 m = m_gethdr(M_NOWAIT, MT_DATA);
 1065         if (m == NULL)
 1066                 return (m);
 1067 
 1068         m->m_pkthdr.len = m->m_len = len;
 1069         rtm = mtod(m, struct rt_msghdr *);
 1070         bzero((caddr_t)rtm, len);
 1071         for (i = 0; i < RTAX_MAX; i++) {
 1072                 if ((sa = rtinfo->rti_info[i]) == NULL)
 1073                         continue;
 1074                 rtinfo->rti_addrs |= (1 << i);
 1075                 dlen = SA_SIZE(sa);
 1076 #ifdef INET6
 1077                 if (V_deembed_scopeid && sa->sa_family == AF_INET6) {
 1078                         sin6 = (struct sockaddr_in6 *)&ss;
 1079                         bcopy(sa, sin6, sizeof(*sin6));
 1080                         if (sa6_recoverscope(sin6) == 0)
 1081                                 sa = (struct sockaddr *)sin6;
 1082                 }
 1083 #endif
 1084                 m_copyback(m, len, dlen, (caddr_t)sa);
 1085                 len += dlen;
 1086         }
 1087         if (m->m_pkthdr.len != len) {
 1088                 m_freem(m);
 1089                 return (NULL);
 1090         }
 1091         rtm->rtm_msglen = len;
 1092         rtm->rtm_version = RTM_VERSION;
 1093         rtm->rtm_type = type;
 1094         return (m);
 1095 }
 1096 
 1097 /*
 1098  * Writes information related to @rtinfo object to preallocated buffer.
 1099  * Stores needed size in @plen. If @w is NULL, calculates size without
 1100  * writing.
 1101  * Used for sysctl dumps and rtsock answers (RTM_DEL/RTM_GET) generation.
 1102  *
 1103  * Returns 0 on success.
 1104  *
 1105  */
 1106 static int
 1107 rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int *plen)
 1108 {
 1109         int i;
 1110         int len, buflen = 0, dlen;
 1111         caddr_t cp = NULL;
 1112         struct rt_msghdr *rtm = NULL;
 1113 #ifdef INET6
 1114         struct sockaddr_storage ss;
 1115         struct sockaddr_in6 *sin6;
 1116 #endif
 1117 
 1118         switch (type) {
 1119 
 1120         case RTM_DELADDR:
 1121         case RTM_NEWADDR:
 1122                 if (w != NULL && w->w_op == NET_RT_IFLISTL) {
 1123 #ifdef COMPAT_FREEBSD32
 1124                         if (w->w_req->flags & SCTL_MASK32)
 1125                                 len = sizeof(struct ifa_msghdrl32);
 1126                         else
 1127 #endif
 1128                                 len = sizeof(struct ifa_msghdrl);
 1129                 } else
 1130                         len = sizeof(struct ifa_msghdr);
 1131                 break;
 1132 
 1133         case RTM_IFINFO:
 1134 #ifdef COMPAT_FREEBSD32
 1135                 if (w != NULL && w->w_req->flags & SCTL_MASK32) {
 1136                         if (w->w_op == NET_RT_IFLISTL)
 1137                                 len = sizeof(struct if_msghdrl32);
 1138                         else
 1139                                 len = sizeof(struct if_msghdr32);
 1140                         break;
 1141                 }
 1142 #endif
 1143                 if (w != NULL && w->w_op == NET_RT_IFLISTL)
 1144                         len = sizeof(struct if_msghdrl);
 1145                 else
 1146                         len = sizeof(struct if_msghdr);
 1147                 break;
 1148 
 1149         case RTM_NEWMADDR:
 1150                 len = sizeof(struct ifma_msghdr);
 1151                 break;
 1152 
 1153         default:
 1154                 len = sizeof(struct rt_msghdr);
 1155         }
 1156 
 1157         if (w != NULL) {
 1158                 rtm = (struct rt_msghdr *)w->w_tmem;
 1159                 buflen = w->w_tmemsize - len;
 1160                 cp = (caddr_t)w->w_tmem + len;
 1161         }
 1162 
 1163         rtinfo->rti_addrs = 0;
 1164         for (i = 0; i < RTAX_MAX; i++) {
 1165                 struct sockaddr *sa;
 1166 
 1167                 if ((sa = rtinfo->rti_info[i]) == NULL)
 1168                         continue;
 1169                 rtinfo->rti_addrs |= (1 << i);
 1170                 dlen = SA_SIZE(sa);
 1171                 if (cp != NULL && buflen >= dlen) {
 1172 #ifdef INET6
 1173                         if (V_deembed_scopeid && sa->sa_family == AF_INET6) {
 1174                                 sin6 = (struct sockaddr_in6 *)&ss;
 1175                                 bcopy(sa, sin6, sizeof(*sin6));
 1176                                 if (sa6_recoverscope(sin6) == 0)
 1177                                         sa = (struct sockaddr *)sin6;
 1178                         }
 1179 #endif
 1180                         bcopy((caddr_t)sa, cp, (unsigned)dlen);
 1181                         cp += dlen;
 1182                         buflen -= dlen;
 1183                 } else if (cp != NULL) {
 1184                         /*
 1185                          * Buffer too small. Count needed size
 1186                          * and return with error.
 1187                          */
 1188                         cp = NULL;
 1189                 }
 1190 
 1191                 len += dlen;
 1192         }
 1193 
 1194         if (cp != NULL) {
 1195                 dlen = ALIGN(len) - len;
 1196                 if (buflen < dlen)
 1197                         cp = NULL;
 1198                 else
 1199                         buflen -= dlen;
 1200         }
 1201         len = ALIGN(len);
 1202 
 1203         if (cp != NULL) {
 1204                 /* fill header iff buffer is large enough */
 1205                 rtm->rtm_version = RTM_VERSION;
 1206                 rtm->rtm_type = type;
 1207                 rtm->rtm_msglen = len;
 1208         }
 1209 
 1210         *plen = len;
 1211 
 1212         if (w != NULL && cp == NULL)
 1213                 return (ENOBUFS);
 1214 
 1215         return (0);
 1216 }
 1217 
 1218 /*
 1219  * This routine is called to generate a message from the routing
 1220  * socket indicating that a redirect has occurred, a routing lookup
 1221  * has failed, or that a protocol has detected timeouts to a particular
 1222  * destination.
 1223  */
 1224 void
 1225 rt_missmsg_fib(int type, struct rt_addrinfo *rtinfo, int flags, int error,
 1226     int fibnum)
 1227 {
 1228         struct rt_msghdr *rtm;
 1229         struct mbuf *m;
 1230         struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
 1231 
 1232         if (V_route_cb.any_count == 0)
 1233                 return;
 1234         m = rtsock_msg_mbuf(type, rtinfo);
 1235         if (m == NULL)
 1236                 return;
 1237 
 1238         if (fibnum != RT_ALL_FIBS) {
 1239                 KASSERT(fibnum >= 0 && fibnum < rt_numfibs, ("%s: fibnum out "
 1240                     "of range 0 <= %d < %d", __func__, fibnum, rt_numfibs));
 1241                 M_SETFIB(m, fibnum);
 1242                 m->m_flags |= RTS_FILTER_FIB;
 1243         }
 1244 
 1245         rtm = mtod(m, struct rt_msghdr *);
 1246         rtm->rtm_flags = RTF_DONE | flags;
 1247         rtm->rtm_errno = error;
 1248         rtm->rtm_addrs = rtinfo->rti_addrs;
 1249         rt_dispatch(m, sa ? sa->sa_family : AF_UNSPEC);
 1250 }
 1251 
 1252 void
 1253 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
 1254 {
 1255 
 1256         rt_missmsg_fib(type, rtinfo, flags, error, RT_ALL_FIBS);
 1257 }
 1258 
 1259 /*
 1260  * This routine is called to generate a message from the routing
 1261  * socket indicating that the status of a network interface has changed.
 1262  */
 1263 void
 1264 rt_ifmsg(struct ifnet *ifp)
 1265 {
 1266         struct if_msghdr *ifm;
 1267         struct mbuf *m;
 1268         struct rt_addrinfo info;
 1269 
 1270         if (V_route_cb.any_count == 0)
 1271                 return;
 1272         bzero((caddr_t)&info, sizeof(info));
 1273         m = rtsock_msg_mbuf(RTM_IFINFO, &info);
 1274         if (m == NULL)
 1275                 return;
 1276         ifm = mtod(m, struct if_msghdr *);
 1277         ifm->ifm_index = ifp->if_index;
 1278         ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
 1279         if_data_copy(ifp, &ifm->ifm_data);
 1280         ifm->ifm_addrs = 0;
 1281         rt_dispatch(m, AF_UNSPEC);
 1282 }
 1283 
 1284 /*
 1285  * Announce interface address arrival/withdraw.
 1286  * Please do not call directly, use rt_addrmsg().
 1287  * Assume input data to be valid.
 1288  * Returns 0 on success.
 1289  */
 1290 int
 1291 rtsock_addrmsg(int cmd, struct ifaddr *ifa, int fibnum)
 1292 {
 1293         struct rt_addrinfo info;
 1294         struct sockaddr *sa;
 1295         int ncmd;
 1296         struct mbuf *m;
 1297         struct ifa_msghdr *ifam;
 1298         struct ifnet *ifp = ifa->ifa_ifp;
 1299         struct sockaddr_storage ss;
 1300 
 1301         if (V_route_cb.any_count == 0)
 1302                 return (0);
 1303 
 1304         ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
 1305 
 1306         bzero((caddr_t)&info, sizeof(info));
 1307         info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr;
 1308         info.rti_info[RTAX_IFP] = ifp->if_addr->ifa_addr;
 1309         info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(
 1310             info.rti_info[RTAX_IFP], ifa->ifa_netmask, &ss);
 1311         info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
 1312         if ((m = rtsock_msg_mbuf(ncmd, &info)) == NULL)
 1313                 return (ENOBUFS);
 1314         ifam = mtod(m, struct ifa_msghdr *);
 1315         ifam->ifam_index = ifp->if_index;
 1316         ifam->ifam_metric = ifa->ifa_ifp->if_metric;
 1317         ifam->ifam_flags = ifa->ifa_flags;
 1318         ifam->ifam_addrs = info.rti_addrs;
 1319 
 1320         if (fibnum != RT_ALL_FIBS) {
 1321                 M_SETFIB(m, fibnum);
 1322                 m->m_flags |= RTS_FILTER_FIB;
 1323         }
 1324 
 1325         rt_dispatch(m, sa ? sa->sa_family : AF_UNSPEC);
 1326 
 1327         return (0);
 1328 }
 1329 
 1330 /*
 1331  * Announce route addition/removal.
 1332  * Please do not call directly, use rt_routemsg().
 1333  * Note that @rt data MAY be inconsistent/invalid:
 1334  * if some userland app sends us "invalid" route message (invalid mask,
 1335  * no dst, wrong address families, etc...) we need to pass it back
 1336  * to app (and any other rtsock consumers) with rtm_errno field set to
 1337  * non-zero value.
 1338  *
 1339  * Returns 0 on success.
 1340  */
 1341 int
 1342 rtsock_routemsg(int cmd, struct ifnet *ifp, int error, struct rtentry *rt,
 1343     int fibnum)
 1344 {
 1345         struct rt_addrinfo info;
 1346         struct sockaddr *sa;
 1347         struct mbuf *m;
 1348         struct rt_msghdr *rtm;
 1349         struct sockaddr_storage ss;
 1350 
 1351         if (V_route_cb.any_count == 0)
 1352                 return (0);
 1353 
 1354         bzero((caddr_t)&info, sizeof(info));
 1355         info.rti_info[RTAX_DST] = sa = rt_key(rt);
 1356         info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(sa, rt_mask(rt), &ss);
 1357         info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
 1358         if ((m = rtsock_msg_mbuf(cmd, &info)) == NULL)
 1359                 return (ENOBUFS);
 1360         rtm = mtod(m, struct rt_msghdr *);
 1361         rtm->rtm_index = ifp->if_index;
 1362         rtm->rtm_flags |= rt->rt_flags;
 1363         rtm->rtm_errno = error;
 1364         rtm->rtm_addrs = info.rti_addrs;
 1365 
 1366         if (fibnum != RT_ALL_FIBS) {
 1367                 M_SETFIB(m, fibnum);
 1368                 m->m_flags |= RTS_FILTER_FIB;
 1369         }
 1370 
 1371         rt_dispatch(m, sa ? sa->sa_family : AF_UNSPEC);
 1372 
 1373         return (0);
 1374 }
 1375 
 1376 /*
 1377  * This is the analogue to the rt_newaddrmsg which performs the same
 1378  * function but for multicast group memberhips.  This is easier since
 1379  * there is no route state to worry about.
 1380  */
 1381 void
 1382 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
 1383 {
 1384         struct rt_addrinfo info;
 1385         struct mbuf *m = NULL;
 1386         struct ifnet *ifp = ifma->ifma_ifp;
 1387         struct ifma_msghdr *ifmam;
 1388 
 1389         if (V_route_cb.any_count == 0)
 1390                 return;
 1391 
 1392         bzero((caddr_t)&info, sizeof(info));
 1393         info.rti_info[RTAX_IFA] = ifma->ifma_addr;
 1394         info.rti_info[RTAX_IFP] = ifp ? ifp->if_addr->ifa_addr : NULL;
 1395         /*
 1396          * If a link-layer address is present, present it as a ``gateway''
 1397          * (similarly to how ARP entries, e.g., are presented).
 1398          */
 1399         info.rti_info[RTAX_GATEWAY] = ifma->ifma_lladdr;
 1400         m = rtsock_msg_mbuf(cmd, &info);
 1401         if (m == NULL)
 1402                 return;
 1403         ifmam = mtod(m, struct ifma_msghdr *);
 1404         KASSERT(ifp != NULL, ("%s: link-layer multicast address w/o ifp\n",
 1405             __func__));
 1406         ifmam->ifmam_index = ifp->if_index;
 1407         ifmam->ifmam_addrs = info.rti_addrs;
 1408         rt_dispatch(m, ifma->ifma_addr ? ifma->ifma_addr->sa_family : AF_UNSPEC);
 1409 }
 1410 
 1411 static struct mbuf *
 1412 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what,
 1413         struct rt_addrinfo *info)
 1414 {
 1415         struct if_announcemsghdr *ifan;
 1416         struct mbuf *m;
 1417 
 1418         if (V_route_cb.any_count == 0)
 1419                 return NULL;
 1420         bzero((caddr_t)info, sizeof(*info));
 1421         m = rtsock_msg_mbuf(type, info);
 1422         if (m != NULL) {
 1423                 ifan = mtod(m, struct if_announcemsghdr *);
 1424                 ifan->ifan_index = ifp->if_index;
 1425                 strlcpy(ifan->ifan_name, ifp->if_xname,
 1426                         sizeof(ifan->ifan_name));
 1427                 ifan->ifan_what = what;
 1428         }
 1429         return m;
 1430 }
 1431 
 1432 /*
 1433  * This is called to generate routing socket messages indicating
 1434  * IEEE80211 wireless events.
 1435  * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way.
 1436  */
 1437 void
 1438 rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len)
 1439 {
 1440         struct mbuf *m;
 1441         struct rt_addrinfo info;
 1442 
 1443         m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info);
 1444         if (m != NULL) {
 1445                 /*
 1446                  * Append the ieee80211 data.  Try to stick it in the
 1447                  * mbuf containing the ifannounce msg; otherwise allocate
 1448                  * a new mbuf and append.
 1449                  *
 1450                  * NB: we assume m is a single mbuf.
 1451                  */
 1452                 if (data_len > M_TRAILINGSPACE(m)) {
 1453                         struct mbuf *n = m_get(M_NOWAIT, MT_DATA);
 1454                         if (n == NULL) {
 1455                                 m_freem(m);
 1456                                 return;
 1457                         }
 1458                         bcopy(data, mtod(n, void *), data_len);
 1459                         n->m_len = data_len;
 1460                         m->m_next = n;
 1461                 } else if (data_len > 0) {
 1462                         bcopy(data, mtod(m, u_int8_t *) + m->m_len, data_len);
 1463                         m->m_len += data_len;
 1464                 }
 1465                 if (m->m_flags & M_PKTHDR)
 1466                         m->m_pkthdr.len += data_len;
 1467                 mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len;
 1468                 rt_dispatch(m, AF_UNSPEC);
 1469         }
 1470 }
 1471 
 1472 /*
 1473  * This is called to generate routing socket messages indicating
 1474  * network interface arrival and departure.
 1475  */
 1476 void
 1477 rt_ifannouncemsg(struct ifnet *ifp, int what)
 1478 {
 1479         struct mbuf *m;
 1480         struct rt_addrinfo info;
 1481 
 1482         m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info);
 1483         if (m != NULL)
 1484                 rt_dispatch(m, AF_UNSPEC);
 1485 }
 1486 
 1487 static void
 1488 rt_dispatch(struct mbuf *m, sa_family_t saf)
 1489 {
 1490         struct m_tag *tag;
 1491 
 1492         /*
 1493          * Preserve the family from the sockaddr, if any, in an m_tag for
 1494          * use when injecting the mbuf into the routing socket buffer from
 1495          * the netisr.
 1496          */
 1497         if (saf != AF_UNSPEC) {
 1498                 tag = m_tag_get(PACKET_TAG_RTSOCKFAM, sizeof(unsigned short),
 1499                     M_NOWAIT);
 1500                 if (tag == NULL) {
 1501                         m_freem(m);
 1502                         return;
 1503                 }
 1504                 *(unsigned short *)(tag + 1) = saf;
 1505                 m_tag_prepend(m, tag);
 1506         }
 1507 #ifdef VIMAGE
 1508         if (V_loif)
 1509                 m->m_pkthdr.rcvif = V_loif;
 1510         else {
 1511                 m_freem(m);
 1512                 return;
 1513         }
 1514 #endif
 1515         netisr_queue(NETISR_ROUTE, m);  /* mbuf is free'd on failure. */
 1516 }
 1517 
 1518 /*
 1519  * This is used in dumping the kernel table via sysctl().
 1520  */
 1521 static int
 1522 sysctl_dumpentry(struct radix_node *rn, void *vw)
 1523 {
 1524         struct walkarg *w = vw;
 1525         struct rtentry *rt = (struct rtentry *)rn;
 1526         int error = 0, size;
 1527         struct rt_addrinfo info;
 1528         struct sockaddr_storage ss;
 1529 
 1530         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
 1531                 return 0;
 1532         if ((rt->rt_flags & RTF_HOST) == 0
 1533             ? jailed_without_vnet(w->w_req->td->td_ucred)
 1534             : prison_if(w->w_req->td->td_ucred, rt_key(rt)) != 0)
 1535                 return (0);
 1536         bzero((caddr_t)&info, sizeof(info));
 1537         info.rti_info[RTAX_DST] = rt_key(rt);
 1538         info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
 1539         info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt),
 1540             rt_mask(rt), &ss);
 1541         info.rti_info[RTAX_GENMASK] = 0;
 1542         if (rt->rt_ifp) {
 1543                 info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addr->ifa_addr;
 1544                 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
 1545                 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
 1546                         info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr;
 1547         }
 1548         if ((error = rtsock_msg_buffer(RTM_GET, &info, w, &size)) != 0)
 1549                 return (error);
 1550         if (w->w_req && w->w_tmem) {
 1551                 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
 1552 
 1553                 if (rt->rt_flags & RTF_GWFLAG_COMPAT)
 1554                         rtm->rtm_flags = RTF_GATEWAY | 
 1555                                 (rt->rt_flags & ~RTF_GWFLAG_COMPAT);
 1556                 else
 1557                         rtm->rtm_flags = rt->rt_flags;
 1558                 rt_getmetrics(rt, &rtm->rtm_rmx);
 1559                 rtm->rtm_index = rt->rt_ifp->if_index;
 1560                 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
 1561                 rtm->rtm_addrs = info.rti_addrs;
 1562                 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
 1563                 return (error);
 1564         }
 1565         return (error);
 1566 }
 1567 
 1568 static int
 1569 sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info,
 1570     struct walkarg *w, int len)
 1571 {
 1572         struct if_msghdrl *ifm;
 1573         struct if_data *ifd;
 1574 
 1575         ifm = (struct if_msghdrl *)w->w_tmem;
 1576 
 1577 #ifdef COMPAT_FREEBSD32
 1578         if (w->w_req->flags & SCTL_MASK32) {
 1579                 struct if_msghdrl32 *ifm32;
 1580 
 1581                 ifm32 = (struct if_msghdrl32 *)ifm;
 1582                 ifm32->ifm_addrs = info->rti_addrs;
 1583                 ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
 1584                 ifm32->ifm_index = ifp->if_index;
 1585                 ifm32->_ifm_spare1 = 0;
 1586                 ifm32->ifm_len = sizeof(*ifm32);
 1587                 ifm32->ifm_data_off = offsetof(struct if_msghdrl32, ifm_data);
 1588                 ifd = &ifm32->ifm_data;
 1589         } else
 1590 #endif
 1591         {
 1592                 ifm->ifm_addrs = info->rti_addrs;
 1593                 ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
 1594                 ifm->ifm_index = ifp->if_index;
 1595                 ifm->_ifm_spare1 = 0;
 1596                 ifm->ifm_len = sizeof(*ifm);
 1597                 ifm->ifm_data_off = offsetof(struct if_msghdrl, ifm_data);
 1598                 ifd = &ifm->ifm_data;
 1599         }
 1600 
 1601         if_data_copy(ifp, ifd);
 1602 
 1603         return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
 1604 }
 1605 
 1606 static int
 1607 sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info,
 1608     struct walkarg *w, int len)
 1609 {
 1610         struct if_msghdr *ifm;
 1611         struct if_data *ifd;
 1612 
 1613         ifm = (struct if_msghdr *)w->w_tmem;
 1614 
 1615 #ifdef COMPAT_FREEBSD32
 1616         if (w->w_req->flags & SCTL_MASK32) {
 1617                 struct if_msghdr32 *ifm32;
 1618 
 1619                 ifm32 = (struct if_msghdr32 *)ifm;
 1620                 ifm32->ifm_addrs = info->rti_addrs;
 1621                 ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
 1622                 ifm32->ifm_index = ifp->if_index;
 1623                 ifd = &ifm32->ifm_data;
 1624         } else
 1625 #endif
 1626         {
 1627                 ifm->ifm_addrs = info->rti_addrs;
 1628                 ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
 1629                 ifm->ifm_index = ifp->if_index;
 1630                 ifd = &ifm->ifm_data;
 1631         }
 1632 
 1633         if_data_copy(ifp, ifd);
 1634 
 1635         return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
 1636 }
 1637 
 1638 static int
 1639 sysctl_iflist_ifaml(struct ifaddr *ifa, struct rt_addrinfo *info,
 1640     struct walkarg *w, int len)
 1641 {
 1642         struct ifa_msghdrl *ifam;
 1643         struct if_data *ifd;
 1644 
 1645         ifam = (struct ifa_msghdrl *)w->w_tmem;
 1646 
 1647 #ifdef COMPAT_FREEBSD32
 1648         if (w->w_req->flags & SCTL_MASK32) {
 1649                 struct ifa_msghdrl32 *ifam32;
 1650 
 1651                 ifam32 = (struct ifa_msghdrl32 *)ifam;
 1652                 ifam32->ifam_addrs = info->rti_addrs;
 1653                 ifam32->ifam_flags = ifa->ifa_flags;
 1654                 ifam32->ifam_index = ifa->ifa_ifp->if_index;
 1655                 ifam32->_ifam_spare1 = 0;
 1656                 ifam32->ifam_len = sizeof(*ifam32);
 1657                 ifam32->ifam_data_off =
 1658                     offsetof(struct ifa_msghdrl32, ifam_data);
 1659                 ifam32->ifam_metric = ifa->ifa_ifp->if_metric;
 1660                 ifd = &ifam32->ifam_data;
 1661         } else
 1662 #endif
 1663         {
 1664                 ifam->ifam_addrs = info->rti_addrs;
 1665                 ifam->ifam_flags = ifa->ifa_flags;
 1666                 ifam->ifam_index = ifa->ifa_ifp->if_index;
 1667                 ifam->_ifam_spare1 = 0;
 1668                 ifam->ifam_len = sizeof(*ifam);
 1669                 ifam->ifam_data_off = offsetof(struct ifa_msghdrl, ifam_data);
 1670                 ifam->ifam_metric = ifa->ifa_ifp->if_metric;
 1671                 ifd = &ifam->ifam_data;
 1672         }
 1673 
 1674         bzero(ifd, sizeof(*ifd));
 1675         ifd->ifi_datalen = sizeof(struct if_data);
 1676         ifd->ifi_ipackets = counter_u64_fetch(ifa->ifa_ipackets);
 1677         ifd->ifi_opackets = counter_u64_fetch(ifa->ifa_opackets);
 1678         ifd->ifi_ibytes = counter_u64_fetch(ifa->ifa_ibytes);
 1679         ifd->ifi_obytes = counter_u64_fetch(ifa->ifa_obytes);
 1680 
 1681         /* Fixup if_data carp(4) vhid. */
 1682         if (carp_get_vhid_p != NULL)
 1683                 ifd->ifi_vhid = (*carp_get_vhid_p)(ifa);
 1684 
 1685         return (SYSCTL_OUT(w->w_req, w->w_tmem, len));
 1686 }
 1687 
 1688 static int
 1689 sysctl_iflist_ifam(struct ifaddr *ifa, struct rt_addrinfo *info,
 1690     struct walkarg *w, int len)
 1691 {
 1692         struct ifa_msghdr *ifam;
 1693 
 1694         ifam = (struct ifa_msghdr *)w->w_tmem;
 1695         ifam->ifam_addrs = info->rti_addrs;
 1696         ifam->ifam_flags = ifa->ifa_flags;
 1697         ifam->ifam_index = ifa->ifa_ifp->if_index;
 1698         ifam->ifam_metric = ifa->ifa_ifp->if_metric;
 1699 
 1700         return (SYSCTL_OUT(w->w_req, w->w_tmem, len));
 1701 }
 1702 
 1703 static int
 1704 sysctl_iflist(int af, struct walkarg *w)
 1705 {
 1706         struct ifnet *ifp;
 1707         struct ifaddr *ifa;
 1708         struct rt_addrinfo info;
 1709         int len, error = 0;
 1710         struct sockaddr_storage ss;
 1711 
 1712         bzero((caddr_t)&info, sizeof(info));
 1713         IFNET_RLOCK_NOSLEEP();
 1714         TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 1715                 if (w->w_arg && w->w_arg != ifp->if_index)
 1716                         continue;
 1717                 IF_ADDR_RLOCK(ifp);
 1718                 ifa = ifp->if_addr;
 1719                 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
 1720                 error = rtsock_msg_buffer(RTM_IFINFO, &info, w, &len);
 1721                 if (error != 0)
 1722                         goto done;
 1723                 info.rti_info[RTAX_IFP] = NULL;
 1724                 if (w->w_req && w->w_tmem) {
 1725                         if (w->w_op == NET_RT_IFLISTL)
 1726                                 error = sysctl_iflist_ifml(ifp, &info, w, len);
 1727                         else
 1728                                 error = sysctl_iflist_ifm(ifp, &info, w, len);
 1729                         if (error)
 1730                                 goto done;
 1731                 }
 1732                 while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != NULL) {
 1733                         if (af && af != ifa->ifa_addr->sa_family)
 1734                                 continue;
 1735                         if (prison_if(w->w_req->td->td_ucred,
 1736                             ifa->ifa_addr) != 0)
 1737                                 continue;
 1738                         info.rti_info[RTAX_IFA] = ifa->ifa_addr;
 1739                         info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(
 1740                             ifa->ifa_addr, ifa->ifa_netmask, &ss);
 1741                         info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
 1742                         error = rtsock_msg_buffer(RTM_NEWADDR, &info, w, &len);
 1743                         if (error != 0)
 1744                                 goto done;
 1745                         if (w->w_req && w->w_tmem) {
 1746                                 if (w->w_op == NET_RT_IFLISTL)
 1747                                         error = sysctl_iflist_ifaml(ifa, &info,
 1748                                             w, len);
 1749                                 else
 1750                                         error = sysctl_iflist_ifam(ifa, &info,
 1751                                             w, len);
 1752                                 if (error)
 1753                                         goto done;
 1754                         }
 1755                 }
 1756                 IF_ADDR_RUNLOCK(ifp);
 1757                 info.rti_info[RTAX_IFA] = NULL;
 1758                 info.rti_info[RTAX_NETMASK] = NULL;
 1759                 info.rti_info[RTAX_BRD] = NULL;
 1760         }
 1761 done:
 1762         if (ifp != NULL)
 1763                 IF_ADDR_RUNLOCK(ifp);
 1764         IFNET_RUNLOCK_NOSLEEP();
 1765         return (error);
 1766 }
 1767 
 1768 static int
 1769 sysctl_ifmalist(int af, struct walkarg *w)
 1770 {
 1771         struct ifnet *ifp;
 1772         struct ifmultiaddr *ifma;
 1773         struct  rt_addrinfo info;
 1774         int     len, error = 0;
 1775         struct ifaddr *ifa;
 1776 
 1777         bzero((caddr_t)&info, sizeof(info));
 1778         IFNET_RLOCK_NOSLEEP();
 1779         TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 1780                 if (w->w_arg && w->w_arg != ifp->if_index)
 1781                         continue;
 1782                 ifa = ifp->if_addr;
 1783                 info.rti_info[RTAX_IFP] = ifa ? ifa->ifa_addr : NULL;
 1784                 IF_ADDR_RLOCK(ifp);
 1785                 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 1786                         if (af && af != ifma->ifma_addr->sa_family)
 1787                                 continue;
 1788                         if (prison_if(w->w_req->td->td_ucred,
 1789                             ifma->ifma_addr) != 0)
 1790                                 continue;
 1791                         info.rti_info[RTAX_IFA] = ifma->ifma_addr;
 1792                         info.rti_info[RTAX_GATEWAY] =
 1793                             (ifma->ifma_addr->sa_family != AF_LINK) ?
 1794                             ifma->ifma_lladdr : NULL;
 1795                         error = rtsock_msg_buffer(RTM_NEWMADDR, &info, w, &len);
 1796                         if (error != 0)
 1797                                 goto done;
 1798                         if (w->w_req && w->w_tmem) {
 1799                                 struct ifma_msghdr *ifmam;
 1800 
 1801                                 ifmam = (struct ifma_msghdr *)w->w_tmem;
 1802                                 ifmam->ifmam_index = ifma->ifma_ifp->if_index;
 1803                                 ifmam->ifmam_flags = 0;
 1804                                 ifmam->ifmam_addrs = info.rti_addrs;
 1805                                 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
 1806                                 if (error) {
 1807                                         IF_ADDR_RUNLOCK(ifp);
 1808                                         goto done;
 1809                                 }
 1810                         }
 1811                 }
 1812                 IF_ADDR_RUNLOCK(ifp);
 1813         }
 1814 done:
 1815         IFNET_RUNLOCK_NOSLEEP();
 1816         return (error);
 1817 }
 1818 
 1819 static int
 1820 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
 1821 {
 1822         int     *name = (int *)arg1;
 1823         u_int   namelen = arg2;
 1824         struct rib_head *rnh = NULL; /* silence compiler. */
 1825         int     i, lim, error = EINVAL;
 1826         int     fib = 0;
 1827         u_char  af;
 1828         struct  walkarg w;
 1829 
 1830         name ++;
 1831         namelen--;
 1832         if (req->newptr)
 1833                 return (EPERM);
 1834         if (name[1] == NET_RT_DUMP) {
 1835                 if (namelen == 3)
 1836                         fib = req->td->td_proc->p_fibnum;
 1837                 else if (namelen == 4)
 1838                         fib = (name[3] == RT_ALL_FIBS) ?
 1839                             req->td->td_proc->p_fibnum : name[3];
 1840                 else
 1841                         return ((namelen < 3) ? EISDIR : ENOTDIR);
 1842                 if (fib < 0 || fib >= rt_numfibs)
 1843                         return (EINVAL);
 1844         } else if (namelen != 3)
 1845                 return ((namelen < 3) ? EISDIR : ENOTDIR);
 1846         af = name[0];
 1847         if (af > AF_MAX)
 1848                 return (EINVAL);
 1849         bzero(&w, sizeof(w));
 1850         w.w_op = name[1];
 1851         w.w_arg = name[2];
 1852         w.w_req = req;
 1853 
 1854         error = sysctl_wire_old_buffer(req, 0);
 1855         if (error)
 1856                 return (error);
 1857         
 1858         /*
 1859          * Allocate reply buffer in advance.
 1860          * All rtsock messages has maximum length of u_short.
 1861          */
 1862         w.w_tmemsize = 65536;
 1863         w.w_tmem = malloc(w.w_tmemsize, M_TEMP, M_WAITOK);
 1864 
 1865         switch (w.w_op) {
 1866 
 1867         case NET_RT_DUMP:
 1868         case NET_RT_FLAGS:
 1869                 if (af == 0) {                  /* dump all tables */
 1870                         i = 1;
 1871                         lim = AF_MAX;
 1872                 } else                          /* dump only one table */
 1873                         i = lim = af;
 1874 
 1875                 /*
 1876                  * take care of llinfo entries, the caller must
 1877                  * specify an AF
 1878                  */
 1879                 if (w.w_op == NET_RT_FLAGS &&
 1880                     (w.w_arg == 0 || w.w_arg & RTF_LLINFO)) {
 1881                         if (af != 0)
 1882                                 error = lltable_sysctl_dumparp(af, w.w_req);
 1883                         else
 1884                                 error = EINVAL;
 1885                         break;
 1886                 }
 1887                 /*
 1888                  * take care of routing entries
 1889                  */
 1890                 for (error = 0; error == 0 && i <= lim; i++) {
 1891                         rnh = rt_tables_get_rnh(fib, i);
 1892                         if (rnh != NULL) {
 1893                                 RIB_RLOCK(rnh); 
 1894                                 error = rnh->rnh_walktree(&rnh->head,
 1895                                     sysctl_dumpentry, &w);
 1896                                 RIB_RUNLOCK(rnh);
 1897                         } else if (af != 0)
 1898                                 error = EAFNOSUPPORT;
 1899                 }
 1900                 break;
 1901 
 1902         case NET_RT_IFLIST:
 1903         case NET_RT_IFLISTL:
 1904                 error = sysctl_iflist(af, &w);
 1905                 break;
 1906 
 1907         case NET_RT_IFMALIST:
 1908                 error = sysctl_ifmalist(af, &w);
 1909                 break;
 1910         }
 1911 
 1912         free(w.w_tmem, M_TEMP);
 1913         return (error);
 1914 }
 1915 
 1916 static SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
 1917 
 1918 /*
 1919  * Definitions of protocols supported in the ROUTE domain.
 1920  */
 1921 
 1922 static struct domain routedomain;               /* or at least forward */
 1923 
 1924 static struct protosw routesw[] = {
 1925 {
 1926         .pr_type =              SOCK_RAW,
 1927         .pr_domain =            &routedomain,
 1928         .pr_flags =             PR_ATOMIC|PR_ADDR,
 1929         .pr_output =            route_output,
 1930         .pr_ctlinput =          raw_ctlinput,
 1931         .pr_init =              raw_init,
 1932         .pr_usrreqs =           &route_usrreqs
 1933 }
 1934 };
 1935 
 1936 static struct domain routedomain = {
 1937         .dom_family =           PF_ROUTE,
 1938         .dom_name =              "route",
 1939         .dom_protosw =          routesw,
 1940         .dom_protoswNPROTOSW =  &routesw[nitems(routesw)]
 1941 };
 1942 
 1943 VNET_DOMAIN_SET(route);

Cache object: 323506e242d8ab5c754f49690ea501d8


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


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