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
This commit is contained in:
Joerg Wunsch 2004-04-20 13:58:14 +00:00
parent 167992ad9a
commit d7706da39f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=128474

View File

@ -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);
init_one(ifa, target, 1);
for (ifa = ifhead; ifa != NULL; ifa = ifa->ifa_next)
init_one(ifa, target, 0);
freeifaddrs(ifhead);
/* Throw away incomplete interfaces */