Re: 9234a50752cd - main - ng_ksocket: add IPv6 support for address parsing and unparsing

From: Ravi Pokala <rpokala_at_freebsd.org>
Date: Sat, 11 Jan 2025 22:52:04 UTC
Hi Gleb,

I believe this change breaks LINT-NOINET6 and LINT-NOIP:

================================================================
>>> stage 3.1: building everything
--------------------------------------------------------------
linking kernel
ld: error: undefined symbol: in6_getscope
>>> referenced by ng_ksocket.c
>>>               ng_ksocket.o:(ng_ksocket_sockaddr_parse)

ld: error: undefined symbol: in6_getscopezone
>>> referenced by ng_ksocket.c
>>>               ng_ksocket.o:(ng_ksocket_sockaddr_parse)
--- kernel ---
*** [kernel] Error code 1
================================================================

Thanks,

Ravi (rpokala@0

-----Original Message-----
From: <owner-src-committers@freebsd.org <mailto:owner-src-committers@freebsd.org>> on behalf of Gleb Smirnoff <glebius@FreeBSD.org <mailto:glebius@FreeBSD.org>>
Date: Friday, January 10, 2025 at 12:04
To: <src-committers@FreeBSD.org <mailto:src-committers@FreeBSD.org>>, <dev-commits-src-all@FreeBSD.org <mailto:dev-commits-src-all@FreeBSD.org>>, <dev-commits-src-main@FreeBSD.org <mailto:dev-commits-src-main@FreeBSD.org>>
Subject: git: 9234a50752cd - main - ng_ksocket: add IPv6 support for address parsing and unparsing


The branch main has been updated by glebius:


URL: https://cgit.FreeBSD.org/src/commit/?id=9234a50752cd47887849d4665af0f9f4abdefb5d <https://cgit.FreeBSD.org/src/commit/?id=9234a50752cd47887849d4665af0f9f4abdefb5d>


commit 9234a50752cd47887849d4665af0f9f4abdefb5d
Author: Seyed Pouria Mousavizadeh Tehrani <info@spmzt.net <mailto:info@spmzt.net>>
AuthorDate: 2025-01-10 09:16:18 +0000
Commit: Gleb Smirnoff <glebius@FreeBSD.org <mailto:glebius@FreeBSD.org>>
CommitDate: 2025-01-10 20:00:58 +0000


ng_ksocket: add IPv6 support for address parsing and unparsing


Differential Revision: https://reviews.freebsd.org/D48204 <https://reviews.freebsd.org/D48204>
---
share/man/man4/ng_ksocket.4 | 13 +++++--
sys/netgraph/ng_ksocket.c | 94 ++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 98 insertions(+), 9 deletions(-)


diff --git a/share/man/man4/ng_ksocket.4 b/share/man/man4/ng_ksocket.4
index 1f32d39dc7d0..bb653c3688ad 100644
--- a/share/man/man4/ng_ksocket.4
+++ b/share/man/man4/ng_ksocket.4
@@ -32,7 +32,7 @@
.\"
.\" Author: Archie Cobbs <archie@FreeBSD.org <mailto:archie@FreeBSD.org>>
.\"
-.Dd January 9, 2012
+.Dd January 9, 2025
.Dt NG_KSOCKET 4
.Os
.Sh NAME
@@ -183,7 +183,8 @@ in the argument field, the normal
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 @@ the protocol family name, followed by a slash, followed by the actual
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 @@ Examples:
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
diff --git a/sys/netgraph/ng_ksocket.c b/sys/netgraph/ng_ksocket.c
index 3e4427f9e387..43a2747224f3 100644
--- 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 @@ static const struct ng_ksocket_alias ng_ksocket_protos[] = {
{ "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 @@ ng_ksocket_sockaddr_parse(const struct ng_parse_type *type,
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 @@ ng_ksocket_sockaddr_unparse(const struct ng_parse_type *type,
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)