in source/code/scxsystemlib/networkinterface/networkinterface.cpp [1808:2045]
void NetworkInterfaceInfo::ParseIPv6Addr(SCXCoreLib::SCXHandle<NetworkInterfaceDependencies> deps)
{
#if defined(linux)
class AutoIFAddr
{
struct ifaddrs * m_ifAddr;
SCXCoreLib::SCXHandle<NetworkInterfaceDependencies> m_deps;
public:
AutoIFAddr(struct ifaddrs * ifAddr, SCXCoreLib::SCXHandle<NetworkInterfaceDependencies> depsInit):
m_ifAddr(ifAddr), m_deps(depsInit)
{
}
~AutoIFAddr()
{
if(m_ifAddr != NULL)
{
m_deps->freeifaddrs(m_ifAddr);
}
}
struct ifaddrs * GetIFAddr()
{
return m_ifAddr;
}
};
struct ifaddrs *ifAddrPtr;
if (deps->getifaddrs(&ifAddrPtr) != 0)
{
SCX_LOGTRACE(m_log, L"For net device " + m_name + L" getifaddrs() failed, errno : " + wstrerror(errno) + L'.');
return;
}
AutoIFAddr ifAddr(ifAddrPtr, m_deps);
struct ifaddrs * ifa = NULL;
void * pTmpAddr = NULL;
for (ifa = ifAddr.GetIFAddr(); ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6 && strcmp(ifa->ifa_name, StrToUTF8(m_name).c_str()) == 0)
{
pTmpAddr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
char addrStr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, pTmpAddr, addrStr, INET6_ADDRSTRLEN);
m_ipv6Address.push_back(StrFromUTF8(addrStr));
}
}
#endif
#if defined(sun) || defined(hpux) || defined(aix)
class AutoSocket
{
wstring m_devName;
int m_sock;
SCXCoreLib::SCXHandle<NetworkInterfaceDependencies> m_deps;
SCXCoreLib::SCXLogHandle m_log;
public:
AutoSocket(int sock, SCXCoreLib::SCXHandle<NetworkInterfaceDependencies> depsInit,
SCXCoreLib::SCXLogHandle log, const wstring &devName):
m_sock(sock), m_deps(depsInit), m_log(log), m_devName(devName)
{
}
~AutoSocket()
{
if(m_sock != -1)
{
if(m_deps->close(m_sock) != 0)
{
SCX_LOGERROR(m_log, L"For net device " + m_devName + L" closing socket failed, errno : " +
wstrerror(errno) + L'.');
}
}
}
int GetSock()
{
return m_sock;
}
};
AutoSocket sd(deps->socket(AF_INET6, SOCK_DGRAM, 0), m_deps, m_log, m_name);
if(sd.GetSock() == -1)
{
SCX_LOGTRACE(m_log, L"For net device " + m_name +
L" opening socket(AF_INET6, SOCK_DGRAM, 0) failed, errno : " + wstrerror(errno) + L'.');
return;
}
#if defined(sun)
int ifCnt = 0;
struct lifnum lifn;
lifn.lifn_family = AF_UNSPEC;
lifn.lifn_flags = 0;
if (deps->ioctl(sd.GetSock(), SIOCGLIFNUM, &lifn) != 0)
{
SCX_LOGTRACE(m_log, L"For net device " + m_name + L" ioctl(SIOCGLIFNUM) failed, errno : " +
wstrerror(errno) + L'.');
return;
}
ifCnt = lifn.lifn_count;
if (ifCnt == 0)
{
// Nothing to do, and also later we count on the vector size to be more than 0.
return;
}
vector<lifreq> lifcBuff;
struct lifconf lifc;
lifcBuff.resize(ifCnt);
lifc.lifc_len = ifCnt * sizeof (lifreq);
lifc.lifc_buf = (caddr_t)&lifcBuff[0];// It's safe because size of the vector is always more than 0.
lifc.lifc_family = AF_UNSPEC;
lifc.lifc_flags = 0;
if (deps->ioctl(sd.GetSock(), SIOCGLIFCONF, &lifc) != 0)
{
SCX_LOGTRACE(m_log, L"For net device " + m_name + L" ioctl(SIOCGLIFCONF) failed, errno : " +
wstrerror(errno) + L'.');
return;
}
size_t lifrCnt = lifc.lifc_len / sizeof (lifreq);
for (size_t i = 0; i < lifrCnt; i++)
{
string currName = lifcBuff[i].lifr_name;
string name = SCXCoreLib::StrToUTF8(m_name);
string name1 = name + ':';
if (currName == name || currName.substr(0, name1.size()) == name1)
{
struct sockaddr * sockAddr = (struct sockaddr *)&lifcBuff[i].lifr_addr;
if (sockAddr->sa_family == AF_INET6)
{
char addrStr[INET6_ADDRSTRLEN];
inet_ntop(sockAddr->sa_family, &((struct sockaddr_in6 *)sockAddr)->sin6_addr, addrStr, INET6_ADDRSTRLEN);
m_ipv6Address.push_back(StrFromUTF8(addrStr));
}
}
}
#elif defined(hpux)
int ifCnt = 0;
if (deps->ioctl(sd.GetSock(), SIOCGLIFNUM, &ifCnt) != 0)
{
SCX_LOGTRACE(m_log, L"For net device " + m_name + L" ioctl(SIOCGLIFNUM) failed, errno : " +
wstrerror(errno) + L'.');
return;
}
if (ifCnt == 0)
{
// Nothing to do, and also later we count on the vector size to be more than 0.
return;
}
vector<if_laddrreq> lifcBuff;
struct if_laddrconf lifc;
lifcBuff.resize(ifCnt);
lifc.iflc_len = ifCnt * sizeof (if_laddrreq);
lifc.iflc_buf = (caddr_t)&lifcBuff[0];// It's safe because size of the vector is always more than 0.
if (deps->ioctl(sd.GetSock(), SIOCGLIFCONF, &lifc) != 0)
{
SCX_LOGTRACE(m_log, L"For net device " + m_name + L" ioctl(SIOCGLIFCONF) failed, errno : " +
wstrerror(errno) + L'.');
return;
}
size_t lifrCnt = lifc.iflc_len / sizeof (if_laddrreq);
for (size_t i = 0; i < lifrCnt; i++)
{
string currName = lifcBuff[i].iflr_name;
string name = SCXCoreLib::StrToUTF8(m_name);
string name1 = name + ':';
if (currName == name || currName.substr(0, name1.size()) == name1)
{
struct sockaddr * sockAddr = (struct sockaddr *)&lifcBuff[i].iflr_addr;
if (sockAddr->sa_family == AF_INET6)
{
char addrStr[INET6_ADDRSTRLEN];
// We cast sockAddr to char* to stop the warning on RISC machines: sockaddr_in6 more strictly
// alligned than sockAddr. Addresses must be right anyway since they're returned by the previous
// ioctl(SIOCGLIFCONF) call.
inet_ntop(sockAddr->sa_family, &((struct sockaddr_in6 *)((char*)sockAddr))->sin6_addr, addrStr,
INET6_ADDRSTRLEN);
m_ipv6Address.push_back(StrFromUTF8(addrStr));
}
}
}
#elif defined(aix)
// Code inspired by the IBM examples on how to use network system calls.
#if !defined(MAX)
#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
#endif
#define SIZE(p) MAX((p).sa_len, sizeof(p))
int buffSize = 0;
if (deps->ioctl(sd.GetSock(), SIOCGSIZIFCONF, &buffSize) != 0)
{
SCX_LOGTRACE(m_log, L"For net device " + m_name + L" ioctl(SIOCGSIZIFCONF) failed, errno : " +
wstrerror(errno) + L'.');
return;
}
vector<char> ifconfBuf;
ifconfBuf.resize(buffSize);
struct ifconf ifc;
ifc.ifc_buf = &ifconfBuf[0];
ifc.ifc_len = ifconfBuf.size();
if (deps->ioctl(sd.GetSock(), SIOCGIFCONF, &ifc) != 0)
{
SCX_LOGTRACE(m_log, L"For net device " + m_name + L" ioctl(SIOCGIFCONF) failed, errno : " +
wstrerror(errno) + L'.');
return;
}
char *cp, *cplim;
struct ifreq *ifr = ifc.ifc_req;
cp = (char *)ifc.ifc_req;
cplim = cp + ifc.ifc_len;
// Iterate through the sequence of variable size data structures containing the interface name. cplim points to
// the end of the sequence. Each data structure consists of the fixed size name array and variable size
// additional data whose size is obtained by using the SIZE macro.
for(; cp < cplim; cp += (sizeof(ifr->ifr_name) + SIZE(ifr->ifr_addr)))
{
ifr = (struct ifreq *)cp;
if (0 == strcmp(ifr->ifr_name, StrToUTF8(m_name).c_str()))
{
// Interface name matches.
struct sockaddr *sa;
sa = (struct sockaddr *)&(ifr->ifr_addr);
if (sa->sa_family == AF_INET6)
{
// It is IPv6 address.
char addrStr[INET6_ADDRSTRLEN];
// Translate address to string.
inet_ntop(AF_INET6, (struct in6_addr *)&(((struct sockaddr_in6 *)sa)->sin6_addr), addrStr,
INET6_ADDRSTRLEN);
// Store the address.
m_ipv6Address.push_back(StrFromUTF8(addrStr));
}
}
}
#endif
#endif// defined(sun) || defined(hpux) || defined(aix)
}