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
This commit is contained in:
Alexander V. Chernikov 2023-01-21 14:36:23 +00:00
parent 03a1b75950
commit 0079d177ab
5 changed files with 63 additions and 21 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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