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

Cache object: 7bd9a96b354cc026963382fbb7689a4a


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