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$
   31  */
   32 #include "opt_sctp.h"
   33 #include <sys/param.h>
   34 #include <sys/domain.h>
   35 #include <sys/kernel.h>
   36 #include <sys/jail.h>
   37 #include <sys/malloc.h>
   38 #include <sys/mbuf.h>
   39 #include <sys/priv.h>
   40 #include <sys/proc.h>
   41 #include <sys/protosw.h>
   42 #include <sys/signalvar.h>
   43 #include <sys/socket.h>
   44 #include <sys/socketvar.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/systm.h>
   47 
   48 #include <net/if.h>
   49 #include <net/netisr.h>
   50 #include <net/raw_cb.h>
   51 #include <net/route.h>
   52 
   53 #include <netinet/in.h>
   54 
   55 #ifdef SCTP
   56 extern void sctp_addr_change(struct ifaddr *ifa, int cmd);
   57 #endif /* SCTP */
   58 
   59 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
   60 
   61 /* NB: these are not modified */
   62 static struct   sockaddr route_src = { 2, PF_ROUTE, };
   63 static struct   sockaddr sa_zero   = { sizeof(sa_zero), AF_INET, };
   64 
   65 static struct {
   66         int     ip_count;       /* attached w/ AF_INET */
   67         int     ip6_count;      /* attached w/ AF_INET6 */
   68         int     ipx_count;      /* attached w/ AF_IPX */
   69         int     any_count;      /* total attached */
   70 } route_cb;
   71 
   72 struct mtx rtsock_mtx;
   73 MTX_SYSINIT(rtsock, &rtsock_mtx, "rtsock route_cb lock", MTX_DEF);
   74 
   75 #define RTSOCK_LOCK()   mtx_lock(&rtsock_mtx)
   76 #define RTSOCK_UNLOCK() mtx_unlock(&rtsock_mtx)
   77 #define RTSOCK_LOCK_ASSERT()    mtx_assert(&rtsock_mtx, MA_OWNED)
   78 
   79 static struct   ifqueue rtsintrq;
   80 
   81 SYSCTL_NODE(_net, OID_AUTO, route, CTLFLAG_RD, 0, "");
   82 SYSCTL_INT(_net_route, OID_AUTO, netisr_maxqlen, CTLFLAG_RW,
   83     &rtsintrq.ifq_maxlen, 0, "maximum routing socket dispatch queue length");
   84 
   85 struct walkarg {
   86         int     w_tmemsize;
   87         int     w_op, w_arg;
   88         caddr_t w_tmem;
   89         struct sysctl_req *w_req;
   90 };
   91 
   92 static void     rts_input(struct mbuf *m);
   93 static struct mbuf *rt_msg1(int type, struct rt_addrinfo *rtinfo);
   94 static int      rt_msg2(int type, struct rt_addrinfo *rtinfo,
   95                         caddr_t cp, struct walkarg *w);
   96 static int      rt_xaddrs(caddr_t cp, caddr_t cplim,
   97                         struct rt_addrinfo *rtinfo);
   98 static int      sysctl_dumpentry(struct radix_node *rn, void *vw);
   99 static int      sysctl_iflist(int af, struct walkarg *w);
  100 static int      sysctl_ifmalist(int af, struct walkarg *w);
  101 static int      route_output(struct mbuf *m, struct socket *so);
  102 static void     rt_setmetrics(u_long which, const struct rt_metrics *in,
  103                         struct rt_metrics_lite *out);
  104 static void     rt_getmetrics(const struct rt_metrics_lite *in,
  105                         struct rt_metrics *out);
  106 static void     rt_dispatch(struct mbuf *, const struct sockaddr *);
  107 
  108 static void
  109 rts_init(void)
  110 {
  111         int tmp;
  112 
  113         rtsintrq.ifq_maxlen = 256;
  114         if (TUNABLE_INT_FETCH("net.route.netisr_maxqlen", &tmp))
  115                 rtsintrq.ifq_maxlen = tmp;
  116         mtx_init(&rtsintrq.ifq_mtx, "rts_inq", NULL, MTX_DEF);
  117         netisr_register(NETISR_ROUTE, rts_input, &rtsintrq, NETISR_MPSAFE);
  118 }
  119 SYSINIT(rtsock, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rts_init, 0);
  120 
  121 static void
  122 rts_input(struct mbuf *m)
  123 {
  124         struct sockproto route_proto;
  125         unsigned short *family;
  126         struct m_tag *tag;
  127 
  128         route_proto.sp_family = PF_ROUTE;
  129         tag = m_tag_find(m, PACKET_TAG_RTSOCKFAM, NULL);
  130         if (tag != NULL) {
  131                 family = (unsigned short *)(tag + 1);
  132                 route_proto.sp_protocol = *family;
  133                 m_tag_delete(m, tag);
  134         } else
  135                 route_proto.sp_protocol = 0;
  136 
  137         raw_input(m, &route_proto, &route_src);
  138 }
  139 
  140 /*
  141  * It really doesn't make any sense at all for this code to share much
  142  * with raw_usrreq.c, since its functionality is so restricted.  XXX
  143  */
  144 static void
  145 rts_abort(struct socket *so)
  146 {
  147 
  148         raw_usrreqs.pru_abort(so);
  149 }
  150 
  151 static void
  152 rts_close(struct socket *so)
  153 {
  154 
  155         raw_usrreqs.pru_close(so);
  156 }
  157 
  158 /* pru_accept is EOPNOTSUPP */
  159 
  160 static int
  161 rts_attach(struct socket *so, int proto, struct thread *td)
  162 {
  163         struct rawcb *rp;
  164         int s, error;
  165 
  166         KASSERT(so->so_pcb == NULL, ("rts_attach: so_pcb != NULL"));
  167 
  168         /* XXX */
  169         MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK | M_ZERO);
  170         if (rp == NULL)
  171                 return ENOBUFS;
  172 
  173         /*
  174          * The splnet() is necessary to block protocols from sending
  175          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
  176          * this PCB is extant but incompletely initialized.
  177          * Probably we should try to do more of this work beforehand and
  178          * eliminate the spl.
  179          */
  180         s = splnet();
  181         so->so_pcb = (caddr_t)rp;
  182         so->so_fibnum = td->td_proc->p_fibnum;
  183         error = raw_attach(so, proto);
  184         rp = sotorawcb(so);
  185         if (error) {
  186                 splx(s);
  187                 so->so_pcb = NULL;
  188                 free(rp, M_PCB);
  189                 return error;
  190         }
  191         RTSOCK_LOCK();
  192         switch(rp->rcb_proto.sp_protocol) {
  193         case AF_INET:
  194                 route_cb.ip_count++;
  195                 break;
  196         case AF_INET6:
  197                 route_cb.ip6_count++;
  198                 break;
  199         case AF_IPX:
  200                 route_cb.ipx_count++;
  201                 break;
  202         }
  203         route_cb.any_count++;
  204         RTSOCK_UNLOCK();
  205         soisconnected(so);
  206         so->so_options |= SO_USELOOPBACK;
  207         splx(s);
  208         return 0;
  209 }
  210 
  211 static int
  212 rts_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
  213 {
  214 
  215         return (raw_usrreqs.pru_bind(so, nam, td)); /* xxx just EINVAL */
  216 }
  217 
  218 static int
  219 rts_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
  220 {
  221 
  222         return (raw_usrreqs.pru_connect(so, nam, td)); /* XXX just EINVAL */
  223 }
  224 
  225 /* pru_connect2 is EOPNOTSUPP */
  226 /* pru_control is EOPNOTSUPP */
  227 
  228 static void
  229 rts_detach(struct socket *so)
  230 {
  231         struct rawcb *rp = sotorawcb(so);
  232 
  233         KASSERT(rp != NULL, ("rts_detach: rp == NULL"));
  234 
  235         RTSOCK_LOCK();
  236         switch(rp->rcb_proto.sp_protocol) {
  237         case AF_INET:
  238                 route_cb.ip_count--;
  239                 break;
  240         case AF_INET6:
  241                 route_cb.ip6_count--;
  242                 break;
  243         case AF_IPX:
  244                 route_cb.ipx_count--;
  245                 break;
  246         }
  247         route_cb.any_count--;
  248         RTSOCK_UNLOCK();
  249         raw_usrreqs.pru_detach(so);
  250 }
  251 
  252 static int
  253 rts_disconnect(struct socket *so)
  254 {
  255 
  256         return (raw_usrreqs.pru_disconnect(so));
  257 }
  258 
  259 /* pru_listen is EOPNOTSUPP */
  260 
  261 static int
  262 rts_peeraddr(struct socket *so, struct sockaddr **nam)
  263 {
  264 
  265         return (raw_usrreqs.pru_peeraddr(so, nam));
  266 }
  267 
  268 /* pru_rcvd is EOPNOTSUPP */
  269 /* pru_rcvoob is EOPNOTSUPP */
  270 
  271 static int
  272 rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
  273          struct mbuf *control, struct thread *td)
  274 {
  275 
  276         return (raw_usrreqs.pru_send(so, flags, m, nam, control, td));
  277 }
  278 
  279 /* pru_sense is null */
  280 
  281 static int
  282 rts_shutdown(struct socket *so)
  283 {
  284 
  285         return (raw_usrreqs.pru_shutdown(so));
  286 }
  287 
  288 static int
  289 rts_sockaddr(struct socket *so, struct sockaddr **nam)
  290 {
  291 
  292         return (raw_usrreqs.pru_sockaddr(so, nam));
  293 }
  294 
  295 static struct pr_usrreqs route_usrreqs = {
  296         .pru_abort =            rts_abort,
  297         .pru_attach =           rts_attach,
  298         .pru_bind =             rts_bind,
  299         .pru_connect =          rts_connect,
  300         .pru_detach =           rts_detach,
  301         .pru_disconnect =       rts_disconnect,
  302         .pru_peeraddr =         rts_peeraddr,
  303         .pru_send =             rts_send,
  304         .pru_shutdown =         rts_shutdown,
  305         .pru_sockaddr =         rts_sockaddr,
  306         .pru_close =            rts_close,
  307 };
  308 
  309 /*ARGSUSED*/
  310 static int
  311 route_output(struct mbuf *m, struct socket *so)
  312 {
  313 #define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0)
  314         struct rt_msghdr *rtm = NULL;
  315         struct rtentry *rt = NULL;
  316         struct radix_node_head *rnh;
  317         struct rt_addrinfo info;
  318         int len, error = 0;
  319         struct ifnet *ifp = NULL;
  320         struct sockaddr_in jail;
  321 
  322 #define senderr(e) { error = e; goto flush;}
  323         if (m == NULL || ((m->m_len < sizeof(long)) &&
  324                        (m = m_pullup(m, sizeof(long))) == NULL))
  325                 return (ENOBUFS);
  326         if ((m->m_flags & M_PKTHDR) == 0)
  327                 panic("route_output");
  328         len = m->m_pkthdr.len;
  329         if (len < sizeof(*rtm) ||
  330             len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
  331                 info.rti_info[RTAX_DST] = NULL;
  332                 senderr(EINVAL);
  333         }
  334         R_Malloc(rtm, struct rt_msghdr *, len);
  335         if (rtm == NULL) {
  336                 info.rti_info[RTAX_DST] = NULL;
  337                 senderr(ENOBUFS);
  338         }
  339         m_copydata(m, 0, len, (caddr_t)rtm);
  340         if (rtm->rtm_version != RTM_VERSION) {
  341                 info.rti_info[RTAX_DST] = NULL;
  342                 senderr(EPROTONOSUPPORT);
  343         }
  344         rtm->rtm_pid = curproc->p_pid;
  345         bzero(&info, sizeof(info));
  346         info.rti_addrs = rtm->rtm_addrs;
  347         if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
  348                 info.rti_info[RTAX_DST] = NULL;
  349                 senderr(EINVAL);
  350         }
  351         info.rti_flags = rtm->rtm_flags;
  352         if (info.rti_info[RTAX_DST] == NULL ||
  353             info.rti_info[RTAX_DST]->sa_family >= AF_MAX ||
  354             (info.rti_info[RTAX_GATEWAY] != NULL &&
  355              info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
  356                 senderr(EINVAL);
  357         if (info.rti_info[RTAX_GENMASK]) {
  358                 struct radix_node *t;
  359                 t = rn_addmask((caddr_t) info.rti_info[RTAX_GENMASK], 0, 1);
  360                 if (t != NULL &&
  361                     bcmp((char *)(void *)info.rti_info[RTAX_GENMASK] + 1,
  362                     (char *)(void *)t->rn_key + 1,
  363                     ((struct sockaddr *)t->rn_key)->sa_len - 1) == 0)
  364                         info.rti_info[RTAX_GENMASK] =
  365                             (struct sockaddr *)t->rn_key;
  366                 else
  367                         senderr(ENOBUFS);
  368         }
  369 
  370         /*
  371          * Verify that the caller has the appropriate privilege; RTM_GET
  372          * is the only operation the non-superuser is allowed.
  373          */
  374         if (rtm->rtm_type != RTM_GET) {
  375                 error = priv_check(curthread, PRIV_NET_ROUTE);
  376                 if (error)
  377                         senderr(error);
  378         }
  379 
  380         switch (rtm->rtm_type) {
  381                 struct rtentry *saved_nrt;
  382 
  383         case RTM_ADD:
  384                 if (info.rti_info[RTAX_GATEWAY] == NULL)
  385                         senderr(EINVAL);
  386                 saved_nrt = NULL;
  387                 error = rtrequest1_fib(RTM_ADD, &info, &saved_nrt,
  388                     so->so_fibnum);
  389                 if (error == 0 && saved_nrt) {
  390                         RT_LOCK(saved_nrt);
  391                         rt_setmetrics(rtm->rtm_inits,
  392                                 &rtm->rtm_rmx, &saved_nrt->rt_rmx);
  393                         rtm->rtm_index = saved_nrt->rt_ifp->if_index;
  394                         RT_REMREF(saved_nrt);
  395                         saved_nrt->rt_genmask = info.rti_info[RTAX_GENMASK];
  396                         RT_UNLOCK(saved_nrt);
  397                 }
  398                 break;
  399 
  400         case RTM_DELETE:
  401                 saved_nrt = NULL;
  402                 error = rtrequest1_fib(RTM_DELETE, &info, &saved_nrt,
  403                     so->so_fibnum);
  404                 if (error == 0) {
  405                         RT_LOCK(saved_nrt);
  406                         rt = saved_nrt;
  407                         goto report;
  408                 }
  409                 break;
  410 
  411         case RTM_GET:
  412         case RTM_CHANGE:
  413         case RTM_LOCK:
  414                 rnh = rt_tables[so->so_fibnum][info.rti_info[RTAX_DST]->sa_family];
  415                 if (rnh == NULL)
  416                         senderr(EAFNOSUPPORT);
  417                 RADIX_NODE_HEAD_LOCK(rnh);
  418                 rt = (struct rtentry *) rnh->rnh_lookup(info.rti_info[RTAX_DST],
  419                         info.rti_info[RTAX_NETMASK], rnh);
  420                 if (rt == NULL) {       /* XXX looks bogus */
  421                         RADIX_NODE_HEAD_UNLOCK(rnh);
  422                         senderr(ESRCH);
  423                 }
  424                 RT_LOCK(rt);
  425                 RT_ADDREF(rt);
  426                 RADIX_NODE_HEAD_UNLOCK(rnh);
  427 
  428                 /* 
  429                  * Fix for PR: 82974
  430                  *
  431                  * RTM_CHANGE/LOCK need a perfect match, rn_lookup()
  432                  * returns a perfect match in case a netmask is
  433                  * specified.  For host routes only a longest prefix
  434                  * match is returned so it is necessary to compare the
  435                  * existence of the netmask.  If both have a netmask
  436                  * rnh_lookup() did a perfect match and if none of them
  437                  * have a netmask both are host routes which is also a
  438                  * perfect match.
  439                  */
  440 
  441                 if (rtm->rtm_type != RTM_GET && 
  442                     (!rt_mask(rt) != !info.rti_info[RTAX_NETMASK])) {
  443                         RT_UNLOCK(rt);
  444                         senderr(ESRCH);
  445                 }
  446 
  447                 switch(rtm->rtm_type) {
  448 
  449                 case RTM_GET:
  450                 report:
  451                         RT_LOCK_ASSERT(rt);
  452                         info.rti_info[RTAX_DST] = rt_key(rt);
  453                         info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
  454                         info.rti_info[RTAX_NETMASK] = rt_mask(rt);
  455                         info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
  456                         if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
  457                                 ifp = rt->rt_ifp;
  458                                 if (ifp) {
  459                                         info.rti_info[RTAX_IFP] =
  460                                             ifp->if_addr->ifa_addr;
  461                                         if (jailed(so->so_cred)) {
  462                                                 bzero(&jail, sizeof(jail));
  463                                                 jail.sin_family = PF_INET;
  464                                                 jail.sin_len = sizeof(jail);
  465                                                 jail.sin_addr.s_addr =
  466                                                 htonl(prison_getip(so->so_cred));
  467                                                 info.rti_info[RTAX_IFA] =
  468                                                     (struct sockaddr *)&jail;
  469                                         } else
  470                                                 info.rti_info[RTAX_IFA] =
  471                                                     rt->rt_ifa->ifa_addr;
  472                                         if (ifp->if_flags & IFF_POINTOPOINT)
  473                                                 info.rti_info[RTAX_BRD] =
  474                                                     rt->rt_ifa->ifa_dstaddr;
  475                                         rtm->rtm_index = ifp->if_index;
  476                                 } else {
  477                                         info.rti_info[RTAX_IFP] = NULL;
  478                                         info.rti_info[RTAX_IFA] = NULL;
  479                                 }
  480                         } else if ((ifp = rt->rt_ifp) != NULL) {
  481                                 rtm->rtm_index = ifp->if_index;
  482                         }
  483                         len = rt_msg2(rtm->rtm_type, &info, NULL, NULL);
  484                         if (len > rtm->rtm_msglen) {
  485                                 struct rt_msghdr *new_rtm;
  486                                 R_Malloc(new_rtm, struct rt_msghdr *, len);
  487                                 if (new_rtm == NULL) {
  488                                         RT_UNLOCK(rt);
  489                                         senderr(ENOBUFS);
  490                                 }
  491                                 bcopy(rtm, new_rtm, rtm->rtm_msglen);
  492                                 Free(rtm); rtm = new_rtm;
  493                         }
  494                         (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, NULL);
  495                         rtm->rtm_flags = rt->rt_flags;
  496                         rtm->rtm_use = 0;
  497                         rt_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
  498                         rtm->rtm_addrs = info.rti_addrs;
  499                         break;
  500 
  501                 case RTM_CHANGE:
  502                         /*
  503                          * New gateway could require new ifaddr, ifp;
  504                          * flags may also be different; ifp may be specified
  505                          * by ll sockaddr when protocol address is ambiguous
  506                          */
  507                         if (((rt->rt_flags & RTF_GATEWAY) &&
  508                              info.rti_info[RTAX_GATEWAY] != NULL) ||
  509                             info.rti_info[RTAX_IFP] != NULL ||
  510                             (info.rti_info[RTAX_IFA] != NULL &&
  511                              !sa_equal(info.rti_info[RTAX_IFA],
  512                                        rt->rt_ifa->ifa_addr))) {
  513                                 RT_UNLOCK(rt);
  514                                 if ((error = rt_getifa_fib(&info,
  515                                     rt->rt_fibnum)) != 0)
  516                                         senderr(error);
  517                                 RT_LOCK(rt);
  518                         }
  519                         if (info.rti_ifa != NULL &&
  520                             info.rti_ifa != rt->rt_ifa &&
  521                             rt->rt_ifa != NULL &&
  522                             rt->rt_ifa->ifa_rtrequest != NULL) {
  523                                 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt,
  524                                     &info);
  525                                 IFAFREE(rt->rt_ifa);
  526                         }
  527                         if (info.rti_info[RTAX_GATEWAY] != NULL) {
  528                                 if ((error = rt_setgate(rt, rt_key(rt),
  529                                         info.rti_info[RTAX_GATEWAY])) != 0) {
  530                                         RT_UNLOCK(rt);
  531                                         senderr(error);
  532                                 }
  533                                 if (!(rt->rt_flags & RTF_LLINFO))
  534                                         rt->rt_flags |= RTF_GATEWAY;
  535                         }
  536                         if (info.rti_ifa != NULL &&
  537                             info.rti_ifa != rt->rt_ifa) {
  538                                 IFAREF(info.rti_ifa);
  539                                 rt->rt_ifa = info.rti_ifa;
  540                                 rt->rt_ifp = info.rti_ifp;
  541                         }
  542                         /* Allow some flags to be toggled on change. */
  543                         if (rtm->rtm_fmask & RTF_FMASK)
  544                                 rt->rt_flags = (rt->rt_flags &
  545                                     ~rtm->rtm_fmask) |
  546                                     (rtm->rtm_flags & rtm->rtm_fmask);
  547                         rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
  548                                         &rt->rt_rmx);
  549                         rtm->rtm_index = rt->rt_ifp->if_index;
  550                         if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
  551                                rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
  552                         if (info.rti_info[RTAX_GENMASK])
  553                                 rt->rt_genmask = info.rti_info[RTAX_GENMASK];
  554                         /* FALLTHROUGH */
  555                 case RTM_LOCK:
  556                         /* We don't support locks anymore */
  557                         break;
  558                 }
  559                 RT_UNLOCK(rt);
  560                 break;
  561 
  562         default:
  563                 senderr(EOPNOTSUPP);
  564         }
  565 
  566 flush:
  567         if (rtm) {
  568                 if (error)
  569                         rtm->rtm_errno = error;
  570                 else
  571                         rtm->rtm_flags |= RTF_DONE;
  572         }
  573         if (rt)         /* XXX can this be true? */
  574                 RTFREE(rt);
  575     {
  576         struct rawcb *rp = NULL;
  577         /*
  578          * Check to see if we don't want our own messages.
  579          */
  580         if ((so->so_options & SO_USELOOPBACK) == 0) {
  581                 if (route_cb.any_count <= 1) {
  582                         if (rtm)
  583                                 Free(rtm);
  584                         m_freem(m);
  585                         return (error);
  586                 }
  587                 /* There is another listener, so construct message */
  588                 rp = sotorawcb(so);
  589         }
  590         if (rtm) {
  591                 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
  592                 if (m->m_pkthdr.len < rtm->rtm_msglen) {
  593                         m_freem(m);
  594                         m = NULL;
  595                 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
  596                         m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
  597                 Free(rtm);
  598         }
  599         if (m) {
  600                 if (rp) {
  601                         /*
  602                          * XXX insure we don't get a copy by
  603                          * invalidating our protocol
  604                          */
  605                         unsigned short family = rp->rcb_proto.sp_family;
  606                         rp->rcb_proto.sp_family = 0;
  607                         rt_dispatch(m, info.rti_info[RTAX_DST]);
  608                         rp->rcb_proto.sp_family = family;
  609                 } else
  610                         rt_dispatch(m, info.rti_info[RTAX_DST]);
  611         }
  612     }
  613         return (error);
  614 #undef  sa_equal
  615 }
  616 
  617 static void
  618 rt_setmetrics(u_long which, const struct rt_metrics *in,
  619         struct rt_metrics_lite *out)
  620 {
  621 #define metric(f, e) if (which & (f)) out->e = in->e;
  622         /*
  623          * Only these are stored in the routing entry since introduction
  624          * of tcp hostcache. The rest is ignored.
  625          */
  626         metric(RTV_MTU, rmx_mtu);
  627         /* Userland -> kernel timebase conversion. */
  628         if (which & RTV_EXPIRE)
  629                 out->rmx_expire = in->rmx_expire ?
  630                     in->rmx_expire - time_second + time_uptime : 0;
  631 #undef metric
  632 }
  633 
  634 static void
  635 rt_getmetrics(const struct rt_metrics_lite *in, struct rt_metrics *out)
  636 {
  637 #define metric(e) out->e = in->e;
  638         bzero(out, sizeof(*out));
  639         metric(rmx_mtu);
  640         /* Kernel -> userland timebase conversion. */
  641         out->rmx_expire = in->rmx_expire ?
  642             in->rmx_expire - time_uptime + time_second : 0;
  643 #undef metric
  644 }
  645 
  646 /*
  647  * Extract the addresses of the passed sockaddrs.
  648  * Do a little sanity checking so as to avoid bad memory references.
  649  * This data is derived straight from userland.
  650  */
  651 static int
  652 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
  653 {
  654         struct sockaddr *sa;
  655         int i;
  656 
  657         for (i = 0; i < RTAX_MAX && cp < cplim; i++) {
  658                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
  659                         continue;
  660                 sa = (struct sockaddr *)cp;
  661                 /*
  662                  * It won't fit.
  663                  */
  664                 if (cp + sa->sa_len > cplim)
  665                         return (EINVAL);
  666                 /*
  667                  * there are no more.. quit now
  668                  * If there are more bits, they are in error.
  669                  * I've seen this. route(1) can evidently generate these. 
  670                  * This causes kernel to core dump.
  671                  * for compatibility, If we see this, point to a safe address.
  672                  */
  673                 if (sa->sa_len == 0) {
  674                         rtinfo->rti_info[i] = &sa_zero;
  675                         return (0); /* should be EINVAL but for compat */
  676                 }
  677                 /* accept it */
  678                 rtinfo->rti_info[i] = sa;
  679                 cp += SA_SIZE(sa);
  680         }
  681         return (0);
  682 }
  683 
  684 static struct mbuf *
  685 rt_msg1(int type, struct rt_addrinfo *rtinfo)
  686 {
  687         struct rt_msghdr *rtm;
  688         struct mbuf *m;
  689         int i;
  690         struct sockaddr *sa;
  691         int len, dlen;
  692 
  693         switch (type) {
  694 
  695         case RTM_DELADDR:
  696         case RTM_NEWADDR:
  697                 len = sizeof(struct ifa_msghdr);
  698                 break;
  699 
  700         case RTM_DELMADDR:
  701         case RTM_NEWMADDR:
  702                 len = sizeof(struct ifma_msghdr);
  703                 break;
  704 
  705         case RTM_IFINFO:
  706                 len = sizeof(struct if_msghdr);
  707                 break;
  708 
  709         case RTM_IFANNOUNCE:
  710         case RTM_IEEE80211:
  711                 len = sizeof(struct if_announcemsghdr);
  712                 break;
  713 
  714         default:
  715                 len = sizeof(struct rt_msghdr);
  716         }
  717         if (len > MCLBYTES)
  718                 panic("rt_msg1");
  719         m = m_gethdr(M_DONTWAIT, MT_DATA);
  720         if (m && len > MHLEN) {
  721                 MCLGET(m, M_DONTWAIT);
  722                 if ((m->m_flags & M_EXT) == 0) {
  723                         m_free(m);
  724                         m = NULL;
  725                 }
  726         }
  727         if (m == NULL)
  728                 return (m);
  729         m->m_pkthdr.len = m->m_len = len;
  730         m->m_pkthdr.rcvif = NULL;
  731         rtm = mtod(m, struct rt_msghdr *);
  732         bzero((caddr_t)rtm, len);
  733         for (i = 0; i < RTAX_MAX; i++) {
  734                 if ((sa = rtinfo->rti_info[i]) == NULL)
  735                         continue;
  736                 rtinfo->rti_addrs |= (1 << i);
  737                 dlen = SA_SIZE(sa);
  738                 m_copyback(m, len, dlen, (caddr_t)sa);
  739                 len += dlen;
  740         }
  741         if (m->m_pkthdr.len != len) {
  742                 m_freem(m);
  743                 return (NULL);
  744         }
  745         rtm->rtm_msglen = len;
  746         rtm->rtm_version = RTM_VERSION;
  747         rtm->rtm_type = type;
  748         return (m);
  749 }
  750 
  751 static int
  752 rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w)
  753 {
  754         int i;
  755         int len, dlen, second_time = 0;
  756         caddr_t cp0;
  757 
  758         rtinfo->rti_addrs = 0;
  759 again:
  760         switch (type) {
  761 
  762         case RTM_DELADDR:
  763         case RTM_NEWADDR:
  764                 len = sizeof(struct ifa_msghdr);
  765                 break;
  766 
  767         case RTM_IFINFO:
  768                 len = sizeof(struct if_msghdr);
  769                 break;
  770 
  771         case RTM_NEWMADDR:
  772                 len = sizeof(struct ifma_msghdr);
  773                 break;
  774 
  775         default:
  776                 len = sizeof(struct rt_msghdr);
  777         }
  778         cp0 = cp;
  779         if (cp0)
  780                 cp += len;
  781         for (i = 0; i < RTAX_MAX; i++) {
  782                 struct sockaddr *sa;
  783 
  784                 if ((sa = rtinfo->rti_info[i]) == NULL)
  785                         continue;
  786                 rtinfo->rti_addrs |= (1 << i);
  787                 dlen = SA_SIZE(sa);
  788                 if (cp) {
  789                         bcopy((caddr_t)sa, cp, (unsigned)dlen);
  790                         cp += dlen;
  791                 }
  792                 len += dlen;
  793         }
  794         len = ALIGN(len);
  795         if (cp == NULL && w != NULL && !second_time) {
  796                 struct walkarg *rw = w;
  797 
  798                 if (rw->w_req) {
  799                         if (rw->w_tmemsize < len) {
  800                                 if (rw->w_tmem)
  801                                         free(rw->w_tmem, M_RTABLE);
  802                                 rw->w_tmem = (caddr_t)
  803                                         malloc(len, M_RTABLE, M_NOWAIT);
  804                                 if (rw->w_tmem)
  805                                         rw->w_tmemsize = len;
  806                         }
  807                         if (rw->w_tmem) {
  808                                 cp = rw->w_tmem;
  809                                 second_time = 1;
  810                                 goto again;
  811                         }
  812                 }
  813         }
  814         if (cp) {
  815                 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
  816 
  817                 rtm->rtm_version = RTM_VERSION;
  818                 rtm->rtm_type = type;
  819                 rtm->rtm_msglen = len;
  820         }
  821         return (len);
  822 }
  823 
  824 /*
  825  * This routine is called to generate a message from the routing
  826  * socket indicating that a redirect has occured, a routing lookup
  827  * has failed, or that a protocol has detected timeouts to a particular
  828  * destination.
  829  */
  830 void
  831 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
  832 {
  833         struct rt_msghdr *rtm;
  834         struct mbuf *m;
  835         struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
  836 
  837         if (route_cb.any_count == 0)
  838                 return;
  839         m = rt_msg1(type, rtinfo);
  840         if (m == NULL)
  841                 return;
  842         rtm = mtod(m, struct rt_msghdr *);
  843         rtm->rtm_flags = RTF_DONE | flags;
  844         rtm->rtm_errno = error;
  845         rtm->rtm_addrs = rtinfo->rti_addrs;
  846         rt_dispatch(m, sa);
  847 }
  848 
  849 /*
  850  * This routine is called to generate a message from the routing
  851  * socket indicating that the status of a network interface has changed.
  852  */
  853 void
  854 rt_ifmsg(struct ifnet *ifp)
  855 {
  856         struct if_msghdr *ifm;
  857         struct mbuf *m;
  858         struct rt_addrinfo info;
  859 
  860         if (route_cb.any_count == 0)
  861                 return;
  862         bzero((caddr_t)&info, sizeof(info));
  863         m = rt_msg1(RTM_IFINFO, &info);
  864         if (m == NULL)
  865                 return;
  866         ifm = mtod(m, struct if_msghdr *);
  867         ifm->ifm_index = ifp->if_index;
  868         ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
  869         ifm->ifm_data = ifp->if_data;
  870         ifm->ifm_addrs = 0;
  871         rt_dispatch(m, NULL);
  872 }
  873 
  874 /*
  875  * This is called to generate messages from the routing socket
  876  * indicating a network interface has had addresses associated with it.
  877  * if we ever reverse the logic and replace messages TO the routing
  878  * socket indicate a request to configure interfaces, then it will
  879  * be unnecessary as the routing socket will automatically generate
  880  * copies of it.
  881  */
  882 void
  883 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
  884 {
  885         struct rt_addrinfo info;
  886         struct sockaddr *sa = NULL;
  887         int pass;
  888         struct mbuf *m = NULL;
  889         struct ifnet *ifp = ifa->ifa_ifp;
  890 
  891         KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE,
  892                 ("unexpected cmd %u", cmd));
  893 #ifdef SCTP
  894         /*
  895          * notify the SCTP stack
  896          * this will only get called when an address is added/deleted
  897          * XXX pass the ifaddr struct instead if ifa->ifa_addr...
  898          */
  899         sctp_addr_change(ifa, cmd);
  900 #endif /* SCTP */
  901         if (route_cb.any_count == 0)
  902                 return;
  903         for (pass = 1; pass < 3; pass++) {
  904                 bzero((caddr_t)&info, sizeof(info));
  905                 if ((cmd == RTM_ADD && pass == 1) ||
  906                     (cmd == RTM_DELETE && pass == 2)) {
  907                         struct ifa_msghdr *ifam;
  908                         int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
  909 
  910                         info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr;
  911                         info.rti_info[RTAX_IFP] = ifp->if_addr->ifa_addr;
  912                         info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
  913                         info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
  914                         if ((m = rt_msg1(ncmd, &info)) == NULL)
  915                                 continue;
  916                         ifam = mtod(m, struct ifa_msghdr *);
  917                         ifam->ifam_index = ifp->if_index;
  918                         ifam->ifam_metric = ifa->ifa_metric;
  919                         ifam->ifam_flags = ifa->ifa_flags;
  920                         ifam->ifam_addrs = info.rti_addrs;
  921                 }
  922                 if ((cmd == RTM_ADD && pass == 2) ||
  923                     (cmd == RTM_DELETE && pass == 1)) {
  924                         struct rt_msghdr *rtm;
  925 
  926                         if (rt == NULL)
  927                                 continue;
  928                         info.rti_info[RTAX_NETMASK] = rt_mask(rt);
  929                         info.rti_info[RTAX_DST] = sa = rt_key(rt);
  930                         info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
  931                         if ((m = rt_msg1(cmd, &info)) == NULL)
  932                                 continue;
  933                         rtm = mtod(m, struct rt_msghdr *);
  934                         rtm->rtm_index = ifp->if_index;
  935                         rtm->rtm_flags |= rt->rt_flags;
  936                         rtm->rtm_errno = error;
  937                         rtm->rtm_addrs = info.rti_addrs;
  938                 }
  939                 rt_dispatch(m, sa);
  940         }
  941 }
  942 
  943 /*
  944  * This is the analogue to the rt_newaddrmsg which performs the same
  945  * function but for multicast group memberhips.  This is easier since
  946  * there is no route state to worry about.
  947  */
  948 void
  949 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
  950 {
  951         struct rt_addrinfo info;
  952         struct mbuf *m = NULL;
  953         struct ifnet *ifp = ifma->ifma_ifp;
  954         struct ifma_msghdr *ifmam;
  955 
  956         if (route_cb.any_count == 0)
  957                 return;
  958 
  959         bzero((caddr_t)&info, sizeof(info));
  960         info.rti_info[RTAX_IFA] = ifma->ifma_addr;
  961         info.rti_info[RTAX_IFP] = ifp ? ifp->if_addr->ifa_addr : NULL;
  962         /*
  963          * If a link-layer address is present, present it as a ``gateway''
  964          * (similarly to how ARP entries, e.g., are presented).
  965          */
  966         info.rti_info[RTAX_GATEWAY] = ifma->ifma_lladdr;
  967         m = rt_msg1(cmd, &info);
  968         if (m == NULL)
  969                 return;
  970         ifmam = mtod(m, struct ifma_msghdr *);
  971         KASSERT(ifp != NULL, ("%s: link-layer multicast address w/o ifp\n",
  972             __func__));
  973         ifmam->ifmam_index = ifp->if_index;
  974         ifmam->ifmam_addrs = info.rti_addrs;
  975         rt_dispatch(m, ifma->ifma_addr);
  976 }
  977 
  978 static struct mbuf *
  979 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what,
  980         struct rt_addrinfo *info)
  981 {
  982         struct if_announcemsghdr *ifan;
  983         struct mbuf *m;
  984 
  985         if (route_cb.any_count == 0)
  986                 return NULL;
  987         bzero((caddr_t)info, sizeof(*info));
  988         m = rt_msg1(type, info);
  989         if (m != NULL) {
  990                 ifan = mtod(m, struct if_announcemsghdr *);
  991                 ifan->ifan_index = ifp->if_index;
  992                 strlcpy(ifan->ifan_name, ifp->if_xname,
  993                         sizeof(ifan->ifan_name));
  994                 ifan->ifan_what = what;
  995         }
  996         return m;
  997 }
  998 
  999 /*
 1000  * This is called to generate routing socket messages indicating
 1001  * IEEE80211 wireless events.
 1002  * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way.
 1003  */
 1004 void
 1005 rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len)
 1006 {
 1007         struct mbuf *m;
 1008         struct rt_addrinfo info;
 1009 
 1010         m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info);
 1011         if (m != NULL) {
 1012                 /*
 1013                  * Append the ieee80211 data.  Try to stick it in the
 1014                  * mbuf containing the ifannounce msg; otherwise allocate
 1015                  * a new mbuf and append.
 1016                  *
 1017                  * NB: we assume m is a single mbuf.
 1018                  */
 1019                 if (data_len > M_TRAILINGSPACE(m)) {
 1020                         struct mbuf *n = m_get(M_NOWAIT, MT_DATA);
 1021                         if (n == NULL) {
 1022                                 m_freem(m);
 1023                                 return;
 1024                         }
 1025                         bcopy(data, mtod(n, void *), data_len);
 1026                         n->m_len = data_len;
 1027                         m->m_next = n;
 1028                 } else if (data_len > 0) {
 1029                         bcopy(data, mtod(m, u_int8_t *) + m->m_len, data_len);
 1030                         m->m_len += data_len;
 1031                 }
 1032                 if (m->m_flags & M_PKTHDR)
 1033                         m->m_pkthdr.len += data_len;
 1034                 mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len;
 1035                 rt_dispatch(m, NULL);
 1036         }
 1037 }
 1038 
 1039 /*
 1040  * This is called to generate routing socket messages indicating
 1041  * network interface arrival and departure.
 1042  */
 1043 void
 1044 rt_ifannouncemsg(struct ifnet *ifp, int what)
 1045 {
 1046         struct mbuf *m;
 1047         struct rt_addrinfo info;
 1048 
 1049         m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info);
 1050         if (m != NULL)
 1051                 rt_dispatch(m, NULL);
 1052 }
 1053 
 1054 static void
 1055 rt_dispatch(struct mbuf *m, const struct sockaddr *sa)
 1056 {
 1057         struct m_tag *tag;
 1058 
 1059         /*
 1060          * Preserve the family from the sockaddr, if any, in an m_tag for
 1061          * use when injecting the mbuf into the routing socket buffer from
 1062          * the netisr.
 1063          */
 1064         if (sa != NULL) {
 1065                 tag = m_tag_get(PACKET_TAG_RTSOCKFAM, sizeof(unsigned short),
 1066                     M_NOWAIT);
 1067                 if (tag == NULL) {
 1068                         m_freem(m);
 1069                         return;
 1070                 }
 1071                 *(unsigned short *)(tag + 1) = sa->sa_family;
 1072                 m_tag_prepend(m, tag);
 1073         }
 1074         netisr_queue(NETISR_ROUTE, m);  /* mbuf is free'd on failure. */
 1075 }
 1076 
 1077 /*
 1078  * This is used in dumping the kernel table via sysctl().
 1079  */
 1080 static int
 1081 sysctl_dumpentry(struct radix_node *rn, void *vw)
 1082 {
 1083         struct walkarg *w = vw;
 1084         struct rtentry *rt = (struct rtentry *)rn;
 1085         int error = 0, size;
 1086         struct rt_addrinfo info;
 1087 
 1088         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
 1089                 return 0;
 1090         bzero((caddr_t)&info, sizeof(info));
 1091         info.rti_info[RTAX_DST] = rt_key(rt);
 1092         info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
 1093         info.rti_info[RTAX_NETMASK] = rt_mask(rt);
 1094         info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
 1095         if (rt->rt_ifp) {
 1096                 info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addr->ifa_addr;
 1097                 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
 1098                 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
 1099                         info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr;
 1100         }
 1101         size = rt_msg2(RTM_GET, &info, NULL, w);
 1102         if (w->w_req && w->w_tmem) {
 1103                 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
 1104 
 1105                 rtm->rtm_flags = rt->rt_flags;
 1106                 rtm->rtm_use = rt->rt_rmx.rmx_pksent;
 1107                 rt_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
 1108                 rtm->rtm_index = rt->rt_ifp->if_index;
 1109                 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
 1110                 rtm->rtm_addrs = info.rti_addrs;
 1111                 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
 1112                 return (error);
 1113         }
 1114         return (error);
 1115 }
 1116 
 1117 static int
 1118 sysctl_iflist(int af, struct walkarg *w)
 1119 {
 1120         struct ifnet *ifp;
 1121         struct ifaddr *ifa;
 1122         struct rt_addrinfo info;
 1123         int len, error = 0;
 1124 
 1125         bzero((caddr_t)&info, sizeof(info));
 1126         IFNET_RLOCK();
 1127         TAILQ_FOREACH(ifp, &ifnet, if_link) {
 1128                 if (w->w_arg && w->w_arg != ifp->if_index)
 1129                         continue;
 1130                 ifa = ifp->if_addr;
 1131                 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
 1132                 len = rt_msg2(RTM_IFINFO, &info, NULL, w);
 1133                 info.rti_info[RTAX_IFP] = NULL;
 1134                 if (w->w_req && w->w_tmem) {
 1135                         struct if_msghdr *ifm;
 1136 
 1137                         ifm = (struct if_msghdr *)w->w_tmem;
 1138                         ifm->ifm_index = ifp->if_index;
 1139                         ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
 1140                         ifm->ifm_data = ifp->if_data;
 1141                         ifm->ifm_addrs = info.rti_addrs;
 1142                         error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
 1143                         if (error)
 1144                                 goto done;
 1145                 }
 1146                 while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != NULL) {
 1147                         if (af && af != ifa->ifa_addr->sa_family)
 1148                                 continue;
 1149                         if (jailed(curthread->td_ucred) &&
 1150                             prison_if(curthread->td_ucred, ifa->ifa_addr))
 1151                                 continue;
 1152                         info.rti_info[RTAX_IFA] = ifa->ifa_addr;
 1153                         info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
 1154                         info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
 1155                         len = rt_msg2(RTM_NEWADDR, &info, NULL, w);
 1156                         if (w->w_req && w->w_tmem) {
 1157                                 struct ifa_msghdr *ifam;
 1158 
 1159                                 ifam = (struct ifa_msghdr *)w->w_tmem;
 1160                                 ifam->ifam_index = ifa->ifa_ifp->if_index;
 1161                                 ifam->ifam_flags = ifa->ifa_flags;
 1162                                 ifam->ifam_metric = ifa->ifa_metric;
 1163                                 ifam->ifam_addrs = info.rti_addrs;
 1164                                 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
 1165                                 if (error)
 1166                                         goto done;
 1167                         }
 1168                 }
 1169                 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
 1170                         info.rti_info[RTAX_BRD] = NULL;
 1171         }
 1172 done:
 1173         IFNET_RUNLOCK();
 1174         return (error);
 1175 }
 1176 
 1177 int
 1178 sysctl_ifmalist(int af, struct walkarg *w)
 1179 {
 1180         struct ifnet *ifp;
 1181         struct ifmultiaddr *ifma;
 1182         struct  rt_addrinfo info;
 1183         int     len, error = 0;
 1184         struct ifaddr *ifa;
 1185 
 1186         bzero((caddr_t)&info, sizeof(info));
 1187         IFNET_RLOCK();
 1188         TAILQ_FOREACH(ifp, &ifnet, if_link) {
 1189                 if (w->w_arg && w->w_arg != ifp->if_index)
 1190                         continue;
 1191                 ifa = ifp->if_addr;
 1192                 info.rti_info[RTAX_IFP] = ifa ? ifa->ifa_addr : NULL;
 1193                 IF_ADDR_LOCK(ifp);
 1194                 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 1195                         if (af && af != ifma->ifma_addr->sa_family)
 1196                                 continue;
 1197                         if (jailed(curproc->p_ucred) &&
 1198                             prison_if(curproc->p_ucred, ifma->ifma_addr))
 1199                                 continue;
 1200                         info.rti_info[RTAX_IFA] = ifma->ifma_addr;
 1201                         info.rti_info[RTAX_GATEWAY] =
 1202                             (ifma->ifma_addr->sa_family != AF_LINK) ?
 1203                             ifma->ifma_lladdr : NULL;
 1204                         len = rt_msg2(RTM_NEWMADDR, &info, NULL, w);
 1205                         if (w->w_req && w->w_tmem) {
 1206                                 struct ifma_msghdr *ifmam;
 1207 
 1208                                 ifmam = (struct ifma_msghdr *)w->w_tmem;
 1209                                 ifmam->ifmam_index = ifma->ifma_ifp->if_index;
 1210                                 ifmam->ifmam_flags = 0;
 1211                                 ifmam->ifmam_addrs = info.rti_addrs;
 1212                                 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
 1213                                 if (error) {
 1214                                         IF_ADDR_UNLOCK(ifp);
 1215                                         goto done;
 1216                                 }
 1217                         }
 1218                 }
 1219                 IF_ADDR_UNLOCK(ifp);
 1220         }
 1221 done:
 1222         IFNET_RUNLOCK();
 1223         return (error);
 1224 }
 1225 
 1226 static int
 1227 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
 1228 {
 1229         int     *name = (int *)arg1;
 1230         u_int   namelen = arg2;
 1231         struct radix_node_head *rnh;
 1232         int     i, lim, error = EINVAL;
 1233         u_char  af;
 1234         struct  walkarg w;
 1235 
 1236         name ++;
 1237         namelen--;
 1238         if (req->newptr)
 1239                 return (EPERM);
 1240         if (namelen != 3)
 1241                 return ((namelen < 3) ? EISDIR : ENOTDIR);
 1242         af = name[0];
 1243         if (af > AF_MAX)
 1244                 return (EINVAL);
 1245         bzero(&w, sizeof(w));
 1246         w.w_op = name[1];
 1247         w.w_arg = name[2];
 1248         w.w_req = req;
 1249 
 1250         error = sysctl_wire_old_buffer(req, 0);
 1251         if (error)
 1252                 return (error);
 1253         switch (w.w_op) {
 1254 
 1255         case NET_RT_DUMP:
 1256         case NET_RT_FLAGS:
 1257                 if (af == 0) {                  /* dump all tables */
 1258                         i = 1;
 1259                         lim = AF_MAX;
 1260                 } else                          /* dump only one table */
 1261                         i = lim = af;
 1262                 for (error = 0; error == 0 && i <= lim; i++)
 1263                         if ((rnh = rt_tables[curthread->td_proc->p_fibnum][i]) != NULL) {
 1264                                 RADIX_NODE_HEAD_LOCK(rnh); 
 1265                                 error = rnh->rnh_walktree(rnh,
 1266                                     sysctl_dumpentry, &w);
 1267                                 RADIX_NODE_HEAD_UNLOCK(rnh);
 1268                         } else if (af != 0)
 1269                                 error = EAFNOSUPPORT;
 1270                 break;
 1271 
 1272         case NET_RT_IFLIST:
 1273                 error = sysctl_iflist(af, &w);
 1274                 break;
 1275 
 1276         case NET_RT_IFMALIST:
 1277                 error = sysctl_ifmalist(af, &w);
 1278                 break;
 1279         }
 1280         if (w.w_tmem)
 1281                 free(w.w_tmem, M_RTABLE);
 1282         return (error);
 1283 }
 1284 
 1285 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
 1286 
 1287 /*
 1288  * Definitions of protocols supported in the ROUTE domain.
 1289  */
 1290 
 1291 static struct domain routedomain;               /* or at least forward */
 1292 
 1293 static struct protosw routesw[] = {
 1294 {
 1295         .pr_type =              SOCK_RAW,
 1296         .pr_domain =            &routedomain,
 1297         .pr_flags =             PR_ATOMIC|PR_ADDR,
 1298         .pr_output =            route_output,
 1299         .pr_ctlinput =          raw_ctlinput,
 1300         .pr_init =              raw_init,
 1301         .pr_usrreqs =           &route_usrreqs
 1302 }
 1303 };
 1304 
 1305 static struct domain routedomain = {
 1306         .dom_family =           PF_ROUTE,
 1307         .dom_name =              "route",
 1308         .dom_protosw =          routesw,
 1309         .dom_protoswNPROTOSW =  &routesw[sizeof(routesw)/sizeof(routesw[0])]
 1310 };
 1311 
 1312 DOMAIN_SET(route);

Cache object: 3491073f2d96c3bb129c1137df5ffbc5


[ 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.