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