diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2007-04-12 20:41:31 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2007-04-12 20:41:31 +0000 |
commit | 774a362e87feab25f1be16fbca08269ddc7121a4 (patch) | |
tree | cf71f4e7466468ac3edc2127125f333224a9acfb /src/libstrongswan/utils/host.c | |
parent | c54a140a445bfe7aa66721f68bb0781f26add91c (diff) | |
download | vyos-strongswan-774a362e87feab25f1be16fbca08269ddc7121a4.tar.gz vyos-strongswan-774a362e87feab25f1be16fbca08269ddc7121a4.zip |
Major new upstream release, just ran svn-upgrade for now (and wrote some
debian/changelong entries).
Diffstat (limited to 'src/libstrongswan/utils/host.c')
-rw-r--r-- | src/libstrongswan/utils/host.c | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c new file mode 100644 index 000000000..8cbfd6ab8 --- /dev/null +++ b/src/libstrongswan/utils/host.c @@ -0,0 +1,526 @@ +/** + * @file host.c + * + * @brief Implementation of host_t. + * + */ + +/* + * Copyright (C) 2006-2007 Tobias Brunner + * Copyright (C) 2006 Daniel Roethlisberger + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <string.h> +#include <printf.h> + +#include "host.h" + + +typedef struct private_host_t private_host_t; + +/** + * @brief Private Data of a host object. + */ +struct private_host_t { + /** + * Public data + */ + host_t public; + + /** + * low-lewel structure, wich stores the address + */ + union { + /** generic type */ + struct sockaddr address; + /** maximum sockaddr size */ + struct sockaddr_storage address_max; + /** IPv4 address */ + struct sockaddr_in address4; + /** IPv6 address */ + struct sockaddr_in6 address6; + }; + /** + * length of address structure + */ + socklen_t socklen; +}; + + +/** + * implements host_t.get_sockaddr + */ +static sockaddr_t *get_sockaddr(private_host_t *this) +{ + return &(this->address); +} + +/** + * implements host_t.get_sockaddr_len + */ +static socklen_t *get_sockaddr_len(private_host_t *this) +{ + return &(this->socklen); +} + +/** + * Implementation of host_t.is_anyaddr. + */ +static bool is_anyaddr(private_host_t *this) +{ + switch (this->address.sa_family) + { + case AF_INET: + { + u_int8_t default_route[4]; + memset(default_route, 0, sizeof(default_route)); + return memeq(default_route, &(this->address4.sin_addr.s_addr), + sizeof(default_route)); + } + case AF_INET6: + { + u_int8_t default_route[16]; + memset(default_route, 0, sizeof(default_route)); + return memeq(default_route, &(this->address6.sin6_addr.s6_addr), + sizeof(default_route)); + } + default: + { + return FALSE; + } + } +} + +/** + * output handler in printf() + */ +static int print(FILE *stream, const struct printf_info *info, + const void *const *args) +{ + private_host_t *this = *((private_host_t**)(args[0])); + char buffer[INET6_ADDRSTRLEN]; + void *address; + u_int16_t port; + + if (this == NULL) + { + return fprintf(stream, "(null)"); + } + + if (is_anyaddr(this)) + { + return fprintf(stream, "%%any"); + } + + switch (this->address.sa_family) + { + case AF_INET: + address = &this->address4.sin_addr; + port = this->address4.sin_port; + break; + case AF_INET6: + address = &this->address6.sin6_addr; + port = this->address6.sin6_port; + break; + default: + return fprintf(stream, "(family not supported)"); + } + + if (inet_ntop(this->address.sa_family, address, + buffer, sizeof(buffer)) == NULL) + { + return fprintf(stream, "(address conversion failed)"); + } + + if (info->alt) + { + return fprintf(stream, "%s[%d]", buffer, ntohs(port)); + } + else + { + return fprintf(stream, "%s", buffer); + } +} + +/** + * register printf() handlers + */ +static void __attribute__ ((constructor))print_register() +{ + register_printf_function(PRINTF_HOST, print, arginfo_ptr); +} + +/** + * Implementation of host_t.get_address. + */ +static chunk_t get_address(private_host_t *this) +{ + chunk_t address = chunk_empty; + + switch (this->address.sa_family) + { + case AF_INET: + { + address.ptr = (char*)&(this->address4.sin_addr.s_addr); + address.len = 4; + return address; + } + case AF_INET6: + { + address.ptr = (char*)&(this->address6.sin6_addr.s6_addr); + address.len = 16; + return address; + } + default: + { + /* return empty chunk */ + return address; + } + } +} + +/** + * implements host_t.get_family + */ +static int get_family(private_host_t *this) +{ + return this->address.sa_family; +} + +/** + * implements host_t.get_port + */ +static u_int16_t get_port(private_host_t *this) +{ + switch (this->address.sa_family) + { + case AF_INET: + { + return ntohs(this->address4.sin_port); + } + case AF_INET6: + { + return ntohs(this->address6.sin6_port); + } + default: + { + return 0; + } + } +} + +/** + * implements host_t.set_port + */ +static void set_port(private_host_t *this, u_int16_t port) +{ + switch (this->address.sa_family) + { + case AF_INET: + { + this->address4.sin_port = htons(port); + break; + } + case AF_INET6: + { + this->address6.sin6_port = htons(port); + break; + } + default: + { + break; + } + } +} + +/** + * Implements host_t.clone. + */ +static private_host_t *clone_(private_host_t *this) +{ + private_host_t *new = malloc_thing(private_host_t); + + memcpy(new, this, sizeof(private_host_t)); + return new; +} + +/** + * Impelements host_t.ip_equals + */ +static bool ip_equals(private_host_t *this, private_host_t *other) +{ + if (this->address.sa_family != other->address.sa_family) + { + /* 0.0.0.0 and ::0 are equal */ + if (is_anyaddr(this) && is_anyaddr(other)) + { + return TRUE; + } + + return FALSE; + } + + switch (this->address.sa_family) + { + case AF_INET: + { + if (memeq(&this->address4.sin_addr, &other->address4.sin_addr, + sizeof(this->address4.sin_addr))) + { + return TRUE; + } + break; + } + case AF_INET6: + { + if (memeq(&this->address6.sin6_addr, &other->address6.sin6_addr, + sizeof(this->address6.sin6_addr))) + { + return TRUE; + } + } + default: + break; + } + return FALSE; +} + +/** + * Implements host_t.get_differences + */ +static host_diff_t get_differences(host_t *this, host_t *other) +{ + host_diff_t ret = HOST_DIFF_NONE; + + if (!this->ip_equals(this, other)) + { + ret |= HOST_DIFF_ADDR; + } + + if (this->get_port(this) != other->get_port(other)) + { + ret |= HOST_DIFF_PORT; + } + + return ret; +} + +/** + * Impelements host_t.equals + */ +static bool equals(private_host_t *this, private_host_t *other) +{ + if (!ip_equals(this, other)) + { + return FAILED; + } + + switch (this->address.sa_family) + { + case AF_INET: + { + if (this->address4.sin_port == other->address4.sin_port) + { + return TRUE; + } + break; + } + case AF_INET6: + { + if (this->address6.sin6_port == other->address6.sin6_port) + { + return TRUE; + } + break; + } + default: + break; + } + return FALSE; +} + +/** + * Implements host_t.destroy + */ +static void destroy(private_host_t *this) +{ + free(this); +} + +/** + * Creates an empty host_t object + */ +static private_host_t *host_create_empty(void) +{ + private_host_t *this = malloc_thing(private_host_t); + + this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr; + this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len; + this->public.clone = (host_t* (*) (host_t*))clone_; + this->public.get_family = (int (*) (host_t*))get_family; + this->public.get_address = (chunk_t (*) (host_t *)) get_address; + this->public.get_port = (u_int16_t (*) (host_t *))get_port; + this->public.set_port = (void (*) (host_t *,u_int16_t))set_port; + this->public.get_differences = get_differences; + this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals; + this->public.equals = (bool (*) (host_t *,host_t *)) equals; + this->public.is_anyaddr = (bool (*) (host_t *)) is_anyaddr; + this->public.destroy = (void (*) (host_t*))destroy; + + return this; +} + +/* + * Described in header. + */ +host_t *host_create_from_string(char *string, u_int16_t port) +{ + private_host_t *this = host_create_empty(); + + if (strchr(string, '.')) + { + this->address.sa_family = AF_INET; + } + else + { + this->address.sa_family = AF_INET6; + } + + switch (this->address.sa_family) + { + case AF_INET: + { + if (inet_pton(AF_INET, string, &this->address4.sin_addr) <=0) + { + break; + } + this->address4.sin_port = htons(port); + this->socklen = sizeof(struct sockaddr_in); + return &this->public; + } + case AF_INET6: + { + if (inet_pton(AF_INET6, string, &this->address6.sin6_addr) <=0) + { + break; + } + this->address6.sin6_port = htons(port); + this->socklen = sizeof(struct sockaddr_in6); + return &this->public; + } + default: + { + break; + } + } + free(this); + return NULL; +} + +/* + * Described in header. + */ +host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port) +{ + private_host_t *this = host_create_empty(); + + this->address.sa_family = family; + switch (family) + { + case AF_INET: + { + if (address.len != 4) + { + break; + } + memcpy(&(this->address4.sin_addr.s_addr), address.ptr,4); + this->address4.sin_port = htons(port); + this->socklen = sizeof(struct sockaddr_in); + return &(this->public); + } + case AF_INET6: + { + if (address.len != 16) + { + break; + } + memcpy(&(this->address6.sin6_addr.s6_addr), address.ptr, 16); + this->address6.sin6_port = htons(port); + this->socklen = sizeof(struct sockaddr_in6); + return &this->public; + } + default: + break; + } + free(this); + return NULL; +} + +/* + * Described in header. + */ +host_t *host_create_from_sockaddr(sockaddr_t *sockaddr) +{ + private_host_t *this = host_create_empty(); + + switch (sockaddr->sa_family) + { + case AF_INET: + { + memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in)); + this->socklen = sizeof(struct sockaddr_in); + return &this->public; + } + case AF_INET6: + { + memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6)); + this->socklen = sizeof(struct sockaddr_in6); + return &this->public; + } + default: + break; + } + free(this); + return NULL; +} + +/* + * Described in header. + */ +host_t *host_create_any(int family) +{ + private_host_t *this = host_create_empty(); + + memset(&this->address_max, 0, sizeof(struct sockaddr_storage)); + this->address.sa_family = family; + + switch (family) + { + case AF_INET: + { + this->socklen = sizeof(struct sockaddr_in); + return &(this->public); + } + case AF_INET6: + { + this->socklen = sizeof(struct sockaddr_in6); + return &this->public; + } + default: + break; + } + return NULL; +} |