summaryrefslogtreecommitdiffstats
path: root/sys/net/route.c
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1997-03-05 08:01:28 +0000
committerjulian <julian@FreeBSD.org>1997-03-05 08:01:28 +0000
commit5b5d5406a485cb9b2d27d33fa7fa96b5502b3ccc (patch)
treec6f90393247bf45e24066629e63ff5785ecaca74 /sys/net/route.c
parentb3456b411af390e7671cf607c8b0551ea0b3b4bd (diff)
downloadFreeBSD-src-5b5d5406a485cb9b2d27d33fa7fa96b5502b3ccc.zip
FreeBSD-src-5b5d5406a485cb9b2d27d33fa7fa96b5502b3ccc.tar.gz
add a bunch of comments to describe what's going on.
This is some of the worst code I've had to wade through in ages and I don't want to have to start from scratch again next time. (I have a 2.2 version of these comments, can I commit them?)
Diffstat (limited to 'sys/net/route.c')
-rw-r--r--sys/net/route.c139
1 files changed, 123 insertions, 16 deletions
diff --git a/sys/net/route.c b/sys/net/route.c
index 0fd7866..b7f17eb 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)route.c 8.2 (Berkeley) 11/15/93
- * $Id$
+ * $Id: route.c,v 1.40 1997/02/22 09:41:14 peter Exp $
*/
#include "opt_mrouting.h"
@@ -186,34 +186,74 @@ rtalloc1(dst, report, ignflags)
return (newrt);
}
+/*
+ * Remove a reference count from an rtentry.
+ * If the count gets low enough, take it out of the routing table
+ */
void
rtfree(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;
}
- ifa = rt->rt_ifa;
- IFAFREE(ifa);
+#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);
}
}
@@ -303,6 +343,9 @@ rtredirect(dst, gateway, netmask, flags, src, rtp)
rt->rt_flags |= RTF_MODIFIED;
flags |= RTF_MODIFIED;
stat = &rtstat.rts_newgateway;
+ /*
+ * add the key and gateway (in one malloc'd chunk).
+ */
rt_setgate(rt, rt_key(rt), gateway);
}
} else
@@ -470,19 +513,27 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
* NB: RTF_UP must be set during the search above,
* because we might delete the last ref, causing
* rt to get freed prematurely.
+ * eh? then why not just add a reference?
+ * I'm not sure how RTF_UP helps matters. (JRE)
*/
rt->rt_flags &= ~RTF_UP;
/*
- * If there is llinfo or similar associated with the
- * route, give the protocol a chance to deal with it..
+ * give the protocol a chance to keep things in sync.
*/
if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
+
+ /*
+ * one more rtentry floating around that is not
+ * linked to the routing table.
+ */
rttrash++;
+
/*
- * If the caller wants it, then it can have it, but it's up to it
- * to free the rtentry as we won't be doing it.
+ * If the caller wants it, then it can have it,
+ * but it's up to it to free the rtentry as we won't be
+ * doing it.
*/
if (ret_nrt)
*ret_nrt = rt;
@@ -517,19 +568,32 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
senderr(ENOBUFS);
Bzero(rt, sizeof(*rt));
rt->rt_flags = RTF_UP | flags;
+ /*
+ * Add the gateway. Possibly re-malloc-ing the storage for it
+ * also add the rt_gwroute if possible.
+ */
if (error = rt_setgate(rt, dst, gateway)) {
Free(rt);
senderr(error);
}
+
+ /*
+ * point to the (possibly newly malloc'd) dest address.
+ */
ndst = rt_key(rt);
+
+ /*
+ * make sure it contains the value we want (masked if needed).
+ */
if (netmask) {
rt_maskedcopy(dst, ndst, netmask);
} else
Bcopy(dst, ndst, dst->sa_len);
/*
+ * Note that we now have a reference to the ifa.
* This moved from below so that rnh->rnh_addaddr() can
- * examine the ifa and ifp if it so desires.
+ * examine the ifa and ifa->ifa_ifp if it so desires.
*/
ifa->ifa_refcnt++;
rt->rt_ifa = ifa;
@@ -557,10 +621,15 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
(caddr_t)netmask,
rnh, rt->rt_nodes);
} else if (rt2) {
+ /* undo the extra ref we got */
RTFREE(rt2);
}
}
+ /*
+ * If it still failed to go into the tree,
+ * then un-make it (this should be a function)
+ */
if (rn == 0) {
if (rt->rt_gwroute)
rtfree(rt->rt_gwroute);
@@ -571,8 +640,14 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
Free(rt);
senderr(EEXIST);
}
+
rt->rt_parent = 0;
+ /*
+ * If we got here from RESOLVE, then we are cloning
+ * so clone the rest, and note that we
+ * are a clone (and increment the parent's references)
+ */
if (req == RTM_RESOLVE) {
rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
if ((*ret_nrt)->rt_flags & RTF_PRCLONING) {
@@ -580,8 +655,14 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
(*ret_nrt)->rt_refcnt++;
}
}
+
+ /*
+ * if this protocol has something to add to this then
+ * allow it to do that as well.
+ */
if (ifa->ifa_rtrequest)
ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0));
+
/*
* We repeat the same procedure from rt_setgate() here because
* it doesn't fire when we call it there because the node
@@ -595,6 +676,10 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
rt_fixchange, &arg);
}
+ /*
+ * actually return a resultant rtentry and
+ * give the caller a single reference.
+ */
if (ret_nrt) {
*ret_nrt = rt;
rt->rt_refcnt++;
@@ -737,6 +822,12 @@ rt_setgate(rt0, dst, gate)
return EADDRNOTAVAIL;
}
+ /*
+ * Both dst and gateway are stored in the same malloc'd chunk
+ * (If I ever get my hands on....)
+ * if we need to malloc a new chunk, then keep the old one around
+ * till we don't need it any more.
+ */
if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) {
old = (caddr_t)rt_key(rt);
R_Malloc(new, caddr_t, dlen + glen);
@@ -744,14 +835,31 @@ rt_setgate(rt0, dst, gate)
return ENOBUFS;
rt->rt_nodes->rn_key = new;
} else {
+ /*
+ * otherwise just overwrite the old one
+ */
new = rt->rt_nodes->rn_key;
old = 0;
}
+
+ /*
+ * copy the new gateway value into the memory chunk
+ */
Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen);
+
+ /*
+ * if we are replacing the chunk (or it's new) we need to
+ * replace the dst as well
+ */
if (old) {
Bcopy(dst, new, dlen);
Free(old);
}
+
+ /*
+ * If there is already a gwroute, it's now almost definitly wrong
+ * so drop it.
+ */
if (rt->rt_gwroute) {
rt = rt->rt_gwroute; RTFREE(rt);
rt = rt0; rt->rt_gwroute = 0;
@@ -764,7 +872,7 @@ rt_setgate(rt0, dst, gate)
* protocol-cloning to operate for gateways (which is probably the
* correct choice anyway), and avoid the resulting reference loops
* by disallowing any route to run through itself as a gateway.
- * This is obviuosly mandatory when we get rt->rt_output().
+ * This is obviously mandatory when we get rt->rt_output().
*/
if (rt->rt_flags & RTF_GATEWAY) {
rt->rt_gwroute = rtalloc1(gate, 1, RTF_PRCLONING);
@@ -847,7 +955,7 @@ rtinit(ifa, cmd, flags)
}
/*
* Get an rtentry that is in the routing tree and
- * contains the correct info. (if this fails we can't get there).
+ * contains the correct info. (if this fails, can't get there).
* We set "report" to FALSE so that if it doesn't exist,
* it doesn't report an error or clone a route, etc. etc.
*/
@@ -925,9 +1033,9 @@ rtinit(ifa, cmd, flags)
printf("rtinit: wrong ifa (%p) was (%p)\n", ifa,
rt->rt_ifa);
/*
- * Ask that the route we got back be removed
- * from the routing tables as we are trying
- * to supersede it.
+ * Ask that the protocol in question
+ * remove anything it has associated with
+ * this route and ifaddr.
*/
if (rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
@@ -943,9 +1051,8 @@ rtinit(ifa, cmd, flags)
rt->rt_ifp = ifa->ifa_ifp;
ifa->ifa_refcnt++;
/*
- * Now add it to the routing table
- * XXX could we have just left it?
- * as it might have been in the right place..
+ * Now ask the protocol to check if it needs
+ * any special processing in it's new form.
*/
if (ifa->ifa_rtrequest)
ifa->ifa_rtrequest(RTM_ADD, rt, SA(0));
OpenPOWER on IntegriCloud