/contrib/bind9/lib/isc/sockaddr.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 506 lines · 405 code · 55 blank · 46 comment · 61 complexity · 4f067c6ea0565385b1cd18c3f2ee30e7 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004-2007, 2010-2012 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. /* $Id$ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <stdio.h>
  21. #include <isc/buffer.h>
  22. #include <isc/hash.h>
  23. #include <isc/msgs.h>
  24. #include <isc/netaddr.h>
  25. #include <isc/print.h>
  26. #include <isc/region.h>
  27. #include <isc/sockaddr.h>
  28. #include <isc/string.h>
  29. #include <isc/util.h>
  30. isc_boolean_t
  31. isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
  32. return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
  33. ISC_SOCKADDR_CMPPORT|
  34. ISC_SOCKADDR_CMPSCOPE));
  35. }
  36. isc_boolean_t
  37. isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
  38. return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
  39. ISC_SOCKADDR_CMPSCOPE));
  40. }
  41. isc_boolean_t
  42. isc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
  43. unsigned int flags)
  44. {
  45. REQUIRE(a != NULL && b != NULL);
  46. if (a->length != b->length)
  47. return (ISC_FALSE);
  48. /*
  49. * We don't just memcmp because the sin_zero field isn't always
  50. * zero.
  51. */
  52. if (a->type.sa.sa_family != b->type.sa.sa_family)
  53. return (ISC_FALSE);
  54. switch (a->type.sa.sa_family) {
  55. case AF_INET:
  56. if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
  57. memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
  58. sizeof(a->type.sin.sin_addr)) != 0)
  59. return (ISC_FALSE);
  60. if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
  61. a->type.sin.sin_port != b->type.sin.sin_port)
  62. return (ISC_FALSE);
  63. break;
  64. case AF_INET6:
  65. if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
  66. memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
  67. sizeof(a->type.sin6.sin6_addr)) != 0)
  68. return (ISC_FALSE);
  69. #ifdef ISC_PLATFORM_HAVESCOPEID
  70. /*
  71. * If ISC_SOCKADDR_CMPSCOPEZERO is set then don't return
  72. * ISC_FALSE if one of the scopes in zero.
  73. */
  74. if ((flags & ISC_SOCKADDR_CMPSCOPE) != 0 &&
  75. a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id &&
  76. ((flags & ISC_SOCKADDR_CMPSCOPEZERO) == 0 ||
  77. (a->type.sin6.sin6_scope_id != 0 &&
  78. b->type.sin6.sin6_scope_id != 0)))
  79. return (ISC_FALSE);
  80. #endif
  81. if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
  82. a->type.sin6.sin6_port != b->type.sin6.sin6_port)
  83. return (ISC_FALSE);
  84. break;
  85. default:
  86. if (memcmp(&a->type, &b->type, a->length) != 0)
  87. return (ISC_FALSE);
  88. }
  89. return (ISC_TRUE);
  90. }
  91. isc_boolean_t
  92. isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
  93. unsigned int prefixlen)
  94. {
  95. isc_netaddr_t na, nb;
  96. isc_netaddr_fromsockaddr(&na, a);
  97. isc_netaddr_fromsockaddr(&nb, b);
  98. return (isc_netaddr_eqprefix(&na, &nb, prefixlen));
  99. }
  100. isc_result_t
  101. isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) {
  102. isc_result_t result;
  103. isc_netaddr_t netaddr;
  104. char pbuf[sizeof("65000")];
  105. unsigned int plen;
  106. isc_region_t avail;
  107. REQUIRE(sockaddr != NULL);
  108. /*
  109. * Do the port first, giving us the opportunity to check for
  110. * unsupported address families before calling
  111. * isc_netaddr_fromsockaddr().
  112. */
  113. switch (sockaddr->type.sa.sa_family) {
  114. case AF_INET:
  115. snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port));
  116. break;
  117. case AF_INET6:
  118. snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port));
  119. break;
  120. #ifdef ISC_PLAFORM_HAVESYSUNH
  121. case AF_UNIX:
  122. plen = strlen(sockaddr->type.sunix.sun_path);
  123. if (plen >= isc_buffer_availablelength(target))
  124. return (ISC_R_NOSPACE);
  125. isc_buffer_putmem(target, sockaddr->type.sunix.sun_path, plen);
  126. /*
  127. * Null terminate after used region.
  128. */
  129. isc_buffer_availableregion(target, &avail);
  130. INSIST(avail.length >= 1);
  131. avail.base[0] = '\0';
  132. return (ISC_R_SUCCESS);
  133. #endif
  134. default:
  135. return (ISC_R_FAILURE);
  136. }
  137. plen = strlen(pbuf);
  138. INSIST(plen < sizeof(pbuf));
  139. isc_netaddr_fromsockaddr(&netaddr, sockaddr);
  140. result = isc_netaddr_totext(&netaddr, target);
  141. if (result != ISC_R_SUCCESS)
  142. return (result);
  143. if (1 + plen + 1 > isc_buffer_availablelength(target))
  144. return (ISC_R_NOSPACE);
  145. isc_buffer_putmem(target, (const unsigned char *)"#", 1);
  146. isc_buffer_putmem(target, (const unsigned char *)pbuf, plen);
  147. /*
  148. * Null terminate after used region.
  149. */
  150. isc_buffer_availableregion(target, &avail);
  151. INSIST(avail.length >= 1);
  152. avail.base[0] = '\0';
  153. return (ISC_R_SUCCESS);
  154. }
  155. void
  156. isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) {
  157. isc_result_t result;
  158. isc_buffer_t buf;
  159. if (size == 0U)
  160. return;
  161. isc_buffer_init(&buf, array, size);
  162. result = isc_sockaddr_totext(sa, &buf);
  163. if (result != ISC_R_SUCCESS) {
  164. /*
  165. * The message is the same as in netaddr.c.
  166. */
  167. snprintf(array, size,
  168. isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
  169. ISC_MSG_UNKNOWNADDR,
  170. "<unknown address, family %u>"),
  171. sa->type.sa.sa_family);
  172. array[size - 1] = '\0';
  173. }
  174. }
  175. unsigned int
  176. isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) {
  177. unsigned int length = 0;
  178. const unsigned char *s = NULL;
  179. unsigned int h = 0;
  180. unsigned int g;
  181. unsigned int p = 0;
  182. const struct in6_addr *in6;
  183. REQUIRE(sockaddr != NULL);
  184. switch (sockaddr->type.sa.sa_family) {
  185. case AF_INET:
  186. s = (const unsigned char *)&sockaddr->type.sin.sin_addr;
  187. p = ntohs(sockaddr->type.sin.sin_port);
  188. length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
  189. break;
  190. case AF_INET6:
  191. in6 = &sockaddr->type.sin6.sin6_addr;
  192. if (IN6_IS_ADDR_V4MAPPED(in6)) {
  193. s = (const unsigned char *)&in6[12];
  194. length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
  195. } else {
  196. s = (const unsigned char *)in6;
  197. length = sizeof(sockaddr->type.sin6.sin6_addr);
  198. }
  199. p = ntohs(sockaddr->type.sin6.sin6_port);
  200. break;
  201. default:
  202. UNEXPECTED_ERROR(__FILE__, __LINE__,
  203. isc_msgcat_get(isc_msgcat,
  204. ISC_MSGSET_SOCKADDR,
  205. ISC_MSG_UNKNOWNFAMILY,
  206. "unknown address family: %d"),
  207. (int)sockaddr->type.sa.sa_family);
  208. s = (const unsigned char *)&sockaddr->type;
  209. length = sockaddr->length;
  210. p = 0;
  211. }
  212. h = isc_hash_calc(s, length, ISC_TRUE);
  213. if (!address_only) {
  214. g = isc_hash_calc((const unsigned char *)&p, sizeof(p),
  215. ISC_TRUE);
  216. h = h ^ g; /* XXX: we should concatenate h and p first */
  217. }
  218. return (h);
  219. }
  220. void
  221. isc_sockaddr_any(isc_sockaddr_t *sockaddr)
  222. {
  223. memset(sockaddr, 0, sizeof(*sockaddr));
  224. sockaddr->type.sin.sin_family = AF_INET;
  225. #ifdef ISC_PLATFORM_HAVESALEN
  226. sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
  227. #endif
  228. sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY;
  229. sockaddr->type.sin.sin_port = 0;
  230. sockaddr->length = sizeof(sockaddr->type.sin);
  231. ISC_LINK_INIT(sockaddr, link);
  232. }
  233. void
  234. isc_sockaddr_any6(isc_sockaddr_t *sockaddr)
  235. {
  236. memset(sockaddr, 0, sizeof(*sockaddr));
  237. sockaddr->type.sin6.sin6_family = AF_INET6;
  238. #ifdef ISC_PLATFORM_HAVESALEN
  239. sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
  240. #endif
  241. sockaddr->type.sin6.sin6_addr = in6addr_any;
  242. sockaddr->type.sin6.sin6_port = 0;
  243. sockaddr->length = sizeof(sockaddr->type.sin6);
  244. ISC_LINK_INIT(sockaddr, link);
  245. }
  246. void
  247. isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
  248. in_port_t port)
  249. {
  250. memset(sockaddr, 0, sizeof(*sockaddr));
  251. sockaddr->type.sin.sin_family = AF_INET;
  252. #ifdef ISC_PLATFORM_HAVESALEN
  253. sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
  254. #endif
  255. sockaddr->type.sin.sin_addr = *ina;
  256. sockaddr->type.sin.sin_port = htons(port);
  257. sockaddr->length = sizeof(sockaddr->type.sin);
  258. ISC_LINK_INIT(sockaddr, link);
  259. }
  260. void
  261. isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) {
  262. switch (pf) {
  263. case AF_INET:
  264. isc_sockaddr_any(sockaddr);
  265. break;
  266. case AF_INET6:
  267. isc_sockaddr_any6(sockaddr);
  268. break;
  269. default:
  270. INSIST(0);
  271. }
  272. }
  273. void
  274. isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
  275. in_port_t port)
  276. {
  277. memset(sockaddr, 0, sizeof(*sockaddr));
  278. sockaddr->type.sin6.sin6_family = AF_INET6;
  279. #ifdef ISC_PLATFORM_HAVESALEN
  280. sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
  281. #endif
  282. sockaddr->type.sin6.sin6_addr = *ina6;
  283. sockaddr->type.sin6.sin6_port = htons(port);
  284. sockaddr->length = sizeof(sockaddr->type.sin6);
  285. ISC_LINK_INIT(sockaddr, link);
  286. }
  287. void
  288. isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
  289. in_port_t port)
  290. {
  291. memset(sockaddr, 0, sizeof(*sockaddr));
  292. sockaddr->type.sin6.sin6_family = AF_INET6;
  293. #ifdef ISC_PLATFORM_HAVESALEN
  294. sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
  295. #endif
  296. sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff;
  297. sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff;
  298. memcpy(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4);
  299. sockaddr->type.sin6.sin6_port = htons(port);
  300. sockaddr->length = sizeof(sockaddr->type.sin6);
  301. ISC_LINK_INIT(sockaddr, link);
  302. }
  303. int
  304. isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) {
  305. /*
  306. * Get the protocol family of 'sockaddr'.
  307. */
  308. #if (AF_INET == PF_INET && AF_INET6 == PF_INET6)
  309. /*
  310. * Assume that PF_xxx == AF_xxx for all AF and PF.
  311. */
  312. return (sockaddr->type.sa.sa_family);
  313. #else
  314. switch (sockaddr->type.sa.sa_family) {
  315. case AF_INET:
  316. return (PF_INET);
  317. case AF_INET6:
  318. return (PF_INET6);
  319. default:
  320. FATAL_ERROR(__FILE__, __LINE__,
  321. isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
  322. ISC_MSG_UNKNOWNFAMILY,
  323. "unknown address family: %d"),
  324. (int)sockaddr->type.sa.sa_family);
  325. }
  326. #endif
  327. }
  328. void
  329. isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
  330. in_port_t port)
  331. {
  332. memset(sockaddr, 0, sizeof(*sockaddr));
  333. sockaddr->type.sin.sin_family = na->family;
  334. switch (na->family) {
  335. case AF_INET:
  336. sockaddr->length = sizeof(sockaddr->type.sin);
  337. #ifdef ISC_PLATFORM_HAVESALEN
  338. sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
  339. #endif
  340. sockaddr->type.sin.sin_addr = na->type.in;
  341. sockaddr->type.sin.sin_port = htons(port);
  342. break;
  343. case AF_INET6:
  344. sockaddr->length = sizeof(sockaddr->type.sin6);
  345. #ifdef ISC_PLATFORM_HAVESALEN
  346. sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
  347. #endif
  348. memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16);
  349. #ifdef ISC_PLATFORM_HAVESCOPEID
  350. sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na);
  351. #endif
  352. sockaddr->type.sin6.sin6_port = htons(port);
  353. break;
  354. default:
  355. INSIST(0);
  356. }
  357. ISC_LINK_INIT(sockaddr, link);
  358. }
  359. void
  360. isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) {
  361. switch (sockaddr->type.sa.sa_family) {
  362. case AF_INET:
  363. sockaddr->type.sin.sin_port = htons(port);
  364. break;
  365. case AF_INET6:
  366. sockaddr->type.sin6.sin6_port = htons(port);
  367. break;
  368. default:
  369. FATAL_ERROR(__FILE__, __LINE__,
  370. isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
  371. ISC_MSG_UNKNOWNFAMILY,
  372. "unknown address family: %d"),
  373. (int)sockaddr->type.sa.sa_family);
  374. }
  375. }
  376. in_port_t
  377. isc_sockaddr_getport(const isc_sockaddr_t *sockaddr) {
  378. in_port_t port = 0;
  379. switch (sockaddr->type.sa.sa_family) {
  380. case AF_INET:
  381. port = ntohs(sockaddr->type.sin.sin_port);
  382. break;
  383. case AF_INET6:
  384. port = ntohs(sockaddr->type.sin6.sin6_port);
  385. break;
  386. default:
  387. FATAL_ERROR(__FILE__, __LINE__,
  388. isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
  389. ISC_MSG_UNKNOWNFAMILY,
  390. "unknown address family: %d"),
  391. (int)sockaddr->type.sa.sa_family);
  392. }
  393. return (port);
  394. }
  395. isc_boolean_t
  396. isc_sockaddr_ismulticast(const isc_sockaddr_t *sockaddr) {
  397. isc_netaddr_t netaddr;
  398. if (sockaddr->type.sa.sa_family == AF_INET ||
  399. sockaddr->type.sa.sa_family == AF_INET6) {
  400. isc_netaddr_fromsockaddr(&netaddr, sockaddr);
  401. return (isc_netaddr_ismulticast(&netaddr));
  402. }
  403. return (ISC_FALSE);
  404. }
  405. isc_boolean_t
  406. isc_sockaddr_isexperimental(const isc_sockaddr_t *sockaddr) {
  407. isc_netaddr_t netaddr;
  408. if (sockaddr->type.sa.sa_family == AF_INET) {
  409. isc_netaddr_fromsockaddr(&netaddr, sockaddr);
  410. return (isc_netaddr_isexperimental(&netaddr));
  411. }
  412. return (ISC_FALSE);
  413. }
  414. isc_boolean_t
  415. isc_sockaddr_issitelocal(const isc_sockaddr_t *sockaddr) {
  416. isc_netaddr_t netaddr;
  417. if (sockaddr->type.sa.sa_family == AF_INET6) {
  418. isc_netaddr_fromsockaddr(&netaddr, sockaddr);
  419. return (isc_netaddr_issitelocal(&netaddr));
  420. }
  421. return (ISC_FALSE);
  422. }
  423. isc_boolean_t
  424. isc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) {
  425. isc_netaddr_t netaddr;
  426. if (sockaddr->type.sa.sa_family == AF_INET6) {
  427. isc_netaddr_fromsockaddr(&netaddr, sockaddr);
  428. return (isc_netaddr_islinklocal(&netaddr));
  429. }
  430. return (ISC_FALSE);
  431. }
  432. isc_result_t
  433. isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path) {
  434. #ifdef ISC_PLATFORM_HAVESYSUNH
  435. if (strlen(path) >= sizeof(sockaddr->type.sunix.sun_path))
  436. return (ISC_R_NOSPACE);
  437. memset(sockaddr, 0, sizeof(*sockaddr));
  438. sockaddr->length = sizeof(sockaddr->type.sunix);
  439. sockaddr->type.sunix.sun_family = AF_UNIX;
  440. #ifdef ISC_PLATFORM_HAVESALEN
  441. sockaddr->type.sunix.sun_len =
  442. (unsigned char)sizeof(sockaddr->type.sunix);
  443. #endif
  444. strcpy(sockaddr->type.sunix.sun_path, path);
  445. return (ISC_R_SUCCESS);
  446. #else
  447. UNUSED(sockaddr);
  448. UNUSED(path);
  449. return (ISC_R_NOTIMPLEMENTED);
  450. #endif
  451. }