netaddr.c revision 309007
1/* 2 * Copyright (C) 2004, 2005, 2007, 2010-2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2002 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$ */ 19 20/*! \file */ 21 22#include <config.h> 23 24#include <stdio.h> 25 26#include <isc/buffer.h> 27#include <isc/msgs.h> 28#include <isc/net.h> 29#include <isc/netaddr.h> 30#include <isc/print.h> 31#include <isc/sockaddr.h> 32#include <isc/string.h> 33#include <isc/util.h> 34#include "ntp_stdlib.h" /* NTP change for strlcpy, strlcat */ 35 36isc_boolean_t 37isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) { 38 REQUIRE(a != NULL && b != NULL); 39 40 if (a->family != b->family) 41 return (ISC_FALSE); 42 43 if (a->zone != b->zone) 44 return (ISC_FALSE); 45 46 switch (a->family) { 47 case AF_INET: 48 if (a->type.in.s_addr != b->type.in.s_addr) 49 return (ISC_FALSE); 50 break; 51 case AF_INET6: 52 if (memcmp(&a->type.in6, &b->type.in6, 53 sizeof(a->type.in6)) != 0 || 54 a->zone != b->zone) 55 return (ISC_FALSE); 56 break; 57#ifdef ISC_PLATFORM_HAVESYSUNH 58 case AF_UNIX: 59 if (strcmp(a->type.un, b->type.un) != 0) 60 return (ISC_FALSE); 61 break; 62#endif 63 default: 64 return (ISC_FALSE); 65 } 66 return (ISC_TRUE); 67} 68 69isc_boolean_t 70isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b, 71 unsigned int prefixlen) 72{ 73 const unsigned char *pa = NULL, *pb = NULL; 74 unsigned int ipabytes = 0; /* Length of whole IP address in bytes */ 75 unsigned int nbytes; /* Number of significant whole bytes */ 76 unsigned int nbits; /* Number of significant leftover bits */ 77 78 REQUIRE(a != NULL && b != NULL); 79 80 if (a->family != b->family) 81 return (ISC_FALSE); 82 83 if (a->zone != b->zone && b->zone != 0) 84 return (ISC_FALSE); 85 86 switch (a->family) { 87 case AF_INET: 88 pa = (const unsigned char *) &a->type.in; 89 pb = (const unsigned char *) &b->type.in; 90 ipabytes = 4; 91 break; 92 case AF_INET6: 93 pa = (const unsigned char *) &a->type.in6; 94 pb = (const unsigned char *) &b->type.in6; 95 ipabytes = 16; 96 break; 97 default: 98 return (ISC_FALSE); 99 } 100 101 /* 102 * Don't crash if we get a pattern like 10.0.0.1/9999999. 103 */ 104 if (prefixlen > ipabytes * 8) 105 prefixlen = ipabytes * 8; 106 107 nbytes = prefixlen / 8; 108 nbits = prefixlen % 8; 109 110 if (nbytes > 0) { 111 if (memcmp(pa, pb, nbytes) != 0) 112 return (ISC_FALSE); 113 } 114 if (nbits > 0) { 115 unsigned int bytea, byteb, mask; 116 INSIST(nbytes < ipabytes); 117 INSIST(nbits < 8); 118 bytea = pa[nbytes]; 119 byteb = pb[nbytes]; 120 mask = (0xFF << (8-nbits)) & 0xFF; 121 if ((bytea & mask) != (byteb & mask)) 122 return (ISC_FALSE); 123 } 124 return (ISC_TRUE); 125} 126 127isc_result_t 128isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) { 129 char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; 130 char zbuf[sizeof("%4294967295")]; 131 unsigned int alen; 132 int zlen; 133 const char *r; 134 const void *type; 135 136 REQUIRE(netaddr != NULL); 137 138 switch (netaddr->family) { 139 case AF_INET: 140 type = &netaddr->type.in; 141 break; 142 case AF_INET6: 143 type = &netaddr->type.in6; 144 break; 145#ifdef ISC_PLATFORM_HAVESYSUNH 146 case AF_UNIX: 147 alen = strlen(netaddr->type.un); 148 if (alen > isc_buffer_availablelength(target)) 149 return (ISC_R_NOSPACE); 150 isc_buffer_putmem(target, 151 (const unsigned char *)(netaddr->type.un), 152 alen); 153 return (ISC_R_SUCCESS); 154#endif 155 default: 156 return (ISC_R_FAILURE); 157 } 158 r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf)); 159 if (r == NULL) 160 return (ISC_R_FAILURE); 161 162 alen = (unsigned int)strlen(abuf); /* no overflow possible */ 163 INSIST(alen < sizeof(abuf)); 164 165 zlen = 0; 166 if (netaddr->family == AF_INET6 && netaddr->zone != 0) { 167 zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone); 168 if (zlen < 0) 169 return (ISC_R_FAILURE); 170 INSIST((unsigned int)zlen < sizeof(zbuf)); 171 } 172 173 if (alen + zlen > isc_buffer_availablelength(target)) 174 return (ISC_R_NOSPACE); 175 176 isc_buffer_putmem(target, (unsigned char *)abuf, alen); 177 isc_buffer_putmem(target, (unsigned char *)zbuf, zlen); 178 179 return (ISC_R_SUCCESS); 180} 181 182void 183isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) { 184 isc_result_t result; 185 isc_buffer_t buf; 186 187 isc_buffer_init(&buf, array, size); 188 result = isc_netaddr_totext(na, &buf); 189 190 if (size == 0) 191 return; 192 193 /* 194 * Null terminate. 195 */ 196 if (result == ISC_R_SUCCESS) { 197 if (isc_buffer_availablelength(&buf) >= 1) 198 isc_buffer_putuint8(&buf, 0); 199 else 200 result = ISC_R_NOSPACE; 201 } 202 203 if (result != ISC_R_SUCCESS) { 204 snprintf(array, size, 205 "<%s %u>", 206 isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR, 207 ISC_MSG_UNKNOWNADDR, 208 "unknown address, family"), 209 na->family); 210 array[size - 1] = '\0'; 211 } 212} 213 214 215isc_result_t 216isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) { 217 static const unsigned char zeros[16] = { 0 }; 218 unsigned int nbits, nbytes, ipbytes = 0; 219 const unsigned char *p; 220 221 switch (na->family) { 222 case AF_INET: 223 p = (const unsigned char *) &na->type.in; 224 ipbytes = 4; 225 if (prefixlen > 32) 226 return (ISC_R_RANGE); 227 break; 228 case AF_INET6: 229 p = (const unsigned char *) &na->type.in6; 230 ipbytes = 16; 231 if (prefixlen > 128) 232 return (ISC_R_RANGE); 233 break; 234 default: 235 return (ISC_R_NOTIMPLEMENTED); 236 } 237 nbytes = prefixlen / 8; 238 nbits = prefixlen % 8; 239 if (nbits != 0) { 240 if ((p[nbytes] & (0xff>>nbits)) != 0U) 241 return (ISC_R_FAILURE); 242 nbytes++; 243 } 244 if (memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0) 245 return (ISC_R_FAILURE); 246 return (ISC_R_SUCCESS); 247} 248 249isc_result_t 250isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) { 251 unsigned int nbits = 0, nbytes = 0, ipbytes = 0, i; 252 const unsigned char *p; 253 254 switch (s->family) { 255 case AF_INET: 256 p = (const unsigned char *) &s->type.in; 257 ipbytes = 4; 258 break; 259 case AF_INET6: 260 p = (const unsigned char *) &s->type.in6; 261 ipbytes = 16; 262 break; 263 default: 264 return (ISC_R_NOTIMPLEMENTED); 265 } 266 for (i = 0; i < ipbytes; i++) { 267 if (p[i] != 0xFF) 268 break; 269 } 270 nbytes = i; 271 if (i < ipbytes) { 272 unsigned int c = p[nbytes]; 273 while ((c & 0x80) != 0 && nbits < 8) { 274 c <<= 1; nbits++; 275 } 276 if ((c & 0xFF) != 0) 277 return (ISC_R_MASKNONCONTIG); 278 i++; 279 } 280 for (; i < ipbytes; i++) { 281 if (p[i] != 0) 282 return (ISC_R_MASKNONCONTIG); 283 } 284 *lenp = nbytes * 8 + nbits; 285 return (ISC_R_SUCCESS); 286} 287 288void 289isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) { 290 memset(netaddr, 0, sizeof(*netaddr)); 291 netaddr->family = AF_INET; 292 netaddr->type.in = *ina; 293} 294 295void 296isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) { 297 memset(netaddr, 0, sizeof(*netaddr)); 298 netaddr->family = AF_INET6; 299 netaddr->type.in6 = *ina6; 300} 301 302isc_result_t 303isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) { 304#ifdef ISC_PLATFORM_HAVESYSUNH 305 if (strlen(path) > sizeof(netaddr->type.un) - 1) 306 return (ISC_R_NOSPACE); 307 308 memset(netaddr, 0, sizeof(*netaddr)); 309 netaddr->family = AF_UNIX; 310 strlcpy(netaddr->type.un, path, sizeof(netaddr->type.un)); 311 netaddr->zone = 0; 312 return (ISC_R_SUCCESS); 313#else 314 UNUSED(netaddr); 315 UNUSED(path); 316 return (ISC_R_NOTIMPLEMENTED); 317#endif 318} 319 320 321void 322isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone) { 323 /* we currently only support AF_INET6. */ 324 REQUIRE(netaddr->family == AF_INET6); 325 326 netaddr->zone = zone; 327} 328 329isc_uint32_t 330isc_netaddr_getzone(const isc_netaddr_t *netaddr) { 331 return (netaddr->zone); 332} 333 334void 335isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) { 336 int family = s->type.sa.sa_family; 337 t->family = family; 338 switch (family) { 339 case AF_INET: 340 t->type.in = s->type.sin.sin_addr; 341 t->zone = 0; 342 break; 343 case AF_INET6: 344 memcpy(&t->type.in6, &s->type.sin6.sin6_addr, 16); 345#ifdef ISC_PLATFORM_HAVESCOPEID 346 t->zone = s->type.sin6.sin6_scope_id; 347#else 348 t->zone = 0; 349#endif 350 break; 351#ifdef ISC_PLATFORM_HAVESYSUNH 352 case AF_UNIX: 353 memcpy(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un)); 354 t->zone = 0; 355 break; 356#endif 357 default: 358 INSIST(0); 359 } 360} 361 362void 363isc_netaddr_any(isc_netaddr_t *netaddr) { 364 memset(netaddr, 0, sizeof(*netaddr)); 365 netaddr->family = AF_INET; 366 netaddr->type.in.s_addr = INADDR_ANY; 367} 368 369void 370isc_netaddr_any6(isc_netaddr_t *netaddr) { 371 memset(netaddr, 0, sizeof(*netaddr)); 372 netaddr->family = AF_INET6; 373 netaddr->type.in6 = in6addr_any; 374} 375 376isc_boolean_t 377isc_netaddr_ismulticast(isc_netaddr_t *na) { 378 switch (na->family) { 379 case AF_INET: 380 return (ISC_TF(ISC_IPADDR_ISMULTICAST(na->type.in.s_addr))); 381 case AF_INET6: 382 return (ISC_TF(IN6_IS_ADDR_MULTICAST(&na->type.in6))); 383 default: 384 return (ISC_FALSE); /* XXXMLG ? */ 385 } 386} 387 388isc_boolean_t 389isc_netaddr_isexperimental(isc_netaddr_t *na) { 390 switch (na->family) { 391 case AF_INET: 392 return (ISC_TF(ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr))); 393 default: 394 return (ISC_FALSE); /* XXXMLG ? */ 395 } 396} 397 398isc_boolean_t 399isc_netaddr_islinklocal(isc_netaddr_t *na) { 400 switch (na->family) { 401 case AF_INET: 402 return (ISC_FALSE); 403 case AF_INET6: 404 return (ISC_TF(IN6_IS_ADDR_LINKLOCAL(&na->type.in6))); 405 default: 406 return (ISC_FALSE); 407 } 408} 409 410isc_boolean_t 411isc_netaddr_issitelocal(isc_netaddr_t *na) { 412 switch (na->family) { 413 case AF_INET: 414 return (ISC_FALSE); 415 case AF_INET6: 416 return (ISC_TF(IN6_IS_ADDR_SITELOCAL(&na->type.in6))); 417 default: 418 return (ISC_FALSE); 419 } 420} 421 422void 423isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) { 424 isc_netaddr_t *src; 425 426 DE_CONST(s, src); /* Must come before IN6_IS_ADDR_V4MAPPED. */ 427 428 REQUIRE(s->family == AF_INET6); 429 REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6)); 430 431 memset(t, 0, sizeof(*t)); 432 t->family = AF_INET; 433 memcpy(&t->type.in, (char *)&src->type.in6 + 12, 4); 434 return; 435} 436