/contrib/bind9/lib/isc/netaddr.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 434 lines · 355 code · 54 blank · 25 comment · 80 complexity · 493ef34b10eac73460a6156cd3258d2c MD5 · raw file

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