static os_result addressToIndexAndMask(struct sockaddr *addr, unsigned int *ifIndex, struct sockaddr *mask ) { os_result result = os_resultSuccess; os_boolean found = OS_FALSE; PMIB_IPADDRTABLE pIPAddrTable = NULL; DWORD dwSize = 0; DWORD i; char* errorMessage; int errNo; if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { pIPAddrTable = (MIB_IPADDRTABLE *) os_malloc(dwSize); if (pIPAddrTable != NULL) { if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) != NO_ERROR) { errNo = os_sockError(); errorMessage = os_reportErrnoToString(errNo); os_report(OS_ERROR, "addressToIndexAndMask", __FILE__, __LINE__, 0, "GetIpAddrTable failed: %d %s", errNo, errorMessage); os_free(errorMessage); result = os_resultFail; } } else { os_report(OS_ERROR, "addressToIndexAndMask", __FILE__, __LINE__, 0, "Failed to allocate %d bytes for IP address table", dwSize); result = os_resultFail; } } else { errNo = os_sockError(); errorMessage = os_reportErrnoToString(errNo); os_report(OS_ERROR, "addressToIndexAndMask", __FILE__, __LINE__, 0, "GetIpAddrTable failed: %d %s", errNo, errorMessage); os_free(errorMessage); result = os_resultFail; } if (result == os_resultSuccess) { for (i = 0; !found && i < pIPAddrTable->dwNumEntries; i++ ) { if (((struct sockaddr_in* ) addr )->sin_addr.s_addr == pIPAddrTable->table[i].dwAddr) { *ifIndex = pIPAddrTable->table[i].dwIndex; ((struct sockaddr_in*) mask)->sin_addr.s_addr= pIPAddrTable->table[i].dwMask; found = OS_TRUE; } } } if (pIPAddrTable) { os_free(pIPAddrTable); } if (!found) { result = os_resultFail; } return result; }
static int join_mcgroup (os_socket socket, const os_sockaddr_storage *mcip, const struct nn_interface *interf) { /* Note: interf == NULL indicates default address for multicast */ int rc; #if OS_SOCKET_HAS_IPV6 if (config.useIpv6) { os_ipv6_mreq ipv6mreq; memset (&ipv6mreq, 0, sizeof (ipv6mreq)); memcpy (&ipv6mreq.ipv6mr_multiaddr, &((os_sockaddr_in6 *) mcip)->sin6_addr, sizeof (ipv6mreq.ipv6mr_multiaddr)); ipv6mreq.ipv6mr_interface = interf ? interf->if_index : 0; rc = os_sockSetsockopt (socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, &ipv6mreq, sizeof (ipv6mreq)); } else #endif { struct ip_mreq mreq; mreq.imr_multiaddr = ((os_sockaddr_in *) mcip)->sin_addr; if (interf) mreq.imr_interface = ((os_sockaddr_in *) &interf->addr)->sin_addr; else mreq.imr_interface.s_addr = htonl (INADDR_ANY); rc = os_sockSetsockopt (socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof (mreq)); } if (rc != os_resultSuccess) { const char *op = config.useIpv6 ? "IPV6_JOIN_GROUP" : "IP_ADD_MEMBERSHIP"; int err = os_sockError (); char buf1[INET6_ADDRSTRLEN_EXTENDED]; sockaddr_to_string_no_port (buf1, mcip); if (interf) { char buf2[INET6_ADDRSTRLEN]; sockaddr_to_string_no_port (buf2, &interf->addr); if (err == os_sockEADDRINUSE) NN_WARNING3 ("%s for %s failed on interface with address %s: already bound\n", op, buf1, buf2); else NN_WARNING4 ("%s for %s failed on interface with address %s (errno %d)\n", op, buf1, buf2, err); } else { if (err == os_sockEADDRINUSE) NN_WARNING2 ("%s for %s failed on default interface: already bound\n", op, buf1); else NN_WARNING3 ("%s for %s failed on default interface (errno %d)\n", op, buf1, err); } return -2; } return 0; }
static int bind_socket (os_socket socket, unsigned short port, const char * address) { int rc; #if OS_SOCKET_HAS_IPV6 if (config.useIpv6) { os_sockaddr_in6 socketname; memset (&socketname, 0, sizeof (socketname)); socketname.sin6_family = AF_INET6; socketname.sin6_port = htons (port); if (address) { #ifdef WIN32 int sslen = sizeof (socketname); WSAStringToAddress ((LPTSTR) address, AF_INET6, NULL, (os_sockaddr*) &socketname, &sslen); #else inet_pton (AF_INET6, address, &(socketname.sin6_addr)); #endif } else { socketname.sin6_addr = os_in6addr_any; } rc = os_sockBind (socket, (struct sockaddr *) &socketname, sizeof (socketname)); } else #endif { struct sockaddr_in socketname; socketname.sin_family = AF_INET; socketname.sin_port = htons (port); socketname.sin_addr.s_addr = (address == NULL) ? htonl (INADDR_ANY) : inet_addr (address); rc = os_sockBind (socket, (struct sockaddr *) &socketname, sizeof (socketname)); } if (rc != os_resultSuccess) { if (os_sockError () != os_sockEADDRINUSE) print_sockerror ("bind"); return -1; } return 0; }
void print_sockerror (const char *msg) { int err = os_sockError (); NN_ERROR2 ("SOCKET ERROR %s %d\n", msg, err); }
os_result os_sockQueryIPv6Interfaces( os_ifAttributes *ifList, os_uint32 listSize, os_uint32 *validElements) { os_result result = os_resultSuccess; os_result addressInfoResult =0; unsigned long returnedBytes; unsigned int listIndex; os_socket ifcs; int retVal, done; char* errorMessage; os_sockErrno errNo; PIP_ADAPTER_ADDRESSES pAddresses = NULL; PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; unsigned long outBufLen = 0; /* Set the flags to pass to GetAdaptersAddresses*/ unsigned long flags = GAA_FLAG_INCLUDE_PREFIX; int i = 0; /* IPv6 addition */ SOCKET_ADDRESS_LIST* ipv6InterfaceList; *validElements = 0; listIndex = 0; outBufLen = sizeof (IP_ADAPTER_ADDRESSES); pAddresses = (IP_ADAPTER_ADDRESSES *) os_malloc(outBufLen); if (GetAdaptersAddresses(AF_INET6, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) { os_free(pAddresses); pAddresses = (IP_ADAPTER_ADDRESSES *) os_malloc(outBufLen); } addressInfoResult = GetAdaptersAddresses(AF_INET6, flags, NULL, pAddresses, &outBufLen); /* Now do the IPv6 interfaces */ ifcs = os_sockNew (AF_INET6, SOCK_DGRAM); if (ifcs != INVALID_SOCKET) { /* List returned from this control code query will need to be sized as 1 * SOCKET_ADDRESS_LIST + n * SOCKET_ADDRESS */ ipv6InterfaceList = os_malloc(sizeof(SOCKET_ADDRESS_LIST) + ((MAX_INTERFACES - 1) * sizeof(SOCKET_ADDRESS))); memset(ipv6InterfaceList, 0, sizeof(SOCKET_ADDRESS_LIST) + ((MAX_INTERFACES - 1) * sizeof(SOCKET_ADDRESS))); retVal = WSAIoctl(ifcs, SIO_ADDRESS_LIST_QUERY, NULL, 0, ipv6InterfaceList, sizeof(SOCKET_ADDRESS_LIST) + ((MAX_INTERFACES - 1) * sizeof(SOCKET_ADDRESS)), &returnedBytes, 0, 0); if (retVal == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT) { /* The buffer wasn't big enough. returnedBytes will now contain the required size so we can reallocate & try again */ os_free(ipv6InterfaceList); ipv6InterfaceList = os_malloc(returnedBytes); memset(ipv6InterfaceList, 0, returnedBytes); retVal = WSAIoctl(ifcs, SIO_ADDRESS_LIST_QUERY, NULL, 0, ipv6InterfaceList, returnedBytes, &returnedBytes, 0, 0); } if (retVal == SOCKET_ERROR) { errNo = os_sockError(); errorMessage = os_sockErrnoToString(errNo); os_report(OS_ERROR, "os_sockQueryInterfaces", __FILE__, __LINE__, 0, "Socket error calling WSAIoctl for IPv6 interfaces: %d %s", errNo, errorMessage); os_free(errorMessage); /* @todo Is it right to return a fail here ? Need to check on box w/ no IPv6 interfaces */ result = os_resultFail; } else { for (i = 0; i < ipv6InterfaceList->iAddressCount; ++i) { if (ipv6InterfaceList->Address[i].lpSockaddr->sa_family == AF_INET6 && ! (IN6_IS_ADDR_UNSPECIFIED(&((os_sockaddr_in6 *)&ipv6InterfaceList->Address[i].lpSockaddr)->sin6_addr))) { done = 0; if (addressInfoResult == NO_ERROR) { pCurrAddresses = pAddresses; while (pCurrAddresses && !done) { /* adapter needs to be enabled*/ if (pCurrAddresses->OperStatus == IfOperStatusUp) { pUnicast = pCurrAddresses->FirstUnicastAddress; while (pUnicast && !done) { /* check if interface ip matches adapter ip */ if (os_sockaddrIPAddressEqual((os_sockaddr*) ipv6InterfaceList->Address[i].lpSockaddr, (os_sockaddr*) pUnicast->Address.lpSockaddr)) { snprintf(ifList[listIndex].name, OS_IFNAMESIZE, "%wS", pCurrAddresses->FriendlyName); ifList[listIndex].interfaceIndexNo = (os_uint) pCurrAddresses->Ipv6IfIndex; done = 1; } pUnicast = pUnicast->Next; } } pCurrAddresses = pCurrAddresses->Next; } } /* if no name was found set this interface name to string representation of the IPv6 address */ if (!done) { os_sockaddrAddressToString((os_sockaddr*) ipv6InterfaceList->Address[i].lpSockaddr, ifList[listIndex].name, OS_IFNAMESIZE); os_report(OS_WARNING, "os_sockQueryInterfaces", __FILE__, __LINE__, 0, "Unable to determine IPv6 adapter name. Setting instead to adapter address %s", ifList[listIndex].name); } ifList[listIndex].flags = 0; ifList[listIndex].address = *((os_sockaddr_storage*) ipv6InterfaceList->Address[i].lpSockaddr); listIndex++; ++(*validElements); } } } os_sockFree (ifcs); } if (addressInfoResult == NO_ERROR) { os_free(pAddresses); } return result; }
os_result os_sockQueryInterfaces( os_ifAttributes *ifList, os_uint listSize, os_uint *validElements) { os_result result = os_resultSuccess; os_result addressInfoResult =0; INTERFACE_INFO *allInterfacesBuf; INTERFACE_INFO *intf; unsigned long returnedBytes; unsigned int listIndex; os_socket ifcs; int retVal, done; char* errorMessage; os_sockErrno errNo; PIP_ADAPTER_ADDRESSES pAddresses = NULL; PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; unsigned long outBufLen = 0; /* Set the flags to pass to GetAdaptersAddresses*/ unsigned long flags = GAA_FLAG_INCLUDE_PREFIX; /* Doesn't matter what value of family you use. WSAIoctl w/ SIO_GET_INTERFACE_LIST only returns IPv4 addresses */ unsigned long family = AF_UNSPEC; int i = 0; *validElements = 0; listIndex = 0; outBufLen = sizeof (IP_ADAPTER_ADDRESSES); pAddresses = (IP_ADAPTER_ADDRESSES *) os_malloc(outBufLen); if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) { os_free(pAddresses); pAddresses = (IP_ADAPTER_ADDRESSES *) os_malloc(outBufLen); } addressInfoResult = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); /* List the IPv4 interfaces */ ifcs = os_sockNew (AF_INET, SOCK_DGRAM); if (ifcs != INVALID_SOCKET) { allInterfacesBuf = os_malloc(MAX_INTERFACES * sizeof(INTERFACE_INFO)); memset(allInterfacesBuf, 0, MAX_INTERFACES * sizeof(INTERFACE_INFO)); retVal = WSAIoctl(ifcs, SIO_GET_INTERFACE_LIST, NULL, 0, allInterfacesBuf, MAX_INTERFACES * sizeof(INTERFACE_INFO), &returnedBytes, 0, 0); if (retVal == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT) { /* The buffer wasn't big enough. returnedBytes will now contain the required size so we can reallocate & try again */ os_free(allInterfacesBuf); allInterfacesBuf = os_malloc(returnedBytes); memset(allInterfacesBuf, 0, returnedBytes); retVal = WSAIoctl(ifcs, SIO_GET_INTERFACE_LIST, NULL, 0, allInterfacesBuf, returnedBytes, &returnedBytes, 0, 0); } if (retVal == SOCKET_ERROR) { errNo = os_sockError(); errorMessage = os_sockErrnoToString(errNo); os_report(OS_ERROR, "os_sockQueryInterfaces", __FILE__, __LINE__, 0, "Socket error calling WSAIoctl for IPv4 interfaces: %d %s", errNo, errorMessage); os_free(errorMessage); /* @todo Is it right to return a fail here ? Need to check on box w/ no IPv4 interfaces */ result = os_resultFail; } else { *validElements = returnedBytes/sizeof(INTERFACE_INFO); } while ((listIndex < listSize) && (listIndex < *validElements)) { done = 0; intf = &allInterfacesBuf[listIndex]; if (addressInfoResult == NO_ERROR) { pCurrAddresses = pAddresses; while (pCurrAddresses && !done) { /* adapter needs to be enabled*/ if (pCurrAddresses->OperStatus == IfOperStatusUp) { pUnicast = pCurrAddresses->FirstUnicastAddress; while (pUnicast && !done) { /* check if interface ip matches adapter ip */ if (os_sockaddrIPAddressEqual((os_sockaddr*) &intf->iiAddress.AddressIn, (os_sockaddr*) pUnicast->Address.lpSockaddr)) { snprintf(ifList[listIndex].name, OS_IFNAMESIZE, "%wS", pCurrAddresses->FriendlyName); ifList[listIndex].interfaceIndexNo = (os_uint) pCurrAddresses->Ipv6IfIndex; done = 1; } pUnicast = pUnicast->Next; } } pCurrAddresses = pCurrAddresses->Next; } } /* if no name is found set this */ if (!done) { snprintf(ifList[listIndex].name, OS_IFNAMESIZE, "0x%x", ntohl(intf->iiAddress.AddressIn.sin_addr.S_un.S_addr)); os_report(OS_WARNING, "os_sockQueryInterfaces", __FILE__, __LINE__, 0, "Unable to determine IPv4 adapter name. Setting instead to adapter address %s", ifList[listIndex].name); } ifList[listIndex].flags = intf->iiFlags; ifList[listIndex].address = *((os_sockaddr_storage*) &intf->iiAddress); ifList[listIndex].broadcast_address = *((os_sockaddr_storage*) &intf->iiBroadcastAddress); ((os_sockaddr_in *)(&(ifList[listIndex].broadcast_address)))->sin_addr.S_un.S_addr = ((os_sockaddr_in *)(&(ifList[listIndex].address)))->sin_addr.S_un.S_addr | ~(intf->iiNetmask.AddressIn.sin_addr.S_un.S_addr); ifList[listIndex].network_mask = *((os_sockaddr_storage*) &intf->iiNetmask); listIndex++; } os_sockFree (ifcs); } if (addressInfoResult == NO_ERROR) { os_free(pAddresses); } return result; }