diff options
author | Martin Schwenke <martin@meltin.net> | 2017-09-11 16:39:38 +1000 |
---|---|---|
committer | Martin Schwenke <martins@samba.org> | 2017-09-19 13:30:26 +0200 |
commit | 6f1b1a05fb821d49c44195c6ff91fbe21b1b10ef (patch) | |
tree | 4a0a48f003211b0aadddb3dcc1dba86fa895d90f /ctdb/protocol | |
parent | 93668f50266ce43e591f0708bc0dcd557719e2dc (diff) | |
download | samba-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.c | 126 | ||||
-rw-r--r-- | ctdb/protocol/protocol_util.h | 2 |
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, |