git: 0079d177ab69 - main - netlink: allow creating sockets with SOCK_DGRAM.

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Sat, 21 Jan 2023 14:59:07 UTC
The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=0079d177ab69168df5e103128a2b15bd8e74d4eb

commit 0079d177ab69168df5e103128a2b15bd8e74d4eb
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2023-01-21 14:36:23 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2023-01-21 14:58:19 +0000

    netlink: allow creating sockets with SOCK_DGRAM.
    
    Some existing applications setup Netlink socket with
    SOCK_DGRAM instead of SOCK_RAW. Update the manpage to clarify
    that the default way of creating the socket should be with
    SOCK_RAW. Update the code to support both SOCK_RAW and SOCK_DGRAM.
    
    Reviewed By: pauamma
    Differential Revision: https://reviews.freebsd.org/D38075
---
 share/man/man4/netlink.4          |  4 ++--
 share/man/man4/rtnetlink.4        |  2 +-
 sys/netlink/netlink_domain.c      | 44 +++++++++++++++++++++++----------------
 tests/sys/netlink/Makefile        |  1 +
 tests/sys/netlink/test_nl_core.py | 33 +++++++++++++++++++++++++++++
 5 files changed, 63 insertions(+), 21 deletions(-)

diff --git a/share/man/man4/netlink.4 b/share/man/man4/netlink.4
index 2aa4903a4594..1894de5841fe 100644
--- a/share/man/man4/netlink.4
+++ b/share/man/man4/netlink.4
@@ -34,7 +34,7 @@
 .In netlink/netlink.h
 .In netlink/netlink_route.h
 .Ft int
-.Fn socket AF_NETLINK SOCK_DGRAM int family
+.Fn socket AF_NETLINK SOCK_RAW "int family"
 .Sh DESCRIPTION
 Netlink is a user-kernel message-based communication protocol primarily used
 for network stack configuration.
@@ -293,7 +293,7 @@ This is the default level, not impacting production performance.
 Socket events such as groups memberships, privilege checks, commands and dumps
 are logged.
 This level does not incur significant performance overhead.
-.It Dv LOG_DEBUG9(9)
+.It Dv LOG_DEBUG3(9)
 All socket events, each dumped or modified entities are logged.
 Turning it on may result in significant performance overhead.
 .El
diff --git a/share/man/man4/rtnetlink.4 b/share/man/man4/rtnetlink.4
index dc40b277d934..5849508b74c2 100644
--- a/share/man/man4/rtnetlink.4
+++ b/share/man/man4/rtnetlink.4
@@ -34,7 +34,7 @@
 .In netlink/netlink.h
 .In netlink/netlink_route.h
 .Ft int
-.Fn socket AF_NETLINK SOCK_DGRAM NETLINK_ROUTE
+.Fn socket AF_NETLINK SOCK_RAW NETLINK_ROUTE
 .Sh DESCRIPTION
 The
 .Dv NETLINK_ROUTE
diff --git a/sys/netlink/netlink_domain.c b/sys/netlink/netlink_domain.c
index f35cc7f09991..4d34fd381c39 100644
--- a/sys/netlink/netlink_domain.c
+++ b/sys/netlink/netlink_domain.c
@@ -698,31 +698,39 @@ nl_setsbopt(struct socket *so, struct sockopt *sopt)
 	return (result ? 0 : ENOBUFS);
 }
 
