Sorry, I did some mistake on my own. Will send v4. On 03/12/17 12:09, Antonio Quartulli wrote: > Similarly to ifconfig(-push), its IPv6 counterpart is now able to > accept hostnames as well instead of IP addresses in numeric form. > > Basically this means that the user is now allowed to specify > something like this: > > ifconfig-ipv6-push my.hostname.cx/64 > > This is exactly the same behaviour that we already have with > ifconfig(-push). > > The generic code introduced in this patch will be later used to > implement the /bits parsing support for IPv4 addresses. > > Trac: #808 > Signed-off-by: Antonio Quartulli <a...@unstable.cc> > --- > > v3: > - declare 'bits' as unsigned long (will store result of strtoul()) > - convert ASSERTs to plain error handling in get_addr_generic() > - remove useless comment about '/' overwriting > - improve debug message by printing hostname > > v2: > - rebased on top of master > - style adapted to new CodingStyle > > src/openvpn/options.c | 61 ---------------------- > src/openvpn/options.h | 4 -- > src/openvpn/socket.c | 140 > +++++++++++++++++++++++++++++++++++++++++++++----- > src/openvpn/socket.h | 12 +++++ > 4 files changed, 140 insertions(+), 77 deletions(-) > > diff --git a/src/openvpn/options.c b/src/openvpn/options.c > index 8e5cdf7f..767cdaeb 100644 > --- a/src/openvpn/options.c > +++ b/src/openvpn/options.c > @@ -1033,67 +1033,6 @@ get_ip_addr(const char *ip_string, int msglevel, bool > *error) > return ret; > } > > -/* helper: parse a text string containing an IPv6 address + netbits > - * in "standard format" (2001:dba::/32) > - * "/nn" is optional, default to /64 if missing > - * > - * return true if parsing succeeded, modify *network and *netbits > - */ > -bool > -get_ipv6_addr( const char *prefix_str, struct in6_addr *network, > - unsigned int *netbits, int msglevel) > -{ > - char *sep, *endp; > - int bits; > - struct in6_addr t_network; > - > - sep = strchr( prefix_str, '/' ); > - if (sep == NULL) > - { > - bits = 64; > - } > - else > - { > - bits = strtol( sep+1, &endp, 10 ); > - if (*endp != '\0' || bits < 0 || bits > 128) > - { > - msg(msglevel, "IPv6 prefix '%s': invalid '/bits' spec", > prefix_str); > - return false; > - } > - } > - > - /* temporary replace '/' in caller-provided string with '\0', otherwise > - * inet_pton() will refuse prefix string > - * (alternative would be to strncpy() the prefix to temporary buffer) > - */ > - > - if (sep != NULL) > - { > - *sep = '\0'; > - } > - > - if (inet_pton( AF_INET6, prefix_str, &t_network ) != 1) > - { > - msg(msglevel, "IPv6 prefix '%s': invalid IPv6 address", prefix_str); > - return false; > - } > - > - if (sep != NULL) > - { > - *sep = '/'; > - } > - > - if (netbits != NULL) > - { > - *netbits = bits; > - } > - if (network != NULL) > - { > - *network = t_network; > - } > - return true; /* parsing OK, values set */ > -} > - > /** > * Returns newly allocated string containing address part without "/nn". > * > diff --git a/src/openvpn/options.h b/src/openvpn/options.h > index 035c6d15..d67c2785 100644 > --- a/src/openvpn/options.h > +++ b/src/openvpn/options.h > @@ -817,8 +817,4 @@ void options_string_import(struct options *options, > unsigned int *option_types_found, > struct env_set *es); > > -bool get_ipv6_addr( const char *prefix_str, struct in6_addr *network, > - unsigned int *netbits, int msglevel ); > - > - > #endif /* ifndef OPTIONS_H */ > diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c > index 0fc91f21..0cb5662c 100644 > --- a/src/openvpn/socket.c > +++ b/src/openvpn/socket.c > @@ -74,12 +74,116 @@ sf2gaf(const unsigned int getaddr_flags, > /* > * Functions related to the translation of DNS names to IP addresses. > */ > +static int > +get_addr_generic(sa_family_t af, unsigned int flags, const char *hostname, > + void *network, unsigned int *netbits, > + int resolve_retry_seconds, volatile int *signal_received, > + int msglevel) > +{ > + char *endp, *sep, *var_host = NULL; > + struct addrinfo *ai = NULL; > + unsigned long bits; > + uint8_t max_bits; > + int ret = -1; > + > + if (!hostname) > + { > + msg(M_NONFTAL, "Can't resolve null hostname!"); > + goto out; > + } > + > + /* assign family specific default values */ > + switch (af) > + { > + case AF_INET: > + bits = 0; > + max_bits = sizeof(in_addr_t) * 8; > + break; > + case AF_INET6: > + bits = 64; > + max_bits = sizeof(struct in6_addr) * 8; > + break; > + default: > + msg(M_WARN, > + "Unsupported AF family passed to getaddrinfo for %s (%d)", > + hostname, af); > + goto out; > + } > + > + /* we need to modify the hostname received as input, but we don't want to > + * touch it directly as it might be a constant string. > + * > + * Therefore, we clone the string here and free it at the end of the > + * function */ > + var_host = strdup(hostname); > + if (!var_host) > + { > + msg(M_NONFTAL | M_ERRNO, > + "Can't allocate hostname buffer for getaddrinfo"); > + goto out; > + } > + > + /* check if this hostname has a /bits suffix */ > + sep = strchr(var_host , '/'); > + if (sep) > + { > + bits = strtoul(sep + 1, &endp, 10); > + if ((*endp != '\0') || (bits > max_bits)) > + { > + msg(msglevel, "IP prefix '%s': invalid '/bits' spec (%s)", > hostname, > + sep + 1); > + goto out; > + } > + *sep = '\0'; > + } > + > + ret = openvpn_getaddrinfo(flags & ~GETADDR_HOST_ORDER, var_host, NULL, > + resolve_retry_seconds, signal_received, af, > &ai); > + if ((ret == 0) && network) > + { > + struct in6_addr *ip6; > + in_addr_t *ip4; > + > + switch (af) > + { > + case AF_INET: > + ip4 = network; > + *ip4 = ((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr; > + > + if (flags & GETADDR_HOST_ORDER) > + { > + *ip4 = ntohl(*ip4); > + } > + break; > + case AF_INET6: > + ip6 = network; > + *ip6 = ((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; > + break; > + default: > + /* can't get here because 'af' was previously checked */ > + msg(M_WARN, > + "Unsupported AF family for %s (%d)", af, var_host); > + goto out; > + } > + } > + > + if (netbits) > + { > + *netbits = bits; > + } > + > + /* restore '/' separator, if any */ > + if (sep) > + { > + *sep = '/'; > + } > +out: > + freeaddrinfo(ai); > + free(var_host); > + > + return ret; > +} > > -/* > - * Translate IP addr or hostname to in_addr_t. > - * If resolve error, try again for > - * resolve_retry_seconds seconds. > - */ > in_addr_t > getaddr(unsigned int flags, > const char *hostname, > @@ -87,20 +191,19 @@ getaddr(unsigned int flags, > bool *succeeded, > volatile int *signal_received) > { > - struct addrinfo *ai; > + in_addr_t addr; > int status; > - status = openvpn_getaddrinfo(flags & ~GETADDR_HOST_ORDER, hostname, NULL, > - resolve_retry_seconds, signal_received, > AF_INET, &ai); > + > + status = get_addr_generic(AF_INET, flags, hostname, &addr, NULL, > + resolve_retry_seconds, signal_received, > + M_WARN); > if (status==0) > { > - struct in_addr ia; > if (succeeded) > { > *succeeded = true; > } > - ia = ((struct sockaddr_in *)ai->ai_addr)->sin_addr; > - freeaddrinfo(ai); > - return (flags & GETADDR_HOST_ORDER) ? ntohl(ia.s_addr) : ia.s_addr; > + return addr; > } > else > { > @@ -112,6 +215,19 @@ getaddr(unsigned int flags, > } > } > > +bool > +get_ipv6_addr(const char *hostname, struct in6_addr *network, > + unsigned int *netbits, int msglevel) > +{ > + if (get_addr_generic(AF_INET6, GETADDR_RESOLVE, hostname, network, > netbits, > + 0, NULL, msglevel) < 0) > + { > + return false; > + } > + > + return true; /* parsing OK, values set */ > +} > + > static inline bool > streqnull(const char *a, const char *b) > { > diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h > index 2d7f2187..81e9e9ae 100644 > --- a/src/openvpn/socket.h > +++ b/src/openvpn/socket.h > @@ -532,12 +532,24 @@ bool unix_socket_get_peer_uid_gid(const > socket_descriptor_t sd, int *uid, int *g > > #define GETADDR_CACHE_MASK (GETADDR_DATAGRAM|GETADDR_PASSIVE) > > +/** > + * Translate an IPv4 addr or hostname from string form to in_addr_t > + * > + * In case of resolve error, it will try again for > + * resolve_retry_seconds seconds. > + */ > in_addr_t getaddr(unsigned int flags, > const char *hostname, > int resolve_retry_seconds, > bool *succeeded, > volatile int *signal_received); > > +/** > + * Translate an IPv6 addr or hostname from string form to in6_addr > + */ > +bool get_ipv6_addr(const char *hostname, struct in6_addr *network, > + unsigned int *netbits, int msglevel); > + > int openvpn_getaddrinfo(unsigned int flags, > const char *hostname, > const char *servname, >
-- Antonio Quartulli
signature.asc
Description: OpenPGP digital signature
------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel