]> granicus.if.org Git - strace/blob - tests/so_linger.c
tests: extend TEST_NETLINK_OBJECT macro
[strace] / tests / so_linger.c
1 /*
2  * Check decoding of SO_LINGER socket option.
3  *
4  * Copyright (c) 2017 Dmitry V. Levin <ldv@altlinux.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "tests.h"
31
32 #include <stdio.h>
33 #include <sys/socket.h>
34 #include <unistd.h>
35
36 static const char *errstr;
37
38 static int
39 get_linger(int fd, void *val, socklen_t *len)
40 {
41         int rc = getsockopt(fd, SOL_SOCKET, SO_LINGER, val, len);
42         errstr = sprintrc(rc);
43         return rc;
44 }
45
46 static int
47 set_linger(int fd, void *val, socklen_t len)
48 {
49         int rc = setsockopt(fd, SOL_SOCKET, SO_LINGER, val, len);
50         errstr = sprintrc(rc);
51         return rc;
52 }
53
54 int
55 main(void)
56 {
57         TAIL_ALLOC_OBJECT_CONST_PTR(struct linger, linger);
58         TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len);
59         int fd = socket(AF_UNIX, SOCK_STREAM, 0);
60         if (fd < 0)
61                 perror_msg_and_skip("socket AF_UNIX SOCK_STREAM");
62
63         /* classic getsockopt */
64         *len = sizeof(*linger);
65         get_linger(fd, linger, len);
66         printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}"
67                ", [%d]) = %s\n",
68                fd, linger->l_onoff, linger->l_linger, *len, errstr);
69
70         /* classic setsockopt */
71         linger->l_onoff = -15;
72         linger->l_linger = -42;
73         set_linger(fd, linger, sizeof(*linger));
74         printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}"
75                ", %d) = %s\n",
76                fd, linger->l_onoff, linger->l_linger,
77                (unsigned int) sizeof(*linger), errstr);
78
79         /* setsockopt with optlen larger than necessary */
80         set_linger(fd, linger, sizeof(*linger) + 1);
81         printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}"
82                ", %d) = %s\n",
83                fd, linger->l_onoff, linger->l_linger,
84                (unsigned int) sizeof(*linger) + 1, errstr);
85
86         /* setsockopt with optlen < 0 - EINVAL */
87         set_linger(fd, linger, -1U);
88         printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, %p, -1) = %s\n",
89                fd, linger, errstr);
90
91         /* setsockopt with optlen smaller than necessary - EINVAL */
92         set_linger(fd, linger, sizeof(linger->l_onoff));
93         printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, %p, %d) = %s\n",
94                fd, linger, (unsigned int) sizeof(linger->l_onoff), errstr);
95
96         /* setsockopt optval EFAULT */
97         set_linger(fd, &linger->l_linger, sizeof(*linger));
98         printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, %p, %d) = %s\n",
99                fd, &linger->l_linger, (unsigned int) sizeof(*linger), errstr);
100
101         /* getsockopt with optlen larger than necessary - shortened */
102         *len = sizeof(*linger) + 1;
103         get_linger(fd, linger, len);
104         printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}"
105                ", [%u->%d]) = %s\n",
106                fd, linger->l_onoff, linger->l_linger,
107                (unsigned int) sizeof(*linger) + 1, *len, errstr);
108
109         /* getsockopt with optlen larger than usual - truncated to l_onoff */
110         *len = sizeof(linger->l_onoff);
111         get_linger(fd, linger, len);
112         printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d}"
113                ", [%d]) = %s\n",
114                fd, linger->l_onoff, *len, errstr);
115
116         /* getsockopt with optlen larger than usual - truncated to raw */
117         *len = sizeof(*linger) - 1;
118         get_linger(fd, linger, len);
119         printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, ", fd);
120         print_quoted_hex(linger, *len);
121         printf(", [%d]) = %s\n", *len, errstr);
122
123         /* getsockopt optval EFAULT */
124         *len = sizeof(*linger);
125         get_linger(fd, &linger->l_linger, len);
126         printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, %p, [%d]) = %s\n",
127                fd, &linger->l_linger, *len, errstr);
128
129         /* getsockopt optlen EFAULT */
130         get_linger(fd, linger, len + 1);
131         printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, %p, %p) = %s\n",
132                fd, linger, len + 1, errstr);
133
134         puts("+++ exited with 0 +++");
135         return 0;
136 }