9
9
#include <errno.h>
10
10
#include <fcntl.h>
11
11
#include <limits.h>
12
+ #include <linux/icmpv6.h>
12
13
#include <linux/in6.h>
13
14
#include <stdbool.h>
14
15
#include <stdio.h>
29
30
#ifndef IPV6_FLOWLABEL_MGR
30
31
#define IPV6_FLOWLABEL_MGR 32
31
32
#endif
33
+ #ifndef IPV6_FLOWINFO_SEND
34
+ #define IPV6_FLOWINFO_SEND 33
35
+ #endif
32
36
33
37
#define FLOWLABEL_WILDCARD ((uint32_t) -1)
34
38
35
39
static const char cfg_data [] = "a" ;
36
40
static uint32_t cfg_label = 1 ;
41
+ static bool use_ping ;
42
+ static bool use_flowinfo_send ;
43
+
44
+ static struct icmp6hdr icmp6 = {
45
+ .icmp6_type = ICMPV6_ECHO_REQUEST
46
+ };
47
+
48
+ static struct sockaddr_in6 addr = {
49
+ .sin6_family = AF_INET6 ,
50
+ .sin6_addr = IN6ADDR_LOOPBACK_INIT ,
51
+ };
37
52
38
53
static void do_send (int fd , bool with_flowlabel , uint32_t flowlabel )
39
54
{
40
55
char control [CMSG_SPACE (sizeof (flowlabel ))] = {0 };
41
56
struct msghdr msg = {0 };
42
- struct iovec iov = {0 };
57
+ struct iovec iov = {
58
+ .iov_base = (char * )cfg_data ,
59
+ .iov_len = sizeof (cfg_data )
60
+ };
43
61
int ret ;
44
62
45
- iov .iov_base = (char * )cfg_data ;
46
- iov .iov_len = sizeof (cfg_data );
63
+ if (use_ping ) {
64
+ iov .iov_base = & icmp6 ;
65
+ iov .iov_len = sizeof (icmp6 );
66
+ }
47
67
48
68
msg .msg_iov = & iov ;
49
69
msg .msg_iovlen = 1 ;
50
70
51
- if (with_flowlabel ) {
71
+ if (use_flowinfo_send ) {
72
+ msg .msg_name = & addr ;
73
+ msg .msg_namelen = sizeof (addr );
74
+ } else if (with_flowlabel ) {
52
75
struct cmsghdr * cm ;
53
76
54
77
cm = (void * )control ;
@@ -94,13 +117,16 @@ static void do_recv(int fd, bool with_flowlabel, uint32_t expect)
94
117
ret = recvmsg (fd , & msg , 0 );
95
118
if (ret == -1 )
96
119
error (1 , errno , "recv" );
120
+ if (use_ping )
121
+ goto parse_cmsg ;
97
122
if (msg .msg_flags & (MSG_TRUNC | MSG_CTRUNC ))
98
123
error (1 , 0 , "recv: truncated" );
99
124
if (ret != sizeof (cfg_data ))
100
125
error (1 , 0 , "recv: length mismatch" );
101
126
if (memcmp (data , cfg_data , sizeof (data )))
102
127
error (1 , 0 , "recv: data mismatch" );
103
128
129
+ parse_cmsg :
104
130
cm = CMSG_FIRSTHDR (& msg );
105
131
if (with_flowlabel ) {
106
132
if (!cm )
@@ -114,9 +140,11 @@ static void do_recv(int fd, bool with_flowlabel, uint32_t expect)
114
140
flowlabel = ntohl (* (uint32_t * )CMSG_DATA (cm ));
115
141
fprintf (stderr , "recv with label %u\n" , flowlabel );
116
142
117
- if (expect != FLOWLABEL_WILDCARD && expect != flowlabel )
143
+ if (expect != FLOWLABEL_WILDCARD && expect != flowlabel ) {
118
144
fprintf (stderr , "recv: incorrect flowlabel %u != %u\n" ,
119
145
flowlabel , expect );
146
+ error (1 , 0 , "recv: flowlabel is wrong" );
147
+ }
120
148
121
149
} else {
122
150
fprintf (stderr , "recv without label\n" );
@@ -165,11 +193,17 @@ static void parse_opts(int argc, char **argv)
165
193
{
166
194
int c ;
167
195
168
- while ((c = getopt (argc , argv , "l:" )) != -1 ) {
196
+ while ((c = getopt (argc , argv , "l:ps " )) != -1 ) {
169
197
switch (c ) {
170
198
case 'l' :
171
199
cfg_label = strtoul (optarg , NULL , 0 );
172
200
break ;
201
+ case 'p' :
202
+ use_ping = true;
203
+ break ;
204
+ case 's' :
205
+ use_flowinfo_send = true;
206
+ break ;
173
207
default :
174
208
error (1 , 0 , "%s: parse error" , argv [0 ]);
175
209
}
@@ -178,27 +212,30 @@ static void parse_opts(int argc, char **argv)
178
212
179
213
int main (int argc , char * * argv )
180
214
{
181
- struct sockaddr_in6 addr = {
182
- .sin6_family = AF_INET6 ,
183
- .sin6_port = htons (8000 ),
184
- .sin6_addr = IN6ADDR_LOOPBACK_INIT ,
185
- };
186
215
const int one = 1 ;
187
216
int fdt , fdr ;
217
+ int prot = 0 ;
218
+
219
+ addr .sin6_port = htons (8000 );
188
220
189
221
parse_opts (argc , argv );
190
222
191
- fdt = socket (PF_INET6 , SOCK_DGRAM , 0 );
223
+ if (use_ping ) {
224
+ fprintf (stderr , "attempting to use ping sockets\n" );
225
+ prot = IPPROTO_ICMPV6 ;
226
+ }
227
+
228
+ fdt = socket (PF_INET6 , SOCK_DGRAM , prot );
192
229
if (fdt == -1 )
193
230
error (1 , errno , "socket t" );
194
231
195
- fdr = socket (PF_INET6 , SOCK_DGRAM , 0 );
232
+ fdr = use_ping ? fdt : socket (PF_INET6 , SOCK_DGRAM , 0 );
196
233
if (fdr == -1 )
197
234
error (1 , errno , "socket r" );
198
235
199
236
if (connect (fdt , (void * )& addr , sizeof (addr )))
200
237
error (1 , errno , "connect" );
201
- if (bind (fdr , (void * )& addr , sizeof (addr )))
238
+ if (! use_ping && bind (fdr , (void * )& addr , sizeof (addr )))
202
239
error (1 , errno , "bind" );
203
240
204
241
flowlabel_get (fdt , cfg_label , IPV6_FL_S_EXCL , IPV6_FL_F_CREATE );
@@ -216,13 +253,21 @@ int main(int argc, char **argv)
216
253
do_recv (fdr , false, 0 );
217
254
}
218
255
256
+ if (use_flowinfo_send ) {
257
+ fprintf (stderr , "using IPV6_FLOWINFO_SEND to send label\n" );
258
+ addr .sin6_flowinfo = htonl (cfg_label );
259
+ if (setsockopt (fdt , SOL_IPV6 , IPV6_FLOWINFO_SEND , & one ,
260
+ sizeof (one )) == -1 )
261
+ error (1 , errno , "setsockopt flowinfo_send" );
262
+ }
263
+
219
264
fprintf (stderr , "send label\n" );
220
265
do_send (fdt , true, cfg_label );
221
266
do_recv (fdr , true, cfg_label );
222
267
223
268
if (close (fdr ))
224
269
error (1 , errno , "close r" );
225
- if (close (fdt ))
270
+ if (! use_ping && close (fdt ))
226
271
error (1 , errno , "close t" );
227
272
228
273
return 0 ;
0 commit comments