diff options
author | Martin Mares <mj@ucw.cz> | 1999-05-06 21:38:11 +0000 |
---|---|---|
committer | Martin Mares <mj@ucw.cz> | 1999-05-06 21:38:11 +0000 |
commit | 9a158361da249e0eab1e0f7bd2c7dbe9f32eddfa (patch) | |
tree | 4d9dff14fd053aaa2d45be859144148eb8851a4d /sysdep | |
parent | ec8b579e9c9703601bf745745b620103fe2e2477 (diff) |
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.c | 10 | ||||
-rw-r--r-- | sysdep/unix/io.c | 8 | ||||
-rw-r--r-- | sysdep/unix/krt-iface.c | 44 |
3 files changed, 37 insertions, 25 deletions
diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c index 31dd608d..5a15607a 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 7764d3df..6d44f809 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 bca70cca..57692ebc 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(); } |