sockunion.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  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 = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  163. ret = inet_pton (AF_INET, str, &su->sin.sin_addr);
  164. if (ret > 0) /* Valid IPv4 address format. */
  165. {
  166. su->sin.sin_family = AF_INET;
  167. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  168. su->sin.sin_len = sizeof(struct sockaddr_in);
  169. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  170. return su;
  171. }
  172. #ifdef HAVE_IPV6
  173. ret = inet_pton (AF_INET6, str, &su->sin6.sin6_addr);
  174. if (ret > 0) /* Valid IPv6 address format. */
  175. {
  176. su->sin6.sin6_family = AF_INET6;
  177. #ifdef SIN6_LEN
  178. su->sin6.sin6_len = sizeof(struct sockaddr_in6);
  179. #endif /* SIN6_LEN */
  180. return su;
  181. }
  182. #endif /* HAVE_IPV6 */
  183. XFREE (MTYPE_SOCKUNION, su);
  184. return NULL;
  185. }
  186. char *
  187. sockunion_su2str (union sockunion *su)
  188. {
  189. char str[SU_ADDRSTRLEN];
  190. switch (su->sa.sa_family)
  191. {
  192. case AF_INET:
  193. inet_ntop (AF_INET, &su->sin.sin_addr, str, sizeof (str));
  194. break;
  195. #ifdef HAVE_IPV6
  196. case AF_INET6:
  197. inet_ntop (AF_INET6, &su->sin6.sin6_addr, str, sizeof (str));
  198. break;
  199. #endif /* HAVE_IPV6 */
  200. }
  201. return XSTRDUP (MTYPE_TMP, str);
  202. }
  203. /* Convert IPv4 compatible IPv6 address to IPv4 address. */
  204. static void
  205. sockunion_normalise_mapped (union sockunion *su)
  206. {
  207. struct sockaddr_in sin;
  208. #ifdef HAVE_IPV6
  209. if (su->sa.sa_family == AF_INET6
  210. && IN6_IS_ADDR_V4MAPPED (&su->sin6.sin6_addr))
  211. {
  212. memset (&sin, 0, sizeof (struct sockaddr_in));
  213. sin.sin_family = AF_INET;
  214. sin.sin_port = su->sin6.sin6_port;
  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. int
  468. sockopt_cork (int sock, int onoff)
  469. {
  470. #ifdef TCP_CORK
  471. return setsockopt (sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff));
  472. #else
  473. return 0;
  474. #endif
  475. }
  476. int
  477. sockopt_minttl (int family, int sock, int minttl)
  478. {
  479. #ifdef IP_MINTTL
  480. if (family == AF_INET)
  481. {
  482. int ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl));
  483. if (ret < 0)
  484. zlog (NULL, LOG_WARNING,
  485. "can't set sockopt IP_MINTTL to %d on socket %d: %s",
  486. minttl, sock, safe_strerror (errno));
  487. return ret;
  488. }
  489. #endif /* IP_MINTTL */
  490. #ifdef IPV6_MINHOPCNT
  491. if (family == AF_INET6)
  492. {
  493. int ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MINHOPCNT, &minttl, sizeof(minttl));
  494. if (ret < 0)
  495. zlog (NULL, LOG_WARNING,
  496. "can't set sockopt IPV6_MINHOPCNT to %d on socket %d: %s",
  497. minttl, sock, safe_strerror (errno));
  498. return ret;
  499. }
  500. #endif
  501. errno = EOPNOTSUPP;
  502. return -1;
  503. }
  504. /* If same family and same prefix return 1. */
  505. int
  506. sockunion_same (union sockunion *su1, union sockunion *su2)
  507. {
  508. int ret = 0;
  509. if (su1->sa.sa_family != su2->sa.sa_family)
  510. return 0;
  511. switch (su1->sa.sa_family)
  512. {
  513. case AF_INET:
  514. ret = memcmp (&su1->sin.sin_addr, &su2->sin.sin_addr,
  515. sizeof (struct in_addr));
  516. break;
  517. #ifdef HAVE_IPV6
  518. case AF_INET6:
  519. ret = memcmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr,
  520. sizeof (struct in6_addr));
  521. break;
  522. #endif /* HAVE_IPV6 */
  523. }
  524. if (ret == 0)
  525. return 1;
  526. else
  527. return 0;
  528. }
  529. /* After TCP connection is established. Get local address and port. */
  530. union sockunion *
  531. sockunion_getsockname (int fd)
  532. {
  533. int ret;
  534. socklen_t len;
  535. union
  536. {
  537. struct sockaddr sa;
  538. struct sockaddr_in sin;
  539. #ifdef HAVE_IPV6
  540. struct sockaddr_in6 sin6;
  541. #endif /* HAVE_IPV6 */
  542. char tmp_buffer[128];
  543. } name;
  544. union sockunion *su;
  545. memset (&name, 0, sizeof name);
  546. len = sizeof name;
  547. ret = getsockname (fd, (struct sockaddr *)&name, &len);
  548. if (ret < 0)
  549. {
  550. zlog_warn ("Can't get local address and port by getsockname: %s",
  551. safe_strerror (errno));
  552. return NULL;
  553. }
  554. if (name.sa.sa_family == AF_INET)
  555. {
  556. su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  557. memcpy (su, &name, sizeof (struct sockaddr_in));
  558. return su;
  559. }
  560. #ifdef HAVE_IPV6
  561. if (name.sa.sa_family == AF_INET6)
  562. {
  563. su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  564. memcpy (su, &name, sizeof (struct sockaddr_in6));
  565. sockunion_normalise_mapped (su);
  566. return su;
  567. }
  568. #endif /* HAVE_IPV6 */
  569. return NULL;
  570. }
  571. /* After TCP connection is established. Get remote address and port. */
  572. union sockunion *
  573. sockunion_getpeername (int fd)
  574. {
  575. int ret;
  576. socklen_t len;
  577. union
  578. {
  579. struct sockaddr sa;
  580. struct sockaddr_in sin;
  581. #ifdef HAVE_IPV6
  582. struct sockaddr_in6 sin6;
  583. #endif /* HAVE_IPV6 */
  584. char tmp_buffer[128];
  585. } name;
  586. union sockunion *su;
  587. memset (&name, 0, sizeof name);
  588. len = sizeof name;
  589. ret = getpeername (fd, (struct sockaddr *)&name, &len);
  590. if (ret < 0)
  591. {
  592. zlog (NULL, LOG_WARNING, "Can't get remote address and port: %s",
  593. safe_strerror (errno));
  594. return NULL;
  595. }
  596. if (name.sa.sa_family == AF_INET)
  597. {
  598. su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  599. memcpy (su, &name, sizeof (struct sockaddr_in));
  600. return su;
  601. }
  602. #ifdef HAVE_IPV6
  603. if (name.sa.sa_family == AF_INET6)
  604. {
  605. su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  606. memcpy (su, &name, sizeof (struct sockaddr_in6));
  607. sockunion_normalise_mapped (su);
  608. return su;
  609. }
  610. #endif /* HAVE_IPV6 */
  611. return NULL;
  612. }
  613. /* Print sockunion structure */
  614. static void __attribute__ ((unused))
  615. sockunion_print (union sockunion *su)
  616. {
  617. if (su == NULL)
  618. return;
  619. switch (su->sa.sa_family)
  620. {
  621. case AF_INET:
  622. printf ("%s\n", inet_ntoa (su->sin.sin_addr));
  623. break;
  624. #ifdef HAVE_IPV6
  625. case AF_INET6:
  626. {
  627. char buf [SU_ADDRSTRLEN];
  628. printf ("%s\n", inet_ntop (AF_INET6, &(su->sin6.sin6_addr),
  629. buf, sizeof (buf)));
  630. }
  631. break;
  632. #endif /* HAVE_IPV6 */
  633. #ifdef AF_LINK
  634. case AF_LINK:
  635. {
  636. struct sockaddr_dl *sdl;
  637. sdl = (struct sockaddr_dl *)&(su->sa);
  638. printf ("link#%d\n", sdl->sdl_index);
  639. }
  640. break;
  641. #endif /* AF_LINK */
  642. default:
  643. printf ("af_unknown %d\n", su->sa.sa_family);
  644. break;
  645. }
  646. }
  647. #ifdef HAVE_IPV6
  648. static int
  649. in6addr_cmp (struct in6_addr *addr1, struct in6_addr *addr2)
  650. {
  651. unsigned int i;
  652. u_char *p1, *p2;
  653. p1 = (u_char *)addr1;
  654. p2 = (u_char *)addr2;
  655. for (i = 0; i < sizeof (struct in6_addr); i++)
  656. {
  657. if (p1[i] > p2[i])
  658. return 1;
  659. else if (p1[i] < p2[i])
  660. return -1;
  661. }
  662. return 0;
  663. }
  664. #endif /* HAVE_IPV6 */
  665. int
  666. sockunion_cmp (union sockunion *su1, union sockunion *su2)
  667. {
  668. if (su1->sa.sa_family > su2->sa.sa_family)
  669. return 1;
  670. if (su1->sa.sa_family < su2->sa.sa_family)
  671. return -1;
  672. if (su1->sa.sa_family == AF_INET)
  673. {
  674. if (ntohl (su1->sin.sin_addr.s_addr) == ntohl (su2->sin.sin_addr.s_addr))
  675. return 0;
  676. if (ntohl (su1->sin.sin_addr.s_addr) > ntohl (su2->sin.sin_addr.s_addr))
  677. return 1;
  678. else
  679. return -1;
  680. }
  681. #ifdef HAVE_IPV6
  682. if (su1->sa.sa_family == AF_INET6)
  683. return in6addr_cmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr);
  684. #endif /* HAVE_IPV6 */
  685. return 0;
  686. }
  687. /* Duplicate sockunion. */
  688. union sockunion *
  689. sockunion_dup (union sockunion *su)
  690. {
  691. union sockunion *dup = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  692. memcpy (dup, su, sizeof (union sockunion));
  693. return dup;
  694. }
  695. void
  696. sockunion_free (union sockunion *su)
  697. {
  698. XFREE (MTYPE_SOCKUNION, su);
  699. }