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