?? route.c
字號:
if ( ((ROUTE_ENTRY*)rt)->primaryRouteFlag == FALSE) routeEntryFree ((ROUTE_ENTRY*)rt, FALSE); else Free ((ROUTE_ENTRY*)rt);#else Free (rt);#endif /* ROUTER_STACK */ }}/* * Force a routing table entry to the specified * destination to go through the given gateway. * Normally called as a result of a routing redirect * message from the network layer. * * N.B.: must be called at splnet * */intrtredirect(dst, gateway, netmask, flags, src, rtp) struct sockaddr *dst, *gateway, *netmask, *src; int flags; struct rtentry **rtp;{ register struct rtentry *rt; int error = 0; short *stat = 0; struct rt_addrinfo info; struct ifaddr *ifa; /* verify the gateway is directly reachable */ if ((ifa = ifa_ifwithnet(gateway)) == 0) { error = ENETUNREACH; goto out; } rt = rtalloc1(dst, 0); /* * If the redirect isn't from our current router for this dst, * it's either old or wrong. If it redirects us to ourselves, * we have a routing loop, perhaps as a result of an interface * going down recently. */#define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0) if (!(flags & RTF_DONE) && rt && (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) error = EINVAL; else if (ifa_ifwithaddr(gateway)) error = EHOSTUNREACH; if (error) goto done; /* * Create a new entry if we just got back a wildcard entry * or the the lookup failed. This is necessary for hosts * which use routing redirects generated by smart gateways * to dynamically build the routing tables. */ if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) goto create; /* * Don't listen to the redirect if it's * for a route to an interface. */ if (rt->rt_flags & RTF_GATEWAY) { if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { /* * Changing from route to net => route to host. * Create new route, rather than smashing route to net. */ create: flags |= RTF_GATEWAY | RTF_DYNAMIC; /* * Create the new route entry using the default * weight. Do not report the change since the * later hook generates both types of messages. */ error = rtrequestAddEqui (dst, netmask, gateway, flags, M2_ipRouteProto_icmp, 0, FALSE, FALSE, NULL); /* error = rtrequest((int)RTM_ADD, dst, gateway, netmask, flags, (struct rtentry **)0); */ stat = &rtstat.rts_dynamic; } else { /* * Smash the current notion of the gateway to * this destination. Should check about netmask!!! */ if (!(error = rt_setgate (rt, rt_key(rt), gateway))) { rt->rt_flags |= RTF_MODIFIED; flags |= RTF_MODIFIED; stat = &rtstat.rts_newgateway; rt->rt_mod = tickGet(); /* last modified */ rtmodified++; } } } else error = EHOSTUNREACH;done: if (rt) { if (rtp && !error) *rtp = rt; else rtfree(rt); }out: if (error) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_CRITICAL event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_CRITICAL, 27, 6, WV_NETEVENT_RTRESET_BADDEST, error, ((struct sockaddr_in *)gateway)->sin_addr.s_addr)#endif /* INCLUDE_WVNET */#endif rtstat.rts_badredirect++; } else if (stat != NULL) (*stat)++; bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = dst; info.rti_info[RTAX_GATEWAY] = gateway; info.rti_info[RTAX_NETMASK] = netmask; info.rti_info[RTAX_AUTHOR] = src; if (rtMissMsgHook) (*rtMissMsgHook) (RTM_REDIRECT, &info, flags, error);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_4 (NET_AUX_EVENT, WV_NET_VERBOSE, 34, 14, WV_NETEVENT_RTRESET_STATUS, error, ((struct sockaddr_in *)dst)->sin_addr.s_addr, ((struct sockaddr_in *)gateway)->sin_addr.s_addr, ((struct sockaddr_in *)netmask)->sin_addr.s_addr)#endif /* INCLUDE_WVNET */#endif return (error); }/** Routing table ioctl interface.** WRS MODS support for this function is being for backward compatibility.* This function has be moved else where because the routing code has * nothing to do with internet specific addresses since routing is independent* of the sockaddress family.*/intrtioctl(req, data) int req; caddr_t data;{ struct ortentry * pORE = NULL; struct sockaddr netMask; struct sockaddr * pNetMask = &netMask; register u_long i; register u_long net; register struct in_ifaddr *ia;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 20, 12, WV_NETEVENT_RTIOCTL_START, req)#endif /* INCLUDE_WVNET */#endif if (req != SIOCADDRT && req != SIOCDELRT) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_ERROR event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 37, 8, WV_NETEVENT_RTIOCTL_BADREQ, req)#endif /* INCLUDE_WVNET */#endif return (EINVAL); } pORE = (struct ortentry *)data; /* BSD4.3 to BSD4.4 conversion */ if (req == SIOCADDRT) req = RTM_ADD; else req = RTM_DELETE; /* * Set the netmask to the netmask of the interface address. * This has to be removed if provision is made with routeAdd * to add the network mask. */ bzero ((caddr_t)&netMask, sizeof (struct sockaddr)); /* check for default gateway address */ if (((struct sockaddr_in *)(&pORE->rt_dst))->sin_addr.s_addr != INADDR_ANY ) { i = ntohl(((struct sockaddr_in*)&pORE->rt_dst)->sin_addr.s_addr); pNetMask->sa_family = AF_INET; pNetMask->sa_len = 8; if (IN_CLASSA(i)) { ((struct sockaddr_in *)pNetMask)->sin_addr.s_addr = htonl(IN_CLASSA_NET); net = i & IN_CLASSA_NET; } else if (IN_CLASSB(i)) { ((struct sockaddr_in *)pNetMask)->sin_addr.s_addr = htonl(IN_CLASSB_NET); net = i & IN_CLASSB_NET; } else if (IN_CLASSC(i)) { ((struct sockaddr_in *)pNetMask)->sin_addr.s_addr = htonl(IN_CLASSC_NET); net = i & IN_CLASSC_NET; } else { ((struct sockaddr_in *)pNetMask)->sin_addr.s_addr = htonl(IN_CLASSD_NET); net = i & IN_CLASSD_NET; } /* * Check whether network is a subnet; * if so, return subnet number. */#ifdef VIRTUAL_STACK for (ia = _in_ifaddr; ia; ia = ia->ia_next)#else for (ia = in_ifaddr; ia; ia = ia->ia_next)#endif /* VIRTUAL_STACK */ if (net == ia->ia_net) ((struct sockaddr_in *)pNetMask)->sin_addr.s_addr = htonl(ia->ia_subnetmask); in_socktrim ((struct sockaddr_in *)pNetMask); } pORE->rt_flags |= RTF_GATEWAY; if(pORE->rt_flags & RTF_HOST) pNetMask=0; #ifdef DEBUG logMsg("rtIoctl:before rtrequestAddEqui/DelEqui\n",0,0,0,0,0,0);#endif /* * Add the requested route using the default weight value or delete * the matching entry. In either case, report the change using both * routing socket messages and direct callbacks. */ if(req==RTM_ADD) return (rtrequestAddEqui (&pORE->rt_dst, pNetMask, &pORE->rt_gateway, pORE->rt_flags, M2_ipRouteProto_other, 0, TRUE, TRUE, NULL)); else return (rtrequestDelEqui (&pORE->rt_dst, pNetMask, &pORE->rt_gateway, pORE->rt_flags, M2_ipRouteProto_other, TRUE, TRUE, NULL));}#define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))int rt_fixdelete (struct radix_node *, void *);static int rt_fixchange (struct radix_node *, void *);intrtrequest(req, dst, gateway, netmask, flags, ret_nrt) int req, flags; struct sockaddr *dst, *gateway, *netmask; struct rtentry **ret_nrt;{ int s = splnet(); int error = 0; register struct rtentry *rt; register struct radix_node *rn; register struct radix_node_head *rnh; struct ifaddr *ifa; struct sockaddr *ndst;#define senderr(x) { error = x ; goto bad; } if ((rnh = rt_tables[dst->sa_family]) == 0) senderr(ESRCH); if (flags & RTF_HOST) { netmask = 0; } if (netmask) { TOS_SET (netmask, 0x1f); /* set the 5 bits in the mask corresponding to the TOS bits */ } switch (req) { case RTM_DELETE: if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0) senderr(ESRCH); if (rn->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, 22, 2, WV_NETEVENT_RTREQ_PANIC)#endif /* INCLUDE_WVNET */#endif panic ("rtrequest delete"); } rt = (struct rtentry *)rn; /* * Search the appropriate subtree to remove any children * (created for path MTU results). This cleanup must occur * before clearing the RTF_UP flag or the system might * release the current node's memory prematurely if the * search deletes the last reference. */ if (dst->sa_family == AF_INET && (rt->rt_flags & RTF_CLONING) && netmask) { rn_walksubtree (rnh, dst, netmask, rt_fixdelete, rt); } rt->rt_flags &= ~RTF_UP; if (rt->rt_gwroute) { rt = rt->rt_gwroute; RTFREE(rt); (rt = (struct rtentry *)rn)->rt_gwroute = 0; } if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); rttrash++; if (ret_nrt) *ret_nrt = rt; else if (rt->rt_refcnt <= 0) { rt->rt_refcnt++; rtfree(rt); } rtmodified++; break; case RTM_RESOLVE: if (ret_nrt == 0 || (rt = *ret_nrt) == 0) {#ifdef DEBUG logMsg("rtrequest: RTM_RESOLVE, EINVAL error\n",0,0,0,0,0,0);#endif senderr(EINVAL); } ifa = rt->rt_ifa; flags = rt->rt_flags & ~RTF_CLONING; gateway = rt->rt_gateway; if ((netmask = rt->rt_genmask) == 0) { flags |= RTF_HOST; } goto makeroute; case RTM_ADD: if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0) senderr(ENETUNREACH); makeroute: R_Malloc(rt, struct rtentry *, sizeof(ROUTE_ENTRY)); if (rt == 0) senderr(ENOBUFS); Bzero(rt, sizeof (ROUTE_ENTRY)); rt->rt_flags = RTF_UP | flags; if (rt_setgate(rt, dst, gateway)) { Free(rt); senderr(ENOBUFS); } ndst = rt_key(rt); if (netmask) { rt_maskedcopy(dst, ndst, netmask); } else Bcopy(dst, ndst, dst->sa_len); /* Set IP routes to create children (for path MTU results). */ if (ndst->sa_family == AF_INET && !IN_MULTICAST (ntohl ( ((struct sockaddr_in *)ndst)->sin_addr.s_addr)) && ! (rt->rt_flags & RTF_HOST)) { if (((struct sockaddr_in *)netmask)->sin_addr.s_addr != 0xffffffff) { rt->rt_flags |= RTF_CLONING; } } rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask, rnh, rt->rt_nodes); /* update proto field of rt entry, in the gateway sockaddr */ if ((req == RTM_ADD) && (gateway->sa_family == AF_INET)) RT_PROTO_SET (ndst, RT_PROTO_GET (dst)); if (rn == 0 && (rt->rt_flags & RTF_HOST)) { /* Replace matching (cloned) entry if possible. */ rn = routeSwap (rnh, rt, ndst, netmask); } if (rn == 0) { if (rt->rt_gwroute) rtfree(rt->rt_gwroute); Free(rt_key(rt)); Free(rt); senderr(EEXIST); } ifa->ifa_refcnt++; rt->rt_ifa = ifa; rt->rt_ifp = ifa->ifa_ifp; if (req == RTM_RESOLVE) { rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ rt->rt_parent = (*ret_nrt); /* record source route */ (*ret_nrt)->rt_refcnt++; rt->rt_flags |= RTF_CLONED; /* * Mark the cloned route as a representative route * so that when it is deleted, Fastpath is called with * ROUTE_REP_DEL operation and the entry gets removed * from the Fastpath cache */ ((ROUTE_ENTRY*)rt)->primaryRouteFlag = TRUE; } if (rt->rt_ifp->if_type == IFT_PMP) { /* * Point-to-multipoint devices do not use a common * MTU value for all destinations or perform address * resolution, so cloning the interface route to store * that information is not necessary. */ rt->rt_flags &= ~RTF_CLONING; } /* Assign initial path MTU estimate, if enabled for route. */ if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU) && rt->rt_ifp) rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; if (ifa->ifa_rtrequest) ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0)); if (ndst->sa_family == AF_INET) { /* * Remove any cloned routes which a new * network route overrides. */ if (!(rt->rt_flags & RTF_HOST) && rt_mask (rt) != 0) { rn_walksubtree (rnh, ndst, netmask, rt_fixchange, rt); } } if (ret_nrt) { *ret_nrt = rt; rt->rt_refcnt++; } rt->rt_mod = tickGet(); /* last modified */ rtmodified++;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -