コード例 #1
0
ファイル: ifiter_ioctl.c プロジェクト: JeanCaron/bind9
static isc_result_t
internal_next(isc_interfaceiter_t *iter) {
#ifdef HAVE_TRUCLUSTER
	int clua_result;
#endif
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
	if (iter->mode == 6) {
		iter->result6 = internal_next6(iter);
		if (iter->result6 != ISC_R_NOMORE)
			return (iter->result6);
		if (iter->first6) {
			iter->first6 = ISC_FALSE;
			return (ISC_R_SUCCESS);
		}
	}
#endif
#ifdef HAVE_TRUCLUSTER
	if (!iter->clua_done) {
		clua_result = clua_getaliasaddress(&iter->clua_sa,
						   &iter->clua_context);
		if (clua_result != CLUA_SUCCESS)
			iter->clua_done = ISC_TRUE;
		return (ISC_R_SUCCESS);
	}
#endif
	return (internal_next4(iter));
}
コード例 #2
0
ファイル: ifiter_ioctl.c プロジェクト: JeanCaron/bind9
static
void internal_first(isc_interfaceiter_t *iter) {
#ifdef HAVE_TRUCLUSTER
	int clua_result;
#endif
	iter->pos = 0;
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
	iter->pos6 = 0;
	if (iter->result6 == ISC_R_NOMORE)
		iter->result6 = ISC_R_SUCCESS;
	iter->first6 = ISC_TRUE;
#endif
#ifdef HAVE_TRUCLUSTER
	iter->clua_context = 0;
	clua_result = clua_getaliasaddress(&iter->clua_sa,
					   &iter->clua_context);
	iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
#endif
#ifdef __linux
	linux_if_inet6_first(iter);
#endif
}
コード例 #3
0
ファイル: SocketUtils.cpp プロジェクト: zhangmxin/EasyDarwin
void SocketUtils::Initialize(bool lookupDNSName)
{
#if defined(__Win32__) || defined(USE_SIOCGIFNUM)

	int tempSocket = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (tempSocket == -1)
		return;

#ifdef __Win32__

	static const UInt32 kMaxAddrBufferSize = 2048;
	char inBuffer[kMaxAddrBufferSize];
	char outBuffer[kMaxAddrBufferSize];
	UInt32 theReturnedSize = 0;

	//
	// Use the WSAIoctl function call to get a list of IP addresses
	int theErr = ::WSAIoctl(tempSocket, SIO_GET_INTERFACE_LIST,
		inBuffer, kMaxAddrBufferSize,
		outBuffer, kMaxAddrBufferSize,
		&theReturnedSize,
		nullptr,
		nullptr);
	Assert(theErr == 0);
	if (theErr != 0)
		return;

	Assert((theReturnedSize % sizeof(INTERFACE_INFO)) == 0);
	LPINTERFACE_INFO addrListP = (LPINTERFACE_INFO)&outBuffer[0];

	sNumIPAddrs = theReturnedSize / sizeof(INTERFACE_INFO);
#else
#if defined(USE_SIOCGIFNUM)
	if (::ioctl(tempSocket, SIOCGIFNUM, (char*)&sNumIPAddrs) == -1)
	{
#ifdef MAXIFS
		sNumIPAddrs = MAXIFS;
#else
		sNumIPAddrs = 64;
#endif
	}
#else
#error
#endif
	struct ifconf ifc;
	::memset(&ifc, 0, sizeof(ifc));
	ifc.ifc_len = sNumIPAddrs * sizeof(struct ifreq);
	ifc.ifc_buf = (caddr_t)new struct ifreq[sNumIPAddrs];
	Assert(ifc.ifc_buf != nullptr);

	::memset(ifc.ifc_buf, '\0', ifc.ifc_len);
	int theErr = ::ioctl(tempSocket, SIOCGIFCONF, (char*)&ifc);
	Assert(theErr == 0);
	if (theErr != 0)
		return;
	struct ifreq* ifr = (struct ifreq*)ifc.ifc_buf;
#endif

	//allocate the IPAddrInfo array. Unfortunately we can't allocate this
	//array the proper way due to a GCC bug
	UInt8* addrInfoMem = new UInt8[sizeof(IPAddrInfo) * sNumIPAddrs];
	::memset(addrInfoMem, 0, sizeof(IPAddrInfo) * sNumIPAddrs);
	sIPAddrInfoArray = (IPAddrInfo*)addrInfoMem;

	//for (UInt32 addrCount = 0; addrCount < sNumIPAddrs; addrCount++)
	UInt32 currentIndex = 0;
	for (UInt32 theIfCount = sNumIPAddrs, addrCount = 0;
		addrCount < theIfCount; addrCount++)
	{
#ifdef __Win32__
		// We *should* count the loopback interface as a valid interface.
		//if (addrListP[addrCount].iiFlags & IFF_LOOPBACK)
		//{
			// Don't count loopback addrs
		//  sNumIPAddrs--;
		//  continue;
		//}
		//if (addrListP[addrCount].iiFlags & IFF_LOOPBACK)
		//  if (lookupDNSName) // The playlist broadcaster doesn't care
		//      Assert(addrCount > 0); // If the loopback interface is interface 0, we've got problems

		struct sockaddr_in* theAddr = (struct sockaddr_in*)&addrListP[addrCount].iiAddress;
#elif defined(USE_SIOCGIFNUM)
		if (ifr[addrCount].ifr_addr.sa_family != AF_INET)
		{
			sNumIPAddrs--;
			continue;
		}
		struct ifreq ifrf;
		::memset(&ifrf, 0, sizeof(ifrf));
		::strncpy(ifrf.ifr_name, ifr[addrCount].ifr_name, sizeof(ifrf.ifr_name));
		theErr = ::ioctl(tempSocket, SIOCGIFFLAGS, (char *)&ifrf);
		Assert(theErr != -1);

#ifndef __solaris__
		/* Skip things which aren't interesting */
		if ((ifrf.ifr_flags & IFF_UP) == 0 ||
			(ifrf.ifr_flags & (IFF_BROADCAST | IFF_POINTOPOINT)) == 0)
		{
			sNumIPAddrs--;
			continue;
		}
		if (ifrf.ifr_flags & IFF_LOOPBACK)
		{
			Assert(addrCount > 0); // If the loopback interface is interface 0, we've got problems
		}
#endif

		struct sockaddr_in* theAddr = (struct sockaddr_in*)&ifr[addrCount].ifr_addr;
#if 0
		puts(ifr[addrCount].ifr_name);
#endif
#else
#error
#endif

		char* theAddrStr = ::inet_ntoa(theAddr->sin_addr);

		//store the IP addr
		sIPAddrInfoArray[currentIndex].fIPAddr = ntohl(theAddr->sin_addr.s_addr);

		//store the IP addr as a string
		sIPAddrInfoArray[currentIndex].fIPAddrStr.Len = ::strlen(theAddrStr);
		sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fIPAddrStr.Len + 2];
		::strcpy(sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr, theAddrStr);


		struct hostent* theDNSName = nullptr;
		if (lookupDNSName) //convert this addr to a dns name, and store it
		{
			theDNSName = ::gethostbyaddr((char *)&theAddr->sin_addr, sizeof(theAddr->sin_addr), AF_INET);
		}

		if (theDNSName != nullptr)
		{
			sIPAddrInfoArray[currentIndex].fDNSNameStr.Len = ::strlen(theDNSName->h_name);
			sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fDNSNameStr.Len + 2];
			::strcpy(sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr, theDNSName->h_name);
		}
		else
		{
			//if we failed to look up the DNS name, just store the IP addr as a string
			sIPAddrInfoArray[currentIndex].fDNSNameStr.Len = sIPAddrInfoArray[currentIndex].fIPAddrStr.Len;
			sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fDNSNameStr.Len + 2];
			::strcpy(sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr, sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr);
		}
		//move onto the next array index
		currentIndex++;

	}
