1/* 2 * Copyright (C) 2004, 2005, 2007, 2008, 2014 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 18/* $Id: interfaceiter.c,v 1.45 2008/12/01 03:51:47 marka Exp $ */ 19 20/*! \file */ 21 22#include <config.h> 23 24#include <sys/types.h> 25#include <sys/ioctl.h> 26#ifdef HAVE_SYS_SOCKIO_H 27#include <sys/sockio.h> /* Required for ifiter_ioctl.c. */ 28#endif 29 30#include <stdio.h> 31#include <stdlib.h> 32#include <unistd.h> 33#include <errno.h> 34 35#include <isc/interfaceiter.h> 36#include <isc/log.h> 37#include <isc/magic.h> 38#include <isc/mem.h> 39#include <isc/msgs.h> 40#include <isc/net.h> 41#include <isc/print.h> 42#include <isc/result.h> 43#include <isc/strerror.h> 44#include <isc/string.h> 45#include <isc/types.h> 46#include <isc/util.h> 47 48/* Must follow <isc/net.h>. */ 49#ifdef HAVE_NET_IF6_H 50#include <net/if6.h> 51#endif 52#include <net/if.h> 53 54/* Common utility functions */ 55 56/*% 57 * Extract the network address part from a "struct sockaddr". 58 * \brief 59 * The address family is given explicitly 60 * instead of using src->sa_family, because the latter does not work 61 * for copying a network mask obtained by SIOCGIFNETMASK (it does 62 * not have a valid address family). 63 */ 64 65static void 66get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src, 67 char *ifname) 68{ 69 struct sockaddr_in6 *sa6; 70 71#if !defined(ISC_PLATFORM_HAVEIFNAMETOINDEX) || \ 72 !defined(ISC_PLATFORM_HAVESCOPEID) 73 UNUSED(ifname); 74#endif 75 76 /* clear any remaining value for safety */ 77 memset(dst, 0, sizeof(*dst)); 78 79 dst->family = family; 80 switch (family) { 81 case AF_INET: 82 memmove(&dst->type.in, 83 &((struct sockaddr_in *) src)->sin_addr, 84 sizeof(struct in_addr)); 85 break; 86 case AF_INET6: 87 sa6 = (struct sockaddr_in6 *)src; 88 memmove(&dst->type.in6, &sa6->sin6_addr, 89 sizeof(struct in6_addr)); 90#ifdef ISC_PLATFORM_HAVESCOPEID 91 if (sa6->sin6_scope_id != 0) 92 isc_netaddr_setzone(dst, sa6->sin6_scope_id); 93 else { 94 /* 95 * BSD variants embed scope zone IDs in the 128bit 96 * address as a kernel internal form. Unfortunately, 97 * the embedded IDs are not hidden from applications 98 * when getting access to them by sysctl or ioctl. 99 * We convert the internal format to the pure address 100 * part and the zone ID part. 101 * Since multicast addresses should not appear here 102 * and they cannot be distinguished from netmasks, 103 * we only consider unicast link-local addresses. 104 */ 105 if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) { 106 isc_uint16_t zone16; 107 108 memmove(&zone16, &sa6->sin6_addr.s6_addr[2], 109 sizeof(zone16)); 110 zone16 = ntohs(zone16); 111 if (zone16 != 0) { 112 /* the zone ID is embedded */ 113 isc_netaddr_setzone(dst, 114 (isc_uint32_t)zone16); 115 dst->type.in6.s6_addr[2] = 0; 116 dst->type.in6.s6_addr[3] = 0; 117#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 118 } else if (ifname != NULL) { 119 unsigned int zone; 120 121 /* 122 * sin6_scope_id is still not provided, 123 * but the corresponding interface name 124 * is know. Use the interface ID as 125 * the link ID. 126 */ 127 zone = if_nametoindex(ifname); 128 if (zone != 0) { 129 isc_netaddr_setzone(dst, 130 (isc_uint32_t)zone); 131 } 132#endif 133 } 134 } 135 } 136#endif 137 break; 138 default: 139 INSIST(0); 140 break; 141 } 142} 143 144/* 145 * Include system-dependent code. 146 */ 147 148#ifdef __linux 149#define ISC_IF_INET6_SZ \ 150 sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n") 151static isc_result_t linux_if_inet6_next(isc_interfaceiter_t *); 152static isc_result_t linux_if_inet6_current(isc_interfaceiter_t *); 153static void linux_if_inet6_first(isc_interfaceiter_t *iter); 154#endif 155 156#if HAVE_GETIFADDRS 157#include "ifiter_getifaddrs.c" 158#elif HAVE_IFLIST_SYSCTL 159#include "ifiter_sysctl.c" 160#else 161#include "ifiter_ioctl.c" 162#endif 163 164#ifdef __linux 165static void 166linux_if_inet6_first(isc_interfaceiter_t *iter) { 167 if (iter->proc != NULL) { 168 rewind(iter->proc); 169 (void)linux_if_inet6_next(iter); 170 } else 171 iter->valid = ISC_R_NOMORE; 172} 173 174static isc_result_t 175linux_if_inet6_next(isc_interfaceiter_t *iter) { 176 if (iter->proc != NULL && 177 fgets(iter->entry, sizeof(iter->entry), iter->proc) != NULL) 178 iter->valid = ISC_R_SUCCESS; 179 else 180 iter->valid = ISC_R_NOMORE; 181 return (iter->valid); 182} 183 184static isc_result_t 185linux_if_inet6_current(isc_interfaceiter_t *iter) { 186 char address[33]; 187 char name[IF_NAMESIZE+1]; 188 struct in6_addr addr6; 189 int ifindex, prefix, flag3, flag4; 190 int res; 191 unsigned int i; 192 193 if (iter->valid != ISC_R_SUCCESS) 194 return (iter->valid); 195 if (iter->proc == NULL) { 196 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 197 ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, 198 "/proc/net/if_inet6:iter->proc == NULL"); 199 return (ISC_R_FAILURE); 200 } 201 202 res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n", 203 address, &ifindex, &prefix, &flag3, &flag4, name); 204 if (res != 6) { 205 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 206 ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, 207 "/proc/net/if_inet6:sscanf() -> %d (expected 6)", 208 res); 209 return (ISC_R_FAILURE); 210 } 211 if (strlen(address) != 32) { 212 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 213 ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, 214 "/proc/net/if_inet6:strlen(%s) != 32", address); 215 return (ISC_R_FAILURE); 216 } 217 for (i = 0; i < 16; i++) { 218 unsigned char byte; 219 static const char hex[] = "0123456789abcdef"; 220 byte = ((strchr(hex, address[i * 2]) - hex) << 4) | 221 (strchr(hex, address[i * 2 + 1]) - hex); 222 addr6.s6_addr[i] = byte; 223 } 224 iter->current.af = AF_INET6; 225 iter->current.flags = INTERFACE_F_UP; 226 isc_netaddr_fromin6(&iter->current.address, &addr6); 227 if (isc_netaddr_islinklocal(&iter->current.address)) { 228 isc_netaddr_setzone(&iter->current.address, 229 (isc_uint32_t)ifindex); 230 } 231 for (i = 0; i < 16; i++) { 232 if (prefix > 8) { 233 addr6.s6_addr[i] = 0xff; 234 prefix -= 8; 235 } else { 236 addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff; 237 prefix = 0; 238 } 239 } 240 isc_netaddr_fromin6(&iter->current.netmask, &addr6); 241 strncpy(iter->current.name, name, sizeof(iter->current.name)); 242 return (ISC_R_SUCCESS); 243} 244#endif 245 246/* 247 * The remaining code is common to the sysctl and ioctl case. 248 */ 249 250isc_result_t 251isc_interfaceiter_current(isc_interfaceiter_t *iter, 252 isc_interface_t *ifdata) 253{ 254 REQUIRE(iter->result == ISC_R_SUCCESS); 255 memmove(ifdata, &iter->current, sizeof(*ifdata)); 256 return (ISC_R_SUCCESS); 257} 258 259isc_result_t 260isc_interfaceiter_first(isc_interfaceiter_t *iter) { 261 isc_result_t result; 262 263 REQUIRE(VALID_IFITER(iter)); 264 265 internal_first(iter); 266 for (;;) { 267 result = internal_current(iter); 268 if (result != ISC_R_IGNORE) 269 break; 270 result = internal_next(iter); 271 if (result != ISC_R_SUCCESS) 272 break; 273 } 274 iter->result = result; 275 return (result); 276} 277 278isc_result_t 279isc_interfaceiter_next(isc_interfaceiter_t *iter) { 280 isc_result_t result; 281 282 REQUIRE(VALID_IFITER(iter)); 283 REQUIRE(iter->result == ISC_R_SUCCESS); 284 285 for (;;) { 286 result = internal_next(iter); 287 if (result != ISC_R_SUCCESS) 288 break; 289 result = internal_current(iter); 290 if (result != ISC_R_IGNORE) 291 break; 292 } 293 iter->result = result; 294 return (result); 295} 296 297void 298isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) 299{ 300 isc_interfaceiter_t *iter; 301 REQUIRE(iterp != NULL); 302 iter = *iterp; 303 REQUIRE(VALID_IFITER(iter)); 304 305 internal_destroy(iter); 306 if (iter->buf != NULL) 307 isc_mem_put(iter->mctx, iter->buf, iter->bufsize); 308 309 iter->magic = 0; 310 isc_mem_put(iter->mctx, iter, sizeof(*iter)); 311 *iterp = NULL; 312} 313