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