]> granicus.if.org Git - strace/blob - tests/sockopt-sol_netlink.c
c6b1649fa3e4982a6e60a94349c770f83e252b76
[strace] / tests / sockopt-sol_netlink.c
1 /*
2  * Check decoding of getsockopt and setsockopt for SOL_NETLINK level.
3  *
4  * Copyright (c) 2017 Dmitry V. Levin <ldv@altlinux.org>
5  * All rights reserved.
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9
10 #include "tests.h"
11 #include "netlink.h"
12 #include <stdio.h>
13
14 #ifndef SOL_NETLINK
15 # define SOL_NETLINK 270
16 #endif
17
18 static int rc;
19 static const char *errstr;
20
21 static int
22 get_sockopt(int fd, int name, void *val, socklen_t *len)
23 {
24         rc = getsockopt(fd, SOL_NETLINK, name, val, len);
25         errstr = sprintrc(rc);
26         return rc;
27 }
28
29 static int
30 set_sockopt(int fd, int name, void *val, socklen_t len)
31 {
32         rc = setsockopt(fd, SOL_NETLINK, name, val, len);
33         errstr = sprintrc(rc);
34         return rc;
35 }
36
37 int
38 main(void)
39 {
40         static const struct {
41                 int val;
42                 const char *str;
43         } names[] = {
44 #ifdef NETLINK_ADD_MEMBERSHIP
45                 { ARG_STR(NETLINK_ADD_MEMBERSHIP) },
46 #endif
47 #ifdef NETLINK_DROP_MEMBERSHIP
48                 { ARG_STR(NETLINK_DROP_MEMBERSHIP) },
49 #endif
50 #ifdef NETLINK_PKTINFO
51                 { ARG_STR(NETLINK_PKTINFO) },
52 #endif
53 #ifdef NETLINK_BROADCAST_ERROR
54                 { ARG_STR(NETLINK_BROADCAST_ERROR) },
55 #endif
56 #ifdef NETLINK_NO_ENOBUFS
57                 { ARG_STR(NETLINK_NO_ENOBUFS) },
58 #endif
59 #ifdef NETLINK_RX_RING
60                 { ARG_STR(NETLINK_RX_RING) },
61 #endif
62 #ifdef NETLINK_TX_RING
63                 { ARG_STR(NETLINK_TX_RING) },
64 #endif
65 #ifdef NETLINK_LISTEN_ALL_NSID
66                 { ARG_STR(NETLINK_LISTEN_ALL_NSID) },
67 #endif
68 #ifdef NETLINK_LIST_MEMBERSHIPS
69                 { ARG_STR(NETLINK_LIST_MEMBERSHIPS) },
70 #endif
71 #ifdef NETLINK_CAP_ACK
72                 { ARG_STR(NETLINK_CAP_ACK) },
73 #endif
74 #ifdef NETLINK_EXT_ACK
75                 { ARG_STR(NETLINK_EXT_ACK) },
76 #endif
77         };
78
79         TAIL_ALLOC_OBJECT_CONST_PTR(int, val);
80         TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len);
81         void *const efault = val + 1;
82         int fd = socket(AF_NETLINK, SOCK_RAW, 0);
83         if (fd < 0)
84                 perror_msg_and_skip("socket AF_NETLINK SOCK_RAW");
85         unsigned int i;
86
87         for (i = 0; i < ARRAY_SIZE(names); ++i) {
88                 /* getsockopt */
89
90                 /* classic */
91                 *len = sizeof(*val);
92                 get_sockopt(fd, names[i].val, val, len);
93                 printf("getsockopt(%d, SOL_NETLINK, %s, ", fd, names[i].str);
94                 if (rc)
95                         printf("%p", val);
96                 else
97                         printf("[%d]", *val);
98                 printf(", [%d]) = %s\n", *len, errstr);
99
100                 /* optlen larger than necessary - shortened */
101                 *len = sizeof(*val) + 1;
102                 get_sockopt(fd, names[i].val, val, len);
103                 printf("getsockopt(%d, SOL_NETLINK, %s, ", fd, names[i].str);
104                 if (rc)
105                         printf("%p", val);
106                 else
107                         printf("[%d]", *val);
108                 printf(", [%d", (int) sizeof(*val) + 1);
109                 if ((int) sizeof(*val) + 1 != *len)
110                         printf("->%d", *len);
111                 printf("]) = %s\n", errstr);
112
113                 /* zero optlen - print returned optlen */
114                 *len = 0;
115                 get_sockopt(fd, names[i].val, NULL, len);
116                 printf("getsockopt(%d, SOL_NETLINK, %s, NULL, [0",
117                        fd, names[i].str);
118                 if (*len)
119                         printf("->%d", *len);
120                 printf("]) = %s\n", errstr);
121
122 #ifdef NETLINK_LIST_MEMBERSHIPS
123                 if (names[i].val != NETLINK_LIST_MEMBERSHIPS) {
124 #endif
125                         /* optlen shorter than necessary - print address */
126                         *len = sizeof(*val) - 1;
127                         get_sockopt(fd, names[i].val, val, len);
128                         printf("getsockopt(%d, SOL_NETLINK, %s, %p, [%d",
129                                fd, names[i].str, val, (int) sizeof(*val) - 1);
130                         if ((int) sizeof(*val) - 1 != *len)
131                                 printf("->%d", *len);
132                         printf("]) = %s\n", errstr);
133 #ifdef NETLINK_LIST_MEMBERSHIPS
134                 } else {
135                         /* optlen shorter than required for the first element */
136                         *len = sizeof(*val) - 1;
137                         get_sockopt(fd, names[i].val, efault, len);
138                         printf("getsockopt(%d, SOL_NETLINK, %s, ",
139                                fd, names[i].str);
140                         if (rc)
141                                 printf("%p", efault);
142                         else
143                                 printf("[]");
144                         printf(", [%d", (int) sizeof(*val) - 1);
145                         if ((int) sizeof(*val) - 1 != *len)
146                                 printf("->%d", *len);
147                         printf("]) = %s\n", errstr);
148                 }
149 #endif
150
151                 /* optval EFAULT - print address */
152                 *len = sizeof(*val);
153                 get_sockopt(fd, names[i].val, efault, len);
154                 printf("getsockopt(%d, SOL_NETLINK, %s, %p, [%d]) = %s\n",
155                        fd, names[i].str, efault, *len, errstr);
156
157                 /* optlen EFAULT - print address */
158                 get_sockopt(fd, names[i].val, val, len + 1);
159                 printf("getsockopt(%d, SOL_NETLINK, %s, %p, %p) = %s\n",
160                        fd, names[i].str, val, len + 1, errstr);
161
162                 /* setsockopt */
163
164                 /* classic */
165                 *val = 0xdefaced;
166                 set_sockopt(fd, names[i].val, val, sizeof(*val));
167                 printf("setsockopt(%d, SOL_NETLINK, %s, [%d], %d) = %s\n",
168                        fd, names[i].str, *val, (int) sizeof(*val), errstr);
169
170                 /* optlen larger than necessary - shortened */
171                 set_sockopt(fd, names[i].val, val, sizeof(*val) + 1);
172                 printf("setsockopt(%d, SOL_NETLINK, %s, [%d], %d) = %s\n",
173                        fd, names[i].str, *val, (int) sizeof(*val) + 1, errstr);
174
175                 /* optlen < 0 - print address */
176                 set_sockopt(fd, names[i].val, val, -1U);
177                 printf("setsockopt(%d, SOL_NETLINK, %s, %p, -1) = %s\n",
178                        fd, names[i].str, val, errstr);
179
180                 /* optlen smaller than necessary - print address */
181                 set_sockopt(fd, names[i].val, val, sizeof(*val) - 1);
182                 printf("setsockopt(%d, SOL_NETLINK, %s, %p, %d) = %s\n",
183                        fd, names[i].str, val, (int) sizeof(*val) - 1, errstr);
184
185                 /* optval EFAULT - print address */
186                 set_sockopt(fd, names[i].val, efault, sizeof(*val));
187                 printf("setsockopt(%d, SOL_NETLINK, %s, %p, %d) = %s\n",
188                        fd, names[i].str, efault, (int) sizeof(*val), errstr);
189         }
190
191         puts("+++ exited with 0 +++");
192         return 0;
193 }