route.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,191 行 · 第 1/3 页
C
1,191 行
//==========================================================================//// src/sys/net/route.c////==========================================================================//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD, // FreeBSD or other sources, and are covered by the appropriate// copyright disclaimers included herein.//// Portions created by Red Hat are// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================/* * Copyright (c) 1980, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)route.c 8.2 (Berkeley) 11/15/93 * $FreeBSD: src/sys/net/route.c,v 1.59.2.3 2001/07/29 19:18:02 ume Exp $ */#include <sys/param.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/domain.h>#include <net/if.h>#include <net/route.h>#include <netinet/in.h>#include <netinet/ip_mroute.h>#include <sys/sockio.h> // for eCos routing protocols#define SA(p) ((struct sockaddr *)(p))struct route_cb route_cb;static struct rtstat rtstat;struct radix_node_head *rt_tables[AF_MAX+1];static int rttrash; /* routes not in table but not freed */static void rt_maskedcopy __P((struct sockaddr *, struct sockaddr *, struct sockaddr *));static void rtable_init __P((void **));static voidrtable_init(table) void **table;{ struct domain *dom; for (dom = domains; dom; dom = dom->dom_next) if (dom->dom_rtattach) dom->dom_rtattach(&table[dom->dom_family], dom->dom_rtoffset);}static void call_route_init( void * arg ){ route_init();}voidroute_init(){ rn_init(); /* initialize all zeroes, all ones, mask table */ rtable_init((void **)rt_tables);}// FIXME: This function is only here because BOOTP fails on a second interface.// This failure is due to the fact that a route to 0.0.0.0 seems to be// incredibly sticky, i.e. can't be deleted. BOOTP uses this to// achieve a generic broadcast. Sadly it seems that BOOTP servers will// only work this way, thus the hack.//// This version enumerates all IPv4 routes and deletes them - this leaks less// store than the previous version.static intrt_reinit_rtdelete( struct radix_node *rn, void *vifp ){ struct rtentry *rt = (struct rtentry *)rn; if (rt->rt_ifa->ifa_addr->sa_family == AF_INET) { rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 0, NULL); } return (0);}voidcyg_route_reinit(void){ int i; for (i = 0; i < AF_MAX+1; i++) { struct radix_node_head *rnh; rnh = rt_tables[i]; if (rnh) { (*rnh->rnh_walktree)(rnh, rt_reinit_rtdelete, NULL); } }}/* * Packet routing routines. */voidrtalloc(ro) register struct route *ro;{ rtalloc_ign(ro, 0UL);}voidrtalloc_ign(ro, ignore) register struct route *ro; u_long ignore;{ struct rtentry *rt; int s; if ((rt = ro->ro_rt) != NULL) { if (rt->rt_ifp != NULL && rt->rt_flags & RTF_UP) return; /* XXX - We are probably always at splnet here already. */ s = splnet(); RTFREE(rt); ro->ro_rt = NULL; splx(s); } ro->ro_rt = rtalloc1(&ro->ro_dst, 1, ignore);}/* * Look up the route that matches the address given * Or, at least try.. Create a cloned route if needed. */struct rtentry *rtalloc1(dst, report, ignflags) register struct sockaddr *dst; int report; u_long ignflags;{ 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 nflags; int s = splnet(), err = 0, msgtype = RTM_MISS; /* * Look up the address in the table for that Address Family */ if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && ((rn->rn_flags & RNF_ROOT) == 0)) { /* * If we find it and it's not the root node, then * get a refernce on the rtentry associated. */ newrt = rt = (struct rtentry *)rn; nflags = rt->rt_flags & ~ignflags; if (report && (nflags & (RTF_CLONING | RTF_PRCLONING))) { /* * We are apparently adding (report = 0 in delete). * If it requires that it be cloned, do so. * (This implies it wasn't a HOST route.) */ err = rtrequest(RTM_RESOLVE, dst, SA(0), SA(0), 0, &newrt); if (err) { /* * If the cloning didn't succeed, maybe * what we have will do. Return that. */ newrt = rt; rt->rt_refcnt++; goto miss; } if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { /* * If the new route specifies it be * externally resolved, then go do that. */ msgtype = RTM_RESOLVE; goto miss; } } else rt->rt_refcnt++; } else { /* * Either we hit the root or couldn't find any match, * Which basically means * "caint get there frm here" */ rtstat.rts_unreach++; miss: if (report) { /* * If required, report the failure to the supervising * Authorities. * For a delete, this is not an error. (report == 0) */ bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = dst; rt_missmsg(msgtype, &info, 0, err); } } splx(s); return (newrt);}/* * Remove a reference count from an rtentry. * If the count gets low enough, take it out of the routing table */voidrtfree(rt) register struct rtentry *rt;{ /* * find the tree for that address family */ register struct radix_node_head *rnh = rt_tables[rt_key(rt)->sa_family]; register struct ifaddr *ifa; if (rt == 0 || rnh == 0) panic("rtfree"); /* * decrement the reference count by one and if it reaches 0, * and there is a close function defined, call the close function */ rt->rt_refcnt--; if(rnh->rnh_close && rt->rt_refcnt == 0) { rnh->rnh_close((struct radix_node *)rt, rnh); } /* * If we are no longer "up" (and ref == 0) * then we can free the resources associated * with the route. */ if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) panic ("rtfree 2"); /* * the rtentry must have been removed from the routing table * so it is represented in rttrash.. remove that now. */ rttrash--;#ifdef DIAGNOSTIC if (rt->rt_refcnt < 0) { printf("rtfree: %p not freed (neg refs)\n", rt); return; }#endif /* * release references on items we hold them on.. * e.g other routes and ifaddrs. */ if((ifa = rt->rt_ifa)) IFAFREE(ifa); if (rt->rt_parent) { RTFREE(rt->rt_parent); } /* * The key is separatly alloc'd so free it (see rt_setgate()). * This also frees the gateway, as they are always malloc'd * together. */ Free(rt_key(rt)); /* * and the rtentry itself of course */ Free(rt); }}voidifafree(ifa) register struct ifaddr *ifa;{ if (ifa == NULL) panic("ifafree"); if (ifa->ifa_refcnt == 0) free(ifa, M_IFADDR); else ifa->ifa_refcnt--;}/* * 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 * */voidrtredirect(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, 0UL); /* * 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) \ ((a1)->sa_len == (a2)->sa_len && \ 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; error = rtrequest((int)RTM_ADD, dst, gateway, netmask, flags, (struct rtentry **)0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?