mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
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.
This commit is contained in:
parent
e69e4ed934
commit
6a636392d3
1
TODO
1
TODO
@ -3,7 +3,6 @@ Core
|
|||||||
- IPv6: hashing functions etc.
|
- IPv6: hashing functions etc.
|
||||||
|
|
||||||
- krt-iface: check whether the interface alias hack works
|
- krt-iface: check whether the interface alias hack works
|
||||||
- krt-iface and netlink: unnumberedness of tunnels
|
|
||||||
|
|
||||||
- better memory allocators
|
- better memory allocators
|
||||||
- real attribute cache
|
- real attribute cache
|
||||||
|
55
nest/iface.c
55
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))
|
if (!(i->flags & IF_UP))
|
||||||
return 0;
|
return 0;
|
||||||
if ((i->flags & IF_UNNUMBERED) && ipa_equal(*a, i->addr->opposite))
|
|
||||||
return 1;
|
|
||||||
WALK_LIST(b, i->addrs)
|
WALK_LIST(b, i->addrs)
|
||||||
if (ipa_in_net(*a, b->prefix, b->pxlen))
|
{
|
||||||
{
|
if (ipa_equal(*a, b->ip))
|
||||||
if (ipa_equal(*a, b->prefix) || /* Network address */
|
return -1;
|
||||||
ipa_equal(*a, b->brd) || /* Broadcast */
|
if (b->flags & IA_UNNUMBERED)
|
||||||
ipa_equal(*a, b->ip)) /* Our own address */
|
{
|
||||||
return -1;
|
if (ipa_equal(*a, b->opposite))
|
||||||
return 1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -184,9 +193,10 @@ list iface_list;
|
|||||||
void
|
void
|
||||||
ifa_dump(struct ifa *a)
|
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 & IF_UP) ? "" : " DOWN",
|
||||||
(a->flags & IA_PRIMARY) ? "" : " SEC");
|
(a->flags & IA_PRIMARY) ? "" : " SEC",
|
||||||
|
(a->flags & IA_UNNUMBERED) ? " UNNUM" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -205,8 +215,6 @@ if_dump(struct iface *i)
|
|||||||
debug(" LINK-UP");
|
debug(" LINK-UP");
|
||||||
if (i->flags & IF_MULTIACCESS)
|
if (i->flags & IF_MULTIACCESS)
|
||||||
debug(" MA");
|
debug(" MA");
|
||||||
if (i->flags & IF_UNNUMBERED)
|
|
||||||
debug(" UNNUM");
|
|
||||||
if (i->flags & IF_BROADCAST)
|
if (i->flags & IF_BROADCAST)
|
||||||
debug(" BC");
|
debug(" BC");
|
||||||
if (i->flags & IF_MULTICAST)
|
if (i->flags & IF_MULTICAST)
|
||||||
@ -492,7 +500,8 @@ ifa_update(struct ifa *a)
|
|||||||
b->pxlen == a->pxlen &&
|
b->pxlen == a->pxlen &&
|
||||||
ipa_equal(b->brd, a->brd) &&
|
ipa_equal(b->brd, a->brd) &&
|
||||||
ipa_equal(b->opposite, a->opposite) &&
|
ipa_equal(b->opposite, a->opposite) &&
|
||||||
b->scope == a->scope)
|
b->scope == a->scope &&
|
||||||
|
!((b->flags ^ a->flags) & IA_UNNUMBERED))
|
||||||
{
|
{
|
||||||
b->flags |= IF_UPDATED;
|
b->flags |= IF_UPDATED;
|
||||||
return b;
|
return b;
|
||||||
@ -500,6 +509,12 @@ ifa_update(struct ifa *a)
|
|||||||
ifa_delete(b);
|
ifa_delete(b);
|
||||||
break;
|
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));
|
b = mb_alloc(if_pool, sizeof(struct ifa));
|
||||||
memcpy(b, a, sizeof(struct ifa));
|
memcpy(b, a, sizeof(struct ifa));
|
||||||
add_tail(&i->addrs, &b->n);
|
add_tail(&i->addrs, &b->n);
|
||||||
@ -545,8 +560,9 @@ auto_router_id(void)
|
|||||||
j = NULL;
|
j = NULL;
|
||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, iface_list)
|
||||||
if ((i->flags & IF_LINK_UP) &&
|
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 &&
|
||||||
|
!(i->addr->flags & IA_UNNUMBERED) &&
|
||||||
(!j || ipa_to_u32(i->addr->ip) < ipa_to_u32(j->addr->ip)))
|
(!j || ipa_to_u32(i->addr->ip) < ipa_to_u32(j->addr->ip)))
|
||||||
j = i;
|
j = i;
|
||||||
if (!j)
|
if (!j)
|
||||||
@ -633,11 +649,12 @@ if_show_addr(struct ifa *a)
|
|||||||
bsprintf(opp, ", opposite %I", a->opposite);
|
bsprintf(opp, ", opposite %I", a->opposite);
|
||||||
else
|
else
|
||||||
opp[0] = 0;
|
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->ip, a->pxlen,
|
||||||
(a->flags & IA_PRIMARY) ? "Primary" : (a->flags & IA_SECONDARY) ? "Secondary" : "???",
|
(a->flags & IA_PRIMARY) ? "Primary" : (a->flags & IA_SECONDARY) ? "Secondary" : "???",
|
||||||
broad, opp,
|
broad, opp,
|
||||||
ip_scope_text(a->scope));
|
ip_scope_text(a->scope),
|
||||||
|
(a->flags & IA_UNNUMBERED) ? ", unnumbered" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -650,9 +667,7 @@ if_show(void)
|
|||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, iface_list)
|
||||||
{
|
{
|
||||||
cli_msg(-1001, "%s %s (index=%d)", i->name, (i->flags & IF_UP) ? "up" : "DOWN", i->index);
|
cli_msg(-1001, "%s %s (index=%d)", i->name, (i->flags & IF_UP) ? "up" : "DOWN", i->index);
|
||||||
if (i->flags & IF_UNNUMBERED)
|
if (!(i->flags & IF_MULTIACCESS))
|
||||||
type = "UnNum-PtP";
|
|
||||||
else if (!(i->flags & IF_MULTIACCESS))
|
|
||||||
type = "PtP";
|
type = "PtP";
|
||||||
else
|
else
|
||||||
type = "MultiAccess";
|
type = "MultiAccess";
|
||||||
|
14
nest/iface.h
14
nest/iface.h
@ -40,16 +40,16 @@ struct iface {
|
|||||||
|
|
||||||
#define IF_UP 1 /* IF_LINK_UP and IP address known */
|
#define IF_UP 1 /* IF_LINK_UP and IP address known */
|
||||||
#define IF_MULTIACCESS 2
|
#define IF_MULTIACCESS 2
|
||||||
#define IF_UNNUMBERED 4
|
#define IF_BROADCAST 4
|
||||||
#define IF_BROADCAST 8
|
#define IF_MULTICAST 8
|
||||||
#define IF_MULTICAST 0x10
|
#define IF_ADMIN_DOWN 0x10
|
||||||
#define IF_ADMIN_DOWN 0x40
|
#define IF_LOOPBACK 0x20
|
||||||
#define IF_LOOPBACK 0x80
|
#define IF_IGNORE 0x40 /* Not to be used by routing protocols (loopbacks etc.) */
|
||||||
#define IF_IGNORE 0x100 /* Not to be used by routing protocols (loopbacks etc.) */
|
#define IF_LINK_UP 0x80
|
||||||
#define IF_LINK_UP 0x200
|
|
||||||
|
|
||||||
#define IA_PRIMARY 0x10000 /* This address is primary */
|
#define IA_PRIMARY 0x10000 /* This address is primary */
|
||||||
#define IA_SECONDARY 0x20000 /* This address has been reported as secondary by the kernel */
|
#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 IA_FLAGS 0xff0000
|
||||||
|
|
||||||
#define IF_JUST_CREATED 0x10000000 /* Send creation event as soon as possible */
|
#define IF_JUST_CREATED 0x10000000 /* Send creation event as soon as possible */
|
||||||
|
@ -56,10 +56,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
|
|||||||
A.iface = ad->iface;
|
A.iface = ad->iface;
|
||||||
A.eattrs = NULL;
|
A.eattrs = NULL;
|
||||||
a = rta_lookup(&A);
|
a = rta_lookup(&A);
|
||||||
if (ad->flags & IF_UNNUMBERED)
|
n = net_get(p->table, ad->prefix, ad->pxlen);
|
||||||
n = net_get(p->table, ad->opposite, ad->pxlen);
|
|
||||||
else
|
|
||||||
n = net_get(p->table, ad->prefix, ad->pxlen);
|
|
||||||
e = rte_get_temp(a);
|
e = rte_get_temp(a);
|
||||||
e->net = n;
|
e->net = n;
|
||||||
e->pflags = 0;
|
e->pflags = 0;
|
||||||
|
@ -301,13 +301,14 @@ nl_parse_link(struct nlmsghdr *h, int scan)
|
|||||||
fl = i->ifi_flags;
|
fl = i->ifi_flags;
|
||||||
if (fl & IFF_UP)
|
if (fl & IFF_UP)
|
||||||
f.flags |= IF_LINK_UP;
|
f.flags |= IF_LINK_UP;
|
||||||
/* FIXME: Unnumberedness of tunnels */
|
if (fl & IFF_LOOPBACK) /* Loopback */
|
||||||
if (fl & IFF_POINTOPOINT)
|
f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE;
|
||||||
f.flags |= IF_UNNUMBERED | IF_MULTICAST;
|
else if (fl & IFF_POINTOPOINT) /* PtP */
|
||||||
if (fl & IFF_LOOPBACK)
|
f.flags |= IF_MULTICAST;
|
||||||
f.flags |= IF_LOOPBACK | IF_IGNORE;
|
else if (fl & IFF_BROADCAST) /* Broadcast */
|
||||||
if (fl & IFF_BROADCAST)
|
f.flags |= IF_MULTIACCESS | IF_BROADCAST | IF_MULTICAST;
|
||||||
f.flags |= IF_BROADCAST | IF_MULTICAST;
|
else
|
||||||
|
f.flags |= IF_MULTIACCESS; /* NBMA */
|
||||||
if_update(&f);
|
if_update(&f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,15 +351,6 @@ nl_parse_addr(struct nlmsghdr *h)
|
|||||||
return;
|
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));
|
bzero(&ifa, sizeof(ifa));
|
||||||
ifa.iface = ifi;
|
ifa.iface = ifi;
|
||||||
if (i->ifa_flags & IFA_F_SECONDARY)
|
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));
|
memcpy(&ifa.ip, RTA_DATA(a[IFA_LOCAL] ? : a[IFA_ADDRESS]), sizeof(ifa.ip));
|
||||||
ipa_ntoh(ifa.ip);
|
ipa_ntoh(ifa.ip);
|
||||||
ifa.pxlen = i->ifa_prefixlen;
|
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));
|
memcpy(&ifa.opposite, RTA_DATA(a[IFA_ADDRESS]), sizeof(ifa.opposite));
|
||||||
ipa_ntoh(ifa.opposite);
|
ipa_ntoh(ifa.opposite);
|
||||||
ifa.brd = ifa.opposite;
|
ifa.prefix = ifa.brd = ifa.opposite;
|
||||||
}
|
}
|
||||||
#ifndef IPV6
|
else
|
||||||
else if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
|
|
||||||
{
|
{
|
||||||
memcpy(&ifa.brd, RTA_DATA(a[IFA_BROADCAST]), sizeof(ifa.brd));
|
if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 2)
|
||||||
ipa_ntoh(ifa.brd);
|
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
|
#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,
|
ifi->index, ifi->name,
|
||||||
new ? "added" : "removed",
|
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)
|
if (new)
|
||||||
ifa_update(&ifa);
|
ifa_update(&ifa);
|
||||||
else
|
else
|
||||||
|
@ -94,12 +94,15 @@ scan_ifs(struct ifreq *r, int cnt)
|
|||||||
|
|
||||||
if (fl & IFF_POINTOPOINT)
|
if (fl & IFF_POINTOPOINT)
|
||||||
{
|
{
|
||||||
i.flags |= IF_UNNUMBERED;
|
a.flags |= IA_UNNUMBERED;
|
||||||
a.pxlen = BITS_PER_IP_ADDRESS;
|
|
||||||
if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0)
|
if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0)
|
||||||
{ err = "SIOCGIFDSTADDR"; goto faulty; }
|
{ err = "SIOCGIFDSTADDR"; goto faulty; }
|
||||||
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL);
|
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)
|
if (fl & IFF_LOOPBACK)
|
||||||
i.flags |= IF_LOOPBACK | IF_IGNORE;
|
i.flags |= IF_LOOPBACK | IF_IGNORE;
|
||||||
if (1
|
if (1
|
||||||
@ -107,12 +110,11 @@ scan_ifs(struct ifreq *r, int cnt)
|
|||||||
&& (fl & IFF_MULTICAST)
|
&& (fl & IFF_MULTICAST)
|
||||||
#endif
|
#endif
|
||||||
#ifndef CONFIG_UNNUM_MULTICAST
|
#ifndef CONFIG_UNNUM_MULTICAST
|
||||||
&& !(i.flags & IF_UNNUMBERED)
|
&& !(a.flags & IA_UNNUMBERED)
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
i.flags |= IF_MULTICAST;
|
i.flags |= IF_MULTICAST;
|
||||||
|
|
||||||
a.prefix = ipa_and(a.ip, ipa_mkmask(a.pxlen));
|
|
||||||
if (a.pxlen < 32)
|
if (a.pxlen < 32)
|
||||||
{
|
{
|
||||||
a.brd = ipa_or(a.prefix, ipa_not(ipa_mkmask(a.pxlen)));
|
a.brd = ipa_or(a.prefix, ipa_not(ipa_mkmask(a.pxlen)));
|
||||||
|
Loading…
Reference in New Issue
Block a user