summaryrefslogtreecommitdiff
path: root/lib/tsocket
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tsocket')
-rw-r--r--lib/tsocket/tsocket.h43
-rw-r--r--lib/tsocket/tsocket_bsd.c100
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)
{