diff options
Diffstat (limited to 'lib/tsocket')
-rw-r--r-- | lib/tsocket/tsocket.h | 43 | ||||
-rw-r--r-- | lib/tsocket/tsocket_bsd.c | 100 |
2 files changed, 143 insertions, 0 deletions
diff --git a/lib/tsocket/tsocket.h b/lib/tsocket/tsocket.h index 2f1c7981346..d3cde99bf5a 100644 --- a/lib/tsocket/tsocket.h +++ b/lib/tsocket/tsocket.h @@ -539,6 +539,49 @@ int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx, __location__) #endif +#ifdef DOXYGEN +/** + * @brief Create a tsocket_address for ipv4 and ipv6 endpoint addresses. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] fam The family can be can be "ipv4", "ipv6" or "ip". With + * "ip" it autodetects "ipv4" or "ipv6" based on the + * addr. + * + * @param[in] host_port_addr A valid ip address string based on the + * selected family (dns names are not allowed!). A port + * number may follow sepatated by a colon. IPv6 may be + * surrounded in square brackets, and these are required + * if appending a port number. It's valid to pass NULL, + * which gets mapped to "0.0.0.0" or "::". + * + * @param[in] default_port A valid port number for the default port if none + * given. + * + * @param[out] _addr A tsocket_address pointer to store the information. + * + * @return 0 on success, -1 on error with errno set. + */ +int tsocket_address_inet_from_hostport_strings(TALLOC_CTX *mem_ctx, + const char *fam, + const char *host_port_addr, + uint16_t default_port, + struct tsocket_address **_addr); +#else +int _tsocket_address_inet_from_hostport_strings(TALLOC_CTX *mem_ctx, + const char *fam, + const char *host_port_addr, + uint16_t default_port, + struct tsocket_address **_addr, + const char *location); + +#define tsocket_address_inet_from_hostport_strings( \ + mem_ctx, fam, host_port_addr, default_port, _addr) \ + _tsocket_address_inet_from_hostport_strings( \ + mem_ctx, fam, host_port_addr, default_port, _addr, __location__) +#endif + /** * @brief Get the address of an 'inet' tsocket_address as a string. * diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c index 9485da7c8af..5650763d1e6 100644 --- a/lib/tsocket/tsocket_bsd.c +++ b/lib/tsocket/tsocket_bsd.c @@ -29,6 +29,7 @@ #include "lib/util/iov_buf.h" #include "lib/util/blocking.h" #include "lib/util/util_net.h" +#include "lib/util/samba_util.h" static int tsocket_bsd_error_from_errno(int ret, int sys_errno, @@ -441,6 +442,105 @@ done: return ret; } +int _tsocket_address_inet_from_hostport_strings(TALLOC_CTX *mem_ctx, + const char *fam, + const char *host_port_addr, + uint16_t default_port, + struct tsocket_address **_addr, + const char *location) +{ + char *pl_sq = NULL; + char *pr_sq = NULL; + char *pl_period = NULL; + char *port_sep = NULL; + char *cport = NULL; + char *buf = NULL; + uint64_t port = 0; + int ret; + char *s_addr = NULL; + uint16_t s_port = default_port; + bool conv_ret; + bool is_ipv6_by_squares = false; + + if (host_port_addr == NULL) { + /* got straight to next function if host_port_addr is NULL */ + goto get_addr; + } + buf = talloc_strdup(mem_ctx, host_port_addr); + if (buf == NULL) { + errno = ENOMEM; + return -1; + } + pl_period = strchr_m(buf, '.'); + port_sep = strrchr_m(buf, ':'); + pl_sq = strchr_m(buf, '['); + pr_sq = strrchr_m(buf, ']'); + /* See if its IPv4 or IPv6 */ + /* Only parse IPv6 with squares with/without port, and IPv4 with port */ + /* Everything else, let tsocket_address_inet_from string() */ + /* find parsing errors */ +#ifdef HAVE_IPV6 + is_ipv6_by_squares = (pl_sq != NULL && pr_sq != NULL && pr_sq > pl_sq); +#endif + if (is_ipv6_by_squares) { + /* IPv6 possibly with port - squares detected */ + port_sep = pr_sq + 1; + if (*port_sep == '\0') { + s_addr = pl_sq + 1; + *pr_sq = 0; + s_port = default_port; + goto get_addr; + } + if (*port_sep != ':') { + errno = EINVAL; + return -1; + } + cport = port_sep + 1; + conv_ret = conv_str_u64(cport, &port); + if (!conv_ret) { + errno = EINVAL; + return -1; + } + if (port > 65535) { + errno = EINVAL; + return -1; + } + s_port = (uint16_t)port; + *port_sep = 0; + *pr_sq = 0; + s_addr = pl_sq + 1; + *pl_sq = 0; + goto get_addr; + } else if (pl_period != NULL && port_sep != NULL) { + /* IPv4 with port - more than one period in string */ + cport = port_sep + 1; + conv_ret = conv_str_u64(cport, &port); + if (!conv_ret) { + errno = EINVAL; + return -1; + } + if (port > 65535) { + errno = EINVAL; + return -1; + } + s_port = (uint16_t)port; + *port_sep = 0; + s_addr = buf; + goto get_addr; + } else { + /* Everything else, let tsocket_address_inet_from string() */ + /* find parsing errors */ + s_addr = buf; + s_port = default_port; + goto get_addr; + } +get_addr: + ret = _tsocket_address_inet_from_strings( + mem_ctx, fam, s_addr, s_port, _addr, location); + + return ret; +} + char *tsocket_address_inet_addr_string(const struct tsocket_address *addr, TALLOC_CTX *mem_ctx) { |