sockunion.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. /* Socket union related function.
  2. * Copyright (c) 1997, 98 Kunihiro Ishiguro
  3. *
  4. * This file is part of GNU Zebra.
  5. *
  6. * GNU Zebra is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version 2, or (at your option) any
  9. * later version.
  10. *
  11. * GNU Zebra is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GNU Zebra; see the file COPYING. If not, write to the Free
  18. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  19. * 02111-1307, USA.
  20. */
  21. #include <zebra.h>
  22. #include "prefix.h"
  23. #include "vty.h"
  24. #include "sockunion.h"
  25. #include "memory.h"
  26. #include "str.h"
  27. #include "log.h"
  28. #ifndef HAVE_INET_ATON
  29. int
  30. inet_aton (const char *cp, struct in_addr *inaddr)
  31. {
  32. int dots = 0;
  33. register u_long addr = 0;
  34. register u_long val = 0, base = 10;
  35. do
  36. {
  37. register char c = *cp;
  38. switch (c)
  39. {
  40. case '0': case '1': case '2': case '3': case '4': case '5':
  41. case '6': case '7': case '8': case '9':
  42. val = (val * base) + (c - '0');
  43. break;
  44. case '.':
  45. if (++dots > 3)
  46. return 0;
  47. case '\0':
  48. if (val > 255)
  49. return 0;
  50. addr = addr << 8 | val;
  51. val = 0;
  52. break;
  53. default:
  54. return 0;
  55. }
  56. } while (*cp++) ;
  57. if (dots < 3)
  58. addr <<= 8 * (3 - dots);
  59. if (inaddr)
  60. inaddr->s_addr = htonl (addr);
  61. return 1;
  62. }
  63. #endif /* ! HAVE_INET_ATON */
  64. #ifndef HAVE_INET_PTON
  65. int
  66. inet_pton (int family, const char *strptr, void *addrptr)
  67. {
  68. if (family == AF_INET)
  69. {
  70. struct in_addr in_val;
  71. if (inet_aton (strptr, &in_val))
  72. {
  73. memcpy (addrptr, &in_val, sizeof (struct in_addr));
  74. return 1;
  75. }
  76. return 0;
  77. }
  78. errno = EAFNOSUPPORT;
  79. return -1;
  80. }
  81. #endif /* ! HAVE_INET_PTON */
  82. #ifndef HAVE_INET_NTOP
  83. const char *
  84. inet_ntop (int family, const void *addrptr, char *strptr, size_t len)
  85. {
  86. unsigned char *p = (unsigned char *) addrptr;
  87. if (family == AF_INET)
  88. {
  89. char temp[INET_ADDRSTRLEN];
  90. snprintf(temp, sizeof(temp), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
  91. if (strlen(temp) >= len)
  92. {
  93. errno = ENOSPC;
  94. return NULL;
  95. }
  96. strcpy(strptr, temp);
  97. return strptr;
  98. }
  99. errno = EAFNOSUPPORT;
  100. return NULL;
  101. }
  102. #endif /* ! HAVE_INET_NTOP */
  103. const char *
  104. inet_sutop (union sockunion *su, char *str)
  105. {
  106. switch (su->sa.sa_family)
  107. {
  108. case AF_INET:
  109. inet_ntop (AF_INET, &su->sin.sin_addr, str, INET_ADDRSTRLEN);
  110. break;
  111. #ifdef HAVE_IPV6
  112. case AF_INET6:
  113. inet_ntop (AF_INET6, &su->sin6.sin6_addr, str, INET6_ADDRSTRLEN);
  114. break;
  115. #endif /* HAVE_IPV6 */
  116. }
  117. return str;
  118. }
  119. int
  120. str2sockunion (const char *str, union sockunion *su)
  121. {
  122. int ret;
  123. memset (su, 0, sizeof (union sockunion));
  124. ret = inet_pton (AF_INET, str, &su->sin.sin_addr);
  125. if (ret > 0) /* Valid IPv4 address format. */
  126. {
  127. su->sin.sin_family = AF_INET;
  128. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  129. su->sin.sin_len = sizeof(struct sockaddr_in);
  130. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  131. return 0;
  132. }
  133. #ifdef HAVE_IPV6
  134. ret = inet_pton (AF_INET6, str, &su->sin6.sin6_addr);
  135. if (ret > 0) /* Valid IPv6 address format. */
  136. {
  137. su->sin6.sin6_family = AF_INET6;
  138. #ifdef SIN6_LEN
  139. su->sin6.sin6_len = sizeof(struct sockaddr_in6);
  140. #endif /* SIN6_LEN */
  141. return 0;
  142. }
  143. #endif /* HAVE_IPV6 */
  144. return -1;
  145. }
  146. const char *
  147. sockunion2str (union sockunion *su, char *buf, size_t len)
  148. {
  149. if (su->sa.sa_family == AF_INET)
  150. return inet_ntop (AF_INET, &su->sin.sin_addr, buf, len);
  151. #ifdef HAVE_IPV6
  152. else if (su->sa.sa_family == AF_INET6)
  153. return inet_ntop (AF_INET6, &su->sin6.sin6_addr, buf, len);
  154. #endif /* HAVE_IPV6 */
  155. return NULL;
  156. }
  157. union sockunion *
  158. sockunion_str2su (const char *str)
  159. {
  160. int ret;
  161. union sockunion *su;
  162. su = XMALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  163. memset (su, 0, sizeof (union sockunion));
  164. ret = inet_pton (AF_INET, str, &su->sin.sin_addr);
  165. if (ret > 0) /* Valid IPv4 address format. */
  166. {
  167. su->sin.sin_family = AF_INET;
  168. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  169. su->sin.sin_len = sizeof(struct sockaddr_in);
  170. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  171. return su;
  172. }
  173. #ifdef HAVE_IPV6
  174. ret = inet_pton (AF_INET6, str, &su->sin6.sin6_addr);
  175. if (ret > 0) /* Valid IPv6 address format. */
  176. {
  177. su->sin6.sin6_family = AF_INET6;
  178. #ifdef SIN6_LEN
  179. su->sin6.sin6_len = sizeof(struct sockaddr_in6);
  180. #endif /* SIN6_LEN */
  181. return su;
  182. }
  183. #endif /* HAVE_IPV6 */
  184. XFREE (MTYPE_SOCKUNION, su);
  185. return NULL;
  186. }
  187. char *
  188. sockunion_su2str (union sockunion *su)
  189. {
  190. char str[SU_ADDRSTRLEN];
  191. switch (su->sa.sa_family)
  192. {
  193. case AF_INET:
  194. inet_ntop (AF_INET, &su->sin.sin_addr, str, sizeof (str));
  195. break;
  196. #ifdef HAVE_IPV6
  197. case AF_INET6:
  198. inet_ntop (AF_INET6, &su->sin6.sin6_addr, str, sizeof (str));
  199. break;
  200. #endif /* HAVE_IPV6 */
  201. }
  202. return XSTRDUP (MTYPE_TMP, str);
  203. }
  204. /* Convert IPv4 compatible IPv6 address to IPv4 address. */
  205. static void
  206. sockunion_normalise_mapped (union sockunion *su)
  207. {
  208. struct sockaddr_in sin;
  209. #ifdef HAVE_IPV6
  210. if (su->sa.sa_family == AF_INET6
  211. && IN6_IS_ADDR_V4MAPPED (&su->sin6.sin6_addr))
  212. {
  213. memset (&sin, 0, sizeof (struct sockaddr_in));
  214. sin.sin_family = AF_INET;
  215. memcpy (&sin.sin_addr, ((char *)&su->sin6.sin6_addr) + 12, 4);
  216. memcpy (su, &sin, sizeof (struct sockaddr_in));
  217. }
  218. #endif /* HAVE_IPV6 */
  219. }
  220. /* Return socket of sockunion. */
  221. int
  222. sockunion_socket (union sockunion *su)
  223. {
  224. int sock;
  225. sock = socket (su->sa.sa_family, SOCK_STREAM, 0);
  226. if (sock < 0)
  227. {
  228. zlog (NULL, LOG_WARNING, "Can't make socket : %s", safe_strerror (errno));
  229. return -1;
  230. }
  231. return sock;
  232. }
  233. /* Return accepted new socket file descriptor. */
  234. int
  235. sockunion_accept (int sock, union sockunion *su)
  236. {
  237. socklen_t len;
  238. int client_sock;
  239. len = sizeof (union sockunion);
  240. client_sock = accept (sock, (struct sockaddr *) su, &len);
  241. sockunion_normalise_mapped (su);
  242. return client_sock;
  243. }
  244. /* Return sizeof union sockunion. */
  245. static int
  246. sockunion_sizeof (union sockunion *su)
  247. {
  248. int ret;
  249. ret = 0;
  250. switch (su->sa.sa_family)
  251. {
  252. case AF_INET:
  253. ret = sizeof (struct sockaddr_in);
  254. break;
  255. #ifdef HAVE_IPV6
  256. case AF_INET6:
  257. ret = sizeof (struct sockaddr_in6);
  258. break;
  259. #endif /* AF_INET6 */
  260. }
  261. return ret;
  262. }
  263. /* return sockunion structure : this function should be revised. */
  264. static char *
  265. sockunion_log (union sockunion *su)
  266. {
  267. static char buf[SU_ADDRSTRLEN];
  268. switch (su->sa.sa_family)
  269. {
  270. case AF_INET:
  271. snprintf (buf, SU_ADDRSTRLEN, "%s", inet_ntoa (su->sin.sin_addr));
  272. break;
  273. #ifdef HAVE_IPV6
  274. case AF_INET6:
  275. snprintf (buf, SU_ADDRSTRLEN, "%s",
  276. inet_ntop (AF_INET6, &(su->sin6.sin6_addr), buf, SU_ADDRSTRLEN));
  277. break;
  278. #endif /* HAVE_IPV6 */
  279. default:
  280. snprintf (buf, SU_ADDRSTRLEN, "af_unknown %d ", su->sa.sa_family);
  281. break;
  282. }
  283. return (XSTRDUP (MTYPE_TMP, buf));
  284. }
  285. /* sockunion_connect returns
  286. -1 : error occured
  287. 0 : connect success
  288. 1 : connect is in progress */
  289. enum connect_result
  290. sockunion_connect (int fd, union sockunion *peersu, unsigned short port,
  291. unsigned int ifindex)
  292. {
  293. int ret;
  294. int val;
  295. union sockunion su;
  296. memcpy (&su, peersu, sizeof (union sockunion));
  297. switch (su.sa.sa_family)
  298. {
  299. case AF_INET:
  300. su.sin.sin_port = port;
  301. break;
  302. #ifdef HAVE_IPV6
  303. case AF_INET6:
  304. su.sin6.sin6_port = port;
  305. #ifdef KAME
  306. if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr) && ifindex)
  307. {
  308. #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
  309. /* su.sin6.sin6_scope_id = ifindex; */
  310. #ifdef MUSICA
  311. su.sin6.sin6_scope_id = ifindex;
  312. #endif
  313. #endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */
  314. #ifndef MUSICA
  315. SET_IN6_LINKLOCAL_IFINDEX (su.sin6.sin6_addr, ifindex);
  316. #endif
  317. }
  318. #endif /* KAME */
  319. break;
  320. #endif /* HAVE_IPV6 */
  321. }
  322. /* Make socket non-block. */
  323. val = fcntl (fd, F_GETFL, 0);
  324. fcntl (fd, F_SETFL, val|O_NONBLOCK);
  325. /* Call connect function. */
  326. ret = connect (fd, (struct sockaddr *) &su, sockunion_sizeof (&su));
  327. /* Immediate success */
  328. if (ret == 0)
  329. {
  330. fcntl (fd, F_SETFL, val);
  331. return connect_success;
  332. }
  333. /* If connect is in progress then return 1 else it's real error. */
  334. if (ret < 0)
  335. {
  336. if (errno != EINPROGRESS)
  337. {
  338. zlog_info ("can't connect to %s fd %d : %s",
  339. sockunion_log (&su), fd, safe_strerror (errno));
  340. return connect_error;
  341. }
  342. }
  343. fcntl (fd, F_SETFL, val);
  344. return connect_in_progress;
  345. }
  346. /* Make socket from sockunion union. */
  347. int
  348. sockunion_stream_socket (union sockunion *su)
  349. {
  350. int sock;
  351. if (su->sa.sa_family == 0)
  352. su->sa.sa_family = AF_INET_UNION;
  353. sock = socket (su->sa.sa_family, SOCK_STREAM, 0);
  354. if (sock < 0)
  355. zlog (NULL, LOG_WARNING, "can't make socket sockunion_stream_socket");
  356. return sock;
  357. }
  358. /* Bind socket to specified address. */
  359. int
  360. sockunion_bind (int sock, union sockunion *su, unsigned short port,
  361. union sockunion *su_addr)
  362. {
  363. int size = 0;
  364. int ret;
  365. if (su->sa.sa_family == AF_INET)
  366. {
  367. size = sizeof (struct sockaddr_in);
  368. su->sin.sin_port = htons (port);
  369. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  370. su->sin.sin_len = size;
  371. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  372. if (su_addr == NULL)
  373. su->sin.sin_addr.s_addr = htonl (INADDR_ANY);
  374. }
  375. #ifdef HAVE_IPV6
  376. else if (su->sa.sa_family == AF_INET6)
  377. {
  378. size = sizeof (struct sockaddr_in6);
  379. su->sin6.sin6_port = htons (port);
  380. #ifdef SIN6_LEN
  381. su->sin6.sin6_len = size;
  382. #endif /* SIN6_LEN */
  383. if (su_addr == NULL)
  384. {
  385. #if defined(LINUX_IPV6) || defined(NRL)
  386. memset (&su->sin6.sin6_addr, 0, sizeof (struct in6_addr));
  387. #else
  388. su->sin6.sin6_addr = in6addr_any;
  389. #endif /* LINUX_IPV6 */
  390. }
  391. }
  392. #endif /* HAVE_IPV6 */
  393. ret = bind (sock, (struct sockaddr *)su, size);
  394. if (ret < 0)
  395. zlog (NULL, LOG_WARNING, "can't bind socket : %s", safe_strerror (errno));
  396. return ret;
  397. }
  398. int
  399. sockopt_reuseaddr (int sock)
  400. {
  401. int ret;
  402. int on = 1;
  403. ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
  404. (void *) &on, sizeof (on));
  405. if (ret < 0)
  406. {
  407. zlog (NULL, LOG_WARNING, "can't set sockopt SO_REUSEADDR to socket %d", sock);
  408. return -1;
  409. }
  410. return 0;
  411. }
  412. #ifdef SO_REUSEPORT
  413. int
  414. sockopt_reuseport (int sock)
  415. {
  416. int ret;
  417. int on = 1;
  418. ret = setsockopt (sock, SOL_SOCKET, SO_REUSEPORT,
  419. (void *) &on, sizeof (on));
  420. if (ret < 0)
  421. {
  422. zlog (NULL, LOG_WARNING, "can't set sockopt SO_REUSEPORT to socket %d", sock);
  423. return -1;
  424. }
  425. return 0;
  426. }
  427. #else
  428. int
  429. sockopt_reuseport (int sock)
  430. {
  431. return 0;
  432. }
  433. #endif /* 0 */
  434. int
  435. sockopt_ttl (int family, int sock, int ttl)
  436. {
  437. int ret;
  438. #ifdef IP_TTL
  439. if (family == AF_INET)
  440. {
  441. ret = setsockopt (sock, IPPROTO_IP, IP_TTL,
  442. (void *) &ttl, sizeof (int));
  443. if (ret < 0)
  444. {
  445. zlog (NULL, LOG_WARNING, "can't set sockopt IP_TTL %d to socket %d", ttl, sock);
  446. return -1;
  447. }
  448. return 0;
  449. }
  450. #endif /* IP_TTL */
  451. #ifdef HAVE_IPV6
  452. if (family == AF_INET6)
  453. {
  454. ret = setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
  455. (void *) &ttl, sizeof (int));
  456. if (ret < 0)
  457. {
  458. zlog (NULL, LOG_WARNING, "can't set sockopt IPV6_UNICAST_HOPS %d to socket %d",
  459. ttl, sock);
  460. return -1;
  461. }
  462. return 0;
  463. }
  464. #endif /* HAVE_IPV6 */
  465. return 0;
  466. }
  467. /* If same family and same prefix return 1. */
  468. int
  469. sockunion_same (union sockunion *su1, union sockunion *su2)
  470. {
  471. int ret = 0;
  472. if (su1->sa.sa_family != su2->sa.sa_family)
  473. return 0;
  474. switch (su1->sa.sa_family)
  475. {
  476. case AF_INET:
  477. ret = memcmp (&su1->sin.sin_addr, &su2->sin.sin_addr,
  478. sizeof (struct in_addr));
  479. break;
  480. #ifdef HAVE_IPV6
  481. case AF_INET6:
  482. ret = memcmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr,
  483. sizeof (struct in6_addr));
  484. break;
  485. #endif /* HAVE_IPV6 */
  486. }
  487. if (ret == 0)
  488. return 1;
  489. else
  490. return 0;
  491. }
  492. /* After TCP connection is established. Get local address and port. */
  493. union sockunion *
  494. sockunion_getsockname (int fd)
  495. {
  496. int ret;
  497. socklen_t len;
  498. union
  499. {
  500. struct sockaddr sa;
  501. struct sockaddr_in sin;
  502. #ifdef HAVE_IPV6
  503. struct sockaddr_in6 sin6;
  504. #endif /* HAVE_IPV6 */
  505. char tmp_buffer[128];
  506. } name;
  507. union sockunion *su;
  508. memset (&name, 0, sizeof name);
  509. len = sizeof name;
  510. ret = getsockname (fd, (struct sockaddr *)&name, &len);
  511. if (ret < 0)
  512. {
  513. zlog_warn ("Can't get local address and port by getsockname: %s",
  514. safe_strerror (errno));
  515. return NULL;
  516. }
  517. if (name.sa.sa_family == AF_INET)
  518. {
  519. su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  520. memcpy (su, &name, sizeof (struct sockaddr_in));
  521. return su;
  522. }
  523. #ifdef HAVE_IPV6
  524. if (name.sa.sa_family == AF_INET6)
  525. {
  526. su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  527. memcpy (su, &name, sizeof (struct sockaddr_in6));
  528. sockunion_normalise_mapped (su);
  529. return su;
  530. }
  531. #endif /* HAVE_IPV6 */
  532. return NULL;
  533. }
  534. /* After TCP connection is established. Get remote address and port. */
  535. union sockunion *
  536. sockunion_getpeername (int fd)
  537. {
  538. int ret;
  539. socklen_t len;
  540. union
  541. {
  542. struct sockaddr sa;
  543. struct sockaddr_in sin;
  544. #ifdef HAVE_IPV6
  545. struct sockaddr_in6 sin6;
  546. #endif /* HAVE_IPV6 */
  547. char tmp_buffer[128];
  548. } name;
  549. union sockunion *su;
  550. memset (&name, 0, sizeof name);
  551. len = sizeof name;
  552. ret = getpeername (fd, (struct sockaddr *)&name, &len);
  553. if (ret < 0)
  554. {
  555. zlog (NULL, LOG_WARNING, "Can't get remote address and port: %s",
  556. safe_strerror (errno));
  557. return NULL;
  558. }
  559. if (name.sa.sa_family == AF_INET)
  560. {
  561. su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  562. memcpy (su, &name, sizeof (struct sockaddr_in));
  563. return su;
  564. }
  565. #ifdef HAVE_IPV6
  566. if (name.sa.sa_family == AF_INET6)
  567. {
  568. su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  569. memcpy (su, &name, sizeof (struct sockaddr_in6));
  570. sockunion_normalise_mapped (su);
  571. return su;
  572. }
  573. #endif /* HAVE_IPV6 */
  574. return NULL;
  575. }
  576. /* Print sockunion structure */
  577. static void __attribute__ ((unused))
  578. sockunion_print (union sockunion *su)
  579. {
  580. if (su == NULL)
  581. return;
  582. switch (su->sa.sa_family)
  583. {
  584. case AF_INET:
  585. printf ("%s\n", inet_ntoa (su->sin.sin_addr));
  586. break;
  587. #ifdef HAVE_IPV6
  588. case AF_INET6:
  589. {
  590. char buf [SU_ADDRSTRLEN];
  591. printf ("%s\n", inet_ntop (AF_INET6, &(su->sin6.sin6_addr),
  592. buf, sizeof (buf)));
  593. }
  594. break;
  595. #endif /* HAVE_IPV6 */
  596. #ifdef AF_LINK
  597. case AF_LINK:
  598. {
  599. struct sockaddr_dl *sdl;
  600. sdl = (struct sockaddr_dl *)&(su->sa);
  601. printf ("link#%d\n", sdl->sdl_index);
  602. }
  603. break;
  604. #endif /* AF_LINK */
  605. default:
  606. printf ("af_unknown %d\n", su->sa.sa_family);
  607. break;
  608. }
  609. }
  610. #ifdef HAVE_IPV6
  611. static int
  612. in6addr_cmp (struct in6_addr *addr1, struct in6_addr *addr2)
  613. {
  614. unsigned int i;
  615. u_char *p1, *p2;
  616. p1 = (u_char *)addr1;
  617. p2 = (u_char *)addr2;
  618. for (i = 0; i < sizeof (struct in6_addr); i++)
  619. {
  620. if (p1[i] > p2[i])
  621. return 1;
  622. else if (p1[i] < p2[i])
  623. return -1;
  624. }
  625. return 0;
  626. }
  627. #endif /* HAVE_IPV6 */
  628. int
  629. sockunion_cmp (union sockunion *su1, union sockunion *su2)
  630. {
  631. if (su1->sa.sa_family > su2->sa.sa_family)
  632. return 1;
  633. if (su1->sa.sa_family < su2->sa.sa_family)
  634. return -1;
  635. if (su1->sa.sa_family == AF_INET)
  636. {
  637. if (ntohl (su1->sin.sin_addr.s_addr) == ntohl (su2->sin.sin_addr.s_addr))
  638. return 0;
  639. if (ntohl (su1->sin.sin_addr.s_addr) > ntohl (su2->sin.sin_addr.s_addr))
  640. return 1;
  641. else
  642. return -1;
  643. }
  644. #ifdef HAVE_IPV6
  645. if (su1->sa.sa_family == AF_INET6)
  646. return in6addr_cmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr);
  647. #endif /* HAVE_IPV6 */
  648. return 0;
  649. }
  650. /* Duplicate sockunion. */
  651. union sockunion *
  652. sockunion_dup (union sockunion *su)
  653. {
  654. union sockunion *dup = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  655. memcpy (dup, su, sizeof (union sockunion));
  656. return dup;
  657. }
  658. void
  659. sockunion_free (union sockunion *su)
  660. {
  661. XFREE (MTYPE_SOCKUNION, su);
  662. }