summaryrefslogtreecommitdiff
path: root/lib/tsocket
diff options
context:
space:
mode:
authorMatthew Grant <matt@mattgrant.net.nz>2021-09-19 17:41:42 +1200
committerAndrew Bartlett <abartlet@samba.org>2021-09-28 09:44:35 +0000
commitf39a06de3bea9ec03a3e82c8892d9e572abd1163 (patch)
treef472f94d46c1c02f1b1c947968629c049323de4d /lib/tsocket
parent775939823a5a956acc236c808d5aee78cbd9e132 (diff)
downloadsamba-f39a06de3bea9ec03a3e82c8892d9e572abd1163.tar.gz
lib/tsocket: new function to parse host port strs.
tsocket_address_inet_from_hostport_strings() on top of tsocket_address_inet_from_strings(), implementing the ability to parse a port number appended to an IPv6 or IPv4 address. IPv6 addresses can also optionally have square brackets around them, but these are needed to specify the port number as colon is used to delimit port from the IP address in the string. Note that this code just recognises and parses the strings with port given, or just IPv6 with square brackets. The rest of the parsing is passed on to tsocket_address_inet_from strings(), and errors from there passed back up the stack. Signed-off-by: Matthew Grant <grantma@mattgrant.net.nz> Reviewed-by: Uri Simchoni <uri@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
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)
{