mirror of
https://github.com/nmap/nmap.git
synced 2025-12-24 00:19:01 +00:00
Simplify and comment getinterfaces_siocgifconf to make its structure
more clear: We call several different ioctls on each interface and use the results to populate the interface_info array.
This commit is contained in:
179
tcpip.cc
179
tcpip.cc
@@ -2912,153 +2912,152 @@ static struct interface_info *getinterfaces_dnet(int *howmany) {
|
||||
|
||||
/* Get a list of interfaces using ioctl(SIOCGIFCONF). */
|
||||
static struct interface_info *getinterfaces_siocgifconf(int *howmany) {
|
||||
struct interface_info *mydevs;
|
||||
int numifaces = 0;
|
||||
int ii_capacity = 0;
|
||||
int sd;
|
||||
struct interface_info *devs;
|
||||
int count = 0;
|
||||
int capacity = 0;
|
||||
struct ifconf ifc;
|
||||
struct ifreq *ifr;
|
||||
struct ifreq tmpifr;
|
||||
int len, rc;
|
||||
char *p;
|
||||
u8 *buf;
|
||||
int bufsz;
|
||||
struct sockaddr_in *sin;
|
||||
u16 ifflags;
|
||||
int sd;
|
||||
int len;
|
||||
|
||||
ii_capacity = 16;
|
||||
mydevs = (struct interface_info *) safe_zalloc(sizeof(struct interface_info) * ii_capacity);
|
||||
capacity = 16;
|
||||
devs = (struct interface_info *) safe_zalloc(sizeof(struct interface_info) * capacity);
|
||||
|
||||
/* Dummy socket for ioctl */
|
||||
sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sd < 0) pfatal("socket in %s", __func__);
|
||||
bufsz = 20480;
|
||||
buf = (u8 *) safe_zalloc(bufsz);
|
||||
ifc.ifc_len = bufsz;
|
||||
ifc.ifc_buf = (char *) buf;
|
||||
if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) {
|
||||
if (sd < 0)
|
||||
pfatal("socket in %s", __func__);
|
||||
|
||||
ifc.ifc_len = 20480;
|
||||
ifc.ifc_buf = (char *) safe_zalloc(ifc.ifc_len);
|
||||
/* Returns an array of struct ifreq in ifc.ifc_req, which is a union with
|
||||
ifc.ifc_buf. */
|
||||
if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
|
||||
fatal("Failed to determine your configured interfaces!\n");
|
||||
}
|
||||
ifr = (struct ifreq *) buf;
|
||||
if (ifc.ifc_len == 0)
|
||||
fatal("%s: SIOCGIFCONF claims you have no network interfaces!\n", __func__);
|
||||
#if HAVE_SOCKADDR_SA_LEN
|
||||
/* len = MAX(sizeof(struct sockaddr), ifr->ifr_addr.sa_len);*/
|
||||
len = ifr->ifr_addr.sa_len + sizeof(ifr->ifr_name);
|
||||
#else
|
||||
len = sizeof(struct ifreq);
|
||||
/* len = sizeof(SA); */
|
||||
#endif
|
||||
ifr = ifc.ifc_req;
|
||||
|
||||
/* Debugging code
|
||||
printf("ifnet list length = %d\n",ifc.ifc_len);
|
||||
printf("sa_len = %d\n",len);
|
||||
hdump((unsigned char *) buf, ifc.ifc_len);
|
||||
printf("ifr = %X\n",(unsigned)(*(char **)&ifr));
|
||||
printf("Size of struct ifreq: %d\n", sizeof(struct ifreq));
|
||||
*/
|
||||
|
||||
for(; ifr && ifr->ifr_name[0] && ((u8 *)ifr) < buf + ifc.ifc_len;
|
||||
ifr = (struct ifreq *)(((char *)ifr) + len)) {
|
||||
|
||||
/* debugging code
|
||||
printf("ifr_name size = %d\n", sizeof(ifr->ifr_name));
|
||||
printf("ifr = %X\n",(unsigned)(*(char **)&ifr));
|
||||
*/
|
||||
for(ifr = ifc.ifc_req;
|
||||
ifr && ifr->ifr_name[0] && (void *) ifr < ifc.ifc_buf + ifc.ifc_len;
|
||||
ifr = (struct ifreq *) ((char *) ifr + len)) {
|
||||
struct sockaddr_in *sin;
|
||||
struct ifreq tmpifr;
|
||||
u16 ifflags;
|
||||
int rc;
|
||||
char *p;
|
||||
|
||||
/* On some platforms (such as FreeBSD), the length of each ifr changes
|
||||
based on the sockaddr type used, so we get the next length now */
|
||||
based on the sockaddr type used, so we get the next length now. */
|
||||
#if HAVE_SOCKADDR_SA_LEN
|
||||
len = ifr->ifr_addr.sa_len + sizeof(ifr->ifr_name);
|
||||
#endif
|
||||
#else
|
||||
len = sizeof(struct ifreq);
|
||||
#endif
|
||||
|
||||
/* skip any device with no name */
|
||||
if (!*((char *)ifr))
|
||||
if (ifr->ifr_name[0] == '\0')
|
||||
continue;
|
||||
|
||||
/* We currently only handle IPv4 */
|
||||
sin = (struct sockaddr_in *) &ifr->ifr_addr;
|
||||
if (sin->sin_family != AF_INET)
|
||||
continue;
|
||||
memcpy(&(mydevs[numifaces].addr), sin, MIN(sizeof(mydevs[numifaces].addr), sizeof(*sin)));
|
||||
Strncpy(mydevs[numifaces].devname, ifr->ifr_name, sizeof(mydevs[numifaces].devname));
|
||||
/* devname isn't allowed to have alias qualification */
|
||||
if ((p = strchr(mydevs[numifaces].devname, ':')))
|
||||
*p = '\0';
|
||||
Strncpy(mydevs[numifaces].devfullname, ifr->ifr_name, sizeof(mydevs[numifaces].devfullname));
|
||||
|
||||
/* Make room for this new interface if necessary. */
|
||||
if (count > capacity) {
|
||||
capacity <<= 2;
|
||||
devs = (struct interface_info *) safe_realloc(devs, sizeof(struct interface_info) * capacity);
|
||||
}
|
||||
|
||||
/* We know the address, put it in the array. */
|
||||
memcpy(&(devs[count].addr), sin, MIN(sizeof(devs[count].addr), sizeof(*sin)));
|
||||
Strncpy(devs[count].devname, ifr->ifr_name, sizeof(devs[count].devname));
|
||||
Strncpy(devs[count].devfullname, ifr->ifr_name, sizeof(devs[count].devfullname));
|
||||
/* devname isn't allowed to have alias qualification */
|
||||
p = strchr(devs[count].devname, ':');
|
||||
if (p != NULL)
|
||||
*p = '\0';
|
||||
|
||||
/* Use tmpifr for further ioctl requests. We're going to make a bunch of
|
||||
ioctl calls to learn about the interface and set fields in devs[count].
|
||||
|
||||
The Linux netdevice(7) man page says that you only have to set ifr_name
|
||||
before making the ioctl, but perhaps other platforms need ifr_addr to be
|
||||
set too. ifr_name will persist but ifr_addr is in a union with the ioctl
|
||||
return value, so it has to be reset before every call. The general
|
||||
pattern is memcpy, then ioctl. */
|
||||
Strncpy(tmpifr.ifr_name, ifr->ifr_name, sizeof(tmpifr.ifr_name));
|
||||
memcpy(&(tmpifr.ifr_addr), sin, MIN(sizeof(tmpifr.ifr_addr), sizeof(*sin)));
|
||||
|
||||
/* Look up the netmask. Note setting of ifr_addr. */
|
||||
memcpy(&tmpifr.ifr_addr, sin, MIN(sizeof(tmpifr.ifr_addr), sizeof(*sin)));
|
||||
rc = ioctl(sd, SIOCGIFNETMASK, &tmpifr);
|
||||
if (rc < 0 && errno != EADDRNOTAVAIL)
|
||||
pfatal("Failed to determine the netmask of %s!", tmpifr.ifr_name);
|
||||
else if (rc < 0)
|
||||
mydevs[numifaces].netmask_bits = 32;
|
||||
devs[count].netmask_bits = 32;
|
||||
else {
|
||||
/* We would use ifr_netmask, but that's only on Linux, so use ifr_addr
|
||||
which shares the same memory space in a union. */
|
||||
addr_stob(&(tmpifr.ifr_addr), &mydevs[numifaces].netmask_bits);
|
||||
addr_stob(&(tmpifr.ifr_addr), &devs[count].netmask_bits);
|
||||
}
|
||||
|
||||
// printf("ifr name=%s addr=%s, mask=%X\n", mydevs[numifaces].name, inet_ntoa(mydevs[numifaces].addr), mydevs[numifaces].netmask.s_addr);
|
||||
|
||||
/* Now we need to determine the device type ... this technique
|
||||
is kinda iffy ... may not be portable. */
|
||||
/* First we get the flags */
|
||||
Strncpy(tmpifr.ifr_name, ifr->ifr_name, sizeof(tmpifr.ifr_name));
|
||||
memcpy(&(tmpifr.ifr_addr), sin, MIN(sizeof(tmpifr.ifr_addr), sizeof(*sin)));
|
||||
/* Now we need to determine the device type ... this technique is kinda iffy
|
||||
... may not be portable. */
|
||||
/* Get the flags. */
|
||||
memcpy(&tmpifr.ifr_addr, sin, MIN(sizeof(tmpifr.ifr_addr), sizeof(*sin)));
|
||||
rc = ioctl(sd, SIOCGIFFLAGS, &tmpifr);
|
||||
if (rc < 0) fatal("Failed to get IF Flags for device %s", ifr->ifr_name);
|
||||
if (rc < 0)
|
||||
pfatal("Failed to get IF Flags for device %s", ifr->ifr_name);
|
||||
|
||||
ifflags = tmpifr.ifr_flags;
|
||||
|
||||
if (ifflags & IFF_LOOPBACK)
|
||||
mydevs[numifaces].device_type = devt_loopback;
|
||||
else if (ifflags & IFF_BROADCAST) {
|
||||
mydevs[numifaces].device_type = devt_ethernet;
|
||||
/* Get the MAC Address ... */
|
||||
if (ifflags & IFF_LOOPBACK) {
|
||||
devs[count].device_type = devt_loopback;
|
||||
} else if (ifflags & IFF_BROADCAST) {
|
||||
devs[count].device_type = devt_ethernet;
|
||||
|
||||
/* If the device type is ethernet, get the MAC address. */
|
||||
#ifdef SIOCGIFHWADDR
|
||||
Strncpy(tmpifr.ifr_name, mydevs[numifaces].devname, sizeof(tmpifr.ifr_name));
|
||||
memcpy(&(tmpifr.ifr_addr), sin, MIN(sizeof(tmpifr.ifr_addr), MIN(sizeof(tmpifr.ifr_addr), sizeof(*sin))));
|
||||
memcpy(&tmpifr.ifr_addr, sin, MIN(sizeof(tmpifr.ifr_addr), sizeof(*sin)));
|
||||
rc = ioctl(sd, SIOCGIFHWADDR, &tmpifr);
|
||||
if (rc < 0 && errno != EADDRNOTAVAIL)
|
||||
pfatal("Failed to determine the MAC address of %s!", tmpifr.ifr_name);
|
||||
else if (rc >= 0)
|
||||
memcpy(mydevs[numifaces].mac, &tmpifr.ifr_addr.sa_data, 6);
|
||||
memcpy(devs[count].mac, &tmpifr.ifr_addr.sa_data, 6);
|
||||
#else
|
||||
/* Let's just let libdnet handle it ... */
|
||||
eth_t *ethsd = eth_open_cached(mydevs[numifaces].devname);
|
||||
eth_t *ethsd = eth_open_cached(devs[count].devname);
|
||||
eth_addr_t ethaddr;
|
||||
|
||||
if (!ethsd) {
|
||||
error("Warning: Unable to open interface %s -- skipping it.", mydevs[numifaces].devname);
|
||||
error("Warning: Unable to open interface %s -- skipping it.", devs[count].devname);
|
||||
continue;
|
||||
}
|
||||
if (eth_get(ethsd, ðaddr) != 0)
|
||||
fatal("%s: Failed to obtain MAC address for ethernet interface (%s)",
|
||||
__func__, mydevs[numifaces].devname);
|
||||
memcpy(mydevs[numifaces].mac, ethaddr.data, 6);
|
||||
__func__, devs[count].devname);
|
||||
memcpy(devs[count].mac, ethaddr.data, 6);
|
||||
#endif /*SIOCGIFHWADDR*/
|
||||
|
||||
} else if (ifflags & IFF_POINTOPOINT) {
|
||||
devs[count].device_type = devt_p2p;
|
||||
} else {
|
||||
devs[count].device_type = devt_other;
|
||||
}
|
||||
else if (ifflags & IFF_POINTOPOINT)
|
||||
mydevs[numifaces].device_type = devt_p2p;
|
||||
else mydevs[numifaces].device_type = devt_other;
|
||||
|
||||
if (ifflags & IFF_UP)
|
||||
mydevs[numifaces].device_up = true;
|
||||
else mydevs[numifaces].device_up = false;
|
||||
numifaces++;
|
||||
if (numifaces == ii_capacity) {
|
||||
ii_capacity <<= 2;
|
||||
mydevs = (struct interface_info *) safe_realloc(mydevs, sizeof(struct interface_info) * ii_capacity);
|
||||
}
|
||||
mydevs[numifaces].devname[0] = mydevs[numifaces].devfullname[0] = '\0';
|
||||
devs[count].device_up = true;
|
||||
else
|
||||
devs[count].device_up = false;
|
||||
|
||||
/* All done with this interface. Increase the count. */
|
||||
count++;
|
||||
}
|
||||
free(buf);
|
||||
free(ifc.ifc_buf);
|
||||
close(sd);
|
||||
|
||||
*howmany = numifaces;
|
||||
return mydevs;
|
||||
*howmany = count;
|
||||
return devs;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user