summaryrefslogtreecommitdiffstats
path: root/usr.sbin/routed/table.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/routed/table.c')
-rw-r--r--usr.sbin/routed/table.c138
1 files changed, 83 insertions, 55 deletions
diff --git a/usr.sbin/routed/table.c b/usr.sbin/routed/table.c
index c181be4..aa7510c 100644
--- a/usr.sbin/routed/table.c
+++ b/usr.sbin/routed/table.c
@@ -31,9 +31,12 @@
* SUCH DAMAGE.
*/
-#if !defined(lint) && !defined(sgi)
+#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
+#elif defined(__NetBSD__)
+static char rcsid[] = "$NetBSD$";
+#endif
+#ident "$Revision: 1.1.3.3 $"
#include "defs.h"
@@ -52,6 +55,8 @@ struct timeval need_kern = { /* need to update kernel table */
int stopint;
+int total_routes;
+
naddr age_bad_gate;
@@ -724,12 +729,12 @@ static struct khash {
u_short k_state;
#define KS_NEW 0x001
#define KS_DELETE 0x002
-#define KS_ADD 0x004
-#define KS_CHANGE 0x008
-#define KS_DEL_ADD 0x010
-#define KS_STATIC 0x020
-#define KS_GATEWAY 0x040
-#define KS_DYNAMIC 0x080
+#define KS_ADD 0x004 /* add to the kernel */
+#define KS_CHANGE 0x008 /* tell kernel to change the route */
+#define KS_DEL_ADD 0x010 /* delete & add to change the kernel */
+#define KS_STATIC 0x020 /* Static flag in kernel */
+#define KS_GATEWAY 0x040 /* G flag in kernel */
+#define KS_DYNAMIC 0x080 /* result of redirect */
#define KS_DELETED 0x100 /* already deleted */
time_t k_keep;
#define K_KEEP_LIM 30
@@ -767,7 +772,6 @@ kern_add(naddr dst, naddr mask)
k->k_dst = dst;
k->k_mask = mask;
k->k_state = KS_NEW;
- k->k_redirect_time = now.tv_sec;
k->k_keep = now.tv_sec;
*pk = k;
@@ -775,8 +779,8 @@ kern_add(naddr dst, naddr mask)
}
-/* If it has a non-zero metric, check that it is still in the table, not
- * having been deleted by interfaces coming and going.
+/* If a kernel route has a non-zero metric, check that it is still in the
+ * daemon table, and not deleted by interfaces coming and going.
*/
static void
kern_check_static(struct khash *k,
@@ -846,22 +850,25 @@ rtm_add(struct rt_msghdr *rtm,
k->k_state |= KS_GATEWAY;
if (rtm->rtm_flags & RTF_STATIC)
k->k_state |= KS_STATIC;
- if (rtm->rtm_flags & RTF_DYNAMIC) {
- k->k_state |= KS_DYNAMIC;
- k->k_redirect_time = now.tv_sec;
- /* Routers are not supposed to listen to redirects,
- * so delete it.
- */
+ if (0 != (rtm->rtm_flags & (RTF_DYNAMIC | RTF_MODIFIED))) {
if (supplier) {
- k->k_keep = now.tv_sec;
+ /* Routers are not supposed to listen to redirects,
+ * so delete it.
+ */
+ k->k_state &= ~KS_DYNAMIC;
+ k->k_state |= KS_DELETE;
trace_act("mark redirected %s --> %s for deletion"
- "since this is a router\n",
+ " since this is a router\n",
addrname(k->k_dst, k->k_mask, 0),
naddr_ntoa(k->k_gate));
+ } else {
+ k->k_state |= KS_DYNAMIC;
+ k->k_redirect_time = now.tv_sec;
}
}
- /* If it is not a static route, quite until it is time to delete it.
+ /* If it is not a static route, quit until the next comparison
+ * between the kernel and daemon tables, when it will be deleted.
*/
if (!(k->k_state & KS_STATIC)) {
k->k_state |= KS_DELETE;
@@ -876,7 +883,8 @@ rtm_add(struct rt_msghdr *rtm,
*/
ifp = iflookup(k->k_gate);
if (ifp == 0) {
- /* if there is no interface, maybe it is new
+ /* if there is no known interface,
+ * maybe there is a new interface
*/
ifinit();
ifp = iflookup(k->k_gate);
@@ -1096,11 +1104,11 @@ read_rt(void)
? HOST_MASK
: std_mask(S_ADDR(INFO_DST(&info))));
- strp += sprintf(strp, " %s",
+ strp += sprintf(strp, ": %s",
addrname(S_ADDR(INFO_DST(&info)), mask, 0));
if (IN_MULTICAST(ntohl(S_ADDR(INFO_DST(&info))))) {
- trace_act("ignore %s for multicast %s\n", str);
+ trace_act("ignore multicast %s\n", str);
continue;
}
@@ -1161,11 +1169,13 @@ kern_out(struct ag_info *ag)
* This includes routes that had RS_NET_SYN for interfaces that
* recently died.
*/
- if (ag->ag_metric == HOPCNT_INFINITY
- && 0 == kern_find(htonl(ag->ag_dst_h), ag->ag_mask, 0))
- return;
-
- k = kern_add(htonl(ag->ag_dst_h), ag->ag_mask);
+ if (ag->ag_metric == HOPCNT_INFINITY) {
+ k = kern_find(htonl(ag->ag_dst_h), ag->ag_mask, 0);
+ if (k == 0)
+ return;
+ } else {
+ k = kern_add(htonl(ag->ag_dst_h), ag->ag_mask);
+ }
if (k->k_state & KS_NEW) {
/* will need to add new entry to the kernel table */
@@ -1181,7 +1191,6 @@ kern_out(struct ag_info *ag)
return;
/* modify existing kernel entry if necessary */
- k->k_state &= ~KS_DELETE;
if (k->k_gate != ag->ag_gate
|| k->k_metric != ag->ag_metric) {
k->k_gate = ag->ag_gate;
@@ -1203,6 +1212,16 @@ kern_out(struct ag_info *ag)
k->k_state |= KS_GATEWAY;
k->k_state |= (KS_ADD | KS_DEL_ADD);
}
+
+ /* Deleting-and-adding is necessary to change aspects of a route.
+ * Just delete instead of deleting and then adding a bad route.
+ * Otherwise, we want to keep the route in the kernel.
+ */
+ if (k->k_metric == HOPCNT_INFINITY
+ && (k->k_state & KS_DEL_ADD))
+ k->k_state |= KS_DELETE;
+ else
+ k->k_state &= ~KS_DELETE;
#undef RT
}
@@ -1296,31 +1315,40 @@ fix_kern(void)
continue;
}
- if (k->k_state & KS_DELETE) {
+ if ((k->k_state & (KS_DELETE | KS_DYNAMIC))
+ == KS_DELETE) {
if (!(k->k_state & KS_DELETED))
rtioctl(RTM_DELETE,
- k->k_dst,k->k_gate,
- k->k_mask, 0, 0);
+ k->k_dst, k->k_gate, k->k_mask,
+ 0, 0);
*pk = k->k_next;
free(k);
continue;
}
- if (k->k_state & KS_DEL_ADD)
- rtioctl(RTM_DELETE,
- k->k_dst,k->k_gate,k->k_mask, 0, 0);
-
- flags = (k->k_state & KS_GATEWAY) ? RTF_GATEWAY : 0;
- if (k->k_state & KS_ADD) {
- rtioctl(RTM_ADD,
- k->k_dst, k->k_gate, k->k_mask,
- k->k_metric, flags);
- } else if (k->k_state & KS_CHANGE) {
- rtioctl(RTM_CHANGE,
- k->k_dst,k->k_gate,k->k_mask,
- k->k_metric, flags);
+ if (0 != (k->k_state&(KS_ADD|KS_CHANGE|KS_DEL_ADD))) {
+ if (k->k_state & KS_DEL_ADD) {
+ rtioctl(RTM_DELETE,
+ k->k_dst,k->k_gate,k->k_mask,
+ 0, 0);
+ k->k_state &= ~KS_DYNAMIC;
+ }
+
+ flags = 0;
+ if (0 != (k->k_state&(KS_GATEWAY|KS_DYNAMIC)))
+ flags |= RTF_GATEWAY;
+
+ if (k->k_state & KS_ADD) {
+ rtioctl(RTM_ADD,
+ k->k_dst, k->k_gate, k->k_mask,
+ k->k_metric, flags);
+ } else if (k->k_state & KS_CHANGE) {
+ rtioctl(RTM_CHANGE,
+ k->k_dst,k->k_gate,k->k_mask,
+ k->k_metric, flags);
+ }
+ k->k_state &= ~(KS_ADD|KS_CHANGE|KS_DEL_ADD);
}
- k->k_state &= ~(KS_ADD | KS_CHANGE | KS_DEL_ADD);
/* Mark this route to be deleted in the next cycle.
* This deletes routes that disappear from the
@@ -1354,7 +1382,7 @@ del_static(naddr dst,
*/
k = kern_find(dst, mask, 0);
if (k != 0) {
- k->k_state &= ~KS_STATIC;
+ k->k_state &= ~(KS_STATIC | KS_DYNAMIC);
k->k_state |= KS_DELETE;
if (gone) {
k->k_state |= KS_DELETED;
@@ -1368,8 +1396,8 @@ del_static(naddr dst,
}
-/* Delete all routes generated from ICMP Redirects that use a given
- * gateway, as well as all old redirected routes.
+/* Delete all routes generated from ICMP Redirects that use a given gateway,
+ * as well as old redirected routes.
*/
void
del_redirects(naddr bad_gate,
@@ -1391,6 +1419,7 @@ del_redirects(naddr bad_gate,
continue;
k->k_state |= KS_DELETE;
+ k->k_state &= ~KS_DYNAMIC;
need_kern.tv_sec = now.tv_sec;
trace_act("mark redirected %s --> %s for deletion\n",
addrname(k->k_dst, k->k_mask, 0),
@@ -1492,11 +1521,7 @@ rtadd(naddr dst,
int i;
struct rt_spare *rts;
- rt = (struct rt_entry *)malloc(sizeof (*rt));
- if (rt == 0) {
- BADERR(1,"rtadd malloc");
- return;
- }
+ rt = (struct rt_entry *)rtmalloc(sizeof (*rt), "rtadd");
bzero(rt, sizeof(*rt));
for (rts = rt->rt_spares, i = NUM_SPARES; i != 0; i--, rts++)
rts->rts_metric = HOPCNT_INFINITY;
@@ -1525,6 +1550,8 @@ rtadd(naddr dst,
rt->rt_ifp = ifp;
rt->rt_seqno = update_seqno;
+ if (++total_routes == MAX_ROUTES)
+ msglog("have maximum (%d) routes", total_routes);
if (TRACEACTIONS)
trace_add_del("Add", rt);
@@ -1672,6 +1699,7 @@ rtdelete(struct rt_entry *rt)
msglog("rnh_deladdr() failed");
} else {
free(rt);
+ total_routes--;
}
}
@@ -1752,7 +1780,7 @@ rtbad_sub(struct rt_entry *rt)
if (ifp1 != 0 || (state & RS_NET_SYN)) {
rtchange(rt, ((rt->rt_state & ~(RS_NET_SYN | RS_LOCAL))
| state),
- rt->rt_gate, rt->rt_router, 1,
+ rt->rt_gate, rt->rt_router, rt->rt_metric,
rt->rt_tag, ifp1, rt->rt_time, 0);
} else {
rtbad(rt);
OpenPOWER on IntegriCloud