/contrib/ntp/libisc/interfaceiter.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 220 lines · 140 code · 28 blank · 52 comment · 28 complexity · b2711ff2be231b929598dbdfc8569faa MD5 · raw file

  1. /*
  2. * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 1999-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: interfaceiter.c,v 1.22.2.1.10.14 2004/08/28 06:25:22 marka Exp $ */
  18. #include <config.h>
  19. #define ISC_ONLY_IPV6
  20. #include <sys/types.h>
  21. #include <sys/ioctl.h>
  22. #ifdef HAVE_SYS_SOCKIO_H
  23. #include <sys/sockio.h> /* Required for ifiter_ioctl.c. */
  24. #endif
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <unistd.h>
  28. #include <errno.h>
  29. #include <isc/interfaceiter.h>
  30. #include <isc/magic.h>
  31. #include <isc/mem.h>
  32. #include <isc/msgs.h>
  33. #include <isc/net.h>
  34. #include <isc/print.h>
  35. #include <isc/result.h>
  36. #include <isc/strerror.h>
  37. #include <isc/string.h>
  38. #include <isc/types.h>
  39. #include <isc/util.h>
  40. /* Must follow <isc/net.h>. */
  41. #ifdef HAVE_NET_IF6_H
  42. #include <net/if6.h>
  43. #endif
  44. /* Common utility functions */
  45. /*
  46. * Extract the network address part from a "struct sockaddr".
  47. *
  48. * The address family is given explicitly
  49. * instead of using src->sa_family, because the latter does not work
  50. * for copying a network mask obtained by SIOCGIFNETMASK (it does
  51. * not have a valid address family).
  52. */
  53. static void
  54. get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src,
  55. char *ifname)
  56. {
  57. struct sockaddr_in6 *sa6;
  58. #if !defined(ISC_PLATFORM_HAVEIFNAMETOINDEX) || \
  59. !defined(ISC_PLATFORM_HAVESCOPEID)
  60. UNUSED(ifname);
  61. #endif
  62. /* clear any remaining value for safety */
  63. memset(dst, 0, sizeof(*dst));
  64. dst->family = family;
  65. switch (family) {
  66. case AF_INET:
  67. memcpy(&dst->type.in,
  68. &((struct sockaddr_in *) src)->sin_addr,
  69. sizeof(struct in_addr));
  70. break;
  71. case AF_INET6:
  72. sa6 = (struct sockaddr_in6 *)src;
  73. memcpy(&dst->type.in6, &sa6->sin6_addr,
  74. sizeof(struct in6_addr));
  75. #ifdef ISC_PLATFORM_HAVESCOPEID
  76. if (sa6->sin6_scope_id != 0)
  77. isc_netaddr_setzone(dst, sa6->sin6_scope_id);
  78. else {
  79. /*
  80. * BSD variants embed scope zone IDs in the 128bit
  81. * address as a kernel internal form. Unfortunately,
  82. * the embedded IDs are not hidden from applications
  83. * when getting access to them by sysctl or ioctl.
  84. * We convert the internal format to the pure address
  85. * part and the zone ID part.
  86. * Since multicast addresses should not appear here
  87. * and they cannot be distinguished from netmasks,
  88. * we only consider unicast link-local addresses.
  89. */
  90. if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
  91. isc_uint16_t zone16;
  92. memcpy(&zone16, &sa6->sin6_addr.s6_addr[2],
  93. sizeof(zone16));
  94. zone16 = ntohs(zone16);
  95. if (zone16 != 0) {
  96. /* the zone ID is embedded */
  97. isc_netaddr_setzone(dst,
  98. (isc_uint32_t)zone16);
  99. dst->type.in6.s6_addr[2] = 0;
  100. dst->type.in6.s6_addr[3] = 0;
  101. #ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
  102. } else if (ifname != NULL) {
  103. unsigned int zone;
  104. /*
  105. * sin6_scope_id is still not provided,
  106. * but the corresponding interface name
  107. * is know. Use the interface ID as
  108. * the link ID.
  109. */
  110. zone = if_nametoindex(ifname);
  111. if (zone != 0) {
  112. isc_netaddr_setzone(dst,
  113. (isc_uint32_t)zone);
  114. }
  115. #endif
  116. }
  117. }
  118. }
  119. #endif
  120. break;
  121. default:
  122. INSIST(0);
  123. break;
  124. }
  125. }
  126. /*
  127. * Include system-dependent code.
  128. */
  129. #if HAVE_GETIFADDRS
  130. #include "ifiter_getifaddrs.c"
  131. #elif HAVE_IFLIST_SYSCTL
  132. #include "ifiter_sysctl.c"
  133. #else
  134. #include "ifiter_ioctl.c"
  135. #endif
  136. /*
  137. * The remaining code is common to the sysctl and ioctl case.
  138. */
  139. isc_result_t
  140. isc_interfaceiter_current(isc_interfaceiter_t *iter,
  141. isc_interface_t *ifdata)
  142. {
  143. REQUIRE(iter->result == ISC_R_SUCCESS);
  144. memcpy(ifdata, &iter->current, sizeof(*ifdata));
  145. return (ISC_R_SUCCESS);
  146. }
  147. isc_result_t
  148. isc_interfaceiter_first(isc_interfaceiter_t *iter) {
  149. isc_result_t result;
  150. REQUIRE(VALID_IFITER(iter));
  151. internal_first(iter);
  152. for (;;) {
  153. result = internal_current(iter);
  154. if (result != ISC_R_IGNORE)
  155. break;
  156. result = internal_next(iter);
  157. if (result != ISC_R_SUCCESS)
  158. break;
  159. }
  160. iter->result = result;
  161. return (result);
  162. }
  163. isc_result_t
  164. isc_interfaceiter_next(isc_interfaceiter_t *iter) {
  165. isc_result_t result;
  166. REQUIRE(VALID_IFITER(iter));
  167. REQUIRE(iter->result == ISC_R_SUCCESS);
  168. for (;;) {
  169. result = internal_next(iter);
  170. if (result != ISC_R_SUCCESS)
  171. break;
  172. result = internal_current(iter);
  173. if (result != ISC_R_IGNORE)
  174. break;
  175. }
  176. iter->result = result;
  177. return (result);
  178. }
  179. void
  180. isc_interfaceiter_destroy(isc_interfaceiter_t **iterp)
  181. {
  182. isc_interfaceiter_t *iter;
  183. REQUIRE(iterp != NULL);
  184. iter = *iterp;
  185. REQUIRE(VALID_IFITER(iter));
  186. internal_destroy(iter);
  187. if (iter->buf != NULL)
  188. isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
  189. iter->magic = 0;
  190. isc_mem_put(iter->mctx, iter, sizeof(*iter));
  191. *iterp = NULL;
  192. }