From f39e4713c270752d7bbfcc8115a7ea7f589c3997 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Tue, 8 Dec 1998 16:20:13 +0000 Subject: Rewritten kernel syncer. Now uses the rta trickery I've introduced yesterday and does things "the right way". Few things are still missing (device routes etc.), I'll add them later in the evening. --- sysdep/linux/krt-scan.c | 200 +++++++++++++++++++++++++++++------------------- sysdep/unix/krt-set.c | 17 ++-- sysdep/unix/krt-set.h | 6 +- sysdep/unix/krt.h | 3 + 4 files changed, 136 insertions(+), 90 deletions(-) diff --git a/sysdep/linux/krt-scan.c b/sysdep/linux/krt-scan.c index baa39d8..7dd6415 100644 --- a/sysdep/linux/krt-scan.c +++ b/sysdep/linux/krt-scan.c @@ -28,54 +28,39 @@ static int krt_scan_fd = -1; /* FIXME: Filtering */ -static void -krt_magic_route(struct krt_proto *p, net *net, ip_addr gw) +static int +krt_uptodate(rte *k, rte *e) { - neighbor *ng; - rta a, *t; - rte *e; + rta *ka = k->attrs, *ea = e->attrs; - ng = neigh_find(&p->p, &gw, 0); - if (!ng) - { - log(L_ERR "Kernel told us to use non-neighbor %I for %I/%d\n", gw, net->n.prefix, net->n.pxlen); - return; - } - a.proto = &p->p; - a.source = RTS_INHERIT; - a.scope = SCOPE_UNIVERSE; - a.cast = RTC_UNICAST; - a.dest = RTD_ROUTER; - a.tos = 0; - a.flags = 0; - a.gw = gw; - a.from = IPA_NONE; - a.iface = ng->iface; - a.attrs = NULL; - t = rta_lookup(&a); - e = rte_get_temp(t); - e->net = net; - rte_update(net, &p->p, e); + if (ka->dest != ea->dest) + return 0; + if (ka->dest == RTD_ROUTER && !ipa_equal(ka->gw, ea->gw)) + return 0; + /* FIXME: Device routes */ + return 1; } static void -krt_parse_entry(byte *e, struct krt_proto *p) +krt_parse_entry(byte *ent, struct krt_proto *p) { u32 dest0, gw0, mask0; ip_addr dest, gw, mask; - unsigned int flags; + unsigned int flags, verdict; int masklen; net *net; - byte *iface = e; + byte *iface = ent; + rta a; + rte *e, *old; - if (sscanf(e, "%*s\t%x\t%x\t%x\t%*d\t%*d\t%*d\t%x\t", &dest0, &gw0, &flags, &mask0) != 4) + if (sscanf(ent, "%*s\t%x\t%x\t%x\t%*d\t%*d\t%*d\t%x\t", &dest0, &gw0, &flags, &mask0) != 4) { - log(L_ERR "krt read: unable to parse `%s'", e); + log(L_ERR "krt read: unable to parse `%s'", ent); return; } - while (*e != '\t') - e++; - *e = 0; + while (*ent != '\t') + ent++; + *ent = 0; dest = ipa_from_u32(dest0); ipa_ntoh(dest); @@ -99,47 +84,69 @@ krt_parse_entry(byte *e, struct krt_proto *p) log(L_WARN "krt: Ignoring redirect to %I/%d via %I", dest, masklen, gw); return; } + net = net_get(&master_table, 0, dest, masklen); - if (net->routes) + a.proto = &p->p; + a.source = RTS_INHERIT; + a.scope = SCOPE_UNIVERSE; + a.cast = RTC_UNICAST; + a.tos = a.flags = a.aflags = 0; + a.from = IPA_NONE; + a.iface = NULL; + a.attrs = NULL; + + if (flags & RTF_GATEWAY) { - rte *e = net->routes; - rta *a = e->attrs; - int ok; - switch (a->dest) - { - case RTD_ROUTER: - ok = (flags & RTF_GATEWAY) && ipa_equal(gw, a->gw); - break; - case RTD_DEVICE: -#ifdef CONFIG_AUTO_ROUTES - ok = 1; - /* FIXME: What about static interface routes? */ -#else - ok = !(flags & RTF_GATEWAY) && !strcmp(iface, a->iface->name); -#endif - break; - case RTD_UNREACHABLE: - ok = flags & RTF_REJECT; - break; - default: - ok = 0; - } - net->n.flags |= ok ? KRF_SEEN : KRF_UPDATE; + neighbor *ng = neigh_find(&p->p, &gw, 0); + if (ng) + a.iface = ng->iface; + else + /* FIXME: Remove this warning? */ + log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d\n", gw, net->n.prefix, net->n.pxlen); + a.dest = RTD_ROUTER; + a.gw = gw; + } + else if (flags & RTF_REJECT) + { + a.dest = RTD_UNREACHABLE; + a.gw = IPA_NONE; } else { -#ifdef CONFIG_AUTO_ROUTES - if (!(flags & RTF_GATEWAY)) /* It's a device route */ - return; -#endif - DBG("krt_parse_entry: kernel reporting unknown route %I/%d\n", dest, masklen); - if (p->scanopt.learn) - { - if (flags & RTF_GATEWAY) - krt_magic_route(p, net, gw); - } - net->n.flags |= KRF_UPDATE; + /* FIXME: Should support interface routes? */ + /* FIXME: What about systems not generating their own if routes? (see CONFIG_AUTO_ROUTES) */ + return; + } + + e = rte_get_temp(&a); + e->net = net; + old = net->routes; + if (old && !krt_capable(old)) + old = NULL; + if (old) + { + if (krt_uptodate(e, net->routes)) + verdict = KRF_SEEN; + else + verdict = KRF_UPDATE; + } + else if (p->scanopt.learn && !net->routes) + verdict = KRF_LEARN; + else + verdict = KRF_DELETE; + + DBG("krt_parse_entry: verdict %d\n", verdict); + + net->n.flags = verdict; + if (verdict != KRF_SEEN) + { + /* Get a cached copy of attributes and link the route */ + e->attrs = rta_lookup(e->attrs); + e->next = net->routes; + net->routes = e; } + else + rte_free(e); } static int @@ -187,7 +194,7 @@ krt_scan_proc(struct krt_proto *p) } static void -krt_prune(void) +krt_prune(struct krt_proto *p) { struct rtable *t = &master_table; struct fib_node *f; @@ -200,24 +207,57 @@ krt_prune(void) FIB_WALK(&t->fib, f) { net *n = (net *) f; - switch (f->flags) + int verdict = f->flags; + rte *new, *old; + + if (verdict != KRF_CREATE && verdict != KRF_SEEN) { - case KRF_UPDATE: - DBG("krt_prune: removing %I/%d\n", n->n.prefix, n->n.pxlen); - krt_remove_route(n, NULL); - /* Fall-thru */ - case 0: - if (n->routes) + old = n->routes; + n->routes = old->next; + } + else + old = NULL; + new = n->routes; + + switch (verdict) + { + case KRF_CREATE: + if (new) { - DBG("krt_prune: reinstalling %I/%d\n", n->n.prefix, n->n.pxlen); - krt_add_route(n, n->routes); + if (new->attrs->source == RTS_INHERIT) + { + DBG("krt_prune: removing inherited %I/%d\n", n->n.prefix, n->n.pxlen); + rte_update(n, &p->p, NULL); + } + else + { + DBG("krt_prune: reinstalling %I/%d\n", n->n.prefix, n->n.pxlen); + krt_add_route(new); + } } break; case KRF_SEEN: + /* Nothing happens */ + break; + case KRF_UPDATE: + DBG("krt_prune: updating %I/%d\n", n->n.prefix, n->n.pxlen); + krt_remove_route(old); + krt_add_route(new); + break; + case KRF_DELETE: + DBG("krt_prune: deleting %I/%d\n", n->n.prefix, n->n.pxlen); + krt_remove_route(old); + break; + case KRF_LEARN: + DBG("krt_prune: learning %I/%d\n", n->n.prefix, n->n.pxlen); + rte_update(n, &p->p, new); break; default: die("krt_prune: invalid route status"); } + + if (old) + rte_free(old); f->flags = 0; } FIB_WALK_END; @@ -229,7 +269,7 @@ krt_scan_fire(timer *t) struct krt_proto *p = t->data; if (krt_scan_proc(p)) - krt_prune(); + krt_prune(p); } void diff --git a/sysdep/unix/krt-set.c b/sysdep/unix/krt-set.c index 2c355ee..8bc2df1 100644 --- a/sysdep/unix/krt-set.c +++ b/sysdep/unix/krt-set.c @@ -22,7 +22,7 @@ #include "lib/krt.h" int -krt_capable(net *net, rte *e) +krt_capable(rte *e) { rta *a = e->attrs; @@ -40,11 +40,12 @@ krt_capable(net *net, rte *e) } void -krt_remove_route(net *net, rte *old) +krt_remove_route(rte *old) { + net *net = old->net; struct rtentry re; - if (old && !krt_capable(net, old)) + if (!krt_capable(old) || old->attrs->source == RTS_INHERIT) { DBG("krt_remove_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen); return; @@ -58,12 +59,13 @@ krt_remove_route(net *net, rte *old) } void -krt_add_route(net *net, rte *new) +krt_add_route(rte *new) { + net *net = new->net; struct rtentry re; rta *a = new->attrs; - if (!krt_capable(net, new)) + if (!krt_capable(new) || new->attrs->source == RTS_INHERIT) { DBG("krt_add_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen); return; @@ -105,9 +107,9 @@ krt_set_notify(struct proto *x, net *net, rte *new, rte *old) if (x->state != PRS_UP) return; if (old) - krt_remove_route(net, old); + krt_remove_route(old); if (new) - krt_add_route(net, new); + krt_add_route(new); } void @@ -117,3 +119,4 @@ krt_set_preconfig(struct krt_proto *x) die("krt set: missing socket"); x->p.rt_notify = krt_set_notify; } + diff --git a/sysdep/unix/krt-set.h b/sysdep/unix/krt-set.h index a2107e1..214d91a 100644 --- a/sysdep/unix/krt-set.h +++ b/sysdep/unix/krt-set.h @@ -12,8 +12,8 @@ struct krt_set_params { }; -void krt_remove_route(net *net, rte *old); -void krt_add_route(net *net, rte *new); -int krt_capable(net *net, rte *e); +void krt_remove_route(rte *old); +void krt_add_route(rte *new); +int krt_capable(rte *e); #endif diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index 24122e9..aae5bd5 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -14,8 +14,11 @@ /* Flags stored in net->n.flags */ +#define KRF_CREATE 0 /* Not seen in kernel table */ #define KRF_SEEN 1 /* Seen in kernel table during last scan */ #define KRF_UPDATE 2 /* Need to update this entry */ +#define KRF_DELETE 3 /* Should be deleted */ +#define KRF_LEARN 4 /* We should learn this route */ /* sync-rt.c */ -- cgit v1.2.3