can generate new routing table entries
SCCS-vsn: sys/net/route.c 4.20
SCCS-vsn: sys/net/route.h 4.10
-/* route.c 4.19 83/04/05 */
+/* route.c 4.20 83/05/30 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/param.h"
#include "../h/systm.h"
#include "../net/route.h"
int rttrash; /* routes not in table but not freed */
#include "../net/route.h"
int rttrash; /* routes not in table but not freed */
+struct sockaddr wildcard; /* zero valued cookie for wildcard searches */
+
/*
* Packet routing routines.
*/
rtalloc(ro)
register struct route *ro;
{
/*
* Packet routing routines.
*/
rtalloc(ro)
register struct route *ro;
{
- register struct rtentry *rt, *rtmin;
+ register struct rtentry *rt;
register struct mbuf *m;
register unsigned hash;
register struct mbuf *m;
register unsigned hash;
- register int (*match)();
- struct afhash h;
struct sockaddr *dst = &ro->ro_dst;
struct sockaddr *dst = &ro->ro_dst;
+ int (*match)(), doinghost;
+ struct afhash h;
u_int af = dst->sa_family;
u_int af = dst->sa_family;
+ struct rtentry *rtmin;
+ struct mbuf **table;
if (ro->ro_rt && ro->ro_rt->rt_ifp) /* XXX */
return;
if (af >= AF_MAX)
return;
(*afswitch[af].af_hash)(dst, &h);
if (ro->ro_rt && ro->ro_rt->rt_ifp) /* XXX */
return;
if (af >= AF_MAX)
return;
(*afswitch[af].af_hash)(dst, &h);
- rtmin = 0, hash = h.afh_hosthash;
- for (m = rthost[hash % RTHASHSIZ]; m; m = m->m_next) {
- rt = mtod(m, struct rtentry *);
- if (rt->rt_hash != hash)
- continue;
- if ((rt->rt_flags & RTF_UP) == 0 ||
- (rt->rt_ifp->if_flags & IFF_UP) == 0)
- continue;
- if (bcmp((caddr_t)&rt->rt_dst, (caddr_t)dst, sizeof (*dst)))
- continue;
- if (rtmin == 0 || rt->rt_use < rtmin->rt_use)
- rtmin = rt;
- }
- if (rtmin)
- goto found;
-
- hash = h.afh_nethash;
match = afswitch[af].af_netmatch;
match = afswitch[af].af_netmatch;
- for (m = rtnet[hash % RTHASHSIZ]; m; m = m->m_next) {
+ hash = h.afh_hosthash, table = rthost, doinghost = 1;
+again:
+ for (m = table[hash % RTHASHSIZ]; m; m = m->m_next) {
rt = mtod(m, struct rtentry *);
if (rt->rt_hash != hash)
continue;
if ((rt->rt_flags & RTF_UP) == 0 ||
(rt->rt_ifp->if_flags & IFF_UP) == 0)
continue;
rt = mtod(m, struct rtentry *);
if (rt->rt_hash != hash)
continue;
if ((rt->rt_flags & RTF_UP) == 0 ||
(rt->rt_ifp->if_flags & IFF_UP) == 0)
continue;
- if (rt->rt_dst.sa_family != af || !(*match)(&rt->rt_dst, dst))
- continue;
+ if (doinghost) {
+ if (bcmp((caddr_t)&rt->rt_dst, (caddr_t)dst,
+ sizeof (*dst)))
+ continue;
+ } else {
+ if (rt->rt_dst.sa_family != af ||
+ !(*match)(&rt->rt_dst, dst))
+ continue;
+ }
if (rtmin == 0 || rt->rt_use < rtmin->rt_use)
rtmin = rt;
}
if (rtmin == 0 || rt->rt_use < rtmin->rt_use)
rtmin = rt;
}
+ if (rtmin == 0 && doinghost) {
+ doinghost = 0;
+ hash = h.afh_nethash, table = rtnet;
+ goto again;
+ }
+ /*
+ * Check for wildcard gateway, by convention network 0.
+ */
+ if (rtmin == 0 && dst != &wildcard) {
+ dst = &wildcard, hash = 0;
+ goto again;
+ }
- if (rtmin)
- rtmin->rt_refcnt++;
+ if (rtmin == 0) {
+ rtstat.rts_unreach++;
+ return;
+ }
+ rtmin->rt_refcnt++;
+ if (dst == &wildcard)
+ rtstat.rts_wildcard++;
*
* Should notify all parties with a reference to
* the route that it's changed (so, for instance,
*
* Should notify all parties with a reference to
* the route that it's changed (so, for instance,
- * round trip time estimates may be recalculated),
+ * current round trip time estimates could be flushed),
* but we have no back pointers at the moment.
*/
rtredirect(dst, gateway)
* but we have no back pointers at the moment.
*/
rtredirect(dst, gateway)
register struct rtentry *rt;
/* verify the gateway is directly reachable */
register struct rtentry *rt;
/* verify the gateway is directly reachable */
- if (if_ifwithnet(gateway) == 0)
+ if (if_ifwithnet(gateway) == 0) {
+ rtstat.rts_badredirect++;
rtalloc(&ro);
rt = ro.ro_rt;
rtalloc(&ro);
rt = ro.ro_rt;
+ /*
+ * Create a new entry if 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) {
+ rtinit(dst, gateway, RTF_GATEWAY);
+ rtstat.rts_dynamic++;
+ return;
+ }
/*
* Don't listen to the redirect if it's
* for a route to an interface.
/*
* Don't listen to the redirect if it's
* for a route to an interface.
- *
- * Should probably create a new entry when
- * the lookup fails. This will be necessary
- * when wildcard routes are added.
- if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) == 0)
+ if (rt->rt_flags & RTF_GATEWAY) {
+ /*
+ * Smash the current notion of the gateway to
+ * this destination. This is probably not right,
+ * as it's conceivable a flurry of redirects could
+ * cause the gateway value to fluctuate wildly during
+ * dynamic routing reconfiguration.
+ */
+ rt->rt_gateway = *gateway;
+ rtfree(rt);
+ rtstat.rts_newgateway++;
- rt->rt_gateway = *gateway;
- rtfree(rt);
}
/*
* Carry out a request to change the routing table. Called by
}
/*
* Carry out a request to change the routing table. Called by
- * interfaces at boot time to make their ``local routes'' known
- * and for ioctl's.
+ * interfaces at boot time to make their ``local routes'' known,
+ * for ioctl's, and as the result of routing redirects.
*/
rtrequest(req, entry)
int req;
*/
rtrequest(req, entry)
int req;
-/* route.h 4.9 83/05/12 */
+/* route.h 4.10 83/05/30 */
/*
* Kernel resident routing tables.
*
* The routing tables are initialized at boot time by
* making entries for all directly connected interfaces.
/*
* Kernel resident routing tables.
*
* The routing tables are initialized at boot time by
* making entries for all directly connected interfaces.
- * Routing daemons can thereafter update the routing tables.
- *
- * TODO:
- * keep statistics
u_long rt_use; /* raw # packets forwarded */
struct ifnet *rt_ifp; /* the answer: interface to use */
};
u_long rt_use; /* raw # packets forwarded */
struct ifnet *rt_ifp; /* the answer: interface to use */
};
-#ifdef KERNEL
-#define RTHASHSIZ 7
-struct mbuf *rthost[RTHASHSIZ];
-struct mbuf *rtnet[RTHASHSIZ];
-#endif
#define RTF_UP 0x1 /* route useable */
#define RTF_GATEWAY 0x2 /* destination is a gateway */
#define RTF_HOST 0x4 /* host entry (net otherwise) */
#define RTF_UP 0x1 /* route useable */
#define RTF_GATEWAY 0x2 /* destination is a gateway */
#define RTF_HOST 0x4 /* host entry (net otherwise) */
+/*
+ * Routing statistics.
+ */
+struct rtstat {
+ short rts_badredirect; /* bogus redirect calls */
+ short rts_dynamic; /* routes created by redirects */
+ short rts_newgateway; /* routes modified by redirects */
+ short rts_unreach; /* lookups which failed */
+ short rts_wildcard; /* lookups satisfied by a wildcard */
+};
+
+#ifdef KERNEL
#define RTFREE(rt) \
if ((rt)->rt_refcnt == 1) \
rtfree(rt); \
else \
(rt)->rt_refcnt--;
#define RTFREE(rt) \
if ((rt)->rt_refcnt == 1) \
rtfree(rt); \
else \
(rt)->rt_refcnt--;
+
+#define RTHASHSIZ 7
+struct mbuf *rthost[RTHASHSIZ];
+struct mbuf *rtnet[RTHASHSIZ];
+struct rtstat rtstat;
+#endif