git: 9234a50752cd - main - ng_ksocket: add IPv6 support for address parsing and unparsing
Date: Fri, 10 Jan 2025 20:04:19 UTC
The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=9234a50752cd47887849d4665af0f9f4abdefb5d commit 9234a50752cd47887849d4665af0f9f4abdefb5d Author: Seyed Pouria Mousavizadeh Tehrani <info@spmzt.net> AuthorDate: 2025-01-10 09:16:18 +0000 Commit: Gleb Smirnoff <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 --- 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> .\" -.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)