(root)/
strace-6.5/
tests/
net-yy-unix.c
       1  /*
       2   * This file is part of net-yy-unix strace test.
       3   *
       4   * Copyright (c) 2013-2017 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2016-2023 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 <assert.h>
      13  #include <fcntl.h>
      14  #include <stddef.h>
      15  #include <stdio.h>
      16  #include <stdlib.h>
      17  #include <string.h>
      18  #include <unistd.h>
      19  #include <sys/socket.h>
      20  #include <sys/un.h>
      21  #ifdef HAVE_SYS_XATTR_H
      22  # include <sys/xattr.h>
      23  # include "xmalloc.h"
      24  #endif
      25  
      26  #define TEST_SOCKET "net-yy-unix.socket"
      27  
      28  int
      29  main(void)
      30  {
      31  	skip_if_unavailable("/proc/self/fd/");
      32  
      33  	struct sockaddr_un addr = {
      34  		.sun_family = AF_UNIX,
      35  		.sun_path = TEST_SOCKET
      36  	};
      37  	struct sockaddr * const listen_sa = tail_memdup(&addr, sizeof(addr));
      38  
      39  	TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len);
      40  	*len = offsetof(struct sockaddr_un, sun_path) + strlen(TEST_SOCKET) + 1;
      41  	if (*len > sizeof(addr))
      42  		*len = sizeof(addr);
      43  
      44  	int listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
      45  	if (listen_fd < 0)
      46  		perror_msg_and_skip("socket");
      47  
      48  	char sock_proto_name[256];
      49  #ifdef HAVE_SYS_XATTR_H
      50  	char *path = xasprintf("/proc/self/fd/%u", listen_fd);
      51  	size_t sock_proto_name_len =
      52  		getxattr(path, "system.sockprotoname", sock_proto_name,
      53  			 sizeof(sock_proto_name) - 1);
      54  	free(path);
      55  	if (sock_proto_name_len &&
      56  	    sock_proto_name_len < sizeof(sock_proto_name))
      57  		sock_proto_name[sock_proto_name_len] = '\0';
      58  	else
      59  #endif
      60  		strcpy(sock_proto_name, "UNIX");
      61  
      62  	unsigned long listen_inode = inode_of_sockfd(listen_fd);
      63  	printf("socket(AF_UNIX, SOCK_STREAM, 0) = %d<%s:[%lu]>\n",
      64  	       listen_fd, sock_proto_name, listen_inode);
      65  
      66  	(void) unlink(TEST_SOCKET);
      67  	if (bind(listen_fd, listen_sa, *len))
      68  		perror_msg_and_skip("bind");
      69  	printf("bind(%d<%s:[%lu]>, {sa_family=AF_UNIX, sun_path=\"%s\"}"
      70  	       ", %u) = 0\n",
      71  	       listen_fd, sock_proto_name, listen_inode, TEST_SOCKET,
      72  	       (unsigned) *len);
      73  
      74  	if (listen(listen_fd, 1))
      75  		perror_msg_and_skip("listen");
      76  	printf("listen(%d<%s:[%lu,\"%s\"]>, 1) = 0\n",
      77  	       listen_fd, sock_proto_name, listen_inode, TEST_SOCKET);
      78  
      79  	TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, optval);
      80  	*len = sizeof(*optval);
      81  	if (getsockopt(listen_fd, SOL_SOCKET, SO_PASSCRED, optval, len))
      82  		perror_msg_and_fail("getsockopt");
      83  	printf("getsockopt(%d<%s:[%lu,\"%s\"]>, SOL_SOCKET, SO_PASSCRED"
      84  	       ", [%u], [%u]) = 0\n",
      85  	       listen_fd, sock_proto_name, listen_inode, TEST_SOCKET,
      86  	       *optval, (unsigned) *len);
      87  
      88  	memset(listen_sa, 0, sizeof(addr));
      89  	*len = sizeof(addr);
      90  	if (getsockname(listen_fd, listen_sa, len))
      91  		perror_msg_and_fail("getsockname");
      92  	printf("getsockname(%d<%s:[%lu,\"%s\"]>, {sa_family=AF_UNIX"
      93  	       ", sun_path=\"%s\"}, [%d => %d]) = 0\n",
      94  	       listen_fd, sock_proto_name, listen_inode,
      95  	       TEST_SOCKET, TEST_SOCKET, (int) sizeof(addr), (int) *len);
      96  
      97  	int connect_fd = socket(AF_UNIX, SOCK_STREAM, 0);
      98  	if (connect_fd < 0)
      99  		perror_msg_and_fail("socket");
     100  	unsigned long connect_inode = inode_of_sockfd(connect_fd);
     101  	printf("socket(AF_UNIX, SOCK_STREAM, 0) = %d<%s:[%lu]>\n",
     102  	       connect_fd, sock_proto_name, connect_inode);
     103  
     104  	if (connect(connect_fd, listen_sa, *len))
     105  		perror_msg_and_fail("connect");
     106  	printf("connect(%d<%s:[%lu]>, {sa_family=AF_UNIX"
     107  	       ", sun_path=\"%s\"}, %u) = 0\n",
     108  	       connect_fd, sock_proto_name, connect_inode, TEST_SOCKET,
     109  	       (unsigned) *len);
     110  
     111  	struct sockaddr * const accept_sa = tail_alloc(sizeof(addr));
     112  	memset(accept_sa, 0, sizeof(addr));
     113  	*len = sizeof(addr);
     114  	int accept_fd = accept4(listen_fd, accept_sa, len, O_CLOEXEC);
     115  	if (accept_fd < 0)
     116  		perror_msg_and_fail("accept");
     117  	unsigned long accept_inode = inode_of_sockfd(accept_fd);
     118  	printf("accept4(%d<%s:[%lu,\"%s\"]>, {sa_family=AF_UNIX}"
     119  	       ", [%d => %d], SOCK_CLOEXEC) = %d<%s:[%lu->%lu,\"%s\"]>\n",
     120  	       listen_fd, sock_proto_name, listen_inode, TEST_SOCKET,
     121  	       (int) sizeof(addr), (int) *len,
     122  	       accept_fd, sock_proto_name, accept_inode, connect_inode,
     123  	       TEST_SOCKET);
     124  
     125  	memset(listen_sa, 0, sizeof(addr));
     126  	*len = sizeof(addr);
     127  	if (getpeername(connect_fd, listen_sa, len))
     128  		perror_msg_and_fail("getpeername");
     129  	printf("getpeername(%d<%s:[%lu->%lu]>, {sa_family=AF_UNIX"
     130  	       ", sun_path=\"%s\"}, [%d => %d]) = 0\n",
     131  	       connect_fd, sock_proto_name, connect_inode,
     132  	       accept_inode, TEST_SOCKET, (int) sizeof(addr), (int) *len);
     133  
     134  	char text[] = "text";
     135  	assert(sendto(connect_fd, text, sizeof(text) - 1, MSG_DONTWAIT, NULL, 0)
     136  	       == sizeof(text) - 1);
     137  	printf("sendto(%d<%s:[%lu->%lu]>, \"%s\", %u, MSG_DONTWAIT"
     138  	       ", NULL, 0) = %u\n",
     139  	       connect_fd, sock_proto_name, connect_inode, accept_inode, text,
     140  	       (unsigned) sizeof(text) - 1, (unsigned) sizeof(text) - 1);
     141  
     142  	assert(recvfrom(accept_fd, text, sizeof(text) - 1, MSG_DONTWAIT, NULL, NULL)
     143  	       == sizeof(text) - 1);
     144  	printf("recvfrom(%d<%s:[%lu->%lu,\"%s\"]>, \"%s\", %u, MSG_DONTWAIT"
     145  	       ", NULL, NULL) = %u\n",
     146  	       accept_fd, sock_proto_name, accept_inode, connect_inode,
     147  	       TEST_SOCKET, text,
     148  	       (unsigned) sizeof(text) - 1, (unsigned) sizeof(text) - 1);
     149  
     150  	assert(close(connect_fd) == 0);
     151  	printf("close(%d<%s:[%lu->%lu]>) = 0\n",
     152  	       connect_fd, sock_proto_name, connect_inode, accept_inode);
     153  
     154  	assert(close(accept_fd) == 0);
     155  	printf("close(%d<%s:[%lu->%lu,\"%s\"]>) = 0\n",
     156  	       accept_fd, sock_proto_name, accept_inode, connect_inode,
     157  	       TEST_SOCKET);
     158  
     159  	connect_fd = socket(AF_UNIX, SOCK_STREAM, 0);
     160  	if (connect_fd < 0)
     161  		perror_msg_and_fail("socket");
     162  	connect_inode = inode_of_sockfd(connect_fd);
     163  	printf("socket(AF_UNIX, SOCK_STREAM, 0) = %d<%s:[%lu]>\n",
     164  	       connect_fd, sock_proto_name, connect_inode);
     165  
     166  	*optval = 1;
     167  	*len = sizeof(*optval);
     168  	if (setsockopt(connect_fd, SOL_SOCKET, SO_PASSCRED, optval, *len))
     169  		perror_msg_and_fail("setsockopt");
     170  	printf("setsockopt(%d<%s:[%lu]>, SOL_SOCKET, SO_PASSCRED"
     171  	       ", [%u], %u) = 0\n",
     172  	       connect_fd, sock_proto_name, connect_inode, *optval,
     173  	       (unsigned) *len);
     174  
     175  	memset(listen_sa, 0, sizeof(addr));
     176  	*len = sizeof(addr);
     177  	if (getsockname(listen_fd, listen_sa, len))
     178  		perror_msg_and_fail("getsockname");
     179  	printf("getsockname(%d<%s:[%lu,\"%s\"]>, {sa_family=AF_UNIX"
     180  	       ", sun_path=\"%s\"}, [%d => %d]) = 0\n",
     181  	       listen_fd, sock_proto_name, listen_inode,
     182  	       TEST_SOCKET, TEST_SOCKET, (int) sizeof(addr), (int) *len);
     183  
     184  	if (connect(connect_fd, listen_sa, *len))
     185  		perror_msg_and_fail("connect");
     186  	printf("connect(%d<%s:[%lu]>, {sa_family=AF_UNIX"
     187  	       ", sun_path=\"%s\"}, %u) = 0\n",
     188  	       connect_fd, sock_proto_name, connect_inode, TEST_SOCKET,
     189  	       (unsigned) *len);
     190  
     191  	memset(accept_sa, 0, sizeof(addr));
     192  	*len = sizeof(addr);
     193  	accept_fd = accept4(listen_fd, accept_sa, len, O_CLOEXEC);
     194  	if (accept_fd < 0)
     195  		perror_msg_and_fail("accept");
     196  	accept_inode = inode_of_sockfd(accept_fd);
     197  	const char * const sun_path1 =
     198  		((struct sockaddr_un *) accept_sa)->sun_path + 1;
     199  	printf("accept4(%d<%s:[%lu,\"%s\"]>, {sa_family=AF_UNIX"
     200  	       ", sun_path=@\"%s\"}, [%d => %d], SOCK_CLOEXEC)"
     201  	       " = %d<%s:[%lu->%lu,\"%s\"]>\n",
     202  	       listen_fd, sock_proto_name, listen_inode, TEST_SOCKET,
     203  	       sun_path1, (int) sizeof(addr), (int) *len,
     204  	       accept_fd, sock_proto_name, accept_inode, connect_inode,
     205  	       TEST_SOCKET);
     206  
     207  	memset(listen_sa, 0, sizeof(addr));
     208  	*len = sizeof(addr);
     209  	if (getpeername(connect_fd, listen_sa, len))
     210  		perror_msg_and_fail("getpeername");
     211  	printf("getpeername(%d<%s:[%lu->%lu,@\"%s\"]>, {sa_family=AF_UNIX"
     212  	       ", sun_path=\"%s\"}, [%d => %d]) = 0\n",
     213  	       connect_fd, sock_proto_name, connect_inode, accept_inode,
     214  	       sun_path1, TEST_SOCKET, (int) sizeof(addr), (int) *len);
     215  
     216  	assert(sendto(connect_fd, text, sizeof(text) - 1, MSG_DONTWAIT, NULL, 0)
     217  	       == sizeof(text) - 1);
     218  	printf("sendto(%d<%s:[%lu->%lu,@\"%s\"]>, \"%s\", %u, MSG_DONTWAIT"
     219  	       ", NULL, 0) = %u\n",
     220  	       connect_fd, sock_proto_name, connect_inode, accept_inode,
     221  	       sun_path1, text,
     222  	       (unsigned) sizeof(text) - 1, (unsigned) sizeof(text) - 1);
     223  
     224  	assert(recvfrom(accept_fd, text, sizeof(text) - 1, MSG_DONTWAIT, NULL, NULL)
     225  	       == sizeof(text) - 1);
     226  	printf("recvfrom(%d<%s:[%lu->%lu,\"%s\"]>, \"%s\", %u, MSG_DONTWAIT"
     227  	       ", NULL, NULL) = %u\n",
     228  	       accept_fd, sock_proto_name, accept_inode, connect_inode,
     229  	       TEST_SOCKET, text,
     230  	       (unsigned) sizeof(text) - 1, (unsigned) sizeof(text) - 1);
     231  
     232  	assert(close(connect_fd) == 0);
     233  	printf("close(%d<%s:[%lu->%lu,@\"%s\"]>) = 0\n",
     234  	       connect_fd, sock_proto_name, connect_inode, accept_inode,
     235  	       sun_path1);
     236  
     237  	assert(close(accept_fd) == 0);
     238  	printf("close(%d<%s:[%lu->%lu,\"%s\"]>) = 0\n",
     239  	       accept_fd, sock_proto_name, accept_inode, connect_inode,
     240  	       TEST_SOCKET);
     241  
     242  	assert(unlink(TEST_SOCKET) == 0);
     243  
     244  	assert(close(listen_fd) == 0);
     245  	printf("close(%d<%s:[%lu,\"%s\"]>) = 0\n",
     246  	       listen_fd, sock_proto_name, listen_inode, TEST_SOCKET);
     247  
     248  	puts("+++ exited with 0 +++");
     249  	return 0;
     250  }