addr.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /* $OpenBSD: addr.c,v 1.1 2021/01/09 11:58:50 dtucker Exp $ */
  2. /*
  3. * Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org>
  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 THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include "includes.h"
  18. #include <sys/types.h>
  19. #include <sys/socket.h>
  20. #include <netinet/in.h>
  21. #include <arpa/inet.h>
  22. #include <netdb.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include "addr.h"
  27. #define _SA(x) ((struct sockaddr *)(x))
  28. int
  29. addr_unicast_masklen(int af)
  30. {
  31. switch (af) {
  32. case AF_INET:
  33. return 32;
  34. case AF_INET6:
  35. return 128;
  36. default:
  37. return -1;
  38. }
  39. }
  40. static inline int
  41. masklen_valid(int af, u_int masklen)
  42. {
  43. switch (af) {
  44. case AF_INET:
  45. return masklen <= 32 ? 0 : -1;
  46. case AF_INET6:
  47. return masklen <= 128 ? 0 : -1;
  48. default:
  49. return -1;
  50. }
  51. }
  52. int
  53. addr_xaddr_to_sa(const struct xaddr *xa, struct sockaddr *sa, socklen_t *len,
  54. u_int16_t port)
  55. {
  56. struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
  57. struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
  58. if (xa == NULL || sa == NULL || len == NULL)
  59. return -1;
  60. switch (xa->af) {
  61. case AF_INET:
  62. if (*len < sizeof(*in4))
  63. return -1;
  64. memset(sa, '\0', sizeof(*in4));
  65. *len = sizeof(*in4);
  66. #ifdef SOCK_HAS_LEN
  67. in4->sin_len = sizeof(*in4);
  68. #endif
  69. in4->sin_family = AF_INET;
  70. in4->sin_port = htons(port);
  71. memcpy(&in4->sin_addr, &xa->v4, sizeof(in4->sin_addr));
  72. break;
  73. case AF_INET6:
  74. if (*len < sizeof(*in6))
  75. return -1;
  76. memset(sa, '\0', sizeof(*in6));
  77. *len = sizeof(*in6);
  78. #ifdef SOCK_HAS_LEN
  79. in6->sin6_len = sizeof(*in6);
  80. #endif
  81. in6->sin6_family = AF_INET6;
  82. in6->sin6_port = htons(port);
  83. memcpy(&in6->sin6_addr, &xa->v6, sizeof(in6->sin6_addr));
  84. #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
  85. in6->sin6_scope_id = xa->scope_id;
  86. #endif
  87. break;
  88. default:
  89. return -1;
  90. }
  91. return 0;
  92. }
  93. /*
  94. * Convert struct sockaddr to struct xaddr
  95. * Returns 0 on success, -1 on failure.
  96. */
  97. int
  98. addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa)
  99. {
  100. struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
  101. struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
  102. memset(xa, '\0', sizeof(*xa));
  103. switch (sa->sa_family) {
  104. case AF_INET:
  105. if (slen < (socklen_t)sizeof(*in4))
  106. return -1;
  107. xa->af = AF_INET;
  108. memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4));
  109. break;
  110. case AF_INET6:
  111. if (slen < (socklen_t)sizeof(*in6))
  112. return -1;
  113. xa->af = AF_INET6;
  114. memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6));
  115. #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
  116. xa->scope_id = in6->sin6_scope_id;
  117. #endif
  118. break;
  119. default:
  120. return -1;
  121. }
  122. return 0;
  123. }
  124. int
  125. addr_invert(struct xaddr *n)
  126. {
  127. int i;
  128. if (n == NULL)
  129. return -1;
  130. switch (n->af) {
  131. case AF_INET:
  132. n->v4.s_addr = ~n->v4.s_addr;
  133. return 0;
  134. case AF_INET6:
  135. for (i = 0; i < 4; i++)
  136. n->addr32[i] = ~n->addr32[i];
  137. return 0;
  138. default:
  139. return -1;
  140. }
  141. }
  142. /*
  143. * Calculate a netmask of length 'l' for address family 'af' and
  144. * store it in 'n'.
  145. * Returns 0 on success, -1 on failure.
  146. */
  147. int
  148. addr_netmask(int af, u_int l, struct xaddr *n)
  149. {
  150. int i;
  151. if (masklen_valid(af, l) != 0 || n == NULL)
  152. return -1;
  153. memset(n, '\0', sizeof(*n));
  154. switch (af) {
  155. case AF_INET:
  156. n->af = AF_INET;
  157. if (l == 0)
  158. return 0;
  159. n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff);
  160. return 0;
  161. case AF_INET6:
  162. n->af = AF_INET6;
  163. for (i = 0; i < 4 && l >= 32; i++, l -= 32)
  164. n->addr32[i] = 0xffffffffU;
  165. if (i < 4 && l != 0)
  166. n->addr32[i] = htonl((0xffffffff << (32 - l)) &
  167. 0xffffffff);
  168. return 0;
  169. default:
  170. return -1;
  171. }
  172. }
  173. int
  174. addr_hostmask(int af, u_int l, struct xaddr *n)
  175. {
  176. if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1)
  177. return -1;
  178. return 0;
  179. }
  180. /*
  181. * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'.
  182. * Returns 0 on success, -1 on failure.
  183. */
  184. int
  185. addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
  186. {
  187. int i;
  188. if (dst == NULL || a == NULL || b == NULL || a->af != b->af)
  189. return -1;
  190. memcpy(dst, a, sizeof(*dst));
  191. switch (a->af) {
  192. case AF_INET:
  193. dst->v4.s_addr &= b->v4.s_addr;
  194. return 0;
  195. case AF_INET6:
  196. dst->scope_id = a->scope_id;
  197. for (i = 0; i < 4; i++)
  198. dst->addr32[i] &= b->addr32[i];
  199. return 0;
  200. default:
  201. return -1;
  202. }
  203. }
  204. int
  205. addr_cmp(const struct xaddr *a, const struct xaddr *b)
  206. {
  207. int i;
  208. if (a->af != b->af)
  209. return (a->af == AF_INET6 ? 1 : -1);
  210. switch (a->af) {
  211. case AF_INET:
  212. /*
  213. * Can't just subtract here as 255.255.255.255 - 0.0.0.0 is
  214. * too big to fit into a signed int
  215. */
  216. if (a->v4.s_addr == b->v4.s_addr)
  217. return 0;
  218. return (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1);
  219. case AF_INET6:;
  220. /*
  221. * Do this a byte at a time to avoid the above issue and
  222. * any endian problems
  223. */
  224. for (i = 0; i < 16; i++)
  225. if (a->addr8[i] - b->addr8[i] != 0)
  226. return (a->addr8[i] - b->addr8[i]);
  227. if (a->scope_id == b->scope_id)
  228. return (0);
  229. return (a->scope_id > b->scope_id ? 1 : -1);
  230. default:
  231. return (-1);
  232. }
  233. }
  234. int
  235. addr_is_all0s(const struct xaddr *a)
  236. {
  237. int i;
  238. switch (a->af) {
  239. case AF_INET:
  240. return (a->v4.s_addr == 0 ? 0 : -1);
  241. case AF_INET6:;
  242. for (i = 0; i < 4; i++)
  243. if (a->addr32[i] != 0)
  244. return -1;
  245. return 0;
  246. default:
  247. return -1;
  248. }
  249. }
  250. /*
  251. * Test whether host portion of address 'a', as determined by 'masklen'
  252. * is all zeros.
  253. * Returns 0 on if host portion of address is all-zeros,
  254. * -1 if not all zeros or on failure.
  255. */
  256. int
  257. addr_host_is_all0s(const struct xaddr *a, u_int masklen)
  258. {
  259. struct xaddr tmp_addr, tmp_mask, tmp_result;
  260. memcpy(&tmp_addr, a, sizeof(tmp_addr));
  261. if (addr_hostmask(a->af, masklen, &tmp_mask) == -1)
  262. return -1;
  263. if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1)
  264. return -1;
  265. return addr_is_all0s(&tmp_result);
  266. }
  267. /*
  268. * Parse string address 'p' into 'n'
  269. * Returns 0 on success, -1 on failure.
  270. */
  271. int
  272. addr_pton(const char *p, struct xaddr *n)
  273. {
  274. struct addrinfo hints, *ai;
  275. memset(&hints, '\0', sizeof(hints));
  276. hints.ai_flags = AI_NUMERICHOST;
  277. if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0)
  278. return -1;
  279. if (ai == NULL || ai->ai_addr == NULL)
  280. return -1;
  281. if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen,
  282. n) == -1) {
  283. freeaddrinfo(ai);
  284. return -1;
  285. }
  286. freeaddrinfo(ai);
  287. return 0;
  288. }
  289. int
  290. addr_sa_pton(const char *h, const char *s, struct sockaddr *sa, socklen_t slen)
  291. {
  292. struct addrinfo hints, *ai;
  293. memset(&hints, '\0', sizeof(hints));
  294. hints.ai_flags = AI_NUMERICHOST;
  295. if (h == NULL || getaddrinfo(h, s, &hints, &ai) != 0)
  296. return -1;
  297. if (ai == NULL || ai->ai_addr == NULL)
  298. return -1;
  299. if (sa != NULL) {
  300. if (slen < ai->ai_addrlen)
  301. return -1;
  302. memcpy(sa, &ai->ai_addr, ai->ai_addrlen);
  303. }
  304. freeaddrinfo(ai);
  305. return 0;
  306. }
  307. int
  308. addr_ntop(const struct xaddr *n, char *p, size_t len)
  309. {
  310. struct sockaddr_storage ss;
  311. socklen_t slen = sizeof(ss);
  312. if (addr_xaddr_to_sa(n, _SA(&ss), &slen, 0) == -1)
  313. return -1;
  314. if (n == NULL || p == NULL || len == 0)
  315. return -1;
  316. if (getnameinfo(_SA(&ss), slen, p, len, NULL, 0,
  317. NI_NUMERICHOST) == -1)
  318. return -1;
  319. return 0;
  320. }
  321. /*
  322. * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z).
  323. * Return -1 on parse error, -2 on inconsistency or 0 on success.
  324. */
  325. int
  326. addr_pton_cidr(const char *p, struct xaddr *n, u_int *l)
  327. {
  328. struct xaddr tmp;
  329. long unsigned int masklen = 999;
  330. char addrbuf[64], *mp, *cp;
  331. /* Don't modify argument */
  332. if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf))
  333. return -1;
  334. if ((mp = strchr(addrbuf, '/')) != NULL) {
  335. *mp = '\0';
  336. mp++;
  337. masklen = strtoul(mp, &cp, 10);
  338. if (*mp == '\0' || *cp != '\0' || masklen > 128)
  339. return -1;
  340. }
  341. if (addr_pton(addrbuf, &tmp) == -1)
  342. return -1;
  343. if (mp == NULL)
  344. masklen = addr_unicast_masklen(tmp.af);
  345. if (masklen_valid(tmp.af, masklen) == -1)
  346. return -2;
  347. if (addr_host_is_all0s(&tmp, masklen) != 0)
  348. return -2;
  349. if (n != NULL)
  350. memcpy(n, &tmp, sizeof(*n));
  351. if (l != NULL)
  352. *l = masklen;
  353. return 0;
  354. }
  355. int
  356. addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen)
  357. {
  358. struct xaddr tmp_mask, tmp_result;
  359. if (host->af != net->af)
  360. return -1;
  361. if (addr_netmask(host->af, masklen, &tmp_mask) == -1)
  362. return -1;
  363. if (addr_and(&tmp_result, host, &tmp_mask) == -1)
  364. return -1;
  365. return addr_cmp(&tmp_result, net);
  366. }