-static struct protosw netlinksw = {
-	.pr_type = SOCK_RAW,
-	.pr_flags = PR_ATOMIC | PR_ADDR | PR_WANTRCVD,
-	.pr_ctloutput = nl_ctloutput,
-	.pr_setsbopt = nl_setsbopt,
-	.pr_abort = nl_pru_abort,
-	.pr_attach = nl_pru_attach,
-	.pr_bind = nl_pru_bind,
-	.pr_connect = nl_pru_connect,
-	.pr_detach = nl_pru_detach,
-	.pr_disconnect = nl_pru_disconnect,
-	.pr_peeraddr = nl_pru_peeraddr,
-	.pr_send = nl_pru_send,
-	.pr_rcvd = nl_pru_rcvd,
-	.pr_shutdown = nl_pru_shutdown,
-	.pr_sockaddr = nl_pru_sockaddr,
+#define	NETLINK_PROTOSW						\
+	.pr_flags = PR_ATOMIC | PR_ADDR | PR_WANTRCVD,		\
+	.pr_ctloutput = nl_ctloutput,				\
+	.pr_setsbopt = nl_setsbopt,				\
+	.pr_abort = nl_pru_abort,				\
+	.pr_attach = nl_pru_attach,				\
+	.pr_bind = nl_pru_bind,					\
+	.pr_connect = nl_pru_connect,				\
+	.pr_detach = nl_pru_detach,				\
+	.pr_disconnect = nl_pru_disconnect,			\
+	.pr_peeraddr = nl_pru_peeraddr,				\
+	.pr_send = nl_pru_send,					\
+	.pr_rcvd = nl_pru_rcvd,					\
+	.pr_shutdown = nl_pru_shutdown,				\
+	.pr_sockaddr = nl_pru_sockaddr,				\
 	.pr_close = nl_pru_close
+
+static struct protosw netlink_raw_sw = {
+	.pr_type = SOCK_RAW,
+	NETLINK_PROTOSW
+};
+
+static struct protosw netlink_dgram_sw = {
+	.pr_type = SOCK_DGRAM,
+	NETLINK_PROTOSW
 };
 
 static struct domain netlinkdomain = {
 	.dom_family = PF_NETLINK,
 	.dom_name = "netlink",
 	.dom_flags = DOMF_UNLOADABLE,
-	.dom_nprotosw =		1,
-	.dom_protosw =		{ &netlinksw },
+	.dom_nprotosw =		2,
+	.dom_protosw =		{ &netlink_raw_sw, &netlink_dgram_sw },
 };
 
 DOMAIN_SET(netlink);
diff --git a/tests/sys/netlink/Makefile b/tests/sys/netlink/Makefile
index 87cee15c9d33..880e5e6e4007 100644
--- a/tests/sys/netlink/Makefile
+++ b/tests/sys/netlink/Makefile
@@ -6,6 +6,7 @@ WARNS?=		1
 TESTSDIR=       ${TESTSBASE}/sys/netlink
 
 ATF_TESTS_C +=	test_snl
+ATF_TESTS_PYTEST +=	test_nl_core.py
 ATF_TESTS_PYTEST +=	test_rtnl_iface.py
 ATF_TESTS_PYTEST +=	test_rtnl_ifaddr.py
 
diff --git a/tests/sys/netlink/test_nl_core.py b/tests/sys/netlink/test_nl_core.py
new file mode 100644
index 000000000000..7af421a929dc
--- /dev/null
+++ b/tests/sys/netlink/test_nl_core.py
@@ -0,0 +1,33 @@
+import errno
+import socket
+
+import pytest
+from atf_python.sys.net.netlink import NetlinkTestTemplate
+from atf_python.sys.net.netlink import NlConst
+from atf_python.sys.net.vnet import SingleVnetTestTemplate
+
+
+class TestNlCore(NetlinkTestTemplate, SingleVnetTestTemplate):
+    @pytest.mark.parametrize(
+        "params",
+        [
+            pytest.param({"type": socket.SOCK_RAW}, id="SOCK_RAW"),
+            pytest.param({"type": socket.SOCK_DGRAM}, id="SOCK_DGRAM"),
+        ],
+    )
+    def test_socket_type(self, params):
+        s = socket.socket(NlConst.AF_NETLINK, params["type"], NlConst.NETLINK_ROUTE)
+        s.close()
+
+    @pytest.mark.parametrize(
+        "params",
+        [
+            pytest.param({"type": socket.SOCK_STREAM}, id="SOCK_STREAM"),
+            pytest.param({"type": socket.SOCK_RDM}, id="SOCK_RDM"),
+            pytest.param({"type": socket.SOCK_SEQPACKET}, id="SOCK_SEQPACKET"),
+        ],
+    )
+    def test_socket_type_unsup(self, params):
+        with pytest.raises(OSError) as exc_info:
+            socket.socket(NlConst.AF_NETLINK, params["type"], NlConst.NETLINK_ROUTE)
+        assert exc_info.value.errno == errno.EPROTOTYPE