1 /* This is a small demo of NetX FTP on the high-performance NetX TCP/IP stack. This demo
2 relies on ThreadX, NetX, and FileX to show a simple file transfer from the client
3 and then back to the server. */
4
5
6
7 #include "tx_api.h"
8 #include "fx_api.h"
9 #include "nx_api.h"
10 #include "nxd_ftp_client.h"
11 #include "nxd_ftp_server.h"
12
13 #define DEMO_STACK_SIZE 4096
14 #define DEMO_DATA "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
15
16 #ifdef FEATURE_NX_IPV6
17 #define USE_IPV6
18 #endif /* FEATURE_NX_IPV6 */
19
20 /* Uncomment the following line to enable passive transfer mode. */
21 /*
22 #define PASSIVE_MODE
23 */
24
25 /* Uncomment the following line to enable block mode. */
26 /*
27 #define BLOCK_MODE
28 */
29
30
31 /* Define the ThreadX, NetX, and FileX object control blocks... */
32
33 TX_THREAD server_thread;
34 TX_THREAD client_thread;
35 NX_PACKET_POOL server_pool;
36 NX_IP server_ip;
37 NX_PACKET_POOL client_pool;
38 NX_IP client_ip;
39 FX_MEDIA ram_disk;
40
41
42 /* Define the NetX FTP object control blocks. */
43
44 NX_FTP_CLIENT ftp_client;
45 NX_FTP_SERVER ftp_server;
46
47
48 /* Define the counters used in the demo application... */
49
50 ULONG error_counter = 0;
51
52
53 /* Define the memory area for the FileX RAM disk. */
54
55 UCHAR ram_disk_memory[32000];
56 UCHAR ram_disk_sector_cache[512];
57
58
59 #define FTP_SERVER_ADDRESS IP_ADDRESS(1,2,3,4)
60 #define FTP_CLIENT_ADDRESS IP_ADDRESS(1,2,3,5)
61
62 extern UINT _fx_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
63 CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
64 ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
65 UINT heads, UINT sectors_per_track);
66
67 /* Define the FileX and NetX driver entry functions. */
68 VOID _fx_ram_driver(FX_MEDIA *media_ptr);
69
70 /* Replace the 'ram' driver with your own Ethernet driver. */
71 VOID _nx_ram_network_driver(NX_IP_DRIVER *driver_req_ptr);
72
73
74 void client_thread_entry(ULONG thread_input);
75 void thread_server_entry(ULONG thread_input);
76
77
78 #ifdef USE_IPV6
79 /* Define NetX Duo IP address for the NetX Duo FTP Server and Client. */
80 NXD_ADDRESS server_ip_address;
81 NXD_ADDRESS client_ip_address;
82 #endif
83
84
85 /* Define server login/logout functions. These are stubs for functions that would
86 validate a client login request. */
87
88 #ifdef USE_IPV6
89 UINT server_login6(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, NXD_ADDRESS *client_ipduo_address, UINT client_port, CHAR *name, CHAR *password, CHAR *extra_info);
90 UINT server_logout6(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, NXD_ADDRESS *client_ipduo_address, UINT client_port, CHAR *name, CHAR *password, CHAR *extra_info);
91 #else
92 UINT server_login(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, ULONG client_ip_address, UINT client_port, CHAR *name, CHAR *password, CHAR *extra_info);
93 UINT server_logout(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, ULONG client_ip_address, UINT client_port, CHAR *name, CHAR *password, CHAR *extra_info);
94 #endif
95
96
97 /* Define main entry point. */
98
main()99 int main()
100 {
101
102 /* Enter the ThreadX kernel. */
103 tx_kernel_enter();
104 return(0);
105 }
106
107
108 /* Define what the initial system looks like. */
109
tx_application_define(void * first_unused_memory)110 void tx_application_define(void *first_unused_memory)
111 {
112
113 UINT status;
114 UCHAR *pointer;
115
116 /* Initialize NetX. */
117 nx_system_initialize();
118
119 /* Initialize FileX. */
120 fx_system_initialize();
121
122 /* Setup the working pointer. */
123 pointer = (UCHAR *) first_unused_memory;
124
125 /* Create a helper thread for the server. */
126 tx_thread_create(&server_thread, "FTP Server thread", thread_server_entry, 0,
127 pointer, DEMO_STACK_SIZE,
128 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
129
130 pointer = pointer + DEMO_STACK_SIZE;
131
132 /* Create the packet pool for the FTP Server. */
133 status = nx_packet_pool_create(&server_pool, "NetX Server Packet Pool", 512, pointer, 8192);
134 pointer = pointer + 8192;
135
136 /* Check for errors. */
137 if (status)
138 error_counter++;
139
140 /* Create the IP instance for the FTP Server. */
141 status = nx_ip_create(&server_ip, "NetX Server IP Instance", FTP_SERVER_ADDRESS, 0xFFFFFF00UL,
142 &server_pool, _nx_ram_network_driver, pointer, 2048, 1);
143 pointer = pointer + 2048;
144
145 /* Check status. */
146 if (status != NX_SUCCESS)
147 {
148 error_counter++;
149 return;
150 }
151
152 #ifndef NX_DISABLE_IPV4
153 /* Enable ARP and supply ARP cache memory for server IP instance. */
154 nx_arp_enable(&server_ip, (void *) pointer, 1024);
155 pointer = pointer + 1024;
156 #endif /* NX_DISABLE_IPV4 */
157
158 /* Enable TCP. */
159 nx_tcp_enable(&server_ip);
160
161 #ifdef USE_IPV6
162
163 /* Next set the NetX Duo FTP Server and Client addresses. */
164 server_ip_address.nxd_ip_address.v6[3] = 0x105;
165 server_ip_address.nxd_ip_address.v6[2] = 0x0;
166 server_ip_address.nxd_ip_address.v6[1] = 0x0000f101;
167 server_ip_address.nxd_ip_address.v6[0] = 0x20010db8;
168 server_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
169
170 client_ip_address.nxd_ip_address.v6[3] = 0x101;
171 client_ip_address.nxd_ip_address.v6[2] = 0x0;
172 client_ip_address.nxd_ip_address.v6[1] = 0x0000f101;
173 client_ip_address.nxd_ip_address.v6[0] = 0x20010db8;
174 client_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
175
176 /* Create the FTP server. */
177 status = nxd_ftp_server_create(&ftp_server, "FTP Server Instance", &server_ip, &ram_disk, pointer, DEMO_STACK_SIZE, &server_pool,
178 server_login6, server_logout6);
179 #else
180 /* Create the FTP server. */
181 status = nx_ftp_server_create(&ftp_server, "FTP Server Instance", &server_ip, &ram_disk, pointer, DEMO_STACK_SIZE, &server_pool,
182 server_login, server_logout);
183 #endif
184 pointer = pointer + DEMO_STACK_SIZE;
185
186 /* Check status. */
187 if (status != NX_SUCCESS)
188 {
189 error_counter++;
190 return;
191 }
192
193 /* Now set up the FTP Client. */
194
195 /* Create the main FTP client thread. */
196 status = tx_thread_create(&client_thread, "FTP Client thread ", client_thread_entry, 0,
197 pointer, DEMO_STACK_SIZE,
198 6, 6, TX_NO_TIME_SLICE, TX_AUTO_START);
199 pointer = pointer + DEMO_STACK_SIZE ;
200
201 /* Check status. */
202 if (status != NX_SUCCESS)
203 {
204 error_counter++;
205 return;
206 }
207
208 /* Create a packet pool for the FTP client. */
209 status = nx_packet_pool_create(&client_pool, "NetX Client Packet Pool", 512, pointer, 8192);
210 pointer = pointer + 8192;
211
212 /* Create an IP instance for the FTP client. */
213 status = nx_ip_create(&client_ip, "NetX Client IP Instance", FTP_CLIENT_ADDRESS, 0xFFFFFF00UL,
214 &client_pool, _nx_ram_network_driver, pointer, 2048, 1);
215 pointer = pointer + 2048;
216
217 #ifndef NX_DISABLE_IPV4
218 /* Enable ARP and supply ARP cache memory for the FTP Client IP. */
219 nx_arp_enable(&client_ip, (void *) pointer, 1024);
220 pointer = pointer + 1024;
221 #endif /* NX_DISABLE_IPV4 */
222
223 /* Enable TCP for client IP instance. */
224 nx_tcp_enable(&client_ip);
225
226 return;
227
228 }
229
230 /* Define the FTP client thread. */
231
client_thread_entry(ULONG thread_input)232 void client_thread_entry(ULONG thread_input)
233 {
234
235 NX_PACKET *my_packet;
236 NX_PACKET *recv_packet_ptr;
237 UINT status;
238 ULONG file_size;
239
240 #ifdef USE_IPV6
241 UINT iface_index, address_index;
242 #endif
243
244 NX_PARAMETER_NOT_USED(thread_input);
245
246 /* Format the RAM disk - the memory for the RAM disk was defined above. */
247 status = _fx_media_format(&ram_disk,
248 _fx_ram_driver, /* Driver entry */
249 ram_disk_memory, /* RAM disk memory pointer */
250 ram_disk_sector_cache, /* Media buffer pointer */
251 sizeof(ram_disk_sector_cache), /* Media buffer size */
252 "MY_RAM_DISK", /* Volume Name */
253 1, /* Number of FATs */
254 32, /* Directory Entries */
255 0, /* Hidden sectors */
256 256, /* Total sectors */
257 128, /* Sector size */
258 1, /* Sectors per cluster */
259 1, /* Heads */
260 1); /* Sectors per track */
261
262 /* Check status. */
263 if (status != NX_SUCCESS)
264 {
265 error_counter++;
266 return;
267 }
268
269 /* Open the RAM disk. */
270 status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory, ram_disk_sector_cache, sizeof(ram_disk_sector_cache));
271
272 /* Check status. */
273 if (status != NX_SUCCESS)
274 {
275 error_counter++;
276 return;
277 }
278
279 /* Let the IP threads and driver initialize the system. */
280 tx_thread_sleep(NX_IP_PERIODIC_RATE);
281
282 #ifdef USE_IPV6
283
284 /* Here's where we make the FTP Client IPv6 enabled. */
285 status = nxd_ipv6_enable(&client_ip);
286
287 /* Check status. */
288 if (status != NX_SUCCESS)
289 {
290 error_counter++;
291 return;
292 }
293
294 status = nxd_icmp_enable(&client_ip);
295
296 /* Check status. */
297 if (status != NX_SUCCESS)
298 {
299 error_counter++;
300 return;
301 }
302
303 /* Set the Client link local and global addresses. */
304 iface_index = 0;
305
306 /* This assumes we are using the primary network interface (index 0). */
307 status = nxd_ipv6_address_set(&client_ip, iface_index, NX_NULL, 10, &address_index);
308
309 /* Check for link local address set error. */
310 if (status != NX_SUCCESS)
311 {
312
313 error_counter++;
314 return;
315 }
316
317 /* Set the host global IP address. We are assuming a 64
318 bit prefix here but this can be any value (< 128). */
319 status = nxd_ipv6_address_set(&client_ip, iface_index, &client_ip_address, 64, &address_index);
320
321 /* Check for global address set error. */
322 if (status != NX_SUCCESS)
323 {
324
325 error_counter++;
326 return;
327 }
328
329 /* Let NetX Duo validate the addresses. */
330 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
331
332 #endif /* USE_IPV6 */
333
334 /* Create an FTP client. */
335 status = nx_ftp_client_create(&ftp_client, "FTP Client", &client_ip, 2000, &client_pool);
336
337 /* Check status. */
338 if (status != NX_SUCCESS)
339 {
340
341 error_counter++;
342 return;
343 }
344
345 printf("Created the FTP Client\n");
346
347 #ifdef USE_IPV6
348
349 do
350 {
351
352 /* Now connect with the NetX Duo FTP (IPv6) server. */
353 status = nxd_ftp_client_connect(&ftp_client, &server_ip_address, "name", "password", NX_IP_PERIODIC_RATE);
354 } while (status != NX_SUCCESS);
355
356 #else
357
358 /* Now connect with the NetX FTP (IPv4) server. */
359 status = nx_ftp_client_connect(&ftp_client, FTP_SERVER_ADDRESS, "name", "password", NX_IP_PERIODIC_RATE);
360
361 #endif /* USE_IPV6 */
362
363 /* Check status. */
364 if (status != NX_SUCCESS)
365 {
366 error_counter++;
367 return;
368 }
369
370 printf("Connected to the FTP Server\n");
371
372 #ifdef PASSIVE_MODE
373 /* Enable passive mode. */
374 status = nx_ftp_client_passive_mode_set(&ftp_client, NX_TRUE);
375 if (status != NX_SUCCESS)
376 {
377 error_counter++;
378 return;
379 }
380
381 printf("Enabled FTP Client Passive Mode\n");
382 #endif /* PASSIVE_MODE */
383
384 #ifdef BLOCK_MODE
385 /* Set block mode. */
386 status = nx_ftp_client_transfer_mode_set(&ftp_client, NX_FTP_TRANSFER_MODE_BLOCK);
387 if (status != NX_SUCCESS)
388 {
389
390 error_counter++;
391 return;
392 }
393
394 printf("Enabled FTP Client Block Mode\n");
395 #endif /* BLOCK_MODE */
396
397 /* Open a FTP file for writing. */
398 status = nx_ftp_client_file_open(&ftp_client, "test.txt", NX_FTP_OPEN_FOR_WRITE, NX_IP_PERIODIC_RATE);
399
400 /* Check status. */
401 if (status != NX_SUCCESS)
402 {
403 error_counter++;
404 return;
405 }
406
407 printf("Opened the FTP client test.txt file\n");
408
409 #ifdef BLOCK_MODE
410 /* Set the file size in block mode. */
411 status = nx_ftp_client_file_size_set(&ftp_client, 28);
412
413 /* Check status. */
414 if (status != NX_SUCCESS)
415 {
416 error_counter++;
417 }
418 else
419 printf("Set the File Size in Block Mode\n");
420 #endif /* BLOCK_MODE */
421
422 /* Allocate a FTP packet. */
423 status = nx_packet_allocate(&client_pool, &my_packet, NX_TCP_PACKET, NX_IP_PERIODIC_RATE);
424
425 /* Check status. */
426 if (status != NX_SUCCESS)
427 {
428 error_counter++;
429 return;
430 }
431
432 /* Write ABCs into the packet payload! */
433 memcpy(my_packet -> nx_packet_prepend_ptr, DEMO_DATA, sizeof(DEMO_DATA)); /* Use case of memcpy is verified. */
434
435 /* Adjust the write pointer. */
436 my_packet -> nx_packet_length = sizeof(DEMO_DATA);
437 my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + sizeof(DEMO_DATA);
438
439 /* Write the packet to the file test.txt. */
440 status = nx_ftp_client_file_write(&ftp_client, my_packet, NX_IP_PERIODIC_RATE);
441
442 /* Check status. */
443 if (status != NX_SUCCESS)
444 {
445 error_counter++;
446 nx_packet_release(my_packet);
447 return;
448 }
449 else
450 printf("Wrote to the FTP client test.txt file\n");
451
452
453 /* Close the file. */
454 status = nx_ftp_client_file_close(&ftp_client, NX_IP_PERIODIC_RATE);
455
456 /* Check status. */
457 if (status != NX_SUCCESS)
458 {
459 error_counter++;
460 return;
461 }
462 else
463 printf("Closed the FTP client test.txt file\n");
464
465
466 /* Now open the same file for reading. */
467 status = nx_ftp_client_file_open(&ftp_client, "test.txt", NX_FTP_OPEN_FOR_READ, NX_IP_PERIODIC_RATE);
468
469 /* Check status. */
470 if (status != NX_SUCCESS)
471 {
472 error_counter++;
473 return;
474 }
475 else
476 printf("Reopened the FTP client test.txt file\n");
477
478 /* Loop to read the data. */
479 file_size = 0;
480 do
481 {
482
483 /* Read the file. */
484 status = nx_ftp_client_file_read(&ftp_client, &my_packet, 100);
485
486 /* Check status. */
487 if (status == NX_SUCCESS)
488 {
489 file_size += my_packet -> nx_packet_length;
490 nx_packet_release(my_packet);
491 }
492 } while(status == NX_SUCCESS);
493
494 /* Check file size. */
495 if (file_size != 28)
496 {
497 error_counter++;
498 return;
499 }
500 else
501 {
502 printf("Reread the FTP client test.txt file\n");
503 }
504
505 /* Close this file. */
506 status = nx_ftp_client_file_close(&ftp_client, NX_IP_PERIODIC_RATE);
507
508 /* Check status. */
509 if (status != NX_SUCCESS)
510 {
511 error_counter++;
512 return;
513 }
514 else
515 printf("Reclosed the FTP client test.txt file\n");
516
517 /* Get directory listing (NLST). */
518 status = nx_ftp_client_directory_listing_get(&ftp_client, "", &my_packet, 200);
519 if (status != NX_SUCCESS)
520 {
521 error_counter++;
522 return;
523 }
524 else
525 {
526 nx_packet_release(my_packet);
527 }
528
529 do
530 {
531 /* Receive the next data packet. */
532 status = nx_ftp_client_directory_listing_continue(&ftp_client, &recv_packet_ptr, 200);
533 if (status == NX_SUCCESS)
534 {
535 nx_packet_release(recv_packet_ptr);
536 }
537
538 /* Check if this is the end of the download. */
539 if (status == NX_FTP_END_OF_LISTING)
540 break;
541
542 } while (status == NX_SUCCESS);
543
544 printf("Got the directory list test.txt\n");
545
546 /* Disconnect from the server. */
547 status = nx_ftp_client_disconnect(&ftp_client, NX_IP_PERIODIC_RATE);
548
549 /* Check status. */
550 if (status != NX_SUCCESS)
551 {
552 error_counter++;
553 return;
554 }
555
556 /* Delete the FTP client. */
557 status = nx_ftp_client_delete(&ftp_client);
558
559 /* Check status. */
560 if (status != NX_SUCCESS)
561 {
562 error_counter++;
563 return;
564 }
565 }
566
567
568 /* Define the helper FTP server thread. */
thread_server_entry(ULONG thread_input)569 void thread_server_entry(ULONG thread_input)
570 {
571
572 UINT status;
573 #ifdef USE_IPV6
574 UINT iface_index, address_index;
575 #endif
576
577 NX_PARAMETER_NOT_USED(thread_input);
578
579 /* Wait till the IP thread and driver have initialized the system. */
580 tx_thread_sleep(NX_IP_PERIODIC_RATE);
581
582 #ifdef USE_IPV6
583
584 /* Here's where we make the FTP server IPv6 enabled. */
585 status = nxd_ipv6_enable(&server_ip);
586
587 /* Check status. */
588 if (status != NX_SUCCESS)
589 {
590
591 error_counter++;
592 return;
593 }
594
595 status = nxd_icmp_enable(&server_ip);
596
597 /* Check status. */
598 if (status != NX_SUCCESS)
599 {
600
601 error_counter++;
602 return;
603 }
604
605 /* Set the link local address with the host MAC address. */
606 iface_index = 0;
607
608 /* This assumes we are using the primary network interface (index 0). */
609 status = nxd_ipv6_address_set(&server_ip, iface_index, NX_NULL, 10, &address_index);
610
611 /* Check for link local address set error. */
612 if (status)
613 {
614
615 error_counter++;
616 return;
617 }
618
619 /* Set the host global IP address. We are assuming a 64
620 bit prefix here but this can be any value (< 128). */
621 status = nxd_ipv6_address_set(&server_ip, iface_index, &server_ip_address, 64, &address_index);
622
623 /* Check for global address set error. */
624 if (status)
625 {
626
627 error_counter++;
628 return;
629 }
630
631 /* Wait while NetX Duo validates the link local and global address. */
632 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
633
634 #endif /* USE_IPV6 */
635
636 /* OK to start the FTP Server. */
637 status = nx_ftp_server_start(&ftp_server);
638
639 if (status != NX_SUCCESS)
640 error_counter++;
641
642 printf("Server started!\n");
643
644 /* FTP server ready to take requests! */
645
646 /* Let the IP threads execute. */
647 tx_thread_relinquish();
648
649 return;
650 }
651
652
653 #ifdef USE_IPV6
server_login6(struct NX_FTP_SERVER_STRUCT * ftp_server_ptr,NXD_ADDRESS * client_ipduo_address,UINT client_port,CHAR * name,CHAR * password,CHAR * extra_info)654 UINT server_login6(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, NXD_ADDRESS *client_ipduo_address, UINT client_port,
655 CHAR *name, CHAR *password, CHAR *extra_info)
656 {
657 NX_PARAMETER_NOT_USED(ftp_server_ptr);
658 NX_PARAMETER_NOT_USED(client_ipduo_address);
659 NX_PARAMETER_NOT_USED(client_port);
660 NX_PARAMETER_NOT_USED(name);
661 NX_PARAMETER_NOT_USED(password);
662 NX_PARAMETER_NOT_USED(extra_info);
663
664 printf("Logged in6!\n");
665
666 /* Always return success. */
667 return(NX_SUCCESS);
668 }
669
server_logout6(struct NX_FTP_SERVER_STRUCT * ftp_server_ptr,NXD_ADDRESS * client_ipduo_address,UINT client_port,CHAR * name,CHAR * password,CHAR * extra_info)670 UINT server_logout6(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, NXD_ADDRESS *client_ipduo_address, UINT client_port,
671 CHAR *name, CHAR *password, CHAR *extra_info)
672 {
673 NX_PARAMETER_NOT_USED(ftp_server_ptr);
674 NX_PARAMETER_NOT_USED(client_ipduo_address);
675 NX_PARAMETER_NOT_USED(client_port);
676 NX_PARAMETER_NOT_USED(name);
677 NX_PARAMETER_NOT_USED(password);
678 NX_PARAMETER_NOT_USED(extra_info);
679
680 printf("Logged out6!\n");
681
682 /* Always return success. */
683 return(NX_SUCCESS);
684 }
685 #else
server_login(struct NX_FTP_SERVER_STRUCT * ftp_server_ptr,ULONG client_ip_address,UINT client_port,CHAR * name,CHAR * password,CHAR * extra_info)686 UINT server_login(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, ULONG client_ip_address, UINT client_port, CHAR *name, CHAR *password, CHAR *extra_info)
687 {
688 NX_PARAMETER_NOT_USED(ftp_server_ptr);
689 NX_PARAMETER_NOT_USED(client_ip_address);
690 NX_PARAMETER_NOT_USED(client_port);
691 NX_PARAMETER_NOT_USED(name);
692 NX_PARAMETER_NOT_USED(password);
693 NX_PARAMETER_NOT_USED(extra_info);
694
695 printf("Logged in!\n");
696 /* Always return success. */
697 return(NX_SUCCESS);
698 }
699
server_logout(struct NX_FTP_SERVER_STRUCT * ftp_server_ptr,ULONG client_ip_address,UINT client_port,CHAR * name,CHAR * password,CHAR * extra_info)700 UINT server_logout(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, ULONG client_ip_address, UINT client_port, CHAR *name, CHAR *password, CHAR *extra_info)
701 {
702 NX_PARAMETER_NOT_USED(ftp_server_ptr);
703 NX_PARAMETER_NOT_USED(client_ip_address);
704 NX_PARAMETER_NOT_USED(client_port);
705 NX_PARAMETER_NOT_USED(name);
706 NX_PARAMETER_NOT_USED(password);
707 NX_PARAMETER_NOT_USED(extra_info);
708
709 printf("Logged out!\n");
710
711 /* Always return success. */
712 return(NX_SUCCESS);
713 }
714 #endif /* USE_IPV6 */
715