[Differential] D48204: Add IPv6 support for address parsing and unparsing in ng_ksocket.

"p.mousavizadeh_protonmail.com (Seyed Pouria Mousavizadeh Tehrani)" <[email protected]>
Newsgroups gmane.os.freebsd.devel.net
Message-ID <[email protected]>
p.mousavizadeh_protonmail.com created this revision.
p.mousavizadeh_protonmail.com added reviewers: manpages, network.
p.mousavizadeh_protonmail.com added a project: network.
Herald added subscribers: glebius, melifaro, donner, imp.
p.mousavizadeh_protonmail.com requested review of this revision.

REVISION SUMMARY
  Add IPv6 support for address parsing and unparsing in ng_ksocket.
  
  - Fix issues related to D23788 <https://reviews.freebsd.org/D23788>.
  - Validate square brackets as a requirement. (src, man)
  
  Co-authored by: Neel Chauhan <neel AT neelc DOT org>
  
  Note: Phabricator won't let me use the update diff function from the original revision.

TEST PLAN
  Here is my current netflow export configuration and it works:
  
    kldstat -qm ng_netflow || kldload ng_netflow
    kldstat -qm ng_ether || kldload ng_ether
    kldload ./ng_ksocket.ko
    ngctl mkpeer vtnet0: netflow lower iface0
    ngctl name vtnet0:lower netflow          
    ngctl connect vtnet0: netflow: upper out0
    ngctl mkpeer netflow: ksocket export9 inet6/dgram/udp6
    ngctl name netflow:export9 ngk
    ngctl msg ngk: connect inet6/[fdb5:c59b:114e:8db4::1]:4444
  
  I have tested this for tcp6 protocol, msg bind, and link-local with [fe80::1%vtnet0]:4444.

REPOSITORY
  rG FreeBSD src repository

REVISION DETAIL
  https://reviews.freebsd.org/D48204

AFFECTED FILES
  share/man/man4/ng_ksocket.4
  sys/netgraph/ng_ksocket.c

EMAIL PREFERENCES
  https://reviews.freebsd.org/settings/panel/emailpreferences/

To: p.mousavizadeh_protonmail.com, #manpages, #network
Cc: imp, nc, donner, freebsd-net-list, melifaro, glebius, #src_committers, p.mousavizadeh_protonmail.com, ghislain_smartix.llc, konrad.kreciwilk_korbank.pl, cmiller_netapp.com, rajeshasp, mmacy, kpraveen.lkml_gmail.com, chris_cretaforce.gr, simonvella_gmail.com, novice_techie.com, herbert_mailbox.org, tommi.pernila_iki.fi, zec, delphij, pstef
D48204.148402.patch (text/x-patch, 4.3 KB)
diff --git a/sys/netgraph/ng_ksocket.c b/sys/netgraph/ng_ksocket.c
--- a/sys/netgraph/ng_ksocket.c
+++ b/sys/netgraph/ng_ksocket.c
@@ -58,6 +58,9 @@
 #include <sys/uio.h>
 #include <sys/un.h>
 
+#include <net/if.h>
+#include <net/if_var.h>
+
 #include <netgraph/ng_message.h>
 #include <netgraph/netgraph.h>
 #include <netgraph/ng_parse.h>
@@ -66,6 +69,8 @@
 #include <netinet/in.h>
 #include <netinet/ip.h>
 
+#include <netinet6/scope6_var.h>
+
 #ifdef NG_SEPARATE_MALLOC
 static MALLOC_DEFINE(M_NETGRAPH_KSOCKET, "netgraph_ksock",
     "netgraph ksock node");
@@ -147,6 +152,19 @@
 	{ "swipe",	IPPROTO_SWIPE,		PF_INET		},
 	{ "encap",	IPPROTO_ENCAP,		PF_INET		},
 	{ "pim",	IPPROTO_PIM,		PF_INET		},
+	{ "ip6",	IPPROTO_IPV6,		PF_INET6	},
+	{ "raw6",	IPPROTO_RAW,		PF_INET6	},
+	{ "icmp6",	IPPROTO_ICMPV6,		PF_INET6	},
+	{ "igmp6",	IPPROTO_IGMP,		PF_INET6	},
+	{ "tcp6",	IPPROTO_TCP,		PF_INET6	},
+	{ "udp6",	IPPROTO_UDP,		PF_INET6	},
+	{ "gre6",	IPPROTO_GRE,		PF_INET6	},
+	{ "esp6",	IPPROTO_ESP,		PF_INET6	},
+	{ "ah6",	IPPROTO_AH,		PF_INET6	},
+	{ "swipe6",	IPPROTO_SWIPE,		PF_INET6	},
+	{ "encap6",	IPPROTO_ENCAP,		PF_INET6	},
+	{ "divert6",	IPPROTO_DIVERT,		PF_INET6	},
+	{ "pim6",	IPPROTO_PIM,		PF_INET6	},
 	{ NULL,		-1					},
 };
 
