summaryrefslogtreecommitdiffstats
path: root/sysdep
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>1999-05-06 23:38:11 +0200
committerMartin Mares <mj@ucw.cz>1999-05-06 23:38:11 +0200
commit9a158361da249e0eab1e0f7bd2c7dbe9f32eddfa (patch)
tree4d9dff14fd053aaa2d45be859144148eb8851a4d /sysdep
parentec8b579e9c9703601bf745745b620103fe2e2477 (diff)
downloadbird-9a158361da249e0eab1e0f7bd2c7dbe9f32eddfa.tar
bird-9a158361da249e0eab1e0f7bd2c7dbe9f32eddfa.zip
I rewrote the interface handling code, so that it supports multiple
addresses per interface (needed for example for IPv6 support). Visible changes: o struct iface now contains a list of all interface addresses (represented by struct ifa), iface->addr points to the primary address (if any). o Interface has IF_UP set iff it's up and it has a primary address. o IF_UP is now independent on IF_IGNORED (i.e., you need to test IF_IGNORED in the protocols; I've added this, but please check). o The if_notify_change hook has been simplified (only one interface pointer etc.). o Introduced a ifa_notify_change hook. (For now, only the Direct protocol does use it -- it's wise to just listen to device routes in all other protocols.) o Removed IF_CHANGE_FLAGS notifier flag (it was meaningless anyway). o Updated all the code except netlink (I'll look at it tomorrow) to match the new semantics (please look at your code to ensure I did it right). Things to fix: o Netlink. o Make krt-iface interpret "eth0:1"-type aliases as secondary addresses.
Diffstat (limited to 'sysdep')
-rw-r--r--sysdep/linux/netlink/netlink.c10
-rw-r--r--sysdep/unix/io.c8
-rw-r--r--sysdep/unix/krt-iface.c44
3 files changed, 37 insertions, 25 deletions
diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c
index 31dd608..5a15607 100644
--- a/sysdep/linux/netlink/netlink.c
+++ b/sysdep/linux/netlink/netlink.c
@@ -407,12 +407,16 @@ krt_if_scan(struct kif_proto *p)
* Routes
*/
-int /* FIXME: Check use of this function in krt.c */
+int
krt_capable(rte *e)
{
rta *a = e->attrs;
- if (a->cast != RTC_UNICAST) /* FIXME: For IPv6, we might support anycasts as well */
+ if (a->cast != RTC_UNICAST
+#ifdef IPV6
+ && a->cast != RTC_ANYCAST
+#endif
+ )
return 0;
if (a->source == RTS_DEVICE) /* Kernel takes care of device routes itself */
return 0;
@@ -597,7 +601,7 @@ nl_parse_route(struct krt_proto *p, struct nlmsghdr *h, int scan)
net = net_get(&master_table, dst, i->rtm_dst_len);
ra.proto = &p->p;
ra.source = RTS_INHERIT;
- ra.scope = SCOPE_UNIVERSE; /* FIXME: Use kernel scope? */
+ ra.scope = SCOPE_UNIVERSE;
ra.cast = RTC_UNICAST;
ra.flags = ra.aflags = 0;
ra.from = IPA_NONE;
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 7764d3d..6d44f80 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -414,14 +414,14 @@ sk_open(sock *s)
#ifdef HAVE_STRUCT_IP_MREQN
struct ip_mreqn mreq;
#define mreq_add mreq
- ASSERT(s->iface);
+ ASSERT(s->iface && s->iface->addr);
mreq.imr_ifindex = s->iface->index;
- set_inaddr(&mreq.imr_address, s->iface->ip);
+ set_inaddr(&mreq.imr_address, s->iface->addr->ip);
#else
struct in_addr mreq;
struct ip_mreq mreq_add;
- ASSERT(s->iface);
- set_inaddr(&mreq, s->iface->ip);
+ ASSERT(s->iface && s->iface->addr);
+ set_inaddr(&mreq, s->iface->addr->ip);
#ifdef SO_BINDTODEVICE
{
struct ifreq ifr;
diff --git a/sysdep/unix/krt-iface.c b/sysdep/unix/krt-iface.c
index bca70cc..57692eb 100644
--- a/sysdep/unix/krt-iface.c
+++ b/sysdep/unix/krt-iface.c
@@ -30,7 +30,8 @@ int if_scan_sock = -1;
static void
scan_ifs(struct ifreq *r, int cnt)
{
- struct iface i;
+ struct iface i, *pi;
+ struct ifa a;
char *err;
unsigned fl;
ip_addr netmask;
@@ -40,6 +41,7 @@ scan_ifs(struct ifreq *r, int cnt)
for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
{
bzero(&i, sizeof(i));
+ bzero(&a, sizeof(a));
DBG("%s\n", r->ifr_name);
if (strchr(r->ifr_name, ':'))
{
@@ -48,17 +50,21 @@ scan_ifs(struct ifreq *r, int cnt)
continue;
}
strncpy(i.name, r->ifr_name, sizeof(i.name) - 1);
- get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &i.ip, NULL);
- if (ipa_nonzero(i.ip))
+ get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.ip, NULL);
+ if (ipa_nonzero(a.ip))
{
- l = ipa_classify(i.ip);
+ l = ipa_classify(a.ip);
if (l < 0 || !(l & IADDR_HOST))
{
log(L_ERR "%s: Invalid interface address", i.name);
- i.ip = IPA_NONE;
+ a.ip = IPA_NONE;
+ }
+ else
+ {
+ a.scope = l & IADDR_SCOPE_MASK;
+ if (a.scope == SCOPE_HOST)
+ i.flags |= IF_LOOPBACK | IF_IGNORE;
}
- else if ((l & IADDR_SCOPE_MASK) == SCOPE_HOST)
- i.flags |= IF_LOOPBACK | IF_IGNORE;
}
if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0)
@@ -83,15 +89,15 @@ scan_ifs(struct ifreq *r, int cnt)
log(L_ERR "%s: Invalid netmask", i.name);
goto bad;
}
- i.pxlen = l;
+ a.pxlen = l;
if (fl & IFF_POINTOPOINT)
{
i.flags |= IF_UNNUMBERED;
- i.pxlen = BITS_PER_IP_ADDRESS;
+ a.pxlen = BITS_PER_IP_ADDRESS;
if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0)
{ err = "SIOCGIFDSTADDR"; goto faulty; }
- get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &i.opposite, NULL);
+ get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL);
}
if (fl & IFF_LOOPBACK)
i.flags |= IF_LOOPBACK | IF_IGNORE;
@@ -100,24 +106,24 @@ scan_ifs(struct ifreq *r, int cnt)
#endif
i.flags |= IF_MULTICAST;
- i.prefix = ipa_and(i.ip, ipa_mkmask(i.pxlen));
- if (i.pxlen < 32)
+ a.prefix = ipa_and(a.ip, ipa_mkmask(a.pxlen));
+ if (a.pxlen < 32)
{
- i.brd = ipa_or(i.prefix, ipa_not(ipa_mkmask(i.pxlen)));
- if (ipa_equal(i.ip, i.prefix) || ipa_equal(i.ip, i.brd))
+ a.brd = ipa_or(a.prefix, ipa_not(ipa_mkmask(a.pxlen)));
+ if (ipa_equal(a.ip, a.prefix) || ipa_equal(a.ip, a.brd))
{
log(L_ERR "%s: Using network or broadcast address for interface", i.name);
goto bad;
}
if (fl & IFF_BROADCAST)
i.flags |= IF_BROADCAST;
- if (i.pxlen < 30)
+ if (a.pxlen < 30)
i.flags |= IF_MULTIACCESS;
else
- i.opposite = ipa_opposite(i.ip);
+ a.opposite = ipa_opposite(a.ip);
}
else
- i.brd = i.opposite;
+ a.brd = a.opposite;
if (ioctl(if_scan_sock, SIOCGIFMTU, r) < 0)
{ err = "SIOCGIFMTU"; goto faulty; }
@@ -132,7 +138,9 @@ scan_ifs(struct ifreq *r, int cnt)
/* FIXME: What else? Guess ifindex (we need it at least for OSPF on unnumbered links)? */
#endif
- if_update(&i);
+ pi = if_update(&i);
+ a.iface = pi;
+ ifa_update(&a);
}
if_end_update();
}