1 /* 12.21:TCP MUST be able to receive MSS option in SYN,ACK segment and calculate the effective send segment size appropriately. */
2
3 /* Procedure
4 1.Connect
5 2.Client_socket's connect_MSS should equal server_socket's MSS.(client_socket's MSS = 1460, server_socket's MSS = 88)
6 3. A packet should be intercepted by function my_tcp_packet_receive_12_21 which is sent from client socket to server socket.
7 4. Check: the packet should be a SYN packet, increment the syn_counter. Whether or not calling the defaulted packet receiving function.
8 5. Check if all of the packets we catched can connected to the my_packet we send*/
9
10 #include "tx_api.h"
11 #include "nx_api.h"
12 #include "nx_tcp.h"
13 #if defined(__PRODUCT_NETXDUO__)
14 #include "nx_ipv4.h"
15 #else
16 #include "nx_ip.h"
17 #endif
18 #include <time.h>
19 extern void test_control_return(UINT status);
20
21 #if !defined(NX_DISABLE_IPV4)
22
23 #define DEMO_STACK_SIZE 2048
24
25 /* Define the counters used in the demo application... */
26
27 static TX_THREAD ntest_0;
28 static TX_THREAD ntest_1;
29 static NX_PACKET_POOL pool_0;
30 static NX_IP ip_0;
31 static NX_IP ip_1;
32 static NX_TCP_SOCKET client_socket;
33 static NX_TCP_SOCKET server_socket;
34
35 /* Define the counters used in the demo applicaton... */
36
37 static ULONG error_counter;
38 static ULONG syn_ack_counter;
39 static ULONG data_counter;
40 static ULONG mss_option_12_21;
41 static ULONG packet_length_12_21;
42
43 static UCHAR callback_rcv_buffer[200];
44 static UINT callback_rcv_length;
45 static UCHAR rcv_buffer[200];
46 static UINT rcv_length;
47 static UCHAR data_12_21[200];
48
49 /* Define thread prototypes. */
50
51 static void ntest_0_entry(ULONG thread_input);
52 static void ntest_1_entry(ULONG thread_input);
53 static void ntest_1_connect_received(NX_TCP_SOCKET *server_socket, UINT port);
54 static void ntest_1_disconnect_received(NX_TCP_SOCKET *server_socket);
55 static void rand_12_21();
56 extern void test_control_return(UINT status);
57 extern void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
58 extern void _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
59 static void my_tcp_packet_receive_12_21(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
60 extern UINT (*advanced_packet_process_callback)(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
61 static UINT my_packet_process_12_21(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
62
63
64 /* Define what the initial system looks like. */
65
66 #ifdef CTEST
test_application_define(void * first_unused_memory)67 VOID test_application_define(void *first_unused_memory)
68 #else
69 void netx_12_21_application_define(void *first_unused_memory)
70 #endif
71 {
72 CHAR *pointer;
73 UINT status;
74
75 /* Setup the working pointer. */
76 pointer = (CHAR *) first_unused_memory;
77
78 error_counter = 0;
79 syn_ack_counter = 0;
80 data_counter = 0;
81 mss_option_12_21 = 0;
82 packet_length_12_21 = 200;
83 rcv_length = 0;
84 callback_rcv_length = 0;
85
86 /* Create the main thread. */
87 tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
88 pointer, DEMO_STACK_SIZE,
89 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
90
91 pointer = pointer + DEMO_STACK_SIZE;
92
93 /* Create the main thread. */
94 tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
95 pointer, DEMO_STACK_SIZE,
96 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
97
98 pointer = pointer + DEMO_STACK_SIZE;
99
100 /* Initialize the NetX system. */
101 nx_system_initialize();
102
103 /* Create a packet pool. */
104 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 512, pointer, 8192);
105 pointer = pointer + 8192;
106
107 if(status)
108 error_counter++;
109
110 /* Create an IP instance. */
111 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500,
112 pointer, 2048, 1);
113 pointer = pointer + 2048;
114
115 /* Create another IP instance. */
116 status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
117 pointer, 2048, 1);
118 pointer = pointer + 2048;
119
120 if(status)
121 error_counter++;
122
123 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
124 status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
125 pointer = pointer + 1024;
126
127 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
128 status += nx_arp_enable(&ip_1, (void *) pointer, 1024);
129 pointer = pointer + 1024;
130
131 /* Check ARP enable status. */
132 if(status)
133 error_counter++;
134
135 /* Enable TCP processing for both IP instances. */
136 status = nx_tcp_enable(&ip_0);
137 status += nx_tcp_enable(&ip_1);
138
139 /* Check TCP enable status. */
140 if(status)
141 error_counter++;
142 }
143
144 /* Define the test threads. */
145
ntest_0_entry(ULONG thread_input)146 static void ntest_0_entry(ULONG thread_input)
147 {
148 UINT status;
149 NX_PACKET *my_packet;
150
151
152
153 /* Print out test information banner. */
154 printf("NetX Test: TCP Spec 12.21 Test.......................................");
155
156 /* Create a socket. */
157 status = nx_tcp_socket_create(&ip_0, &client_socket, "Client Socket",
158 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 300,
159 NX_NULL, NX_NULL);
160
161
162 /* Check for error. */
163 if(status)
164 error_counter++;
165
166 /* Bind the socket. */
167 status = nx_tcp_client_socket_bind(&client_socket, 12, NX_IP_PERIODIC_RATE);
168
169 /* Check for error. */
170 if(status)
171 error_counter++;
172
173 ip_0.nx_ip_tcp_packet_receive = my_tcp_packet_receive_12_21;
174
175 status = nx_tcp_client_socket_connect(&client_socket, IP_ADDRESS(1, 2, 3, 5), 12, 5 * NX_IP_PERIODIC_RATE);
176
177 /* Check for error. */
178 if(status)
179 error_counter++;
180
181 /*Check if the MSS option of server socket has calculated to the appropriate 88(server_socket's MSS) which the SYN,ACK packet from client socket carried*/
182 if(client_socket.nx_tcp_socket_connect_mss != mss_option_12_21)
183 error_counter++;
184
185 advanced_packet_process_callback = my_packet_process_12_21;
186
187 /* Allocate a packet. */
188 status = nx_packet_allocate(&pool_0, &my_packet, NX_TCP_PACKET, NX_IP_PERIODIC_RATE);
189
190 /* Check status. */
191 if (status)
192 error_counter++;
193
194 /* Create a 200-byte length message randomly. */
195 rand_12_21();
196
197 /* Fill in the packet with data. */
198 status = nx_packet_data_append(my_packet, data_12_21, packet_length_12_21, &pool_0, NX_IP_PERIODIC_RATE);
199
200 /* Check status. */
201 if(status)
202 error_counter++;
203
204 /* Send the packet out! */
205 status = nx_tcp_socket_send(&client_socket, my_packet, 5 * NX_IP_PERIODIC_RATE);
206
207 /* Check for error. */
208 if (status)
209 error_counter++;
210
211
212 /* Disconnect this socket. */
213 status = nx_tcp_socket_disconnect(&client_socket, NX_IP_PERIODIC_RATE);
214
215 /* Check for error. */
216 if(status)
217 error_counter++;
218
219 /*Check if the content of the callback_rcv_buffer which appended by all the received packets' payload is the data_12_18 sent before*/
220 if(!memcmp(callback_rcv_buffer, data_12_21, packet_length_12_21))
221 data_counter++;
222
223 /* Unbind the socket. */
224 status = nx_tcp_client_socket_unbind(&client_socket);
225
226 /* Check for error. */
227 if(status)
228 error_counter++;
229
230 status += nx_tcp_socket_delete(&client_socket);
231
232 /* Check for error. */
233 if(status)
234 error_counter++;
235
236
237 /* Check for error. */
238 if((error_counter !=0) || (syn_ack_counter != 1) || (data_counter != 2))
239 {
240 printf("ERROR\n");
241 test_control_return(1);
242 }
243 else
244 {
245 printf("SUCCESS!\n");
246 test_control_return(0);
247 }
248 }
249
ntest_1_entry(ULONG thread_input)250 static void ntest_1_entry(ULONG thread_input)
251 {
252 UINT status;
253 ULONG actual_status;
254 NX_PACKET *my_packet;
255 ULONG bytes_copied;
256
257 /* Ensure the IP instance has been initialized. */
258 status = nx_ip_status_check(&ip_1, NX_IP_INITIALIZE_DONE, &actual_status, NX_IP_PERIODIC_RATE);
259
260 /* Check for error. */
261 if(status)
262 error_counter++;
263
264 /* Create a socket. */
265 status = nx_tcp_socket_create(&ip_1, &server_socket, "Server Socket",
266 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 200,
267 NX_NULL, ntest_1_disconnect_received);
268
269 /* Check for error. */
270 if(status)
271 error_counter++;
272
273 /* Setup this thread to listen. */
274 status = nx_tcp_server_socket_listen(&ip_1, 12, &server_socket, 5, ntest_1_connect_received);
275
276 /* Check for error. */
277 if(status)
278 error_counter++;
279
280 /* Accept a client socket connection. */
281 status = nx_tcp_server_socket_accept(&server_socket, NX_IP_PERIODIC_RATE);
282
283 /* Check for error. */
284 if(status)
285 error_counter++;
286
287 while(!(nx_tcp_socket_receive(&server_socket, &my_packet, NX_IP_PERIODIC_RATE)))
288 {
289 /*Check if the packet is fragmented by TCP layer.*/
290 if(my_packet -> nx_packet_length > mss_option_12_21)
291 error_counter++;
292
293 /* Retrieve data from packet to the receive buffer. */
294 status = nx_packet_data_retrieve(my_packet, &rcv_buffer[rcv_length], &bytes_copied);
295 if(status)
296 error_counter++;
297
298 rcv_length += bytes_copied;
299 }
300
301 /*Check if the content which connected by all the received packets is the data_12_21 sent from the client socket*/
302 if(!memcmp(rcv_buffer, data_12_21, packet_length_12_21))
303 data_counter++;
304
305 /* Disconnect the server socket. */
306 status = nx_tcp_socket_disconnect(&server_socket, NX_IP_PERIODIC_RATE);
307
308 /* Check for error. */
309 if (status)
310 error_counter++;
311
312 /* Unaccept the server socket. */
313 status = nx_tcp_server_socket_unaccept(&server_socket);
314
315 /* Check for error. */
316 if (status)
317 error_counter++;
318
319 /* Unlisten on the server port. */
320 status = nx_tcp_server_socket_unlisten(&ip_1, 12);
321
322 /* Check for error. */
323 if (status)
324 error_counter++;
325
326 /* Delete the socket. */
327 status = nx_tcp_socket_delete(&server_socket);
328
329 /* Check for error. */
330 if(status)
331 error_counter++;
332
333
334 }
335
ntest_1_connect_received(NX_TCP_SOCKET * socket_ptr,UINT port)336 static void ntest_1_connect_received(NX_TCP_SOCKET *socket_ptr, UINT port)
337 {
338
339 /* Check for the proper socket and port. */
340 if((socket_ptr != &server_socket) || (port != 12))
341 error_counter++;
342 }
343
ntest_1_disconnect_received(NX_TCP_SOCKET * socket)344 static void ntest_1_disconnect_received(NX_TCP_SOCKET *socket)
345 {
346
347 /* Check for proper disconnected socket. */
348 if(socket != &server_socket)
349 error_counter++;
350 }
351
rand_12_21()352 static void rand_12_21()
353 {
354 UINT flag;
355 UINT j, k = 0;
356
357 srand((unsigned)time(NULL));
358 for(j = 0;j < 200;j++)
359 {
360 flag = rand() & 1;
361 if(flag)
362 data_12_21[k++] = 'A' + rand() % 26;
363 else
364 data_12_21[k++] = 'a' + rand() % 26;
365 }
366 }
367
368
my_packet_process_12_21(NX_IP * ip_ptr,NX_PACKET * packet_ptr,UINT * operation_ptr,UINT * delay_ptr)369 static UINT my_packet_process_12_21(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr)
370 {
371 #if defined(__PRODUCT_NETXDUO__)
372 NX_IPV4_HEADER *ip_header_ptr = (NX_IPV4_HEADER*)(packet_ptr -> nx_packet_prepend_ptr);
373 #else
374 NX_IP_HEADER *ip_header_ptr = (NX_IP_HEADER*)(packet_ptr -> nx_packet_prepend_ptr);
375 #endif
376
377 if((packet_ptr -> nx_packet_length) > 40)
378 {
379 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_1);
380
381 /*Check if the packet is fragmented by IP layer.*/
382 if(!(ip_header_ptr->nx_ip_header_word_1& NX_IP_FRAGMENT_MASK))
383 {
384 /*Check if the packet is fragmented by TCP layer*/
385 if((packet_ptr->nx_packet_length - 40) > mss_option_12_21)
386 error_counter++;
387 }
388 else
389 error_counter++;
390
391 /* Append the intercepted packet's content to the receive buffer. */
392 memcpy(&callback_rcv_buffer[callback_rcv_length], packet_ptr->nx_packet_prepend_ptr + 40, packet_ptr -> nx_packet_length - 40);
393 callback_rcv_length = callback_rcv_length + packet_ptr -> nx_packet_length - 40;
394
395 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_1);
396 }
397
398 return NX_TRUE;
399 }
400
my_tcp_packet_receive_12_21(NX_IP * ip_ptr,NX_PACKET * packet_ptr)401 static void my_tcp_packet_receive_12_21(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
402 {
403 NX_TCP_HEADER *header_ptr;
404 ULONG option_words;
405
406 header_ptr = (NX_TCP_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
407 NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_3);
408
409 /* Client receives a SYN+ACK packet. */
410 if((header_ptr -> nx_tcp_header_word_3 & NX_TCP_SYN_BIT) && (header_ptr -> nx_tcp_header_word_3 & NX_TCP_ACK_BIT) && !(header_ptr -> nx_tcp_header_word_3 & NX_TCP_RST_BIT))
411 {
412 /* It is a SYN+ACK packet. */
413 syn_ack_counter++;
414
415 /*Get the MSS option kind*/
416 option_words = (header_ptr -> nx_tcp_header_word_3 >> 28) - 5;
417
418 /*Get the MSS option form the SYN packet.*/
419 _nx_tcp_mss_option_get((packet_ptr -> nx_packet_prepend_ptr + sizeof(NX_TCP_HEADER)), option_words*sizeof(ULONG), &mss_option_12_21);
420
421 ip_0.nx_ip_tcp_packet_receive = _nx_tcp_packet_receive;
422 }
423
424 NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_3);
425
426 _nx_tcp_packet_receive(ip_ptr, packet_ptr);
427
428 }
429 #else
430
431 #ifdef CTEST
test_application_define(void * first_unused_memory)432 VOID test_application_define(void *first_unused_memory)
433 #else
434 void netx_12_21_application_define(void *first_unused_memory)
435 #endif
436 {
437
438 /* Print out test information banner. */
439 printf("NetX Test: TCP Spec 12.21 Test.......................................N/A\n");
440
441 test_control_return(3);
442 }
443 #endif