1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Duo Component */
16 /** */
17 /** File Transfer Protocol (FTP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_FTP_SOURCE_CODE
23
24
25 /* Force error checking to be disabled in this module */
26
27 #ifndef NX_DISABLE_ERROR_CHECKING
28 #define NX_DISABLE_ERROR_CHECKING
29 #endif
30
31 /* If FileX is not used in your application, define this option. Then define the
32 services declared in filex_stub.h elsewhere.
33 #define NX_FTP_NO_FILEX
34 */
35
36 /* Include necessary system files. */
37
38 #include "nx_api.h"
39 #include "nx_ip.h"
40 #ifdef FEATURE_NX_IPV6
41 #include "nx_ipv6.h"
42 #endif /* FEATURE_NX_IPV6 */
43 #include "nxd_ftp_client.h"
44 #include "stdio.h"
45 #include "string.h"
46
47
48
49 /* Bring in externs for caller checking code. */
50
51 NX_CALLER_CHECKING_EXTERNS
52
53
54 /**************************************************************************/
55 /* */
56 /* FUNCTION RELEASE */
57 /* */
58 /* _nxe_ftp_client_connect PORTABLE C */
59 /* 6.1 */
60 /* AUTHOR */
61 /* */
62 /* Yuxin Zhou, Microsoft Corporation */
63 /* */
64 /* DESCRIPTION */
65 /* */
66 /* This function checks for errors in the FTP client connect call. */
67 /* */
68 /* Note: The string lengths of username and password are limited by */
69 /* the packet payload size. */
70 /* */
71 /* INPUT */
72 /* */
73 /* ftp_client_ptr Pointer to FTP client */
74 /* server_ip FTP server IPv4 address */
75 /* username Pointer to login username */
76 /* password Pointer to login password */
77 /* wait_option Specifies how long to wait */
78 /* */
79 /* OUTPUT */
80 /* */
81 /* status Completion status */
82 /* */
83 /* CALLS */
84 /* */
85 /* _nxe_ftp_client_connect Actual client connect call */
86 /* */
87 /* CALLED BY */
88 /* */
89 /* Application Code */
90 /* */
91 /* RELEASE HISTORY */
92 /* */
93 /* DATE NAME DESCRIPTION */
94 /* */
95 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
96 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
97 /* resulting in version 6.1 */
98 /* */
99 /**************************************************************************/
_nxe_ftp_client_connect(NX_FTP_CLIENT * ftp_client_ptr,ULONG server_ip,CHAR * username,CHAR * password,ULONG wait_option)100 UINT _nxe_ftp_client_connect(NX_FTP_CLIENT *ftp_client_ptr, ULONG server_ip, CHAR *username,
101 CHAR *password, ULONG wait_option)
102 {
103
104 #ifndef NX_DISABLE_IPV4
105 UINT status;
106
107
108 /* Check for invalid input pointers. */
109 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
110 return(NX_PTR_ERROR);
111
112 /* Check for an invalid server IP address. */
113 if (server_ip == 0)
114 return(NX_IP_ADDRESS_ERROR);
115
116 /* Check for appropriate caller. */
117 NX_THREADS_ONLY_CALLER_CHECKING
118
119 /* Call actual client connect function. */
120 status = _nx_ftp_client_connect(ftp_client_ptr, server_ip, username, password, wait_option);
121
122 /* Return completion status. */
123 return(status);
124 #else
125 NX_PARAMETER_NOT_USED(ftp_client_ptr);
126 NX_PARAMETER_NOT_USED(server_ip);
127 NX_PARAMETER_NOT_USED(username);
128 NX_PARAMETER_NOT_USED(password);
129 NX_PARAMETER_NOT_USED(wait_option);
130
131 return(NX_NOT_SUPPORTED);
132 #endif /* NX_DISABLE_IPV4 */
133 }
134
135
136 /**************************************************************************/
137 /* */
138 /* FUNCTION RELEASE */
139 /* */
140 /* _nx_ftp_client_connect PORTABLE C */
141 /* 6.1 */
142 /* AUTHOR */
143 /* */
144 /* Yuxin Zhou, Microsoft Corporation */
145 /* */
146 /* DESCRIPTION */
147 /* */
148 /* This function connects a previously created FTP instance with the */
149 /* FTP server at the specified IP address. */
150 /* */
151 /* Note: The string lengths of username and password are limited by */
152 /* the packet payload size. */
153 /* */
154 /* INPUT */
155 /* */
156 /* ftp_client_ptr Pointer to FTP client */
157 /* server_ip FTP server IPv4 address */
158 /* username Pointer to login username */
159 /* password Pointer to login password */
160 /* wait_option Specifies how long to wait */
161 /* */
162 /* OUTPUT */
163 /* */
164 /* status Completion status */
165 /* */
166 /* CALLS */
167 /* */
168 /* _nx_ftp_client_connect_internal Connect to FTP server using */
169 /* IP address */
170 /* */
171 /* CALLED BY */
172 /* */
173 /* Application Code */
174 /* */
175 /* RELEASE HISTORY */
176 /* */
177 /* DATE NAME DESCRIPTION */
178 /* */
179 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
180 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
181 /* resulting in version 6.1 */
182 /* */
183 /**************************************************************************/
_nx_ftp_client_connect(NX_FTP_CLIENT * ftp_client_ptr,ULONG server_ip,CHAR * username,CHAR * password,ULONG wait_option)184 UINT _nx_ftp_client_connect(NX_FTP_CLIENT *ftp_client_ptr, ULONG server_ip, CHAR *username,
185 CHAR *password, ULONG wait_option)
186 {
187
188 #ifndef NX_DISABLE_IPV4
189 NXD_ADDRESS server_ipduo;
190
191 /* Construct an IP address structure, and fill in IPv4 address information. */
192 server_ipduo.nxd_ip_version = NX_IP_VERSION_V4;
193 server_ipduo.nxd_ip_address.v4 = server_ip;
194
195
196 /* Invoke the real connection call. */
197 return (_nx_ftp_client_connect_internal(ftp_client_ptr, &server_ipduo, username, password, wait_option));
198 #else
199 NX_PARAMETER_NOT_USED(ftp_client_ptr);
200 NX_PARAMETER_NOT_USED(server_ip);
201 NX_PARAMETER_NOT_USED(username);
202 NX_PARAMETER_NOT_USED(password);
203 NX_PARAMETER_NOT_USED(wait_option);
204
205 return(NX_NOT_SUPPORTED);
206 #endif /* NX_DISABLE_IPV4 */
207 }
208
209
210 /**************************************************************************/
211 /* */
212 /* FUNCTION RELEASE */
213 /* */
214 /* _nxde_ftp_client_connect PORTABLE C */
215 /* 6.1 */
216 /* AUTHOR */
217 /* */
218 /* Yuxin Zhou, Microsoft Corporation */
219 /* */
220 /* DESCRIPTION */
221 /* */
222 /* This function checks for errors in the FTP client connect call. */
223 /* */
224 /* Note: The string lengths of username and password are limited by */
225 /* the packet payload size. */
226 /* */
227 /* INPUT */
228 /* */
229 /* ftp_client_ptr Pointer to FTP client */
230 /* server_ip FTP server IP address */
231 /* username Pointer to login username */
232 /* password Pointer to login password */
233 /* wait_option Specifies how long to wait */
234 /* */
235 /* OUTPUT */
236 /* */
237 /* status Completion status */
238 /* */
239 /* CALLS */
240 /* */
241 /* _nxe_ftp_client_connect Actual client connect call */
242 /* */
243 /* CALLED BY */
244 /* */
245 /* Application Code */
246 /* */
247 /* RELEASE HISTORY */
248 /* */
249 /* DATE NAME DESCRIPTION */
250 /* */
251 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
252 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
253 /* resulting in version 6.1 */
254 /* */
255 /**************************************************************************/
_nxde_ftp_client_connect(NX_FTP_CLIENT * ftp_client_ptr,NXD_ADDRESS * server_ipduo,CHAR * username,CHAR * password,ULONG wait_option)256 UINT _nxde_ftp_client_connect(NX_FTP_CLIENT *ftp_client_ptr, NXD_ADDRESS *server_ipduo, CHAR *username,
257 CHAR *password, ULONG wait_option)
258 {
259
260 UINT status;
261
262
263 /* Check for invalid input pointers. */
264 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
265 return(NX_PTR_ERROR);
266
267 /* Check for an invalid server IP address. */
268 if (!server_ipduo)
269 return(NX_IP_ADDRESS_ERROR);
270
271 /* Check for appropriate caller. */
272 NX_THREADS_ONLY_CALLER_CHECKING
273
274 /* Call actual client connect function. */
275 status = _nxd_ftp_client_connect(ftp_client_ptr, server_ipduo, username, password, wait_option);
276
277 return status;
278 }
279
280
281 /**************************************************************************/
282 /* */
283 /* FUNCTION RELEASE */
284 /* */
285 /* _nxd_ftp_client_connect PORTABLE C */
286 /* 6.1 */
287 /* AUTHOR */
288 /* */
289 /* Yuxin Zhou, Microsoft Corporation */
290 /* */
291 /* DESCRIPTION */
292 /* */
293 /* This function connects a previously created FTP instance with the */
294 /* FTP server at the specified IP address. */
295 /* */
296 /* Note: The string lengths of username and password are limited by */
297 /* the packet payload size. */
298 /* */
299 /* INPUT */
300 /* */
301 /* ftp_client_ptr Pointer to FTP client */
302 /* server_ip FTP server IP duo address */
303 /* username Pointer to login username */
304 /* password Pointer to login password */
305 /* wait_option Specifies how long to wait */
306 /* */
307 /* OUTPUT */
308 /* */
309 /* status Completion status */
310 /* */
311 /* CALLS */
312 /* */
313 /* _nx_ftp_client_connect_internal Acutal connect service */
314 /* */
315 /* CALLED BY */
316 /* */
317 /* Application Code */
318 /* */
319 /* RELEASE HISTORY */
320 /* */
321 /* DATE NAME DESCRIPTION */
322 /* */
323 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
324 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
325 /* resulting in version 6.1 */
326 /* */
327 /**************************************************************************/
_nxd_ftp_client_connect(NX_FTP_CLIENT * ftp_client_ptr,NXD_ADDRESS * server_ipduo,CHAR * username,CHAR * password,ULONG wait_option)328 UINT _nxd_ftp_client_connect(NX_FTP_CLIENT *ftp_client_ptr, NXD_ADDRESS *server_ipduo, CHAR *username,
329 CHAR *password, ULONG wait_option)
330 {
331
332 /* Invoke the real connection call. */
333 return (_nx_ftp_client_connect_internal(ftp_client_ptr, server_ipduo, username, password, wait_option));
334 }
335
336
337 /**************************************************************************/
338 /* */
339 /* FUNCTION RELEASE */
340 /* */
341 /* _nx_ftp_client_connect_internal PORTABLE C */
342 /* 6.3.0 */
343 /* AUTHOR */
344 /* */
345 /* Yuxin Zhou, Microsoft Corporation */
346 /* */
347 /* DESCRIPTION */
348 /* */
349 /* This function connects a previously created FTP instance with the */
350 /* FTP server at the specified IP address. */
351 /* */
352 /* INPUT */
353 /* */
354 /* ftp_client_ptr Pointer to FTP client */
355 /* server_ip FTP server IP address */
356 /* username Pointer to login username */
357 /* password Pointer to login password */
358 /* wait_option Specifies how long to wait */
359 /* */
360 /* OUTPUT */
361 /* */
362 /* status Completion status */
363 /* */
364 /* CALLS */
365 /* */
366 /* nx_tcp_client_socket_bind Bind client socket to port */
367 /* nxd_tcp_client_socket_connect Connect to FTP server */
368 /* nx_tcp_client_socket_unbind Unbind client socket from port*/
369 /* nx_packet_release Release packet */
370 /* nx_tcp_socket_receive Receive server response */
371 /* nx_tcp_socket_send Send request to server */
372 /* */
373 /* CALLED BY */
374 /* */
375 /* Application Code */
376 /* */
377 /* RELEASE HISTORY */
378 /* */
379 /* DATE NAME DESCRIPTION */
380 /* */
381 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
382 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
383 /* resulting in version 6.1 */
384 /* 10-31-2023 Tiejun Zhou Modified comment(s), */
385 /* corrected length of buffer, */
386 /* resulting in version 6.3.0 */
387 /* */
388 /**************************************************************************/
_nx_ftp_client_connect_internal(NX_FTP_CLIENT * ftp_client_ptr,NXD_ADDRESS * server_ip,CHAR * username,CHAR * password,ULONG wait_option)389 UINT _nx_ftp_client_connect_internal(NX_FTP_CLIENT *ftp_client_ptr, NXD_ADDRESS *server_ip, CHAR *username,
390 CHAR *password, ULONG wait_option)
391 {
392
393 NX_PACKET *packet_ptr;
394 UCHAR *buffer_ptr;
395 UINT length;
396 UINT i;
397 UINT status;
398
399
400 /* Determine if the client is still in a not connected state. */
401 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_NOT_CONNECTED)
402 {
403
404 /* Already connected, return an error. */
405 return(NX_FTP_NOT_DISCONNECTED);
406 }
407
408 /* Bind the client control socket. */
409 status = nx_tcp_client_socket_bind(&(ftp_client_ptr -> nx_ftp_client_control_socket), NX_FTP_CLIENT_SOURCE_PORT, wait_option);
410
411 /* Check for an error. */
412 if ((status != NX_SUCCESS) && (status != NX_ALREADY_BOUND))
413 {
414
415 /* Unable to bind socket to port. */
416 return(status);
417 }
418
419 /* Connect the socket to the FTP server. */
420 status = nxd_tcp_client_socket_connect(&(ftp_client_ptr -> nx_ftp_client_control_socket), server_ip, NX_FTP_SERVER_CONTROL_PORT, wait_option);
421
422
423 /* Check for an error. */
424 if (status != NX_SUCCESS)
425 {
426
427 /* Unbind the socket. */
428 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
429
430 /* Unable to connect socket to server FTP control port. */
431 return(status);
432 }
433
434 /* Now wait for the "220 " response from the FTP server to indicate the connection has been
435 established. */
436 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
437
438 /* Check to see if no packet was received. */
439 if (status)
440 {
441
442 /* Close the socket. */
443 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
444
445 /* Unbind the socket. */
446 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
447
448 /* Unable to connect socket to server FTP control port. */
449 return(status);
450 }
451
452 #ifndef NX_DISABLE_PACKET_CHAIN
453 if (packet_ptr -> nx_packet_next)
454 {
455
456 /* Release the packet. */
457 nx_packet_release(packet_ptr);
458
459 /* Close the socket. */
460 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
461
462 /* Unbind the socket. */
463 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
464
465 /* Return. */
466 return(NX_INVALID_PACKET);
467 }
468 #endif /* NX_DISABLE_PACKET_CHAIN */
469
470 /* We have a packet, setup pointer to the buffer area. */
471 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
472 length = packet_ptr -> nx_packet_length;
473
474 /* Check for 220 message. */
475 if ((length < 3) || (buffer_ptr[0] != '2') || (buffer_ptr[1] != '2'))
476 {
477
478 /* Close the socket. */
479 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
480
481 /* Release the packet. */
482 nx_packet_release(packet_ptr);
483
484 /* Unbind the socket. */
485 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
486
487 /* Unable to connect socket to server FTP control port. */
488 return(NX_FTP_EXPECTED_22X_CODE);
489 }
490
491 memset(buffer_ptr, 0, length);
492
493 /* Check if out of boundary. */
494 if (((!username) && ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 11)) ||
495 ((username) && ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 7)))
496 {
497
498 /* Release the packet. */
499 nx_packet_release(packet_ptr);
500
501 /* Close the socket. */
502 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
503
504 /* Unbind the socket. */
505 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
506
507 /* Set the error status. */
508 return(NX_FTP_FAILED);
509 }
510
511 /* Now build the user name message. */
512 buffer_ptr[0] = 'U';
513 buffer_ptr[1] = 'S';
514 buffer_ptr[2] = 'E';
515 buffer_ptr[3] = 'R';
516 buffer_ptr[4] = ' ';
517
518 /* Determine if a user name was supplied. */
519 if (username == NX_NULL)
520 {
521
522 /* No username specified, use "USER". */
523 buffer_ptr[5] = 'U';
524 buffer_ptr[6] = 'S';
525 buffer_ptr[7] = 'E';
526 buffer_ptr[8] = 'R';
527 buffer_ptr[9] = 13;
528 buffer_ptr[10]= 10;
529
530 /* Set the length of the packet. */
531 packet_ptr -> nx_packet_length = 11;
532 }
533 else
534 {
535
536 /* A username was supplied, copy it into the buffer. */
537 for(i = 0; username[i]; i++)
538 {
539
540 /* Check if out of boundary. */
541 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
542 {
543
544 /* Release the packet. */
545 nx_packet_release(packet_ptr);
546
547 /* Close the socket. */
548 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
549
550 /* Unbind the socket. */
551 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
552
553 /* Set the error status. */
554 return(NX_FTP_FAILED);
555 }
556
557 /* Copy byte of the username. */
558 buffer_ptr[5+i] = (UCHAR)username[i];
559 }
560
561 /* Now insert the CR/LF. */
562 buffer_ptr[5+i] = 13;
563 buffer_ptr[5+i+1] = 10;
564
565 /* Setup the length of the packet. */
566 packet_ptr -> nx_packet_length = i + 7;
567 }
568
569 /* Setup the packet append pointer. */
570 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
571
572 /* Send the username to the FTP server. */
573 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
574
575 /* Check for unsuccessful send. */
576 if (status)
577 {
578
579 /* Release the packet. */
580 nx_packet_release(packet_ptr);
581
582 /* Close the socket. */
583 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
584
585 /* Unbind the socket. */
586 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
587
588 /* Unable to connect socket to server FTP control port. */
589 return(status);
590 }
591
592 /* There may be multiple 220 responses from FTP server after establishing connection.
593 Flush mutiple 220 respones and wait for 331 response from the FTP server. */
594 while(1)
595 {
596
597 /* Wait for response from the FTP server. */
598 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
599
600 /* Determine if a packet was not received. */
601 if (status)
602 {
603
604 /* Close the socket. */
605 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
606
607 /* Unbind the socket. */
608 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
609
610 /* Unable to connect socket to server FTP control port. */
611 return(status);
612 }
613
614 #ifndef NX_DISABLE_PACKET_CHAIN
615 if (packet_ptr -> nx_packet_next)
616 {
617
618 /* Release the packet. */
619 nx_packet_release(packet_ptr);
620
621 /* Close the socket. */
622 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
623
624 /* Unbind the socket. */
625 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
626
627 /* Return. */
628 return(NX_INVALID_PACKET);
629 }
630 #endif /* NX_DISABLE_PACKET_CHAIN */
631
632 /* We have a packet, setup pointer to the buffer area. */
633 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
634 length = packet_ptr -> nx_packet_length;
635
636 /* Check for 220 message. */
637 if ((packet_ptr -> nx_packet_length >= 3) && (buffer_ptr[0] == '2') && (buffer_ptr[1] == '2'))
638 {
639
640 /* Release the packet. */
641 nx_packet_release(packet_ptr);
642 continue;
643 }
644
645 /* Check to make sure the response is proper. */
646
647 /* Check for 331 message. */
648 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '3') || (buffer_ptr[1] != '3'))
649 {
650
651 /* Release the packet. */
652 nx_packet_release(packet_ptr);
653
654 /* Close the socket. */
655 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
656
657 /* Unbind the socket. */
658 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
659
660 /* Unable to connect socket to server FTP control port. */
661 return(NX_FTP_EXPECTED_33X_CODE);
662 }
663 else
664 {
665 break;
666 }
667 }
668
669 memset(buffer_ptr, 0, length);
670
671 /* Check if out of boundary. */
672 if (((!password) && ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 11)) ||
673 ((password) && ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 7)))
674 {
675
676 /* Release the packet. */
677 nx_packet_release(packet_ptr);
678
679 /* Close the socket. */
680 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
681
682 /* Unbind the socket. */
683 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
684
685 /* Set the error status. */
686 return(NX_FTP_FAILED);
687 }
688
689 /* Now build the password message. */
690 buffer_ptr[0] = 'P';
691 buffer_ptr[1] = 'A';
692 buffer_ptr[2] = 'S';
693 buffer_ptr[3] = 'S';
694 buffer_ptr[4] = ' ';
695
696 /* Determine if a password was specified. */
697 if (password == NX_NULL)
698 {
699
700 /* No password was specified, use "PASS". */
701 buffer_ptr[5] = 'P';
702 buffer_ptr[6] = 'A';
703 buffer_ptr[7] = 'S';
704 buffer_ptr[8] = 'S';
705 buffer_ptr[9] = 13;
706 buffer_ptr[10]= 10;
707
708 /* Setup the packet length. */
709 packet_ptr -> nx_packet_length = 11;
710 }
711 else
712 {
713
714 /* Password was specified, copy it into the buffer. */
715 for(i = 0; password[i]; i++)
716 {
717
718 /* Check if out of boundary. */
719 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
720 {
721
722 /* Release the packet. */
723 nx_packet_release(packet_ptr);
724
725 /* Close the socket. */
726 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
727
728 /* Unbind the socket. */
729 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
730
731 /* Set the error status. */
732 return(NX_FTP_FAILED);
733 }
734
735 /* Copy byte of password. */
736 buffer_ptr[5+i] = (UCHAR)password[i];
737 }
738
739 /* Now insert the CR/LF. */
740 buffer_ptr[5+i] = 13;
741 buffer_ptr[5+i+1] = 10;
742
743 /* Setup the length of the packet. */
744 packet_ptr -> nx_packet_length = i + 7;
745 }
746
747 /* Setup the packet append pointer. */
748 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
749
750 /* Send the password to the FTP server. */
751 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
752
753 /* Check for successful send. */
754 if (status)
755 {
756
757 /* Release the packet. */
758 nx_packet_release(packet_ptr);
759
760 /* Close the socket. */
761 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
762
763 /* Unbind the socket. */
764 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
765
766 /* Unable to connect socket to server FTP control port. */
767 return(status);
768 }
769
770 /* Wait for response from the FTP server. */
771 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
772
773 /* Determine if a packet was not received. */
774 if (status)
775 {
776
777 /* Close the socket. */
778 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
779
780 /* Unbind the socket. */
781 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
782
783 /* Unable to connect socket to server FTP control port. */
784 return(status);
785 }
786
787 /* We have a packet, setup pointer to the buffer area. */
788 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
789
790 /* Check for 230 message, signaling successful login. */
791 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2') || (buffer_ptr[1] != '3'))
792 {
793
794 /* Release the packet. */
795 nx_packet_release(packet_ptr);
796
797 /* Close the socket. */
798 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
799
800 /* Unbind the socket. */
801 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
802
803 /* Unable to connect socket to server FTP control port. */
804 return(NX_FTP_EXPECTED_23X_CODE);
805 }
806
807 /* Release the packet. */
808 nx_packet_release(packet_ptr);
809
810 /* If we get here, we have a successful connect with the FTP server. */
811 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_CONNECTED;
812
813 ftp_client_ptr -> nx_ftp_client_data_port = ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_port;
814
815 /* Return success to caller. */
816 return(NX_SUCCESS);
817 }
818
819
820 /**************************************************************************/
821 /* */
822 /* FUNCTION RELEASE */
823 /* */
824 /* _nxe_ftp_client_create PORTABLE C */
825 /* 6.1 */
826 /* AUTHOR */
827 /* */
828 /* Yuxin Zhou, Microsoft Corporation */
829 /* */
830 /* DESCRIPTION */
831 /* */
832 /* This function checks for errors in the FTP client create call. */
833 /* */
834 /* */
835 /* INPUT */
836 /* */
837 /* ftp_client_ptr Pointer to FTP client */
838 /* ftp_client_name Name of this FTP client */
839 /* ip_ptr Pointer to IP instance */
840 /* window_size Size of TCP receive window */
841 /* pool_ptr Pointer to packet pool */
842 /* */
843 /* OUTPUT */
844 /* */
845 /* status Completion status */
846 /* */
847 /* CALLS */
848 /* */
849 /* _nx_ftp_client_create Actual client create call */
850 /* */
851 /* CALLED BY */
852 /* */
853 /* Application Code */
854 /* */
855 /* RELEASE HISTORY */
856 /* */
857 /* DATE NAME DESCRIPTION */
858 /* */
859 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
860 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
861 /* resulting in version 6.1 */
862 /* */
863 /**************************************************************************/
_nxe_ftp_client_create(NX_FTP_CLIENT * ftp_client_ptr,CHAR * ftp_client_name,NX_IP * ip_ptr,ULONG window_size,NX_PACKET_POOL * pool_ptr)864 UINT _nxe_ftp_client_create(NX_FTP_CLIENT *ftp_client_ptr, CHAR *ftp_client_name, NX_IP *ip_ptr,
865 ULONG window_size, NX_PACKET_POOL *pool_ptr)
866 {
867
868 UINT status;
869
870
871 /* Check for invalid input pointers. */
872 if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
873 (ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id == NXD_FTP_CLIENT_ID) ||
874 (pool_ptr == NX_NULL))
875 return(NX_PTR_ERROR);
876
877 /* Call actual client create function. */
878 status = _nx_ftp_client_create(ftp_client_ptr, ftp_client_name, ip_ptr, window_size, pool_ptr);
879
880 /* Return completion status. */
881 return(status);
882 }
883
884
885 /**************************************************************************/
886 /* */
887 /* FUNCTION RELEASE */
888 /* */
889 /* _nx_ftp_client_create PORTABLE C */
890 /* 6.1 */
891 /* AUTHOR */
892 /* */
893 /* Yuxin Zhou, Microsoft Corporation */
894 /* */
895 /* DESCRIPTION */
896 /* */
897 /* This function creates an FTP client instance. */
898 /* */
899 /* */
900 /* INPUT */
901 /* */
902 /* ftp_client_ptr Pointer to FTP client */
903 /* ftp_client_name Name of this FTP client */
904 /* ip_ptr Pointer to IP instance */
905 /* window_size Size of TCP receive window */
906 /* pool_ptr Pointer to packet pool */
907 /* */
908 /* OUTPUT */
909 /* */
910 /* status Completion status */
911 /* */
912 /* CALLS */
913 /* */
914 /* nx_tcp_socket_create Create TCP socket */
915 /* nx_tcp_socket_delete Delete TCP socket */
916 /* */
917 /* CALLED BY */
918 /* */
919 /* Application Code */
920 /* */
921 /* RELEASE HISTORY */
922 /* */
923 /* DATE NAME DESCRIPTION */
924 /* */
925 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
926 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
927 /* resulting in version 6.1 */
928 /* */
929 /**************************************************************************/
_nx_ftp_client_create(NX_FTP_CLIENT * ftp_client_ptr,CHAR * ftp_client_name,NX_IP * ip_ptr,ULONG window_size,NX_PACKET_POOL * pool_ptr)930 UINT _nx_ftp_client_create(NX_FTP_CLIENT *ftp_client_ptr, CHAR *ftp_client_name, NX_IP *ip_ptr,
931 ULONG window_size, NX_PACKET_POOL *pool_ptr)
932 {
933
934 UINT status;
935
936
937 /* Clear the client FTP control block. */
938 memset((void *) ftp_client_ptr, 0, sizeof(NX_FTP_CLIENT));
939
940 /* Create the TCP control socket. */
941 status = nx_tcp_socket_create(ip_ptr, &(ftp_client_ptr -> nx_ftp_client_control_socket), ftp_client_name,
942 NX_FTP_CONTROL_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, window_size,
943 NX_NULL, NX_NULL);
944
945 /* Check for an error. */
946 if (status)
947 {
948
949 /* Return an error. */
950 return(status);
951 }
952
953 /* Create the TCP data socket. */
954 status = nx_tcp_socket_create(ip_ptr, &(ftp_client_ptr -> nx_ftp_client_data_socket), ftp_client_name,
955 NX_FTP_CONTROL_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, window_size,
956 NX_NULL, _nx_ftp_client_data_disconnect);
957
958 /* Check for an error. */
959 if (status)
960 {
961
962 /* Delete the control socket. */
963 nx_tcp_socket_delete(&(ftp_client_ptr -> nx_ftp_client_control_socket));
964
965 /* Return an error. */
966 return(status);
967 }
968
969 /* Save off the remaining information. */
970
971 /* Save the client name. */
972 ftp_client_ptr -> nx_ftp_client_name = ftp_client_name;
973
974 /* Save the IP pointer. */
975 ftp_client_ptr -> nx_ftp_client_ip_ptr = ip_ptr;
976
977 /* Save the packet pool pointer. */
978 ftp_client_ptr -> nx_ftp_client_packet_pool_ptr = pool_ptr;
979
980 /* Set the initial client state. */
981 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_NOT_CONNECTED;
982
983 /* Set the FTP client id. */
984 ftp_client_ptr -> nx_ftp_client_id = NXD_FTP_CLIENT_ID;
985
986 /* Default to active transfer mode. */
987 ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled = NX_FALSE;
988
989 /* Default to stream mode. */
990 ftp_client_ptr -> nx_ftp_client_transfer_mode = NX_FTP_TRANSFER_MODE_STREAM;
991
992 /* Return success to caller. */
993 return(NX_SUCCESS);
994 }
995
996
997 /**************************************************************************/
998 /* */
999 /* FUNCTION RELEASE */
1000 /* */
1001 /* _nx_ftp_client_data_disconnect PORTABLE C */
1002 /* 6.1 */
1003 /* AUTHOR */
1004 /* */
1005 /* Yuxin Zhou, Microsoft Corporation */
1006 /* */
1007 /* DESCRIPTION */
1008 /* */
1009 /* This function handles the disconnect from the server. */
1010 /* */
1011 /* */
1012 /* INPUT */
1013 /* */
1014 /* data_socket_ptr Pointer to FTP client data */
1015 /* socket */
1016 /* */
1017 /* OUTPUT */
1018 /* */
1019 /* None */
1020 /* */
1021 /* CALLS */
1022 /* */
1023 /* nx_tcp_socket_disconnect Disconnect TCP socket */
1024 /* */
1025 /* CALLED BY */
1026 /* */
1027 /* Application Code */
1028 /* */
1029 /* RELEASE HISTORY */
1030 /* */
1031 /* DATE NAME DESCRIPTION */
1032 /* */
1033 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1034 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1035 /* resulting in version 6.1 */
1036 /* */
1037 /**************************************************************************/
_nx_ftp_client_data_disconnect(NX_TCP_SOCKET * data_socket_ptr)1038 void _nx_ftp_client_data_disconnect(NX_TCP_SOCKET *data_socket_ptr)
1039 {
1040
1041 /* Disconnect FTP client data socket. */
1042 nx_tcp_socket_disconnect(data_socket_ptr, NX_NO_WAIT);
1043 }
1044
1045
1046 /**************************************************************************/
1047 /* */
1048 /* FUNCTION RELEASE */
1049 /* */
1050 /* _nxe_ftp_client_delete PORTABLE C */
1051 /* 6.1 */
1052 /* AUTHOR */
1053 /* */
1054 /* Yuxin Zhou, Microsoft Corporation */
1055 /* */
1056 /* DESCRIPTION */
1057 /* */
1058 /* This function checks for errors in the FTP client delete call. */
1059 /* */
1060 /* */
1061 /* INPUT */
1062 /* */
1063 /* ftp_client_ptr Pointer to FTP client */
1064 /* */
1065 /* OUTPUT */
1066 /* */
1067 /* status Completion status */
1068 /* */
1069 /* CALLS */
1070 /* */
1071 /* _nx_ftp_client_delete Actual client delete call */
1072 /* */
1073 /* CALLED BY */
1074 /* */
1075 /* Application Code */
1076 /* */
1077 /* RELEASE HISTORY */
1078 /* */
1079 /* DATE NAME DESCRIPTION */
1080 /* */
1081 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1082 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1083 /* resulting in version 6.1 */
1084 /* */
1085 /**************************************************************************/
_nxe_ftp_client_delete(NX_FTP_CLIENT * ftp_client_ptr)1086 UINT _nxe_ftp_client_delete(NX_FTP_CLIENT *ftp_client_ptr)
1087 {
1088
1089 UINT status;
1090
1091
1092 /* Check for invalid input pointers. */
1093 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
1094 return(NX_PTR_ERROR);
1095
1096 /* Check for appropriate caller. */
1097 NX_THREADS_ONLY_CALLER_CHECKING
1098
1099 /* Call actual client delete function. */
1100 status = _nx_ftp_client_delete(ftp_client_ptr);
1101
1102 /* Return completion status. */
1103 return(status);
1104 }
1105
1106
1107 /**************************************************************************/
1108 /* */
1109 /* FUNCTION RELEASE */
1110 /* */
1111 /* _nx_ftp_client_delete PORTABLE C */
1112 /* 6.2.1 */
1113 /* AUTHOR */
1114 /* */
1115 /* Yuxin Zhou, Microsoft Corporation */
1116 /* */
1117 /* DESCRIPTION */
1118 /* */
1119 /* This function deletes a previously created FTP client instance. */
1120 /* */
1121 /* */
1122 /* INPUT */
1123 /* */
1124 /* ftp_client_ptr Pointer to FTP client */
1125 /* */
1126 /* OUTPUT */
1127 /* */
1128 /* status Completion status */
1129 /* */
1130 /* CALLS */
1131 /* */
1132 /* nx_tcp_socket_create Create TCP socket */
1133 /* nx_tcp_socket_delete Delete TCP socket */
1134 /* */
1135 /* CALLED BY */
1136 /* */
1137 /* Application Code */
1138 /* */
1139 /* RELEASE HISTORY */
1140 /* */
1141 /* DATE NAME DESCRIPTION */
1142 /* */
1143 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1144 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1145 /* resulting in version 6.1 */
1146 /* 03-08-2023 Wenhui Xie Modified comment(s), */
1147 /* cleared the client ID, */
1148 /* resulting in version 6.2.1 */
1149 /* */
1150 /**************************************************************************/
_nx_ftp_client_delete(NX_FTP_CLIENT * ftp_client_ptr)1151 UINT _nx_ftp_client_delete(NX_FTP_CLIENT *ftp_client_ptr)
1152 {
1153
1154 /* Determine if the client is still in a not connected state. */
1155 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_NOT_CONNECTED)
1156 {
1157
1158 /* Already connected, return an error. */
1159 return(NX_FTP_NOT_DISCONNECTED);
1160 }
1161
1162 /* Clear the client ID . */
1163 ftp_client_ptr -> nx_ftp_client_id = 0;
1164
1165 /* Delete the control and data sockets. */
1166 nx_tcp_socket_delete(&(ftp_client_ptr -> nx_ftp_client_control_socket));
1167 nx_tcp_socket_delete(&(ftp_client_ptr -> nx_ftp_client_data_socket));
1168
1169 /* Return success to caller. */
1170 return(NX_SUCCESS);
1171 }
1172
1173 /**************************************************************************/
1174 /* */
1175 /* FUNCTION RELEASE */
1176 /* */
1177 /* _nxe_ftp_client_directory_create PORTABLE C */
1178 /* 6.1 */
1179 /* AUTHOR */
1180 /* */
1181 /* Yuxin Zhou, Microsoft Corporation */
1182 /* */
1183 /* DESCRIPTION */
1184 /* */
1185 /* This function checks for errors in the FTP client directory */
1186 /* create call. */
1187 /* */
1188 /* Note: The string length of directory_name is limited by the packet */
1189 /* payload size. */
1190 /* */
1191 /* INPUT */
1192 /* */
1193 /* ftp_client_ptr Pointer to FTP client */
1194 /* directory_name New directory name */
1195 /* wait_option Specifies how long to wait */
1196 /* */
1197 /* OUTPUT */
1198 /* */
1199 /* status Completion status */
1200 /* */
1201 /* CALLS */
1202 /* */
1203 /* _nx_ftp_client_directory_create Actual client directory */
1204 /* create call */
1205 /* */
1206 /* CALLED BY */
1207 /* */
1208 /* Application Code */
1209 /* */
1210 /* RELEASE HISTORY */
1211 /* */
1212 /* DATE NAME DESCRIPTION */
1213 /* */
1214 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1215 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1216 /* resulting in version 6.1 */
1217 /* */
1218 /**************************************************************************/
_nxe_ftp_client_directory_create(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_name,ULONG wait_option)1219 UINT _nxe_ftp_client_directory_create(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_name, ULONG wait_option)
1220 {
1221
1222 UINT status;
1223
1224
1225 /* Check for invalid input pointers. */
1226 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (directory_name == NX_NULL))
1227 return(NX_PTR_ERROR);
1228
1229 /* Check for appropriate caller. */
1230 NX_THREADS_ONLY_CALLER_CHECKING
1231
1232 /* Call actual client directory create function. */
1233 status = _nx_ftp_client_directory_create(ftp_client_ptr, directory_name, wait_option);
1234
1235 /* Return completion status. */
1236 return(status);
1237 }
1238
1239
1240 /**************************************************************************/
1241 /* */
1242 /* FUNCTION RELEASE */
1243 /* */
1244 /* _nx_ftp_client_directory_create PORTABLE C */
1245 /* 6.1 */
1246 /* AUTHOR */
1247 /* */
1248 /* Yuxin Zhou, Microsoft Corporation */
1249 /* */
1250 /* DESCRIPTION */
1251 /* */
1252 /* This function creates the specified directory name on the FTP */
1253 /* server. */
1254 /* */
1255 /* Note: The string length of directory_name is limited by the packet */
1256 /* payload size. */
1257 /* */
1258 /* INPUT */
1259 /* */
1260 /* ftp_client_ptr Pointer to FTP client */
1261 /* directory_name New directory name */
1262 /* wait_option Specifies how long to wait */
1263 /* */
1264 /* OUTPUT */
1265 /* */
1266 /* status Completion status */
1267 /* */
1268 /* CALLS */
1269 /* */
1270 /* nx_packet_allocate Allocate packet */
1271 /* nx_packet_release Release packet */
1272 /* nx_tcp_socket_receive Receive packet from server */
1273 /* nx_tcp_socket_send Send data packet to server */
1274 /* */
1275 /* CALLED BY */
1276 /* */
1277 /* Application Code */
1278 /* */
1279 /* RELEASE HISTORY */
1280 /* */
1281 /* DATE NAME DESCRIPTION */
1282 /* */
1283 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1284 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1285 /* resulting in version 6.1 */
1286 /* */
1287 /**************************************************************************/
_nx_ftp_client_directory_create(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_name,ULONG wait_option)1288 UINT _nx_ftp_client_directory_create(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_name, ULONG wait_option)
1289 {
1290
1291 UINT i;
1292 UCHAR *buffer_ptr;
1293 NX_PACKET *packet_ptr;
1294 UINT status;
1295
1296 /* Ensure the client is the proper state for directory create request. */
1297 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
1298 return(NX_FTP_NOT_CONNECTED);
1299
1300 /* Allocate a packet for sending the directory create command. */
1301 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
1302
1303 /* Determine if the packet allocation was successful. */
1304 if (status)
1305 {
1306
1307 /* Return error. */
1308 return(status);
1309 }
1310
1311 /* Check if out of boundary. */
1312 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 6)
1313 {
1314
1315 /* Release the packet. */
1316 nx_packet_release(packet_ptr);
1317
1318 /* Set the error status. */
1319 return(NX_FTP_FAILED);
1320 }
1321
1322 /* We have a packet, setup pointer to the buffer area. */
1323 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1324
1325 /* Now build "MKD" message to indicate directory create. */
1326 buffer_ptr[0] = 'M';
1327 buffer_ptr[1] = 'K';
1328 buffer_ptr[2] = 'D';
1329 buffer_ptr[3] = ' ';
1330
1331 /* Copy the new directory name into the message. */
1332 for(i = 0; directory_name[i]; i++)
1333 {
1334
1335 /* Check if out of boundary. */
1336 if ((i + 6) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
1337 {
1338
1339 /* Release the packet. */
1340 nx_packet_release(packet_ptr);
1341
1342 /* Set the error status. */
1343 return(NX_FTP_FAILED);
1344 }
1345
1346 /* Copy character of the directory name. */
1347 buffer_ptr[4+i] = (UCHAR)directory_name[i];
1348 }
1349
1350 /* Set the CR/LF. */
1351 buffer_ptr[i+4] = 13;
1352 buffer_ptr[i+5] = 10;
1353
1354 /* Set the packet length. */
1355 packet_ptr -> nx_packet_length = i+6;
1356
1357 /* Setup the packet append pointer. */
1358 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
1359
1360 /* Send the MKD message. */
1361 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
1362
1363 /* Determine if the send was unsuccessful. */
1364 if (status)
1365 {
1366
1367 /* Release the packet. */
1368 nx_packet_release(packet_ptr);
1369
1370 /* Return error. */
1371 return(status);
1372 }
1373
1374 /* Wait for response from the FTP server. */
1375 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
1376
1377 /* Determine if a packet was not received. */
1378 if (status)
1379 {
1380
1381 /* MKD error. */
1382 return(status);
1383 }
1384
1385 /* We have a packet, setup pointer to the buffer area. */
1386 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1387
1388 /* Check for 2xx message, signaling the "MKD" was processed successfully. */
1389 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
1390 {
1391
1392 /* Release the packet. */
1393 nx_packet_release(packet_ptr);
1394
1395 /* Create directory error. */
1396 return(NX_FTP_EXPECTED_2XX_CODE);
1397 }
1398
1399 /* Yes, the directory was created. */
1400
1401 /* Release the packet. */
1402 nx_packet_release(packet_ptr);
1403
1404 /* Return success to caller. */
1405 return(NX_SUCCESS);
1406 }
1407
1408
1409 /**************************************************************************/
1410 /* */
1411 /* FUNCTION RELEASE */
1412 /* */
1413 /* _nxe_ftp_client_directory_default_set PORTABLE C */
1414 /* 6.1 */
1415 /* AUTHOR */
1416 /* */
1417 /* Yuxin Zhou, Microsoft Corporation */
1418 /* */
1419 /* DESCRIPTION */
1420 /* */
1421 /* This function checks for errors in the FTP client directory */
1422 /* default set. */
1423 /* */
1424 /* Note: The string length of directory_path is limited by the packet */
1425 /* payload size. */
1426 /* */
1427 /* INPUT */
1428 /* */
1429 /* ftp_client_ptr Pointer to FTP client */
1430 /* directory_path New default directory path */
1431 /* wait_option Specifies how long to wait */
1432 /* */
1433 /* OUTPUT */
1434 /* */
1435 /* status Completion status */
1436 /* */
1437 /* CALLS */
1438 /* */
1439 /* _nx_ftp_client_directory_default_set Actual client directory */
1440 /* default set call */
1441 /* */
1442 /* CALLED BY */
1443 /* */
1444 /* Application Code */
1445 /* */
1446 /* RELEASE HISTORY */
1447 /* */
1448 /* DATE NAME DESCRIPTION */
1449 /* */
1450 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1451 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1452 /* resulting in version 6.1 */
1453 /* */
1454 /**************************************************************************/
_nxe_ftp_client_directory_default_set(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_path,ULONG wait_option)1455 UINT _nxe_ftp_client_directory_default_set(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_path, ULONG wait_option)
1456 {
1457
1458 UINT status;
1459
1460
1461 /* Check for invalid input pointers. */
1462 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
1463 return(NX_PTR_ERROR);
1464
1465 /* Check for appropriate caller. */
1466 NX_THREADS_ONLY_CALLER_CHECKING
1467
1468 /* Call actual client directory default set function. */
1469 status = _nx_ftp_client_directory_default_set(ftp_client_ptr, directory_path, wait_option);
1470
1471 /* Return completion status. */
1472 return(status);
1473 }
1474
1475
1476 /**************************************************************************/
1477 /* */
1478 /* FUNCTION RELEASE */
1479 /* */
1480 /* _nx_ftp_client_directory_default_set PORTABLE C */
1481 /* 6.1 */
1482 /* AUTHOR */
1483 /* */
1484 /* Yuxin Zhou, Microsoft Corporation */
1485 /* */
1486 /* DESCRIPTION */
1487 /* */
1488 /* This function changes the default working directory on the FTP */
1489 /* server. */
1490 /* */
1491 /* Note: The string length of directory_path is limited by the packet */
1492 /* payload size. */
1493 /* */
1494 /* INPUT */
1495 /* */
1496 /* ftp_client_ptr Pointer to FTP client */
1497 /* directory_path New default directory path */
1498 /* wait_option Specifies how long to wait */
1499 /* */
1500 /* OUTPUT */
1501 /* */
1502 /* status Completion status */
1503 /* */
1504 /* CALLS */
1505 /* */
1506 /* nx_packet_allocate Allocate packet */
1507 /* nx_packet_release Release packet */
1508 /* nx_tcp_socket_receive Receive packet from server */
1509 /* nx_tcp_socket_send Send data packet to server */
1510 /* */
1511 /* CALLED BY */
1512 /* */
1513 /* Application Code */
1514 /* */
1515 /* RELEASE HISTORY */
1516 /* */
1517 /* DATE NAME DESCRIPTION */
1518 /* */
1519 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1520 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1521 /* resulting in version 6.1 */
1522 /* */
1523 /**************************************************************************/
_nx_ftp_client_directory_default_set(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_path,ULONG wait_option)1524 UINT _nx_ftp_client_directory_default_set(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_path, ULONG wait_option)
1525 {
1526
1527 UINT i;
1528 UCHAR *buffer_ptr;
1529 NX_PACKET *packet_ptr;
1530 UINT status;
1531
1532
1533 /* Ensure the client is the proper state for a default directory request. */
1534 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
1535 return(NX_FTP_NOT_CONNECTED);
1536
1537 /* Allocate a packet for sending the change directory command. */
1538 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
1539
1540 /* Determine if the packet allocation was successful. */
1541 if (status)
1542 {
1543
1544 /* Return error. */
1545 return(status);
1546 }
1547
1548 /* Check if out of boundary. */
1549 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 6)
1550 {
1551
1552 /* Release the packet. */
1553 nx_packet_release(packet_ptr);
1554
1555 /* Set the error status. */
1556 return(NX_FTP_FAILED);
1557 }
1558
1559 /* We have a packet, setup pointer to the buffer area. */
1560 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1561
1562 /* Now build "CWD" message to indicate default directory change. */
1563 buffer_ptr[0] = 'C';
1564 buffer_ptr[1] = 'W';
1565 buffer_ptr[2] = 'D';
1566 buffer_ptr[3] = ' ';
1567
1568 /* Copy the new default directory into the message. */
1569 for(i = 0; directory_path[i]; i++)
1570 {
1571
1572 /* Check if out of boundary. */
1573 if ((i + 6) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
1574 {
1575
1576 /* Release the packet. */
1577 nx_packet_release(packet_ptr);
1578
1579 /* Set the error status. */
1580 return(NX_FTP_FAILED);
1581 }
1582
1583 /* Copy character of the directory path. */
1584 buffer_ptr[4+i] = (UCHAR)directory_path[i];
1585 }
1586
1587 /* Set the CR/LF. */
1588 buffer_ptr[i+4] = 13;
1589 buffer_ptr[i+5] = 10;
1590
1591 /* Set the packet length. */
1592 packet_ptr -> nx_packet_length = i+6;
1593
1594 /* Setup the packet append pointer. */
1595 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
1596
1597 /* Send the CWD message. */
1598 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
1599
1600 /* Determine if the send was unsuccessful. */
1601 if (status)
1602 {
1603
1604 /* Release the packet. */
1605 nx_packet_release(packet_ptr);
1606
1607 /* Return error. */
1608 return(status);
1609 }
1610
1611 /* Wait for response from the FTP server. */
1612 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
1613
1614 /* Determine if a packet was not received. */
1615 if (status)
1616 {
1617
1618 /* RNFR file error. */
1619 return(status);
1620 }
1621
1622 /* We have a packet, setup pointer to the buffer area. */
1623 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1624
1625 /* Check for 2xx message, signaling the "CWD" was processed successfully. */
1626 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
1627 {
1628
1629 /* Release the packet. */
1630 nx_packet_release(packet_ptr);
1631
1632 /* Change directory error. */
1633 return(NX_FTP_EXPECTED_2XX_CODE);
1634 }
1635
1636 /* Yes, the default directory was changed. */
1637
1638 /* Release the packet. */
1639 nx_packet_release(packet_ptr);
1640
1641 /* Return success to caller. */
1642 return(NX_SUCCESS);
1643 }
1644
1645
1646 /**************************************************************************/
1647 /* */
1648 /* FUNCTION RELEASE */
1649 /* */
1650 /* _nxe_ftp_client_directory_delete PORTABLE C */
1651 /* 6.1 */
1652 /* AUTHOR */
1653 /* */
1654 /* Yuxin Zhou, Microsoft Corporation */
1655 /* */
1656 /* DESCRIPTION */
1657 /* */
1658 /* This function checks for errors in the FTP client directory */
1659 /* delete. */
1660 /* */
1661 /* Note: The string length of directory_name is limited by the packet */
1662 /* payload size. */
1663 /* */
1664 /* INPUT */
1665 /* */
1666 /* ftp_client_ptr Pointer to FTP client */
1667 /* directory_name Directory name to delete */
1668 /* wait_option Specifies how long to wait */
1669 /* */
1670 /* OUTPUT */
1671 /* */
1672 /* status Completion status */
1673 /* */
1674 /* CALLS */
1675 /* */
1676 /* _nx_ftp_client_directory_delete Actual client directory */
1677 /* delete call */
1678 /* */
1679 /* CALLED BY */
1680 /* */
1681 /* Application Code */
1682 /* */
1683 /* RELEASE HISTORY */
1684 /* */
1685 /* DATE NAME DESCRIPTION */
1686 /* */
1687 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1688 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1689 /* resulting in version 6.1 */
1690 /* */
1691 /**************************************************************************/
_nxe_ftp_client_directory_delete(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_name,ULONG wait_option)1692 UINT _nxe_ftp_client_directory_delete(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_name, ULONG wait_option)
1693 {
1694
1695 UINT status;
1696
1697
1698 /* Check for invalid input pointers. */
1699 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
1700 return(NX_PTR_ERROR);
1701
1702 /* Check for appropriate caller. */
1703 NX_THREADS_ONLY_CALLER_CHECKING
1704
1705 /* Call actual client directory delete function. */
1706 status = _nx_ftp_client_directory_delete(ftp_client_ptr, directory_name, wait_option);
1707
1708 /* Return completion status. */
1709 return(status);
1710 }
1711
1712
1713 /**************************************************************************/
1714 /* */
1715 /* FUNCTION RELEASE */
1716 /* */
1717 /* _nx_ftp_client_directory_delete PORTABLE C */
1718 /* 6.1 */
1719 /* AUTHOR */
1720 /* */
1721 /* Yuxin Zhou, Microsoft Corporation */
1722 /* */
1723 /* DESCRIPTION */
1724 /* */
1725 /* This function deletes the specified directory on the FTP */
1726 /* server. */
1727 /* */
1728 /* Note: The string length of directory_name is limited by the packet */
1729 /* payload size. */
1730 /* */
1731 /* INPUT */
1732 /* */
1733 /* ftp_client_ptr Pointer to FTP client */
1734 /* directory_name Directory name to delete */
1735 /* wait_option Specifies how long to wait */
1736 /* */
1737 /* OUTPUT */
1738 /* */
1739 /* status Completion status */
1740 /* */
1741 /* CALLS */
1742 /* */
1743 /* nx_packet_allocate Allocate packet */
1744 /* nx_packet_release Release packet */
1745 /* nx_tcp_socket_receive Receive packet from server */
1746 /* nx_tcp_socket_send Send data packet to server */
1747 /* */
1748 /* CALLED BY */
1749 /* */
1750 /* Application Code */
1751 /* */
1752 /* RELEASE HISTORY */
1753 /* */
1754 /* DATE NAME DESCRIPTION */
1755 /* */
1756 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1757 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1758 /* resulting in version 6.1 */
1759 /* */
1760 /**************************************************************************/
_nx_ftp_client_directory_delete(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_name,ULONG wait_option)1761 UINT _nx_ftp_client_directory_delete(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_name, ULONG wait_option)
1762 {
1763
1764 UINT i;
1765 UCHAR *buffer_ptr;
1766 NX_PACKET *packet_ptr;
1767 UINT status;
1768
1769
1770 /* Ensure the client is the proper state for directory delete request. */
1771 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
1772 return(NX_FTP_NOT_CONNECTED);
1773
1774 /* Allocate a packet for sending the directory delete command. */
1775 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
1776
1777 /* Determine if the packet allocation was successful. */
1778 if (status)
1779 {
1780
1781 /* Return error. */
1782 return(status);
1783 }
1784
1785 /* Check if out of boundary. */
1786 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 6)
1787 {
1788
1789 /* Release the packet. */
1790 nx_packet_release(packet_ptr);
1791
1792 /* Set the error status. */
1793 return(NX_FTP_FAILED);
1794 }
1795
1796 /* We have a packet, setup pointer to the buffer area. */
1797 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1798
1799 /* Now build "RMD" message to indicate directory delete. */
1800 buffer_ptr[0] = 'R';
1801 buffer_ptr[1] = 'M';
1802 buffer_ptr[2] = 'D';
1803 buffer_ptr[3] = ' ';
1804
1805 /* Copy the directory name into the message. */
1806 for(i = 0; directory_name[i]; i++)
1807 {
1808
1809 /* Check if out of boundary. */
1810 if ((i + 6) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
1811 {
1812
1813 /* Release the packet. */
1814 nx_packet_release(packet_ptr);
1815
1816 /* Set the error status. */
1817 return(NX_FTP_FAILED);
1818 }
1819
1820 /* Copy character of the directory name. */
1821 buffer_ptr[4+i] = (UCHAR)directory_name[i];
1822 }
1823
1824 /* Set the CR/LF. */
1825 buffer_ptr[i+4] = 13;
1826 buffer_ptr[i+5] = 10;
1827
1828 /* Set the packet length. */
1829 packet_ptr -> nx_packet_length = i+6;
1830
1831 /* Setup the packet append pointer. */
1832 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
1833
1834 /* Send the RMD message. */
1835 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
1836
1837 /* Determine if the send was unsuccessful. */
1838 if (status)
1839 {
1840
1841 /* Release the packet. */
1842 nx_packet_release(packet_ptr);
1843
1844 /* Return error. */
1845 return(status);
1846 }
1847
1848 /* Wait for response from the FTP server. */
1849 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
1850
1851 /* Determine if a packet was not received. */
1852 if (status)
1853 {
1854
1855 /* DELE error. */
1856 return(status);
1857 }
1858
1859 /* We have a packet, setup pointer to the buffer area. */
1860 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1861
1862 /* Check for 2xx message, signaling the "RMD" was processed successfully. */
1863 if ((packet_ptr -> nx_packet_length < 3) ||(buffer_ptr[0] != '2'))
1864 {
1865
1866 /* Release the packet. */
1867 nx_packet_release(packet_ptr);
1868
1869 /* Delete directory error. */
1870 return(NX_FTP_EXPECTED_2XX_CODE);
1871 }
1872
1873 /* Yes, the directory was deleted. */
1874
1875 /* Release the packet. */
1876 nx_packet_release(packet_ptr);
1877
1878 /* Return success to caller. */
1879 return(NX_SUCCESS);
1880 }
1881
1882 /**************************************************************************/
1883 /* */
1884 /* FUNCTION RELEASE */
1885 /* */
1886 /* _nxe_ftp_client_directory_listing_get PORTABLE C */
1887 /* 6.1 */
1888 /* AUTHOR */
1889 /* */
1890 /* Yuxin Zhou, Microsoft Corporation */
1891 /* */
1892 /* DESCRIPTION */
1893 /* */
1894 /* This function checks for errors in the FTP client directory */
1895 /* listing get. */
1896 /* */
1897 /* Note: The string length of directory_path is limited by the packet */
1898 /* payload size. */
1899 /* */
1900 /* INPUT */
1901 /* */
1902 /* ftp_client_ptr Pointer to FTP client */
1903 /* directory_path Directory to get listing for */
1904 /* packet_ptr Destination of for the */
1905 /* received packet pointer */
1906 /* that contains the listing */
1907 /* wait_option Specifies how long to wait */
1908 /* */
1909 /* OUTPUT */
1910 /* */
1911 /* status Completion status */
1912 /* */
1913 /* CALLS */
1914 /* */
1915 /* _nx_ftp_client_directory_listing_get Actual client directory */
1916 /* listing get call */
1917 /* */
1918 /* CALLED BY */
1919 /* */
1920 /* Application Code */
1921 /* */
1922 /* RELEASE HISTORY */
1923 /* */
1924 /* DATE NAME DESCRIPTION */
1925 /* */
1926 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1927 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1928 /* resulting in version 6.1 */
1929 /* */
1930 /**************************************************************************/
_nxe_ftp_client_directory_listing_get(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_path,NX_PACKET ** packet_ptr,ULONG wait_option)1931 UINT _nxe_ftp_client_directory_listing_get(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_path,
1932 NX_PACKET **packet_ptr, ULONG wait_option)
1933 {
1934
1935 UINT status;
1936
1937
1938 /* Check for invalid input pointers. */
1939 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (packet_ptr == NX_NULL))
1940 return(NX_PTR_ERROR);
1941
1942 /* Check for appropriate caller. */
1943 NX_THREADS_ONLY_CALLER_CHECKING
1944
1945 /* Call actual client directory listing get function. */
1946 status = _nx_ftp_client_directory_listing_get(ftp_client_ptr, directory_path, packet_ptr, wait_option);
1947
1948 /* Return completion status. */
1949 return(status);
1950 }
1951
1952
1953 /**************************************************************************/
1954 /* */
1955 /* FUNCTION RELEASE */
1956 /* */
1957 /* _nx_ftp_client_directory_listing_get PORTABLE C */
1958 /* 6.1 */
1959 /* AUTHOR */
1960 /* */
1961 /* Yuxin Zhou, Microsoft Corporation */
1962 /* */
1963 /* DESCRIPTION */
1964 /* */
1965 /* This function gets a listing for the specified directory on the */
1966 /* FTP server. */
1967 /* */
1968 /* Note: The string length of directory_path is limited by the packet */
1969 /* payload size. */
1970 /* */
1971 /* INPUT */
1972 /* */
1973 /* ftp_client_ptr Pointer to FTP client */
1974 /* directory_path Directory to get listing for */
1975 /* packet_ptr Destination of for the */
1976 /* received packet pointer */
1977 /* that contains the listing */
1978 /* wait_option Specifies how long to wait */
1979 /* */
1980 /* OUTPUT */
1981 /* */
1982 /* status Completion status */
1983 /* */
1984 /* CALLS */
1985 /* */
1986 /* _nx_ftp_client_packet_allocate Allocate packet */
1987 /* _nx_ftp_client_active_transfer_setup Setup active transfer */
1988 /* _nx_ftp_client_passive_transfer_setup Setup passive transfer */
1989 /* _nx_ftp_client_block_mode_send Send block mode command */
1990 /* _nx_ftp_client_data_socket_cleanup Cleanup data socket */
1991 /* nx_packet_release Release packet */
1992 /* nx_tcp_server_socket_accept Connect data socket to server */
1993 /* nx_tcp_socket_receive Receive response from server */
1994 /* nx_tcp_socket_send Send request to server */
1995 /* */
1996 /* CALLED BY */
1997 /* */
1998 /* Application Code */
1999 /* */
2000 /* RELEASE HISTORY */
2001 /* */
2002 /* DATE NAME DESCRIPTION */
2003 /* */
2004 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2005 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2006 /* resulting in version 6.1 */
2007 /* */
2008 /**************************************************************************/
_nx_ftp_client_directory_listing_get(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_path,NX_PACKET ** packet_ptr,ULONG wait_option)2009 UINT _nx_ftp_client_directory_listing_get(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_path,
2010 NX_PACKET **packet_ptr, ULONG wait_option)
2011 {
2012
2013 UINT i;
2014 UCHAR *buffer_ptr;
2015 NX_PACKET *new_packet_ptr;
2016 UINT status;
2017
2018
2019 /* Set packet pointer to NULL. */
2020 *packet_ptr = NX_NULL;
2021
2022 /* Ensure the client is the proper state for directory listing request. */
2023 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
2024 return(NX_FTP_NOT_CONNECTED);
2025
2026 /* Divert to passive mode operation if passive mode is enabled. */
2027 if (ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled)
2028 {
2029
2030 /* Transfer the data in passive transfer mode. */
2031 status = _nx_ftp_client_passive_transfer_setup(ftp_client_ptr, wait_option);
2032 }
2033 else
2034 {
2035
2036 /* Transfer the data in active transfer mode. */
2037 status = _nx_ftp_client_active_transfer_setup(ftp_client_ptr, wait_option);
2038 }
2039
2040 /* Determine if set up successful. */
2041 if (status)
2042 {
2043 return(status);
2044 }
2045
2046 /* Check if enable block mode. */
2047 if (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
2048 {
2049
2050 /* Send MODE B command to FTP server. */
2051 status = _nx_ftp_client_block_mode_send(ftp_client_ptr, wait_option);
2052
2053 /* Determine if the send was unsuccessful. */
2054 if (status != NX_SUCCESS)
2055 {
2056
2057 /* Cleanup data socket. */
2058 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2059 return(status);
2060 }
2061 }
2062
2063 /* Allocate a packet for sending the NLST command. */
2064 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &new_packet_ptr, wait_option);
2065
2066 /* Determine if the packet allocation was successful. */
2067 if (status != NX_SUCCESS)
2068 {
2069
2070 /* Cleanup data socket. */
2071 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2072
2073 /* Return error. */
2074 return(status);
2075 }
2076
2077 /* Check if out of boundary. */
2078 if ((UINT)(new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_prepend_ptr) < 7)
2079 {
2080
2081 /* Cleanup data socket. */
2082 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2083
2084 /* Release the packet. */
2085 nx_packet_release(new_packet_ptr);
2086
2087 /* Set the error status. */
2088 return(NX_FTP_FAILED);
2089 }
2090
2091 /* We have a packet, setup pointer to the buffer area. */
2092 buffer_ptr = new_packet_ptr -> nx_packet_prepend_ptr;
2093
2094 /* Now build the actual NLST request. */
2095 buffer_ptr[0] = 'N';
2096 buffer_ptr[1] = 'L';
2097 buffer_ptr[2] = 'S';
2098 buffer_ptr[3] = 'T';
2099 buffer_ptr[4] = ' ';
2100
2101 /* Copy the directory path into the buffer. */
2102 for(i = 0; directory_path[i]; i++)
2103 {
2104
2105 /* Check if out of boundary. */
2106 if ((i + 7) >= (UINT)(new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_prepend_ptr))
2107 {
2108
2109 /* Cleanup data socket. */
2110 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2111
2112 /* Release the packet. */
2113 nx_packet_release(new_packet_ptr);
2114
2115 /* Set the error status. */
2116 return(NX_FTP_FAILED);
2117 }
2118
2119 /* Copy character of directory path. */
2120 buffer_ptr[5+i] = (UCHAR)directory_path[i];
2121 }
2122
2123 /* Insert the CR/LF. */
2124 buffer_ptr[5+i] = 13;
2125 buffer_ptr[5+i+1] = 10;
2126
2127 /* Setup the length of the packet. */
2128 new_packet_ptr -> nx_packet_length = i + 7;
2129
2130 /* Setup the packet append pointer. */
2131 new_packet_ptr -> nx_packet_append_ptr = new_packet_ptr -> nx_packet_prepend_ptr + new_packet_ptr -> nx_packet_length;
2132
2133 /* Send the NLST message. */
2134 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), new_packet_ptr, wait_option);
2135
2136 /* Determine if the send was unsuccessful. */
2137 if (status)
2138 {
2139
2140 /* Cleanup data socket. */
2141 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2142
2143 /* Release the packet. */
2144 nx_packet_release(new_packet_ptr);
2145
2146 /* Return error. */
2147 return(status);
2148 }
2149
2150 /* Check if enable passive mode. */
2151 if (ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled == NX_FALSE)
2152 {
2153
2154 /* Now wait for the data connection to connect. */
2155 status = nx_tcp_server_socket_accept(&(ftp_client_ptr -> nx_ftp_client_data_socket), wait_option);
2156
2157 /* Determine if the accept was unsuccessful. */
2158 if (status)
2159 {
2160
2161 /* Cleanup data socket. */
2162 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2163
2164 /* Return error. */
2165 return(status);
2166 }
2167 }
2168
2169 /* Now wait for response from the FTP server control port. */
2170 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &new_packet_ptr, wait_option);
2171
2172 /* Determine if a packet was not received. */
2173 if (status)
2174 {
2175
2176 /* Cleanup data socket. */
2177 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2178
2179 /* Error in NLST request to FTP server. */
2180 return(status);
2181 }
2182
2183 /* We have a packet, setup pointer to the buffer area. */
2184 buffer_ptr = new_packet_ptr -> nx_packet_prepend_ptr;
2185
2186 /* Check for 1xx message, signaling the data port was connected properly and ready for
2187 transfer. */
2188 if ((new_packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '1'))
2189 {
2190
2191 /* Cleanup data socket. */
2192 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2193
2194 /* Release the packet. */
2195 nx_packet_release(new_packet_ptr);
2196
2197 /* Error in NLST request to FTP server. */
2198 return(NX_FTP_EXPECTED_1XX_CODE);
2199 }
2200
2201 /* Release the last packet. */
2202 nx_packet_release(new_packet_ptr);
2203
2204 /* Now read a listing packet from the data socket. */
2205 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_data_socket), packet_ptr, wait_option);
2206
2207 /* Determine if an error occurred. */
2208 if (status)
2209 {
2210
2211 /* Cleanup data socket. */
2212 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2213
2214 /* Map all unsuccessful status to error. */
2215 return(status);
2216 }
2217
2218 /* Determine if the block mode is enabled. */
2219 if (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
2220 {
2221
2222 /* Retrieve the block header. */
2223 status = _nx_ftp_client_block_header_retrieve(ftp_client_ptr, (*packet_ptr));
2224
2225 /* Determine if an error occurred. */
2226 if (status)
2227 {
2228
2229 /* Cleanup data socket. */
2230 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2231 }
2232 }
2233
2234 /* Return staus to caller. */
2235 return(status);
2236 }
2237
2238
2239 /**************************************************************************/
2240 /* */
2241 /* FUNCTION RELEASE */
2242 /* */
2243 /* _nxe_ftp_client_directory_listing_continue PORTABLE C */
2244 /* 6.1 */
2245 /* AUTHOR */
2246 /* */
2247 /* Yuxin Zhou, Microsoft Corporation */
2248 /* */
2249 /* DESCRIPTION */
2250 /* */
2251 /* This function checks for errors in the FTP client directory */
2252 /* listing continue. */
2253 /* */
2254 /* */
2255 /* INPUT */
2256 /* */
2257 /* ftp_client_ptr Pointer to FTP client */
2258 /* packet_ptr Destination of for the */
2259 /* received packet pointer */
2260 /* that contains the listing */
2261 /* wait_option Specifies how long to wait */
2262 /* */
2263 /* OUTPUT */
2264 /* */
2265 /* status Completion status */
2266 /* */
2267 /* CALLS */
2268 /* */
2269 /* _nx_ftp_client_directory_listing_continue Actual client directory */
2270 /* listing continue call */
2271 /* */
2272 /* CALLED BY */
2273 /* */
2274 /* Application Code */
2275 /* */
2276 /* RELEASE HISTORY */
2277 /* */
2278 /* DATE NAME DESCRIPTION */
2279 /* */
2280 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2281 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2282 /* resulting in version 6.1 */
2283 /* */
2284 /**************************************************************************/
_nxe_ftp_client_directory_listing_continue(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)2285 UINT _nxe_ftp_client_directory_listing_continue(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
2286 {
2287
2288 UINT status;
2289
2290
2291 /* Check for invalid input pointers. */
2292 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (packet_ptr == NX_NULL))
2293 return(NX_PTR_ERROR);
2294
2295 /* Check for appropriate caller. */
2296 NX_THREADS_ONLY_CALLER_CHECKING
2297
2298 /* Call actual client directory listing continue function. */
2299 status = _nx_ftp_client_directory_listing_continue(ftp_client_ptr, packet_ptr, wait_option);
2300
2301 /* Return completion status. */
2302 return(status);
2303 }
2304
2305
2306 /**************************************************************************/
2307 /* */
2308 /* FUNCTION RELEASE */
2309 /* */
2310 /* _nx_ftp_client_directory_listing_continue PORTABLE C */
2311 /* 6.1 */
2312 /* AUTHOR */
2313 /* */
2314 /* Yuxin Zhou, Microsoft Corporation */
2315 /* */
2316 /* DESCRIPTION */
2317 /* */
2318 /* This function gets the next listing buffer. It is assumed that */
2319 /* a successful _nx_ftp_client_directory_listing_get immediately */
2320 /* preceded this call. */
2321 /* */
2322 /* */
2323 /* INPUT */
2324 /* */
2325 /* ftp_client_ptr Pointer to FTP client */
2326 /* packet_ptr Destination of for the */
2327 /* received packet pointer */
2328 /* that contains the listing */
2329 /* wait_option Specifies how long to wait */
2330 /* */
2331 /* OUTPUT */
2332 /* */
2333 /* status Completion status */
2334 /* */
2335 /* CALLS */
2336 /* */
2337 /* _nx_ftp_client_data_socket_cleanup Cleanup data socket */
2338 /* nx_tcp_server_socket_unaccept Unaccept server connection */
2339 /* nx_tcp_server_socket_unlisten Unlisten on server port */
2340 /* nx_tcp_socket_receive Receive packet from server */
2341 /* */
2342 /* CALLED BY */
2343 /* */
2344 /* Application Code */
2345 /* */
2346 /* RELEASE HISTORY */
2347 /* */
2348 /* DATE NAME DESCRIPTION */
2349 /* */
2350 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2351 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2352 /* resulting in version 6.1 */
2353 /* */
2354 /**************************************************************************/
_nx_ftp_client_directory_listing_continue(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)2355 UINT _nx_ftp_client_directory_listing_continue(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
2356 {
2357
2358 UINT status;
2359 NX_PACKET *response_ptr;
2360 UCHAR *buffer_ptr;
2361
2362
2363 /* Set packet pointer to NULL. */
2364 *packet_ptr = NX_NULL;
2365
2366 /* Ensure the client is the proper state for directory listing request. */
2367 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
2368 return(NX_FTP_NOT_CONNECTED);
2369
2370 /* Now read a listing packet from the data socket. */
2371 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_data_socket), packet_ptr, wait_option);
2372
2373 /* Determine if the block mode is enabled. */
2374 if ((status == NX_SUCCESS) &&
2375 (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK))
2376 {
2377
2378 /* Retrieve the block header. */
2379 status = _nx_ftp_client_block_header_retrieve(ftp_client_ptr, (*packet_ptr));
2380 }
2381
2382 /* Determine if an error occurred. */
2383 if (status)
2384 {
2385
2386 /* Cleanup data socket. */
2387 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2388
2389 /* Wait for response from the FTP server on the control socket. */
2390 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &response_ptr, wait_option);
2391
2392 /* Determine if a packet was not received. */
2393 if (status)
2394 {
2395
2396 /* Directory listing error. */
2397 return(status);
2398 }
2399
2400 /* We have a packet, setup pointer to the buffer area. */
2401 buffer_ptr = response_ptr -> nx_packet_prepend_ptr;
2402
2403 /* Check for 2xx message, signaling the "NLST" was processed successfully. */
2404 if ((response_ptr -> nx_packet_length >= 3) && (buffer_ptr[0] == '2'))
2405 {
2406
2407 /* Release the packet. */
2408 nx_packet_release(response_ptr);
2409
2410 /* Appropriate end of listing error. */
2411 return(NX_FTP_END_OF_LISTING);
2412 }
2413 else
2414 {
2415
2416 /* Release the packet. */
2417 nx_packet_release(response_ptr);
2418
2419 /* Map all other unsuccessful status to error. */
2420 return(NX_FTP_EXPECTED_2XX_CODE);
2421 }
2422 }
2423
2424 /* Return success to caller. */
2425 return(status);
2426 }
2427
2428
2429 /**************************************************************************/
2430 /* */
2431 /* FUNCTION RELEASE */
2432 /* */
2433 /* _nxe_ftp_client_disconnect PORTABLE C */
2434 /* 6.1 */
2435 /* AUTHOR */
2436 /* */
2437 /* Yuxin Zhou, Microsoft Corporation */
2438 /* */
2439 /* DESCRIPTION */
2440 /* */
2441 /* This function checks for errors in the FTP client disconnect. */
2442 /* */
2443 /* */
2444 /* INPUT */
2445 /* */
2446 /* ftp_client_ptr Pointer to FTP client */
2447 /* wait_option Specifies how long to wait */
2448 /* */
2449 /* OUTPUT */
2450 /* */
2451 /* status Completion status */
2452 /* */
2453 /* CALLS */
2454 /* */
2455 /* _nx_ftp_client_disconnect Actual client disconnect call */
2456 /* */
2457 /* CALLED BY */
2458 /* */
2459 /* Application Code */
2460 /* */
2461 /* RELEASE HISTORY */
2462 /* */
2463 /* DATE NAME DESCRIPTION */
2464 /* */
2465 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2466 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2467 /* resulting in version 6.1 */
2468 /* */
2469 /**************************************************************************/
_nxe_ftp_client_disconnect(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)2470 UINT _nxe_ftp_client_disconnect(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
2471 {
2472
2473 UINT status;
2474
2475
2476 /* Check for invalid input pointers. */
2477 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
2478 return(NX_PTR_ERROR);
2479
2480 /* Check for appropriate caller. */
2481 NX_THREADS_ONLY_CALLER_CHECKING
2482
2483 /* Call actual client disconnect function. */
2484 status = _nx_ftp_client_disconnect(ftp_client_ptr, wait_option);
2485
2486 /* Return completion status. */
2487 return(status);
2488 }
2489
2490
2491 /**************************************************************************/
2492 /* */
2493 /* FUNCTION RELEASE */
2494 /* */
2495 /* _nx_ftp_client_disconnect PORTABLE C */
2496 /* 6.1 */
2497 /* AUTHOR */
2498 /* */
2499 /* Yuxin Zhou, Microsoft Corporation */
2500 /* */
2501 /* DESCRIPTION */
2502 /* */
2503 /* This function disconnects a previously established FTP connection. */
2504 /* */
2505 /* */
2506 /* INPUT */
2507 /* */
2508 /* ftp_client_ptr Pointer to FTP client */
2509 /* wait_option Specifies how long to wait */
2510 /* */
2511 /* OUTPUT */
2512 /* */
2513 /* status Completion status */
2514 /* */
2515 /* CALLS */
2516 /* */
2517 /* nx_packet_allocate Allocate packet */
2518 /* nx_packet_release Release packet */
2519 /* nx_tcp_client_socket_unbind Unbind a socket */
2520 /* nx_tcp_socket_disconnect Disconnect a socket */
2521 /* nx_tcp_socket_receive Receive response from server */
2522 /* nx_tcp_socket_send Send request to server */
2523 /* */
2524 /* CALLED BY */
2525 /* */
2526 /* Application Code */
2527 /* */
2528 /* RELEASE HISTORY */
2529 /* */
2530 /* DATE NAME DESCRIPTION */
2531 /* */
2532 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2533 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2534 /* resulting in version 6.1 */
2535 /* */
2536 /**************************************************************************/
_nx_ftp_client_disconnect(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)2537 UINT _nx_ftp_client_disconnect(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
2538 {
2539
2540 NX_PACKET *packet_ptr;
2541 UCHAR *buffer_ptr;
2542 UINT status;
2543
2544
2545 /* Determine if the client is in a not connected state. */
2546 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
2547 {
2548
2549 /* Already connected, return an error. */
2550 return(NX_FTP_NOT_CONNECTED);
2551 }
2552
2553 /* Enter the not connected state. */
2554 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_NOT_CONNECTED;
2555
2556 /* Allocate a packet for sending the port and IP address. */
2557 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
2558
2559 /* Determine if the packet allocation was successful. */
2560 if (status)
2561 {
2562
2563 /* Clean up connection socket. */
2564 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2565 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2566
2567 /* Return error. */
2568 return(status);
2569 }
2570
2571 /* Check if out of boundary. */
2572 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 6)
2573 {
2574
2575 /* Clean up connection socket. */
2576 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2577 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2578
2579 /* Release the packet. */
2580 nx_packet_release(packet_ptr);
2581
2582 /* Set the error status. */
2583 return(NX_FTP_FAILED);
2584 }
2585
2586 /* We have a packet, setup pointer to the buffer area. */
2587 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
2588
2589 /* Build QUIT message to end the FTP connection. */
2590 buffer_ptr[0] = 'Q';
2591 buffer_ptr[1] = 'U';
2592 buffer_ptr[2] = 'I';
2593 buffer_ptr[3] = 'T';
2594 buffer_ptr[4] = 13;
2595 buffer_ptr[5] = 10;
2596
2597 /* Set the packet length. */
2598 packet_ptr -> nx_packet_length = 6;
2599
2600 /* Setup the packet append pointer. */
2601 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
2602
2603 /* Send the QUIT message. */
2604 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
2605
2606 /* Determine if the send was unsuccessful. */
2607 if (status)
2608 {
2609
2610 /* Clean up connection socket. */
2611 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2612 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2613
2614 /* Release the packet. */
2615 nx_packet_release(packet_ptr);
2616
2617 /* Return error. */
2618 return(status);
2619 }
2620
2621 /* Wait for response from the FTP server. */
2622 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
2623
2624 /* Determine if a packet was not received. */
2625 if (status)
2626 {
2627
2628 /* Clean up connection socket. */
2629 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2630 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2631
2632 /* Unable to connect socket to server FTP control port. */
2633 return(status);
2634 }
2635
2636 /* We have a packet, setup pointer to the buffer area. */
2637 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
2638
2639 /* Check for 2xx message, signaling the disconnect was processed properly. */
2640 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
2641 {
2642
2643 /* Clean up connection socket. */
2644 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2645 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2646
2647 /* Release the packet. */
2648 nx_packet_release(packet_ptr);
2649
2650 /* Return error. */
2651 return(NX_FTP_EXPECTED_2XX_CODE);
2652 }
2653
2654 /* Success. Disconnect and unbind the control socket. */
2655 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2656 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2657
2658 /* Release the packet. */
2659 nx_packet_release(packet_ptr);
2660
2661 /* Return success to caller. */
2662 return(NX_SUCCESS);
2663 }
2664
2665
2666 /**************************************************************************/
2667 /* */
2668 /* FUNCTION RELEASE */
2669 /* */
2670 /* _nxe_ftp_client_file_close PORTABLE C */
2671 /* 6.1 */
2672 /* AUTHOR */
2673 /* */
2674 /* Yuxin Zhou, Microsoft Corporation */
2675 /* */
2676 /* DESCRIPTION */
2677 /* */
2678 /* This function checks for errors in the FTP client file close. */
2679 /* */
2680 /* */
2681 /* INPUT */
2682 /* */
2683 /* ftp_client_ptr Pointer to FTP client */
2684 /* wait_option Specifies how long to wait */
2685 /* */
2686 /* OUTPUT */
2687 /* */
2688 /* status Completion status */
2689 /* */
2690 /* CALLS */
2691 /* */
2692 /* _nx_ftp_client_file_close Actual client file close call */
2693 /* */
2694 /* CALLED BY */
2695 /* */
2696 /* Application Code */
2697 /* */
2698 /* RELEASE HISTORY */
2699 /* */
2700 /* DATE NAME DESCRIPTION */
2701 /* */
2702 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2703 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2704 /* resulting in version 6.1 */
2705 /* */
2706 /**************************************************************************/
_nxe_ftp_client_file_close(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)2707 UINT _nxe_ftp_client_file_close(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
2708 {
2709
2710 UINT status;
2711
2712
2713 /* Check for invalid input pointers. */
2714 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
2715 return(NX_PTR_ERROR);
2716
2717
2718 /* Check for appropriate caller. */
2719 NX_THREADS_ONLY_CALLER_CHECKING
2720
2721 /* Call actual client file close function. */
2722 status = _nx_ftp_client_file_close(ftp_client_ptr, wait_option);
2723
2724 /* Return completion status. */
2725 return(status);
2726 }
2727
2728
2729 /**************************************************************************/
2730 /* */
2731 /* FUNCTION RELEASE */
2732 /* */
2733 /* _nx_ftp_client_file_close PORTABLE C */
2734 /* 6.1 */
2735 /* AUTHOR */
2736 /* */
2737 /* Yuxin Zhou, Microsoft Corporation */
2738 /* */
2739 /* DESCRIPTION */
2740 /* */
2741 /* This function closes a previously open client FTP file. */
2742 /* */
2743 /* */
2744 /* INPUT */
2745 /* */
2746 /* ftp_client_ptr Pointer to FTP client */
2747 /* wait_option Specifies how long to wait */
2748 /* */
2749 /* OUTPUT */
2750 /* */
2751 /* status Completion status */
2752 /* */
2753 /* CALLS */
2754 /* */
2755 /* _nx_ftp_client_data_socket_cleanup Cleanup data socket */
2756 /* nx_packet_release Release packet */
2757 /* nx_tcp_server_socket_unaccept Unaccept server connection */
2758 /* nx_tcp_server_socket_unlisten Unlisten on server socket */
2759 /* nx_tcp_socket_disconnect Disconnect a socket */
2760 /* nx_tcp_socket_receive Receive response from server */
2761 /* */
2762 /* CALLED BY */
2763 /* */
2764 /* Application Code */
2765 /* */
2766 /* RELEASE HISTORY */
2767 /* */
2768 /* DATE NAME DESCRIPTION */
2769 /* */
2770 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2771 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2772 /* resulting in version 6.1 */
2773 /* */
2774 /**************************************************************************/
_nx_ftp_client_file_close(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)2775 UINT _nx_ftp_client_file_close(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
2776 {
2777
2778 NX_PACKET *packet_ptr;
2779 UCHAR *buffer_ptr;
2780 UINT status;
2781
2782
2783 /* Ensure the client is in the proper state for closing the socket. */
2784 if (ftp_client_ptr -> nx_ftp_client_state == NX_FTP_STATE_NOT_CONNECTED)
2785 return(NX_FTP_NOT_CONNECTED);
2786 else if ((ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_OPEN) &&
2787 (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_WRITE_OPEN))
2788 return(NX_FTP_NOT_OPEN);
2789
2790 /* Cleanup data socket. */
2791 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2792
2793 /* Set the state to connected. */
2794 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_CONNECTED;
2795
2796 /* Wait for response from the FTP server. */
2797 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
2798
2799 /* Determine if a packet was not received. */
2800 if (status)
2801 {
2802
2803 /* Unable to connect socket to server FTP control port. */
2804 return(status);
2805 }
2806
2807 /* We have a packet, setup pointer to the packet payload area. */
2808 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
2809
2810 /* Check for 2xx message, signaling the close was processed properly. */
2811 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
2812 {
2813
2814 /* Release the packet. */
2815 nx_packet_release(packet_ptr);
2816
2817 /* Return error. */
2818 return(NX_FTP_EXPECTED_2XX_CODE);
2819 }
2820
2821 /* Release the packet. */
2822 nx_packet_release(packet_ptr);
2823
2824 /* Return success to caller. */
2825 return(NX_SUCCESS);
2826 }
2827
2828
2829 /**************************************************************************/
2830 /* */
2831 /* FUNCTION RELEASE */
2832 /* */
2833 /* _nxe_ftp_client_file_delete PORTABLE C */
2834 /* 6.1 */
2835 /* AUTHOR */
2836 /* */
2837 /* Yuxin Zhou, Microsoft Corporation */
2838 /* */
2839 /* DESCRIPTION */
2840 /* */
2841 /* This function checks for errors in the FTP client file delete. */
2842 /* */
2843 /* Note: The string length of file_name is limited by the packet */
2844 /* payload size. */
2845 /* */
2846 /* INPUT */
2847 /* */
2848 /* ftp_client_ptr Pointer to FTP client */
2849 /* file_name File name to delete */
2850 /* wait_option Specifies how long to wait */
2851 /* */
2852 /* OUTPUT */
2853 /* */
2854 /* status Completion status */
2855 /* */
2856 /* CALLS */
2857 /* */
2858 /* _nx_ftp_client_file_delete Actual client file delete call*/
2859 /* */
2860 /* CALLED BY */
2861 /* */
2862 /* Application Code */
2863 /* */
2864 /* RELEASE HISTORY */
2865 /* */
2866 /* DATE NAME DESCRIPTION */
2867 /* */
2868 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2869 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2870 /* resulting in version 6.1 */
2871 /* */
2872 /**************************************************************************/
_nxe_ftp_client_file_delete(NX_FTP_CLIENT * ftp_client_ptr,CHAR * file_name,ULONG wait_option)2873 UINT _nxe_ftp_client_file_delete(NX_FTP_CLIENT *ftp_client_ptr, CHAR *file_name, ULONG wait_option)
2874 {
2875
2876 UINT status;
2877
2878
2879 /* Check for invalid input pointers. */
2880 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (file_name == NX_NULL))
2881 return(NX_PTR_ERROR);
2882
2883 /* Check for appropriate caller. */
2884 NX_THREADS_ONLY_CALLER_CHECKING
2885
2886 /* Call actual client file delete function. */
2887 status = _nx_ftp_client_file_delete(ftp_client_ptr, file_name, wait_option);
2888
2889 /* Return completion status. */
2890 return(status);
2891 }
2892
2893
2894 /**************************************************************************/
2895 /* */
2896 /* FUNCTION RELEASE */
2897 /* */
2898 /* _nx_ftp_client_file_delete PORTABLE C */
2899 /* 6.1 */
2900 /* AUTHOR */
2901 /* */
2902 /* Yuxin Zhou, Microsoft Corporation */
2903 /* */
2904 /* DESCRIPTION */
2905 /* */
2906 /* This function deletes the specified file on the FTP */
2907 /* server. */
2908 /* */
2909 /* Note: The string length of file_name is limited by the packet */
2910 /* payload size. */
2911 /* */
2912 /* INPUT */
2913 /* */
2914 /* ftp_client_ptr Pointer to FTP client */
2915 /* file_name File name to delete */
2916 /* wait_option Specifies how long to wait */
2917 /* */
2918 /* OUTPUT */
2919 /* */
2920 /* status Completion status */
2921 /* */
2922 /* CALLS */
2923 /* */
2924 /* nx_packet_allocate Allocate packet */
2925 /* nx_packet_release Release packet */
2926 /* nx_tcp_socket_receive Receive packet from server */
2927 /* nx_tcp_socket_send Send data packet to server */
2928 /* */
2929 /* CALLED BY */
2930 /* */
2931 /* Application Code */
2932 /* */
2933 /* RELEASE HISTORY */
2934 /* */
2935 /* DATE NAME DESCRIPTION */
2936 /* */
2937 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2938 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2939 /* resulting in version 6.1 */
2940 /* */
2941 /**************************************************************************/
_nx_ftp_client_file_delete(NX_FTP_CLIENT * ftp_client_ptr,CHAR * file_name,ULONG wait_option)2942 UINT _nx_ftp_client_file_delete(NX_FTP_CLIENT *ftp_client_ptr, CHAR *file_name, ULONG wait_option)
2943 {
2944
2945 UINT i;
2946 UCHAR *buffer_ptr;
2947 NX_PACKET *packet_ptr;
2948 UINT status;
2949
2950
2951 /* Ensure the client is the proper state for file delete request. */
2952 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
2953 return(NX_FTP_NOT_CONNECTED);
2954
2955 /* Allocate a packet for sending the file delete command. */
2956 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
2957
2958 /* Determine if the packet allocation was successful. */
2959 if (status)
2960 {
2961
2962 /* Return error. */
2963 return(status);
2964 }
2965
2966 /* Check if out of boundary. */
2967 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 7)
2968 {
2969
2970 /* Release the packet. */
2971 nx_packet_release(packet_ptr);
2972
2973 /* Set the error status. */
2974 return(NX_FTP_FAILED);
2975 }
2976
2977 /* We have a packet, setup pointer to the buffer area. */
2978 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
2979
2980 /* Now build "DELE" message to indicate file delete. */
2981 buffer_ptr[0] = 'D';
2982 buffer_ptr[1] = 'E';
2983 buffer_ptr[2] = 'L';
2984 buffer_ptr[3] = 'E';
2985 buffer_ptr[4] = ' ';
2986
2987 /* Copy the file name into the message. */
2988 for(i = 0; file_name[i]; i++)
2989 {
2990
2991 /* Check if out of boundary. */
2992 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
2993 {
2994
2995 /* Release the packet. */
2996 nx_packet_release(packet_ptr);
2997
2998 /* Set the error status. */
2999 return(NX_FTP_FAILED);
3000 }
3001
3002 /* Copy character of the file name. */
3003 buffer_ptr[5+i] = (UCHAR)file_name[i];
3004 }
3005
3006 /* Set the CR/LF. */
3007 buffer_ptr[i+5] = 13;
3008 buffer_ptr[i+6] = 10;
3009
3010 /* Set the packet length. */
3011 packet_ptr -> nx_packet_length = i+7;
3012
3013 /* Setup the packet append pointer. */
3014 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
3015
3016 /* Send the DELE message. */
3017 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
3018
3019 /* Determine if the send was unsuccessful. */
3020 if (status)
3021 {
3022
3023 /* Release the packet. */
3024 nx_packet_release(packet_ptr);
3025
3026 /* Return error. */
3027 return(status);
3028 }
3029
3030 /* Wait for response from the FTP server. */
3031 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
3032
3033 /* Determine if a packet was not received. */
3034 if (status)
3035 {
3036
3037 /* DELE error. */
3038 return(status);
3039 }
3040
3041 /* We have a packet, setup pointer to the buffer area. */
3042 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3043
3044 /* Check for 2xx message, signaling the "DELE" was processed successfully. */
3045 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
3046 {
3047
3048 /* Release the packet. */
3049 nx_packet_release(packet_ptr);
3050
3051 /* File delete error. */
3052 return(NX_FTP_EXPECTED_2XX_CODE);
3053 }
3054
3055 /* Yes, the file was deleted. */
3056
3057 /* Release the packet. */
3058 nx_packet_release(packet_ptr);
3059
3060 /* Return success to caller. */
3061 return(NX_SUCCESS);
3062 }
3063
3064 /**************************************************************************/
3065 /* */
3066 /* FUNCTION RELEASE */
3067 /* */
3068 /* _nxe_ftp_client_passive_mode_set PORTABLE C */
3069 /* 6.1 */
3070 /* AUTHOR */
3071 /* */
3072 /* Yuxin Zhou, Microsoft Corporation */
3073 /* */
3074 /* DESCRIPTION */
3075 /* */
3076 /* This function sets the request to passive mode. Once this is set */
3077 /* the Client will send a PASV command preceding any FTP Client command*/
3078 /* involving transferring data on the data socket. */
3079 /* */
3080 /* INPUT */
3081 /* */
3082 /* ftp_client_ptr Pointer to FTP client */
3083 /* passive_mode_enabled True to enable */
3084 /* False to disable */
3085 /* */
3086 /* OUTPUT */
3087 /* */
3088 /* NX_PTR_ERROR Invalid pointer input */
3089 /* NX_INVALID_PARAMETERS Invalid non pointer input */
3090 /* status Completion status */
3091 /* */
3092 /* CALLS */
3093 /* None */
3094 /* */
3095 /* CALLED BY */
3096 /* */
3097 /* Application Code */
3098 /* */
3099 /* RELEASE HISTORY */
3100 /* */
3101 /* DATE NAME DESCRIPTION */
3102 /* */
3103 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3104 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3105 /* resulting in version 6.1 */
3106 /* */
3107 /**************************************************************************/
_nxe_ftp_client_passive_mode_set(NX_FTP_CLIENT * ftp_client_ptr,UINT passive_mode_enabled)3108 UINT _nxe_ftp_client_passive_mode_set(NX_FTP_CLIENT *ftp_client_ptr, UINT passive_mode_enabled)
3109 {
3110
3111 UINT status;
3112
3113 if (ftp_client_ptr == NX_NULL)
3114 {
3115 return NX_PTR_ERROR;
3116 }
3117
3118 if ((passive_mode_enabled != NX_TRUE) && (passive_mode_enabled != NX_FALSE))
3119 {
3120 return NX_INVALID_PARAMETERS;
3121 }
3122
3123 status = _nx_ftp_client_passive_mode_set(ftp_client_ptr, passive_mode_enabled);
3124
3125 return status;
3126
3127 }
3128
3129
3130 /**************************************************************************/
3131 /* */
3132 /* FUNCTION RELEASE */
3133 /* */
3134 /* _nx_ftp_client_passive_mode_set PORTABLE C */
3135 /* 6.1 */
3136 /* AUTHOR */
3137 /* */
3138 /* Yuxin Zhou, Microsoft Corporation */
3139 /* */
3140 /* DESCRIPTION */
3141 /* */
3142 /* This function sets the request to passive mode. Once this is set */
3143 /* the Client will send a PASV command preceding any FTP Client command*/
3144 /* for accessing a server data port. If passive mode is not set, */
3145 /* the FTP Client will send and receive data via active transfer mode. */
3146 /* */
3147 /* INPUT */
3148 /* */
3149 /* ftp_client_ptr Pointer to FTP client */
3150 /* passive_mode_enabled True to enable passive mode */
3151 /* False to disable passive mode */
3152 /* */
3153 /* OUTPUT */
3154 /* */
3155 /* NX_SUCCESS Successful completion status */
3156 /* */
3157 /* CALLS */
3158 /* None */
3159 /* */
3160 /* CALLED BY */
3161 /* */
3162 /* Application Code */
3163 /* */
3164 /* RELEASE HISTORY */
3165 /* */
3166 /* DATE NAME DESCRIPTION */
3167 /* */
3168 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3169 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3170 /* resulting in version 6.1 */
3171 /* */
3172 /**************************************************************************/
_nx_ftp_client_passive_mode_set(NX_FTP_CLIENT * ftp_client_ptr,UINT passive_mode_enabled)3173 UINT _nx_ftp_client_passive_mode_set(NX_FTP_CLIENT *ftp_client_ptr, UINT passive_mode_enabled)
3174 {
3175
3176 /* Set the transfer status according to the passive mode enabled input. */
3177 ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled = passive_mode_enabled;
3178
3179 return(NX_SUCCESS);
3180 }
3181
3182
3183 /**************************************************************************/
3184 /* */
3185 /* FUNCTION RELEASE */
3186 /* */
3187 /* _nxe_ftp_client_transfer_mode_set PORTABLE C */
3188 /* 6.1 */
3189 /* AUTHOR */
3190 /* */
3191 /* Yuxin Zhou, Microsoft Corporation */
3192 /* */
3193 /* DESCRIPTION */
3194 /* */
3195 /* This function checks for errors in the FTP transfer mode set. */
3196 /* */
3197 /* INPUT */
3198 /* */
3199 /* ftp_client_ptr Pointer to FTP client */
3200 /* transfer_mode Transfer mode */
3201 /* */
3202 /* OUTPUT */
3203 /* */
3204 /* NX_PTR_ERROR Invalid pointer input */
3205 /* status Completion status */
3206 /* */
3207 /* CALLS */
3208 /* */
3209 /* _nx_ftp_client_transfer_mode_set Actual transfer mode set */
3210 /* */
3211 /* CALLED BY */
3212 /* */
3213 /* Application Code */
3214 /* */
3215 /* RELEASE HISTORY */
3216 /* */
3217 /* DATE NAME DESCRIPTION */
3218 /* */
3219 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3220 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3221 /* resulting in version 6.1 */
3222 /* */
3223 /**************************************************************************/
_nxe_ftp_client_transfer_mode_set(NX_FTP_CLIENT * ftp_client_ptr,UINT transfer_mode)3224 UINT _nxe_ftp_client_transfer_mode_set(NX_FTP_CLIENT *ftp_client_ptr, UINT transfer_mode)
3225 {
3226
3227 UINT status;
3228
3229 /* Check for valid pointer. */
3230 if (ftp_client_ptr == NX_NULL)
3231 {
3232 return(NX_PTR_ERROR);
3233 }
3234
3235 /* Check for appropriate caller. */
3236 NX_THREADS_ONLY_CALLER_CHECKING
3237
3238 /* Call actual transfer mode set function. */
3239 status = _nx_ftp_client_transfer_mode_set(ftp_client_ptr, transfer_mode);
3240
3241 return(status);
3242 }
3243
3244
3245 /**************************************************************************/
3246 /* */
3247 /* FUNCTION RELEASE */
3248 /* */
3249 /* _nx_ftp_client_transfer_mode_set PORTABLE C */
3250 /* 6.1 */
3251 /* AUTHOR */
3252 /* */
3253 /* Yuxin Zhou, Microsoft Corporation */
3254 /* */
3255 /* DESCRIPTION */
3256 /* */
3257 /* This function sets the transfer mode. */
3258 /* Note: just support stream mode and block mode yet. */
3259 /* */
3260 /* INPUT */
3261 /* */
3262 /* ftp_client_ptr Pointer to FTP client */
3263 /* transfer_mode Transfer mode */
3264 /* */
3265 /* OUTPUT */
3266 /* */
3267 /* NX_SUCCESS Successful completion status */
3268 /* NX_INVALID_PARAMETERS Invalid non pointer input */
3269 /* */
3270 /* CALLS */
3271 /* */
3272 /* None */
3273 /* */
3274 /* CALLED BY */
3275 /* */
3276 /* Application Code */
3277 /* */
3278 /* RELEASE HISTORY */
3279 /* */
3280 /* DATE NAME DESCRIPTION */
3281 /* */
3282 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3283 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3284 /* resulting in version 6.1 */
3285 /* */
3286 /**************************************************************************/
_nx_ftp_client_transfer_mode_set(NX_FTP_CLIENT * ftp_client_ptr,UINT transfer_mode)3287 UINT _nx_ftp_client_transfer_mode_set(NX_FTP_CLIENT *ftp_client_ptr, UINT transfer_mode)
3288 {
3289
3290 /* Check for transfer mode. */
3291 if ((transfer_mode != NX_FTP_TRANSFER_MODE_STREAM) &&
3292 (transfer_mode != NX_FTP_TRANSFER_MODE_BLOCK))
3293 {
3294 return(NX_INVALID_PARAMETERS);
3295 }
3296
3297 /* Set the transfer mode. */
3298 ftp_client_ptr -> nx_ftp_client_transfer_mode = transfer_mode;
3299
3300 return(NX_SUCCESS);
3301 }
3302
3303
3304 /**************************************************************************/
3305 /* */
3306 /* FUNCTION RELEASE */
3307 /* */
3308 /* _nxe_ftp_client_file_open PORTABLE C */
3309 /* 6.1 */
3310 /* AUTHOR */
3311 /* */
3312 /* Yuxin Zhou, Microsoft Corporation */
3313 /* */
3314 /* DESCRIPTION */
3315 /* */
3316 /* This function checks for errors in the FTP client file open. */
3317 /* */
3318 /* Note: The string length of file_name is limited by the packet */
3319 /* payload size. */
3320 /* */
3321 /* INPUT */
3322 /* */
3323 /* ftp_client_ptr Pointer to FTP client */
3324 /* file_name Client file name */
3325 /* open_type Open for read or open for */
3326 /* write */
3327 /* wait_option Specifies how long to wait */
3328 /* */
3329 /* OUTPUT */
3330 /* */
3331 /* status Completion status */
3332 /* */
3333 /* CALLS */
3334 /* */
3335 /* _nx_ftp_client_file_open Actual client file open call */
3336 /* */
3337 /* CALLED BY */
3338 /* */
3339 /* Application Code */
3340 /* */
3341 /* RELEASE HISTORY */
3342 /* */
3343 /* DATE NAME DESCRIPTION */
3344 /* */
3345 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3346 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3347 /* resulting in version 6.1 */
3348 /* */
3349 /**************************************************************************/
_nxe_ftp_client_file_open(NX_FTP_CLIENT * ftp_client_ptr,CHAR * file_name,UINT open_type,ULONG wait_option)3350 UINT _nxe_ftp_client_file_open(NX_FTP_CLIENT *ftp_client_ptr, CHAR *file_name, UINT open_type, ULONG wait_option)
3351 {
3352
3353 UINT status;
3354
3355
3356 /* Check for invalid input pointers. */
3357 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (file_name == NX_NULL))
3358 return(NX_PTR_ERROR);
3359
3360 /* Check for illegal open option type. */
3361 if ((open_type != NX_FTP_OPEN_FOR_READ) && (open_type != NX_FTP_OPEN_FOR_WRITE))
3362 return(NX_OPTION_ERROR);
3363
3364 /* Check for appropriate caller. */
3365 NX_THREADS_ONLY_CALLER_CHECKING
3366
3367 /* Call actual client file open function. */
3368 status = _nx_ftp_client_file_open(ftp_client_ptr, file_name, open_type, wait_option);
3369
3370 /* Return completion status. */
3371 return(status);
3372 }
3373
3374
3375 /**************************************************************************/
3376 /* */
3377 /* FUNCTION RELEASE */
3378 /* */
3379 /* _nx_ftp_client_file_open PORTABLE C */
3380 /* 6.1 */
3381 /* AUTHOR */
3382 /* */
3383 /* Yuxin Zhou, Microsoft Corporation */
3384 /* */
3385 /* DESCRIPTION */
3386 /* */
3387 /* This function opens a client FTP file. */
3388 /* */
3389 /* Note: The string length of file_name is limited by the packet */
3390 /* payload size. */
3391 /* */
3392 /* INPUT */
3393 /* */
3394 /* ftp_client_ptr Pointer to FTP client */
3395 /* file_name Client file name */
3396 /* open_type Open for read or open for */
3397 /* write */
3398 /* wait_option Specifies how long to wait */
3399 /* */
3400 /* OUTPUT */
3401 /* */
3402 /* status Completion status */
3403 /* */
3404 /* CALLS */
3405 /* */
3406 /* _nx_ftp_client_packet_allocate Allocate packet */
3407 /* _nx_ftp_client_active_transfer_setup Setup active transfer */
3408 /* _nx_ftp_client_passive_transfer_setup Setup passive transfer */
3409 /* _nx_ftp_client_block_mode_send Send block mode command */
3410 /* _nx_ftp_client_data_socket_cleanup Cleanup data socket */
3411 /* nx_packet_release Release packet */
3412 /* nx_tcp_server_socket_accept Connect data socket to server */
3413 /* nx_tcp_socket_receive Receive response from server */
3414 /* nx_tcp_socket_send Send request to server */
3415 /* */
3416 /* CALLED BY */
3417 /* */
3418 /* Application Code */
3419 /* */
3420 /* RELEASE HISTORY */
3421 /* */
3422 /* DATE NAME DESCRIPTION */
3423 /* */
3424 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3425 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3426 /* resulting in version 6.1 */
3427 /* */
3428 /**************************************************************************/
_nx_ftp_client_file_open(NX_FTP_CLIENT * ftp_client_ptr,CHAR * file_name,UINT open_type,ULONG wait_option)3429 UINT _nx_ftp_client_file_open(NX_FTP_CLIENT *ftp_client_ptr, CHAR *file_name, UINT open_type, ULONG wait_option)
3430 {
3431
3432 UINT i;
3433 UCHAR *buffer_ptr;
3434 NX_PACKET *packet_ptr;
3435 UINT status;
3436
3437
3438 /* Ensure the client is the proper state for an open request. */
3439 if (ftp_client_ptr -> nx_ftp_client_state == NX_FTP_STATE_NOT_CONNECTED)
3440 return(NX_FTP_NOT_CONNECTED);
3441 else if (ftp_client_ptr -> nx_ftp_client_state == NX_FTP_STATE_OPEN)
3442 return(NX_FTP_NOT_CLOSED);
3443 else if (ftp_client_ptr -> nx_ftp_client_state == NX_FTP_STATE_WRITE_OPEN)
3444 return(NX_FTP_NOT_CLOSED);
3445
3446 /* Flush the control socket queue for any old messages before starting a new file open request. */
3447 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, 1);
3448
3449 /* Determine if a packet was received. */
3450 if (status == NX_SUCCESS)
3451 {
3452
3453 /* Just discard it. */
3454 nx_packet_release(packet_ptr);
3455 }
3456
3457 /* Allocate a packet for sending the TYPE command. */
3458 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
3459
3460 /* Determine if the packet allocation was successful. */
3461 if (status != NX_SUCCESS)
3462 {
3463
3464 /* Return error. */
3465 return(status);
3466 }
3467
3468 /* Check if out of boundary. */
3469 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 8)
3470 {
3471
3472 /* Release the packet. */
3473 nx_packet_release(packet_ptr);
3474
3475 /* Set the error status. */
3476 return(NX_INVALID_PACKET);
3477 }
3478
3479 /* We have a packet, setup pointer to the buffer area. */
3480 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3481
3482 /* Now build "TYPE I" message to indicate binary file transfer. */
3483 buffer_ptr[0] = 'T';
3484 buffer_ptr[1] = 'Y';
3485 buffer_ptr[2] = 'P';
3486 buffer_ptr[3] = 'E';
3487 buffer_ptr[4] = ' ';
3488 buffer_ptr[5] = 'I';
3489
3490 /* Set the CR/LF. */
3491 buffer_ptr[6] = 13;
3492 buffer_ptr[7] = 10;
3493
3494 /* Set the packet length. */
3495 packet_ptr -> nx_packet_length = 8;
3496
3497 /* Setup the packet append pointer. */
3498 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
3499
3500 /* Send the TYPE message. */
3501 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
3502
3503 /* Determine if the send was unsuccessful. */
3504 if (status != NX_SUCCESS)
3505 {
3506
3507 /* Release the packet. */
3508 nx_packet_release(packet_ptr);
3509
3510 /* Return error. */
3511 return(status);
3512 }
3513
3514 /* Wait for response from the FTP server. */
3515 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
3516
3517 /* Determine if a packet was not received. */
3518 if (status != NX_SUCCESS)
3519 {
3520
3521 /* Unable to open file with FTP server. */
3522 return(status);
3523 }
3524
3525 #ifndef NX_DISABLE_PACKET_CHAIN
3526 if (packet_ptr -> nx_packet_next)
3527 {
3528
3529 /* Release the packet. */
3530 nx_packet_release(packet_ptr);
3531
3532 /* Return. */
3533 return(NX_INVALID_PACKET);
3534 }
3535 #endif /* NX_DISABLE_PACKET_CHAIN */
3536
3537 /* We have a packet, setup pointer to the buffer area. */
3538 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3539
3540 /* Check for 2xx message, signaling the "TYPE I" was received properly. */
3541 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
3542 {
3543
3544 /* Release the packet. */
3545 nx_packet_release(packet_ptr);
3546
3547 /* Unable to open file with FTP server. */
3548 return(NX_FTP_EXPECTED_2XX_CODE);
3549 }
3550
3551 /* Release the packet. */
3552 nx_packet_release(packet_ptr);
3553
3554 /* Divert to passive mode operation if passive mode is enabled. */
3555 if (ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled)
3556 {
3557
3558 /* Set up the passive transfer mode:
3559 Send PASV request,
3560 Get server IP and port to connect to,
3561 Open data socket based on server info in PASV response. */
3562 status = _nx_ftp_client_passive_transfer_setup(ftp_client_ptr, wait_option);
3563 }
3564 else
3565 {
3566
3567 /* Open in active transfer mode. */
3568 status = _nx_ftp_client_active_transfer_setup(ftp_client_ptr, wait_option);
3569 }
3570
3571 /* Determine if set up successful. */
3572 if (status)
3573 {
3574 return(status);
3575 }
3576
3577 /* Check if enable block mode. */
3578 if (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
3579 {
3580
3581 /* Send MODE B command to FTP server. */
3582 status = _nx_ftp_client_block_mode_send(ftp_client_ptr, wait_option);
3583
3584 /* Determine if the send was unsuccessful. */
3585 if (status != NX_SUCCESS)
3586 {
3587
3588 /* Cleanup data socket. */
3589 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3590 return(status);
3591 }
3592 }
3593
3594 /* Allocate a packet for sending the TYPE command. */
3595 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
3596
3597 /* Determine if the packet allocation was successful. */
3598 if (status != NX_SUCCESS)
3599 {
3600
3601 /* Cleanup data socket. */
3602 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3603
3604 /* Return error. */
3605 return(status);
3606 }
3607
3608 /* We have a packet, setup pointer to the buffer area. */
3609 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3610
3611 /* Now build the actual open request. */
3612 if (open_type == NX_FTP_OPEN_FOR_WRITE)
3613 {
3614
3615 /* File write request, STOR is the command for writing a file. */
3616 buffer_ptr[0] = 'S';
3617 buffer_ptr[1] = 'T';
3618 buffer_ptr[2] = 'O';
3619 buffer_ptr[3] = 'R';
3620 buffer_ptr[4] = ' ';
3621 }
3622 else
3623 {
3624
3625 /* File read request, RETR is the command for reading a file. */
3626 buffer_ptr[0] = 'R';
3627 buffer_ptr[1] = 'E';
3628 buffer_ptr[2] = 'T';
3629 buffer_ptr[3] = 'R';
3630 buffer_ptr[4] = ' ';
3631 }
3632
3633 /* Copy the file name into the buffer. */
3634 for(i = 0; file_name[i]; i++)
3635 {
3636
3637 /* Check if out of boundary. */
3638 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
3639 {
3640
3641 /* Cleanup data socket. */
3642 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3643
3644 /* Release the packet. */
3645 nx_packet_release(packet_ptr);
3646
3647 /* Set the error status. */
3648 return(NX_FTP_FAILED);
3649 }
3650
3651 /* Copy character of file name. */
3652 buffer_ptr[5+i] = (UCHAR)file_name[i];
3653 }
3654
3655 /* Insert the CR/LF. */
3656 buffer_ptr[5+i] = 13;
3657 buffer_ptr[5+i+1] = 10;
3658
3659 /* Setup the length of the packet. */
3660 packet_ptr -> nx_packet_length = i + 7;
3661
3662 /* Setup the packet append pointer. */
3663 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
3664
3665 /* Send the STOR/RETR message. */
3666 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
3667
3668 /* Determine if the send was unsuccessful. */
3669 if (status != NX_SUCCESS)
3670 {
3671
3672 /* Cleanup data socket. */
3673 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3674
3675 /* Release the packet. */
3676 nx_packet_release(packet_ptr);
3677
3678 /* Return error. */
3679 return(status);
3680 }
3681
3682 /* Check if enable passive mode. */
3683 if (ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled == NX_FALSE)
3684 {
3685
3686 /* Active mode. Now wait for the data connection to connect. */
3687 status = nx_tcp_server_socket_accept(&(ftp_client_ptr -> nx_ftp_client_data_socket), wait_option);
3688
3689 /* Determine if the accept was unsuccessful. */
3690 if (status != NX_SUCCESS)
3691 {
3692
3693 /* Cleanup data socket. */
3694 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3695
3696 /* Return error. */
3697 return(status);
3698 }
3699 }
3700
3701 /* Now wait for response from the FTP server control port. */
3702 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
3703
3704 /* Determine if a packet was not received. */
3705 if (status != NX_SUCCESS)
3706 {
3707
3708 /* Cleanup data socket. */
3709 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3710
3711 /* Unable to open file with FTP server. */
3712 return(status);
3713 }
3714
3715 /* We have a packet, setup pointer to the buffer area. */
3716 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3717
3718 /* Check for 1xx message, signaling the data port was connected properly and ready for transfer. */
3719 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '1'))
3720 {
3721
3722 /* Cleanup data socket. */
3723 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3724
3725 /* Release the packet. */
3726 nx_packet_release(packet_ptr);
3727
3728 /* Unable to open file with FTP server. */
3729 return(NX_FTP_EXPECTED_1XX_CODE);
3730 }
3731
3732 /* Release the last packet. */
3733 nx_packet_release(packet_ptr);
3734
3735 /* At this point, the client has successfully opened a FTP connection. */
3736 if (open_type == NX_FTP_OPEN_FOR_WRITE)
3737 {
3738
3739 /* Set the client state to open for write. */
3740 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_WRITE_OPEN;
3741 }
3742 else
3743 {
3744
3745 /* Set the client state to open for read. */
3746 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_OPEN;
3747 }
3748
3749 /* Return success to caller. */
3750 return(NX_SUCCESS);
3751 }
3752
3753
3754 /**************************************************************************/
3755 /* */
3756 /* FUNCTION RELEASE */
3757 /* */
3758 /* _nxe_ftp_client_file_read PORTABLE C */
3759 /* 6.1 */
3760 /* AUTHOR */
3761 /* */
3762 /* Yuxin Zhou, Microsoft Corporation */
3763 /* */
3764 /* DESCRIPTION */
3765 /* */
3766 /* This function checks for errors in the FTP client file read. */
3767 /* */
3768 /* */
3769 /* INPUT */
3770 /* */
3771 /* ftp_client_ptr Pointer to FTP client */
3772 /* packet_ptr Destination of for the */
3773 /* received packet pointer */
3774 /* wait_option Specifies how long to wait */
3775 /* */
3776 /* OUTPUT */
3777 /* */
3778 /* status Completion status */
3779 /* */
3780 /* CALLS */
3781 /* */
3782 /* _nx_ftp_client_file_read Actual client file read call */
3783 /* */
3784 /* CALLED BY */
3785 /* */
3786 /* Application Code */
3787 /* */
3788 /* RELEASE HISTORY */
3789 /* */
3790 /* DATE NAME DESCRIPTION */
3791 /* */
3792 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3793 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3794 /* resulting in version 6.1 */
3795 /* */
3796 /**************************************************************************/
_nxe_ftp_client_file_read(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)3797 UINT _nxe_ftp_client_file_read(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
3798 {
3799
3800 UINT status;
3801
3802
3803 /* Check for invalid input pointers. */
3804 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (packet_ptr == NX_NULL))
3805 return(NX_PTR_ERROR);
3806
3807 /* Check for appropriate caller. */
3808 NX_THREADS_ONLY_CALLER_CHECKING
3809
3810 /* Call actual client file read function. */
3811 status = _nx_ftp_client_file_read(ftp_client_ptr, packet_ptr, wait_option);
3812
3813 /* Return completion status. */
3814 return(status);
3815 }
3816
3817
3818 /**************************************************************************/
3819 /* */
3820 /* FUNCTION RELEASE */
3821 /* */
3822 /* _nx_ftp_client_file_read PORTABLE C */
3823 /* 6.1 */
3824 /* AUTHOR */
3825 /* */
3826 /* Yuxin Zhou, Microsoft Corporation */
3827 /* */
3828 /* DESCRIPTION */
3829 /* */
3830 /* This function reads a packet of the file from the data connection */
3831 /* with the FTP server. */
3832 /* */
3833 /* */
3834 /* INPUT */
3835 /* */
3836 /* ftp_client_ptr Pointer to FTP client */
3837 /* packet_ptr Destination of for the */
3838 /* received packet pointer */
3839 /* wait_option Specifies how long to wait */
3840 /* */
3841 /* OUTPUT */
3842 /* */
3843 /* status Completion status */
3844 /* */
3845 /* CALLS */
3846 /* */
3847 /* nx_tcp_socket_receive Receive response from server */
3848 /* */
3849 /* CALLED BY */
3850 /* */
3851 /* Application Code */
3852 /* */
3853 /* RELEASE HISTORY */
3854 /* */
3855 /* DATE NAME DESCRIPTION */
3856 /* */
3857 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3858 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3859 /* resulting in version 6.1 */
3860 /* */
3861 /**************************************************************************/
_nx_ftp_client_file_read(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)3862 UINT _nx_ftp_client_file_read(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
3863 {
3864
3865 UINT status;
3866
3867
3868 /* Determine if the file is open for writing. */
3869 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_OPEN)
3870 return(NX_FTP_NOT_OPEN);
3871
3872 /* Default the packet pointer to NULL. */
3873 *packet_ptr = NX_NULL;
3874
3875 /* Read the packet from the data connection. */
3876 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_data_socket), packet_ptr, wait_option);
3877
3878 /* Determine if an error occurred. */
3879 if (status == NX_NOT_CONNECTED)
3880 {
3881
3882 /* Map not-connected status to end of file. */
3883 status = NX_FTP_END_OF_FILE;
3884 }
3885
3886 /* Determine if the block mode is enabled. */
3887 if ((status == NX_SUCCESS) &&
3888 (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK))
3889 {
3890
3891 /* Retrieve the block header. */
3892 status = _nx_ftp_client_block_header_retrieve(ftp_client_ptr, (*packet_ptr));
3893 }
3894
3895 /* Return status to caller. */
3896 return(status);
3897 }
3898
3899
3900 /**************************************************************************/
3901 /* */
3902 /* FUNCTION RELEASE */
3903 /* */
3904 /* _nxe_ftp_client_file_rename PORTABLE C */
3905 /* 6.1 */
3906 /* AUTHOR */
3907 /* */
3908 /* Yuxin Zhou, Microsoft Corporation */
3909 /* */
3910 /* DESCRIPTION */
3911 /* */
3912 /* This function checks for errors in the FTP client file rename. */
3913 /* */
3914 /* Note: The string lengths of filename and new_filename are limited */
3915 /* by the packet payload size. */
3916 /* */
3917 /* INPUT */
3918 /* */
3919 /* ftp_client_ptr Pointer to FTP client */
3920 /* filename Current file name */
3921 /* new_filename New file name */
3922 /* wait_option Specifies how long to wait */
3923 /* */
3924 /* OUTPUT */
3925 /* */
3926 /* status Completion status */
3927 /* */
3928 /* CALLS */
3929 /* */
3930 /* _nxe_ftp_client_file_rename Actual client file rename call*/
3931 /* */
3932 /* CALLED BY */
3933 /* */
3934 /* Application Code */
3935 /* */
3936 /* RELEASE HISTORY */
3937 /* */
3938 /* DATE NAME DESCRIPTION */
3939 /* */
3940 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3941 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3942 /* resulting in version 6.1 */
3943 /* */
3944 /**************************************************************************/
_nxe_ftp_client_file_rename(NX_FTP_CLIENT * ftp_client_ptr,CHAR * filename,CHAR * new_filename,ULONG wait_option)3945 UINT _nxe_ftp_client_file_rename(NX_FTP_CLIENT *ftp_client_ptr, CHAR *filename, CHAR *new_filename, ULONG wait_option)
3946 {
3947
3948 UINT status;
3949
3950
3951 /* Check for invalid input pointers. */
3952 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) ||
3953 (filename == NX_NULL) || (new_filename == NX_NULL))
3954 return(NX_PTR_ERROR);
3955
3956 /* Check for appropriate caller. */
3957 NX_THREADS_ONLY_CALLER_CHECKING
3958
3959 /* Call actual client file rename function. */
3960 status = _nx_ftp_client_file_rename(ftp_client_ptr, filename, new_filename, wait_option);
3961
3962 /* Return completion status. */
3963 return(status);
3964 }
3965
3966
3967 /**************************************************************************/
3968 /* */
3969 /* FUNCTION RELEASE */
3970 /* */
3971 /* _nx_ftp_client_file_rename PORTABLE C */
3972 /* 6.1 */
3973 /* AUTHOR */
3974 /* */
3975 /* Yuxin Zhou, Microsoft Corporation */
3976 /* */
3977 /* DESCRIPTION */
3978 /* */
3979 /* This function renames the specified file with the supplied */
3980 /* filename. */
3981 /* */
3982 /* Note: The string lengths of filename and new_filename are limited */
3983 /* by the packet payload size. */
3984 /* */
3985 /* INPUT */
3986 /* */
3987 /* ftp_client_ptr Pointer to FTP client */
3988 /* filename Current file name */
3989 /* new_filename New file name */
3990 /* wait_option Specifies how long to wait */
3991 /* */
3992 /* OUTPUT */
3993 /* */
3994 /* status Completion status */
3995 /* */
3996 /* CALLS */
3997 /* */
3998 /* nx_packet_allocate Allocate packet */
3999 /* nx_packet_release Release packet */
4000 /* nx_tcp_socket_receive Receive packet from server */
4001 /* nx_tcp_socket_send Send data packet to server */
4002 /* */
4003 /* CALLED BY */
4004 /* */
4005 /* Application Code */
4006 /* */
4007 /* RELEASE HISTORY */
4008 /* */
4009 /* DATE NAME DESCRIPTION */
4010 /* */
4011 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4012 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4013 /* resulting in version 6.1 */
4014 /* */
4015 /**************************************************************************/
_nx_ftp_client_file_rename(NX_FTP_CLIENT * ftp_client_ptr,CHAR * filename,CHAR * new_filename,ULONG wait_option)4016 UINT _nx_ftp_client_file_rename(NX_FTP_CLIENT *ftp_client_ptr, CHAR *filename, CHAR *new_filename, ULONG wait_option)
4017 {
4018
4019 UINT i;
4020 UCHAR *buffer_ptr;
4021 NX_PACKET *packet_ptr;
4022 UINT status;
4023
4024
4025 /* Ensure the client is the proper state for a rename file request. */
4026 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
4027 return(NX_FTP_NOT_CONNECTED);
4028
4029 /* Allocate a packet for sending the file rename command. */
4030 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
4031
4032 /* Determine if the packet allocation was successful. */
4033 if (status)
4034 {
4035
4036 /* Return error. */
4037 return(status);
4038 }
4039
4040 /* Check if out of boundary. */
4041 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 7)
4042 {
4043
4044 /* Release the packet. */
4045 nx_packet_release(packet_ptr);
4046
4047 /* Set the error status. */
4048 return(NX_FTP_FAILED);
4049 }
4050
4051 /* We have a packet, setup pointer to the buffer area. */
4052 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
4053
4054 /* Now build "RNFR" message to indicate file rename request. */
4055 buffer_ptr[0] = 'R';
4056 buffer_ptr[1] = 'N';
4057 buffer_ptr[2] = 'F';
4058 buffer_ptr[3] = 'R';
4059 buffer_ptr[4] = ' ';
4060
4061 /* Copy the old file name into the message. */
4062 for(i = 0; filename[i]; i++)
4063 {
4064
4065 /* Check if out of boundary. */
4066 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
4067 {
4068
4069 /* Release the packet. */
4070 nx_packet_release(packet_ptr);
4071
4072 /* Set the error status. */
4073 return(NX_FTP_FAILED);
4074 }
4075
4076 /* Copy character of the file name. */
4077 buffer_ptr[5+i] = (UCHAR)filename[i];
4078 }
4079
4080 /* Set the CR/LF. */
4081 buffer_ptr[i+5] = 13;
4082 buffer_ptr[i+6] = 10;
4083
4084 /* Set the packet length. */
4085 packet_ptr -> nx_packet_length = i+7;
4086
4087 /* Setup the packet append pointer. */
4088 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
4089
4090 /* Send the RNFR message. */
4091 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
4092
4093 /* Determine if the send was unsuccessful. */
4094 if (status)
4095 {
4096
4097 /* Release the packet. */
4098 nx_packet_release(packet_ptr);
4099
4100 /* Return error. */
4101 return(status);
4102 }
4103
4104 /* Wait for response from the FTP server. */
4105 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
4106
4107 /* Determine if a packet was not received. */
4108 if (status)
4109 {
4110
4111 /* RNFR file error. */
4112 return(status);
4113 }
4114
4115 #ifndef NX_DISABLE_PACKET_CHAIN
4116 if (packet_ptr -> nx_packet_next)
4117 {
4118
4119 /* Release the packet. */
4120 nx_packet_release(packet_ptr);
4121
4122 /* Return. */
4123 return(NX_INVALID_PACKET);
4124 }
4125 #endif /* NX_DISABLE_PACKET_CHAIN */
4126
4127 /* We have a packet, setup pointer to the buffer area. */
4128 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
4129
4130 /* Check for 3xx message, signaling the "RNFR" was received properly. */
4131 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '3'))
4132 {
4133
4134 /* Release the packet. */
4135 nx_packet_release(packet_ptr);
4136
4137 /* Unable to rename file with FTP server. */
4138 return(NX_FTP_EXPECTED_3XX_CODE);
4139 }
4140
4141 /* Check if out of boundary. */
4142 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 7)
4143 {
4144
4145 /* Release the packet. */
4146 nx_packet_release(packet_ptr);
4147
4148 /* Set the error status. */
4149 return(NX_FTP_FAILED);
4150 }
4151
4152 /* Now build "RNTO" message to specify new file name. */
4153 buffer_ptr[0] = 'R';
4154 buffer_ptr[1] = 'N';
4155 buffer_ptr[2] = 'T';
4156 buffer_ptr[3] = 'O';
4157 buffer_ptr[4] = ' ';
4158
4159 /* Copy the old file name into the message. */
4160 for(i = 0; new_filename[i]; i++)
4161 {
4162
4163 /* Check if out of boundary. */
4164 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
4165 {
4166
4167 /* Release the packet. */
4168 nx_packet_release(packet_ptr);
4169
4170 /* Set the error status. */
4171 return(NX_FTP_FAILED);
4172 }
4173
4174 /* Copy character of the new file name. */
4175 buffer_ptr[5+i] = (UCHAR)new_filename[i];
4176 }
4177
4178 /* Set the CR/LF. */
4179 buffer_ptr[i+5] = 13;
4180 buffer_ptr[i+6] = 10;
4181
4182 /* Set the packet length. */
4183 packet_ptr -> nx_packet_length = i+7;
4184
4185 /* Setup the packet append pointer. */
4186 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
4187
4188 /* Send the RNTO message. */
4189 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
4190
4191 /* Determine if the send was unsuccessful. */
4192 if (status)
4193 {
4194
4195 /* Release the packet. */
4196 nx_packet_release(packet_ptr);
4197
4198 /* Return error. */
4199 return(status);
4200 }
4201
4202 /* Wait for response from the FTP server. */
4203 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
4204
4205 /* Determine if a packet was not received. */
4206 if (status)
4207 {
4208
4209 /* RNTO file error. */
4210 return(status);
4211 }
4212
4213 /* We have a packet, setup pointer to the buffer area. */
4214 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
4215
4216 /* Check for 2xx message, signaling the "RNTO" was processed properly. */
4217 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
4218 {
4219
4220 /* Release the packet. */
4221 nx_packet_release(packet_ptr);
4222
4223 /* Unable to rename with FTP server. */
4224 return(NX_FTP_EXPECTED_2XX_CODE);
4225 }
4226
4227 /* Release packet. */
4228 nx_packet_release(packet_ptr);
4229
4230 /* Return success to caller. */
4231 return(NX_SUCCESS);
4232 }
4233
4234
4235 /**************************************************************************/
4236 /* */
4237 /* FUNCTION RELEASE */
4238 /* */
4239 /* _nxe_ftp_client_file_size_set PORTABLE C */
4240 /* 6.1 */
4241 /* AUTHOR */
4242 /* */
4243 /* Yuxin Zhou, Microsoft Corporation */
4244 /* */
4245 /* DESCRIPTION */
4246 /* */
4247 /* This function checks for errors in the FTP client file size set. */
4248 /* */
4249 /* */
4250 /* INPUT */
4251 /* */
4252 /* ftp_client_ptr Pointer to FTP client */
4253 /* file_size The total size of file */
4254 /* */
4255 /* OUTPUT */
4256 /* */
4257 /* status Completion status */
4258 /* */
4259 /* CALLS */
4260 /* */
4261 /* _nx_ftp_client_file_size_set Actual file size set call */
4262 /* */
4263 /* CALLED BY */
4264 /* */
4265 /* Application Code */
4266 /* */
4267 /* RELEASE HISTORY */
4268 /* */
4269 /* DATE NAME DESCRIPTION */
4270 /* */
4271 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4272 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4273 /* resulting in version 6.1 */
4274 /* */
4275 /**************************************************************************/
_nxe_ftp_client_file_size_set(NX_FTP_CLIENT * ftp_client_ptr,ULONG file_size)4276 UINT _nxe_ftp_client_file_size_set(NX_FTP_CLIENT *ftp_client_ptr, ULONG file_size)
4277 {
4278
4279 UINT status;
4280
4281
4282 /* Check for invalid input pointers. */
4283 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
4284 return(NX_PTR_ERROR);
4285
4286 /* Check for appropriate caller. */
4287 NX_THREADS_ONLY_CALLER_CHECKING
4288
4289 /* Call actual client file size set function. */
4290 status = _nx_ftp_client_file_size_set(ftp_client_ptr, file_size);
4291
4292 /* Return completion status. */
4293 return(status);
4294 }
4295
4296
4297 /**************************************************************************/
4298 /* */
4299 /* FUNCTION RELEASE */
4300 /* */
4301 /* _nx_ftp_client_file_size_set PORTABLE C */
4302 /* 6.1 */
4303 /* AUTHOR */
4304 /* */
4305 /* Yuxin Zhou, Microsoft Corporation */
4306 /* */
4307 /* DESCRIPTION */
4308 /* */
4309 /* This function sets the file size for block mode before send packets */
4310 /* to the file on the data connection with the FTP server. */
4311 /* */
4312 /* Note:a. This API is only used for block mode, */
4313 /* b. Must call this API before call nx_ftp_client_file_write. */
4314 /* */
4315 /* INPUT */
4316 /* */
4317 /* ftp_client_ptr Pointer to FTP client */
4318 /* file_size The total size of file */
4319 /* */
4320 /* OUTPUT */
4321 /* */
4322 /* status Completion status */
4323 /* */
4324 /* CALLS */
4325 /* */
4326 /* nx_packet_release Release packet */
4327 /* nx_tcp_socket_send Send data packet to server */
4328 /* */
4329 /* CALLED BY */
4330 /* */
4331 /* Application Code */
4332 /* */
4333 /* RELEASE HISTORY */
4334 /* */
4335 /* DATE NAME DESCRIPTION */
4336 /* */
4337 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4338 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4339 /* resulting in version 6.1 */
4340 /* */
4341 /**************************************************************************/
_nx_ftp_client_file_size_set(NX_FTP_CLIENT * ftp_client_ptr,ULONG file_size)4342 UINT _nx_ftp_client_file_size_set(NX_FTP_CLIENT *ftp_client_ptr, ULONG file_size)
4343 {
4344
4345 UINT status;
4346
4347
4348 /* Check for invalid file size. */
4349 if (file_size == 0)
4350 return(NX_FTP_CLIENT_INVALID_SIZE);
4351
4352 /* Check if already set the file size. */
4353 if (ftp_client_ptr -> nx_ftp_client_block_total_size != 0)
4354 return(NX_FTP_CLIENT_FILE_SIZE_ALREADY_SET);
4355
4356 /* Determine if the block mode is enabled. */
4357 if (ftp_client_ptr -> nx_ftp_client_transfer_mode != NX_FTP_TRANSFER_MODE_BLOCK)
4358 return(NX_FTP_CLIENT_NOT_BLOCK_MODE);
4359
4360 /* Determine if the file is open for writing. */
4361 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_WRITE_OPEN)
4362 return(NX_FTP_NOT_OPEN);
4363
4364 /* Send start block header for file size. */
4365 status = _nx_ftp_client_block_header_send(ftp_client_ptr, file_size);
4366
4367 /* Determine if the send was unsuccessful. */
4368 if (status)
4369 {
4370
4371 /* Return error. */
4372 return(status);
4373 }
4374
4375 /* Store the file size for writing. */
4376 ftp_client_ptr -> nx_ftp_client_block_total_size = file_size;
4377 ftp_client_ptr -> nx_ftp_client_block_remaining_size = file_size;
4378
4379 /* Return success to caller. */
4380 return(NX_SUCCESS);
4381 }
4382
4383
4384 /**************************************************************************/
4385 /* */
4386 /* FUNCTION RELEASE */
4387 /* */
4388 /* _nxe_ftp_client_file_write PORTABLE C */
4389 /* 6.1 */
4390 /* AUTHOR */
4391 /* */
4392 /* Yuxin Zhou, Microsoft Corporation */
4393 /* */
4394 /* DESCRIPTION */
4395 /* */
4396 /* This function checks for errors in the FTP client file write. */
4397 /* */
4398 /* */
4399 /* INPUT */
4400 /* */
4401 /* ftp_client_ptr Pointer to FTP client */
4402 /* packet_ptr Pointer to packet to write */
4403 /* wait_option Specifies how long to wait */
4404 /* */
4405 /* OUTPUT */
4406 /* */
4407 /* status Completion status */
4408 /* */
4409 /* CALLS */
4410 /* */
4411 /* _nx_ftp_client_file_write Actual client file write call */
4412 /* */
4413 /* CALLED BY */
4414 /* */
4415 /* Application Code */
4416 /* */
4417 /* RELEASE HISTORY */
4418 /* */
4419 /* DATE NAME DESCRIPTION */
4420 /* */
4421 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4422 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4423 /* resulting in version 6.1 */
4424 /* */
4425 /**************************************************************************/
_nxe_ftp_client_file_write(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET * packet_ptr,ULONG wait_option)4426 UINT _nxe_ftp_client_file_write(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET *packet_ptr, ULONG wait_option)
4427 {
4428
4429 UINT status;
4430
4431
4432 /* Check for invalid input pointers. */
4433 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) ||
4434 (packet_ptr == NX_NULL))
4435 return(NX_PTR_ERROR);
4436
4437 /* Check for appropriate caller. */
4438 NX_THREADS_ONLY_CALLER_CHECKING
4439
4440 /* Call actual client file write function. */
4441 status = _nx_ftp_client_file_write(ftp_client_ptr, packet_ptr, wait_option);
4442
4443 /* Return completion status. */
4444 return(status);
4445 }
4446
4447
4448 /**************************************************************************/
4449 /* */
4450 /* FUNCTION RELEASE */
4451 /* */
4452 /* _nx_ftp_client_file_write PORTABLE C */
4453 /* 6.3.0 */
4454 /* AUTHOR */
4455 /* */
4456 /* Yuxin Zhou, Microsoft Corporation */
4457 /* */
4458 /* DESCRIPTION */
4459 /* */
4460 /* This function writes a packet to the file on the data connection */
4461 /* with the FTP server. */
4462 /* */
4463 /* */
4464 /* INPUT */
4465 /* */
4466 /* ftp_client_ptr Pointer to FTP client */
4467 /* packet_ptr Pointer to packet to write */
4468 /* wait_option Specifies how long to wait */
4469 /* */
4470 /* OUTPUT */
4471 /* */
4472 /* status Completion status */
4473 /* */
4474 /* CALLS */
4475 /* */
4476 /* nx_packet_release Release packet */
4477 /* nx_tcp_socket_send Send data packet to server */
4478 /* */
4479 /* CALLED BY */
4480 /* */
4481 /* Application Code */
4482 /* */
4483 /* RELEASE HISTORY */
4484 /* */
4485 /* DATE NAME DESCRIPTION */
4486 /* */
4487 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4488 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4489 /* resulting in version 6.1 */
4490 /* 10-31-2023 Tiejun Zhou Modified comment(s), */
4491 /* fixed packet double release,*/
4492 /* resulting in version 6.3.0 */
4493 /* */
4494 /**************************************************************************/
_nx_ftp_client_file_write(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET * packet_ptr,ULONG wait_option)4495 UINT _nx_ftp_client_file_write(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET *packet_ptr, ULONG wait_option)
4496 {
4497
4498 UINT status;
4499 ULONG file_size = 0;
4500
4501
4502 /* Determine if the file is open for writing. */
4503 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_WRITE_OPEN)
4504 return(NX_FTP_NOT_OPEN);
4505
4506 /* Determine if the block mode is enabled. */
4507 if (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
4508 {
4509
4510 /* Record the file size. */
4511 file_size = packet_ptr -> nx_packet_length;
4512
4513 /* Check the file size. */
4514 if (ftp_client_ptr -> nx_ftp_client_block_remaining_size < packet_ptr -> nx_packet_length)
4515 return(NX_FTP_CLIENT_INVALID_SIZE);
4516 }
4517
4518 /* Write packet payload to the file. */
4519 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_data_socket), packet_ptr, wait_option);
4520
4521 /* Determine if the send was unsuccessful. */
4522 if (status)
4523 {
4524
4525 /* Return error. */
4526 return(status);
4527 }
4528
4529 /* Determine if the block mode is enabled. */
4530 if (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
4531 {
4532
4533 /* Update the file size. */
4534 ftp_client_ptr -> nx_ftp_client_block_remaining_size -= file_size;
4535
4536 /* Check if the file is already sent. */
4537 if (ftp_client_ptr -> nx_ftp_client_block_remaining_size == 0)
4538 {
4539
4540 /* Send end block header for file size. */
4541 status = _nx_ftp_client_block_header_send(ftp_client_ptr, 0);
4542 }
4543 }
4544
4545 /* Return success to caller. */
4546 return(status);
4547 }
4548
4549
4550 #ifdef FEATURE_NX_IPV6
4551 /**************************************************************************/
4552 /* */
4553 /* FUNCTION RELEASE */
4554 /* */
4555 /* _nx_ftp_utility_convert_IPv6_to_ascii PORTABLE C */
4556 /* 6.1 */
4557 /* AUTHOR */
4558 /* */
4559 /* Yuxin Zhou, Microsoft Corporation */
4560 /* */
4561 /* DESCRIPTION */
4562 /* */
4563 /* This function converts an IP address to ascii e.g. for insertion */
4564 /* into FTP EPRT or PORT command. */
4565 /* */
4566 /* INPUT */
4567 /* */
4568 /* ftp_client_ptr Pointer to FTP client */
4569 /* buffer Pointer to ascii port number string*/
4570 /* buffer_length Size of buffer */
4571 /* size IPv6 address string size */
4572 /* */
4573 /* OUTPUT */
4574 /* */
4575 /* NX_SUCCESS Successful conversion */
4576 /* */
4577 /* CALLS */
4578 /* */
4579 /* _nx_ftp_utility_convert_number_ascii */
4580 /* Converts a single number to ascii */
4581 /* */
4582 /* CALLED BY */
4583 /* */
4584 /* _nx_ftp_client_file_open FTP Client file open service */
4585 /* */
4586 /* RELEASE HISTORY */
4587 /* */
4588 /* DATE NAME DESCRIPTION */
4589 /* */
4590 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4591 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4592 /* verified memcpy use cases, */
4593 /* resulting in version 6.1 */
4594 /* */
4595 /**************************************************************************/
4596
_nx_ftp_utility_convert_IPv6_to_ascii(NX_TCP_SOCKET * socket_ptr,CHAR * buffer,UINT buffer_length,UINT * size)4597 UINT _nx_ftp_utility_convert_IPv6_to_ascii(NX_TCP_SOCKET *socket_ptr, CHAR *buffer, UINT buffer_length, UINT *size)
4598 {
4599
4600
4601 CHAR *temp;
4602 CHAR number_buf[10]; /* 0x20010000 -> "2001:0000:" */
4603
4604
4605 /* Set a pointer to the start of the buffer. */
4606 temp = buffer;
4607
4608 /* Clear the buffer. */
4609 memset(temp, 0, buffer_length);
4610
4611 /* Clear the scratch buffer. */
4612 memset(number_buf, 0, 10);
4613
4614 _nx_ftp_utility_convert_number_ascii(socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address[0], number_buf);
4615
4616 /* Append to string buffer. */
4617 memcpy(temp, number_buf, 10); /* Use case of memcpy is verified. */
4618
4619 /* Move the pointer past this number. */
4620 temp += 10;
4621
4622 /* Clear the scratch buffer. */
4623 memset(number_buf, 0, 10);
4624
4625 _nx_ftp_utility_convert_number_ascii(socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address[1], number_buf);
4626
4627 /* Append to string buffer. */
4628 memcpy(temp, number_buf, 10); /* Use case of memcpy is verified. */
4629
4630 /* Move the pointer past this number. */
4631 temp += 10;
4632
4633 /* Clear the scratch buffer. */
4634 memset(number_buf, 0, 10);
4635
4636 _nx_ftp_utility_convert_number_ascii(socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address[2], number_buf);
4637
4638 /* Append to string buffer. */
4639 memcpy(temp, number_buf, 10); /* Use case of memcpy is verified. */
4640
4641 /* Move the pointer past this number. */
4642 temp += 10;
4643
4644 /* Clear the scratch buffer. */
4645 memset(number_buf, 0, 10);
4646
4647 _nx_ftp_utility_convert_number_ascii(socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address[3], number_buf);
4648
4649 /* Append to string buffer. */
4650 memcpy(temp, number_buf, 10); /* Use case of memcpy is verified. */
4651
4652 /* Move the pointer past this number. */
4653 temp += 10;
4654
4655 /* Remove the trailing ':'. */
4656 *(temp - 1) = 0x0;
4657 *size = 39;
4658
4659 return NX_SUCCESS;
4660 }
4661
4662
4663 /**************************************************************************/
4664 /* */
4665 /* FUNCTION RELEASE */
4666 /* */
4667 /* _nx_ftp_utility_convert_number_ascii PORTABLE C */
4668 /* 6.1 */
4669 /* AUTHOR */
4670 /* */
4671 /* Yuxin Zhou, Microsoft Corporation */
4672 /* */
4673 /* DESCRIPTION */
4674 /* */
4675 /* This function converts a number to ascii text for inserting IP */
4676 /* address and port numbers into FTP EPRT and PORT commands. It is up */
4677 /* to the caller to provide a buffer large enough to hold the ascii */
4678 /* conversion of the input number. */
4679 /* */
4680 /* INPUT */
4681 /* */
4682 /* number Number to convert to ASCII */
4683 /* numstring Pointer to ascii string */
4684 /* */
4685 /* OUTPUT */
4686 /* NX_SUCCESS Successful completion */
4687 /* */
4688 /* CALLS */
4689 /* None */
4690 /* */
4691 /* CALLED BY */
4692 /* _nx_ftp_utility_convert_IPv6_to_ascii */
4693 /* Convert IPv6 address to ASCII */
4694 /* */
4695 /* RELEASE HISTORY */
4696 /* */
4697 /* DATE NAME DESCRIPTION */
4698 /* */
4699 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4700 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4701 /* resulting in version 6.1 */
4702 /* */
4703 /**************************************************************************/
4704
_nx_ftp_utility_convert_number_ascii(ULONG number,CHAR * numstring)4705 UINT _nx_ftp_utility_convert_number_ascii(ULONG number, CHAR *numstring)
4706 {
4707
4708 UINT j;
4709 UCHAR c;
4710
4711 /* Go through each bit of the ULONG to convert. */
4712 for (j = 0; j <=7 ; j++)
4713 {
4714
4715 /* Save the bit off the most significant end. */
4716 c = (UCHAR)((number & 0xF0000000) >> 28);
4717
4718 /* Make it the most significant byte. */
4719 number = number << 4;
4720
4721 /* Convert the digit to an ascii character. */
4722 if (c < 10)
4723 {
4724 *numstring = (CHAR)('0' + c);
4725 }
4726 else /* Handle HEX digits... */
4727 {
4728 *numstring = (CHAR)('A' + (c - 10));
4729 }
4730
4731 /* Move past the digit. */
4732 numstring++;
4733
4734 /* Determine if we need to add a colon. */
4735 if (j == 3 || j == 7)
4736 {
4737 /* Yes, append the colon and move the pointer past it. */
4738 *numstring = ':';
4739 numstring++;
4740 }
4741 }
4742
4743 return NX_SUCCESS;
4744 }
4745
4746
4747 /**************************************************************************/
4748 /* */
4749 /* FUNCTION RELEASE */
4750 /* */
4751 /* _nx_ftp_utility_convert_portnumber_ascii PORTABLE C */
4752 /* 6.1 */
4753 /* AUTHOR */
4754 /* */
4755 /* Yuxin Zhou, Microsoft Corporation */
4756 /* */
4757 /* DESCRIPTION */
4758 /* */
4759 /* This function converts a number to ascii text e.g. used by */
4760 /* _nx_nat_utility_convert_portnumber_ULONG_to_ascii for inserting */
4761 /* changed port numbers back into FTP PORT command . */
4762 /* */
4763 /* INPUT */
4764 /* */
4765 /* number Port number to convert to ASCII */
4766 /* numstring Pointer to ascii portnumber string */
4767 /* numstring_length Portnumber string length */
4768 /* */
4769 /* OUTPUT */
4770 /* */
4771 /* NX_FTP_ERROR Unable to convert e.g. overflow error*/
4772 /* NX_SUCCESS Successful conversion */
4773 /* */
4774 /* CALLS */
4775 /* */
4776 /* None */
4777 /* */
4778 /* CALLED BY */
4779 /* */
4780 /* _nx_ftp_client_file_open Processes the FTP file open service */
4781 /* */
4782 /* */
4783 /* RELEASE HISTORY */
4784 /* */
4785 /* DATE NAME DESCRIPTION */
4786 /* */
4787 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4788 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4789 /* resulting in version 6.1 */
4790 /* */
4791 /**************************************************************************/
4792
_nx_ftp_utility_convert_portnumber_ascii(UINT number,CHAR * numstring,UINT * numstring_length)4793 UINT _nx_ftp_utility_convert_portnumber_ascii(UINT number, CHAR *numstring, UINT *numstring_length)
4794 {
4795
4796 UINT j;
4797 UINT digit;
4798
4799
4800 /* Initialize counters. */
4801 (*numstring_length) = 0;
4802
4803 /* Loop to convert the number to ASCII. */
4804 while ((*numstring_length) < 10)
4805 {
4806
4807 /* Shift the current digits over one. */
4808 for (j = (*numstring_length); j != 0; j--)
4809 {
4810
4811 /* Move each digit over one place. */
4812 numstring[j] = numstring[j-1];
4813 }
4814
4815 /* Compute the next decimal digit. */
4816 digit = number % 10;
4817
4818 /* Update the input number. */
4819 number = number / 10;
4820
4821 /* Store the new digit in ASCII form. */
4822 numstring[0] = (CHAR) (digit + 0x30);
4823
4824 /* Increment the size. */
4825 (*numstring_length)++;
4826
4827 /* Determine if the number is now zero. */
4828 if (number == 0)
4829 break;
4830 }
4831
4832 /* Make the string NULL terminated. */
4833 numstring[(*numstring_length)] = (CHAR) NX_NULL;
4834
4835 /* Determine if there is an overflow error. */
4836 if (number)
4837 {
4838
4839 /* Error, return bad values to user. */
4840 (*numstring_length) = 0;
4841 numstring[0] = '0';
4842 return NX_FTP_INVALID_NUMBER;
4843 }
4844
4845 /* Return size to caller. */
4846 return NX_SUCCESS;
4847 }
4848 #endif
4849
4850
4851 /**************************************************************************/
4852 /* */
4853 /* FUNCTION RELEASE */
4854 /* */
4855 /* _nx_ftp_client_packet_allocate PORTABLE C */
4856 /* 6.1 */
4857 /* AUTHOR */
4858 /* */
4859 /* Yuxin Zhou, Microsoft Corporation */
4860 /* */
4861 /* DESCRIPTION */
4862 /* */
4863 /* This function determines which IP TCP packet to allocate based on */
4864 /* the FTP connection address IP type and then allocates the packet. */
4865 /* */
4866 /* */
4867 /* INPUT */
4868 /* */
4869 /* ftp_client_ptr Pointer to FTP client */
4870 /* packet_ptr Allocated packet to return */
4871 /* wait_option Packet allocate wait option */
4872 /* */
4873 /* OUTPUT */
4874 /* */
4875 /* status Completion status */
4876 /* NX_NOT_ENABLED IPv6 not enabled */
4877 /* */
4878 /* CALLS */
4879 /* */
4880 /* nx_packet_allocate Allocate packet */
4881 /* */
4882 /* CALLED BY */
4883 /* */
4884 /* Application Code */
4885 /* */
4886 /* RELEASE HISTORY */
4887 /* */
4888 /* DATE NAME DESCRIPTION */
4889 /* */
4890 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4891 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4892 /* resulting in version 6.1 */
4893 /* */
4894 /**************************************************************************/
_nx_ftp_client_packet_allocate(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)4895 UINT _nx_ftp_client_packet_allocate(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
4896 {
4897
4898 UINT packet_type;
4899 UINT status;
4900
4901
4902 /* Default to IPv4 TCP packet to allocate. */
4903 packet_type = NX_IPv4_TCP_PACKET;
4904
4905 /* Determine IP version by FTP connection type. */
4906 if (ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
4907 {
4908
4909 #ifndef FEATURE_NX_IPV6
4910
4911 return NX_NOT_ENABLED;
4912 #else
4913
4914 /* Allocate a TCP IPv6 packet. */
4915 packet_type = NX_IPv6_TCP_PACKET;
4916 #endif
4917 }
4918
4919
4920 /* Allocate the actual packet. */
4921 status = nx_packet_allocate(ftp_client_ptr -> nx_ftp_client_packet_pool_ptr, packet_ptr, packet_type, wait_option);
4922
4923 /* Return completion status. */
4924 return status;
4925 }
4926
4927
4928 /**************************************************************************/
4929 /* */
4930 /* FUNCTION RELEASE */
4931 /* */
4932 /* _nx_ftp_client_active_transfer_setup PORTABLE C */
4933 /* 6.1 */
4934 /* AUTHOR */
4935 /* */
4936 /* Yuxin Zhou, Microsoft Corporation */
4937 /* */
4938 /* DESCRIPTION */
4939 /* */
4940 /* This function sets up the Client data socket for active transfer */
4941 /* where the Client data socket is the TCP client. */
4942 /* */
4943 /* Find free port and listen on it, sends the PORT/EPRT command to */
4944 /* server, then wait for a connection from server. */
4945 /* */
4946 /* INPUT */
4947 /* */
4948 /* ftp_client_ptr Pointer to FTP client */
4949 /* wait_option Specifies how long to wait */
4950 /* */
4951 /* OUTPUT */
4952 /* */
4953 /* status Completion status */
4954 /* */
4955 /* CALLS */
4956 /* */
4957 /* _nx_ftp_client_packet_allocate Allocate packet */
4958 /* _nx_ftp_utility_convert_IPv6_to_ascii Convert IPv6 address to ASCII */
4959 /* _nx_ftp_utility_convert_portnumber_ascii Convert port to ASCII */
4960 /* nx_packet_release Release packet */
4961 /* nx_tcp_free_port_find Find a free port */
4962 /* nx_tcp_server_socket_listen Listen for TCP data socket */
4963 /* connection from server */
4964 /* nx_tcp_server_socket_unlisten Unlisten on server socket */
4965 /* nx_tcp_socket_receive Receive response from server */
4966 /* nx_tcp_socket_send Send request to server */
4967 /* */
4968 /* CALLED BY */
4969 /* */
4970 /* _nx_ftp_client_file_open Open a file for read or write */
4971 /* _nx_ftp_client_directory_listing_get Get directory list */
4972 /* */
4973 /* RELEASE HISTORY */
4974 /* */
4975 /* DATE NAME DESCRIPTION */
4976 /* */
4977 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4978 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4979 /* verified memcpy use cases, */
4980 /* fixed packet leak, */
4981 /* resulting in version 6.1 */
4982 /* */
4983 /**************************************************************************/
_nx_ftp_client_active_transfer_setup(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)4984 UINT _nx_ftp_client_active_transfer_setup(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
4985 {
4986
4987 UINT status;
4988 UINT data_port;
4989 #ifndef NX_DISABLE_IPV4
4990 ULONG ip_address;
4991 #endif /* NX_DISABLE_IPV4 */
4992 UCHAR *buffer_ptr;
4993 NX_PACKET *packet_ptr;
4994 #ifdef FEATURE_NX_IPV6
4995 UINT ipduo_size;
4996 #endif
4997
4998
4999 /* Pickup the next free port for the data socket. */
5000 status = nx_tcp_free_port_find(ftp_client_ptr -> nx_ftp_client_ip_ptr,
5001 ftp_client_ptr -> nx_ftp_client_data_port + 1, &data_port);
5002
5003 /* Determine if the port find was successful. */
5004 if (status != NX_SUCCESS)
5005 {
5006 return(status);
5007 }
5008
5009 /* Save the data port to the client record. */
5010 ftp_client_ptr -> nx_ftp_client_data_port = data_port;
5011
5012 /* Start listening on the data port. */
5013 status = nx_tcp_server_socket_listen(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port, &(ftp_client_ptr -> nx_ftp_client_data_socket), 5, NX_NULL);
5014
5015 /* Determine if the listen is successful. */
5016 if (status != NX_SUCCESS)
5017 {
5018
5019 /* Return error. */
5020 return(status);
5021 }
5022
5023 /* Allocate a packet for sending the PORT/EPRT command. */
5024 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
5025
5026 /* Determine if the packet allocation was successful. */
5027 if (status != NX_SUCCESS)
5028 {
5029
5030 /* Stop listening on the data port. */
5031 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5032
5033 /* Return error. */
5034 return(status);
5035 }
5036
5037 /* We have a packet, setup pointer to the buffer area. */
5038 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5039
5040 /* Now build the IP and port number FTP message. */
5041 if (ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
5042 {
5043 #ifndef FEATURE_NX_IPV6
5044 return NX_NOT_ENABLED;
5045 #else
5046 CHAR ipduo_buffer[NX_FTP_IPV6_ADDRESS_BUFSIZE];
5047 UINT index;
5048
5049 /* EPRT command: EPRT |2|1080::8:800:200C:417A|5282|
5050 RFC2428, Section2, Page3. */
5051
5052 /* Check if out of boundary.
5053 Max EPRT command sring: 8 ("EPRT |2|") + 39 (IPv6 address string) + 1 ('|') + 5 (Max port string) + 1 ('|') + 2 ("\r\n") = 56. */
5054 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 56)
5055 {
5056
5057 /* Stop listening on the data port. */
5058 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5059
5060 /* Release the packet. */
5061 nx_packet_release(packet_ptr);
5062
5063 /* Set the error status. */
5064 return(NX_INVALID_PACKET);
5065 }
5066
5067 buffer_ptr[0] = 'E';
5068 buffer_ptr[1] = 'P';
5069 buffer_ptr[2] = 'R';
5070 buffer_ptr[3] = 'T';
5071 buffer_ptr[4] = ' ';
5072 buffer_ptr[5] = '|';
5073 buffer_ptr[6] = '2';
5074 buffer_ptr[7] = '|';
5075
5076 /* Convert the PORT command ipv6 address and port number format to ascii text. */
5077
5078 /* Clear our scratch buffer. */
5079 memset(&ipduo_buffer[0], 0, NX_FTP_IPV6_ADDRESS_BUFSIZE);
5080
5081 /* Convert the IPv6 address to text. */
5082 status = _nx_ftp_utility_convert_IPv6_to_ascii(&(ftp_client_ptr -> nx_ftp_client_control_socket),
5083 &ipduo_buffer[0], NX_FTP_IPV6_ADDRESS_BUFSIZE, &ipduo_size);
5084
5085 /* Append to the packet buffer . */
5086 memcpy(buffer_ptr + 8, ipduo_buffer, ipduo_size); /* Use case of memcpy is verified. */
5087
5088 /* Update the index past the IPv6 address. */
5089 index = 8 + ipduo_size;
5090
5091 /* Add the required space character. */
5092 buffer_ptr[index++] = '|';
5093
5094 /* Clear the scratch buffer again. */
5095 memset(&ipduo_buffer[0], 0, NX_FTP_IPV6_ADDRESS_BUFSIZE);
5096
5097 /* Convert the preferred port to ascii. */
5098 status = _nx_ftp_utility_convert_portnumber_ascii(data_port, &ipduo_buffer[0], &ipduo_size);
5099
5100 /* Append to the packet buffer. */
5101 memcpy(buffer_ptr + index, ipduo_buffer, ipduo_size); /* Use case of memcpy is verified. */
5102
5103 /* Update the index past the port. */
5104 index += ipduo_size;
5105
5106 /* Add the required space character. */
5107 buffer_ptr[index++] = '|';
5108
5109 /* Set the CR/LF. */
5110 buffer_ptr[index++] = 13;
5111 buffer_ptr[index++] = 10;
5112
5113 /* Set the packet length. */
5114 packet_ptr -> nx_packet_length = index;
5115 #endif /* FEATURE_NX_IPV6 */
5116 }
5117 else
5118 {
5119 /* IPv4 FTP connection */
5120 #ifdef NX_DISABLE_IPV4
5121 return NX_NOT_ENABLED;
5122 #else
5123
5124 /* Check if out of boundary. */
5125 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 30)
5126 {
5127
5128 /* Stop listening on the data port. */
5129 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5130
5131 /* Release the packet. */
5132 nx_packet_release(packet_ptr);
5133
5134 /* Set the error status. */
5135 return(NX_INVALID_PACKET);
5136 }
5137
5138 /* Pickup the IPv4 address of this IP instance. */
5139 ip_address = ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_interface -> nx_interface_ip_address ;
5140
5141 /* Now build the IP and port number FTP message. */
5142 buffer_ptr[0] = 'P';
5143 buffer_ptr[1] = 'O';
5144 buffer_ptr[2] = 'R';
5145 buffer_ptr[3] = 'T';
5146 buffer_ptr[4] = ' ';
5147
5148 buffer_ptr[5] = (UCHAR)('0' + (ip_address >> 24)/100);
5149 buffer_ptr[6] = (UCHAR)('0' + ((ip_address >> 24)/10)%10);
5150 buffer_ptr[7] = (UCHAR)('0' + (ip_address >> 24)%10);
5151 buffer_ptr[8] = ',';
5152
5153 buffer_ptr[9] = (UCHAR)('0' + ((ip_address >> 16) & 0xFF)/100);
5154 buffer_ptr[10] = (UCHAR)('0' + (((ip_address >> 16) & 0xFF)/10)%10);
5155 buffer_ptr[11] = (UCHAR)('0' + ((ip_address >> 16) & 0xFF)%10);
5156 buffer_ptr[12] = ',';
5157
5158 buffer_ptr[13] = (UCHAR)('0' + ((ip_address >> 8) & 0xFF)/100);
5159 buffer_ptr[14] = (UCHAR)('0' + (((ip_address >> 8) & 0xFF)/10)%10);
5160 buffer_ptr[15] = (UCHAR)('0' + ((ip_address >> 8) & 0xFF)%10);
5161 buffer_ptr[16] = ',';
5162
5163 buffer_ptr[17] = (UCHAR)('0' + (ip_address & 0xFF)/100);
5164 buffer_ptr[18] = (UCHAR)('0' + ((ip_address & 0xFF)/10)%10);
5165 buffer_ptr[19] = (UCHAR)('0' + (ip_address & 0xFF)%10);
5166 buffer_ptr[20] = ',';
5167
5168 buffer_ptr[21] = (UCHAR)('0' + (data_port >> 8)/100);
5169 buffer_ptr[22] = (UCHAR)('0' + ((data_port >> 8)/10)%10);
5170 buffer_ptr[23] = (UCHAR)('0' + ((data_port >> 8)%10));
5171 buffer_ptr[24] = ',';
5172
5173 buffer_ptr[25] = (UCHAR)('0' + (data_port & 255)/100);
5174 buffer_ptr[26] = (UCHAR)('0' + ((data_port & 255)/10)%10);
5175 buffer_ptr[27] = (UCHAR)('0' + ((data_port & 255)%10));
5176
5177 /* Set the CR/LF. */
5178 buffer_ptr[28] = 13;
5179 buffer_ptr[29] = 10;
5180
5181 /* Set the packet length. */
5182 packet_ptr -> nx_packet_length = 30;
5183 #endif /* NX_DISABLE_IPV4 */
5184 }
5185
5186 /* Setup the packet append pointer. */
5187 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
5188
5189 /* Send the PORT/EPRT message. */
5190 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
5191
5192 /* Determine if the send was unsuccessful. */
5193 if (status != NX_SUCCESS)
5194 {
5195
5196 /* Stop listening on the data port. */
5197 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5198
5199 /* Release the packet. */
5200 nx_packet_release(packet_ptr);
5201
5202 /* Return error. */
5203 return(status);
5204 }
5205
5206 /* Wait for response from the FTP server. */
5207 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
5208
5209 /* Determine if a packet was not received. */
5210 if (status != NX_SUCCESS)
5211 {
5212
5213 /* Stop listening on the data port. */
5214 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5215
5216 /* Unable to open file with FTP server. */
5217 return(status);
5218 }
5219
5220 /* We have a packet, setup pointer to the buffer area. */
5221 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5222
5223 /* Check for 2xx message, signaling the IP/port was received properly. */
5224 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
5225 {
5226
5227 /* Stop listening on the data port. */
5228 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5229
5230 /* Release the packet. */
5231 nx_packet_release(packet_ptr);
5232
5233 /* Unable to open file with FTP server. */
5234 return(NX_FTP_EXPECTED_2XX_CODE);
5235 }
5236
5237 /* Release the packet. */
5238 nx_packet_release(packet_ptr);
5239
5240 return(NX_SUCCESS);
5241 }
5242
5243
5244 /**************************************************************************/
5245 /* */
5246 /* FUNCTION RELEASE */
5247 /* */
5248 /* _nx_ftp_client_passive_transfer_setup PORTABLE C */
5249 /* 6.1 */
5250 /* AUTHOR */
5251 /* */
5252 /* Yuxin Zhou, Microsoft Corporation */
5253 /* */
5254 /* DESCRIPTION */
5255 /* */
5256 /* This function sets up the Client data socket for passive transfer */
5257 /* where the Client data socket is the TCP client. */
5258 /* */
5259 /* It sends the PASV command and if the server sends an OK status, it */
5260 /* extracts the server connection info from the server response and */
5261 /* opens a connection on the data socket. */
5262 /* */
5263 /* INPUT */
5264 /* */
5265 /* ftp_client_ptr Pointer to FTP client */
5266 /* wait_option Specifies how long to wait */
5267 /* */
5268 /* OUTPUT */
5269 /* */
5270 /* status Completion status */
5271 /* */
5272 /* CALLS */
5273 /* */
5274 /* _nx_ftp_client_packet_allocate Allocate packet */
5275 /* nx_packet_release Release packet */
5276 /* nx_tcp_client_socket_bind Bind the data socket to a port*/
5277 /* nxd_tcp_client_socket_connect Connect to server data socket */
5278 /* nx_tcp_socket_receive Receive response from server */
5279 /* nx_tcp_socket_send Send request to server */
5280 /* */
5281 /* CALLED BY */
5282 /* */
5283 /* _nx_ftp_client_file_open Open a file for read or write */
5284 /* _nx_ftp_client_directory_listing_get Get directory list */
5285 /* */
5286 /* RELEASE HISTORY */
5287 /* */
5288 /* DATE NAME DESCRIPTION */
5289 /* */
5290 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5291 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5292 /* resulting in version 6.1 */
5293 /* */
5294 /**************************************************************************/
_nx_ftp_client_passive_transfer_setup(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)5295 UINT _nx_ftp_client_passive_transfer_setup(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
5296 {
5297
5298 UCHAR *buffer_ptr;
5299 NX_PACKET *packet_ptr;
5300 UINT status;
5301 UINT i;
5302 UINT data_port;
5303 #ifndef NX_DISABLE_IPV4
5304 UINT commas = 0;
5305 ULONG ip_address = 0;
5306 ULONG temp = 0;
5307 #endif /* NX_DISABLE_IPV4 */
5308
5309
5310 /* Send the PASV command to switch to passive mode. */
5311
5312 /* Allocate a packet for sending the TYPE command. */
5313 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
5314
5315 /* Determine if the packet allocation was successful. */
5316 if (status != NX_SUCCESS)
5317 {
5318
5319 /* Return error. */
5320 return(status);
5321 }
5322
5323 /* Check if out of boundary. */
5324 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 6)
5325 {
5326
5327 /* Release the packet. */
5328 nx_packet_release(packet_ptr);
5329
5330 /* Set the error status. */
5331 return(NX_FTP_FAILED);
5332 }
5333
5334 /* We have a packet, setup pointer to the buffer area. */
5335 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5336
5337 if (ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
5338 {
5339 #ifndef FEATURE_NX_IPV6
5340 return(NX_NOT_ENABLED);
5341 #else
5342
5343 /* Now build "EPSV" message. RFC2428. */
5344 buffer_ptr[0] = 'E';
5345 buffer_ptr[1] = 'P';
5346 buffer_ptr[2] = 'S';
5347 buffer_ptr[3] = 'V';
5348 #endif /* FEATURE_NX_IPV6 */
5349 }
5350 else
5351 {
5352 #ifdef NX_DISABLE_IPV4
5353 return(NX_NOT_ENABLED);
5354 #else
5355
5356 /* Now build "PASV" message . */
5357 buffer_ptr[0] = 'P';
5358 buffer_ptr[1] = 'A';
5359 buffer_ptr[2] = 'S';
5360 buffer_ptr[3] = 'V';
5361 #endif /* NX_DISABLE_IPV4 */
5362 }
5363
5364 /* Set the CR/LF. */
5365 buffer_ptr[4] = 13;
5366 buffer_ptr[5] = 10;
5367
5368 /* Set the packet length. */
5369 packet_ptr -> nx_packet_length = 6;
5370
5371 /* Setup the packet append pointer. */
5372 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
5373
5374 /* Send the PASV or EPSV message. */
5375 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
5376
5377 /* Determine if the send was unsuccessful. */
5378 if (status != NX_SUCCESS)
5379 {
5380
5381 /* Release the packet. */
5382 nx_packet_release(packet_ptr);
5383
5384 /* Return error. */
5385 return(status);
5386 }
5387
5388 /* Wait for response from the FTP server. */
5389 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
5390
5391 /* Determine if a packet was not received. */
5392 if (status != NX_SUCCESS)
5393 {
5394
5395 /* Unable to open file with FTP server. */
5396 return(status);
5397 }
5398
5399 /* Setup pointer to the buffer area. */
5400 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5401
5402 if (ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
5403 {
5404 #ifndef FEATURE_NX_IPV6
5405 return(NX_NOT_ENABLED);
5406 #else
5407
5408 /* EPSV command, RFC2428. */
5409
5410 /* Check for 2xx message, signaling the "EPSV" was received properly. */
5411 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2') || (buffer_ptr[1] != '2') || (buffer_ptr[2] != '9'))
5412 {
5413
5414 /* Release the packet. */
5415 nx_packet_release(packet_ptr);
5416
5417 /* Unable to open file with FTP server. */
5418 return(NX_FTP_EXPECTED_2XX_CODE);
5419 }
5420
5421 /* The text returned in response to the EPSV command MUST be:
5422 <text indicating server is entering extended passive mode> \
5423 (<d><d><d><tcp-port><d>) */
5424
5425 /* The netowrk address used to establish the data connnection will be the same
5426 network address used for the control connection.
5427 An example response string follows:
5428 Entering Extended Passive Mode (|||6446|) */
5429
5430 /* Check the length. command + <sp> + passive key word "(|||"*/
5431 if (packet_ptr -> nx_packet_length < 8)
5432 {
5433
5434 /* Release the packet. */
5435 nx_packet_release(packet_ptr);
5436 return(NX_FTP_INVALID_COMMAND);
5437 }
5438
5439 /* Set the index. */
5440 i = 7;
5441
5442 /* Skip the text to locate the key word "(|||". */
5443 while (i < packet_ptr -> nx_packet_length)
5444 {
5445
5446 /* Check if match the key word. */
5447 if ((buffer_ptr[i - 3] == '(') &&
5448 (buffer_ptr[i - 2] == '|') &&
5449 (buffer_ptr[i - 1] == '|') &&
5450 (buffer_ptr[i] == '|'))
5451 {
5452 break;
5453 }
5454
5455 /* Move to next character. */
5456 i++;
5457 }
5458
5459 /* Check for properly formated address command from server. */
5460 if (i >= packet_ptr -> nx_packet_length)
5461 {
5462
5463 /* Release the packet. */
5464 nx_packet_release(packet_ptr);
5465 return(NX_FTP_INVALID_COMMAND);
5466 }
5467
5468 /* Update the index to pickup the port number. */
5469 data_port = 0;
5470 i++;
5471 while ((i < packet_ptr -> nx_packet_length) && (buffer_ptr[i] != '|'))
5472 {
5473
5474 /* Is a numeric character present? */
5475 if ((buffer_ptr[i] < '0') || (buffer_ptr[i] > '9'))
5476 {
5477
5478 /* Invalid port number. */
5479 break;
5480 }
5481
5482 /* Yes, numeric character is present. Update the IP port. */
5483 data_port = (data_port * 10) + (UINT) (buffer_ptr[i] - '0');
5484
5485 /* Move to next character. */
5486 i++;
5487 }
5488
5489 /* At this point we are done with the packet. */
5490 nx_packet_release(packet_ptr);
5491
5492 /* Determine if an error occurred. */
5493 if ((buffer_ptr[i] != '|') || (data_port == 0))
5494 {
5495
5496 /* Set the error status. */
5497 return(NX_FTP_INVALID_COMMAND);
5498 }
5499
5500 /* Save the passive IP address and data port. */
5501 COPY_NXD_ADDRESS(&(ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_ip), &(ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_ip));
5502 ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_port = data_port;
5503 #endif /* FEATURE_NX_IPV6 */
5504 }
5505 else
5506 {
5507 #ifdef NX_DISABLE_IPV4
5508 return(NX_NOT_ENABLED);
5509 #else
5510
5511 /* Check for 2xx message, signaling the "PASV" was received properly. */
5512 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2') || (buffer_ptr[1] != '2') || (buffer_ptr[2] != '7'))
5513 {
5514
5515 /* Release the packet. */
5516 nx_packet_release(packet_ptr);
5517
5518 /* Unable to open file with FTP server. */
5519 return(NX_FTP_EXPECTED_2XX_CODE);
5520 }
5521
5522 /* Now parse the address and port for the Client to connect to on the data socket.
5523 IP address and port are comma delimited and port number is the last two numbers,
5524 PASV port = (p1 * 256) + p2. */
5525
5526 /* Skip non numeric text and whitespace. */
5527 i = 3;
5528 while (((buffer_ptr[i] > '9') || (buffer_ptr[i] < '0')) && (i < packet_ptr -> nx_packet_length))
5529 {
5530 i++;
5531 }
5532
5533 /* Check for properly formated command from server. */
5534 if (i >= packet_ptr -> nx_packet_length)
5535 {
5536
5537 /* Release the packet. */
5538 nx_packet_release(packet_ptr);
5539 return NX_FTP_INVALID_COMMAND;
5540 }
5541
5542 /* First, pickup the IP address. */
5543 commas = 0;
5544 ip_address = 0;
5545 temp = 0;
5546 status = NX_SUCCESS;
5547
5548 while (i < packet_ptr -> nx_packet_length)
5549 {
5550
5551 /* Is a numeric character present? */
5552 if ((buffer_ptr[i] >= '0') && (buffer_ptr[i] <= '9'))
5553 {
5554
5555 /* Yes, numeric character is present. Update the IP address. */
5556 temp = (temp*10) + (ULONG) (buffer_ptr[i] - '0');
5557 }
5558
5559 /* Determine if a CR/LF is present. */
5560 if ((buffer_ptr[i] == 0x0D) || (buffer_ptr[i] == 0x0A) || (buffer_ptr[i] == 0))
5561 {
5562 status = NX_FTP_INVALID_COMMAND;
5563 break;
5564 }
5565
5566 /* Determine if a comma is present. */
5567 if (buffer_ptr[i] == ',')
5568 {
5569
5570 /* Increment the comma count. */
5571 commas++;
5572
5573 /* Setup next byte of IP address. */
5574 ip_address = (ip_address << 8) & 0xFFFFFFFF;
5575 ip_address = ip_address | (temp & 0xFF);
5576 temp = 0;
5577
5578 /* Have we finished with the IP address? */
5579 if (commas == 4)
5580 {
5581
5582 /* Finished with IP address. */
5583 i++;
5584 break;
5585 }
5586 }
5587
5588 /* Move to next character. */
5589 i++;
5590 }
5591
5592 /* Now pickup the port number. */
5593 data_port = 0;
5594 temp = 0;
5595 while (i < packet_ptr -> nx_packet_length)
5596 {
5597
5598 /* Is a numeric character present? */
5599 if ((buffer_ptr[i] >= '0') && (buffer_ptr[i] <= '9'))
5600 {
5601
5602 /* Yes, numeric character is present. Update the IP port. */
5603 temp = (temp*10) + (UINT) (buffer_ptr[i] - '0');
5604 }
5605
5606 /* Determine if a CR/LF is present. */
5607 if ((buffer_ptr[i] == 0x0D) || (buffer_ptr[i] == 0x0A) || (buffer_ptr[i] == 0))
5608 {
5609 /* Good condition on the port number! */
5610 break;
5611 }
5612
5613 /* Determine if a comma is present. */
5614 if (buffer_ptr[i] == ',')
5615 {
5616
5617 /* Increment the comma count. */
5618 commas++;
5619
5620 /* Move the data port number up. */
5621 data_port = (data_port << 8) & 0xFFFFFFFF;
5622 data_port = data_port | (temp & 0xFF);
5623 temp = 0;
5624
5625 /* Have we finished with the port? */
5626 if (commas >= 6)
5627 {
5628
5629 /* Error, get out of the loop. */
5630 status = NX_FTP_INVALID_ADDRESS;
5631 break;
5632 }
5633 }
5634
5635 /* Move to next character. */
5636 i++;
5637 }
5638
5639 /* Move port number up. */
5640 data_port = (data_port << 8) & 0xFFFFFFFF;
5641 data_port = data_port | (temp & 0xFF);
5642
5643 /* At this point we are done with the packet. */
5644 nx_packet_release(packet_ptr);
5645
5646 /* Determine if an error occurred. */
5647 if ((status != NX_SUCCESS) || (buffer_ptr[i] != 13) || (commas != 5) || (ip_address == 0) || (data_port == 0))
5648 {
5649
5650 /* Set the error status. */
5651 return NX_FTP_INVALID_COMMAND;
5652 }
5653
5654 /* Save the passive IP address and data port. */
5655 ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_ip.nxd_ip_version = NX_IP_VERSION_V4;
5656 ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v4 = ip_address;
5657 ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_port = data_port;
5658
5659 #endif /* NX_DISABLE_IPV4 */
5660 }
5661
5662 /* Bind the client data socket to any port. */
5663 status = nx_tcp_client_socket_bind((&ftp_client_ptr -> nx_ftp_client_data_socket), NX_ANY_PORT, wait_option);
5664
5665 /* Check for an error. */
5666 if (status != NX_SUCCESS)
5667 {
5668
5669 /* Unable to bind socket to port. */
5670 return(status);
5671 }
5672
5673 /* Now connect to the IP address and port the server asked us to. */
5674 status = nxd_tcp_client_socket_connect(&(ftp_client_ptr -> nx_ftp_client_data_socket),
5675 &(ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_ip),
5676 data_port, wait_option);
5677
5678 /* Check for an error. */
5679 if (status != NX_SUCCESS)
5680 {
5681
5682 /* Unbind the socket. */
5683 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_data_socket));
5684 }
5685
5686 return(status);
5687 }
5688
5689
5690 /**************************************************************************/
5691 /* */
5692 /* FUNCTION RELEASE */
5693 /* */
5694 /* _nx_ftp_client_data_socket_cleanup PORTABLE C */
5695 /* 6.1 */
5696 /* AUTHOR */
5697 /* */
5698 /* Yuxin Zhou, Microsoft Corporation */
5699 /* */
5700 /* DESCRIPTION */
5701 /* */
5702 /* This function cleans up the data socket. */
5703 /* */
5704 /* INPUT */
5705 /* */
5706 /* ftp_client_ptr Pointer to FTP client */
5707 /* */
5708 /* OUTPUT */
5709 /* */
5710 /* None */
5711 /* */
5712 /* CALLS */
5713 /* */
5714 /* nx_tcp_socket_disconnect Disconnect a socket */
5715 /* nx_tcp_client_socket_unbind Release the data socket port */
5716 /* nx_tcp_server_socket_unaccept Unaccept server connection */
5717 /* nx_tcp_server_socket_unlisten Unlisten on server socket */
5718 /* */
5719 /* CALLED BY */
5720 /* */
5721 /* _nx_ftp_client_file_open Open a file for read or write */
5722 /* _nx_ftp_client_file_close Actual client file close call */
5723 /* _nx_ftp_client_directory_listing_get Get directory list */
5724 /* _nx_ftp_client_directory_listing_continue */
5725 /* Continue to get directory list*/
5726 /* */
5727 /* RELEASE HISTORY */
5728 /* */
5729 /* DATE NAME DESCRIPTION */
5730 /* */
5731 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5732 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5733 /* resulting in version 6.1 */
5734 /* */
5735 /**************************************************************************/
_nx_ftp_client_data_socket_cleanup(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)5736 VOID _nx_ftp_client_data_socket_cleanup(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
5737 {
5738
5739
5740 /* Disconnect the data socket. */
5741 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_data_socket), wait_option);
5742
5743 /* Check if enable passive mode. */
5744 if (ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled == NX_FALSE)
5745 {
5746
5747 /* Unaccept the data socket. */
5748 nx_tcp_server_socket_unaccept(&(ftp_client_ptr -> nx_ftp_client_data_socket));
5749
5750 /* Stop listening on the data port. */
5751 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr,
5752 ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_port);
5753 }
5754 else
5755 {
5756
5757 /* Release the socket port. */
5758 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_data_socket));
5759 }
5760
5761 /* Clear the block size. */
5762 ftp_client_ptr -> nx_ftp_client_block_total_size = 0;
5763 ftp_client_ptr -> nx_ftp_client_block_remaining_size = 0;
5764 }
5765
5766
5767 /**************************************************************************/
5768 /* */
5769 /* FUNCTION RELEASE */
5770 /* */
5771 /* _nx_ftp_client_block_mode_send PORTABLE C */
5772 /* 6.1 */
5773 /* AUTHOR */
5774 /* */
5775 /* Yuxin Zhou, Microsoft Corporation */
5776 /* */
5777 /* DESCRIPTION */
5778 /* */
5779 /* This function sends MODE B command to FTP server for block mode. */
5780 /* */
5781 /* INPUT */
5782 /* */
5783 /* ftp_client_ptr Pointer to FTP client */
5784 /* */
5785 /* OUTPUT */
5786 /* */
5787 /* status Completion status */
5788 /* */
5789 /* CALLS */
5790 /* */
5791 /* nx_packet_release Release packet */
5792 /* nx_tcp_socket_send Send data packet to server */
5793 /* */
5794 /* CALLED BY */
5795 /* */
5796 /* _nx_ftp_client_file_open Open a file for read or write */
5797 /* _nx_ftp_client_directory_listing_get Get directory list */
5798 /* */
5799 /* RELEASE HISTORY */
5800 /* */
5801 /* DATE NAME DESCRIPTION */
5802 /* */
5803 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5804 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5805 /* resulting in version 6.1 */
5806 /* */
5807 /**************************************************************************/
_nx_ftp_client_block_mode_send(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)5808 UINT _nx_ftp_client_block_mode_send(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
5809 {
5810
5811 UINT status;
5812 NX_PACKET *packet_ptr;
5813 UCHAR *buffer_ptr;
5814
5815
5816 /* Send MODE B command. */
5817
5818 /* Allocate the packet. */
5819 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, NX_NO_WAIT);
5820
5821 /* Determine if the send was unsuccessful. */
5822 if (status)
5823 {
5824
5825 /* Return error. */
5826 return(status);
5827 }
5828
5829 /* We have a packet, setup pointer to the buffer area. */
5830 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5831
5832 /* Now build the actual MODE B request. */
5833 buffer_ptr[0] = 'M';
5834 buffer_ptr[1] = 'O';
5835 buffer_ptr[2] = 'D';
5836 buffer_ptr[3] = 'E';
5837 buffer_ptr[4] = ' ';
5838 buffer_ptr[5] = 'B';
5839
5840 /* Insert the CR/LF. */
5841 buffer_ptr[6] = 13;
5842 buffer_ptr[7] = 10;
5843
5844 /* Setup the length of the packet. */
5845 packet_ptr -> nx_packet_length = 8;
5846
5847 /* Setup the packet append pointer. */
5848 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
5849
5850 /* Send the MODE B message. */
5851 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
5852
5853 /* Determine if the send was unsuccessful. */
5854 if (status != NX_SUCCESS)
5855 {
5856
5857 /* Release the packet. */
5858 nx_packet_release(packet_ptr);
5859
5860 /* Return error. */
5861 return(status);
5862 }
5863
5864 /* Now wait for response from the FTP server control port. */
5865 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
5866
5867 /* Determine if a packet was not received. */
5868 if (status != NX_SUCCESS)
5869 {
5870
5871 /* Unable to open file with FTP server. */
5872 return(status);
5873 }
5874
5875 /* We have a packet, setup pointer to the buffer area. */
5876 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5877
5878 /* Check for 2xx message, signaling the data port was connected properly and ready for transfer. */
5879 if (buffer_ptr[0] != '2')
5880 {
5881
5882 /* Release the packet. */
5883 nx_packet_release(packet_ptr);
5884
5885 /* Unable to open file with FTP server. */
5886 return(NX_FTP_EXPECTED_2XX_CODE);
5887 }
5888
5889 /* Release the packet. */
5890 nx_packet_release(packet_ptr);
5891
5892 /* Return success to caller. */
5893 return(NX_SUCCESS);
5894 }
5895
5896
5897 /**************************************************************************/
5898 /* */
5899 /* FUNCTION RELEASE */
5900 /* */
5901 /* _nx_ftp_client_block_header_send PORTABLE C */
5902 /* 6.1 */
5903 /* AUTHOR */
5904 /* */
5905 /* Yuxin Zhou, Microsoft Corporation */
5906 /* */
5907 /* DESCRIPTION */
5908 /* */
5909 /* This function sends the block header for block mode. */
5910 /* */
5911 /* INPUT */
5912 /* */
5913 /* ftp_client_ptr Pointer to FTP client */
5914 /* block_size The size of block data */
5915 /* */
5916 /* OUTPUT */
5917 /* */
5918 /* status Completion status */
5919 /* */
5920 /* CALLS */
5921 /* */
5922 /* nx_packet_release Release packet */
5923 /* nx_tcp_socket_send Send data packet to server */
5924 /* */
5925 /* CALLED BY */
5926 /* */
5927 /* _nx_ftp_client_file_size_set Set the file size for writing */
5928 /* _nx_ftp_client_file_write Send data packet to server */
5929 /* */
5930 /* RELEASE HISTORY */
5931 /* */
5932 /* DATE NAME DESCRIPTION */
5933 /* */
5934 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5935 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5936 /* resulting in version 6.1 */
5937 /* */
5938 /**************************************************************************/
_nx_ftp_client_block_header_send(NX_FTP_CLIENT * ftp_client_ptr,ULONG block_size)5939 UINT _nx_ftp_client_block_header_send(NX_FTP_CLIENT *ftp_client_ptr, ULONG block_size)
5940 {
5941
5942 UINT status;
5943 NX_PACKET *packet_ptr;
5944 UCHAR *buffer_ptr;
5945
5946
5947 /* Use block mode to transfer data. RFC959, Section3.4.2, Page21-22. */
5948
5949 /* Allocate the packet. */
5950 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, NX_NO_WAIT);
5951
5952 /* Determine if the send was unsuccessful. */
5953 if (status)
5954 {
5955
5956 /* Return error. */
5957 return(status);
5958 }
5959
5960 /* We have a packet, setup pointer to the buffer area. */
5961 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5962
5963 /* Set the block header. */
5964 if (block_size)
5965 {
5966
5967 /* Descriptor. */
5968 buffer_ptr[0] = 0;
5969
5970 /* Byte count. */
5971 buffer_ptr[1] = (UCHAR)(block_size >> 8);
5972 buffer_ptr[2] = (UCHAR)(block_size);
5973 }
5974 else
5975 {
5976
5977 /* Descriptor. */
5978 buffer_ptr[0] = 64;
5979
5980 /* Byte count. */
5981 buffer_ptr[1] = 0;
5982 buffer_ptr[2] = 0;
5983 }
5984
5985 /* Setup the length of the packet. */
5986 packet_ptr -> nx_packet_length = 3;
5987
5988 /* Setup the packet append pointer. */
5989 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
5990
5991 /* Write packet payload to the file. */
5992 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_data_socket), packet_ptr, NX_NO_WAIT);
5993
5994 /* Determine if the send was unsuccessful. */
5995 if (status)
5996 {
5997
5998 /* Release the packet. */
5999 nx_packet_release(packet_ptr);
6000 }
6001
6002 /* Return success to caller. */
6003 return(status);
6004 }
6005
6006
6007 /**************************************************************************/
6008 /* */
6009 /* FUNCTION RELEASE */
6010 /* */
6011 /* _nx_ftp_client_block_header_retrieve PORTABLE C */
6012 /* 6.1 */
6013 /* AUTHOR */
6014 /* */
6015 /* Yuxin Zhou, Microsoft Corporation */
6016 /* */
6017 /* DESCRIPTION */
6018 /* */
6019 /* This function retrieves the block header for block mode. */
6020 /* */
6021 /* INPUT */
6022 /* */
6023 /* ftp_client_ptr Pointer to FTP client */
6024 /* packet_ptr Pointer to packet to write */
6025 /* */
6026 /* OUTPUT */
6027 /* */
6028 /* status Completion status */
6029 /* */
6030 /* CALLS */
6031 /* */
6032 /* nx_packet_release Release packet */
6033 /* nx_tcp_socket_send Send data packet to server */
6034 /* */
6035 /* CALLED BY */
6036 /* */
6037 /* _nx_ftp_client_file_read Read data from server */
6038 /* _nx_ftp_client_directory_listing_get Get directory list */
6039 /* _nx_ftp_client_directory_listing_continue */
6040 /* Continue to get directory list*/
6041 /* */
6042 /* RELEASE HISTORY */
6043 /* */
6044 /* DATE NAME DESCRIPTION */
6045 /* */
6046 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6047 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6048 /* resulting in version 6.1 */
6049 /* */
6050 /**************************************************************************/
_nx_ftp_client_block_header_retrieve(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET * packet_ptr)6051 UINT _nx_ftp_client_block_header_retrieve(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET *packet_ptr)
6052 {
6053
6054 ULONG delta;
6055 UCHAR *buffer_ptr;
6056 #ifndef NX_DISABLE_PACKET_CHAIN
6057 NX_PACKET *before_last_packet;
6058 NX_PACKET *last_packet;
6059 #endif /* NX_DISABLE_PACKET_CHAIN */
6060
6061
6062 /* Check if it is the first packet. */
6063 if (ftp_client_ptr -> nx_ftp_client_block_total_size == 0)
6064 {
6065
6066 /* Check the packet length. */
6067 if ((packet_ptr -> nx_packet_length < 3) ||
6068 (packet_ptr -> nx_packet_prepend_ptr + 3 > packet_ptr -> nx_packet_append_ptr))
6069 {
6070
6071 /* Release the packet. */
6072 nx_packet_release(packet_ptr);
6073 return(NX_FTP_CLIENT_INVALID_SIZE);
6074 }
6075
6076 /* We have a packet, setup pointer to the buffer area. */
6077 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
6078
6079 /* Process block header. */
6080 ftp_client_ptr -> nx_ftp_client_block_total_size = (ULONG)((buffer_ptr[1] << 8) | buffer_ptr[2]);
6081 ftp_client_ptr -> nx_ftp_client_block_remaining_size = ftp_client_ptr -> nx_ftp_client_block_total_size;
6082
6083 /* Skip the block header. */
6084 packet_ptr -> nx_packet_prepend_ptr += 3;
6085 packet_ptr -> nx_packet_length -= 3;
6086 }
6087
6088 /* Check if have remaining data. */
6089 if (ftp_client_ptr -> nx_ftp_client_block_remaining_size == 0)
6090 {
6091
6092 /* Release the packet. */
6093 nx_packet_release(packet_ptr);
6094 return(NX_FTP_CLIENT_END_OF_BLOCK);
6095 }
6096
6097 /* Check the data of current packet. */
6098 if (ftp_client_ptr -> nx_ftp_client_block_remaining_size < packet_ptr -> nx_packet_length)
6099 {
6100
6101 /* Remove the extra data, such as: end block header. */
6102
6103 /* Calculate the difference in the length. */
6104 delta = packet_ptr -> nx_packet_length - ftp_client_ptr -> nx_ftp_client_block_remaining_size;
6105
6106 /* Adjust the packet length. */
6107 packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - delta;
6108
6109 /* Adjust the append pointer. */
6110
6111 #ifndef NX_DISABLE_PACKET_CHAIN
6112 /* Loop to process adjustment that spans multiple packets. */
6113 while (delta)
6114 {
6115
6116 /* Determine if the packet is chained (or still chained after the adjustment). */
6117 if (packet_ptr -> nx_packet_last == NX_NULL)
6118 {
6119
6120 /* No, packet is not chained, simply adjust the append pointer in the packet. */
6121 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_append_ptr - delta;
6122
6123 /* Break out of the loop, since the adjustment is complete. */
6124 break;
6125 }
6126
6127 /* Pickup the pointer to the last packet. */
6128 last_packet = packet_ptr -> nx_packet_last;
6129
6130 /* Determine if the amount to adjust is less than the payload in the last packet. */
6131 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
6132 if (((ULONG)(last_packet -> nx_packet_append_ptr - last_packet -> nx_packet_prepend_ptr)) > delta)
6133 {
6134
6135 /* Yes, simply adjust the append pointer of the last packet in the chain. */
6136 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
6137 last_packet -> nx_packet_append_ptr = last_packet -> nx_packet_append_ptr - delta;
6138
6139 /* Get out of the loop, since the adjustment is complete. */
6140 break;
6141 }
6142 else
6143 {
6144
6145 /* Adjust the delta by the amount in the last packet. */
6146 delta = delta - ((ULONG)(last_packet -> nx_packet_append_ptr - last_packet -> nx_packet_prepend_ptr));
6147
6148 /* Find the packet before the last packet. */
6149 before_last_packet = packet_ptr;
6150 while (before_last_packet -> nx_packet_next != last_packet)
6151 {
6152
6153 /* Move to the next packet in the chain. */
6154 before_last_packet = before_last_packet -> nx_packet_next;
6155 }
6156
6157 /* At this point, we need to release the last packet and adjust the other packet
6158 pointers. */
6159
6160 /* Ensure the next packet pointer is NULL in what is now the last packet. */
6161 before_last_packet -> nx_packet_next = NX_NULL;
6162
6163 /* Determine if the packet is still chained. */
6164 if (packet_ptr != before_last_packet)
6165 {
6166
6167 /* Yes, the packet is still chained, setup the last packet pointer. */
6168 packet_ptr -> nx_packet_last = before_last_packet;
6169 }
6170 else
6171 {
6172
6173 /* The packet is no longer chained, set the last packet pointer to NULL. */
6174 packet_ptr -> nx_packet_last = NX_NULL;
6175 }
6176
6177 /* Release the last packet. */
6178 _nx_packet_release(last_packet);
6179 }
6180 }
6181 #else
6182
6183 /* Simply adjust the append pointer in the packet. */
6184 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_append_ptr - delta;
6185 #endif /* NX_DISABLE_PACKET_CHAIN */
6186 }
6187
6188 /* Update the file size. */
6189 ftp_client_ptr -> nx_ftp_client_block_remaining_size -= packet_ptr -> nx_packet_length;
6190
6191 /* Return success to caller. */
6192 return(NX_SUCCESS);
6193 }
6194