masscan-mark-ii/src/rawsock-getmac.c

231 lines
5.5 KiB
C

/*
get MAC address of named network interface/adapter like "eth0"
This works on:
- Windows
- Linux
- Apple
- FreeBSD
I think it'll work the same on any BSD system.
*/
#include "rawsock.h"
#include "util-safefunc.h"
#include "util-logger.h"
/*****************************************************************************
*****************************************************************************/
#if defined(__linux__)
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
int
rawsock_get_adapter_mac(const char *ifname, unsigned char *mac)
{
int fd;
int x;
struct ifreq ifr;
fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd < 0){
perror("socket");
goto end;
}
safe_strcpy(ifr.ifr_name, IFNAMSIZ, ifname);
x = ioctl(fd, SIOCGIFHWADDR, (char *)&ifr);
if (x < 0) {
perror("ioctl");
goto end;
}
/* Log helpful info about the interface type */
switch (ifr.ifr_ifru.ifru_hwaddr.sa_family) {
case 1:
LOG(1, "if:%s: type=ethernet(1)\n", ifname);
break;
default:
LOG(1, "if:%s: type=0x%04x\n", ifname, ifr.ifr_ifru.ifru_hwaddr.sa_family);
}
memcpy(mac, ifr.ifr_ifru.ifru_hwaddr.sa_data, 6);
/*
* [KLUDGE]
* For VPN tunnels with raw IP there isn't a hardware address, so just
* return a fake one instead.
*/
if (memcmp(mac, "\0\0\0\0\0\0", 6) == 0
&& ifr.ifr_ifru.ifru_hwaddr.sa_family == 0xfffe) {
LOG(1, "%s: creating fake address\n", ifname);
mac[5] = 1;
}
end:
close(fd);
return 0;
}
/*****************************************************************************
*****************************************************************************/
#elif defined(WIN32)
/* From:
* https://stackoverflow.com/questions/10972794/undefined-reference-to-getadaptersaddresses20-but-i-included-liphlpapi
* I think this fixes issue #734
*/
#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x501
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x501
#endif
#include <winsock2.h>
#include <iphlpapi.h>
#ifdef _MSC_VER
#pragma comment(lib, "IPHLPAPI.lib")
#endif
int
rawsock_get_adapter_mac(const char *ifname, unsigned char *mac)
{
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = NULL;
DWORD err;
ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);
ifname = rawsock_win_name(ifname);
/*
* Allocate a proper sized buffer
*/
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof (IP_ADAPTER_INFO));
if (pAdapterInfo == NULL) {
fprintf(stderr, "Error allocating memory needed to call GetAdaptersinfo\n");
return EFAULT;
}
/*
* Query the adapter info. If the buffer is not big enough, loop around
* and try again
*/
again:
err = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
if (err == ERROR_BUFFER_OVERFLOW) {
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
if (pAdapterInfo == NULL) {
fprintf(stderr, "Error allocating memory needed to call GetAdaptersinfo\n");
return EFAULT;
}
goto again;
}
if (err != NO_ERROR) {
fprintf(stderr, "if: GetAdaptersInfo failed with error: %u\n", (unsigned)err);
return EFAULT;
}
/*
* loop through all adapters looking for ours
*/
for ( pAdapter = pAdapterInfo;
pAdapter;
pAdapter = pAdapter->Next) {
if (rawsock_is_adapter_names_equal(pAdapter->AdapterName, ifname))
break;
}
if (pAdapter) {
if (pAdapter->AddressLength != 6)
return EFAULT;
memcpy(mac, pAdapter->Address, 6);
}
if (pAdapterInfo)
free(pAdapterInfo);
return 0;
}
/*****************************************************************************
*****************************************************************************/
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || 1
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <arpa/inet.h>
#ifdef AF_LINK
# include <net/if_dl.h>
#endif
#ifdef AF_PACKET
# include <netpacket/packet.h>
#endif
int
rawsock_get_adapter_mac(const char *ifname, unsigned char *mac)
{
int err;
struct ifaddrs *ifap;
struct ifaddrs *p;
/* Get the list of all network adapters */
err = getifaddrs(&ifap);
if (err != 0) {
perror("getifaddrs");
return 1;
}
/* Look through the list until we get our adapter */
for (p = ifap; p; p = p->ifa_next) {
if (strcmp(ifname, p->ifa_name) == 0
&& p->ifa_addr
&& p->ifa_addr->sa_family == AF_LINK)
break;
}
if (p == NULL) {
LOG(1, "if:%s: not found\n", ifname);
goto error; /* not found */
}
/* Return the address */
{
size_t len = 6;
struct sockaddr_dl *link;
link = (struct sockaddr_dl *)p->ifa_addr;
if (len > link->sdl_alen) {
memset(mac, 0, 6);
len = link->sdl_alen;
}
LOG(1, "[+] if(%s): family=%u, type=%u, len=%u\n",
ifname,
link->sdl_family,
link->sdl_type,
len);
memcpy(mac,
link->sdl_data + link->sdl_nlen,
len);
}
freeifaddrs(ifap);
return 0;
error:
freeifaddrs(ifap);
return -1;
}
#endif