subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 1 | /******************************************************************************/ |
| 2 | /* */ |
| 3 | /* Copyright (C) 2008, Linux Foundation, */ |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 4 | /* written by Michael Kerrisk <mtk.manpages@gmail.com> */ |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 5 | /* */ |
| 6 | /* Licensed under the GNU GPLv2 or later. */ |
| 7 | /* This program is free software; you can redistribute it and/or modify */ |
| 8 | /* it under the terms of the GNU General Public License as published by */ |
| 9 | /* the Free Software Foundation; either version 2 of the License, or */ |
| 10 | /* (at your option) any later version. */ |
| 11 | /* */ |
| 12 | /* This program is distributed in the hope that it will be useful, */ |
| 13 | /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ |
| 14 | /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ |
| 15 | /* the GNU General Public License for more details. */ |
| 16 | /* */ |
| 17 | /* You should have received a copy of the GNU General Public License */ |
| 18 | /* along with this program; if not, write to the Free Software */ |
Wanlong Gao | 4548c6c | 2012-10-19 18:03:36 +0800 | [diff] [blame] | 19 | /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 20 | /* */ |
| 21 | /******************************************************************************/ |
| 22 | |
| 23 | /******************************************************************************/ |
| 24 | /* */ |
| 25 | /* File: accept4_01.c */ |
| 26 | /* */ |
| 27 | /* Description: This will test the newly introduced syscall accept4() */ |
| 28 | /* */ |
| 29 | /* Total Tests: 4 */ |
| 30 | /* */ |
| 31 | /* Test Name: accept4_01 */ |
| 32 | /* */ |
| 33 | /* Author: Michael Kerrisk <mtk.manpages@gmail.com> */ |
| 34 | /* */ |
| 35 | /* History: Created - Nov 17 2008 - Michael <mtk.manpages@gmail.com> */ |
| 36 | /* Initial Porting to LTP */ |
| 37 | /* - Nov 17 2008 - Subrata <subrata@linux.vnet.ibm.com> */ |
| 38 | /* */ |
| 39 | /******************************************************************************/ |
| 40 | |
| 41 | #define _GNU_SOURCE |
| 42 | #include <unistd.h> |
| 43 | #include <sys/syscall.h> |
| 44 | #include <sys/socket.h> |
| 45 | #include <netinet/in.h> |
| 46 | #include <stdlib.h> |
| 47 | #include <fcntl.h> |
| 48 | #include <stdio.h> |
| 49 | #include <string.h> |
| 50 | #include <errno.h> |
| 51 | |
| 52 | #include "test.h" |
| 53 | #include "usctest.h" |
| 54 | |
| 55 | #include "linux_syscall_numbers.h" |
| 56 | |
| 57 | #define PORT_NUM 33333 |
| 58 | |
Garrett Cooper | e683a86 | 2010-12-20 12:51:50 -0800 | [diff] [blame] | 59 | #define die(msg) tst_brkm(TBROK|TERRNO, cleanup, msg) |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 60 | |
| 61 | /**********************************************************************/ |
| 62 | |
| 63 | /* The following is what we need until glibc gets a wrapper for |
| 64 | accept4() */ |
| 65 | |
| 66 | /* Flags for socket(), socketpair(), accept4() */ |
| 67 | #ifndef O_CLOEXEC |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 68 | #define O_CLOEXEC 02000000 |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 69 | #endif |
| 70 | |
| 71 | #ifndef SOCK_CLOEXEC |
| 72 | #define SOCK_CLOEXEC O_CLOEXEC |
| 73 | #endif |
| 74 | #ifndef SOCK_NONBLOCK |
| 75 | #define SOCK_NONBLOCK O_NONBLOCK |
| 76 | #endif |
| 77 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 78 | #if defined(SYS_ACCEPT4) /* the socketcall() number */ |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 79 | #define USE_SOCKETCALL 1 |
| 80 | #endif |
| 81 | |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 82 | /* Global Variables */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 83 | char *TCID = "accept04_01"; /* test program identifier. */ |
| 84 | int TST_TOTAL = 1; /* total number of tests in this file. */ |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 85 | |
| 86 | /* Extern Global Functions */ |
| 87 | /******************************************************************************/ |
| 88 | /* */ |
| 89 | /* Function: cleanup */ |
| 90 | /* */ |
| 91 | /* Description: Performs all one time clean up for this test on successful */ |
| 92 | /* completion, premature exit or failure. Closes all temporary */ |
| 93 | /* files, removes all temporary directories exits the test with */ |
| 94 | /* appropriate return code by calling tst_exit() function. */ |
| 95 | /* */ |
| 96 | /* Input: None. */ |
| 97 | /* */ |
| 98 | /* Output: None. */ |
| 99 | /* */ |
| 100 | /* Return: On failure - Exits calling tst_exit(). Non '0' return code. */ |
| 101 | /* On success - Exits calling tst_exit(). With '0' return code. */ |
| 102 | /* */ |
| 103 | /******************************************************************************/ |
| 104 | /* We would need this for many more reasons in future */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 105 | extern void cleanup() |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 106 | { |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 107 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 108 | TEST_CLEANUP; |
| 109 | tst_rmdir(); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 110 | |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 111 | } |
| 112 | |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 113 | /* Local Functions */ |
| 114 | /******************************************************************************/ |
| 115 | /* */ |
| 116 | /* Function: setup */ |
| 117 | /* */ |
| 118 | /* Description: Performs all one time setup for this test. This function is */ |
| 119 | /* typically used to capture signals, create temporary dirs */ |
| 120 | /* and temporary files that may be used in the course of this */ |
| 121 | /* test. */ |
| 122 | /* */ |
| 123 | /* Input: None. */ |
| 124 | /* */ |
| 125 | /* Output: None. */ |
| 126 | /* */ |
| 127 | /* Return: On failure - Exits by calling cleanup(). */ |
| 128 | /* On success - returns 0. */ |
| 129 | /* */ |
| 130 | /******************************************************************************/ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 131 | void setup() |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 132 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 133 | /* Capture signals if any */ |
| 134 | /* Create temporary directories */ |
| 135 | TEST_PAUSE; |
| 136 | tst_tmpdir(); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 137 | } |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 138 | |
subrata_modak | f4194f0 | 2009-05-12 06:01:04 +0000 | [diff] [blame] | 139 | #if !(__GLIBC_PREREQ(2,10)) |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 140 | static int |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 141 | accept4_01(int fd, struct sockaddr *sockaddr, socklen_t * addrlen, int flags) |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 142 | { |
| 143 | #ifdef DEBUG |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 144 | tst_resm(TINFO, "Calling accept4(): flags = %x", flags); |
| 145 | if (flags != 0) { |
| 146 | tst_resm(TINFO, " ("); |
| 147 | if (flags & SOCK_CLOEXEC) |
| 148 | tst_resm(TINFO, "SOCK_CLOEXEC"); |
| 149 | if ((flags & SOCK_CLOEXEC) && (flags & SOCK_NONBLOCK)) |
| 150 | tst_resm(TINFO, " "); |
| 151 | if (flags & SOCK_NONBLOCK) |
| 152 | tst_resm(TINFO, "SOCK_NONBLOCK"); |
| 153 | tst_resm(TINFO, ")"); |
| 154 | } |
| 155 | tst_resm(TINFO, "\n"); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 156 | #endif |
| 157 | |
| 158 | #if USE_SOCKETCALL |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 159 | long args[6]; |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 160 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 161 | args[0] = fd; |
| 162 | args[1] = (long)sockaddr; |
| 163 | args[2] = (long)addrlen; |
| 164 | args[3] = flags; |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 165 | |
Jan Stancek | 359980f | 2013-02-15 10:16:05 +0100 | [diff] [blame^] | 166 | return ltp_syscall(__NR_socketcall, SYS_ACCEPT4, args); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 167 | #else |
Jan Stancek | 359980f | 2013-02-15 10:16:05 +0100 | [diff] [blame^] | 168 | return ltp_syscall(__NR_accept4, fd, sockaddr, addrlen, flags); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 169 | #endif |
| 170 | } |
subrata_modak | f4194f0 | 2009-05-12 06:01:04 +0000 | [diff] [blame] | 171 | #endif |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 172 | |
| 173 | /**********************************************************************/ |
| 174 | |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 175 | static void |
| 176 | do_test(int lfd, struct sockaddr_in *conn_addr, |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 177 | int closeonexec_flag, int nonblock_flag) |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 178 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 179 | int connfd, acceptfd; |
| 180 | int fdf, flf, fdf_pass, flf_pass; |
| 181 | struct sockaddr_in claddr; |
| 182 | socklen_t addrlen; |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 183 | |
| 184 | #ifdef DEBUG |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 185 | tst_resm(TINFO, "=======================================\n"); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 186 | #endif |
| 187 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 188 | connfd = socket(AF_INET, SOCK_STREAM, 0); |
| 189 | if (connfd == -1) |
| 190 | die("Socket Error"); |
| 191 | if (connect(connfd, (struct sockaddr *)conn_addr, |
| 192 | sizeof(struct sockaddr_in)) == -1) |
| 193 | die("Connect Error"); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 194 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 195 | addrlen = sizeof(struct sockaddr_in); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 196 | #if !(__GLIBC_PREREQ(2,10)) |
subrata_modak | f4194f0 | 2009-05-12 06:01:04 +0000 | [diff] [blame] | 197 | acceptfd = accept4_01(lfd, (struct sockaddr *)&claddr, &addrlen, |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 198 | closeonexec_flag | nonblock_flag); |
| 199 | #else |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 200 | acceptfd = accept4(lfd, (struct sockaddr *)&claddr, &addrlen, |
| 201 | closeonexec_flag | nonblock_flag); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 202 | #endif |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 203 | if (acceptfd == -1) { |
| 204 | tst_resm(TCONF, |
| 205 | "syscall __NR_accept4 not supported on your arch"); |
| 206 | } |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 207 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 208 | fdf = fcntl(acceptfd, F_GETFD); |
| 209 | if (fdf == -1) |
| 210 | die("fcntl:F_GETFD"); |
| 211 | fdf_pass = ((fdf & FD_CLOEXEC) != 0) == |
| 212 | ((closeonexec_flag & SOCK_CLOEXEC) != 0); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 213 | #ifdef DEBUG |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 214 | tst_resm(TINFO, "Close-on-exec flag is %sset (%s); ", |
| 215 | (fdf & FD_CLOEXEC) ? "" : "not ", fdf_pass ? "OK" : "failed"); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 216 | #endif |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 217 | if (!fdf_pass) |
| 218 | tst_resm(TFAIL, |
| 219 | "Close-on-exec flag mismatch, should be %x, actual %x", |
| 220 | fdf & FD_CLOEXEC, closeonexec_flag & SOCK_CLOEXEC); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 221 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 222 | flf = fcntl(acceptfd, F_GETFL); |
| 223 | if (flf == -1) |
| 224 | die("fcntl:F_GETFD"); |
| 225 | flf_pass = ((flf & O_NONBLOCK) != 0) == |
| 226 | ((nonblock_flag & SOCK_NONBLOCK) != 0); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 227 | #ifdef DEBUG |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 228 | tst_resm(TINFO, "nonblock flag is %sset (%s)\n", |
| 229 | (flf & O_NONBLOCK) ? "" : "not ", flf_pass ? "OK" : "failed"); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 230 | #endif |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 231 | if (!flf_pass) |
| 232 | tst_resm(TFAIL, |
| 233 | "nonblock flag mismatch, should be %x, actual %x", |
| 234 | fdf & O_NONBLOCK, nonblock_flag & SOCK_NONBLOCK); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 235 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 236 | close(acceptfd); |
| 237 | close(connfd); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 238 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 239 | if (fdf_pass && flf_pass) |
| 240 | tst_resm(TPASS, "Test passed"); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 241 | } |
| 242 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 243 | static int create_listening_socket(int port_num) |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 244 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 245 | struct sockaddr_in svaddr; |
| 246 | int lfd; |
| 247 | int optval; |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 248 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 249 | memset(&svaddr, 0, sizeof(struct sockaddr_in)); |
| 250 | svaddr.sin_family = AF_INET; |
| 251 | svaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 252 | svaddr.sin_port = htons(port_num); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 253 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 254 | lfd = socket(AF_INET, SOCK_STREAM, 0); |
| 255 | if (lfd == -1) |
| 256 | die("Socket Error"); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 257 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 258 | optval = 1; |
| 259 | if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &optval, |
| 260 | sizeof(optval)) == -1) |
| 261 | die("Setsockopt Error"); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 262 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 263 | if (bind(lfd, (struct sockaddr *)&svaddr, |
| 264 | sizeof(struct sockaddr_in)) == -1) |
| 265 | die("Bind Error"); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 266 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 267 | if (listen(lfd, 5) == -1) |
| 268 | die("Listen Error"); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 269 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 270 | return lfd; |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 271 | } |
| 272 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 273 | int main(int argc, char *argv[]) |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 274 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 275 | #if defined(__NR_accept4) || defined(__NR_socketcall) |
| 276 | struct sockaddr_in conn_addr; |
| 277 | int lfd; |
| 278 | int port_num; |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 279 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 280 | setup(); |
| 281 | port_num = (argc > 1) ? atoi(argv[1]) : PORT_NUM; |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 282 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 283 | memset(&conn_addr, 0, sizeof(struct sockaddr_in)); |
| 284 | conn_addr.sin_family = AF_INET; |
| 285 | conn_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 286 | conn_addr.sin_port = htons(port_num); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 287 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 288 | lfd = create_listening_socket(port_num); |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 289 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 290 | do_test(lfd, &conn_addr, 0, 0); |
| 291 | do_test(lfd, &conn_addr, SOCK_CLOEXEC, 0); |
| 292 | do_test(lfd, &conn_addr, 0, SOCK_NONBLOCK); |
| 293 | do_test(lfd, &conn_addr, SOCK_CLOEXEC, SOCK_NONBLOCK); |
| 294 | close(lfd); |
| 295 | #else |
| 296 | tst_resm(TCONF, "syscall __NR_accept4 not supported on your arch"); |
| 297 | #endif |
subrata_modak | cb1d6ce | 2008-11-19 10:34:37 +0000 | [diff] [blame] | 298 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 299 | cleanup(); |
| 300 | tst_exit(); |
Garrett Cooper | e683a86 | 2010-12-20 12:51:50 -0800 | [diff] [blame] | 301 | } |