1 /* 2 * This file is part of net-yy-inet strace test. 3 * 4 * Copyright (c) 2014-2016 Dmitry V. Levin <ldv (at) altlinux.org> 5 * Copyright (c) 2016-2018 The strace developers. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "tests.h" 32 #include <assert.h> 33 #include <stddef.h> 34 #include <stdio.h> 35 #include <string.h> 36 #include <unistd.h> 37 #include <sys/socket.h> 38 #include <netinet/in.h> 39 #include <netinet/tcp.h> 40 #include <arpa/inet.h> 41 42 #include "accept_compat.h" 43 44 #ifndef ADDR_FAMILY 45 # define ADDR_FAMILY_FIELD sin_family 46 # define ADDR_FAMILY AF_INET 47 # define AF_STR "AF_INET" 48 # define LOOPBACK_FIELD .sin_addr.s_addr = htonl(INADDR_LOOPBACK) 49 # define LOOPBACK "127.0.0.1" 50 # define SOCKADDR_TYPE sockaddr_in 51 # define TCP_STR "TCP" 52 # define INPORT sin_port 53 # define INPORT_STR "sin_port" 54 # define INADDR_STR "sin_addr=inet_addr(\"" LOOPBACK "\")" 55 # define SA_FIELDS "" 56 #endif 57 58 int 59 main(void) 60 { 61 skip_if_unavailable("/proc/self/fd/"); 62 63 const struct SOCKADDR_TYPE addr = { 64 .ADDR_FAMILY_FIELD = ADDR_FAMILY, 65 LOOPBACK_FIELD 66 }; 67 struct sockaddr * const listen_sa = tail_memdup(&addr, sizeof(addr)); 68 TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); 69 *len = sizeof(addr); 70 71 const int listen_fd = socket(ADDR_FAMILY, SOCK_STREAM, 0); 72 if (listen_fd < 0) 73 perror_msg_and_skip("socket"); 74 const unsigned long listen_inode = inode_of_sockfd(listen_fd); 75 printf("socket(" AF_STR ", SOCK_STREAM, IPPROTO_IP) = %d<" TCP_STR 76 ":[%lu]>\n", 77 listen_fd, listen_inode); 78 79 if (bind(listen_fd, listen_sa, *len)) 80 perror_msg_and_skip("bind"); 81 printf("bind(%d<" TCP_STR ":[%lu]>, {sa_family=" AF_STR ", " INPORT_STR 82 "=htons(0), " INADDR_STR SA_FIELDS "}, %u) = 0\n", 83 listen_fd, listen_inode, (unsigned) *len); 84 85 if (listen(listen_fd, 1)) 86 perror_msg_and_skip("listen"); 87 printf("listen(%d<" TCP_STR ":[%lu]>, 1) = 0\n", 88 listen_fd, listen_inode); 89 90 memset(listen_sa, 0, sizeof(addr)); 91 *len = sizeof(addr); 92 if (getsockname(listen_fd, listen_sa, len)) 93 perror_msg_and_fail("getsockname"); 94 const unsigned int listen_port = 95 ntohs(((struct SOCKADDR_TYPE *) listen_sa)->INPORT); 96 printf("getsockname(%d<" TCP_STR ":[" LOOPBACK ":%u]>, {sa_family=" 97 AF_STR ", " INPORT_STR "=htons(%u), " INADDR_STR SA_FIELDS "}" 98 ", [%u]) = 0\n", 99 listen_fd, listen_port, listen_port, (unsigned) *len); 100 101 TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, optval); 102 *len = sizeof(*optval); 103 if (getsockopt(listen_fd, SOL_TCP, TCP_MAXSEG, optval, len)) 104 perror_msg_and_fail("getsockopt"); 105 printf("getsockopt(%d<" TCP_STR ":[" LOOPBACK ":%u]>, SOL_TCP, " 106 "TCP_MAXSEG, [%u], [%u]) = 0\n", 107 listen_fd, listen_port, *optval, (unsigned) *len); 108 109 const int connect_fd = socket(ADDR_FAMILY, SOCK_STREAM, 0); 110 if (connect_fd < 0) 111 perror_msg_and_fail("socket"); 112 const unsigned long connect_inode = inode_of_sockfd(connect_fd); 113 printf("socket(" AF_STR ", SOCK_STREAM, IPPROTO_IP) = %d<" TCP_STR 114 ":[%lu]>\n", 115 connect_fd, connect_inode); 116 117 *len = sizeof(addr); 118 if (connect(connect_fd, listen_sa, *len)) 119 perror_msg_and_fail("connect"); 120 printf("connect(%d<" TCP_STR ":[%lu]>, {sa_family=" AF_STR ", " 121 INPORT_STR "=htons(%u), " INADDR_STR SA_FIELDS "}, %u) = 0\n", 122 connect_fd, connect_inode, listen_port, (unsigned) *len); 123 124 struct sockaddr * const accept_sa = tail_alloc(sizeof(addr)); 125 memset(accept_sa, 0, sizeof(addr)); 126 *len = sizeof(addr); 127 const int accept_fd = do_accept(listen_fd, accept_sa, len); 128 if (accept_fd < 0) 129 perror_msg_and_fail("accept"); 130 const unsigned int connect_port = 131 ntohs(((struct SOCKADDR_TYPE *) accept_sa)->INPORT); 132 printf("accept(%d<" TCP_STR ":[" LOOPBACK ":%u]>, {sa_family=" AF_STR 133 ", " INPORT_STR "=htons(%u), " INADDR_STR SA_FIELDS "}" 134 ", [%u]) = %d<" TCP_STR ":[" LOOPBACK ":%u->" LOOPBACK ":%u]>\n", 135 listen_fd, listen_port, connect_port, (unsigned) *len, 136 accept_fd, listen_port, connect_port); 137 138 memset(accept_sa, 0, sizeof(addr)); 139 *len = sizeof(addr); 140 if (getpeername(accept_fd, accept_sa, len)) 141 perror_msg_and_fail("getpeername"); 142 printf("getpeername(%d<" TCP_STR ":[" LOOPBACK ":%u->" LOOPBACK ":%u]>" 143 ", {sa_family=" AF_STR ", " INPORT_STR "=htons(%u)" 144 ", " INADDR_STR SA_FIELDS "}, [%u]) = 0\n", 145 accept_fd, listen_port, connect_port, connect_port, 146 (unsigned) *len); 147 148 memset(listen_sa, 0, sizeof(addr)); 149 *len = sizeof(addr); 150 if (getpeername(connect_fd, listen_sa, len)) 151 perror_msg_and_fail("getpeername"); 152 printf("getpeername(%d<" TCP_STR ":[" LOOPBACK ":%u->" LOOPBACK ":%u]>" 153 ", {sa_family=" AF_STR ", " INPORT_STR "=htons(%u)" 154 ", " INADDR_STR SA_FIELDS "}, [%u]) = 0\n", 155 connect_fd, connect_port, listen_port, listen_port, 156 (unsigned) *len); 157 158 *len = sizeof(*optval); 159 if (setsockopt(connect_fd, SOL_TCP, TCP_MAXSEG, optval, *len)) 160 perror_msg_and_fail("setsockopt"); 161 printf("setsockopt(%d<" TCP_STR ":[" LOOPBACK ":%u->" LOOPBACK ":%u]>" 162 ", SOL_TCP, TCP_MAXSEG, [%u], %u) = 0\n", 163 connect_fd, connect_port, listen_port, *optval, 164 (unsigned) *len); 165 166 char text[] = "text"; 167 assert(sendto(connect_fd, text, sizeof(text) - 1, 168 MSG_DONTROUTE | MSG_DONTWAIT, NULL, 0) == sizeof(text) - 1); 169 printf("sendto(%d<" TCP_STR ":[" LOOPBACK ":%u->" LOOPBACK ":%u]>, " 170 "\"%s\", %u, MSG_DONTROUTE|MSG_DONTWAIT, NULL, 0) = %u\n", 171 connect_fd, connect_port, listen_port, text, 172 (unsigned) sizeof(text) - 1, (unsigned) sizeof(text) - 1); 173 174 assert(close(connect_fd) == 0); 175 printf("close(%d<" TCP_STR ":[" LOOPBACK ":%u->" LOOPBACK ":%u]>) = " 176 "0\n", 177 connect_fd, connect_port, listen_port); 178 179 assert(recvfrom(accept_fd, text, sizeof(text) - 1, MSG_WAITALL, 180 NULL, NULL) == sizeof(text) - 1); 181 printf("recvfrom(%d<" TCP_STR ":[" LOOPBACK ":%u->" LOOPBACK ":%u]>, " 182 "\"%s\", %u, MSG_WAITALL, NULL, NULL) = %u\n", 183 accept_fd, listen_port, connect_port, text, 184 (unsigned) sizeof(text) - 1, (unsigned) sizeof(text) - 1); 185 186 assert(close(accept_fd) == 0); 187 printf("close(%d<" TCP_STR ":[" LOOPBACK ":%u->" LOOPBACK ":%u]>) = " 188 "0\n", 189 accept_fd, listen_port, connect_port); 190 191 assert(close(listen_fd) == 0); 192 printf("close(%d<" TCP_STR ":[" LOOPBACK ":%u]>) = 0\n", 193 listen_fd, listen_port); 194 195 puts("+++ exited with 0 +++"); 196 return 0; 197 } 198