#ifdef __Win32__
	::closesocket(tempSocket);
#elif defined(USE_SIOCGIFNUM)
	delete[] ifc.ifc_buf;
	close(tempSocket);
#else
#error
#endif

#else // !__Win32__

	//Most of this code is similar to the SIOCGIFCONF code presented in Stevens,
	//Unix Network Programming, section 16.6

	//Use the SIOCGIFCONF ioctl call to iterate through the network interfaces
	static const UInt32 kMaxAddrBufferSize = 2048;

	struct ifconf ifc;
	::memset(&ifc, 0, sizeof(ifc));
	struct ifreq* ifr;
	char buffer[kMaxAddrBufferSize];

	int tempSocket = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (tempSocket == -1)
		return;

	ifc.ifc_len = kMaxAddrBufferSize;
	ifc.ifc_buf = buffer;

#if __linux__ || __linuxppc__ || __solaris__ || __MacOSX__ || __sgi__ || __osf__
	int err = ::ioctl(tempSocket, SIOCGIFCONF, (char*)&ifc);
#elif __FreeBSD__
	int err = ::ioctl(tempSocket, OSIOCGIFCONF, (char*)&ifc);
#else
#error
#endif
	if (err == -1)
		return;

#if __FreeBSD__
	int netdev1, netdev2;
	struct ifreq *netdevifr;
	netdevifr = ifc.ifc_req;
	netdev1 = ifc.ifc_len / sizeof(struct ifreq);
	for (netdev2 = netdev1 - 1; netdev2 >= 0; netdev2--)
	{
		if (ioctl(tempSocket, SIOCGIFADDR, &netdevifr[netdev2]) != 0)
			continue;
	}
