1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <poll.h>
21 #include <errno.h>
22 #include <arpa/inet.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdbool.h>
26 #include <net/if.h>
27 #include <linux/sockios.h>
28 #include <ifaddrs.h>
29 #include <sys/ioctl.h>
30 #include <unistd.h>
31
32 #define SERVER_PORT 42042
33 #define CLIENT_PORT 0
34 #define MAX_BUF_SIZE 1280 /* min IPv6 MTU, the actual data is smaller */
35 #define MAX_TIMEOUT 5 /* in seconds */
36
37 #define ENTRY(e, expect_result) { sizeof(e), e, expect_result }
38 #define ENTRY_OK(e) ENTRY(e, true)
39 #define ENTRY_FAIL(e) ENTRY(e, false)
40
41 #define TYPE_SEQ_NUM 42
42
43 struct header {
44 unsigned char type;
45 unsigned char len;
46 unsigned char value[0];
47 } __packed;
48
49 /* Next entry is 1232 bytes long which is the maximum length for IPv6 user
50 * payload the Zephyr IP stack supports (1280 - IPv6 (40) - UDP (8))
51 */
52 static unsigned char lorem_ipsum[1232] = \
53 "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam congue non neque vel tempor. In id porta nibh, ut cursus tortor. Morbi eleifend tristique vehicula. Nunc vitae risus mauris. Praesent vel imperdiet dolor, et ultricies nibh. Aliquam erat volutpat. Maecenas pellentesque dolor vitae dictum tincidunt. Fusce vel nibh nec leo tristique auctor eu a massa. Nam et tellus ac tortor sollicitudin semper vitae nec tortor. Aliquam nec lacus velit. Maecenas ornare ullamcorper justo non auctor. Donec aliquam feugiat turpis, quis elementum sem rutrum ut. Sed eu ullamcorper libero, ut suscipit magna."
54 "\n"
55 "Donec vehicula magna ut varius aliquam. Ut vitae commodo nulla, quis ornare dolor. Nulla tortor sem, venenatis eu iaculis id, commodo ut massa. Sed est lorem, euismod vitae enim sed, hendrerit gravida felis. Donec eros lacus, auctor ut ultricies eget, lobortis quis nisl. Aliquam sit amet blandit eros. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque egestas nisl leo, sed consectetur leo ornare eu. Suspendisse vitae urna vel purus maximus finibus. Proin sed sollicitudin turpis. Mauris interdum neque eu tellus pellentesque, id fringilla nisi fermentum. Suspendisse gravida pharetra sodales orci aliquam\n";
56
57 /* 1232 bytes of binary data */
58 static unsigned char array_1232[1232] = {
59 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
60 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
61 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
62 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
63 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
64 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
65 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
66 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
67 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
68 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
69 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
70 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
71 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
72 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
73 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
74 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
75 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
76 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
77 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
78 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
79 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
80 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
81 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
82 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
83 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
84 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
85 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
86 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
87 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
88 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
89 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
90 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00,
91 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
92 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
93 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
94 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
95 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
96 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
97 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
98 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
99 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
100 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
101 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
102 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
103 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
104 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
105 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
106 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
107 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
108 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
109 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
110 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
111 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
112 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
113 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
114 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
115 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
116 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
117 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
118 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
119 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
120 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
121 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
122 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00,
123 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
124 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
125 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
126 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
127 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
128 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
129 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
130 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
131 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
132 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
133 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
134 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
135 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
136 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
137 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
138 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
139 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
140 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
141 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
142 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
143 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
144 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
145 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
146 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
147 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
148 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
149 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
150 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
151 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
152 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
153 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
154 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00,
155 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
156 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
157 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
158 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
159 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
160 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
161 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
162 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
163 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
164 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
165 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
166 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
167 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
168 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
169 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
170 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
171 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
172 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
173 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
174 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
175 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
176 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
177 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
178 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
179 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
180 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
181 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
182 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
183 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
184 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
185 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
186 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00,
187 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
188 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
189 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
190 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
191 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
192 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
193 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
194 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
195 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
196 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
197 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
198 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
199 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
200 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
201 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
202 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
203 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
204 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
205 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
206 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
207 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
208 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
209 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
210 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
211 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
212 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
213 };
214
215 static struct {
216 int len;
217 const unsigned char *buf;
218 bool expecting_reply;
219 } data[] = {
220 ENTRY_OK(lorem_ipsum),
221 ENTRY_OK(array_1232),
222
223 { 0, 0 }
224 };
225
get_ifindex(const char * name)226 static int get_ifindex(const char *name)
227 {
228 struct ifreq ifr;
229 int sk, err;
230
231 if (!name)
232 return -1;
233
234 sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
235 if (sk < 0)
236 return -1;
237
238 memset(&ifr, 0, sizeof(ifr));
239 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
240
241 err = ioctl(sk, SIOCGIFINDEX, &ifr);
242
243 close(sk);
244
245 if (err < 0)
246 return -1;
247
248 return ifr.ifr_ifindex;
249 }
250
find_address(int family,struct ifaddrs * if_address,const char * if_name,void * address)251 static int find_address(int family, struct ifaddrs *if_address,
252 const char *if_name, void *address)
253 {
254 struct ifaddrs *tmp;
255 struct sockaddr_in6 *ll = NULL;
256 int error = -ENOENT;
257
258 for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
259 if (tmp->ifa_addr &&
260 !strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
261 tmp->ifa_addr->sa_family == family) {
262
263 switch (family) {
264 case AF_INET: {
265 struct sockaddr_in *in4 =
266 (struct sockaddr_in *)tmp->ifa_addr;
267 if (in4->sin_addr.s_addr == INADDR_ANY)
268 continue;
269 if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
270 ((in_addr_t)0xa9fe0000))
271 continue;
272 memcpy(address, &in4->sin_addr,
273 sizeof(struct in_addr));
274 error = 0;
275 goto out;
276 }
277 case AF_INET6: {
278 struct sockaddr_in6 *in6 =
279 (struct sockaddr_in6 *)tmp->ifa_addr;
280 if (!memcmp(&in6->sin6_addr, &in6addr_any,
281 sizeof(struct in6_addr)))
282 continue;
283 if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr)) {
284 ll = in6;
285 continue;
286 }
287
288 memcpy(address, &in6->sin6_addr,
289 sizeof(struct in6_addr));
290 error = 0;
291 goto out;
292 }
293 default:
294 error = -EINVAL;
295 goto out;
296 }
297 }
298 }
299
300 out:
301 if (error < 0 && ll) {
302 /* As a last resort use link local address */
303 memcpy(address, &ll->sin6_addr, sizeof(struct in6_addr));
304 error = 0;
305 }
306
307 return error;
308 }
309
get_address(const char * if_name,int family,void * address)310 static int get_address(const char *if_name, int family, void *address)
311 {
312 struct ifaddrs *if_address;
313 int err;
314
315 if (getifaddrs(&if_address) < 0) {
316 err = -errno;
317 fprintf(stderr, "Cannot get interface addresses for "
318 "interface %s error %d/%s",
319 if_name, err, strerror(-err));
320 return err;
321 }
322
323 err = find_address(family, if_address, if_name, address);
324
325 freeifaddrs(if_address);
326
327 return err;
328 }
329
330 extern int optind, opterr, optopt;
331 extern char *optarg;
332
333 #define min(a,b) (((a) < (b)) ? (a) : (b))
334
335 /* The application returns:
336 * < 0 : connection or similar error
337 * 0 : no errors, all tests passed
338 * > 0 : could not send all the data to server
339 */
main(int argc,char ** argv)340 int main(int argc, char**argv)
341 {
342 int c, ret, fd, i = 0, timeout = -1, port = SERVER_PORT;
343 bool flood = false, multicast = false;
344 struct sockaddr_in6 addr6_send = { 0 }, addr6_recv = { 0 };
345 struct sockaddr_in addr4_send = { 0 }, addr4_recv = { 0 };
346 struct sockaddr *addr_send, *addr_recv;
347 int family, addr_len;
348 unsigned char buf[MAX_BUF_SIZE];
349 const struct in6_addr any = IN6ADDR_ANY_INIT;
350 const char *target = NULL, *interface = NULL;
351 fd_set rfds;
352 struct timeval tv = {};
353 int ifindex = -1, optval = 1;
354 void *address = NULL;
355 bool forever = true, help = false, do_reverse = false;
356 int data_size = 0;
357 unsigned pkt_seq = 0;
358
359 opterr = 0;
360
361 while ((c = getopt(argc, argv, "Fi:p:hs:")) != -1) {
362 switch (c) {
363 case 'F':
364 flood = true;
365 break;
366 case 'i':
367 interface = optarg;
368 break;
369 case 'p':
370 port = atoi(optarg);
371 break;
372 case 's':
373 data_size = atoi(optarg);
374 break;
375 case 'h':
376 help = true;
377 break;
378 }
379 }
380
381 if (optind < argc)
382 target = argv[optind];
383
384 if (!target || help) {
385 printf("usage: %s [-i iface] [-F] <IPv{6|4} address of the "
386 "throughput-server>\n", argv[0]);
387 printf("\n-i Use this network interface\n");
388 printf("-p Use this port, default port is %d\n", SERVER_PORT);
389 printf("-F (flood) option will prevent the client from "
390 "waiting the data.\n"
391 " The -F option will stress test the server.\n");
392 printf("-s Max data size to send.\n");
393 exit(-EINVAL);
394 }
395
396 if (inet_pton(AF_INET6, target, &addr6_send.sin6_addr) != 1) {
397 if (inet_pton(AF_INET, target, &addr4_send.sin_addr) != 1) {
398 printf("Invalid address family\n");
399 exit(-EINVAL);
400 } else {
401 if (IN_MULTICAST(addr4_recv.sin_addr.s_addr))
402 multicast = true;
403
404 addr_send = (struct sockaddr *)&addr4_send;
405 addr_recv = (struct sockaddr *)&addr4_recv;
406 addr4_send.sin_port = htons(port);
407 addr4_recv.sin_family = AF_INET;
408 addr4_recv.sin_addr.s_addr = INADDR_ANY;
409 addr4_recv.sin_port = htons(CLIENT_PORT);
410 family = AF_INET;
411 addr_len = sizeof(addr4_send);
412 address = &addr4_recv.sin_addr;
413 }
414 } else {
415 if (IN6_IS_ADDR_MULTICAST(&addr6_send.sin6_addr))
416 multicast = true;
417
418 addr_send = (struct sockaddr *)&addr6_send;
419 addr_recv = (struct sockaddr *)&addr6_recv;
420 addr6_send.sin6_port = htons(port);
421 addr6_recv.sin6_family = AF_INET6;
422 addr6_recv.sin6_addr = any;
423 addr6_recv.sin6_port = htons(CLIENT_PORT);
424 family = AF_INET6;
425 addr_len = sizeof(addr6_send);
426 address = &addr6_recv.sin6_addr;
427 }
428
429 addr_send->sa_family = family;
430 addr_recv->sa_family = family;
431
432 fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
433 if (fd < 0) {
434 perror("socket");
435 exit(-errno);
436 }
437
438 if (interface) {
439 struct ifreq ifr;
440 char addr_buf[INET6_ADDRSTRLEN];
441
442 memset(&ifr, 0, sizeof(ifr));
443 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", interface);
444
445 if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
446 (void *)&ifr, sizeof(ifr)) < 0) {
447 perror("SO_BINDTODEVICE");
448 exit(-errno);
449 }
450
451 ifindex = get_ifindex(interface);
452 if (ifindex < 0) {
453 printf("Invalid interface %s\n", interface);
454 exit(-EINVAL);
455 }
456
457 ret = get_address(interface, family, address);
458 if (ret < 0) {
459 printf("Cannot find suitable source address "
460 "for interface %s [%d/%s]\n",
461 interface, ret, strerror(-ret));
462 }
463
464 printf("Binding to %s\n", inet_ntop(family, address,
465 addr_buf, sizeof(addr_buf)));
466 }
467
468 if (multicast) {
469 if (!interface) {
470 printf("Need to use -i option for multicast "
471 "addresses.\n");
472 exit(-EINVAL);
473 }
474 }
475
476 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT,
477 &optval, sizeof(optval));
478 if (ret < 0) {
479 perror("setsockopt");
480 }
481
482 ret = bind(fd, addr_recv, addr_len);
483 if (ret < 0) {
484 perror("bind");
485 exit(-errno);
486 }
487
488 again:
489 do {
490 int sent;
491
492 while (data[i].buf) {
493 struct header *hdr;
494 unsigned seq;
495 int pos = 0;
496 int len;
497
498 if (data_size) {
499 len = min(data[i].len, data_size);
500 } else {
501 len = data[i].len;
502 }
503
504 sent = 0;
505
506 seq = htonl(pkt_seq);
507
508 hdr = (struct header *)data[i].buf;
509 hdr->type = TYPE_SEQ_NUM;
510 hdr->len = sizeof(seq);
511 memcpy(hdr->value, &seq, sizeof(seq));
512
513 ret = sendto(fd, data[i].buf, len, 0,
514 addr_send, addr_len);
515 if (ret < 0) {
516 perror("send");
517 goto out;
518 }
519
520 pkt_seq++;
521
522 /* Print some feedback to the user every X packets */
523 if (!(pkt_seq % 1000)) {
524 printf(".");
525 fflush(stdout);
526 }
527
528 FD_ZERO(&rfds);
529 FD_SET(fd, &rfds);
530
531 if (!flood)
532 tv.tv_sec = MAX_TIMEOUT;
533 else
534 tv.tv_sec = 0;
535
536 tv.tv_usec = 0;
537
538 ret = select(fd + 1, &rfds, NULL, NULL, &tv);
539 if (ret < 0) {
540 perror("select");
541 goto out;
542 } else if (ret == 0) {
543 if (!flood && data[i].expecting_reply) {
544 fprintf(stderr,
545 "Timeout while waiting "
546 "idx %d len %d\n",
547 i, data[i].len);
548 timeout = i;
549 }
550 i++;
551 continue;
552 } else if (!FD_ISSET(fd, &rfds)) {
553 fprintf(stderr, "Invalid fd\n");
554 ret = i;
555 goto out;
556 }
557
558 ret = recv(fd, buf, sizeof(buf), 0);
559 if (ret <= 0) {
560 perror("recv");
561 ret = -EINVAL;
562 goto out;
563 }
564
565 if (!flood && (data[i].len != ret ||
566 memcmp(data[i].buf, buf, ret) != 0)) {
567 fprintf(stderr,
568 "Check failed idx %d len %d\n",
569 i, ret);
570 ret = i;
571 goto out;
572 }
573
574 i++;
575 }
576
577 if (flood)
578 i = 0;
579
580 } while (flood);
581
582 if (forever) {
583 i = 0;
584 goto again;
585 }
586
587 ret = timeout + 1;
588
589 printf("\n");
590
591 out:
592 close(fd);
593
594 exit(ret);
595 }
596