Annotation of embedaddon/strongswan/src/libstrongswan/networking/host.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2006-2014 Tobias Brunner
! 3: * Copyright (C) 2006 Daniel Roethlisberger
! 4: * Copyright (C) 2005-2006 Martin Willi
! 5: * Copyright (C) 2005 Jan Hutter
! 6: * HSR Hochschule fuer Technik Rapperswil
! 7: *
! 8: * This program is free software; you can redistribute it and/or modify it
! 9: * under the terms of the GNU General Public License as published by the
! 10: * Free Software Foundation; either version 2 of the License, or (at your
! 11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 12: *
! 13: * This program is distributed in the hope that it will be useful, but
! 14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 16: * for more details.
! 17: */
! 18:
! 19: #include "host.h"
! 20:
! 21: #include <utils/debug.h>
! 22: #include <library.h>
! 23:
! 24: #define IPV4_LEN 4
! 25: #define IPV6_LEN 16
! 26:
! 27: typedef struct private_host_t private_host_t;
! 28:
! 29: /**
! 30: * Private Data of a host object.
! 31: */
! 32: struct private_host_t {
! 33: /**
! 34: * Public data
! 35: */
! 36: host_t public;
! 37:
! 38: /**
! 39: * low-lewel structure, which stores the address
! 40: */
! 41: union {
! 42: /** generic type */
! 43: struct sockaddr address;
! 44: /** maximum sockaddr size */
! 45: struct sockaddr_storage address_max;
! 46: /** IPv4 address */
! 47: struct sockaddr_in address4;
! 48: /** IPv6 address */
! 49: struct sockaddr_in6 address6;
! 50: };
! 51: /**
! 52: * length of address structure
! 53: */
! 54: socklen_t socklen;
! 55: };
! 56:
! 57: /**
! 58: * Update the sockaddr internal sa_len option, if available
! 59: */
! 60: static inline void update_sa_len(private_host_t *this)
! 61: {
! 62: #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
! 63: this->address.sa_len = this->socklen;
! 64: #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
! 65: }
! 66:
! 67: METHOD(host_t, get_sockaddr, sockaddr_t*,
! 68: private_host_t *this)
! 69: {
! 70: return &(this->address);
! 71: }
! 72:
! 73: METHOD(host_t, get_sockaddr_len, socklen_t*,
! 74: private_host_t *this)
! 75: {
! 76: return &(this->socklen);
! 77: }
! 78:
! 79: METHOD(host_t, is_anyaddr, bool,
! 80: private_host_t *this)
! 81: {
! 82: static const uint8_t zeroes[IPV6_LEN];
! 83:
! 84: switch (this->address.sa_family)
! 85: {
! 86: case AF_INET:
! 87: {
! 88: return memeq(zeroes, &(this->address4.sin_addr.s_addr), IPV4_LEN);
! 89: }
! 90: case AF_INET6:
! 91: {
! 92: return memeq(zeroes, &(this->address6.sin6_addr.s6_addr), IPV6_LEN);
! 93: }
! 94: default:
! 95: {
! 96: return FALSE;
! 97: }
! 98: }
! 99: }
! 100:
! 101: /**
! 102: * Described in header.
! 103: */
! 104: int host_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
! 105: const void *const *args)
! 106: {
! 107: private_host_t *this = *((private_host_t**)(args[0]));
! 108: char buffer[INET6_ADDRSTRLEN + 16];
! 109:
! 110: if (this == NULL)
! 111: {
! 112: snprintf(buffer, sizeof(buffer), "(null)");
! 113: }
! 114: else if (is_anyaddr(this) && !spec->plus && !spec->hash)
! 115: {
! 116: snprintf(buffer, sizeof(buffer), "%%any%s",
! 117: this->address.sa_family == AF_INET6 ? "6" : "");
! 118: }
! 119: else
! 120: {
! 121: void *address;
! 122: uint16_t port;
! 123: int len;
! 124:
! 125: address = &this->address6.sin6_addr;
! 126: port = this->address6.sin6_port;
! 127:
! 128: switch (this->address.sa_family)
! 129: {
! 130: case AF_INET:
! 131: address = &this->address4.sin_addr;
! 132: port = this->address4.sin_port;
! 133: /* fall */
! 134: case AF_INET6:
! 135:
! 136: if (inet_ntop(this->address.sa_family, address,
! 137: buffer, sizeof(buffer)) == NULL)
! 138: {
! 139: snprintf(buffer, sizeof(buffer),
! 140: "(address conversion failed)");
! 141: }
! 142: else if (spec->hash && port)
! 143: {
! 144: len = strlen(buffer);
! 145: snprintf(buffer + len, sizeof(buffer) - len,
! 146: "[%d]", ntohs(port));
! 147: }
! 148: break;
! 149: default:
! 150: snprintf(buffer, sizeof(buffer), "(family not supported)");
! 151: break;
! 152: }
! 153: }
! 154: if (spec->minus)
! 155: {
! 156: return print_in_hook(data, "%-*s", spec->width, buffer);
! 157: }
! 158: return print_in_hook(data, "%*s", spec->width, buffer);
! 159: }
! 160:
! 161: METHOD(host_t, get_address, chunk_t,
! 162: private_host_t *this)
! 163: {
! 164: chunk_t address = chunk_empty;
! 165:
! 166: switch (this->address.sa_family)
! 167: {
! 168: case AF_INET:
! 169: {
! 170: address.ptr = (char*)&(this->address4.sin_addr.s_addr);
! 171: address.len = IPV4_LEN;
! 172: return address;
! 173: }
! 174: case AF_INET6:
! 175: {
! 176: address.ptr = (char*)&(this->address6.sin6_addr.s6_addr);
! 177: address.len = IPV6_LEN;
! 178: return address;
! 179: }
! 180: default:
! 181: {
! 182: /* return empty chunk */
! 183: return address;
! 184: }
! 185: }
! 186: }
! 187:
! 188: METHOD(host_t, get_family, int,
! 189: private_host_t *this)
! 190: {
! 191: return this->address.sa_family;
! 192: }
! 193:
! 194: METHOD(host_t, get_port, uint16_t,
! 195: private_host_t *this)
! 196: {
! 197: switch (this->address.sa_family)
! 198: {
! 199: case AF_INET:
! 200: {
! 201: return ntohs(this->address4.sin_port);
! 202: }
! 203: case AF_INET6:
! 204: {
! 205: return ntohs(this->address6.sin6_port);
! 206: }
! 207: default:
! 208: {
! 209: return 0;
! 210: }
! 211: }
! 212: }
! 213:
! 214: METHOD(host_t, set_port, void,
! 215: private_host_t *this, uint16_t port)
! 216: {
! 217: switch (this->address.sa_family)
! 218: {
! 219: case AF_INET:
! 220: {
! 221: this->address4.sin_port = htons(port);
! 222: break;
! 223: }
! 224: case AF_INET6:
! 225: {
! 226: this->address6.sin6_port = htons(port);
! 227: break;
! 228: }
! 229: default:
! 230: {
! 231: break;
! 232: }
! 233: }
! 234: }
! 235:
! 236: METHOD(host_t, clone_, host_t*,
! 237: private_host_t *this)
! 238: {
! 239: private_host_t *new;
! 240:
! 241: new = malloc_thing(private_host_t);
! 242: memcpy(new, this, sizeof(private_host_t));
! 243:
! 244: return &new->public;
! 245: }
! 246:
! 247: /**
! 248: * Implements host_t.ip_equals
! 249: */
! 250: static bool ip_equals(private_host_t *this, private_host_t *other)
! 251: {
! 252: if (this->address.sa_family != other->address.sa_family)
! 253: {
! 254: /* 0.0.0.0 and 0::0 are equal */
! 255: return (is_anyaddr(this) && is_anyaddr(other));
! 256: }
! 257:
! 258: switch (this->address.sa_family)
! 259: {
! 260: case AF_INET:
! 261: {
! 262: return memeq(&this->address4.sin_addr, &other->address4.sin_addr,
! 263: sizeof(this->address4.sin_addr));
! 264: }
! 265: case AF_INET6:
! 266: {
! 267: return memeq(&this->address6.sin6_addr, &other->address6.sin6_addr,
! 268: sizeof(this->address6.sin6_addr));
! 269: }
! 270: default:
! 271: break;
! 272: }
! 273: return FALSE;
! 274: }
! 275:
! 276: /**
! 277: * Implements host_t.equals
! 278: */
! 279: static bool equals(private_host_t *this, private_host_t *other)
! 280: {
! 281: if (!ip_equals(this, other))
! 282: {
! 283: return FALSE;
! 284: }
! 285:
! 286: switch (this->address.sa_family)
! 287: {
! 288: case AF_INET:
! 289: {
! 290: return (this->address4.sin_port == other->address4.sin_port);
! 291: }
! 292: case AF_INET6:
! 293: {
! 294: return (this->address6.sin6_port == other->address6.sin6_port);
! 295: }
! 296: default:
! 297: break;
! 298: }
! 299: return FALSE;
! 300: }
! 301:
! 302: METHOD(host_t, destroy, void,
! 303: private_host_t *this)
! 304: {
! 305: free(this);
! 306: }
! 307:
! 308: /**
! 309: * Creates an empty host_t object
! 310: */
! 311: static private_host_t *host_create_empty(void)
! 312: {
! 313: private_host_t *this;
! 314:
! 315: INIT(this,
! 316: .public = {
! 317: .get_sockaddr = _get_sockaddr,
! 318: .get_sockaddr_len = _get_sockaddr_len,
! 319: .clone = _clone_,
! 320: .get_family = _get_family,
! 321: .get_address = _get_address,
! 322: .get_port = _get_port,
! 323: .set_port = _set_port,
! 324: .ip_equals = (bool (*)(host_t *,host_t *))ip_equals,
! 325: .equals = (bool (*)(host_t *,host_t *)) equals,
! 326: .is_anyaddr = _is_anyaddr,
! 327: .destroy = _destroy,
! 328: },
! 329: );
! 330:
! 331: return this;
! 332: }
! 333:
! 334: /*
! 335: * Create a %any host with port
! 336: */
! 337: static host_t *host_create_any_port(int family, uint16_t port)
! 338: {
! 339: host_t *this;
! 340:
! 341: this = host_create_any(family);
! 342: this->set_port(this, port);
! 343: return this;
! 344: }
! 345:
! 346: /*
! 347: * Described in header.
! 348: */
! 349: host_t *host_create_from_string_and_family(char *string, int family,
! 350: uint16_t port)
! 351: {
! 352: union {
! 353: struct sockaddr_in v4;
! 354: struct sockaddr_in6 v6;
! 355: } addr;
! 356:
! 357: if (!string)
! 358: {
! 359: return NULL;
! 360: }
! 361: if (streq(string, "%any"))
! 362: {
! 363: return host_create_any_port(family ? family : AF_INET, port);
! 364: }
! 365: if (family == AF_UNSPEC || family == AF_INET)
! 366: {
! 367: if (streq(string, "%any4") || streq(string, "0.0.0.0"))
! 368: {
! 369: return host_create_any_port(AF_INET, port);
! 370: }
! 371: }
! 372: if (family == AF_UNSPEC || family == AF_INET6)
! 373: {
! 374: if (streq(string, "%any6") || streq(string, "::"))
! 375: {
! 376: return host_create_any_port(AF_INET6, port);
! 377: }
! 378: }
! 379: switch (family)
! 380: {
! 381: case AF_UNSPEC:
! 382: if (strchr(string, '.'))
! 383: {
! 384: goto af_inet;
! 385: }
! 386: /* FALL */
! 387: case AF_INET6:
! 388: memset(&addr.v6, 0, sizeof(addr.v6));
! 389: if (inet_pton(AF_INET6, string, &addr.v6.sin6_addr) != 1)
! 390: {
! 391: return NULL;
! 392: }
! 393: addr.v6.sin6_port = htons(port);
! 394: addr.v6.sin6_family = AF_INET6;
! 395: return host_create_from_sockaddr((sockaddr_t*)&addr);
! 396: case AF_INET:
! 397: if (strchr(string, ':'))
! 398: { /* do not try to convert v6 addresses for v4 family */
! 399: return NULL;
! 400: }
! 401: af_inet:
! 402: memset(&addr.v4, 0, sizeof(addr.v4));
! 403: if (inet_pton(AF_INET, string, &addr.v4.sin_addr) != 1)
! 404: {
! 405: return NULL;
! 406: }
! 407: addr.v4.sin_port = htons(port);
! 408: addr.v4.sin_family = AF_INET;
! 409: return host_create_from_sockaddr((sockaddr_t*)&addr);
! 410: default:
! 411: return NULL;
! 412: }
! 413: }
! 414:
! 415: /*
! 416: * Described in header.
! 417: */
! 418: host_t *host_create_from_string(char *string, uint16_t port)
! 419: {
! 420: return host_create_from_string_and_family(string, AF_UNSPEC, port);
! 421: }
! 422:
! 423: /*
! 424: * Described in header.
! 425: */
! 426: host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
! 427: {
! 428: private_host_t *this = host_create_empty();
! 429:
! 430: switch (sockaddr->sa_family)
! 431: {
! 432: case AF_INET:
! 433: {
! 434: memcpy(&this->address4, (struct sockaddr_in*)sockaddr,
! 435: sizeof(struct sockaddr_in));
! 436: this->socklen = sizeof(struct sockaddr_in);
! 437: update_sa_len(this);
! 438: return &this->public;
! 439: }
! 440: case AF_INET6:
! 441: {
! 442: memcpy(&this->address6, (struct sockaddr_in6*)sockaddr,
! 443: sizeof(struct sockaddr_in6));
! 444: this->socklen = sizeof(struct sockaddr_in6);
! 445: update_sa_len(this);
! 446: return &this->public;
! 447: }
! 448: default:
! 449: break;
! 450: }
! 451: free(this);
! 452: return NULL;
! 453: }
! 454:
! 455: /*
! 456: * Described in header.
! 457: */
! 458: host_t *host_create_from_dns(char *string, int af, uint16_t port)
! 459: {
! 460: host_t *this;
! 461:
! 462: this = host_create_from_string_and_family(string, af, port);
! 463: if (!this)
! 464: {
! 465: this = lib->hosts->resolve(lib->hosts, string, af);
! 466: }
! 467: if (this)
! 468: {
! 469: this->set_port(this, port);
! 470: }
! 471: return this;
! 472: }
! 473:
! 474: /*
! 475: * Described in header.
! 476: */
! 477: host_t *host_create_from_chunk(int family, chunk_t address, uint16_t port)
! 478: {
! 479: private_host_t *this;
! 480:
! 481: switch (family)
! 482: {
! 483: case AF_INET:
! 484: if (address.len < IPV4_LEN)
! 485: {
! 486: return NULL;
! 487: }
! 488: address.len = IPV4_LEN;
! 489: break;
! 490: case AF_INET6:
! 491: if (address.len < IPV6_LEN)
! 492: {
! 493: return NULL;
! 494: }
! 495: address.len = IPV6_LEN;
! 496: break;
! 497: case AF_UNSPEC:
! 498: switch (address.len)
! 499: {
! 500: case IPV4_LEN:
! 501: family = AF_INET;
! 502: break;
! 503: case IPV6_LEN:
! 504: family = AF_INET6;
! 505: break;
! 506: default:
! 507: return NULL;
! 508: }
! 509: break;
! 510: default:
! 511: return NULL;
! 512: }
! 513: this = host_create_empty();
! 514: this->address.sa_family = family;
! 515: switch (family)
! 516: {
! 517: case AF_INET:
! 518: memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len);
! 519: this->address4.sin_port = htons(port);
! 520: this->socklen = sizeof(struct sockaddr_in);
! 521: break;
! 522: case AF_INET6:
! 523: memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len);
! 524: this->address6.sin6_port = htons(port);
! 525: this->socklen = sizeof(struct sockaddr_in6);
! 526: break;
! 527: }
! 528: update_sa_len(this);
! 529: return &this->public;
! 530: }
! 531:
! 532: /*
! 533: * Described in header.
! 534: */
! 535: bool host_create_from_range(char *string, host_t **from, host_t **to)
! 536: {
! 537: char *sep, *pos;
! 538:
! 539: sep = strchr(string, '-');
! 540: if (!sep)
! 541: {
! 542: return FALSE;
! 543: }
! 544: for (pos = sep+1; *pos && *pos == ' '; pos++)
! 545: {
! 546: /* trim spaces before to address*/
! 547: }
! 548: *to = host_create_from_string(pos, 0);
! 549: if (!*to)
! 550: {
! 551: return FALSE;
! 552: }
! 553: for (pos = sep-1; pos > string && *pos == ' '; pos--)
! 554: {
! 555: /* trim spaces behind from address */
! 556: }
! 557: pos = strndup(string, pos - string + 1);
! 558: *from = host_create_from_string_and_family(pos, (*to)->get_family(*to), 0);
! 559: free(pos);
! 560: if (!*from)
! 561: {
! 562: (*to)->destroy(*to);
! 563: return FALSE;
! 564: }
! 565: return TRUE;
! 566: }
! 567:
! 568: /*
! 569: * Described in header.
! 570: */
! 571: host_t *host_create_from_subnet(char *string, int *bits)
! 572: {
! 573: char *pos, buf[64];
! 574: host_t *net;
! 575:
! 576: pos = strchr(string, '/');
! 577: if (pos)
! 578: {
! 579: if (pos - string >= sizeof(buf))
! 580: {
! 581: return NULL;
! 582: }
! 583: strncpy(buf, string, pos - string);
! 584: buf[pos - string] = '\0';
! 585: *bits = atoi(pos + 1);
! 586: return host_create_from_string(buf, 0);
! 587: }
! 588: net = host_create_from_string(string, 0);
! 589: if (net)
! 590: {
! 591: if (net->get_family(net) == AF_INET)
! 592: {
! 593: *bits = 32;
! 594: }
! 595: else
! 596: {
! 597: *bits = 128;
! 598: }
! 599: }
! 600: return net;
! 601: }
! 602:
! 603: /*
! 604: * See header.
! 605: */
! 606: host_t *host_create_netmask(int family, int netbits)
! 607: {
! 608: private_host_t *this;
! 609: int bits, bytes, len = 0;
! 610: char *target;
! 611:
! 612: switch (family)
! 613: {
! 614: case AF_INET:
! 615: if (netbits < 0 || netbits > 32)
! 616: {
! 617: return NULL;
! 618: }
! 619: this = host_create_empty();
! 620: this->socklen = sizeof(struct sockaddr_in);
! 621: target = (char*)&this->address4.sin_addr;
! 622: len = 4;
! 623: break;
! 624: case AF_INET6:
! 625: if (netbits < 0 || netbits > 128)
! 626: {
! 627: return NULL;
! 628: }
! 629: this = host_create_empty();
! 630: this->socklen = sizeof(struct sockaddr_in6);
! 631: target = (char*)&this->address6.sin6_addr;
! 632: len = 16;
! 633: break;
! 634: default:
! 635: return NULL;
! 636: }
! 637:
! 638: memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
! 639: this->address.sa_family = family;
! 640: update_sa_len(this);
! 641:
! 642: bytes = netbits / 8;
! 643: bits = 8 - (netbits & 0x07);
! 644:
! 645: memset(target, 0xff, bytes);
! 646: if (bytes < len)
! 647: {
! 648: memset(target + bytes, 0x00, len - bytes);
! 649: target[bytes] = (uint8_t)(0xff << bits);
! 650: }
! 651: return &this->public;
! 652: }
! 653:
! 654: /*
! 655: * Described in header.
! 656: */
! 657: host_t *host_create_any(int family)
! 658: {
! 659: private_host_t *this = host_create_empty();
! 660:
! 661: memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
! 662: this->address.sa_family = family;
! 663:
! 664: switch (family)
! 665: {
! 666: case AF_INET:
! 667: {
! 668: this->socklen = sizeof(struct sockaddr_in);
! 669: update_sa_len(this);
! 670: return &(this->public);
! 671: }
! 672: case AF_INET6:
! 673: {
! 674: this->socklen = sizeof(struct sockaddr_in6);
! 675: update_sa_len(this);
! 676: return &this->public;
! 677: }
! 678: default:
! 679: break;
! 680: }
! 681: free(this);
! 682: return NULL;
! 683: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>