#endif

	close(tempSocket);
	tempSocket = -1;

	//walk through the list of IP addrs twice. Once to find out how many,
	//the second time to actually grab their information
	char* ifReqIter = nullptr;
	sNumIPAddrs = 0;

	for (ifReqIter = buffer; ifReqIter < (buffer + ifc.ifc_len);)
	{
		ifr = (struct ifreq*)ifReqIter;
		if (!SocketUtils::IncrementIfReqIter(&ifReqIter, ifr))
			return;

		// Some platforms have lo as the first interface, so we have code to
		// work around this problem below
		//if (::strncmp(ifr->ifr_name, "lo", 2) == 0)
		//  Assert(sNumIPAddrs > 0); // If the loopback interface is interface 0, we've got problems

		//Only count interfaces in the AF_INET family.
		if (ifr->ifr_addr.sa_family == AF_INET)
			sNumIPAddrs++;
	}

#ifdef TRUCLUSTER

	int clusterAliases = 0;

	if (clu_is_member())
	{
		/* loading the vector table */
		if (clua_getaliasaddress_vector == nullptr)
		{
			clucall_stat    clustat;
			struct sockaddr_in  sin;

			clustat = clucall_load("libclua.so", clua_vectors);
			int context = 0;
			clua_status_t      addr_err;

			if (clua_getaliasaddress_vector != nullptr)
				while ((addr_err = clua_getaliasaddress
				((struct sockaddr*)&sin, &context)) == CLUA_SUCCESS)
				{
					sNumIPAddrs++;
					clusterAliases++;
				}
		}

	}

#endif // TRUCLUSTER

	//allocate the IPAddrInfo array. Unfortunately we can't allocate this
	//array the proper way due to a GCC bug
	UInt8* addrInfoMem = new UInt8[sizeof(IPAddrInfo) * sNumIPAddrs];
	::memset(addrInfoMem, 0, sizeof(IPAddrInfo) * sNumIPAddrs);
	sIPAddrInfoArray = (IPAddrInfo*)addrInfoMem;

	//Now extract all the necessary information about each interface
	//and put it into the array
	UInt32 currentIndex = 0;

