sockunion.c 18 KB

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