support for multiple IP addresses on one device with getifaddrs

This commit is contained in:
依云
2016-02-29 12:06:48 +08:00
parent fe65bfb340
commit b0033564eb
2 changed files with 33 additions and 90 deletions

View File

@@ -36,79 +36,51 @@
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <sys/ioctl.h>
#include <cstdio>
#include <ifaddrs.h>
// #include "inet6.c"
local_addr * local_addrs = NULL;
/* moves the pointer right until a non-space is seen */
char * stripspaces (char * input)
{
char * retval = input;
while (*retval == ' ')
retval++;
return retval;
}
/*
* getLocal
* device: This should be device explicit (e.g. eth0:1)
*
* uses ioctl to get address of this device, and adds it to the
* uses getifaddrs to get addresses of this device, and adds them to the
* local_addrs-list.
*/
void getLocal (const char *device, bool tracemode)
{
/* get local IPv4 addresses */
int sock;
struct ifreq iFreq;
struct sockaddr_in *saddr;
if((sock=socket(AF_INET, SOCK_DGRAM, 0))<0)
forceExit(false, "creating socket failed while establishing local IP - are you root?");
strcpy(iFreq.ifr_name, device);
if(ioctl(sock, SIOCGIFADDR, &iFreq)<0)
forceExit(false, "ioctl failed while establishing local IP for selected device %s. You may specify the device on the command line.", device);
saddr=(struct sockaddr_in*)&iFreq.ifr_addr;
local_addrs = new local_addr (saddr->sin_addr.s_addr, local_addrs);
if (tracemode || DEBUG) {
printf ("Adding local address: %s\n", inet_ntoa(saddr->sin_addr));
struct ifaddrs *ifaddr, *ifa;
if(getifaddrs(&ifaddr) == -1) {
forceExit(false, "getifaddrs failed while establishing local IP.");
}
/* also get local IPv6 addresses */
FILE * ifinfo = fopen ("/proc/net/if_inet6", "r");
char buffer [500];
if (ifinfo)
{
do
{
if (fgets(buffer, sizeof(buffer), ifinfo))
{
char address [33];
char ifname [9];
int n_results = sscanf (buffer, "%32[0-9a-f] %*d %*d %*d %*d %8[0-9a-zA-Z]", address, ifname);
assert (n_results = 2);
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if(ifa->ifa_addr == NULL)
continue;
if (strcmp (stripspaces(ifname), device) == 0)
{
local_addrs = new local_addr (address, local_addrs);
if (tracemode || DEBUG) {
printf ("Adding local address: %s\n", address);
}
}
#if DEBUG
else
{
std::cerr << "Address skipped for interface " << ifname << std::endl;
}
#endif
if(strcmp(ifa->ifa_name, device) != 0)
continue;
int family = ifa->ifa_addr->sa_family;
if(family == AF_INET){
struct sockaddr_in *addr = (struct sockaddr_in*)ifa->ifa_addr;
local_addrs = new local_addr(addr->sin_addr.s_addr, local_addrs);
if (tracemode || DEBUG) {
printf("Adding local address: %s\n", inet_ntoa(addr->sin_addr));
}
} while (!feof(ifinfo));
fclose(ifinfo);
}else if(family == AF_INET6){
struct sockaddr_in6 *addr = (struct sockaddr_in6*)ifa->ifa_addr;
local_addrs = new local_addr(&addr->sin6_addr, local_addrs);
if (tracemode || DEBUG) {
char host[512];
printf("Adding local address: %s\n",
inet_ntop(AF_INET6, &addr->sin6_addr, host, sizeof(struct in6_addr)));
}
}
}
}