blob: 526be6e0539f6f0d1c84259606c9aed6178b07b8 [file] [log] [blame]
subrata_modakcb1d6ce2008-11-19 10:34:37 +00001/******************************************************************************/
2/* */
3/* Copyright (C) 2008, Linux Foundation, */
subrata_modak4bb656a2009-02-26 12:02:09 +00004/* written by Michael Kerrisk <mtk.manpages@gmail.com> */
subrata_modakcb1d6ce2008-11-19 10:34:37 +00005/* */
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 Gao4548c6c2012-10-19 18:03:36 +080019/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
subrata_modakcb1d6ce2008-11-19 10:34:37 +000020/* */
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 Coopere683a862010-12-20 12:51:50 -080059#define die(msg) tst_brkm(TBROK|TERRNO, cleanup, msg)
subrata_modakcb1d6ce2008-11-19 10:34:37 +000060
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 Gao354ebb42012-12-07 10:10:04 +080068#define O_CLOEXEC 02000000
subrata_modakcb1d6ce2008-11-19 10:34:37 +000069#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_modak56207ce2009-03-23 13:35:39 +000078#if defined(SYS_ACCEPT4) /* the socketcall() number */
subrata_modakcb1d6ce2008-11-19 10:34:37 +000079#define USE_SOCKETCALL 1
80#endif
81
subrata_modakcb1d6ce2008-11-19 10:34:37 +000082/* Global Variables */
subrata_modak56207ce2009-03-23 13:35:39 +000083char *TCID = "accept04_01"; /* test program identifier. */
84int TST_TOTAL = 1; /* total number of tests in this file. */
subrata_modakcb1d6ce2008-11-19 10:34:37 +000085
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_modak56207ce2009-03-23 13:35:39 +0000105extern void cleanup()
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000106{
Garrett Cooper2c282152010-12-16 00:55:50 -0800107
subrata_modak56207ce2009-03-23 13:35:39 +0000108 TEST_CLEANUP;
109 tst_rmdir();
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000110
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000111}
112
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000113/* 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_modak56207ce2009-03-23 13:35:39 +0000131void setup()
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000132{
subrata_modak56207ce2009-03-23 13:35:39 +0000133 /* Capture signals if any */
134 /* Create temporary directories */
135 TEST_PAUSE;
136 tst_tmpdir();
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000137}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800138
subrata_modakf4194f02009-05-12 06:01:04 +0000139#if !(__GLIBC_PREREQ(2,10))
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000140static int
Wanlong Gao354ebb42012-12-07 10:10:04 +0800141accept4_01(int fd, struct sockaddr *sockaddr, socklen_t * addrlen, int flags)
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000142{
143#ifdef DEBUG
subrata_modak56207ce2009-03-23 13:35:39 +0000144 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_modakcb1d6ce2008-11-19 10:34:37 +0000156#endif
157
158#if USE_SOCKETCALL
subrata_modak56207ce2009-03-23 13:35:39 +0000159 long args[6];
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000160
subrata_modak56207ce2009-03-23 13:35:39 +0000161 args[0] = fd;
162 args[1] = (long)sockaddr;
163 args[2] = (long)addrlen;
164 args[3] = flags;
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000165
Jan Stancek359980f2013-02-15 10:16:05 +0100166 return ltp_syscall(__NR_socketcall, SYS_ACCEPT4, args);
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000167#else
Jan Stancek359980f2013-02-15 10:16:05 +0100168 return ltp_syscall(__NR_accept4, fd, sockaddr, addrlen, flags);
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000169#endif
170}
subrata_modakf4194f02009-05-12 06:01:04 +0000171#endif
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000172
173/**********************************************************************/
174
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000175static void
176do_test(int lfd, struct sockaddr_in *conn_addr,
subrata_modak56207ce2009-03-23 13:35:39 +0000177 int closeonexec_flag, int nonblock_flag)
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000178{
subrata_modak56207ce2009-03-23 13:35:39 +0000179 int connfd, acceptfd;
180 int fdf, flf, fdf_pass, flf_pass;
181 struct sockaddr_in claddr;
182 socklen_t addrlen;
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000183
184#ifdef DEBUG
subrata_modak56207ce2009-03-23 13:35:39 +0000185 tst_resm(TINFO, "=======================================\n");
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000186#endif
187
subrata_modak56207ce2009-03-23 13:35:39 +0000188 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_modakcb1d6ce2008-11-19 10:34:37 +0000194
subrata_modak56207ce2009-03-23 13:35:39 +0000195 addrlen = sizeof(struct sockaddr_in);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800196#if !(__GLIBC_PREREQ(2,10))
subrata_modakf4194f02009-05-12 06:01:04 +0000197 acceptfd = accept4_01(lfd, (struct sockaddr *)&claddr, &addrlen,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800198 closeonexec_flag | nonblock_flag);
199#else
subrata_modak56207ce2009-03-23 13:35:39 +0000200 acceptfd = accept4(lfd, (struct sockaddr *)&claddr, &addrlen,
201 closeonexec_flag | nonblock_flag);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800202#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000203 if (acceptfd == -1) {
204 tst_resm(TCONF,
205 "syscall __NR_accept4 not supported on your arch");
206 }
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000207
subrata_modak56207ce2009-03-23 13:35:39 +0000208 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_modakcb1d6ce2008-11-19 10:34:37 +0000213#ifdef DEBUG
subrata_modak56207ce2009-03-23 13:35:39 +0000214 tst_resm(TINFO, "Close-on-exec flag is %sset (%s); ",
215 (fdf & FD_CLOEXEC) ? "" : "not ", fdf_pass ? "OK" : "failed");
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000216#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000217 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_modakcb1d6ce2008-11-19 10:34:37 +0000221
subrata_modak56207ce2009-03-23 13:35:39 +0000222 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_modakcb1d6ce2008-11-19 10:34:37 +0000227#ifdef DEBUG
subrata_modak56207ce2009-03-23 13:35:39 +0000228 tst_resm(TINFO, "nonblock flag is %sset (%s)\n",
229 (flf & O_NONBLOCK) ? "" : "not ", flf_pass ? "OK" : "failed");
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000230#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000231 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_modakcb1d6ce2008-11-19 10:34:37 +0000235
subrata_modak56207ce2009-03-23 13:35:39 +0000236 close(acceptfd);
237 close(connfd);
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000238
subrata_modak56207ce2009-03-23 13:35:39 +0000239 if (fdf_pass && flf_pass)
240 tst_resm(TPASS, "Test passed");
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000241}
242
subrata_modak56207ce2009-03-23 13:35:39 +0000243static int create_listening_socket(int port_num)
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000244{
subrata_modak56207ce2009-03-23 13:35:39 +0000245 struct sockaddr_in svaddr;
246 int lfd;
247 int optval;
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000248
subrata_modak56207ce2009-03-23 13:35:39 +0000249 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_modakcb1d6ce2008-11-19 10:34:37 +0000253
subrata_modak56207ce2009-03-23 13:35:39 +0000254 lfd = socket(AF_INET, SOCK_STREAM, 0);
255 if (lfd == -1)
256 die("Socket Error");
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000257
subrata_modak56207ce2009-03-23 13:35:39 +0000258 optval = 1;
259 if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &optval,
260 sizeof(optval)) == -1)
261 die("Setsockopt Error");
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000262
subrata_modak56207ce2009-03-23 13:35:39 +0000263 if (bind(lfd, (struct sockaddr *)&svaddr,
264 sizeof(struct sockaddr_in)) == -1)
265 die("Bind Error");
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000266
subrata_modak56207ce2009-03-23 13:35:39 +0000267 if (listen(lfd, 5) == -1)
268 die("Listen Error");
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000269
subrata_modak56207ce2009-03-23 13:35:39 +0000270 return lfd;
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000271}
272
subrata_modak56207ce2009-03-23 13:35:39 +0000273int main(int argc, char *argv[])
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000274{
subrata_modak56207ce2009-03-23 13:35:39 +0000275#if defined(__NR_accept4) || defined(__NR_socketcall)
276 struct sockaddr_in conn_addr;
277 int lfd;
278 int port_num;
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000279
subrata_modak56207ce2009-03-23 13:35:39 +0000280 setup();
281 port_num = (argc > 1) ? atoi(argv[1]) : PORT_NUM;
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000282
subrata_modak56207ce2009-03-23 13:35:39 +0000283 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_modakcb1d6ce2008-11-19 10:34:37 +0000287
subrata_modak56207ce2009-03-23 13:35:39 +0000288 lfd = create_listening_socket(port_num);
subrata_modakcb1d6ce2008-11-19 10:34:37 +0000289
subrata_modak56207ce2009-03-23 13:35:39 +0000290 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_modakcb1d6ce2008-11-19 10:34:37 +0000298
subrata_modak56207ce2009-03-23 13:35:39 +0000299 cleanup();
300 tst_exit();
Garrett Coopere683a862010-12-20 12:51:50 -0800301}