1 /*
2 * Copyright (c) 2018-2019 The strace developers.
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include "tests.h"
9 #include <stdio.h>
10 #include <sys/socket.h>
11 #include <linux/if_packet.h>
12
13 static const char *errstr;
14
15 static long
16 packet_mreq_membership(int optname, void *optval, socklen_t len)
17 {
18 long rc = setsockopt(-1, SOL_PACKET, optname, optval, len);
19 errstr = sprintrc(rc);
20 return rc;
21 }
22
23 static void
24 test_packet_mreq(const int optname, const char *const optname_str)
25 {
26 TAIL_ALLOC_OBJECT_CONST_PTR(struct packet_mreq, pmreq);
27 socklen_t len = sizeof(struct packet_mreq);
28
29 /* setsockopt with optname unknown */
30 packet_mreq_membership(-1, NULL, 0);
31 #if XLAT_RAW
32 printf("setsockopt(-1, %#x, %#x, NULL, 0) = %s\n",
33 SOL_PACKET, -1, errstr);
34 #elif XLAT_VERBOSE
35 printf("setsockopt(-1, %#x /* SOL_PACKET */, %#x /* PACKET_??? */"
36 ", NULL, 0) = %s\n", SOL_PACKET, -1, errstr);
37 #else
38 printf("setsockopt(-1, SOL_PACKET, %#x /* PACKET_??? */, NULL, 0) = %s\n",
39 -1, errstr);
40 #endif
41
42 /* setsockopt with mr_type unknown */
43 pmreq->mr_ifindex = 0;
44 pmreq->mr_alen = ARRAY_SIZE(pmreq->mr_address);
45 packet_mreq_membership(optname, pmreq, len);
46 #if XLAT_RAW
47 printf("setsockopt(-1, %#x, %#x, {mr_ifindex=%d,"
48 " mr_type=%#x, mr_alen=%d, mr_address=",
49 SOL_PACKET, optname, pmreq->mr_ifindex,
50 pmreq->mr_type, pmreq->mr_alen);
51 print_quoted_hex((const void *) pmreq->mr_address,
52 ARRAY_SIZE(pmreq->mr_address));
53 printf("}, %d) = %s\n", len, errstr);
54 #elif XLAT_VERBOSE
55 printf("setsockopt(-1, %#x /* SOL_PACKET */, %#x /* %s */"
56 ", {mr_ifindex=%d, mr_type=%#x /* PACKET_MR_??? */"
57 ", mr_alen=%d, mr_address=",
58 SOL_PACKET, optname, optname_str, pmreq->mr_ifindex,
59 pmreq->mr_type, pmreq->mr_alen);
60 print_quoted_hex((const void *) pmreq->mr_address,
61 ARRAY_SIZE(pmreq->mr_address));
62 printf(" /* ");
63 for (unsigned int i = 0; i < ARRAY_SIZE(pmreq->mr_address); i++)
64 printf("%s%02x", i > 0 ? ":" : "", pmreq->mr_address[i]);
65 printf(" */}, %d) = %s\n", len, errstr);
66 #else
67 printf("setsockopt(-1, SOL_PACKET, %s, {mr_ifindex=%d,"
68 " mr_type=%#x /* PACKET_MR_??? */, mr_alen=%d, mr_address=",
69 optname_str, pmreq->mr_ifindex, pmreq->mr_type, pmreq->mr_alen);
70 for (unsigned int i = 0; i < ARRAY_SIZE(pmreq->mr_address); i++)
71 printf("%s%02x", i > 0 ? ":" : "", pmreq->mr_address[i]);
72 printf("}, %d) = %s\n", len, errstr);
73 #endif
74
75 /* setsockopt with mr_type unknown and mr_alen > sizeof(mr_address) */
76 pmreq->mr_alen = ARRAY_SIZE(pmreq->mr_address) + 1;
77 packet_mreq_membership(optname, pmreq, len);
78 #if XLAT_RAW
79 printf("setsockopt(-1, %#x, %#x, {mr_ifindex=%d,"
80 " mr_type=%#x, mr_alen=%d, mr_address=",
81 SOL_PACKET, optname, pmreq->mr_ifindex,
82 pmreq->mr_type, pmreq->mr_alen);
83 print_quoted_hex((const void *) pmreq->mr_address,
84 ARRAY_SIZE(pmreq->mr_address));
85 printf("}, %d) = %s\n", len, errstr);
86 #elif XLAT_VERBOSE
87 printf("setsockopt(-1, %#x /* SOL_PACKET */, %#x /* %s */"
88 ", {mr_ifindex=%d, mr_type=%#x /* PACKET_MR_??? */"
89 ", mr_alen=%d, mr_address=",
90 SOL_PACKET, optname, optname_str, pmreq->mr_ifindex,
91 pmreq->mr_type, pmreq->mr_alen);
92 print_quoted_hex((const void *) pmreq->mr_address,
93 ARRAY_SIZE(pmreq->mr_address));
94 printf(" /* ");
95 for (unsigned int i = 0; i < ARRAY_SIZE(pmreq->mr_address); i++)
96 printf("%s%02x", i > 0 ? ":" : "", pmreq->mr_address[i]);
97 printf(" */}, %d) = %s\n", len, errstr);
98 #else
99 printf("setsockopt(-1, SOL_PACKET, %s, {mr_ifindex=%d,"
100 " mr_type=%#x /* PACKET_MR_??? */, mr_alen=%d, mr_address=",
101 optname_str, pmreq->mr_ifindex, pmreq->mr_type, pmreq->mr_alen);
102 for (unsigned int i = 0; i < ARRAY_SIZE(pmreq->mr_address); i++)
103 printf("%s%02x", i > 0 ? ":" : "", pmreq->mr_address[i]);
104 printf("}, %d) = %s\n", len, errstr);
105 #endif
106
107 /* setsockopt with mr_type unknown and mr_alen < sizeof(mr_address) */
108 pmreq->mr_alen = ARRAY_SIZE(pmreq->mr_address) - 1;
109 packet_mreq_membership(optname, pmreq, len);
110 #if XLAT_RAW
111 printf("setsockopt(-1, %#x, %#x, {mr_ifindex=%d,"
112 " mr_type=%#x, mr_alen=%d, mr_address=",
113 SOL_PACKET, optname, pmreq->mr_ifindex,
114 pmreq->mr_type, pmreq->mr_alen);
115 print_quoted_hex((const void *) pmreq->mr_address, pmreq->mr_alen);
116 printf("}, %d) = %s\n", len, errstr);
117 #elif XLAT_VERBOSE
118 printf("setsockopt(-1, %#x /* SOL_PACKET */, %#x /* %s */"
119 ", {mr_ifindex=%d, mr_type=%#x /* PACKET_MR_??? */"
120 ", mr_alen=%d, mr_address=",
121 SOL_PACKET, optname, optname_str, pmreq->mr_ifindex,
122 pmreq->mr_type, pmreq->mr_alen);
123 print_quoted_hex((const void *) pmreq->mr_address, pmreq->mr_alen);
124 printf(" /* ");
125 for (unsigned int i = 0; i < pmreq->mr_alen; i++)
126 printf("%s%02x", i > 0 ? ":" : "", pmreq->mr_address[i]);
127 printf(" */}, %d) = %s\n", len, errstr);
128 #else
129 printf("setsockopt(-1, SOL_PACKET, %s, {mr_ifindex=%d,"
130 " mr_type=%#x /* PACKET_MR_??? */, mr_alen=%d, mr_address=",
131 optname_str, pmreq->mr_ifindex, pmreq->mr_type, pmreq->mr_alen);
132 for (unsigned int i = 0; i < pmreq->mr_alen; i++)
133 printf("%s%02x", i > 0 ? ":" : "", pmreq->mr_address[i]);
134 printf("}, %d) = %s\n", len, errstr);
135 #endif
136
137 /* setsockopt with valid mr_type */
138 pmreq->mr_alen = ARRAY_SIZE(pmreq->mr_address);
139 static const struct {
140 unsigned short type;
141 const char *const type_str;
142 } a[] = {
143 { ARG_STR(PACKET_MR_MULTICAST) },
144 { ARG_STR(PACKET_MR_PROMISC) },
145 { ARG_STR(PACKET_MR_ALLMULTI) },
146 #ifdef PACKET_MR_UNICAST
147 { ARG_STR(PACKET_MR_UNICAST) },
148 #endif
149 };
150
151 for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) {
152 pmreq->mr_type = a[i].type;
153 packet_mreq_membership(optname, pmreq, len);
154 #if XLAT_RAW
155 printf("setsockopt(-1, %#x, %#x, {mr_ifindex=%d,"
156 " mr_type=%#x, mr_alen=%d, mr_address=",
157 SOL_PACKET, optname, pmreq->mr_ifindex,
158 pmreq->mr_type, pmreq->mr_alen);
159 print_quoted_hex((const void *) pmreq->mr_address, pmreq->mr_alen);
160 printf("}, %d) = %s\n", len, errstr);
161 #elif XLAT_VERBOSE
162 printf("setsockopt(-1, %#x /* SOL_PACKET */, %#x /* %s */"
163 ", {mr_ifindex=%d, mr_type=%#x /* %s */"
164 ", mr_alen=%d, mr_address=",
165 SOL_PACKET, optname, optname_str, pmreq->mr_ifindex,
166 pmreq->mr_type, a[i].type_str, pmreq->mr_alen);
167 print_quoted_hex((const void *) pmreq->mr_address, pmreq->mr_alen);
168 printf(" /* ");
169 for (unsigned int i = 0; i < pmreq->mr_alen; i++)
170 printf("%s%02x", i > 0 ? ":" : "", pmreq->mr_address[i]);
171 printf(" */}, %d) = %s\n", len, errstr);
172 #else
173 printf("setsockopt(-1, SOL_PACKET, %s, {mr_ifindex=%d,"
174 " mr_type=%s, mr_alen=%d, mr_address=",
175 optname_str, pmreq->mr_ifindex, a[i].type_str, pmreq->mr_alen);
176 for (unsigned int i = 0; i < pmreq->mr_alen; i++)
177 printf("%s%02x", i > 0 ? ":" : "", pmreq->mr_address[i]);
178 printf("}, %d) = %s\n", len, errstr);
179 #endif
180 }
181
182 /* setsockopt with optlen larger than usual */
183 len = len + 1;
184 packet_mreq_membership(optname, pmreq, len);
185 #if XLAT_RAW
186 printf("setsockopt(-1, %#x, %#x, %p, %d) = %s\n",
187 SOL_PACKET, optname, pmreq, len, errstr);
188 #elif XLAT_VERBOSE
189 printf("setsockopt(-1, %#x /* SOL_PACKET */, %#x /* %s */"
190 ", %p, %d) = %s\n", SOL_PACKET, optname, optname_str,
191 pmreq, len, errstr);
192 #else
193 printf("setsockopt(-1, SOL_PACKET, %s, %p,"
194 " %d) = %s\n", optname_str, pmreq, len, errstr);
195 #endif
196 }
197
198 int
199 main(void)
200 {
201 test_packet_mreq(ARG_STR(PACKET_ADD_MEMBERSHIP));
202 test_packet_mreq(ARG_STR(PACKET_DROP_MEMBERSHIP));
203
204 puts("+++ exited with 0 +++");
205 return 0;
206 }