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