1234949Sbapt/* 2234949Sbapt * Copyright (C) 2004, 2005, 2007, 2010-2012 Internet Systems Consortium, Inc. ("ISC") 3234949Sbapt * Copyright (C) 1999-2002 Internet Software Consortium. 4234949Sbapt * 5234949Sbapt * Permission to use, copy, modify, and/or distribute this software for any 6234949Sbapt * purpose with or without fee is hereby granted, provided that the above 7234949Sbapt * copyright notice and this permission notice appear in all copies. 8234949Sbapt * 9234949Sbapt * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10234949Sbapt * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11234949Sbapt * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12234949Sbapt * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13234949Sbapt * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14234949Sbapt * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15234949Sbapt * PERFORMANCE OF THIS SOFTWARE. 16234949Sbapt */ 17234949Sbapt 18234949Sbapt/* $Id$ */ 19234949Sbapt 20234949Sbapt/*! \file */ 21234949Sbapt 22234949Sbapt#include <config.h> 23234949Sbapt 24234949Sbapt#include <stdio.h> 25234949Sbapt 26234949Sbapt#include <isc/buffer.h> 27234949Sbapt#include <isc/msgs.h> 28234949Sbapt#include <isc/net.h> 29234949Sbapt#include <isc/netaddr.h> 30234949Sbapt#include <isc/print.h> 31234949Sbapt#include <isc/sockaddr.h> 32234949Sbapt#include <isc/string.h> 33234949Sbapt#include <isc/util.h> 34234949Sbapt#include "ntp_stdlib.h" /* NTP change for strlcpy, strlcat */ 35234949Sbapt 36234949Sbaptisc_boolean_t 37234949Sbaptisc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) { 38234949Sbapt REQUIRE(a != NULL && b != NULL); 39234949Sbapt 40234949Sbapt if (a->family != b->family) 41234949Sbapt return (ISC_FALSE); 42234949Sbapt 43234949Sbapt if (a->zone != b->zone) 44234949Sbapt return (ISC_FALSE); 45234949Sbapt 46234949Sbapt switch (a->family) { 47234949Sbapt case AF_INET: 48234949Sbapt if (a->type.in.s_addr != b->type.in.s_addr) 49234949Sbapt return (ISC_FALSE); 50234949Sbapt break; 51234949Sbapt case AF_INET6: 52234949Sbapt if (memcmp(&a->type.in6, &b->type.in6, 53234949Sbapt sizeof(a->type.in6)) != 0 || 54234949Sbapt a->zone != b->zone) 55234949Sbapt return (ISC_FALSE); 56234949Sbapt break; 57234949Sbapt#ifdef ISC_PLATFORM_HAVESYSUNH 58234949Sbapt case AF_UNIX: 59234949Sbapt if (strcmp(a->type.un, b->type.un) != 0) 60234949Sbapt return (ISC_FALSE); 61234949Sbapt break; 62234949Sbapt#endif 63234949Sbapt default: 64234949Sbapt return (ISC_FALSE); 65234949Sbapt } 66234949Sbapt return (ISC_TRUE); 67234949Sbapt} 68234949Sbapt 69234949Sbaptisc_boolean_t 70234949Sbaptisc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b, 71234949Sbapt unsigned int prefixlen) 72234949Sbapt{ 73234949Sbapt const unsigned char *pa = NULL, *pb = NULL; 74234949Sbapt unsigned int ipabytes = 0; /* Length of whole IP address in bytes */ 75234949Sbapt unsigned int nbytes; /* Number of significant whole bytes */ 76234949Sbapt unsigned int nbits; /* Number of significant leftover bits */ 77234949Sbapt 78234949Sbapt REQUIRE(a != NULL && b != NULL); 79234949Sbapt 80234949Sbapt if (a->family != b->family) 81234949Sbapt return (ISC_FALSE); 82234949Sbapt 83234949Sbapt if (a->zone != b->zone && b->zone != 0) 84234949Sbapt return (ISC_FALSE); 85234949Sbapt 86234949Sbapt switch (a->family) { 87234949Sbapt case AF_INET: 88234949Sbapt pa = (const unsigned char *) &a->type.in; 89234949Sbapt pb = (const unsigned char *) &b->type.in; 90234949Sbapt ipabytes = 4; 91234949Sbapt break; 92234949Sbapt case AF_INET6: 93234949Sbapt pa = (const unsigned char *) &a->type.in6; 94234949Sbapt pb = (const unsigned char *) &b->type.in6; 95234949Sbapt ipabytes = 16; 96234949Sbapt break; 97234949Sbapt default: 98234949Sbapt return (ISC_FALSE); 99234949Sbapt } 100234949Sbapt 101234949Sbapt /* 102234949Sbapt * Don't crash if we get a pattern like 10.0.0.1/9999999. 103234949Sbapt */ 104234949Sbapt if (prefixlen > ipabytes * 8) 105234949Sbapt prefixlen = ipabytes * 8; 106234949Sbapt 107234949Sbapt nbytes = prefixlen / 8; 108234949Sbapt nbits = prefixlen % 8; 109234949Sbapt 110234949Sbapt if (nbytes > 0) { 111234949Sbapt if (memcmp(pa, pb, nbytes) != 0) 112234949Sbapt return (ISC_FALSE); 113234949Sbapt } 114234949Sbapt if (nbits > 0) { 115234949Sbapt unsigned int bytea, byteb, mask; 116234949Sbapt INSIST(nbytes < ipabytes); 117234949Sbapt INSIST(nbits < 8); 118234949Sbapt bytea = pa[nbytes]; 119234949Sbapt byteb = pb[nbytes]; 120234949Sbapt mask = (0xFF << (8-nbits)) & 0xFF; 121234949Sbapt if ((bytea & mask) != (byteb & mask)) 122234949Sbapt return (ISC_FALSE); 123234949Sbapt } 124234949Sbapt return (ISC_TRUE); 125234949Sbapt} 126234949Sbapt 127234949Sbaptisc_result_t 128234949Sbaptisc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) { 129234949Sbapt char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; 130234949Sbapt char zbuf[sizeof("%4294967295")]; 131234949Sbapt unsigned int alen; 132234949Sbapt int zlen; 133234949Sbapt const char *r; 134234949Sbapt const void *type; 135234949Sbapt 136234949Sbapt REQUIRE(netaddr != NULL); 137234949Sbapt 138234949Sbapt switch (netaddr->family) { 139234949Sbapt case AF_INET: 140234949Sbapt type = &netaddr->type.in; 141234949Sbapt break; 142234949Sbapt case AF_INET6: 143234949Sbapt type = &netaddr->type.in6; 144234949Sbapt break; 145234949Sbapt#ifdef ISC_PLATFORM_HAVESYSUNH 146234949Sbapt case AF_UNIX: 147234949Sbapt alen = strlen(netaddr->type.un); 148234949Sbapt if (alen > isc_buffer_availablelength(target)) 149234949Sbapt return (ISC_R_NOSPACE); 150234949Sbapt isc_buffer_putmem(target, 151234949Sbapt (const unsigned char *)(netaddr->type.un), 152234949Sbapt alen); 153234949Sbapt return (ISC_R_SUCCESS); 154234949Sbapt#endif 155234949Sbapt default: 156234949Sbapt return (ISC_R_FAILURE); 157234949Sbapt } 158234949Sbapt r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf)); 159234949Sbapt if (r == NULL) 160234949Sbapt return (ISC_R_FAILURE); 161234949Sbapt 162234949Sbapt alen = (unsigned int)strlen(abuf); /* no overflow possible */ 163234949Sbapt INSIST(alen < sizeof(abuf)); 164234949Sbapt 165234949Sbapt zlen = 0; 166234949Sbapt if (netaddr->family == AF_INET6 && netaddr->zone != 0) { 167234949Sbapt zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone); 168234949Sbapt if (zlen < 0) 169234949Sbapt return (ISC_R_FAILURE); 170234949Sbapt INSIST((unsigned int)zlen < sizeof(zbuf)); 171234949Sbapt } 172234949Sbapt 173234949Sbapt if (alen + zlen > isc_buffer_availablelength(target)) 174234949Sbapt return (ISC_R_NOSPACE); 175234949Sbapt 176234949Sbapt isc_buffer_putmem(target, (unsigned char *)abuf, alen); 177234949Sbapt isc_buffer_putmem(target, (unsigned char *)zbuf, zlen); 178234949Sbapt 179234949Sbapt return (ISC_R_SUCCESS); 180234949Sbapt} 181234949Sbapt 182234949Sbaptvoid 183234949Sbaptisc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) { 184234949Sbapt isc_result_t result; 185234949Sbapt isc_buffer_t buf; 186234949Sbapt 187234949Sbapt isc_buffer_init(&buf, array, size); 188234949Sbapt result = isc_netaddr_totext(na, &buf); 189234949Sbapt 190234949Sbapt if (size == 0) 191234949Sbapt return; 192234949Sbapt 193234949Sbapt /* 194234949Sbapt * Null terminate. 195234949Sbapt */ 196234949Sbapt if (result == ISC_R_SUCCESS) { 197234949Sbapt if (isc_buffer_availablelength(&buf) >= 1) 198234949Sbapt isc_buffer_putuint8(&buf, 0); 199234949Sbapt else 200234949Sbapt result = ISC_R_NOSPACE; 201234949Sbapt } 202234949Sbapt 203234949Sbapt if (result != ISC_R_SUCCESS) { 204234949Sbapt snprintf(array, size, 205234949Sbapt "<%s %u>", 206234949Sbapt isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR, 207234949Sbapt ISC_MSG_UNKNOWNADDR, 208234949Sbapt "unknown address, family"), 209234949Sbapt na->family); 210234949Sbapt 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