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