00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00027 #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
00028 #define lifc_len iflc_len
00029 #define lifc_buf iflc_buf
00030 #define lifc_req iflc_req
00031 #define LIFCONF if_laddrconf
00032 #else
00033 #define ISC_HAVE_LIFC_FAMILY 1
00034 #define ISC_HAVE_LIFC_FLAGS 1
00035 #define LIFCONF lifconf
00036 #endif
00037
00038 #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
00039 #define lifr_addr iflr_addr
00040 #define lifr_name iflr_name
00041 #define lifr_dstaddr iflr_dstaddr
00042 #define lifr_flags iflr_flags
00043 #define ss_family sa_family
00044 #define LIFREQ if_laddrreq
00045 #else
00046 #define LIFREQ lifreq
00047 #endif
00048 #endif
00049
00050 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
00051 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
00052
00053 struct isc_interfaceiter {
00054 unsigned int magic;
00055 isc_mem_t *mctx;
00056 int mode;
00057 int socket;
00058 struct ifconf ifc;
00059 void *buf;
00060 unsigned int bufsize;
00061 unsigned int pos;
00062
00063 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00064 int socket6;
00065 struct LIFCONF lifc;
00066 void *buf6;
00067 unsigned int bufsize6;
00068 unsigned int pos6;
00069
00070 isc_result_t result6;
00071 isc_boolean_t first6;
00072 #endif
00073 #ifdef HAVE_TRUCLUSTER
00074 int clua_context;
00075 isc_boolean_t clua_done;
00076 struct sockaddr clua_sa;
00077 #endif
00078 #ifdef __linux
00079 FILE * proc;
00080 char entry[ISC_IF_INET6_SZ];
00081 isc_result_t valid;
00082 #endif
00083 isc_interface_t current;
00084 isc_result_t result;
00085 };
00086
00087 #ifdef HAVE_TRUCLUSTER
00088 #include <clua/clua.h>
00089 #include <sys/socket.h>
00090 #endif
00091
00092
00093
00094
00095
00096
00097 #define IFCONF_BUFSIZE_INITIAL 4096
00098 #define IFCONF_BUFSIZE_MAX 1048576
00099
00100 #ifdef __linux
00101 #ifndef IF_NAMESIZE
00102 # ifdef IFNAMSIZ
00103 # define IF_NAMESIZE IFNAMSIZ
00104 # else
00105 # define IF_NAMESIZE 16
00106 # endif
00107 #endif
00108 #endif
00109
00110 static isc_result_t
00111 getbuf4(isc_interfaceiter_t *iter) {
00112 char strbuf[ISC_STRERRORSIZE];
00113
00114 iter->bufsize = IFCONF_BUFSIZE_INITIAL;
00115
00116 for (;;) {
00117 iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
00118 if (iter->buf == NULL)
00119 return (ISC_R_NOMEMORY);
00120
00121 memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
00122 iter->ifc.ifc_len = iter->bufsize;
00123 iter->ifc.ifc_buf = iter->buf;
00124
00125
00126
00127
00128
00129 if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
00130 == -1) {
00131 if (errno != EINVAL) {
00132 isc__strerror(errno, strbuf, sizeof(strbuf));
00133 UNEXPECTED_ERROR(__FILE__, __LINE__,
00134 isc_msgcat_get(isc_msgcat,
00135 ISC_MSGSET_IFITERIOCTL,
00136 ISC_MSG_GETIFCONFIG,
00137 "get interface "
00138 "configuration: %s"),
00139 strbuf);
00140 goto unexpected;
00141 }
00142
00143
00144
00145 } else {
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
00156 < iter->bufsize)
00157 break;
00158 }
00159 if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
00160 UNEXPECTED_ERROR(__FILE__, __LINE__,
00161 isc_msgcat_get(isc_msgcat,
00162 ISC_MSGSET_IFITERIOCTL,
00163 ISC_MSG_BUFFERMAX,
00164 "get interface "
00165 "configuration: "
00166 "maximum buffer "
00167 "size exceeded"));
00168 goto unexpected;
00169 }
00170 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
00171
00172 iter->bufsize *= 2;
00173 }
00174 return (ISC_R_SUCCESS);
00175
00176 unexpected:
00177 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
00178 iter->buf = NULL;
00179 return (ISC_R_UNEXPECTED);
00180 }
00181
00182 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00183 static isc_result_t
00184 getbuf6(isc_interfaceiter_t *iter) {
00185 char strbuf[ISC_STRERRORSIZE];
00186 isc_result_t result;
00187
00188 iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
00189
00190 for (;;) {
00191 iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
00192 if (iter->buf6 == NULL)
00193 return (ISC_R_NOMEMORY);
00194
00195 memset(&iter->lifc, 0, sizeof(iter->lifc));
00196 #ifdef ISC_HAVE_LIFC_FAMILY
00197 iter->lifc.lifc_family = AF_INET6;
00198 #endif
00199 #ifdef ISC_HAVE_LIFC_FLAGS
00200 iter->lifc.lifc_flags = 0;
00201 #endif
00202 iter->lifc.lifc_len = iter->bufsize6;
00203 iter->lifc.lifc_buf = iter->buf6;
00204
00205
00206
00207
00208
00209 if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
00210 == -1) {
00211 #ifdef __hpux
00212
00213
00214
00215
00216 if (errno == ENOENT) {
00217 isc__strerror(errno, strbuf, sizeof(strbuf));
00218 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
00219 ISC_LOGMODULE_INTERFACE,
00220 ISC_LOG_DEBUG(1),
00221 isc_msgcat_get(isc_msgcat,
00222 ISC_MSGSET_IFITERIOCTL,
00223 ISC_MSG_GETIFCONFIG,
00224 "get interface "
00225 "configuration: %s"),
00226 strbuf);
00227 result = ISC_R_FAILURE;
00228 goto cleanup;
00229 }
00230 #endif
00231 if (errno != EINVAL) {
00232 isc__strerror(errno, strbuf, sizeof(strbuf));
00233 UNEXPECTED_ERROR(__FILE__, __LINE__,
00234 isc_msgcat_get(isc_msgcat,
00235 ISC_MSGSET_IFITERIOCTL,
00236 ISC_MSG_GETIFCONFIG,
00237 "get interface "
00238 "configuration: %s"),
00239 strbuf);
00240 result = ISC_R_UNEXPECTED;
00241 goto cleanup;
00242 }
00243
00244
00245
00246 } else {
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
00257 < iter->bufsize6)
00258 break;
00259 }
00260 if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
00261 UNEXPECTED_ERROR(__FILE__, __LINE__,
00262 isc_msgcat_get(isc_msgcat,
00263 ISC_MSGSET_IFITERIOCTL,
00264 ISC_MSG_BUFFERMAX,
00265 "get interface "
00266 "configuration: "
00267 "maximum buffer "
00268 "size exceeded"));
00269 result = ISC_R_UNEXPECTED;
00270 goto cleanup;
00271 }
00272 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
00273
00274 iter->bufsize6 *= 2;
00275 }
00276
00277 if (iter->lifc.lifc_len != 0)
00278 iter->mode = 6;
00279 return (ISC_R_SUCCESS);
00280
00281 cleanup:
00282 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
00283 iter->buf6 = NULL;
00284 return (result);
00285 }
00286 #endif
00287
00288 isc_result_t
00289 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
00290 isc_interfaceiter_t *iter;
00291 isc_result_t result;
00292 char strbuf[ISC_STRERRORSIZE];
00293
00294 REQUIRE(mctx != NULL);
00295 REQUIRE(iterp != NULL);
00296 REQUIRE(*iterp == NULL);
00297
00298 iter = isc_mem_get(mctx, sizeof(*iter));
00299 if (iter == NULL)
00300 return (ISC_R_NOMEMORY);
00301
00302 iter->mctx = mctx;
00303 iter->mode = 4;
00304 iter->buf = NULL;
00305 iter->pos = (unsigned int) -1;
00306 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00307 iter->buf6 = NULL;
00308 iter->pos6 = (unsigned int) -1;
00309 iter->result6 = ISC_R_NOMORE;
00310 iter->socket6 = -1;
00311 iter->first6 = ISC_FALSE;
00312 #endif
00313
00314
00315
00316
00317
00318
00319 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00320 result = isc_net_probeipv6();
00321 if (result == ISC_R_SUCCESS) {
00322
00323
00324
00325
00326
00327 if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
00328 isc__strerror(errno, strbuf, sizeof(strbuf));
00329 UNEXPECTED_ERROR(__FILE__, __LINE__,
00330 isc_msgcat_get(isc_msgcat,
00331 ISC_MSGSET_IFITERIOCTL,
00332 ISC_MSG_MAKESCANSOCKET,
00333 "making interface "
00334 "scan socket: %s"),
00335 strbuf);
00336 result = ISC_R_UNEXPECTED;
00337 goto socket6_failure;
00338 }
00339 result = iter->result6 = getbuf6(iter);
00340 if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
00341 goto ioctl6_failure;
00342 }
00343 #endif
00344 if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
00345 isc__strerror(errno, strbuf, sizeof(strbuf));
00346 UNEXPECTED_ERROR(__FILE__, __LINE__,
00347 isc_msgcat_get(isc_msgcat,
00348 ISC_MSGSET_IFITERIOCTL,
00349 ISC_MSG_MAKESCANSOCKET,
00350 "making interface "
00351 "scan socket: %s"),
00352 strbuf);
00353 result = ISC_R_UNEXPECTED;
00354 goto socket_failure;
00355 }
00356 result = getbuf4(iter);
00357 if (result != ISC_R_SUCCESS)
00358 goto ioctl_failure;
00359
00360
00361
00362
00363
00364 #ifdef HAVE_TRUCLUSTER
00365 iter->clua_context = -1;
00366 iter->clua_done = ISC_TRUE;
00367 #endif
00368 #ifdef __linux
00369 iter->proc = fopen("/proc/net/if_inet6", "r");
00370 iter->valid = ISC_R_FAILURE;
00371 #endif
00372 iter->result = ISC_R_FAILURE;
00373
00374 iter->magic = IFITER_MAGIC;
00375 *iterp = iter;
00376 return (ISC_R_SUCCESS);
00377
00378 ioctl_failure:
00379 if (iter->buf != NULL)
00380 isc_mem_put(mctx, iter->buf, iter->bufsize);
00381 (void) close(iter->socket);
00382
00383 socket_failure:
00384 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00385 if (iter->buf6 != NULL)
00386 isc_mem_put(mctx, iter->buf6, iter->bufsize6);
00387 ioctl6_failure:
00388 if (iter->socket6 != -1)
00389 (void) close(iter->socket6);
00390 socket6_failure:
00391 #endif
00392
00393 isc_mem_put(mctx, iter, sizeof(*iter));
00394 return (result);
00395 }
00396
00397 #ifdef HAVE_TRUCLUSTER
00398 static void
00399 get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
00400 dst->family = AF_INET;
00401 memmove(&dst->type.in, src, sizeof(struct in_addr));
00402 }
00403
00404 static isc_result_t
00405 internal_current_clusteralias(isc_interfaceiter_t *iter) {
00406 struct clua_info ci;
00407 if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
00408 return (ISC_R_IGNORE);
00409 memset(&iter->current, 0, sizeof(iter->current));
00410 iter->current.af = iter->clua_sa.sa_family;
00411 memset(iter->current.name, 0, sizeof(iter->current.name));
00412 sprintf(iter->current.name, "clua%d", ci.aliasid);
00413 iter->current.flags = INTERFACE_F_UP;
00414 get_inaddr(&iter->current.address, &ci.addr);
00415 get_inaddr(&iter->current.netmask, &ci.netmask);
00416 return (ISC_R_SUCCESS);
00417 }
00418 #endif
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 static isc_result_t
00429 internal_current4(isc_interfaceiter_t *iter) {
00430 struct ifreq *ifrp;
00431 struct ifreq ifreq;
00432 int family;
00433 char strbuf[ISC_STRERRORSIZE];
00434 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
00435 struct lifreq lifreq;
00436 #else
00437 char sabuf[256];
00438 #endif
00439 int i, bits, prefixlen;
00440
00441 REQUIRE(VALID_IFITER(iter));
00442
00443 if (iter->ifc.ifc_len == 0 ||
00444 iter->pos == (unsigned int)iter->ifc.ifc_len) {
00445 #ifdef __linux
00446 return (linux_if_inet6_current(iter));
00447 #else
00448 return (ISC_R_NOMORE);
00449 #endif
00450 }
00451
00452 INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len);
00453
00454 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
00455
00456 memset(&ifreq, 0, sizeof(ifreq));
00457 memmove(&ifreq, ifrp, sizeof(ifreq));
00458
00459 family = ifreq.ifr_addr.sa_family;
00460 #if defined(ISC_PLATFORM_HAVEIPV6)
00461 if (family != AF_INET && family != AF_INET6)
00462 #else
00463 if (family != AF_INET)
00464 #endif
00465 return (ISC_R_IGNORE);
00466
00467 memset(&iter->current, 0, sizeof(iter->current));
00468 iter->current.af = family;
00469
00470 INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
00471 memset(iter->current.name, 0, sizeof(iter->current.name));
00472 memmove(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
00473
00474 get_addr(family, &iter->current.address,
00475 (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
00476
00477
00478
00479
00480 switch (family) {
00481 case AF_INET:
00482 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
00483 return (ISC_R_IGNORE);
00484 break;
00485 case AF_INET6:
00486 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
00487 sizeof(in6addr_any)) == 0)
00488 return (ISC_R_IGNORE);
00489 break;
00490 }
00491
00492
00493
00494
00495
00496 iter->current.flags = 0;
00497
00498
00499
00500
00501
00502
00503 if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
00504 isc__strerror(errno, strbuf, sizeof(strbuf));
00505 UNEXPECTED_ERROR(__FILE__, __LINE__,
00506 "%s: getting interface flags: %s",
00507 ifreq.ifr_name, strbuf);
00508 return (ISC_R_IGNORE);
00509 }
00510
00511 if ((ifreq.ifr_flags & IFF_UP) != 0)
00512 iter->current.flags |= INTERFACE_F_UP;
00513
00514 #ifdef IFF_POINTOPOINT
00515 if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
00516 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
00517 #endif
00518
00519 if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
00520 iter->current.flags |= INTERFACE_F_LOOPBACK;
00521
00522 if (family == AF_INET)
00523 goto inet;
00524
00525 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
00526 memset(&lifreq, 0, sizeof(lifreq));
00527 memmove(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
00528 memmove(&lifreq.lifr_addr, &iter->current.address.type.in6,
00529 sizeof(iter->current.address.type.in6));
00530
00531 if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
00532 isc__strerror(errno, strbuf, sizeof(strbuf));
00533 UNEXPECTED_ERROR(__FILE__, __LINE__,
00534 "%s: getting interface address: %s",
00535 ifreq.ifr_name, strbuf);
00536 return (ISC_R_IGNORE);
00537 }
00538 prefixlen = lifreq.lifr_addrlen;
00539 #else
00540 isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
00541 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
00542 ISC_LOGMODULE_INTERFACE,
00543 ISC_LOG_INFO,
00544 isc_msgcat_get(isc_msgcat,
00545 ISC_MSGSET_IFITERIOCTL,
00546 ISC_MSG_GETIFCONFIG,
00547 "prefix length for %s is unknown "
00548 "(assume 128)"), sabuf);
00549 prefixlen = 128;
00550 #endif
00551
00552
00553
00554
00555 iter->current.netmask.family = family;
00556 for (i = 0; i < 16; i++) {
00557 if (prefixlen > 8) {
00558 bits = 0;
00559 prefixlen -= 8;
00560 } else {
00561 bits = 8 - prefixlen;
00562 prefixlen = 0;
00563 }
00564 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
00565 }
00566 return (ISC_R_SUCCESS);
00567
00568 inet:
00569 if (family != AF_INET)
00570 return (ISC_R_IGNORE);
00571 #ifdef IFF_POINTOPOINT
00572
00573
00574
00575 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
00576
00577
00578
00579
00580
00581 if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
00582 < 0) {
00583 isc__strerror(errno, strbuf, sizeof(strbuf));
00584 UNEXPECTED_ERROR(__FILE__, __LINE__,
00585 isc_msgcat_get(isc_msgcat,
00586 ISC_MSGSET_IFITERIOCTL,
00587 ISC_MSG_GETDESTADDR,
00588 "%s: getting "
00589 "destination address: %s"),
00590 ifreq.ifr_name, strbuf);
00591 return (ISC_R_IGNORE);
00592 }
00593 get_addr(family, &iter->current.dstaddress,
00594 (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
00595 }
00596 #endif
00597
00598
00599
00600
00601 memset(&ifreq, 0, sizeof(ifreq));
00602 memmove(&ifreq, ifrp, sizeof(ifreq));
00603
00604
00605
00606
00607
00608 if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
00609 isc__strerror(errno, strbuf, sizeof(strbuf));
00610 UNEXPECTED_ERROR(__FILE__, __LINE__,
00611 isc_msgcat_get(isc_msgcat,
00612 ISC_MSGSET_IFITERIOCTL,
00613 ISC_MSG_GETNETMASK,
00614 "%s: getting netmask: %s"),
00615 ifreq.ifr_name, strbuf);
00616 return (ISC_R_IGNORE);
00617 }
00618 get_addr(family, &iter->current.netmask,
00619 (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
00620 return (ISC_R_SUCCESS);
00621 }
00622
00623 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00624 static isc_result_t
00625 internal_current6(isc_interfaceiter_t *iter) {
00626 struct LIFREQ *ifrp;
00627 struct LIFREQ lifreq;
00628 int family;
00629 char strbuf[ISC_STRERRORSIZE];
00630 int fd;
00631
00632 REQUIRE(VALID_IFITER(iter));
00633 if (iter->result6 != ISC_R_SUCCESS)
00634 return (iter->result6);
00635 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
00636
00637 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
00638
00639 memset(&lifreq, 0, sizeof(lifreq));
00640 memmove(&lifreq, ifrp, sizeof(lifreq));
00641
00642 family = lifreq.lifr_addr.ss_family;
00643 #ifdef ISC_PLATFORM_HAVEIPV6
00644 if (family != AF_INET && family != AF_INET6)
00645 #else
00646 if (family != AF_INET)
00647 #endif
00648 return (ISC_R_IGNORE);
00649
00650 memset(&iter->current, 0, sizeof(iter->current));
00651 iter->current.af = family;
00652
00653 INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
00654 memset(iter->current.name, 0, sizeof(iter->current.name));
00655 memmove(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
00656
00657 get_addr(family, &iter->current.address,
00658 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
00659
00660
00661
00662
00663 switch (family) {
00664 case AF_INET:
00665 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
00666 return (ISC_R_IGNORE);
00667 break;
00668 case AF_INET6:
00669 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
00670 sizeof(in6addr_any)) == 0)
00671 return (ISC_R_IGNORE);
00672 break;
00673 }
00674
00675
00676
00677
00678
00679 iter->current.flags = 0;
00680
00681 if (family == AF_INET6)
00682 fd = iter->socket6;
00683 else
00684 fd = iter->socket;
00685
00686
00687
00688
00689
00690
00691 if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
00692 isc__strerror(errno, strbuf, sizeof(strbuf));
00693 UNEXPECTED_ERROR(__FILE__, __LINE__,
00694 "%s: getting interface flags: %s",
00695 lifreq.lifr_name, strbuf);
00696 return (ISC_R_IGNORE);
00697 }
00698
00699 if ((lifreq.lifr_flags & IFF_UP) != 0)
00700 iter->current.flags |= INTERFACE_F_UP;
00701
00702 #ifdef IFF_POINTOPOINT
00703 if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
00704 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
00705 #endif
00706
00707 if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
00708 iter->current.flags |= INTERFACE_F_LOOPBACK;
00709
00710 #ifdef IFF_POINTOPOINT
00711
00712
00713
00714 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
00715
00716
00717
00718
00719
00720 if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
00721 < 0) {
00722 isc__strerror(errno, strbuf, sizeof(strbuf));
00723 UNEXPECTED_ERROR(__FILE__, __LINE__,
00724 isc_msgcat_get(isc_msgcat,
00725 ISC_MSGSET_IFITERIOCTL,
00726 ISC_MSG_GETDESTADDR,
00727 "%s: getting "
00728 "destination address: %s"),
00729 lifreq.lifr_name, strbuf);
00730 return (ISC_R_IGNORE);
00731 }
00732 get_addr(family, &iter->current.dstaddress,
00733 (struct sockaddr *)&lifreq.lifr_dstaddr,
00734 lifreq.lifr_name);
00735 }
00736 #endif
00737
00738
00739
00740
00741 memset(&lifreq, 0, sizeof(lifreq));
00742 memmove(&lifreq, ifrp, sizeof(lifreq));
00743
00744 #ifdef lifr_addrlen
00745
00746
00747
00748
00749
00750 if (family == AF_INET6) {
00751 int i, bits;
00752
00753 iter->current.netmask.family = family;
00754 for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
00755 bits = lifreq.lifr_addrlen - i;
00756 bits = (bits < 8) ? (8 - bits) : 0;
00757 iter->current.netmask.type.in6.s6_addr[i / 8] =
00758 (~0 << bits) & 0xff;
00759 }
00760
00761 return (ISC_R_SUCCESS);
00762 }
00763 #endif
00764
00765
00766
00767
00768
00769
00770 if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
00771 isc__strerror(errno, strbuf, sizeof(strbuf));
00772 UNEXPECTED_ERROR(__FILE__, __LINE__,
00773 isc_msgcat_get(isc_msgcat,
00774 ISC_MSGSET_IFITERIOCTL,
00775 ISC_MSG_GETNETMASK,
00776 "%s: getting netmask: %s"),
00777 lifreq.lifr_name, strbuf);
00778 return (ISC_R_IGNORE);
00779 }
00780 get_addr(family, &iter->current.netmask,
00781 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
00782
00783 return (ISC_R_SUCCESS);
00784 }
00785 #endif
00786
00787 static isc_result_t
00788 internal_current(isc_interfaceiter_t *iter) {
00789 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00790 if (iter->mode == 6) {
00791 iter->result6 = internal_current6(iter);
00792 if (iter->result6 != ISC_R_NOMORE)
00793 return (iter->result6);
00794 }
00795 #endif
00796 #ifdef HAVE_TRUCLUSTER
00797 if (!iter->clua_done)
00798 return(internal_current_clusteralias(iter));
00799 #endif
00800 return (internal_current4(iter));
00801 }
00802
00803
00804
00805
00806
00807
00808
00809
00810 static isc_result_t
00811 internal_next4(isc_interfaceiter_t *iter) {
00812 #ifdef ISC_PLATFORM_HAVESALEN
00813 struct ifreq *ifrp;
00814 #endif
00815
00816 if (iter->pos < (unsigned int) iter->ifc.ifc_len) {
00817 #ifdef ISC_PLATFORM_HAVESALEN
00818 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
00819
00820 if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
00821 iter->pos += sizeof(ifrp->ifr_name) +
00822 ifrp->ifr_addr.sa_len;
00823 else
00824 #endif
00825 iter->pos += sizeof(struct ifreq);
00826
00827 } else {
00828 INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len);
00829 #ifdef __linux
00830 return (linux_if_inet6_next(iter));
00831 #else
00832 return (ISC_R_NOMORE);
00833 #endif
00834 }
00835 return (ISC_R_SUCCESS);
00836 }
00837
00838 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00839 static isc_result_t
00840 internal_next6(isc_interfaceiter_t *iter) {
00841 #ifdef ISC_PLATFORM_HAVESALEN
00842 struct LIFREQ *ifrp;
00843 #endif
00844
00845 if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
00846 return (iter->result6);
00847
00848 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
00849
00850 #ifdef ISC_PLATFORM_HAVESALEN
00851 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
00852
00853 if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
00854 iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
00855 else
00856 #endif
00857 iter->pos6 += sizeof(struct LIFREQ);
00858
00859 if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
00860 return (ISC_R_NOMORE);
00861
00862 return (ISC_R_SUCCESS);
00863 }
00864 #endif
00865
00866 static isc_result_t
00867 internal_next(isc_interfaceiter_t *iter) {
00868 #ifdef HAVE_TRUCLUSTER
00869 int clua_result;
00870 #endif
00871 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00872 if (iter->mode == 6) {
00873 iter->result6 = internal_next6(iter);
00874 if (iter->result6 != ISC_R_NOMORE)
00875 return (iter->result6);
00876 if (iter->first6) {
00877 iter->first6 = ISC_FALSE;
00878 return (ISC_R_SUCCESS);
00879 }
00880 }
00881 #endif
00882 #ifdef HAVE_TRUCLUSTER
00883 if (!iter->clua_done) {
00884 clua_result = clua_getaliasaddress(&iter->clua_sa,
00885 &iter->clua_context);
00886 if (clua_result != CLUA_SUCCESS)
00887 iter->clua_done = ISC_TRUE;
00888 return (ISC_R_SUCCESS);
00889 }
00890 #endif
00891 return (internal_next4(iter));
00892 }
00893
00894 static void
00895 internal_destroy(isc_interfaceiter_t *iter) {
00896 (void) close(iter->socket);
00897 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00898 if (iter->socket6 != -1)
00899 (void) close(iter->socket6);
00900 if (iter->buf6 != NULL) {
00901 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
00902 }
00903 #endif
00904 #ifdef __linux
00905 if (iter->proc != NULL)
00906 fclose(iter->proc);
00907 #endif
00908 }
00909
00910 static
00911 void internal_first(isc_interfaceiter_t *iter) {
00912 #ifdef HAVE_TRUCLUSTER
00913 int clua_result;
00914 #endif
00915 iter->pos = 0;
00916 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
00917 iter->pos6 = 0;
00918 if (iter->result6 == ISC_R_NOMORE)
00919 iter->result6 = ISC_R_SUCCESS;
00920 iter->first6 = ISC_TRUE;
00921 #endif
00922 #ifdef HAVE_TRUCLUSTER
00923 iter->clua_context = 0;
00924 clua_result = clua_getaliasaddress(&iter->clua_sa,
00925 &iter->clua_context);
00926 iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
00927 #endif
00928 #ifdef __linux
00929 linux_if_inet6_first(iter);
00930 #endif
00931 }