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 UINT         generate_login(CHAR *name, CHAR *password);
51 static UINT         verify_login(CHAR *name, CHAR *password);
52 static void         ppp_0_serial_byte_output(UCHAR byte);
53 static void         ppp_1_serial_byte_output(UCHAR byte);
54 static void         invalid_packet_handler(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_ppp_IPCP_nak_test_application_define(void *first_unused_memory)
62 #endif
63 {
64 
65 CHAR    *pointer;
66 UINT    status;
67 
68 
69     /* Setup the working pointer.  */
70     pointer =  (CHAR *) first_unused_memory;
71 
72     /* Create the thread 0.  */
73     tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
74             pointer, DEMO_STACK_SIZE,
75             5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);
76     pointer =  pointer + DEMO_STACK_SIZE;
77 
78     /* Create the thread 1.  */
79     tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0,
80             pointer, DEMO_STACK_SIZE,
81             5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);
82     pointer =  pointer + DEMO_STACK_SIZE;
83 
84     /* Initialize the NetX system.  */
85     nx_system_initialize();
86 
87     /* Create a packet pool.  */
88     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, 2048);
89     pointer = pointer + 2048;
90 
91     /* Check for pool creation error.  */
92     if (status)
93         error_counter++;
94 
95     /* Create the first PPP instance.  */
96     status =  nx_ppp_create(&ppp_0, "PPP 0", &ip_0, pointer, 2048, 1, &pool_0, invalid_packet_handler, ppp_0_serial_byte_output);
97     pointer =  pointer + 2048;
98 
99     /* Check for PPP create error.   */
100     if (status)
101         error_counter++;
102 
103     /* Define IP address. This PPP instance is effectively the server since it has both IP addresses. */
104     status =  nx_ppp_ip_address_assign(&ppp_0, IP_ADDRESS(1, 2, 3, 4), IP_ADDRESS(1, 2, 3, 5));
105 
106     /* Check for PPP IP address assign error.   */
107     if (status)
108         error_counter++;
109 
110     /* Register the link up/down callbacks.  */
111     status =  nx_ppp_link_up_notify(&ppp_0, link_up_callback);
112     status += nx_ppp_link_down_notify(&ppp_0, link_down_callback);
113 
114     /* Check for PPP link up/down callback registration error(s).   */
115     if (status)
116         error_counter++;
117 
118     /* Setup PAP, this PPP instance is effectively the server since it will verify the name and password.  */
119     status =  nx_ppp_pap_enable(&ppp_0, NX_NULL, verify_login);
120 
121     /* Check for PPP PAP enable error.  */
122     if (status)
123         error_counter++;
124 
125     /* Create an IP instance.  */
126     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(0, 0, 0, 0), 0xFFFFF000UL, &pool_0, nx_ppp_driver,
127                     pointer, 2048, 1);
128     pointer =  pointer + 2048;
129 
130     if (status)
131         error_counter++;
132 
133     /* Create the next PPP instance.  */
134     status =  nx_ppp_create(&ppp_1, "PPP 1", &ip_1, pointer, 2048, 1, &pool_0, invalid_packet_handler, ppp_1_serial_byte_output);
135     pointer =  pointer + 2048;
136 
137     /* Check for PPP create error.   */
138     if (status)
139         error_counter++;
140 
141     /* Define IP address. This PPP instance is effectively the client since it doesn't have any IP addresses. */
142     status =  nx_ppp_ip_address_assign(&ppp_1, IP_ADDRESS(0, 0, 0, 0), IP_ADDRESS(0, 0, 0, 0));
143 
144     /* Check for PPP IP address assign error.   */
145     if (status)
146         error_counter++;
147 
148     /* Register the link up/down callbacks.  */
149     status =  nx_ppp_link_up_notify(&ppp_1, link_up_callback);
150     status += nx_ppp_link_down_notify(&ppp_1, link_down_callback);
151 
152     /* Check for PPP link up/down callback registration error(s).   */
153     if (status)
154         error_counter++;
155 
156     /* Setup PAP, this PPP instance is effectively the since it generates the name and password for the peer.  */
157     status =  nx_ppp_pap_enable(&ppp_1, generate_login, NX_NULL);
158 
159     /* Check for PPP PAP enable error.  */
160     if (status)
161         error_counter++;
162 
163     /* Create another IP instance.  */
164     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);
165     pointer =  pointer + 2048;
166 
167     if (status)
168         error_counter++;
169 
170     /* Enable UDP traffic.  */
171     nx_udp_enable(&ip_0);
172     nx_udp_enable(&ip_1);
173 }
174 
175 
176 /* Define the test threads.  */
177 
thread_0_entry(ULONG thread_input)178 static void    thread_0_entry(ULONG thread_input)
179 {
180 
181 UINT        status;
182 ULONG       ip_status;
183 NX_PACKET   *my_packet;
184 
185     /* Print out test information banner.  */
186     printf("NetX Test:   PPP IPCP NAK Test.........................................");
187 
188     if (error_counter)
189     {
190 
191         printf("ERROR!\n");
192         test_control_return(1);
193     }
194 
195     /* Wait for the link to come up.  */
196     status =  nx_ip_status_check(&ip_0, NX_IP_LINK_ENABLED, &ip_status, 30 * NX_IP_PERIODIC_RATE);
197 
198     if (status != NX_SUCCESS)
199     {
200 
201         printf("ERROR!\n");
202         test_control_return(1);
203     }
204 
205 
206     /* Create a UDP socket.  */
207     status = nx_udp_socket_create(&ip_0, &socket_0, "Socket 0", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
208 
209     /* Check status.  */
210     if (status)
211     {
212         error_counter++;
213     }
214 
215     /* Bind the UDP socket to the IP port.  */
216     status =  nx_udp_socket_bind(&socket_0, 0x88, TX_WAIT_FOREVER);
217 
218     /* Check status.  */
219     if (status)
220     {
221         error_counter++;
222     }
223 
224     /* Disable checksum logic for this socket.  */
225     nx_udp_socket_checksum_disable(&socket_0);
226 
227     /* Let receiver thread run.  */
228     tx_thread_relinquish();
229 
230     /* Allocate a packet.  */
231     status =  nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
232 
233     /* Check status.  */
234     if (status != NX_SUCCESS)
235         error_counter++;
236 
237     /* Write ABCs into the packet payload!  */
238     nx_packet_data_append(my_packet, DEMO_DATA, sizeof(DEMO_DATA), &pool_0, TX_WAIT_FOREVER);
239 
240     /* Send the UDP packet.  */
241     status =  nx_udp_socket_send(&socket_0, my_packet, IP_ADDRESS(1, 2, 3, 5), 0x89);
242 
243     /* Check status.  */
244     if (status != NX_SUCCESS)
245     {
246         error_counter++;
247     }
248 
249     while(thread_1_alive)
250         tx_thread_sleep(50);
251 
252     if (error_counter)
253     {
254         printf("ERROR!\n");
255         test_control_return(1);
256     }
257     else
258     {
259         printf("SUCCESS!\n");
260         test_control_return(0);
261     }
262 }
263 
264 
thread_1_entry(ULONG thread_input)265 static void    thread_1_entry(ULONG thread_input)
266 {
267 
268 UINT        status;
269 ULONG       ip_status;
270 NX_PACKET   *my_packet;
271 
272     /* Wait for the link to come up.  */
273     status =  nx_ip_status_check(&ip_0, NX_IP_LINK_ENABLED, &ip_status, 30 * NX_IP_PERIODIC_RATE);
274 
275     if (status != NX_SUCCESS)
276     {
277 
278         printf("ERROR!\n");
279         test_control_return(1);
280     }
281 
282     /* Create a UDP socket.  */
283     status = nx_udp_socket_create(&ip_1, &socket_1, "Socket 1", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
284 
285     /* Check status.  */
286     if (status)
287     {
288         error_counter++;
289         return;
290     }
291 
292     /* Bind the UDP socket to the IP port.  */
293     status =  nx_udp_socket_bind(&socket_1, 0x89, TX_WAIT_FOREVER);
294 
295     /* Check status.  */
296     if (status)
297     {
298         error_counter++;
299         return;
300     }
301 
302     /* Receive a UDP packet.  */
303     status =  nx_udp_socket_receive(&socket_1, &my_packet, TX_WAIT_FOREVER);
304 
305     /* Check status.  */
306     if (status != NX_SUCCESS)
307         error_counter++;
308 
309     /* Release the packet.  */
310     status =  nx_packet_release(my_packet);
311 
312     /* Check status.  */
313     if (status != NX_SUCCESS)
314         error_counter++;
315 
316     thread_1_alive = NX_FALSE;
317 
318     return;
319 }
320 
321 /* Define serial output routines.  Normally these routines would
322    map to physical UART routines and the nx_ppp_byte_receive call
323    would be made from a UART receive interrupt.  */
324 static UCHAR temp_data[8] = {0};
325 static UCHAR temp_index = 0;
326 static UINT i = 0;
327 static UINT packet_drop = NX_FALSE;
328 
329 static UCHAR configure_request[] = {0x7E, 0xFF, 0x7D, 0x23, 0x80, 0x21, 0x7D, 0x21};
330 
ppp_0_serial_byte_output(UCHAR byte)331 static void    ppp_0_serial_byte_output(UCHAR byte)
332 {
333 
334     /* Just feed the PPP 1 input routine.  */
335     nx_ppp_byte_receive(&ppp_1, byte);
336 }
337 
ppp_1_serial_byte_output(UCHAR byte)338 static void    ppp_1_serial_byte_output(UCHAR byte)
339 {
340 
341     /* Discard IPCP Configure Request before NX_PPP_IPCP_CONFIGURE_REQUEST_ACKED_STATE. */
342     if (ppp_0.nx_ppp_ipcp_state > NX_PPP_IPCP_INITIAL_STATE &&
343         ppp_0.nx_ppp_ipcp_state < NX_PPP_IPCP_CONFIGURE_REQUEST_ACKED_STATE)
344     {
345 
346         if (byte == 0x7e)
347         {
348 
349             if (temp_index == 0)
350             {
351                 packet_drop = NX_TRUE;
352                 i = 0;
353             }
354             else
355             {
356                 temp_index = 0;
357             }
358         }
359 
360         if (temp_index < 8)
361         {
362             temp_data[temp_index++] = byte;
363         }
364         else if (memcmp(temp_data, configure_request, 8) != 0)
365         {
366             packet_drop = NX_FALSE;
367         }
368 
369         if (packet_drop)
370         {
371             return;
372         }
373         else
374         {
375             for (;i < temp_index; i++)
376             {
377                 nx_ppp_byte_receive(&ppp_0, temp_data[i]);
378             }
379         }
380     }
381 
382     /* Just feed the PPP 0 input routine.  */
383     nx_ppp_byte_receive(&ppp_0, byte);
384 }
385 
386 
invalid_packet_handler(NX_PACKET * packet_ptr)387 static void invalid_packet_handler(NX_PACKET *packet_ptr)
388 {
389     /* Print out the non-PPP byte. In Windows, the string "CLIENT" will
390        be sent before Windows PPP starts. Once CLIENT is received, we need
391        to send "CLIENTSERVER" to establish communication. It's also possible
392        to receive modem commands here that might need some response to
393        continue.  */
394     nx_packet_release(packet_ptr);
395 }
396 
397 
link_up_callback(NX_PPP * ppp_ptr)398 static void link_up_callback(NX_PPP *ppp_ptr)
399 {
400 
401     /* Just increment the link up counter.  */
402     if (ppp_ptr == &ppp_0)
403         ppp_0_link_up_counter++;
404     else
405         ppp_1_link_up_counter++;
406 }
407 
408 
link_down_callback(NX_PPP * ppp_ptr)409 static void link_down_callback(NX_PPP *ppp_ptr)
410 {
411 
412     /* Just increment the link down counter.  */
413     if (ppp_ptr == &ppp_0)
414         ppp_0_link_down_counter++;
415     else
416         ppp_1_link_down_counter++;
417 
418     /* Restart the PPP instance.  */
419     nx_ppp_restart(ppp_ptr);
420 }
421 
422 
generate_login(CHAR * name,CHAR * password)423 static UINT generate_login(CHAR *name, CHAR *password)
424 {
425 
426     /* Make a name and password, called "myname" and "mypassword".  */
427     name[0] = 'm';
428     name[1] = 'y';
429     name[2] = 'n';
430     name[3] = 'a';
431     name[4] = 'm';
432     name[5] = 'e';
433     name[6] = (CHAR) 0;
434 
435     password[0] = 'm';
436     password[1] = 'y';
437     password[2] = 'p';
438     password[3] = 'a';
439     password[4] = 's';
440     password[5] = 's';
441     password[6] = 'w';
442     password[7] = 'o';
443     password[8] = 'r';
444     password[9] = 'd';
445     password[10] = (CHAR) 0;
446 
447     return(NX_SUCCESS);
448 }
449 
450 
verify_login(CHAR * name,CHAR * password)451 static UINT verify_login(CHAR *name, CHAR *password)
452 {
453 
454 if ((name[0] == 'm') &&
455     (name[1] == 'y') &&
456     (name[2] == 'n') &&
457     (name[3] == 'a') &&
458     (name[4] == 'm') &&
459     (name[5] == 'e') &&
460     (name[6] == (CHAR) 0) &&
461     (password[0] == 'm') &&
462     (password[1] == 'y') &&
463     (password[2] == 'p') &&
464     (password[3] == 'a') &&
465     (password[4] == 's') &&
466     (password[5] == 's') &&
467     (password[6] == 'w') &&
468     (password[7] == 'o') &&
469     (password[8] == 'r') &&
470     (password[9] == 'd') &&
471     (password[10] == (CHAR) 0))
472         return(NX_SUCCESS);
473    else
474         return(NX_PPP_ERROR);
475 }
476 #else
477 
478 #ifdef CTEST
test_application_define(void * first_unused_memory)479 VOID test_application_define(void *first_unused_memory)
480 #else
481 void    netx_ppp_IPCP_nak_test_application_define(void *first_unused_memory)
482 #endif
483 {
484 
485     /* Print out test information banner.  */
486     printf("NetX Test:   PPP IPCP NAK Test.........................................N/A\n");
487 
488     test_control_return(3);
489 }
490 #endif
491