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/bsd/net/rtsock.c

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

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  * Copyright (c) 1988, 1991, 1993
   27  *      The Regents of the University of California.  All rights reserved.
   28  *
   29  * Redistribution and use in source and binary forms, with or without
   30  * modification, are permitted provided that the following conditions
   31  * are met:
   32  * 1. Redistributions of source code must retain the above copyright
   33  *    notice, this list of conditions and the following disclaimer.
   34  * 2. Redistributions in binary form must reproduce the above copyright
   35  *    notice, this list of conditions and the following disclaimer in the
   36  *    documentation and/or other materials provided with the distribution.
   37  * 3. All advertising materials mentioning features or use of this software
   38  *    must display the following acknowledgement:
   39  *      This product includes software developed by the University of
   40  *      California, Berkeley and its contributors.
   41  * 4. Neither the name of the University nor the names of its contributors
   42  *    may be used to endorse or promote products derived from this software
   43  *    without specific prior written permission.
   44  *
   45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   55  * SUCH DAMAGE.
   56  *
   57  *      @(#)rtsock.c    8.5 (Berkeley) 11/2/94
   58  */
   59 
   60 
   61 #include <sys/param.h>
   62 #include <sys/systm.h>
   63 #include <sys/kernel.h>
   64 #include <sys/sysctl.h>
   65 #include <sys/proc.h>
   66 #include <sys/malloc.h>
   67 #include <sys/mbuf.h>
   68 #include <sys/socket.h>
   69 #include <sys/socketvar.h>
   70 #include <sys/domain.h>
   71 #include <sys/protosw.h>
   72 #include <sys/syslog.h>
   73 
   74 #include <net/if.h>
   75 #include <net/route.h>
   76 #include <net/raw_cb.h>
   77 #include <netinet/in.h>
   78 
   79 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
   80 
   81 static struct   sockaddr route_dst = { 2, PF_ROUTE, };
   82 static struct   sockaddr route_src = { 2, PF_ROUTE, };
   83 static struct   sockaddr sa_zero   = { sizeof(sa_zero), AF_INET, };
   84 static struct   sockproto route_proto = { PF_ROUTE, };
   85 
   86 struct walkarg {
   87         int     w_tmemsize;
   88         int     w_op, w_arg;
   89         caddr_t w_tmem;
   90         struct sysctl_req *w_req;
   91 };
   92 
   93 static struct mbuf *
   94                 rt_msg1 __P((int, struct rt_addrinfo *));
   95 static int      rt_msg2 __P((int,
   96                     struct rt_addrinfo *, caddr_t, struct walkarg *));
   97 static int      rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
   98 static int      sysctl_dumpentry __P((struct radix_node *rn, void *vw));
   99 static int      sysctl_iflist __P((int af, struct walkarg *w));
  100 static int       route_output __P((struct mbuf *, struct socket *));
  101 static void      rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *));
  102 static void     rt_setif __P((struct rtentry *, struct sockaddr *, struct sockaddr *,
  103                               struct sockaddr *));
  104 
  105 /* Sleazy use of local variables throughout file, warning!!!! */
  106 #define dst     info.rti_info[RTAX_DST]
  107 #define gate    info.rti_info[RTAX_GATEWAY]
  108 #define netmask info.rti_info[RTAX_NETMASK]
  109 #define genmask info.rti_info[RTAX_GENMASK]
  110 #define ifpaddr info.rti_info[RTAX_IFP]
  111 #define ifaaddr info.rti_info[RTAX_IFA]
  112 #define brdaddr info.rti_info[RTAX_BRD]
  113 
  114 /*
  115  * It really doesn't make any sense at all for this code to share much
  116  * with raw_usrreq.c, since its functionality is so restricted.  XXX
  117  */
  118 static int
  119 rts_abort(struct socket *so)
  120 {
  121         int s, error;
  122         s = splnet();
  123         error = raw_usrreqs.pru_abort(so);
  124         splx(s);
  125         return error;
  126 }
  127 
  128 /* pru_accept is EOPNOTSUPP */
  129 
  130 static int
  131 rts_attach(struct socket *so, int proto, struct proc *p)
  132 {
  133         struct rawcb *rp;
  134         int s, error;
  135 
  136         if (sotorawcb(so) != 0)
  137                 return EISCONN; /* XXX panic? */
  138         MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK); /* XXX */
  139         if (rp == 0)
  140                 return ENOBUFS;
  141         bzero(rp, sizeof *rp);
  142 
  143         /*
  144          * The splnet() is necessary to block protocols from sending
  145          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
  146          * this PCB is extant but incompletely initialized.
  147          * Probably we should try to do more of this work beforehand and
  148          * eliminate the spl.
  149          */
  150         s = splnet();
  151         so->so_pcb = (caddr_t)rp;
  152         error = raw_attach(so, proto);  /* don't use raw_usrreqs.pru_attach, it checks for SS_PRIV */
  153         rp = sotorawcb(so);
  154         if (error) {
  155                 splx(s);
  156                 FREE(rp, M_PCB);
  157                 so->so_pcb = 0;
  158                 return error;
  159         }
  160         switch(rp->rcb_proto.sp_protocol) {
  161         case AF_INET:
  162                 route_cb.ip_count++;
  163                 break;
  164         case AF_INET6:
  165                 route_cb.ip6_count++;
  166                 break;
  167         case AF_IPX:
  168                 route_cb.ipx_count++;
  169                 break;
  170         case AF_NS:
  171                 route_cb.ns_count++;
  172                 break;
  173         }
  174         rp->rcb_faddr = &route_src;
  175         route_cb.any_count++;
  176         soisconnected(so);
  177         so->so_options |= SO_USELOOPBACK;
  178         splx(s);
  179         return 0;
  180 }
  181 
  182 static int
  183 rts_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
  184 {
  185         int s, error;
  186         s = splnet();
  187         error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
  188         splx(s);
  189         return error;
  190 }
  191 
  192 static int
  193 rts_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
  194 {
  195         int s, error;
  196         s = splnet();
  197         error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
  198         splx(s);
  199         return error;
  200 }
  201 
  202 /* pru_connect2 is EOPNOTSUPP */
  203 /* pru_control is EOPNOTSUPP */
  204 
  205 static int
  206 rts_detach(struct socket *so)
  207 {
  208         struct rawcb *rp = sotorawcb(so);
  209         int s, error;
  210 
  211         s = splnet();
  212         if (rp != 0) {
  213                 switch(rp->rcb_proto.sp_protocol) {
  214                 case AF_INET:
  215                         route_cb.ip_count--;
  216                         break;
  217                 case AF_INET6:
  218                         route_cb.ip6_count--;
  219                         break;
  220                 case AF_IPX:
  221                         route_cb.ipx_count--;
  222                         break;
  223                 case AF_NS:
  224                         route_cb.ns_count--;
  225                         break;
  226                 }
  227                 route_cb.any_count--;
  228         }
  229         error = raw_usrreqs.pru_detach(so);
  230         splx(s);
  231         return error;
  232 }
  233 
  234 static int
  235 rts_disconnect(struct socket *so)
  236 {
  237         int s, error;
  238         s = splnet();
  239         error = raw_usrreqs.pru_disconnect(so);
  240         splx(s);
  241         return error;
  242 }
  243 
  244 /* pru_listen is EOPNOTSUPP */
  245 
  246 static int
  247 rts_peeraddr(struct socket *so, struct sockaddr **nam)
  248 {
  249         int s, error;
  250         s = splnet();
  251         error = raw_usrreqs.pru_peeraddr(so, nam);
  252         splx(s);
  253         return error;
  254 }
  255 
  256 /* pru_rcvd is EOPNOTSUPP */
  257 /* pru_rcvoob is EOPNOTSUPP */
  258 
  259 static int
  260 rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
  261          struct mbuf *control, struct proc *p)
  262 {
  263         int s, error;
  264         s = splnet();
  265         error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
  266         splx(s);
  267         return error;
  268 }
  269 
  270 /* pru_sense is null */
  271 
  272 static int
  273 rts_shutdown(struct socket *so)
  274 {
  275         int s, error;
  276         s = splnet();
  277         error = raw_usrreqs.pru_shutdown(so);
  278         splx(s);
  279         return error;
  280 }
  281 
  282 static int
  283 rts_sockaddr(struct socket *so, struct sockaddr **nam)
  284 {
  285         int s, error;
  286         s = splnet();
  287         error = raw_usrreqs.pru_sockaddr(so, nam);
  288         splx(s);
  289         return error;
  290 }
  291 
  292 static struct pr_usrreqs route_usrreqs = {
  293         rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect,
  294         pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect,
  295         pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
  296         rts_send, pru_sense_null, rts_shutdown, rts_sockaddr,
  297         sosend, soreceive, sopoll
  298 };
  299 
  300 /*ARGSUSED*/
  301 static int
  302 route_output(m, so)
  303         register struct mbuf *m;
  304         struct socket *so;
  305 {
  306         register struct rt_msghdr *rtm = 0;
  307         register struct rtentry *rt = 0;
  308         struct rtentry *saved_nrt = 0;
  309         struct radix_node_head *rnh;
  310         struct rt_addrinfo info;
  311         int len, error = 0;
  312         struct ifnet *ifp = 0;
  313         struct ifaddr *ifa = 0;
  314         struct proc  *curproc = current_proc();
  315         int sendonlytoself = 0;
  316 
  317 #define senderr(e) { error = e; goto flush;}
  318         if (m == 0 || ((m->m_len < sizeof(long)) &&
  319                        (m = m_pullup(m, sizeof(long))) == 0))
  320                 return (ENOBUFS);
  321         if ((m->m_flags & M_PKTHDR) == 0)
  322                 panic("route_output");
  323         len = m->m_pkthdr.len;
  324         if (len < sizeof(*rtm) ||
  325             len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
  326                 dst = 0;
  327                 senderr(EINVAL);
  328         }
  329         R_Malloc(rtm, struct rt_msghdr *, len);
  330         if (rtm == 0) {
  331                 dst = 0;
  332                 senderr(ENOBUFS);
  333         }
  334         m_copydata(m, 0, len, (caddr_t)rtm);
  335         if (rtm->rtm_version != RTM_VERSION) {
  336                 dst = 0;
  337                 senderr(EPROTONOSUPPORT);
  338         }
  339         
  340         /*
  341          * Silent version of RTM_GET for Reachabiltiy APIs. We may change
  342          * all RTM_GETs to be silent in the future, so this is private for now.
  343          */
  344         if (rtm->rtm_type == RTM_GET_SILENT) {
  345                 if ((so->so_options & SO_USELOOPBACK) == 0)
  346                         senderr(EINVAL);
  347                 sendonlytoself = 1;
  348                 rtm->rtm_type = RTM_GET;
  349         }
  350         
  351         /*
  352          * Perform permission checking, only privileged sockets
  353          * may perform operations other than RTM_GET
  354          */
  355         if (rtm->rtm_type != RTM_GET && (so->so_state & SS_PRIV) == 0) {
  356                 dst = 0;
  357                 senderr(EPERM);
  358         }
  359         rtm->rtm_pid = curproc->p_pid;
  360         info.rti_addrs = rtm->rtm_addrs;
  361         if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
  362                 dst = 0;
  363                 senderr(EINVAL);
  364         }
  365         if (dst == 0 || (dst->sa_family >= AF_MAX)
  366             || (gate != 0 && (gate->sa_family >= AF_MAX)))
  367                 senderr(EINVAL);
  368         if (genmask) {
  369                 struct radix_node *t;
  370                 t = rn_addmask((caddr_t)genmask, 0, 1);
  371                 if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
  372                         genmask = (struct sockaddr *)(t->rn_key);
  373                 else
  374                         senderr(ENOBUFS);
  375         }
  376         switch (rtm->rtm_type) {
  377 
  378         case RTM_ADD:
  379                 if (gate == 0)
  380                         senderr(EINVAL);
  381 
  382 #ifdef __APPLE__
  383 /* XXX LD11JUL02 Special case for AOL 5.1.2 connectivity issue to AirPort BS (Radar 2969954)
  384  * AOL is adding a circular route ("10.0.1.1/32 10.0.1.1") when establishing its ppp tunnel
  385  * to the AP BaseStation by removing the default gateway and replacing it with their tunnel entry point.
  386  * There is no apparent reason to add this route as there is a valid 10.0.1.1/24 route to the BS.
  387  * That circular route was ignored on previous version of MacOS X because of a routing bug
  388  * corrected with the merge to FreeBSD4.4 (a route generated from an RTF_CLONING route had the RTF_WASCLONED
  389  * flag set but did not have a reference to the parent route) and that entry was left in the RT. This workaround is
  390  * made in order to provide binary compatibility with AOL. 
  391  * If we catch a process adding a circular route with a /32 from the routing socket, we error it out instead of
  392  * confusing the routing table with a wrong route to the previous default gateway
  393  */
  394 {
  395                 extern int check_routeselfref;
  396 #define satosinaddr(sa) (((struct sockaddr_in *)sa)->sin_addr.s_addr)
  397 
  398                 if (check_routeselfref && (dst && dst->sa_family == AF_INET) && 
  399                         (netmask && satosinaddr(netmask) == INADDR_BROADCAST) &&
  400                         (gate && satosinaddr(dst) == satosinaddr(gate))) {
  401                                 log(LOG_WARNING, "route_output: circular route %ld.%ld.%ld.%ld/32 ignored\n",
  402                                         (ntohl(satosinaddr(gate)>>24))&0xff,
  403                                         (ntohl(satosinaddr(gate)>>16))&0xff,
  404                                         (ntohl(satosinaddr(gate)>>8))&0xff,
  405                                         (ntohl(satosinaddr(gate)))&0xff);
  406                                         
  407                                 senderr(EINVAL);
  408                 }
  409 }
  410 #endif  
  411                 error = rtrequest(RTM_ADD, dst, gate, netmask,
  412                                         rtm->rtm_flags, &saved_nrt);
  413                 if (error == 0 && saved_nrt) {
  414 #ifdef __APPLE__
  415                     /* 
  416                      * If the route request specified an interface with
  417                      * IFA and/or IFP, we set the requested interface on
  418                      * the route with rt_setif.  It would be much better
  419                      * to do this inside rtrequest, but that would
  420                      * require passing the desired interface, in some
  421                      * form, to rtrequest.  Since rtrequest is called in
  422                      * so many places (roughly 40 in our source), adding
  423                      * a parameter is to much for us to swallow; this is
  424                      * something for the FreeBSD developers to tackle.
  425                      * Instead, we let rtrequest compute whatever
  426                      * interface it wants, then come in behind it and
  427                      * stick in the interface that we really want.  This
  428                      * works reasonably well except when rtrequest can't
  429                      * figure out what interface to use (with
  430                      * ifa_withroute) and returns ENETUNREACH.  Ideally
  431                      * it shouldn't matter if rtrequest can't figure out
  432                      * the interface if we're going to explicitly set it
  433                      * ourselves anyway.  But practically we can't
  434                      * recover here because rtrequest will not do any of
  435                      * the work necessary to add the route if it can't
  436                      * find an interface.  As long as there is a default
  437                      * route that leads to some interface, rtrequest will
  438                      * find an interface, so this problem should be
  439                      * rarely encountered.
  440                      * dwiggins@bbn.com
  441                      */
  442 
  443                         rt_setif(saved_nrt, ifpaddr, ifaaddr, gate);
  444 #endif
  445                         rt_setmetrics(rtm->rtm_inits,
  446                                 &rtm->rtm_rmx, &saved_nrt->rt_rmx);
  447                         saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
  448                         saved_nrt->rt_rmx.rmx_locks |=
  449                                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
  450                         rtunref(saved_nrt);
  451                         saved_nrt->rt_genmask = genmask;
  452                 }
  453                 break;
  454 
  455         case RTM_DELETE:
  456                 error = rtrequest(RTM_DELETE, dst, gate, netmask,
  457                                 rtm->rtm_flags, &saved_nrt);
  458                 if (error == 0) {
  459                         if ((rt = saved_nrt))
  460                                 rtref(rt);
  461                         goto report;
  462                 }
  463                 break;
  464 
  465         case RTM_GET:
  466         case RTM_CHANGE:
  467         case RTM_LOCK:
  468                 if ((rnh = rt_tables[dst->sa_family]) == 0) {
  469                         senderr(EAFNOSUPPORT);
  470                 } else if ((rt = (struct rtentry *)
  471                                 rnh->rnh_lookup(dst, netmask, rnh)) != NULL)
  472                         rtref(rt);
  473                 else
  474                         senderr(ESRCH);
  475                 switch(rtm->rtm_type) {
  476 
  477                 case RTM_GET:
  478                 report:
  479                         dst = rt_key(rt);
  480                         gate = rt->rt_gateway;
  481                         netmask = rt_mask(rt);
  482                         genmask = rt->rt_genmask;
  483                         if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
  484                                 ifp = rt->rt_ifp;
  485                                 if (ifp) {
  486                                         ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
  487                                         ifaaddr = rt->rt_ifa->ifa_addr;
  488                                         rtm->rtm_index = ifp->if_index;
  489                                 } else {
  490                                         ifpaddr = 0;
  491                                         ifaaddr = 0;
  492                             }
  493                         }
  494                         len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
  495                                 (struct walkarg *)0);
  496                         if (len > rtm->rtm_msglen) {
  497                                 struct rt_msghdr *new_rtm;
  498                                 R_Malloc(new_rtm, struct rt_msghdr *, len);
  499                                 if (new_rtm == 0)
  500                                         senderr(ENOBUFS);
  501                                 Bcopy(rtm, new_rtm, rtm->rtm_msglen);
  502                                 Free(rtm); rtm = new_rtm;
  503                         }
  504                         (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
  505                                 (struct walkarg *)0);
  506                         rtm->rtm_flags = rt->rt_flags;
  507                         rtm->rtm_rmx = rt->rt_rmx;
  508                         rtm->rtm_addrs = info.rti_addrs;
  509                         break;
  510 
  511                 case RTM_CHANGE:
  512                         if (gate && (error = rt_setgate(rt, rt_key(rt), gate)))
  513                                 senderr(error);
  514 
  515                         /*
  516                          * If they tried to change things but didn't specify
  517                          * the required gateway, then just use the old one.
  518                          * This can happen if the user tries to change the
  519                          * flags on the default route without changing the
  520                          * default gateway.  Changing flags still doesn't work.
  521                          */
  522                         if ((rt->rt_flags & RTF_GATEWAY) && !gate)
  523                                 gate = rt->rt_gateway;
  524 
  525 #ifdef __APPLE__
  526                         /*
  527                          * On Darwin, we call rt_setif which contains the
  528                          * equivalent to the code found at this very spot
  529                          * in BSD.
  530                          */
  531                         rt_setif(rt, ifpaddr, ifaaddr, gate);
  532 #endif
  533 
  534                         rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
  535                                         &rt->rt_rmx);
  536 #ifndef __APPLE__
  537                         /* rt_setif, called above does this for us on darwin */
  538                         if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
  539                                rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
  540 #endif
  541                         if (genmask)
  542                                 rt->rt_genmask = genmask;
  543                         /*
  544                          * Fall into
  545                          */
  546                 case RTM_LOCK:
  547                         rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
  548                         rt->rt_rmx.rmx_locks |=
  549                                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
  550                         break;
  551                 }
  552                 break;
  553 
  554         default:
  555                 senderr(EOPNOTSUPP);
  556         }
  557 
  558 flush:
  559         if (rtm) {
  560                 if (error)
  561                         rtm->rtm_errno = error;
  562                 else
  563                         rtm->rtm_flags |= RTF_DONE;
  564         }
  565         if (rt)
  566                 rtfree(rt);
  567     {
  568         register struct rawcb *rp = 0;
  569         /*
  570          * Check to see if we don't want our own messages.
  571          */
  572         if ((so->so_options & SO_USELOOPBACK) == 0) {
  573                 if (route_cb.any_count <= 1) {
  574                         if (rtm)
  575                                 Free(rtm);
  576                         m_freem(m);
  577                         return (error);
  578                 }
  579                 /* There is another listener, so construct message */
  580                 rp = sotorawcb(so);
  581         }
  582         if (rtm) {
  583                 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
  584                 if (m->m_pkthdr.len < rtm->rtm_msglen) {
  585                         m_freem(m);
  586                         m = NULL;
  587                 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
  588                         m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
  589                 Free(rtm);
  590         }
  591         if (sendonlytoself && m) {
  592                 if (sbappendaddr(&so->so_rcv, &route_src, m, (struct mbuf*)0) == 0) {
  593                         m_freem(m);
  594                         error = ENOBUFS;
  595                 } else {
  596                         sorwakeup(so);
  597                 }
  598         } else {
  599                 if (rp)
  600                         rp->rcb_proto.sp_family = 0; /* Avoid us */
  601                 if (dst)
  602                         route_proto.sp_protocol = dst->sa_family;
  603                 if (m)
  604                         raw_input(m, &route_proto, &route_src, &route_dst);
  605                 if (rp)
  606                         rp->rcb_proto.sp_family = PF_ROUTE;
  607                 }
  608         }
  609         return (error);
  610 }
  611 
  612 static void
  613 rt_setmetrics(which, in, out)
  614         u_long which;
  615         register struct rt_metrics *in, *out;
  616 {
  617 #define metric(f, e) if (which & (f)) out->e = in->e;
  618         metric(RTV_RPIPE, rmx_recvpipe);
  619         metric(RTV_SPIPE, rmx_sendpipe);
  620         metric(RTV_SSTHRESH, rmx_ssthresh);
  621         metric(RTV_RTT, rmx_rtt);
  622         metric(RTV_RTTVAR, rmx_rttvar);
  623         metric(RTV_HOPCOUNT, rmx_hopcount);
  624         metric(RTV_MTU, rmx_mtu);
  625         metric(RTV_EXPIRE, rmx_expire);
  626 #undef metric
  627 }
  628 
  629 /*
  630  * Set route's interface given ifpaddr, ifaaddr, and gateway.
  631  */
  632 static void
  633 rt_setif(rt, Ifpaddr, Ifaaddr, Gate)
  634         struct rtentry *rt;
  635         struct sockaddr *Ifpaddr, *Ifaaddr, *Gate;
  636 {
  637         struct ifaddr *ifa = 0;
  638         struct ifnet  *ifp = 0;
  639 
  640         /* new gateway could require new ifaddr, ifp;
  641            flags may also be different; ifp may be specified
  642            by ll sockaddr when protocol address is ambiguous */
  643         if (Ifpaddr && (ifa = ifa_ifwithnet(Ifpaddr)) &&
  644             (ifp = ifa->ifa_ifp) && (Ifaaddr || Gate))
  645                 ifa = ifaof_ifpforaddr(Ifaaddr ? Ifaaddr : Gate,
  646                                         ifp);
  647         else if (Ifpaddr && (ifp = if_withname(Ifpaddr)) ) {
  648                 ifa = Gate ? ifaof_ifpforaddr(Gate, ifp) :
  649                                 TAILQ_FIRST(&ifp->if_addrhead);
  650         }
  651         else if ((Ifaaddr && (ifa = ifa_ifwithaddr(Ifaaddr))) ||
  652                  (Gate && (ifa = ifa_ifwithroute(rt->rt_flags,
  653                                         rt_key(rt), Gate))))
  654                 ifp = ifa->ifa_ifp;
  655         if (ifa) {
  656                 register struct ifaddr *oifa = rt->rt_ifa;
  657                 if (oifa != ifa) {
  658                     if (oifa && oifa->ifa_rtrequest)
  659                         oifa->ifa_rtrequest(RTM_DELETE,
  660                                                 rt, Gate);
  661                         rtsetifa(rt, ifa);
  662                     rt->rt_ifp = ifp;
  663                     rt->rt_rmx.rmx_mtu = ifp->if_mtu;
  664                     if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
  665                                 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);
  666                 } else
  667                         goto call_ifareq;
  668                 return;
  669         }
  670       call_ifareq:
  671         /* XXX: to reset gateway to correct value, at RTM_CHANGE */
  672         if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
  673                 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);
  674 }
  675 
  676 
  677 #define ROUNDUP(a) \
  678         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  679 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
  680 
  681 
  682 /*
  683  * Extract the addresses of the passed sockaddrs.
  684  * Do a little sanity checking so as to avoid bad memory references.
  685  * This data is derived straight from userland.
  686  */
  687 static int
  688 rt_xaddrs(cp, cplim, rtinfo)
  689         register caddr_t cp, cplim;
  690         register struct rt_addrinfo *rtinfo;
  691 {
  692         register struct sockaddr *sa;
  693         register int i;
  694 
  695         bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
  696         for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
  697                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
  698                         continue;
  699                 sa = (struct sockaddr *)cp;
  700                 /*
  701                  * It won't fit.
  702                  */
  703                 if ( (cp + sa->sa_len) > cplim ) {
  704                         return (EINVAL);
  705                 }
  706 
  707                 /*
  708                  * there are no more.. quit now
  709                  * If there are more bits, they are in error.
  710                  * I've seen this. route(1) can evidently generate these. 
  711                  * This causes kernel to core dump.
  712                  * for compatibility, If we see this, point to a safe address.
  713                  */
  714                 if (sa->sa_len == 0) {
  715                         rtinfo->rti_info[i] = &sa_zero;
  716                         return (0); /* should be EINVAL but for compat */
  717                 }
  718 
  719                 /* accept it */
  720                 rtinfo->rti_info[i] = sa;
  721                 ADVANCE(cp, sa);
  722         }
  723         return (0);
  724 }
  725 
  726 static struct mbuf *
  727 rt_msg1(type, rtinfo)
  728         int type;
  729         register struct rt_addrinfo *rtinfo;
  730 {
  731         register struct rt_msghdr *rtm;
  732         register struct mbuf *m;
  733         register int i;
  734         register struct sockaddr *sa;
  735         int len, dlen;
  736 
  737         switch (type) {
  738 
  739         case RTM_DELADDR:
  740         case RTM_NEWADDR:
  741                 len = sizeof(struct ifa_msghdr);
  742                 break;
  743 
  744         case RTM_DELMADDR:
  745         case RTM_NEWMADDR:
  746                 len = sizeof(struct ifma_msghdr);
  747                 break;
  748 
  749         case RTM_IFINFO:
  750                 len = sizeof(struct if_msghdr);
  751                 break;
  752 
  753         default:
  754                 len = sizeof(struct rt_msghdr);
  755         }
  756         if (len > MCLBYTES)
  757                 panic("rt_msg1");
  758         m = m_gethdr(M_DONTWAIT, MT_DATA);
  759         if (m && len > MHLEN) {
  760                 MCLGET(m, M_DONTWAIT);
  761                 if ((m->m_flags & M_EXT) == 0) {
  762                         m_free(m);
  763                         m = NULL;
  764                 }
  765         }
  766         if (m == 0)
  767                 return (m);
  768         m->m_pkthdr.len = m->m_len = len;
  769         m->m_pkthdr.rcvif = 0;
  770         rtm = mtod(m, struct rt_msghdr *);
  771         bzero((caddr_t)rtm, len);
  772         for (i = 0; i < RTAX_MAX; i++) {
  773                 if ((sa = rtinfo->rti_info[i]) == NULL)
  774                         continue;
  775                 rtinfo->rti_addrs |= (1 << i);
  776                 dlen = ROUNDUP(sa->sa_len);
  777                 m_copyback(m, len, dlen, (caddr_t)sa);
  778                 len += dlen;
  779         }
  780         if (m->m_pkthdr.len != len) {
  781                 m_freem(m);
  782                 return (NULL);
  783         }
  784         rtm->rtm_msglen = len;
  785         rtm->rtm_version = RTM_VERSION;
  786         rtm->rtm_type = type;
  787         return (m);
  788 }
  789 
  790 static int
  791 rt_msg2(type, rtinfo, cp, w)
  792         int type;
  793         register struct rt_addrinfo *rtinfo;
  794         caddr_t cp;
  795         struct walkarg *w;
  796 {
  797         register int i;
  798         int len, dlen, second_time = 0;
  799         caddr_t cp0;
  800 
  801         rtinfo->rti_addrs = 0;
  802 again:
  803         switch (type) {
  804 
  805         case RTM_DELADDR:
  806         case RTM_NEWADDR:
  807                 len = sizeof(struct ifa_msghdr);
  808                 break;
  809 
  810         case RTM_IFINFO:
  811                 len = sizeof(struct if_msghdr);
  812                 break;
  813 
  814         default:
  815                 len = sizeof(struct rt_msghdr);
  816         }
  817         cp0 = cp;
  818         if (cp0)
  819                 cp += len;
  820         for (i = 0; i < RTAX_MAX; i++) {
  821                 register struct sockaddr *sa;
  822 
  823                 if ((sa = rtinfo->rti_info[i]) == 0)
  824                         continue;
  825                 rtinfo->rti_addrs |= (1 << i);
  826                 dlen = ROUNDUP(sa->sa_len);
  827                 if (cp) {
  828                         bcopy((caddr_t)sa, cp, (unsigned)dlen);
  829                         cp += dlen;
  830                 }
  831                 len += dlen;
  832         }
  833         if (cp == 0 && w != NULL && !second_time) {
  834                 register struct walkarg *rw = w;
  835 
  836                 if (rw->w_req) {
  837                         if (rw->w_tmemsize < len) {
  838                                 if (rw->w_tmem)
  839                                         FREE(rw->w_tmem, M_RTABLE);
  840                                 rw->w_tmem = (caddr_t)
  841                                         _MALLOC(len, M_RTABLE, M_WAITOK); /*###LD0412 was NOWAIT */
  842                                 if (rw->w_tmem)
  843                                         rw->w_tmemsize = len;
  844                         }
  845                         if (rw->w_tmem) {
  846                                 cp = rw->w_tmem;
  847                                 second_time = 1;
  848                                 goto again;
  849                         }
  850                 }
  851         }
  852         if (cp) {
  853                 register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
  854 
  855                 rtm->rtm_version = RTM_VERSION;
  856                 rtm->rtm_type = type;
  857                 rtm->rtm_msglen = len;
  858         }
  859         return (len);
  860 }
  861 
  862 /*
  863  * This routine is called to generate a message from the routing
  864  * socket indicating that a redirect has occured, a routing lookup
  865  * has failed, or that a protocol has detected timeouts to a particular
  866  * destination.
  867  */
  868 void
  869 rt_missmsg(type, rtinfo, flags, error)
  870         int type, flags, error;
  871         register struct rt_addrinfo *rtinfo;
  872 {
  873         register struct rt_msghdr *rtm;
  874         register struct mbuf *m;
  875         struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
  876 
  877         if (route_cb.any_count == 0)
  878                 return;
  879         m = rt_msg1(type, rtinfo);
  880         if (m == 0)
  881                 return;
  882         rtm = mtod(m, struct rt_msghdr *);
  883         rtm->rtm_flags = RTF_DONE | flags;
  884         rtm->rtm_errno = error;
  885         rtm->rtm_addrs = rtinfo->rti_addrs;
  886         route_proto.sp_protocol = sa ? sa->sa_family : 0;
  887         raw_input(m, &route_proto, &route_src, &route_dst);
  888 }
  889 
  890 /*
  891  * This routine is called to generate a message from the routing
  892  * socket indicating that the status of a network interface has changed.
  893  */
  894 void
  895 rt_ifmsg(ifp)
  896         register struct ifnet *ifp;
  897 {
  898         register struct if_msghdr *ifm;
  899         struct mbuf *m;
  900         struct rt_addrinfo info;
  901 
  902         if (route_cb.any_count == 0)
  903                 return;
  904         bzero((caddr_t)&info, sizeof(info));
  905         m = rt_msg1(RTM_IFINFO, &info);
  906         if (m == 0)
  907                 return;
  908         ifm = mtod(m, struct if_msghdr *);
  909         ifm->ifm_index = ifp->if_index;
  910         ifm->ifm_flags = (u_short)ifp->if_flags;
  911         ifm->ifm_data = ifp->if_data;
  912         ifm->ifm_addrs = 0;
  913         route_proto.sp_protocol = 0;
  914         raw_input(m, &route_proto, &route_src, &route_dst);
  915 }
  916 
  917 /*
  918  * This is called to generate messages from the routing socket
  919  * indicating a network interface has had addresses associated with it.
  920  * if we ever reverse the logic and replace messages TO the routing
  921  * socket indicate a request to configure interfaces, then it will
  922  * be unnecessary as the routing socket will automatically generate
  923  * copies of it.
  924  */
  925 void
  926 rt_newaddrmsg(cmd, ifa, error, rt)
  927         int cmd, error;
  928         register struct ifaddr *ifa;
  929         register struct rtentry *rt;
  930 {
  931         struct rt_addrinfo info;
  932         struct sockaddr *sa = 0;
  933         int pass;
  934         struct mbuf *m = 0;
  935         struct ifnet *ifp = ifa->ifa_ifp;
  936 
  937         if (route_cb.any_count == 0)
  938                 return;
  939         for (pass = 1; pass < 3; pass++) {
  940                 bzero((caddr_t)&info, sizeof(info));
  941                 if ((cmd == RTM_ADD && pass == 1) ||
  942                     (cmd == RTM_DELETE && pass == 2)) {
  943                         register struct ifa_msghdr *ifam;
  944                         int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
  945 
  946                         ifaaddr = sa = ifa->ifa_addr;
  947                         ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
  948                         netmask = ifa->ifa_netmask;
  949                         brdaddr = ifa->ifa_dstaddr;
  950                         if ((m = rt_msg1(ncmd, &info)) == NULL)
  951                                 continue;
  952                         ifam = mtod(m, struct ifa_msghdr *);
  953                         ifam->ifam_index = ifp->if_index;
  954                         ifam->ifam_metric = ifa->ifa_metric;
  955                         ifam->ifam_flags = ifa->ifa_flags;
  956                         ifam->ifam_addrs = info.rti_addrs;
  957                 }
  958                 if ((cmd == RTM_ADD && pass == 2) ||
  959                     (cmd == RTM_DELETE && pass == 1)) {
  960                         register struct rt_msghdr *rtm;
  961 
  962                         if (rt == 0)
  963                                 continue;
  964                         netmask = rt_mask(rt);
  965                         dst = sa = rt_key(rt);
  966                         gate = rt->rt_gateway;
  967                         if ((m = rt_msg1(cmd, &info)) == NULL)
  968                                 continue;
  969                         rtm = mtod(m, struct rt_msghdr *);
  970                         rtm->rtm_index = ifp->if_index;
  971                         rtm->rtm_flags |= rt->rt_flags;
  972                         rtm->rtm_errno = error;
  973                         rtm->rtm_addrs = info.rti_addrs;
  974                 }
  975                 route_proto.sp_protocol = sa ? sa->sa_family : 0;
  976                 raw_input(m, &route_proto, &route_src, &route_dst);
  977         }
  978 }
  979 
  980 /*
  981  * This is the analogue to the rt_newaddrmsg which performs the same
  982  * function but for multicast group memberhips.  This is easier since
  983  * there is no route state to worry about.
  984  */
  985 void
  986 rt_newmaddrmsg(cmd, ifma)
  987         int cmd;
  988         struct ifmultiaddr *ifma;
  989 {
  990         struct rt_addrinfo info;
  991         struct mbuf *m = 0;
  992         struct ifnet *ifp = ifma->ifma_ifp;
  993         struct ifma_msghdr *ifmam;
  994 
  995         if (route_cb.any_count == 0)
  996                 return;
  997 
  998         bzero((caddr_t)&info, sizeof(info));
  999         ifaaddr = ifma->ifma_addr;
 1000         if (ifp && ifp->if_addrhead.tqh_first)
 1001                 ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
 1002         else
 1003                 ifpaddr = NULL;
 1004         /*
 1005          * If a link-layer address is present, present it as a ``gateway''
 1006          * (similarly to how ARP entries, e.g., are presented).
 1007          */
 1008         gate = ifma->ifma_lladdr;
 1009         if ((m = rt_msg1(cmd, &info)) == NULL)
 1010                 return;
 1011         ifmam = mtod(m, struct ifma_msghdr *);
 1012         ifmam->ifmam_index = ifp->if_index;
 1013         ifmam->ifmam_addrs = info.rti_addrs;
 1014         route_proto.sp_protocol = ifma->ifma_addr->sa_family;
 1015         raw_input(m, &route_proto, &route_src, &route_dst);
 1016 }
 1017 
 1018 /*
 1019  * This is used in dumping the kernel table via sysctl().
 1020  */
 1021 int
 1022 sysctl_dumpentry(rn, vw)
 1023         struct radix_node *rn;
 1024         void *vw;
 1025 {
 1026         register struct walkarg *w = vw;
 1027         register struct rtentry *rt = (struct rtentry *)rn;
 1028         int error = 0, size;
 1029         struct rt_addrinfo info;
 1030 
 1031         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
 1032                 return 0;
 1033         bzero((caddr_t)&info, sizeof(info));
 1034         dst = rt_key(rt);
 1035         gate = rt->rt_gateway;
 1036         netmask = rt_mask(rt);
 1037         genmask = rt->rt_genmask;
 1038         size = rt_msg2(RTM_GET, &info, 0, w);
 1039         if (w->w_req && w->w_tmem) {
 1040                 register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
 1041 
 1042                 rtm->rtm_flags = rt->rt_flags;
 1043                 rtm->rtm_use = rt->rt_use;
 1044                 rtm->rtm_rmx = rt->rt_rmx;
 1045                 rtm->rtm_index = rt->rt_ifp->if_index;
 1046                 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
 1047                 rtm->rtm_addrs = info.rti_addrs;
 1048                 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
 1049                 return (error);
 1050         }
 1051         return (error);
 1052 }
 1053 
 1054 int
 1055 sysctl_iflist(af, w)
 1056         int     af;
 1057         register struct walkarg *w;
 1058 {
 1059         register struct ifnet *ifp;
 1060         register struct ifaddr *ifa;
 1061         struct  rt_addrinfo info;
 1062         int     len, error = 0;
 1063 
 1064         bzero((caddr_t)&info, sizeof(info));
 1065         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
 1066                 if (w->w_arg && w->w_arg != ifp->if_index)
 1067                         continue;
 1068                 ifa = ifp->if_addrhead.tqh_first;
 1069                 ifpaddr = ifa->ifa_addr;
 1070                 len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
 1071                 ifpaddr = 0;
 1072                 if (w->w_req && w->w_tmem) {
 1073                         register struct if_msghdr *ifm;
 1074 
 1075                         ifm = (struct if_msghdr *)w->w_tmem;
 1076                         ifm->ifm_index = ifp->if_index;
 1077                         ifm->ifm_flags = (u_short)ifp->if_flags;
 1078                         ifm->ifm_data = ifp->if_data;
 1079                         ifm->ifm_addrs = info.rti_addrs;
 1080                         error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
 1081                         if (error)
 1082                                 return (error);
 1083                 }
 1084                 while ((ifa = ifa->ifa_link.tqe_next) != 0) {
 1085                         if (af && af != ifa->ifa_addr->sa_family)
 1086                                 continue;
 1087 #ifndef __APPLE__
 1088                         if (curproc->p_prison && prison_if(curproc, ifa->ifa_addr))
 1089                                 continue;
 1090 #endif
 1091                         ifaaddr = ifa->ifa_addr;
 1092                         netmask = ifa->ifa_netmask;
 1093                         brdaddr = ifa->ifa_dstaddr;
 1094                         len = rt_msg2(RTM_NEWADDR, &info, 0, w);
 1095                         if (w->w_req && w->w_tmem) {
 1096                                 register struct ifa_msghdr *ifam;
 1097 
 1098                                 ifam = (struct ifa_msghdr *)w->w_tmem;
 1099                                 ifam->ifam_index = ifa->ifa_ifp->if_index;
 1100                                 ifam->ifam_flags = ifa->ifa_flags;
 1101                                 ifam->ifam_metric = ifa->ifa_metric;
 1102                                 ifam->ifam_addrs = info.rti_addrs;
 1103                                 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
 1104                                 if (error)
 1105                                         return (error);
 1106                         }
 1107                 }
 1108                 ifaaddr = netmask = brdaddr = 0;
 1109         }
 1110         return (0);
 1111 }
 1112 
 1113 static int
 1114 sysctl_rtsock SYSCTL_HANDLER_ARGS
 1115 {
 1116         int     *name = (int *)arg1;
 1117         u_int   namelen = arg2;
 1118         register struct radix_node_head *rnh;
 1119         int     i, s, error = EINVAL;
 1120         u_char  af;
 1121         struct  walkarg w;
 1122 
 1123         name ++;
 1124         namelen--;
 1125         if (req->newptr)
 1126                 return (EPERM);
 1127         if (namelen != 3)
 1128                 return (EINVAL);
 1129         af = name[0];
 1130         Bzero(&w, sizeof(w));
 1131         w.w_op = name[1];
 1132         w.w_arg = name[2];
 1133         w.w_req = req;
 1134 
 1135         s = splnet();
 1136         switch (w.w_op) {
 1137 
 1138         case NET_RT_DUMP:
 1139         case NET_RT_FLAGS:
 1140                 for (i = 1; i <= AF_MAX; i++)
 1141                         if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
 1142                             (error = rnh->rnh_walktree(rnh,
 1143                                                         sysctl_dumpentry, &w)))
 1144                                 break;
 1145                 break;
 1146 
 1147         case NET_RT_IFLIST:
 1148                 error = sysctl_iflist(af, &w);
 1149         }
 1150         splx(s);
 1151         if (w.w_tmem)
 1152                 FREE(w.w_tmem, M_RTABLE);
 1153         return (error);
 1154 }
 1155 
 1156 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
 1157 
 1158 /*
 1159  * Definitions of protocols supported in the ROUTE domain.
 1160  */
 1161 
 1162 struct domain routedomain;              /* or at least forward */
 1163 
 1164 static struct protosw routesw[] = {
 1165 { SOCK_RAW,     &routedomain,   0,              PR_ATOMIC|PR_ADDR,
 1166   0,            route_output,   raw_ctlinput,   0,
 1167   0,
 1168   raw_init,     0,              0,              0,
 1169   0, &route_usrreqs, 0, 0
 1170 }
 1171 };
 1172 
 1173 struct domain routedomain =
 1174     { PF_ROUTE, "route", route_init, 0, 0,
 1175       routesw};
 1176 
 1177 DOMAIN_SET(route);
 1178 

Cache object: db8289701eb48c0555ace2e1ce7c000c


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