@@ -296,9 +314,58 @@
 		break;
 	    }
 
-#if 0
-	case PF_INET6:	/* XXX implement this someday */
-#endif
+	case PF_INET6:
+	    {
+		struct sockaddr_in6 *const sin6 = (struct sockaddr_in6 *)sa;
+		char *eptr;
+		char addr[INET6_ADDRSTRLEN];
+		char ifname[16];
+		u_long port;
+		bool hasifname = true;
+
+		/* RFC 3986 Section 3.2.2, Validate IP literal within square brackets. */
+		if (s[*off] == '[' && (strstr(&s[*off], "]")))
+			(*off)++;
+		else
+			return (EINVAL);
+		if ((eptr = strstr(&s[*off], "%")) == NULL) {
+			hasifname = false;
+			eptr = strstr(&s[*off], "]");
+		}
+		snprintf(addr, eptr - (s + *off) + 1, "%s", &s[*off]);
+		*off += (eptr - (s + *off));
+		if (!inet_pton(AF_INET6, addr, &sin6->sin6_addr))
+			return (EINVAL);
+
+		if (hasifname) {
+			uint16_t scope;
+
+			eptr = strstr(&s[*off], "]");
+			(*off)++;
+			snprintf(ifname, eptr - (s + *off) + 1, "%s", &s[*off]);
+			*off += (eptr - (s + *off));
+
+			if (sin6->sin6_addr.s6_addr16[0] != IPV6_ADDR_INT16_ULL)
+				return (EINVAL);
+			scope = in6_getscope(&sin6->sin6_addr);
+			sin6->sin6_scope_id =
+			    in6_getscopezone(ifunit(ifname), scope);
+		}
+
+		(*off)++;
+		if (s[*off] == ':') {
+			(*off)++;
+			port = strtoul(s + *off, &eptr, 10);
+			if (port > 0xffff || eptr == s + *off)
+				return (EINVAL);
+			*off += (eptr - (s + *off));
+			sin6->sin6_port = htons(port);
+		} else
+			sin6->sin6_port = 0;
+
+		sin6->sin6_len = sizeof(*sin6);
+		break;
+	    }
 
 	default:
 		return (EINVAL);
@@ -358,9 +425,24 @@
 		return(0);
 	    }
 
-#if 0
-	case PF_INET6:	/* XXX implement this someday */
-#endif
+	case PF_INET6:
+	    {
+		const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
+		char addr[INET6_ADDRSTRLEN];
+
+		inet_ntop(AF_INET6, &sin6->sin6_addr, addr, INET6_ADDRSTRLEN);
+		slen += snprintf(cbuf, cbuflen, "inet6/[%s]", addr);
+
+		if (sin6->sin6_port != 0) {
+			slen += snprintf(cbuf + strlen(cbuf),
+			    cbuflen - strlen(cbuf), ":%d",
+			    (u_int)ntohs(sin6->sin6_port));
+		}
+		if (slen >= cbuflen)
+			return (ERANGE);
+		*off += sizeof(*sin6);
+		return(0);
+	    }
 
 	default:
 		return (*ng_ksocket_generic_sockaddr_type.supertype->unparse)
diff --git a/share/man/man4/ng_ksocket.4 b/share/man/man4/ng_ksocket.4
--- a/share/man/man4/ng_ksocket.4
+++ b/share/man/man4/ng_ksocket.4
@@ -183,7 +183,8 @@
 equivalent of the C structure
 is an acceptable form.
 For the
-.Dv PF_INET
+.Dv PF_INET ,
+.Dv PF_INET6
 and
 .Dv PF_LOCAL
 address families, a more convenient form is also used, which is
@@ -191,7 +192,11 @@
 address.
 For
 .Dv PF_INET ,
-the address is an IP address followed by an optional colon and port number.
+the address is an IPv4 address followed by an optional colon and port number.
+For
+.Dv PF_INET6 ,
+the address is an IPv6 address enclosed in square brackets followed
+by an optional colon and port number.
 For
 .Dv PF_LOCAL ,
 the address is the pathname as a doubly quoted string.
@@ -202,6 +207,8 @@
 local/"/tmp/foo.socket"
 .It Dv PF_INET
 inet/192.168.1.1:1234
+.It Dv PF_INET6
+inet6/[2001::1]:1234
 .It Other
 .Dv "\&{ family=16 len=16 data=[0x70 0x00 0x01 0x23] \&}"
 .El
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.