/contrib/ntp/libisc/sockaddr.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 480 lines · 384 code · 52 blank · 44 comment · 62 complexity · 880e3eaad9734f682cbb5fe79866d664 MD5 · raw file

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