/* * Copyright (c) 2016 Fabien Siron * Copyright (c) 2017 JingPiao Chen * Copyright (c) 2017-2021 The strace developers. * All rights reserved. * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "tests.h" #include #include #include #include #include #include #include #include "test_netlink.h" #include #include #include #include #ifdef AF_SMC # include #endif #include #include #define SMC_ACTIVE 1 #define TEST_SOCK_DIAG(fd_, nlh0_, \ family_, type_, flags_, \ obj_, print_family_, ...) \ \ do { \ /* family only */ \ uint8_t family = (family_); \ TEST_NETLINK_((fd_), (nlh0_), \ type_, #type_, \ flags_, #flags_, \ sizeof(family), &family, sizeof(family), \ printf("{family=%s}", #family_)); \ \ /* family and string */ \ char buf[sizeof(family) + 4]; \ memcpy(buf, &family, sizeof(family)); \ memcpy(buf + sizeof(family), "1234", 4); \ TEST_NETLINK_((fd_), (nlh0_), \ type_, #type_, \ flags_, #flags_, \ sizeof(buf), buf, sizeof(buf), \ (print_family_); \ printf(", ...}")); \ \ /* sizeof(obj_) */ \ TEST_NETLINK_((fd_), (nlh0_), \ type_, #type_, \ flags_, #flags_, \ sizeof(obj_), &(obj_), sizeof(obj_), \ (print_family_); \ __VA_ARGS__); \ \ /* short read of sizeof(obj_) */ \ TEST_NETLINK_((fd_), (nlh0_), \ type_, #type_, \ flags_, #flags_, \ sizeof(obj_), &(obj_), sizeof(obj_) - 1, \ (print_family_); \ printf(", %p}", \ NLMSG_DATA(TEST_NETLINK_nlh) + 1));\ } while (0) static void test_nlmsg_type(const int fd) { long rc; struct nlmsghdr nlh = { .nlmsg_len = sizeof(nlh), .nlmsg_type = SOCK_DIAG_BY_FAMILY, .nlmsg_flags = NLM_F_REQUEST, }; rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); printf("sendto(%d, {nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY" ", nlmsg_flags=NLM_F_REQUEST, nlmsg_seq=0, nlmsg_pid=0}" ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); } static void test_nlmsg_flags(const int fd) { long rc; struct nlmsghdr nlh = { .nlmsg_len = sizeof(nlh), .nlmsg_type = SOCK_DIAG_BY_FAMILY, .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, }; rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); printf("sendto(%d, {nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY" ", nlmsg_flags=NLM_F_REQUEST|NLM_F_DUMP, nlmsg_seq=0" ", nlmsg_pid=0}, %u, MSG_DONTWAIT, NULL, 0) = %s\n", fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); } static void test_odd_family_req(const int fd) { uint8_t family = 0; char buf[sizeof(family) + 4]; void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(buf)); /* unspecified family only */ TEST_NETLINK(fd, nlh0, SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, sizeof(family), &family, sizeof(family), printf("{family=AF_UNSPEC}")); /* unknown family only */ family = 0xff; TEST_NETLINK(fd, nlh0, SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, sizeof(family), &family, sizeof(family), printf("{family=%#x /* AF_??? */}", family)); /* short read of family */ TEST_NETLINK(fd, nlh0, SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, sizeof(family), &family, sizeof(family) - 1, printf("%p", NLMSG_DATA(TEST_NETLINK_nlh))); /* unspecified family and string */ family = 0; memcpy(buf, &family, sizeof(family)); memcpy(buf + sizeof(family), "1234", 4); TEST_NETLINK(fd, nlh0, SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, sizeof(buf), buf, sizeof(buf), printf("{family=AF_UNSPEC, data=\"\\x31\\x32\\x33\\x34\"}")); /* unknown family and string */ family = 0xfd; memcpy(buf, &family, sizeof(family)); TEST_NETLINK(fd, nlh0, SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, sizeof(buf), buf, sizeof(buf), printf("{family=%#x /* AF_??? */" ", data=\"\\x31\\x32\\x33\\x34\"}", family)); } static void test_odd_family_msg(const int fd) { uint8_t family = 0; char buf[sizeof(family) + 4]; void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(buf)); /* unspecified family only */ TEST_NETLINK(fd, nlh0, SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, sizeof(family), &family, sizeof(family), printf("{family=AF_UNSPEC}")); /* unknown family only */ family = 0xff; TEST_NETLINK(fd, nlh0, SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, sizeof(family), &family, sizeof(family), printf("{family=%#x /* AF_??? */}", family)); /* short read of family */ TEST_NETLINK(fd, nlh0, SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, sizeof(family), &family, sizeof(family) - 1, printf("%p", NLMSG_DATA(TEST_NETLINK_nlh))); /* unspecified family and string */ family = 0; memcpy(buf, &family, sizeof(family)); memcpy(buf + sizeof(family), "1234", 4); TEST_NETLINK(fd, nlh0, SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, sizeof(buf), buf, sizeof(buf), printf("{family=AF_UNSPEC, data=\"\\x31\\x32\\x33\\x34\"}")); /* unknown family and string */ family = 0xfd; memcpy(buf, &family, sizeof(family)); TEST_NETLINK(fd, nlh0, SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, sizeof(buf), buf, sizeof(buf), printf("{family=%#x /* AF_??? */" ", data=\"\\x31\\x32\\x33\\x34\"}", family)); } static void test_unix_diag_req(const int fd) { static const struct unix_diag_req req = { .sdiag_family = AF_UNIX, .sdiag_protocol = 253, .udiag_states = 1 << TCP_ESTABLISHED | 1 << TCP_LISTEN, .udiag_ino = 0xfacefeed, .udiag_show = UDIAG_SHOW_NAME, .udiag_cookie = { 0xdeadbeef, 0xbadc0ded } }; void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(req)); TEST_SOCK_DIAG(fd, nlh0, AF_UNIX, SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req, printf("{sdiag_family=AF_UNIX"), printf(", "); PRINT_FIELD_U(req, sdiag_protocol); printf(", udiag_states=1<