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