Пример #1
0
/**
* Use the SIOCGIFCONF ioctl query on a socket to list available network interfaces.
* Is used for IPv4 address querying & IPv6 queries on platforms
* where getifaddrs is not available
* @param addressFamily Determines the type of socket and hence which
* interfaces you wish to query. AF_INET for IPv4, AF_INET6 for IPv6
* @see os_sockQueryInterfaces
* @see os_sockQueryIPv6Interfaces
*/
os_result
os_sockQueryInterfacesBase(
    os_ifAttributes *ifList,
    os_uint32 listSize,
    os_uint32 *validElements,
    short addressFamily)
{
    os_result result = os_resultSuccess;
    struct ifconf ifc;
    struct ifreq *ifr;
    int bufLen = 1000;
    os_socket ifcs;
    unsigned int listIndex;
    unsigned int ifrLen;

    ifcs = os_sockNew (addressFamily, SOCK_DGRAM);
    if (ifcs >= -1) {
        ifc.ifc_len = bufLen;
        ifc.ifc_buf = os_malloc (ifc.ifc_len);
        while (ifc.ifc_len == bufLen) {
            memset(ifc.ifc_buf, 0, bufLen);
            ioctl (ifcs, SIOCGIFCONF, &ifc);
            if (ifc.ifc_len < bufLen) {
                listIndex = 0;
                ifr = (struct ifreq *)ifc.ifc_buf;
                /* returned smaller than provided */
                while ((listIndex < listSize) &&
                      ((char *)ifr < ((char *)ifc.ifc_buf + ifc.ifc_len)) &&
                      (result == os_resultSuccess)) {
                    ifrLen = (unsigned int)sizeof(ifr->ifr_name);
#if (OS_SOCKET_HAS_SA_LEN == 1)
                    if (sizeof(struct sockaddr) > ifr->ifr_addr.sa_len) {
                        ifrLen += (unsigned int)sizeof(struct sockaddr);
                    } else {
                        ifrLen += ifr->ifr_addr.sa_len;
                    }
#else

                    if (ifr->ifr_addr.sa_family == AF_INET) {
                        ifrLen += sizeof(struct sockaddr_in);
                    } else if (ifr->ifr_addr.sa_family == AF_INET6) {
                        ifrLen += sizeof(os_sockaddr_in6);
                    } else {
                        ifrLen += (unsigned int)sizeof(struct sockaddr);
                    }
#endif
                   /*
                    * For some platforms (e.g. 64 bit), the sockaddr members may not be the longest members
                    * of the Union. In that case the "sizeof"-size should be used.
                    */
                   if (ifrLen < sizeof(struct ifreq)) {
                      ifrLen = sizeof(struct ifreq);
                   }

                   if (ifr->ifr_addr.sa_family == addressFamily) {
                        /* Get other interface attributes */
                        result = os_queryInterfaceAttributes (ifcs, ifr,
                            &ifList[listIndex]);
                        if (result == os_resultSuccess) {
                            listIndex++;
                        }
                    }
                    ifr = (struct ifreq *)((char *)ifr + ifrLen);
                }
                if (result == os_resultSuccess) {
                    *validElements = listIndex;
                }
            } else {
                os_free (ifc.ifc_buf);
                bufLen += 1000;
                ifc.ifc_len = bufLen;
                ifc.ifc_buf = os_malloc (ifc.ifc_len);
            }
        }
        os_free (ifc.ifc_buf);
        os_sockFree (ifcs);
    }
    return result;
}
Пример #2
0
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;
}
Пример #3
0
int make_socket
(
  os_socket * sock,
  unsigned short port,
  c_bool stream,
  c_bool reuse,
  const os_sockaddr_storage * mcip,
  const char * address
)
{
  int rc = -2;

  *sock = os_sockNew ((config.useIpv6 ? AF_INET6 : AF_INET), stream ? SOCK_STREAM : SOCK_DGRAM);

  if (! Q_VALID_SOCKET (*sock))
  {
    print_sockerror ("socket");
    return rc;
  }

  if (port && reuse && ((rc = set_reuse_options (*sock)) < 0))
  {
    goto fail;
  }

  if
  (
    (rc = set_rcvbuf (*sock) < 0) ||
    (rc = set_sndbuf (*sock) < 0) ||
    ((rc = maybe_set_dont_route (*sock)) < 0) ||
    ((rc = bind_socket (*sock, port, address)) < 0)
  )
  {
    goto fail;
  }

  if (! stream)
  {
    if ((rc = set_mc_options_transmit (*sock)) < 0)
    {
      goto fail;
    }
  }

  if (stream)
  {
#ifdef SO_NOSIGPIPE
    set_socket_nosigpipe (*sock);
#endif
#ifdef TCP_NODELAY
    if (config.tcp_nodelay)
    {
      set_socket_nodelay (*sock);
    }
#endif
  }

  if (mcip && ((rc = join_mcgroups (*sock, mcip)) < 0))
  {
    goto fail;
  }

  return 0;

fail:

  os_sockFree (*sock);
  *sock = Q_INVALID_SOCKET;
  return rc;
}
Пример #4
0
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;
}