/contrib/ntp/libisc/ifiter_getifaddrs.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 191 lines · 116 code · 38 blank · 37 comment · 36 complexity · 970d8e301d2d0260478b3bf95e8af1d4 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. * PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /* $Id: ifiter_getifaddrs.c,v 1.2.68.3 2004/03/06 08:14:59 marka Exp $ */
  18. /*
  19. * Obtain the list of network interfaces using the getifaddrs(3) library.
  20. */
  21. #include <ifaddrs.h>
  22. #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'G')
  23. #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
  24. struct isc_interfaceiter {
  25. unsigned int magic; /* Magic number. */
  26. isc_mem_t *mctx;
  27. void *buf; /* (unused) */
  28. unsigned int bufsize; /* (always 0) */
  29. struct ifaddrs *ifaddrs; /* List of ifaddrs */
  30. struct ifaddrs *pos; /* Ptr to current ifaddr */
  31. isc_interface_t current; /* Current interface data. */
  32. isc_result_t result; /* Last result code. */
  33. };
  34. isc_result_t
  35. isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
  36. isc_interfaceiter_t *iter;
  37. isc_result_t result;
  38. char strbuf[ISC_STRERRORSIZE];
  39. REQUIRE(iterp != NULL);
  40. REQUIRE(*iterp == NULL);
  41. iter = isc_mem_get(mctx, sizeof(*iter));
  42. if (iter == NULL)
  43. return (ISC_R_NOMEMORY);
  44. iter->mctx = mctx;
  45. iter->buf = NULL;
  46. iter->bufsize = 0;
  47. iter->ifaddrs = NULL;
  48. if (getifaddrs(&iter->ifaddrs) < 0) {
  49. isc__strerror(errno, strbuf, sizeof(strbuf));
  50. UNEXPECTED_ERROR(__FILE__, __LINE__,
  51. isc_msgcat_get(isc_msgcat,
  52. ISC_MSGSET_IFITERGETIFADDRS,
  53. ISC_MSG_GETIFADDRS,
  54. "getting interface "
  55. "addresses: getifaddrs: %s"),
  56. strbuf);
  57. result = ISC_R_UNEXPECTED;
  58. goto failure;
  59. }
  60. /*
  61. * A newly created iterator has an undefined position
  62. * until isc_interfaceiter_first() is called.
  63. */
  64. iter->pos = NULL;
  65. iter->result = ISC_R_FAILURE;
  66. iter->magic = IFITER_MAGIC;
  67. *iterp = iter;
  68. return (ISC_R_SUCCESS);
  69. failure:
  70. if (iter->ifaddrs != NULL) /* just in case */
  71. freeifaddrs(iter->ifaddrs);
  72. isc_mem_put(mctx, iter, sizeof(*iter));
  73. return (result);
  74. }
  75. /*
  76. * Get information about the current interface to iter->current.
  77. * If successful, return ISC_R_SUCCESS.
  78. * If the interface has an unsupported address family,
  79. * return ISC_R_IGNORE.
  80. */
  81. static isc_result_t
  82. internal_current(isc_interfaceiter_t *iter) {
  83. struct ifaddrs *ifa;
  84. int family;
  85. unsigned int namelen;
  86. REQUIRE(VALID_IFITER(iter));
  87. ifa = iter->pos;
  88. INSIST(ifa != NULL);
  89. INSIST(ifa->ifa_name != NULL);
  90. INSIST(ifa->ifa_addr != NULL);
  91. family = ifa->ifa_addr->sa_family;
  92. if (family != AF_INET && family != AF_INET6)
  93. return (ISC_R_IGNORE);
  94. memset(&iter->current, 0, sizeof(iter->current));
  95. namelen = strlen(ifa->ifa_name);
  96. if (namelen > sizeof(iter->current.name) - 1)
  97. namelen = sizeof(iter->current.name) - 1;
  98. memset(iter->current.name, 0, sizeof(iter->current.name));
  99. memcpy(iter->current.name, ifa->ifa_name, namelen);
  100. iter->current.flags = 0;
  101. if ((ifa->ifa_flags & IFF_UP) != 0)
  102. iter->current.flags |= INTERFACE_F_UP;
  103. if ((ifa->ifa_flags & IFF_POINTOPOINT) != 0)
  104. iter->current.flags |= INTERFACE_F_POINTTOPOINT;
  105. if ((ifa->ifa_flags & IFF_LOOPBACK) != 0)
  106. iter->current.flags |= INTERFACE_F_LOOPBACK;
  107. if ((ifa->ifa_flags & IFF_BROADCAST) != 0) {
  108. iter->current.flags |= INTERFACE_F_BROADCAST;
  109. }
  110. #ifdef IFF_MULTICAST
  111. if ((ifa->ifa_flags & IFF_MULTICAST) != 0) {
  112. iter->current.flags |= INTERFACE_F_MULTICAST;
  113. }
  114. #endif
  115. iter->current.af = family;
  116. get_addr(family, &iter->current.address, ifa->ifa_addr, ifa->ifa_name);
  117. if (ifa->ifa_netmask != NULL)
  118. get_addr(family, &iter->current.netmask, ifa->ifa_netmask,
  119. ifa->ifa_name);
  120. if (ifa->ifa_dstaddr != NULL &&
  121. (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
  122. get_addr(family, &iter->current.dstaddress, ifa->ifa_dstaddr,
  123. ifa->ifa_name);
  124. if (ifa->ifa_broadaddr != NULL &&
  125. (iter->current.flags & INTERFACE_F_BROADCAST) != 0)
  126. get_addr(family, &iter->current.broadcast, ifa->ifa_broadaddr,
  127. ifa->ifa_name);
  128. return (ISC_R_SUCCESS);
  129. }
  130. /*
  131. * Step the iterator to the next interface. Unlike
  132. * isc_interfaceiter_next(), this may leave the iterator
  133. * positioned on an interface that will ultimately
  134. * be ignored. Return ISC_R_NOMORE if there are no more
  135. * interfaces, otherwise ISC_R_SUCCESS.
  136. */
  137. static isc_result_t
  138. internal_next(isc_interfaceiter_t *iter) {
  139. iter->pos = iter->pos->ifa_next;
  140. if (iter->pos == NULL)
  141. return (ISC_R_NOMORE);
  142. return (ISC_R_SUCCESS);
  143. }
  144. static void
  145. internal_destroy(isc_interfaceiter_t *iter) {
  146. if (iter->ifaddrs)
  147. freeifaddrs(iter->ifaddrs);
  148. iter->ifaddrs = NULL;
  149. }
  150. static
  151. void internal_first(isc_interfaceiter_t *iter) {
  152. iter->pos = iter->ifaddrs;
  153. }