Annotation of embedaddon/quagga/lib/sockunion.c, revision 1.1
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. */
! 300: static char *
! 301: sockunion_log (union sockunion *su)
! 302: {
! 303: static char buf[SU_ADDRSTRLEN];
! 304:
! 305: switch (su->sa.sa_family)
! 306: {
! 307: case AF_INET:
! 308: snprintf (buf, SU_ADDRSTRLEN, "%s", inet_ntoa (su->sin.sin_addr));
! 309: break;
! 310: #ifdef HAVE_IPV6
! 311: case AF_INET6:
! 312: snprintf (buf, SU_ADDRSTRLEN, "%s",
! 313: inet_ntop (AF_INET6, &(su->sin6.sin6_addr), buf, SU_ADDRSTRLEN));
! 314: break;
! 315: #endif /* HAVE_IPV6 */
! 316: default:
! 317: snprintf (buf, SU_ADDRSTRLEN, "af_unknown %d ", su->sa.sa_family);
! 318: break;
! 319: }
! 320: return (XSTRDUP (MTYPE_TMP, buf));
! 321: }
! 322:
! 323: /* sockunion_connect returns
! 324: -1 : error occured
! 325: 0 : connect success
! 326: 1 : connect is in progress */
! 327: enum connect_result
! 328: sockunion_connect (int fd, union sockunion *peersu, unsigned short port,
! 329: unsigned int ifindex)
! 330: {
! 331: int ret;
! 332: int val;
! 333: union sockunion su;
! 334:
! 335: memcpy (&su, peersu, sizeof (union sockunion));
! 336:
! 337: switch (su.sa.sa_family)
! 338: {
! 339: case AF_INET:
! 340: su.sin.sin_port = port;
! 341: break;
! 342: #ifdef HAVE_IPV6
! 343: case AF_INET6:
! 344: su.sin6.sin6_port = port;
! 345: #ifdef KAME
! 346: if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr) && ifindex)
! 347: {
! 348: #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
! 349: /* su.sin6.sin6_scope_id = ifindex; */
! 350: #ifdef MUSICA
! 351: su.sin6.sin6_scope_id = ifindex;
! 352: #endif
! 353: #endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */
! 354: #ifndef MUSICA
! 355: SET_IN6_LINKLOCAL_IFINDEX (su.sin6.sin6_addr, ifindex);
! 356: #endif
! 357: }
! 358: #endif /* KAME */
! 359: break;
! 360: #endif /* HAVE_IPV6 */
! 361: }
! 362:
! 363: /* Make socket non-block. */
! 364: val = fcntl (fd, F_GETFL, 0);
! 365: fcntl (fd, F_SETFL, val|O_NONBLOCK);
! 366:
! 367: /* Call connect function. */
! 368: ret = connect (fd, (struct sockaddr *) &su, sockunion_sizeof (&su));
! 369:
! 370: /* Immediate success */
! 371: if (ret == 0)
! 372: {
! 373: fcntl (fd, F_SETFL, val);
! 374: return connect_success;
! 375: }
! 376:
! 377: /* If connect is in progress then return 1 else it's real error. */
! 378: if (ret < 0)
! 379: {
! 380: if (errno != EINPROGRESS)
! 381: {
! 382: zlog_info ("can't connect to %s fd %d : %s",
! 383: sockunion_log (&su), fd, safe_strerror (errno));
! 384: return connect_error;
! 385: }
! 386: }
! 387:
! 388: fcntl (fd, F_SETFL, val);
! 389:
! 390: return connect_in_progress;
! 391: }
! 392:
! 393: /* Make socket from sockunion union. */
! 394: int
! 395: sockunion_stream_socket (union sockunion *su)
! 396: {
! 397: int sock;
! 398:
! 399: if (su->sa.sa_family == 0)
! 400: su->sa.sa_family = AF_INET_UNION;
! 401:
! 402: sock = socket (su->sa.sa_family, SOCK_STREAM, 0);
! 403:
! 404: if (sock < 0)
! 405: zlog (NULL, LOG_WARNING, "can't make socket sockunion_stream_socket");
! 406:
! 407: return sock;
! 408: }
! 409:
! 410: /* Bind socket to specified address. */
! 411: int
! 412: sockunion_bind (int sock, union sockunion *su, unsigned short port,
! 413: union sockunion *su_addr)
! 414: {
! 415: int size = 0;
! 416: int ret;
! 417:
! 418: if (su->sa.sa_family == AF_INET)
! 419: {
! 420: size = sizeof (struct sockaddr_in);
! 421: su->sin.sin_port = htons (port);
! 422: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
! 423: su->sin.sin_len = size;
! 424: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
! 425: if (su_addr == NULL)
! 426: su->sin.sin_addr.s_addr = htonl (INADDR_ANY);
! 427: }
! 428: #ifdef HAVE_IPV6
! 429: else if (su->sa.sa_family == AF_INET6)
! 430: {
! 431: size = sizeof (struct sockaddr_in6);
! 432: su->sin6.sin6_port = htons (port);
! 433: #ifdef SIN6_LEN
! 434: su->sin6.sin6_len = size;
! 435: #endif /* SIN6_LEN */
! 436: if (su_addr == NULL)
! 437: {
! 438: #if defined(LINUX_IPV6) || defined(NRL)
! 439: memset (&su->sin6.sin6_addr, 0, sizeof (struct in6_addr));
! 440: #else
! 441: su->sin6.sin6_addr = in6addr_any;
! 442: #endif /* LINUX_IPV6 */
! 443: }
! 444: }
! 445: #endif /* HAVE_IPV6 */
! 446:
! 447:
! 448: ret = bind (sock, (struct sockaddr *)su, size);
! 449: if (ret < 0)
! 450: zlog (NULL, LOG_WARNING, "can't bind socket : %s", safe_strerror (errno));
! 451:
! 452: return ret;
! 453: }
! 454:
! 455: int
! 456: sockopt_reuseaddr (int sock)
! 457: {
! 458: int ret;
! 459: int on = 1;
! 460:
! 461: ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
! 462: (void *) &on, sizeof (on));
! 463: if (ret < 0)
! 464: {
! 465: zlog (NULL, LOG_WARNING, "can't set sockopt SO_REUSEADDR to socket %d", sock);
! 466: return -1;
! 467: }
! 468: return 0;
! 469: }
! 470:
! 471: #ifdef SO_REUSEPORT
! 472: int
! 473: sockopt_reuseport (int sock)
! 474: {
! 475: int ret;
! 476: int on = 1;
! 477:
! 478: ret = setsockopt (sock, SOL_SOCKET, SO_REUSEPORT,
! 479: (void *) &on, sizeof (on));
! 480: if (ret < 0)
! 481: {
! 482: zlog (NULL, LOG_WARNING, "can't set sockopt SO_REUSEPORT to socket %d", sock);
! 483: return -1;
! 484: }
! 485: return 0;
! 486: }
! 487: #else
! 488: int
! 489: sockopt_reuseport (int sock)
! 490: {
! 491: return 0;
! 492: }
! 493: #endif /* 0 */
! 494:
! 495: int
! 496: sockopt_ttl (int family, int sock, int ttl)
! 497: {
! 498: int ret;
! 499:
! 500: #ifdef IP_TTL
! 501: if (family == AF_INET)
! 502: {
! 503: ret = setsockopt (sock, IPPROTO_IP, IP_TTL,
! 504: (void *) &ttl, sizeof (int));
! 505: if (ret < 0)
! 506: {
! 507: zlog (NULL, LOG_WARNING, "can't set sockopt IP_TTL %d to socket %d", ttl, sock);
! 508: return -1;
! 509: }
! 510: return 0;
! 511: }
! 512: #endif /* IP_TTL */
! 513: #ifdef HAVE_IPV6
! 514: if (family == AF_INET6)
! 515: {
! 516: ret = setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
! 517: (void *) &ttl, sizeof (int));
! 518: if (ret < 0)
! 519: {
! 520: zlog (NULL, LOG_WARNING, "can't set sockopt IPV6_UNICAST_HOPS %d to socket %d",
! 521: ttl, sock);
! 522: return -1;
! 523: }
! 524: return 0;
! 525: }
! 526: #endif /* HAVE_IPV6 */
! 527: return 0;
! 528: }
! 529:
! 530: int
! 531: sockopt_cork (int sock, int onoff)
! 532: {
! 533: #ifdef TCP_CORK
! 534: return setsockopt (sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff));
! 535: #else
! 536: return 0;
! 537: #endif
! 538: }
! 539:
! 540: int
! 541: sockopt_minttl (int family, int sock, int minttl)
! 542: {
! 543: #ifdef IP_MINTTL
! 544: if (family == AF_INET)
! 545: {
! 546: int ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl));
! 547: if (ret < 0)
! 548: zlog (NULL, LOG_WARNING,
! 549: "can't set sockopt IP_MINTTL to %d on socket %d: %s",
! 550: minttl, sock, safe_strerror (errno));
! 551: return ret;
! 552: }
! 553: #endif /* IP_MINTTL */
! 554: #ifdef IPV6_MINHOPCNT
! 555: if (family == AF_INET6)
! 556: {
! 557: int ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MINHOPCNT, &minttl, sizeof(minttl));
! 558: if (ret < 0)
! 559: zlog (NULL, LOG_WARNING,
! 560: "can't set sockopt IPV6_MINHOPCNT to %d on socket %d: %s",
! 561: minttl, sock, safe_strerror (errno));
! 562: return ret;
! 563: }
! 564: #endif
! 565:
! 566: errno = EOPNOTSUPP;
! 567: return -1;
! 568: }
! 569:
! 570: /* If same family and same prefix return 1. */
! 571: int
! 572: sockunion_same (union sockunion *su1, union sockunion *su2)
! 573: {
! 574: int ret = 0;
! 575:
! 576: if (su1->sa.sa_family != su2->sa.sa_family)
! 577: return 0;
! 578:
! 579: switch (su1->sa.sa_family)
! 580: {
! 581: case AF_INET:
! 582: ret = memcmp (&su1->sin.sin_addr, &su2->sin.sin_addr,
! 583: sizeof (struct in_addr));
! 584: break;
! 585: #ifdef HAVE_IPV6
! 586: case AF_INET6:
! 587: ret = memcmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr,
! 588: sizeof (struct in6_addr));
! 589: break;
! 590: #endif /* HAVE_IPV6 */
! 591: }
! 592: if (ret == 0)
! 593: return 1;
! 594: else
! 595: return 0;
! 596: }
! 597:
! 598: /* After TCP connection is established. Get local address and port. */
! 599: union sockunion *
! 600: sockunion_getsockname (int fd)
! 601: {
! 602: int ret;
! 603: socklen_t len;
! 604: union
! 605: {
! 606: struct sockaddr sa;
! 607: struct sockaddr_in sin;
! 608: #ifdef HAVE_IPV6
! 609: struct sockaddr_in6 sin6;
! 610: #endif /* HAVE_IPV6 */
! 611: char tmp_buffer[128];
! 612: } name;
! 613: union sockunion *su;
! 614:
! 615: memset (&name, 0, sizeof name);
! 616: len = sizeof name;
! 617:
! 618: ret = getsockname (fd, (struct sockaddr *)&name, &len);
! 619: if (ret < 0)
! 620: {
! 621: zlog_warn ("Can't get local address and port by getsockname: %s",
! 622: safe_strerror (errno));
! 623: return NULL;
! 624: }
! 625:
! 626: if (name.sa.sa_family == AF_INET)
! 627: {
! 628: su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
! 629: memcpy (su, &name, sizeof (struct sockaddr_in));
! 630: return su;
! 631: }
! 632: #ifdef HAVE_IPV6
! 633: if (name.sa.sa_family == AF_INET6)
! 634: {
! 635: su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
! 636: memcpy (su, &name, sizeof (struct sockaddr_in6));
! 637: sockunion_normalise_mapped (su);
! 638: return su;
! 639: }
! 640: #endif /* HAVE_IPV6 */
! 641: return NULL;
! 642: }
! 643:
! 644: /* After TCP connection is established. Get remote address and port. */
! 645: union sockunion *
! 646: sockunion_getpeername (int fd)
! 647: {
! 648: int ret;
! 649: socklen_t len;
! 650: union
! 651: {
! 652: struct sockaddr sa;
! 653: struct sockaddr_in sin;
! 654: #ifdef HAVE_IPV6
! 655: struct sockaddr_in6 sin6;
! 656: #endif /* HAVE_IPV6 */
! 657: char tmp_buffer[128];
! 658: } name;
! 659: union sockunion *su;
! 660:
! 661: memset (&name, 0, sizeof name);
! 662: len = sizeof name;
! 663: ret = getpeername (fd, (struct sockaddr *)&name, &len);
! 664: if (ret < 0)
! 665: {
! 666: zlog (NULL, LOG_WARNING, "Can't get remote address and port: %s",
! 667: safe_strerror (errno));
! 668: return NULL;
! 669: }
! 670:
! 671: if (name.sa.sa_family == AF_INET)
! 672: {
! 673: su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
! 674: memcpy (su, &name, sizeof (struct sockaddr_in));
! 675: return su;
! 676: }
! 677: #ifdef HAVE_IPV6
! 678: if (name.sa.sa_family == AF_INET6)
! 679: {
! 680: su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
! 681: memcpy (su, &name, sizeof (struct sockaddr_in6));
! 682: sockunion_normalise_mapped (su);
! 683: return su;
! 684: }
! 685: #endif /* HAVE_IPV6 */
! 686: return NULL;
! 687: }
! 688:
! 689: /* Print sockunion structure */
! 690: static void __attribute__ ((unused))
! 691: sockunion_print (union sockunion *su)
! 692: {
! 693: if (su == NULL)
! 694: return;
! 695:
! 696: switch (su->sa.sa_family)
! 697: {
! 698: case AF_INET:
! 699: printf ("%s\n", inet_ntoa (su->sin.sin_addr));
! 700: break;
! 701: #ifdef HAVE_IPV6
! 702: case AF_INET6:
! 703: {
! 704: char buf [SU_ADDRSTRLEN];
! 705:
! 706: printf ("%s\n", inet_ntop (AF_INET6, &(su->sin6.sin6_addr),
! 707: buf, sizeof (buf)));
! 708: }
! 709: break;
! 710: #endif /* HAVE_IPV6 */
! 711:
! 712: #ifdef AF_LINK
! 713: case AF_LINK:
! 714: {
! 715: struct sockaddr_dl *sdl;
! 716:
! 717: sdl = (struct sockaddr_dl *)&(su->sa);
! 718: printf ("link#%d\n", sdl->sdl_index);
! 719: }
! 720: break;
! 721: #endif /* AF_LINK */
! 722: default:
! 723: printf ("af_unknown %d\n", su->sa.sa_family);
! 724: break;
! 725: }
! 726: }
! 727:
! 728: #ifdef HAVE_IPV6
! 729: static int
! 730: in6addr_cmp (struct in6_addr *addr1, struct in6_addr *addr2)
! 731: {
! 732: unsigned int i;
! 733: u_char *p1, *p2;
! 734:
! 735: p1 = (u_char *)addr1;
! 736: p2 = (u_char *)addr2;
! 737:
! 738: for (i = 0; i < sizeof (struct in6_addr); i++)
! 739: {
! 740: if (p1[i] > p2[i])
! 741: return 1;
! 742: else if (p1[i] < p2[i])
! 743: return -1;
! 744: }
! 745: return 0;
! 746: }
! 747: #endif /* HAVE_IPV6 */
! 748:
! 749: int
! 750: sockunion_cmp (union sockunion *su1, union sockunion *su2)
! 751: {
! 752: if (su1->sa.sa_family > su2->sa.sa_family)
! 753: return 1;
! 754: if (su1->sa.sa_family < su2->sa.sa_family)
! 755: return -1;
! 756:
! 757: if (su1->sa.sa_family == AF_INET)
! 758: {
! 759: if (ntohl (su1->sin.sin_addr.s_addr) == ntohl (su2->sin.sin_addr.s_addr))
! 760: return 0;
! 761: if (ntohl (su1->sin.sin_addr.s_addr) > ntohl (su2->sin.sin_addr.s_addr))
! 762: return 1;
! 763: else
! 764: return -1;
! 765: }
! 766: #ifdef HAVE_IPV6
! 767: if (su1->sa.sa_family == AF_INET6)
! 768: return in6addr_cmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr);
! 769: #endif /* HAVE_IPV6 */
! 770: return 0;
! 771: }
! 772:
! 773: /* Duplicate sockunion. */
! 774: union sockunion *
! 775: sockunion_dup (union sockunion *su)
! 776: {
! 777: union sockunion *dup = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
! 778: memcpy (dup, su, sizeof (union sockunion));
! 779: return dup;
! 780: }
! 781:
! 782: void
! 783: sockunion_free (union sockunion *su)
! 784: {
! 785: XFREE (MTYPE_SOCKUNION, su);
! 786: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>