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