1 /* 8.2 :TCP in LISTEN state,
2         TCP MUST send RST in response to incoming segment with ACK and remain in the same state,
3         SEQ number of RST is taken from SEG.ACK.   */
4 
5 /* Procedure
6 1. Connection.
7 2. Server calls disconnect command.
8 3. Server calls  unaccept and relisten command.
9 4. Client sends a segment that is carrying an  ACK flag.
10 5. Server sends a RST segment with SEQ number taken from SEG.ACK.
11 6. Clean up.Print the resuit. */
12 
13 #include   "tx_api.h"
14 #include   "nx_api.h"
15 #include   "nx_tcp.h"
16 #include   "nx_ip.h"
17 #include   "nx_ram_network_driver_test_1500.h"
18 
19 extern void    test_control_return(UINT status);
20 
21 #if !defined(NX_DISABLE_RESET_DISCONNECT) && !defined(NX_DISABLE_IPV4)
22 
23 #define     MSG                "ABCDEFGHIJKLMNOPQRSTUVWXYZ  "
24 #define     DEMO_STACK_SIZE    2048
25 
26 /* Define the ThreadX and NetX object control blocks...  */
27 
28 static TX_THREAD               ntest_0;
29 static TX_THREAD               ntest_1;
30 
31 static NX_PACKET_POOL          pool_0;
32 static NX_IP                   ip_0;
33 static NX_IP                   ip_1;
34 static NX_TCP_SOCKET           client_socket;
35 static NX_TCP_SOCKET           server_socket;
36 
37 /* Define the counters used in the demo application...  */
38 
39 static ULONG                   error_counter;
40 static ULONG                   rst_counter;
41 static ULONG                   data_packet_counter;
42 static ULONG                   ack_segment;
43 
44 /* Define thread prototypes.  */
45 
46 static void    ntest_0_entry(ULONG thread_input);
47 static void    ntest_1_entry(ULONG thread_input);
48 static void    ntest_0_connect_received(NX_TCP_SOCKET *server_socket, UINT port);
49 static void    ntest_0_disconnect_received(NX_TCP_SOCKET *server_socket);
50 extern void    _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
51 extern UINT    (*advanced_packet_process_callback)(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
52 static UINT    my_packet_process_8_02(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
53 static void    my_tcp_packet_receive_8_02(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
54 static void    my_tcp_packet_receive_8_02_2(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
55 
56 /* Define what the initial system looks like.  */
57 
58 #ifdef CTEST
test_application_define(void * first_unused_memory)59 VOID test_application_define(void *first_unused_memory)
60 #else
61 void           netx_8_02_application_define(void *first_unused_memory)
62 #endif
63 {
64 CHAR       *pointer;
65 UINT       status;
66 
67     /* Setup the working pointer.  */
68     pointer = (CHAR *) first_unused_memory;
69 
70     error_counter = 0;
71     rst_counter = 0;
72     data_packet_counter = 0;
73 
74     /* Create the main thread.  */
75     tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
76                      pointer, DEMO_STACK_SIZE,
77                      3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
78 
79     pointer = pointer + DEMO_STACK_SIZE;
80 
81     /* Create the main thread.  */
82     tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
83                      pointer, DEMO_STACK_SIZE,
84                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
85 
86     pointer = pointer + DEMO_STACK_SIZE;
87 
88     /* Initialize the NetX system.  */
89     nx_system_initialize();
90 
91     /* Create a packet pool.  */
92     status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, 8192);
93     pointer = pointer + 8192;
94 
95     if(status)
96         error_counter++;
97 
98     /* Create an IP instance.  */
99     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500,
100                           pointer, 2048, 1);
101     pointer = pointer + 2048;
102 
103     /* Create another IP instance.  */
104     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500,
105                            pointer, 2048, 1);
106     pointer = pointer + 2048;
107 
108     if(status)
109         error_counter++;
110 
111     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
112     status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
113     pointer = pointer + 1024;
114 
115     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
116     status += nx_arp_enable(&ip_1, (void *) pointer, 1024);
117     pointer = pointer + 1024;
118 
119     /* Check ARP enable status.  */
120     if(status)
121         error_counter++;
122 
123     /* Enable TCP processing for both IP instances.  */
124     status = nx_tcp_enable(&ip_0);
125     status += nx_tcp_enable(&ip_1);
126 
127     /* Check TCP enable status.  */
128     if(status)
129         error_counter++;
130 }
131 
132 /* Define the test threads.  */
133 
ntest_0_entry(ULONG thread_input)134 static void    ntest_0_entry(ULONG thread_input)
135 {
136 UINT       status;
137 ULONG      actual_status;
138 
139     /* Print out some test information banners.  */
140     printf("NetX Test:   TCP Spec 8.02 Test........................................");
141 
142     /* Check for earlier error.  */
143     if(error_counter)
144     {
145         printf("ERROR!\n");
146         test_control_return(1);
147     }
148 
149     /* Ensure the IP instance has been initialized.  */
150     status = nx_ip_status_check(&ip_0, NX_IP_INITIALIZE_DONE, &actual_status, NX_IP_PERIODIC_RATE);
151 
152     /* Check status...  */
153     if(status != NX_SUCCESS)
154         error_counter++;
155 
156     /* Create a socket.  */
157     status = nx_tcp_socket_create(&ip_0, &server_socket, "Server Socket",
158                                   NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
159                                   100, NX_NULL, ntest_0_disconnect_received);
160 
161     /* Check for error.  */
162     if(status)
163         error_counter++;
164 
165     /* Setup this thread to listen.  */
166     status = nx_tcp_server_socket_listen(&ip_0, 12, &server_socket, 5, ntest_0_connect_received);
167 
168     /* Check for error.  */
169     if(status)
170         error_counter++;
171 
172     /* Accept a client socket connection.  */
173     status = nx_tcp_server_socket_accept(&server_socket, NX_IP_PERIODIC_RATE);
174 
175     /* Check for error.  */
176     if(status)
177         error_counter++;
178 
179     /* Set the callback function to my_packet_process_8_02. */
180     advanced_packet_process_callback = my_packet_process_8_02;
181 
182     /* Disconnect the server socket.  */
183     status = nx_tcp_socket_disconnect(&server_socket, NX_NO_WAIT);
184 
185     /* Set the port to NULL. */
186     status = nx_tcp_server_socket_unaccept(&server_socket);
187 
188     /* Check for error.  */
189     if(status)
190         error_counter++;
191 
192     /* Setup server socket state to LISTEN   */
193     status = nx_tcp_server_socket_relisten(&ip_0, 12, &server_socket);
194 
195     if(status)
196         error_counter++;
197 
198     if (server_socket.nx_tcp_socket_state != NX_TCP_LISTEN_STATE)
199         error_counter++;
200 
201     /* Set the receive function to my_tcp_packet_receive_8_02.  */
202     ip_0.nx_ip_tcp_packet_receive = my_tcp_packet_receive_8_02;
203 
204     /* suspend the thread ntest_0 */
205     tx_thread_suspend(&ntest_0);
206 
207     /* Check whether the server socket is in LISTEN state.  */
208     if((data_packet_counter == 1) && (rst_counter == 2))
209     {
210         if (server_socket.nx_tcp_socket_state != NX_TCP_LISTEN_STATE)
211             error_counter++;
212     }
213     else
214         error_counter++;
215 
216     /* Unlisten on the server port.  */
217     status = nx_tcp_server_socket_unlisten(&ip_0, 12);
218 
219     /* Check for error.  */
220     if (status)
221         error_counter++;
222 
223     /* Delete the socket.  */
224     status = nx_tcp_socket_delete(&server_socket);
225 
226     /* Check for error.  */
227     if(status)
228         error_counter++;
229 }
230 
ntest_1_entry(ULONG thread_input)231 static void    ntest_1_entry(ULONG thread_input)
232 {
233 UINT         status;
234 NX_PACKET    *my_packet;
235 
236 
237     /* Create a socket.  */
238     status = nx_tcp_socket_create(&ip_1, &client_socket, "Client Socket",
239                                   NX_IP_NORMAL, NX_FRAGMENT_OKAY,
240                                   NX_IP_TIME_TO_LIVE, 200,
241                                   NX_NULL, NX_NULL);
242 
243     /* Check for error.  */
244     if(status)
245         error_counter++;
246 
247     /* Bind the socket.  */
248     status = nx_tcp_client_socket_bind(&client_socket, 12, NX_IP_PERIODIC_RATE);
249 
250     /* Check for error.  */
251     if(status)
252         error_counter++;
253 
254     /* Attempt to connect the socket.  */
255     status = nx_tcp_client_socket_connect(&client_socket, IP_ADDRESS(1, 2, 3, 4), 12, 5 * NX_IP_PERIODIC_RATE);
256 
257     /* Check for error.  */
258     if(status)
259         error_counter++;
260 
261     /* Replace the TCP receive function with my_tcp_packet_receive_8_02 for ip_1.  */
262     ip_1.nx_ip_tcp_packet_receive = my_tcp_packet_receive_8_02_2;
263 
264     /* Allocate a packet.  */
265     status = nx_packet_allocate(&pool_0, &my_packet, NX_TCP_PACKET, NX_IP_PERIODIC_RATE);
266 
267     /* Check status.  */
268     if(status)
269         error_counter++;
270 
271     status = nx_packet_data_append(my_packet, MSG, 20, &pool_0, NX_IP_PERIODIC_RATE);
272 
273     /* Check status.  */
274     if(status)
275         error_counter++;
276 
277     /* Send the packet out!  */
278     status = nx_tcp_socket_send(&client_socket, my_packet, NX_IP_PERIODIC_RATE);
279 
280     /* Check status.  */
281     if(status)
282         error_counter++;
283 
284     /* Resume the thread ntest_0.  */
285     tx_thread_resume(&ntest_0);
286 
287     /* Unbind the socket.  */
288     status = nx_tcp_client_socket_unbind(&client_socket);
289 
290     /* Check for error.  */
291     if(status)
292         error_counter++;
293 
294     /* Delete the socket.  */
295     status = nx_tcp_socket_delete(&client_socket);
296 
297     /* Check for error.  */
298     if(status)
299         error_counter++;
300 
301     /*Check  the program status.  */
302     if((error_counter == 0) && (data_packet_counter == 1) && (rst_counter == 2))
303     {
304         printf("SUCCESS!\n");
305         test_control_return(0);
306     }
307     else
308     {
309         printf("ERROR!\n");
310         test_control_return(1);
311     }
312 }
313 
ntest_0_connect_received(NX_TCP_SOCKET * socket_ptr,UINT port)314 static void    ntest_0_connect_received(NX_TCP_SOCKET *socket_ptr, UINT port)
315 {
316 
317     /* Check for the proper socket and port.  */
318     if((socket_ptr != &server_socket) || (port != 12))
319         error_counter++;
320 }
321 
ntest_0_disconnect_received(NX_TCP_SOCKET * socket)322 static void    ntest_0_disconnect_received(NX_TCP_SOCKET *socket)
323 {
324 
325     /* Check for proper disconnected socket.  */
326     if(socket != &server_socket)
327         error_counter++;
328 }
329 
my_packet_process_8_02(NX_IP * ip_ptr,NX_PACKET * packet_ptr,UINT * operation_ptr,UINT * delay_ptr)330 static UINT    my_packet_process_8_02(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr)
331 {
332 
333 NX_TCP_HEADER *tcp_header_ptr;
334 
335     if(packet_ptr -> nx_packet_length < 40)
336         return NX_TRUE;
337 
338     /* Point to the TCP header   */
339     tcp_header_ptr = (NX_TCP_HEADER *)((packet_ptr -> nx_packet_prepend_ptr) + 20);
340 
341     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
342 
343     if (tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_RST_BIT)
344     {
345         *operation_ptr = NX_RAMDRIVER_OP_DROP;
346         rst_counter++;
347 
348         advanced_packet_process_callback = NULL;
349     }
350 
351     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
352 
353     return NX_TRUE;
354 }
355 
my_tcp_packet_receive_8_02(NX_IP * ip_ptr,NX_PACKET * packet_ptr)356 static void    my_tcp_packet_receive_8_02(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
357 {
358 
359 NX_TCP_HEADER  *tcp_header_ptr;
360 
361     tcp_header_ptr = (NX_TCP_HEADER *)packet_ptr->nx_packet_prepend_ptr;
362 
363     if ((packet_ptr -> nx_packet_length - 20 == 20) && !memcmp(packet_ptr -> nx_packet_prepend_ptr + 20, MSG, 20))
364     {
365         NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
366 
367         if ((tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_ACK_BIT) && !(tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_SYN_BIT) && !(tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_RST_BIT))
368         {
369             NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_acknowledgment_number);
370             ack_segment = tcp_header_ptr -> nx_tcp_acknowledgment_number;
371             NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_acknowledgment_number);
372 
373             data_packet_counter++;
374         }
375 
376         NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
377 
378         /* Deal packets with default routing.  */
379         ip_0.nx_ip_tcp_packet_receive = _nx_tcp_packet_receive;
380 
381     }
382 
383     /* Let server receives the packet.  */
384     _nx_tcp_packet_receive(ip_ptr, packet_ptr);
385 }
386 
my_tcp_packet_receive_8_02_2(NX_IP * ip_ptr,NX_PACKET * packet_ptr)387 static void    my_tcp_packet_receive_8_02_2(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
388 {
389 
390 NX_TCP_HEADER  *tcp_header_ptr;
391 
392     tcp_header_ptr = (NX_TCP_HEADER*)packet_ptr->nx_packet_prepend_ptr;
393     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
394 
395     if (tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_RST_BIT)
396     {
397 
398         NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_sequence_number);
399 
400         if (tcp_header_ptr -> nx_tcp_sequence_number == ack_segment)
401             rst_counter++;
402 
403         NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_sequence_number);
404 
405         ip_1.nx_ip_tcp_packet_receive = _nx_tcp_packet_receive;
406     }
407 
408     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
409 
410     /* Let server receives the packet.  */
411     _nx_tcp_packet_receive(ip_ptr, packet_ptr);
412 }
413 
414 #else
415 
416 #ifdef CTEST
test_application_define(void * first_unused_memory)417 VOID test_application_define(void *first_unused_memory)
418 #else
419 void    netx_8_02_application_define(void *first_unused_memory)
420 #endif
421 {
422 
423     /* Print out test information banner.  */
424     printf("NetX Test:   TCP Spec 8.02 Test........................................N/A\n");
425     test_control_return(3);
426 
427 }
428 #endif
429