1/*
2* Copyright (c) Ulrich Drepper <drepper@redhat.com>
3* Copyright (c) International Business Machines  Corp., 2009
4*
5* This program is free software;  you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation; either version 2 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY;  without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13* the GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program.
17*/
18
19/*
20* Test Name:	socketpair02
21*
22* Description:
23* This Program tests the new flag SOCK_CLOEXEC and SOCK_NONBLOCK introduced
24* in socketpair() in kernel 2.6.27.
25*/
26
27#include <errno.h>
28#include <fcntl.h>
29#include <pthread.h>
30#include <stdio.h>
31#include <unistd.h>
32#include <netinet/in.h>
33#include <sys/socket.h>
34#include <sys/syscall.h>
35#include "lapi/fcntl.h"
36#include "tst_test.h"
37
38static int fds[2];
39
40static struct tcase {
41	int type;
42	int flag;
43	int fl_flag;
44	char *des;
45} tcases[] = {
46	{SOCK_STREAM, 0, F_GETFD, "no close-on-exec"},
47	{SOCK_STREAM | SOCK_CLOEXEC, FD_CLOEXEC, F_GETFD, "close-on-exec"},
48	{SOCK_STREAM, 0, F_GETFL, "no non-blocking"},
49	{SOCK_STREAM | SOCK_NONBLOCK, O_NONBLOCK, F_GETFL, "non-blocking"}
50};
51
52static void verify_socketpair(unsigned int n)
53{
54	int res, i;
55	struct tcase *tc = &tcases[n];
56
57	TEST(socketpair(PF_UNIX, tc->type, 0, fds));
58
59	if (TEST_RETURN == -1)
60		tst_brk(TFAIL | TTERRNO, "socketpair() failed");
61
62	for (i = 0; i < 2; i++) {
63		res = SAFE_FCNTL(fds[i], tc->fl_flag);
64
65		if (tc->flag != 0 && (res & tc->flag) == 0) {
66			tst_res(TFAIL, "socketpair() failed to set %s flag for fds[%d]",
67				tc->des, i);
68			goto ret;
69		}
70
71		if (tc->flag == 0 && (res & tc->flag) != 0) {
72			tst_res(TFAIL, "socketpair() failed to set %s flag for fds[%d]",
73				tc->des, i);
74			goto ret;
75		}
76	}
77
78	tst_res(TPASS, "socketpair() passed to set %s flag", tc->des);
79
80ret:
81	SAFE_CLOSE(fds[0]);
82	SAFE_CLOSE(fds[1]);
83}
84
85static void cleanup(void)
86{
87	if (fds[0] > 0)
88		SAFE_CLOSE(fds[0]);
89
90	if (fds[1] > 0)
91		SAFE_CLOSE(fds[1]);
92}
93
94static struct tst_test test = {
95	.tcnt = ARRAY_SIZE(tcases),
96	.test = verify_socketpair,
97	.min_kver = "2.6.27",
98	.cleanup = cleanup
99};
100