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


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

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

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

    1 /*
    2  * Copyright (c) 1988, 1991, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Berkeley and its contributors.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)rtsock.c    8.5 (Berkeley) 11/2/94
   34  * $FreeBSD: src/sys/net/rtsock.c,v 1.20.2.8 1999/09/05 08:18:02 peter Exp $
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/queue.h>
   39 #include <sys/systm.h>
   40 #include <sys/kernel.h>
   41 #include <sys/sysctl.h>
   42 #include <sys/proc.h>
   43 #include <sys/mbuf.h>
   44 #include <sys/socket.h>
   45 #include <sys/socketvar.h>
   46 #include <sys/domain.h>
   47 #include <sys/protosw.h>
   48 
   49 #include <net/if.h>
   50 #include <net/route.h>
   51 #include <net/raw_cb.h>
   52 
   53 static struct   sockaddr route_dst = { 2, PF_ROUTE, };
   54 static struct   sockaddr route_src = { 2, PF_ROUTE, };
   55 static struct   sockaddr sa_zero   = { sizeof(sa_zero), AF_INET, };
   56 static struct   sockproto route_proto = { PF_ROUTE, };
   57 
   58 struct walkarg {
   59         int     w_tmemsize;
   60         int     w_op, w_arg;
   61         caddr_t w_tmem;
   62         struct sysctl_req *w_req;
   63 };
   64 
   65 static struct mbuf *
   66                 rt_msg1 __P((int, struct rt_addrinfo *));
   67 static int      rt_msg2 __P((int,
   68                     struct rt_addrinfo *, caddr_t, struct walkarg *));
   69 static int      rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
   70 static int      sysctl_dumpentry __P((struct radix_node *rn, void *vw));
   71 static int      sysctl_iflist __P((int af, struct walkarg *w));
   72 static int       route_output __P((struct mbuf *, struct socket *));
   73 static int       route_usrreq __P((struct socket *,
   74             int, struct mbuf *, struct mbuf *, struct mbuf *));
   75 static void      rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *));
   76 
   77 /* Sleazy use of local variables throughout file, warning!!!! */
   78 #define dst     info.rti_info[RTAX_DST]
   79 #define gate    info.rti_info[RTAX_GATEWAY]
   80 #define netmask info.rti_info[RTAX_NETMASK]
   81 #define genmask info.rti_info[RTAX_GENMASK]
   82 #define ifpaddr info.rti_info[RTAX_IFP]
   83 #define ifaaddr info.rti_info[RTAX_IFA]
   84 #define brdaddr info.rti_info[RTAX_BRD]
   85 
   86 /*ARGSUSED*/
   87 static int
   88 route_usrreq(so, req, m, nam, control)
   89         register struct socket *so;
   90         int req;
   91         struct mbuf *m, *nam, *control;
   92 {
   93         register int error = 0;
   94         register struct rawcb *rp = sotorawcb(so);
   95         int s;
   96 
   97         if (req == PRU_ATTACH) {
   98                 MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
   99                 if (rp)
  100                         bzero((caddr_t)rp, sizeof(*rp));
  101                 s = splnet();
  102                 so->so_pcb = (caddr_t)rp;
  103         } else
  104                 s = splnet();
  105         if (req == PRU_DETACH && rp) {
  106                 int af = rp->rcb_proto.sp_protocol;
  107                 if (af == AF_INET)
  108                         route_cb.ip_count--;
  109                 else if (af == AF_IPX)
  110                         route_cb.ipx_count--;
  111                 else if (af == AF_NS)
  112                         route_cb.ns_count--;
  113                 else if (af == AF_ISO)
  114                         route_cb.iso_count--;
  115                 route_cb.any_count--;
  116         }
  117         error = raw_usrreq(so, req, m, nam, control);
  118         rp = sotorawcb(so);
  119         if (req == PRU_ATTACH && rp) {
  120                 int af = rp->rcb_proto.sp_protocol;
  121                 if (error) {
  122                         free((caddr_t)rp, M_PCB);
  123                         splx(s);
  124                         return (error);
  125                 }
  126                 if (af == AF_INET)
  127                         route_cb.ip_count++;
  128                 else if (af == AF_IPX)
  129                         route_cb.ipx_count++;
  130                 else if (af == AF_NS)
  131                         route_cb.ns_count++;
  132                 else if (af == AF_ISO)
  133                         route_cb.iso_count++;
  134                 rp->rcb_faddr = &route_src;
  135                 route_cb.any_count++;
  136                 soisconnected(so);
  137                 so->so_options |= SO_USELOOPBACK;
  138         }
  139         splx(s);
  140         return (error);
  141 }
  142 
  143 /*ARGSUSED*/
  144 static int
  145 route_output(m, so)
  146         register struct mbuf *m;
  147         struct socket *so;
  148 {
  149         register struct rt_msghdr *rtm = 0;
  150         register struct rtentry *rt = 0;
  151         struct rtentry *saved_nrt = 0;
  152         struct radix_node_head *rnh;
  153         struct rt_addrinfo info;
  154         int len, error = 0;
  155         struct ifnet *ifp = 0;
  156         struct ifaddr *ifa = 0;
  157 
  158 #define senderr(e) { error = e; goto flush;}
  159         if (m == 0 || ((m->m_len < sizeof(long)) &&
  160                        (m = m_pullup(m, sizeof(long))) == 0))
  161                 return (ENOBUFS);
  162         if ((m->m_flags & M_PKTHDR) == 0)
  163                 panic("route_output");
  164         len = m->m_pkthdr.len;
  165         if (len < sizeof(*rtm) ||
  166             len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
  167                 dst = 0;
  168                 senderr(EINVAL);
  169         }
  170         R_Malloc(rtm, struct rt_msghdr *, len);
  171         if (rtm == 0) {
  172                 dst = 0;
  173                 senderr(ENOBUFS);
  174         }
  175         m_copydata(m, 0, len, (caddr_t)rtm);
  176         if (rtm->rtm_version != RTM_VERSION) {
  177                 dst = 0;
  178                 senderr(EPROTONOSUPPORT);
  179         }
  180         rtm->rtm_pid = curproc->p_pid;
  181         info.rti_addrs = rtm->rtm_addrs;
  182         if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
  183                 dst = 0;
  184                 senderr(EINVAL);
  185         }
  186         if (dst == 0 || (dst->sa_family >= AF_MAX)
  187             || (gate != 0 && (gate->sa_family >= AF_MAX)))
  188                 senderr(EINVAL);
  189         if (genmask) {
  190                 struct radix_node *t;
  191                 t = rn_addmask((caddr_t)genmask, 0, 1);
  192                 if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
  193                         genmask = (struct sockaddr *)(t->rn_key);
  194                 else
  195                         senderr(ENOBUFS);
  196         }
  197         switch (rtm->rtm_type) {
  198 
  199         case RTM_ADD:
  200                 if (gate == 0)
  201                         senderr(EINVAL);
  202                 error = rtrequest(RTM_ADD, dst, gate, netmask,
  203                                         rtm->rtm_flags, &saved_nrt);
  204                 if (error == 0 && saved_nrt) {
  205                         rt_setmetrics(rtm->rtm_inits,
  206                                 &rtm->rtm_rmx, &saved_nrt->rt_rmx);
  207                         saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
  208                         saved_nrt->rt_rmx.rmx_locks |=
  209                                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
  210                         saved_nrt->rt_refcnt--;
  211                         saved_nrt->rt_genmask = genmask;
  212                 }
  213                 break;
  214 
  215         case RTM_DELETE:
  216                 error = rtrequest(RTM_DELETE, dst, gate, netmask,
  217                                 rtm->rtm_flags, &saved_nrt);
  218                 if (error == 0) {
  219                         if ((rt = saved_nrt))
  220                                 rt->rt_refcnt++;
  221                         goto report;
  222                 }
  223                 break;
  224 
  225         case RTM_GET:
  226         case RTM_CHANGE:
  227         case RTM_LOCK:
  228                 if ((rnh = rt_tables[dst->sa_family]) == 0) {
  229                         senderr(EAFNOSUPPORT);
  230                 } else if (rt = (struct rtentry *)
  231                                 rnh->rnh_lookup(dst, netmask, rnh))
  232                         rt->rt_refcnt++;
  233                 else
  234                         senderr(ESRCH);
  235                 switch(rtm->rtm_type) {
  236 
  237                 case RTM_GET:
  238                 report:
  239                         dst = rt_key(rt);
  240                         gate = rt->rt_gateway;
  241                         netmask = rt_mask(rt);
  242                         genmask = rt->rt_genmask;
  243                         if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
  244                                 ifp = rt->rt_ifp;
  245                                 if (ifp) {
  246                                         ifpaddr = ifp->if_addrlist->ifa_addr;
  247                                         ifaaddr = rt->rt_ifa->ifa_addr;
  248                                         rtm->rtm_index = ifp->if_index;
  249                                 } else {
  250                                         ifpaddr = 0;
  251                                         ifaaddr = 0;
  252                             }
  253                         }
  254                         len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
  255                                 (struct walkarg *)0);
  256                         if (len > rtm->rtm_msglen) {
  257                                 struct rt_msghdr *new_rtm;
  258                                 R_Malloc(new_rtm, struct rt_msghdr *, len);
  259                                 if (new_rtm == 0)
  260                                         senderr(ENOBUFS);
  261                                 Bcopy(rtm, new_rtm, rtm->rtm_msglen);
  262                                 Free(rtm); rtm = new_rtm;
  263                         }
  264                         (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
  265                                 (struct walkarg *)0);
  266                         rtm->rtm_flags = rt->rt_flags;
  267                         rtm->rtm_rmx = rt->rt_rmx;
  268                         rtm->rtm_addrs = info.rti_addrs;
  269                         break;
  270 
  271                 case RTM_CHANGE:
  272                         if (gate && (error = rt_setgate(rt, rt_key(rt), gate)))
  273                                 senderr(error);
  274 
  275                         /*
  276                          * If they tried to change things but didn't specify
  277                          * the required gateway, then just use the old one.
  278                          * This can happen if the user tries to change the
  279                          * flags on the default route without changing the
  280                          * default gateway.  Changing flags still doesn't work.
  281                          */
  282                         if ((rt->rt_flags & RTF_GATEWAY) && !gate)
  283                                 gate = rt->rt_gateway;
  284 
  285                         /* new gateway could require new ifaddr, ifp;
  286                            flags may also be different; ifp may be specified
  287                            by ll sockaddr when protocol address is ambiguous */
  288                         if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
  289                             (ifp = ifa->ifa_ifp) && (ifaaddr || gate))
  290                                 ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
  291                                                         ifp);
  292                         else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
  293                                  (gate && (ifa = ifa_ifwithroute(rt->rt_flags,
  294                                                         rt_key(rt), gate))))
  295                                 ifp = ifa->ifa_ifp;
  296                         if (ifa) {
  297                                 register struct ifaddr *oifa = rt->rt_ifa;
  298                                 if (oifa != ifa) {
  299                                     if (oifa && oifa->ifa_rtrequest)
  300                                         oifa->ifa_rtrequest(RTM_DELETE,
  301                                                                 rt, gate);
  302                                     IFAFREE(rt->rt_ifa);
  303                                     rt->rt_ifa = ifa;
  304                                     ifa->ifa_refcnt++;
  305                                     rt->rt_ifp = ifp;
  306                                 }
  307                         }
  308                         rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
  309                                         &rt->rt_rmx);
  310                         if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
  311                                rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
  312                         if (genmask)
  313                                 rt->rt_genmask = genmask;
  314                         /*
  315                          * Fall into
  316                          */
  317                 case RTM_LOCK:
  318                         rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
  319                         rt->rt_rmx.rmx_locks |=
  320                                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
  321                         break;
  322                 }
  323                 break;
  324 
  325         default:
  326                 senderr(EOPNOTSUPP);
  327         }
  328 
  329 flush:
  330         if (rtm) {
  331                 if (error)
  332                         rtm->rtm_errno = error;
  333                 else
  334                         rtm->rtm_flags |= RTF_DONE;
  335         }
  336         if (rt)
  337                 rtfree(rt);
  338     {
  339         register struct rawcb *rp = 0;
  340         /*
  341          * Check to see if we don't want our own messages.
  342          */
  343         if ((so->so_options & SO_USELOOPBACK) == 0) {
  344                 if (route_cb.any_count <= 1) {
  345                         if (rtm)
  346                                 Free(rtm);
  347                         m_freem(m);
  348                         return (error);
  349                 }
  350                 /* There is another listener, so construct message */
  351                 rp = sotorawcb(so);
  352         }
  353         if (rtm) {
  354                 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
  355                 Free(rtm);
  356         }
  357         if (rp)
  358                 rp->rcb_proto.sp_family = 0; /* Avoid us */
  359         if (dst)
  360                 route_proto.sp_protocol = dst->sa_family;
  361         raw_input(m, &route_proto, &route_src, &route_dst);
  362         if (rp)
  363                 rp->rcb_proto.sp_family = PF_ROUTE;
  364     }
  365         return (error);
  366 }
  367 
  368 static void
  369 rt_setmetrics(which, in, out)
  370         u_long which;
  371         register struct rt_metrics *in, *out;
  372 {
  373 #define metric(f, e) if (which & (f)) out->e = in->e;
  374         metric(RTV_RPIPE, rmx_recvpipe);
  375         metric(RTV_SPIPE, rmx_sendpipe);
  376         metric(RTV_SSTHRESH, rmx_ssthresh);
  377         metric(RTV_RTT, rmx_rtt);
  378         metric(RTV_RTTVAR, rmx_rttvar);
  379         metric(RTV_HOPCOUNT, rmx_hopcount);
  380         metric(RTV_MTU, rmx_mtu);
  381         metric(RTV_EXPIRE, rmx_expire);
  382 #undef metric
  383 }
  384 
  385 #define ROUNDUP(a) \
  386         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  387 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
  388 
  389 
  390 /*
  391  * Extract the addresses of the passed sockaddrs.
  392  * Do a little sanity checking so as to avoid bad memory references.
  393  * This data is derived straight from userland.
  394  */
  395 static int
  396 rt_xaddrs(cp, cplim, rtinfo)
  397         register caddr_t cp, cplim;
  398         register struct rt_addrinfo *rtinfo;
  399 {
  400         register struct sockaddr *sa;
  401         register int i;
  402 
  403         bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
  404         for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
  405                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
  406                         continue;
  407                 sa = (struct sockaddr *)cp;
  408                 /*
  409                  * It won't fit.
  410                  */
  411                 if ( (cp + sa->sa_len) > cplim ) {
  412                         return (EINVAL);
  413                 }
  414 
  415                 /*
  416                  * there are no more.. quit now
  417                  * If there are more bits, they are in error.
  418                  * I've seen this. route(1) can evidently generate these. 
  419                  * This causes kernel to core dump.
  420                  * for compatibility, If we see this, point to a safe address.
  421                  */
  422                 if (sa->sa_len == 0) {
  423                         rtinfo->rti_info[i] = &sa_zero;
  424                         return (0); /* should be EINVAL but for compat */
  425                 }
  426 
  427                 /* accept it */
  428                 rtinfo->rti_info[i] = sa;
  429                 ADVANCE(cp, sa);
  430         }
  431         return (0);
  432 }
  433 
  434 static struct mbuf *
  435 rt_msg1(type, rtinfo)
  436         int type;
  437         register struct rt_addrinfo *rtinfo;
  438 {
  439         register struct rt_msghdr *rtm;
  440         register struct mbuf *m;
  441         register int i;
  442         register struct sockaddr *sa;
  443         int len, dlen;
  444 
  445         m = m_gethdr(M_DONTWAIT, MT_DATA);
  446         if (m == 0)
  447                 return (m);
  448         switch (type) {
  449 
  450         case RTM_DELADDR:
  451         case RTM_NEWADDR:
  452                 len = sizeof(struct ifa_msghdr);
  453                 break;
  454 
  455         case RTM_IFINFO:
  456                 len = sizeof(struct if_msghdr);
  457                 break;
  458 
  459         default:
  460                 len = sizeof(struct rt_msghdr);
  461         }
  462         if (len > MHLEN)
  463                 panic("rt_msg1");
  464         m->m_pkthdr.len = m->m_len = len;
  465         m->m_pkthdr.rcvif = 0;
  466         rtm = mtod(m, struct rt_msghdr *);
  467         bzero((caddr_t)rtm, len);
  468         for (i = 0; i < RTAX_MAX; i++) {
  469                 if ((sa = rtinfo->rti_info[i]) == NULL)
  470                         continue;
  471                 rtinfo->rti_addrs |= (1 << i);
  472                 dlen = ROUNDUP(sa->sa_len);
  473                 m_copyback(m, len, dlen, (caddr_t)sa);
  474                 len += dlen;
  475         }
  476         if (m->m_pkthdr.len != len) {
  477                 m_freem(m);
  478                 return (NULL);
  479         }
  480         rtm->rtm_msglen = len;
  481         rtm->rtm_version = RTM_VERSION;
  482         rtm->rtm_type = type;
  483         return (m);
  484 }
  485 
  486 static int
  487 rt_msg2(type, rtinfo, cp, w)
  488         int type;
  489         register struct rt_addrinfo *rtinfo;
  490         caddr_t cp;
  491         struct walkarg *w;
  492 {
  493         register int i;
  494         int len, dlen, second_time = 0;
  495         caddr_t cp0;
  496 
  497         rtinfo->rti_addrs = 0;
  498 again:
  499         switch (type) {
  500 
  501         case RTM_DELADDR:
  502         case RTM_NEWADDR:
  503                 len = sizeof(struct ifa_msghdr);
  504                 break;
  505 
  506         case RTM_IFINFO:
  507                 len = sizeof(struct if_msghdr);
  508                 break;
  509 
  510         default:
  511                 len = sizeof(struct rt_msghdr);
  512         }
  513         cp0 = cp;
  514         if (cp0)
  515                 cp += len;
  516         for (i = 0; i < RTAX_MAX; i++) {
  517                 register struct sockaddr *sa;
  518 
  519                 if ((sa = rtinfo->rti_info[i]) == 0)
  520                         continue;
  521                 rtinfo->rti_addrs |= (1 << i);
  522                 dlen = ROUNDUP(sa->sa_len);
  523                 if (cp) {
  524                         bcopy((caddr_t)sa, cp, (unsigned)dlen);
  525                         cp += dlen;
  526                 }
  527                 len += dlen;
  528         }
  529         if (cp == 0 && w != NULL && !second_time) {
  530                 register struct walkarg *rw = w;
  531 
  532                 if (rw->w_req) {
  533                         if (rw->w_tmemsize < len) {
  534                                 if (rw->w_tmem)
  535                                         free(rw->w_tmem, M_RTABLE);
  536                                 rw->w_tmem = (caddr_t)
  537                                         malloc(len, M_RTABLE, M_NOWAIT);
  538                                 if (rw->w_tmem)
  539                                         rw->w_tmemsize = len;
  540                         }
  541                         if (rw->w_tmem) {
  542                                 cp = rw->w_tmem;
  543                                 second_time = 1;
  544                                 goto again;
  545                         }
  546                 }
  547         }
  548         if (cp) {
  549                 register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
  550 
  551                 rtm->rtm_version = RTM_VERSION;
  552                 rtm->rtm_type = type;
  553                 rtm->rtm_msglen = len;
  554         }
  555         return (len);
  556 }
  557 
  558 /*
  559  * This routine is called to generate a message from the routing
  560  * socket indicating that a redirect has occured, a routing lookup
  561  * has failed, or that a protocol has detected timeouts to a particular
  562  * destination.
  563  */
  564 void
  565 rt_missmsg(type, rtinfo, flags, error)
  566         int type, flags, error;
  567         register struct rt_addrinfo *rtinfo;
  568 {
  569         register struct rt_msghdr *rtm;
  570         register struct mbuf *m;
  571         struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
  572 
  573         if (route_cb.any_count == 0)
  574                 return;
  575         m = rt_msg1(type, rtinfo);
  576         if (m == 0)
  577                 return;
  578         rtm = mtod(m, struct rt_msghdr *);
  579         rtm->rtm_flags = RTF_DONE | flags;
  580         rtm->rtm_errno = error;
  581         rtm->rtm_addrs = rtinfo->rti_addrs;
  582         route_proto.sp_protocol = sa ? sa->sa_family : 0;
  583         raw_input(m, &route_proto, &route_src, &route_dst);
  584 }
  585 
  586 /*
  587  * This routine is called to generate a message from the routing
  588  * socket indicating that the status of a network interface has changed.
  589  */
  590 void
  591 rt_ifmsg(ifp)
  592         register struct ifnet *ifp;
  593 {
  594         register struct if_msghdr *ifm;
  595         struct mbuf *m;
  596         struct rt_addrinfo info;
  597 
  598         if (route_cb.any_count == 0)
  599                 return;
  600         bzero((caddr_t)&info, sizeof(info));
  601         m = rt_msg1(RTM_IFINFO, &info);
  602         if (m == 0)
  603                 return;
  604         ifm = mtod(m, struct if_msghdr *);
  605         ifm->ifm_index = ifp->if_index;
  606         ifm->ifm_flags = (u_short)ifp->if_flags;
  607         ifm->ifm_data = ifp->if_data;
  608         ifm->ifm_addrs = 0;
  609         route_proto.sp_protocol = 0;
  610         raw_input(m, &route_proto, &route_src, &route_dst);
  611 }
  612 
  613 /*
  614  * This is called to generate messages from the routing socket
  615  * indicating a network interface has had addresses associated with it.
  616  * if we ever reverse the logic and replace messages TO the routing
  617  * socket indicate a request to configure interfaces, then it will
  618  * be unnecessary as the routing socket will automatically generate
  619  * copies of it.
  620  */
  621 void
  622 rt_newaddrmsg(cmd, ifa, error, rt)
  623         int cmd, error;
  624         register struct ifaddr *ifa;
  625         register struct rtentry *rt;
  626 {
  627         struct rt_addrinfo info;
  628         struct sockaddr *sa = 0;
  629         int pass;
  630         struct mbuf *m = 0;
  631         struct ifnet *ifp = ifa->ifa_ifp;
  632 
  633         if (route_cb.any_count == 0)
  634                 return;
  635         for (pass = 1; pass < 3; pass++) {
  636                 bzero((caddr_t)&info, sizeof(info));
  637                 if ((cmd == RTM_ADD && pass == 1) ||
  638                     (cmd == RTM_DELETE && pass == 2)) {
  639                         register struct ifa_msghdr *ifam;
  640                         int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
  641 
  642                         ifaaddr = sa = ifa->ifa_addr;
  643                         ifpaddr = ifp->if_addrlist->ifa_addr;
  644                         netmask = ifa->ifa_netmask;
  645                         brdaddr = ifa->ifa_dstaddr;
  646                         if ((m = rt_msg1(ncmd, &info)) == NULL)
  647                                 continue;
  648                         ifam = mtod(m, struct ifa_msghdr *);
  649                         ifam->ifam_index = ifp->if_index;
  650                         ifam->ifam_metric = ifa->ifa_metric;
  651                         ifam->ifam_flags = ifa->ifa_flags;
  652                         ifam->ifam_addrs = info.rti_addrs;
  653                 }
  654                 if ((cmd == RTM_ADD && pass == 2) ||
  655                     (cmd == RTM_DELETE && pass == 1)) {
  656                         register struct rt_msghdr *rtm;
  657 
  658                         if (rt == 0)
  659                                 continue;
  660                         netmask = rt_mask(rt);
  661                         dst = sa = rt_key(rt);
  662                         gate = rt->rt_gateway;
  663                         if ((m = rt_msg1(cmd, &info)) == NULL)
  664                                 continue;
  665                         rtm = mtod(m, struct rt_msghdr *);
  666                         rtm->rtm_index = ifp->if_index;
  667                         rtm->rtm_flags |= rt->rt_flags;
  668                         rtm->rtm_errno = error;
  669                         rtm->rtm_addrs = info.rti_addrs;
  670                 }
  671                 route_proto.sp_protocol = sa ? sa->sa_family : 0;
  672                 raw_input(m, &route_proto, &route_src, &route_dst);
  673         }
  674 }
  675 
  676 
  677 /*
  678  * This is used in dumping the kernel table via sysctl().
  679  */
  680 int
  681 sysctl_dumpentry(rn, vw)
  682         struct radix_node *rn;
  683         void *vw;
  684 {
  685         register struct walkarg *w = vw;
  686         register struct rtentry *rt = (struct rtentry *)rn;
  687         int error = 0, size;
  688         struct rt_addrinfo info;
  689 
  690         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
  691                 return 0;
  692         bzero((caddr_t)&info, sizeof(info));
  693         dst = rt_key(rt);
  694         gate = rt->rt_gateway;
  695         netmask = rt_mask(rt);
  696         genmask = rt->rt_genmask;
  697         size = rt_msg2(RTM_GET, &info, 0, w);
  698         if (w->w_req && w->w_tmem) {
  699                 register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
  700 
  701                 rtm->rtm_flags = rt->rt_flags;
  702                 rtm->rtm_use = rt->rt_use;
  703                 rtm->rtm_rmx = rt->rt_rmx;
  704                 rtm->rtm_index = rt->rt_ifp->if_index;
  705                 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
  706                 rtm->rtm_addrs = info.rti_addrs;
  707                 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
  708                 return (error);
  709         }
  710         return (error);
  711 }
  712 
  713 int
  714 sysctl_iflist(af, w)
  715         int     af;
  716         register struct walkarg *w;
  717 {
  718         register struct ifnet *ifp;
  719         register struct ifaddr *ifa;
  720         struct  rt_addrinfo info;
  721         int     len, error = 0;
  722 
  723         bzero((caddr_t)&info, sizeof(info));
  724         for (ifp = ifnet; ifp; ifp = ifp->if_next) {
  725                 if (w->w_arg && w->w_arg != ifp->if_index)
  726                         continue;
  727                 ifa = ifp->if_addrlist;
  728                 ifpaddr = ifa->ifa_addr;
  729                 len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
  730                 ifpaddr = 0;
  731                 if (w->w_req && w->w_tmem) {
  732                         register struct if_msghdr *ifm;
  733 
  734                         ifm = (struct if_msghdr *)w->w_tmem;
  735                         ifm->ifm_index = ifp->if_index;
  736                         ifm->ifm_flags = (u_short)ifp->if_flags;
  737                         ifm->ifm_data = ifp->if_data;
  738                         ifm->ifm_addrs = info.rti_addrs;
  739                         error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
  740                         if (error)
  741                                 return (error);
  742                 }
  743                 while ((ifa = ifa->ifa_next) != 0) {
  744                         if (af && af != ifa->ifa_addr->sa_family)
  745                                 continue;
  746                         ifaaddr = ifa->ifa_addr;
  747                         netmask = ifa->ifa_netmask;
  748                         brdaddr = ifa->ifa_dstaddr;
  749                         len = rt_msg2(RTM_NEWADDR, &info, 0, w);
  750                         if (w->w_req && w->w_tmem) {
  751                                 register struct ifa_msghdr *ifam;
  752 
  753                                 ifam = (struct ifa_msghdr *)w->w_tmem;
  754                                 ifam->ifam_index = ifa->ifa_ifp->if_index;
  755                                 ifam->ifam_flags = ifa->ifa_flags;
  756                                 ifam->ifam_metric = ifa->ifa_metric;
  757                                 ifam->ifam_addrs = info.rti_addrs;
  758                                 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
  759                                 if (error)
  760                                         return (error);
  761                         }
  762                 }
  763                 ifaaddr = netmask = brdaddr = 0;
  764         }
  765         return (0);
  766 }
  767 
  768 static int
  769 sysctl_rtsock SYSCTL_HANDLER_ARGS
  770 {
  771         int     *name = (int *)arg1;
  772         u_int   namelen = arg2;
  773         register struct radix_node_head *rnh;
  774         int     i, s, error = EINVAL;
  775         u_char  af;
  776         struct  walkarg w;
  777 
  778         name ++;
  779         namelen--;
  780         if (req->newptr)
  781                 return (EPERM);
  782         if (namelen != 3)
  783                 return (EINVAL);
  784         af = name[0];
  785         Bzero(&w, sizeof(w));
  786         w.w_op = name[1];
  787         w.w_arg = name[2];
  788         w.w_req = req;
  789 
  790         s = splnet();
  791         switch (w.w_op) {
  792 
  793         case NET_RT_DUMP:
  794         case NET_RT_FLAGS:
  795                 for (i = 1; i <= AF_MAX; i++)
  796                         if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
  797                             (error = rnh->rnh_walktree(rnh,
  798                                                         sysctl_dumpentry, &w)))
  799                                 break;
  800                 break;
  801 
  802         case NET_RT_IFLIST:
  803                 error = sysctl_iflist(af, &w);
  804         }
  805         splx(s);
  806         if (w.w_tmem)
  807                 free(w.w_tmem, M_RTABLE);
  808         return (error);
  809 }
  810 
  811 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock,"");
  812 
  813 /*
  814  * Definitions of protocols supported in the ROUTE domain.
  815  */
  816 
  817 extern struct domain routedomain;               /* or at least forward */
  818 
  819 static struct protosw routesw[] = {
  820 { SOCK_RAW,     &routedomain,   0,              PR_ATOMIC|PR_ADDR,
  821   0,            route_output,   raw_ctlinput,   0,
  822   route_usrreq,
  823   raw_init
  824 }
  825 };
  826 
  827 static struct domain routedomain =
  828     { PF_ROUTE, "route", route_init, 0, 0,
  829       routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
  830 
  831 DOMAIN_SET(route);

Cache object: 77af54385245651b79266822cddba30e


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