Beispiel #1
0
static int interface_in_recvips_p (const struct nn_interface *interf)
{
  struct ospl_in_addr_node *nodeaddr;
  for (nodeaddr = gv.recvips; nodeaddr; nodeaddr = nodeaddr->next)
  {
    if (os_sockaddrIPAddressEqual ((const os_sockaddr *) &nodeaddr->addr, (const os_sockaddr *) &interf->addr))
      return 1;
  }
  return 0;
}
Beispiel #2
0
int find_own_ip (const char *requested_address)
{
  const char *sep = " ";
  char last_if_name[80] = "";
  int quality = -1;
  os_result res;
  int i;
  unsigned int nif;
  os_ifAttributes *ifs;
  int maxq_list[MAX_INTERFACES];
  int maxq_count = 0;
  int maxq_strlen = 0;
  int selected_idx = -1;
  char addrbuf[INET6_ADDRSTRLEN_EXTENDED];

  if ((ifs = os_malloc (MAX_INTERFACES * sizeof (*ifs))) == NULL)
  {
    NN_FATAL0 ("ddsi2: insufficient memory for enumerating network interfaces\n");
    return 0;
  }

  nn_log (LC_CONFIG, "interfaces:");

  if (config.useIpv6)
    res = os_sockQueryIPv6Interfaces (ifs, (os_uint32) MAX_INTERFACES, &nif);
  else
    res = os_sockQueryInterfaces (ifs, (os_uint32) MAX_INTERFACES, &nif);
  if (res != os_resultSuccess)
  {
    NN_ERROR1 ("os_sockQueryInterfaces: %d\n", (int) res);
    os_free (ifs);
    return 0;
  }

  gv.n_interfaces = 0;
  for (i = 0; i < (int) nif; i++, sep = ", ")
  {
    os_sockaddr_storage tmpip, tmpmask;
    char if_name[sizeof (last_if_name)];
    int q = 0;

    os_strncpy (if_name, ifs[i].name, sizeof (if_name) - 1);
    if_name[sizeof (if_name) - 1] = 0;

    if (strcmp (if_name, last_if_name))
      nn_log (LC_CONFIG, "%s%s", sep, if_name);
    os_strcpy (last_if_name, if_name);

    /* interface must be up */
    if ((ifs[i].flags & IFF_UP) == 0)
    {
      nn_log (LC_CONFIG, " (interface down)");
      continue;
    }

    tmpip = ifs[i].address;
    tmpmask = ifs[i].network_mask;
    sockaddr_to_string_no_port (addrbuf, &tmpip);
    nn_log (LC_CONFIG, " %s", addrbuf);

    if (ifs[i].flags & IFF_LOOPBACK)
    {
      /* Loopback device has the lowest priority of every interface
         available, because the other interfaces at least in principle
         allow communicating with other machines. */
      q += 0;
#if OS_SOCKET_HAS_IPV6
      if (!(tmpip.ss_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL (&((os_sockaddr_in6 *) &tmpip)->sin6_addr)))
        q += 1;
#endif
    }
    else
    {
#if OS_SOCKET_HAS_IPV6
      /* We accept link-local IPv6 addresses, but an interface with a
         link-local address will end up lower in the ordering than one
         with a global address.  When forced to use a link-local
         address, we restrict ourselves to operating on that one
         interface only and assume any advertised (incoming) link-local
         address belongs to that interface.  FIXME: this is wrong, and
         should be changed to tag addresses with the interface over
         which it was received.  But that means proper multi-homing
         support and has quite an impact in various places, not least of
         which is the abstraction layer. */
      if (!(tmpip.ss_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL (&((os_sockaddr_in6 *) &tmpip)->sin6_addr)))
        q += 5;
#endif

      /* We strongly prefer a multicast capable interface, if that's
         not available anything that's not point-to-point, or else we
         hope IP routing will take care of the issues. */
      if (ifs[i].flags & IFF_MULTICAST)
        q += 4;
      else if (!(ifs[i].flags & IFF_POINTOPOINT))
        q += 3;
      else
        q += 2;
    }

    nn_log (LC_CONFIG, "(q%d)", q);
    if (q == quality) {
      maxq_list[maxq_count] = gv.n_interfaces;
      maxq_strlen += 2 + strlen (if_name);
      maxq_count++;
    } else if (q > quality) {
      maxq_list[0] = gv.n_interfaces;
      maxq_strlen += 2 + strlen (if_name);
      maxq_count = 1;
      quality = q;
    }

    gv.interfaces[gv.n_interfaces].addr = tmpip;
    gv.interfaces[gv.n_interfaces].netmask = tmpmask;
    gv.interfaces[gv.n_interfaces].mc_capable = ((ifs[i].flags & IFF_MULTICAST) != 0);
    gv.interfaces[gv.n_interfaces].point_to_point = ((ifs[i].flags & IFF_POINTOPOINT) != 0);
    gv.interfaces[gv.n_interfaces].if_index = ifs[i].interfaceIndexNo;
    gv.interfaces[gv.n_interfaces].name = os_strdup (if_name);
    gv.n_interfaces++;
  }
  nn_log (LC_CONFIG, "\n");
  os_free (ifs);

  if (requested_address == NULL)
  {
    if (maxq_count > 1)
    {
      const int idx = maxq_list[0];
      char *names;
      sockaddr_to_string_no_port (addrbuf, &gv.interfaces[idx].addr);
      if ((names = os_malloc (maxq_strlen + 1)) == NULL)
        NN_WARNING2 ("using network interface %s (%s) out of multiple candidates\n",
                     gv.interfaces[idx].name, addrbuf);
      else
      {
        int p = 0;
        for (i = 0; i < maxq_count; i++)
          p += snprintf (names + p, maxq_strlen - p, ", %s", gv.interfaces[maxq_list[i]].name);
        NN_WARNING3 ("using network interface %s (%s) selected arbitrarily from: %s\n",
                     gv.interfaces[idx].name, addrbuf, names + 2);
        os_free (names);
      }
    }

    if (maxq_count > 0)
      selected_idx = maxq_list[0];
    else
      NN_ERROR0 ("failed to determine default own IP address\n");
  }
  else
  {
    os_sockaddr_storage req;
    if (!os_sockaddrStringToAddress (config.networkAddressString, (os_sockaddr *) &req, !config.useIpv6))
    {
      /* Presumably an interface name */
      for (i = 0; i < gv.n_interfaces; i++)
        if (strcmp (gv.interfaces[i].name, config.networkAddressString) == 0)
          break;
    }
    else
    {
      /* Try an exact match on the address */
      for (i = 0; i < gv.n_interfaces; i++)
        if (os_sockaddrIPAddressEqual ((os_sockaddr *) &gv.interfaces[i].addr, (os_sockaddr *) &req))
          break;
      if (i == gv.n_interfaces && !config.useIpv6)
      {
        /* Try matching on network portion only, where the network
           portion is based on the netmask of the interface under
           consideration */
        for (i = 0; i < gv.n_interfaces; i++)
        {
          os_sockaddr_storage req1 = req, ip1 = gv.interfaces[i].addr;
          assert (req1.ss_family == AF_INET);
          assert (ip1.ss_family == AF_INET);

          /* If the host portion of the requested address is non-zero,
             skip this interface */
          if (((os_sockaddr_in *) &req1)->sin_addr.s_addr &
              ~((os_sockaddr_in *) &gv.interfaces[i].netmask)->sin_addr.s_addr)
            continue;

          ((os_sockaddr_in *) &req1)->sin_addr.s_addr &=
            ((os_sockaddr_in *) &gv.interfaces[i].netmask)->sin_addr.s_addr;
          ((os_sockaddr_in *) &ip1)->sin_addr.s_addr &=
            ((os_sockaddr_in *) &gv.interfaces[i].netmask)->sin_addr.s_addr;
          if (os_sockaddrIPAddressEqual ((os_sockaddr *) &ip1, (os_sockaddr *) &req1))
            break;
        }
      }
    }

    if (i < gv.n_interfaces)
      selected_idx = i;
    else
      NN_ERROR1 ("%s: does not match an available interface\n", config.networkAddressString);
  }

  if (selected_idx < 0)
    return 0;
  else
  {
    gv.ownip = gv.interfaces[selected_idx].addr;
    sockaddr_set_port (&gv.ownip, 0);
    gv.selected_interface = selected_idx;
    gv.interfaceNo = gv.interfaces[selected_idx].if_index;
#if OS_SOCKET_HAS_IPV6
    if (config.useIpv6)
    {
      assert (gv.ownip.ss_family == AF_INET6);
      gv.ipv6_link_local =
        IN6_IS_ADDR_LINKLOCAL (&((os_sockaddr_in6 *) &gv.ownip)->sin6_addr) != 0;
    }
    else
    {
      gv.ipv6_link_local = 0;
    }
#endif
    nn_log (LC_CONFIG, "selected interface: %s (index %u)\n",
            gv.interfaces[selected_idx].name, (unsigned) gv.interfaceNo);
    return 1;
  }
}
Beispiel #3
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;
}
Beispiel #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;
}