1 /******************************************************************************/
2 /*                                                                            */
3 /* Copyright (c) Ulrich Drepper <drepper@redhat.com>                          */
4 /* Copyright (c) International Business Machines  Corp., 2009                 */
5 /*                                                                            */
6 /* This program is free software;  you can redistribute it and/or modify      */
7 /* it under the terms of the GNU General Public License as published by       */
8 /* the Free Software Foundation; either version 2 of the License, or          */
9 /* (at your option) any later version.                                        */
10 /*                                                                            */
11 /* This program is distributed in the hope that it will be useful,            */
12 /* but WITHOUT ANY WARRANTY;  without even the implied warranty of            */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                  */
14 /* the GNU General Public License for more details.                           */
15 /*                                                                            */
16 /* You should have received a copy of the GNU General Public License          */
17 /* along with this program;  if not, write to the Free Software               */
18 /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    */
19 /*                                                                            */
20 /******************************************************************************/
21 /******************************************************************************/
22 /*                                                                            */
23 /* File:        socket02.c                                                    */
24 /*                                                                            */
25 /* Description: This program tests the new flag SOCK_CLOEXEC introduced in    */
26 /*              socket() & socketpair() and in kernel 2.6.27. Ulrich´s comment*/
27 /*              as in:                                                        */
28 /*              http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=a677a039be7243357d93502bff2b40850c942e2d */
29 /*              says:                                                         */
30 /*                                                                            */
31 /*              flag parameters: socket and socketpair                        */
32 /*              This patch adds support for flag values which are ORed to the */
33 /*              type passwd to socket and socketpair.  The additional code is */
34 /*              minimal. The flag values in this implementation can and must  */
35 /*              match the O_* flags. This avoids overhead in the conversion.  */
36 /*              The internal functions sock_alloc_fd and sock_map_fd get a new*/
37 /*              parameters and all callers are changed.                       */
38 /*                                                                            */
39 /* Usage:  <for command-line>                                                 */
40 /*  socket02 [-c n] [-e][-i n] [-I x] [-p x] [-t]                             */
41 /*      where,  -c n : Run n copies concurrently.                             */
42 /*              -e   : Turn on errno logging.                                 */
43 /*              -i n : Execute test n times.                                  */
44 /*              -I x : Execute test for x seconds.                            */
45 /*              -P x : Pause for x seconds between iterations.                */
46 /*              -t   : Turn on syscall timing.                                */
47 /*                                                                            */
48 /* Total Tests: 1                                                             */
49 /*                                                                            */
50 /* Test Name:   socket02                                                      */
51 /*                                                                            */
52 /* Author:      Ulrich Drepper <drepper@redhat.com>                           */
53 /*                                                                            */
54 /* History:     Created - Jan 05 2009 - Ulrich Drepper <drepper@redhat.com>   */
55 /*              Ported to LTP                                                 */
56 /*                      - Jan 05 2009 - Subrata <subrata@linux.vnet.ibm.com>  */
57 /******************************************************************************/
58 
59 #include <fcntl.h>
60 #include <stdio.h>
61 #include <unistd.h>
62 #include <netinet/in.h>
63 #include <sys/socket.h>
64 
65 #include "test.h"
66 #include "lapi/fcntl.h"
67 
68 #define PORT 57392
69 
70 /* For Linux these must be the same.  */
71 #ifndef SOCK_CLOEXEC
72 #define SOCK_CLOEXEC O_CLOEXEC
73 #endif
74 
75 char *TCID = "socket02";
76 int testno;
77 int TST_TOTAL = 1;
78 
79 /* Extern Global Functions */
80 /******************************************************************************/
81 /*                                                                            */
82 /* Function:    cleanup                                                       */
83 /*                                                                            */
84 /* Description: Performs all one time clean up for this test on successful    */
85 /*              completion,  premature exit or  failure. Closes all temporary */
86 /*              files, removes all temporary directories exits the test with  */
87 /*              appropriate return code by calling tst_exit() function.       */
88 /*                                                                            */
89 /* Input:       None.                                                         */
90 /*                                                                            */
91 /* Output:      None.                                                         */
92 /*                                                                            */
93 /* Return:      On failure - Exits calling tst_exit(). Non '0' return code.   */
94 /*              On success - Exits calling tst_exit(). With '0' return code.  */
95 /*                                                                            */
96 /******************************************************************************/
cleanup(void)97 void cleanup(void)
98 {
99 
100 	tst_rmdir();
101 
102 }
103 
104 /* Local  Functions */
105 /******************************************************************************/
106 /*                                                                            */
107 /* Function:    setup                                                         */
108 /*                                                                            */
109 /* Description: Performs all one time setup for this test. This function is   */
110 /*              typically used to capture signals, create temporary dirs      */
111 /*              and temporary files that may be used in the course of this    */
112 /*              test.                                                         */
113 /*                                                                            */
114 /* Input:       None.                                                         */
115 /*                                                                            */
116 /* Output:      None.                                                         */
117 /*                                                                            */
118 /* Return:      On failure - Exits by calling cleanup().                      */
119 /*              On success - returns 0.                                       */
120 /*                                                                            */
121 /******************************************************************************/
setup(void)122 void setup(void)
123 {
124 	/* Capture signals if any */
125 	/* Create temporary directories */
126 	TEST_PAUSE;
127 	tst_tmpdir();
128 }
129 
main(int argc,char * argv[])130 int main(int argc, char *argv[])
131 {
132 	int fd, fds[2], i, coe;
133 	int lc;
134 
135 	tst_parse_opts(argc, argv, NULL, NULL);
136 	if ((tst_kvercmp(2, 6, 27)) < 0) {
137 		tst_brkm(TCONF,
138 			 NULL,
139 			 "This test can only run on kernels that are 2.6.27 and higher");
140 	}
141 	setup();
142 
143 	for (lc = 0; TEST_LOOPING(lc); ++lc) {
144 		tst_count = 0;
145 		for (testno = 0; testno < TST_TOTAL; ++testno) {
146 			fd = socket(PF_INET, SOCK_STREAM, 0);
147 			if (fd == -1) {
148 				tst_brkm(TBROK, cleanup, "socket(0) failed");
149 			}
150 			coe = fcntl(fd, F_GETFD);
151 			if (coe == -1) {
152 				tst_brkm(TBROK, cleanup, "fcntl failed");
153 			}
154 			if (coe & FD_CLOEXEC) {
155 				tst_brkm(TFAIL,
156 					 cleanup,
157 					 "socket(0) set close-on-exec flag");
158 			}
159 			close(fd);
160 
161 			fd = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
162 			if (fd == -1) {
163 				tst_brkm(TFAIL, cleanup,
164 					 "socket(SOCK_CLOEXEC) failed");
165 			}
166 			coe = fcntl(fd, F_GETFD);
167 			if (coe == -1) {
168 				tst_brkm(TBROK, cleanup, "fcntl failed");
169 			}
170 			if ((coe & FD_CLOEXEC) == 0) {
171 				tst_brkm(TFAIL,
172 					 cleanup,
173 					 "socket(SOCK_CLOEXEC) does not set close-on-exec flag");
174 			}
175 			close(fd);
176 
177 			if (socketpair(PF_UNIX, SOCK_STREAM, 0, fds) == -1) {
178 				tst_brkm(TBROK, cleanup,
179 					 "socketpair(0) failed");
180 			}
181 			for (i = 0; i < 2; ++i) {
182 				coe = fcntl(fds[i], F_GETFD);
183 				if (coe == -1) {
184 					tst_brkm(TBROK, cleanup,
185 						 "fcntl failed");
186 				}
187 				if (coe & FD_CLOEXEC) {
188 					tst_brkm(TFAIL,
189 						 cleanup, "socketpair(0) set close-on-exec flag for fds[%d]\n",
190 						 i);
191 				}
192 				close(fds[i]);
193 			}
194 
195 			if (socketpair
196 			    (PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0,
197 			     fds) == -1) {
198 				tst_brkm(TBROK, cleanup,
199 					 "socketpair(SOCK_CLOEXEC) failed");
200 			}
201 			for (i = 0; i < 2; ++i) {
202 				coe = fcntl(fds[i], F_GETFD);
203 				if (coe == -1) {
204 					tst_brkm(TBROK, cleanup,
205 						 "fcntl failed");
206 				}
207 				if ((coe & FD_CLOEXEC) == 0) {
208 					tst_brkm(TFAIL,
209 						 cleanup, "socketpair(SOCK_CLOEXEC) does not set close-on-exec flag for fds[%d]\n",
210 						 i);
211 				}
212 				close(fds[i]);
213 			}
214 			tst_resm(TPASS, "socket(SOCK_CLOEXEC) PASSED");
215 			cleanup();
216 		}
217 	}
218 	tst_exit();
219 }
220