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