(root)/
strace-6.5/
tests/
netlink_netlink_diag.c
       1  /*
       2   * This file is part of net-yy-netlink strace test.
       3   *
       4   * Copyright (c) 2014-2016 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
       6   * Copyright (c) 2016-2021 The strace developers.
       7   * All rights reserved.
       8   *
       9   * SPDX-License-Identifier: GPL-2.0-or-later
      10   */
      11  
      12  #include "tests.h"
      13  #include <errno.h>
      14  #include <string.h>
      15  #include <unistd.h>
      16  #include <netinet/in.h>
      17  #include "netlink.h"
      18  #include <linux/sock_diag.h>
      19  #include <linux/netlink_diag.h>
      20  
      21  static void
      22  send_query(const int fd)
      23  {
      24  	struct sockaddr_nl nladdr = {
      25  		.nl_family = AF_NETLINK
      26  	};
      27  	struct {
      28  		struct nlmsghdr nlh;
      29  		struct netlink_diag_req ndr;
      30  	} req = {
      31  		.nlh = {
      32  			.nlmsg_len = sizeof(req),
      33  			.nlmsg_type = SOCK_DIAG_BY_FAMILY,
      34  			.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST
      35  		},
      36  		.ndr = {
      37  			.sdiag_family = AF_NETLINK,
      38  			.sdiag_protocol = NDIAG_PROTO_ALL
      39  		}
      40  	};
      41  	struct iovec iov = {
      42  		.iov_base = &req,
      43  		.iov_len = sizeof(req)
      44  	};
      45  	struct msghdr msg = {
      46  		.msg_name = (void *) &nladdr,
      47  		.msg_namelen = sizeof(nladdr),
      48  		.msg_iov = &iov,
      49  		.msg_iovlen = 1
      50  	};
      51  
      52  	if (sendmsg(fd, &msg, 0) <= 0)
      53  		perror_msg_and_skip("sendmsg");
      54  }
      55  
      56  static void
      57  check_responses(const int fd)
      58  {
      59  	static union {
      60  		struct nlmsghdr hdr;
      61  		long buf[8192 / sizeof(long)];
      62  	} hdr_buf;
      63  
      64  	struct sockaddr_nl nladdr = {
      65  		.nl_family = AF_NETLINK
      66  	};
      67  	struct iovec iov = {
      68  		.iov_base = hdr_buf.buf,
      69  		.iov_len = sizeof(hdr_buf.buf)
      70  	};
      71  	struct msghdr msg = {
      72  		.msg_name = (void *) &nladdr,
      73  		.msg_namelen = sizeof(nladdr),
      74  		.msg_iov = &iov,
      75  		.msg_iovlen = 1
      76  	};
      77  
      78  	ssize_t ret = recvmsg(fd, &msg, 0);
      79  	if (ret <= 0)
      80  		perror_msg_and_skip("recvmsg");
      81  
      82  	struct nlmsghdr *h = &hdr_buf.hdr;
      83  	if (!is_nlmsg_ok(h, ret))
      84  		error_msg_and_skip("!is_nlmsg_ok");
      85  	if (h->nlmsg_type == NLMSG_ERROR) {
      86  		const struct nlmsgerr *err = NLMSG_DATA(h);
      87  		if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
      88  			error_msg_and_skip("NLMSG_ERROR");
      89  		errno = -err->error;
      90  		perror_msg_and_skip("NLMSG_ERROR");
      91  	}
      92  	if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY)
      93  		error_msg_and_skip("unexpected nlmsg_type %u",
      94  				   (unsigned) h->nlmsg_type);
      95  
      96  	const struct netlink_diag_msg *diag = NLMSG_DATA(h);
      97  	if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*diag)))
      98  		error_msg_and_skip("short response");
      99  }
     100  
     101  int main(void)
     102  {
     103  	struct sockaddr_nl addr;
     104  	socklen_t len = sizeof(addr);
     105  
     106  	memset(&addr, 0, sizeof(addr));
     107  	addr.nl_family = AF_NETLINK;
     108  
     109  	close(0);
     110  	close(1);
     111  
     112  	if (socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG))
     113  		perror_msg_and_skip("socket AF_NETLINK");
     114  	if (bind(0, (struct sockaddr *) &addr, len))
     115  		perror_msg_and_skip("bind");
     116  
     117  	if (socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG) != 1)
     118  		perror_msg_and_skip("socket AF_NETLINK");
     119  
     120  	send_query(1);
     121  	check_responses(1);
     122  	return 0;
     123  }