summaryrefslogtreecommitdiff
path: root/ctdb/protocol
diff options
context:
space:
mode:
authorMartin Schwenke <martin@meltin.net>2017-09-11 16:39:38 +1000
committerMartin Schwenke <martins@samba.org>2017-09-19 13:30:26 +0200
commit6f1b1a05fb821d49c44195c6ff91fbe21b1b10ef (patch)
tree4a0a48f003211b0aadddb3dcc1dba86fa895d90f /ctdb/protocol
parent93668f50266ce43e591f0708bc0dcd557719e2dc (diff)
downloadsamba-6f1b1a05fb821d49c44195c6ff91fbe21b1b10ef.tar.gz
ctdb-protocol: Add ctdb_sock_addr_from_string()
This and the supporting functions duplicate functionality (parse_ip() and parse_ip_port()) from common/system_util.c. The old functions will be removed at a later time. Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com>
Diffstat (limited to 'ctdb/protocol')
-rw-r--r--ctdb/protocol/protocol_util.c126
-rw-r--r--ctdb/protocol/protocol_util.h2
2 files changed, 128 insertions, 0 deletions
diff --git a/ctdb/protocol/protocol_util.c b/ctdb/protocol/protocol_util.c
index 26425d97a56..3c8c21a472a 100644
--- a/ctdb/protocol/protocol_util.c
+++ b/ctdb/protocol/protocol_util.c
@@ -174,6 +174,132 @@ const char *ctdb_sock_addr_to_string(TALLOC_CTX *mem_ctx,
return cip;
}
+static int ipv4_from_string(const char *str, struct sockaddr_in *ip)
+{
+ int ret;
+
+ *ip = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ };
+
+ ret = inet_pton(AF_INET, str, &ip->sin_addr);
+ if (ret != 1) {
+ return EINVAL;
+ }
+
+#ifdef HAVE_SOCK_SIN_LEN
+ ip->sin_len = sizeof(*ip);
+#endif
+ return 0;
+}
+
+static int ipv6_from_string(const char *str, struct sockaddr_in6 *ip6)
+{
+ int ret;
+
+ *ip6 = (struct sockaddr_in6) {
+ .sin6_family = AF_INET6,
+ };
+
+ ret = inet_pton(AF_INET6, str, &ip6->sin6_addr);
+ if (ret != 1) {
+ return EINVAL;
+ }
+
+#ifdef HAVE_SOCK_SIN_LEN
+ ip6->sin6_len = sizeof(*ip6);
+#endif
+ return 0;
+}
+
+static int ip_from_string(const char *str, ctdb_sock_addr *addr)
+{
+ char *p;
+ int ret;
+
+ if (addr == NULL) {
+ return EINVAL;
+ }
+
+ ZERO_STRUCTP(addr); /* valgrind :-) */
+
+ /* IPv4 or IPv6 address?
+ *
+ * Use rindex() because we need the right-most ':' below for
+ * IPv4-mapped IPv6 addresses anyway...
+ */
+ p = rindex(str, ':');
+ if (p == NULL) {
+ ret = ipv4_from_string(str, &addr->ip);
+ } else {
+ uint8_t ipv4_mapped_prefix[12] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff
+ };
+
+ ret = ipv6_from_string(str, &addr->ip6);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /*
+ * Check for IPv4-mapped IPv6 address
+ * (e.g. ::ffff:192.0.2.128) - reparse as IPv4 if
+ * necessary
+ */
+ if (memcmp(&addr->ip6.sin6_addr.s6_addr[0],
+ ipv4_mapped_prefix,
+ sizeof(ipv4_mapped_prefix)) == 0) {
+ /* Reparse as IPv4 */
+ ret = ipv4_from_string(p+1, &addr->ip);
+ }
+ }
+
+ return ret;
+}
+
+int ctdb_sock_addr_from_string(const char *str,
+ ctdb_sock_addr *addr, bool with_port)
+{
+ char *p;
+ char s[64]; /* Much longer than INET6_ADDRSTRLEN */
+ unsigned port;
+ char *endp = NULL;
+ size_t len;
+ bool ret;
+
+ if (! with_port) {
+ ret = ip_from_string(str, addr);
+ return ret;
+ }
+
+ /* Parse out port number and then IP address */
+
+ len = strlen(str);
+ if (len >= sizeof(s)) {
+ return EINVAL;
+ }
+
+ strncpy(s, str, len+1);
+
+ p = rindex(s, ':');
+ if (p == NULL) {
+ return EINVAL;
+ }
+
+ port = strtoul(p+1, &endp, 10);
+ if (endp == p+1 || *endp != '\0') {
+ /* Empty string or trailing garbage */
+ return EINVAL;
+ }
+
+ *p = '\0';
+ ret = ip_from_string(s, addr);
+
+ ctdb_sock_addr_set_port(addr, port);
+
+ return ret;
+}
+
unsigned int ctdb_sock_addr_port(ctdb_sock_addr *addr)
{
switch (addr->sa.sa_family) {
diff --git a/ctdb/protocol/protocol_util.h b/ctdb/protocol/protocol_util.h
index b8c4f0aae42..88819366e5d 100644
--- a/ctdb/protocol/protocol_util.h
+++ b/ctdb/protocol/protocol_util.h
@@ -39,6 +39,8 @@ int ctdb_sock_addr_to_buf(char *buf, socklen_t buflen,
ctdb_sock_addr *addr, bool with_port);
const char *ctdb_sock_addr_to_string(TALLOC_CTX *mem_ctx,
ctdb_sock_addr *addr, bool with_port);
+int ctdb_sock_addr_from_string(const char *str,
+ ctdb_sock_addr *addr, bool with_port);
unsigned int ctdb_sock_addr_port(ctdb_sock_addr *addr);
void ctdb_sock_addr_set_port(ctdb_sock_addr *addr, unsigned int port);
int ctdb_sock_addr_cmp_ip(const ctdb_sock_addr *addr1,