/* * Copyright (c) 2016 Fabien Siron * Copyright (c) 2017 JingPiao Chen * Copyright (c) 2017 The strace developers. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #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, {len=%u, type=SOCK_DIAG_BY_FAMILY" ", flags=NLM_F_REQUEST, seq=0, 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, {len=%u, type=SOCK_DIAG_BY_FAMILY" ", flags=NLM_F_REQUEST|NLM_F_DUMP, seq=0, 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) { void *const nlh0 = tail_alloc(NLMSG_HDRLEN); /* unspecified family only */ uint8_t family = 0; 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 */ char buf[sizeof(family) + 4]; 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, \"\\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_??? */" ", \"\\x31\\x32\\x33\\x34\"}", family)); } static void test_odd_family_msg(const int fd) { void *const nlh0 = tail_alloc(NLMSG_HDRLEN); /* unspecified family only */ uint8_t family = 0; 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 */ char buf[sizeof(family) + 4]; 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, \"\\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_??? */" ", \"\\x31\\x32\\x33\\x34\"}", family)); } static void test_unix_diag_req(const int fd) { void *const nlh0 = tail_alloc(NLMSG_HDRLEN); 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 } }; TEST_SOCK_DIAG(fd, nlh0, AF_UNIX, SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req, printf("{sdiag_family=AF_UNIX"), PRINT_FIELD_U(", ", req, sdiag_protocol); printf(", udiag_states=1<