summaryrefslogtreecommitdiffstats
path: root/usr.sbin/rarpd
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>2004-04-20 13:58:14 +0000
committerjoerg <joerg@FreeBSD.org>2004-04-20 13:58:14 +0000
commit1c58fc2576aa7a81858b5641d8d45629ce53edb7 (patch)
treee78b0ab3c38d5bacfe3877c2764025cc54a081d1 /usr.sbin/rarpd
parent77ecc19ba0814dd8d1278476c36f312ac72cbc34 (diff)
downloadFreeBSD-src-1c58fc2576aa7a81858b5641d8d45629ce53edb7.zip
FreeBSD-src-1c58fc2576aa7a81858b5641d8d45629ce53edb7.tar.gz
While walking over the list of interfaces obtained from getifaddrs(3),
rarpd clobbered any AF_INET information already configured for a given interface name, so interfaces with more than one IP address made rarpd listen only for the last address out of all IP aliases. I changed this, so that AF_LINK information is always collected first (to ensure the interface name gets its link-layer address associated), but while looking for AF_INET addresses, the configuration is cloned if there has already been one IP address seen for that interface name. Thus, rarpd now effectively listens on all subnets. MFC after: 1 week
Diffstat (limited to 'usr.sbin/rarpd')
-rw-r--r--usr.sbin/rarpd/rarpd.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/usr.sbin/rarpd/rarpd.c b/usr.sbin/rarpd/rarpd.c
index 8c34dca..a5d745b 100644
--- a/usr.sbin/rarpd/rarpd.c
+++ b/usr.sbin/rarpd/rarpd.c
@@ -109,7 +109,7 @@ static in_addr_t choose_ipaddr(in_addr_t **, in_addr_t, in_addr_t);
static char *eatoa(u_char *);
static int expand_syslog_m(const char *fmt, char **newfmt);
static void init(char *);
-static void init_one(struct ifaddrs *, char *);
+static void init_one(struct ifaddrs *, char *, int);
static char *intoa(in_addr_t);
static in_addr_t ipaddrtonetmask(in_addr_t);
static void logmsg(int, const char *, ...) __printflike(2, 3);
@@ -200,15 +200,19 @@ main(int argc, char *argv[])
* Add to the interface list.
*/
static void
-init_one(struct ifaddrs *ifa, char *target)
+init_one(struct ifaddrs *ifa, char *target, int pass1)
{
- struct if_info *ii;
+ struct if_info *ii, *ii2;
struct sockaddr_dl *ll;
int family;
family = ifa->ifa_addr->sa_family;
switch (family) {
case AF_INET:
+ if (pass1)
+ /* Consider only AF_LINK during pass1. */
+ return;
+ /* FALLTHROUGH */
case AF_LINK:
if (!(ifa->ifa_flags & IFF_UP) ||
(ifa->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)))
@@ -227,6 +231,10 @@ init_one(struct ifaddrs *ifa, char *target)
if (strcmp(ifa->ifa_name, ii->ii_ifname) == 0)
break;
+ if (pass1 && ii != NULL)
+ /* We've already seen that interface once. */
+ return;
+
/* Allocate a new one if not found */
if (ii == NULL) {
ii = (struct if_info *)malloc(sizeof(*ii));
@@ -239,6 +247,24 @@ init_one(struct ifaddrs *ifa, char *target)
strlcpy(ii->ii_ifname, ifa->ifa_name, sizeof(ii->ii_ifname));
ii->ii_next = iflist;
iflist = ii;
+ } else if (!pass1 && ii->ii_ipaddr != 0) {
+ /*
+ * Second AF_INET definition for that interface: clone
+ * the existing one, and work on that cloned one.
+ * This must be another IP address for this interface,
+ * so avoid killing the previous configuration.
+ */
+ ii2 = (struct if_info *)malloc(sizeof(*ii2));
+ if (ii2 == NULL) {
+ logmsg(LOG_ERR, "malloc: %m");
+ exit(1);
+ }
+ memcpy(ii2, ii, sizeof(*ii2));
+ ii2->ii_fd = -1;
+ ii2->ii_next = iflist;
+ iflist = ii2;
+
+ ii = ii2;
}
switch (family) {
@@ -275,8 +301,18 @@ init(char *target)
logmsg(LOG_ERR, "getifaddrs: %m");
exit(1);
}
+ /*
+ * We make two passes over the list we have got. In the first
+ * one, we only collect AF_LINK interfaces, and initialize our
+ * list of interfaces from them. In the second pass, we
+ * collect the actual IP addresses from the AF_INET
+ * interfaces, and allow for the same interface name to appear
+ * multiple times (in case of more than one IP address).
+ */
+ for (ifa = ifhead; ifa != NULL; ifa = ifa->ifa_next)
+ init_one(ifa, target, 1);
for (ifa = ifhead; ifa != NULL; ifa = ifa->ifa_next)
- init_one(ifa, target);
+ init_one(ifa, target, 0);
freeifaddrs(ifhead);
/* Throw away incomplete interfaces */
OpenPOWER on IntegriCloud