mirror of
https://github.com/versity/scoutfs.git
synced 2025-12-23 05:25:18 +00:00
Add ipv6 support to scoutfs userspace utility.
This change adds ipv6 support to various scoutfs sub-commands, allowing users to mkfs, print and change-quorum-config using ipv6 addresses, and modifies the outputs. Any ipv6 address/port is displayed as [::1]:5000 to comply with the related RFC's. Input strings remain consistent as the quorum config input value is comma-separated already, not posing any issues. Signed-off-by: Auke Kok <auke.kok@versity.com>
This commit is contained in:
@@ -160,15 +160,16 @@ int parse_timespec(char *str, struct timespec *ts)
|
||||
* Parse a quorum slot specification string "NR,ADDR,PORT" into its
|
||||
* component parts. We use sscanf to both parse the leading NR and
|
||||
* trailing PORT integers, and to pull out the inner ADDR string which
|
||||
* is then parsed to make sure that it's a valid unicast ipv4 address.
|
||||
* is then parsed to make sure that it's a valid unicast ip address.
|
||||
* We require that all components be specified, and sccanf will check
|
||||
* this by the number of matches it returns.
|
||||
*/
|
||||
int parse_quorum_slot(struct scoutfs_quorum_slot *slot, char *arg)
|
||||
{
|
||||
#define ADDR_CHARS 45 /* max ipv6 */
|
||||
char addr[ADDR_CHARS + 1] = {'\0',};
|
||||
#define ADDR_CHARS 45 /* (INET6_ADDRSTRLEN - 1) */
|
||||
char addr[INET6_ADDRSTRLEN] = {'\0',};
|
||||
struct in_addr in;
|
||||
struct in6_addr in6;
|
||||
int port;
|
||||
int parsed;
|
||||
int nr;
|
||||
@@ -206,15 +207,25 @@ int parse_quorum_slot(struct scoutfs_quorum_slot *slot, char *arg)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (inet_aton(addr, &in) == 0 || htonl(in.s_addr) == 0 ||
|
||||
htonl(in.s_addr) == UINT_MAX) {
|
||||
printf("invalid ipv4 address '%s' in quorum slot '%s'\n",
|
||||
addr, arg);
|
||||
return -EINVAL;
|
||||
if (inet_pton(AF_INET, addr, &in) == 1) {
|
||||
if (htonl(in.s_addr) == 0 || htonl(in.s_addr) == UINT_MAX) {
|
||||
printf("invalid ipv4 address '%s' in quorum slot '%s'\n",
|
||||
addr, arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
slot->addr.v4.family = cpu_to_le16(SCOUTFS_AF_IPV4);
|
||||
slot->addr.v4.addr = cpu_to_le32(htonl(in.s_addr));
|
||||
slot->addr.v4.port = cpu_to_le16(port);
|
||||
} else if (inet_pton(AF_INET6, addr, &in6) == 1) {
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&in6) || IN6_IS_ADDR_MULTICAST(&in6)) {
|
||||
printf("invalid ipv6 address '%s' in quorum slot '%s'\n",
|
||||
addr, arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
slot->addr.v6.family = cpu_to_le16(SCOUTFS_AF_IPV6);
|
||||
memcpy(slot->addr.v6.addr, &in6, 16);
|
||||
slot->addr.v6.port = cpu_to_le16(port);
|
||||
}
|
||||
|
||||
slot->addr.v4.family = cpu_to_le16(SCOUTFS_AF_IPV4);
|
||||
slot->addr.v4.addr = cpu_to_le32(htonl(in.s_addr));
|
||||
slot->addr.v4.port = cpu_to_le16(port);
|
||||
return nr;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "srch.h"
|
||||
#include "leaf_item_hash.h"
|
||||
#include "dev.h"
|
||||
#include "quorum.h"
|
||||
|
||||
static void print_block_header(struct scoutfs_block_header *hdr, int size)
|
||||
{
|
||||
@@ -400,12 +401,20 @@ static int print_mounted_client_entry(struct scoutfs_key *key, u64 seq, u8 flags
|
||||
{
|
||||
struct scoutfs_mounted_client_btree_val *mcv = val;
|
||||
struct in_addr in;
|
||||
char ip6addr[INET6_ADDRSTRLEN];
|
||||
|
||||
memset(&in, 0, sizeof(in));
|
||||
in.s_addr = htonl(le32_to_cpu(mcv->addr.v4.addr));
|
||||
if (mcv->addr.v4.family == cpu_to_le16(SCOUTFS_AF_IPV4)) {
|
||||
in.s_addr = htonl(le32_to_cpu(mcv->addr.v4.addr));
|
||||
|
||||
printf(" rid %016llx ipv4_addr %s flags 0x%x\n",
|
||||
le64_to_cpu(key->skmc_rid), inet_ntoa(in), mcv->flags);
|
||||
printf(" rid %016llx ipv4_addr %s flags 0x%x\n",
|
||||
le64_to_cpu(key->skmc_rid), inet_ntoa(in), mcv->flags);
|
||||
} else if (mcv->addr.v6.family == cpu_to_le16(SCOUTFS_AF_IPV6)) {
|
||||
printf(" rid %016llx ipv6_addr %s flags 0x%x\n",
|
||||
le64_to_cpu(key->skmc_rid),
|
||||
inet_ntop(AF_INET, mcv->addr.v6.addr, ip6addr, INET6_ADDRSTRLEN),
|
||||
mcv->flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -891,26 +900,40 @@ static int print_btree_leaf_items(int fd, struct scoutfs_super_block *super,
|
||||
static char *alloc_addr_str(union scoutfs_inet_addr *ia)
|
||||
{
|
||||
struct in_addr addr;
|
||||
char ip6addr[INET6_ADDRSTRLEN];
|
||||
char *quad;
|
||||
char *str;
|
||||
int len;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.s_addr = htonl(le32_to_cpu(ia->v4.addr));
|
||||
quad = inet_ntoa(addr);
|
||||
if (quad == NULL)
|
||||
return NULL;
|
||||
if (le16_to_cpu(ia->v4.family) == SCOUTFS_AF_IPV4) {
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.s_addr = htonl(le32_to_cpu(ia->v4.addr));
|
||||
quad = inet_ntoa(addr);
|
||||
if (quad == NULL)
|
||||
return NULL;
|
||||
|
||||
len = snprintf(NULL, 0, "%s:%u", quad, le16_to_cpu(ia->v4.port));
|
||||
if (len < 1 || len > 22)
|
||||
return NULL;
|
||||
len = snprintf(NULL, 0, "%s:%u", quad, le16_to_cpu(ia->v4.port));
|
||||
if (len < 1 || len > 22)
|
||||
return NULL;
|
||||
|
||||
len++; /* null */
|
||||
str = malloc(len);
|
||||
if (!str)
|
||||
return NULL;
|
||||
len++; /* null */
|
||||
str = malloc(len);
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
snprintf(str, len, "%s:%u", quad, le16_to_cpu(ia->v4.port));
|
||||
snprintf(str, len, "%s:%u", quad, le16_to_cpu(ia->v4.port));
|
||||
} else if (le16_to_cpu(ia->v6.family) == SCOUTFS_AF_IPV6) {
|
||||
if (inet_ntop(AF_INET6, ia->v6.addr, ip6addr, INET6_ADDRSTRLEN) == NULL)
|
||||
return NULL;
|
||||
|
||||
len = strlen(ip6addr) + 9; /* "[]:\0" (4) plus max strlen(u16) (5) */
|
||||
str = malloc(len);
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
snprintf(str, len, "[%s]:%u", ip6addr, le16_to_cpu(ia->v6.port));
|
||||
} else
|
||||
return NULL;
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -1026,7 +1049,7 @@ static void print_super_block(struct scoutfs_super_block *super, u64 blkno)
|
||||
printf(" quorum config version %llu\n",
|
||||
le64_to_cpu(super->qconf.version));
|
||||
for (i = 0; i < array_size(super->qconf.slots); i++) {
|
||||
if (super->qconf.slots[i].addr.v4.family != cpu_to_le16(SCOUTFS_AF_IPV4))
|
||||
if (!quorum_slot_present(super, i))
|
||||
continue;
|
||||
|
||||
addr = alloc_addr_str(&super->qconf.slots[i].addr);
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
|
||||
bool quorum_slot_present(struct scoutfs_super_block *super, int i)
|
||||
{
|
||||
return super->qconf.slots[i].addr.v4.family == cpu_to_le16(SCOUTFS_AF_IPV4);
|
||||
return ((super->qconf.slots[i].addr.v4.family == cpu_to_le16(SCOUTFS_AF_IPV4)) ||
|
||||
(super->qconf.slots[i].addr.v6.family == cpu_to_le16(SCOUTFS_AF_IPV6)));
|
||||
}
|
||||
|
||||
bool valid_quorum_slots(struct scoutfs_quorum_slot *slots)
|
||||
@@ -18,35 +19,40 @@ bool valid_quorum_slots(struct scoutfs_quorum_slot *slots)
|
||||
struct in_addr in;
|
||||
bool valid = true;
|
||||
char *addr;
|
||||
char ip6addr[INET6_ADDRSTRLEN];
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < SCOUTFS_QUORUM_MAX_SLOTS; i++) {
|
||||
if (slots[i].addr.v4.family == cpu_to_le16(SCOUTFS_AF_NONE))
|
||||
continue;
|
||||
|
||||
if (slots[i].addr.v4.family != cpu_to_le16(SCOUTFS_AF_IPV4)) {
|
||||
if (slots[i].addr.v4.family == cpu_to_le16(SCOUTFS_AF_IPV4)) {
|
||||
for (j = i + 1; j < SCOUTFS_QUORUM_MAX_SLOTS; j++) {
|
||||
if (slots[i].addr.v4.addr == slots[j].addr.v4.addr &&
|
||||
slots[i].addr.v4.port == slots[j].addr.v4.port) {
|
||||
in.s_addr =
|
||||
htonl(le32_to_cpu(slots[i].addr.v4.addr));
|
||||
addr = inet_ntoa(in);
|
||||
fprintf(stderr, "quorum slot nr %u and %u have the same address %s:%u\n",
|
||||
i, j, addr,
|
||||
le16_to_cpu(slots[i].addr.v4.port));
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
} else if (slots[i].addr.v6.family == cpu_to_le16(SCOUTFS_AF_IPV6)) {
|
||||
for (j = i + 1; j < SCOUTFS_QUORUM_MAX_SLOTS; j++) {
|
||||
if ((IN6_ARE_ADDR_EQUAL(slots[i].addr.v6.addr, slots[j].addr.v6.addr)) &&
|
||||
(slots[i].addr.v6.port == slots[j].addr.v6.port)) {
|
||||
fprintf(stderr, "quorum slot nr %u and %u have the same address [%s]:%u\n",
|
||||
i, j,
|
||||
inet_ntop(AF_INET6, slots[i].addr.v6.addr, ip6addr, INET6_ADDRSTRLEN),
|
||||
le16_to_cpu(slots[i].addr.v6.port));
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
} else if (slots[i].addr.v6.family != cpu_to_le16(SCOUTFS_AF_NONE)) {
|
||||
fprintf(stderr, "quorum slot nr %u has invalid family %u\n",
|
||||
i, le16_to_cpu(slots[i].addr.v4.family));
|
||||
valid = false;
|
||||
}
|
||||
|
||||
for (j = i + 1; j < SCOUTFS_QUORUM_MAX_SLOTS; j++) {
|
||||
if (slots[i].addr.v4.family != cpu_to_le16(SCOUTFS_AF_IPV4))
|
||||
continue;
|
||||
|
||||
if (slots[i].addr.v4.addr == slots[j].addr.v4.addr &&
|
||||
slots[i].addr.v4.port == slots[j].addr.v4.port) {
|
||||
|
||||
in.s_addr =
|
||||
htonl(le32_to_cpu(slots[i].addr.v4.addr));
|
||||
addr = inet_ntoa(in);
|
||||
fprintf(stderr, "quorum slot nr %u and %u have the same address %s:%u\n",
|
||||
i, j, addr,
|
||||
le16_to_cpu(slots[i].addr.v4.port));
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return valid;
|
||||
@@ -61,19 +67,23 @@ void print_quorum_slots(struct scoutfs_quorum_slot *slots, int nr, char *indent)
|
||||
{
|
||||
struct scoutfs_quorum_slot *sl;
|
||||
struct in_addr in;
|
||||
char ip6addr[INET6_ADDRSTRLEN];
|
||||
bool first = true;
|
||||
int i;
|
||||
|
||||
for (i = 0, sl = slots; i < SCOUTFS_QUORUM_MAX_SLOTS; i++, sl++) {
|
||||
if (sl->addr.v4.family == cpu_to_le16(SCOUTFS_AF_IPV4)) {
|
||||
in.s_addr = htonl(le32_to_cpu(sl->addr.v4.addr));
|
||||
printf("%s%u: %s:%u\n", first ? "" : indent,
|
||||
i, inet_ntoa(in), le16_to_cpu(sl->addr.v4.port));
|
||||
|
||||
if (sl->addr.v4.family != cpu_to_le16(SCOUTFS_AF_IPV4))
|
||||
continue;
|
||||
|
||||
in.s_addr = htonl(le32_to_cpu(sl->addr.v4.addr));
|
||||
printf("%s%u: %s:%u\n", first ? "" : indent,
|
||||
i, inet_ntoa(in), le16_to_cpu(sl->addr.v4.port));
|
||||
|
||||
first = false;
|
||||
first = false;
|
||||
} else if (sl->addr.v6.family == cpu_to_le16(SCOUTFS_AF_IPV6)) {
|
||||
printf("%s%u: [%s]:%u\n", first ? "" : indent, i,
|
||||
inet_ntop(AF_INET6, sl->addr.v6.addr, ip6addr, INET6_ADDRSTRLEN),
|
||||
le16_to_cpu(sl->addr.v6.port));
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user