ifiter_ioctl.c revision 9c3531d72aeaad6c5f01efe6a1c82023e1379e4d
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley/*
f6b909274159da7aaad8463c90f15018136cf6cbTinderbox User * Copyright (C) 1999, 2000 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Permission to use, copy, modify, and distribute this software for any
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * purpose with or without fee is hereby granted, provided that the above
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * copyright notice and this permission notice appear in all copies.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley *
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * SOFTWARE.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley */
142784f574e0b63e8bbcccb762eb8727ac7c76feBrian Wellington
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley/* $Id: ifiter_ioctl.c,v 1.11 2000/06/22 21:58:37 tale Exp $ */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley/*
9297259c7abecc78470fdeca173c101137e4b5bbMark Andrews * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
9297259c7abecc78470fdeca173c101137e4b5bbMark Andrews * See netintro(4).
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson */
3759f10fc543747668b1ca4b4671f35b0dea8445Francis Dupont#ifndef SIOCGLIFCONF
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define SIOCGLIFCONF SIOCGIFCONF
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define lifc_len ifc_len
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define lifc_buf ifc_buf
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define lifc_req ifc_req
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define lifconf ifconf
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#else
558ab0f6a8046499bfe3e39ea4789036313b72b3Michael Graff#define ISC_HAVE_LIFC_FAMILY 1
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define ISC_HAVE_LIFC_FLAGS 1
de4ef688d73a449d4c1218adbb35a4f70a71e672Brian Wellington#endif
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#ifndef SIOCGLIFADDR
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#define SIOCGLIFADDR SIOCGIFADDR
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#define SIOCGLIFFLAGS SIOCGIFFLAGS
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define SIOCGLIFDSTADDR SIOCGIFDSTADDR
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define SIOCGLIFNETMASK SIOCGIFNETMASK
9297259c7abecc78470fdeca173c101137e4b5bbMark Andrews#define lifr_addr ifr_addr
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson#define lifr_name ifr_name
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define lifr_dstaddr ifr_dstaddr
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define lifr_flags ifr_flags
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define ss_family sa_family
c2687b0594673a6e2b8558cc92d9936af069edacMark Andrews#define lifreq ifreq
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#endif
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
6af51ff1a30dd977c4fc6c342a0661bb4f6501a5Bob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define IFITER_MAGIC 0x49464954U /* IFIT. */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define VALID_IFITER(t) ((t) != NULL && (t)->magic == IFITER_MAGIC)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halleystruct isc_interfaceiter {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley unsigned int magic; /* Magic number. */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley isc_mem_t *mctx;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley int socket;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley struct lifconf ifc;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley void *buf; /* Buffer for sysctl data. */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley unsigned int bufsize; /* Bytes allocated. */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley unsigned int pos; /* Current offset in
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley SIOCGLIFCONF data */
6af51ff1a30dd977c4fc6c342a0661bb4f6501a5Bob Halley isc_interface_t current; /* Current interface data. */
c90f5e8d1edbd5c277f2ee320167a12a30ba7c7bMichael Graff isc_result_t result; /* Last result code. */
6af51ff1a30dd977c4fc6c342a0661bb4f6501a5Bob Halley};
c90f5e8d1edbd5c277f2ee320167a12a30ba7c7bMichael Graff
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley/*
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * will have more than a megabyte of interface configuration data.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define IFCONF_BUFSIZE_INITIAL 4096
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define IFCONF_BUFSIZE_MAX 1048576
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halleyisc_result_t
6af51ff1a30dd977c4fc6c342a0661bb4f6501a5Bob Halleyisc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley isc_interfaceiter_t *iter;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley isc_result_t result;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley REQUIRE(mctx != NULL);
6af51ff1a30dd977c4fc6c342a0661bb4f6501a5Bob Halley REQUIRE(iterp != NULL);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley REQUIRE(*iterp == NULL);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter = isc_mem_get(mctx, sizeof(*iter));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (iter == NULL)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley return (ISC_R_NOMEMORY);
c2687b0594673a6e2b8558cc92d9936af069edacMark Andrews
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->mctx = mctx;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->buf = NULL;
c2687b0594673a6e2b8558cc92d9936af069edacMark Andrews
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley /*
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Create an unbound datagram socket to do the SIOCGLIFADDR ioctl on.
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson */
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
315879710704bbcf66df301664cd90df8ad31265David Lawrence UNEXPECTED_ERROR(__FILE__, __LINE__,
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson "making interface scan socket: %s",
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson strerror(errno));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley result = ISC_R_UNEXPECTED;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley goto socket_failure;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley }
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley /*
e605e98f3e4be079f545b26bb53ba02a6d04b0b6Andreas Gustafsson * Get the interface configuration, allocating more memory if
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * necessary.
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson */
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson iter->bufsize = IFCONF_BUFSIZE_INITIAL;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley for (;;) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->buf = isc_mem_get(mctx, iter->bufsize);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (iter->buf == NULL) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley result = ISC_R_NOMEMORY;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley goto alloc_failure;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley }
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley memset(&iter->ifc.lifc_len, 0, sizeof(iter->ifc.lifc_len));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#ifdef ISC_HAVE_LIFC_FAMILY
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->ifc.lifc_family = AF_UNSPEC;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#endif
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#ifdef ISC_HAVE_LIFC_FLAGS
c2687b0594673a6e2b8558cc92d9936af069edacMark Andrews iter->ifc.lifc_flags = 0;
9297259c7abecc78470fdeca173c101137e4b5bbMark Andrews#endif
315879710704bbcf66df301664cd90df8ad31265David Lawrence iter->ifc.lifc_len = iter->bufsize;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->ifc.lifc_buf = iter->buf;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley /*
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Ignore the HP/UX warning about "interger overflow during
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * conversion. It comes from its own macro definition,
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * and is really hard to shut up.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (ioctl(iter->socket, SIOCGLIFCONF, (char *)&iter->ifc)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley == -1) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (errno != EINVAL) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley UNEXPECTED_ERROR(__FILE__, __LINE__,
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley "get interface configuration: %s",
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley strerror(errno));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley result = ISC_R_UNEXPECTED;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley goto ioctl_failure;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley }
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley /*
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * EINVAL. Retry with a bigger buffer.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley } else {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley /*
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * The ioctl succeeded.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Some OS's just return what will fit rather
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * than set EINVAL if the buffer is too small
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * to fit all the interfaces in. If
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * ifc.lifc_len is too near to the end of the
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * buffer we will grow it just in case and
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * retry.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (iter->ifc.lifc_len + 2 * sizeof(struct lifreq)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley < iter->bufsize)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley break;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley }
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley UNEXPECTED_ERROR(__FILE__, __LINE__,
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley "get interface configuration: "
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley "maximum buffer size exceeded");
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley result = ISC_R_UNEXPECTED;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley goto ioctl_failure;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley }
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley isc_mem_put(mctx, iter->buf, iter->bufsize);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->bufsize *= 2;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley }
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley /*
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff * A newly created iterator has an undefined position
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * until isc_interfaceiter_first() is called.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->pos = (unsigned int) -1;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->result = ISC_R_FAILURE;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->magic = IFITER_MAGIC;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley *iterp = iter;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley return (ISC_R_SUCCESS);
808af432356c7592e80bd41416eca61e7bc8791dBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley ioctl_failure:
808af432356c7592e80bd41416eca61e7bc8791dBob Halley isc_mem_put(mctx, iter->buf, iter->bufsize);
808af432356c7592e80bd41416eca61e7bc8791dBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley alloc_failure:
808af432356c7592e80bd41416eca61e7bc8791dBob Halley (void) close(iter->socket);
808af432356c7592e80bd41416eca61e7bc8791dBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley socket_failure:
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley isc_mem_put(mctx, iter, sizeof *iter);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley return (result);
c2687b0594673a6e2b8558cc92d9936af069edacMark Andrews}
c2687b0594673a6e2b8558cc92d9936af069edacMark Andrews
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley/*
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Get information about the current interface to iter->current.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * If successful, return ISC_R_SUCCESS.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * If the interface has an unsupported address family, or if
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * some operation on it fails, return ISC_R_IGNORE to make
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * the higher-level iterator code ignore it.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halleystatic isc_result_t
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halleyinternal_current(isc_interfaceiter_t *iter) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley struct lifreq *ifrp;
558ab0f6a8046499bfe3e39ea4789036313b72b3Michael Graff struct lifreq lifreq;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley int family;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley REQUIRE(VALID_IFITER(iter));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley REQUIRE (iter->pos < (unsigned int) iter->ifc.lifc_len);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley ifrp = (struct lifreq *)((char *) iter->ifc.lifc_req + iter->pos);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley memset(&lifreq, 0, sizeof lifreq);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley memcpy(&lifreq, ifrp, sizeof lifreq);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
9297259c7abecc78470fdeca173c101137e4b5bbMark Andrews family = lifreq.lifr_addr.ss_family;
9297259c7abecc78470fdeca173c101137e4b5bbMark Andrews if (family != AF_INET)
9297259c7abecc78470fdeca173c101137e4b5bbMark Andrews return (ISC_R_IGNORE);
9297259c7abecc78470fdeca173c101137e4b5bbMark Andrews
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley memset(&iter->current, 0, sizeof(iter->current));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->current.af = family;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley get_addr(family, &iter->current.address,
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley (struct sockaddr *)&lifreq.lifr_addr);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley /*
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Get interface flags.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->current.flags = 0;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley /*
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Ignore the HP/UX warning about "interger overflow during
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * conversion. It comes from its own macro definition,
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * and is really hard to shut up.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (ioctl(iter->socket, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley UNEXPECTED_ERROR(__FILE__, __LINE__,
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley "%s: getting interface flags: %s",
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley lifreq.lifr_name,
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley strerror(errno));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley return (ISC_R_IGNORE);
738b9aa3ded1ef724922d6695cb04ec2e721bdd1Bob Halley }
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson if ((lifreq.lifr_flags & IFF_UP) != 0)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->current.flags |= INTERFACE_F_UP;
558ab0f6a8046499bfe3e39ea4789036313b72b3Michael Graff
4e21e54a0394d0f87798620a95c1f675c0b0d09cMichael Graff if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
558ab0f6a8046499bfe3e39ea4789036313b72b3Michael Graff iter->current.flags |= INTERFACE_F_POINTTOPOINT;
558ab0f6a8046499bfe3e39ea4789036313b72b3Michael Graff
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->current.flags |= INTERFACE_F_LOOPBACK;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley /*
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * If the interface is point-to-point, get the destination address.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley /*
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Ignore the HP/UX warning about "interger overflow during
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * conversion. It comes from its own macro definition,
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * and is really hard to shut up.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (ioctl(iter->socket, SIOCGLIFDSTADDR, (char *)&lifreq)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley < 0) {
95b41befcb9e75df2b451ceeb9f8812ccedcc25fAndreas Gustafsson UNEXPECTED_ERROR(__FILE__, __LINE__,
95b41befcb9e75df2b451ceeb9f8812ccedcc25fAndreas Gustafsson "%s: getting destination address: %s",
95b41befcb9e75df2b451ceeb9f8812ccedcc25fAndreas Gustafsson lifreq.lifr_name,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence strerror(errno));
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson return (ISC_R_IGNORE);
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson }
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson get_addr(family, &iter->current.dstaddress,
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson (struct sockaddr *)&lifreq.lifr_dstaddr);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson /*
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson * Get the network mask.
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson */
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson memset(&lifreq, 0, sizeof lifreq);
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson memcpy(&lifreq, ifrp, sizeof lifreq);
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson switch (family) {
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson case AF_INET:
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson /*
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson * Ignore the HP/UX warning about "interger overflow during
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson * conversion. It comes from its own macro definition,
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson * and is really hard to shut up.
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (ioctl(iter->socket, SIOCGLIFNETMASK, (char *)&lifreq)
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson < 0) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence UNEXPECTED_ERROR(__FILE__, __LINE__,
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson "%s: getting netmask: %s",
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson lifreq.lifr_name,
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson strerror(errno));
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson return (ISC_R_IGNORE);
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson }
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson get_addr(family, &iter->current.netmask,
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson (struct sockaddr *)&lifreq.lifr_addr);
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson break;
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson case AF_INET6: {
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson#ifdef lifr_addrlen
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence int i, bits;
4e8fe357a619ae2b789b15df7e3d6abf782b4a71Evan Hunt
95b41befcb9e75df2b451ceeb9f8812ccedcc25fAndreas Gustafsson /*
95b41befcb9e75df2b451ceeb9f8812ccedcc25fAndreas Gustafsson * Netmask already zeroed.
95b41befcb9e75df2b451ceeb9f8812ccedcc25fAndreas Gustafsson */
95b41befcb9e75df2b451ceeb9f8812ccedcc25fAndreas Gustafsson iter->current.netmask.family = family;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff for (i = 0 ; i < lifreq.lifr_addrlen; i += 8) {
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson bits = lifreq.lifr_addrlen - i;
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson bits = (bits < 8 ) ? (8-bits) : 0;
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson iter->current.netmask.type.in6.s6_addr[i/8] =
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence (~0 << bits) &0xff;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
95b41befcb9e75df2b451ceeb9f8812ccedcc25fAndreas Gustafsson#endif
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley break;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley }
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley }
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley return (ISC_R_SUCCESS);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley}
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley/*
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Step the iterator to the next interface. Unlike
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * isc_interfaceiter_next(), this may leave the iterator
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * positioned on an interface that will ultimately
de4ef688d73a449d4c1218adbb35a4f70a71e672Brian Wellington * be ignored. Return ISC_R_NOMORE if there are no more
de4ef688d73a449d4c1218adbb35a4f70a71e672Brian Wellington * interfaces, otherwise ISC_R_SUCCESS.
de4ef688d73a449d4c1218adbb35a4f70a71e672Brian Wellington */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halleystatic isc_result_t
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halleyinternal_next(isc_interfaceiter_t *iter) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley struct lifreq *ifrp;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley REQUIRE (iter->pos < (unsigned int) iter->ifc.lifc_len);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley ifrp = (struct lifreq *)((char *) iter->ifc.lifc_req + iter->pos);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#ifdef ISC_PLATFORM_HAVESALEN
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->pos += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
c2687b0594673a6e2b8558cc92d9936af069edacMark Andrews else
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#endif
c2687b0594673a6e2b8558cc92d9936af069edacMark Andrews iter->pos += sizeof *ifrp;
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (iter->pos >= (unsigned int) iter->ifc.lifc_len)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley return (ISC_R_NOMORE);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley return (ISC_R_SUCCESS);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley}
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halleystatic void
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halleyinternal_destroy(isc_interfaceiter_t *iter) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley (void) close(iter->socket);
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson}
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson