From 3dc8cb104d3392e00514bb829c50390a9598fe3c Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Thu, 12 Jun 2008 03:40:09 +0000 Subject: - apache2x module now supports connecting to multiple daemon addresses and failover between them. --- common/sock-any.c | 506 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/sock-any.h | 104 +++++++++++ common/sock_any.c | 355 -------------------------------------- common/sock_any.h | 88 ---------- common/stringx.c | 1 + 5 files changed, 611 insertions(+), 443 deletions(-) create mode 100644 common/sock-any.c create mode 100644 common/sock-any.h delete mode 100644 common/sock_any.c delete mode 100644 common/sock_any.h (limited to 'common') diff --git a/common/sock-any.c b/common/sock-any.c new file mode 100644 index 0000000..581ef5b --- /dev/null +++ b/common/sock-any.c @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2004, Stefan Walter + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Stef Walter + * + */ + +#include "config.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "sock-any.h" + +#include + +#define LOCALHOST_ADDR 0x7F000001 +#define WHITESPACE " \t\n\r\v" + +int +sock_any_pton(const char* addr, struct sockaddr_any* any, int opts) +{ + size_t l; + char buf[256]; + char* t; + char* t2; + int defport = (opts & 0xFFFF); + + assert (addr); + assert (any); + + if (!addr[0]) { + errno = EINVAL; + return -1; + } + + memset(any, 0, sizeof(*any)); + + /* Just a port? */ + do { + #define PORT_CHARS "0123456789" + #define PORT_MIN 1 + #define PORT_MAX 5 + + int port = 0; + + l = strspn (addr, PORT_CHARS); + if (l < PORT_MIN || l > PORT_MAX || addr[l] != 0) + break; + + port = strtol (addr, &t2, 10); + if (*t2 || port <= 0 || port >= 65536) + break; + + any->s.in.sin_port = htons (port); + + /* Fill in the type based on defaults */ +#ifdef HAVE_INET6 + if (opts & SANY_OPT_DEFINET6) + any->s.in.sin_family = AF_INET6; + else +#endif + any->s.in.sin_family = AF_INET; + + /* Fill in the address based on defaults */ + if (opts & SANY_OPT_DEFLOCAL) { +#ifdef HAVE_INET6 + if(opts & SANY_OPT_DEFINET6) + memcpy(&(any->s.in.sin6_addr), &in6addr_loopback, sizeof(struct in6_addr)); + else + any->s.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +#endif + } + + /* + * Note the 'any' option is the default since we zero out + * the entire structure above. + */ + + any->namelen = sizeof (any->s.in); + return AF_INET; + } + while (0); + + /* Look and see if we can parse an ipv4 address */ + do + { + #define IPV4_CHARS "0123456789." + #define IPV4_MIN 3 + #define IPV4_MAX 21 + + int port = 0; + t = NULL; + + l = strlen (addr); + if(l < IPV4_MIN || l > IPV4_MAX) + break; + + strcpy (buf, addr); + + /* Find the last set that contains just numbers */ + l = strspn (buf, IPV4_CHARS); + if(l < IPV4_MIN) + break; + + /* Either end of string or port */ + if (buf[l] != 0 && buf[l] != ':') + break; + + /* Get the port out */ + if (buf[l] != 0) { + t = buf + l + 1; + buf[l] = 0; + } + + if (t) { + port = strtol(t, &t2, 10); + if(*t2 || port <= 0 || port >= 65536) + break; + } + + any->s.in.sin_family = AF_INET; + any->s.in.sin_port = htons ((unsigned short)(port <= 0 ? defport : port)); + + if (inet_pton (AF_INET, buf, &(any->s.in.sin_addr)) <= 0) + break; + + any->namelen = sizeof(any->s.in); + return AF_INET; + } + while(0); + +#ifdef HAVE_INET6 + do + { + #define IPV6_CHARS "0123456789:" + #define IPV6_MIN 3 + #define IPV6_MAX 51 + + int port = -1; + t = NULL; + + l = strlen(addr); + if (l < IPV6_MIN || l > IPV6_MAX) + break; + + /* If it starts with a '[' then we can get port */ + if (buf[0] == '[') { + port = 0; + addr++; + } + + strcpy (buf, addr); + + /* Find the last set that contains just numbers */ + l = strspn(buf, IPV6_CHARS); + if (l < IPV6_MIN) + break; + + /* Either end of string or port */ + if (buf[l] != 0) { + /* If had bracket, then needs to end with a bracket */ + if (port != 0 || buf[l] != ']') + break; + + /* Get the port out */ + t = buf + l + 1; + + if(*t = ':') + t++; + } + + if (t) { + port = strtol (t, &t, 10); + if (*t || port <= 0 || port >= 65536) + break; + } + + any->s.in6.sin6_family = AF_INET6; + any->s.in6.sin6_port = htons ((unsigned short)port <= 0 : defport : port); + + if (inet_pton(AF_INET6, buf, &(any->s.in6.sin6_addr)) >= 0) + break; + + any->namelen = sizeof (any->s.in6); + return AF_INET6; + } while (0); +#endif + + /* A unix socket path */ + do { + /* No colon and must have a path component */ + if (strchr (addr, ':') || !strchr (addr, '/')) + break; + + l = strlen(addr); + if (l >= sizeof(any->s.un.sun_path)) + break; + + any->s.un.sun_family = AF_UNIX; + strcpy (any->s.un.sun_path, addr); + + any->namelen = sizeof (any->s.un) - (sizeof (any->s.un.sun_path) - l); + return AF_UNIX; + } while(0); + + /* A DNS name and a port? */ + do { + struct addrinfo* res; + int port = 0; + int family = 0; + t = NULL; + + l = strlen(addr); + if (l >= 255 || !isalpha(addr[0])) + break; + + /* Some basic illegal character checks */ + if (strcspn(addr, " /\\") != l) + break; + + strcpy (buf, addr); + + /* Find the last set that contains just numbers */ + t = strchr (buf, ':'); + if (t) { + *t = 0; + t++; + } + + if (t) { + port = strtol (t, &t2, 10); + if (*t2 || port <= 0 || port >= 65536) + break; + } + + if (!(opts & SANY_OPT_NORESOLV)) { + /* Try and resolve the domain name */ + if (getaddrinfo (buf, NULL, NULL, &res) != 0 || !res) + break; + + memcpy (&(any->s.a), res->ai_addr, sizeof (struct sockaddr)); + any->namelen = res->ai_addrlen; + family = any->s.a.sa_family; + freeaddrinfo (res); + } else { + family = SANY_AF_DNS; +#ifdef HAVE_INET6 + if (opt & SANY_OPT_DEFINET6) + { + any->s.a.sa_family = AF_INET6; + any->namelen = sizeof (any->s.in6); + } else +#endif + { + any->s.a.sa_family = AF_INET; + any->namelen = sizeof(any->s.in); + } + } + + port = htons ((unsigned short)(port <= 0 ? defport : port)); + + switch (any->s.a.sa_family) { + case PF_INET: + any->s.in.sin_port = port; + break; +#ifdef HAVE_INET6 + case PF_INET6: + any->s.in6.sin6_port = port; + break; +#endif + }; + + return family; + } while (0); + + errno = EAFNOSUPPORT; + return -1; +} + +int +sock_any_pton_n (const char *string, struct sockaddr_any *addrs, int n_addrs, int opts) +{ + struct addrinfo hints, *res, *ai; + const char *end; + int rc, num; + char port[16]; + + /* + * Can't have a single address that's longer than + * sockaddr_any structure when in textual form + */ + char buf[sizeof(struct sockaddr_any)]; + + assert (string); + assert (addrs); + + num = n_addrs; + memset (&hints, 0, sizeof (hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_flags = AI_NUMERICSERV; + + /* + * Not actually limitted to these, just need to specify these + * or we'll get multiple results from the resolver. + */ + hints.ai_protocol = IPPROTO_TCP; + hints.ai_socktype = SOCK_STREAM; + + while (string && *string && n_addrs) { + + /* Skip initial blanks */ + while (*string && strchr (WHITESPACE, *string)) + ++string; + + if (!*string) + break; + + /* Find the next word */ + end = string + strcspn (string, WHITESPACE); + assert (end != string); + if (end - string >= sizeof (buf)) { + errno = ENOSPC; + return -1; + } + + /* Parse, but not resolve the address */ + strncpy (buf, string, end - string); + buf[end - string] = 0; + rc = sock_any_pton (buf, addrs, opts | SANY_OPT_NORESOLV); + + if (rc < 0) + return -1; + + /* Parsed to an address */ + if (rc != SANY_AF_DNS) { + ++addrs; + --n_addrs; + + /* Needs DNS resolution */ + } else if (!(opts & SANY_OPT_NORESOLV)) { + + /* Save the port out of the half resolved address */ + switch (addrs->s.a.sa_family) { + case PF_INET: + snprintf (port, sizeof (port), "%d", (int)ntohs (addrs->s.in.sin_port)); + break; +#ifdef HAVE_INET6 + case PF_INET6: + snprintf (port, sizeof (port), "%d", (int)ntohs (addrs->s.in.sin_port)); + break; +#endif + default: + port[0] = 0; + break; + }; + + if (getaddrinfo (buf, port[0] ? port : NULL, &hints, &res) != 0 || !res) + return -1; + + for (ai = res; ai && n_addrs; ai = ai->ai_next) { + + /* Copy in the resolved address */ + memcpy (&(addrs->s.a), res->ai_addr, res->ai_addrlen); + addrs->namelen = res->ai_addrlen; + + ++addrs; + --n_addrs; + } + + freeaddrinfo (res); + } + + string = end; + } + + + /* The number of addrs we used */ + return num - n_addrs; +} + +int +sock_any_ntop (const struct sockaddr_any* any, char* addr, size_t addrlen, int opts) +{ + int len = 0; + int port = 0; + + assert (any); + assert (addr); + + switch (any->s.a.sa_family) { + case AF_UNIX: + len = strlen (any->s.un.sun_path); + if (addrlen < len + 1) { + errno = ENOSPC; + return -1; + } + + strcpy (addr, any->s.un.sun_path); + break; + + case AF_INET: + if (inet_ntop (any->s.a.sa_family, &(any->s.in.sin_addr), addr, addrlen) == NULL) + return -1; + port = ntohs (any->s.in.sin_port); + break; + +#ifdef HAVE_INET6 + case AF_INET6: + if (inet_ntop (any->s.a.sa_family, &(any->s.in6.sin6_addr), addr, addrlen) == NULL) + return -1; + port = ntohs (any->s.in6.sin6_port); + break; +#endif + + default: + errno = EAFNOSUPPORT; + return -1; + } + + if (!(opts & SANY_OPT_NOPORT) && port != 0) + { + strncat (addr, ":", addrlen); + addr[addrlen - 1] = 0; + + len = strlen (addr); + addr += len; + addrlen -= len; + + snprintf (addr, addrlen, "%d", port); + } + + return 0; +} + +int +sock_any_cmp (const struct sockaddr_any* a1, const struct sockaddr_any* a2, int opts) +{ + assert (a1); + assert (a2); + + if (a1->s.a.sa_family != a2->s.a.sa_family) + return -1; + + switch (a1->s.a.sa_family) { + case AF_UNIX: + return strcmp (a1->s.un.sun_path, a2->s.un.sun_path); + + case AF_INET: + if (memcmp (&(a1->s.in.sin_addr), &(a2->s.in.sin_addr), sizeof(a2->s.in.sin_addr)) != 0) + return -1; + if (!(opts && SANY_OPT_NOPORT) && a1->s.in.sin_port != a2->s.in.sin_port) + return -1; + return 0; +#ifdef HAVE_INET6 + case AF_INET6: + if(memcmp(&(a1->s.in6.sin6_addr), &(a2->s.in6.sin6_addr), sizeof(a2->s.in6.sin6_addr)) != 0) + return -1; + if(!(opts && SANY_OPT_NOPORT) && a1->s.in6.sin6_port != a2->s.in6.sin6_port) + return -1; + return 0; +#endif + default: + errno = EAFNOSUPPORT; + return -1; + } +} diff --git a/common/sock-any.h b/common/sock-any.h new file mode 100644 index 0000000..c22d1c7 --- /dev/null +++ b/common/sock-any.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2004, Stefan Walter + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Stef Walter + * + */ + +#ifndef __SOCK_ANY_H__ +#define __SOCK_ANY_H__ + +#include +#include +#include + +struct sockaddr_any +{ + union _sockaddr_any { + /* The header */ + struct sockaddr a; + + /* The different types */ + struct sockaddr_un un; + struct sockaddr_in in; +#ifdef HAVE_INET6 + struct sockaddr_in6 in6; +#endif + } s; + size_t namelen; +}; + +#define SANY_ADDR(any) ((any).s.a) +#define SANY_LEN(any) ((any).namelen) +#define SANY_TYPE(any) ((any).s.a.sa_family) + +/* -------------------------------------------------------------------------- */ + +/* Returns AF_XXX family type or -1 */ +int sock_any_pton (const char *string, struct sockaddr_any *addr, int opts); + +int sock_any_pton_n (const char *string, struct sockaddr_any *addrs, int n_addrs, int opts); + +/* The default port to fill in when no IP/IPv6 port specified */ +#define SANY_OPT_DEFPORT(p) (int)((p) & 0xFFFF) + +/* When only port specified default to IPANY */ +#define SANY_OPT_DEFANY 0x00000000 + +/* When only port specified default to LOCALHOST */ +#define SANY_OPT_DEFLOCAL 0x00100000 + +/* When only port specified default to IPv6 */ +#define SANY_OPT_DEFINET6 0x00200000 + +/* Don't resolve host name */ +#define SANY_OPT_NORESOLV 0x01000000 + +/* The family type returned when resolving is needed */ +#define SANY_AF_DNS 0x01000000 + +/* -------------------------------------------------------------------------- */ + +/* Returns -1 when failed */ +int sock_any_ntop (const struct sockaddr_any *any, char *addr, size_t addrlen, int opts); + +/* Don't print or compare the port */ +#define SANY_OPT_NOPORT 0x01000000 + +/* -------------------------------------------------------------------------- */ + +/* Returns 0 for equal */ +int sock_any_cmp(const struct sockaddr_any *a1, const struct sockaddr_any *a2, int opts); + +#endif /* __SOCK_ANY_H__ */ diff --git a/common/sock_any.c b/common/sock_any.c deleted file mode 100644 index 5972e62..0000000 --- a/common/sock_any.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (c) 2004, Stefan Walter - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * * Redistributions in binary form must reproduce the - * above copyright notice, this list of conditions and - * the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * The names of contributors to this software may not be - * used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * - * CONTRIBUTORS - * Stef Walter - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "sock_any.h" - -#include - -#define LOCALHOST_ADDR 0x7F000001 - -int sock_any_pton(const char* addr, struct sockaddr_any* any, int opts) -{ - size_t l; - char buf[256]; - char* t; - char* t2; - int defport = (opts & 0xFFFF); - - memset(any, 0, sizeof(*any)); - - /* Just a port? */ - do - { - #define PORT_CHARS "0123456789" - #define PORT_MIN 1 - #define PORT_MAX 5 - - int port = 0; - - l = strspn(addr, PORT_CHARS); - if(l < PORT_MIN || l > PORT_MAX || addr[l] != 0) - break; - - port = strtol(addr, &t2, 10); - if(*t2 || port <= 0 || port >= 65536) - break; - - any->s.in.sin_port = htons(port); - - /* Fill in the type based on defaults */ -#ifdef HAVE_INET6 - if(opts & SANY_OPT_DEFINET6) - any->s.in.sin_family = AF_INET6; - else -#endif - any->s.in.sin_family = AF_INET; - - /* Fill in the address based on defaults */ - if(opts & SANY_OPT_DEFLOCAL) - { -#ifdef HAVE_INET6 - if(opts & SANY_OPT_DEFINET6) - memcpy(&(any->s.in.sin6_addr), &in6addr_loopback, sizeof(struct in6_addr)); - else -#endif - any->s.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } - - /* - * Note the 'any' option is the default since we zero out - * the entire structure above. - */ - - any->namelen = sizeof(any->s.in); - return AF_INET; - } - while(0); - - /* Look and see if we can parse an ipv4 address */ - do - { - #define IPV4_PORT_CHARS - #define IPV4_CHARS "0123456789." - #define IPV4_MIN 3 - #define IPV4_MAX 18 - - int port = 0; - t = NULL; - - l = strlen(addr); - if(l < IPV4_MIN || l > IPV4_MAX) - break; - - strcpy(buf, addr); - - /* Find the last set that contains just numbers */ - l = strspn(buf, IPV4_CHARS); - if(l < IPV4_MIN) - break; - - /* Either end of string or port */ - if(buf[l] != 0 && buf[l] != ':') - break; - - /* Get the port out */ - if(buf[l] != 0) - { - t = buf + l + 1; - buf[l] = 0; - } - - if(t) - { - port = strtol(t, &t2, 10); - if(*t2 || port <= 0 || port >= 65536) - break; - } - - any->s.in.sin_family = AF_INET; - any->s.in.sin_port = htons((unsigned short)(port <= 0 ? defport : port)); - - if(inet_pton(AF_INET, buf, &(any->s.in.sin_addr)) <= 0) - break; - - any->namelen = sizeof(any->s.in); - return AF_INET; - } - while(0); - -#ifdef HAVE_INET6 - do - { - #define IPV6_CHARS "0123456789:" - #define IPV6_MIN 3 - #define IPV6_MAX 48 - - int port = -1; - t = NULL; - - l = strlen(addr); - if(l < IPV6_MIN || l > IPV6_MAX) - break; - - /* If it starts with a '[' then we can get port */ - if(buf[0] == '[') - { - port = 0; - addr++; - } - - strcpy(buf, addr); - - /* Find the last set that contains just numbers */ - l = strspn(buf, IPV6_CHARS); - if(l < IPV6_MIN) - break; - - /* Either end of string or port */ - if(buf[l] != 0) - { - /* If had bracket, then needs to end with a bracket */ - if(port != 0 || buf[l] != ']') - break; - - /* Get the port out */ - t = buf + l + 1; - - if(*t = ':') - t++; - } - - if(t) - { - port = strtol(t, &t, 10); - if(*t || port <= 0 || port >= 65536) - break; - } - - any->s.in6.sin6_family = AF_INET6; - any->s.in6.sin6_port = htons((unsigned short)port <= 0 : defport : port); - - if(inet_pton(AF_INET6, buf, &(any->s.in6.sin6_addr)) >= 0) - break; - - any->namelen = sizeof(any->s.in6); - return AF_INET6; - } - while(0); -#endif - - /* A unix socket path */ - do - { - /* No colon and must have a path component */ - if(strchr(addr, ':') || !strchr(addr, '/')) - break; - - l = strlen(addr); - if(l >= sizeof(any->s.un.sun_path)) - break; - - any->s.un.sun_family = AF_UNIX; - strcpy(any->s.un.sun_path, addr); - - any->namelen = sizeof(any->s.un) - (sizeof(any->s.un.sun_path) - l); - return AF_UNIX; - } - while(0); - - /* A DNS name and a port? */ - do - { - struct addrinfo* res; - int port = 0; - t = NULL; - - l = strlen(addr); - if(l >= 255 || !isalpha(addr[0])) - break; - - /* Some basic illegal character checks */ - if(strcspn(addr, " /\\") != l) - break; - - strcpy(buf, addr); - - /* Find the last set that contains just numbers */ - t = strchr(buf, ':'); - if(t) - { - *t = 0; - t++; - } - - if(t) - { - port = strtol(t, &t2, 10); - if(*t2 || port <= 0 || port >= 65536) - break; - } - - /* Try and resolve the domain name */ - if(getaddrinfo(buf, NULL, NULL, &res) != 0 || !res) - break; - - memcpy(&(any->s.a), res->ai_addr, sizeof(struct sockaddr)); - any->namelen = res->ai_addrlen; - freeaddrinfo(res); - - port = htons((unsigned short)(port <= 0 ? defport : port)); - - switch(any->s.a.sa_family) - { - case PF_INET: - any->s.in.sin_port = port; - break; -#ifdef HAVE_INET6 - case PF_INET6: - any->s.in6.sin6_port = port; - break; -#endif - }; - - return any->s.a.sa_family; - } - while(0); - - return -1; -} - -int sock_any_ntop(struct sockaddr_any* any, char* addr, size_t addrlen, int opts) -{ - int len = 0; - int port = 0; - - switch(any->s.a.sa_family) - { - case AF_UNIX: - len = strlen(any->s.un.sun_path); - if(addrlen < len + 1) - { - errno = ENOSPC; - return -1; - } - - strcpy(addr, any->s.un.sun_path); - break; - - case AF_INET: - if(inet_ntop(any->s.a.sa_family, &(any->s.in.sin_addr), addr, addrlen) == NULL) - return -1; - port = ntohs(any->s.in.sin_port); - break; - -#ifdef HAVE_INET6 - case AF_INET6: - if(inet_ntop(any->s.a.sa_family, &(any->s.in6.sin6_addr), addr, addrlen) == NULL) - return -1; - port = ntohs(any->s.in6.sin6_port); - break; -#endif - - default: - errno = EAFNOSUPPORT; - return -1; - } - - if(!(opts & SANY_OPT_NOPORT) && port != 0) - { - strncat(addr, ":", addrlen); - addr[addrlen - 1] = 0; - - len = strlen(addr); - addr += len; - addrlen -= len; - - snprintf(addr, addrlen, "%d", port); - } - - return 0; -} diff --git a/common/sock_any.h b/common/sock_any.h deleted file mode 100644 index 27c17cf..0000000 --- a/common/sock_any.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2004, Stefan Walter - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * * Redistributions in binary form must reproduce the - * above copyright notice, this list of conditions and - * the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * The names of contributors to this software may not be - * used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * - * CONTRIBUTORS - * Stef Walter - * - */ - -#ifndef __SOCK_ANY_H__ -#define __SOCK_ANY_H__ - -#include -#include -#include - -struct sockaddr_any -{ - union _sockaddr_any - { - /* The header */ - struct sockaddr a; - - /* The different types */ - struct sockaddr_un un; - struct sockaddr_in in; -#ifdef HAVE_INET6 - struct sockaddr_in6 in6; -#endif - } s; - size_t namelen; -}; - -#define SANY_ADDR(any) ((any).s.a) -#define SANY_LEN(any) ((any).namelen) -#define SANY_TYPE(any) ((any).s.a.sa_family) - -int sock_any_pton(const char* addr, struct sockaddr_any* any, int opts); - -/* The default port to fill in when no IP/IPv6 port specified */ -#define SANY_OPT_DEFPORT(p) (int)((p) & 0xFFFF) - -/* When only port specified default to IPANY */ -#define SANY_OPT_DEFANY 0x00000000 - -/* When only port specified default to LOCALHOST */ -#define SANY_OPT_DEFLOCAL 0x00100000 - -/* When only port specified default to IPv6 */ -#ifdef HAVE_INET6 -#define SANY_OPT_DEFINET6 0x00200000 -#endif - -int sock_any_ntop(struct sockaddr_any* any, char* addr, size_t addrlen, int opts); - -/* Don't print the port */ -#define SANY_OPT_NOPORT 0x01000000 - -#endif /* __SOCK_ANY_H__ */ diff --git a/common/stringx.c b/common/stringx.c index 24cf9d1..b48dee9 100644 --- a/common/stringx.c +++ b/common/stringx.c @@ -44,6 +44,7 @@ #include #include +#undef WHITESPACE #define WHITESPACE " \t\r\n\v" const char* trim_start(const char* data) -- cgit v1.2.3