mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
Treat all interface aliases as local addresses.
The new rtiparse() function should really be in libc IMHO.... I'm sick of writing this code :-( PR: 20381
This commit is contained in:
parent
3ebdf3366d
commit
7bdb026118
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=64450
|
@ -63,6 +63,7 @@ static const char rcsid[] =
|
|||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "pmap_check.h"
|
||||
|
@ -72,12 +73,31 @@ static const char rcsid[] =
|
|||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define ROUNDUP(x) ((x) ? (1 + (((x) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||
|
||||
/* How many interfaces could there be on a computer? */
|
||||
|
||||
#define ESTIMATED_LOCAL 20
|
||||
static int num_local = -1;
|
||||
static struct in_addr *addrs;
|
||||
|
||||
static void
|
||||
rtiparse(struct ifa_msghdr *ifam, struct rt_addrinfo *ai)
|
||||
{
|
||||
char *wp;
|
||||
int rtax;
|
||||
|
||||
wp = (char *)(ifam + 1);
|
||||
|
||||
ai->rti_addrs = ifam->ifam_addrs;
|
||||
for (rtax = 0; rtax < sizeof ai->rti_info / sizeof *ai->rti_info; rtax++)
|
||||
if (ifam->ifam_addrs & (1 << rtax)) {
|
||||
ai->rti_info[rtax] = (struct sockaddr *)wp;
|
||||
wp += ROUNDUP(ai->rti_info[rtax]->sa_len);
|
||||
} else
|
||||
ai->rti_info[rtax] = NULL;
|
||||
}
|
||||
|
||||
/* find_local - find all IP addresses for this host */
|
||||
|
||||
static int
|
||||
|
@ -87,6 +107,8 @@ find_local()
|
|||
size_t needed;
|
||||
char *buf, *end, *ptr;
|
||||
struct if_msghdr *ifm;
|
||||
struct ifa_msghdr *ifam;
|
||||
struct rt_addrinfo ai;
|
||||
struct ifreq ifr;
|
||||
struct sockaddr_dl *dl;
|
||||
|
||||
|
@ -129,7 +151,7 @@ find_local()
|
|||
dl = (struct sockaddr_dl *)(ifm + 1);
|
||||
|
||||
if (ifm->ifm_index != dl->sdl_index || dl->sdl_nlen == 0)
|
||||
/* We only want to see each interface once */
|
||||
/* Skip over remaining ifa_msghdrs */
|
||||
continue;
|
||||
|
||||
n = dl->sdl_nlen > sizeof ifr.ifr_name ?
|
||||
|
@ -143,23 +165,26 @@ find_local()
|
|||
fprintf(stderr, "%.*s: SIOCGIFFLAGS: %s\n", n, ifr.ifr_name,
|
||||
strerror(errno));
|
||||
else if (ifr.ifr_flags & IFF_UP) { /* active interface */
|
||||
if (ioctl(s, SIOCGIFADDR, &ifr) < 0)
|
||||
fprintf(stderr, "%.*s: SIOCGIFADDR: %s\n", n, ifr.ifr_name,
|
||||
strerror(errno));
|
||||
else {
|
||||
if (alloced < num_local + 1) {
|
||||
alloced += ESTIMATED_LOCAL;
|
||||
if (addrs)
|
||||
ifam = (struct ifa_msghdr *)(ptr + ifm->ifm_msglen);
|
||||
while ((char *)ifam < end && ifam->ifam_type == RTM_NEWADDR) {
|
||||
rtiparse(ifam, &ai);
|
||||
|
||||
if (ai.rti_info[RTAX_IFA] != NULL &&
|
||||
ai.rti_info[RTAX_IFA]->sa_family == AF_INET) {
|
||||
if (alloced < num_local + 1) {
|
||||
alloced += ESTIMATED_LOCAL;
|
||||
addrs = (struct in_addr *)realloc(addrs, alloced * sizeof addrs[0]);
|
||||
else
|
||||
addrs = (struct in_addr *)malloc(alloced * sizeof addrs[0]);
|
||||
if (addrs == NULL) {
|
||||
perror("malloc/realloc");
|
||||
num_local = 0;
|
||||
break;
|
||||
if (addrs == NULL) {
|
||||
perror("malloc/realloc");
|
||||
num_local = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
addrs[num_local++] = ((struct sockaddr_in *)
|
||||
ai.rti_info[RTAX_IFA])->sin_addr;
|
||||
|
||||
}
|
||||
addrs[num_local++] = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
|
||||
ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue