/contrib/ntp/libisc/ifiter_ioctl.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1118 lines · 829 code · 115 blank · 174 comment · 195 complexity · e62477b724f349b4f147df4a71820867 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: ifiter_ioctl.c,v 1.19.2.5.2.14 2004/06/22 04:40:23 marka Exp $ */
  18. /*
  19. * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
  20. * See netintro(4).
  21. */
  22. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  23. #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
  24. #define lifc_len iflc_len
  25. #define lifc_buf iflc_buf
  26. #define lifc_req iflc_req
  27. #define LIFCONF if_laddrconf
  28. #else
  29. #define ISC_HAVE_LIFC_FAMILY 1
  30. #define ISC_HAVE_LIFC_FLAGS 1
  31. #define LIFCONF lifconf
  32. #endif
  33. #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
  34. #define lifr_addr iflr_addr
  35. #define lifr_name iflr_name
  36. #define lifr_dstaddr iflr_dstaddr
  37. #define lifr_broadaddr iflr_broadaddr
  38. #define lifr_flags iflr_flags
  39. #define lifr_index iflr_index
  40. #define ss_family sa_family
  41. #define LIFREQ if_laddrreq
  42. #else
  43. #define LIFREQ lifreq
  44. #endif
  45. #endif
  46. #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
  47. #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
  48. #define ISC_IF_INET6_SZ \
  49. sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n")
  50. struct isc_interfaceiter {
  51. unsigned int magic; /* Magic number. */
  52. isc_mem_t *mctx;
  53. int mode;
  54. int socket;
  55. struct ifconf ifc;
  56. void *buf; /* Buffer for sysctl data. */
  57. unsigned int bufsize; /* Bytes allocated. */
  58. unsigned int pos; /* Current offset in
  59. SIOCGIFCONF data */
  60. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  61. int socket6;
  62. struct LIFCONF lifc;
  63. void *buf6; /* Buffer for sysctl data. */
  64. unsigned int bufsize6; /* Bytes allocated. */
  65. unsigned int pos6; /* Current offset in
  66. SIOCGLIFCONF data */
  67. isc_result_t result6; /* Last result code. */
  68. isc_boolean_t first6;
  69. #endif
  70. #ifdef HAVE_TRUCLUSTER
  71. int clua_context; /* Cluster alias context */
  72. isc_boolean_t clua_done;
  73. struct sockaddr clua_sa;
  74. #endif
  75. #ifdef __linux
  76. FILE * proc;
  77. char entry[ISC_IF_INET6_SZ];
  78. isc_result_t valid;
  79. isc_boolean_t first;
  80. #endif
  81. isc_interface_t current; /* Current interface data. */
  82. isc_result_t result; /* Last result code. */
  83. };
  84. #ifdef HAVE_TRUCLUSTER
  85. #include <clua/clua.h>
  86. #include <sys/socket.h>
  87. #endif
  88. /*
  89. * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
  90. * will have more than a megabyte of interface configuration data.
  91. */
  92. #define IFCONF_BUFSIZE_INITIAL 4096
  93. #define IFCONF_BUFSIZE_MAX 1048576
  94. #ifdef __linux
  95. #ifndef IF_NAMESIZE
  96. # ifdef IFNAMSIZ
  97. # define IF_NAMESIZE IFNAMSIZ
  98. # else
  99. # define IF_NAMESIZE 16
  100. # endif
  101. #endif
  102. #endif
  103. static isc_result_t
  104. getbuf4(isc_interfaceiter_t *iter) {
  105. char strbuf[ISC_STRERRORSIZE];
  106. iter->bufsize = IFCONF_BUFSIZE_INITIAL;
  107. for (;;) {
  108. iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
  109. if (iter->buf == NULL)
  110. return (ISC_R_NOMEMORY);
  111. memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
  112. iter->ifc.ifc_len = iter->bufsize;
  113. iter->ifc.ifc_buf = iter->buf;
  114. /*
  115. * Ignore the HP/UX warning about "integer overflow during
  116. * conversion". It comes from its own macro definition,
  117. * and is really hard to shut up.
  118. */
  119. if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
  120. == -1) {
  121. if (errno != EINVAL) {
  122. isc__strerror(errno, strbuf, sizeof(strbuf));
  123. UNEXPECTED_ERROR(__FILE__, __LINE__,
  124. isc_msgcat_get(isc_msgcat,
  125. ISC_MSGSET_IFITERIOCTL,
  126. ISC_MSG_GETIFCONFIG,
  127. "get interface "
  128. "configuration: %s"),
  129. strbuf);
  130. goto unexpected;
  131. }
  132. /*
  133. * EINVAL. Retry with a bigger buffer.
  134. */
  135. } else {
  136. /*
  137. * The ioctl succeeded.
  138. * Some OS's just return what will fit rather
  139. * than set EINVAL if the buffer is too small
  140. * to fit all the interfaces in. If
  141. * ifc.lifc_len is too near to the end of the
  142. * buffer we will grow it just in case and
  143. * retry.
  144. */
  145. if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
  146. < iter->bufsize)
  147. break;
  148. }
  149. if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
  150. UNEXPECTED_ERROR(__FILE__, __LINE__,
  151. isc_msgcat_get(isc_msgcat,
  152. ISC_MSGSET_IFITERIOCTL,
  153. ISC_MSG_BUFFERMAX,
  154. "get interface "
  155. "configuration: "
  156. "maximum buffer "
  157. "size exceeded"));
  158. goto unexpected;
  159. }
  160. isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
  161. iter->bufsize *= 2;
  162. }
  163. return (ISC_R_SUCCESS);
  164. unexpected:
  165. isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
  166. iter->buf = NULL;
  167. return (ISC_R_UNEXPECTED);
  168. }
  169. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  170. static isc_result_t
  171. getbuf6(isc_interfaceiter_t *iter) {
  172. char strbuf[ISC_STRERRORSIZE];
  173. isc_result_t result;
  174. iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
  175. for (;;) {
  176. iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
  177. if (iter->buf6 == NULL)
  178. return (ISC_R_NOMEMORY);
  179. memset(&iter->lifc, 0, sizeof(iter->lifc));
  180. #ifdef ISC_HAVE_LIFC_FAMILY
  181. iter->lifc.lifc_family = AF_INET6;
  182. #endif
  183. #ifdef ISC_HAVE_LIFC_FLAGS
  184. iter->lifc.lifc_flags = 0;
  185. #endif
  186. iter->lifc.lifc_len = iter->bufsize6;
  187. iter->lifc.lifc_buf = iter->buf6;
  188. /*
  189. * Ignore the HP/UX warning about "integer overflow during
  190. * conversion". It comes from its own macro definition,
  191. * and is really hard to shut up.
  192. */
  193. if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
  194. == -1) {
  195. #ifdef __hpux
  196. /*
  197. * IPv6 interface scanning is not available on all
  198. * kernels w/ IPv6 sockets.
  199. */
  200. if (errno == ENOENT) {
  201. isc__strerror(errno, strbuf, sizeof(strbuf));
  202. UNEXPECTED_ERROR(__FILE__, __LINE__,
  203. isc_msgcat_get(isc_msgcat,
  204. ISC_MSGSET_IFITERIOCTL,
  205. ISC_MSG_GETIFCONFIG,
  206. "get interface "
  207. "configuration: %s"),
  208. strbuf);
  209. result = ISC_R_FAILURE;
  210. goto cleanup;
  211. }
  212. #endif
  213. if (errno != EINVAL) {
  214. isc__strerror(errno, strbuf, sizeof(strbuf));
  215. UNEXPECTED_ERROR(__FILE__, __LINE__,
  216. isc_msgcat_get(isc_msgcat,
  217. ISC_MSGSET_IFITERIOCTL,
  218. ISC_MSG_GETIFCONFIG,
  219. "get interface "
  220. "configuration: %s"),
  221. strbuf);
  222. result = ISC_R_UNEXPECTED;
  223. goto cleanup;
  224. }
  225. /*
  226. * EINVAL. Retry with a bigger buffer.
  227. */
  228. } else {
  229. /*
  230. * The ioctl succeeded.
  231. * Some OS's just return what will fit rather
  232. * than set EINVAL if the buffer is too small
  233. * to fit all the interfaces in. If
  234. * ifc.ifc_len is too near to the end of the
  235. * buffer we will grow it just in case and
  236. * retry.
  237. */
  238. if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
  239. < iter->bufsize6)
  240. break;
  241. }
  242. if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
  243. UNEXPECTED_ERROR(__FILE__, __LINE__,
  244. isc_msgcat_get(isc_msgcat,
  245. ISC_MSGSET_IFITERIOCTL,
  246. ISC_MSG_BUFFERMAX,
  247. "get interface "
  248. "configuration: "
  249. "maximum buffer "
  250. "size exceeded"));
  251. result = ISC_R_UNEXPECTED;
  252. goto cleanup;
  253. }
  254. isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
  255. iter->bufsize6 *= 2;
  256. }
  257. if (iter->lifc.lifc_len != 0)
  258. iter->mode = 6;
  259. return (ISC_R_SUCCESS);
  260. cleanup:
  261. isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
  262. iter->buf6 = NULL;
  263. return (result);
  264. }
  265. #endif
  266. isc_result_t
  267. isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
  268. isc_interfaceiter_t *iter;
  269. isc_result_t result;
  270. char strbuf[ISC_STRERRORSIZE];
  271. REQUIRE(iterp != NULL);
  272. REQUIRE(*iterp == NULL);
  273. iter = isc_mem_get(mctx, sizeof(*iter));
  274. if (iter == NULL)
  275. return (ISC_R_NOMEMORY);
  276. iter->mctx = mctx;
  277. iter->mode = 4;
  278. iter->buf = NULL;
  279. iter->pos = (unsigned int) -1;
  280. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  281. iter->buf6 = NULL;
  282. iter->pos6 = (unsigned int) -1;
  283. iter->result6 = ISC_R_NOMORE;
  284. iter->socket6 = -1;
  285. iter->first6 = ISC_FALSE;
  286. #endif
  287. /*
  288. * Get the interface configuration, allocating more memory if
  289. * necessary.
  290. */
  291. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  292. result = isc_net_probeipv6();
  293. if (result == ISC_R_SUCCESS) {
  294. /*
  295. * Create an unbound datagram socket to do the SIOCGLIFCONF
  296. * ioctl on. HP/UX requires an AF_INET6 socket for
  297. * SIOCGLIFCONF to get IPv6 addresses.
  298. */
  299. if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
  300. isc__strerror(errno, strbuf, sizeof(strbuf));
  301. UNEXPECTED_ERROR(__FILE__, __LINE__,
  302. isc_msgcat_get(isc_msgcat,
  303. ISC_MSGSET_IFITERIOCTL,
  304. ISC_MSG_MAKESCANSOCKET,
  305. "making interface "
  306. "scan socket: %s"),
  307. strbuf);
  308. result = ISC_R_UNEXPECTED;
  309. goto socket6_failure;
  310. }
  311. iter->result6 = getbuf6(iter);
  312. if (iter->result6 != ISC_R_NOTIMPLEMENTED &&
  313. iter->result6 != ISC_R_SUCCESS)
  314. goto ioctl6_failure;
  315. }
  316. #endif
  317. if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  318. isc__strerror(errno, strbuf, sizeof(strbuf));
  319. UNEXPECTED_ERROR(__FILE__, __LINE__,
  320. isc_msgcat_get(isc_msgcat,
  321. ISC_MSGSET_IFITERIOCTL,
  322. ISC_MSG_MAKESCANSOCKET,
  323. "making interface "
  324. "scan socket: %s"),
  325. strbuf);
  326. result = ISC_R_UNEXPECTED;
  327. goto socket_failure;
  328. }
  329. result = getbuf4(iter);
  330. if (result != ISC_R_SUCCESS)
  331. goto ioctl_failure;
  332. /*
  333. * A newly created iterator has an undefined position
  334. * until isc_interfaceiter_first() is called.
  335. */
  336. #ifdef HAVE_TRUCLUSTER
  337. iter->clua_context = -1;
  338. iter->clua_done = ISC_TRUE;
  339. #endif
  340. #ifdef __linux
  341. iter->proc = fopen("/proc/net/if_inet6", "r");
  342. iter->valid = ISC_R_FAILURE;
  343. iter->first = ISC_FALSE;
  344. #endif
  345. iter->result = ISC_R_FAILURE;
  346. iter->magic = IFITER_MAGIC;
  347. *iterp = iter;
  348. return (ISC_R_SUCCESS);
  349. ioctl_failure:
  350. if (iter->buf != NULL)
  351. isc_mem_put(mctx, iter->buf, iter->bufsize);
  352. (void) close(iter->socket);
  353. socket_failure:
  354. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  355. if (iter->buf6 != NULL)
  356. isc_mem_put(mctx, iter->buf6, iter->bufsize6);
  357. ioctl6_failure:
  358. if (iter->socket6 != -1)
  359. (void) close(iter->socket6);
  360. socket6_failure:
  361. #endif
  362. isc_mem_put(mctx, iter, sizeof(*iter));
  363. return (result);
  364. }
  365. #ifdef HAVE_TRUCLUSTER
  366. static void
  367. get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
  368. dst->family = AF_INET;
  369. memcpy(&dst->type.in, src, sizeof(struct in_addr));
  370. }
  371. static isc_result_t
  372. internal_current_clusteralias(isc_interfaceiter_t *iter) {
  373. struct clua_info ci;
  374. if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
  375. return (ISC_R_IGNORE);
  376. memset(&iter->current, 0, sizeof(iter->current));
  377. iter->current.af = iter->clua_sa.sa_family;
  378. memset(iter->current.name, 0, sizeof(iter->current.name));
  379. sprintf(iter->current.name, "clua%d", ci.aliasid);
  380. iter->current.flags = INTERFACE_F_UP;
  381. get_inaddr(&iter->current.address, &ci.addr);
  382. get_inaddr(&iter->current.netmask, &ci.netmask);
  383. return (ISC_R_SUCCESS);
  384. }
  385. #endif
  386. #ifdef __linux
  387. static isc_result_t
  388. linux_if_inet6_next(isc_interfaceiter_t *iter) {
  389. if (iter->proc != NULL &&
  390. fgets(iter->entry, sizeof(iter->entry), iter->proc) != NULL)
  391. iter->valid = ISC_R_SUCCESS;
  392. else
  393. iter->valid = ISC_R_NOMORE;
  394. return (iter->valid);
  395. }
  396. static void
  397. linux_if_inet6_first(isc_interfaceiter_t *iter) {
  398. if (iter->proc != NULL) {
  399. rewind(iter->proc);
  400. (void)linux_if_inet6_next(iter);
  401. } else
  402. iter->valid = ISC_R_NOMORE;
  403. iter->first = ISC_FALSE;
  404. }
  405. static isc_result_t
  406. linux_if_inet6_current(isc_interfaceiter_t *iter) {
  407. char address[33];
  408. char name[IF_NAMESIZE+1];
  409. char strbuf[ISC_STRERRORSIZE];
  410. struct in6_addr addr6;
  411. struct ifreq ifreq;
  412. int ifindex, prefix, scope, flags;
  413. int res;
  414. unsigned int i;
  415. if (iter->valid != ISC_R_SUCCESS)
  416. return (iter->valid);
  417. if (iter->proc == NULL) {
  418. UNEXPECTED_ERROR(__FILE__, __LINE__,
  419. "/proc/net/if_inet6:iter->proc == NULL");
  420. return (ISC_R_FAILURE);
  421. }
  422. /*
  423. * Format for /proc/net/if_inet6:
  424. * (see iface_proc_info() in net/ipv6/addrconf.c)
  425. * <addr6:32> <ifindex:2> <prefix:2> <scope:2> <flags:2> <name:8>
  426. */
  427. res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n",
  428. address, &ifindex, &prefix, &scope, &flags, name);
  429. if (res != 6) {
  430. UNEXPECTED_ERROR(__FILE__, __LINE__,
  431. "/proc/net/if_inet6:sscanf() -> %d (expected 6)",
  432. res);
  433. return (ISC_R_FAILURE);
  434. }
  435. if (strlen(address) != 32) {
  436. UNEXPECTED_ERROR(__FILE__, __LINE__,
  437. "/proc/net/if_inet6:strlen(%s) != 32", address);
  438. return (ISC_R_FAILURE);
  439. }
  440. for (i = 0; i < 16; i++) {
  441. unsigned char byte;
  442. static const char hex[] = "0123456789abcdef";
  443. byte = ((index(hex, address[i * 2]) - hex) << 4) |
  444. (index(hex, address[i * 2 + 1]) - hex);
  445. addr6.s6_addr[i] = byte;
  446. }
  447. iter->current.af = AF_INET6;
  448. /* iter->current.ifindex = ifindex; */
  449. iter->current.flags = 0;
  450. memset(&ifreq, 0, sizeof(ifreq));
  451. INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
  452. strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name));
  453. if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
  454. isc__strerror(errno, strbuf, sizeof(strbuf));
  455. UNEXPECTED_ERROR(__FILE__, __LINE__,
  456. "%s: getting interface flags: %s",
  457. ifreq.ifr_name, strbuf);
  458. return (ISC_R_IGNORE);
  459. }
  460. if ((ifreq.ifr_flags & IFF_UP) != 0)
  461. iter->current.flags |= INTERFACE_F_UP;
  462. #ifdef IFF_POINTOPOINT
  463. if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
  464. iter->current.flags |= INTERFACE_F_POINTTOPOINT;
  465. #endif
  466. if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
  467. iter->current.flags |= INTERFACE_F_LOOPBACK;
  468. if ((ifreq.ifr_flags & IFF_BROADCAST) != 0)
  469. iter->current.flags |= INTERFACE_F_BROADCAST;
  470. #ifdef IFF_MULTICAST
  471. if ((ifreq.ifr_flags & IFF_MULTICAST) != 0)
  472. iter->current.flags |= INTERFACE_F_MULTICAST;
  473. #endif
  474. /*
  475. * enable_multicast_if() requires scopeid for setsockopt,
  476. * so associate address with their corresponding ifindex.
  477. */
  478. isc_netaddr_fromin6(&iter->current.address, &addr6);
  479. isc_netaddr_setzone(&iter->current.address, (isc_uint32_t)ifindex);
  480. for (i = 0; i < 16; i++) {
  481. if (prefix > 8) {
  482. addr6.s6_addr[i] = 0xff;
  483. prefix -= 8;
  484. } else {
  485. addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff;
  486. prefix = 0;
  487. }
  488. }
  489. isc_netaddr_fromin6(&iter->current.netmask, &addr6);
  490. strncpy(iter->current.name, name, sizeof(iter->current.name));
  491. return (ISC_R_SUCCESS);
  492. }
  493. #endif
  494. /*
  495. * Get information about the current interface to iter->current.
  496. * If successful, return ISC_R_SUCCESS.
  497. * If the interface has an unsupported address family, or if
  498. * some operation on it fails, return ISC_R_IGNORE to make
  499. * the higher-level iterator code ignore it.
  500. */
  501. static isc_result_t
  502. internal_current4(isc_interfaceiter_t *iter) {
  503. struct ifreq *ifrp;
  504. struct ifreq ifreq;
  505. int family;
  506. char strbuf[ISC_STRERRORSIZE];
  507. #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
  508. struct lifreq lifreq;
  509. #else
  510. char sabuf[256];
  511. #endif
  512. int i, bits, prefixlen;
  513. #ifdef __linux
  514. isc_result_t result;
  515. #endif
  516. REQUIRE(VALID_IFITER(iter));
  517. REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
  518. #ifdef __linux
  519. result = linux_if_inet6_current(iter);
  520. if (result != ISC_R_NOMORE)
  521. return (result);
  522. iter->first = ISC_TRUE;
  523. #endif
  524. ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
  525. memset(&ifreq, 0, sizeof(ifreq));
  526. memcpy(&ifreq, ifrp, sizeof(ifreq));
  527. family = ifreq.ifr_addr.sa_family;
  528. #if defined(ISC_PLATFORM_HAVEIPV6)
  529. if (family != AF_INET && family != AF_INET6)
  530. #else
  531. if (family != AF_INET)
  532. #endif
  533. return (ISC_R_IGNORE);
  534. memset(&iter->current, 0, sizeof(iter->current));
  535. iter->current.af = family;
  536. INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
  537. memset(iter->current.name, 0, sizeof(iter->current.name));
  538. memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
  539. get_addr(family, &iter->current.address,
  540. (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
  541. /*
  542. * If the interface does not have a address ignore it.
  543. */
  544. switch (family) {
  545. case AF_INET:
  546. if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
  547. return (ISC_R_IGNORE);
  548. break;
  549. #ifdef ISC_PLATFORM_HAVEIPV6
  550. case AF_INET6:
  551. if (memcmp(&iter->current.address.type.in6, &in6addr_any,
  552. sizeof(in6addr_any)) == 0)
  553. return (ISC_R_IGNORE);
  554. break;
  555. #endif
  556. }
  557. /*
  558. * Get interface flags.
  559. */
  560. iter->current.flags = 0;
  561. /*
  562. * Ignore the HP/UX warning about "integer overflow during
  563. * conversion. It comes from its own macro definition,
  564. * and is really hard to shut up.
  565. */
  566. if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
  567. isc__strerror(errno, strbuf, sizeof(strbuf));
  568. UNEXPECTED_ERROR(__FILE__, __LINE__,
  569. "%s: getting interface flags: %s",
  570. ifreq.ifr_name, strbuf);
  571. return (ISC_R_IGNORE);
  572. }
  573. if ((ifreq.ifr_flags & IFF_UP) != 0)
  574. iter->current.flags |= INTERFACE_F_UP;
  575. #ifdef IFF_POINTOPOINT
  576. if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
  577. iter->current.flags |= INTERFACE_F_POINTTOPOINT;
  578. #endif
  579. if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
  580. iter->current.flags |= INTERFACE_F_LOOPBACK;
  581. if ((ifreq.ifr_flags & IFF_BROADCAST) != 0) {
  582. iter->current.flags |= INTERFACE_F_BROADCAST;
  583. }
  584. #ifdef IFF_MULTICAST
  585. if ((ifreq.ifr_flags & IFF_MULTICAST) != 0) {
  586. iter->current.flags |= INTERFACE_F_MULTICAST;
  587. }
  588. #endif
  589. if (family == AF_INET)
  590. goto inet;
  591. #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
  592. memset(&lifreq, 0, sizeof(lifreq));
  593. memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
  594. memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
  595. sizeof(iter->current.address.type.in6));
  596. if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
  597. isc__strerror(errno, strbuf, sizeof(strbuf));
  598. UNEXPECTED_ERROR(__FILE__, __LINE__,
  599. "%s: getting interface address: %s",
  600. ifreq.ifr_name, strbuf);
  601. return (ISC_R_IGNORE);
  602. }
  603. prefixlen = lifreq.lifr_addrlen;
  604. #else
  605. isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
  606. UNEXPECTED_ERROR(__FILE__, __LINE__,
  607. isc_msgcat_get(isc_msgcat,
  608. ISC_MSGSET_IFITERIOCTL,
  609. ISC_MSG_GETIFCONFIG,
  610. "prefix length for %s is unknown "
  611. "(assume 128)"), sabuf);
  612. prefixlen = 128;
  613. #endif
  614. /*
  615. * Netmask already zeroed.
  616. */
  617. iter->current.netmask.family = family;
  618. for (i = 0; i < 16; i++) {
  619. if (prefixlen > 8) {
  620. bits = 0;
  621. prefixlen -= 8;
  622. } else {
  623. bits = 8 - prefixlen;
  624. prefixlen = 0;
  625. }
  626. iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
  627. }
  628. return (ISC_R_SUCCESS);
  629. inet:
  630. if (family != AF_INET)
  631. return (ISC_R_IGNORE);
  632. #ifdef IFF_POINTOPOINT
  633. /*
  634. * If the interface is point-to-point, get the destination address.
  635. */
  636. if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
  637. /*
  638. * Ignore the HP/UX warning about "integer overflow during
  639. * conversion. It comes from its own macro definition,
  640. * and is really hard to shut up.
  641. */
  642. if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
  643. < 0) {
  644. isc__strerror(errno, strbuf, sizeof(strbuf));
  645. UNEXPECTED_ERROR(__FILE__, __LINE__,
  646. isc_msgcat_get(isc_msgcat,
  647. ISC_MSGSET_IFITERIOCTL,
  648. ISC_MSG_GETDESTADDR,
  649. "%s: getting "
  650. "destination address: %s"),
  651. ifreq.ifr_name, strbuf);
  652. return (ISC_R_IGNORE);
  653. }
  654. get_addr(family, &iter->current.dstaddress,
  655. (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
  656. }
  657. #endif
  658. if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) {
  659. /*
  660. * Ignore the HP/UX warning about "integer overflow during
  661. * conversion. It comes from its own macro definition,
  662. * and is really hard to shut up.
  663. */
  664. if (ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq)
  665. < 0) {
  666. isc__strerror(errno, strbuf, sizeof(strbuf));
  667. UNEXPECTED_ERROR(__FILE__, __LINE__,
  668. isc_msgcat_get(isc_msgcat,
  669. ISC_MSGSET_IFITERIOCTL,
  670. ISC_MSG_GETDESTADDR,
  671. "%s: getting "
  672. "broadcast address: %s"),
  673. ifreq.ifr_name, strbuf);
  674. return (ISC_R_IGNORE);
  675. }
  676. get_addr(family, &iter->current.broadcast,
  677. (struct sockaddr *)&ifreq.ifr_broadaddr, ifreq.ifr_name);
  678. }
  679. /*
  680. * Get the network mask.
  681. */
  682. memset(&ifreq, 0, sizeof(ifreq));
  683. memcpy(&ifreq, ifrp, sizeof(ifreq));
  684. /*
  685. * Ignore the HP/UX warning about "integer overflow during
  686. * conversion. It comes from its own macro definition,
  687. * and is really hard to shut up.
  688. */
  689. if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
  690. isc__strerror(errno, strbuf, sizeof(strbuf));
  691. UNEXPECTED_ERROR(__FILE__, __LINE__,
  692. isc_msgcat_get(isc_msgcat,
  693. ISC_MSGSET_IFITERIOCTL,
  694. ISC_MSG_GETNETMASK,
  695. "%s: getting netmask: %s"),
  696. ifreq.ifr_name, strbuf);
  697. return (ISC_R_IGNORE);
  698. }
  699. get_addr(family, &iter->current.netmask,
  700. (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
  701. return (ISC_R_SUCCESS);
  702. }
  703. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  704. static isc_result_t
  705. internal_current6(isc_interfaceiter_t *iter) {
  706. struct LIFREQ *ifrp;
  707. struct LIFREQ lifreq;
  708. int family;
  709. char strbuf[ISC_STRERRORSIZE];
  710. int fd;
  711. REQUIRE(VALID_IFITER(iter));
  712. if (iter->result6 != ISC_R_SUCCESS)
  713. return (iter->result6);
  714. REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
  715. ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
  716. memset(&lifreq, 0, sizeof(lifreq));
  717. memcpy(&lifreq, ifrp, sizeof(lifreq));
  718. family = lifreq.lifr_addr.ss_family;
  719. #ifdef ISC_PLATFORM_HAVEIPV6
  720. if (family != AF_INET && family != AF_INET6)
  721. #else
  722. if (family != AF_INET)
  723. #endif
  724. return (ISC_R_IGNORE);
  725. memset(&iter->current, 0, sizeof(iter->current));
  726. iter->current.af = family;
  727. INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
  728. memset(iter->current.name, 0, sizeof(iter->current.name));
  729. memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
  730. get_addr(family, &iter->current.address,
  731. (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
  732. /*
  733. * If the interface does not have a address ignore it.
  734. */
  735. switch (family) {
  736. case AF_INET:
  737. if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
  738. return (ISC_R_IGNORE);
  739. break;
  740. #ifdef ISC_PLATFORM_HAVEIPV6
  741. case AF_INET6:
  742. if (memcmp(&iter->current.address.type.in6, &in6addr_any,
  743. sizeof(in6addr_any)) == 0)
  744. return (ISC_R_IGNORE);
  745. break;
  746. #endif
  747. }
  748. /*
  749. * Get interface flags.
  750. */
  751. iter->current.flags = 0;
  752. if (family == AF_INET6)
  753. fd = iter->socket6;
  754. else
  755. fd = iter->socket;
  756. /*
  757. * Ignore the HP/UX warning about "integer overflow during
  758. * conversion. It comes from its own macro definition,
  759. * and is really hard to shut up.
  760. */
  761. if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
  762. isc__strerror(errno, strbuf, sizeof(strbuf));
  763. UNEXPECTED_ERROR(__FILE__, __LINE__,
  764. "%s: getting interface flags: %s",
  765. lifreq.lifr_name, strbuf);
  766. return (ISC_R_IGNORE);
  767. }
  768. if ((lifreq.lifr_flags & IFF_UP) != 0)
  769. iter->current.flags |= INTERFACE_F_UP;
  770. #ifdef IFF_POINTOPOINT
  771. if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
  772. iter->current.flags |= INTERFACE_F_POINTTOPOINT;
  773. #endif
  774. if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
  775. iter->current.flags |= INTERFACE_F_LOOPBACK;
  776. if ((lifreq.lifr_flags & IFF_BROADCAST) != 0) {
  777. iter->current.flags |= INTERFACE_F_BROADCAST;
  778. }
  779. #ifdef IFF_MULTICAST
  780. if ((lifreq.lifr_flags & IFF_MULTICAST) != 0) {
  781. iter->current.flags |= INTERFACE_F_MULTICAST;
  782. }
  783. #endif
  784. #ifdef IFF_POINTOPOINT
  785. /*
  786. * If the interface is point-to-point, get the destination address.
  787. */
  788. if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
  789. /*
  790. * Ignore the HP/UX warning about "interger overflow during
  791. * conversion. It comes from its own macro definition,
  792. * and is really hard to shut up.
  793. */
  794. if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
  795. < 0) {
  796. isc__strerror(errno, strbuf, sizeof(strbuf));
  797. UNEXPECTED_ERROR(__FILE__, __LINE__,
  798. isc_msgcat_get(isc_msgcat,
  799. ISC_MSGSET_IFITERIOCTL,
  800. ISC_MSG_GETDESTADDR,
  801. "%s: getting "
  802. "destination address: %s"),
  803. lifreq.lifr_name, strbuf);
  804. return (ISC_R_IGNORE);
  805. }
  806. get_addr(family, &iter->current.dstaddress,
  807. (struct sockaddr *)&lifreq.lifr_dstaddr,
  808. lifreq.lifr_name);
  809. }
  810. #endif
  811. #ifdef SIOCGLIFBRDADDR
  812. if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) {
  813. /*
  814. * Ignore the HP/UX warning about "integer overflow during
  815. * conversion. It comes from its own macro definition,
  816. * and is really hard to shut up.
  817. */
  818. if (ioctl(iter->socket, SIOCGLIFBRDADDR, (char *)&lifreq)
  819. < 0) {
  820. isc__strerror(errno, strbuf, sizeof(strbuf));
  821. UNEXPECTED_ERROR(__FILE__, __LINE__,
  822. isc_msgcat_get(isc_msgcat,
  823. ISC_MSGSET_IFITERIOCTL,
  824. ISC_MSG_GETDESTADDR,
  825. "%s: getting "
  826. "broadcast address: %s"),
  827. lifreq.lifr_name, strbuf);
  828. return (ISC_R_IGNORE);
  829. }
  830. get_addr(family, &iter->current.broadcast,
  831. (struct sockaddr *)&lifreq.lifr_broadaddr,
  832. lifreq.lifr_name);
  833. }
  834. #endif /* SIOCGLIFBRDADDR */
  835. /*
  836. * Get the network mask. Netmask already zeroed.
  837. */
  838. memset(&lifreq, 0, sizeof(lifreq));
  839. memcpy(&lifreq, ifrp, sizeof(lifreq));
  840. #ifdef lifr_addrlen
  841. /*
  842. * Special case: if the system provides lifr_addrlen member, the
  843. * netmask of an IPv6 address can be derived from the length, since
  844. * an IPv6 address always has a contiguous mask.
  845. */
  846. if (family == AF_INET6) {
  847. int i, bits;
  848. iter->current.netmask.family = family;
  849. for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
  850. bits = lifreq.lifr_addrlen - i;
  851. bits = (bits < 8) ? (8 - bits) : 0;
  852. iter->current.netmask.type.in6.s6_addr[i / 8] =
  853. (~0 << bits) & 0xff;
  854. }
  855. return (ISC_R_SUCCESS);
  856. }
  857. #endif
  858. /*
  859. * Ignore the HP/UX warning about "integer overflow during
  860. * conversion. It comes from its own macro definition,
  861. * and is really hard to shut up.
  862. */
  863. if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
  864. isc__strerror(errno, strbuf, sizeof(strbuf));
  865. UNEXPECTED_ERROR(__FILE__, __LINE__,
  866. isc_msgcat_get(isc_msgcat,
  867. ISC_MSGSET_IFITERIOCTL,
  868. ISC_MSG_GETNETMASK,
  869. "%s: getting netmask: %s"),
  870. lifreq.lifr_name, strbuf);
  871. return (ISC_R_IGNORE);
  872. }
  873. get_addr(family, &iter->current.netmask,
  874. (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
  875. return (ISC_R_SUCCESS);
  876. }
  877. #endif
  878. static isc_result_t
  879. internal_current(isc_interfaceiter_t *iter) {
  880. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  881. if (iter->mode == 6) {
  882. iter->result6 = internal_current6(iter);
  883. if (iter->result6 != ISC_R_NOMORE)
  884. return (iter->result6);
  885. }
  886. #endif
  887. #ifdef HAVE_TRUCLUSTER
  888. if (!iter->clua_done)
  889. return(internal_current_clusteralias(iter));
  890. #endif
  891. return (internal_current4(iter));
  892. }
  893. /*
  894. * Step the iterator to the next interface. Unlike
  895. * isc_interfaceiter_next(), this may leave the iterator
  896. * positioned on an interface that will ultimately
  897. * be ignored. Return ISC_R_NOMORE if there are no more
  898. * interfaces, otherwise ISC_R_SUCCESS.
  899. */
  900. static isc_result_t
  901. internal_next4(isc_interfaceiter_t *iter) {
  902. struct ifreq *ifrp;
  903. REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
  904. #ifdef __linux
  905. if (linux_if_inet6_next(iter) == ISC_R_SUCCESS)
  906. return (ISC_R_SUCCESS);
  907. if (!iter->first)
  908. return (ISC_R_SUCCESS);
  909. #endif
  910. ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
  911. #ifdef ISC_PLATFORM_HAVESALEN
  912. if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
  913. iter->pos += sizeof(ifrp->ifr_name) + ifrp->ifr_addr.sa_len;
  914. else
  915. #endif
  916. iter->pos += sizeof(*ifrp);
  917. if (iter->pos >= (unsigned int) iter->ifc.ifc_len)
  918. return (ISC_R_NOMORE);
  919. return (ISC_R_SUCCESS);
  920. }
  921. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  922. static isc_result_t
  923. internal_next6(isc_interfaceiter_t *iter) {
  924. struct LIFREQ *ifrp;
  925. if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
  926. return (iter->result6);
  927. REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
  928. ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
  929. #ifdef ISC_PLATFORM_HAVESALEN
  930. if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
  931. iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
  932. else
  933. #endif
  934. iter->pos6 += sizeof(*ifrp);
  935. if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
  936. return (ISC_R_NOMORE);
  937. return (ISC_R_SUCCESS);
  938. }
  939. #endif
  940. static isc_result_t
  941. internal_next(isc_interfaceiter_t *iter) {
  942. #ifdef HAVE_TRUCLUSTER
  943. int clua_result;
  944. #endif
  945. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  946. if (iter->mode == 6) {
  947. iter->result6 = internal_next6(iter);
  948. if (iter->result6 != ISC_R_NOMORE)
  949. return (iter->result6);
  950. if (iter->first6) {
  951. iter->first6 = ISC_FALSE;
  952. return (ISC_R_SUCCESS);
  953. }
  954. }
  955. #endif
  956. #ifdef HAVE_TRUCLUSTER
  957. if (!iter->clua_done) {
  958. clua_result = clua_getaliasaddress(&iter->clua_sa,
  959. &iter->clua_context);
  960. if (clua_result != CLUA_SUCCESS)
  961. iter->clua_done = ISC_TRUE;
  962. return (ISC_R_SUCCESS);
  963. }
  964. #endif
  965. return (internal_next4(iter));
  966. }
  967. static void
  968. internal_destroy(isc_interfaceiter_t *iter) {
  969. (void) close(iter->socket);
  970. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  971. if (iter->socket6 != -1)
  972. (void) close(iter->socket6);
  973. if (iter->buf6 != NULL) {
  974. isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
  975. }
  976. #endif
  977. #ifdef __linux
  978. if (iter->proc != NULL)
  979. fclose(iter->proc);
  980. #endif
  981. }
  982. static
  983. void internal_first(isc_interfaceiter_t *iter) {
  984. #ifdef HAVE_TRUCLUSTER
  985. int clua_result;
  986. #endif
  987. iter->pos = 0;
  988. #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  989. iter->pos6 = 0;
  990. if (iter->result6 == ISC_R_NOMORE)
  991. iter->result6 = ISC_R_SUCCESS;
  992. iter->first6 = ISC_TRUE;
  993. #endif
  994. #ifdef HAVE_TRUCLUSTER
  995. iter->clua_context = 0;
  996. clua_result = clua_getaliasaddress(&iter->clua_sa,
  997. &iter->clua_context);
  998. iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
  999. #endif
  1000. #ifdef __linux
  1001. linux_if_inet6_first(iter);
  1002. #endif
  1003. }