From 6a636392d33627944df9d5a9573932cdc0bf6da5 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Tue, 29 Feb 2000 23:19:52 +0000 Subject: [PATCH] Rewrote interface type detection logic. The `unnumbered' flag is now per address, not per interface (hence it's ifa->flags & IA_UNNUMBERED) and should be set reliably. IF_MULTIACCESS should be fixed now, but it isn't wise to rely on it on interfaces configured with /30 prefix. --- TODO | 1 - nest/iface.c | 55 ++++++++++++++++++++------------ nest/iface.h | 14 ++++----- nest/rt-dev.c | 5 +-- sysdep/linux/netlink/netlink.c | 57 ++++++++++++++++++---------------- sysdep/unix/krt-iface.c | 10 +++--- 6 files changed, 79 insertions(+), 63 deletions(-) diff --git a/TODO b/TODO index f0c54866..4b033b08 100644 --- a/TODO +++ b/TODO @@ -3,7 +3,6 @@ Core - IPv6: hashing functions etc. - krt-iface: check whether the interface alias hack works -- krt-iface and netlink: unnumberedness of tunnels - better memory allocators - real attribute cache diff --git a/nest/iface.c b/nest/iface.c index ce233cd8..9b4eff00 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -36,16 +36,25 @@ if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */ if (!(i->flags & IF_UP)) return 0; - if ((i->flags & IF_UNNUMBERED) && ipa_equal(*a, i->addr->opposite)) - return 1; WALK_LIST(b, i->addrs) - if (ipa_in_net(*a, b->prefix, b->pxlen)) - { - if (ipa_equal(*a, b->prefix) || /* Network address */ - ipa_equal(*a, b->brd) || /* Broadcast */ - ipa_equal(*a, b->ip)) /* Our own address */ - return -1; - return 1; + { + if (ipa_equal(*a, b->ip)) + return -1; + if (b->flags & IA_UNNUMBERED) + { + if (ipa_equal(*a, b->opposite)) + return 1; + } + else + { + if (ipa_in_net(*a, b->prefix, b->pxlen)) + { + if (ipa_equal(*a, b->prefix) || /* Network address */ + ipa_equal(*a, b->brd)) /* Broadcast */ + return -1; + return 1; + } + } } return 0; } @@ -184,9 +193,10 @@ list iface_list; void ifa_dump(struct ifa *a) { - debug("\t%I, net %I/%-2d bc %I -> %I%s%s\n", a->ip, a->prefix, a->pxlen, a->brd, a->opposite, + debug("\t%I, net %I/%-2d bc %I -> %I%s%s%s\n", a->ip, a->prefix, a->pxlen, a->brd, a->opposite, (a->flags & IF_UP) ? "" : " DOWN", - (a->flags & IA_PRIMARY) ? "" : " SEC"); + (a->flags & IA_PRIMARY) ? "" : " SEC", + (a->flags & IA_UNNUMBERED) ? " UNNUM" : ""); } void @@ -205,8 +215,6 @@ if_dump(struct iface *i) debug(" LINK-UP"); if (i->flags & IF_MULTIACCESS) debug(" MA"); - if (i->flags & IF_UNNUMBERED) - debug(" UNNUM"); if (i->flags & IF_BROADCAST) debug(" BC"); if (i->flags & IF_MULTICAST) @@ -492,7 +500,8 @@ ifa_update(struct ifa *a) b->pxlen == a->pxlen && ipa_equal(b->brd, a->brd) && ipa_equal(b->opposite, a->opposite) && - b->scope == a->scope) + b->scope == a->scope && + !((b->flags ^ a->flags) & IA_UNNUMBERED)) { b->flags |= IF_UPDATED; return b; @@ -500,6 +509,12 @@ ifa_update(struct ifa *a) ifa_delete(b); break; } + + if (!(i->flags & IF_MULTIACCESS) && a->pxlen < BITS_PER_IP_ADDRESS - 2) + log(L_WARN "Strange prefix length %d for point-to-point interface %s", a->pxlen, i->name); + if ((i->flags & IF_BROADCAST) && !ipa_nonzero(a->brd)) + log(L_ERR "Missing broadcast address for interface %s", i->name); + b = mb_alloc(if_pool, sizeof(struct ifa)); memcpy(b, a, sizeof(struct ifa)); add_tail(&i->addrs, &b->n); @@ -545,8 +560,9 @@ auto_router_id(void) j = NULL; WALK_LIST(i, iface_list) if ((i->flags & IF_LINK_UP) && - !(i->flags & (IF_UNNUMBERED | IF_IGNORE | IF_ADMIN_DOWN)) && + !(i->flags & (IF_IGNORE | IF_ADMIN_DOWN)) && i->addr && + !(i->addr->flags & IA_UNNUMBERED) && (!j || ipa_to_u32(i->addr->ip) < ipa_to_u32(j->addr->ip))) j = i; if (!j) @@ -633,11 +649,12 @@ if_show_addr(struct ifa *a) bsprintf(opp, ", opposite %I", a->opposite); else opp[0] = 0; - cli_msg(-1003, "\t%I/%d (%s%s%s, scope %s)", + cli_msg(-1003, "\t%I/%d (%s%s%s, scope %s%s)", a->ip, a->pxlen, (a->flags & IA_PRIMARY) ? "Primary" : (a->flags & IA_SECONDARY) ? "Secondary" : "???", broad, opp, - ip_scope_text(a->scope)); + ip_scope_text(a->scope), + (a->flags & IA_UNNUMBERED) ? ", unnumbered" : ""); } void @@ -650,9 +667,7 @@ if_show(void) WALK_LIST(i, iface_list) { cli_msg(-1001, "%s %s (index=%d)", i->name, (i->flags & IF_UP) ? "up" : "DOWN", i->index); - if (i->flags & IF_UNNUMBERED) - type = "UnNum-PtP"; - else if (!(i->flags & IF_MULTIACCESS)) + if (!(i->flags & IF_MULTIACCESS)) type = "PtP"; else type = "MultiAccess"; diff --git a/nest/iface.h b/nest/iface.h index b13ec719..5ac9f2f7 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -40,16 +40,16 @@ struct iface { #define IF_UP 1 /* IF_LINK_UP and IP address known */ #define IF_MULTIACCESS 2 -#define IF_UNNUMBERED 4 -#define IF_BROADCAST 8 -#define IF_MULTICAST 0x10 -#define IF_ADMIN_DOWN 0x40 -#define IF_LOOPBACK 0x80 -#define IF_IGNORE 0x100 /* Not to be used by routing protocols (loopbacks etc.) */ -#define IF_LINK_UP 0x200 +#define IF_BROADCAST 4 +#define IF_MULTICAST 8 +#define IF_ADMIN_DOWN 0x10 +#define IF_LOOPBACK 0x20 +#define IF_IGNORE 0x40 /* Not to be used by routing protocols (loopbacks etc.) */ +#define IF_LINK_UP 0x80 #define IA_PRIMARY 0x10000 /* This address is primary */ #define IA_SECONDARY 0x20000 /* This address has been reported as secondary by the kernel */ +#define IA_UNNUMBERED 0x40000 /* This address belongs to an unnumbered device */ #define IA_FLAGS 0xff0000 #define IF_JUST_CREATED 0x10000000 /* Send creation event as soon as possible */ diff --git a/nest/rt-dev.c b/nest/rt-dev.c index b9253ccb..edadeba5 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -56,10 +56,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad) A.iface = ad->iface; A.eattrs = NULL; a = rta_lookup(&A); - if (ad->flags & IF_UNNUMBERED) - n = net_get(p->table, ad->opposite, ad->pxlen); - else - n = net_get(p->table, ad->prefix, ad->pxlen); + n = net_get(p->table, ad->prefix, ad->pxlen); e = rte_get_temp(a); e->net = n; e->pflags = 0; diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c index 54e5cd8b..fd8689dc 100644 --- a/sysdep/linux/netlink/netlink.c +++ b/sysdep/linux/netlink/netlink.c @@ -301,13 +301,14 @@ nl_parse_link(struct nlmsghdr *h, int scan) fl = i->ifi_flags; if (fl & IFF_UP) f.flags |= IF_LINK_UP; - /* FIXME: Unnumberedness of tunnels */ - if (fl & IFF_POINTOPOINT) - f.flags |= IF_UNNUMBERED | IF_MULTICAST; - if (fl & IFF_LOOPBACK) - f.flags |= IF_LOOPBACK | IF_IGNORE; - if (fl & IFF_BROADCAST) - f.flags |= IF_BROADCAST | IF_MULTICAST; + if (fl & IFF_LOOPBACK) /* Loopback */ + f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE; + else if (fl & IFF_POINTOPOINT) /* PtP */ + f.flags |= IF_MULTICAST; + else if (fl & IFF_BROADCAST) /* Broadcast */ + f.flags |= IF_MULTIACCESS | IF_BROADCAST | IF_MULTICAST; + else + f.flags |= IF_MULTIACCESS; /* NBMA */ if_update(&f); } } @@ -350,15 +351,6 @@ nl_parse_addr(struct nlmsghdr *h) return; } -#ifndef IPV6 - if (i->ifa_prefixlen > 32 || i->ifa_prefixlen == 31 || - (ifi->flags & IF_UNNUMBERED) && i->ifa_prefixlen != 32) - { - log(L_ERR "KIF: Invalid prefix length for interface %s: %d", ifi->name, i->ifa_prefixlen); - new = 0; - } -#endif - bzero(&ifa, sizeof(ifa)); ifa.iface = ifi; if (i->ifa_flags & IFA_F_SECONDARY) @@ -367,26 +359,37 @@ nl_parse_addr(struct nlmsghdr *h) memcpy(&ifa.ip, RTA_DATA(a[IFA_LOCAL] ? : a[IFA_ADDRESS]), sizeof(ifa.ip)); ipa_ntoh(ifa.ip); ifa.pxlen = i->ifa_prefixlen; - if (ifi->flags & IF_UNNUMBERED) + if (i->ifa_prefixlen > BITS_PER_IP_ADDRESS || + i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 1) { + log(L_ERR "KIF: Invalid prefix length for interface %s: %d", ifi->name, i->ifa_prefixlen); + new = 0; + } + if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS) + { + ifa.flags |= IA_UNNUMBERED; memcpy(&ifa.opposite, RTA_DATA(a[IFA_ADDRESS]), sizeof(ifa.opposite)); ipa_ntoh(ifa.opposite); - ifa.brd = ifa.opposite; + ifa.prefix = ifa.brd = ifa.opposite; } -#ifndef IPV6 - else if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST]) + else { - memcpy(&ifa.brd, RTA_DATA(a[IFA_BROADCAST]), sizeof(ifa.brd)); - ipa_ntoh(ifa.brd); - } + if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 2) + ifa.opposite = ipa_opposite(ifa.ip); +#ifndef IPV6 + if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST]) + { + memcpy(&ifa.brd, RTA_DATA(a[IFA_BROADCAST]), sizeof(ifa.brd)); + ipa_ntoh(ifa.brd); + } #endif - /* else a NBMA link */ - ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(ifa.pxlen)); + ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(ifa.pxlen)); + } - DBG("KIF: IF%d(%s): %s IPA %I, net %I/%d, brd %I, opp %I\n", + DBG("KIF: IF%d(%s): %s IPA %I, flg %x, net %I/%d, brd %I, opp %I\n", ifi->index, ifi->name, new ? "added" : "removed", - ifa.ip, ifa.prefix, ifa.pxlen, ifa.brd, ifa.opposite); + ifa.ip, ifa.flags, ifa.prefix, ifa.pxlen, ifa.brd, ifa.opposite); if (new) ifa_update(&ifa); else diff --git a/sysdep/unix/krt-iface.c b/sysdep/unix/krt-iface.c index 8c82ffdf..2b774a13 100644 --- a/sysdep/unix/krt-iface.c +++ b/sysdep/unix/krt-iface.c @@ -94,12 +94,15 @@ scan_ifs(struct ifreq *r, int cnt) if (fl & IFF_POINTOPOINT) { - i.flags |= IF_UNNUMBERED; - a.pxlen = BITS_PER_IP_ADDRESS; + a.flags |= IA_UNNUMBERED; if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0) { err = "SIOCGIFDSTADDR"; goto faulty; } get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL); + a.prefix = a.opposite; + a.pxlen = BITS_PER_IP_ADDRESS; } + else + a.prefix = ipa_and(a.ip, ipa_mkmask(a.pxlen)); if (fl & IFF_LOOPBACK) i.flags |= IF_LOOPBACK | IF_IGNORE; if (1 @@ -107,12 +110,11 @@ scan_ifs(struct ifreq *r, int cnt) && (fl & IFF_MULTICAST) #endif #ifndef CONFIG_UNNUM_MULTICAST - && !(i.flags & IF_UNNUMBERED) + && !(a.flags & IA_UNNUMBERED) #endif ) i.flags |= IF_MULTICAST; - a.prefix = ipa_and(a.ip, ipa_mkmask(a.pxlen)); if (a.pxlen < 32) { a.brd = ipa_or(a.prefix, ipa_not(ipa_mkmask(a.pxlen)));