/contrib/bind9/lib/isc/unix/ifiter_ioctl.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 931 lines · 678 code · 98 blank · 155 comment · 155 complexity · c633a70f6010fd9d6eea38165ba9171b MD5 · raw file

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