blob: 00ef6934ced521bd528cb6ce3d479c4d12389894 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
Cyril Hrubise90b03c2012-10-10 11:40:24 +02004 * Copyright (c) Cyril Hrubis <chrubis@suse.cz> 2012
plars865695b2001-08-27 22:15:12 +00005 *
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
Wanlong Gao4548c6c2012-10-19 18:03:36 +080018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000019 */
20
21/*
22 * Test Name: send01
23 *
24 * Test Description:
25 * Verify that send() returns the proper errno for various failure cases
26 *
plars865695b2001-08-27 22:15:12 +000027 * HISTORY
28 * 07/2001 Ported by Wayne Boyer
29 *
plars865695b2001-08-27 22:15:12 +000030 */
31
32#include <stdio.h>
33#include <unistd.h>
34#include <errno.h>
plars0c850b72002-03-26 20:39:19 +000035#include <fcntl.h>
plars865695b2001-08-27 22:15:12 +000036
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <sys/signal.h>
40#include <sys/un.h>
41
42#include <netinet/in.h>
43
44#include "test.h"
plars865695b2001-08-27 22:15:12 +000045
Cyril Hrubise90b03c2012-10-10 11:40:24 +020046char *TCID = "send01";
plars865695b2001-08-27 22:15:12 +000047int testno;
48
Cyril Hrubise90b03c2012-10-10 11:40:24 +020049static char buf[1024], bigbuf[128 * 1024];
50static int s;
51static struct sockaddr_in sin1;
Wanlong Gao354ebb42012-12-07 10:10:04 +080052static int sfd; /* shared between do_child and start_server */
plars865695b2001-08-27 22:15:12 +000053
54struct test_case_t { /* test case structure */
subrata_modak56207ce2009-03-23 13:35:39 +000055 int domain; /* PF_INET, PF_UNIX, ... */
56 int type; /* SOCK_STREAM, SOCK_DGRAM ... */
57 int proto; /* protocol number (usually 0 = default) */
58 void *buf; /* send data buffer */
59 int buflen; /* send's 3rd argument */
60 unsigned flags; /* send's 4th argument */
Cyril Hrubise90b03c2012-10-10 11:40:24 +020061 int retval;
62 int experrno;
Wanlong Gao354ebb42012-12-07 10:10:04 +080063 void (*setup) (void);
64 void (*cleanup) (void);
plars865695b2001-08-27 22:15:12 +000065 char *desc;
Cyril Hrubise90b03c2012-10-10 11:40:24 +020066};
67
68static void cleanup(void);
69static void do_child(void);
70static void setup(void);
71static void setup0(void);
72static void setup1(void);
73static void setup2(void);
74static void cleanup0(void);
75static void cleanup1(void);
76
77static struct test_case_t tdat[] = {
78 {.domain = PF_INET,
79 .type = SOCK_STREAM,
80 .proto = 0,
81 .buf = buf,
82 .buflen = sizeof(buf),
83 .flags = 0,
84 .retval = -1,
85 .experrno = EBADF,
86 .setup = setup0,
87 .cleanup = cleanup0,
Wanlong Gao354ebb42012-12-07 10:10:04 +080088 .desc = "bad file descriptor"}
89 ,
Cyril Hrubise90b03c2012-10-10 11:40:24 +020090 {.domain = 0,
91 .type = 0,
92 .proto = 0,
93 .buf = buf,
94 .buflen = sizeof(buf),
95 .flags = 0,
96 .retval = -1,
97 .experrno = ENOTSOCK,
98 .setup = setup0,
99 .cleanup = cleanup0,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800100 .desc = "invalid socket"}
101 ,
vapier7ec19d92006-02-27 04:38:56 +0000102#ifndef UCLINUX
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200103 /* Skip since uClinux does not implement memory protection */
104 {.domain = PF_INET,
105 .type = SOCK_STREAM,
106 .proto = 0,
107 .buf = (void *)-1,
108 .buflen = sizeof(buf),
109 .flags = 0,
110 .retval = -1,
111 .experrno = EFAULT,
112 .setup = setup1,
113 .cleanup = cleanup1,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800114 .desc = "invalid send buffer"}
115 ,
vapier7ec19d92006-02-27 04:38:56 +0000116#endif
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200117 {.domain = PF_INET,
118 .type = SOCK_DGRAM,
119 .proto = 0,
120 .buf = bigbuf,
121 .buflen = sizeof(bigbuf),
122 .flags = 0,
123 .retval = -1,
124 .experrno = EMSGSIZE,
125 .setup = setup1,
126 .cleanup = cleanup1,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800127 .desc = "UDP message too big"}
128 ,
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200129 {.domain = PF_INET,
130 .type = SOCK_STREAM,
131 .proto = 0,
132 .buf = buf,
133 .buflen = sizeof(buf),
134 .flags = 0,
135 .retval = -1,
136 .experrno = EPIPE,
137 .setup = setup2,
138 .cleanup = cleanup1,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800139 .desc = "local endpoint shutdown"}
140 ,
vapier7ec19d92006-02-27 04:38:56 +0000141#ifndef UCLINUX
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200142 /* Skip since uClinux does not implement memory protection */
143 {.domain = PF_INET,
Jan Stancek1c6354e2013-11-29 11:39:34 +0100144 .type = SOCK_DGRAM,
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200145 .proto = 0,
Jan Stancek1c6354e2013-11-29 11:39:34 +0100146 .buf = buf,
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200147 .buflen = sizeof(buf),
Jan Stancek1c6354e2013-11-29 11:39:34 +0100148 .flags = MSG_OOB,
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200149 .retval = -1,
Jan Stancek1c6354e2013-11-29 11:39:34 +0100150 .experrno = EOPNOTSUPP,
151 .setup = setup1,
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200152 .cleanup = cleanup1,
153 .desc = "invalid flags set"}
vapier7ec19d92006-02-27 04:38:56 +0000154#endif
plars865695b2001-08-27 22:15:12 +0000155};
156
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200157int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
plars865695b2001-08-27 22:15:12 +0000158
robbiewd34d5812005-07-11 22:28:09 +0000159#ifdef UCLINUX
160static char *argv0;
161#endif
162
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200163static pid_t start_server(struct sockaddr_in *sin0)
robbiewaa01abd2003-03-27 18:39:24 +0000164{
subrata_modak56207ce2009-03-23 13:35:39 +0000165 pid_t pid;
Jan Stancek6e4e77a2014-03-07 11:39:56 +0100166 socklen_t slen = sizeof(*sin0);
167
168 sin0->sin_family = AF_INET;
169 sin0->sin_port = 0; /* pick random free port */
170 sin0->sin_addr.s_addr = INADDR_ANY;
robbiewaa01abd2003-03-27 18:39:24 +0000171
172 sfd = socket(PF_INET, SOCK_STREAM, 0);
173 if (sfd < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800174 tst_brkm(TBROK | TERRNO, cleanup, "server socket failed");
robbiewaa01abd2003-03-27 18:39:24 +0000175 return -1;
176 }
Jan Stancek6e4e77a2014-03-07 11:39:56 +0100177 if (bind(sfd, (struct sockaddr *)sin0, sizeof(*sin0)) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800178 tst_brkm(TBROK | TERRNO, cleanup, "server bind failed");
robbiewaa01abd2003-03-27 18:39:24 +0000179 return -1;
180 }
181 if (listen(sfd, 10) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800182 tst_brkm(TBROK | TERRNO, cleanup, "server listen failed");
robbiewaa01abd2003-03-27 18:39:24 +0000183 return -1;
184 }
Jan Stancek6e4e77a2014-03-07 11:39:56 +0100185 if (getsockname(sfd, (struct sockaddr *)sin0, &slen) == -1)
186 tst_brkm(TBROK | TERRNO, cleanup, "getsockname failed");
187
robbiewd34d5812005-07-11 22:28:09 +0000188 switch ((pid = FORK_OR_VFORK())) {
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200189 case 0:
robbiewd34d5812005-07-11 22:28:09 +0000190#ifdef UCLINUX
vapierc450e062009-08-28 14:28:52 +0000191 if (self_exec(argv0, "d", sfd) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800192 tst_brkm(TBROK | TERRNO, cleanup,
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200193 "server self_exec failed");
robbiewd34d5812005-07-11 22:28:09 +0000194#else
195 do_child();
196#endif
robbiewaa01abd2003-03-27 18:39:24 +0000197 break;
198 case -1:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800199 tst_brkm(TBROK | TERRNO, cleanup, "server fork failed");
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200200 default:
201 close(sfd);
robbiewaa01abd2003-03-27 18:39:24 +0000202 return pid;
203 }
204
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200205 exit(1);
robbiewd34d5812005-07-11 22:28:09 +0000206}
207
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200208static void do_child(void)
robbiewd34d5812005-07-11 22:28:09 +0000209{
subrata_modak56207ce2009-03-23 13:35:39 +0000210 fd_set afds, rfds;
211 int nfds, cc, fd;
212 struct sockaddr_in fsin;
robbiewd34d5812005-07-11 22:28:09 +0000213
robbiewaa01abd2003-03-27 18:39:24 +0000214 FD_ZERO(&afds);
215 FD_SET(sfd, &afds);
216
Cyril Hrubis7855d092014-10-09 16:13:05 +0200217 nfds = sfd + 1;
robbiewaa01abd2003-03-27 18:39:24 +0000218
219 /* accept connections until killed */
220 while (1) {
subrata_modak56207ce2009-03-23 13:35:39 +0000221 socklen_t fromlen;
robbiewaa01abd2003-03-27 18:39:24 +0000222
223 memcpy(&rfds, &afds, sizeof(rfds));
224
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200225 if (select(nfds, &rfds, NULL, NULL, NULL) < 0)
robbiewaa01abd2003-03-27 18:39:24 +0000226 if (errno != EINTR)
227 exit(1);
228 if (FD_ISSET(sfd, &rfds)) {
229 int newfd;
230
231 fromlen = sizeof(fsin);
subrata_modak56207ce2009-03-23 13:35:39 +0000232 newfd = accept(sfd, (struct sockaddr *)&fsin, &fromlen);
Cyril Hrubis7855d092014-10-09 16:13:05 +0200233 if (newfd >= 0) {
robbiewaa01abd2003-03-27 18:39:24 +0000234 FD_SET(newfd, &afds);
Cyril Hrubis7855d092014-10-09 16:13:05 +0200235 nfds = MAX(nfds, newfd + 1);
236 }
robbiewaa01abd2003-03-27 18:39:24 +0000237 }
subrata_modak56207ce2009-03-23 13:35:39 +0000238 for (fd = 0; fd < nfds; ++fd) {
robbiewaa01abd2003-03-27 18:39:24 +0000239 if (fd != sfd && FD_ISSET(fd, &rfds)) {
240 cc = read(fd, buf, sizeof(buf));
241 if (cc == 0 || (cc < 0 && errno != EINTR)) {
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200242 close(fd);
robbiewaa01abd2003-03-27 18:39:24 +0000243 FD_CLR(fd, &afds);
244 }
245 }
246 }
247 }
248}
249
subrata_modak56207ce2009-03-23 13:35:39 +0000250int main(int ac, char *av[])
plars865695b2001-08-27 22:15:12 +0000251{
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200252 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200253 const char *msg;
plars865695b2001-08-27 22:15:12 +0000254
Garrett Coopera9e49f12010-12-16 10:54:03 -0800255 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -0800256 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200257
robbiewd34d5812005-07-11 22:28:09 +0000258#ifdef UCLINUX
259 argv0 = av[0];
260 maybe_run_child(&do_child, "d", &sfd);
261#endif
262
plars865695b2001-08-27 22:15:12 +0000263 setup();
264
plars865695b2001-08-27 22:15:12 +0000265 for (lc = 0; TEST_LOOPING(lc); ++lc) {
266
Caspar Zhangd59a6592013-03-07 14:59:12 +0800267 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000268
subrata_modak56207ce2009-03-23 13:35:39 +0000269 for (testno = 0; testno < TST_TOTAL; ++testno) {
plars865695b2001-08-27 22:15:12 +0000270 tdat[testno].setup();
271
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200272 TEST(send(s, tdat[testno].buf, tdat[testno].buflen,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800273 tdat[testno].flags));
plars865695b2001-08-27 22:15:12 +0000274
275 if (TEST_RETURN != -1) {
276 tst_resm(TFAIL, "call succeeded unexpectedly");
277 continue;
278 }
279
plars865695b2001-08-27 22:15:12 +0000280 if (TEST_ERRNO != tdat[testno].experrno) {
281 tst_resm(TFAIL, "%s ; returned"
vapierc450e062009-08-28 14:28:52 +0000282 " %ld (expected %d), errno %d (expected"
subrata_modak56207ce2009-03-23 13:35:39 +0000283 " %d)", tdat[testno].desc,
284 TEST_RETURN, tdat[testno].retval,
285 TEST_ERRNO, tdat[testno].experrno);
plars865695b2001-08-27 22:15:12 +0000286 } else {
287 tst_resm(TPASS, "%s successful",
subrata_modak56207ce2009-03-23 13:35:39 +0000288 tdat[testno].desc);
plars865695b2001-08-27 22:15:12 +0000289 }
290 tdat[testno].cleanup();
291 }
292 }
293 cleanup();
294
Garrett Cooper53740502010-12-16 00:04:01 -0800295 tst_exit();
plars865695b2001-08-27 22:15:12 +0000296}
297
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200298static pid_t server_pid;
plars865695b2001-08-27 22:15:12 +0000299
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200300static void setup(void)
plars865695b2001-08-27 22:15:12 +0000301{
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200302 TEST_PAUSE;
plars865695b2001-08-27 22:15:12 +0000303
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200304 server_pid = start_server(&sin1);
plars865695b2001-08-27 22:15:12 +0000305
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200306 signal(SIGPIPE, SIG_IGN);
plars865695b2001-08-27 22:15:12 +0000307}
308
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200309static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000310{
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200311 kill(server_pid, SIGKILL);
Garrett Cooper2c282152010-12-16 00:55:50 -0800312
plars865695b2001-08-27 22:15:12 +0000313}
314
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200315static void setup0(void)
plars865695b2001-08-27 22:15:12 +0000316{
317 if (tdat[testno].experrno == EBADF)
318 s = 400; /* anything not an open file */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800319 else if ((s = open("/dev/null", O_WRONLY)) == -1)
320 tst_brkm(TBROK | TERRNO, cleanup, "open(/dev/null) failed");
plars865695b2001-08-27 22:15:12 +0000321}
322
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200323static void cleanup0(void)
plars865695b2001-08-27 22:15:12 +0000324{
325 s = -1;
326}
327
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200328static void setup1(void)
plars865695b2001-08-27 22:15:12 +0000329{
330 s = socket(tdat[testno].domain, tdat[testno].type, tdat[testno].proto);
vapierc450e062009-08-28 14:28:52 +0000331 if (s < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800332 tst_brkm(TBROK | TERRNO, cleanup, "socket setup failed");
vapierc450e062009-08-28 14:28:52 +0000333 if (connect(s, (const struct sockaddr *)&sin1, sizeof(sin1)) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800334 tst_brkm(TBROK | TERRNO, cleanup, "connect failed");
plars865695b2001-08-27 22:15:12 +0000335}
336
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200337static void cleanup1(void)
plars865695b2001-08-27 22:15:12 +0000338{
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200339 close(s);
plars865695b2001-08-27 22:15:12 +0000340 s = -1;
341}
342
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200343static void setup2(void)
plars865695b2001-08-27 22:15:12 +0000344{
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200345 setup1();
346
vapierc450e062009-08-28 14:28:52 +0000347 if (shutdown(s, 1) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800348 tst_brkm(TBROK | TERRNO, cleanup, "socket setup failed connect "
vapierc450e062009-08-28 14:28:52 +0000349 "test %d", testno);
Cyril Hrubise90b03c2012-10-10 11:40:24 +0200350}