204 lines
4.8 KiB
C
204 lines
4.8 KiB
C
|
/*
|
||
|
retrieve IPv4 address of the 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 "massip-parse.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>
|
||
|
unsigned
|
||
|
rawsock_get_adapter_ip(const char *ifname)
|
||
|
{
|
||
|
int fd;
|
||
|
struct ifreq ifr;
|
||
|
struct sockaddr_in *sin;
|
||
|
struct sockaddr *sa;
|
||
|
int x;
|
||
|
|
||
|
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||
|
|
||
|
ifr.ifr_addr.sa_family = AF_INET;
|
||
|
safe_strcpy(ifr.ifr_name, IFNAMSIZ, ifname);
|
||
|
|
||
|
x = ioctl(fd, SIOCGIFADDR, &ifr);
|
||
|
if (x < 0) {
|
||
|
fprintf(stderr, "ERROR:'%s': %s\n", ifname, strerror(errno));
|
||
|
//fprintf(stderr, "ERROR:'%s': couldn't discover IP address of network interface\n", ifname);
|
||
|
close(fd);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
close(fd);
|
||
|
|
||
|
sa = &ifr.ifr_addr;
|
||
|
sin = (struct sockaddr_in *)sa;
|
||
|
return ntohl(sin->sin_addr.s_addr);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*****************************************************************************/
|
||
|
#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
|
||
|
|
||
|
unsigned
|
||
|
rawsock_get_adapter_ip(const char *ifname)
|
||
|
{
|
||
|
PIP_ADAPTER_INFO pAdapterInfo;
|
||
|
PIP_ADAPTER_INFO pAdapter = NULL;
|
||
|
DWORD err;
|
||
|
ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);
|
||
|
unsigned result = 0;
|
||
|
|
||
|
ifname = rawsock_win_name(ifname);
|
||
|
|
||
|
/*
|
||
|
* Allocate a proper sized buffer
|
||
|
*/
|
||
|
pAdapterInfo = malloc(sizeof (IP_ADAPTER_INFO));
|
||
|
if (pAdapterInfo == NULL) {
|
||
|
fprintf(stderr, "error:malloc(): for GetAdaptersinfo\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* 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:malloc(): for GetAdaptersinfo\n");
|
||
|
return 0;
|
||
|
}
|
||
|
goto again;
|
||
|
}
|
||
|
if (err != NO_ERROR) {
|
||
|
fprintf(stderr, "GetAdaptersInfo failed with error: %u\n", (unsigned)err);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* 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) {
|
||
|
const IP_ADDR_STRING *addr;
|
||
|
|
||
|
for (addr = &pAdapter->IpAddressList; addr; addr = addr->Next) {
|
||
|
unsigned x;
|
||
|
|
||
|
x = massip_parse_ipv4(addr->IpAddress.String);
|
||
|
if (x != 0xFFFFFFFF) {
|
||
|
result = x;
|
||
|
goto end;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
end:
|
||
|
if (pAdapterInfo)
|
||
|
free(pAdapterInfo);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
/*****************************************************************************
|
||
|
*****************************************************************************/
|
||
|
#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>
|
||
|
#include <netinet/in.h>
|
||
|
|
||
|
#ifdef AF_LINK
|
||
|
# include <net/if_dl.h>
|
||
|
#endif
|
||
|
#ifdef AF_PACKET
|
||
|
# include <netpacket/packet.h>
|
||
|
#endif
|
||
|
|
||
|
unsigned
|
||
|
rawsock_get_adapter_ip(const char *ifname)
|
||
|
{
|
||
|
int err;
|
||
|
struct ifaddrs *ifap;
|
||
|
struct ifaddrs *p;
|
||
|
unsigned ip;
|
||
|
|
||
|
|
||
|
/* Get the list of all network adapters */
|
||
|
err = getifaddrs(&ifap);
|
||
|
if (err != 0) {
|
||
|
perror("getifaddrs");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* 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_INET)
|
||
|
break;
|
||
|
}
|
||
|
if (p == NULL)
|
||
|
goto error; /* not found */
|
||
|
|
||
|
/* Return the address */
|
||
|
{
|
||
|
struct sockaddr_in *sin = (struct sockaddr_in *)p->ifa_addr;
|
||
|
|
||
|
ip = ntohl(sin->sin_addr.s_addr);
|
||
|
}
|
||
|
|
||
|
freeifaddrs(ifap);
|
||
|
return ip;
|
||
|
error:
|
||
|
freeifaddrs(ifap);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|