0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 1999-2005, 2007, 2014-2016 Internet Systems Consortium, Inc. ("ISC")
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
70e5a7403f0e0a3bd292b8287c5fed5772c15270Automatic Updater/* $Id: ifiter_sysctl.c,v 1.25 2007/06/19 23:47:18 tbox Exp $ */
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * Obtain the list of network interfaces using sysctl.
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * See TCP/IP Illustrated Volume 2, sections 19.8, 19.14,
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson/* XXX what about Alpha? */
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) : \
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \
431a83fb29482c5170b3e4026e59bb14849a6707Tinderbox User : sizeof(long))
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'S')
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson unsigned int bufsize; /* Bytes allocated. */
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson sysctl data. */
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson isc_interface_t current; /* Current interface data. */
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson isc_result_t result; /* Last result code. */
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson 0, /* Any address family. */
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson 0 /* Flags. */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrenceisc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Determine the amount of memory needed.
79c08618e9f27da052ad6bbc0b232f23ff2e568eAndreas Gustafsson if (sysctl(mib, 6, NULL, &bufsize, NULL, (size_t) 0) < 0) {
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrence "getting interface "
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrence "list size: sysctl: %s"),
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
79c08618e9f27da052ad6bbc0b232f23ff2e568eAndreas Gustafsson if (sysctl(mib, 6, iter->buf, &bufused, NULL, (size_t) 0) < 0) {
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrence "getting interface list: "
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrence "sysctl: %s"),
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * A newly created iterator has an undefined position
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * until isc_interfaceiter_first() is called.
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson isc_mem_put(mctx, iter->buf, iter->bufsize);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * Get information about the current interface to iter->current.
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * If successful, return ISC_R_SUCCESS.
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * If the interface has an unsupported address family,
461a00bbdee50a46ba7fcfb3f9f2847d3bda5ad3Andreas Gustafsson * return ISC_R_IGNORE. In case of other failure,
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * return ISC_R_UNEXPECTED.
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafssoninternal_current(isc_interfaceiter_t *iter) {
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson REQUIRE (iter->pos < (unsigned int) iter->bufused);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson ifam_end = (struct ifa_msghdr *) ((char *) iter->buf + iter->bufused);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson struct if_msghdr *ifm = (struct if_msghdr *) ifam;
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson struct sockaddr_dl *sdl = (struct sockaddr_dl *) (ifm + 1);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson memset(&iter->current, 0, sizeof(iter->current));
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson if (namelen > sizeof(iter->current.name) - 1)
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson namelen = sizeof(iter->current.name) - 1;
2305225a1c70bf80dd544f801f3259d35d4220ceBrian Wellington memset(iter->current.name, 0, sizeof(iter->current.name));
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(iter->current.name, sdl->sdl_data, namelen);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson if ((ifam->ifam_flags & IFF_POINTOPOINT) != 0)
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson iter->current.flags |= INTERFACE_F_POINTTOPOINT;
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson if ((ifam->ifam_flags & IFF_LOOPBACK) != 0)
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson iter->current.flags |= INTERFACE_F_LOOPBACK;
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * This is not an interface address.
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * Force another iteration.
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson } else if (ifam->ifam_type == RTM_NEWADDR) {
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson struct sockaddr *sa = (struct sockaddr *)(ifam + 1);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson for (i = 0; i < RTAX_MAX; i++)
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson INSIST(sa < (struct sockaddr *) ifam_end);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson case RTAX_BRD: /* Broadcast or destination address */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Do as the contributed SGI code does.
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson /* XXX untested. */
846f974d5737710588eb676b64ba138da27c45ddMark Andrews get_addr(family, &iter->current.address, addr_sa,
846f974d5737710588eb676b64ba138da27c45ddMark Andrews get_addr(family, &iter->current.netmask, mask_sa,
5a4854e226ce5eca99bcfb5557b36ea210bb25bcMark Andrews (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
846f974d5737710588eb676b64ba138da27c45ddMark Andrews get_addr(family, &iter->current.dstaddress, dst_sa,
5456bddd393aafd9fa5ac4cc905d3ac1b9854635Mukund Sivaraman isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERSYSCTL,
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrence "warning: unexpected interface list "
9cd6d409b78a6f833b681c13a68fbdc7c024fe66David Lawrence "message type\n"));
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Step the iterator to the next interface. Unlike
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * isc_interfaceiter_next(), this may leave the iterator
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * positioned on an interface that will ultimately
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * be ignored. Return ISC_R_NOMORE if there are no more
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * interfaces, otherwise ISC_R_SUCCESS.
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafssoninternal_next(isc_interfaceiter_t *iter) {
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson REQUIRE (iter->pos < (unsigned int) iter->bufused);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafssoninternal_destroy(isc_interfaceiter_t *iter) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Do nothing.