1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** NetX Duo Component                                                    */
16 /**   Trivial File Transfer Protocol (TFTP) Server                        */
17 /**                                                                       */
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 /* Include necessary system files.  */
32 
33 #include    "nx_api.h"
34 #include    "nx_ip.h"
35 #include    "nxd_tftp_server.h"
36 #ifdef FEATURE_NX_IPV6
37 #include    "nx_ipv6.h"
38 #endif
39 
40 /* Bring in externs for caller checking code.  */
41 
42 NX_CALLER_CHECKING_EXTERNS
43 
44 /**************************************************************************/
45 /*                                                                        */
46 /*  FUNCTION                                               RELEASE        */
47 /*                                                                        */
48 /*    _nxde_tftp_server_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 server create call.     */
57 /*                                                                        */
58 /*                                                                        */
59 /*  INPUT                                                                 */
60 /*                                                                        */
61 /*    tftp_server_ptr                       Pointer to TFTP server        */
62 /*    tftp_server_name                      Name of TFTP server           */
63 /*    ip_ptr                                Pointer to IP instance        */
64 /*    media_ptr                             Pointer to media structure    */
65 /*    stack_ptr                             Server thread's stack pointer */
66 /*    stack_size                            Server thread's stack size    */
67 /*    pool_ptr                              Pointer to packet pool        */
68 /*                                                                        */
69 /*  OUTPUT                                                                */
70 /*                                                                        */
71 /*    status                                Completion status             */
72 /*    NX_PTR_ERROR                          Invalid pointer input         */
73 /*    NX_TFTP_POOL_ERROR                    Invalid packet size for TFTP  */
74 /*                                              server packet pool        */
75 /*                                                                        */
76 /*  CALLS                                                                 */
77 /*                                                                        */
78 /*    _nxd_tftp_server_create               Actual server create call     */
79 /*                                                                        */
80 /*  CALLED BY                                                             */
81 /*                                                                        */
82 /*    Application Code                                                    */
83 /*                                                                        */
84 /*  RELEASE HISTORY                                                       */
85 /*                                                                        */
86 /*    DATE              NAME                      DESCRIPTION             */
87 /*                                                                        */
88 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
89 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
90 /*                                            resulting in version 6.1    */
91 /*                                                                        */
92 /**************************************************************************/
_nxde_tftp_server_create(NX_TFTP_SERVER * tftp_server_ptr,CHAR * tftp_server_name,NX_IP * ip_ptr,FX_MEDIA * media_ptr,VOID * stack_ptr,ULONG stack_size,NX_PACKET_POOL * pool_ptr)93 UINT  _nxde_tftp_server_create(NX_TFTP_SERVER *tftp_server_ptr, CHAR *tftp_server_name, NX_IP *ip_ptr,
94                                 FX_MEDIA *media_ptr, VOID *stack_ptr, ULONG stack_size, NX_PACKET_POOL *pool_ptr)
95 {
96 
97 UINT        status;
98 NX_PACKET   *packet_ptr;
99 
100 
101     /* Check for invalid input pointers.  */
102     if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
103         (tftp_server_ptr == NX_NULL) || (tftp_server_ptr -> nx_tftp_server_id == NXD_TFTP_SERVER_ID) ||
104         (stack_ptr == NX_NULL) || (pool_ptr == NX_NULL))
105     {
106 
107         return(NX_PTR_ERROR);
108     }
109 
110     /* Pickup a packet from the supplied packet pool.  */
111     packet_ptr =  pool_ptr -> nx_packet_pool_available_list;
112 
113     /* Determine if the packet payload is large enough (must include 512 bytes plus packet headers).  */
114     if ((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start) < NX_TFTP_PACKET_SIZE)
115     {
116 
117         return(NX_TFTP_POOL_ERROR);
118     }
119 
120     /* Call actual server create function.  */
121     status =  _nxd_tftp_server_create(tftp_server_ptr, tftp_server_name, ip_ptr, media_ptr, stack_ptr, stack_size, pool_ptr);
122 
123     /* Return completion status.  */
124     return(status);
125 }
126 
127 
128 /**************************************************************************/
129 /*                                                                        */
130 /*  FUNCTION                                               RELEASE        */
131 /*                                                                        */
132 /*    _nxd_tftp_server_create                             PORTABLE C      */
133 /*                                                           6.1          */
134 /*  AUTHOR                                                                */
135 /*                                                                        */
136 /*    Yuxin Zhou, Microsoft Corporation                                   */
137 /*                                                                        */
138 /*  DESCRIPTION                                                           */
139 /*                                                                        */
140 /*    This function creates a TFTP server on the specified IP. In doing   */
141 /*    so this function creates an UDP socket for subsequent TFTP          */
142 /*    transfers and a thread for the TFTP server.                         */
143 /*                                                                        */
144 /*    If  NX_TFTP_SERVER_RETRANSMIT_ENABLE is enabled, it also creates    */
145 /*    a timer for retransmitting TFTP server packets up to a maximum      */
146 /*    number of retries before terminating the connection.                */
147 /*                                                                        */
148 /*  INPUT                                                                 */
149 /*                                                                        */
150 /*    tftp_server_ptr                       Pointer to TFTP server        */
151 /*    tftpvserver_name                      Name of TFTP server           */
152 /*    ip_ptr                                Pointer to IP instance        */
153 /*    media_ptr                             Pointer to media structure    */
154 /*    stack_ptr                             Server thread's stack pointer */
155 /*    stack_size                            Server thread's stack size    */
156 /*    pool_ptr                              Pointer to packet pool        */
157 /*                                                                        */
158 /*  OUTPUT                                                                */
159 /*                                                                        */
160 /*    status                                Actual cmpletion status       */
161 /*    NX_SUCCESS                            Successful completion         */
162 /*                                                                        */
163 /*  CALLS                                                                 */
164 /*                                                                        */
165 /*    nx_udp_socket_bind                    Bind the TFTP server socket   */
166 /*    nx_udp_socket_create                  Create TFTP server socket     */
167 /*    nx_udp_socket_delete                  Delete TFTP server socket     */
168 /*    nx_udp_socket_unbind                  Unbind TFTP server socket     */
169 /*    tx_thread_create                      Create TFTP server thread     */
170 /*    tx_timer_create                       Create retransmit timer       */
171 /*    nx_udp_socket_receive_notify          Set a receive callback        */
172 /*                                                                        */
173 /*  CALLED BY                                                             */
174 /*                                                                        */
175 /*    Application Code                                                    */
176 /*                                                                        */
177 /*  RELEASE HISTORY                                                       */
178 /*                                                                        */
179 /*    DATE              NAME                      DESCRIPTION             */
180 /*                                                                        */
181 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
182 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
183 /*                                            resulting in version 6.1    */
184 /*                                                                        */
185 /**************************************************************************/
_nxd_tftp_server_create(NX_TFTP_SERVER * tftp_server_ptr,CHAR * tftp_server_name,NX_IP * ip_ptr,FX_MEDIA * media_ptr,VOID * stack_ptr,ULONG stack_size,NX_PACKET_POOL * pool_ptr)186 UINT  _nxd_tftp_server_create(NX_TFTP_SERVER *tftp_server_ptr, CHAR *tftp_server_name, NX_IP *ip_ptr,
187                                FX_MEDIA *media_ptr, VOID *stack_ptr, ULONG stack_size, NX_PACKET_POOL *pool_ptr)
188 {
189 
190 UINT        status;
191 
192 
193     /* Clear the TFTP server structure.  */
194     memset((void *) tftp_server_ptr, 0, sizeof(NX_TFTP_SERVER));
195 
196     /* Create the server's UDP socket.  */
197     status =  nx_udp_socket_create(ip_ptr, &(tftp_server_ptr -> nx_tftp_server_socket), tftp_server_name,
198                           NX_TFTP_TYPE_OF_SERVICE,  NX_TFTP_FRAGMENT_OPTION, NX_TFTP_TIME_TO_LIVE, NX_TFTP_QUEUE_DEPTH);
199 
200     /* Determine if an error occurred.   */
201     if (status != NX_SUCCESS)
202     {
203 
204         /* Yes, return error code.  */
205         return(status);
206     }
207 
208     /* Register the receive function.  */
209     nx_udp_socket_receive_notify(&(tftp_server_ptr -> nx_tftp_server_socket), _nx_tftp_server_data_present);
210 
211     /* Make sure the socket points to the TFTP server.  */
212     tftp_server_ptr -> nx_tftp_server_socket.nx_udp_socket_reserved_ptr =  tftp_server_ptr;
213 
214     /* Now, bind the socket to a the well known TFTP UDP port number.  */
215     status =  nx_udp_socket_bind(&(tftp_server_ptr -> nx_tftp_server_socket), NX_TFTP_SERVER_PORT, NX_NO_WAIT);
216 
217     /* Determine if an error occurred.  */
218     if (status != NX_SUCCESS)
219     {
220 
221         /* Delete the UDP socket.  */
222         nx_udp_socket_delete(&(tftp_server_ptr -> nx_tftp_server_socket));
223 
224         /* Yes, return error code.  */
225         return(status);
226     }
227 
228     /* Now create the TFTP Server thread.  */
229     status =  tx_thread_create(&(tftp_server_ptr -> nx_tftp_server_thread), "TFTP Server Thread", _nx_tftp_server_thread_entry,
230                 (ULONG) tftp_server_ptr, stack_ptr, stack_size, NX_TFTP_SERVER_PRIORITY, NX_TFTP_SERVER_PRIORITY,
231                 NX_TFTP_SERVER_TIME_SLICE, TX_DONT_START);
232 
233     /* Determine if an error occurred creating the thread.  */
234     if (status != NX_SUCCESS)
235     {
236 
237         /* Unbind the UDP socket.  */
238         nx_udp_socket_unbind(&(tftp_server_ptr -> nx_tftp_server_socket));
239 
240         /* Delete the UDP socket.  */
241         nx_udp_socket_delete(&(tftp_server_ptr -> nx_tftp_server_socket));
242 
243         /* Yes, return error code.  */
244         return(status);
245     }
246 
247     /* Create the ThreadX event flags.  These will be used to drive the TFTP server thread.  */
248     status =  tx_event_flags_create(&(tftp_server_ptr -> nx_tftp_server_event_flags), "TFTP Server Thread Events");
249 
250     /* Determine if an error occurred creating the event flags.  */
251     if (status != TX_SUCCESS)
252     {
253 
254         /* Unbind the UDP socket.  */
255         nx_udp_socket_unbind(&(tftp_server_ptr -> nx_tftp_server_socket));
256 
257         /* Delete the UDP socket.  */
258         nx_udp_socket_delete(&(tftp_server_ptr -> nx_tftp_server_socket));
259 
260         /* Delete the server thread.  */
261         tx_thread_delete(&(tftp_server_ptr -> nx_tftp_server_thread));
262 
263         /* Error creating the server event flags.  */
264         return(status);
265     }
266 
267 #ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE
268 
269     /* Create the ThreadX retransmit timeout timer.  This will be used to retransmit TFTP server
270        packets if the Client has not responded or sends a duplicate (old) ACK or data packet.  */
271     status =  tx_timer_create(&(tftp_server_ptr -> nx_tftp_server_timer), "TFTP Server Timer",
272                               _nx_tftp_server_timer_entry, (ULONG) tftp_server_ptr,
273                               (NX_TFTP_SERVER_TIMEOUT_PERIOD),
274                               (NX_TFTP_SERVER_TIMEOUT_PERIOD), TX_NO_ACTIVATE);
275 
276     if (status != NX_SUCCESS)
277     {
278 
279         /* Unbind the UDP socket.  */
280         nx_udp_socket_unbind(&(tftp_server_ptr -> nx_tftp_server_socket));
281 
282         /* Delete the UDP socket.  */
283         nx_udp_socket_delete(&(tftp_server_ptr -> nx_tftp_server_socket));
284 
285         /* Delete the event flags.  */
286         tx_event_flags_delete(&(tftp_server_ptr -> nx_tftp_server_event_flags));
287 
288         /* Delete the server thread.  */
289         tx_thread_delete(&(tftp_server_ptr -> nx_tftp_server_thread));
290 
291         /* Yes, return error code.  */
292         return(status);
293     }
294 #endif /* NX_TFTP_SERVER_RETRANSMIT_ENABLE */
295 
296     /* Save the Server name.  */
297     tftp_server_ptr -> nx_tftp_server_name =  tftp_server_name;
298 
299     /* Save the IP pointer address.  */
300     tftp_server_ptr -> nx_tftp_server_ip_ptr =  ip_ptr;
301 
302     /* Save the packet pool pointer.  */
303     tftp_server_ptr -> nx_tftp_server_packet_pool_ptr =  pool_ptr;
304 
305     /* Save the media pointer address.  */
306     tftp_server_ptr -> nx_tftp_server_media_ptr =  media_ptr;
307 
308     /* Clear the error code and error string.  */
309     tftp_server_ptr -> nx_tftp_server_error_code =       0;
310     tftp_server_ptr -> nx_tftp_server_error_string[0] =  NX_NULL;
311 
312     /* Set the server ID to indicate the TFTP server thread is ready.  */
313     tftp_server_ptr -> nx_tftp_server_id =  NXD_TFTP_SERVER_ID;
314 
315     /* Return successful completion.  */
316     return(NX_SUCCESS);
317 }
318 
319 /**************************************************************************/
320 /*                                                                        */
321 /*  FUNCTION                                               RELEASE        */
322 /*                                                                        */
323 /*    _nxde_tftp_server_delete                            PORTABLE C      */
324 /*                                                           6.1          */
325 /*  AUTHOR                                                                */
326 /*                                                                        */
327 /*    Yuxin Zhou, Microsoft Corporation                                   */
328 /*                                                                        */
329 /*  DESCRIPTION                                                           */
330 /*                                                                        */
331 /*    This function checks for errors in the TFTP server delete call.     */
332 /*                                                                        */
333 /*                                                                        */
334 /*  INPUT                                                                 */
335 /*                                                                        */
336 /*    tftp_server_ptr                       Pointer to TFTP server        */
337 /*                                                                        */
338 /*  OUTPUT                                                                */
339 /*                                                                        */
340 /*    status                                Completion status             */
341 /*    NX_PTR_ERROR                          Invalid pointer input         */
342 /*                                                                        */
343 /*  CALLS                                                                 */
344 /*                                                                        */
345 /*    _nxd_tftp_server_delete               Actual server delete call     */
346 /*                                                                        */
347 /*  CALLED BY                                                             */
348 /*                                                                        */
349 /*    Application Code                                                    */
350 /*                                                                        */
351 /*  RELEASE HISTORY                                                       */
352 /*                                                                        */
353 /*    DATE              NAME                      DESCRIPTION             */
354 /*                                                                        */
355 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
356 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
357 /*                                            resulting in version 6.1    */
358 /*                                                                        */
359 /**************************************************************************/
_nxde_tftp_server_delete(NX_TFTP_SERVER * tftp_server_ptr)360 UINT  _nxde_tftp_server_delete(NX_TFTP_SERVER *tftp_server_ptr)
361 {
362 
363 UINT    status;
364 
365 
366     /* Check for invalid input pointers.  */
367     if ((tftp_server_ptr == NX_NULL) || (tftp_server_ptr -> nx_tftp_server_id != NXD_TFTP_SERVER_ID))
368         return(NX_PTR_ERROR);
369 
370     /* Check for appropriate caller.  */
371     NX_THREADS_ONLY_CALLER_CHECKING
372 
373     /* Call actual server delete function.  */
374     status =  _nxd_tftp_server_delete(tftp_server_ptr);
375 
376     /* Return completion status.  */
377     return(status);
378 }
379 
380 
381 /**************************************************************************/
382 /*                                                                        */
383 /*  FUNCTION                                               RELEASE        */
384 /*                                                                        */
385 /*    _nxd_tftp_server_delete                             PORTABLE C      */
386 /*                                                           6.1          */
387 /*  AUTHOR                                                                */
388 /*                                                                        */
389 /*    Yuxin Zhou, Microsoft Corporation                                   */
390 /*                                                                        */
391 /*  DESCRIPTION                                                           */
392 /*                                                                        */
393 /*    This function deletes a previously created TFTP server on the       */
394 /*    specified IP.                                                       */
395 /*                                                                        */
396 /*                                                                        */
397 /*  INPUT                                                                 */
398 /*                                                                        */
399 /*    tftp_server_ptr                       Pointer to TFTP server        */
400 /*                                                                        */
401 /*  OUTPUT                                                                */
402 /*                                                                        */
403 /*    NX_SUCCESS                            Successful completion         */
404 /*    status                                Actual completion status      */
405 /*                                                                        */
406 /*  CALLS                                                                 */
407 /*                                                                        */
408 /*    fx_file_close                         File close                    */
409 /*    nx_udp_socket_delete                  Delete TFTP server socket     */
410 /*    nx_udp_socket_unbind                  Unbind TFTP server socket     */
411 /*    tx_thread_delete                      Delete TFTP server thread     */
412 /*    tx_thread_suspend                     Suspend TFTP server thread    */
413 /*    tx_thread_terminate                   Terminate TFTP server         */
414 /*                                            thread                      */
415 /*                                                                        */
416 /*  CALLED BY                                                             */
417 /*                                                                        */
418 /*    Application Code                                                    */
419 /*                                                                        */
420 /*  RELEASE HISTORY                                                       */
421 /*                                                                        */
422 /*    DATE              NAME                      DESCRIPTION             */
423 /*                                                                        */
424 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
425 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
426 /*                                            resulting in version 6.1    */
427 /*                                                                        */
428 /**************************************************************************/
_nxd_tftp_server_delete(NX_TFTP_SERVER * tftp_server_ptr)429 UINT  _nxd_tftp_server_delete(NX_TFTP_SERVER *tftp_server_ptr)
430 {
431 
432 UINT                        i;
433 NX_TFTP_CLIENT_REQUEST      *client_request_ptr;
434 
435 
436     /* Clear the server ID to indicate the TFTP server is no longer ready.  */
437     tftp_server_ptr -> nx_tftp_server_id =  0;
438 
439     /* Unbind the UDP socket.  */
440     nx_udp_socket_unbind(&(tftp_server_ptr -> nx_tftp_server_socket));
441 
442     /* Delete the UDP socket.  */
443     nx_udp_socket_delete(&(tftp_server_ptr -> nx_tftp_server_socket));
444 
445     /* Suspend the TFTP server thread.  */
446     tx_thread_suspend(&(tftp_server_ptr -> nx_tftp_server_thread));
447 
448     /* Terminate server thread. */
449     tx_thread_terminate(&(tftp_server_ptr -> nx_tftp_server_thread));
450 
451     /* Delete the server flag group. */
452     tx_event_flags_delete(&(tftp_server_ptr -> nx_tftp_server_event_flags));
453 
454 #ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE
455     tx_timer_delete(&(tftp_server_ptr -> nx_tftp_server_timer));
456 #endif
457 
458 
459     /* Delete server thread.  */
460     tx_thread_delete(&(tftp_server_ptr -> nx_tftp_server_thread));
461 
462     /* Walk through the server structure to close any remaining open files.  */
463     i =  0;
464 
465     client_request_ptr =  &(tftp_server_ptr -> nx_tftp_server_client_list[0]);
466 
467     while (i < NX_TFTP_MAX_CLIENTS)
468     {
469 
470         /* Is this entry in use?  */
471 
472         /* First determine which IP address type. */
473         if (client_request_ptr -> nx_tftp_client_request_ip_address.nxd_ip_version == NX_IP_VERSION_V4)
474         {
475 
476 #ifndef NX_DISABLE_IPV4
477             /* This is an IPv4 client. Is this slot empty? */
478             if ((client_request_ptr -> nx_tftp_client_request_port != 0) &&
479                 (client_request_ptr -> nx_tftp_client_request_ip_address.nxd_ip_address.v4) != 0)
480             {
481 
482                 /* No, need to close the file on this client!  */
483                 fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
484             }
485 #endif /* NX_DISABLE_IPV4 */
486         }
487         else if (client_request_ptr -> nx_tftp_client_request_ip_address.nxd_ip_version == NX_IP_VERSION_V6)
488         {
489 
490 #ifdef FEATURE_NX_IPV6
491               /* This is an IPv6 Client. Is this slot empty? */
492               if ((client_request_ptr -> nx_tftp_client_request_port != 0) &&
493                   (!CHECK_UNSPECIFIED_ADDRESS(&client_request_ptr -> nx_tftp_client_request_ip_address.nxd_ip_address.v6[0])))
494               {
495 
496                   /* No, need to close the file on this client!*/
497                   fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
498               }
499 #endif  /* FEATURE_NX_IPV6  */
500         }
501 
502         /* Increment the pointer into the client request list.  */
503         client_request_ptr++;
504         i++;
505     }
506 
507     /* Return successful completion.  */
508     return(NX_SUCCESS);
509 }
510 
511 
512 /**************************************************************************/
513 /*                                                                        */
514 /*  FUNCTION                                               RELEASE        */
515 /*                                                                        */
516 /*    _nxde_tftp_server_start                             PORTABLE C      */
517 /*                                                           6.1          */
518 /*  AUTHOR                                                                */
519 /*                                                                        */
520 /*    Yuxin Zhou, Microsoft Corporation                                   */
521 /*                                                                        */
522 /*  DESCRIPTION                                                           */
523 /*                                                                        */
524 /*    This function checks for errors in the TFTP server start call.      */
525 /*                                                                        */
526 /*                                                                        */
527 /*  INPUT                                                                 */
528 /*                                                                        */
529 /*    tftp_server_ptr                       Pointer to TFTP server        */
530 /*                                                                        */
531 /*  OUTPUT                                                                */
532 /*                                                                        */
533 /*    status                                Completion status             */
534 /*    NX_PTR_ERROR                          Invalid pointer input         */
535 /*                                                                        */
536 /*  CALLS                                                                 */
537 /*                                                                        */
538 /*    _nxd_tftp_server_start                Actual server start call      */
539 /*                                                                        */
540 /*  CALLED BY                                                             */
541 /*                                                                        */
542 /*    Application Code                                                    */
543 /*                                                                        */
544 /*  RELEASE HISTORY                                                       */
545 /*                                                                        */
546 /*    DATE              NAME                      DESCRIPTION             */
547 /*                                                                        */
548 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
549 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
550 /*                                            resulting in version 6.1    */
551 /*                                                                        */
552 /**************************************************************************/
_nxde_tftp_server_start(NX_TFTP_SERVER * tftp_server_ptr)553 UINT  _nxde_tftp_server_start(NX_TFTP_SERVER *tftp_server_ptr)
554 {
555 
556 UINT    status;
557 
558 
559     /* Check for invalid input pointers.  */
560     if ((tftp_server_ptr == NX_NULL) || (tftp_server_ptr -> nx_tftp_server_id != NXD_TFTP_SERVER_ID))
561         return(NX_PTR_ERROR);
562 
563     /* Call actual server start function.  */
564     status =  _nxd_tftp_server_start(tftp_server_ptr);
565 
566     /* Return completion status.  */
567     return(status);
568 }
569 
570 
571 /**************************************************************************/
572 /*                                                                        */
573 /*  FUNCTION                                               RELEASE        */
574 /*                                                                        */
575 /*    _nxd_tftp_server_start                              PORTABLE C      */
576 /*                                                           6.1          */
577 /*  AUTHOR                                                                */
578 /*                                                                        */
579 /*    Yuxin Zhou, Microsoft Corporation                                   */
580 /*                                                                        */
581 /*  DESCRIPTION                                                           */
582 /*                                                                        */
583 /*    This function starts a previously created TFTP server on the        */
584 /*    specified IP.                                                       */
585 /*                                                                        */
586 /*                                                                        */
587 /*  INPUT                                                                 */
588 /*                                                                        */
589 /*    tftp_server_ptr                       Pointer to TFTP server        */
590 /*                                                                        */
591 /*  OUTPUT                                                                */
592 /*                                                                        */
593 /*    NX_SUCCESS                            Successful completion         */
594 /*                                                                        */
595 /*  CALLS                                                                 */
596 /*                                                                        */
597 /*    tx_thread_resume                      Resume TFTP server thread     */
598 /*                                                                        */
599 /*  CALLED BY                                                             */
600 /*                                                                        */
601 /*    Application Code                                                    */
602 /*                                                                        */
603 /*  RELEASE HISTORY                                                       */
604 /*                                                                        */
605 /*    DATE              NAME                      DESCRIPTION             */
606 /*                                                                        */
607 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
608 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
609 /*                                            resulting in version 6.1    */
610 /*                                                                        */
611 /**************************************************************************/
_nxd_tftp_server_start(NX_TFTP_SERVER * tftp_server_ptr)612 UINT  _nxd_tftp_server_start(NX_TFTP_SERVER *tftp_server_ptr)
613 {
614 
615 #ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE
616     /* Activate TFTP server timer.  */
617     tx_timer_activate(&(tftp_server_ptr -> nx_tftp_server_timer));
618 #endif
619 
620     /* Start the TFTP server thread.  */
621     tx_thread_resume(&(tftp_server_ptr -> nx_tftp_server_thread));
622 
623     /* Return successful completion.  */
624     return(NX_SUCCESS);
625 }
626 
627 
628 /**************************************************************************/
629 /*                                                                        */
630 /*  FUNCTION                                               RELEASE        */
631 /*                                                                        */
632 /*    _nxde_tftp_server_stop                              PORTABLE C      */
633 /*                                                           6.1          */
634 /*  AUTHOR                                                                */
635 /*                                                                        */
636 /*    Yuxin Zhou, Microsoft Corporation                                   */
637 /*                                                                        */
638 /*  DESCRIPTION                                                           */
639 /*                                                                        */
640 /*    This function checks for errors in the TFTP server stop call.       */
641 /*                                                                        */
642 /*                                                                        */
643 /*  INPUT                                                                 */
644 /*                                                                        */
645 /*    tftp_server_ptr                       Pointer to TFTP server        */
646 /*                                                                        */
647 /*  OUTPUT                                                                */
648 /*                                                                        */
649 /*    status                                Completion status             */
650 /*    NX_PTR_ERROR                          Invalid pointer input         */
651 /*                                                                        */
652 /*  CALLS                                                                 */
653 /*                                                                        */
654 /*    _nxd_tftp_server_stop                 Actual server start call      */
655 /*                                                                        */
656 /*  CALLED BY                                                             */
657 /*                                                                        */
658 /*    Application Code                                                    */
659 /*                                                                        */
660 /*  RELEASE HISTORY                                                       */
661 /*                                                                        */
662 /*    DATE              NAME                      DESCRIPTION             */
663 /*                                                                        */
664 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
665 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
666 /*                                            resulting in version 6.1    */
667 /*                                                                        */
668 /**************************************************************************/
_nxde_tftp_server_stop(NX_TFTP_SERVER * tftp_server_ptr)669 UINT  _nxde_tftp_server_stop(NX_TFTP_SERVER *tftp_server_ptr)
670 {
671 
672 UINT    status;
673 
674 
675     /* Check for invalid input pointers.  */
676     if ((tftp_server_ptr == NX_NULL) || (tftp_server_ptr -> nx_tftp_server_id != NXD_TFTP_SERVER_ID))
677         return(NX_PTR_ERROR);
678 
679     /* Check for appropriate caller.  */
680     NX_THREADS_ONLY_CALLER_CHECKING
681 
682     /* Call actual server delete function.  */
683     status =  _nxd_tftp_server_stop(tftp_server_ptr);
684 
685     /* Return completion status.  */
686     return(status);
687 }
688 
689 
690 /**************************************************************************/
691 /*                                                                        */
692 /*  FUNCTION                                               RELEASE        */
693 /*                                                                        */
694 /*    _nxd_tftp_server_stop                               PORTABLE C      */
695 /*                                                           6.1          */
696 /*  AUTHOR                                                                */
697 /*                                                                        */
698 /*    Yuxin Zhou, Microsoft Corporation                                   */
699 /*                                                                        */
700 /*  DESCRIPTION                                                           */
701 /*                                                                        */
702 /*    This function stops a previously started TFTP server on the         */
703 /*    specified IP.                                                       */
704 /*                                                                        */
705 /*                                                                        */
706 /*  INPUT                                                                 */
707 /*                                                                        */
708 /*    tftp_server_ptr                       Pointer to TFTP server        */
709 /*                                                                        */
710 /*  OUTPUT                                                                */
711 /*                                                                        */
712 /*    NX_SUCCESS                            Successful completion         */
713 /*                                                                        */
714 /*  CALLS                                                                 */
715 /*                                                                        */
716 /*    tx_thread_suspend                     Suspend TFTP server thread    */
717 /*                                                                        */
718 /*  CALLED BY                                                             */
719 /*                                                                        */
720 /*    Application Code                                                    */
721 /*                                                                        */
722 /*  RELEASE HISTORY                                                       */
723 /*                                                                        */
724 /*    DATE              NAME                      DESCRIPTION             */
725 /*                                                                        */
726 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
727 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
728 /*                                            resulting in version 6.1    */
729 /*                                                                        */
730 /**************************************************************************/
_nxd_tftp_server_stop(NX_TFTP_SERVER * tftp_server_ptr)731 UINT  _nxd_tftp_server_stop(NX_TFTP_SERVER *tftp_server_ptr)
732 {
733 
734 #ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE
735     /* Deactivate TFTP server timer.  */
736     tx_timer_deactivate(&(tftp_server_ptr -> nx_tftp_server_timer));
737 #endif
738 
739     /* Suspend the TFTP server thread.  */
740     tx_thread_suspend(&(tftp_server_ptr -> nx_tftp_server_thread));
741 
742     /* Return successful completion.  */
743     return(NX_SUCCESS);
744 }
745 
746 
747 /**************************************************************************/
748 /*                                                                        */
749 /*  FUNCTION                                               RELEASE        */
750 /*                                                                        */
751 /*    _nx_tftp_server_data_present                        PORTABLE C      */
752 /*                                                           6.1          */
753 /*  AUTHOR                                                                */
754 /*                                                                        */
755 /*    Yuxin Zhou, Microsoft Corporation                                   */
756 /*                                                                        */
757 /*  DESCRIPTION                                                           */
758 /*                                                                        */
759 /*    This function is notified by NetX of receive events generated by    */
760 /*    TFTP Clients connecting or sending data.                            */
761 /*                                                                        */
762 /*  INPUT                                                                 */
763 /*                                                                        */
764 /*    socket_ptr                            Socket receiving data         */
765 /*                                                                        */
766 /*  OUTPUT                                                                */
767 /*                                                                        */
768 /*    None                                                                */
769 /*                                                                        */
770 /*  CALLS                                                                 */
771 /*                                                                        */
772 /*    tx_event_flags_set                    Set events for server thread  */
773 /*                                                                        */
774 /*  CALLED BY                                                             */
775 /*                                                                        */
776 /*    NetX                                  NetX TCP socket callback      */
777 /*                                                                        */
778 /*  RELEASE HISTORY                                                       */
779 /*                                                                        */
780 /*    DATE              NAME                      DESCRIPTION             */
781 /*                                                                        */
782 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
783 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
784 /*                                            resulting in version 6.1    */
785 /*                                                                        */
786 /**************************************************************************/
_nx_tftp_server_data_present(NX_UDP_SOCKET * socket_ptr)787 VOID  _nx_tftp_server_data_present(NX_UDP_SOCKET *socket_ptr)
788 {
789 
790 NX_TFTP_SERVER   *server_ptr;
791 
792     /* Pickup server pointer.  This is setup in the reserved field of the TCP socket.  */
793     server_ptr = (NX_TFTP_SERVER *)(socket_ptr -> nx_udp_socket_reserved_ptr);
794 
795     /* Set the data event flag.  */
796     tx_event_flags_set(&(server_ptr -> nx_tftp_server_event_flags), NX_TFTP_SERVER_RECEIVE_EVENT, TX_OR);
797 }
798 
799 
800 #ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE
801 /**************************************************************************/
802 /*                                                                        */
803 /*  FUNCTION                                               RELEASE        */
804 /*                                                                        */
805 /*    _nx_tftp_server_timer_entry                         PORTABLE C      */
806 /*                                                           6.1          */
807 /*  AUTHOR                                                                */
808 /*                                                                        */
809 /*    Yuxin Zhou, Microsoft Corporation                                   */
810 /*                                                                        */
811 /*  DESCRIPTION                                                           */
812 /*                                                                        */
813 /*    This function captures timer events used to determine if the Client */
814 /*    retransmit timer has expired.                                       */
815 /*                                                                        */
816 /*                                                                        */
817 /*  INPUT                                                                 */
818 /*                                                                        */
819 /*    ULONG                                 Pointer to TFTP server        */
820 /*                                                                        */
821 /*  OUTPUT                                                                */
822 /*                                                                        */
823 /*    None                                                                */
824 /*                                                                        */
825 /*  CALLS                                                                 */
826 /*                                                                        */
827 /*    tx_event_flags_set                    Set events for server thread  */
828 /*                                                                        */
829 /*  CALLED BY                                                             */
830 /*                                                                        */
831 /*    NetX                                  NetX connect callback         */
832 /*                                                                        */
833 /*  RELEASE HISTORY                                                       */
834 /*                                                                        */
835 /*    DATE              NAME                      DESCRIPTION             */
836 /*                                                                        */
837 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
838 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
839 /*                                            resulting in version 6.1    */
840 /*                                                                        */
841 /**************************************************************************/
_nx_tftp_server_timer_entry(ULONG tftp_server_address)842 VOID  _nx_tftp_server_timer_entry(ULONG tftp_server_address)
843 {
844 
845 NX_TFTP_SERVER   *server_ptr;
846 
847     /* Pickup server pointer.  */
848     server_ptr =  (NX_TFTP_SERVER *) tftp_server_address;
849 
850     /* Set the data event flag.  */
851     tx_event_flags_set(&(server_ptr -> nx_tftp_server_event_flags), NX_TFTP_SERVER_TIMER_EVENT, TX_OR);
852 
853     return;
854 }
855 
856 /**************************************************************************/
857 /*                                                                        */
858 /*  FUNCTION                                               RELEASE        */
859 /*                                                                        */
860 /*    _nx_tftp_server_timer_process                       PORTABLE C      */
861 /*                                                           6.1          */
862 /*  AUTHOR                                                                */
863 /*                                                                        */
864 /*    Yuxin Zhou, Microsoft Corporation                                   */
865 /*                                                                        */
866 /*  DESCRIPTION                                                           */
867 /*                                                                        */
868 /*    This function checks all the active TFTP client connections         */
869 /*    for their retransmission timeout. If expired, the Server retransmits*/
870 /*    the data or ACK up to a maximum number of retries                   */
871 /*    (NX_TFTP_SERVER_MAX_RETRIES) and then terminates the connection and */
872 /*    closes any open files. The client request is cleared and available  */
873 /*    for the next client request                                         */
874 /*                                                                        */
875 /*                                                                        */
876 /*  INPUT                                                                 */
877 /*                                                                        */
878 /*    server_ptr                            Pointer to TFTP server        */
879 /*                                                                        */
880 /*  OUTPUT                                                                */
881 /*                                                                        */
882 /*    None                                                                */
883 /*                                                                        */
884 /*  CALLS                                                                 */
885 /*                                                                        */
886 /*    fx_file_close                         Close session file.           */
887 /*    fx_file_delete                        Delete the file               */
888 /*                                                                        */
889 /*  CALLED BY                                                             */
890 /*                                                                        */
891 /*    _nx_tftp_server_thread_entry          TFTP server task function     */
892 /*                                                                        */
893 /*  RELEASE HISTORY                                                       */
894 /*                                                                        */
895 /*    DATE              NAME                      DESCRIPTION             */
896 /*                                                                        */
897 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
898 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
899 /*                                            resulting in version 6.1    */
900 /*                                                                        */
901 /**************************************************************************/
_nx_tftp_server_timer_process(NX_TFTP_SERVER * server_ptr)902 VOID  _nx_tftp_server_timer_process(NX_TFTP_SERVER *server_ptr)
903 {
904 
905 UINT                     i;
906 NX_TFTP_CLIENT_REQUEST   *client_request_ptr;
907 
908 
909     /* Now look through all the sockets.  */
910     for (i = 0; i < NX_TFTP_MAX_CLIENTS; i++)
911     {
912 
913         /* Set a pointer to client request structure.  */
914         client_request_ptr =  &(server_ptr -> nx_tftp_server_client_list[i]);
915 
916         /* Check if this request has a retransmit timeout pending. */
917         if (client_request_ptr -> nx_tftp_client_retransmit_timeout )
918         {
919 
920             /* Update reatransmit timeout. */
921             if (client_request_ptr -> nx_tftp_client_retransmit_timeout >= NX_TFTP_SERVER_TIMEOUT_PERIOD)
922             {
923 
924                 client_request_ptr -> nx_tftp_client_retransmit_timeout -= NX_TFTP_SERVER_TIMEOUT_PERIOD;
925             }
926             else
927             {
928 
929                 client_request_ptr -> nx_tftp_client_retransmit_timeout = 0;
930             }
931 
932             /* Has the retransmit timeout expired? */
933             if (client_request_ptr -> nx_tftp_client_retransmit_timeout == 0)
934             {
935 
936                 /* Yes, retransmit unless we have hit the max retry limit. */
937                 if (client_request_ptr -> nx_tftp_client_retransmit_retries < NX_TFTP_SERVER_MAX_RETRIES)
938                 {
939 
940 
941                     /* Update the Client request retransmit timeout and number of retries. */
942                     client_request_ptr -> nx_tftp_client_retransmit_timeout = NX_TFTP_SERVER_RETRANSMIT_TIMEOUT;
943                     client_request_ptr -> nx_tftp_client_retransmit_retries++;
944 
945                     /* Determine which type of request this is. */
946                     if (client_request_ptr -> nx_tftp_client_request_open_type == NX_TFTP_STATE_WRITE_OPEN)
947                     {
948 
949                         /* Retransmit the ACK. */
950                         _nx_tftp_server_send_ack(server_ptr, client_request_ptr, NX_TRUE);
951                     }
952                     else
953                     {
954 
955                         /* Retransmit the file data. */
956                         _nx_tftp_server_send_data(server_ptr, client_request_ptr, NX_TRUE);
957                     }
958                 }
959                 else
960                 {
961 
962                     /* The session has timed out. Send error and close. */
963                     _nx_tftp_server_send_error(server_ptr, &client_request_ptr -> nx_tftp_client_request_ip_address,
964                                                client_request_ptr -> nx_tftp_client_request_port,
965                                                NX_TFTP_SESSION_TIMED_OUT, "NetX TFTP Server: Session timed out");
966 
967                     /* Error, close the file and delete the client request.  */
968                     fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
969 
970                     memset(client_request_ptr, 0, sizeof(NX_TFTP_CLIENT_REQUEST));
971                 }
972             }
973         }
974     }
975 }
976 #endif /* NX_TFTP_SERVER_RETRANSMIT_ENABLE */
977 
978 
979 /**************************************************************************/
980 /*                                                                        */
981 /*  FUNCTION                                               RELEASE        */
982 /*                                                                        */
983 /*    _nx_tftp_server_thread_entry                        PORTABLE C      */
984 /*                                                           6.1          */
985 /*  AUTHOR                                                                */
986 /*                                                                        */
987 /*    Yuxin Zhou, Microsoft Corporation                                   */
988 /*                                                                        */
989 /*  DESCRIPTION                                                           */
990 /*                                                                        */
991 /*    This function is the entry of the TFTP server.  All basic           */
992 /*    processing is initiated by this function.                           */
993 /*                                                                        */
994 /*                                                                        */
995 /*  INPUT                                                                 */
996 /*                                                                        */
997 /*    tftp_server                           Pointer to TFTP server        */
998 /*                                                                        */
999 /*  OUTPUT                                                                */
1000 /*                                                                        */
1001 /*    None                                                                */
1002 /*                                                                        */
1003 /*  CALLS                                                                 */
1004 /*                                                                        */
1005 /*    tx_event_flags_get                    Get the TFTP events           */
1006 /*    _nx_tftp_server_process_received_data Process received packet       */
1007 /*    _nx_tftp_server_timer_process         Process TFTP timer            */
1008 /*                                                                        */
1009 /*  CALLED BY                                                             */
1010 /*                                                                        */
1011 /*    ThreadX                                                             */
1012 /*                                                                        */
1013 /*  RELEASE HISTORY                                                       */
1014 /*                                                                        */
1015 /*    DATE              NAME                      DESCRIPTION             */
1016 /*                                                                        */
1017 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1018 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1019 /*                                            resulting in version 6.1    */
1020 /*                                                                        */
1021 /**************************************************************************/
_nx_tftp_server_thread_entry(ULONG tftp_server)1022 VOID  _nx_tftp_server_thread_entry(ULONG tftp_server)
1023 {
1024 
1025 NX_TFTP_SERVER          *server_ptr;
1026 UINT                    status;
1027 ULONG                   events;
1028 
1029 
1030     /* Setup the server pointer.  */
1031     server_ptr =  (NX_TFTP_SERVER *) tftp_server;
1032 
1033     /* Loop to process TFTP Server requests.  */
1034     while(1)
1035     {
1036 
1037         /* Wait for TFTP events.  */
1038         status =  tx_event_flags_get(&(server_ptr -> nx_tftp_server_event_flags), NX_SERVER_TFTP_ANY_EVENT,
1039                                      TX_OR_CLEAR, &events, TX_WAIT_FOREVER);
1040 
1041         /* Check the return status.  */
1042         if (status)
1043         {
1044 
1045             /* If an error occurs, simply continue the loop.  */
1046             continue;
1047         }
1048 
1049         /* Otherwise, an event is present.  Process according to the event.  */
1050 
1051         /* Check for a client receive event.  */
1052         if (events & NX_TFTP_SERVER_RECEIVE_EVENT)
1053         {
1054 
1055             /* Call the data received handler.  */
1056             _nx_tftp_server_process_received_data(server_ptr);
1057         }
1058 
1059 #ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE
1060         /* Check for a  timer event. */
1061         if (events & NX_TFTP_SERVER_TIMER_EVENT)
1062         {
1063             /* Call the timer timeout handler.  */
1064             _nx_tftp_server_timer_process(server_ptr);
1065         }
1066 #endif /* NX_TFTP_SERVER_RETRANSMIT_ENABLE*/
1067     }
1068 }
1069 
1070 
1071 /**************************************************************************/
1072 /*                                                                        */
1073 /*  FUNCTION                                               RELEASE        */
1074 /*                                                                        */
1075 /*    _nx_tftp_server_process_received_data               PORTABLE C      */
1076 /*                                                           6.1.10       */
1077 /*  AUTHOR                                                                */
1078 /*                                                                        */
1079 /*    Yuxin Zhou, Microsoft Corporation                                   */
1080 /*                                                                        */
1081 /*  DESCRIPTION                                                           */
1082 /*                                                                        */
1083 /*    This function is called when the TFTP server is notified of a       */
1084 /*    receive event. It parses the TFTP Client message and calls the      */
1085 /*    appropriate handler for read and write requests, client errors, or  */
1086 /*    ACKing data sent by the server.                                     */
1087 /*                                                                        */
1088 /*  INPUT                                                                 */
1089 /*                                                                        */
1090 /*    server_ptr                            Pointer to TFTP server        */
1091 /*                                                                        */
1092 /*  OUTPUT                                                                */
1093 /*                                                                        */
1094 /*    status                                Completion status             */
1095 /*                                                                        */
1096 /*  CALLS                                                                 */
1097 /*                                                                        */
1098 /*    _nx_tftp_server_ack_process           Process ACK from previous read*/
1099 /*    _nx_tftp_server_data_process          Write data packet to file     */
1100 /*    _nx_tftp_server_error_process         Process error packet          */
1101 /*    _nx_tftp_server_open_for_read_process Open file for reading         */
1102 /*    _nx_tftp_server_open_for_write_process Open for writing             */
1103 /*    nx_packet_release                     Release packet                */
1104 /*    nx_udp_socket_receive                 Receive next TFTP packet      */
1105 /*                                                                        */
1106 /*  CALLED BY                                                             */
1107 /*                                                                        */
1108 /*    nx_tftp_server_thread_entry           TFTP thread task function     */
1109 /*                                                                        */
1110 /*  RELEASE HISTORY                                                       */
1111 /*                                                                        */
1112 /*    DATE              NAME                      DESCRIPTION             */
1113 /*                                                                        */
1114 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1115 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1116 /*                                            resulting in version 6.1    */
1117 /*  01-31-2022     Yuxin Zhou               Modified comment(s), improved */
1118 /*                                            the logic of processing     */
1119 /*                                            chained packet,             */
1120 /*                                            resulting in version 6.1.10 */
1121 /*                                                                        */
1122 /**************************************************************************/
_nx_tftp_server_process_received_data(NX_TFTP_SERVER * server_ptr)1123 VOID _nx_tftp_server_process_received_data(NX_TFTP_SERVER *server_ptr)
1124 {
1125 
1126 UINT         status;
1127 NX_PACKET    *packet_ptr;
1128 UCHAR        request_code[2];
1129 ULONG        bytes_copyed;
1130 
1131 
1132     /* Wait for a request on the TFTP UDP well known port 69.  */
1133     status =  nx_udp_socket_receive(&(server_ptr -> nx_tftp_server_socket), &packet_ptr, NX_NO_WAIT);
1134 
1135     /* Check the return status. */
1136     if (status)
1137     {
1138 
1139         /* If an error occurs, simply return to caller.  */
1140         return;
1141     }
1142 
1143     /* Check for valid packet length (The minimum TFTP header size is ACK packet, four bytes).  */
1144     if (packet_ptr -> nx_packet_length < 4)
1145     {
1146 
1147         /* Release the packet. */
1148         nx_packet_release(packet_ptr);
1149 
1150         /* Return.  */
1151         return;
1152     }
1153 
1154     /* Otherwise, we have received a packet successfully.  */
1155 
1156     /* Pickup up the request code. First one must be zero.  */
1157     status = nx_packet_data_extract_offset(packet_ptr, 0, request_code, sizeof(request_code), &bytes_copyed);
1158 
1159     /* Check the return status. */
1160     if (status || (request_code[0] != 0))
1161     {
1162 
1163         nx_packet_release(packet_ptr);
1164         return;
1165     }
1166 
1167     /* Process relative to the TFTP request code.  */
1168     switch (request_code[1])
1169     {
1170 
1171     case NX_TFTP_CODE_READ:
1172 
1173         /* Process an open for read request.  */
1174         _nx_tftp_server_open_for_read_process(server_ptr, packet_ptr);
1175 
1176         /* Increment the number of open for read requests.  */
1177         server_ptr -> nx_tftp_server_open_for_read_requests++;
1178         break;
1179 
1180     case NX_TFTP_CODE_WRITE:
1181 
1182         /* Process an open for write request.  */
1183         _nx_tftp_server_open_for_write_process(server_ptr, packet_ptr);
1184 
1185         /* Increment the number of open for write requests.  */
1186         server_ptr -> nx_tftp_server_open_for_write_requests++;
1187         break;
1188 
1189     case NX_TFTP_CODE_DATA:
1190 
1191         /* Process a data request.  */
1192         _nx_tftp_server_data_process(server_ptr, packet_ptr);
1193 
1194         /* Increment the number of data block write requests.  */
1195         server_ptr -> nx_tftp_server_data_blocks_received++;
1196         break;
1197 
1198     case NX_TFTP_CODE_ACK:
1199 
1200         /* Process an ack response.  */
1201         _nx_tftp_server_ack_process(server_ptr, packet_ptr);
1202 
1203         /* Increment the number of acks for previous data blocks sent.  */
1204         server_ptr -> nx_tftp_server_acks_received++;
1205         break;
1206 
1207     case NX_TFTP_CODE_ERROR:
1208 
1209         /* Process an error request.  */
1210         _nx_tftp_server_error_process(server_ptr, packet_ptr);
1211 
1212         /* Increment the number of errors received.  */
1213         server_ptr -> nx_tftp_server_errors_received++;
1214         break;
1215 
1216     default:
1217 
1218         /* Increment the number of unknown codes received.  */
1219         server_ptr -> nx_tftp_server_unknown_commands++;
1220 
1221         /* Just release the packet.  */
1222         nx_packet_release(packet_ptr);
1223     }
1224 }
1225 
1226 
1227 /**************************************************************************/
1228 /*                                                                        */
1229 /*  FUNCTION                                               RELEASE        */
1230 /*                                                                        */
1231 /*    _nx_tftp_server_open_for_read_process               PORTABLE C      */
1232 /*                                                           6.1.10       */
1233 /*  AUTHOR                                                                */
1234 /*                                                                        */
1235 /*    Yuxin Zhou, Microsoft Corporation                                   */
1236 /*                                                                        */
1237 /*  DESCRIPTION                                                           */
1238 /*                                                                        */
1239 /*    This function opens the specified file for reading, and returns     */
1240 /*    the first block of the file.                                        */
1241 /*                                                                        */
1242 /*                                                                        */
1243 /*  INPUT                                                                 */
1244 /*                                                                        */
1245 /*    server_ptr                            Pointer to TFTP server        */
1246 /*    packet_ptr                            Pointer to TFTP request packet*/
1247 /*                                                                        */
1248 /*  OUTPUT                                                                */
1249 /*                                                                        */
1250 /*    None                                                                */
1251 /*                                                                        */
1252 /*  CALLS                                                                 */
1253 /*                                                                        */
1254 /*    fx_directory_information_get          Get information about file    */
1255 /*    fx_file_close                         Close file on EOF or error    */
1256 /*    fx_file_open                          Open file for reading         */
1257 /*    fx_file_read                          Read block from file          */
1258 /*    _nx_tftp_server_find_client_request   Find client entry             */
1259 /*    _nx_tftp_server_send_error            Send error message            */
1260 /*    nx_packet_allocate                    Allocate a new packet         */
1261 /*    nx_packet_release                     Release packet                */
1262 /*    nx_udp_socket_send                    Send TFTP data packet         */
1263 /*    nx_udp_source_extract                 Extract IP and port           */
1264 /*                                                                        */
1265 /*  CALLED BY                                                             */
1266 /*                                                                        */
1267 /*    _nx_tftp_server_thread_entry          TFTP Server thread            */
1268 /*                                                                        */
1269 /*  RELEASE HISTORY                                                       */
1270 /*                                                                        */
1271 /*    DATE              NAME                      DESCRIPTION             */
1272 /*                                                                        */
1273 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1274 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1275 /*                                            resulting in version 6.1    */
1276 /*  01-31-2022     Yuxin Zhou               Modified comment(s),          */
1277 /*                                            checked the format of the   */
1278 /*                                            received packet, improved   */
1279 /*                                            the logic of processing     */
1280 /*                                            chained packet, fixed the   */
1281 /*                                            issue of cleaning up the    */
1282 /*                                            client request entry,       */
1283 /*                                            resulting in version 6.1.10 */
1284 /*                                                                        */
1285 /**************************************************************************/
_nx_tftp_server_open_for_read_process(NX_TFTP_SERVER * server_ptr,NX_PACKET * packet_ptr)1286 void  _nx_tftp_server_open_for_read_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
1287 {
1288 NXD_ADDRESS              ip_address;
1289 ULONG                    file_size;
1290 ULONG                    actual_size;
1291 UINT                     port;
1292 UCHAR                    *buffer_ptr;
1293 NX_TFTP_CLIENT_REQUEST   *client_request_ptr;
1294 NX_PACKET                *new_packet = NX_NULL;
1295 UINT                     status;
1296 UINT                     count = 0;
1297 
1298 
1299     /* Extract the source IP and port numbers.  */
1300     nxd_udp_source_extract(packet_ptr, &ip_address, &port);
1301 
1302     /* First, try to find a matching exiting entry in the client request structure.  */
1303     client_request_ptr =  _nx_tftp_server_find_client_request(server_ptr, port, &ip_address);
1304 
1305     /* See if we need to find a new entry.  */
1306     if (client_request_ptr == NX_NULL)
1307     {
1308 
1309         /* Yes, find a free entry in the client request structure.  */
1310         client_request_ptr =  _nx_tftp_server_find_client_request(server_ptr, 0, NX_NULL);
1311     }
1312     else
1313     {
1314 
1315         /* This is a dupe request. Ignore it. */
1316         nx_packet_release(packet_ptr);
1317         return;
1318     }
1319 
1320     /* Determine if there was a free entry.  */
1321     if (client_request_ptr == NX_NULL)
1322     {
1323 
1324         /* Increment the maximum clients errors.  */
1325         server_ptr -> nx_tftp_server_clients_exceeded_errors++;
1326 
1327         /* Send an error to the client.  */
1328         _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_NOT_DEFINED, "NetX TFTP Server: Too Many Clients");
1329 
1330         /* No more clients can be serviced, release the packet.  */
1331         nx_packet_release(packet_ptr);
1332         return;
1333     }
1334 
1335     /* Packet chain isn't supported.  */
1336 #ifndef NX_DISABLE_PACKET_CHAIN
1337     if (packet_ptr -> nx_packet_next)
1338     {
1339         nx_packet_release(packet_ptr);
1340         return;
1341     }
1342 #endif /* NX_DISABLE_PACKET_CHAIN */
1343 
1344     /* Setup a pointer to the file name.  */
1345     buffer_ptr =  (UCHAR *) (packet_ptr -> nx_packet_prepend_ptr + 2);
1346 
1347     /* The format of RRQ/WRQ packet should be:
1348         2 bytes     string    1 byte     string   1 byte
1349         ------------------------------------------------
1350         | Opcode |  Filename  |   0  |    Mode    |   0  |
1351         ------------------------------------------------
1352     */
1353     while (buffer_ptr < (packet_ptr -> nx_packet_append_ptr - 1))
1354     {
1355         if (*buffer_ptr == 0)
1356         {
1357             count++;
1358             if (count == 2)
1359                 break;
1360         }
1361 
1362         buffer_ptr++;
1363     }
1364 
1365     /* Check if the format of the termination is correct.  */
1366     if ((count != 1) || *(UCHAR *)(packet_ptr -> nx_packet_append_ptr - 1))
1367     {
1368         nx_packet_release(packet_ptr);
1369         return;
1370     }
1371 
1372     /* Reset the pointer to the file name.  */
1373     buffer_ptr =  (UCHAR *) (packet_ptr -> nx_packet_prepend_ptr + 2);
1374 
1375     /* Pickup the file size.  */
1376     status =  fx_directory_information_get(server_ptr -> nx_tftp_server_media_ptr, (CHAR *) buffer_ptr, NX_NULL, &file_size, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL);
1377 
1378     /* Check the return status.  */
1379     if (status != FX_SUCCESS)
1380     {
1381 
1382         /* Send an error to the client.  */
1383         _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_FILE_NOT_FOUND, "NetX TFTP Server: File Not Found");
1384 
1385         /* Unable to find the file size, release the packet.  */
1386         nx_packet_release(packet_ptr);
1387         return;
1388     }
1389 
1390     /* Attempt to open the file.  */
1391     status =  fx_file_open(server_ptr -> nx_tftp_server_media_ptr, &(client_request_ptr ->nx_tftp_client_request_file), (CHAR *) buffer_ptr, FX_OPEN_FOR_READ);
1392 
1393     /* Check the return status.  */
1394     if (status != FX_SUCCESS)
1395     {
1396 
1397         /* Send an error to the client.  */
1398         _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_FILE_NOT_FOUND, "NetX TFTP Server: File Open Failed");
1399 
1400         /* Unable to open the file, release the packet.  */
1401         nx_packet_release(packet_ptr);
1402         return;
1403     }
1404 
1405     /* The file has been opened successfully, now try to read up to 512 bytes.  */
1406 
1407    /* Allocate packet for the read packet. Determine whether we are sending IP packets.   */
1408     if (ip_address.nxd_ip_version == NX_IP_VERSION_V4)
1409     {
1410         status =  nx_packet_allocate(server_ptr -> nx_tftp_server_packet_pool_ptr, &new_packet, NX_IPv4_UDP_PACKET, NX_WAIT_FOREVER);
1411     }
1412     else if (ip_address.nxd_ip_version == NX_IP_VERSION_V6)
1413     {
1414         status =  nx_packet_allocate(server_ptr -> nx_tftp_server_packet_pool_ptr, &new_packet, NX_IPv6_UDP_PACKET, NX_WAIT_FOREVER);
1415     }
1416     else
1417         status = NX_TFTP_INVALID_ADDRESS_TYPE;
1418     /* Check for successful packet allocation.  */
1419     if (status != NX_SUCCESS)
1420     {
1421 
1422         /* Increment the number of server allocation errors.  */
1423         server_ptr -> nx_tftp_server_allocation_errors++;
1424 
1425         /* Unable to allocate net packet, release the original.  */
1426         nx_packet_release(packet_ptr);
1427         return;
1428     }
1429 
1430     if (4u + NX_TFTP_FILE_TRANSFER_MAX > ((ULONG)(new_packet -> nx_packet_data_end) - (ULONG)(new_packet -> nx_packet_append_ptr)))
1431     {
1432         /* Release the original packet.  */
1433         nx_packet_release(packet_ptr);
1434 
1435         nx_packet_release(new_packet);
1436         return;
1437     }
1438 
1439     /* Initialize the client request structure.  */
1440 #ifndef NX_DISABLE_IPV4
1441     if (ip_address.nxd_ip_version == NX_IP_VERSION_V4)
1442     {
1443 
1444         client_request_ptr ->nx_tftp_client_request_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
1445         client_request_ptr ->nx_tftp_client_request_ip_address.nxd_ip_address.v4 = ip_address.nxd_ip_address.v4;
1446     }
1447     else
1448 #endif /* NX_DISABLE_IPV4 */
1449 #ifdef FEATURE_NX_IPV6
1450     if (ip_address.nxd_ip_version == NX_IP_VERSION_V6)
1451     {
1452         COPY_NXD_ADDRESS(&ip_address, &(client_request_ptr ->nx_tftp_client_request_ip_address));
1453     }
1454     else
1455 #endif
1456     {
1457         /* Release the original packet.  */
1458         nx_packet_release(packet_ptr);
1459 
1460         return;
1461     }
1462 
1463     client_request_ptr -> nx_tftp_client_request_port =             port;
1464     client_request_ptr -> nx_tftp_client_request_block_number =     1;
1465     client_request_ptr -> nx_tftp_client_request_open_type =        NX_TFTP_STATE_OPEN;
1466     client_request_ptr -> nx_tftp_client_request_exact_fit =        NX_FALSE;
1467 
1468 #ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE
1469 
1470     /* Reset the retransmission timeout and retries for the client request. */
1471     client_request_ptr -> nx_tftp_client_retransmit_timeout =  NX_TFTP_SERVER_RETRANSMIT_TIMEOUT;
1472     client_request_ptr -> nx_tftp_client_retransmit_retries =  0;
1473 #else
1474 
1475     /* Clear the count of ACK retransmits from the other side. */
1476     client_request_ptr -> nx_tftp_client_request_retransmits = 0;
1477 
1478 #endif
1479 
1480     client_request_ptr -> nx_tftp_client_file_size = file_size;
1481 
1482     /* Read data when length of file is larger then 0. */
1483     if(file_size)
1484     {
1485 
1486         /* Attempt to read the requested file.  */
1487         status =  fx_file_read(&(client_request_ptr ->nx_tftp_client_request_file), new_packet -> nx_packet_prepend_ptr+4, NX_TFTP_FILE_TRANSFER_MAX, &actual_size);
1488 
1489         /* Check for successful file read.  */
1490         if ((status != NX_SUCCESS) ||
1491             ((file_size > NX_TFTP_FILE_TRANSFER_MAX) && (actual_size != NX_TFTP_FILE_TRANSFER_MAX)) ||
1492             ((file_size < NX_TFTP_FILE_TRANSFER_MAX) && (actual_size != file_size)))
1493         {
1494 
1495             /* Send an error to the client.  */
1496             _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_NOT_DEFINED, "NetX TFTP Server: File Read Error");
1497 
1498             /* Unable to read the file, close it and release the packet.  */
1499             fx_file_close(&(client_request_ptr ->nx_tftp_client_request_file));
1500 
1501             memset(client_request_ptr, 0, sizeof(NX_TFTP_CLIENT_REQUEST));
1502 
1503             nx_packet_release(packet_ptr);
1504             return;
1505         }
1506     }
1507     else
1508     {
1509 
1510         actual_size = 0;
1511     }
1512 
1513     /* Increment the number of total bytes sent.  */
1514     server_ptr -> nx_tftp_server_total_bytes_sent +=  actual_size;
1515 
1516     /* Setup the client request structure.  */
1517     client_request_ptr -> nx_tftp_client_request_remaining_bytes =  file_size - actual_size;
1518 
1519     /* Determine if the file size is evenly divisible by our TFTP transfer size.  */
1520     if (file_size % NX_TFTP_FILE_TRANSFER_MAX)
1521     {
1522 
1523         /* Not an exact fit, ensure the exact fit flag is clear.  */
1524         client_request_ptr -> nx_tftp_client_request_exact_fit =  NX_FALSE;
1525     }
1526     else if (file_size > 0)
1527     {
1528 
1529         /* Yes, the file size happens to be evenly divisible by the TFTP transfer size.  In this
1530            case, we need to send a zero-length data packet at the end of file to let the other side
1531            know we are at the end.  */
1532         client_request_ptr -> nx_tftp_client_request_exact_fit =  NX_TRUE;
1533     }
1534 
1535     /* Move the TFTP data code and block number into the payload before sending it to the client.  */
1536     buffer_ptr =  new_packet -> nx_packet_prepend_ptr;
1537     *buffer_ptr++ =  0;
1538     *buffer_ptr++ =  NX_TFTP_CODE_DATA;
1539     *buffer_ptr++ =  0;
1540     *buffer_ptr++ =  1;                                     /* First block number of file.  */
1541 
1542     /* Setup the packet pointers appropriately.  */
1543     new_packet -> nx_packet_length =  actual_size + 4;
1544     new_packet -> nx_packet_append_ptr =  new_packet -> nx_packet_prepend_ptr + new_packet -> nx_packet_length;
1545 
1546     /* Send the data packet out.  */
1547     status = nxd_udp_socket_send(&(server_ptr -> nx_tftp_server_socket), new_packet, &ip_address, port);
1548 
1549     /* Release packet if send fails. */
1550     if (status)
1551     {
1552         nx_packet_release(new_packet);
1553     }
1554 
1555     /* Release the original packet.  */
1556     nx_packet_release(packet_ptr);
1557 }
1558 
1559 
1560 /**************************************************************************/
1561 /*                                                                        */
1562 /*  FUNCTION                                               RELEASE        */
1563 /*                                                                        */
1564 /*    _nx_tftp_server_open_for_write_process              PORTABLE C      */
1565 /*                                                           6.1.10       */
1566 /*  AUTHOR                                                                */
1567 /*                                                                        */
1568 /*    Yuxin Zhou, Microsoft Corporation                                   */
1569 /*                                                                        */
1570 /*  DESCRIPTION                                                           */
1571 /*                                                                        */
1572 /*    This function opens the specified file for writing, and returns     */
1573 /*    an ACK for block 0 to let the client know everything is good.       */
1574 /*                                                                        */
1575 /*                                                                        */
1576 /*  INPUT                                                                 */
1577 /*                                                                        */
1578 /*    server_ptr                            Pointer to TFTP server        */
1579 /*    packet_ptr                            Pointer to TFTP request packet*/
1580 /*                                                                        */
1581 /*  OUTPUT                                                                */
1582 /*                                                                        */
1583 /*    None                                                                */
1584 /*                                                                        */
1585 /*  CALLS                                                                 */
1586 /*                                                                        */
1587 /*    fx_file_create                        Create file, if necessary     */
1588 /*    fx_file_close                         Close file on EOF or error    */
1589 /*    fx_file_open                          Open file for reading         */
1590 /*    fx_file_write                         Write block to file           */
1591 /*    _nx_tftp_server_find_client_request   Find client entry             */
1592 /*    _nx_tftp_server_send_error            Send error message            */
1593 /*    nx_packet_allocate                    Allocate a new packet         */
1594 /*    nx_packet_release                     Release packet                */
1595 /*    nx_udp_socket_send                    Send TFTP data packet         */
1596 /*    nx_udp_source_extract                 Extract IP and port           */
1597 /*                                                                        */
1598 /*  CALLED BY                                                             */
1599 /*                                                                        */
1600 /*    _nx_tftp_server_thread_entry          TFTP Server thread task       */
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 /*  01-31-2022     Yuxin Zhou               Modified comment(s),          */
1610 /*                                            checked the format of the   */
1611 /*                                            received packet, improved   */
1612 /*                                            the logic of processing     */
1613 /*                                            chained packet,             */
1614 /*                                            resulting in version 6.1.10 */
1615 /*                                                                        */
1616 /**************************************************************************/
_nx_tftp_server_open_for_write_process(NX_TFTP_SERVER * server_ptr,NX_PACKET * packet_ptr)1617 VOID  _nx_tftp_server_open_for_write_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
1618 {
1619 NXD_ADDRESS             ip_address;
1620 UINT                    port;
1621 UCHAR                   *buffer_ptr;
1622 NX_TFTP_CLIENT_REQUEST  *client_request_ptr;
1623 NX_PACKET               *new_packet;
1624 UINT                    status;
1625 UINT                    count = 0;
1626 
1627 
1628     /* Extract the source IP and port numbers.  */
1629     nxd_udp_source_extract(packet_ptr, &ip_address, &port);
1630 
1631     /* First, try to find a matching exiting entry in the client request structure.  */
1632     client_request_ptr =  _nx_tftp_server_find_client_request(server_ptr, port, &ip_address);
1633 
1634     /* See if we need to find a new entry.  */
1635     if (client_request_ptr == NX_NULL)
1636     {
1637 
1638         /* Find a free entry in the client request structure.  */
1639         client_request_ptr =  _nx_tftp_server_find_client_request(server_ptr, 0, NX_NULL);
1640     }
1641     else
1642     {
1643 
1644         /* This is a dupe request. Ignore it. */
1645         nx_packet_release(packet_ptr);
1646         return;
1647     }
1648 
1649     /* Determine if there was a free entry.  */
1650     if (client_request_ptr == NX_NULL)
1651     {
1652 
1653         /* Increment the maximum clients errors.  */
1654         server_ptr -> nx_tftp_server_clients_exceeded_errors++;
1655 
1656         /* Send an error to the client.  */
1657         _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_NOT_DEFINED, "NetX TFTP Server: Too Many Clients");
1658 
1659         /* No more clients can be serviced, release the packet.  */
1660         nx_packet_release(packet_ptr);
1661         return;
1662     }
1663 
1664     /* Packet chain isn't supported.  */
1665 #ifndef NX_DISABLE_PACKET_CHAIN
1666     if (packet_ptr -> nx_packet_next)
1667     {
1668         nx_packet_release(packet_ptr);
1669         return;
1670     }
1671 #endif /* NX_DISABLE_PACKET_CHAIN */
1672 
1673     /* Setup a pointer to the file name.  */
1674     buffer_ptr =  (UCHAR *) (packet_ptr -> nx_packet_prepend_ptr + 2);
1675 
1676     /* The format of RRQ/WRQ packet should be:
1677         2 bytes     string    1 byte     string   1 byte
1678         ------------------------------------------------
1679         | Opcode |  Filename  |   0  |    Mode    |   0  |
1680         ------------------------------------------------
1681     */
1682     while (buffer_ptr < (packet_ptr -> nx_packet_append_ptr - 1))
1683     {
1684         if (*buffer_ptr == 0)
1685         {
1686             count++;
1687             if (count == 2)
1688                 break;
1689         }
1690 
1691         buffer_ptr++;
1692     }
1693 
1694     /* Check if the format of the termination is correct.  */
1695     if ((count != 1) || *(UCHAR *)(packet_ptr -> nx_packet_append_ptr - 1))
1696     {
1697         nx_packet_release(packet_ptr);
1698         return;
1699     }
1700 
1701     /* Reset the pointer to the file name.  */
1702     buffer_ptr =  (UCHAR *) (packet_ptr -> nx_packet_prepend_ptr + 2);
1703 
1704     /* Perform a file create. This will fail if the file is already present, which we don't care about at this point.  */
1705     fx_file_delete(server_ptr -> nx_tftp_server_media_ptr, (CHAR *) buffer_ptr);
1706     fx_file_create(server_ptr -> nx_tftp_server_media_ptr, (CHAR *) buffer_ptr);
1707 
1708     /* Attempt to open the file.  */
1709     status =  fx_file_open(server_ptr -> nx_tftp_server_media_ptr, &(client_request_ptr -> nx_tftp_client_request_file), (CHAR *) buffer_ptr, FX_OPEN_FOR_WRITE);
1710 
1711     /* Check for file is open errors. */
1712     if (status != NX_SUCCESS)
1713     {
1714 
1715         /*  This is an actual file open error. Send an error to the client.  */
1716         if (status == FX_ACCESS_ERROR)
1717             _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_ACCESS_VIOLATION, "NetX TFTP Server: File Access Error");
1718         else
1719             _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_FILE_NOT_FOUND, "NetX TFTP Server: File Open Failed");
1720 
1721         /* Unable to open the file, release the packet.  */
1722         nx_packet_release(packet_ptr);
1723         return;
1724     }
1725 
1726     /* Now, attempt to build an ACK response to let the client know it can start writing.  */
1727 
1728     /* Allocate packet for the ACK packet.  Determine whether we are sending IP packets.   */
1729     if (ip_address.nxd_ip_version == NX_IP_VERSION_V4)
1730     {
1731         status =  nx_packet_allocate(server_ptr -> nx_tftp_server_packet_pool_ptr, &new_packet, NX_IPv4_UDP_PACKET, NX_WAIT_FOREVER);
1732     }
1733     else
1734     {
1735         status =  nx_packet_allocate(server_ptr -> nx_tftp_server_packet_pool_ptr, &new_packet, NX_IPv6_UDP_PACKET, NX_WAIT_FOREVER);
1736     }
1737 
1738     /* Check for successful packet allocation.  */
1739     if (status != NX_SUCCESS)
1740     {
1741 
1742         /* Increment the number of server allocation errors.  */
1743         server_ptr -> nx_tftp_server_allocation_errors++;
1744 
1745         /* Close the file.  */
1746         fx_file_close(&(client_request_ptr ->nx_tftp_client_request_file));
1747 
1748         /* Unable to allocate net packet, release the original.  */
1749         nx_packet_release(packet_ptr);
1750         return;
1751     }
1752 
1753     if (4u > ((ULONG)(new_packet -> nx_packet_data_end) - (ULONG)(new_packet -> nx_packet_append_ptr)))
1754     {
1755         nx_packet_release(new_packet);
1756 
1757         /* Release the original packet.  */
1758         nx_packet_release(packet_ptr);
1759 
1760         return;
1761     }
1762 
1763     new_packet -> nx_packet_append_ptr = new_packet -> nx_packet_prepend_ptr;
1764 
1765     /* Setup the client request structure.  */
1766 #ifndef NX_DISABLE_IPV4
1767     if (ip_address.nxd_ip_version == NX_IP_VERSION_V4)
1768     {
1769 
1770         client_request_ptr ->nx_tftp_client_request_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
1771         client_request_ptr ->nx_tftp_client_request_ip_address.nxd_ip_address.v4 = ip_address.nxd_ip_address.v4;
1772     }
1773     else
1774 #endif /* NX_DISABLE_IPV4 */
1775 #ifdef FEATURE_NX_IPV6
1776     if (ip_address.nxd_ip_version == NX_IP_VERSION_V6)
1777     {
1778         COPY_NXD_ADDRESS(&ip_address, &(client_request_ptr ->nx_tftp_client_request_ip_address));
1779     }
1780     else
1781 #endif
1782     {
1783 
1784         /* Close the file.  */
1785         fx_file_close(&(client_request_ptr ->nx_tftp_client_request_file));
1786 
1787         /* Release the original packet.  */
1788         nx_packet_release(packet_ptr);
1789 
1790         return;
1791     }
1792 
1793 
1794     client_request_ptr -> nx_tftp_client_request_port =             port;
1795     client_request_ptr -> nx_tftp_client_request_block_number =     1;
1796     client_request_ptr -> nx_tftp_client_request_open_type =        NX_TFTP_STATE_WRITE_OPEN;
1797     client_request_ptr -> nx_tftp_client_request_remaining_bytes =  0;
1798 
1799 #ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE
1800     /* Reset retransmission timeouts and retries on current client request.  */
1801     client_request_ptr -> nx_tftp_client_retransmit_timeout =  NX_TFTP_SERVER_RETRANSMIT_TIMEOUT;
1802     client_request_ptr -> nx_tftp_client_retransmit_retries =  0;
1803 
1804 #else
1805 
1806     /* Clear the count of data retransmits from the other side. */
1807     client_request_ptr -> nx_tftp_client_request_retransmits = 0;
1808 #endif
1809 
1810     /* Create the ACK packet.  */
1811     buffer_ptr =  new_packet -> nx_packet_prepend_ptr;
1812     *buffer_ptr++ =  0;
1813     *buffer_ptr++ =  NX_TFTP_CODE_ACK;
1814     *buffer_ptr++ =  0;
1815     *buffer_ptr++ =  0;                                     /* 0, just to signal server is ready.  */
1816 
1817     /* Setup the packet pointers appropriately.  */
1818     new_packet -> nx_packet_length =  4;
1819     new_packet -> nx_packet_append_ptr =  new_packet -> nx_packet_prepend_ptr + 4;
1820 
1821     /* Send the data packet out.  */
1822     status = nxd_udp_socket_send(&(server_ptr -> nx_tftp_server_socket), new_packet, &ip_address, port);
1823 
1824     /* Release packet if send fails. */
1825     if (status)
1826     {
1827         nx_packet_release(new_packet);
1828     }
1829 
1830     /* Release the original packet.  */
1831     nx_packet_release(packet_ptr);
1832 }
1833 
1834 
1835 /**************************************************************************/
1836 /*                                                                        */
1837 /*  FUNCTION                                               RELEASE        */
1838 /*                                                                        */
1839 /*    _nx_tftp_server_data_process                        PORTABLE C      */
1840 /*                                                           6.1.10       */
1841 /*  AUTHOR                                                                */
1842 /*                                                                        */
1843 /*    Yuxin Zhou, Microsoft Corporation                                   */
1844 /*                                                                        */
1845 /*  DESCRIPTION                                                           */
1846 /*                                                                        */
1847 /*    This function takes the supplied data packet and writes it to the   */
1848 /*    previously opened file.                                             */
1849 /*                                                                        */
1850 /*                                                                        */
1851 /*  INPUT                                                                 */
1852 /*                                                                        */
1853 /*    server_ptr                            Pointer to TFTP server        */
1854 /*    packet_ptr                            Pointer to TFTP request packet*/
1855 /*                                                                        */
1856 /*  OUTPUT                                                                */
1857 /*                                                                        */
1858 /*    None                                                                */
1859 /*                                                                        */
1860 /*  CALLS                                                                 */
1861 /*                                                                        */
1862 /*    fx_file_close                         Close file on EOF or error    */
1863 /*    fx_file_write                         Write block to file           */
1864 /*    _nx_tftp_server_find_client_request   Find client entry             */
1865 /*    _nx_tftp_server_send_error            Send error message            */
1866 /*    nx_packet_allocate                    Allocate a new packet         */
1867 /*    nx_packet_copy                        Copy packet                   */
1868 /*    nx_packet_release                     Release packet                */
1869 /*    nx_udp_socket_send                    Send TFTP ACK packet          */
1870 /*    nx_udp_source_extract                 Extract IP and port           */
1871 /*                                                                        */
1872 /*  CALLED BY                                                             */
1873 /*                                                                        */
1874 /*    _nx_tftp_server_thread_entry          TFTP Server thread loop       */
1875 /*                                                                        */
1876 /*  RELEASE HISTORY                                                       */
1877 /*                                                                        */
1878 /*    DATE              NAME                      DESCRIPTION             */
1879 /*                                                                        */
1880 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1881 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1882 /*                                            resulting in version 6.1    */
1883 /*  01-31-2022     Yuxin Zhou               Modified comment(s), improved */
1884 /*                                            the logic of processing     */
1885 /*                                            chained packet,             */
1886 /*                                            resulting in version 6.1.10 */
1887 /*                                                                        */
1888 /**************************************************************************/
_nx_tftp_server_data_process(NX_TFTP_SERVER * server_ptr,NX_PACKET * packet_ptr)1889 VOID  _nx_tftp_server_data_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
1890 {
1891 
1892 NXD_ADDRESS             ip_address;
1893 UINT                    port;
1894 USHORT                  block_number;
1895 ULONG                   bytes_copyed;
1896 NX_TFTP_CLIENT_REQUEST  *client_request_ptr;
1897 UINT                    status;
1898 
1899     /* Extract the source IP and port numbers.  */
1900     nxd_udp_source_extract(packet_ptr, &ip_address, &port);
1901 
1902     /* Find the matching entry in the client request structure.  */
1903     client_request_ptr =  _nx_tftp_server_find_client_request(server_ptr, port, &ip_address);
1904 
1905 
1906     /* Determine if there was a matching entry.  */
1907     if (client_request_ptr == NX_NULL)
1908     {
1909 
1910         /* Increment the unknown clients errors.  */
1911         server_ptr -> nx_tftp_server_unknown_clients_errors++;
1912 
1913         /* Send an error to the client.  */
1914         _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_NO_SUCH_USER, "NetX TFTP Server: Unknown connection");
1915 
1916         /* No more clients can be serviced, release the packet.  */
1917         nx_packet_release(packet_ptr);
1918 
1919         return;
1920     }
1921 
1922     /* Pickup the block number.  */
1923     status = nx_packet_data_extract_offset(packet_ptr, 2, (UCHAR *)&block_number, sizeof(block_number), &bytes_copyed);
1924 
1925     /* Check return status.  */
1926     if (status || (bytes_copyed != 2))
1927     {
1928         nx_packet_release(packet_ptr);
1929         return;
1930     }
1931 
1932     /* Adjust the endianness.  */
1933     NX_CHANGE_USHORT_ENDIAN(block_number);
1934 
1935     /* Determine if this block number matches the current client block number.  */
1936     if (client_request_ptr -> nx_tftp_client_request_block_number != block_number)
1937     {
1938 
1939         /* No, it does not. */
1940 
1941         /* Check if it matches our previous ACK e.g. it could be a retransmit from the other side. */
1942         if (client_request_ptr -> nx_tftp_client_request_block_number == (USHORT)(block_number + 1))
1943         {
1944 
1945 #ifndef NX_TFTP_SERVER_RETRANSMIT_ENABLE
1946 
1947             /* It does. Update how many we have received. */
1948             client_request_ptr -> nx_tftp_client_request_retransmits++;
1949 
1950             /* Decide if we should close the client request. */
1951             if (client_request_ptr -> nx_tftp_client_request_retransmits <= NX_TFTP_MAX_CLIENT_RETRANSMITS)
1952             {
1953 
1954                 /* Not yet. Just drop the packet for now. */
1955                 nx_packet_release(packet_ptr);
1956 
1957                 return;
1958             }
1959             /* Else handle as an error. */
1960 #else
1961             nx_packet_release(packet_ptr);
1962 
1963             /* (Let the retransmit timeout handler retransmit our ACK to the client.) */
1964             return;
1965 #endif
1966         }
1967 
1968          /* Send an error to the client.  */
1969          _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_ILLEGAL_OPERATION, "NetX TFTP Server: Bad block number");
1970 
1971         /* Error, close the file, release the packet and delete the client request.  */
1972         fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
1973 
1974         /* Release the packet. */
1975         nx_packet_release(packet_ptr);
1976 
1977         memset(client_request_ptr, 0, sizeof(NX_TFTP_CLIENT_REQUEST));
1978 
1979         return;
1980     }
1981 
1982     /* At this point we have a valid packet. */
1983 
1984 #ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE
1985 
1986     /* Reset the retransmit retry counter and retransmit timeout. */
1987     client_request_ptr -> nx_tftp_client_retransmit_retries =  0;
1988     client_request_ptr -> nx_tftp_client_retransmit_timeout =  NX_TFTP_SERVER_RETRANSMIT_TIMEOUT;
1989 #else
1990 
1991     /* Clear the count of retransmits from the other side. */
1992     client_request_ptr -> nx_tftp_client_request_retransmits = 0;
1993 #endif
1994 
1995     /* Determine if there is anything to write.  */
1996     if (packet_ptr -> nx_packet_length > 4)
1997     {
1998 
1999         /* At this point, we need to write the next block of the file.  */
2000 
2001 #ifndef NX_DISABLE_PACKET_CHAIN
2002         /* Determine if the current packet is chained.  */
2003         if (packet_ptr -> nx_packet_next)
2004         {
2005 
2006         NX_PACKET   *temp_ptr;
2007 
2008 
2009             /* Yes, the packet is chained.  We have to copy the receive packet into a packet with the
2010                a payload of at least 560 bytes so the write request can be supplied with just the
2011                payload pointer.  */
2012             status =  nx_packet_copy(packet_ptr, &temp_ptr, server_ptr -> nx_tftp_server_packet_pool_ptr, NX_WAIT_FOREVER);
2013 
2014             /* Check for successful packet copy.  */
2015             if (status != NX_SUCCESS)
2016             {
2017 
2018                 /* Increment the number of server allocation errors.  */
2019                 server_ptr -> nx_tftp_server_allocation_errors++;
2020 
2021                 /* Unable to allocate net packet, release the original.  */
2022                 fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
2023 
2024                 nx_packet_release(packet_ptr);
2025 
2026                 memset(client_request_ptr,0, sizeof(NX_TFTP_CLIENT_REQUEST));
2027 
2028                 return;
2029             }
2030 
2031             /* Successful packet copy.  Release the original packet and reassign the packet pointer variable.  */
2032             nx_packet_release(packet_ptr);
2033             packet_ptr =  temp_ptr;
2034         }
2035 #endif /* NX_DISABLE_PACKET_CHAIN */
2036 
2037         /* Attempt to write the block to the file.  */
2038         status =  fx_file_write(&(client_request_ptr -> nx_tftp_client_request_file), packet_ptr -> nx_packet_prepend_ptr+4,
2039                                packet_ptr -> nx_packet_length - 4);
2040 
2041         /* Check for successful file write.  */
2042         if (status != NX_SUCCESS)
2043         {
2044 
2045             /* Send an error to the client.  */
2046             _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_NOT_DEFINED, "NetX TFTP Server: File Write Error");
2047 
2048             /* Unable to write the file, close it and release the packet.  */
2049             fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
2050 
2051             nx_packet_release(packet_ptr);
2052 
2053             return;
2054         }
2055     }
2056 
2057     /* Check the last packet. */
2058     if (packet_ptr -> nx_packet_length - 4 < NX_TFTP_FILE_TRANSFER_MAX)
2059     {
2060         fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
2061     }
2062 
2063     status = _nx_tftp_server_send_ack(server_ptr, client_request_ptr, NX_FALSE);
2064 
2065     if (status == NX_SUCCESS)
2066     {
2067 
2068         /* Increment the number of total bytes received.  */
2069         server_ptr -> nx_tftp_server_total_bytes_received +=  (packet_ptr -> nx_packet_length - 4);
2070 
2071         /* Determine if this was the last write.  */
2072         if ((packet_ptr -> nx_packet_length - 4) < NX_TFTP_FILE_TRANSFER_MAX)
2073         {
2074 
2075             /* No, nothing left to write.  Close the file, release the packet and delete
2076                the client request.  */
2077             fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
2078             memset(client_request_ptr, 0, sizeof(NX_TFTP_CLIENT_REQUEST));
2079         }
2080     }
2081 
2082     /* Release the original packet.  */
2083     nx_packet_release(packet_ptr);
2084 
2085     return;
2086 }
2087 
2088 
2089 /**************************************************************************/
2090 /*                                                                        */
2091 /*  FUNCTION                                               RELEASE        */
2092 /*                                                                        */
2093 /*    _nx_tftp_server_ack_process                         PORTABLE C      */
2094 /*                                                           6.1.10       */
2095 /*  AUTHOR                                                                */
2096 /*                                                                        */
2097 /*    Yuxin Zhou, Microsoft Corporation                                   */
2098 /*                                                                        */
2099 /*  DESCRIPTION                                                           */
2100 /*                                                                        */
2101 /*    This function processes an ACK to the previous file read            */
2102 /*    operation and prepares the next data packet to send if necessary.   */
2103 /*                                                                        */
2104 /*                                                                        */
2105 /*  INPUT                                                                 */
2106 /*                                                                        */
2107 /*    server_ptr                            Pointer to TFTP server        */
2108 /*    packet_ptr                            Pointer to TFTP request packet*/
2109 /*                                                                        */
2110 /*  OUTPUT                                                                */
2111 /*                                                                        */
2112 /*    None                                                                */
2113 /*                                                                        */
2114 /*  CALLS                                                                 */
2115 /*                                                                        */
2116 /*    fx_file_close                         Close file on EOF or error    */
2117 /*    fx_file_read                          Read block from file          */
2118 /*    _nx_tftp_server_find_client_request   Find client entry             */
2119 /*    _nx_tftp_server_send_error            Send error message            */
2120 /*    nx_packet_allocate                    Allocate a new packet         */
2121 /*    nx_packet_copy                        Copy packet                   */
2122 /*    nx_packet_release                     Release packet                */
2123 /*    nx_udp_socket_send                    Send TFTP data packet         */
2124 /*    nx_udp_source_extract                 Extract IP and port           */
2125 /*                                                                        */
2126 /*  CALLED BY                                                             */
2127 /*                                                                        */
2128 /*    _nx_tftp_server_thread_entry          TFTP Server thread            */
2129 /*                                                                        */
2130 /*  RELEASE HISTORY                                                       */
2131 /*                                                                        */
2132 /*    DATE              NAME                      DESCRIPTION             */
2133 /*                                                                        */
2134 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2135 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2136 /*                                            resulting in version 6.1    */
2137 /*  01-31-2022     Yuxin Zhou               Modified comment(s), improved */
2138 /*                                            the logic of processing     */
2139 /*                                            chained packet,             */
2140 /*                                            resulting in version 6.1.10 */
2141 /*                                                                        */
2142 /**************************************************************************/
_nx_tftp_server_ack_process(NX_TFTP_SERVER * server_ptr,NX_PACKET * packet_ptr)2143 VOID  _nx_tftp_server_ack_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
2144 {
2145 
2146 NXD_ADDRESS             ip_address;
2147 UINT                    port;
2148 USHORT                  block_number;
2149 ULONG                   bytes_copyed;
2150 NX_TFTP_CLIENT_REQUEST  *client_request_ptr;
2151 UINT                    status;
2152 
2153 
2154     /* Extract the source IP and port numbers.  */
2155     nxd_udp_source_extract(packet_ptr, &ip_address, &port);
2156 
2157 
2158     /* Find a matching entry in the client request structure.  */
2159     client_request_ptr =  _nx_tftp_server_find_client_request(server_ptr, port, &ip_address);
2160 
2161     /* Determine if there was a matching entry.  */
2162     if (client_request_ptr == NX_NULL)
2163     {
2164 
2165         /* Increment the unknown clients errors.  */
2166         server_ptr -> nx_tftp_server_unknown_clients_errors++;
2167 
2168         /* Send an error to the client.  */
2169         _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_NO_SUCH_USER, "NetX TFTP Server: Unknown connection");
2170 
2171         /* No more clients can be serviced, release the packet.  */
2172         nx_packet_release(packet_ptr);
2173         return;
2174     }
2175 
2176     /* Pickup the block number.  */
2177     status = nx_packet_data_extract_offset(packet_ptr, 2, (UCHAR *)&block_number, sizeof(block_number), &bytes_copyed);
2178 
2179     /* Check return status.  */
2180     if (status || (bytes_copyed != 2))
2181     {
2182         nx_packet_release(packet_ptr);
2183         return;
2184     }
2185 
2186     /* Adjust the endianness.  */
2187     NX_CHANGE_USHORT_ENDIAN(block_number);
2188 
2189     /* Determine if this block number matches the request.  */
2190     if (client_request_ptr -> nx_tftp_client_request_block_number != block_number)
2191     {
2192 
2193         /* Check if this is a retransmitted ACK e.g. our previous data packet was dropped our
2194            delayed. */
2195         if (client_request_ptr -> nx_tftp_client_request_block_number == (USHORT)(block_number + 1))
2196         {
2197 
2198 #ifndef NX_TFTP_SERVER_RETRANSMIT_ENABLE
2199 
2200             /* It does. Update how many we have received. */
2201             client_request_ptr -> nx_tftp_client_request_retransmits++;
2202 
2203             /* Decide if we should close the client request. */
2204             if (client_request_ptr -> nx_tftp_client_request_retransmits <= NX_TFTP_MAX_CLIENT_RETRANSMITS)
2205             {
2206 
2207                 /* Not yet. Just drop the packet for now. */
2208                 nx_packet_release(packet_ptr);
2209 
2210                 return;
2211             }
2212 
2213             /* Else handle as an error. */
2214 #else
2215             nx_packet_release(packet_ptr);
2216 
2217             /* (Let the retransmit timeout handler retransmit our data to the client.) */
2218             return;
2219 #endif
2220         }
2221 
2222         /* Send an error to the client.  */
2223         _nx_tftp_server_send_error(server_ptr, &ip_address, port, NX_TFTP_ERROR_ILLEGAL_OPERATION, "NetX TFTP Server: Bad block number");
2224 
2225         /* Error, close the file, release the packet and delete the client request.  */
2226         fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
2227 
2228         nx_packet_release(packet_ptr);
2229 
2230         memset(client_request_ptr, 0, sizeof(NX_TFTP_CLIENT_REQUEST));
2231 
2232         return;
2233     }
2234 
2235     /* The block number matches, see if there is anything left to send.  */
2236     if ((client_request_ptr -> nx_tftp_client_request_remaining_bytes == 0) &&
2237         (client_request_ptr -> nx_tftp_client_request_exact_fit == NX_FALSE))
2238     {
2239 
2240         /* No, nothing left to send.  Close the file, release the packet and delete
2241            the client request.  */
2242         fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
2243 
2244         nx_packet_release(packet_ptr);
2245 
2246         memset(client_request_ptr, 0, sizeof(NX_TFTP_CLIENT_REQUEST));
2247 
2248         return;
2249     }
2250 
2251 #ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE
2252     /* We have a valid ACK. Reset the retransmit retry counter and retransmit timeout. */
2253     client_request_ptr -> nx_tftp_client_retransmit_retries =  0;
2254     client_request_ptr -> nx_tftp_client_retransmit_timeout =  NX_TFTP_SERVER_RETRANSMIT_TIMEOUT;
2255 #endif
2256 
2257     /* At this point, we need to send the next block of the file.  */
2258     _nx_tftp_server_send_data(server_ptr, client_request_ptr, NX_FALSE);
2259 
2260     /* Release the original packet.  */
2261     nx_packet_release(packet_ptr);
2262 
2263     return;
2264 }
2265 
2266 
2267 /**************************************************************************/
2268 /*                                                                        */
2269 /*  FUNCTION                                               RELEASE        */
2270 /*                                                                        */
2271 /*    _nx_tftp_server_send_data                           PORTABLE C      */
2272 /*                                                           6.1          */
2273 /*  AUTHOR                                                                */
2274 /*                                                                        */
2275 /*    Yuxin Zhou, Microsoft Corporation                                   */
2276 /*                                                                        */
2277 /*  DESCRIPTION                                                           */
2278 /*                                                                        */
2279 /*    This function creates a data packet based on the last ACK  received */
2280 /*    and sends it out. This will also retransmit a data packet if        */
2281 /*    specified. On error it will close the file and the client request.  */
2282 /*    It does not update the Client request e.g. block number.            */
2283 /*                                                                        */
2284 /*  INPUT                                                                 */
2285 /*                                                                        */
2286 /*    server_ptr                            Pointer to TFTP server        */
2287 /*    client_request_ptr                    Pointer to Client request     */
2288 /*    retransmit                            Indicate if retransmiting a   */
2289 /*                                            previously sent ACK         */
2290 /*                                                                        */
2291 /*  OUTPUT                                                                */
2292 /*                                                                        */
2293 /*    status                                Completion status             */
2294 /*                                                                        */
2295 /*  CALLS                                                                 */
2296 /*                                                                        */
2297 /*    _nx_tftp_server_close_client_request  Terminate a client request    */
2298 /*    _nx_tftp_server_send_error            Send error status to Client   */
2299 /*    nx_packet_allocate                    Allocate a new packet         */
2300 /*    nx_udp_socket_send                    Send TFTP data packet         */
2301 /*    fx_file_seek                          Set location in file          */
2302 /*    fx_file_read                          Read from set location in file*/
2303 /*                                                                        */
2304 /*  CALLED BY                                                             */
2305 /*                                                                        */
2306 /*    _nx_tftp_server_timer_process         TFTP timeout event            */
2307 /*    _nx_tftp_server_ack_process           Process a received ACK        */
2308 /*                                                                        */
2309 /*  RELEASE HISTORY                                                       */
2310 /*                                                                        */
2311 /*    DATE              NAME                      DESCRIPTION             */
2312 /*                                                                        */
2313 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2314 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2315 /*                                            resulting in version 6.1    */
2316 /*                                                                        */
2317 /**************************************************************************/
_nx_tftp_server_send_data(NX_TFTP_SERVER * server_ptr,NX_TFTP_CLIENT_REQUEST * client_request_ptr,UINT retransmit)2318 UINT _nx_tftp_server_send_data(NX_TFTP_SERVER *server_ptr, NX_TFTP_CLIENT_REQUEST *client_request_ptr, UINT retransmit)
2319 {
2320 
2321 UINT        status;
2322 ULONG       actual_size = 0;
2323 NX_PACKET   *new_packet;
2324 UCHAR       *buffer_ptr;
2325 
2326 
2327    /* Allocate packet for the read packet. Determine whether we are sending IP packets.   */
2328     if (client_request_ptr -> nx_tftp_client_request_ip_address.nxd_ip_version == NX_IP_VERSION_V4)
2329     {
2330         status =  nx_packet_allocate(server_ptr -> nx_tftp_server_packet_pool_ptr, &new_packet, NX_IPv4_UDP_PACKET, NX_WAIT_FOREVER);
2331     }
2332     else
2333     {
2334         status =  nx_packet_allocate(server_ptr -> nx_tftp_server_packet_pool_ptr, &new_packet, NX_IPv6_UDP_PACKET, NX_WAIT_FOREVER);
2335     }
2336 
2337 
2338     /* Check for successful packet allocation.  */
2339     if (status != NX_SUCCESS)
2340     {
2341 
2342         /* Increment the number of server allocation errors.  */
2343         server_ptr -> nx_tftp_server_allocation_errors++;
2344 
2345         /* Unable to allocate net packet, release the original.  */
2346         fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
2347 
2348         memset(client_request_ptr, 0, sizeof(NX_TFTP_CLIENT_REQUEST));
2349 
2350         return status;
2351     }
2352 
2353     if (4u + NX_TFTP_FILE_TRANSFER_MAX > ((ULONG)(new_packet -> nx_packet_data_end) - (ULONG)(new_packet -> nx_packet_append_ptr)))
2354     {
2355         nx_packet_release(new_packet);
2356         return(NX_SIZE_ERROR);
2357     }
2358 
2359     new_packet -> nx_packet_append_ptr = new_packet -> nx_packet_prepend_ptr;
2360 
2361     /* Determine if there are more bytes to read.  */
2362     if (client_request_ptr -> nx_tftp_client_request_remaining_bytes)
2363     {
2364 
2365         status = NX_SUCCESS;
2366 
2367         /* Are we retransmitting? */
2368         if (retransmit)
2369         {
2370 
2371             /* Yes, figure out where to reset the file pointer to the previous
2372                file read so we can retrieve the previous data we sent. */
2373             UINT index =  client_request_ptr -> nx_tftp_client_file_size -
2374                                    client_request_ptr -> nx_tftp_client_request_remaining_bytes -
2375                                    client_request_ptr -> nx_tftp_client_previous_write_size;
2376 
2377             status = fx_file_seek(&(client_request_ptr -> nx_tftp_client_request_file), index);
2378         }
2379 
2380         /* Are we still ok to do a file read? */
2381         if (status == NX_SUCCESS)
2382         {
2383 
2384             /* Yes. Attempt to read the requested file.  */
2385             UINT status_read =  fx_file_read(&(client_request_ptr -> nx_tftp_client_request_file), new_packet -> nx_packet_prepend_ptr+4,
2386                                              NX_TFTP_FILE_TRANSFER_MAX, &actual_size);
2387 
2388             /* Check for successful file read.  */
2389             if ((status_read != NX_SUCCESS) ||
2390                ((client_request_ptr -> nx_tftp_client_request_remaining_bytes > NX_TFTP_FILE_TRANSFER_MAX) && (actual_size < NX_TFTP_FILE_TRANSFER_MAX)) ||
2391                ((client_request_ptr -> nx_tftp_client_request_remaining_bytes < NX_TFTP_FILE_TRANSFER_MAX) && (actual_size != client_request_ptr -> nx_tftp_client_request_remaining_bytes)))
2392             {
2393 
2394                 /* Update our 'status' variable with the result from file read. */
2395                 status = status_read;
2396             }
2397         }
2398 
2399         /* Are we ok to transmit more data? */
2400         if (status != NX_SUCCESS)
2401         {
2402 
2403             /* No, send an error back to the client.  */
2404             _nx_tftp_server_send_error(server_ptr, &client_request_ptr -> nx_tftp_client_request_ip_address,
2405                                        client_request_ptr -> nx_tftp_client_request_port,
2406                                        NX_TFTP_ERROR_NOT_DEFINED, "NetX TFTP Server: File Read Error");
2407 
2408             memset(client_request_ptr, 0, sizeof(NX_TFTP_CLIENT_REQUEST));
2409 
2410             /* Unable to read the file, close it and release the packet.  */
2411             fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
2412 
2413             nx_packet_release(new_packet);
2414 
2415             return status;
2416         }
2417     }
2418     else
2419     {
2420 
2421         /* Clear the exact fit flag since the only way we can be here is if the TFTP transfer size
2422            evenly divided into the file size and we need to send a zero length data buffer to signal
2423            the end of the file.  */
2424         client_request_ptr -> nx_tftp_client_request_exact_fit =  NX_FALSE;
2425 
2426         /* Set the actual size to zero for exact fit case.  */
2427         actual_size =  0;
2428     }
2429 
2430     /* Increment the number of total bytes sent.  */
2431     server_ptr -> nx_tftp_server_total_bytes_sent +=  actual_size;
2432 
2433     /* Is this new data being sent (not a retransmit)?   */
2434     if (retransmit == NX_FALSE)
2435     {
2436 
2437         /* Yes, so advance the block number and number of bytes of the file sent. */
2438         client_request_ptr -> nx_tftp_client_request_block_number++;
2439 
2440         client_request_ptr -> nx_tftp_client_request_remaining_bytes -=  actual_size;
2441     }
2442 
2443     client_request_ptr -> nx_tftp_client_previous_write_size = actual_size;
2444 
2445     /* Move the TFTP data code and block number into the payload before sending it to the client.  */
2446     buffer_ptr =  new_packet -> nx_packet_prepend_ptr;
2447     *buffer_ptr++ =  0;
2448     *buffer_ptr++ =  NX_TFTP_CODE_DATA;
2449     *buffer_ptr++ =  (UCHAR) (client_request_ptr -> nx_tftp_client_request_block_number >> 8);
2450     *buffer_ptr++ =  (UCHAR) (client_request_ptr -> nx_tftp_client_request_block_number & 0xFF);
2451 
2452     /* Setup the packet pointers appropriately.  */
2453     new_packet -> nx_packet_length =  actual_size + 4;
2454     new_packet -> nx_packet_append_ptr =  new_packet -> nx_packet_prepend_ptr + new_packet -> nx_packet_length;
2455 
2456     /* Send the data packet out.  */
2457     status = nxd_udp_socket_send(&(server_ptr -> nx_tftp_server_socket), new_packet, &client_request_ptr -> nx_tftp_client_request_ip_address,
2458                                  client_request_ptr -> nx_tftp_client_request_port);
2459 
2460     /* Release packet if send fails. */
2461     if (status)
2462     {
2463         nx_packet_release(new_packet);
2464     }
2465 
2466    return NX_SUCCESS;
2467 }
2468 
2469 
2470 /**************************************************************************/
2471 /*                                                                        */
2472 /*  FUNCTION                                               RELEASE        */
2473 /*                                                                        */
2474 /*    _nx_tftp_server_send_ack                            PORTABLE C      */
2475 /*                                                           6.1          */
2476 /*  AUTHOR                                                                */
2477 /*                                                                        */
2478 /*    Yuxin Zhou, Microsoft Corporation                                   */
2479 /*                                                                        */
2480 /*  DESCRIPTION                                                           */
2481 /*                                                                        */
2482 /*    This function creates an ACK packet based on the last block of data */
2483 /*    received, and sends it out. This will also retransmit an ACK if     */
2484 /*    specified. On error it will close the file and the client request.  */
2485 /*    It does not update the Client request e.g. block number.            */
2486 /*                                                                        */
2487 /*  INPUT                                                                 */
2488 /*                                                                        */
2489 /*    server_ptr                            Pointer to TFTP server        */
2490 /*    client_request_ptr                    Pointer to Client request     */
2491 /*    retransmit                            Indicate if retransmiting a   */
2492 /*                                            previously sent ACK         */
2493 /*                                                                        */
2494 /*  OUTPUT                                                                */
2495 /*                                                                        */
2496 /*    status                                Completion status             */
2497 /*                                                                        */
2498 /*  CALLS                                                                 */
2499 /*                                                                        */
2500 /*    _nx_tftp_server_close_client_request  Terminate a client request    */
2501 /*    nx_packet_allocate                    Allocate a new packet         */
2502 /*    nx_udp_socket_send                    Send TFTP data packet         */
2503 /*                                                                        */
2504 /*  CALLED BY                                                             */
2505 /*                                                                        */
2506 /*    _nx_tftp_server_timer_process         TFTP timeout event            */
2507 /*    _nx_tftp_server_data_process          Process a received packet     */
2508 /*                                                                        */
2509 /*  RELEASE HISTORY                                                       */
2510 /*                                                                        */
2511 /*    DATE              NAME                      DESCRIPTION             */
2512 /*                                                                        */
2513 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2514 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2515 /*                                            resulting in version 6.1    */
2516 /*                                                                        */
2517 /**************************************************************************/
_nx_tftp_server_send_ack(NX_TFTP_SERVER * server_ptr,NX_TFTP_CLIENT_REQUEST * client_request_ptr,UINT retransmit)2518 UINT _nx_tftp_server_send_ack(NX_TFTP_SERVER *server_ptr, NX_TFTP_CLIENT_REQUEST *client_request_ptr, UINT retransmit)
2519 {
2520 
2521 UINT        status;
2522 UCHAR       *buffer_ptr;
2523 NX_PACKET   *new_packet;
2524 
2525 
2526    /* Allocate packet for the ACK.  Determine whether we are sending IP packets.   */
2527     if (client_request_ptr -> nx_tftp_client_request_ip_address.nxd_ip_version == NX_IP_VERSION_V4)
2528     {
2529         status =  nx_packet_allocate(server_ptr -> nx_tftp_server_packet_pool_ptr, &new_packet, NX_IPv4_UDP_PACKET, NX_WAIT_FOREVER);
2530     }
2531     else
2532     {
2533         status =  nx_packet_allocate(server_ptr -> nx_tftp_server_packet_pool_ptr, &new_packet, NX_IPv6_UDP_PACKET, NX_WAIT_FOREVER);
2534     }
2535 
2536     /* Check for successful packet allocation.  */
2537     if (status != NX_SUCCESS)
2538     {
2539 
2540         /* Increment the number of server allocation errors.  */
2541         server_ptr -> nx_tftp_server_allocation_errors++;
2542 
2543         /* Unable to allocate net packet, release the original.  */
2544         fx_file_close(&(client_request_ptr -> nx_tftp_client_request_file));
2545 
2546         memset(client_request_ptr, 0, sizeof(NX_TFTP_CLIENT_REQUEST));
2547 
2548         return status;
2549     }
2550 
2551     if (4u > ((ULONG)(new_packet -> nx_packet_data_end) - (ULONG)(new_packet -> nx_packet_append_ptr)))
2552     {
2553         nx_packet_release(new_packet);
2554         return(NX_SIZE_ERROR);
2555     }
2556 
2557     new_packet -> nx_packet_append_ptr = new_packet -> nx_packet_prepend_ptr;
2558 
2559     /* Now build the ACK message to the client.  */
2560     buffer_ptr =  new_packet -> nx_packet_prepend_ptr;
2561     *buffer_ptr++ =  0;
2562     *buffer_ptr++ =  NX_TFTP_CODE_ACK;
2563 
2564     /* If we are retransmitting, send the block number of the previous ACK. */
2565     if (retransmit)
2566     {
2567 
2568         *buffer_ptr++ =  (UCHAR) ((client_request_ptr -> nx_tftp_client_request_block_number - 1) >> 8);
2569         *buffer_ptr++ =  (UCHAR) ((client_request_ptr -> nx_tftp_client_request_block_number - 1) & 0xFF);
2570     }
2571     else
2572     {
2573 
2574         *buffer_ptr++ =  (UCHAR) ((client_request_ptr -> nx_tftp_client_request_block_number) >> 8);
2575         *buffer_ptr++ =  (UCHAR) (client_request_ptr -> nx_tftp_client_request_block_number & 0xFF);
2576     }
2577 
2578     /* Setup the packet pointers appropriately.  */
2579     new_packet -> nx_packet_length =  4;
2580     new_packet -> nx_packet_append_ptr =  new_packet -> nx_packet_prepend_ptr + 4;
2581 
2582     /* Send the ACK packet out.  */
2583     status = nxd_udp_socket_send(&(server_ptr -> nx_tftp_server_socket), new_packet, &client_request_ptr -> nx_tftp_client_request_ip_address,
2584                                  client_request_ptr -> nx_tftp_client_request_port);
2585 
2586     /* Release packet if send fails. */
2587     if (status)
2588     {
2589         nx_packet_release(new_packet);
2590     }
2591 
2592     /* Is this ACK for new data received (e.g. not a retransmit)? */
2593     if (retransmit == NX_FALSE)
2594     {
2595 
2596         /* Yes, so increase the block number.  */
2597         client_request_ptr -> nx_tftp_client_request_block_number++;
2598     }
2599 
2600     return NX_SUCCESS;
2601 }
2602 
2603 
2604 /**************************************************************************/
2605 /*                                                                        */
2606 /*  FUNCTION                                               RELEASE        */
2607 /*                                                                        */
2608 /*    _nx_tftp_server_error_process                      PORTABLE C       */
2609 /*                                                           6.1.10       */
2610 /*  AUTHOR                                                                */
2611 /*                                                                        */
2612 /*    Yuxin Zhou, Microsoft Corporation                                   */
2613 /*                                                                        */
2614 /*  DESCRIPTION                                                           */
2615 /*                                                                        */
2616 /*    This function processes an error sent by a client.                  */
2617 /*                                                                        */
2618 /*                                                                        */
2619 /*  INPUT                                                                 */
2620 /*                                                                        */
2621 /*    server_ptr                            Pointer to TFTP server        */
2622 /*    packet_ptr                            Pointer to TFTP request packet*/
2623 /*                                                                        */
2624 /*  OUTPUT                                                                */
2625 /*                                                                        */
2626 /*    None                                                                */
2627 /*                                                                        */
2628 /*  CALLS                                                                 */
2629 /*                                                                        */
2630 /*    nx_packet_release                     Release packet                */
2631 /*                                                                        */
2632 /*  CALLED BY                                                             */
2633 /*                                                                        */
2634 /*    _nx_tftp_server_thread_entry          TFTP Server thread task       */
2635 /*                                                                        */
2636 /*  RELEASE HISTORY                                                       */
2637 /*                                                                        */
2638 /*    DATE              NAME                      DESCRIPTION             */
2639 /*                                                                        */
2640 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2641 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2642 /*                                            resulting in version 6.1    */
2643 /*  01-31-2022     Yuxin Zhou               Modified comment(s), improved */
2644 /*                                            the logic of processing     */
2645 /*                                            chained packet,             */
2646 /*                                            resulting in version 6.1.10 */
2647 /*                                                                        */
2648 /**************************************************************************/
_nx_tftp_server_error_process(NX_TFTP_SERVER * server_ptr,NX_PACKET * packet_ptr)2649 VOID  _nx_tftp_server_error_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
2650 {
2651 
2652 UINT    i;
2653 UCHAR   *buffer_ptr;
2654 UINT    port;
2655 NXD_ADDRESS  ip_address;
2656 NX_TFTP_CLIENT_REQUEST *client_request_ptr;
2657 
2658     /* Packet chain isn't supported.  */
2659 #ifndef NX_DISABLE_PACKET_CHAIN
2660     if (packet_ptr -> nx_packet_next)
2661     {
2662         nx_packet_release(packet_ptr);
2663         return;
2664     }
2665 #endif /* NX_DISABLE_PACKET_CHAIN */
2666 
2667     /* Pickup a pointer to the error code in the buffer.  */
2668     buffer_ptr =  packet_ptr -> nx_packet_prepend_ptr + 2;
2669 
2670     /* Set the error code in the server control block.  */
2671     server_ptr -> nx_tftp_server_error_code =  (((UINT) (*buffer_ptr)) << 8);
2672     buffer_ptr++;
2673     server_ptr -> nx_tftp_server_error_code |= ((UINT) (*buffer_ptr) & 0xFF);
2674     buffer_ptr++;
2675 
2676     /* Loop to save error message.  */
2677     server_ptr -> nx_tftp_server_error_string[sizeof(server_ptr -> nx_tftp_server_error_string) - 1] =  NX_NULL;
2678     for (i = 0; i < NX_TFTP_ERROR_STRING_MAX; i++)
2679     {
2680 
2681         /* Store desired file name.  */
2682         server_ptr -> nx_tftp_server_error_string[i] =  (CHAR) *buffer_ptr++;
2683 
2684         /* Check for NULL character.  */
2685         if (server_ptr -> nx_tftp_server_error_string[i] == NX_NULL)
2686             break;
2687 
2688         /* Check for packet buffer boundary. */
2689         if (buffer_ptr >= packet_ptr -> nx_packet_append_ptr)
2690             break;
2691     }
2692 
2693     /* Extract the source IP and port numbers.  */
2694 
2695     nxd_udp_source_extract(packet_ptr, &ip_address, &port);
2696 
2697     /* First, try to find a matching existing entry in the client request structure.  */
2698     client_request_ptr =  _nx_tftp_server_find_client_request(server_ptr, port, &ip_address);
2699 
2700     /* Reset the retransmit timeout on the client request. */
2701     if (client_request_ptr)
2702     {
2703 #ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE
2704 
2705         client_request_ptr -> nx_tftp_client_retransmit_timeout =  NX_TFTP_SERVER_RETRANSMIT_TIMEOUT;
2706         client_request_ptr -> nx_tftp_client_retransmit_retries =  0;
2707 #else
2708 
2709         client_request_ptr -> nx_tftp_client_request_retransmits = 0;
2710 
2711 #endif /* NX_TFTP_SERVER_RETRANSMIT_ENABLE */
2712     }
2713 
2714     /* Release the packet.  */
2715     nx_packet_release(packet_ptr);
2716 }
2717 
2718 
2719 /**************************************************************************/
2720 /*                                                                        */
2721 /*  FUNCTION                                               RELEASE        */
2722 /*                                                                        */
2723 /*    _nx_tftp_server_find_client_request                 PORTABLE C      */
2724 /*                                                           6.1          */
2725 /*  AUTHOR                                                                */
2726 /*                                                                        */
2727 /*    Yuxin Zhou, Microsoft Corporation                                   */
2728 /*                                                                        */
2729 /*  DESCRIPTION                                                           */
2730 /*                                                                        */
2731 /*    This function attempts to find the specified IP and port number in  */
2732 /*    the client request array of this TFTP server instance.              */
2733 /*                                                                        */
2734 /*                                                                        */
2735 /*  INPUT                                                                 */
2736 /*                                                                        */
2737 /*    server_ptr                            Pointer to TFTP server        */
2738 /*    port                                  Client port number            */
2739 /*    ip_address                            Client IP address             */
2740 /*                                                                        */
2741 /*  OUTPUT                                                                */
2742 /*                                                                        */
2743 /*    NX_TFTP_CLIENT_REQUEST *              NULL if not found             */
2744 /*                                          Non null if match found       */
2745 /*                                                                        */
2746 /*  CALLS                                                                 */
2747 /*                                                                        */
2748 /*    nx_packet_release                     Release packet                */
2749 /*                                                                        */
2750 /*  CALLED BY                                                             */
2751 /*                                                                        */
2752 /*    _nx_tftp_server_ack_process             ACK processing              */
2753 /*    _nx_tftp_server_data_process            Data packet processing      */
2754 /*    _nx_tftp_server_open_for_write_process  Open for write processing   */
2755 /*    _nx_tftp_server_open_for_read_process   Open for read processing    */
2756 /*                                                                        */
2757 /*  RELEASE HISTORY                                                       */
2758 /*                                                                        */
2759 /*    DATE              NAME                      DESCRIPTION             */
2760 /*                                                                        */
2761 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2762 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2763 /*                                            resulting in version 6.1    */
2764 /*                                                                        */
2765 /**************************************************************************/
_nx_tftp_server_find_client_request(NX_TFTP_SERVER * server_ptr,UINT port,NXD_ADDRESS * ip_address)2766 NX_TFTP_CLIENT_REQUEST * _nx_tftp_server_find_client_request(NX_TFTP_SERVER *server_ptr, UINT port, NXD_ADDRESS *ip_address)
2767 {
2768 
2769 UINT                        i;
2770 NX_TFTP_CLIENT_REQUEST    *client_request_ptr;
2771 
2772     /* First, find a free entry in the client request structure.  */
2773     i =  0;
2774     for (i = 0; i < NX_TFTP_MAX_CLIENTS; i++)
2775     {
2776         client_request_ptr =  &(server_ptr -> nx_tftp_server_client_list[i]);
2777 
2778         /* First check if we are adding an address.  If the caller sends in a blank
2779            address and port, we are. */
2780         if (port == 0)
2781         {
2782 
2783             /* We are adding an address. Now check if this slot is empty. */
2784 
2785             if (client_request_ptr -> nx_tftp_client_request_port == 0)
2786             {
2787 
2788                 /* If there is no port number, this is an empty slot. But let's clear the slot anyway. */
2789                 memset(&(server_ptr -> nx_tftp_server_client_list[i]), 0, sizeof(NX_TFTP_CLIENT_REQUEST));
2790 
2791                 break;
2792             }
2793         }
2794         /* This is a valid address. Does it match the current entry?  */
2795         else
2796         {
2797             /* Check if it is an IPv4 or IPv6 packet. */
2798             if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4)
2799             {
2800 
2801 #ifndef NX_DISABLE_IPV4
2802                 /* This is an IPv4 request packet. */
2803                 if ((client_request_ptr -> nx_tftp_client_request_port == port) &&
2804                     (client_request_ptr -> nx_tftp_client_request_ip_address.nxd_ip_address.v4 == ip_address -> nxd_ip_address.v4))
2805                 {
2806 
2807                     /* Yes, they match! */
2808                     break;
2809                 }
2810 #else
2811                 return NX_NULL;
2812 #endif /* NX_DISABLE_IPV4 */
2813             }
2814             else if (ip_address -> nxd_ip_version == NX_IP_VERSION_V6)
2815             {
2816 
2817 #ifndef FEATURE_NX_IPV6
2818                 return NX_NULL;
2819 #else
2820                 /* This is an IPv6 request packet. */
2821                 if ((client_request_ptr -> nx_tftp_client_request_port == port) &&
2822                     (CHECK_IPV6_ADDRESSES_SAME(&client_request_ptr -> nx_tftp_client_request_ip_address.nxd_ip_address.v6[0], &ip_address -> nxd_ip_address.v6[0])))
2823                 {
2824 
2825                     /* Yes, they match! */
2826                     break;
2827                 }
2828 #endif
2829             }
2830         }
2831     }
2832 
2833     /* Determine if a match was found.    */
2834     if (i < NX_TFTP_MAX_CLIENTS)
2835     {
2836         /* Return a pointer to the matching client request. */
2837         return(&(server_ptr -> nx_tftp_server_client_list[i]));
2838     }
2839     else
2840     {
2841         /* Return a NULL pointer indicating no match found. */
2842         return((NX_TFTP_CLIENT_REQUEST *)NX_NULL);
2843     }
2844 }
2845 
2846 
2847 /**************************************************************************/
2848 /*                                                                        */
2849 /*  FUNCTION                                               RELEASE        */
2850 /*                                                                        */
2851 /*    _nx_tftp_server_send_error                          PORTABLE C      */
2852 /*                                                           6.1          */
2853 /*  AUTHOR                                                                */
2854 /*                                                                        */
2855 /*    Yuxin Zhou, Microsoft Corporation                                   */
2856 /*                                                                        */
2857 /*  DESCRIPTION                                                           */
2858 /*                                                                        */
2859 /*    This function send a TFTP error message to the client specified     */
2860 /*    by the port and IP address.                                         */
2861 /*                                                                        */
2862 /*                                                                        */
2863 /*  INPUT                                                                 */
2864 /*                                                                        */
2865 /*    server_ptr                            Pointer to TFTP server        */
2866 /*    ip_address                            Client IP address             */
2867 /*    port                                  Client port number            */
2868 /*    error                                 TFTP error code               */
2869 /*    error_message                         Error string                  */
2870 /*                                                                        */
2871 /*  OUTPUT                                                                */
2872 /*                                                                        */
2873 /*    None                                                                */
2874 /*                                                                        */
2875 /*  CALLS                                                                 */
2876 /*                                                                        */
2877 /*    nx_packet_allocate                      Allocate error packet       */
2878 /*    nx_udp_socket_send                      Send TFPT error packet      */
2879 /*                                                                        */
2880 /*  CALLED BY                                                             */
2881 /*                                                                        */
2882 /*    _nx_tftp_server_ack_process             ACK processing              */
2883 /*    _nx_tftp_server_data_process            Data packet processing      */
2884 /*    _nx_tftp_server_open_for_write_process  Open for write processing   */
2885 /*    _nx_tftp_server_open_for_read_process   Open for read processing    */
2886 /*                                                                        */
2887 /*  RELEASE HISTORY                                                       */
2888 /*                                                                        */
2889 /*    DATE              NAME                      DESCRIPTION             */
2890 /*                                                                        */
2891 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2892 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2893 /*                                            resulting in version 6.1    */
2894 /*                                                                        */
2895 /**************************************************************************/
_nx_tftp_server_send_error(NX_TFTP_SERVER * server_ptr,NXD_ADDRESS * ip_address,UINT port,UINT error,CHAR * error_message)2896 VOID  _nx_tftp_server_send_error(NX_TFTP_SERVER *server_ptr, NXD_ADDRESS *ip_address, UINT port, UINT error, CHAR *error_message)
2897 {
2898 
2899 UINT        status;
2900 UCHAR       *buffer_ptr;
2901 NX_PACKET   *new_packet;
2902 
2903 
2904    /* Allocate packet for the read packet. Determine whether we are sending IP packets.   */
2905     if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4)
2906     {
2907         status =  nx_packet_allocate(server_ptr -> nx_tftp_server_packet_pool_ptr, &new_packet, NX_IPv4_UDP_PACKET, NX_WAIT_FOREVER);
2908     }
2909     else
2910     {
2911         status =  nx_packet_allocate(server_ptr -> nx_tftp_server_packet_pool_ptr, &new_packet, NX_IPv6_UDP_PACKET, NX_WAIT_FOREVER);
2912     }
2913 
2914     /* Check for successful packet allocation.  */
2915     if (status != NX_SUCCESS)
2916     {
2917 
2918         /* Increment the number of server allocation errors.  */
2919         server_ptr -> nx_tftp_server_allocation_errors++;
2920 
2921         /* Unable to allocate packet for error message, just return!  */
2922         return;
2923     }
2924 
2925     if (6u > ((ULONG)(new_packet -> nx_packet_data_end) - (ULONG)(new_packet -> nx_packet_append_ptr)))
2926     {
2927         nx_packet_release(new_packet);
2928         return;
2929     }
2930 
2931     new_packet -> nx_packet_append_ptr = new_packet -> nx_packet_prepend_ptr;
2932 
2933     /* Move the TFTP error code and message into the payload before sending it to the client.  */
2934     buffer_ptr =  new_packet -> nx_packet_prepend_ptr;
2935     *buffer_ptr++ =  0;
2936     *buffer_ptr++ =  NX_TFTP_CODE_ERROR;
2937     *buffer_ptr++ =  0;
2938     *buffer_ptr++ =  (UCHAR) (error & 0xFF);
2939 
2940     /* Loop to copy the error message into the buffer.  */
2941     do
2942     {
2943 
2944         /* Copy a byte of the error message into the buffer.  */
2945         *buffer_ptr =  (UCHAR) *error_message;
2946 
2947         /* Determine if a NULL is present.  */
2948         if (*buffer_ptr == NX_NULL)
2949         {
2950 
2951             /* Yes, we are at the end of the string end the loop.  */
2952             break;
2953         }
2954 
2955         /* Move both pointers to the next character.  */
2956         buffer_ptr++;
2957         error_message++;
2958     } while (buffer_ptr < (new_packet -> nx_packet_data_end - 1));
2959 
2960     /* Ensure a NULL is in the last position!  */
2961     *buffer_ptr++ =  NX_NULL;
2962 
2963     /* Setup the packet pointers appropriately.  */
2964     new_packet -> nx_packet_length =  (ULONG)(buffer_ptr - new_packet -> nx_packet_prepend_ptr);
2965     new_packet -> nx_packet_append_ptr =  buffer_ptr;
2966 
2967     /* Send the data packet out.  */
2968     status = nxd_udp_socket_send(&(server_ptr -> nx_tftp_server_socket), new_packet, ip_address, port);
2969 
2970     /* Release packet if send fails. */
2971     if (status)
2972     {
2973         nx_packet_release(new_packet);
2974     }
2975 }
2976