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 /*      $NetBSD: rtsock.c,v 1.75 2005/02/26 22:45:09 perry Exp $        */
    2 
    3 /*
    4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the project nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Copyright (c) 1988, 1991, 1993
   34  *      The Regents of the University of California.  All rights reserved.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  * 3. Neither the name of the University nor the names of its contributors
   45  *    may be used to endorse or promote products derived from this software
   46  *    without specific prior written permission.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  *
   60  *      @(#)rtsock.c    8.7 (Berkeley) 10/12/95
   61  */
   62 
   63 #include <sys/cdefs.h>
   64 __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.75 2005/02/26 22:45:09 perry Exp $");
   65 
   66 #include "opt_inet.h"
   67 
   68 #include <sys/param.h>
   69 #include <sys/systm.h>
   70 #include <sys/proc.h>
   71 #include <sys/mbuf.h>
   72 #include <sys/socket.h>
   73 #include <sys/socketvar.h>
   74 #include <sys/domain.h>
   75 #include <sys/protosw.h>
   76 #include <sys/sysctl.h>
   77 
   78 #include <net/if.h>
   79 #include <net/route.h>
   80 #include <net/raw_cb.h>
   81 
   82 #include <machine/stdarg.h>
   83 
   84 DOMAIN_DEFINE(routedomain);     /* forward declare and add to link set */
   85 
   86 struct  sockaddr route_dst = { 2, PF_ROUTE, };
   87 struct  sockaddr route_src = { 2, PF_ROUTE, };
   88 struct  sockproto route_proto = { PF_ROUTE, };
   89 
   90 struct walkarg {
   91         int     w_op;
   92         int     w_arg;
   93         int     w_given;
   94         int     w_needed;
   95         caddr_t w_where;
   96         int     w_tmemsize;
   97         int     w_tmemneeded;
   98         caddr_t w_tmem;
   99 };
  100 
  101 static struct mbuf *rt_msg1(int, struct rt_addrinfo *, caddr_t, int);
  102 static int rt_msg2(int, struct rt_addrinfo *, caddr_t, struct walkarg *, int *);
  103 static int rt_xaddrs(u_char, const char *, const char *, struct rt_addrinfo *);
  104 static int sysctl_dumpentry(struct radix_node *, void *);
  105 static int sysctl_iflist(int, struct walkarg *, int);
  106 static int sysctl_rtable(SYSCTLFN_PROTO);
  107 static __inline void rt_adjustcount(int, int);
  108 
  109 /* Sleazy use of local variables throughout file, warning!!!! */
  110 #define dst     info.rti_info[RTAX_DST]
  111 #define gate    info.rti_info[RTAX_GATEWAY]
  112 #define netmask info.rti_info[RTAX_NETMASK]
  113 #define genmask info.rti_info[RTAX_GENMASK]
  114 #define ifpaddr info.rti_info[RTAX_IFP]
  115 #define ifaaddr info.rti_info[RTAX_IFA]
  116 #define brdaddr info.rti_info[RTAX_BRD]
  117 
  118 static __inline void
  119 rt_adjustcount(int af, int cnt)
  120 {
  121         route_cb.any_count += cnt;
  122         switch (af) {
  123         case AF_INET:
  124                 route_cb.ip_count += cnt;
  125                 return;
  126 #ifdef INET6
  127         case AF_INET6:
  128                 route_cb.ip6_count += cnt;
  129                 return;
  130 #endif
  131         case AF_IPX:
  132                 route_cb.ipx_count += cnt;
  133                 return;
  134         case AF_NS:
  135                 route_cb.ns_count += cnt;
  136                 return;
  137         case AF_ISO:
  138                 route_cb.iso_count += cnt;
  139                 return;
  140         }
  141 }
  142 
  143 /*ARGSUSED*/
  144 int
  145 route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
  146         struct mbuf *control, struct proc *p)
  147 {
  148         int error = 0;
  149         struct rawcb *rp = sotorawcb(so);
  150         int s;
  151 
  152         if (req == PRU_ATTACH) {
  153                 MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
  154                 if ((so->so_pcb = rp) != NULL)
  155                         memset(so->so_pcb, 0, sizeof(*rp));
  156 
  157         }
  158         if (req == PRU_DETACH && rp)
  159                 rt_adjustcount(rp->rcb_proto.sp_protocol, -1);
  160         s = splsoftnet();
  161 
  162         /*
  163          * Don't call raw_usrreq() in the attach case, because
  164          * we want to allow non-privileged processes to listen on
  165          * and send "safe" commands to the routing socket.
  166          */
  167         if (req == PRU_ATTACH) {
  168                 if (p == 0)
  169                         error = EACCES;
  170                 else
  171                         error = raw_attach(so, (int)(long)nam);
  172         } else
  173                 error = raw_usrreq(so, req, m, nam, control, p);
  174 
  175         rp = sotorawcb(so);
  176         if (req == PRU_ATTACH && rp) {
  177                 if (error) {
  178                         free((caddr_t)rp, M_PCB);
  179                         splx(s);
  180                         return (error);
  181                 }
  182                 rt_adjustcount(rp->rcb_proto.sp_protocol, 1);
  183                 rp->rcb_laddr = &route_src;
  184                 rp->rcb_faddr = &route_dst;
  185                 soisconnected(so);
  186                 so->so_options |= SO_USELOOPBACK;
  187         }
  188         splx(s);
  189         return (error);
  190 }
  191 
  192 /*ARGSUSED*/
  193 int
  194 route_output(struct mbuf *m, ...)
  195 {
  196         struct rt_msghdr *rtm = 0;
  197         struct radix_node *rn = 0;
  198         struct rtentry *rt = 0;
  199         struct rtentry *saved_nrt = 0;
  200         struct radix_node_head *rnh;
  201         struct rt_addrinfo info;
  202         int len, error = 0;
  203         struct ifnet *ifp = 0;
  204         struct ifaddr *ifa = 0;
  205         struct socket *so;
  206         va_list ap;
  207         sa_family_t family;
  208 
  209         va_start(ap, m);
  210         so = va_arg(ap, struct socket *);
  211         va_end(ap);
  212 
  213 #define senderr(e) do { error = e; goto flush;} while (/*CONSTCOND*/ 0)
  214         if (m == 0 || ((m->m_len < sizeof(int32_t)) &&
  215            (m = m_pullup(m, sizeof(int32_t))) == 0))
  216                 return (ENOBUFS);
  217         if ((m->m_flags & M_PKTHDR) == 0)
  218                 panic("route_output");
  219         len = m->m_pkthdr.len;
  220         if (len < sizeof(*rtm) ||
  221             len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
  222                 dst = 0;
  223                 senderr(EINVAL);
  224         }
  225         R_Malloc(rtm, struct rt_msghdr *, len);
  226         if (rtm == 0) {
  227                 dst = 0;
  228                 senderr(ENOBUFS);
  229         }
  230         m_copydata(m, 0, len, (caddr_t)rtm);
  231         if (rtm->rtm_version != RTM_VERSION) {
  232                 dst = 0;
  233                 senderr(EPROTONOSUPPORT);
  234         }
  235         rtm->rtm_pid = curproc->p_pid;
  236         memset(&info, 0, sizeof(info));
  237         info.rti_addrs = rtm->rtm_addrs;
  238         if (rt_xaddrs(rtm->rtm_type, (caddr_t)(rtm + 1), len + (caddr_t)rtm, &info))
  239                 senderr(EINVAL);
  240         info.rti_flags = rtm->rtm_flags;
  241         if (dst == 0 || (dst->sa_family >= AF_MAX))
  242                 senderr(EINVAL);
  243         if (gate != 0 && (gate->sa_family >= AF_MAX))
  244                 senderr(EINVAL);
  245         if (genmask) {
  246                 struct radix_node *t;
  247                 t = rn_addmask((caddr_t)genmask, 0, 1);
  248                 if (t && genmask->sa_len >= ((struct sockaddr *)t->rn_key)->sa_len &&
  249                     Bcmp((caddr_t *)genmask + 1, (caddr_t *)t->rn_key + 1,
  250                     ((struct sockaddr *)t->rn_key)->sa_len) - 1)
  251                         genmask = (struct sockaddr *)(t->rn_key);
  252                 else
  253                         senderr(ENOBUFS);
  254         }
  255 
  256         /*
  257          * Verify that the caller has the appropriate privilege; RTM_GET
  258          * is the only operation the non-superuser is allowed.
  259          */
  260         if (rtm->rtm_type != RTM_GET &&
  261             suser(curproc->p_ucred, &curproc->p_acflag) != 0)
  262                 senderr(EACCES);
  263 
  264         switch (rtm->rtm_type) {
  265 
  266         case RTM_ADD:
  267                 if (gate == 0)
  268                         senderr(EINVAL);
  269                 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt);
  270                 if (error == 0 && saved_nrt) {
  271                         rt_setmetrics(rtm->rtm_inits,
  272                             &rtm->rtm_rmx, &saved_nrt->rt_rmx);
  273                         saved_nrt->rt_refcnt--;
  274                         saved_nrt->rt_genmask = genmask;
  275                 }
  276                 break;
  277 
  278         case RTM_DELETE:
  279                 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt);
  280                 if (error == 0) {
  281                         (rt = saved_nrt)->rt_refcnt++;
  282                         goto report;
  283                 }
  284                 break;
  285 
  286         case RTM_GET:
  287         case RTM_CHANGE:
  288         case RTM_LOCK:
  289                 if ((rnh = rt_tables[dst->sa_family]) == 0) {
  290                         senderr(EAFNOSUPPORT);
  291                 }
  292                 rn = rnh->rnh_lookup(dst, netmask, rnh);
  293                 if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0) {
  294                         senderr(ESRCH);
  295                 }
  296                 rt = (struct rtentry *)rn;
  297                 rt->rt_refcnt++;
  298                 if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */
  299                         struct radix_node *rn;
  300                         extern struct radix_node_head *mask_rnhead;
  301 
  302                         if (Bcmp(dst, rt_key(rt), dst->sa_len) != 0)
  303                                 senderr(ESRCH);
  304                         if (netmask && (rn = rn_search(netmask,
  305                                             mask_rnhead->rnh_treetop)))
  306                                 netmask = (struct sockaddr *)rn->rn_key;
  307                         for (rn = rt->rt_nodes; rn; rn = rn->rn_dupedkey)
  308                                 if (netmask == (struct sockaddr *)rn->rn_mask)
  309                                         break;
  310                         if (rn == 0)
  311                                 senderr(ETOOMANYREFS);
  312                         rt = (struct rtentry *)rn;
  313                 }
  314 
  315                 switch (rtm->rtm_type) {
  316                 case RTM_GET:
  317                 report:
  318                         dst = rt_key(rt);
  319                         gate = rt->rt_gateway;
  320                         netmask = rt_mask(rt);
  321                         genmask = rt->rt_genmask;
  322                         if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
  323                                 if ((ifp = rt->rt_ifp) != NULL) {
  324                                         ifpaddr = TAILQ_FIRST(&ifp->if_addrlist)->ifa_addr;
  325                                         ifaaddr = rt->rt_ifa->ifa_addr;
  326                                         if (ifp->if_flags & IFF_POINTOPOINT)
  327                                                 brdaddr = rt->rt_ifa->ifa_dstaddr;
  328                                         else
  329                                                 brdaddr = 0;
  330                                         rtm->rtm_index = ifp->if_index;
  331                                 } else {
  332                                         ifpaddr = 0;
  333                                         ifaaddr = 0;
  334                                 }
  335                         }
  336                         (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
  337                             (struct walkarg *)0, &len);
  338                         if (len > rtm->rtm_msglen) {
  339                                 struct rt_msghdr *new_rtm;
  340                                 R_Malloc(new_rtm, struct rt_msghdr *, len);
  341                                 if (new_rtm == 0)
  342                                         senderr(ENOBUFS);
  343                                 Bcopy(rtm, new_rtm, rtm->rtm_msglen);
  344                                 Free(rtm); rtm = new_rtm;
  345                         }
  346                         (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
  347                             (struct walkarg *)0, 0);
  348                         rtm->rtm_flags = rt->rt_flags;
  349                         rtm->rtm_rmx = rt->rt_rmx;
  350                         rtm->rtm_addrs = info.rti_addrs;
  351                         break;
  352 
  353                 case RTM_CHANGE:
  354                         /*
  355                          * new gateway could require new ifaddr, ifp;
  356                          * flags may also be different; ifp may be specified
  357                          * by ll sockaddr when protocol address is ambiguous
  358                          */
  359                         if ((error = rt_getifa(&info)) != 0)
  360                                 senderr(error);
  361                         if (gate && rt_setgate(rt, rt_key(rt), gate))
  362                                 senderr(EDQUOT);
  363                         /* new gateway could require new ifaddr, ifp;
  364                            flags may also be different; ifp may be specified
  365                            by ll sockaddr when protocol address is ambiguous */
  366                         if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
  367                             (ifp = ifa->ifa_ifp) && (ifaaddr || gate))
  368                                 ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
  369                                     ifp);
  370                         else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
  371                             (gate && (ifa = ifa_ifwithroute(rt->rt_flags,
  372                             rt_key(rt), gate))))
  373                                 ifp = ifa->ifa_ifp;
  374                         if (ifa) {
  375                                 struct ifaddr *oifa = rt->rt_ifa;
  376                                 if (oifa != ifa) {
  377                                     if (oifa && oifa->ifa_rtrequest)
  378                                         oifa->ifa_rtrequest(RTM_DELETE, rt,
  379                                             &info);
  380                                     IFAFREE(rt->rt_ifa);
  381                                     rt->rt_ifa = ifa;
  382                                     IFAREF(rt->rt_ifa);
  383                                     rt->rt_ifp = ifp;
  384                                 }
  385                         }
  386                         rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
  387                             &rt->rt_rmx);
  388                         if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
  389                                 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
  390                         if (genmask)
  391                                 rt->rt_genmask = genmask;
  392                         /*
  393                          * Fall into
  394                          */
  395                 case RTM_LOCK:
  396                         rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
  397                         rt->rt_rmx.rmx_locks |=
  398                             (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
  399                         break;
  400                 }
  401                 break;
  402 
  403         default:
  404                 senderr(EOPNOTSUPP);
  405         }
  406 
  407 flush:
  408         if (rtm) {
  409                 if (error)
  410                         rtm->rtm_errno = error;
  411                 else
  412                         rtm->rtm_flags |= RTF_DONE;
  413         }
  414         family = dst ? dst->sa_family : 0;
  415         if (rt)
  416                 rtfree(rt);
  417     {
  418         struct rawcb *rp = 0;
  419         /*
  420          * Check to see if we don't want our own messages.
  421          */
  422         if ((so->so_options & SO_USELOOPBACK) == 0) {
  423                 if (route_cb.any_count <= 1) {
  424                         if (rtm)
  425                                 Free(rtm);
  426                         m_freem(m);
  427                         return (error);
  428                 }
  429                 /* There is another listener, so construct message */
  430                 rp = sotorawcb(so);
  431         }
  432         if (rtm) {
  433                 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
  434                 if (m->m_pkthdr.len < rtm->rtm_msglen) {
  435                         m_freem(m);
  436                         m = NULL;
  437                 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
  438                         m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
  439                 Free(rtm);
  440         }
  441         if (rp)
  442                 rp->rcb_proto.sp_family = 0; /* Avoid us */
  443         if (family)
  444                 route_proto.sp_protocol = family;
  445         if (m)
  446                 raw_input(m, &route_proto, &route_src, &route_dst);
  447         if (rp)
  448                 rp->rcb_proto.sp_family = PF_ROUTE;
  449     }
  450         return (error);
  451 }
  452 
  453 void
  454 rt_setmetrics(u_long which, const struct rt_metrics *in, struct rt_metrics *out)
  455 {
  456 #define metric(f, e) if (which & (f)) out->e = in->e;
  457         metric(RTV_RPIPE, rmx_recvpipe);
  458         metric(RTV_SPIPE, rmx_sendpipe);
  459         metric(RTV_SSTHRESH, rmx_ssthresh);
  460         metric(RTV_RTT, rmx_rtt);
  461         metric(RTV_RTTVAR, rmx_rttvar);
  462         metric(RTV_HOPCOUNT, rmx_hopcount);
  463         metric(RTV_MTU, rmx_mtu);
  464         metric(RTV_EXPIRE, rmx_expire);
  465 #undef metric
  466 }
  467 
  468 #define ROUNDUP(a) \
  469         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  470 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
  471 
  472 static int
  473 rt_xaddrs(u_char rtmtype, const char *cp, const char *cplim, struct rt_addrinfo *rtinfo)
  474 {
  475         const struct sockaddr *sa = NULL;       /* Quell compiler warning */
  476         int i;
  477 
  478         for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
  479                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
  480                         continue;
  481                 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
  482                 ADVANCE(cp, sa);
  483         }
  484 
  485         /* Check for extra addresses specified, except RTM_GET asking for interface info.  */
  486         if (rtmtype == RTM_GET) {
  487                 if (((rtinfo->rti_addrs & (~((1 << RTAX_IFP) | (1 << RTAX_IFA)))) & (~0 << i)) != 0)
  488                         return (1);
  489         } else {
  490                 if ((rtinfo->rti_addrs & (~0 << i)) != 0)
  491                         return (1);
  492         }
  493         /* Check for bad data length.  */
  494         if (cp != cplim) {
  495                 if (i == RTAX_NETMASK + 1 &&
  496                     cp - ROUNDUP(sa->sa_len) + sa->sa_len == cplim)
  497                         /*
  498                          * The last sockaddr was netmask.
  499                          * We accept this for now for the sake of old
  500                          * binaries or third party softwares.
  501                          */
  502                         ;
  503                 else
  504                         return (1);
  505         }
  506         return (0);
  507 }
  508 
  509 static struct mbuf *
  510 rt_msg1(int type, struct rt_addrinfo *rtinfo, caddr_t data, int datalen)
  511 {
  512         struct rt_msghdr *rtm;
  513         struct mbuf *m;
  514         int i;
  515         const struct sockaddr *sa;
  516         int len, dlen;
  517 
  518         m = m_gethdr(M_DONTWAIT, MT_DATA);
  519         if (m == 0)
  520                 return (m);
  521         MCLAIM(m, &routedomain.dom_mowner);
  522         switch (type) {
  523 
  524         case RTM_DELADDR:
  525         case RTM_NEWADDR:
  526                 len = sizeof(struct ifa_msghdr);
  527                 break;
  528 
  529 #ifdef COMPAT_14
  530         case RTM_OIFINFO:
  531                 len = sizeof(struct if_msghdr14);
  532                 break;
  533 #endif
  534 
  535         case RTM_IFINFO:
  536                 len = sizeof(struct if_msghdr);
  537                 break;
  538 
  539         case RTM_IFANNOUNCE:
  540                 len = sizeof(struct if_announcemsghdr);
  541                 break;
  542 
  543         default:
  544                 len = sizeof(struct rt_msghdr);
  545         }
  546         if (len > MHLEN + MLEN)
  547                 panic("rt_msg1: message too long");
  548         else if (len > MHLEN) {
  549                 m->m_next = m_get(M_DONTWAIT, MT_DATA);
  550                 if (m->m_next == NULL) {
  551                         m_freem(m);
  552                         return (NULL);
  553                 }
  554                 MCLAIM(m->m_next, m->m_owner);
  555                 m->m_pkthdr.len = len;
  556                 m->m_len = MHLEN;
  557                 m->m_next->m_len = len - MHLEN;
  558         } else {
  559                 m->m_pkthdr.len = m->m_len = len;
  560         }
  561         m->m_pkthdr.rcvif = 0;
  562         m_copyback(m, 0, datalen, data);
  563         rtm = mtod(m, struct rt_msghdr *);
  564         for (i = 0; i < RTAX_MAX; i++) {
  565                 if ((sa = rtinfo->rti_info[i]) == NULL)
  566                         continue;
  567                 rtinfo->rti_addrs |= (1 << i);
  568                 dlen = ROUNDUP(sa->sa_len);
  569                 m_copyback(m, len, dlen, (caddr_t)sa);
  570                 len += dlen;
  571         }
  572         if (m->m_pkthdr.len != len) {
  573                 m_freem(m);
  574                 return (NULL);
  575         }
  576         rtm->rtm_msglen = len;
  577         rtm->rtm_version = RTM_VERSION;
  578         rtm->rtm_type = type;
  579         return (m);
  580 }
  581 
  582 /*
  583  * rt_msg2
  584  *
  585  *       fills 'cp' or 'w'.w_tmem with the routing socket message and
  586  *              returns the length of the message in 'lenp'.
  587  *
  588  * if walkarg is 0, cp is expected to be 0 or a buffer large enough to hold
  589  *      the message
  590  * otherwise walkarg's w_needed is updated and if the user buffer is
  591  *      specified and w_needed indicates space exists the information is copied
  592  *      into the temp space (w_tmem). w_tmem is [re]allocated if necessary,
  593  *      if the allocation fails ENOBUFS is returned.
  594  */
  595 static int
  596 rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w,
  597         int *lenp)
  598 {
  599         int i;
  600         int len, dlen, second_time = 0;
  601         caddr_t cp0;
  602 
  603         rtinfo->rti_addrs = 0;
  604 again:
  605         switch (type) {
  606 
  607         case RTM_DELADDR:
  608         case RTM_NEWADDR:
  609                 len = sizeof(struct ifa_msghdr);
  610                 break;
  611 #ifdef COMPAT_14
  612         case RTM_OIFINFO:
  613                 len = sizeof(struct if_msghdr14);
  614                 break;
  615 #endif
  616 
  617         case RTM_IFINFO:
  618                 len = sizeof(struct if_msghdr);
  619                 break;
  620 
  621         default:
  622                 len = sizeof(struct rt_msghdr);
  623         }
  624         if ((cp0 = cp) != NULL)
  625                 cp += len;
  626         for (i = 0; i < RTAX_MAX; i++) {
  627                 const struct sockaddr *sa;
  628 
  629                 if ((sa = rtinfo->rti_info[i]) == 0)
  630                         continue;
  631                 rtinfo->rti_addrs |= (1 << i);
  632                 dlen = ROUNDUP(sa->sa_len);
  633                 if (cp) {
  634                         bcopy(sa, cp, (unsigned)dlen);
  635                         cp += dlen;
  636                 }
  637                 len += dlen;
  638         }
  639         if (cp == 0 && w != NULL && !second_time) {
  640                 struct walkarg *rw = w;
  641 
  642                 rw->w_needed += len;
  643                 if (rw->w_needed <= 0 && rw->w_where) {
  644                         if (rw->w_tmemsize < len) {
  645                                 if (rw->w_tmem)
  646                                         free(rw->w_tmem, M_RTABLE);
  647                                 rw->w_tmem = (caddr_t) malloc(len, M_RTABLE,
  648                                     M_NOWAIT);
  649                                 if (rw->w_tmem)
  650                                         rw->w_tmemsize = len;
  651                         }
  652                         if (rw->w_tmem) {
  653                                 cp = rw->w_tmem;
  654                                 second_time = 1;
  655                                 goto again;
  656                         } else {
  657                                 rw->w_tmemneeded = len;
  658                                 return (ENOBUFS);
  659                         }
  660                 }
  661         }
  662         if (cp) {
  663                 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
  664 
  665                 rtm->rtm_version = RTM_VERSION;
  666                 rtm->rtm_type = type;
  667                 rtm->rtm_msglen = len;
  668         }
  669         if (lenp)
  670                 *lenp = len;
  671         return (0);
  672 }
  673 
  674 /*
  675  * This routine is called to generate a message from the routing
  676  * socket indicating that a redirect has occurred, a routing lookup
  677  * has failed, or that a protocol has detected timeouts to a particular
  678  * destination.
  679  */
  680 void
  681 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
  682 {
  683         struct rt_msghdr rtm;
  684         struct mbuf *m;
  685         const struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
  686 
  687         if (route_cb.any_count == 0)
  688                 return;
  689         memset(&rtm, 0, sizeof(rtm));
  690         rtm.rtm_flags = RTF_DONE | flags;
  691         rtm.rtm_errno = error;
  692         m = rt_msg1(type, rtinfo, (caddr_t)&rtm, sizeof(rtm));
  693         if (m == 0)
  694                 return;
  695         mtod(m, struct rt_msghdr *)->rtm_addrs = rtinfo->rti_addrs;
  696         route_proto.sp_protocol = sa ? sa->sa_family : 0;
  697         raw_input(m, &route_proto, &route_src, &route_dst);
  698 }
  699 
  700 /*
  701  * This routine is called to generate a message from the routing
  702  * socket indicating that the status of a network interface has changed.
  703  */
  704 void
  705 rt_ifmsg(struct ifnet *ifp)
  706 {
  707         struct if_msghdr ifm;
  708 #ifdef COMPAT_14
  709         struct if_msghdr14 oifm;
  710 #endif
  711         struct mbuf *m;
  712         struct rt_addrinfo info;
  713 
  714         if (route_cb.any_count == 0)
  715                 return;
  716         memset(&info, 0, sizeof(info));
  717         memset(&ifm, 0, sizeof(ifm));
  718         ifm.ifm_index = ifp->if_index;
  719         ifm.ifm_flags = ifp->if_flags;
  720         ifm.ifm_data = ifp->if_data;
  721         ifm.ifm_addrs = 0;
  722         m = rt_msg1(RTM_IFINFO, &info, (caddr_t)&ifm, sizeof(ifm));
  723         if (m == 0)
  724                 return;
  725         route_proto.sp_protocol = 0;
  726         raw_input(m, &route_proto, &route_src, &route_dst);
  727 #ifdef COMPAT_14
  728         memset(&info, 0, sizeof(info));
  729         memset(&oifm, 0, sizeof(oifm));
  730         oifm.ifm_index = ifp->if_index;
  731         oifm.ifm_flags = ifp->if_flags;
  732         oifm.ifm_data.ifi_type = ifp->if_data.ifi_type;
  733         oifm.ifm_data.ifi_addrlen = ifp->if_data.ifi_addrlen;
  734         oifm.ifm_data.ifi_hdrlen = ifp->if_data.ifi_hdrlen;
  735         oifm.ifm_data.ifi_mtu = ifp->if_data.ifi_mtu;
  736         oifm.ifm_data.ifi_metric = ifp->if_data.ifi_metric;
  737         oifm.ifm_data.ifi_baudrate = ifp->if_data.ifi_baudrate;
  738         oifm.ifm_data.ifi_ipackets = ifp->if_data.ifi_ipackets;
  739         oifm.ifm_data.ifi_ierrors = ifp->if_data.ifi_ierrors;
  740         oifm.ifm_data.ifi_opackets = ifp->if_data.ifi_opackets;
  741         oifm.ifm_data.ifi_oerrors = ifp->if_data.ifi_oerrors;
  742         oifm.ifm_data.ifi_collisions = ifp->if_data.ifi_collisions;
  743         oifm.ifm_data.ifi_ibytes = ifp->if_data.ifi_ibytes;
  744         oifm.ifm_data.ifi_obytes = ifp->if_data.ifi_obytes;
  745         oifm.ifm_data.ifi_imcasts = ifp->if_data.ifi_imcasts;
  746         oifm.ifm_data.ifi_omcasts = ifp->if_data.ifi_omcasts;
  747         oifm.ifm_data.ifi_iqdrops = ifp->if_data.ifi_iqdrops;
  748         oifm.ifm_data.ifi_noproto = ifp->if_data.ifi_noproto;
  749         oifm.ifm_data.ifi_lastchange = ifp->if_data.ifi_lastchange;
  750         oifm.ifm_addrs = 0;
  751         m = rt_msg1(RTM_OIFINFO, &info, (caddr_t)&oifm, sizeof(oifm));
  752         if (m == 0)
  753                 return;
  754         route_proto.sp_protocol = 0;
  755         raw_input(m, &route_proto, &route_src, &route_dst);
  756 #endif
  757 }
  758 
  759 /*
  760  * This is called to generate messages from the routing socket
  761  * indicating a network interface has had addresses associated with it.
  762  * if we ever reverse the logic and replace messages TO the routing
  763  * socket indicate a request to configure interfaces, then it will
  764  * be unnecessary as the routing socket will automatically generate
  765  * copies of it.
  766  */
  767 void
  768 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
  769 {
  770         struct rt_addrinfo info;
  771         struct sockaddr *sa = NULL;
  772         int pass;
  773         struct mbuf *m = NULL;
  774         struct ifnet *ifp = ifa->ifa_ifp;
  775 
  776         if (route_cb.any_count == 0)
  777                 return;
  778         for (pass = 1; pass < 3; pass++) {
  779                 memset(&info, 0, sizeof(info));
  780                 if ((cmd == RTM_ADD && pass == 1) ||
  781                     (cmd == RTM_DELETE && pass == 2)) {
  782                         struct ifa_msghdr ifam;
  783                         int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
  784 
  785                         ifaaddr = sa = ifa->ifa_addr;
  786                         ifpaddr = TAILQ_FIRST(&ifp->if_addrlist)->ifa_addr;
  787                         netmask = ifa->ifa_netmask;
  788                         brdaddr = ifa->ifa_dstaddr;
  789                         memset(&ifam, 0, sizeof(ifam));
  790                         ifam.ifam_index = ifp->if_index;
  791                         ifam.ifam_metric = ifa->ifa_metric;
  792                         ifam.ifam_flags = ifa->ifa_flags;
  793                         m = rt_msg1(ncmd, &info, (caddr_t)&ifam, sizeof(ifam));
  794                         if (m == NULL)
  795                                 continue;
  796                         mtod(m, struct ifa_msghdr *)->ifam_addrs =
  797                             info.rti_addrs;
  798                 }
  799                 if ((cmd == RTM_ADD && pass == 2) ||
  800                     (cmd == RTM_DELETE && pass == 1)) {
  801                         struct rt_msghdr rtm;
  802 
  803                         if (rt == 0)
  804                                 continue;
  805                         netmask = rt_mask(rt);
  806                         dst = sa = rt_key(rt);
  807                         gate = rt->rt_gateway;
  808                         memset(&rtm, 0, sizeof(rtm));
  809                         rtm.rtm_index = ifp->if_index;
  810                         rtm.rtm_flags |= rt->rt_flags;
  811                         rtm.rtm_errno = error;
  812                         m = rt_msg1(cmd, &info, (caddr_t)&rtm, sizeof(rtm));
  813                         if (m == NULL)
  814                                 continue;
  815                         mtod(m, struct rt_msghdr *)->rtm_addrs = info.rti_addrs;
  816                 }
  817                 route_proto.sp_protocol = sa ? sa->sa_family : 0;
  818                 raw_input(m, &route_proto, &route_src, &route_dst);
  819         }
  820 }
  821 
  822 /*
  823  * This is called to generate routing socket messages indicating
  824  * network interface arrival and departure.
  825  */
  826 void
  827 rt_ifannouncemsg(struct ifnet *ifp, int what)
  828 {
  829         struct if_announcemsghdr ifan;
  830         struct mbuf *m;
  831         struct rt_addrinfo info;
  832 
  833         if (route_cb.any_count == 0)
  834                 return;
  835         memset(&info, 0, sizeof(info));
  836         memset(&ifan, 0, sizeof(ifan));
  837         ifan.ifan_index = ifp->if_index;
  838         strlcpy(ifan.ifan_name, ifp->if_xname, sizeof(ifan.ifan_name));
  839         ifan.ifan_what = what;
  840         m = rt_msg1(RTM_IFANNOUNCE, &info, (caddr_t)&ifan, sizeof(ifan));
  841         if (m == 0)
  842                 return;
  843         route_proto.sp_protocol = 0;
  844         raw_input(m, &route_proto, &route_src, &route_dst);
  845 }
  846 
  847 /*
  848  * This is used in dumping the kernel table via sysctl().
  849  */
  850 static int
  851 sysctl_dumpentry(struct radix_node *rn, void *v)
  852 {
  853         struct walkarg *w = v;
  854         struct rtentry *rt = (struct rtentry *)rn;
  855         int error = 0, size;
  856         struct rt_addrinfo info;
  857 
  858         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
  859                 return 0;
  860         memset(&info, 0, sizeof(info));
  861         dst = rt_key(rt);
  862         gate = rt->rt_gateway;
  863         netmask = rt_mask(rt);
  864         genmask = rt->rt_genmask;
  865         if (rt->rt_ifp) {
  866                 ifpaddr = TAILQ_FIRST(&rt->rt_ifp->if_addrlist)->ifa_addr;
  867                 ifaaddr = rt->rt_ifa->ifa_addr;
  868                 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
  869                         brdaddr = rt->rt_ifa->ifa_dstaddr;
  870         }
  871         if ((error = rt_msg2(RTM_GET, &info, 0, w, &size)))
  872                 return (error);
  873         if (w->w_where && w->w_tmem && w->w_needed <= 0) {
  874                 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
  875 
  876                 rtm->rtm_flags = rt->rt_flags;
  877                 rtm->rtm_use = rt->rt_use;
  878                 rtm->rtm_rmx = rt->rt_rmx;
  879                 rtm->rtm_index = rt->rt_ifp->if_index;
  880                 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
  881                 rtm->rtm_addrs = info.rti_addrs;
  882                 if ((error = copyout(rtm, w->w_where, size)) != 0)
  883                         w->w_where = NULL;
  884                 else
  885                         w->w_where += size;
  886         }
  887         return (error);
  888 }
  889 
  890 static int
  891 sysctl_iflist(int af, struct walkarg *w, int type)
  892 {
  893         struct ifnet *ifp;
  894         struct ifaddr *ifa;
  895         struct  rt_addrinfo info;
  896         int     len, error = 0;
  897 
  898         memset(&info, 0, sizeof(info));
  899         IFNET_FOREACH(ifp) {
  900                 if (w->w_arg && w->w_arg != ifp->if_index)
  901                         continue;
  902                 ifa = TAILQ_FIRST(&ifp->if_addrlist);
  903                 ifpaddr = ifa->ifa_addr;
  904                 switch (type) {
  905                 case NET_RT_IFLIST:
  906                         error =
  907                             rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w, &len);
  908                         break;
  909 #ifdef COMPAT_14
  910                 case NET_RT_OIFLIST:
  911                         error =
  912                             rt_msg2(RTM_OIFINFO, &info, (caddr_t)0, w, &len);
  913                         break;
  914 #endif
  915                 default:
  916                         panic("sysctl_iflist(1)");
  917                 }
  918                 if (error)
  919                         return (error);
  920                 ifpaddr = 0;
  921                 if (w->w_where && w->w_tmem && w->w_needed <= 0) {
  922                         switch (type) {
  923                         case NET_RT_IFLIST: {
  924                                 struct if_msghdr *ifm;
  925 
  926                                 ifm = (struct if_msghdr *)w->w_tmem;
  927                                 ifm->ifm_index = ifp->if_index;
  928                                 ifm->ifm_flags = ifp->if_flags;
  929                                 ifm->ifm_data = ifp->if_data;
  930                                 ifm->ifm_addrs = info.rti_addrs;
  931                                 error = copyout(ifm, w->w_where, len);
  932                                 if (error)
  933                                         return (error);
  934                                 w->w_where += len;
  935                                 break;
  936                         }
  937 
  938 #ifdef COMPAT_14
  939                         case NET_RT_OIFLIST: {
  940                                 struct if_msghdr14 *ifm;
  941 
  942                                 ifm = (struct if_msghdr14 *)w->w_tmem;
  943                                 ifm->ifm_index = ifp->if_index;
  944                                 ifm->ifm_flags = ifp->if_flags;
  945                                 ifm->ifm_data.ifi_type = ifp->if_data.ifi_type;
  946                                 ifm->ifm_data.ifi_addrlen =
  947                                     ifp->if_data.ifi_addrlen;
  948                                 ifm->ifm_data.ifi_hdrlen =
  949                                     ifp->if_data.ifi_hdrlen;
  950                                 ifm->ifm_data.ifi_mtu = ifp->if_data.ifi_mtu;
  951                                 ifm->ifm_data.ifi_metric =
  952                                     ifp->if_data.ifi_metric;
  953                                 ifm->ifm_data.ifi_baudrate =
  954                                     ifp->if_data.ifi_baudrate;
  955                                 ifm->ifm_data.ifi_ipackets =
  956                                     ifp->if_data.ifi_ipackets;
  957                                 ifm->ifm_data.ifi_ierrors =
  958                                     ifp->if_data.ifi_ierrors;
  959                                 ifm->ifm_data.ifi_opackets =
  960                                     ifp->if_data.ifi_opackets;
  961                                 ifm->ifm_data.ifi_oerrors =
  962                                     ifp->if_data.ifi_oerrors;
  963                                 ifm->ifm_data.ifi_collisions =
  964                                     ifp->if_data.ifi_collisions;
  965                                 ifm->ifm_data.ifi_ibytes =
  966                                     ifp->if_data.ifi_ibytes;
  967                                 ifm->ifm_data.ifi_obytes =
  968                                     ifp->if_data.ifi_obytes;
  969                                 ifm->ifm_data.ifi_imcasts =
  970                                     ifp->if_data.ifi_imcasts;
  971                                 ifm->ifm_data.ifi_omcasts =
  972                                     ifp->if_data.ifi_omcasts;
  973                                 ifm->ifm_data.ifi_iqdrops =
  974                                     ifp->if_data.ifi_iqdrops;
  975                                 ifm->ifm_data.ifi_noproto =
  976                                     ifp->if_data.ifi_noproto;
  977                                 ifm->ifm_data.ifi_lastchange =
  978                                     ifp->if_data.ifi_lastchange;
  979                                 ifm->ifm_addrs = info.rti_addrs;
  980                                 error = copyout(ifm, w->w_where, len);
  981                                 if (error)
  982                                         return (error);
  983                                 w->w_where += len;
  984                                 break;
  985                         }
  986 #endif
  987                         default:
  988                                 panic("sysctl_iflist(2)");
  989                         }
  990                 }
  991                 while ((ifa = TAILQ_NEXT(ifa, ifa_list)) != NULL) {
  992                         if (af && af != ifa->ifa_addr->sa_family)
  993                                 continue;
  994                         ifaaddr = ifa->ifa_addr;
  995                         netmask = ifa->ifa_netmask;
  996                         brdaddr = ifa->ifa_dstaddr;
  997                         if ((error = rt_msg2(RTM_NEWADDR, &info, 0, w, &len)))
  998                                 return (error);
  999                         if (w->w_where && w->w_tmem && w->w_needed <= 0) {
 1000                                 struct ifa_msghdr *ifam;
 1001 
 1002                                 ifam = (struct ifa_msghdr *)w->w_tmem;
 1003                                 ifam->ifam_index = ifa->ifa_ifp->if_index;
 1004                                 ifam->ifam_flags = ifa->ifa_flags;
 1005                                 ifam->ifam_metric = ifa->ifa_metric;
 1006                                 ifam->ifam_addrs = info.rti_addrs;
 1007                                 error = copyout(w->w_tmem, w->w_where, len);
 1008                                 if (error)
 1009                                         return (error);
 1010                                 w->w_where += len;
 1011                         }
 1012                 }
 1013                 ifaaddr = netmask = brdaddr = 0;
 1014         }
 1015         return (0);
 1016 }
 1017 
 1018 static int
 1019 sysctl_rtable(SYSCTLFN_ARGS)
 1020 {
 1021         void    *where = oldp;
 1022         size_t  *given = oldlenp;
 1023         const void *new = newp;
 1024         struct radix_node_head *rnh;
 1025         int     i, s, error = EINVAL;
 1026         u_char  af;
 1027         struct  walkarg w;
 1028 
 1029         if (namelen == 1 && name[0] == CTL_QUERY)
 1030                 return (sysctl_query(SYSCTLFN_CALL(rnode)));
 1031 
 1032         if (new)
 1033                 return (EPERM);
 1034         if (namelen != 3)
 1035                 return (EINVAL);
 1036         af = name[0];
 1037         w.w_tmemneeded = 0;
 1038         w.w_tmemsize = 0;
 1039         w.w_tmem = NULL;
 1040 again:
 1041         /* we may return here if a later [re]alloc of the t_mem buffer fails */
 1042         if (w.w_tmemneeded) {
 1043                 w.w_tmem = (caddr_t) malloc(w.w_tmemneeded, M_RTABLE, M_WAITOK);
 1044                 w.w_tmemsize = w.w_tmemneeded;
 1045                 w.w_tmemneeded = 0;
 1046         }
 1047         w.w_op = name[1];
 1048         w.w_arg = name[2];
 1049         w.w_given = *given;
 1050         w.w_needed = 0 - w.w_given;
 1051         w.w_where = where;
 1052 
 1053         s = splsoftnet();
 1054         switch (w.w_op) {
 1055 
 1056         case NET_RT_DUMP:
 1057         case NET_RT_FLAGS:
 1058                 for (i = 1; i <= AF_MAX; i++)
 1059                         if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
 1060                             (error = (*rnh->rnh_walktree)(rnh,
 1061                             sysctl_dumpentry, &w)))
 1062                                 break;
 1063                 break;
 1064 
 1065 #ifdef COMPAT_14
 1066         case NET_RT_OIFLIST:
 1067                 error = sysctl_iflist(af, &w, w.w_op);
 1068                 break;
 1069 #endif
 1070 
 1071         case NET_RT_IFLIST:
 1072                 error = sysctl_iflist(af, &w, w.w_op);
 1073         }
 1074         splx(s);
 1075 
 1076         /* check to see if we couldn't allocate memory with NOWAIT */
 1077         if (error == ENOBUFS && w.w_tmem == 0 && w.w_tmemneeded)
 1078                 goto again;
 1079 
 1080         if (w.w_tmem)
 1081                 free(w.w_tmem, M_RTABLE);
 1082         w.w_needed += w.w_given;
 1083         if (where) {
 1084                 *given = w.w_where - (caddr_t) where;
 1085                 if (*given < w.w_needed)
 1086                         return (ENOMEM);
 1087         } else {
 1088                 *given = (11 * w.w_needed) / 10;
 1089         }
 1090         return (error);
 1091 }
 1092 
 1093 /*
 1094  * Definitions of protocols supported in the ROUTE domain.
 1095  */
 1096 
 1097 const struct protosw routesw[] = {
 1098 {
 1099         SOCK_RAW,       &routedomain,   0,              PR_ATOMIC|PR_ADDR,
 1100         raw_input,      route_output,   raw_ctlinput,   0,
 1101         route_usrreq,
 1102         raw_init,       0,              0,              0,
 1103 } };
 1104 
 1105 struct domain routedomain = {
 1106         PF_ROUTE, "route", route_init, 0, 0,
 1107         routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])]
 1108 };
 1109 
 1110 SYSCTL_SETUP(sysctl_net_route_setup, "sysctl net.route subtree setup")
 1111 {
 1112         sysctl_createv(clog, 0, NULL, NULL,
 1113                        CTLFLAG_PERMANENT,
 1114                        CTLTYPE_NODE, "net", NULL,
 1115                        NULL, 0, NULL, 0,
 1116                        CTL_NET, CTL_EOL);
 1117 
 1118         sysctl_createv(clog, 0, NULL, NULL,
 1119                        CTLFLAG_PERMANENT,
 1120                        CTLTYPE_NODE, "route",
 1121                        SYSCTL_DESCR("PF_ROUTE information"),
 1122                        NULL, 0, NULL, 0,
 1123                        CTL_NET, PF_ROUTE, CTL_EOL);
 1124         sysctl_createv(clog, 0, NULL, NULL,
 1125                        CTLFLAG_PERMANENT,
 1126                        CTLTYPE_NODE, "rtable",
 1127                        SYSCTL_DESCR("Routing table information"),
 1128                        sysctl_rtable, 0, NULL, 0,
 1129                        CTL_NET, PF_ROUTE, 0 /* any protocol */, CTL_EOL);
 1130 }

Cache object: 02e8352476eb38763130e06ecd92121a


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