?? rtsock.c
字號:
/* * This is used in dumping the kernel table via sysctl(). */intsysctl_dumpentry(rn, w) struct radix_node *rn; register struct walkarg *w;{ register struct rtentry *rt = (struct rtentry *)rn; int error = 0, size; struct rt_addrinfo info; if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) return 0; bzero((caddr_t)&info, sizeof(info)); dst = rt_key(rt); gate = rt->rt_gateway; netmask = rt_mask(rt); genmask = rt->rt_genmask; if (rt->rt_ifp) { ifpaddr = rt->rt_ifp->if_addrlist->ifa_addr; ifaaddr = rt->rt_ifa->ifa_addr; if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) brdaddr = rt->rt_ifa->ifa_dstaddr; } size = rt_msg2(RTM_GET, &info, 0, w); if (w->w_where && w->w_tmem) { register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; rtm->rtm_flags = rt->rt_flags; rtm->rtm_use = rt->rt_use; rtm->rtm_rmx = rt->rt_rmx; rtm->rtm_index = rt->rt_ifp->if_index; rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; rtm->rtm_addrs = info.rti_addrs; if ((error = copyout((caddr_t)rtm, w->w_where, size))) w->w_where = NULL; else w->w_where += size; } return (error);}intsysctl_iflist(af, w) int af; register struct walkarg *w;{ register struct ifnet *ifp; register struct ifaddr *ifa; struct rt_addrinfo info; int len, error = 0; bzero((caddr_t)&info, sizeof(info));#ifdef VIRTUAL_STACK for (ifp = _ifnet; ifp; ifp = ifp->if_next) {#else for (ifp = ifnet; ifp; ifp = ifp->if_next) {#endif if (w->w_arg && w->w_arg != ifp->if_index) continue; ifa = ifp->if_addrlist; ifpaddr = ifa->ifa_addr; len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); ifpaddr = 0; if (w->w_where && w->w_tmem) { register struct if_msghdr *ifm; ifm = (struct if_msghdr *)w->w_tmem; ifm->ifm_index = ifp->if_index; ifm->ifm_flags = ifp->if_flags; ifm->ifm_data = ifp->if_data; ifm->ifm_addrs = info.rti_addrs; if ((error = copyout((caddr_t)ifm, w->w_where, len))) return (error); w->w_where += len; } while ((ifa = ifa->ifa_next)) { if (af && af != ifa->ifa_addr->sa_family) continue; ifaaddr = ifa->ifa_addr; netmask = ifa->ifa_netmask; brdaddr = ifa->ifa_dstaddr; len = rt_msg2(RTM_NEWADDR, &info, 0, w); if (w->w_where && w->w_tmem) { register struct ifa_msghdr *ifam; ifam = (struct ifa_msghdr *)w->w_tmem; ifam->ifam_index = ifa->ifa_ifp->if_index; ifam->ifam_flags = ifa->ifa_flags; ifam->ifam_metric = ifa->ifa_metric; ifam->ifam_addrs = info.rti_addrs; if ((error = copyout(w->w_tmem, w->w_where, len))) return (error); w->w_where += len; } } ifaaddr = netmask = brdaddr = 0; } return (0);}intsysctl_rtable(name, namelen, where, given, new, newlen) int *name; int namelen; caddr_t where; size_t *given; caddr_t *new; size_t newlen;{ register struct radix_node_head *rnh; int i, s, error = EINVAL; u_char af; struct walkarg w;/* * XXX - This event does not usually occur: the sysctl_rtable() routine * is typically only called by the Unix sysctl command which is not * supported by VxWorks. It is also called by the RIP implementation * as a legacy of the port from BSD, but that implementation detail * is not of sufficient interest to include the event.#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /@ WV_NET_INFO event @/ if (namelen != 3) { WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 22, 7, WV_NETEVENT_ROUTEWALK_START, 0) } else { WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 22, 7, WV_NETEVENT_ROUTEWALK_START, name[1]) }#endif /@ INCLUDE_WVNET @/#endif * XXX - end of unused event */ if (new) return (EPERM); if (namelen != 3) return (EINVAL); af = name[0]; Bzero(&w, sizeof(w)); w.w_where = where; w.w_given = *given; w.w_needed = 0 - w.w_given; w.w_op = name[1]; w.w_arg = name[2]; s = splnet(); switch (w.w_op) { case NET_RT_DUMP: case NET_RT_FLAGS: for (i = 1; i <= AF_MAX; i++) if ((rnh = rt_tables[i]) && (af == 0 || af == i) && (error = rnh->rnh_walktree(rnh, sysctl_dumpentry, &w))) break; break; case NET_RT_IFLIST: error = sysctl_iflist(af, &w); } splx(s); if (w.w_tmem){ FREE(w.w_tmem, MT_RTABLE); } w.w_needed += w.w_given; if (where) { *given = w.w_where - where; if (*given < w.w_needed) return (ENOMEM); } else { *given = (11 * w.w_needed) / 10; } return (error);}/* * Definitions of protocols supported in the ROUTE domain. */extern struct domain routedomain; /* or at least forward */struct protosw routesw[] = {{ SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, raw_input, route_output, raw_ctlinput, 0, route_usrreq, rtSockInit, 0, 0, 0, sysctl_rtable,}};struct domain routedomain = { PF_ROUTE, "route", 0, 0, 0, routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };/* * Copy data from a buffer back into the indicated mbuf chain, * starting "off" bytes from the beginning, extending the mbuf * chain if necessary. */static voidm_copyback(m0, off, len, cp) struct mbuf *m0; register int off; register int len; caddr_t cp;{ register int mlen; register struct mbuf *m = m0, *n; int totlen = 0; if (m0 == 0) return; while (off > (mlen = m->m_len)) { off -= mlen; totlen += mlen; if (m->m_next == 0) { n = m_getclr(M_DONTWAIT, m->m_type, CL_SIZE_128, TRUE); if (n == 0) goto out; n->m_len = min(n->m_extSize, len + off); m->m_next = n; } m = m->m_next; } while (len > 0) { mlen = min (m->m_len - off, len); bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); cp += mlen; len -= mlen; mlen += off; off = 0; totlen += mlen; if (len == 0) break; if (m->m_next == 0) { n = mBufClGet(M_DONTWAIT, m->m_type, CL_SIZE_128, TRUE); if (n == 0) break; n->m_len = min(n->m_extSize, len); m->m_next = n; } m = m->m_next; }out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) m->m_pkthdr.len = totlen;}/********************************************************************************* m_copydata - copy data from an mbuf chain into a buff* Copy data from an mbuf chain starting "off" bytes from the beginning,* continuing for "len" bytes, into the indicated buffer.*/static void m_copydata(m, off, len, cp) register struct mbuf *m; register int off; register int len; caddr_t cp; { register unsigned count; if (off < 0 || len < 0) panic("m_copydata"); while (off > 0) { if (m == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 26, 3, WV_NETEVENT_COPYDATA_PANIC)#endif /* INCLUDE_WVNET */#endif panic("m_copydata"); } if (off < m->m_len) break; off -= m->m_len; m = m->m_next; } while (len > 0) { if (m == 0) panic("m_copydata"); count = min(m->m_len - off, len); bcopy(mtod(m, caddr_t) + off, cp, count); len -= count; cp += count; off = 0; m = m->m_next; } }#ifdef ROUTER_STACK/********************************************************************************* routeGatewayFetch - build a message which includes a list of gateways** This routine constructs a routing socket message which supplies each* next-hop router for all duplicate routes with a given destination and* netmask. When the <pMessage> parameter is NULL, the routine simply* counts the required length for the message. When that parameter provides* an actual value, the routine stores the appropriate information in* the supplied buffer. The RTAX_GATEWAY pointer for the resulting message* accesses a series of customized address structures which include the* protocol identifier and all additional metrics for each entry.** RETURNS: Length of message for all route entries** NOMANUAL*/LOCAL int routeGatewayFetch ( struct rtentry * pRoute, /* primary route for destination/netmask */ struct rt_msghdr * pMessage /* list of routes for routing socket */ ) { int length; char * pBuffer; struct sockaddr * pAddress = NULL; struct sockaddr_gate * pGate; int addrlen; ROUTE_ENTRY * pGroup; /* route entries for each protocol */ ROUTE_ENTRY * pMatch; /* current route entry for message */ length = sizeof (struct rt_msghdr); if (pMessage) { /* Fill in the initial message header. */ pMessage->rtm_version = RTM_VERSION; pMessage->rtm_type = RTM_GETALL; pMessage->rtm_flags = pRoute->rt_flags; pMessage->rtm_addrs = RTA_DST | RTA_GATEWAY; } pAddress = rt_key (pRoute); addrlen = ROUNDUP(pAddress->sa_len); pBuffer = (char *)pMessage; if (pBuffer) { /* Copy the destination address for the route entries. */ pBuffer += length; bcopy ( (char *)pAddress, pBuffer, addrlen); pBuffer += addrlen; } length += addrlen; /* * Find the length of all entries for the specified destination * and netmask. Copy the relevant values if appropriate. */ for (pGroup = (ROUTE_ENTRY *)pRoute; pGroup != NULL; pGroup = pGroup->diffNode.pFrwd) { for (pMatch = pGroup; pMatch != NULL; pMatch = pMatch->sameNode.pFrwd) { pAddress = ROUTE_ENTRY_GATEWAY (pMatch); if (pAddress->sa_family == AF_LINK) { /* * The entry contains an ARP template. Use the * interface's IP address as the gateway value. */ pAddress = pMatch->rtEntry.rt_ifa->ifa_addr; } addrlen = ROUNDUP(sizeof (struct sockaddr_gate)); if (pBuffer) { /* Copy the gateway address for the route entry. */ pGate = (struct sockaddr_gate *)pBuffer; pGate->gate_family = pAddress->sa_family; pGate->gate_addr = ( (struct sockaddr_in *)pAddress)->sin_addr.s_addr; /* Set length to reflect increased size for metrics. */ pGate->gate_len = sizeof (struct sockaddr_gate); /* Copy additional information into gateway field. */ pGate->routeProto = RT_PROTO_GET (ROUTE_ENTRY_KEY (pMatch)); pGate->weight = pMatch->rtEntry.rt_rmx.weight; pGate->value1 = pMatch->rtEntry.rt_rmx.value1; pGate->value2 = pMatch->rtEntry.rt_rmx.value2; pGate->value3 = pMatch->rtEntry.rt_rmx.value3; pGate->value4 = pMatch->rtEntry.rt_rmx.value4; pGate->value5 = pMatch->rtEntry.rt_rmx.value5; pGate->routeTag = pMatch->rtEntry.rt_rmx.routeTag; pBuffer += addrlen; } length += addrlen; } } /* Copy any netmask information for the route. */ pAddress = rt_mask (pRoute); if (pAddress) { addrlen = ROUNDUP(pAddress->sa_len); if (pBuffer) { bcopy ( (char *)pAddress, pBuffer, addrlen); pBuffer += addrlen; /* Indicate that netmask information is present in the message. */ pMessage->rtm_addrs |= RTA_NETMASK; } length += addrlen; } if (pMessage) { /* Set the total message length. */ pMessage->rtm_msglen = length; } return (length); }/********************************************************************************* routeMatch - find a unique entry within a set of duplicate routes** This routine searches the extended lists attached to the <pRoute>* primary route entry to find a matching route with the same next-hop* gateway as the <pGateway> argument and a creator which matches the* <protoId> value. That combination is unique for a particular destination* address and netmask. This routine allows routing sockets to retrieve* a duplicate route entry which is not visible to the IP forwarding process.** RETURNS: Pointer to existing route, or NULL if none.** NOMANUAL*/LOCAL ROUTE_ENTRY * routeMatch ( struct rtentry * pRoute, /* primary route for destination/netmask */ short protoId, /* protocol identifer for matching route */ struct sockaddr * pGateway /* next hop gateway for matching route */ ) { ROUTE_ENTRY * pGroup; /* route entries with matching protocol */ ROUTE_ENTRY * pMatch; /* exact match for protocol and gateway */ if (protoId) { /* Find the list of entries for the specified protocol. */ for (pGroup = (ROUTE_ENTRY *)pRoute; pGroup != NULL; pGroup = pGroup->diffNode.pFrwd) { if (RT_PROTO_GET(ROUTE_ENTRY_KEY(pGroup)) == protoId) break; } } else { /* No protocol ID specified: use the initial group. */ pGroup = (ROUTE_ENTRY *)pRoute; } /* Find matching gateway if matching protocol found. */ for (pMatch = pGroup; pMatch != NULL; pMatch = pMatch->sameNode.pFrwd) { if (ROUTE_ENTRY_GATEWAY (pMatch)->sa_family == AF_LINK) { /* * The gateway field contains an ARP template. The entry * only matches for a search using the interface's IP address * as the gateway. */ if (SOCKADDR_IN (pMatch->rtEntry.rt_ifa->ifa_addr) == SOCKADDR_IN (pGateway)) { /* Matching route entry found - halt search. */ break; } } else if (SOCKADDR_IN (ROUTE_ENTRY_GATEWAY (pMatch)) == SOCKADDR_IN (pGateway)) { /* Matching route entry found - halt search. */ break; } } return (pMatch); }#endif /* ROUTER_STACK */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -