📄 route.c
字号:
*/voidrtalloc(ro) register struct route *ro;{ if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) return; /* XXX */ ro->ro_rt = rtalloc1(&ro->ro_dst, 1);}struct rtentry *rtalloc1(dst, report) register struct sockaddr *dst; int report;{ register struct radix_node_head *rnh = rt_tables[dst->sa_family]; register struct rtentry *rt; register struct radix_node *rn; struct rtentry *newrt = 0; struct rt_addrinfo info; u_long tosRtMask; /* TOS route mask */ u_long newRtMask; /* TOS 0 route mask */ int s = splnet(), err = 0, msgtype = RTM_MISS; struct rtentry * tosRt = NULL; u_char savedTos; /* * save original tos since we overwrite it temporarily in the * dst socketaddr */ savedTos = TOS_GET (dst); /* * The Type of Service octet consists of three fields: * * 0 1 2 3 4 5 6 7 * +-----+-----+-----+-----+-----+-----+-----+-----+ * | | | | * | PRECEDENCE | TOS | MBZ | * | | | | * +-----+-----+-----+-----+-----+-----+-----+-----+ * * Precedence bits should not be considered when searching * the table. An existing matching route would not be found * and if a new route were created, since dst is copied to * generate the key, precedence bits would be part * of the new route's TOS field which is wrong. This * would create a leak if this wrong route were created * for a local address. ARP would hold on to a packet, * while it resolves the local address. When the reply * comes back, since ARP does not look for routes with * TOS set, the packet would never be sent. * */ TOS_SET(dst, savedTos & 0x1f);match: if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && ((rn->rn_flags & RNF_ROOT) == 0)) { newrt = rt = (struct rtentry *)rn; if ( (dst->sa_family == AF_INET) && (rt->rt_refcnt == 0) && (rt->rt_flags & RTF_DELETE) && !(rt->rt_flags & RTF_STATIC)) { /* * Reusing a (cloned) route to a remote destination. * Remove deletion tag and reset timer. * * NOTE: All manually added proxy ARP entries include * the RTF_ANNOUNCE flag which uses the same value as * the RTF_DELETE flag. The preceding test for RTF_STATIC * preserves the flag settings for those ARP entries, * even though the removal of RTF_ANNOUNCE should be * harmless since its only purpose is to trigger the * gratuitous ARP request when the entry is created. */ rt->rt_flags &= ~RTF_DELETE; rt->rt_rmx.rmx_expire = 0; } if (report && (rt->rt_flags & RTF_CLONING)) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 17, 9, WV_NETEVENT_RTALLOC_CLONE, ((struct sockaddr_in *)rt_key (rt))->sin_addr.s_addr, ((struct sockaddr_in *)dst)->sin_addr.s_addr)#endif /* INCLUDE_WVNET */#endif err = rtrequest(RTM_RESOLVE, dst, SA(0), SA(0), 0, &newrt); if (err) { newrt = rt; rt->rt_refcnt++; goto miss; } if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { msgtype = RTM_RESOLVE; goto miss; } } else {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_DSTADDROUT_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 18, 10, ((struct sockaddr_in *)dst)->sin_addr.s_addr, WV_NETEVENT_RTALLOC_SEARCHGOOD, ((struct sockaddr_in *)dst)->sin_addr.s_addr)#endif /* INCLUDE_WVNET */#endif rt->rt_refcnt++; } } else { rtstat.rts_unreach++; miss:#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_CRITICAL event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_CRITICAL, 26, 5, WV_NETEVENT_RTALLOC_SEARCHFAIL, ((struct sockaddr_in *)dst)->sin_addr.s_addr)#endif /* INCLUDE_WVNET */#endif if (report) { bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = dst; if (rtMissMsgHook) (*rtMissMsgHook) (msgtype, &info, 0, err); } } /* * RFC 1583 Section 11.1: * * "Select the routing table entry whose value matches the TOS found * in the packet header. If there is no routing table entry for * this TOS, select the routing table entry for TOS 0. In other * words, packets requesting TOS X are routed along the TOS 0 * path if a TOS X path does not exist." * See also RFC 1349, Appendix B.4. */ if (TOS_GET (dst) != 0) { TOS_SET (dst, 0); tosRt = newrt; newrt = NULL; goto match; } /* * tosRt is the TOS route match, if any. If none exists, tosRt is the * default route ("0.0.0.0"), if any. Otherwise, tosRt is NULL. * newrt is the TOS 0 route. */ if (tosRt != NULL) { if (newrt != NULL) { /* * Host route entries created by ARP have null masks with * implied mask = 0xffffffff */ tosRtMask = (rt_mask (tosRt) == NULL) ? 0xffffffff : ((struct sockaddr_in *) rt_mask (tosRt))->sin_addr.s_addr;#ifdef RTALLOC_DEBUG printf("\nBEST MATCHING TOS ROUTE:\n"); routeEntryDebugShow ((struct radix_node *)tosRt); printf("\nTOS 0 ROUTE:\n"); routeEntryDebugShow ((struct radix_node *)newrt);#endif /* RTALLOC_DEBUG */ newRtMask = (rt_mask (newrt) == NULL) ? 0xffffffff : ((struct sockaddr_in *) rt_mask (newrt))->sin_addr.s_addr; /* * select the route with longest netmask. we assume * contiguous masks starting at the same bit position. * The default route has a mask = 0x00000000 */ if (tosRtMask >= newRtMask) { RTFREE (newrt); newrt = tosRt; } else { /* newrt is more specific: keep it */ RTFREE (tosRt); } } else /* newrt is NULL */ { /* * Restore previously found TOS route. Can happen if there is a * route entered with TOS set, but no default route exists nor * route match with 0 TOS. */ newrt = tosRt; } }#ifdef RTALLOC_DEBUG if (savedTos && newrt != NULL) { printf ("\nSELECTED ROUTE:\n"); routeEntryDebugShow ((struct radix_node *)newrt); }#endif /* RTALLOC_DEBUG */ /* Restore the saved TOS. */ TOS_SET (dst, savedTos); splx(s); return (newrt);} /* * This version of the route search routine is specifically designed * for retrieving a route when forwarding packets. Unlike the original * case, this route search never clones routes to remote destinations. * Those cloned routes are necessary for path MTU discovery, but should * only exist when the Internet host originates the traffic, not when * it forwards it as a router. */struct rtentry *rtalloc2(dst) register struct sockaddr *dst;{ register struct radix_node_head *rnh = rt_tables[dst->sa_family]; register struct rtentry *rt; register struct radix_node *rn; struct rtentry *newrt = 0; struct rt_addrinfo info; int s = splnet(), err = 0, msgtype = RTM_MISS; struct rtentry * tosRt = NULL; u_long tosRtMask; /* TOS route mask */ u_long newRtMask; /* TOS 0 route mask */ u_char savedTos; /* * save original tos since we overwrite it temporarily in the * dst socketaddr */ savedTos = TOS_GET (dst);match: if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && ((rn->rn_flags & RNF_ROOT) == 0)) { newrt = rt = (struct rtentry *)rn; if ( (dst->sa_family == AF_INET) && (rt->rt_refcnt == 0) && (rt->rt_flags & RTF_DELETE) && !(rt->rt_flags & RTF_STATIC)) { /* * Reusing a (cloned) route to a remote destination. * Remove deletion tag and reset timer. * * NOTE: All manually added proxy ARP entries include * the RTF_ANNOUNCE flag which uses the same value as * the RTF_DELETE flag. The preceding test for RTF_STATIC * preserves the flag settings for those ARP entries, * even though the removal of RTF_ANNOUNCE should be * harmless since its only purpose is to trigger the * gratuitous ARP request when the entry is created. */ rt->rt_flags &= ~RTF_DELETE; rt->rt_rmx.rmx_expire = 0; } /* * Disable cloning when forwarding data to a remote * destination. This search will still create a * cloned entry if the destination is directly reachable * to hold the ARP information for the target host. */ if ( !(rt->rt_flags & RTF_GATEWAY) && (rt->rt_flags & RTF_CLONING)) { err = rtrequest(RTM_RESOLVE, dst, SA(0), SA(0), 0, &newrt); if (err) { newrt = rt; rt->rt_refcnt++; goto miss; } if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { msgtype = RTM_RESOLVE; goto miss; } } else rt->rt_refcnt++; } else { rtstat.rts_unreach++; miss: bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = dst; if (rtMissMsgHook) (*rtMissMsgHook) (msgtype, &info, 0, err); } /* * RFC 1583 Section 11.1: * * "Select the routing table entry whose value matches the TOS found * in the packet header. If there is no routing table entry for * this TOS, select the routing table entry for TOS 0. In other * words, packets requesting TOS X are routed along the TOS 0 * path if a TOS X path does not exist." * See also RFC 1349, Appendix B.4. */ if (TOS_GET (dst) != 0) { TOS_SET (dst, 0); tosRt = newrt; newrt = NULL; goto match; } /* * tosRt is the TOS route match, if any. If none exists, tosRt is the * default route ("0.0.0.0"), if any. Otherwise, tosRt is NULL. * newrt is the TOS 0 route. */ if (tosRt != NULL) { if (newrt != NULL) { /* * Host route entries created by ARP have null masks with * implied mask = 0xffffffff */ tosRtMask = (rt_mask (tosRt) == NULL) ? 0xffffffff : ((struct sockaddr_in *) rt_mask (tosRt))->sin_addr.s_addr; newRtMask = (rt_mask (newrt) == NULL) ? 0xffffffff : ((struct sockaddr_in *) rt_mask (newrt))->sin_addr.s_addr; /* * select the route with longest netmask. we assume * contiguous masks starting at the same bit position. * The default route has a mask = 0x00000000 */ if (tosRtMask >= newRtMask) { RTFREE (newrt); newrt = tosRt; } else { /* newrt is more specific: keep it */ RTFREE (tosRt); } } else /* newrt is NULL */ { /* * Restore previously found TOS route. Can happen if there is a * route entered with TOS set, but no default route exists nor * route match with 0 TOS. */ newrt = tosRt; } } /* * restore the saved tos. is redundant but harmless in case tos * was default to start with. */ TOS_SET (dst, savedTos); splx(s); return (newrt); }voidrtfree(rt) register struct rtentry *rt;{ register struct ifaddr *ifa;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ if (rt) { WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 19, 11, WV_NETEVENT_RTFREE_START, ((struct sockaddr_in *)rt_key (rt))->sin_addr.s_addr, rt->rt_refcnt) } else { WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 19, 11, WV_NETEVENT_RTFREE_START, 0, 0) }#endif /* INCLUDE_WVNET */#endif if (rt == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 21, 1, WV_NETEVENT_RTFREE_PANIC)#endif /* INCLUDE_WVNET */#endif panic("rtfree"); } rt->rt_refcnt--; if (rt_key(rt)->sa_family == AF_INET) { /* * If route was cloned for path MTU results, mark for later * removal (if not reused) instead of deleting immediately. */ if ( (rt->rt_refcnt == 0) && (rt->rt_flags & RTF_UP) && (rt->rt_flags & RTF_HOST) && !(rt->rt_flags & RTF_LLINFO) && (rt->rt_flags & RTF_CLONED)) { rt->rt_flags |= RTF_DELETE; if (rt->rt_rmx.rmx_expire == 0) /* Not yet assigned. */ rt->rt_rmx.rmx_expire = tickGet() + routePendInterval; } } if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 21, 1, WV_NETEVENT_RTFREE_PANIC)#endif /* INCLUDE_WVNET */#endif panic ("rtfree 2"); } rttrash--; if (rt->rt_refcnt < 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_ALERT event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_ALERT, 8, 4, WV_NETEVENT_RTFREE_BADREFCNT)#endif /* INCLUDE_WVNET */#endif logMsg ("rtfree: %x not freed (neg refs)\n", (int)rt, 0, 0, 0, 0, 0); return; } ifa = rt->rt_ifa; IFAFREE(ifa); if (rt->rt_parent) { RTFREE (rt->rt_parent) } Free(rt_key(rt));#ifdef ROUTER_STACK /* * Entries which are not directly attached to the * tree use a different free routine since the netmask * information is stored in a uniquely allocated buffer, * not shared among multiple route entries. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -