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