1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

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>
This commit is contained in:
Martin Schwenke 2017-09-11 16:39:38 +10:00 committed by Martin Schwenke
parent 93668f5026
commit 6f1b1a05fb
3 changed files with 168 additions and 22 deletions

View File

@ -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) {

View File

@ -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,

View File

@ -26,33 +26,42 @@
#include "protocol/protocol_types.c"
#include "protocol/protocol_util.c"
#include "common/system_util.c"
/*
* Test parsing of IPs, conversion to string
*/
/* Test parsing of IPs, conversion to string */
static void test_sock_addr_to_string(const char *ip, bool with_port)
{
ctdb_sock_addr sa;
const char *s;
bool status;
int ret;
if (with_port) {
status = parse_ip_port(ip, &sa);
} else {
status = parse_ip(ip, NULL, 0, &sa);
}
assert(status);
ret = ctdb_sock_addr_from_string(ip, &sa, with_port);
assert(ret == 0);
s = ctdb_sock_addr_to_string(NULL, &sa, with_port);
assert(strcmp(ip, s) == 0);
talloc_free(discard_const(s));
}
static void test_sock_addr_cmp(const char *ip1, const char *ip2, int res)
static void test_sock_addr_from_string_bad(const char *ip, bool with_port)
{
ctdb_sock_addr sa;
int ret;
ret = ctdb_sock_addr_from_string(ip, &sa, with_port);
assert(ret != 0);
}
static void test_sock_addr_cmp(const char *ip1, const char *ip2,
bool with_port, int res)
{
ctdb_sock_addr sa1, sa2;
int ret;
assert(parse_ip(ip1, NULL, 0, &sa1));
assert(parse_ip(ip2, NULL, 0, &sa2));
ret = ctdb_sock_addr_from_string(ip1, &sa1, with_port);
assert(ret == 0);
ret = ctdb_sock_addr_from_string(ip2, &sa2, with_port);
assert(ret == 0);
ret = ctdb_sock_addr_cmp(&sa1, &sa2);
if (ret < 0) {
ret = -1;
@ -77,20 +86,29 @@ int main(int argc, char *argv[])
test_sock_addr_to_string("192.168.2.1:123", true);
test_sock_addr_to_string("fe80::6af7:28ff:fefa:d136:234", true);
test_sock_addr_from_string_bad("0.0.0", false);
test_sock_addr_from_string_bad("0.0.0:0", true);
test_sock_addr_from_string_bad("fe80::6af7:28ff:fefa:d136", true);
test_sock_addr_from_string_bad("junk", false);
test_sock_addr_from_string_bad("0.0.0.0:0 trailing junk", true);
test_sock_addr_cmp("127.0.0.1", "127.0.0.1" , 0);
test_sock_addr_cmp("127.0.0.1", "127.0.0.2" , -1);
test_sock_addr_cmp("127.0.0.2", "127.0.0.1" , 1);
test_sock_addr_cmp("127.0.1.2", "127.0.2.1" , -1);
test_sock_addr_cmp("127.0.2.1", "127.0.1.2" , 1);
test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136", "127.0.1.2" , 1);
test_sock_addr_cmp("127.0.0.1", "127.0.0.1" , false, 0);
test_sock_addr_cmp("127.0.0.1", "127.0.0.2" , false, -1);
test_sock_addr_cmp("127.0.0.2", "127.0.0.1" , false, 1);
test_sock_addr_cmp("127.0.1.2", "127.0.2.1" , false, -1);
test_sock_addr_cmp("127.0.2.1", "127.0.1.2" , false, 1);
test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136", "127.0.1.2" , false, 1);
test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136",
"fe80::6af7:28ff:fefa:d136" , 0);
"fe80::6af7:28ff:fefa:d136" , false, 0);
test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136",
"fe80::6af7:28ff:fefa:d137" , -1);
"fe80::6af7:28ff:fefa:d137" , false, -1);
test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136",
"fe80:0000:0000:0000:6af7:28ff:fefa:d136" , 0);
test_sock_addr_cmp("::ffff:192.0.2.128", "192.0.2.128", 0);
"fe80:0000:0000:0000:6af7:28ff:fefa:d136" ,
false, 0);
test_sock_addr_cmp("::ffff:192.0.2.128", "192.0.2.128", false, 0);
test_sock_addr_cmp("127.0.0.1:123", "127.0.0.1:124" , true, -1);
test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136:123",
"fe80::6af7:28ff:fefa:d136:122" , true, 1);
return 0;
}