commit 9186b8e0fd8b76553b87d0a64b4a071c09b255c5
Author: Lars Ellenberg <lars.ellenberg@linbit.com>
Date:   Mon Dec 14 17:34:46 2015 +0100

    drbdsetup: show: fix ipv6 address output
    
    Code restructuring introduced a bug using some character buffer
    both as target and source of an sprintf().
    
    While at it, use getnameinfo rather than inet_ntop,
    we want to include the scope in the output (if any).

diff --git a/user/v84/config_flags.c b/user/v84/config_flags.c
index 3b0303f..c6f867e 100644
--- a/user/v84/config_flags.c
+++ b/user/v84/config_flags.c
@@ -526,10 +526,16 @@ void sprint_address(char *buffer, void *address, int addr_len)
 		       inet_ntoa(a.addr4.sin_addr),
 		       ntohs(a.addr4.sin_port));
 	} else if (a.addr.sa_family == AF_INET6) {
-		sprintf(buffer, "%s [%s]:%d",
-		       af_to_str(a.addr6.sin6_family),
-		       inet_ntop(a.addr6.sin6_family, &a.addr6.sin6_addr, buffer, INET6_ADDRSTRLEN),
-		       ntohs(a.addr6.sin6_port));
+		char buf2[ADDRESS_STR_MAX];
+		int n;
+		buf2[0] = 0;
+		getnameinfo(&a.addr, addr_len, buf2, sizeof(buf2),
+			NULL, 0, NI_NUMERICHOST|NI_NUMERICSERV);
+		n = snprintf(buffer, ADDRESS_STR_MAX, "%s [%s]:%d",
+			af_to_str(a.addr6.sin6_family), buf2,
+			ntohs(a.addr6.sin6_port));
+		assert(n > 0);
+		assert(n < ADDRESS_STR_MAX); /* there should be no need to truncate */
 	} else {
 		sprintf(buffer, "[unknown af=%d, len=%d]", a.addr.sa_family, addr_len);
 	}
@@ -537,8 +543,7 @@ void sprint_address(char *buffer, void *address, int addr_len)
 
 static const char *get_address(struct context_def *ctx, struct field_def *field, struct nlattr *nla)
 {
-	static char buffer[INET6_ADDRSTRLEN];
-
+	static char buffer[ADDRESS_STR_MAX];
 	sprint_address(buffer, nla_data(nla), nla_len(nla));
 
 	return buffer;
diff --git a/user/v84/config_flags.h b/user/v84/config_flags.h
index 4d6919e..4e34c3b 100644
--- a/user/v84/config_flags.h
+++ b/user/v84/config_flags.h
@@ -60,6 +60,8 @@ extern const char *double_quote_string(const char *str);
 
 /* Also used by argument processing in drbdsetup */
 extern int nla_put_address(struct msg_buff *msg, int attrtype, const char *arg);
+/* INET6_ADDRSTRLEN + 'ipv6 []:54321 + possible scope + some */
+#define ADDRESS_STR_MAX 256
 extern void sprint_address(char *buffer, void *address, int addr_len);
 extern int get_af_ssocks(int warn_and_use_default);
 
diff --git a/user/v84/drbdsetup.c b/user/v84/drbdsetup.c
index 247866e..8a4c5da 100644
--- a/user/v84/drbdsetup.c
+++ b/user/v84/drbdsetup.c
@@ -1538,8 +1538,7 @@ static int generic_get_cmd(const struct drbd_cmd *cm, int argc, char **argv)
 
 static void show_address(void* address, int addr_len)
 {
-	char buffer[INET6_ADDRSTRLEN];
-
+	char buffer[ADDRESS_STR_MAX];
 	sprint_address(buffer, address, addr_len);
 	printI("address\t\t\t%s;\n", buffer);
 }
diff --git a/user/v9/drbdsetup.c b/user/v9/drbdsetup.c
index 27a5bb6..33d39dc 100644
--- a/user/v9/drbdsetup.c
+++ b/user/v9/drbdsetup.c
@@ -2499,11 +2499,17 @@ static char *address_str(char *buffer, void* address, int addr_len)
 			 ntohs(a.addr4.sin_port));
 		return buffer;
 	} else if (a.addr.sa_family == AF_INET6) {
-		char buffer2[INET6_ADDRSTRLEN];
-		snprintf(buffer, ADDRESS_STR_MAX, "%s:[%s]:%u",
-		        af_to_str(a.addr6.sin6_family),
-		        inet_ntop(a.addr6.sin6_family, &a.addr6.sin6_addr, buffer2, INET6_ADDRSTRLEN),
+		char buf2[ADDRESS_STR_MAX];
+		int n;
+		buf2[0] = 0;
+		/* inet_ntop does not include scope info */
+		getnameinfo(&a.addr, addr_len, buf2, sizeof(buf2),
+			NULL, 0, NI_NUMERICHOST|NI_NUMERICSERV);
+		n = snprintf(buffer, ADDRESS_STR_MAX, "%s:[%s]:%u",
+		        af_to_str(a.addr6.sin6_family), buf2,
 		        ntohs(a.addr6.sin6_port));
+		assert(n > 0);
+		assert(n < ADDRESS_STR_MAX); /* there should be no need to truncate */
 		return buffer;
 	} else
 		return NULL;
