From c00cf65b1c29b836e0c95c28b22279157585a2e7 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Tue, 10 Jun 2008 02:47:43 +0000 Subject: Add support for resolving name server to multiple ip addresses --- common/sock-any.c | 609 ++++++++++++++++++++++++++---------------------------- common/sock-any.h | 41 ++-- 2 files changed, 316 insertions(+), 334 deletions(-) (limited to 'common') diff --git a/common/sock-any.c b/common/sock-any.c index 4476fde..4613931 100644 --- a/common/sock-any.c +++ b/common/sock-any.c @@ -36,6 +36,8 @@ * */ +#include "config.h" + #include #include @@ -50,357 +52,338 @@ #include -#define LOCALHOST_ADDR 0x7F000001 +#define LOCALHOST_ADDR 0x7F000001 -int sock_any_pton(const char* addr, struct sockaddr_any* any, int opts) +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); + size_t l; + char buf[256]; + char* t; + char* t2; + int defport = (opts & 0xFFFF); - memset(any, 0, sizeof(*any)); + memset(any, 0, sizeof(*any)); - /* Just a port? */ - do - { - #define PORT_CHARS "0123456789" - #define PORT_MIN 1 - #define PORT_MAX 5 + /* Just a port? */ + do { + #define PORT_CHARS "0123456789" + #define PORT_MIN 1 + #define PORT_MAX 5 - int port = 0; + int port = 0; - l = strspn(addr, PORT_CHARS); - if(l < PORT_MIN || l > PORT_MAX || addr[l] != 0) - break; + 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; + port = strtol (addr, &t2, 10); + if (*t2 || port <= 0 || port >= 65536) + break; - any->s.in.sin_port = htons(port); + any->s.in.sin_port = htons (port); - /* Fill in the type based on defaults */ + /* Fill in the type based on defaults */ #ifdef HAVE_INET6 - if(opts & SANY_OPT_DEFINET6) - any->s.in.sin_family = AF_INET6; - else + if (opts & SANY_OPT_DEFINET6) + any->s.in.sin_family = AF_INET6; + else #endif - any->s.in.sin_family = AF_INET; + any->s.in.sin_family = AF_INET; - /* Fill in the address based on defaults */ - if(opts & SANY_OPT_DEFLOCAL) - { + /* 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 + 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 - 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 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); + } + + /* + * 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); + 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; + /* 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 + 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; + { + 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; + case PF_INET6: + any->s.in6.sin6_port = port; + break; #endif - }; + }; - return family; - } - while(0); + return family; + } while (0); - return -1; + errno = EAFNOSUPPORT; + return -1; } -int sock_any_ntop(const struct sockaddr_any* any, char* addr, size_t addrlen, int opts) +int +sock_any_ntop (const 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; + 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; + 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; - } + default: + errno = EAFNOSUPPORT; + return -1; + } - if(!(opts & SANY_OPT_NOPORT) && port != 0) - { - strncat(addr, ":", addrlen); - addr[addrlen - 1] = 0; + if (!(opts & SANY_OPT_NOPORT) && port != 0) + { + strncat (addr, ":", addrlen); + addr[addrlen - 1] = 0; - len = strlen(addr); - addr += len; - addrlen -= len; + len = strlen (addr); + addr += len; + addrlen -= len; - snprintf(addr, addrlen, "%d", port); - } + snprintf (addr, addrlen, "%d", port); + } - return 0; + return 0; } -int sock_any_cmp(const struct sockaddr_any* a1, const struct sockaddr_any* a2, int opts) +int +sock_any_cmp (const struct sockaddr_any* a1, const struct sockaddr_any* a2, int opts) { - 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; + 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; + 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; - } + default: + errno = EAFNOSUPPORT; + return -1; + } } diff --git a/common/sock-any.h b/common/sock-any.h index e9b57ef..7b5da34 100644 --- a/common/sock-any.h +++ b/common/sock-any.h @@ -45,24 +45,23 @@ struct sockaddr_any { - union _sockaddr_any - { - /* The header */ - struct sockaddr a; - - /* The different types */ - struct sockaddr_un un; - struct sockaddr_in in; + 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; + struct sockaddr_in6 in6; #endif - } s; - size_t namelen; + } 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) +#define SANY_ADDR(any) ((any).s.a) +#define SANY_LEN(any) ((any).namelen) +#define SANY_TYPE(any) ((any).s.a.sa_family) /* -------------------------------------------------------------------------- */ @@ -70,22 +69,22 @@ struct sockaddr_any 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) +#define SANY_OPT_DEFPORT(p) (int)((p) & 0xFFFF) /* When only port specified default to IPANY */ -#define SANY_OPT_DEFANY 0x00000000 +#define SANY_OPT_DEFANY 0x00000000 /* When only port specified default to LOCALHOST */ -#define SANY_OPT_DEFLOCAL 0x00100000 +#define SANY_OPT_DEFLOCAL 0x00100000 /* When only port specified default to IPv6 */ -#define SANY_OPT_DEFINET6 0x00200000 +#define SANY_OPT_DEFINET6 0x00200000 /* Don't resolve host name */ -#define SANY_OPT_NORESOLV 0x01000000 +#define SANY_OPT_NORESOLV 0x01000000 /* The family type returned when resolving is needed */ -#define SANY_AF_DNS 0x01000000 +#define SANY_AF_DNS 0x01000000 /* -------------------------------------------------------------------------- */ @@ -93,7 +92,7 @@ int sock_any_pton(const char* addr, struct sockaddr_any* any, int opts); 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 +#define SANY_OPT_NOPORT 0x01000000 /* -------------------------------------------------------------------------- */ -- cgit v1.2.3