(root)/
strace-6.5/
tests/
netlink_inet_diag.c
       1  /*
       2   * This file is part of inet-yy strace test.
       3   *
       4   * Copyright (c) 2014-2016 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2014-2021 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  #include <errno.h>
      13  #include <string.h>
      14  #include <unistd.h>
      15  #include <netinet/in.h>
      16  #include "netlink.h"
      17  #include <linux/sock_diag.h>
      18  #include <linux/inet_diag.h>
      19  
      20  static void
      21  send_query(const int fd, const int family, const int proto)
      22  {
      23  	struct sockaddr_nl nladdr = {
      24  		.nl_family = AF_NETLINK
      25  	};
      26  	struct {
      27  		struct nlmsghdr nlh;
      28  		struct inet_diag_req_v2 idr;
      29  	} req = {
      30  		.nlh = {
      31  			.nlmsg_len = sizeof(req),
      32  			.nlmsg_type = SOCK_DIAG_BY_FAMILY,
      33  			.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST
      34  		},
      35  		.idr = {
      36  			.sdiag_family = family,
      37  			.sdiag_protocol = proto,
      38  			.idiag_states = -1
      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 inet_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_in addr;
     104  	socklen_t len = sizeof(addr);
     105  
     106  	memset(&addr, 0, sizeof(addr));
     107  	addr.sin_family = AF_INET;
     108  	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
     109  
     110  	close(0);
     111  	close(1);
     112  
     113  	if (socket(AF_INET, SOCK_STREAM, 0))
     114  		perror_msg_and_skip("socket AF_INET");
     115  	if (bind(0, (struct sockaddr *) &addr, len))
     116  		perror_msg_and_skip("bind");
     117  	if (listen(0, 5))
     118  		perror_msg_and_skip("listen");
     119  	if (socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG) != 1)
     120  		perror_msg_and_skip("socket AF_NETLINK");
     121  
     122  	send_query(1, AF_INET, IPPROTO_TCP);
     123  	check_responses(1);
     124  	return 0;
     125  }