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 Component */
16 /** */
17 /** Trivial File Transfer Protocol (TFTP) Client */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_TFTP_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
32 /* Include necessary system files. */
33
34 #include "nx_api.h"
35 #include "nx_ip.h"
36 #include "nx_ipv6.h"
37 #include "nxd_tftp_client.h"
38
39 /* Bring in externs for caller checking code. */
40
41 NX_CALLER_CHECKING_EXTERNS
42
43
44 /**************************************************************************/
45 /* */
46 /* FUNCTION RELEASE */
47 /* */
48 /* _nxde_tftp_client_create PORTABLE C */
49 /* 6.1 */
50 /* AUTHOR */
51 /* */
52 /* Yuxin Zhou, Microsoft Corporation */
53 /* */
54 /* DESCRIPTION */
55 /* */
56 /* This function checks for errors in the TFTP client create call. */
57 /* */
58 /* */
59 /* INPUT */
60 /* */
61 /* tftp_client_ptr Pointer to TFTP client */
62 /* tftp_client_name Name of TFTP client */
63 /* ip_ptr Pointer to IP instance */
64 /* pool_ptr Pointer to packet pool */
65 /* ip_type IP type */
66 /* */
67 /* OUTPUT */
68 /* */
69 /* status Completion status */
70 /* NX_PTR_ERROR Invalid pointer input */
71 /* NX_INVALID_PARAMETERS Invalid non pointer input */
72 /* */
73 /* CALLS */
74 /* */
75 /* _nxd_tftp_client_create Actual client create call */
76 /* */
77 /* CALLED BY */
78 /* */
79 /* Application Code */
80 /* */
81 /* RELEASE HISTORY */
82 /* */
83 /* DATE NAME DESCRIPTION */
84 /* */
85 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
86 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
87 /* resulting in version 6.1 */
88 /* */
89 /**************************************************************************/
_nxde_tftp_client_create(NX_TFTP_CLIENT * tftp_client_ptr,CHAR * tftp_client_name,NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,UINT ip_type)90 UINT _nxde_tftp_client_create(NX_TFTP_CLIENT *tftp_client_ptr, CHAR *tftp_client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, UINT ip_type)
91 {
92
93 UINT status;
94
95
96 /* Check for invalid input pointers. */
97 if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
98 (tftp_client_ptr == NX_NULL) || (tftp_client_ptr -> nx_tftp_client_id == NXD_TFTP_CLIENT_ID) ||
99 (pool_ptr == NX_NULL))
100 return(NX_PTR_ERROR);
101
102 /* Check for valid IP version*/
103 if ((ip_type != NX_IP_VERSION_V4) && (ip_type != NX_IP_VERSION_V6))
104 {
105 return NX_INVALID_PARAMETERS;
106 }
107
108 /* Call actual client create function. */
109 status = _nxd_tftp_client_create(tftp_client_ptr, tftp_client_name, ip_ptr, pool_ptr, ip_type);
110
111 /* Return completion status. */
112 return(status);
113 }
114
115 /**************************************************************************/
116 /* */
117 /* FUNCTION RELEASE */
118 /* */
119 /* _nxd_tftp_client_create PORTABLE C */
120 /* 6.1 */
121 /* AUTHOR */
122 /* */
123 /* Yuxin Zhou, Microsoft Corporation */
124 /* */
125 /* DESCRIPTION */
126 /* */
127 /* This function creates a TFTP client on the specified IP. In doing */
128 /* so this function creates an UDP socket for subsequent TFTP */
129 /* transfers. */
130 /* */
131 /* */
132 /* INPUT */
133 /* */
134 /* tftp_client_ptr Pointer to TFTP client */
135 /* tftp_client_name Name of TFTP client */
136 /* ip_ptr Pointer to IP instance */
137 /* pool_ptr Pointer to TFTP pool */
138 /* ip_type IP type */
139 /* */
140 /* OUTPUT */
141 /* */
142 /* NX_SUCCESS Successful completion status */
143 /* status Actual completion status */
144 /* */
145 /* CALLS */
146 /* */
147 /* nx_udp_socket_bind Bind the UDP socket */
148 /* nx_udp_socket_create Create a UDP socket */
149 /* nx_udp_socket_delete Delete the UDP socket */
150 /* */
151 /* CALLED BY */
152 /* */
153 /* Application Code */
154 /* */
155 /* RELEASE HISTORY */
156 /* */
157 /* DATE NAME DESCRIPTION */
158 /* */
159 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
160 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
161 /* resulting in version 6.1 */
162 /* */
163 /**************************************************************************/
_nxd_tftp_client_create(NX_TFTP_CLIENT * tftp_client_ptr,CHAR * tftp_client_name,NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,UINT ip_type)164 UINT _nxd_tftp_client_create(NX_TFTP_CLIENT *tftp_client_ptr, CHAR *tftp_client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, UINT ip_type)
165 {
166
167 UINT status;
168
169
170 /* Clear the TFTP server structure. */
171 memset((void *) tftp_client_ptr, 0, sizeof(NX_TFTP_CLIENT));
172
173 /* Setup the TFTP client data structure. */
174
175 /* Save the TFTP client name. */
176 tftp_client_ptr -> nx_tftp_client_name = tftp_client_name;
177
178 /* Save the TFTP IP pointer. */
179 tftp_client_ptr -> nx_tftp_client_ip_ptr = ip_ptr;
180
181 /* Save the TFTP packet pool pointer. */
182 tftp_client_ptr -> nx_tftp_client_packet_pool_ptr = pool_ptr;
183
184 /* Initialize the server port number. This can change after the open request. */
185 tftp_client_ptr -> nx_tftp_client_server_port = NX_TFTP_SERVER_PORT;
186
187 /* Setup the current state to not open. */
188 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_NOT_OPEN;
189
190 /* Default the client network interface to the primary interface. */
191 tftp_client_ptr -> nx_tftp_client_interface_index = 0;
192
193 /* Create the UDP socket. */
194 status = nx_udp_socket_create(ip_ptr, &(tftp_client_ptr -> nx_tftp_client_socket), tftp_client_name,
195 NX_TFTP_TYPE_OF_SERVICE, NX_TFTP_FRAGMENT_OPTION, NX_TFTP_TIME_TO_LIVE, NX_TFTP_QUEUE_DEPTH);
196
197 /* Determine if an error occurred. */
198 if (status)
199 {
200
201 /* Yes, return error code. */
202 return(status);
203 }
204
205 /* Now, bind the socket to a port number. */
206
207 /* Let NetX decide which port. */
208 status = nx_udp_socket_bind(&(tftp_client_ptr -> nx_tftp_client_socket), NX_TFTP_SOURCE_PORT, NX_WAIT_FOREVER);
209
210 /* Determine if an error occurred. */
211 if (status)
212 {
213
214 /* Delete the UDP socket. */
215 nx_udp_socket_delete(&(tftp_client_ptr -> nx_tftp_client_socket));
216
217 /* Yes, return error code. */
218 return(status);
219 }
220
221 /* Otherwise, all is okay. Set the TFTP ID to indicate success. */
222 tftp_client_ptr -> nx_tftp_client_id = NXD_TFTP_CLIENT_ID;
223
224 NX_PARAMETER_NOT_USED(ip_type);
225
226 /* Return success to the caller. */
227 return(NX_SUCCESS);
228 }
229
230
231 /**************************************************************************/
232 /* */
233 /* FUNCTION RELEASE */
234 /* */
235 /* _nxde_tftp_client_delete PORTABLE C */
236 /* 6.1 */
237 /* AUTHOR */
238 /* */
239 /* Yuxin Zhou, Microsoft Corporation */
240 /* */
241 /* DESCRIPTION */
242 /* */
243 /* This function checks for errors in the TFTP client delete call. */
244 /* */
245 /* */
246 /* INPUT */
247 /* */
248 /* tftp_client_ptr Pointer to TFTP client */
249 /* */
250 /* OUTPUT */
251 /* */
252 /* status Completion status */
253 /* NX_PTR_ERROR Invalid pointer input */
254 /* */
255 /* CALLS */
256 /* */
257 /* _nxd_tftp_client_delete Actual client delete call */
258 /* */
259 /* CALLED BY */
260 /* */
261 /* Application Code */
262 /* */
263 /* RELEASE HISTORY */
264 /* */
265 /* DATE NAME DESCRIPTION */
266 /* */
267 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
268 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
269 /* resulting in version 6.1 */
270 /* */
271 /**************************************************************************/
_nxde_tftp_client_delete(NX_TFTP_CLIENT * tftp_client_ptr)272 UINT _nxde_tftp_client_delete(NX_TFTP_CLIENT *tftp_client_ptr)
273 {
274
275 UINT status;
276
277
278 /* Check for invalid input pointers. */
279 if ((tftp_client_ptr == NX_NULL) || (tftp_client_ptr -> nx_tftp_client_id != NXD_TFTP_CLIENT_ID))
280 return(NX_PTR_ERROR);
281
282 /* Check for appropriate caller. */
283 NX_THREADS_ONLY_CALLER_CHECKING
284
285 /* Call actual client delete function. */
286 status = _nxd_tftp_client_delete(tftp_client_ptr);
287
288 /* Return completion status. */
289 return(status);
290 }
291
292
293 /**************************************************************************/
294 /* */
295 /* FUNCTION RELEASE */
296 /* */
297 /* _nxd_tftp_client_delete PORTABLE C */
298 /* 6.1 */
299 /* AUTHOR */
300 /* */
301 /* Yuxin Zhou, Microsoft Corporation */
302 /* */
303 /* DESCRIPTION */
304 /* */
305 /* This function deletes a TFTP client on the specified IP. */
306 /* */
307 /* */
308 /* INPUT */
309 /* */
310 /* tftp_client_ptr Pointer to TFTP client */
311 /* */
312 /* OUTPUT */
313 /* */
314 /* NX_SUCCESS Successful completion status */
315 /* */
316 /* CALLS */
317 /* */
318 /* nx_udp_socket_unbind Unbind the UDP socket */
319 /* nx_udp_socket_delete Delete the UDP socket */
320 /* */
321 /* CALLED BY */
322 /* */
323 /* Application Code */
324 /* */
325 /* RELEASE HISTORY */
326 /* */
327 /* DATE NAME DESCRIPTION */
328 /* */
329 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
330 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
331 /* resulting in version 6.1 */
332 /* */
333 /**************************************************************************/
_nxd_tftp_client_delete(NX_TFTP_CLIENT * tftp_client_ptr)334 UINT _nxd_tftp_client_delete(NX_TFTP_CLIENT *tftp_client_ptr)
335 {
336
337 /* Unbind the TFTP client UDP socket. */
338 nx_udp_socket_unbind(&(tftp_client_ptr -> nx_tftp_client_socket));
339
340 /* Delete the TFTP client UDP socket. */
341 nx_udp_socket_delete(&(tftp_client_ptr -> nx_tftp_client_socket));
342
343 /* Clear the TFTP client ID. */
344 tftp_client_ptr -> nx_tftp_client_id = 0;
345
346 /* Return success to the caller. */
347 return(NX_SUCCESS);
348 }
349
350 /**************************************************************************/
351 /* */
352 /* FUNCTION RELEASE */
353 /* */
354 /* _nxde_tftp_client_set_interface PORTABLE C */
355 /* 6.1 */
356 /* AUTHOR */
357 /* */
358 /* Yuxin Zhou, Microsoft Corporation */
359 /* */
360 /* DESCRIPTION */
361 /* */
362 /* This function checks for errors in the TFTP client set interface */
363 /* call. */
364 /* */
365 /* */
366 /* INPUT */
367 /* */
368 /* tftp_client_ptr Pointer to TFTP client */
369 /* if_index Interface for tftp messages */
370 /* */
371 /* OUTPUT */
372 /* */
373 /* status Completion status */
374 /* NX_PTR_ERROR Invalid pointer input */
375 /* NX_INVALID_INTERFACE Invalid interface index input */
376 /* */
377 /* CALLS */
378 /* */
379 /* _nxd_tftp_client_set_interface Actual set interface call */
380 /* */
381 /* CALLED BY */
382 /* */
383 /* Application Code */
384 /* */
385 /* RELEASE HISTORY */
386 /* */
387 /* DATE NAME DESCRIPTION */
388 /* */
389 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
390 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
391 /* resulting in version 6.1 */
392 /* */
393 /**************************************************************************/
_nxde_tftp_client_set_interface(NX_TFTP_CLIENT * tftp_client_ptr,UINT if_index)394 UINT _nxde_tftp_client_set_interface(NX_TFTP_CLIENT *tftp_client_ptr, UINT if_index)
395 {
396
397 UINT status;
398
399 /* Check for invalid input pointer input. */
400 if (tftp_client_ptr == NX_NULL)
401 return(NX_PTR_ERROR);
402
403 /* Verify a valid index as been supplied. */
404 if (if_index >= NX_MAX_PHYSICAL_INTERFACES)
405 {
406 return NX_TFTP_INVALID_INTERFACE;
407 }
408
409 /* Check for appropriate caller. */
410 NX_THREADS_ONLY_CALLER_CHECKING
411
412 /* Call actual client delete function. */
413 status = _nxd_tftp_client_set_interface(tftp_client_ptr, if_index);
414
415 /* Return completion status. */
416 return(status);
417 }
418
419
420 /**************************************************************************/
421 /* */
422 /* FUNCTION RELEASE */
423 /* */
424 /* _nxd_tftp_client_set_interface PORTABLE C */
425 /* 6.1 */
426 /* AUTHOR */
427 /* */
428 /* Yuxin Zhou, Microsoft Corporation */
429 /* */
430 /* DESCRIPTION */
431 /* */
432 /* This function sets the physical interface which the TFTP client */
433 /* sends and receives TFTP packets. */
434 /* */
435 /* */
436 /* INPUT */
437 /* */
438 /* tftp_client_ptr Pointer to TFTP client */
439 /* if_index Interface for tftp messages */
440 /* */
441 /* OUTPUT */
442 /* */
443 /* NX_SUCCESS Successful completion status */
444 /* NX_INVALID_INTERFACE Invalid interface index input */
445 /* */
446 /* CALLS */
447 /* */
448 /* nx_udp_socket_unbind Unbind the UDP socket */
449 /* nx_udp_socket_delete Delete the UDP socket */
450 /* */
451 /* CALLED BY */
452 /* */
453 /* Application Code */
454 /* */
455 /* RELEASE HISTORY */
456 /* */
457 /* DATE NAME DESCRIPTION */
458 /* */
459 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
460 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
461 /* resulting in version 6.1 */
462 /* */
463 /**************************************************************************/
_nxd_tftp_client_set_interface(NX_TFTP_CLIENT * tftp_client_ptr,UINT if_index)464 UINT _nxd_tftp_client_set_interface(NX_TFTP_CLIENT *tftp_client_ptr, UINT if_index)
465 {
466
467
468 /* Set the TFTP client interface index. */
469 tftp_client_ptr -> nx_tftp_client_interface_index = if_index;
470
471 /* Return success to the caller. */
472 return(NX_SUCCESS);
473 }
474
475
476
477 /**************************************************************************/
478 /* */
479 /* FUNCTION RELEASE */
480 /* */
481 /* _nxde_tftp_client_error_info_get PORTABLE C */
482 /* 6.1 */
483 /* AUTHOR */
484 /* */
485 /* Yuxin Zhou, Microsoft Corporation */
486 /* */
487 /* DESCRIPTION */
488 /* */
489 /* This function checks for errors in the TFTP error information */
490 /* get call. */
491 /* */
492 /* Note: error_string pointer points to string generated by internal */
493 /* logic and it is always NULL-terminated. */
494 /* */
495 /* INPUT */
496 /* */
497 /* tftp_client_ptr Pointer to TFTP client */
498 /* error_code Pointer to destination for */
499 /* error code */
500 /* error_string Pointer to destination for */
501 /* the error string */
502 /* */
503 /* OUTPUT */
504 /* */
505 /* status Completion status */
506 /* NX_PTR_ERROR Invalid pointer input */
507 /* */
508 /* CALLS */
509 /* */
510 /* _nxd_tftp_client_error_info_get Actual get error info call */
511 /* */
512 /* CALLED BY */
513 /* */
514 /* Application Code */
515 /* */
516 /* RELEASE HISTORY */
517 /* */
518 /* DATE NAME DESCRIPTION */
519 /* */
520 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
521 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
522 /* resulting in version 6.1 */
523 /* */
524 /**************************************************************************/
_nxde_tftp_client_error_info_get(NX_TFTP_CLIENT * tftp_client_ptr,UINT * error_code,CHAR ** error_string)525 UINT _nxde_tftp_client_error_info_get(NX_TFTP_CLIENT *tftp_client_ptr, UINT *error_code, CHAR **error_string)
526 {
527
528 UINT status;
529
530
531 /* Check for invalid input pointers. */
532 if ((tftp_client_ptr == NX_NULL) || (tftp_client_ptr -> nx_tftp_client_id != NXD_TFTP_CLIENT_ID) ||
533 (error_code == NX_NULL) || (error_string == NX_NULL))
534 return(NX_PTR_ERROR);
535
536 /* Check for appropriate caller. */
537 NX_THREADS_ONLY_CALLER_CHECKING
538
539 /* Call actual client error information get function. */
540 status = _nxd_tftp_client_error_info_get(tftp_client_ptr, error_code, error_string);
541
542 /* Return completion status. */
543 return(status);
544 }
545
546 /**************************************************************************/
547 /* */
548 /* FUNCTION RELEASE */
549 /* */
550 /* _nxd_tftp_client_error_info_get PORTABLE C */
551 /* 6.1 */
552 /* AUTHOR */
553 /* */
554 /* Yuxin Zhou, Microsoft Corporation */
555 /* */
556 /* DESCRIPTION */
557 /* */
558 /* This function picks up the error code and error string for the */
559 /* specified TFTP client instance. */
560 /* */
561 /* Note: error_string pointer points to string generated by internal */
562 /* logic and it is always NULL-terminated. */
563 /* */
564 /* INPUT */
565 /* */
566 /* tftp_client_ptr Pointer to TFTP client */
567 /* error_code Pointer to destination for */
568 /* error code */
569 /* error_string Pointer to destination for */
570 /* the error string */
571 /* */
572 /* OUTPUT */
573 /* */
574 /* NX_SUCCESS Successful completion status */
575 /* */
576 /* CALLS */
577 /* */
578 /* None */
579 /* */
580 /* CALLED BY */
581 /* */
582 /* Application Code */
583 /* */
584 /* RELEASE HISTORY */
585 /* */
586 /* DATE NAME DESCRIPTION */
587 /* */
588 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
589 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
590 /* resulting in version 6.1 */
591 /* */
592 /**************************************************************************/
_nxd_tftp_client_error_info_get(NX_TFTP_CLIENT * tftp_client_ptr,UINT * error_code,CHAR ** error_string)593 UINT _nxd_tftp_client_error_info_get(NX_TFTP_CLIENT *tftp_client_ptr, UINT *error_code, CHAR **error_string)
594 {
595
596 /* Return the error code and the error string. */
597 *error_code = tftp_client_ptr -> nx_tftp_client_error_code;
598 *error_string = &(tftp_client_ptr -> nx_tftp_client_error_string[0]);
599
600 /* Return success to the caller. */
601 return(NX_SUCCESS);
602 }
603
604
605 /**************************************************************************/
606 /* */
607 /* FUNCTION RELEASE */
608 /* */
609 /* _nxde_tftp_client_file_close PORTABLE C */
610 /* 6.1 */
611 /* AUTHOR */
612 /* */
613 /* Yuxin Zhou, Microsoft Corporation */
614 /* */
615 /* DESCRIPTION */
616 /* */
617 /* This function checks for errors in the TFTP file close call. */
618 /* */
619 /* */
620 /* INPUT */
621 /* */
622 /* tftp_client_ptr Pointer to TFTP client */
623 /* ip_type IP type */
624 /* */
625 /* OUTPUT */
626 /* */
627 /* status Completion status */
628 /* NX_PTR_ERROR Invalid pointer input */
629 /* NX_INVALID_PARAMETERS Invalid non pointer input */
630 /* */
631 /* CALLS */
632 /* */
633 /* _nxd_tftp_client_file_close Actual client file close */
634 /* */
635 /* CALLED BY */
636 /* */
637 /* Application Code */
638 /* */
639 /* RELEASE HISTORY */
640 /* */
641 /* DATE NAME DESCRIPTION */
642 /* */
643 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
644 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
645 /* resulting in version 6.1 */
646 /* */
647 /**************************************************************************/
_nxde_tftp_client_file_close(NX_TFTP_CLIENT * tftp_client_ptr,UINT ip_type)648 UINT _nxde_tftp_client_file_close(NX_TFTP_CLIENT *tftp_client_ptr, UINT ip_type)
649 {
650
651 UINT status;
652
653
654 /* Check for invalid input pointers. */
655 if ((tftp_client_ptr == NX_NULL) || (tftp_client_ptr -> nx_tftp_client_id != NXD_TFTP_CLIENT_ID))
656 return(NX_PTR_ERROR);
657
658 /* Check for valid IP version*/
659 if ((ip_type != NX_IP_VERSION_V4) && (ip_type != NX_IP_VERSION_V6))
660 {
661 return NX_INVALID_PARAMETERS;
662 }
663
664 /* Check for appropriate caller. */
665 NX_THREADS_ONLY_CALLER_CHECKING
666
667 /* Call actual client file close function. */
668 status = _nxd_tftp_client_file_close(tftp_client_ptr, ip_type);
669
670 /* Return completion status. */
671 return(status);
672 }
673
674 /**************************************************************************/
675 /* */
676 /* FUNCTION RELEASE */
677 /* */
678 /* _nxd_tftp_client_file_close PORTABLE C */
679 /* 6.1 */
680 /* AUTHOR */
681 /* */
682 /* Yuxin Zhou, Microsoft Corporation */
683 /* */
684 /* DESCRIPTION */
685 /* */
686 /* This function closes the previously opened TFTP file. */
687 /* */
688 /* */
689 /* INPUT */
690 /* */
691 /* tftp_client_ptr Pointer to TFTP client */
692 /* ip_type IP type */
693 /* */
694 /* OUTPUT */
695 /* */
696 /* NX_SUCCESS Successful completion status */
697 /* status Actual completion status */
698 /* */
699 /* CALLS */
700 /* */
701 /* nx_packet_allocate Allocate packet for 0-length */
702 /* data packet */
703 /* nxd_udp_socket_send Send UDP data packet */
704 /* */
705 /* CALLED BY */
706 /* */
707 /* Application Code */
708 /* */
709 /* RELEASE HISTORY */
710 /* */
711 /* DATE NAME DESCRIPTION */
712 /* */
713 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
714 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
715 /* resulting in version 6.1 */
716 /* */
717 /**************************************************************************/
_nxd_tftp_client_file_close(NX_TFTP_CLIENT * tftp_client_ptr,UINT ip_type)718 UINT _nxd_tftp_client_file_close(NX_TFTP_CLIENT *tftp_client_ptr, UINT ip_type)
719 {
720
721 NX_PACKET *packet_ptr;
722 UCHAR *buffer_ptr;
723 UINT status;
724
725
726 /* Determine if the file is still open for writing. */
727 if (tftp_client_ptr -> nx_tftp_client_state == NX_TFTP_STATE_WRITE_OPEN)
728 {
729
730 /* Allocate a new packet for the final data message. */
731 if (ip_type == NX_IP_VERSION_V4)
732 {
733 status = nx_packet_allocate(tftp_client_ptr -> nx_tftp_client_packet_pool_ptr, &packet_ptr, NX_IPv4_UDP_PACKET, NX_NO_WAIT);
734 }
735 else
736 {
737 status = nx_packet_allocate(tftp_client_ptr -> nx_tftp_client_packet_pool_ptr, &packet_ptr, NX_IPv6_UDP_PACKET, NX_NO_WAIT);
738 }
739
740 /* Determine if an error occurred trying to allocate a packet. */
741 if (status != NX_SUCCESS)
742 {
743
744 /* Enter error state. */
745 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
746
747 /* Return error condition. */
748 return(status);
749 }
750
751 if (4u > ((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(packet_ptr -> nx_packet_append_ptr)))
752 {
753 /* Return the unsent packet to the packet pool. */
754 nx_packet_release(packet_ptr);
755
756 /* Enter error state. */
757 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
758
759 return(NX_SIZE_ERROR);
760 }
761
762 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr;
763
764 /* Now, build the TFTP 0-data length message. */
765
766 /* Setup a pointer to the packet payload. */
767 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
768
769 /* Initial byte is always zero. */
770 *buffer_ptr++ = 0;
771
772 /* Set the ACK code. */
773 *buffer_ptr++ = NX_TFTP_CODE_DATA;
774
775 /* Put the block number in. */
776 *buffer_ptr++ = (UCHAR) ((UCHAR) (tftp_client_ptr -> nx_tftp_client_block_number >> 8));
777 *buffer_ptr = (UCHAR) ((UCHAR) (tftp_client_ptr -> nx_tftp_client_block_number & 0xFF));
778
779 /* Adjust the packet pointers and length. */
780 packet_ptr -> nx_packet_length = 4;
781 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_append_ptr + 4;
782
783 /* Send the 0-length data packet out. */
784 status = nxd_udp_socket_send(&(tftp_client_ptr -> nx_tftp_client_socket), packet_ptr,
785 &tftp_client_ptr -> nx_tftp_client_server_ip,
786 tftp_client_ptr -> nx_tftp_client_server_port);
787
788 /* Determine if an error occurred trying to sending the packet. */
789 if (status)
790 {
791
792 /* Return the unsent packet to the packet pool. */
793 nx_packet_release(packet_ptr);
794
795 /* Enter error state. */
796 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
797
798 /* Return error condition. */
799 return(status);
800 }
801 }
802
803 /* Indicate the client is finished with the file. */
804 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_FINISHED;
805
806 /* Return success to the caller. */
807 return(NX_SUCCESS);
808 }
809
810
811 /**************************************************************************/
812 /* */
813 /* FUNCTION RELEASE */
814 /* */
815 /* _nxe_tftp_client_file_open PORTABLE C */
816 /* 6.1 */
817 /* AUTHOR */
818 /* */
819 /* Yuxin Zhou, Microsoft Corporation */
820 /* */
821 /* DESCRIPTION */
822 /* */
823 /* This function checks for errors in the TFTP file open call. */
824 /* */
825 /* Note: The string length of file_name is limited by the packet */
826 /* payload size. */
827 /* */
828 /* INPUT */
829 /* */
830 /* tftp_client_ptr Pointer to TFTP client */
831 /* file_name Pointer to file name */
832 /* server_ip_address IP address of TFTP server */
833 /* open_type Open for read or write */
834 /* wait_option Timeout for the open request */
835 /* */
836 /* OUTPUT */
837 /* */
838 /* status Completion status */
839 /* NX_PTR_ERROR Invalid pointer input */
840 /* NX_IP_ADDRESS_ERROR Invalid address supplied */
841 /* NX_OPTION_ERROR Invalid TFTP option supplied */
842 /* */
843 /* CALLS */
844 /* */
845 /* _nx_tftp_client_file_open Actual client file open */
846 /* */
847 /* CALLED BY */
848 /* */
849 /* Application Code */
850 /* */
851 /* RELEASE HISTORY */
852 /* */
853 /* DATE NAME DESCRIPTION */
854 /* */
855 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
856 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
857 /* resulting in version 6.1 */
858 /* */
859 /**************************************************************************/
_nxe_tftp_client_file_open(NX_TFTP_CLIENT * tftp_client_ptr,CHAR * file_name,ULONG server_ip_address,UINT open_type,ULONG wait_option)860 UINT _nxe_tftp_client_file_open(NX_TFTP_CLIENT *tftp_client_ptr, CHAR *file_name, ULONG server_ip_address, UINT open_type, ULONG wait_option)
861 {
862
863 #ifndef NX_DISABLE_IPV4
864 UINT status;
865
866
867 /* Check for invalid input pointers. */
868 if ((tftp_client_ptr == NX_NULL) || (tftp_client_ptr -> nx_tftp_client_id != NXD_TFTP_CLIENT_ID))
869 return(NX_PTR_ERROR);
870
871 /* Check for an invalid server IP address. */
872 if (server_ip_address == 0)
873 return(NX_IP_ADDRESS_ERROR);
874
875 /* Check for illegal open option type. */
876 if ((open_type != NX_TFTP_OPEN_FOR_READ) && (open_type != NX_TFTP_OPEN_FOR_WRITE))
877 return(NX_OPTION_ERROR);
878
879 /* Check for appropriate caller. */
880 NX_THREADS_ONLY_CALLER_CHECKING
881
882 /* Call actual client file open function. */
883 status = _nx_tftp_client_file_open(tftp_client_ptr, file_name, server_ip_address, open_type, wait_option);
884
885 /* Return completion status. */
886 return(status);
887 #else
888 NX_PARAMETER_NOT_USED(tftp_client_ptr);
889 NX_PARAMETER_NOT_USED(file_name);
890 NX_PARAMETER_NOT_USED(server_ip_address);
891 NX_PARAMETER_NOT_USED(open_type);
892 NX_PARAMETER_NOT_USED(wait_option);
893
894 return(NX_NOT_SUPPORTED);
895 #endif /* NX_DISABLE_IPV4 */
896 }
897
898 /**************************************************************************/
899 /* */
900 /* FUNCTION RELEASE */
901 /* */
902 /* _nx_tftp_client_file_open PORTABLE C */
903 /* 6.1 */
904 /* AUTHOR */
905 /* */
906 /* Yuxin Zhou, Microsoft Corporation */
907 /* */
908 /* DESCRIPTION */
909 /* */
910 /* This function opens a TFTP file. */
911 /* */
912 /* Note: The string length of file_name is limited by the packet */
913 /* payload size. */
914 /* */
915 /* INPUT */
916 /* */
917 /* tftp_client_ptr Pointer to TFTP client */
918 /* file_name Pointer to file name */
919 /* tftp_server_address IP address of TFTP server */
920 /* open_type Open for read or write */
921 /* wait_option Timeout for the open request */
922 /* */
923 /* OUTPUT */
924 /* */
925 /* status Completion status */
926 /* */
927 /* CALLS */
928 /* */
929 /* _nx_tftp_client_file_open_internal Actual open service */
930 /* */
931 /* CALLED BY */
932 /* */
933 /* Application Code */
934 /* */
935 /* RELEASE HISTORY */
936 /* */
937 /* DATE NAME DESCRIPTION */
938 /* */
939 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
940 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
941 /* resulting in version 6.1 */
942 /* */
943 /**************************************************************************/
_nx_tftp_client_file_open(NX_TFTP_CLIENT * tftp_client_ptr,CHAR * file_name,ULONG server_ip_address,UINT open_type,ULONG wait_option)944 UINT _nx_tftp_client_file_open(NX_TFTP_CLIENT *tftp_client_ptr, CHAR *file_name, ULONG server_ip_address, UINT open_type, ULONG wait_option)
945 {
946 #ifndef NX_DISABLE_IPV4
947 UINT status;
948
949
950 NXD_ADDRESS server_address;
951
952 /* Create the IPv4 address block. Set the version to IPv4. */
953 server_address.nxd_ip_version = NX_IP_VERSION_V4;
954 server_address.nxd_ip_address.v4 = server_ip_address;
955
956 /* Call the actual file open service. */
957 status = _nx_tftp_client_file_open_internal(tftp_client_ptr, file_name, &server_address, open_type, wait_option, NX_IP_VERSION_V4);
958
959
960 /* Return the completion status. */
961 return status;
962 #else
963 NX_PARAMETER_NOT_USED(tftp_client_ptr);
964 NX_PARAMETER_NOT_USED(file_name);
965 NX_PARAMETER_NOT_USED(server_ip_address);
966 NX_PARAMETER_NOT_USED(open_type);
967 NX_PARAMETER_NOT_USED(wait_option);
968
969 return(NX_NOT_SUPPORTED);
970 #endif /* NX_DISABLE_IPV4 */
971 }
972
973
974 /**************************************************************************/
975 /* */
976 /* FUNCTION RELEASE */
977 /* */
978 /* _nxde_tftp_client_file_open PORTABLE C */
979 /* 6.1 */
980 /* AUTHOR */
981 /* */
982 /* Yuxin Zhou, Microsoft Corporation */
983 /* */
984 /* DESCRIPTION */
985 /* */
986 /* This function checks for errors in the TFTP file open call. */
987 /* */
988 /* Note: The string length of file_name is limited by the packet */
989 /* payload size. */
990 /* */
991 /* INPUT */
992 /* */
993 /* tftp_client_ptr Pointer to TFTP client */
994 /* file_name Pointer to file name */
995 /* server_ip_address IP address of TFTP server */
996 /* open_type Open for read or write */
997 /* wait_option Timeout for the open request */
998 /* ip_type IP type */
999 /* */
1000 /* OUTPUT */
1001 /* */
1002 /* status Completion status */
1003 /* NX_PTR_ERROR Invalid pointer input */
1004 /* NX_INVALID_PARAMETERS Invalid non pointer input */
1005 /* NX_IP_ADDRESS_ERROR Invalid address supplied */
1006 /* NX_OPTION_ERROR Invalid TFTP option supplied */
1007 /* */
1008 /* CALLS */
1009 /* */
1010 /* _nxd_tftp_client_file_open Actual client file open */
1011 /* */
1012 /* CALLED BY */
1013 /* */
1014 /* Application Code */
1015 /* */
1016 /* RELEASE HISTORY */
1017 /* */
1018 /* DATE NAME DESCRIPTION */
1019 /* */
1020 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1021 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1022 /* resulting in version 6.1 */
1023 /* */
1024 /**************************************************************************/
_nxde_tftp_client_file_open(NX_TFTP_CLIENT * tftp_client_ptr,CHAR * file_name,NXD_ADDRESS * server_ip_address,UINT open_type,ULONG wait_option,UINT ip_type)1025 UINT _nxde_tftp_client_file_open(NX_TFTP_CLIENT *tftp_client_ptr, CHAR *file_name, NXD_ADDRESS *server_ip_address, UINT open_type, ULONG wait_option, UINT ip_type)
1026 {
1027
1028 UINT status;
1029
1030
1031 /* Check for invalid input pointers. */
1032 if ((tftp_client_ptr == NX_NULL) || (tftp_client_ptr -> nx_tftp_client_id != NXD_TFTP_CLIENT_ID))
1033 return(NX_PTR_ERROR);
1034
1035 /* Check for an invalid server IP address. */
1036 if (!server_ip_address)
1037 return(NX_IP_ADDRESS_ERROR);
1038
1039 /* Check for valid IP version*/
1040 if ((ip_type != NX_IP_VERSION_V4) && (ip_type != NX_IP_VERSION_V6))
1041 {
1042 return NX_INVALID_PARAMETERS;
1043 }
1044
1045 /* Check for illegal open option type. */
1046 if ((open_type != NX_TFTP_OPEN_FOR_READ) && (open_type != NX_TFTP_OPEN_FOR_WRITE))
1047 return(NX_OPTION_ERROR);
1048
1049 /* Check for appropriate caller. */
1050 NX_THREADS_ONLY_CALLER_CHECKING
1051
1052 /* Call actual client file open function. */
1053 status = _nxd_tftp_client_file_open(tftp_client_ptr, file_name, server_ip_address, open_type, wait_option, ip_type);
1054
1055 /* Return completion status. */
1056 return(status);
1057 }
1058
1059
1060 /**************************************************************************/
1061 /* */
1062 /* FUNCTION RELEASE */
1063 /* */
1064 /* _nxd_tftp_client_file_open PORTABLE C */
1065 /* 6.1 */
1066 /* AUTHOR */
1067 /* */
1068 /* Yuxin Zhou, Microsoft Corporation */
1069 /* */
1070 /* DESCRIPTION */
1071 /* */
1072 /* This function opens a TFTP file received over IPv4 or IPv6 networks.*/
1073 /* */
1074 /* Note: The string length of file_name is limited by the packet */
1075 /* payload size. */
1076 /* */
1077 /* INPUT */
1078 /* */
1079 /* tftp_client_ptr Pointer to TFTP client */
1080 /* file_name Pointer to file name */
1081 /* tftp_server_address IP address of TFTP server */
1082 /* open_type Open for read or write */
1083 /* wait_option Timeout for the open request */
1084 /* ip_type IP type */
1085 /* */
1086 /* OUTPUT */
1087 /* */
1088 /* status Completion status */
1089 /* NX_TFTP_INVALID_IP_VERSION Unsupported IP protocol */
1090 /* NX_TFTP_NO_ACK_RECEIVED ACK not received from Server */
1091 /* NX_TFTP_NOT_CLOSED TFTP client file already open */
1092 /* NX_TFTP_INVALID_SERVER_ADDRESS Reply from unknown Server */
1093 /* */
1094 /* CALLS */
1095 /* */
1096 /* _nx_tftp_client_file_open_internal Actual open service */
1097 /* */
1098 /* CALLED BY */
1099 /* */
1100 /* Application Code */
1101 /* */
1102 /* RELEASE HISTORY */
1103 /* */
1104 /* DATE NAME DESCRIPTION */
1105 /* */
1106 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1107 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1108 /* resulting in version 6.1 */
1109 /* */
1110 /**************************************************************************/
_nxd_tftp_client_file_open(NX_TFTP_CLIENT * tftp_client_ptr,CHAR * file_name,NXD_ADDRESS * server_ip_address,UINT open_type,ULONG wait_option,UINT ip_type)1111 UINT _nxd_tftp_client_file_open(NX_TFTP_CLIENT *tftp_client_ptr, CHAR *file_name, NXD_ADDRESS *server_ip_address, UINT open_type, ULONG wait_option, UINT ip_type)
1112 {
1113
1114 UINT status;
1115
1116
1117 /* Call the actual file open service. */
1118 status = _nx_tftp_client_file_open_internal(tftp_client_ptr, file_name, server_ip_address, open_type, wait_option, ip_type);
1119
1120 /* Return the completion status. */
1121 return status;
1122 }
1123
1124
1125 /**************************************************************************/
1126 /* */
1127 /* FUNCTION RELEASE */
1128 /* */
1129 /* _nx_tftp_client_file_open_internal PORTABLE C */
1130 /* 6.1 */
1131 /* AUTHOR */
1132 /* */
1133 /* Yuxin Zhou, Microsoft Corporation */
1134 /* */
1135 /* DESCRIPTION */
1136 /* */
1137 /* This function opens a TFTP file received. */
1138 /* */
1139 /* */
1140 /* INPUT */
1141 /* */
1142 /* tftp_client_ptr Pointer to TFTP client */
1143 /* file_name Pointer to file name */
1144 /* tftp_server_address IP address of TFTP server */
1145 /* open_type Open for read or write */
1146 /* wait_option Timeout for the open request */
1147 /* ip_type IP type */
1148 /* */
1149 /* OUTPUT */
1150 /* */
1151 /* status Completion status */
1152 /* NX_TFTP_INVALID_IP_VERSION Unsupported IP protocol */
1153 /* NX_TFTP_NO_ACK_RECEIVED ACK not received from Server */
1154 /* NX_TFTP_NOT_CLOSED TFTP client file already open */
1155 /* NX_TFTP_INVALID_SERVER_ADDRESS Reply from unknown Server */
1156 /* */
1157 /* CALLS */
1158 /* */
1159 /* nx_packet_allocate Allocate packet for TFTP */
1160 /* request or data */
1161 /* nx_packet_release Release packet */
1162 /* nx_udp_socket_receive Receive UDP data packet */
1163 /* nxd_udp_socket_send Send UDP data packet */
1164 /* nxd_udp_source_extract Extract IP and port from msg */
1165 /* */
1166 /* CALLED BY */
1167 /* */
1168 /* Application Code */
1169 /* */
1170 /* RELEASE HISTORY */
1171 /* */
1172 /* DATE NAME DESCRIPTION */
1173 /* */
1174 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1175 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1176 /* resulting in version 6.1 */
1177 /* */
1178 /**************************************************************************/
_nx_tftp_client_file_open_internal(NX_TFTP_CLIENT * tftp_client_ptr,CHAR * file_name,NXD_ADDRESS * server_ip_address,UINT open_type,ULONG wait_option,UINT ip_type)1179 UINT _nx_tftp_client_file_open_internal(NX_TFTP_CLIENT *tftp_client_ptr, CHAR *file_name, NXD_ADDRESS *server_ip_address, UINT open_type, ULONG wait_option, UINT ip_type)
1180
1181 {
1182
1183 UINT status;
1184 UINT i;
1185 NXD_ADDRESS ip_address;
1186
1187 UINT port;
1188 UCHAR *buffer_ptr;
1189 NX_PACKET *packet_ptr;
1190 UINT matching = NX_FALSE;
1191
1192
1193 /* Determine if the TFTP instance is already open. */
1194 if ((tftp_client_ptr -> nx_tftp_client_state == NX_TFTP_STATE_OPEN) ||
1195 (tftp_client_ptr -> nx_tftp_client_state == NX_TFTP_STATE_WRITE_OPEN))
1196 {
1197
1198 /* This instance is already open, return an error. */
1199 return(NX_TFTP_NOT_CLOSED);
1200 }
1201
1202 /* Enter the open state. */
1203 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_OPEN;
1204
1205 /* Save the server's IP address. */
1206
1207 if (ip_type == NX_IP_VERSION_V6)
1208 {
1209
1210 #ifndef FEATURE_NX_IPV6
1211 return NX_TFTP_INVALID_IP_VERSION;
1212 #else
1213 COPY_NXD_ADDRESS(server_ip_address, &tftp_client_ptr -> nx_tftp_client_server_ip);
1214 #endif
1215 }
1216 else
1217 {
1218
1219 #ifndef NX_DISABLE_IPV4
1220 /* If not IPv6, assume the client IP request is using IPv4 if not explicitly specified. */
1221 tftp_client_ptr -> nx_tftp_client_server_ip.nxd_ip_version = ip_type;
1222 tftp_client_ptr -> nx_tftp_client_server_ip.nxd_ip_address.v4 = server_ip_address -> nxd_ip_address.v4;
1223 #else
1224 return NX_TFTP_INVALID_IP_VERSION;
1225 #endif /* NX_DISABLE_IPV4 */
1226 }
1227
1228 /* Initialize the server port number. This can change after the open request. */
1229 tftp_client_ptr -> nx_tftp_client_server_port = NX_TFTP_SERVER_PORT;
1230
1231 /* Clear the error code. */
1232 tftp_client_ptr -> nx_tftp_client_error_code = 0;
1233
1234 /* Specify that the first block. */
1235 tftp_client_ptr -> nx_tftp_client_block_number = 1;
1236
1237 /* Allocate a packet for initial open request message. Determine whether we are sending
1238 IPv4 or IPv6 packets. */
1239
1240 if (ip_type == NX_IP_VERSION_V4)
1241 {
1242
1243 status = nx_packet_allocate((tftp_client_ptr -> nx_tftp_client_ip_ptr) -> nx_ip_default_packet_pool,
1244 &packet_ptr, NX_IPv4_UDP_PACKET, wait_option);
1245 }
1246 else
1247 {
1248
1249 status = nx_packet_allocate((tftp_client_ptr -> nx_tftp_client_ip_ptr) -> nx_ip_default_packet_pool,
1250 &packet_ptr, NX_IPv6_UDP_PACKET, wait_option);
1251 }
1252
1253 /* Determine if an error occurred trying to allocate a packet. */
1254 if (status != NX_SUCCESS)
1255 {
1256
1257 /* Enter error state. */
1258 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
1259
1260 /* Return error condition. */
1261 return(status);
1262 }
1263
1264 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr;
1265
1266 /* Now, build the TFTP open request. */
1267
1268 /* Setup a pointer to the packet payload. */
1269 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1270
1271 /* Initial byte is always zero. */
1272 *buffer_ptr++ = 0;
1273
1274 /* Determine the type of open requested. */
1275 if (open_type == NX_TFTP_OPEN_FOR_READ)
1276 *buffer_ptr++ = NX_TFTP_CODE_READ;
1277 else
1278 *buffer_ptr++ = NX_TFTP_CODE_WRITE;
1279
1280 /* Now place the file name in the buffer. */
1281 i = 0;
1282 while (file_name[i] && (ULONG)(packet_ptr -> nx_packet_data_end - buffer_ptr) > 7u)
1283 {
1284
1285 /* Store character of file name into request. */
1286 *buffer_ptr++ = (UCHAR) file_name[i];
1287 i++;
1288 }
1289
1290 /* Place a NULL after the file name. */
1291 *buffer_ptr++ = NX_NULL;
1292
1293 /* Now place the mode string. */
1294 *buffer_ptr++ = (UCHAR) 'O';
1295 *buffer_ptr++ = (UCHAR) 'C';
1296 *buffer_ptr++ = (UCHAR) 'T';
1297 *buffer_ptr++ = (UCHAR) 'E';
1298 *buffer_ptr++ = (UCHAR) 'T';
1299
1300 /* Place a NULL after the mode. */
1301 *buffer_ptr++ = NX_NULL;
1302
1303 /* Adjust the packet length and the append pointer. */
1304 packet_ptr -> nx_packet_append_ptr = buffer_ptr;
1305 packet_ptr -> nx_packet_length = (ULONG)(buffer_ptr - packet_ptr -> nx_packet_prepend_ptr);
1306
1307 /* Now send the open request to the TFTP server. */
1308 status = nxd_udp_socket_send(&(tftp_client_ptr -> nx_tftp_client_socket), packet_ptr,
1309 server_ip_address, tftp_client_ptr -> nx_tftp_client_server_port);
1310
1311
1312 /* Check for error condition. */
1313 if (status != NX_SUCCESS)
1314 {
1315
1316 nx_packet_release(packet_ptr);
1317
1318 /* Enter error state. */
1319 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
1320
1321 /* Return error condition. */
1322 return(status);
1323 }
1324
1325 /* Determine if the TFTP file was open for writing. */
1326 if (open_type == NX_TFTP_OPEN_FOR_WRITE)
1327 {
1328
1329 /* Change to the open for writing state. */
1330 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_WRITE_OPEN;
1331
1332 /* Open for write request is present. We now need to wait for the ACK of block number 0
1333 from the server. */
1334 status = nx_udp_socket_receive(&(tftp_client_ptr -> nx_tftp_client_socket), &packet_ptr, wait_option);
1335
1336 /* Check the return status. */
1337 if (status != NX_SUCCESS)
1338 {
1339
1340 /* Enter error state. */
1341 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
1342
1343 /* Return error condition. */
1344 return(status);
1345 }
1346
1347 /* Check for valid packet length (The minimum TFTP header size is ACK packet, four bytes). */
1348 if (packet_ptr -> nx_packet_length < 4)
1349 {
1350
1351 /* Release the packet. */
1352 nx_packet_release(packet_ptr);
1353
1354 /* Return. */
1355 return(NX_INVALID_PACKET);
1356 }
1357
1358 /* Extract the source IP and port numbers. */
1359 status = nxd_udp_source_extract(packet_ptr, &ip_address, &port);
1360
1361
1362 /* Check for an invalid server IP address. */
1363
1364 #ifndef NX_DISABLE_IPV4
1365 if ((ip_type == NX_IP_VERSION_V4)&&
1366 (ip_address.nxd_ip_address.v4 == tftp_client_ptr -> nx_tftp_client_server_ip.nxd_ip_address.v4))
1367 {
1368
1369 matching = NX_TRUE;
1370 }
1371 else
1372 #endif /* NX_DISABLE_IPV4 */
1373 #ifdef FEATURE_NX_IPV6
1374 if (ip_type == NX_IP_VERSION_V6)
1375 {
1376
1377 if (CHECK_IPV6_ADDRESSES_SAME(&ip_address.nxd_ip_address.v6[0], &tftp_client_ptr -> nx_tftp_client_server_ip.nxd_ip_address.v6[0]))
1378 {
1379
1380 matching = NX_TRUE;
1381 }
1382 }
1383 else
1384 #endif
1385 {
1386 /* Release the packet. */
1387 nx_packet_release(packet_ptr);
1388
1389 return NX_TFTP_INVALID_IP_VERSION;
1390 }
1391
1392 /* Do we have a match? */
1393 if (!matching)
1394 {
1395 /* No, invalid IP address! */
1396
1397 /* Enter error state. */
1398 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
1399
1400 /* Release the packet. */
1401 nx_packet_release(packet_ptr);
1402
1403 /* Return error condition. */
1404 return(NX_TFTP_INVALID_SERVER_ADDRESS);
1405 }
1406
1407 /* Save the source port since the server can change its port. */
1408 tftp_client_ptr -> nx_tftp_client_server_port = port;
1409
1410 /* Check for valid server ACK. */
1411
1412 /* Setup a pointer to the packet payload. */
1413 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1414
1415 /* Check for valid ACK message. */
1416 if ((buffer_ptr[0] != 0) || (buffer_ptr[1] != NX_TFTP_CODE_ACK) ||
1417 (buffer_ptr[2] != 0) || (buffer_ptr[3] != 0) ||
1418 (packet_ptr -> nx_packet_length != 4))
1419 {
1420
1421 UINT code;
1422
1423 /* Enter error state. */
1424 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
1425
1426 /* Get the error status from the server message. */
1427 buffer_ptr++;
1428 code = *(buffer_ptr);
1429
1430 /* If this is a server error, save it to the TFTP client. */
1431 if (code == NX_TFTP_CODE_ERROR)
1432 {
1433
1434 buffer_ptr++;
1435 tftp_client_ptr -> nx_tftp_client_error_code = ((UINT) (*buffer_ptr)) << 8;
1436 buffer_ptr++;
1437 tftp_client_ptr -> nx_tftp_client_error_code |= (UINT) (*buffer_ptr);
1438 buffer_ptr++;
1439
1440 /* Loop to save error message to TFTP Client. */
1441 tftp_client_ptr -> nx_tftp_client_error_string[sizeof(tftp_client_ptr -> nx_tftp_client_error_string) - 1] = NX_NULL;
1442 for (i = 0; i < NX_TFTP_ERROR_STRING_MAX; i++)
1443 {
1444
1445 /* Store desired file name. */
1446 tftp_client_ptr -> nx_tftp_client_error_string[i] = (CHAR) *buffer_ptr++;
1447
1448 /* Check for NULL character. */
1449 if (tftp_client_ptr -> nx_tftp_client_error_string[i] == NX_NULL)
1450 {
1451 break;
1452 }
1453 }
1454
1455 /* Release the packet. */
1456 nx_packet_release(packet_ptr);
1457
1458 /* Return error condition. */
1459 return(NX_TFTP_CODE_ERROR);
1460 }
1461 /* Unknown code, not an error or an ACK. */
1462 else
1463 {
1464
1465 /* Release the packet. */
1466 nx_packet_release(packet_ptr);
1467
1468 /* Return error condition. */
1469 return(NX_TFTP_NO_ACK_RECEIVED);
1470 }
1471 }
1472
1473 /* Release the packet. */
1474 nx_packet_release(packet_ptr);
1475 }
1476
1477 /* Otherwise, return success! */
1478 return(NX_SUCCESS);
1479 }
1480
1481
1482 /**************************************************************************/
1483 /* */
1484 /* FUNCTION RELEASE */
1485 /* */
1486 /* _nxde_tftp_client_file_read PORTABLE C */
1487 /* 6.1 */
1488 /* AUTHOR */
1489 /* */
1490 /* Yuxin Zhou, Microsoft Corporation */
1491 /* */
1492 /* DESCRIPTION */
1493 /* */
1494 /* This function checks for errors in the TFTP file read call. */
1495 /* */
1496 /* */
1497 /* INPUT */
1498 /* */
1499 /* tftp_client_ptr Pointer to TFTP client */
1500 /* packet_ptr Pointer to destination for */
1501 /* return packet pointer */
1502 /* wait_option Timeout for the read request */
1503 /* ip_type IP type */
1504 /* */
1505 /* OUTPUT */
1506 /* */
1507 /* status Completion status */
1508 /* NX_PTR_ERROR Invalid pointer input */
1509 /* NX_INVALID_PARAMETERS Invalid non pointer input */
1510 /* */
1511 /* CALLS */
1512 /* */
1513 /* _nxd_tftp_client_file_read Actual client file read */
1514 /* */
1515 /* CALLED BY */
1516 /* */
1517 /* Application Code */
1518 /* */
1519 /* RELEASE HISTORY */
1520 /* */
1521 /* DATE NAME DESCRIPTION */
1522 /* */
1523 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1524 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1525 /* resulting in version 6.1 */
1526 /* */
1527 /**************************************************************************/
_nxde_tftp_client_file_read(NX_TFTP_CLIENT * tftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option,UINT ip_type)1528 UINT _nxde_tftp_client_file_read(NX_TFTP_CLIENT *tftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option, UINT ip_type)
1529 {
1530
1531 UINT status;
1532
1533
1534 /* Check for invalid input pointers. */
1535 if ((tftp_client_ptr == NX_NULL) || (tftp_client_ptr -> nx_tftp_client_id != NXD_TFTP_CLIENT_ID) ||
1536 (packet_ptr == NX_NULL))
1537 return(NX_PTR_ERROR);
1538
1539 /* Check for valid IP version*/
1540 if ((ip_type != NX_IP_VERSION_V4) && (ip_type != NX_IP_VERSION_V6))
1541 {
1542 return NX_INVALID_PARAMETERS;
1543 }
1544
1545 /* Check for appropriate caller. */
1546 NX_THREADS_ONLY_CALLER_CHECKING
1547
1548 /* Call actual client file read function. */
1549 status = _nxd_tftp_client_file_read(tftp_client_ptr, packet_ptr, wait_option, ip_type);
1550
1551 /* Return completion status. */
1552 return(status);
1553 }
1554
1555 /**************************************************************************/
1556 /* */
1557 /* FUNCTION RELEASE */
1558 /* */
1559 /* _nxd_tftp_client_file_read PORTABLE C */
1560 /* 6.1 */
1561 /* AUTHOR */
1562 /* */
1563 /* Yuxin Zhou, Microsoft Corporation */
1564 /* */
1565 /* DESCRIPTION */
1566 /* */
1567 /* This function reads a buffer from a previously opened TFTP file. */
1568 /* */
1569 /* */
1570 /* INPUT */
1571 /* */
1572 /* tftp_client_ptr Pointer to TFTP client */
1573 /* packet_ptr Pointer to destination for */
1574 /* return packet pointer */
1575 /* wait_option Timeout for the read request */
1576 /* ip_type IP type */
1577 /* */
1578 /* OUTPUT */
1579 /* */
1580 /* status Completion status */
1581 /* NX_TFTP_CLIENT_NOT_OPEN Requested file not open */
1582 /* NX_TFTP_INVALID_SERVER_ADDRESS Reply from unknown Server */
1583 /* NX_TFTP_INVALID_IP_VERSION Unsupported IP protocol */
1584 /* NX_TFTP_END_OF_FILE No more data in file */
1585 /* NX_TFTP_INVALID_BLOCK_NUMBER Mismatching block number in */
1586 /* received TFTP packet */
1587 /* NX_TFTP_CODE_ERROR Unknown TFTP code received */
1588 /* */
1589 /* CALLS */
1590 /* */
1591 /* nx_packet_allocate Allocate packet for ACK packet*/
1592 /* nx_packet_release Release packet */
1593 /* nx_udp_socket_receive Receive UDP data packet */
1594 /* nxd_udp_socket_send Send TFTP ACK packet */
1595 /* nxd_udp_source_extract Extract IP and port from msg */
1596 /* */
1597 /* CALLED BY */
1598 /* */
1599 /* Application Code */
1600 /* */
1601 /* RELEASE HISTORY */
1602 /* */
1603 /* DATE NAME DESCRIPTION */
1604 /* */
1605 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1606 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1607 /* resulting in version 6.1 */
1608 /* */
1609 /**************************************************************************/
_nxd_tftp_client_file_read(NX_TFTP_CLIENT * tftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option,UINT ip_type)1610 UINT _nxd_tftp_client_file_read(NX_TFTP_CLIENT *tftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option, UINT ip_type)
1611 {
1612
1613 UCHAR *buffer_ptr;
1614 UINT status;
1615 NXD_ADDRESS ip_address;
1616 UINT port;
1617 UINT i;
1618 USHORT block_number;
1619 UCHAR code;
1620 NX_PACKET *ack_packet;
1621 UINT matching = NX_FALSE;
1622 UCHAR resend_ACK_packet = NX_FALSE;
1623
1624
1625 /* Determine if we are still in an open state. */
1626 if (tftp_client_ptr -> nx_tftp_client_state != NX_TFTP_STATE_OPEN)
1627 {
1628
1629 /* This instance is not open, return an error. */
1630 if (tftp_client_ptr -> nx_tftp_client_state == NX_TFTP_STATE_END_OF_FILE)
1631 return(NX_TFTP_END_OF_FILE);
1632 else
1633 return(NX_TFTP_NOT_OPEN);
1634 }
1635
1636 /* Read the next block of the file. */
1637 status = nx_udp_socket_receive(&(tftp_client_ptr -> nx_tftp_client_socket), packet_ptr, wait_option);
1638
1639 /* Check the return status. */
1640 if (status != NX_SUCCESS)
1641 {
1642
1643 /* Check for the type of error. */
1644 if (status != NX_NO_PACKET)
1645 {
1646
1647 /* Serious error, enter error state. */
1648 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
1649 }
1650
1651 /* Return error condition. */
1652 return(status);
1653 }
1654
1655 /* Check for valid packet length (The minimum TFTP header size is ACK packet, four bytes). */
1656 if ((*packet_ptr) -> nx_packet_length < 4)
1657 {
1658
1659 /* Release the packet. */
1660 nx_packet_release(*packet_ptr);
1661
1662 /* Return. */
1663 return(NX_INVALID_PACKET);
1664 }
1665
1666 /* At this point, we have a block of the file from the server. */
1667
1668 /* Extract the source IP and port numbers. */
1669 nxd_udp_source_extract(*packet_ptr, &ip_address, &port);
1670
1671 /* Check for an invalid server IP address. */
1672
1673 #ifndef NX_DISABLE_IPV4
1674 if (ip_type == NX_IP_VERSION_V4)
1675 {
1676
1677 if (ip_address.nxd_ip_address.v4 == tftp_client_ptr -> nx_tftp_client_server_ip.nxd_ip_address.v4)
1678 {
1679 matching = NX_TRUE;
1680 }
1681 }
1682 else
1683 #endif /* NX_DISABLE_IPV4 */
1684 #ifdef FEATURE_NX_IPV6
1685 if (ip_type == NX_IP_VERSION_V6)
1686 {
1687 if (CHECK_IPV6_ADDRESSES_SAME(&ip_address.nxd_ip_address.v6[0], &tftp_client_ptr -> nx_tftp_client_server_ip.nxd_ip_address.v6[0]))
1688 {
1689
1690 matching = NX_TRUE;
1691 }
1692 }
1693 else
1694 #endif
1695 {
1696
1697 /* Release the packet. */
1698 nx_packet_release(*packet_ptr);
1699
1700 return NX_TFTP_INVALID_IP_VERSION;
1701 }
1702
1703 /* Do we have a match? */
1704 if (matching == NX_FALSE)
1705 {
1706
1707 /* No, Invalid IP address! */
1708
1709 /* Enter error state. */
1710 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
1711
1712 /* Release the packet. */
1713 nx_packet_release(*packet_ptr);
1714
1715 /* Set packet pointer to NULL. */
1716 *packet_ptr = NX_NULL;
1717
1718 /* Return error condition. */
1719 return(NX_TFTP_INVALID_SERVER_ADDRESS);
1720 }
1721
1722 /* Save the source port since the server can change its port. */
1723 tftp_client_ptr -> nx_tftp_client_server_port = port;
1724
1725 /* Setup a pointer to the buffer. */
1726 buffer_ptr = (*packet_ptr) -> nx_packet_prepend_ptr;
1727
1728 /* Pickup the type of packet. */
1729 buffer_ptr++;
1730 code = *buffer_ptr;
1731
1732 /* Is a data packet present? */
1733 if (code == NX_TFTP_CODE_DATA)
1734 {
1735
1736 /* Yes, a data packet is present. */
1737
1738 /* Pickup the block number. */
1739 buffer_ptr++;
1740 block_number = (USHORT)((*buffer_ptr) << 8);
1741 buffer_ptr++;
1742 block_number = (USHORT)(block_number | (*buffer_ptr));
1743
1744 /* Check if the server didn't receive last TFTP ACK. */
1745 if ((USHORT)(tftp_client_ptr -> nx_tftp_client_block_number - 1) == block_number)
1746 {
1747
1748 /* The Server will resend previous packet till it times out.
1749 set a flag to indicate we need to resend the ACK packet to
1750 prevent this. */
1751 resend_ACK_packet = NX_TRUE;
1752 }
1753 /* Is there a block number match (greater than 1) ? */
1754 else if (tftp_client_ptr -> nx_tftp_client_block_number != block_number)
1755 {
1756
1757 /* Block numbers don't match. Invalid packet or old data packet. Discard it. */
1758
1759 /* Release the packet. */
1760 nx_packet_release(*packet_ptr);
1761
1762 /* Set packet pointer to NULL. */
1763 *packet_ptr = NX_NULL;
1764
1765 /* Return error condition. */
1766 return(NX_TFTP_INVALID_BLOCK_NUMBER);
1767 }
1768
1769 /* Valid block number, end ACK back to server. */
1770
1771 /* Allocate a new packet for the ACK message. Determine whether we are sending
1772 IPv4 or IPv6 packets. */
1773
1774 if (ip_type == NX_IP_VERSION_V4)
1775 {
1776
1777 status = nx_packet_allocate(tftp_client_ptr -> nx_tftp_client_packet_pool_ptr, &ack_packet, NX_IPv4_UDP_PACKET, wait_option);
1778 }
1779 else
1780 {
1781
1782 status = nx_packet_allocate(tftp_client_ptr -> nx_tftp_client_packet_pool_ptr, &ack_packet, NX_IPv6_UDP_PACKET, wait_option);
1783 }
1784
1785 /* Determine if an error occurred trying to allocate a packet. */
1786 if (status != NX_SUCCESS)
1787 {
1788
1789 /* Enter error state. */
1790 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
1791
1792 /* Release the data packet. */
1793 nx_packet_release(*packet_ptr);
1794
1795 /* Set packet pointer to NULL. */
1796 *packet_ptr = NX_NULL;
1797
1798 /* Return error condition. */
1799 return(status);
1800 }
1801
1802 if (4u > ((ULONG)(ack_packet -> nx_packet_data_end) - (ULONG)(ack_packet -> nx_packet_append_ptr)))
1803 {
1804 nx_packet_release(*packet_ptr);
1805
1806 nx_packet_release(ack_packet);
1807 return(NX_SIZE_ERROR);
1808 }
1809
1810 ack_packet -> nx_packet_append_ptr = ack_packet -> nx_packet_prepend_ptr;
1811
1812 /* Valid block number, we need to send an ACK back to server. So now
1813 build the TFTP ACK message. */
1814
1815 /* Setup a pointer to the packet payload. */
1816 buffer_ptr = ack_packet -> nx_packet_prepend_ptr;
1817
1818 /* Initial byte is always zero. */
1819 *buffer_ptr++ = 0;
1820
1821 /* Set the ACK code. */
1822 *buffer_ptr++ = NX_TFTP_CODE_ACK;
1823
1824 /* Put the block number in. */
1825 *buffer_ptr++ = (UCHAR) (block_number >> 8);
1826 *buffer_ptr = (UCHAR) (block_number & 0xFF);
1827
1828 /* Adjust the ACK packet pointers and length. */
1829 ack_packet -> nx_packet_length = 4;
1830 ack_packet -> nx_packet_append_ptr = ack_packet -> nx_packet_append_ptr + 4;
1831
1832 /* Send the ACK packet out. */
1833 status = nxd_udp_socket_send(&(tftp_client_ptr -> nx_tftp_client_socket), ack_packet,
1834 &tftp_client_ptr -> nx_tftp_client_server_ip,
1835 tftp_client_ptr -> nx_tftp_client_server_port);
1836
1837 /* Check error status. */
1838 if (status != NX_SUCCESS)
1839 {
1840 nx_packet_release(*packet_ptr);
1841
1842 nx_packet_release(ack_packet);
1843 return status;
1844 }
1845
1846 /* If we received a duplicate data packet, release it here. */
1847 if (resend_ACK_packet == NX_TRUE)
1848 {
1849
1850 /* ACK for previous packet sent, so we can release this duplicate packet. */
1851 nx_packet_release(*packet_ptr);
1852
1853 /* Set packet pointer to NULL. */
1854 *packet_ptr = NX_NULL;
1855
1856 /* Do not handle as an error. Indicate the TFTP Client is still downloading a file. */
1857 return NX_TFTP_INVALID_BLOCK_NUMBER;
1858 }
1859
1860 /* Adjust the packet to position past the TFTP header. */
1861 (*packet_ptr) -> nx_packet_length = (*packet_ptr) -> nx_packet_length - 4;
1862 (*packet_ptr) -> nx_packet_prepend_ptr = (*packet_ptr) -> nx_packet_prepend_ptr + 4;
1863
1864 /* Check for end of file condition. Anything less than 512 bytes signals an end of file. */
1865 if ((*packet_ptr) -> nx_packet_length < NX_TFTP_FILE_TRANSFER_MAX)
1866 {
1867
1868 /* End of file is present. */
1869
1870 /* Mark the state as end of file. */
1871 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_END_OF_FILE;
1872
1873
1874 /* Return EOF condition. */
1875 return(NX_TFTP_END_OF_FILE);
1876
1877 }
1878 else
1879 {
1880
1881 /* More packets are still required. Increment the block number. */
1882 tftp_client_ptr -> nx_tftp_client_block_number++;
1883 }
1884
1885 /* Return a successful status. */
1886 return(NX_SUCCESS);
1887 }
1888 else if (code == NX_TFTP_CODE_ERROR)
1889 {
1890
1891 /* Error code received. */
1892
1893 /* Change the state to error. */
1894 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
1895
1896 /* Save the error code and message. */
1897 buffer_ptr++;
1898 tftp_client_ptr -> nx_tftp_client_error_code = (((UINT) (*buffer_ptr)) << 8);
1899 buffer_ptr++;
1900 tftp_client_ptr -> nx_tftp_client_error_code |= (UINT) (*buffer_ptr);
1901 buffer_ptr++;
1902
1903 /* Loop to save error message. */
1904 for (i = 0; (i < (sizeof(tftp_client_ptr -> nx_tftp_client_error_string) -1)) && (*buffer_ptr); i++)
1905 {
1906
1907 /* Store desired file name. */
1908 tftp_client_ptr -> nx_tftp_client_error_string[i] = (CHAR) *buffer_ptr++;
1909 }
1910
1911 /* Set NULL terminator. */
1912 tftp_client_ptr -> nx_tftp_client_error_string[i] = NX_NULL;
1913
1914 /* Release the packet. */
1915 nx_packet_release(*packet_ptr);
1916
1917 /* Return a failed status. */
1918 return(NX_TFTP_CODE_ERROR);
1919 }
1920 /* This could be an ack from the previous file write. Just ignore it. */
1921 else if (code == NX_TFTP_CODE_ACK)
1922 {
1923
1924 /* Release the data packet. */
1925 nx_packet_release(*packet_ptr);
1926
1927 /* Not an error. */
1928 return NX_SUCCESS;
1929 }
1930 else
1931 {
1932
1933 /* Change the state to error. */
1934 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
1935
1936 /* Release the packet. */
1937 nx_packet_release(*packet_ptr);
1938
1939 /* Return a failed status. */
1940 return(NX_TFTP_FAILED);
1941 }
1942 }
1943
1944
1945 /**************************************************************************/
1946 /* */
1947 /* FUNCTION RELEASE */
1948 /* */
1949 /* _nxde_tftp_client_file_write PORTABLE C */
1950 /* 6.1 */
1951 /* AUTHOR */
1952 /* */
1953 /* Yuxin Zhou, Microsoft Corporation */
1954 /* */
1955 /* DESCRIPTION */
1956 /* */
1957 /* This function checks for errors in the TFTP file write call. */
1958 /* */
1959 /* */
1960 /* INPUT */
1961 /* */
1962 /* tftp_client_ptr Pointer to TFTP client */
1963 /* packet_ptr Pointer to packet */
1964 /* wait_option Timeout for the write request */
1965 /* ip_type IP type */
1966 /* */
1967 /* OUTPUT */
1968 /* */
1969 /* status Completion status */
1970 /* NX_PTR_ERROR Invalid pointer input */
1971 /* NX_INVALID_PARAMETERS Invalid non pointer input */
1972 /* */
1973 /* CALLS */
1974 /* */
1975 /* _nxd_tftp_client_file_write Actual client file write */
1976 /* */
1977 /* CALLED BY */
1978 /* */
1979 /* Application Code */
1980 /* */
1981 /* RELEASE HISTORY */
1982 /* */
1983 /* DATE NAME DESCRIPTION */
1984 /* */
1985 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1986 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1987 /* resulting in version 6.1 */
1988 /* */
1989 /**************************************************************************/
_nxde_tftp_client_file_write(NX_TFTP_CLIENT * tftp_client_ptr,NX_PACKET * packet_ptr,ULONG wait_option,UINT ip_type)1990 UINT _nxde_tftp_client_file_write(NX_TFTP_CLIENT *tftp_client_ptr, NX_PACKET *packet_ptr, ULONG wait_option, UINT ip_type)
1991 {
1992
1993 UINT status;
1994
1995
1996 /* Check for invalid input pointers. */
1997 if ((tftp_client_ptr == NX_NULL) || (tftp_client_ptr -> nx_tftp_client_id != NXD_TFTP_CLIENT_ID) ||
1998 (packet_ptr == NX_NULL))
1999 return(NX_PTR_ERROR);
2000
2001 /* Check for valid IP version*/
2002 if ((ip_type != NX_IP_VERSION_V4) && (ip_type != NX_IP_VERSION_V6))
2003 {
2004 return NX_INVALID_PARAMETERS;
2005 }
2006
2007 /* Check for appropriate caller. */
2008 NX_THREADS_ONLY_CALLER_CHECKING
2009
2010 /* Call actual client file write function. */
2011 status = _nxd_tftp_client_file_write(tftp_client_ptr, packet_ptr, wait_option, ip_type);
2012
2013 /* Return completion status. */
2014 return(status);
2015 }
2016
2017
2018 /**************************************************************************/
2019 /* */
2020 /* FUNCTION RELEASE */
2021 /* */
2022 /* _nxd_tftp_client_file_write PORTABLE C */
2023 /* 6.1 */
2024 /* AUTHOR */
2025 /* */
2026 /* Yuxin Zhou, Microsoft Corporation */
2027 /* */
2028 /* DESCRIPTION */
2029 /* */
2030 /* This function writes a buffer to a previously opened TFTP file. */
2031 /* */
2032 /* */
2033 /* INPUT */
2034 /* */
2035 /* tftp_client_ptr Pointer to TFTP client */
2036 /* packet_ptr Pointer to packet */
2037 /* wait_option Timeout for the write request */
2038 /* ip_type IP type */
2039 /* */
2040 /* OUTPUT */
2041 /* */
2042 /* status Completion status */
2043 /* NX_TFTP_INVALID_IP_VERSION Unsupported IP protocol */
2044 /* NX_TFTP_NO_ACK_RECEIVED ACK not received from Server */
2045 /* */
2046 /* CALLS */
2047 /* */
2048 /* nx_packet_release Release packet */
2049 /* nx_udp_socket_receive Receive UDP data packet */
2050 /* nxd_udp_socket_send Send TFTP ACK packet */
2051 /* nxd_udp_source_extract Extract IP and port */
2052 /* */
2053 /* CALLED BY */
2054 /* */
2055 /* Application Code */
2056 /* */
2057 /* RELEASE HISTORY */
2058 /* */
2059 /* DATE NAME DESCRIPTION */
2060 /* */
2061 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2062 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2063 /* resulting in version 6.1 */
2064 /* */
2065 /**************************************************************************/
_nxd_tftp_client_file_write(NX_TFTP_CLIENT * tftp_client_ptr,NX_PACKET * packet_ptr,ULONG wait_option,UINT ip_type)2066 UINT _nxd_tftp_client_file_write(NX_TFTP_CLIENT *tftp_client_ptr, NX_PACKET *packet_ptr, ULONG wait_option, UINT ip_type)
2067 {
2068
2069 UCHAR *buffer_ptr;
2070 UINT status;
2071 ULONG length;
2072 NXD_ADDRESS ip_address;
2073 UINT port;
2074 UINT matching = NX_FALSE;
2075
2076
2077 /* Determine if we are still in an open state. */
2078 if (tftp_client_ptr -> nx_tftp_client_state != NX_TFTP_STATE_WRITE_OPEN)
2079 {
2080
2081 /* This instance is not open, return an error. */
2082 return(NX_TFTP_NOT_OPEN);
2083 }
2084
2085 /* Save the length of the TFTP write data. */
2086 length = packet_ptr -> nx_packet_length;
2087
2088 /* Place the TFTP information in front of the data packet. */
2089 packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - 4;
2090 packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + 4;
2091
2092 /* Setup a pointer to the buffer. */
2093 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
2094
2095 /* Set the TFTP data code. */
2096 *buffer_ptr++ = 0;
2097 *buffer_ptr++ = NX_TFTP_CODE_DATA;
2098
2099 /* Set the block number. */
2100 *buffer_ptr++ = (UCHAR) (tftp_client_ptr -> nx_tftp_client_block_number >> 8);
2101 *buffer_ptr++ = (UCHAR) (tftp_client_ptr -> nx_tftp_client_block_number & 0xFF);
2102
2103 /* Send the data packet out. */
2104 status = nxd_udp_socket_send(&(tftp_client_ptr -> nx_tftp_client_socket), packet_ptr,
2105 &tftp_client_ptr -> nx_tftp_client_server_ip, tftp_client_ptr -> nx_tftp_client_server_port);
2106
2107 /* Determine if an error occurred trying to send the packet. */
2108 if (status)
2109 {
2110
2111 /* Enter error state. */
2112 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
2113
2114 /* Release the data packet. */
2115 nx_packet_release(packet_ptr);
2116
2117 /* Return error condition. */
2118 return(status);
2119 }
2120
2121 /* We now need to wait for the ACK for this write request. */
2122 status = nx_udp_socket_receive(&(tftp_client_ptr -> nx_tftp_client_socket), &packet_ptr, wait_option);
2123
2124 /* Check the return status. */
2125 if (status)
2126 {
2127
2128 /* Return error code, the application may rebuild another packet and try again. */
2129
2130 /* Return error condition. */
2131 return(NX_TFTP_TIMEOUT);
2132 }
2133
2134 /* Check for valid packet length (The minimum TFTP header size is ACK packet, four bytes). */
2135 if (packet_ptr -> nx_packet_length < 4)
2136 {
2137
2138 /* Release the packet. */
2139 nx_packet_release(packet_ptr);
2140
2141 /* Return. */
2142 return(NX_INVALID_PACKET);
2143 }
2144
2145 /* Extract the source IP and port numbers. */
2146 nxd_udp_source_extract(packet_ptr, &ip_address, &port);
2147
2148 /* Check for an invalid server IP address. */
2149
2150 #ifndef NX_DISABLE_IPV4
2151 if (ip_type == NX_IP_VERSION_V4)
2152 {
2153
2154 if (ip_address.nxd_ip_address.v4 == tftp_client_ptr -> nx_tftp_client_server_ip.nxd_ip_address.v4)
2155 {
2156 matching = NX_TRUE;
2157 }
2158 }
2159 else
2160 #endif /* NX_DISABLE_IPV4 */
2161 #ifdef FEATURE_NX_IPV6
2162 if (ip_type == NX_IP_VERSION_V6)
2163 {
2164 if (CHECK_IPV6_ADDRESSES_SAME(&ip_address.nxd_ip_address.v6[0], &tftp_client_ptr -> nx_tftp_client_server_ip.nxd_ip_address.v6[0]))
2165 {
2166
2167 matching = NX_TRUE;
2168 }
2169 }
2170 else
2171 #endif
2172 {
2173 /* Release the packet. */
2174 nx_packet_release(packet_ptr);
2175
2176 return NX_TFTP_INVALID_IP_VERSION;
2177 }
2178
2179 /* Do we have a match? */
2180 if (!matching)
2181 {
2182
2183 /* No, Invalid IP address! */
2184
2185 /* Enter error state. */
2186 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
2187
2188 /* Release the packet. */
2189 nx_packet_release(packet_ptr);
2190
2191 /* Return error condition. */
2192 return(NX_TFTP_INVALID_SERVER_ADDRESS);
2193 }
2194
2195 /* Setup a pointer to the buffer. */
2196 buffer_ptr = (packet_ptr) -> nx_packet_prepend_ptr;
2197
2198 /* Check for valid ACK message. */
2199 if ((buffer_ptr[0] != 0) || (buffer_ptr[1] != NX_TFTP_CODE_ACK) ||
2200 (buffer_ptr[2] != ((UCHAR) (tftp_client_ptr -> nx_tftp_client_block_number >> 8))) ||
2201 (buffer_ptr[3] != ((UCHAR) (tftp_client_ptr -> nx_tftp_client_block_number & 0xFF))) ||
2202 (packet_ptr -> nx_packet_length != 4))
2203 {
2204
2205 UINT code;
2206
2207 /* Enter error state. */
2208 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_ERROR;
2209
2210 /* Get the error status from the server message. */
2211 buffer_ptr++;
2212 code = *(buffer_ptr);
2213
2214 /* Check if this is a error reported by the server. If so save it to
2215 the TFTP Client. */
2216 if (code == NX_TFTP_CODE_ERROR)
2217 {
2218 UINT i;
2219
2220 buffer_ptr++;
2221 tftp_client_ptr -> nx_tftp_client_error_code = ((UINT) (*buffer_ptr)) << 8;
2222 buffer_ptr++;
2223 tftp_client_ptr -> nx_tftp_client_error_code |= (UINT) (*buffer_ptr);
2224 buffer_ptr++;
2225
2226 /* Loop to save error message. */
2227 for (i = 0; (i < (sizeof(tftp_client_ptr -> nx_tftp_client_error_string) -1)) && (*buffer_ptr); i++)
2228 {
2229
2230 /* Store desired file name. */
2231 tftp_client_ptr -> nx_tftp_client_error_string[i] = (CHAR) *buffer_ptr++;
2232 }
2233
2234 /* Set NULL terminator. */
2235 tftp_client_ptr -> nx_tftp_client_error_string[i] = NX_NULL;
2236
2237 /* Release the packet. */
2238 nx_packet_release(packet_ptr);
2239
2240 /* Return error condition. */
2241 return(NX_TFTP_CODE_ERROR);
2242 }
2243 /* Unknown code, not an error or an ACK. */
2244 else
2245 {
2246
2247 /* Release the packet. */
2248 nx_packet_release(packet_ptr);
2249
2250 /* Return error condition. */
2251 return(NX_TFTP_NO_ACK_RECEIVED);
2252 }
2253 }
2254
2255 /* At this point, everything is okay. */
2256
2257 /* Release the ACK packet. */
2258 nx_packet_release(packet_ptr);
2259
2260 /* Check the length to see if we have the end of the file. */
2261 if (length < NX_TFTP_FILE_TRANSFER_MAX)
2262 {
2263
2264 /* Yes, this is the last packet. */
2265
2266 /* Enter into the finished state. */
2267 tftp_client_ptr -> nx_tftp_client_state = NX_TFTP_STATE_FINISHED;
2268 }
2269 else
2270 {
2271
2272 /* More blocks to transfer still, increment the block number. */
2273 tftp_client_ptr -> nx_tftp_client_block_number++;
2274 }
2275
2276 /* Return success to the caller. */
2277 return(NX_SUCCESS);
2278 }
2279
2280
2281 /**************************************************************************/
2282 /* */
2283 /* FUNCTION RELEASE */
2284 /* */
2285 /* _nxde_tftp_client_packet_allocate PORTABLE C */
2286 /* 6.1 */
2287 /* AUTHOR */
2288 /* */
2289 /* Yuxin Zhou, Microsoft Corporation */
2290 /* */
2291 /* DESCRIPTION */
2292 /* */
2293 /* This function checks for errors in the TFTP packet allocate call. */
2294 /* */
2295 /* */
2296 /* INPUT */
2297 /* */
2298 /* pool_ptr Pointer to packet pool */
2299 /* packet_ptr Pointer to destination for */
2300 /* pointer of newly allocated */
2301 /* packet */
2302 /* wait_option Timeout for the request */
2303 /* ip_type IP type */
2304 /* */
2305 /* OUTPUT */
2306 /* */
2307 /* status Completion status */
2308 /* NX_PTR_ERROR Invalid pointer input */
2309 /* NX_INVALID_PARAMETERS Invalid non pointer input */
2310 /* */
2311 /* CALLS */
2312 /* */
2313 /* _nxd_tftp _client_file_write Actual client file write */
2314 /* */
2315 /* CALLED BY */
2316 /* */
2317 /* Application Code */
2318 /* */
2319 /* RELEASE HISTORY */
2320 /* */
2321 /* DATE NAME DESCRIPTION */
2322 /* */
2323 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2324 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2325 /* resulting in version 6.1 */
2326 /* */
2327 /**************************************************************************/
_nxde_tftp_client_packet_allocate(NX_PACKET_POOL * pool_ptr,NX_PACKET ** packet_ptr,ULONG wait_option,UINT ip_type)2328 UINT _nxde_tftp_client_packet_allocate(NX_PACKET_POOL *pool_ptr, NX_PACKET **packet_ptr, ULONG wait_option, UINT ip_type)
2329 {
2330
2331 UINT status;
2332
2333
2334 /* Check for invalid input pointers. */
2335 if ((pool_ptr == NX_NULL) || (packet_ptr == NX_NULL))
2336 return(NX_PTR_ERROR);
2337
2338 /* Check for valid IP version*/
2339 if ((ip_type != NX_IP_VERSION_V4) && (ip_type != NX_IP_VERSION_V6))
2340 {
2341 return NX_INVALID_PARAMETERS;
2342 }
2343
2344 /* Check for appropriate caller. */
2345 NX_THREADS_ONLY_CALLER_CHECKING
2346
2347 /* Call actual client packet allocate function. */
2348 status = _nxd_tftp_client_packet_allocate(pool_ptr, packet_ptr, wait_option, ip_type);
2349
2350 /* Return completion status. */
2351 return(status);
2352 }
2353
2354
2355 /**************************************************************************/
2356 /* */
2357 /* FUNCTION RELEASE */
2358 /* */
2359 /* _nxd_tftp_client_packet_allocate PORTABLE C */
2360 /* 6.1 */
2361 /* AUTHOR */
2362 /* */
2363 /* Yuxin Zhou, Microsoft Corporation */
2364 /* */
2365 /* DESCRIPTION */
2366 /* */
2367 /* This function allocates a packet with extra room for the TFTP */
2368 /* control information. */
2369 /* */
2370 /* */
2371 /* INPUT */
2372 /* */
2373 /* pool_ptr Pointer to packet pool */
2374 /* packet_ptr Pointer to destination for */
2375 /* pointer of newly allocated */
2376 /* packet */
2377 /* wait_option Timeout for the request */
2378 /* ip_type IP type */
2379 /* */
2380 /* OUTPUT */
2381 /* */
2382 /* status Completion status */
2383 /* */
2384 /* CALLS */
2385 /* */
2386 /* nx_packet_allocate Allocate packet */
2387 /* */
2388 /* CALLED BY */
2389 /* */
2390 /* Application Code */
2391 /* */
2392 /* RELEASE HISTORY */
2393 /* */
2394 /* DATE NAME DESCRIPTION */
2395 /* */
2396 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2397 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2398 /* resulting in version 6.1 */
2399 /* */
2400 /**************************************************************************/
_nxd_tftp_client_packet_allocate(NX_PACKET_POOL * pool_ptr,NX_PACKET ** packet_ptr,ULONG wait_option,UINT ip_type)2401 UINT _nxd_tftp_client_packet_allocate(NX_PACKET_POOL *pool_ptr, NX_PACKET **packet_ptr, ULONG wait_option, UINT ip_type)
2402 {
2403
2404 UINT status;
2405
2406
2407 /* Allocate a new packet. Determine whether we are sending IPv4 or IPv6 packets. */
2408 if (ip_type == NX_IP_VERSION_V4)
2409 {
2410
2411 status = nx_packet_allocate(pool_ptr, packet_ptr, NX_IPv4_UDP_PACKET, wait_option);
2412 }
2413 else
2414 {
2415
2416 status = nx_packet_allocate(pool_ptr, packet_ptr, NX_IPv6_UDP_PACKET, wait_option);
2417 }
2418
2419 /* Determine if an error is present. */
2420 if (status)
2421 {
2422
2423 /* Return the error code from the allocate routine. */
2424 return(status);
2425 }
2426
2427 (*packet_ptr) -> nx_packet_append_ptr = (*packet_ptr) -> nx_packet_prepend_ptr;
2428
2429 /* Successful packet allocation. Adjust the prepend and append pointers forward to
2430 accommodate the TFTP header. */
2431 (*packet_ptr) -> nx_packet_prepend_ptr += 4;
2432 (*packet_ptr) -> nx_packet_append_ptr += 4;
2433
2434 /* Return success to the caller. */
2435 return(NX_SUCCESS);
2436 }
2437
2438