Online-Skater
Erfahrenes Mitglied
Hi Leute,
wie im Thema angekündigt geht es darum zu einer gegebenen IP-Adresse das zugehörige logische Interface auszugeben z.b. eth0. Dazu habe ich folgende Funktion geschrieben:
Wie ihr seht, soll die Funktion mit ipv4 und ipv6 Adressen umgehen können. Die Funktion funktioniert, jedoch empfinde ich den Ansatz bei ipv6 nicht zufriedenstellend. Leider lässt mein Kernel keine ioctl-Aufrufe bzgl. IPv6 zu, daher den Umweg mit dem Parsen. Sicher könnte man auch Programmausgaben wie ifconfig parsen, jedoch soll das später auf einem eingebettetem System laufen und da kann man nicht für Programmexistenzen garantieren. Daher suche ich einen Weg der möglichst sicher eine Antwort geben kann. Vielleicht hat einer von euch noch eine Idee bzw. Vorschläge den Code eleganter bzw. zuverlässiger zu machen.
Habt dank
wie im Thema angekündigt geht es darum zu einer gegebenen IP-Adresse das zugehörige logische Interface auszugeben z.b. eth0. Dazu habe ich folgende Funktion geschrieben:
C:
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <string>
#include <boost/asio/ip/address.hpp>
#include <iostream>
static const std::string getIFaceNameFromIpAddr(const boost::asio::ip::address& ipAddr)
{
std::string retVal = "unknown";
if (ipAddr.is_v4())
{
char buf[1024] = {0};
struct ifconf ifc = {0};
struct ifreq *ifr = NULL;
int sck = 0;
int nInterfaces = 0;
int i = 0;
/* Get a socket handle. */
sck = socket(AF_INET, SOCK_DGRAM, 0);
if (sck < 0)
{
perror("socket");
return retVal;
}
/* Query available interfaces. */
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if (ioctl(sck, SIOCGIFCONF, &ifc) < 0)
{
perror("ioctl(SIOCGIFCONF)");
return retVal;
}
/* Iterate through the list of interfaces. */
ifr = ifc.ifc_req;
nInterfaces = ifc.ifc_len / sizeof(struct ifreq);
for(i = 0; i < nInterfaces; i++)
{
struct ifreq *item = &ifr[i];
/* Search device name that have a given ip address */
struct sockaddr *addr = &(item->ifr_addr);
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(((struct sockaddr_in *)addr)->sin_addr), ip, INET_ADDRSTRLEN);
if (strcmp(ip , ipAddr.to_string().c_str()) == 0)
{
return retVal.assign(item->ifr_name);
}
}
}
else if (ipAddr.is_v6())
{
// must finding a better alternative ?
std::string ipv6 = ipAddr.to_string();
// count colons
short anz = 0;
size_t found = ipv6.find_first_of(':');
while (found != std::string::npos)
{
anz++;
found = ipv6.find_first_of(':', found+1);
}
// find double colons for replacing with zeros
found = ipv6.find("::");
if (found != std::string::npos)
{
short zeros = 32 - (ipv6.length() - anz);
ipv6.insert(found, zeros, '0'); // insert zeros
}
// remove colons
for (std::string::iterator it = ipv6.begin(); it != ipv6.end(); ++it)
{
if (*it == ':')
ipv6.erase(it--);
}
// parse /proc/net/if_inet6
FILE *fp;
char str_addr[40];
unsigned int plen, scope, dad_status, if_idx;
char devname[IFNAMSIZ];
char buf[256];
if ((fp = fopen("/proc/net/if_inet6", "r")) != NULL)
{
while ((fgets(buf, sizeof(buf), fp) != NULL)
&& sscanf(buf, "%32s %02x %02x %02x %02x %15s\n", str_addr, &if_idx, &plen, &scope, &dad_status, devname) != EOF)
{
if (strcmp(str_addr, ipv6.c_str()) == 0)
{
return retVal.assign(devname);
}
}
fclose(fp);
}
}
return retVal;
}
Habt dank
