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