diff --git a/test/zdtm.sh b/test/zdtm.sh index 69bfa0b61..36ae94d1f 100755 --- a/test/zdtm.sh +++ b/test/zdtm.sh @@ -85,6 +85,7 @@ static/fdt_shared static/file_locks00 static/file_locks01 static/sigpending +static/sk-netlink " # Duplicate list with ns/ prefix TEST_LIST=$TEST_LIST$(echo $TEST_LIST | tr ' ' '\n' | sed 's#^#ns/#') diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile index e6c71c309..ff1277d6c 100644 --- a/test/zdtm/live/static/Makefile +++ b/test/zdtm/live/static/Makefile @@ -90,6 +90,7 @@ TST_NOFILE = \ child_opened_proc \ posix_timers \ sigpending \ + sk-netlink \ # jobctl00 \ TST_FILE = \ diff --git a/test/zdtm/live/static/sk-netlink.c b/test/zdtm/live/static/sk-netlink.c new file mode 100644 index 000000000..7b384adb0 --- /dev/null +++ b/test/zdtm/live/static/sk-netlink.c @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include + +#include "zdtmtst.h" + +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + +#define UDEV_MONITOR_TEST 32 + +const char *test_doc = "Support of netlink sockets"; +const char *test_author = "Andrew Vagin "; + +int main(int argc, char ** argv) +{ + int ssk, bsk, csk, dsk; + struct sockaddr_nl addr; + struct msghdr msg; + struct { + struct nlmsghdr hdr; + } req; + struct iovec iov; + char buf[4096]; + + test_init(argc, argv); + + ssk = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); + if (ssk < 0) { + err("Can't create sock diag socket"); + return -1; + } + bsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); + if (bsk < 0) { + err("Can't create sock diag socket"); + return -1; + } +#if 0 + int on, bbsk; + + bbsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); + if (bbsk < 0) { + err("Can't create sock diag socket"); + return -1; + } + + on = UDEV_MONITOR_TEST; + setsockopt(bbsk, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on)); +#endif + csk = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); + if (csk < 0) { + err("Can't create sock diag socket"); + return -1; + } + dsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); + if (dsk < 0) { + err("Can't create sock diag socket"); + return -1; + } + + addr.nl_family = AF_NETLINK; + addr.nl_groups = 0; + addr.nl_pid = getpid(); + if (bind(ssk, (struct sockaddr *) &addr, sizeof(struct sockaddr_nl))) { + err("bind"); + return 1; + } + + addr.nl_groups = 1 << (UDEV_MONITOR_TEST - 1); + addr.nl_pid = 0; + if (bind(bsk, (struct sockaddr *) &addr, sizeof(struct sockaddr_nl))) { + err("bind"); + return 1; + } + + addr.nl_pid = getpid();; + addr.nl_groups = 1 << (UDEV_MONITOR_TEST - 1); + if (connect(csk, (struct sockaddr *) &addr, sizeof(struct sockaddr_nl))) { + err("connect"); + return 1; + } + + test_daemon(); + + test_waitsig(); + + req.hdr.nlmsg_len = sizeof(req); + req.hdr.nlmsg_type = 0x1234; + req.hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; + req.hdr.nlmsg_seq = 0xabcd; + + memset(&msg, 0, sizeof(msg)); + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + iov.iov_base = (void *) &req; + iov.iov_len = sizeof(req);; + + if (sendmsg(csk, &msg, 0) < 0) { + err("Can't send request message"); + return 1; + } + + memset(&msg, 0, sizeof(msg)); + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + iov.iov_base = buf; + iov.iov_len = sizeof(buf); + + if (recvmsg(ssk, &msg, 0) < 0) { + err("Can't recv request message"); + return 1; + } + + if (recvmsg(bsk, &msg, 0) < 0) { + err("Can't recv request message"); + return 1; + } + + addr.nl_family = AF_NETLINK; + addr.nl_groups = 0; + addr.nl_pid = getpid(); + + memset(&msg, 0, sizeof(msg)); + msg.msg_namelen = sizeof(addr); + msg.msg_name = &addr; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + iov.iov_base = (void *) &req; + iov.iov_len = sizeof(req);; + + if (sendmsg(dsk, &msg, 0) < 0) { + err("Can't send request message"); + return 1; + } + + memset(&msg, 0, sizeof(msg)); + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + iov.iov_base = buf; + iov.iov_len = sizeof(buf); + + if (recvmsg(ssk, &msg, 0) < 0) { + err("Can't recv request message"); + return 1; + } + + pass(); + + return 0; +}