From 6cb5e1e7591da20af3a15793e022345a73e40fb7 Mon Sep 17 00:00:00 2001
From: felixdoerre <felixdoerre@users.noreply.github.com>
Date: Wed, 20 Oct 2021 19:40:00 +0200
Subject: [PATCH] libshare: nfs: pass through ipv6 addresses in bracket
 notation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Recognize when the host part of a sharenfs attribute is an ipv6
Literal and pass that through without modification.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Felix Dörre <felix@dogcraft.de>
Closes: #11171
Closes #11939
Closes: #1894
---
--- a/lib/libshare/os/linux/nfs.c
+++ b/lib/libshare/os/linux/nfs.c
@@ -180,8 +180,9 @@
 {
 	int error;
 	const char *access;
-	char *host_dup, *host, *next;
+	char *host_dup, *host, *next, *v6Literal;
 	nfs_host_cookie_t *udata = (nfs_host_cookie_t *)pcookie;
+	int cidr_len;
 
 #ifdef DEBUG
 	fprintf(stderr, "foreach_nfs_host_cb: key=%s, value=%s\n", opt, value);
@@ -204,10 +205,46 @@
 		host = host_dup;
 
 		do {
-			next = strchr(host, ':');
-			if (next != NULL) {
-				*next = '\0';
-				next++;
+			if (*host == '[') {
+				host++;
+				v6Literal = strchr(host, ']');
+				if (v6Literal == NULL) {
+					free(host_dup);
+					return (SA_SYNTAX_ERR);
+				}
+				if (v6Literal[1] == '\0') {
+					*v6Literal = '\0';
+					next = NULL;
+				} else if (v6Literal[1] == '/') {
+					next = strchr(v6Literal + 2, ':');
+					if (next == NULL) {
+						cidr_len =
+						    strlen(v6Literal + 1);
+						memmove(v6Literal,
+						    v6Literal + 1,
+						    cidr_len);
+						v6Literal[cidr_len] = '\0';
+					} else {
+						cidr_len = next - v6Literal - 1;
+						memmove(v6Literal,
+						    v6Literal + 1,
+						    cidr_len);
+						v6Literal[cidr_len] = '\0';
+						next++;
+					}
+				} else if (v6Literal[1] == ':') {
+					*v6Literal = '\0';
+					next = v6Literal + 2;
+				} else {
+					free(host_dup);
+					return (SA_SYNTAX_ERR);
+				}
+			} else {
+				next = strchr(host, ':');
+				if (next != NULL) {
+					*next = '\0';
+					next++;
+				}
 			}
 
 			error = udata->callback(udata->filename,
--- a/man/man8/zfs.8
+++ b/man/man8/zfs.8
@@ -545,7 +545,7 @@
 on the
 .Ar tank/home
 file system:
-.Dl # Nm zfs Cm set Sy sharenfs Ns = Ns ' Ns Ar rw Ns =@123.123.0.0/16,root= Ns Ar neo Ns ' tank/home
+.Dl # Nm zfs Cm set Sy sharenfs Ns = Ns ' Ns Ar rw Ns =@123.123.0.0/16:[::1],root= Ns Ar neo Ns ' tank/home
 .Pp
 If you are using DNS for host name resolution,
 specify the fully-qualified hostname.

