1 /*
2  * Copyright (c) 2015 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 #include <time.h>
32 #include <sys/time.h>
33 #include <signal.h>
34 
35 #define SERVER_PORT  4242
36 #define CLIENT_PORT  0
37 #define MAX_TIMEOUT  5		/* in seconds */
38 
39 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
40 
41 #define ENTRY(e, expect_result) { sizeof(e), e, expect_result }
42 #define ENTRY_OK(e) ENTRY(e, true)
43 #define ENTRY_FAIL(e) ENTRY(e, false)
44 
45 static const unsigned char A[] = { 'A' };
46 static const unsigned char null_byte[] = { 0x00 };
47 static const unsigned char foobar[] = { 'f','o','o','b','a','r' };
48 static const unsigned char small_binary[] = { 0x20, 0xff, 0x00, 0x56 };
49 
50 static bool do_exit;
51 
52 /* Generated 2 paragraphs, 221 words, 1500 bytes of Lorem Ipsum */
53 static const unsigned char lorem_ipsum[] = \
54 	"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a lacinia ligula. Duis maximus ac turpis in sollicitudin. Nam luctus porta finibus. Duis id suscipit turpis. Ut ac venenatis urna. Phasellus nec elementum lectus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque id ultrices lacus. Aenean sapien orci, eleifend eu imperdiet vitae, fringilla sed felis. Sed sit amet consequat nibh, nec rhoncus ipsum. Praesent in tellus in ligula dapibus feugiat. Aliquam at lectus pulvinar, viverra sem, dignissim turpis. Pellentesque quis sagittis leo."
55 	"\n"
56 	"Ut eget neque quis nisi volutpat consectetur. Curabitur faucibus metus non arcu pharetra, et aliquam mi molestie. Fusce commodo purus a arcu porta blandit. Integer blandit posuere urna vitae feugiat. Mauris mollis tempus nulla. Aliquam quis lacinia justo, at pellentesque purus. Integer commodo, mi et egestas scelerisque, arcu orci convallis turpis, et blandit dui ante ut turpis. In metus ipsum, imperdiet ut dignissim ac, scelerisque quis purus. Mauris mattis mattis fermentum. Suspendisse a suscipit mi, in interdum massa. Duis magna mi, lacinia bibendum faucibus in, consequat in nisl. Praesent nibh mi, ullamcorper vel fringilla quis, scelerisque eu magna. Vestibulum ipsum purus, eleifend ac mi at, volutpat fermentum sapien. Etiam maximus tortor elementum egestas varius. Aenean sagittis lectus sapien, sed commodo dui consectetur id. Praesent imperdiet, risus at feugiat sodales, elit ex aliquet dui, quis porttitor.\n";
57 
58 #define MAX_BUF_SIZE sizeof(lorem_ipsum)
59 
60 /* 256 bytes of binary data */
61 static const unsigned char array_256[] = {
62 	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
63 	0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
64 	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
65 	0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
66 	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
67 	0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
68 	0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
69 	0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
70 	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
71 	0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
72 	0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
73 	0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
74 	0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
75 	0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
76 	0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
77 	0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
78 	0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
79 	0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
80 	0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
81 	0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
82 	0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
83 	0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
84 	0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
85 	0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
86 	0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
87 	0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
88 	0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
89 	0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
90 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
91 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
92 	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
93 	0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00
94 };
95 
96 /* 1280 bytes of binary data */
97 static const unsigned char array_1280[] = {
98 	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
99 	0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
100 	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
101 	0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
102 	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
103 	0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
104 	0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
105 	0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
106 	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
107 	0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
108 	0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
109 	0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
110 	0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
111 	0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
112 	0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
113 	0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
114 	0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
115 	0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
116 	0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
117 	0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
118 	0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
119 	0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
120 	0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
121 	0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
122 	0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
123 	0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
124 	0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
125 	0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
126 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
127 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
128 	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
129 	0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00,
130 	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
131 	0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
132 	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
133 	0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
134 	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
135 	0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
136 	0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
137 	0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
138 	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
139 	0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
140 	0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
141 	0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
142 	0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
143 	0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
144 	0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
145 	0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
146 	0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
147 	0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
148 	0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
149 	0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
150 	0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
151 	0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
152 	0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
153 	0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
154 	0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
155 	0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
156 	0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
157 	0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
158 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
159 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
160 	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
161 	0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00,
162 	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
163 	0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
164 	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
165 	0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
166 	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
167 	0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
168 	0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
169 	0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
170 	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
171 	0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
172 	0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
173 	0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
174 	0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
175 	0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
176 	0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
177 	0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
178 	0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
179 	0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
180 	0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
181 	0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
182 	0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
183 	0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
184 	0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
185 	0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
186 	0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
187 	0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
188 	0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
189 	0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
190 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
191 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
192 	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
193 	0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00,
194 	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
195 	0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
196 	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
197 	0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
198 	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
199 	0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
200 	0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
201 	0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
202 	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
203 	0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
204 	0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
205 	0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
206 	0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
207 	0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
208 	0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
209 	0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
210 	0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
211 	0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
212 	0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
213 	0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
214 	0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
215 	0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
216 	0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
217 	0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
218 	0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
219 	0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
220 	0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
221 	0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
222 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
223 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
224 	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
225 	0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00,
226 	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
227 	0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
228 	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
229 	0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
230 	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
231 	0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
232 	0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
233 	0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
234 	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
235 	0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
236 	0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
237 	0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
238 	0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
239 	0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
240 	0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
241 	0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
242 	0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
243 	0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
244 	0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
245 	0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
246 	0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
247 	0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
248 	0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
249 	0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
250 	0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
251 	0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
252 	0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
253 	0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
254 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
255 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
256 	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
257 	0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00
258 };
259 
260 static struct {
261 	int len;
262 	const unsigned char *buf;
263 	bool expecting_reply;
264 } data[] = {
265 	ENTRY_OK(A),
266 	ENTRY_OK(foobar),
267 	ENTRY_OK(small_binary),
268 	ENTRY_OK("a bit longer data message"),
269 	ENTRY_OK(lorem_ipsum),
270 	ENTRY_OK(null_byte),
271 	ENTRY_OK(array_256),
272 
273 	{ 0, 0 }
274 };
275 
get_ifindex(const char * name)276 static int get_ifindex(const char *name)
277 {
278 	struct ifreq ifr;
279 	int sk, err;
280 
281 	if (!name)
282 		return -1;
283 
284 	sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
285 	if (sk < 0)
286 		return -1;
287 
288 	memset(&ifr, 0, sizeof(ifr));
289 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
290 
291 	err = ioctl(sk, SIOCGIFINDEX, &ifr);
292 
293 	close(sk);
294 
295 	if (err < 0)
296 		return -1;
297 
298 	return ifr.ifr_ifindex;
299 }
300 
find_address(int family,struct ifaddrs * if_address,const char * if_name,void * address)301 static int find_address(int family, struct ifaddrs *if_address,
302 			const char *if_name, void *address)
303 {
304 	struct ifaddrs *tmp;
305 	struct sockaddr_in6 *ll = NULL;
306 	int error = -ENOENT;
307 
308 	for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
309 		if (tmp->ifa_addr &&
310 		    !strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
311 		    tmp->ifa_addr->sa_family == family) {
312 
313 			switch (family) {
314 			case AF_INET: {
315 				struct sockaddr_in *in4 =
316 					(struct sockaddr_in *)tmp->ifa_addr;
317 				if (in4->sin_addr.s_addr == INADDR_ANY)
318 					continue;
319 				if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
320 						((in_addr_t)0xa9fe0000))
321 					continue;
322 				memcpy(address, &in4->sin_addr,
323 				       sizeof(struct in_addr));
324 				error = 0;
325 				goto out;
326 			}
327 			case AF_INET6: {
328 				struct sockaddr_in6 *in6 =
329 					(struct sockaddr_in6 *)tmp->ifa_addr;
330 				if (!memcmp(&in6->sin6_addr, &in6addr_any,
331 					    sizeof(struct in6_addr)))
332 					continue;
333 				if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr)) {
334 					ll = in6;
335 					continue;
336 				}
337 
338 				memcpy(address, &in6->sin6_addr,
339 				       sizeof(struct in6_addr));
340 				error = 0;
341 				goto out;
342 			}
343 			default:
344 				error = -EINVAL;
345 				goto out;
346 			}
347 		}
348 	}
349 
350 out:
351 	if (error < 0 && ll) {
352 		/* As a last resort use link local address */
353 		memcpy(address, &ll->sin6_addr, sizeof(struct in6_addr));
354 		error = 0;
355 	}
356 
357 	return error;
358 }
359 
get_address(const char * if_name,int family,void * address)360 static int get_address(const char *if_name, int family, void *address)
361 {
362 	struct ifaddrs *if_address;
363 	int err;
364 
365 	if (getifaddrs(&if_address) < 0) {
366 		err = -errno;
367 		fprintf(stderr, "Cannot get interface addresses for "
368 			"interface %s error %d/%s",
369 			if_name, err, strerror(-err));
370 		return err;
371 	}
372 
373 	err = find_address(family, if_address, if_name, address);
374 
375 	freeifaddrs(if_address);
376 
377 	return err;
378 }
379 
signal_handler(int sig)380 static void signal_handler(int sig)
381 {
382 	do_exit = true;
383 }
384 
385 extern int optind, opterr, optopt;
386 extern char *optarg;
387 
388 /* The application returns:
389  *    < 0 : connection or similar error
390  *      0 : no errors, all tests passed
391  *    > 0 : could not send all the data to server
392  */
main(int argc,char ** argv)393 int main(int argc, char**argv)
394 {
395 	int c, ret, fd, i = 0, timeout = -1, port = SERVER_PORT;
396 	bool flood = false, multicast = false;
397 	struct sockaddr_in6 addr6_send = { 0 }, addr6_recv = { 0 };
398 	struct sockaddr_in addr4_send = { 0 }, addr4_recv = { 0 };
399 	struct sockaddr *addr_send, *addr_recv;
400 	int family, addr_len;
401 	unsigned char buf[MAX_BUF_SIZE];
402 	const struct in6_addr any = IN6ADDR_ANY_INIT;
403 	const char *target = NULL, *interface = NULL;
404 	fd_set rfds;
405 	struct timeval tv = {};
406 	int ifindex = -1, optval = 1;
407 	void *address = NULL;
408 	bool forever = false, help = false, tcp = false, do_randomize = false;
409 	struct timeval start_time, end_time, diff_time;
410 	unsigned long long sum_time = 0ULL;
411 	unsigned long long count_time = 0ULL;
412 	unsigned long long pkt_counter = 0ULL;
413 
414 	opterr = 0;
415 
416 	while ((c = getopt(argc, argv, "Fi:p:ethr")) != -1) {
417 		switch (c) {
418 		case 'F':
419 			flood = true;
420 			break;
421 		case 'i':
422 			interface = optarg;
423 			break;
424 		case 'e':
425 			forever = true;
426 			break;
427 		case 't':
428 			tcp = true;
429 			break;
430 		case 'p':
431 			port = atoi(optarg);
432 			break;
433 		case 'r':
434 			gettimeofday(&start_time, NULL);
435 			srandom(start_time.tv_usec);
436 			do_randomize = true;
437 			break;
438 		case 'h':
439 			help = true;
440 			break;
441 		}
442 	}
443 
444 	if (optind < argc)
445 		target = argv[optind];
446 
447 	if (!target || help) {
448 		printf("usage: %s [-i iface] [-F] <IPv{6|4} address of the echo-server>\n",
449 		       argv[0]);
450 		printf("\n-i Use this network interface, needed if using "
451 		       "multicast server address.\n");
452 		printf("-e Do not quit, send packets forever\n");
453 		printf("-t Use TCP, default is to use UDP only\n");
454 		printf("-p Use this port, default port is %d\n", SERVER_PORT);
455 		printf("-r Send random packet lengths\n");
456 		printf("-F (flood) option will prevent the client from "
457 		       "waiting the data.\n"
458 		       "   The -F option will stress test the server.\n");
459 		exit(-EINVAL);
460 	}
461 
462 	signal(SIGINT, signal_handler);
463 	signal(SIGTERM, signal_handler);
464 
465 	if (inet_pton(AF_INET6, target, &addr6_send.sin6_addr) != 1) {
466 		if (inet_pton(AF_INET, target, &addr4_send.sin_addr) != 1) {
467 			printf("Invalid address family\n");
468 			exit(-EINVAL);
469 		} else {
470 			if (IN_MULTICAST(addr4_recv.sin_addr.s_addr))
471 				multicast = true;
472 
473 			addr_send = (struct sockaddr *)&addr4_send;
474 			addr_recv = (struct sockaddr *)&addr4_recv;
475 			addr4_send.sin_port = htons(port);
476 			addr4_recv.sin_family = AF_INET;
477 			addr4_recv.sin_addr.s_addr = INADDR_ANY;
478 			if (!tcp)
479 				addr4_recv.sin_port = htons(CLIENT_PORT);
480 			family = AF_INET;
481 			addr_len = sizeof(addr4_send);
482 			address = &addr4_recv.sin_addr;
483 		}
484 	} else {
485 		if (IN6_IS_ADDR_MULTICAST(&addr6_send.sin6_addr))
486 			multicast = true;
487 
488 		addr_send = (struct sockaddr *)&addr6_send;
489 		addr_recv = (struct sockaddr *)&addr6_recv;
490 		addr6_send.sin6_port = htons(port);
491 		addr6_recv.sin6_family = AF_INET6;
492 		addr6_recv.sin6_addr = any;
493 		if (!tcp)
494 			addr6_recv.sin6_port = htons(CLIENT_PORT);
495 		family = AF_INET6;
496 		addr_len = sizeof(addr6_send);
497 		address = &addr6_recv.sin6_addr;
498 	}
499 
500 	addr_send->sa_family = family;
501 	addr_recv->sa_family = family;
502 
503 	fd = socket(family, tcp ? SOCK_STREAM : SOCK_DGRAM,
504 		    tcp ? IPPROTO_TCP : IPPROTO_UDP);
505 	if (fd < 0) {
506 		perror("socket");
507 		exit(-errno);
508 	}
509 
510 	if (interface) {
511 		struct ifreq ifr;
512 		char addr_buf[INET6_ADDRSTRLEN];
513 
514 		memset(&ifr, 0, sizeof(ifr));
515 		snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", interface);
516 
517 		if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
518 			       (void *)&ifr, sizeof(ifr)) < 0) {
519 			perror("SO_BINDTODEVICE");
520 			exit(-errno);
521 		}
522 
523 		ifindex = get_ifindex(interface);
524 		if (ifindex < 0) {
525 			printf("Invalid interface %s\n", interface);
526 			exit(-EINVAL);
527 		}
528 
529 		ret = get_address(interface, family, address);
530 		if (ret < 0) {
531 			printf("Cannot find suitable source address "
532 			       "for interface %s [%d/%s]\n",
533 			       interface, ret, strerror(-ret));
534 		}
535 
536 		printf("Binding to %s\n", inet_ntop(family, address,
537 					    addr_buf, sizeof(addr_buf)));
538 	}
539 
540 	if (multicast) {
541 		if (!interface) {
542 			printf("Need to use -i option for multicast "
543 			       "addresses.\n");
544 			exit(-EINVAL);
545 		}
546 	}
547 
548 	ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT,
549 			 &optval, sizeof(optval));
550 	if (ret < 0) {
551 		perror("setsockopt");
552 	}
553 
554 	ret = bind(fd, addr_recv, addr_len);
555 	if (ret < 0) {
556 		perror("bind");
557 		exit(-errno);
558 	}
559 
560 	if (tcp) {
561 		ret = connect(fd, addr_send, addr_len);
562 		if (ret < 0) {
563 			perror("connect");
564 			exit(-errno);
565 		}
566 	}
567 
568 again:
569 	do {
570 		int sent;
571 
572 		while (data[i].buf) {
573 			const unsigned char *buf_ptr;
574 			int pos = 0;
575 			int len;
576 
577 			sent = 0;
578 
579 			gettimeofday(&start_time, NULL);
580 
581 			if (do_randomize) {
582 				buf_ptr = lorem_ipsum;
583 
584 				/* For UDP, we send max 1280 bytes which is
585 				 * the IPv6 MTU size
586 				 */
587 				if (tcp)
588 					len = random() % sizeof(lorem_ipsum);
589 				else
590 					len = random() %
591 						MIN(1280, sizeof(lorem_ipsum));
592 
593 				if (len == 0)
594 					len = 1;
595 			} else {
596 				if (tcp)
597 					len = data[i].len;
598 				else
599 					len = MIN(1280, data[i].len);
600 
601 				buf_ptr = data[i].buf;
602 			}
603 
604 			if (tcp) {
605 				pos = 0;
606 
607 				do {
608 					ret = write(fd, &buf_ptr[pos],
609 						    len - pos);
610 					if (ret <= 0)
611 						break;
612 
613 					sent += len;
614 					pos += ret;
615 				} while (sent < len);
616 			} else
617 				ret = sendto(fd, buf_ptr, len, 0, addr_send,
618 					     addr_len);
619 			if (ret < 0) {
620 				perror("send");
621 				goto out;
622 			}
623 
624 			if (flood) {
625 				i++;
626 				continue;
627 			}
628 
629 			FD_ZERO(&rfds);
630 			FD_SET(fd, &rfds);
631 
632 			if (do_randomize || data[i].expecting_reply) {
633 				tv.tv_sec = MAX_TIMEOUT;
634 				tv.tv_usec = 0;
635 			} else {
636 				tv.tv_sec = 0;
637 				tv.tv_usec = 0;
638 			}
639 
640 			ret = select(fd + 1, &rfds, NULL, NULL, &tv);
641 			if (ret < 0) {
642 				if (!do_exit) {
643 					perror("select");
644 				}
645 
646 				goto out;
647 			} else if (ret == 0) {
648 				if (do_randomize) {
649 					timeout++;
650 					continue;
651 				}
652 
653 				if (data[i].expecting_reply) {
654 					fprintf(stderr,
655 						"Timeout while waiting "
656 						"idx %d len %d\n",
657 						i, data[i].len);
658 					timeout = i;
659 				}
660 				i++;
661 				continue;
662 			} else if (!FD_ISSET(fd, &rfds)) {
663 				fprintf(stderr, "Invalid fd\n");
664 				ret = i;
665 				goto out;
666 			}
667 
668 			if (tcp) {
669 				int received = 0;
670 
671 				pos = 0;
672 
673 				do {
674 					ret = read(fd, buf + pos,
675 						   sizeof(buf) - pos);
676 					if (ret <= 0)
677 						break;
678 
679 					received += ret;
680 					pos += ret;
681 					ret = received;
682 				} while (received < sent);
683 			} else
684 				ret = recv(fd, buf, sizeof(buf), 0);
685 			if (ret <= 0) {
686 				if (ret)
687 					perror("recv");
688 				else
689 					printf("Connection closed by peer.\n");
690 
691 				ret = -EINVAL;
692 				goto out;
693 			}
694 
695 			if (len != ret ||
696 			    memcmp(buf_ptr, buf, ret) != 0) {
697 				fprintf(stderr,
698 					"Check failed idx %d len %d\n",
699 					i, ret);
700 				ret = i;
701 				goto out;
702 			} else {
703 				gettimeofday(&end_time, NULL);
704 
705 				timersub(&end_time, &start_time, &diff_time);
706 
707 				sum_time +=
708 					(unsigned long long)diff_time.tv_sec *
709 					1000000ULL +
710 					(unsigned long long)diff_time.tv_usec;
711 				count_time++;
712 				pkt_counter++;
713 
714 				printf(".");
715 
716 				/* Flush stdout only every 10 packets */
717 				if (forever) {
718 					if (!(pkt_counter % 10))
719 						fflush(stdout);
720 				} else
721 					fflush(stdout);
722 			}
723 
724 			i++;
725 		}
726 
727 		if (flood)
728 			i = 0;
729 
730 		if (do_exit)
731 			break;
732 
733 	} while (flood);
734 
735 	if (forever && !do_exit) {
736 		i = 0;
737 		goto again;
738 	}
739 
740 	ret = timeout + 1;
741 
742 	printf("\n");
743 
744 out:
745 	if (count_time > 0ULL) {
746 		unsigned long long time_spent;
747 		unsigned long long ms;
748 
749 		if (do_exit) {
750 			printf("\n");
751 		}
752 
753 		time_spent = sum_time / count_time;
754 		ms = time_spent / 1000ULL;
755 
756 		if (ms == 0) {
757 			printf("Average round trip %llu us\n", time_spent);
758 		} else {
759 			printf("Average round trip %llu ms\n", ms);
760 		}
761 
762 		printf("Sent %llu packets\n", pkt_counter);
763 	} else {
764 		printf("No packets sent!\n");
765 	}
766 
767 	close(fd);
768 
769 	exit(ret);
770 }
771