rtsock.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:44k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* rtsock.c - routines for routing sockets */
  2. /* Copyright 1990 - 2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1988, 1991, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  * This product includes software developed by the University of
  19.  * California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  * @(#)rtsock.c 8.6 (Berkeley) 2/11/95
  37.  */
  38. /*
  39. modification history
  40. --------------------
  41. 01g,12oct01,rae  merge from truestack ver 01u, base o1f (SPR #70185 ROUTER_STACK)
  42. 01f,26aug98,n_s  added return val check for MALLOC in route_usrreq. spr #22238.
  43. 01e,04dec97,vin  moved back m_copyback and m_copydata from uipc_mbuf.c as
  44.  these are only used in rt_sock. Ifdefed m_copyback and
  45.                  m_copydata in uipc_mbuf.c these need some rework so that
  46.                  they can be tied up efficiently with the new buffering scheme.
  47. 01d,01jul97,vin  added rtSockInit, removed route_init from routedomain, it is
  48.  called from netLibInit. Added route message hooks for
  49.                  scalability.
  50. 01c,05dec96,vin  changed malloc(..) to MALLOC(..) to use only network buffers,
  51.  changed free(..) to FREE(..).
  52. 01b,22nov96,vin  added cluster support replaced m_get(..) with mBufClGet(..).
  53.  m_gethdr(..) with mHdrClGet(..), moved m_copyback(..) to 
  54.  uipc_mbuf.c
  55. 01a,03mar96,vin  created from BSD4.4lite2.
  56. */
  57. #include "net/systm.h"
  58. #include "net/mbuf.h"
  59. #include "sys/socket.h"
  60. #include "net/socketvar.h"
  61. #include "net/domain.h"
  62. #include "net/protosw.h"
  63. #include "net/unixLib.h"
  64. #include "net/if.h"
  65. #include "net/route.h"
  66. #include "net/raw_cb.h"
  67. #include "netinet/in.h"
  68. #include "routeEnhLib.h"
  69. #ifdef WV_INSTRUMENTATION
  70. #ifdef INCLUDE_WVNET
  71. #include "wvNetLib.h"
  72. #endif
  73. #endif
  74. #ifdef ROUTER_STACK
  75. #define SOCKADDR_IN(s) (((struct sockaddr_in*)(s))->sin_addr.s_addr)
  76. #endif
  77. struct walkarg {
  78. int w_op, w_arg, w_given, w_needed, w_tmemsize;
  79. caddr_t w_where, w_tmem;
  80. };
  81. #ifndef VIRTUAL_STACK
  82.     /*
  83.      * This global counts the number of routing socket listeners
  84.      * for a particular family. It is not used outside this module.
  85.      */
  86. struct  route_cb route_cb;
  87. #endif
  88. static struct sockaddr route_dst = { 2, PF_ROUTE, };
  89. static struct sockaddr route_src = { 2, PF_ROUTE, };
  90. #ifndef VIRTUAL_STACK
  91.     /*
  92.      * The following protocol structure is the only global in this module
  93.      * which differs between virtual stacks. It limits the routing messages
  94.      * based on the associated address family, if a specific protocol value
  95.      * is chosen during the socket creation.
  96.      *
  97.      * The source address variable above is read, but never altered. It
  98.      * is the preassigned remote address for all routing sockets, which
  99.      * disables the use of any alternatives when writing to a socket and
  100.      * limits the delivery of any routing message to members of the routing
  101.      * socket family.
  102.      *
  103.      * Since the bind operation is not supported, a local address can't be
  104.      * assigned to a routing socket. As a result, the preceding destination
  105.      * address variable, although passed to the routine which sends routing
  106.      * messages to any listening sockets, is never actually used.
  107.      */ 
  108.      
  109. static struct sockproto route_proto = { PF_ROUTE, };
  110. #endif /* VIRTUAL_STACK */
  111. #ifdef ROUTER_STACK
  112. IMPORT void routeIfStatusUpdate (struct ifnet *);
  113. IMPORT void routeIfAddressUpdate (int, struct ifaddr *, struct rtentry *);
  114. IMPORT void routeMissUpdate (int, struct rt_addrinfo *, int, int);
  115. #endif /* ROUTER_STACK */
  116. IMPORT int rt_fixdelete (struct radix_node *, void *);
  117. struct mbuf *
  118. rt_msg1 (int, struct rt_addrinfo *);
  119. static int rt_msg2 (int, struct rt_addrinfo *, caddr_t, 
  120.  struct walkarg *);
  121. static void rt_xaddrs (caddr_t, caddr_t, struct rt_addrinfo *);
  122. static int route_usrreq (struct socket *, int, struct mbuf *,
  123.                               struct mbuf *, struct mbuf *);
  124. void rt_ifmsg (struct ifnet *);
  125. void rt_missmsg (int, struct rt_addrinfo *, int, int);
  126. void rt_newaddrmsg (int, struct ifaddr *, int, struct rtentry *);
  127. static int route_output (struct mbuf *, struct socket *);
  128. static void rt_setmetrics (u_long, struct rt_metrics *,
  129.                                struct rt_metrics *);
  130. static void m_copyback (struct mbuf *, int, int, caddr_t);
  131. static void  m_copydata(struct mbuf *, int, int, caddr_t);
  132. #ifdef ROUTER_STACK
  133. LOCAL int routeGatewayFetch (struct rtentry *, struct rt_msghdr *);
  134. LOCAL ROUTE_ENTRY * routeMatch (struct rtentry *, short, struct sockaddr *);
  135. #endif /* ROUTER_STACK */
  136. #ifdef WV_INSTRUMENTATION
  137. #ifdef INCLUDE_WVNET
  138.     /* Set common fields of event identifiers for this module. */
  139. LOCAL UCHAR wvNetModuleId = WV_NET_RTSOCK_MODULE;   /* Value for rtsock.c */
  140. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */
  141. LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */
  142. #endif    /* INCLUDE_WVNET */
  143. #endif
  144. /* Sleazy use of local variables throughout file, warning!!!! */
  145. #define dst info.rti_info[RTAX_DST]
  146. #define gate info.rti_info[RTAX_GATEWAY]
  147. #define netmask info.rti_info[RTAX_NETMASK]
  148. #define genmask info.rti_info[RTAX_GENMASK]
  149. #define ifpaddr info.rti_info[RTAX_IFP]
  150. #define ifaaddr info.rti_info[RTAX_IFA]
  151. #define brdaddr info.rti_info[RTAX_BRD]
  152. /*******************************************************************************
  153. * rtSockInit - intialize route sockets
  154. *
  155. * This function initializes the route msg hooks used in various places in the
  156. * system. The hooks are provided to scale out route sockets. The same hooks
  157. * also generate the internal callback messages for the router stack product.
  158. *
  159. * The domain_init entry point of the route socket domain calls this function.
  160. *
  161. * RETURNS: N/A
  162. *
  163. * NOMANUAL
  164. */
  165. LOCAL void rtSockInit (void)
  166.     {
  167. #ifdef WV_INSTRUMENTATION
  168. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  169.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 36, 8,
  170.                      WV_NETEVENT_RTSOCKINIT_START)
  171. #endif  /* INCLUDE_WVNET */
  172. #endif
  173.     /* Set the function hooks for receiving status changes from the stack. */
  174. #ifdef ROUTER_STACK
  175.     rtIfaceMsgHook = routeIfStatusUpdate;
  176.     rtNewAddrMsgHook = routeIfAddressUpdate;
  177.     rtMissMsgHook = routeMissUpdate;
  178. #else
  179.     rtIfaceMsgHook = rt_ifmsg;
  180.     rtNewAddrMsgHook = rt_newaddrmsg;
  181.     rtMissMsgHook = rt_missmsg;
  182. #endif /* ROUTER_STACK */
  183.     raw_init ();       /* initialize the raw control block */
  184.     }
  185.     
  186. /*ARGSUSED*/
  187. static int
  188. route_usrreq(so, req, m, nam, control)
  189. register struct socket *so;
  190. int req;
  191. struct mbuf *m, *nam, *control;
  192. {
  193. register int error = 0;
  194. register struct rawcb *rp = sotorawcb(so);
  195. int s;
  196. #ifdef WV_INSTRUMENTATION
  197. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  198.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 21, 6,
  199.                      WV_NETEVENT_ROUTEREQ_START, so->so_fd, req)
  200. #endif  /* INCLUDE_WVNET */
  201. #endif
  202. if (req == PRU_ATTACH) {
  203. MALLOC(rp, struct rawcb *, sizeof(*rp), MT_PCB, M_WAIT);
  204. if (rp == (struct rawcb *) NULL)
  205.     {
  206.     return (ENOBUFS);
  207.     }
  208. if ((so->so_pcb = (caddr_t)rp))
  209. bzero(so->so_pcb, sizeof(*rp));
  210. }
  211. if (req == PRU_DETACH && rp) {
  212. int af = rp->rcb_proto.sp_protocol;
  213. if (af == AF_INET)
  214. route_cb.ip_count--;
  215. else if (af == AF_NS)
  216. route_cb.ns_count--;
  217. else if (af == AF_ISO)
  218. route_cb.iso_count--;
  219. route_cb.any_count--;
  220. }
  221. s = splnet();
  222. error = raw_usrreq(so, req, m, nam, control);
  223. rp = sotorawcb(so);
  224. if (req == PRU_ATTACH && rp) {
  225. int af = rp->rcb_proto.sp_protocol;
  226. if (error) {
  227. FREE(rp, MT_PCB);
  228. splx(s);
  229. return (error);
  230. }
  231. if (af == AF_INET)
  232. route_cb.ip_count++;
  233. else if (af == AF_NS)
  234. route_cb.ns_count++;
  235. else if (af == AF_ISO)
  236. route_cb.iso_count++;
  237. rp->rcb_faddr = &route_src;
  238. route_cb.any_count++;
  239. soisconnected(so);
  240. so->so_options |= SO_USELOOPBACK;
  241. }
  242. splx(s);
  243. return (error);
  244. }
  245. /*ARGSUSED*/
  246. static int
  247. route_output(m, so)
  248. register struct mbuf *m;
  249. struct socket *so;
  250. {
  251. register struct rt_msghdr *rtm = 0;
  252. register struct rtentry *rt = 0;
  253. struct rtentry *saved_nrt = 0;
  254. struct radix_node_head *rnh;
  255. struct rt_addrinfo info;
  256. int len, error = 0;
  257. struct ifnet *ifp = 0;
  258. struct ifaddr *ifa = 0;
  259. #ifdef ROUTER_STACK
  260.         struct sockaddr * pGateway = 0;
  261.         short             protoId = 0;
  262.         ROUTE_ENTRY *     pRoute = NULL;
  263. #endif
  264. #define senderr(e) { error = e; goto flush;}
  265. #ifdef WV_INSTRUMENTATION
  266. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  267.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_NOTICE, 5, 5, 
  268.                      WV_NETEVENT_RTOUTPUT_START, so->so_fd)
  269. #endif  /* INCLUDE_WVNET */
  270. #endif
  271. if (m == 0 || ((m->m_len < sizeof(long)) &&
  272.        (m = m_pullup(m, sizeof(long))) == 0))
  273.             {
  274. #ifdef WV_INSTRUMENTATION
  275. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  276.             WV_NET_EVENT_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 24, 1, 
  277.                             WV_NETEVENT_RTOUT_BADMSG, WV_NET_SEND,
  278.                             so->so_fd)
  279. #endif  /* INCLUDE_WVNET */
  280. #endif
  281.             return (ENOBUFS);
  282.             }
  283. if ((m->m_flags & M_PKTHDR) == 0)
  284.             {
  285. #ifdef WV_INSTRUMENTATION
  286. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  287.             WV_NET_EVENT_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 25, 2, 
  288.                             WV_NETEVENT_RTOUT_PANIC, WV_NET_SEND,
  289.                             so->so_fd)
  290. #endif  /* INCLUDE_WVNET */
  291. #endif
  292.             panic("route_output");
  293.             }
  294. len = m->m_pkthdr.len;
  295. if (len < sizeof(*rtm) ||
  296.     len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
  297. dst = 0;
  298. senderr(EINVAL);
  299. }
  300. R_Malloc(rtm, struct rt_msghdr *, len);
  301. if (rtm == 0) {
  302. dst = 0;
  303. senderr(ENOBUFS);
  304. }
  305. m_copydata(m, 0, len, (caddr_t)rtm);
  306. if (rtm->rtm_version != RTM_VERSION) {
  307. dst = 0;
  308. senderr(EPROTONOSUPPORT);
  309. }
  310. info.rti_addrs = rtm->rtm_addrs;
  311. rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info);
  312. if (dst == 0)
  313. senderr(EINVAL);
  314. if (genmask) {
  315. struct radix_node *t;
  316. t = rn_addmask((caddr_t)genmask, 0, 1);
  317. if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
  318. genmask = (struct sockaddr *)(t->rn_key);
  319. else
  320. senderr(ENOBUFS);
  321. }
  322. switch (rtm->rtm_type) {
  323. case RTM_ADD:
  324. if (gate == 0)
  325. senderr(EINVAL);
  326.                 /*
  327.                  * Create the new route using the default weight value.
  328.                  * Report the change using direct callbacks, but do not
  329.                  * generate a routing socket message to avoid duplicates.
  330.                  */
  331.                 error = rtrequestAddEqui(dst, netmask, gate, rtm->rtm_flags,
  332.  M2_ipRouteProto_other, 0, TRUE,
  333.                                          FALSE, (ROUTE_ENTRY **) &saved_nrt);
  334. if (error == 0 && saved_nrt) {
  335. rt_setmetrics(rtm->rtm_inits,
  336. &rtm->rtm_rmx, &saved_nrt->rt_rmx);
  337. #ifdef ROUTER_STACK
  338.                         /* Set the initial weight value, if any. */
  339.                         if (rtm->rtm_inits & RTV_WEIGHT)
  340.                             saved_nrt->rt_rmx.weight = rtm->rtm_rmx.weight;
  341. #endif
  342. saved_nrt->rt_refcnt--;
  343. saved_nrt->rt_genmask = genmask;
  344. #ifdef ROUTER_STACK
  345.                 /* Use different message type for additional routes. */
  346.                 if ( ((ROUTE_ENTRY *)saved_nrt)->primaryRouteFlag == FALSE)
  347.                     rtm->rtm_type = RTM_ADDEXTRA;
  348. #endif
  349. }
  350. break;
  351. case RTM_DELETE:
  352.                 /*
  353.                  * Delete the matching route entry. Report the change using
  354.                  * direct callbacks, but do not generate a routing socket
  355.                  * message to avoid duplicates.
  356.                  */
  357.                 error = rtrequestDelEqui(dst, netmask, gate, rtm->rtm_flags,
  358.  M2_ipRouteProto_other, TRUE, FALSE,
  359.  (ROUTE_ENTRY **) &saved_nrt);
  360. if (error == 0) {
  361. (rt = saved_nrt)->rt_refcnt++;
  362. #ifdef ROUTER_STACK
  363.                 /* Use different message type for additional routes. */
  364.                 if ( ((ROUTE_ENTRY *)saved_nrt)->primaryRouteFlag == FALSE)
  365.                     rtm->rtm_type = RTM_DELEXTRA;
  366. #endif
  367. goto report;
  368. }
  369. break;
  370. case RTM_GET:
  371. case RTM_CHANGE:
  372. case RTM_LOCK:
  373. #ifdef ROUTER_STACK
  374.         case RTM_NEWCHANGE:
  375.         case RTM_NEWGET:
  376.         case RTM_GETALL:
  377. #endif
  378. if ((rnh = rt_tables[dst->sa_family]) == 0) {
  379. senderr(EAFNOSUPPORT);
  380. } else if ((rt = (struct rtentry *)
  381. rnh->rnh_lookup(dst, netmask, rnh)))
  382. rt->rt_refcnt++;
  383. else
  384. senderr(ESRCH);
  385. #ifdef ROUTER_STACK
  386. switch(rtm->rtm_type) {
  387.                 case RTM_GETALL:
  388.                     /*
  389.                      * Create a message containing information about all
  390.                      * routes with the matching destination and netmask.
  391.                      */
  392.                     len = routeGatewayFetch (rt, NULL);
  393.                     if (len > rtm->rtm_msglen)
  394.                         {
  395.                         struct rt_msghdr * pNewMessage;
  396.                         R_Malloc(pNewMessage, struct rt_msghdr *, len);
  397.                 if (pNewMessage == NULL)
  398.                             senderr(ENOBUFS);
  399.                         Free(rtm);
  400.                         rtm = pNewMessage;
  401. }
  402.                     routeGatewayFetch (rt, rtm);
  403.                     break;
  404.                 case RTM_NEWCHANGE:
  405. case RTM_NEWGET:
  406.                     /*
  407.                      * If the search command specifies a gateway address, use
  408.                      * that value and the included protocol ID (if any) to
  409.                      * select a matching entry from any duplicate routes.
  410.                      */
  411.                     pGateway = gate;
  412.                     if (gate)
  413.                         {
  414.                         protoId = RT_PROTO_GET (gate);
  415.                         pRoute = routeMatch (rt, protoId, gate);
  416.                         if (pRoute)
  417.                             {
  418.                             /*
  419.                              * Matching entry found. Increase the
  420.                              * reference count for the exact match.
  421.                              */
  422.                             pRoute->rtEntry.rt_refcnt++;
  423.                             }     
  424.                         else
  425.                             senderr(ESRCH);
  426.                         }
  427.                     break;
  428.                 }
  429. #endif
  430. switch(rtm->rtm_type) {
  431. case RTM_GET:
  432. #ifdef ROUTER_STACK
  433.                 case RTM_NEWGET:
  434.                         if (pGateway)
  435.                             {
  436.                             /* The command used the gateway address to get
  437.                              * an exact match. Use that entry instead of
  438.                              * the original reference to the primary route.
  439.                              */ 
  440.                             rtfree (rt);
  441.                             rt = (struct rtentry *)pRoute;
  442.                             }
  443. #endif
  444. report:
  445. dst = rt_key(rt);
  446. gate = rt->rt_gateway;
  447. netmask = rt_mask(rt);
  448. genmask = rt->rt_genmask;
  449. if ((rtm->rtm_addrs & (RTA_IFP | RTA_IFA))) {
  450. if ((ifp = rt->rt_ifp)) {
  451. ifpaddr = ifp->if_addrlist->ifa_addr;
  452. ifaaddr = rt->rt_ifa->ifa_addr;
  453. if (ifp->if_flags & IFF_POINTOPOINT)
  454. brdaddr = rt->rt_ifa->ifa_dstaddr;
  455. else
  456. brdaddr = 0;
  457. rtm->rtm_index = ifp->if_index;
  458. } else {
  459. ifpaddr = 0;
  460. ifaaddr = 0;
  461.     }
  462. }
  463. len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
  464. (struct walkarg *)0);
  465. if (len > rtm->rtm_msglen) {
  466. struct rt_msghdr *new_rtm;
  467. R_Malloc(new_rtm, struct rt_msghdr *, len);
  468. if (new_rtm == 0)
  469. senderr(ENOBUFS);
  470. Bcopy(rtm, new_rtm, rtm->rtm_msglen);
  471. Free(rtm); rtm = new_rtm;
  472. }
  473. (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
  474. (struct walkarg *)0);
  475. rtm->rtm_flags = rt->rt_flags;
  476. rtm->rtm_rmx = rt->rt_rmx;
  477. rtm->rtm_addrs = info.rti_addrs;
  478. break;
  479. #ifdef ROUTER_STACK
  480. case RTM_NEWCHANGE:
  481.                         /*
  482.                          * Use the exact match selected with the gateway
  483.                          * address, if available. Save the primary route
  484.                          * in case the change operation alters the weight.
  485.                          */
  486.                         if (pGateway)
  487.                             {
  488.                             saved_nrt = rt;
  489.                             rt = (struct rtentry *)pRoute;
  490.                             }
  491.                     /* Access the new gateway value for a route, if any. */
  492.                     gate = info.rti_info[RTAX_AUTHOR];
  493. #endif
  494. case RTM_CHANGE:
  495. if (gate && rt_setgate(rt, rt_key(rt), gate))
  496. senderr(ENOSPC);
  497. #ifdef ROUTER_STACK
  498.        /* Only remove cloned routes when altering the primary entry. */
  499.                     if ( ((ROUTE_ENTRY *)rt)->primaryRouteFlag)
  500.                         {
  501. #endif /* ROUTER_STACK */
  502.                         if (gate && (rt_key(rt)->sa_family == AF_INET))
  503.                             {
  504.                             /*
  505.                              * Remove any cloned routes using the
  506.                              * (now obsolete) gateway.
  507.                              */
  508.                            if ( (rt->rt_flags & RTF_CLONING) && rt_mask (rt))
  509.                                rn_walksubtree (rnh, rt_key (rt), rt_mask (rt),
  510.                                                rt_fixdelete, rt);
  511.                            }
  512. #ifdef ROUTER_STACK
  513.     /* End of condition for cloned route removal */
  514.                         }
  515. #endif
  516. /* new gateway could require new ifaddr, ifp;
  517.    flags may also be different; ifp may be specified
  518.    by ll sockaddr when protocol address is ambiguous */
  519. if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
  520.     (ifp = ifa->ifa_ifp))
  521. ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, ifp);
  522. else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
  523.  (ifa = ifa_ifwithroute(rt->rt_flags,
  524. rt_key(rt), gate)))
  525. ifp = ifa->ifa_ifp;
  526. if (ifa) {
  527. register struct ifaddr *oifa = rt->rt_ifa;
  528. if (oifa != ifa) {
  529.     if (oifa && oifa->ifa_rtrequest)
  530. oifa->ifa_rtrequest(RTM_DELETE,
  531. rt, gate);
  532.     IFAFREE(rt->rt_ifa);
  533.     rt->rt_ifa = ifa;
  534.     ifa->ifa_refcnt++;
  535.     rt->rt_ifp = ifp;
  536. }
  537. }
  538. #ifdef ROUTER_STACK
  539.     /*
  540.      * Note: Setting the metrics does not change the new weight
  541.      *       value for the selected route entry, since that
  542.      *       alteration could replace the current route before
  543.      *       completing all the changes required.
  544.      */
  545. #endif
  546. rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
  547. &rt->rt_rmx);
  548. if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
  549.        rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
  550. if (genmask)
  551. rt->rt_genmask = genmask;
  552. /*
  553.  * Fall into
  554.  */
  555. case RTM_LOCK:
  556. rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
  557. rt->rt_rmx.rmx_locks |=
  558. (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
  559. break;
  560. }
  561. #ifdef ROUTER_STACK
  562.                 /*
  563.                  * Since a weight change could replace the primary route
  564.                  * visible to the IP forwarding process and the original
  565.                  * routing socket messages, reorganizing the routes must
  566.                  * wait until after all the prior changes so that any new
  567.                  * copy of the selected route is correct.
  568.                  */
  569. switch(rtm->rtm_type) {
  570. case RTM_CHANGE:
  571. case RTM_NEWCHANGE:
  572.                     /* Do nothing if the weight did not change. */
  573.                     if ( (rtm->rtm_inits & RTV_WEIGHT) == 0)
  574.                         break;
  575.                     /*
  576.                      * Get the primary route to find the matching group
  577.                      * for an existing entry when updating the weight.
  578.                      */
  579.                     if (saved_nrt)
  580.                         {
  581.                         /*
  582.                          * The new change operation set a gateway to get
  583.                          * an exact match and saved the primary route.
  584.                          */
  585.                         pRoute = (ROUTE_ENTRY *)saved_nrt;
  586.                         }
  587.                     else
  588.                         {
  589.                         /*
  590.                          * The original change operation only modifies the
  591.                          * primary route. The new change operation also
  592.                          * alters that entry if no gateway is set.
  593.                          */
  594.                         pRoute = (ROUTE_ENTRY *)rt;
  595.                         }
  596.                     routeWeightUpdate (pRoute, protoId, (ROUTE_ENTRY *)rt, 
  597.                                        gate, rtm->rtm_rmx.weight);
  598.                     if (saved_nrt)
  599.                         {
  600.                         /*
  601.                          * Release the reference to the primary route
  602.                          * if a specified gateway used an exact match.
  603.                          */
  604.                         rtfree (saved_nrt);
  605.                         }
  606.                     break;
  607.                 }
  608. #endif /* ROUTER_STACK */
  609. break;
  610. default:
  611. senderr(EOPNOTSUPP);
  612. }
  613. flush:
  614. #ifdef WV_INSTRUMENTATION
  615. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  616.         if (error)
  617.             {
  618.             WV_NET_EVENT_2 (NET_AUX_EVENT, WV_NET_CRITICAL, 29, 4, 
  619.                             WV_NETEVENT_RTOUTPUT_FAIL, WV_NET_SEND,
  620.                             so->so_fd, error)
  621.             }
  622. #endif  /* INCLUDE_WVNET */
  623. #endif
  624. if (rtm) {
  625. if (error)
  626. rtm->rtm_errno = error;
  627. else 
  628. rtm->rtm_flags |= RTF_DONE;
  629. }
  630. if (rt)
  631. rtfree(rt);
  632.     {
  633. register struct rawcb *rp = 0;
  634. /*
  635.  * Check to see if we don't want our own messages.
  636.  */
  637. if ((so->so_options & SO_USELOOPBACK) == 0) {
  638. if (route_cb.any_count <= 1) {
  639. if (rtm)
  640. Free(rtm);
  641. m_freem(m);
  642. return (error);
  643. }
  644. /* There is another listener, so construct message */
  645. rp = sotorawcb(so);
  646. }
  647. if (rtm) {
  648. m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
  649. Free(rtm);
  650. }
  651. if (rp)
  652. rp->rcb_proto.sp_family = 0; /* Avoid us */
  653. if (dst)
  654. route_proto.sp_protocol = dst->sa_family;
  655. raw_input(m, &route_proto, &route_src, &route_dst);
  656. if (rp)
  657. rp->rcb_proto.sp_family = PF_ROUTE;
  658.     }
  659. return (error);
  660. }
  661. static void
  662. rt_setmetrics(which, in, out)
  663. u_long which;
  664. register struct rt_metrics *in, *out;
  665. {
  666. #define metric(f, e) if (which & (f)) out->e = in->e;
  667. metric(RTV_RPIPE, rmx_recvpipe);
  668. metric(RTV_SPIPE, rmx_sendpipe);
  669. metric(RTV_SSTHRESH, rmx_ssthresh);
  670. metric(RTV_RTT, rmx_rtt);
  671. metric(RTV_RTTVAR, rmx_rttvar);
  672. metric(RTV_HOPCOUNT, rmx_hopcount);
  673. metric(RTV_MTU, rmx_mtu);
  674. metric(RTV_EXPIRE, rmx_expire);
  675. #ifdef ROUTER_STACK
  676.     /*
  677.      * Set the values for the new additional metrics,
  678.      * except the weight, which must be postponed when
  679.      * altering that value.
  680.      */
  681.     metric(RTV_VALUE1, value1)
  682.     metric(RTV_VALUE2, value2)
  683.     metric(RTV_VALUE3, value3)
  684.     metric(RTV_VALUE4, value4)
  685.     metric(RTV_VALUE5, value5)
  686.     metric(RTV_ROUTETAG, routeTag)
  687. #endif /* ROUTER_STACK */
  688. #undef metric
  689. }
  690. #define ROUNDUP(a) 
  691. ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  692. #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
  693. static void
  694. rt_xaddrs(cp, cplim, rtinfo)
  695. register caddr_t cp, cplim;
  696. register struct rt_addrinfo *rtinfo;
  697. {
  698. register struct sockaddr *sa;
  699. register int i;
  700. bzero((char *)rtinfo->rti_info, sizeof(rtinfo->rti_info));
  701. for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
  702. if ((rtinfo->rti_addrs & (1 << i)) == 0)
  703. continue;
  704. rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
  705. ADVANCE(cp, sa);
  706. }
  707. }
  708. struct mbuf *
  709. rt_msg1(type, rtinfo)
  710. int type;
  711. register struct rt_addrinfo *rtinfo;
  712. {
  713. register struct rt_msghdr *rtm;
  714. register struct mbuf *m;
  715. register int i;
  716. register struct sockaddr *sa;
  717. int len, dlen;
  718. m = mHdrClGet(M_DONTWAIT, MT_DATA, CL_SIZE_128, TRUE);
  719. if (m == 0)
  720. return (m);
  721. switch (type) {
  722. case RTM_DELADDR:
  723. case RTM_NEWADDR:
  724. len = sizeof(struct ifa_msghdr);
  725. break;
  726. case RTM_IFINFO:
  727. len = sizeof(struct if_msghdr);
  728. break;
  729. default:
  730. len = sizeof(struct rt_msghdr);
  731. }
  732. if (len > m->m_extSize)
  733. panic("rt_msg1");
  734. m->m_pkthdr.len = m->m_len = len;
  735. m->m_pkthdr.rcvif = 0;
  736. rtm = mtod(m, struct rt_msghdr *);
  737. bzero((caddr_t)rtm, len);
  738. for (i = 0; i < RTAX_MAX; i++) {
  739. if ((sa = rtinfo->rti_info[i]) == NULL)
  740. continue;
  741. rtinfo->rti_addrs |= (1 << i);
  742. dlen = ROUNDUP(sa->sa_len);
  743. m_copyback(m, len, dlen, (caddr_t)sa);
  744. len += dlen;
  745. }
  746. if (m->m_pkthdr.len != len) {
  747. m_freem(m);
  748. return (NULL);
  749. }
  750. rtm->rtm_msglen = len;
  751. rtm->rtm_version = RTM_VERSION;
  752. rtm->rtm_type = type;
  753. return (m);
  754. }
  755. static int
  756. rt_msg2(type, rtinfo, cp, w)
  757. int type;
  758. register struct rt_addrinfo *rtinfo;
  759. caddr_t cp;
  760. struct walkarg *w;
  761. {
  762. register int i;
  763. int len, dlen, second_time = 0;
  764. caddr_t cp0;
  765. rtinfo->rti_addrs = 0;
  766. again:
  767. switch (type) {
  768. case RTM_DELADDR:
  769. case RTM_NEWADDR:
  770. len = sizeof(struct ifa_msghdr);
  771. break;
  772. case RTM_IFINFO:
  773. len = sizeof(struct if_msghdr);
  774. break;
  775. default:
  776. len = sizeof(struct rt_msghdr);
  777. }
  778. if ((cp0 = cp))
  779. cp += len;
  780. for (i = 0; i < RTAX_MAX; i++) {
  781. register struct sockaddr *sa;
  782. if ((sa = rtinfo->rti_info[i]) == 0)
  783. continue;
  784. rtinfo->rti_addrs |= (1 << i);
  785. dlen = ROUNDUP(sa->sa_len);
  786. if (cp) {
  787. bcopy((caddr_t)sa, cp, (unsigned)dlen);
  788. cp += dlen;
  789. }
  790. len += dlen;
  791. }
  792. if (cp == 0 && w != NULL && !second_time) {
  793. register struct walkarg *rw = w;
  794. rw->w_needed += len;
  795. if (rw->w_needed <= 0 && rw->w_where) {
  796. if (rw->w_tmemsize < len) {
  797. if (rw->w_tmem)
  798.         {
  799. FREE(rw->w_tmem, MT_RTABLE);
  800. }
  801. MALLOC(rw->w_tmem, caddr_t, len, MT_RTABLE,
  802.        M_DONTWAIT); 
  803. if (rw->w_tmem)
  804. rw->w_tmemsize = len;
  805. }
  806. if (rw->w_tmem) {
  807. cp = rw->w_tmem;
  808. second_time = 1;
  809. goto again;
  810. } else
  811. rw->w_where = 0;
  812. }
  813. }
  814. if (cp) {
  815. register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
  816. rtm->rtm_version = RTM_VERSION;
  817. rtm->rtm_type = type;
  818. rtm->rtm_msglen = len;
  819. }
  820. return (len);
  821. }
  822. /*
  823.  * This routine is called to generate a message from the routing
  824.  * socket indicating that a redirect has occured, a routing lookup
  825.  * has failed, or that a protocol has detected timeouts to a particular
  826.  * destination.
  827.  */
  828. void
  829. rt_missmsg(type, rtinfo, flags, error)
  830. int type, flags, error;
  831. register struct rt_addrinfo *rtinfo;
  832. {
  833. register struct rt_msghdr *rtm;
  834. register struct mbuf *m;
  835. struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
  836. if (route_cb.any_count == 0)
  837. return;
  838. m = rt_msg1(type, rtinfo);
  839. if (m == 0)
  840. return;
  841. rtm = mtod(m, struct rt_msghdr *);
  842. rtm->rtm_flags = RTF_DONE | flags;
  843. rtm->rtm_errno = error;
  844. rtm->rtm_addrs = rtinfo->rti_addrs;
  845. route_proto.sp_protocol = sa ? sa->sa_family : 0;
  846. raw_input(m, &route_proto, &route_src, &route_dst);
  847. }
  848. /*
  849.  * This routine is called to generate a message from the routing
  850.  * socket indicating that the status of a network interface has changed.
  851.  */
  852. void
  853. rt_ifmsg(ifp)
  854. register struct ifnet *ifp;
  855. {
  856. register struct if_msghdr *ifm;
  857. struct mbuf *m;
  858. struct rt_addrinfo info;
  859. if (route_cb.any_count == 0)
  860. return;
  861. bzero((caddr_t)&info, sizeof(info));
  862. m = rt_msg1(RTM_IFINFO, &info);
  863. if (m == 0)
  864. return;
  865. ifm = mtod(m, struct if_msghdr *);
  866. ifm->ifm_index = ifp->if_index;
  867. ifm->ifm_flags = ifp->if_flags;
  868. ifm->ifm_data = ifp->if_data;
  869. ifm->ifm_addrs = 0;
  870. route_proto.sp_protocol = 0;
  871. raw_input(m, &route_proto, &route_src, &route_dst);
  872. }
  873. /*
  874.  * This is called to generate messages from the routing socket
  875.  * indicating a network interface has had addresses associated with it.
  876.  * if we ever reverse the logic and replace messages TO the routing
  877.  * socket indicate a request to configure interfaces, then it will
  878.  * be unnecessary as the routing socket will automatically generate
  879.  * copies of it.
  880.  */
  881. void
  882. rt_newaddrmsg(cmd, ifa, error, rt)
  883. int cmd, error;
  884. register struct ifaddr *ifa;
  885. register struct rtentry *rt;
  886. {
  887. struct rt_addrinfo info;
  888. struct sockaddr *sa = NULL;
  889. int pass;
  890. struct mbuf *m = NULL;
  891. struct ifnet *ifp = ifa->ifa_ifp;
  892.         int ncmd;
  893. if (route_cb.any_count == 0)
  894. return;
  895. for (pass = 1; pass < 3; pass++) {
  896. bzero((caddr_t)&info, sizeof(info));
  897. if ((cmd == RTM_ADD && pass == 1) ||
  898.     (cmd == RTM_DELETE && pass == 2)) {
  899. register struct ifa_msghdr *ifam;
  900. ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
  901. ifaaddr = sa = ifa->ifa_addr;
  902. ifpaddr = ifp->if_addrlist->ifa_addr;
  903. netmask = ifa->ifa_netmask;
  904. brdaddr = ifa->ifa_dstaddr;
  905. if ((m = rt_msg1(ncmd, &info)) == NULL)
  906. continue;
  907. ifam = mtod(m, struct ifa_msghdr *);
  908. ifam->ifam_index = ifp->if_index;
  909. ifam->ifam_metric = ifa->ifa_metric;
  910. ifam->ifam_flags = ifa->ifa_flags;
  911. ifam->ifam_addrs = info.rti_addrs;
  912. }
  913. if ((cmd == RTM_ADD && pass == 2) ||
  914.     (cmd == RTM_DELETE && pass == 1)) {
  915. register struct rt_msghdr *rtm;
  916. if (rt == 0)
  917. continue;
  918.                         ncmd = cmd;
  919. netmask = rt_mask(rt);
  920. dst = sa = rt_key(rt);
  921. gate = rt->rt_gateway;
  922. #ifdef ROUTER_STACK
  923.                 /* Use a different message type for additional routes. */
  924.                 if ( ((ROUTE_ENTRY *)rt)->primaryRouteFlag == FALSE)
  925.                     {
  926.                     if (ncmd == RTM_ADD)
  927.                         ncmd = RTM_ADDEXTRA;
  928.                     else
  929.                         ncmd = RTM_DELEXTRA;
  930.                     }
  931. #endif /* ROUTER_STACK */
  932. if ((m = rt_msg1(ncmd, &info)) == NULL)
  933. continue;
  934. rtm = mtod(m, struct rt_msghdr *);
  935. rtm->rtm_index = ifp->if_index;
  936. rtm->rtm_flags |= rt->rt_flags;
  937. rtm->rtm_errno = error;
  938. rtm->rtm_addrs = info.rti_addrs;
  939. }
  940. route_proto.sp_protocol = sa ? sa->sa_family : 0;
  941. raw_input(m, &route_proto, &route_src, &route_dst);
  942. }
  943. }
  944. /*
  945.  * This is used in dumping the kernel table via sysctl().
  946.  */
  947. int
  948. sysctl_dumpentry(rn, w)
  949. struct radix_node *rn;
  950. register struct walkarg *w;
  951. {
  952. register struct rtentry *rt = (struct rtentry *)rn;
  953. int error = 0, size;
  954. struct rt_addrinfo info;
  955. if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
  956. return 0;
  957. bzero((caddr_t)&info, sizeof(info));
  958. dst = rt_key(rt);
  959. gate = rt->rt_gateway;
  960. netmask = rt_mask(rt);
  961. genmask = rt->rt_genmask;
  962. if (rt->rt_ifp) {
  963. ifpaddr = rt->rt_ifp->if_addrlist->ifa_addr;
  964. ifaaddr = rt->rt_ifa->ifa_addr;
  965. if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
  966. brdaddr = rt->rt_ifa->ifa_dstaddr;
  967. }
  968. size = rt_msg2(RTM_GET, &info, 0, w);
  969. if (w->w_where && w->w_tmem) {
  970. register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
  971. rtm->rtm_flags = rt->rt_flags;
  972. rtm->rtm_use = rt->rt_use;
  973. rtm->rtm_rmx = rt->rt_rmx;
  974. rtm->rtm_index = rt->rt_ifp->if_index;
  975. rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
  976. rtm->rtm_addrs = info.rti_addrs;
  977. if ((error = copyout((caddr_t)rtm, w->w_where, size)))
  978. w->w_where = NULL;
  979. else
  980. w->w_where += size;
  981. }
  982. return (error);
  983. }
  984. int
  985. sysctl_iflist(af, w)
  986. int af;
  987. register struct walkarg *w;
  988. {
  989. register struct ifnet *ifp;
  990. register struct ifaddr *ifa;
  991. struct rt_addrinfo info;
  992. int len, error = 0;
  993. bzero((caddr_t)&info, sizeof(info));
  994. #ifdef VIRTUAL_STACK
  995. for (ifp = _ifnet; ifp; ifp = ifp->if_next) {
  996. #else
  997. for (ifp = ifnet; ifp; ifp = ifp->if_next) {
  998. #endif
  999. if (w->w_arg && w->w_arg != ifp->if_index)
  1000. continue;
  1001. ifa = ifp->if_addrlist;
  1002. ifpaddr = ifa->ifa_addr;
  1003. len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
  1004. ifpaddr = 0;
  1005. if (w->w_where && w->w_tmem) {
  1006. register struct if_msghdr *ifm;
  1007. ifm = (struct if_msghdr *)w->w_tmem;
  1008. ifm->ifm_index = ifp->if_index;
  1009. ifm->ifm_flags = ifp->if_flags;
  1010. ifm->ifm_data = ifp->if_data;
  1011. ifm->ifm_addrs = info.rti_addrs;
  1012. if ((error = copyout((caddr_t)ifm, w->w_where, len)))
  1013. return (error);
  1014. w->w_where += len;
  1015. }
  1016. while ((ifa = ifa->ifa_next)) {
  1017. if (af && af != ifa->ifa_addr->sa_family)
  1018. continue;
  1019. ifaaddr = ifa->ifa_addr;
  1020. netmask = ifa->ifa_netmask;
  1021. brdaddr = ifa->ifa_dstaddr;
  1022. len = rt_msg2(RTM_NEWADDR, &info, 0, w);
  1023. if (w->w_where && w->w_tmem) {
  1024. register struct ifa_msghdr *ifam;
  1025. ifam = (struct ifa_msghdr *)w->w_tmem;
  1026. ifam->ifam_index = ifa->ifa_ifp->if_index;
  1027. ifam->ifam_flags = ifa->ifa_flags;
  1028. ifam->ifam_metric = ifa->ifa_metric;
  1029. ifam->ifam_addrs = info.rti_addrs;
  1030. if ((error = copyout(w->w_tmem, w->w_where,
  1031.                                                      len)))
  1032. return (error);
  1033. w->w_where += len;
  1034. }
  1035. }
  1036. ifaaddr = netmask = brdaddr = 0;
  1037. }
  1038. return (0);
  1039. }
  1040. int
  1041. sysctl_rtable(name, namelen, where, given, new, newlen)
  1042. int *name;
  1043. int namelen;
  1044. caddr_t where;
  1045. size_t *given;
  1046. caddr_t *new;
  1047. size_t newlen;
  1048. {
  1049. register struct radix_node_head *rnh;
  1050. int i, s, error = EINVAL;
  1051. u_char  af;
  1052. struct walkarg w;
  1053. /*
  1054.  * XXX - This event does not usually occur: the sysctl_rtable() routine
  1055.  *       is typically only called by the Unix sysctl command which is not
  1056.  *       supported by VxWorks. It is also called by the RIP implementation
  1057.  *       as a legacy of the port from BSD, but that implementation detail
  1058.  *       is not of sufficient interest to include the event.
  1059. #ifdef WV_INSTRUMENTATION
  1060. #ifdef INCLUDE_WVNET    /@ WV_NET_INFO event @/
  1061.         if (namelen != 3)
  1062.             {
  1063.             WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 22, 7, 
  1064.                              WV_NETEVENT_ROUTEWALK_START, 0)
  1065.             }
  1066.         else
  1067.             {
  1068.             WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 22, 7, 
  1069.                              WV_NETEVENT_ROUTEWALK_START, name[1])
  1070.             }
  1071. #endif  /@ INCLUDE_WVNET @/
  1072. #endif
  1073.  * XXX - end of unused event
  1074.  */
  1075. if (new)
  1076. return (EPERM);
  1077. if (namelen != 3)
  1078. return (EINVAL);
  1079. af = name[0];
  1080. Bzero(&w, sizeof(w));
  1081. w.w_where = where;
  1082. w.w_given = *given;
  1083. w.w_needed = 0 - w.w_given;
  1084. w.w_op = name[1];
  1085. w.w_arg = name[2];
  1086. s = splnet();
  1087. switch (w.w_op) {
  1088. case NET_RT_DUMP:
  1089. case NET_RT_FLAGS:
  1090. for (i = 1; i <= AF_MAX; i++)
  1091. if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
  1092.     (error = rnh->rnh_walktree(rnh,
  1093. sysctl_dumpentry, &w)))
  1094. break;
  1095. break;
  1096. case NET_RT_IFLIST:
  1097. error = sysctl_iflist(af, &w);
  1098. }
  1099. splx(s);
  1100. if (w.w_tmem){
  1101. FREE(w.w_tmem, MT_RTABLE);
  1102. }
  1103. w.w_needed += w.w_given;
  1104. if (where) {
  1105. *given = w.w_where - where;
  1106. if (*given < w.w_needed)
  1107. return (ENOMEM);
  1108. } else {
  1109. *given = (11 * w.w_needed) / 10;
  1110. }
  1111. return (error);
  1112. }
  1113. /*
  1114.  * Definitions of protocols supported in the ROUTE domain.
  1115.  */
  1116. extern struct domain routedomain; /* or at least forward */
  1117. struct protosw routesw[] = {
  1118. { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR,
  1119.   raw_input, route_output, raw_ctlinput, 0,
  1120.   route_usrreq,
  1121.   rtSockInit, 0, 0, 0,
  1122.   sysctl_rtable,
  1123. }
  1124. };
  1125. struct domain routedomain =
  1126.     { PF_ROUTE, "route", 0, 0, 0,
  1127.       routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
  1128. /*
  1129.  * Copy data from a buffer back into the indicated mbuf chain,
  1130.  * starting "off" bytes from the beginning, extending the mbuf
  1131.  * chain if necessary.
  1132.  */
  1133. static void
  1134. m_copyback(m0, off, len, cp)
  1135. struct mbuf *m0;
  1136. register int off;
  1137. register int len;
  1138. caddr_t cp;
  1139. {
  1140. register int mlen;
  1141. register struct mbuf *m = m0, *n;
  1142. int totlen = 0;
  1143. if (m0 == 0)
  1144. return;
  1145. while (off > (mlen = m->m_len)) {
  1146. off -= mlen;
  1147. totlen += mlen;
  1148. if (m->m_next == 0) {
  1149. n = m_getclr(M_DONTWAIT, m->m_type, CL_SIZE_128, TRUE);
  1150. if (n == 0)
  1151. goto out;
  1152. n->m_len = min(n->m_extSize, len + off);
  1153. m->m_next = n;
  1154. }
  1155. m = m->m_next;
  1156. }
  1157. while (len > 0) {
  1158. mlen = min (m->m_len - off, len);
  1159. bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
  1160. cp += mlen;
  1161. len -= mlen;
  1162. mlen += off;
  1163. off = 0;
  1164. totlen += mlen;
  1165. if (len == 0)
  1166. break;
  1167. if (m->m_next == 0) {
  1168. n = mBufClGet(M_DONTWAIT, m->m_type, CL_SIZE_128, TRUE);
  1169. if (n == 0)
  1170. break;
  1171. n->m_len = min(n->m_extSize, len);
  1172. m->m_next = n;
  1173. }
  1174. m = m->m_next;
  1175. }
  1176. out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
  1177. m->m_pkthdr.len = totlen;
  1178. }
  1179. /*******************************************************************************
  1180. *
  1181. * m_copydata - copy data from an mbuf chain into a buff
  1182. * Copy data from an mbuf chain starting "off" bytes from the beginning,
  1183. * continuing for "len" bytes, into the indicated buffer.
  1184. */
  1185. static void m_copydata(m, off, len, cp)
  1186.     register struct mbuf *m;
  1187.     register int off;
  1188.     register int len;
  1189.     caddr_t cp;
  1190.     {
  1191.     register unsigned count;
  1192.     if (off < 0 || len < 0)
  1193. panic("m_copydata");
  1194.     while (off > 0)
  1195. {
  1196. if (m == 0)
  1197.             {
  1198. #ifdef WV_INSTRUMENTATION
  1199. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  1200.             WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 26, 3, 
  1201.                              WV_NETEVENT_COPYDATA_PANIC)
  1202. #endif  /* INCLUDE_WVNET */
  1203. #endif
  1204.             panic("m_copydata");
  1205.             }
  1206. if (off < m->m_len)
  1207.     break;
  1208. off -= m->m_len;
  1209. m = m->m_next;
  1210. }
  1211.     while (len > 0)
  1212. {
  1213. if (m == 0)
  1214.     panic("m_copydata");
  1215. count = min(m->m_len - off, len);
  1216. bcopy(mtod(m, caddr_t) + off, cp, count);
  1217. len -= count;
  1218. cp += count;
  1219. off = 0;
  1220. m = m->m_next;
  1221. }
  1222.     }
  1223. #ifdef ROUTER_STACK
  1224. /*******************************************************************************
  1225. *
  1226. * routeGatewayFetch - build a message which includes a list of gateways
  1227. *
  1228. * This routine constructs a routing socket message which supplies each
  1229. * next-hop router for all duplicate routes with a given destination and
  1230. * netmask. When the <pMessage> parameter is NULL, the routine simply
  1231. * counts the required length for the message. When that parameter provides
  1232. * an actual value, the routine stores the appropriate information in
  1233. * the supplied buffer. The RTAX_GATEWAY pointer for the resulting message
  1234. * accesses a series of customized address structures which include the
  1235. * protocol identifier and all additional metrics for each entry.
  1236. *
  1237. * RETURNS: Length of message for all route entries
  1238. *
  1239. * NOMANUAL
  1240. */
  1241. LOCAL int routeGatewayFetch
  1242.     (
  1243.     struct rtentry * pRoute,     /* primary route for destination/netmask */
  1244.     struct rt_msghdr * pMessage  /* list of routes for routing socket */
  1245.     )
  1246.     {
  1247.     int length;
  1248.     char * pBuffer;
  1249.     struct sockaddr * pAddress = NULL;
  1250.     struct sockaddr_gate * pGate;
  1251.     int addrlen;
  1252.     ROUTE_ENTRY * pGroup;    /* route entries for each protocol */
  1253.     ROUTE_ENTRY * pMatch;    /* current route entry for message */
  1254.     length = sizeof (struct rt_msghdr);
  1255.     if (pMessage)
  1256.         {
  1257.         /* Fill in the initial message header. */
  1258.         pMessage->rtm_version = RTM_VERSION;
  1259.         pMessage->rtm_type = RTM_GETALL;
  1260.         pMessage->rtm_flags = pRoute->rt_flags;
  1261.         pMessage->rtm_addrs = RTA_DST | RTA_GATEWAY;
  1262.         }
  1263.     pAddress = rt_key (pRoute);
  1264.     addrlen = ROUNDUP(pAddress->sa_len);
  1265.     pBuffer = (char *)pMessage;
  1266.     if (pBuffer)
  1267.         {
  1268.         /* Copy the destination address for the route entries. */
  1269.         pBuffer += length;
  1270.         bcopy ( (char *)pAddress, pBuffer, addrlen);
  1271.         pBuffer += addrlen;
  1272.         }
  1273.     length += addrlen;
  1274.     /*
  1275.      * Find the length of all entries for the specified destination
  1276.      * and netmask. Copy the relevant values if appropriate.
  1277.      */
  1278.     for (pGroup = (ROUTE_ENTRY *)pRoute; pGroup != NULL;
  1279.                  pGroup = pGroup->diffNode.pFrwd)
  1280.         {
  1281.         for (pMatch = pGroup; pMatch != NULL; pMatch = pMatch->sameNode.pFrwd)
  1282.             {
  1283.             pAddress = ROUTE_ENTRY_GATEWAY (pMatch);
  1284.             if (pAddress->sa_family == AF_LINK)
  1285.                 {
  1286.                 /*
  1287.                  * The entry contains an ARP template. Use the
  1288.                  * interface's IP address as the gateway value.
  1289.                  */
  1290.                 pAddress = pMatch->rtEntry.rt_ifa->ifa_addr;
  1291.                 }
  1292.             addrlen = ROUNDUP(sizeof (struct sockaddr_gate));
  1293.             if (pBuffer)
  1294.                 {
  1295.                 /* Copy the gateway address for the route entry. */
  1296.                 pGate = (struct sockaddr_gate *)pBuffer;
  1297.                 pGate->gate_family = pAddress->sa_family;
  1298.                 pGate->gate_addr = 
  1299.                     ( (struct sockaddr_in *)pAddress)->sin_addr.s_addr;
  1300.                 /* Set length to reflect increased size for metrics. */
  1301.                 pGate->gate_len = sizeof (struct sockaddr_gate);
  1302.                 /* Copy additional information into gateway field. */
  1303.                 pGate->routeProto = RT_PROTO_GET (ROUTE_ENTRY_KEY (pMatch));
  1304.                 pGate->weight = pMatch->rtEntry.rt_rmx.weight;
  1305.                 pGate->value1 = pMatch->rtEntry.rt_rmx.value1;
  1306.                 pGate->value2 = pMatch->rtEntry.rt_rmx.value2;
  1307.                 pGate->value3 = pMatch->rtEntry.rt_rmx.value3;
  1308.                 pGate->value4 = pMatch->rtEntry.rt_rmx.value4;
  1309.                 pGate->value5 = pMatch->rtEntry.rt_rmx.value5;
  1310.                 pGate->routeTag = pMatch->rtEntry.rt_rmx.routeTag;
  1311.                 pBuffer += addrlen;
  1312.                 }
  1313.             length += addrlen;
  1314.             }
  1315.         }
  1316.     /* Copy any netmask information for the route. */
  1317.     pAddress = rt_mask (pRoute);
  1318.     if (pAddress)
  1319.         {
  1320.         addrlen = ROUNDUP(pAddress->sa_len);
  1321.         if (pBuffer)
  1322.             {
  1323.             bcopy ( (char *)pAddress, pBuffer, addrlen);
  1324.             pBuffer += addrlen;
  1325.             /* Indicate that netmask information is present in the message. */
  1326.             pMessage->rtm_addrs |= RTA_NETMASK;
  1327.             }
  1328.         length += addrlen;
  1329.         }
  1330.     if (pMessage)
  1331.         {
  1332.         /* Set the total message length. */
  1333.         pMessage->rtm_msglen = length;
  1334.         }
  1335.     return (length);
  1336.     }
  1337. /*******************************************************************************
  1338. *
  1339. * routeMatch - find a unique entry within a set of duplicate routes
  1340. *
  1341. * This routine searches the extended lists attached to the <pRoute>
  1342. * primary route entry to find a matching route with the same next-hop
  1343. * gateway as the <pGateway> argument and a creator which matches the
  1344. * <protoId> value. That combination is unique for a particular destination
  1345. * address and netmask. This routine allows routing sockets to retrieve
  1346. * a duplicate route entry which is not visible to the IP forwarding process.
  1347. *
  1348. * RETURNS: Pointer to existing route, or NULL if none.
  1349. *
  1350. * NOMANUAL
  1351. */
  1352. LOCAL ROUTE_ENTRY * routeMatch
  1353.     (
  1354.     struct rtentry * pRoute,    /* primary route for destination/netmask */
  1355.     short protoId,              /* protocol identifer for matching route */
  1356.     struct sockaddr * pGateway  /* next hop gateway for matching route */
  1357.     )
  1358.     {
  1359.     ROUTE_ENTRY * pGroup;    /* route entries with matching protocol */
  1360.     ROUTE_ENTRY * pMatch;    /* exact match for protocol and gateway */
  1361.     if (protoId)
  1362.         {
  1363.         /* Find the list of entries for the specified protocol. */
  1364.         for (pGroup = (ROUTE_ENTRY *)pRoute; pGroup != NULL;
  1365.                  pGroup = pGroup->diffNode.pFrwd)
  1366.             {
  1367.             if (RT_PROTO_GET(ROUTE_ENTRY_KEY(pGroup)) == protoId)
  1368.                 break;
  1369.             }
  1370.         }
  1371.     else
  1372.         {
  1373.         /* No protocol ID specified: use the initial group. */
  1374.         pGroup = (ROUTE_ENTRY *)pRoute;
  1375.         }
  1376.     /* Find matching gateway if matching protocol found. */
  1377.     for (pMatch = pGroup; pMatch != NULL; pMatch = pMatch->sameNode.pFrwd)
  1378.         {
  1379.         if (ROUTE_ENTRY_GATEWAY (pMatch)->sa_family == AF_LINK)
  1380.             {
  1381.             /*
  1382.              * The gateway field contains an ARP template. The entry
  1383.              * only matches for a search using the interface's IP address
  1384.              * as the gateway.
  1385.              */
  1386.             if (SOCKADDR_IN (pMatch->rtEntry.rt_ifa->ifa_addr)
  1387.                                     == SOCKADDR_IN (pGateway))
  1388.                 {
  1389.                 /* Matching route entry found - halt search. */
  1390.                 break;
  1391.                 }
  1392.             }
  1393.         else if (SOCKADDR_IN (ROUTE_ENTRY_GATEWAY (pMatch))
  1394.                                     == SOCKADDR_IN (pGateway))
  1395.             {
  1396.             /* Matching route entry found - halt search. */
  1397.             break;
  1398.             }
  1399.         }
  1400.     return (pMatch);
  1401.     }
  1402. #endif /* ROUTER_STACK */