NetworkInfoServiceLinux.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/socket.h>
  9. #include <sys/types.h>
  10. #include <net/if.h>
  11. #include <netdb.h>
  12. #include "mozilla/DebugOnly.h"
  13. #include "mozilla/ScopeExit.h"
  14. #include "NetworkInfoServiceImpl.h"
  15. namespace mozilla {
  16. namespace net {
  17. static nsresult
  18. ListInterfaceAddresses(int aFd, const char* aIface, AddrMapType& aAddrMap);
  19. nsresult
  20. DoListAddresses(AddrMapType& aAddrMap)
  21. {
  22. int fd = socket(AF_INET, SOCK_DGRAM, 0);
  23. if (fd < 0) {
  24. return NS_ERROR_FAILURE;
  25. }
  26. auto autoCloseSocket = MakeScopeExit([&] {
  27. close(fd);
  28. });
  29. struct ifconf ifconf;
  30. /* 16k of space should be enough to list all interfaces. Worst case, if it's
  31. * not then we will error out and fail to list addresses. This should only
  32. * happen on pathological machines with way too many interfaces.
  33. */
  34. char buf[16384];
  35. ifconf.ifc_len = sizeof(buf);
  36. ifconf.ifc_buf = buf;
  37. if (ioctl(fd, SIOCGIFCONF, &ifconf) != 0) {
  38. return NS_ERROR_FAILURE;
  39. }
  40. struct ifreq* ifreq = ifconf.ifc_req;
  41. int i = 0;
  42. while (i < ifconf.ifc_len) {
  43. size_t len = sizeof(struct ifreq);
  44. DebugOnly<nsresult> rv =
  45. ListInterfaceAddresses(fd, ifreq->ifr_name, aAddrMap);
  46. NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "ListInterfaceAddresses failed");
  47. ifreq = (struct ifreq*) ((char*)ifreq + len);
  48. i += len;
  49. }
  50. autoCloseSocket.release();
  51. return NS_OK;
  52. }
  53. static nsresult
  54. ListInterfaceAddresses(int aFd, const char* aInterface, AddrMapType& aAddrMap)
  55. {
  56. struct ifreq ifreq;
  57. memset(&ifreq, 0, sizeof(struct ifreq));
  58. strncpy(ifreq.ifr_name, aInterface, IFNAMSIZ - 1);
  59. if (ioctl(aFd, SIOCGIFADDR, &ifreq) != 0) {
  60. return NS_ERROR_FAILURE;
  61. }
  62. char host[128];
  63. int family;
  64. switch(family=ifreq.ifr_addr.sa_family) {
  65. case AF_INET:
  66. case AF_INET6:
  67. getnameinfo(&ifreq.ifr_addr, sizeof(ifreq.ifr_addr), host, sizeof(host), 0, 0, NI_NUMERICHOST);
  68. break;
  69. case AF_UNSPEC:
  70. return NS_OK;
  71. default:
  72. // Unknown family.
  73. return NS_OK;
  74. }
  75. nsCString ifaceStr;
  76. ifaceStr.AssignASCII(aInterface);
  77. nsCString addrStr;
  78. addrStr.AssignASCII(host);
  79. aAddrMap.Put(ifaceStr, addrStr);
  80. return NS_OK;
  81. }
  82. } // namespace net
  83. } // namespace mozilla