#ifdef TRUCLUSTER
	// Do these cluster aliases first so they'll be first in the list
	if (clusterAliases > 0)
	{
		int context = 0;
		struct sockaddr_in sin;
		clua_status_t      addr_err;

		while ((addr_err = clua_getaliasaddress((struct sockaddr*)&sin, &context)) == CLUA_SUCCESS)
		{
			char* theAddrStr = ::inet_ntoa(sin.sin_addr);

			//store the IP addr
			sIPAddrInfoArray[currentIndex].fIPAddr = ntohl(sin.sin_addr.s_addr);

			//store the IP addr as a string
			sIPAddrInfoArray[currentIndex].fIPAddrStr.Len = ::strlen(theAddrStr);
			sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fIPAddrStr.Len + 2];
			::strcpy(sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr, theAddrStr);

			//convert this addr to a dns name, and store it
			struct hostent* theDNSName = ::gethostbyaddr((char *)&sin.sin_addr,
				sizeof(sin.sin_addr), AF_INET);
			if (theDNSName != nullptr)
			{
				sIPAddrInfoArray[currentIndex].fDNSNameStr.Len = ::strlen(theDNSName->h_name);
				sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fDNSNameStr.Len + 2];
				::strcpy(sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr, theDNSName->h_name);
			}
			else
			{
				//if we failed to look up the DNS name, just store the IP addr as a string
				sIPAddrInfoArray[currentIndex].fDNSNameStr.Len = sIPAddrInfoArray[currentIndex].fIPAddrStr.Len;
				sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fDNSNameStr.Len + 2];
				::strcpy(sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr, sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr);
			}

			currentIndex++;
		}
	}
#endif // TRUCLUSTER	

	for (ifReqIter = buffer; ifReqIter < (buffer + ifc.ifc_len);)
	{
		ifr = (struct ifreq*)ifReqIter;
		if (!SocketUtils::IncrementIfReqIter(&ifReqIter, ifr))
		{
			Assert(0);//we should have already detected this error
			return;
		}

		//Only count interfaces in the AF_INET family
		if (ifr->ifr_addr.sa_family == AF_INET)
		{
			struct sockaddr_in* addrPtr = (struct sockaddr_in*)&ifr->ifr_addr;
			char* theAddrStr = ::inet_ntoa(addrPtr->sin_addr);

			//store the IP addr
			sIPAddrInfoArray[currentIndex].fIPAddr = ntohl(addrPtr->sin_addr.s_addr);

			//store the IP addr as a string
			sIPAddrInfoArray[currentIndex].fIPAddrStr.Len = ::strlen(theAddrStr);
			sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fIPAddrStr.Len + 2];
			::strcpy(sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr, theAddrStr);

			struct hostent* theDNSName = nullptr;
			if (lookupDNSName) //convert this addr to a dns name, and store it
			{
				theDNSName = ::gethostbyaddr((char *)&addrPtr->sin_addr, sizeof(addrPtr->sin_addr), AF_INET);
			}

			if (theDNSName != nullptr)
			{
				sIPAddrInfoArray[currentIndex].fDNSNameStr.Len = ::strlen(theDNSName->h_name);
				sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fDNSNameStr.Len + 2];
				::strcpy(sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr, theDNSName->h_name);
			}
			else
			{
				//if we failed to look up the DNS name, just store the IP addr as a string
				sIPAddrInfoArray[currentIndex].fDNSNameStr.Len = sIPAddrInfoArray[currentIndex].fIPAddrStr.Len;
				sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fDNSNameStr.Len + 2];
				::strcpy(sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr, sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr);
			}

			//move onto the next array index
			currentIndex++;
		}
	}

	Assert(currentIndex == sNumIPAddrs);
#endif

	//
	// If LocalHost is the first element in the array, switch it to be the second.
	// The first element is supposed to be the "default" interface on the machine,
	// which should really always be en0.
	if ((sNumIPAddrs > 1) && (::strcmp(sIPAddrInfoArray[0].fIPAddrStr.Ptr, "127.0.0.1") == 0))
	{
		UInt32 tempIP = sIPAddrInfoArray[1].fIPAddr;
		sIPAddrInfoArray[1].fIPAddr = sIPAddrInfoArray[0].fIPAddr;
		sIPAddrInfoArray[0].fIPAddr = tempIP;
		StrPtrLen tempIPStr(sIPAddrInfoArray[1].fIPAddrStr);
		sIPAddrInfoArray[1].fIPAddrStr = sIPAddrInfoArray[0].fIPAddrStr;
		sIPAddrInfoArray[0].fIPAddrStr = tempIPStr;
		StrPtrLen tempDNSStr(sIPAddrInfoArray[1].fDNSNameStr);
		sIPAddrInfoArray[1].fDNSNameStr = sIPAddrInfoArray[0].fDNSNameStr;
		sIPAddrInfoArray[0].fDNSNameStr = tempDNSStr;
	}
}