1 /* This tests that in NX_PPP_IPCP_CONFIGURE_REQUEST_ACKED_STATE state, we can send the correct NAK.  */
2 
3 #include "tx_api.h"
4 #include "nx_api.h"
5 #include "nx_ppp.h"
6 
7 extern void         test_control_return(UINT status);
8 
9 #if !defined(NX_DISABLE_IPV4)
10 
11 /* Define demo stack size.   */
12 
13 #define DEMO_STACK_SIZE     2048
14 #define DEMO_DATA           "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
15 
16 
17 /* Define the ThreadX and NetX object control blocks...  */
18 
19 static TX_THREAD               thread_0;
20 static TX_THREAD               thread_1;
21 
22 static NX_PACKET_POOL          pool_0;
23 
24 static NX_IP                   ip_0;
25 static NX_IP                   ip_1;
26 
27 static NX_PPP                  ppp_0;
28 static NX_PPP                  ppp_1;
29 
30 static NX_UDP_SOCKET           socket_0;
31 static NX_UDP_SOCKET           socket_1;
32 
33 
34 /* Define the counters used in the demo application...  */
35 
36 static ULONG                   ppp_0_link_up_counter;
37 static ULONG                   ppp_0_link_down_counter;
38 static ULONG                   ppp_1_link_up_counter;
39 static ULONG                   ppp_1_link_down_counter;
40 static UINT                    error_counter = 0;
41 static UINT                    thread_1_alive = NX_TRUE;
42 
43 
44 /* Define thread prototypes.  */
45 static void         thread_0_entry(ULONG thread_input);
46 static void         thread_1_entry(ULONG thread_input);
47 
48 static void         link_up_callback(NX_PPP *ppp_ptr);
49 static void         link_down_callback(NX_PPP *ppp_ptr);
50 static void         ppp_0_serial_byte_output(UCHAR byte);
51 static void         ppp_1_serial_byte_output(UCHAR byte);
52 static void         invalid_packet_handler(NX_PACKET *packet_ptr);
53 
54 /* Define what the initial system looks like.  */
55 
56 #ifdef CTEST
test_application_define(void * first_unused_memory)57 VOID test_application_define(void *first_unused_memory)
58 #else
59 void    netx_ppp_IPCP_retransmit_test_application_define(void *first_unused_memory)
60 #endif
61 {
62 
63 CHAR    *pointer;
64 UINT    status;
65 
66 
67     /* Setup the working pointer.  */
68     pointer =  (CHAR *) first_unused_memory;
69 
70     /* Create the thread 0.  */
71     tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
72             pointer, DEMO_STACK_SIZE,
73             5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);
74     pointer =  pointer + DEMO_STACK_SIZE;
75 
76     /* Create the thread 1.  */
77     tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0,
78             pointer, DEMO_STACK_SIZE,
79             5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);
80     pointer =  pointer + DEMO_STACK_SIZE;
81 
82     /* Initialize the NetX system.  */
83     nx_system_initialize();
84 
85     /* Create a packet pool.  */
86     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, 2048);
87     pointer = pointer + 2048;
88 
89     /* Check for pool creation error.  */
90     if (status)
91         error_counter++;
92 
93     /* Create the first PPP instance.  */
94     status =  nx_ppp_create(&ppp_0, "PPP 0", &ip_0, pointer, 2048, 1, &pool_0, invalid_packet_handler, ppp_0_serial_byte_output);
95     pointer =  pointer + 2048;
96 
97     /* Check for PPP create error.   */
98     if (status)
99         error_counter++;
100 
101     /* Define IP address. This PPP instance is effectively the server since it has both IP addresses. */
102     status =  nx_ppp_ip_address_assign(&ppp_0, IP_ADDRESS(1, 2, 3, 4), IP_ADDRESS(1, 2, 3, 5));
103 
104     /* Check for PPP IP address assign error.   */
105     if (status)
106         error_counter++;
107 
108     /* Register the link up/down callbacks.  */
109     status =  nx_ppp_link_up_notify(&ppp_0, link_up_callback);
110     status += nx_ppp_link_down_notify(&ppp_0, link_down_callback);
111 
112     /* Check for PPP link up/down callback registration error(s).   */
113     if (status)
114         error_counter++;
115 
116     /* Create an IP instance.  */
117     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(0, 0, 0, 0), 0xFFFFF000UL, &pool_0, nx_ppp_driver,
118                     pointer, 2048, 1);
119     pointer =  pointer + 2048;
120 
121     if (status)
122         error_counter++;
123 
124     /* Create the next PPP instance.  */
125     status =  nx_ppp_create(&ppp_1, "PPP 1", &ip_1, pointer, 2048, 1, &pool_0, invalid_packet_handler, ppp_1_serial_byte_output);
126     pointer =  pointer + 2048;
127 
128     /* Check for PPP create error.   */
129     if (status)
130         error_counter++;
131 
132     /* Define IP address. This PPP instance is effectively the client since it doesn't have any IP addresses. */
133     status =  nx_ppp_ip_address_assign(&ppp_1, IP_ADDRESS(0, 0, 0, 0), IP_ADDRESS(0, 0, 0, 0));
134 
135     /* Check for PPP IP address assign error.   */
136     if (status)
137         error_counter++;
138 
139     /* Register the link up/down callbacks.  */
140     status =  nx_ppp_link_up_notify(&ppp_1, link_up_callback);
141     status += nx_ppp_link_down_notify(&ppp_1, link_down_callback);
142 
143     /* Check for PPP link up/down callback registration error(s).   */
144     if (status)
145         error_counter++;
146 
147     /* Create another IP instance.  */
148     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(0, 0, 0, 0), 0xFFFFF000UL, &pool_0, nx_ppp_driver, pointer, 2048, 1);
149     pointer =  pointer + 2048;
150 
151     if (status)
152         error_counter++;
153 
154     /* Enable UDP traffic.  */
155     nx_udp_enable(&ip_0);
156     nx_udp_enable(&ip_1);
157 }
158 
159 
160 /* Define the test threads.  */
161 
thread_0_entry(ULONG thread_input)162 static void    thread_0_entry(ULONG thread_input)
163 {
164 
165 UINT        status;
166 ULONG       ip_status;
167 NX_PACKET   *my_packet;
168 
169     /* Print out test information banner.  */
170     printf("NetX Test:   PPP IPCP Retransmit Test..................................");
171 
172     if (error_counter)
173     {
174 
175         printf("ERROR!\n");
176         test_control_return(1);
177     }
178 
179     /* Wait for the link to come up.  */
180     status =  nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &ip_status, 30 * NX_IP_PERIODIC_RATE);
181 
182     if (status != NX_SUCCESS)
183     {
184 
185         printf("ERROR!\n");
186         test_control_return(1);
187     }
188 
189 
190     /* Create a UDP socket.  */
191     status = nx_udp_socket_create(&ip_0, &socket_0, "Socket 0", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
192 
193     /* Check status.  */
194     if (status)
195     {
196         error_counter++;
197     }
198 
199     /* Bind the UDP socket to the IP port.  */
200     status =  nx_udp_socket_bind(&socket_0, 0x88, TX_WAIT_FOREVER);
201 
202     /* Check status.  */
203     if (status)
204     {
205         error_counter++;
206     }
207 
208     /* Disable checksum logic for this socket.  */
209     nx_udp_socket_checksum_disable(&socket_0);
210 
211     /* Let receiver thread run.  */
212     tx_thread_relinquish();
213 
214     /* Allocate a packet.  */
215     status =  nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
216 
217     /* Check status.  */
218     if (status != NX_SUCCESS)
219         error_counter++;
220 
221     /* Write ABCs into the packet payload!  */
222     nx_packet_data_append(my_packet, DEMO_DATA, sizeof(DEMO_DATA), &pool_0, TX_WAIT_FOREVER);
223 
224     /* Send the UDP packet.  */
225     status =  nx_udp_socket_send(&socket_0, my_packet, IP_ADDRESS(1, 2, 3, 5), 0x89);
226 
227     /* Check status.  */
228     if (status != NX_SUCCESS)
229     {
230         error_counter++;
231     }
232 
233     while(thread_1_alive)
234         tx_thread_sleep(50);
235 
236     if (error_counter)
237     {
238         printf("ERROR!\n");
239         test_control_return(1);
240     }
241     else
242     {
243         printf("SUCCESS!\n");
244         test_control_return(0);
245     }
246 }
247 
248 
thread_1_entry(ULONG thread_input)249 static void    thread_1_entry(ULONG thread_input)
250 {
251 
252 UINT        status;
253 ULONG       ip_status;
254 NX_PACKET   *my_packet;
255 
256     /* Wait for the link to come up.  */
257     status =  nx_ip_status_check(&ip_1, NX_IP_ADDRESS_RESOLVED, &ip_status, 30 * NX_IP_PERIODIC_RATE);
258 
259     if (status != NX_SUCCESS)
260     {
261 
262         printf("ERROR!\n");
263         test_control_return(1);
264     }
265 
266     /* Create a UDP socket.  */
267     status = nx_udp_socket_create(&ip_1, &socket_1, "Socket 1", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
268 
269     /* Check status.  */
270     if (status)
271     {
272         error_counter++;
273         return;
274     }
275 
276     /* Bind the UDP socket to the IP port.  */
277     status =  nx_udp_socket_bind(&socket_1, 0x89, TX_WAIT_FOREVER);
278 
279     /* Check status.  */
280     if (status)
281     {
282         error_counter++;
283         return;
284     }
285 
286     /* Receive a UDP packet.  */
287     status =  nx_udp_socket_receive(&socket_1, &my_packet, TX_WAIT_FOREVER);
288 
289     /* Check status.  */
290     if (status != NX_SUCCESS)
291         error_counter++;
292 
293     /* Release the packet.  */
294     status =  nx_packet_release(my_packet);
295 
296     /* Check status.  */
297     if (status != NX_SUCCESS)
298         error_counter++;
299 
300     thread_1_alive = NX_FALSE;
301 
302     return;
303 }
304 
305 /* Define serial output routines.  Normally these routines would
306    map to physical UART routines and the nx_ppp_byte_receive call
307    would be made from a UART receive interrupt.  */
308 static UCHAR temp_data[8] = {0};
309 static UCHAR temp_index = 0;
310 static UINT i = 0;
311 static UINT packet_drop = NX_FALSE;
312 static UINT packet_end = NX_FALSE;
313 
314 static UCHAR configure_request_ack[] = {0x7E, 0xFF, 0x7D, 0x23, 0xc0, 0x21, 0x7D, 0x22};
315 
ppp_0_serial_byte_output(UCHAR byte)316 static void    ppp_0_serial_byte_output(UCHAR byte)
317 {
318 
319     /* Discard LCP Configure Request ACK before NX_PPP_IPCP_CONFIGURE_REQUEST_SENT_STATE. */
320     if (ppp_0.nx_ppp_ipcp_state < NX_PPP_IPCP_CONFIGURE_REQUEST_SENT_STATE)
321     {
322 
323         if (byte == 0x7e)
324         {
325 
326             if (temp_index == 0)
327             {
328                 packet_drop = NX_TRUE;
329                 packet_end = NX_FALSE;
330                 i = 0;
331             }
332             else
333             {
334                 packet_end = NX_TRUE;
335             }
336         }
337 
338         if (temp_index < 8)
339         {
340             temp_data[temp_index++] = byte;
341         }
342         else if (memcmp(temp_data, configure_request_ack, 8) != 0)
343         {
344             packet_drop = NX_FALSE;
345         }
346 
347         if (packet_drop)
348         {
349             if (packet_end)
350                 temp_index = 0;
351             return;
352         }
353         else
354         {
355             for (;i < temp_index; i++)
356             {
357                 nx_ppp_byte_receive(&ppp_1, temp_data[i]);
358             }
359 
360             if (packet_end)
361                 temp_index = 0;
362         }
363     }
364 
365     /* Just feed the PPP 1 input routine.  */
366     nx_ppp_byte_receive(&ppp_1, byte);
367 }
368 
ppp_1_serial_byte_output(UCHAR byte)369 static void    ppp_1_serial_byte_output(UCHAR byte)
370 {
371 
372     /* Just feed the PPP 0 input routine.  */
373     nx_ppp_byte_receive(&ppp_0, byte);
374 }
375 
376 
invalid_packet_handler(NX_PACKET * packet_ptr)377 static void invalid_packet_handler(NX_PACKET *packet_ptr)
378 {
379     /* Print out the non-PPP byte. In Windows, the string "CLIENT" will
380        be sent before Windows PPP starts. Once CLIENT is received, we need
381        to send "CLIENTSERVER" to establish communication. It's also possible
382        to receive modem commands here that might need some response to
383        continue.  */
384     nx_packet_release(packet_ptr);
385 }
386 
387 
link_up_callback(NX_PPP * ppp_ptr)388 static void link_up_callback(NX_PPP *ppp_ptr)
389 {
390 
391     /* Just increment the link up counter.  */
392     if (ppp_ptr == &ppp_0)
393         ppp_0_link_up_counter++;
394     else
395         ppp_1_link_up_counter++;
396 }
397 
398 
link_down_callback(NX_PPP * ppp_ptr)399 static void link_down_callback(NX_PPP *ppp_ptr)
400 {
401 
402     /* Just increment the link down counter.  */
403     if (ppp_ptr == &ppp_0)
404         ppp_0_link_down_counter++;
405     else
406         ppp_1_link_down_counter++;
407 
408     /* Restart the PPP instance.  */
409     nx_ppp_restart(ppp_ptr);
410 }
411 #else
412 
413 #ifdef CTEST
test_application_define(void * first_unused_memory)414 VOID test_application_define(void *first_unused_memory)
415 #else
416 void    netx_ppp_IPCP_retransmit_test_application_define(void *first_unused_memory)
417 #endif
418 {
419 
420     /* Print out test information banner.  */
421     printf("NetX Test:   PPP IPCP retransmit Test..................................N/A\n");
422 
423     test_control_return(3);
424 }
425 #endif
426