home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / os / bsdss4.tz / bsdss4 / bsdss / server / net / rtsock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-22  |  18.2 KB  |  694 lines

  1. /* 
  2.  * Mach Operating System
  3.  * Copyright (c) 1992 Carnegie Mellon University
  4.  * All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify and distribute this software and its
  7.  * documentation is hereby granted, provided that both the copyright
  8.  * notice and this permission notice appear in all copies of the
  9.  * software, derivative works or modified versions, and any portions
  10.  * thereof, and that both notices appear in supporting documentation.
  11.  * 
  12.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15.  * 
  16.  * Carnegie Mellon requests users of this software to return to
  17.  * 
  18.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  19.  *  School of Computer Science
  20.  *  Carnegie Mellon University
  21.  *  Pittsburgh PA 15213-3890
  22.  * 
  23.  * any improvements or extensions that they make and grant Carnegie Mellon 
  24.  * the rights to redistribute these changes.
  25.  */
  26. /*
  27.  * HISTORY
  28.  * $Log:    rtsock.c,v $
  29.  * Revision 2.1  92/04/21  17:13:58  rwd
  30.  * BSDSS
  31.  * 
  32.  *
  33.  */
  34.  
  35. /*
  36.  * Copyright (c) 1988, 1991 Regents of the University of California.
  37.  * All rights reserved.
  38.  *
  39.  * Redistribution and use in source and binary forms, with or without
  40.  * modification, are permitted provided that the following conditions
  41.  * are met:
  42.  * 1. Redistributions of source code must retain the above copyright
  43.  *    notice, this list of conditions and the following disclaimer.
  44.  * 2. Redistributions in binary form must reproduce the above copyright
  45.  *    notice, this list of conditions and the following disclaimer in the
  46.  *    documentation and/or other materials provided with the distribution.
  47.  * 3. All advertising materials mentioning features or use of this software
  48.  *    must display the following acknowledgement:
  49.  *    This product includes software developed by the University of
  50.  *    California, Berkeley and its contributors.
  51.  * 4. Neither the name of the University nor the names of its contributors
  52.  *    may be used to endorse or promote products derived from this software
  53.  *    without specific prior written permission.
  54.  *
  55.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  56.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  57.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  58.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  59.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  60.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  61.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  62.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  63.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  64.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  65.  * SUCH DAMAGE.
  66.  *
  67.  *    @(#)rtsock.c    7.18 (Berkeley) 6/27/91
  68.  */
  69.  
  70. #include <sys/param.h>
  71. #include <sys/mbuf.h>
  72. #include <sys/proc.h>
  73. #include <sys/socket.h>
  74. #include <sys/socketvar.h>
  75. #include <sys/domain.h>
  76. #include <sys/protosw.h>
  77. #include <sys/synch.h>
  78.  
  79. #include <net/af.h>
  80. #include <net/if.h>
  81. #include <net/route.h>
  82. #include <net/raw_cb.h>
  83.  
  84. struct sockaddr route_dst = { 2, PF_ROUTE, };
  85. struct sockaddr route_src = { 2, PF_ROUTE, };
  86. struct sockproto route_proto = { PF_ROUTE, };
  87.  
  88. /*ARGSUSED*/
  89. route_usrreq(so, req, m, nam, control)
  90.     register struct socket *so;
  91.     int req;
  92.     struct mbuf *m, *nam, *control;
  93. {
  94.     register int error = 0;
  95.     register struct rawcb *rp = sotorawcb(so);
  96.     int s;
  97.     if (req == PRU_ATTACH) {
  98.         MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
  99.         if (so->so_pcb = (caddr_t)rp)
  100.             bzero(so->so_pcb, sizeof(*rp));
  101.  
  102.     }
  103.     if (req == PRU_DETACH && rp) {
  104.         int af = rp->rcb_proto.sp_protocol;
  105.         if (af == AF_INET)
  106.             route_cb.ip_count--;
  107.         else if (af == AF_NS)
  108.             route_cb.ns_count--;
  109.         else if (af == AF_ISO)
  110.             route_cb.iso_count--;
  111.         route_cb.any_count--;
  112.     }
  113.     s = splnet();
  114.     error = raw_usrreq(so, req, m, nam, control);
  115.     rp = sotorawcb(so);
  116.     if (req == PRU_ATTACH && rp) {
  117.         int af = rp->rcb_proto.sp_protocol;
  118.         if (error) {
  119.             bsd_free((caddr_t)rp, M_PCB);
  120.             splx(s);
  121.             return (error);
  122.         }
  123.         if (af == AF_INET)
  124.             route_cb.ip_count++;
  125.         else if (af == AF_NS)
  126.             route_cb.ns_count++;
  127.         else if (af == AF_ISO)
  128.             route_cb.iso_count++;
  129.         rp->rcb_faddr = &route_src;
  130.         route_cb.any_count++;
  131.         soisconnected(so);
  132.         so->so_options |= SO_USELOOPBACK;
  133.     }
  134.     splx(s);
  135.     return (error);
  136. }
  137. #define ROUNDUP(a) \
  138.     ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  139. #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
  140.  
  141. /*ARGSUSED*/
  142. route_output(m, so)
  143.     register struct mbuf *m;
  144.     struct socket *so;
  145. {
  146.     register struct rt_msghdr *rtm = 0;
  147.     register struct rtentry *rt = 0;
  148.     struct rtentry *saved_nrt = 0;
  149.     struct sockaddr *dst = 0, *gate = 0, *netmask = 0, *genmask = 0;
  150.     struct sockaddr *ifpaddr = 0, *ifaaddr = 0;
  151.     caddr_t cp, lim;
  152.     int len, error = 0;
  153.     struct ifnet *ifp = 0;
  154.     struct ifaddr *ifa = 0;
  155.     struct ifaddr *ifaof_ifpforaddr(), *ifa_ifwithroute();
  156.         struct proc *curproc = (struct proc*)cthread_data(cthread_self());
  157.  
  158. #define senderr(e) { error = e; goto flush;}
  159.     if (m == 0 || m->m_len < sizeof(long))
  160.         return (ENOBUFS);
  161.     if ((m = m_pullup(m, sizeof(long))) == 0)
  162.         return (ENOBUFS);
  163.     if ((m->m_flags & M_PKTHDR) == 0)
  164.         panic("route_output");
  165.     len = m->m_pkthdr.len;
  166.     if (len < sizeof(*rtm) ||
  167.         len != mtod(m, struct rt_msghdr *)->rtm_msglen)
  168.         senderr(EINVAL);
  169.     R_Malloc(rtm, struct rt_msghdr *, len);
  170.     if (rtm == 0)
  171.         senderr(ENOBUFS);
  172.     m_copydata(m, 0, len, (caddr_t)rtm);
  173.     if (rtm->rtm_version != RTM_VERSION)
  174.         senderr(EPROTONOSUPPORT);
  175.     rtm->rtm_pid = curproc->p_pid;
  176.     lim = len + (caddr_t) rtm;
  177.     cp = (caddr_t) (rtm + 1);
  178.     if (rtm->rtm_addrs & RTA_DST) {
  179.         dst = (struct sockaddr *)cp;
  180.         ADVANCE(cp, dst);
  181.     } else
  182.         senderr(EINVAL);
  183.     if ((rtm->rtm_addrs & RTA_GATEWAY) && cp < lim)  {
  184.         gate = (struct sockaddr *)cp;
  185.         ADVANCE(cp, gate);
  186.     }
  187.     if ((rtm->rtm_addrs & RTA_NETMASK) && cp < lim)  {
  188.         netmask = (struct sockaddr *)cp;
  189.         ADVANCE(cp, netmask);
  190.     }
  191.     if ((rtm->rtm_addrs & RTA_GENMASK) && cp < lim)  {
  192.         struct radix_node *t, *rn_addmask();
  193.         genmask = (struct sockaddr *)cp;
  194.         ADVANCE(cp, genmask);
  195.         t = rn_addmask(genmask, 1, 2);
  196.         if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
  197.             genmask = (struct sockaddr *)(t->rn_key);
  198.         else
  199.             senderr(ENOBUFS);
  200.     }
  201.     if ((rtm->rtm_addrs & RTA_IFP) && cp < lim)  {
  202.         ifpaddr = (struct sockaddr *)cp;
  203.         ADVANCE(cp, ifpaddr);
  204.     }
  205.     if ((rtm->rtm_addrs & RTA_IFA) && cp < lim)  {
  206.         ifaaddr = (struct sockaddr *)cp;
  207.     }
  208.     switch (rtm->rtm_type) {
  209.     case RTM_ADD:
  210.         if (gate == 0)
  211.             senderr(EINVAL);
  212.         error = rtrequest(RTM_ADD, dst, gate, netmask,
  213.                     rtm->rtm_flags, &saved_nrt);
  214.         if (error == 0 && saved_nrt) {
  215.             rt_setmetrics(rtm->rtm_inits,
  216.                 &rtm->rtm_rmx, &saved_nrt->rt_rmx);
  217.             saved_nrt->rt_refcnt--;
  218.             saved_nrt->rt_genmask = genmask;
  219.         }
  220.         break;
  221.  
  222.     case RTM_DELETE:
  223.         error = rtrequest(RTM_DELETE, dst, gate, netmask,
  224.                 rtm->rtm_flags, (struct rtentry **)0);
  225.         break;
  226.  
  227.     case RTM_GET:
  228.     case RTM_CHANGE:
  229.     case RTM_LOCK:
  230.         rt = rtalloc1(dst, 0);
  231.         if (rt == 0)
  232.             senderr(ESRCH);
  233.         if (rtm->rtm_type != RTM_GET) {
  234.             if (Bcmp(dst, rt_key(rt), dst->sa_len) != 0)
  235.                 senderr(ESRCH);
  236.             if (rt->rt_nodes->rn_dupedkey &&
  237.                 (netmask == 0 ||
  238.                  Bcmp(netmask, rt_mask(rt), netmask->sa_len)))
  239.                 senderr(ETOOMANYREFS);
  240.         }
  241.         switch(rtm->rtm_type) {
  242.  
  243.         case RTM_GET:
  244.             dst = rt_key(rt); len = sizeof(*rtm);
  245.             ADVANCE(len, dst);
  246.             rtm->rtm_addrs |= RTA_DST;
  247.             if (gate = rt->rt_gateway) {
  248.                 ADVANCE(len, gate);
  249.                 rtm->rtm_addrs |= RTA_GATEWAY;
  250.             } else
  251.                 rtm->rtm_addrs &= ~RTA_GATEWAY;
  252.             if (netmask = rt_mask(rt)) {
  253.                 ADVANCE(len, netmask);
  254.                 rtm->rtm_addrs |= RTA_NETMASK;
  255.             } else
  256.                 rtm->rtm_addrs &= ~RTA_NETMASK;
  257.             if (genmask = rt->rt_genmask) {
  258.                 ADVANCE(len, genmask);
  259.                 rtm->rtm_addrs |= RTA_GENMASK;
  260.             } else
  261.                 rtm->rtm_addrs &= ~RTA_GENMASK;
  262.             if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
  263.                 if (rt->rt_ifp == 0)
  264.                     goto badif;
  265.                 for (ifa = rt->rt_ifp->if_addrlist;
  266.                     ifa && ifa->ifa_addr->sa_family != AF_LINK;
  267.                      ifa = ifa->ifa_next){}
  268.                 if (ifa && rt->rt_ifa) {
  269.                     ifpaddr = ifa->ifa_addr;
  270.                     ADVANCE(len, ifpaddr);
  271.                     ifaaddr = rt->rt_ifa->ifa_addr;
  272.                     ADVANCE(len, ifaaddr);
  273.                     rtm->rtm_addrs |= RTA_IFP | RTA_IFA;
  274.                 } else {
  275.                 badif:    ifpaddr = 0;
  276.                     rtm->rtm_addrs &= ~(RTA_IFP | RTA_IFA);
  277.                 }
  278.             }
  279.             if (len > rtm->rtm_msglen) {
  280.                 struct rt_msghdr *new_rtm;
  281.                 R_Malloc(new_rtm, struct rt_msghdr *, len);
  282.                 if (new_rtm == 0)
  283.                     senderr(ENOBUFS);
  284.                 Bcopy(rtm, new_rtm, rtm->rtm_msglen);
  285.                 Free(rtm); rtm = new_rtm;
  286.             }
  287.             rtm->rtm_msglen = len;
  288.             rtm->rtm_flags = rt->rt_flags;
  289.             rtm->rtm_rmx = rt->rt_rmx;
  290.             cp = (caddr_t) (1 + rtm);
  291.             len = ROUNDUP(dst->sa_len); 
  292.             Bcopy(dst, cp, len); cp += len;
  293.             if (gate) {
  294.                 len = ROUNDUP(gate->sa_len);
  295.                 Bcopy(gate, cp, len); cp += len;
  296.             }
  297.             if (netmask) {
  298.                 len = ROUNDUP(netmask->sa_len);
  299.                 Bcopy(netmask, cp, len); cp += len;
  300.             }
  301.             if (genmask) {
  302.                 len = ROUNDUP(genmask->sa_len);
  303.                 Bcopy(genmask, cp, len); cp += len;
  304.             }
  305.             if (ifpaddr) {
  306.                 len = ROUNDUP(ifpaddr->sa_len);
  307.                 Bcopy(ifpaddr, cp, len); cp += len;
  308.                 len = ROUNDUP(ifaaddr->sa_len);
  309.                 Bcopy(ifaaddr, cp, len); cp += len;
  310.             }
  311.             break;
  312.  
  313.         case RTM_CHANGE:
  314.             if (gate &&
  315.                 (gate->sa_len > (len = rt->rt_gateway->sa_len)))
  316.                 senderr(EDQUOT);
  317.             /* new gateway could require new ifaddr, ifp;
  318.                flags may also be different; ifp may be specified
  319.                by ll sockaddr when protocol address is ambiguous */
  320.             if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
  321.                 (ifp = ifa->ifa_ifp))
  322.                 ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
  323.                             ifp);
  324.             else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
  325.                  (ifa = ifa_ifwithroute(rt->rt_flags,
  326.                             rt_key(rt), gate)))
  327.                 ifp = ifa->ifa_ifp;
  328.             if (ifa) {
  329.                 register struct ifaddr *oifa = rt->rt_ifa;
  330.                 if (oifa != ifa) {
  331.                     if (oifa && oifa->ifa_rtrequest)
  332.                     oifa->ifa_rtrequest(RTM_DELETE,
  333.                                 rt, gate);
  334.                     rt->rt_ifa = ifa;
  335.                     rt->rt_ifp = ifp;
  336.                 }
  337.             }
  338.             if (gate)
  339.                 Bcopy(gate, rt->rt_gateway, len);
  340.             rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
  341.                     &rt->rt_rmx);
  342.             if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
  343.                    rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
  344.             if (genmask)
  345.                 rt->rt_genmask = genmask;
  346.             /*
  347.              * Fall into
  348.              */
  349.         case RTM_LOCK:
  350.             rt->rt_rmx.rmx_locks |=
  351.                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
  352.             rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
  353.             break;
  354.         }
  355.         goto cleanup;
  356.  
  357.     default:
  358.         senderr(EOPNOTSUPP);
  359.     }
  360.  
  361. flush:
  362.     if (rtm) {
  363.         if (error)
  364.             rtm->rtm_errno = error;
  365.         else 
  366.             rtm->rtm_flags |= RTF_DONE;
  367.     }
  368. cleanup:
  369.     if (rt)
  370.         rtfree(rt);
  371.     {
  372.     register struct rawcb *rp = 0;
  373.     /*
  374.      * Check to see if we don't want our own messages.
  375.      */
  376.     if ((so->so_options & SO_USELOOPBACK) == 0) {
  377.         if (route_cb.any_count <= 1) {
  378.             if (rtm)
  379.                 Free(rtm);
  380.             m_freem(m);
  381.             return (error);
  382.         }
  383.         /* There is another listener, so construct message */
  384.         rp = sotorawcb(so);
  385.     }
  386.     if (rtm) {
  387.         m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
  388.         Free(rtm);
  389.     }
  390.     if (rp)
  391.         rp->rcb_proto.sp_family = 0; /* Avoid us */
  392.     if (dst)
  393.         route_proto.sp_protocol = dst->sa_family;
  394.     raw_input(m, &route_proto, &route_src, &route_dst);
  395.     if (rp)
  396.         rp->rcb_proto.sp_family = PF_ROUTE;
  397.     }
  398.     return (error);
  399. }
  400.  
  401. rt_setmetrics(which, in, out)
  402.     u_long which;
  403.     register struct rt_metrics *in, *out;
  404. {
  405. #define metric(f, e) if (which & (f)) out->e = in->e;
  406.     metric(RTV_RPIPE, rmx_recvpipe);
  407.     metric(RTV_SPIPE, rmx_sendpipe);
  408.     metric(RTV_SSTHRESH, rmx_ssthresh);
  409.     metric(RTV_RTT, rmx_rtt);
  410.     metric(RTV_RTTVAR, rmx_rttvar);
  411.     metric(RTV_HOPCOUNT, rmx_hopcount);
  412.     metric(RTV_MTU, rmx_mtu);
  413.     metric(RTV_EXPIRE, rmx_expire);
  414. #undef metric
  415. }
  416.  
  417. /*
  418.  * Copy data from a buffer back into the indicated mbuf chain,
  419.  * starting "off" bytes from the beginning, extending the mbuf
  420.  * chain if necessary.
  421.  */
  422. m_copyback(m0, off, len, cp)
  423.     struct    mbuf *m0;
  424.     register int off;
  425.     register int len;
  426.     caddr_t cp;
  427.  
  428. {
  429.     register int mlen;
  430.     register struct mbuf *m = m0, *n;
  431.     int totlen = 0;
  432.  
  433.     if (m0 == 0)
  434.         return;
  435.     while (off > (mlen = m->m_len)) {
  436.         off -= mlen;
  437.         totlen += mlen;
  438.         if (m->m_next == 0) {
  439.             n = m_getclr(M_DONTWAIT, m->m_type);
  440.             if (n == 0)
  441.                 goto out;
  442.             n->m_len = min(MLEN, len + off);
  443.             m->m_next = n;
  444.         }
  445.         m = m->m_next;
  446.     }
  447.     while (len > 0) {
  448.         mlen = min (m->m_len - off, len);
  449.         bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
  450.         cp += mlen;
  451.         len -= mlen;
  452.         mlen += off;
  453.         off = 0;
  454.         totlen += mlen;
  455.         if (len == 0)
  456.             break;
  457.         if (m->m_next == 0) {
  458.             n = m_get(M_DONTWAIT, m->m_type);
  459.             if (n == 0)
  460.                 break;
  461.             n->m_len = min(MLEN, len);
  462.             m->m_next = n;
  463.         }
  464.         m = m->m_next;
  465.     }
  466. out:    if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
  467.         m->m_pkthdr.len = totlen;
  468. }
  469.  
  470. /* 
  471.  * The miss message and losing message are very similar.
  472.  */
  473.  
  474. rt_missmsg(type, dst, gate, mask, src, flags, error)
  475. register struct sockaddr *dst;
  476. struct sockaddr *gate, *mask, *src;
  477. {
  478.     register struct rt_msghdr *rtm;
  479.     register struct mbuf *m;
  480.     int dlen = ROUNDUP(dst->sa_len);
  481.     int len = dlen + sizeof(*rtm);
  482.         struct proc *curproc = (struct proc*)cthread_data(cthread_self());
  483.  
  484.     if (route_cb.any_count == 0)
  485.         return;
  486.     m = m_gethdr(M_DONTWAIT, MT_DATA);
  487.     if (m == 0)
  488.         return;
  489.     m->m_pkthdr.len = m->m_len = min(len, MHLEN);
  490.     m->m_pkthdr.rcvif = 0;
  491.     rtm = mtod(m, struct rt_msghdr *);
  492.     bzero((caddr_t)rtm, sizeof(*rtm)); /*XXX assumes sizeof(*rtm) < MHLEN*/
  493.     rtm->rtm_flags = RTF_DONE | flags;
  494.     rtm->rtm_msglen = len;
  495.     rtm->rtm_version = RTM_VERSION;
  496.     rtm->rtm_type = type;
  497.     rtm->rtm_addrs = RTA_DST;
  498.     if (type == RTM_OLDADD || type == RTM_OLDDEL) {
  499.         rtm->rtm_pid = curproc->p_pid;
  500.     }
  501.     m_copyback(m, sizeof (*rtm), dlen, (caddr_t)dst);
  502.     if (gate) {
  503.         dlen = ROUNDUP(gate->sa_len);
  504.         m_copyback(m, len ,  dlen, (caddr_t)gate);
  505.         len += dlen;
  506.         rtm->rtm_addrs |= RTA_GATEWAY;
  507.     }
  508.     if (mask) {
  509.         dlen = ROUNDUP(mask->sa_len);
  510.         m_copyback(m, len ,  dlen, (caddr_t)mask);
  511.         len += dlen;
  512.         rtm->rtm_addrs |= RTA_NETMASK;
  513.     }
  514.     if (src) {
  515.         dlen = ROUNDUP(src->sa_len);
  516.         m_copyback(m, len ,  dlen, (caddr_t)src);
  517.         len += dlen;
  518.         rtm->rtm_addrs |= RTA_AUTHOR;
  519.     }
  520.     if (m->m_pkthdr.len != len) {
  521.         m_freem(m);
  522.         return;
  523.     }
  524.     rtm->rtm_errno = error;
  525.     rtm->rtm_msglen = len;
  526.     route_proto.sp_protocol = dst->sa_family;
  527.     raw_input(m, &route_proto, &route_src, &route_dst);
  528. }
  529.  
  530. #include <sys/kinfo.h>
  531. struct walkarg {
  532.     int    w_op, w_arg;
  533.     int    w_given, w_needed;
  534.     caddr_t    w_where;
  535.     struct    {
  536.         struct rt_msghdr m_rtm;
  537.         char    m_sabuf[128];
  538.     } w_m;
  539. #define w_rtm w_m.m_rtm
  540. };
  541. /*
  542.  * This is used in dumping the kernel table via getkinfo().
  543.  */
  544. rt_dumpentry(rn, w)
  545.     struct radix_node *rn;
  546.     register struct walkarg *w;
  547. {
  548.     register struct sockaddr *sa;
  549.     int n, error;
  550.  
  551.     for (; rn; rn = rn->rn_dupedkey) {
  552.     int count = 0, size = sizeof(w->w_rtm);
  553.     register struct rtentry *rt = (struct rtentry *)rn;
  554.  
  555.     if (rn->rn_flags & RNF_ROOT)
  556.         continue;
  557.     if (w->w_op == KINFO_RT_FLAGS && !(rt->rt_flags & w->w_arg))
  558.         continue;
  559. #define next(a, l) {size += (l); w->w_rtm.rtm_addrs |= (a); }
  560.     w->w_rtm.rtm_addrs = 0;
  561.     if (sa = rt_key(rt))
  562.         next(RTA_DST, ROUNDUP(sa->sa_len));
  563.     if (sa = rt->rt_gateway)
  564.         next(RTA_GATEWAY, ROUNDUP(sa->sa_len));
  565.     if (sa = rt_mask(rt))
  566.         next(RTA_NETMASK, ROUNDUP(sa->sa_len));
  567.     if (sa = rt->rt_genmask)
  568.         next(RTA_GENMASK, ROUNDUP(sa->sa_len));
  569.     w->w_needed += size;
  570.     if (w->w_where == NULL || w->w_needed > 0)
  571.         continue;
  572.     w->w_rtm.rtm_msglen = size;
  573.     w->w_rtm.rtm_flags = rt->rt_flags;
  574.     w->w_rtm.rtm_use = rt->rt_use;
  575.     w->w_rtm.rtm_rmx = rt->rt_rmx;
  576.     w->w_rtm.rtm_index = rt->rt_ifp->if_index;
  577. #undef next
  578. #define next(l) {n = (l); Bcopy(sa, cp, n); cp += n;}
  579.     if (size <= sizeof(w->w_m)) {
  580.         register caddr_t cp = (caddr_t)(w->w_m.m_sabuf);
  581.         if (sa = rt_key(rt))
  582.             next(ROUNDUP(sa->sa_len));
  583.         if (sa = rt->rt_gateway)
  584.             next(ROUNDUP(sa->sa_len));
  585.         if (sa = rt_mask(rt))
  586.             next(ROUNDUP(sa->sa_len));
  587.         if (sa = rt->rt_genmask)
  588.             next(ROUNDUP(sa->sa_len));
  589. #undef next
  590. #define next(s, l) {n = (l); \
  591.     if (error = copyout((caddr_t)(s), w->w_where, n)) return (error); \
  592.     w->w_where += n;}
  593.  
  594.         next(&w->w_m, size); /* Copy rtmsg and sockaddrs back */
  595.         continue;
  596.     }
  597.     next(&w->w_rtm, sizeof(w->w_rtm));
  598.     if (sa = rt_key(rt))
  599.         next(sa, ROUNDUP(sa->sa_len));
  600.     if (sa = rt->rt_gateway)
  601.         next(sa, ROUNDUP(sa->sa_len));
  602.     if (sa = rt_mask(rt))
  603.         next(sa, ROUNDUP(sa->sa_len));
  604.     if (sa = rt->rt_genmask)
  605.         next(sa, ROUNDUP(sa->sa_len));
  606.     }
  607.     return (0);
  608. #undef next
  609. }
  610.  
  611. kinfo_rtable(op, where, given, arg, needed)
  612.     int    op, arg;
  613.     caddr_t    where;
  614.     int    *given, *needed;
  615. {
  616.     register struct radix_node_head *rnh;
  617.     int    s, error = 0;
  618.     u_char  af = ki_af(op);
  619.     struct    walkarg w;
  620.  
  621.     op &= 0xffff;
  622.     if (op != KINFO_RT_DUMP && op != KINFO_RT_FLAGS)
  623.         return (EINVAL);
  624.  
  625.     Bzero(&w, sizeof(w));
  626.     if ((w.w_where = where) && given)
  627.         w.w_given = *given;
  628.     w.w_needed = 0 - w.w_given;
  629.     w.w_arg = arg;
  630.     w.w_op = op;
  631.     w.w_rtm.rtm_version = RTM_VERSION;
  632.     w.w_rtm.rtm_type = RTM_GET;
  633.  
  634.     s = splnet();
  635.     for (rnh = radix_node_head; rnh; rnh = rnh->rnh_next) {
  636.         if (rnh->rnh_af == 0)
  637.             continue;
  638.         if (af && af != rnh->rnh_af)
  639.             continue;
  640.         error = rt_walk(rnh->rnh_treetop, rt_dumpentry, &w);
  641.         if (error)
  642.             break;
  643.     }
  644.     w.w_needed += w.w_given;
  645.     if (where && given)
  646.         *given = w.w_where - where;
  647.     else
  648.         w.w_needed = (11 * w.w_needed) / 10;
  649.     *needed = w.w_needed;
  650.     splx(s);
  651.     return (error);
  652. }
  653.  
  654. rt_walk(rn, f, w)
  655.     register struct radix_node *rn;
  656.     register int (*f)();
  657.     struct walkarg *w;
  658. {
  659.     int error;
  660.     for (;;) {
  661.         while (rn->rn_b >= 0)
  662.             rn = rn->rn_l;    /* First time through node, go left */
  663.         if (error = (*f)(rn, w))
  664.             return (error);    /* Process Leaf */
  665.         while (rn->rn_p->rn_r == rn) {    /* if coming back from right */
  666.             rn = rn->rn_p;        /* go back up */
  667.             if (rn->rn_flags & RNF_ROOT)
  668.                 return 0;
  669.         }
  670.         rn = rn->rn_p->rn_r;        /* otherwise, go right*/
  671.     }
  672. }
  673.  
  674. /*
  675.  * Definitions of protocols supported in the ROUTE domain.
  676.  */
  677.  
  678. int    raw_init(),raw_usrreq(),raw_input(),raw_ctlinput();
  679. extern    struct domain routedomain;        /* or at least forward */
  680.  
  681. struct protosw routesw[] = {
  682. { SOCK_RAW,    &routedomain,    0,        PR_ATOMIC|PR_ADDR,
  683.   raw_input,    route_output,    raw_ctlinput,    0,
  684.   route_usrreq,
  685.   raw_init,    0,        0,        0,
  686. }
  687. };
  688.  
  689. int    unp_externalize(), unp_dispose();
  690.  
  691. struct domain routedomain =
  692.     { PF_ROUTE, "route", 0, 0, 0,
  693.       routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
  694.