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 /**                                                                       */
18 /**   Network Address Translation Protocol (NAT)                          */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 #define NX_NAT_SOURCE_CODE
25 
26 
27 /* Force error checking to be disabled in this module */
28 
29 #ifndef NX_DISABLE_ERROR_CHECKING
30 #define NX_DISABLE_ERROR_CHECKING
31 #endif
32 
33 
34 #include "tx_api.h"
35 #include "tx_thread.h"
36 #include "nx_api.h"
37 #include "nx_nat.h"
38 #include "nx_udp.h"
39 #include "nx_tcp.h"
40 #include "nx_icmp.h"
41 #include "nx_packet.h"
42 #include "nx_system.h"
43 
44 #ifdef NX_NAT_ENABLE
45 /* Bring in externs for caller checking code.  */
46 
47 NX_CALLER_CHECKING_EXTERNS
48 
49 /* Define */
50 NX_NAT_DEVICE       *nat_server_ptr;
51 
52 
53 /* Define internal NAT services. */
54 
55 static UINT    _nx_nat_process_packet(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT packet_process);
56 static UINT    _nx_nat_process_inbound_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr);
57 static UINT    _nx_nat_process_inbound_TCP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr);
58 static UINT    _nx_nat_process_inbound_UDP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr);
59 static UINT    _nx_nat_process_inbound_ICMP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr);
60 static UINT    _nx_nat_process_outbound_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr);
61 static UINT    _nx_nat_process_outbound_TCP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr);
62 static UINT    _nx_nat_process_outbound_UDP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr);
63 static UINT    _nx_nat_process_outbound_ICMP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr);
64 static VOID    _nx_nat_ip_packet_send(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr, UCHAR packet_type, ULONG next_hop_address);
65 static UINT    _nx_nat_inbound_entry_find(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr, NX_NAT_TRANSLATION_ENTRY **matched_entry_ptr, ULONG *next_hop_address);
66 static UINT    _nx_nat_outbound_entry_find(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr, NX_NAT_TRANSLATION_ENTRY **matched_entry_ptr, ULONG *next_hop_address);
67 static UINT    _nx_nat_entry_create(NX_NAT_DEVICE *nat_ptr, UCHAR protocol, ULONG local_ip_address, ULONG peer_ip_address,
68                                     USHORT local_port, USHORT  external_port, USHORT  peer_port, ULONG response_timeout, NX_NAT_TRANSLATION_ENTRY **match_entry_ptr);
69 static UINT    _nx_nat_entry_add(NX_NAT_DEVICE *nat_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr);
70 static VOID    _nx_nat_entry_find(NX_NAT_DEVICE *nat_ptr, NX_NAT_TRANSLATION_ENTRY *entry_to_match, NX_NAT_TRANSLATION_ENTRY **match_entry_ptr, UCHAR direction, UINT skip_static_entries);
71 static VOID    _nx_nat_entry_timeout_check(NX_NAT_DEVICE *nat_ptr);
72 static UINT    _nx_nat_packet_is_icmp_error_message(NX_PACKET *packet_ptr, UINT *is_icmp_error_msg);
73 static UINT    _nx_nat_find_available_port(NX_NAT_DEVICE *nat_ptr, UCHAR protocol, USHORT *port);
74 static UINT    _nx_nat_entry_port_verify(NX_IP *ip_ptr, UINT protocol, UINT port);
75 static UINT    _nx_nat_socket_port_verify(NX_IP *ip_ptr, UINT protocol, UINT port);
76 static UINT    _nx_nat_utility_get_source_port(NX_PACKET *packet_ptr, UCHAR protocol, USHORT *source_port);
77 static UINT    _nx_nat_utility_get_destination_port(NX_PACKET *packet_ptr, UCHAR protocol, USHORT *destination_port);
78 static VOID    _nx_nat_checksum_adjust(UCHAR *checksum, UCHAR *old_data, INT old_data_length, UCHAR *new_data, INT new_data_length);
79 
80 
81 /**************************************************************************/
82 /*                                                                        */
83 /*  FUNCTION                                               RELEASE        */
84 /*                                                                        */
85 /*    _nxe_nat_create                                     PORTABLE C      */
86 /*                                                           6.1          */
87 /*  AUTHOR                                                                */
88 /*                                                                        */
89 /*    Yuxin Zhou, Microsoft Corporation                                   */
90 /*                                                                        */
91 /*  DESCRIPTION                                                           */
92 /*                                                                        */
93 /*    This function performs error checking on the create NAT service.    */
94 /*                                                                        */
95 /*  INPUT                                                                 */
96 /*                                                                        */
97 /*    nat_ptr                           Pointer to NAT instance           */
98 /*    ip_ptr                            Pointer to NAT IP instance        */
99 /*    global_interface_index            Index of global interface         */
100 /*    dynamic_cache_memory              Pointer to dynamic entry cache    */
101 /*    dynamic_cache_size                The size of dynamic entry cache   */
102 /*                                                                        */
103 /*  OUTPUT                                                                */
104 /*                                                                        */
105 /*    NX_PTR_ERROR                       Invalid pointer parameter        */
106 /*    NX_NAT_PARAM_ERROR                 Invalid non pointer input        */
107 /*    status                             Actual completion status         */
108 /*                                                                        */
109 /*  CALLS                                                                 */
110 /*                                                                        */
111 /*    _nx_nat_create                    Creates the NAT instance service  */
112 /*                                                                        */
113 /*  CALLED BY                                                             */
114 /*                                                                        */
115 /*    Application Code                                                    */
116 /*                                                                        */
117 /*  RELEASE HISTORY                                                       */
118 /*                                                                        */
119 /*    DATE              NAME                      DESCRIPTION             */
120 /*                                                                        */
121 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
122 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
123 /*                                            resulting in version 6.1    */
124 /*                                                                        */
125 /**************************************************************************/
_nxe_nat_create(NX_NAT_DEVICE * nat_ptr,NX_IP * ip_ptr,UINT global_interface_index,VOID * dynamic_cache_memory,UINT dynamic_cache_size)126 UINT  _nxe_nat_create(NX_NAT_DEVICE *nat_ptr, NX_IP *ip_ptr, UINT global_interface_index, VOID *dynamic_cache_memory, UINT dynamic_cache_size)
127 {
128 
129 UINT status;
130 
131 
132     /* Check for valid input pointers. */
133     if ((!nat_ptr) || (!ip_ptr))
134     {
135 
136        /* Return pointer error. */
137        return(NX_PTR_ERROR);
138     }
139 
140     /* Check for invalid non pointer input.  */
141     if (ip_ptr -> nx_ip_id != NX_IP_ID)
142     {
143 
144         /* Return pointer error. */
145         return(NX_NAT_PARAM_ERROR);
146     }
147 
148     /* Check the interface index.  */
149     if (global_interface_index >= NX_MAX_PHYSICAL_INTERFACES)
150     {
151 
152         /* Return pointer error. */
153         return(NX_NAT_PARAM_ERROR);
154     }
155 
156     /* Make sure entry cache is 4-byte aligned. */
157     if ((((UINT)dynamic_cache_memory & 0x3) != 0) ||
158         ((dynamic_cache_size & 0x3) != 0))
159     {
160 
161         /* Return error status.  */
162         return(NX_NAT_CACHE_ERROR);
163     }
164 
165     /* Check the cache size.  */
166     if (dynamic_cache_size < (NX_NAT_MIN_ENTRY_COUNT * sizeof (NX_NAT_TRANSLATION_ENTRY)))
167     {
168 
169         /* Return error status.  */
170         return(NX_NAT_CACHE_ERROR);
171     }
172 
173     /* Call the actual NAT create service.  */
174     status = _nx_nat_create(nat_ptr, ip_ptr, global_interface_index, dynamic_cache_memory, dynamic_cache_size);
175 
176     /* Return completion status. */
177     return(status);
178 }
179 
180 
181 /**************************************************************************/
182 /*                                                                        */
183 /*  FUNCTION                                               RELEASE        */
184 /*                                                                        */
185 /*    _nx_nat_create                                      PORTABLE C      */
186 /*                                                           6.1          */
187 /*  AUTHOR                                                                */
188 /*                                                                        */
189 /*    Yuxin Zhou, Microsoft Corporation                                   */
190 /*                                                                        */
191 /*  DESCRIPTION                                                           */
192 /*                                                                        */
193 /*   This function creates the NetX NAT instance and various NAT          */
194 /*   configuration options, it also creates the NAT mutex.                */
195 /*                                                                        */
196 /*  INPUT                                                                 */
197 /*                                                                        */
198 /*    nat_ptr                           Pointer to NAT instance           */
199 /*    ip_ptr                            Pointer to NAT IP instance        */
200 /*    global_interface_index            Index of global interface         */
201 /*    dynamic_cache_memory              Pointer to dynamic entry cache    */
202 /*    dynamic_cache_size                The size of dynamic entry cache   */
203 /*                                                                        */
204 /*  OUTPUT                                                                */
205 /*                                                                        */
206 /*    status                             Actual completion status         */
207 /*    NX_SUCCESS                         Successful completion            */
208 /*    NX_NAT_OVERLAPPING_SUBNET_ERROR    Invalid NAT network interfaces   */
209 /*                                                                        */
210 /*  CALLS                                                                 */
211 /*                                                                        */
212 /*    tx_mutex_create                    Create NAT flag group mutex      */
213 /*    memset                             Clear specified area of memory   */
214 /*                                                                        */
215 /*  CALLED BY                                                             */
216 /*                                                                        */
217 /*    Application code                                                    */
218 /*                                                                        */
219 /*  RELEASE HISTORY                                                       */
220 /*                                                                        */
221 /*    DATE              NAME                      DESCRIPTION             */
222 /*                                                                        */
223 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
224 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
225 /*                                            resulting in version 6.1    */
226 /*                                                                        */
227 /**************************************************************************/
_nx_nat_create(NX_NAT_DEVICE * nat_ptr,NX_IP * ip_ptr,UINT global_interface_index,VOID * dynamic_cache_memory,UINT dynamic_cache_size)228 UINT  _nx_nat_create(NX_NAT_DEVICE *nat_ptr, NX_IP *ip_ptr, UINT global_interface_index, VOID *dynamic_cache_memory, UINT dynamic_cache_size)
229 {
230 
231 UINT                          i;
232 UINT                          dynamic_entries;
233 NX_NAT_TRANSLATION_ENTRY      *entry_ptr;
234 
235 
236     /* First clear memory for setting up the NAT server instance.  */
237     memset(nat_ptr, 0, sizeof(NX_NAT_DEVICE));
238 
239     /* Bind the IP instance and related parameters. */
240     nat_ptr -> nx_nat_ip_ptr = ip_ptr;
241     nat_ptr -> nx_nat_global_interface_index = (UCHAR)global_interface_index;
242 
243     /* Clear the entry cache.  */
244     memset((void *) dynamic_cache_memory, 0, dynamic_cache_size);
245 
246     /* Pickup starting address of the available entry list.  */
247     entry_ptr = (NX_NAT_TRANSLATION_ENTRY *) dynamic_cache_memory;
248 
249     /* Determine how many NAT daynamic entries will fit in this cache area.  */
250     dynamic_entries = dynamic_cache_size / sizeof(NX_NAT_TRANSLATION_ENTRY);
251 
252     /* Initialize the pointers of available NAT entries.  */
253     for (i = 0; i < (dynamic_entries - 1); i++)
254     {
255         /* Setup each entry to point to the next entry.  */
256         entry_ptr -> next_entry_ptr = entry_ptr + 1;
257         entry_ptr ++;
258     }
259 
260     /* Setup the head pointers of the available and dynamic (active) lists in the NAT Device.  */
261     nat_ptr -> nx_nat_dynamic_available_entry_head = (NX_NAT_TRANSLATION_ENTRY *) dynamic_cache_memory;
262     nat_ptr -> nx_nat_dynamic_active_entry_head = NX_NULL;
263     nat_ptr -> nx_nat_dynamic_available_entries = dynamic_entries;
264     nat_ptr -> nx_nat_dynamic_active_entries = 0;
265     nat_ptr -> nx_nat_static_active_entries = 0;
266 
267     /* Load the NAT ID field in the NAT control block.  */
268     nat_ptr -> nx_nat_id =  NX_NAT_ID;
269 
270     /* Define a global NAT pointer. NetX forwards all packets to _nx_nat_process_packet if _nx_ip_packet_forward() is defined as such.
271        The latter service can only send the current NX_IP and NX_PACKET pointer, so _nx_nat_process_packet()
272        requries this global pointer. */
273     /* Set the pointer of global variable NAT.  */
274     nat_server_ptr = nat_ptr;
275 
276     /* Return successful completion. */
277     return NX_SUCCESS;
278 }
279 
280 
281 /**************************************************************************/
282 /*                                                                        */
283 /*  FUNCTION                                               RELEASE        */
284 /*                                                                        */
285 /*    _nxe_nat_delete                                     PORTABLE C      */
286 /*                                                           6.1          */
287 /*  AUTHOR                                                                */
288 /*                                                                        */
289 /*    Yuxin Zhou, Microsoft Corporation                                   */
290 /*                                                                        */
291 /*  DESCRIPTION                                                           */
292 /*                                                                        */
293 /*    This function performs error checking on the delete NAT service.    */
294 /*                                                                        */
295 /*  INPUT                                                                 */
296 /*                                                                        */
297 /*    nat_ptr                           Pointer to NAT instance           */
298 /*                                                                        */
299 /*  OUTPUT                                                                */
300 /*                                                                        */
301 /*    NX_PTR_ERROR                      Invalid pointer parameter         */
302 /*    status                            Actual completion status          */
303 /*                                                                        */
304 /*  CALLS                                                                 */
305 /*                                                                        */
306 /*    _nx_nat_delete                    Deletes a NAT instance            */
307 /*                                                                        */
308 /*  CALLED BY                                                             */
309 /*                                                                        */
310 /*    Application Code                                                    */
311 /*                                                                        */
312 /*  RELEASE HISTORY                                                       */
313 /*                                                                        */
314 /*    DATE              NAME                      DESCRIPTION             */
315 /*                                                                        */
316 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
317 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
318 /*                                            resulting in version 6.1    */
319 /*                                                                        */
320 /**************************************************************************/
_nxe_nat_delete(NX_NAT_DEVICE * nat_ptr)321 UINT  _nxe_nat_delete(NX_NAT_DEVICE *nat_ptr)
322 {
323 
324 UINT status;
325 
326 
327     /* Check for invalid input pointers.  */
328     if ((nat_ptr == NX_NULL) || (nat_ptr -> nx_nat_id != NX_NAT_ID))
329         return(NX_PTR_ERROR);
330 
331     /* Check for appropriate caller.  */
332     NX_THREADS_ONLY_CALLER_CHECKING
333 
334     /* Call the actual NAT delete service.  */
335     status = _nx_nat_delete(nat_ptr);
336 
337     /* Return completion status. */
338     return(status);
339 }
340 
341 
342 /**************************************************************************/
343 /*                                                                        */
344 /*  FUNCTION                                               RELEASE        */
345 /*                                                                        */
346 /*    _nx_nat_delete                                      PORTABLE C      */
347 /*                                                           6.1          */
348 /*  AUTHOR                                                                */
349 /*                                                                        */
350 /*    Yuxin Zhou, Microsoft Corporation                                   */
351 /*                                                                        */
352 /*  DESCRIPTION                                                           */
353 /*                                                                        */
354 /*   This function deletes the specified NetX NAT instance.               */
355 /*                                                                        */
356 /*  INPUT                                                                 */
357 /*                                                                        */
358 /*    nat_ptr                           Pointer to NAT server to delete   */
359 /*                                                                        */
360 /*  OUTPUT                                                                */
361 /*                                                                        */
362 /*    status                            Actual completion status          */
363 /*                                                                        */
364 /*  CALLS                                                                 */
365 /*                                                                        */
366 /*    tx_mutex_delete                   Delete NAT mutex                  */
367 /*                                                                        */
368 /*  CALLED BY                                                             */
369 /*                                                                        */
370 /*    Application code                                                    */
371 /*                                                                        */
372 /*  RELEASE HISTORY                                                       */
373 /*                                                                        */
374 /*    DATE              NAME                      DESCRIPTION             */
375 /*                                                                        */
376 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
377 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
378 /*                                            resulting in version 6.1    */
379 /*                                                                        */
380 /**************************************************************************/
_nx_nat_delete(NX_NAT_DEVICE * nat_ptr)381 UINT  _nx_nat_delete(NX_NAT_DEVICE *nat_ptr)
382 {
383 
384     /* Clear the NAT ID to make it invalid.  */
385     nat_ptr -> nx_nat_id =  0;
386 
387     return NX_SUCCESS;
388 }
389 
390 
391 /**************************************************************************/
392 /*                                                                        */
393 /*  FUNCTION                                               RELEASE        */
394 /*                                                                        */
395 /*    _nxe_nat_enable                                     PORTABLE C      */
396 /*                                                           6.1          */
397 /*  AUTHOR                                                                */
398 /*                                                                        */
399 /*    Yuxin Zhou, Microsoft Corporation                                   */
400 /*                                                                        */
401 /*  DESCRIPTION                                                           */
402 /*                                                                        */
403 /*   This function performs error checking on the resume NAT thread       */
404 /*   service.                                                             */
405 /*                                                                        */
406 /*  INPUT                                                                 */
407 /*                                                                        */
408 /*    ip_ptr                          Pointer to IP instance              */
409 /*                                                                        */
410 /*  OUTPUT                                                                */
411 /*                                                                        */
412 /*    status                          Actual completion status            */
413 /*    NX_PTR_ERROR                    Invalid pointer parameter           */
414 /*                                                                        */
415 /*  CALLS                                                                 */
416 /*                                                                        */
417 /*    _nx_nat_enable                  Actual enable NAT server            */
418 /*                                                                        */
419 /*  CALLED BY                                                             */
420 /*                                                                        */
421 /*    Application code                                                    */
422 /*                                                                        */
423 /*  RELEASE HISTORY                                                       */
424 /*                                                                        */
425 /*    DATE              NAME                      DESCRIPTION             */
426 /*                                                                        */
427 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
428 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
429 /*                                            resulting in version 6.1    */
430 /*                                                                        */
431 /**************************************************************************/
_nxe_nat_enable(NX_NAT_DEVICE * nat_ptr)432 UINT  _nxe_nat_enable(NX_NAT_DEVICE *nat_ptr)
433 {
434 
435 UINT status;
436 
437     /* Check for invalid input pointers.  */
438     if ((nat_ptr == NX_NULL) || (nat_ptr -> nx_nat_id != NX_NAT_ID))
439         return(NX_PTR_ERROR);
440 
441     /* Call the actual service. */
442     status = _nx_nat_enable(nat_ptr);
443 
444     /* Return completion status. */
445     return status;
446 }
447 
448 
449 /**************************************************************************/
450 /*                                                                        */
451 /*  FUNCTION                                               RELEASE        */
452 /*                                                                        */
453 /*    _nx_nat_enable                                      PORTABLE C      */
454 /*                                                           6.1          */
455 /*  AUTHOR                                                                */
456 /*                                                                        */
457 /*    Yuxin Zhou, Microsoft Corporation                                   */
458 /*                                                                        */
459 /*  DESCRIPTION                                                           */
460 /*                                                                        */
461 /*   This function enables the NAT server.                                */
462 /*                                                                        */
463 /*  INPUT                                                                 */
464 /*                                                                        */
465 /*    nat_ptr                         Pointer to NAT server to resume     */
466 /*                                                                        */
467 /*  OUTPUT                                                                */
468 /*                                                                        */
469 /*    NX_SUCCESS                      Successful completion status        */
470 /*                                                                        */
471 /*  CALLS                                                                 */
472 /*                                                                        */
473 /*    tx_mutex_get                    Get IP mutex                        */
474 /*    tx_mutex_put                    Put IP mutex                        */
475 /*                                                                        */
476 /*  CALLED BY                                                             */
477 /*                                                                        */
478 /*    Application code                                                    */
479 /*                                                                        */
480 /*  RELEASE HISTORY                                                       */
481 /*                                                                        */
482 /*    DATE              NAME                      DESCRIPTION             */
483 /*                                                                        */
484 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
485 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
486 /*                                            resulting in version 6.1    */
487 /*                                                                        */
488 /**************************************************************************/
_nx_nat_enable(NX_NAT_DEVICE * nat_ptr)489 UINT  _nx_nat_enable(NX_NAT_DEVICE *nat_ptr)
490 {
491 
492 
493     /* Get the IP mutex.  */
494     tx_mutex_get(&(nat_ptr -> nx_nat_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
495 
496     /* Setup the IP nat processing routine pointer for NAT services.  */
497     nat_ptr -> nx_nat_ip_ptr -> nx_ip_nat_packet_process =  _nx_nat_process_packet;
498 
499     /* Setup the IP nat free port check for NAT services.  */
500     nat_ptr -> nx_nat_ip_ptr -> nx_ip_nat_port_verify =  _nx_nat_entry_port_verify;
501 
502     /* Release the IP mutex.  */
503     tx_mutex_put(&(nat_ptr ->  nx_nat_ip_ptr -> nx_ip_protection));
504 
505     /* Return successful completion.  */
506     return(NX_SUCCESS);
507 }
508 
509 
510 /**************************************************************************/
511 /*                                                                        */
512 /*  FUNCTION                                               RELEASE        */
513 /*                                                                        */
514 /*    _nxe_nat_disable                                    PORTABLE C      */
515 /*                                                           6.1          */
516 /*  AUTHOR                                                                */
517 /*                                                                        */
518 /*    Yuxin Zhou, Microsoft Corporation                                   */
519 /*                                                                        */
520 /*  DESCRIPTION                                                           */
521 /*                                                                        */
522 /*   This function performs error checking on the disable NAT service.    */
523 /*  INPUT                                                                 */
524 /*                                                                        */
525 /*    nat_ptr                         Pointer to NAT instance             */
526 /*                                                                        */
527 /*  OUTPUT                                                                */
528 /*                                                                        */
529 /*    status                          Actual completion status            */
530 /*    NX_PTR_ERROR                    Invalid pointer parameter           */
531 /*                                                                        */
532 /*  CALLS                                                                 */
533 /*                                                                        */
534 /*    _nx_nat_enable                  Actual enable NAT server            */
535 /*                                                                        */
536 /*  CALLED BY                                                             */
537 /*                                                                        */
538 /*    Application code                                                    */
539 /*                                                                        */
540 /*  RELEASE HISTORY                                                       */
541 /*                                                                        */
542 /*    DATE              NAME                      DESCRIPTION             */
543 /*                                                                        */
544 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
545 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
546 /*                                            resulting in version 6.1    */
547 /*                                                                        */
548 /**************************************************************************/
_nxe_nat_disable(NX_NAT_DEVICE * nat_ptr)549 UINT  _nxe_nat_disable(NX_NAT_DEVICE *nat_ptr)
550 {
551 
552 UINT status;
553 
554 
555     /* Check for invalid input pointers.  */
556     if ((nat_ptr == NX_NULL) || (nat_ptr -> nx_nat_id != NX_NAT_ID))
557         return(NX_PTR_ERROR);
558 
559     /* Call the actual service. */
560     status = _nx_nat_disable(nat_ptr);
561 
562     /* Return completion status. */
563     return status;
564 }
565 
566 
567 /**************************************************************************/
568 /*                                                                        */
569 /*  FUNCTION                                               RELEASE        */
570 /*                                                                        */
571 /*    _nx_nat_disable                                     PORTABLE C      */
572 /*                                                           6.1          */
573 /*  AUTHOR                                                                */
574 /*                                                                        */
575 /*    Yuxin Zhou, Microsoft Corporation                                   */
576 /*                                                                        */
577 /*  DESCRIPTION                                                           */
578 /*                                                                        */
579 /*   This function disables the NAT server.                               */
580 /*                                                                        */
581 /*  INPUT                                                                 */
582 /*                                                                        */
583 /*    nat_ptr                         Pointer to NAT server to resume     */
584 /*                                                                        */
585 /*  OUTPUT                                                                */
586 /*                                                                        */
587 /*    NX_SUCCESS                      Successful completion status        */
588 /*                                                                        */
589 /*  CALLS                                                                 */
590 /*                                                                        */
591 /*    tx_mutex_get                    Get IP mutex                        */
592 /*    tx_mutex_put                    Put IP mutex                        */
593 /*                                                                        */
594 /*  CALLED BY                                                             */
595 /*                                                                        */
596 /*    Application code                                                    */
597 /*                                                                        */
598 /*  RELEASE HISTORY                                                       */
599 /*                                                                        */
600 /*    DATE              NAME                      DESCRIPTION             */
601 /*                                                                        */
602 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
603 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
604 /*                                            resulting in version 6.1    */
605 /*                                                                        */
606 /**************************************************************************/
_nx_nat_disable(NX_NAT_DEVICE * nat_ptr)607 UINT  _nx_nat_disable(NX_NAT_DEVICE *nat_ptr)
608 {
609 
610     /* Get the IP mutex.  */
611     tx_mutex_get(&(nat_ptr -> nx_nat_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
612 
613     /* Clear the IP nat processing routine pointer.  */
614     nat_ptr -> nx_nat_ip_ptr -> nx_ip_nat_packet_process = NX_NULL;
615 
616     /* Release the IP mutex.  */
617     tx_mutex_put(&(nat_ptr ->  nx_nat_ip_ptr -> nx_ip_protection));
618 
619     /* Return successful completion.  */
620     return(NX_SUCCESS);
621 }
622 
623 
624 /**************************************************************************/
625 /*                                                                        */
626 /*  FUNCTION                                               RELEASE        */
627 /*                                                                        */
628 /*    _nxe_nat_cache_notify_set                           PORTABLE C      */
629 /*                                                           6.1          */
630 /*  AUTHOR                                                                */
631 /*                                                                        */
632 /*    Yuxin Zhou, Microsoft Corporation                                   */
633 /*                                                                        */
634 /*  DESCRIPTION                                                           */
635 /*                                                                        */
636 /*    This function checks for errors in the NAT cache full notify        */
637 /*    function call.                                                      */
638 /*                                                                        */
639 /*  INPUT                                                                 */
640 /*                                                                        */
641 /*    nat_ptr                           Pointer to NAT instance           */
642 /*    cache_full_notify                 Cache full notify function        */
643 /*                                                                        */
644 /*  OUTPUT                                                                */
645 /*                                                                        */
646 /*    status                                Completion status             */
647 /*                                                                        */
648 /*  CALLS                                                                 */
649 /*                                                                        */
650 /*    _nx_nat_cache_notify_set          Actual cache notify set  function */
651 /*                                                                        */
652 /*  CALLED BY                                                             */
653 /*                                                                        */
654 /*    Application Code                                                    */
655 /*                                                                        */
656 /*  RELEASE HISTORY                                                       */
657 /*                                                                        */
658 /*    DATE              NAME                      DESCRIPTION             */
659 /*                                                                        */
660 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
661 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
662 /*                                            resulting in version 6.1    */
663 /*                                                                        */
664 /**************************************************************************/
_nxe_nat_cache_notify_set(NX_NAT_DEVICE * nat_ptr,VOID (* cache_full_notify_cb)(NX_NAT_DEVICE * nat_ptr))665 UINT _nxe_nat_cache_notify_set(NX_NAT_DEVICE *nat_ptr, VOID (*cache_full_notify_cb)(NX_NAT_DEVICE *nat_ptr))
666 {
667 
668 UINT    status;
669 
670 
671     /* Check for invalid input pointers.  */
672     if (!nat_ptr)
673     {
674         return(NX_PTR_ERROR);
675     }
676 
677     /* Check for invalid non pointer input. */
678     if (nat_ptr -> nx_nat_id != NX_NAT_ID)
679     {
680         return(NX_NAT_PARAM_ERROR);
681     }
682 
683     /* Call actual NAT cache notify set function.  */
684     status =  _nx_nat_cache_notify_set(nat_ptr, cache_full_notify_cb);
685 
686     /* Return status.  */
687     return(status);
688 }
689 
690 
691 /**************************************************************************/
692 /*                                                                        */
693 /*  FUNCTION                                               RELEASE        */
694 /*                                                                        */
695 /*    _nx_nat_cache_notify_set                            PORTABLE C      */
696 /*                                                           6.1          */
697 /*  AUTHOR                                                                */
698 /*                                                                        */
699 /*    Yuxin Zhou, Microsoft Corporation                                   */
700 /*                                                                        */
701 /*  DESCRIPTION                                                           */
702 /*                                                                        */
703 /*    This function set the cache full notify function.                   */
704 /*                                                                        */
705 /*  INPUT                                                                 */
706 /*                                                                        */
707 /*    nat_ptr                           Pointer to nat instance           */
708 /*    cache_full_notify                 Cache full notify function        */
709 /*                                                                        */
710 /*  OUTPUT                                                                */
711 /*                                                                        */
712 /*    status                                Completion status             */
713 /*                                                                        */
714 /*  CALLS                                                                 */
715 /*                                                                        */
716 /*    tx_mutex_get                      Get IP mutex                      */
717 /*    tx_mutex_put                      Put IP mutex                      */
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 /**************************************************************************/
_nx_nat_cache_notify_set(NX_NAT_DEVICE * nat_ptr,VOID (* cache_full_notify_cb)(NX_NAT_DEVICE * nat_ptr))732 UINT _nx_nat_cache_notify_set(NX_NAT_DEVICE *nat_ptr, VOID (*cache_full_notify_cb)(NX_NAT_DEVICE *nat_ptr))
733 {
734 
735 
736     /* Get the IP mutex.  */
737     tx_mutex_get(&(nat_ptr -> nx_nat_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
738 
739     /* Set the cache notify.  */
740     nat_ptr -> nx_nat_cache_full_notify = cache_full_notify_cb;
741 
742     /* Release the IP mutex.  */
743     tx_mutex_put(&(nat_ptr ->  nx_nat_ip_ptr -> nx_ip_protection));
744 
745     return(NX_SUCCESS);
746 }
747 
748 /**************************************************************************/
749 /*                                                                        */
750 /*  FUNCTION                                               RELEASE        */
751 /*                                                                        */
752 /*    _nxe_nat_inbound_entry_create                       PORTABLE C      */
753 /*                                                           6.1          */
754 /*  AUTHOR                                                                */
755 /*                                                                        */
756 /*    Yuxin Zhou, Microsoft Corporation                                   */
757 /*                                                                        */
758 /*  DESCRIPTION                                                           */
759 /*                                                                        */
760 /*   This function performs error checking on the create NAT translation  */
761 /*   inbound entry service.                                               */
762 /*                                                                        */
763 /*  INPUT                                                                 */
764 /*                                                                        */
765 /*    nat_ptr                           Pointer to NAT instance           */
766 /*    entry_ptr                         Pointer to entry to add to table  */
767 /*    local_ip_address                  Entry local IP address            */
768 /*    external_port                     Entry external port               */
769 /*    local_port                        Entry local port                  */
770 /*    protocol                          Entry network protocol            */
771 /*                                                                        */
772 /*  OUTPUT                                                                */
773 /*                                                                        */
774 /*    NX_PTR_ERROR                       Invalid pointer parameter        */
775 /*    NX_NAT_PARAM_ERROR                 Invalid non pointer parameter    */
776 /*    status                             Actual completion status         */
777 /*                                                                        */
778 /*  CALLS                                                                 */
779 /*                                                                        */
780 /*    _nx_nat_inbound_entry_create     Calls actual create entry service  */
781 /*                                                                        */
782 /*  CALLED BY                                                             */
783 /*                                                                        */
784 /*    Application code                                                    */
785 /*                                                                        */
786 /*  RELEASE HISTORY                                                       */
787 /*                                                                        */
788 /*    DATE              NAME                      DESCRIPTION             */
789 /*                                                                        */
790 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
791 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
792 /*                                            resulting in version 6.1    */
793 /*                                                                        */
794 /**************************************************************************/
_nxe_nat_inbound_entry_create(NX_NAT_DEVICE * nat_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr,ULONG local_ip_address,USHORT external_port,USHORT local_port,UCHAR protocol)795 UINT  _nxe_nat_inbound_entry_create(NX_NAT_DEVICE *nat_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr,
796                                     ULONG local_ip_address, USHORT external_port, USHORT local_port, UCHAR protocol)
797 {
798 
799 UINT  status;
800 
801 
802     /* Check for invalid input pointers.  */
803     if ((nat_ptr == NX_NULL) || (nat_ptr -> nx_nat_id != NX_NAT_ID) || (!entry_ptr))
804     {
805         return (NX_PTR_ERROR);
806     }
807 
808     /* Check for invalid non pointer input. */
809     if ((!local_ip_address) || (!protocol))
810     {
811 
812         /* Return ptr error. */
813         return (NX_NAT_PARAM_ERROR);
814     }
815 
816     /* Call the actual service. */
817     status = _nx_nat_inbound_entry_create(nat_ptr, entry_ptr, local_ip_address, external_port, local_port, protocol);
818 
819     /* Return completion status. */
820     return status;
821 }
822 
823 
824 /**************************************************************************/
825 /*                                                                        */
826 /*  FUNCTION                                               RELEASE        */
827 /*                                                                        */
828 /*    _nx_nat_inbound_entry_create                        PORTABLE C      */
829 /*                                                           6.1          */
830 /*  AUTHOR                                                                */
831 /*                                                                        */
832 /*    Yuxin Zhou, Microsoft Corporation                                   */
833 /*                                                                        */
834 /*  DESCRIPTION                                                           */
835 /*                                                                        */
836 /*   This function creates a inbound NAT translation entry and adds it to */
837 /*   the NAT entry list. This is allows an  external host to initiate     */
838 /*   a session with a private host (typically a server).                  */
839 /*                                                                        */
840 /*   This entry can never expire. To remove the entry, use the            */
841 /*   nx_nat_inbound_entry_delete() service.                               */
842 /*                                                                        */
843 /*  INPUT                                                                 */
844 /*                                                                        */
845 /*    nat_ptr                           Pointer to NAT instance           */
846 /*    entry_ptr                         Pointer to entry to add to table  */
847 /*    local_ip_address                  Entry local IP address            */
848 /*    external_port                     Entry external port               */
849 /*    local_port                        Entry local port                  */
850 /*    protocol                          Table entry network protocol      */
851 /*                                                                        */
852 /*  OUTPUT                                                                */
853 /*                                                                        */
854 /*    NX_SUCCESS                         Successful completion status     */
855 /*                                                                        */
856 /*  CALLS                                                                 */
857 /*                                                                        */
858 /*    tx_mutex_get                      Get IP mutex                      */
859 /*    tx_mutex_put                      Put IP mutex                      */
860 /*    _nx_nat_entry_add                 Add entry to table linked list    */
861 /*    memset                            Clear specified area of memory    */
862 /*                                                                        */
863 /*  CALLED BY                                                             */
864 /*                                                                        */
865 /*    Application code                                                    */
866 /*                                                                        */
867 /*  RELEASE HISTORY                                                       */
868 /*                                                                        */
869 /*    DATE              NAME                      DESCRIPTION             */
870 /*                                                                        */
871 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
872 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
873 /*                                            resulting in version 6.1    */
874 /*                                                                        */
875 /**************************************************************************/
_nx_nat_inbound_entry_create(NX_NAT_DEVICE * nat_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr,ULONG local_ip_address,USHORT external_port,USHORT local_port,UCHAR protocol)876 UINT  _nx_nat_inbound_entry_create(NX_NAT_DEVICE *nat_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr,
877                                    ULONG local_ip_address, USHORT external_port, USHORT local_port, UCHAR protocol)
878 {
879 
880 UINT                     bound;
881 
882     /* Get the IP mutex.  */
883     tx_mutex_get(&(nat_ptr -> nx_nat_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
884 
885     /* Check whether this port has been used by NAT entry.  */
886     bound = _nx_nat_entry_port_verify(nat_ptr -> nx_nat_ip_ptr, protocol, external_port);
887 
888     /* Check the status.  */
889     if (bound == NX_TRUE)
890     {
891 
892         /* Release the IP mutex.  */
893         tx_mutex_put(&(nat_ptr ->  nx_nat_ip_ptr -> nx_ip_protection));
894 
895         /* Return error status.  */
896         return(NX_NAT_PORT_UNAVAILABLE);
897     }
898 
899     /* Check whether this port has been used by NetXDuo socket.  */
900     bound = _nx_nat_socket_port_verify(nat_ptr -> nx_nat_ip_ptr, protocol, external_port);
901 
902     /* Check the status.  */
903     if (bound == NX_TRUE)
904     {
905 
906         /* Release the IP mutex.  */
907         tx_mutex_put(&(nat_ptr ->  nx_nat_ip_ptr -> nx_ip_protection));
908 
909         /* Return error status.  */
910         return(NX_NAT_PORT_UNAVAILABLE);
911     }
912 
913     /* Initialize the entry to NULL. */
914     memset(entry_ptr, 0, sizeof(NX_NAT_TRANSLATION_ENTRY));
915 
916     /* Assign the entry attributes. */
917     entry_ptr -> local_ip_address = local_ip_address;
918     entry_ptr -> external_port = external_port;
919     entry_ptr -> local_port = local_port;
920     entry_ptr -> protocol = protocol;
921 
922     /* Set the transaction type. */
923     entry_ptr -> translation_type = NX_NAT_STATIC_ENTRY;
924 
925     /* Add the entry to the table. */
926     _nx_nat_entry_add(nat_ptr, entry_ptr);
927 
928     /* Release the IP mutex.  */
929     tx_mutex_put(&(nat_ptr ->  nx_nat_ip_ptr -> nx_ip_protection));
930 
931     /* Return successful completion status. */
932     return NX_SUCCESS;
933 }
934 
935 
936 /**************************************************************************/
937 /*                                                                        */
938 /*  FUNCTION                                               RELEASE        */
939 /*                                                                        */
940 /*    _nxe_nat_inbound_entry_delete                       PORTABLE C      */
941 /*                                                           6.1          */
942 /*  AUTHOR                                                                */
943 /*                                                                        */
944 /*    Yuxin Zhou, Microsoft Corporation                                   */
945 /*                                                                        */
946 /*  DESCRIPTION                                                           */
947 /*                                                                        */
948 /*   This function performs error checking on the delete NAT translation  */
949 /*   inbound entry service.                                               */
950 /*                                                                        */
951 /*  INPUT                                                                 */
952 /*                                                                        */
953 /*    nat_ptr                           Pointer to NAT instance           */
954 /*    remove_entry_ptr                  Pointer to NAT translation entry  */
955 /*                                                                        */
956 /*  OUTPUT                                                                */
957 /*                                                                        */
958 /*    status                             Actual completion status         */
959 /*    NX_PTR_ERROR                       Invalid pointer parameter        */
960 /*                                                                        */
961 /*  CALLS                                                                 */
962 /*                                                                        */
963 /*    _nx_nat_inbound_entry_delete      Actual table entry delete service */
964 /*                                                                        */
965 /*  CALLED BY                                                             */
966 /*                                                                        */
967 /*    Application code                                                    */
968 /*                                                                        */
969 /*  RELEASE HISTORY                                                       */
970 /*                                                                        */
971 /*    DATE              NAME                      DESCRIPTION             */
972 /*                                                                        */
973 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
974 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
975 /*                                            resulting in version 6.1    */
976 /*                                                                        */
977 /**************************************************************************/
_nxe_nat_inbound_entry_delete(NX_NAT_DEVICE * nat_ptr,NX_NAT_TRANSLATION_ENTRY * delete_entry_ptr)978 UINT  _nxe_nat_inbound_entry_delete( NX_NAT_DEVICE *nat_ptr, NX_NAT_TRANSLATION_ENTRY *delete_entry_ptr)
979 {
980 
981 UINT status;
982 
983     /* Check for invalid input pointers.  */
984     if ((nat_ptr == NX_NULL) || (nat_ptr -> nx_nat_id != NX_NAT_ID) || (delete_entry_ptr == NX_NULL))
985     {
986 
987         return(NX_PTR_ERROR);
988     }
989 
990     /* Check the entry tranlation type.  */
991     if (delete_entry_ptr ->translation_type != NX_NAT_STATIC_ENTRY)
992     {
993         return(NX_NAT_ENTRY_TYPE_ERROR);
994     }
995 
996     /* Check if this function is called from the appropriate thread.  */
997     NX_THREADS_ONLY_CALLER_CHECKING
998 
999     /* Call the actual NAT entry delete service.  */
1000     status = _nx_nat_inbound_entry_delete(nat_ptr, delete_entry_ptr);
1001 
1002     /* Return completion status. */
1003     return(status);
1004 }
1005 
1006 
1007 /**************************************************************************/
1008 /*                                                                        */
1009 /*  FUNCTION                                               RELEASE        */
1010 /*                                                                        */
1011 /*    _nx_nat_inbound_entry_delete                        PORTABLE C      */
1012 /*                                                           6.1          */
1013 /*  AUTHOR                                                                */
1014 /*                                                                        */
1015 /*    Yuxin Zhou, Microsoft Corporation                                   */
1016 /*                                                                        */
1017 /*  DESCRIPTION                                                           */
1018 /*                                                                        */
1019 /*   This function deletes the specified static entry from the NAT        */
1020 /*   translation list.                                                    */
1021 /*                                                                        */
1022 /*  INPUT                                                                 */
1023 /*                                                                        */
1024 /*    nat_ptr                           Pointer to NAT instance           */
1025 /*    remove_entry_ptr                  Pointer to NAT translation entry  */
1026 /*                                                                        */
1027 /*  OUTPUT                                                                */
1028 /*                                                                        */
1029 /*    status                            Actual completion status          */
1030 /*                                                                        */
1031 /*  CALLS                                                                 */
1032 /*                                                                        */
1033 /*    memset                            Clear specified area of memory    */
1034 /*                                                                        */
1035 /*  CALLED BY                                                             */
1036 /*                                                                        */
1037 /*    Application code                                                    */
1038 /*                                                                        */
1039 /*  RELEASE HISTORY                                                       */
1040 /*                                                                        */
1041 /*    DATE              NAME                      DESCRIPTION             */
1042 /*                                                                        */
1043 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1044 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1045 /*                                            resulting in version 6.1    */
1046 /*                                                                        */
1047 /**************************************************************************/
_nx_nat_inbound_entry_delete(NX_NAT_DEVICE * nat_ptr,NX_NAT_TRANSLATION_ENTRY * delete_entry_ptr)1048 UINT  _nx_nat_inbound_entry_delete(NX_NAT_DEVICE *nat_ptr, NX_NAT_TRANSLATION_ENTRY *delete_entry_ptr)
1049 {
1050 
1051 NX_NAT_TRANSLATION_ENTRY *entry_ptr;
1052 NX_NAT_TRANSLATION_ENTRY *previous_ptr;
1053 NX_NAT_TRANSLATION_ENTRY *next_entry_ptr;
1054 
1055 
1056     /* Get the IP mutex.  */
1057     tx_mutex_get(&(nat_ptr -> nx_nat_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
1058 
1059     /* Get a pointer to the start of the entries in the translation table. */
1060     entry_ptr = nat_ptr -> nx_nat_dynamic_active_entry_head;
1061 
1062     /* Initialize the previous pointer.  */
1063     previous_ptr = NX_NULL;
1064 
1065     /* We need to loop through the translation table again so we
1066        can remove the entry to delete and connect the previous and
1067        next entries around it. */
1068     while (entry_ptr)
1069     {
1070 
1071         /* Set a pointer to the next entry in the table. */
1072         next_entry_ptr = entry_ptr -> next_entry_ptr;
1073 
1074         /* Is this the entry we want to delete? */
1075         if (entry_ptr == delete_entry_ptr)
1076         {
1077 
1078             /* Yes; check if this is the first entry in the list). */
1079             if (previous_ptr)
1080             {
1081 
1082                 /* It is not, so link the previous entry around the entry we are deleting. */
1083                 previous_ptr -> next_entry_ptr = next_entry_ptr;
1084             }
1085             else
1086             {
1087 
1088                 /* It is the first entry, so set the next pointer as the starting translation table entry. */
1089                 nat_ptr -> nx_nat_dynamic_active_entry_head = next_entry_ptr;
1090             }
1091 
1092             /* Update the static active entry count.  */
1093             nat_ptr -> nx_nat_static_active_entries --;
1094 
1095             /* Release the IP mutex.  */
1096             tx_mutex_put(&(nat_ptr ->  nx_nat_ip_ptr -> nx_ip_protection));
1097 
1098             /* We're done here. */
1099             return NX_SUCCESS;
1100         }
1101 
1102         /* We didn't delete the current entry, so now it is the previous entry. */
1103         previous_ptr = entry_ptr;
1104 
1105         /* Get the next entry in the table. */
1106         entry_ptr = next_entry_ptr;
1107     }
1108 
1109     /* Release the IP mutex.  */
1110     tx_mutex_put(&(nat_ptr ->  nx_nat_ip_ptr -> nx_ip_protection));
1111 
1112     /* Return error status. */
1113     return (NX_NAT_ENTRY_NOT_FOUND);
1114 }
1115 
1116 
1117 /**************************************************************************/
1118 /*                                                                        */
1119 /*  FUNCTION                                               RELEASE        */
1120 /*                                                                        */
1121 /*    _nx_nat_process_packet                              PORTABLE C      */
1122 /*                                                           6.3.0        */
1123 /*  AUTHOR                                                                */
1124 /*                                                                        */
1125 /*    Yuxin Zhou, Microsoft Corporation                                   */
1126 /*                                                                        */
1127 /*  DESCRIPTION                                                           */
1128 /*                                                                        */
1129 /*   This function receives packets to forward from both public and       */
1130 /*   private networks on either side of NAT if IP forwarding is enabled   */
1131 /*   and this function is specified as the packet handler.  It determines */
1132 /*   packet direction (e.g. out to the public internet or inbound to a    */
1133 /*   host on the private network) and forwards it to the appropriate      */
1134 /*   handler.                                                             */
1135 /*                                                                        */
1136 /*  INPUT                                                                 */
1137 /*                                                                        */
1138 /*    ip_ptr                            Pointer to IP instance            */
1139 /*    packet_ptr                        Pointer to packet to forward      */
1140 /*    packet_process                    The flag for packet processing    */
1141 /*                                        NX_TRUE or NX_FALSE             */
1142 /*                                                                        */
1143 /*  OUTPUT                                                                */
1144 /*                                                                        */
1145 /*    NX_TRUE                          Packet is consumed by NAT          */
1146 /*    NX_FALSE                         Packet is not consumed by NAT      */
1147 /*                                                                        */
1148 /*  CALLS                                                                 */
1149 /*                                                                        */
1150 /*    nx_packet_release                Release the packet                 */
1151 /*    _nx_ip_route_find                Find the outgoing interface        */
1152 /*    _nx_nat_process_outbound_packet  Forward packet to public Internet  */
1153 /*    _nx_nat_process_inbound_packet   Forward packet to private host     */
1154 /*                                                                        */
1155 /*  CALLED BY                                                             */
1156 /*                                                                        */
1157 /*    _nx_ipv4_packet_receive          NetX forwards packet to NAT first  */
1158 /*                                        if forwarding is enabled.       */
1159 /*                                                                        */
1160 /*  RELEASE HISTORY                                                       */
1161 /*                                                                        */
1162 /*    DATE              NAME                      DESCRIPTION             */
1163 /*                                                                        */
1164 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1165 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1166 /*                                            resulting in version 6.1    */
1167 /*  10-31-2023     Tiejun Zhou              Modified comment(s),          */
1168 /*                                            fixed packet double release,*/
1169 /*                                            resulting in version 6.3.0  */
1170 /*                                                                        */
1171 /**************************************************************************/
_nx_nat_process_packet(NX_IP * ip_ptr,NX_PACKET * packet_ptr,UINT packet_process)1172 static UINT  _nx_nat_process_packet(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT packet_process)
1173 {
1174 
1175 UINT                            status;
1176 UINT                            protocol;
1177 ULONG                           header_size = sizeof(NX_IPV4_HEADER);
1178 UINT                            global_interface_index;
1179 ULONG                           next_hop_address;
1180 NX_IPV4_HEADER                  *ip_header_ptr;
1181 NX_INTERFACE                    *interface_ptr;
1182 
1183 
1184     /* Check the NAT's IP instance.  */
1185     if (nat_server_ptr -> nx_nat_ip_ptr != ip_ptr)
1186     {
1187 
1188         /* Let IP packet receive process this packet. */
1189         return (NX_FALSE);
1190     }
1191 
1192     /* Pickup the packet header.  */
1193     ip_header_ptr =  (NX_IPV4_HEADER *) packet_ptr -> nx_packet_prepend_ptr;
1194 
1195     /* Determine what protocol the current IP datagram is.  */
1196     protocol =  (ip_header_ptr -> nx_ip_header_word_2 >> 16) & 0xFF;
1197 
1198     /* Check the protocol.  */
1199     if ((protocol != NX_PROTOCOL_ICMP) && (protocol != NX_PROTOCOL_UDP) && (protocol != NX_PROTOCOL_TCP))
1200     {
1201 
1202         /* Let IP packet receive process this packet. */
1203         return (NX_FALSE);
1204     }
1205 
1206 #ifndef NX_DISABLE_RX_SIZE_CHECKING
1207     /* Check the next protocol.  */
1208     if (protocol == NX_PROTOCOL_ICMP)
1209     {
1210         header_size += sizeof(NX_ICMP_HEADER);
1211     }
1212     else if (protocol == NX_PROTOCOL_UDP)
1213     {
1214         header_size += sizeof(NX_UDP_HEADER);
1215     }
1216     else
1217     {
1218         header_size += sizeof(NX_TCP_HEADER);
1219     }
1220 
1221     /* Check for valid packet length.  */
1222     if (packet_ptr -> nx_packet_length < header_size)
1223     {
1224         if (packet_process == NX_TRUE)
1225         {
1226 #ifndef NX_DISABLE_IP_INFO
1227             /* Increment the IP invalid packet error.  */
1228             ip_ptr -> nx_ip_invalid_packets++;
1229 
1230             /* Increment the IP receive packets dropped count.  */
1231             ip_ptr -> nx_ip_receive_packets_dropped++;
1232 #endif
1233 
1234             /* Invalid packet length, just release it.  */
1235             _nx_packet_release(packet_ptr);
1236         }
1237 
1238         /* Return NX_TRUE to indicate this packet has been processed.  */
1239         return (NX_TRUE);
1240     }
1241 #endif /* NX_DISABLE_RX_SIZE_CHECKING */
1242 
1243     /* Set the packet interface pointer and NAT's global interface index.  */
1244     interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
1245     global_interface_index = nat_server_ptr -> nx_nat_global_interface_index;
1246 
1247     /* Check if the direction of the translation is inbound. */
1248     if (interface_ptr == &(ip_ptr -> nx_ip_interface[global_interface_index]))
1249     {
1250 
1251         /* Yes, this packet is received on NAT's external interface (an inbound packet). */
1252 
1253         /* Check the destination ip address against NAT's external IP address.  */
1254         if (ip_header_ptr -> nx_ip_header_destination_ip != interface_ptr -> nx_interface_ip_address)
1255         {
1256 
1257             /* NAT cannot process this packet. Let IP packet receive process this packet. */
1258             return (NX_FALSE);
1259         }
1260 
1261         /* Check if the caller wants NAT to process this packet. */
1262         if (packet_process == NX_TRUE)
1263         {
1264 
1265 #ifndef NX_DISABLE_NAT_INFO
1266             /* Yes, so update the count.  */
1267             nat_server_ptr -> forwarded_packets_received ++;
1268 #endif
1269 
1270             /* Try to deliver the packet to the local host. */
1271             status = _nx_nat_process_inbound_packet(nat_server_ptr, packet_ptr);
1272 
1273             /* Check the status.  */
1274             if (status == NX_NAT_PACKET_CONSUMED_FAILED)
1275             {
1276 
1277                 /* Let IP packet receive process this packet. */
1278                 return (NX_FALSE);
1279             }
1280         }
1281     }
1282     else
1283     {
1284 
1285         /* Check the destination ip address.  */
1286         if (
1287 
1288             /* Check for zero address.  */
1289             (ip_header_ptr -> nx_ip_header_destination_ip == 0) ||
1290 
1291             /* Check for limited broadcast.  */
1292             (ip_header_ptr -> nx_ip_header_destination_ip == NX_IP_LIMITED_BROADCAST) ||
1293 
1294             /* Check for multicast address*/
1295             ((ip_header_ptr -> nx_ip_header_destination_ip & NX_IP_CLASS_D_MASK) == NX_IP_CLASS_D_TYPE) ||
1296 
1297             /* Check for loopback address.  */
1298             ((ip_header_ptr -> nx_ip_header_destination_ip >= NX_IP_LOOPBACK_FIRST) &&
1299              (ip_header_ptr -> nx_ip_header_destination_ip <= NX_IP_LOOPBACK_LAST)))
1300         {
1301 
1302             /* Let IP packet receive process this packet. */
1303             return (NX_FALSE);
1304         }
1305 
1306         /* Clear the packet interface.  */
1307         interface_ptr = NX_NULL;
1308 
1309         /* Find the suitable interface and next hop address according to the destination ip.  */
1310         if(_nx_ip_route_find(ip_ptr, ip_header_ptr -> nx_ip_header_destination_ip, &interface_ptr, &next_hop_address) != NX_SUCCESS)
1311         {
1312 
1313             /* Let IP packet receive process this packet. */
1314             return (NX_FALSE);
1315         }
1316 
1317         /* Check the NAT forward interface.  */
1318         if (interface_ptr != &(ip_ptr -> nx_ip_interface[global_interface_index]))
1319         {
1320 
1321             /* Let IP packet receive process this packet. */
1322             return (NX_FALSE);
1323         }
1324 
1325         /* Check for IP broadcast.  */
1326         if(((ip_header_ptr -> nx_ip_header_destination_ip & interface_ptr -> nx_interface_ip_network_mask) ==
1327             interface_ptr -> nx_interface_ip_network) &&
1328             ((ip_header_ptr -> nx_ip_header_destination_ip & ~(interface_ptr -> nx_interface_ip_network_mask)) ==
1329             ~(interface_ptr -> nx_interface_ip_network_mask)))
1330         {
1331 
1332             /* Let IP packet receive process this packet. */
1333             return (NX_FALSE);
1334         }
1335 
1336         /* Check if NAT need to process this packet.  */
1337         if (packet_process == NX_TRUE)
1338         {
1339 
1340             /* Set the packet interface as global interface.  */
1341             packet_ptr -> nx_packet_address.nx_packet_interface_ptr = interface_ptr;
1342 
1343 #ifndef NX_DISABLE_NAT_INFO
1344             /* Update the count.  */
1345             nat_server_ptr -> forwarded_packets_received ++;
1346 #endif
1347 
1348             /* Deliver the packet to the outbound packet handler. */
1349             _nx_nat_process_outbound_packet(nat_server_ptr, packet_ptr);
1350         }
1351     }
1352 
1353     /* Return NX_TRUE to indicate packet has been processed by NAT.  */
1354     return (NX_TRUE);
1355 }
1356 
1357 
1358 /**************************************************************************/
1359 /*                                                                        */
1360 /*  FUNCTION                                               RELEASE        */
1361 /*                                                                        */
1362 /*    _nx_nat_process_inbound_packet                      PORTABLE C      */
1363 /*                                                           6.1          */
1364 /*  AUTHOR                                                                */
1365 /*                                                                        */
1366 /*    Yuxin Zhou, Microsoft Corporation                                   */
1367 /*                                                                        */
1368 /*  DESCRIPTION                                                           */
1369 /*                                                                        */
1370 /*   This function processes a packet from the external network for       */
1371 /*   forwarding to the private network.  It sends each packet to a        */
1372 /*   protocol handler for protocol specific processing.                   */
1373 /*                                                                        */
1374 /*  INPUT                                                                 */
1375 /*                                                                        */
1376 /*    nat_ptr                            Pointer to the NAT server        */
1377 /*    packet_ptr                         Pointer to the packet to process */
1378 /*                                                                        */
1379 /*  OUTPUT                                                                */
1380 /*                                                                        */
1381 /*    status                             Actual completion status         */
1382 /*    NX_SUCCESS                         Successful completion status     */
1383 /*    NX_NAT_INVALID_PROTOCOL            Unknown packet protocol          */
1384 /*                                                                        */
1385 /*  CALLS                                                                 */
1386 /*                                                                        */
1387 /*   _nx_nat_process_inbound_TCP_packet                                   */
1388 /*                                    Process external host's TCP packet  */
1389 /*   _nx_nat_process_inbound_UDCP_packet                                  */
1390 /*                                    Process external host's UDP packet  */
1391 /*   _nx_nat_process_inbound_ICMP_packet                                  */
1392 /*                                    Process external host's ICMP packet */
1393 /*   nx_packet_release                Release the packet                  */
1394 /*                                                                        */
1395 /*  CALLED BY                                                             */
1396 /*                                                                        */
1397 /*    _nx_nat_process_packet          Process packet from external host   */
1398 /*                                                                        */
1399 /*  RELEASE HISTORY                                                       */
1400 /*                                                                        */
1401 /*    DATE              NAME                      DESCRIPTION             */
1402 /*                                                                        */
1403 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1404 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1405 /*                                            resulting in version 6.1    */
1406 /*                                                                        */
1407 /**************************************************************************/
_nx_nat_process_inbound_packet(NX_NAT_DEVICE * nat_ptr,NX_PACKET * packet_ptr)1408 static UINT  _nx_nat_process_inbound_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr)
1409 {
1410 
1411 
1412 UINT                        status = NX_SUCCESS;
1413 UCHAR                       protocol;
1414 NX_IPV4_HEADER              *ip_header_ptr;
1415 NX_NAT_TRANSLATION_ENTRY    translation_entry;
1416 
1417 
1418     /* Pick a pointer to the IP header. */
1419     ip_header_ptr =  (NX_IPV4_HEADER *) packet_ptr -> nx_packet_prepend_ptr;
1420 
1421     /* Determine what protocol the current IP datagram is.  */
1422     protocol =  (ip_header_ptr -> nx_ip_header_word_2 >> 16) & 0xFF;
1423 
1424     /* Set up the search criteria in the NAT translation table. */
1425     memset(&translation_entry, 0, sizeof(NX_NAT_TRANSLATION_ENTRY));
1426     translation_entry.peer_ip_address = ip_header_ptr -> nx_ip_header_source_ip;
1427     translation_entry.protocol = protocol;
1428 
1429     /* Choose which packet handler by protocol. */
1430     switch (protocol)
1431     {
1432 
1433         case  NX_PROTOCOL_TCP:
1434             status = _nx_nat_process_inbound_TCP_packet(nat_ptr, packet_ptr, &translation_entry);
1435             break;
1436 
1437         case  NX_PROTOCOL_UDP:
1438             status = _nx_nat_process_inbound_UDP_packet(nat_ptr, packet_ptr, &translation_entry);
1439             break;
1440 
1441         case  NX_PROTOCOL_ICMP:
1442             status = _nx_nat_process_inbound_ICMP_packet(nat_ptr, packet_ptr, &translation_entry);
1443             break;
1444     }
1445 
1446     /* Return completion status. */
1447     return status;
1448 }
1449 
1450 
1451 /**************************************************************************/
1452 /*                                                                        */
1453 /*  FUNCTION                                               RELEASE        */
1454 /*                                                                        */
1455 /*    _nx_nat_process_inbound_TCP_packet                  PORTABLE C      */
1456 /*                                                           6.1          */
1457 /*  AUTHOR                                                                */
1458 /*                                                                        */
1459 /*    Yuxin Zhou, Microsoft Corporation                                   */
1460 /*                                                                        */
1461 /*  DESCRIPTION                                                           */
1462 /*                                                                        */
1463 /*   This function finds the local IP address:port for an incoming packet */
1464 /*   in the NAT translation table and replaces the global packet          */
1465 /*   destination IP address and port with the local IP address and port.  */
1466 /*   If none is found, it rejects the packet. Otherwise it updates the TCP*/
1467 /*   checksum with the changed IP address and port. The packet is then    */
1468 /*   sent to private host.                                                */
1469 /*                                                                        */
1470 /*  INPUT                                                                 */
1471 /*                                                                        */
1472 /*    nat_ptr                            Pointer to the NAT server        */
1473 /*    packet_ptr                         Pointer to the packet to process */
1474 /*    entry_ptr                          Pointer to the entry             */
1475 /*                                                                        */
1476 /*  OUTPUT                                                                */
1477 /*                                                                        */
1478 /*    status                             Actual completion status         */
1479 /*    NX_SUCCESS                         Successful completion status     */
1480 /*                                        (packet is not necessarily      */
1481 /*                                        forwarded)                      */
1482 /*                                                                        */
1483 /*  CALLS                                                                 */
1484 /*                                                                        */
1485 /*    _nx_nat_inbound_entry_find        Find inbound entry in entry list  */
1486 /*    _nx_nat_ip_packet_send            Send packet to private interface  */
1487 /*    nx_packet_release                 Release the packet                */
1488 /*                                                                        */
1489 /*  CALLED BY                                                             */
1490 /*                                                                        */
1491 /*    _nx_nat_process_inbound_packet     Process inbound packets          */
1492 /*                                                                        */
1493 /*  RELEASE HISTORY                                                       */
1494 /*                                                                        */
1495 /*    DATE              NAME                      DESCRIPTION             */
1496 /*                                                                        */
1497 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1498 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1499 /*                                            resulting in version 6.1    */
1500 /*                                                                        */
1501 /**************************************************************************/
_nx_nat_process_inbound_TCP_packet(NX_NAT_DEVICE * nat_ptr,NX_PACKET * packet_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr)1502 static UINT  _nx_nat_process_inbound_TCP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr)
1503 {
1504 
1505 UINT                            status;
1506 UINT                            entry_found;
1507 USHORT                          old_port;
1508 USHORT                          new_port;
1509 ULONG                           old_address;
1510 ULONG                           new_address;
1511 USHORT                          checksum;
1512 ULONG                           compute_checksum;
1513 ULONG                           next_hop_address;
1514 NX_TCP_HEADER                   *tcp_header_ptr;
1515 NX_NAT_TRANSLATION_ENTRY        *record_entry;
1516 
1517 
1518     /* Initialize local variables. */
1519     compute_checksum = 1;
1520     record_entry = NX_NULL;
1521     entry_found = NX_TRUE;
1522 
1523     /* Pickup the pointer to the head of the TCP packet.  */
1524     packet_ptr -> nx_packet_prepend_ptr += sizeof(NX_IPV4_HEADER);
1525     packet_ptr -> nx_packet_length -= sizeof(NX_IPV4_HEADER);
1526     tcp_header_ptr =  (NX_TCP_HEADER *) (packet_ptr -> nx_packet_prepend_ptr);
1527 
1528     /* For little endian processors, adjust byte order for big endianness. */
1529     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_0);
1530     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_sequence_number);
1531     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_acknowledgment_number);
1532     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
1533     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_4);
1534 
1535     /* Find the inbound entry, set the packet private interface and next hop address.  */
1536     status = _nx_nat_inbound_entry_find(nat_ptr, packet_ptr, entry_ptr, &record_entry, &next_hop_address);
1537 
1538     /* Check for error. */
1539     if (status != NX_SUCCESS)
1540     {
1541 
1542 #ifndef NX_DISABLE_NAT_INFO
1543         /* Update the count.  */
1544         nat_ptr -> forwarded_packets_dropped++;
1545 #endif
1546 
1547         /* Check the status.  */
1548         if (status == NX_NAT_ENTRY_NOT_FOUND)
1549         {
1550 
1551             /* Set the entry found flag.  */
1552             entry_found = NX_FALSE;
1553         }
1554         else
1555         {
1556 
1557             /* Release the packet */
1558             nx_packet_release(packet_ptr);
1559 
1560             /* Return completion status. */
1561             return NX_SUCCESS;
1562         }
1563     }
1564     else
1565     {
1566 
1567         /* Check the inbound packet destination port, and update the TCP header. */
1568         if (record_entry -> external_port != record_entry -> local_port)
1569         {
1570 
1571             /* Replace the destination port with the local (source) port of the preceding outbound packet.   */
1572 
1573             tcp_header_ptr -> nx_tcp_header_word_0 = ((ULONG)(tcp_header_ptr -> nx_tcp_header_word_0 & ~NX_LOWER_16_MASK)) |
1574                                                       ((ULONG) record_entry -> local_port);
1575         }
1576 
1577 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
1578         if(packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM)
1579             compute_checksum = 0;
1580         else
1581             compute_checksum = 1;
1582 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
1583         if(compute_checksum)
1584         {
1585 
1586             /* Get the old checksum.  */
1587             checksum = (USHORT)(tcp_header_ptr -> nx_tcp_header_word_4 >> NX_SHIFT_BY_16);
1588 
1589             /* Check whether the port is updated.   */
1590             if (record_entry -> external_port != record_entry -> local_port)
1591             {
1592 
1593                 /* Set the old port and new port.  */
1594                 old_port = record_entry -> external_port;
1595                 new_port = record_entry -> local_port;
1596 
1597                 /* Adjust the checksum for port.  */
1598                 _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_port, sizeof(USHORT), (UCHAR *)&new_port, sizeof(USHORT));
1599             }
1600 
1601             /* Set the old address and new address.  */
1602             old_address = nat_ptr -> nx_nat_ip_ptr -> nx_ip_interface[nat_ptr -> nx_nat_global_interface_index].nx_interface_ip_address;
1603             new_address = record_entry -> local_ip_address;
1604 
1605             /* Adjust the checksum for address.  */
1606             _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_address, sizeof(LONG), (UCHAR *)&new_address, sizeof(LONG));
1607 
1608             /* OK to clear the TCP checksum field to zero before the checksum update. */
1609             tcp_header_ptr -> nx_tcp_header_word_4 = tcp_header_ptr -> nx_tcp_header_word_4 & NX_LOWER_16_MASK;
1610 
1611             /* Place the checksum into the first header word.  */
1612             tcp_header_ptr -> nx_tcp_header_word_4 = tcp_header_ptr -> nx_tcp_header_word_4 | (ULONG)(checksum << NX_SHIFT_BY_16);
1613         }
1614 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
1615         else
1616         {
1617 
1618             /* OK to clear the TCP checksum field to zero before the checksum update. */
1619             tcp_header_ptr -> nx_tcp_header_word_4 = tcp_header_ptr -> nx_tcp_header_word_4 & NX_LOWER_16_MASK;
1620 
1621             /* Set the flag.  */
1622             packet_ptr -> nx_packet_interface_capability_flag |= NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM;
1623         }
1624 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
1625     }
1626 
1627     /* Swap endianness back before sending. */
1628     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_sequence_number);
1629     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_acknowledgment_number);
1630     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_0);
1631     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
1632     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_4);
1633 
1634     /* Check the entry found flag.  */
1635     if (entry_found == NX_FALSE)
1636     {
1637 
1638         /* Stop processing, recover packet length to Let NetXDuo process this packet.  */
1639         packet_ptr -> nx_packet_prepend_ptr -= sizeof(NX_IPV4_HEADER);
1640         packet_ptr -> nx_packet_length += sizeof(NX_IPV4_HEADER);
1641 
1642         /* Let NetXDuo process this pcaket. */
1643         return(NX_NAT_PACKET_CONSUMED_FAILED);
1644     }
1645 
1646     /* Send the TCP packet onto the private host. */
1647     _nx_nat_ip_packet_send(nat_ptr, packet_ptr, record_entry, NX_NAT_INBOUND_PACKET, next_hop_address);
1648 
1649     /* Return completion status. */
1650     return NX_SUCCESS;
1651 }
1652 
1653 
1654 /**************************************************************************/
1655 /*                                                                        */
1656 /*  FUNCTION                                               RELEASE        */
1657 /*                                                                        */
1658 /*    _nx_nat_process_inbound_UDP_packet                  PORTABLE C      */
1659 /*                                                           6.1          */
1660 /*  AUTHOR                                                                */
1661 /*                                                                        */
1662 /*    Yuxin Zhou, Microsoft Corporation                                   */
1663 /*                                                                        */
1664 /*  DESCRIPTION                                                           */
1665 /*                                                                        */
1666 /*   This function finds the local IP address:port for an incoming packet */
1667 /*   in the NAT translation table and replaces the global packet          */
1668 /*   destination IP address and port with the local IP address andport.   */
1669 /*   If none is found, it rejects the packet. Otherwise it updates the UDP*/
1670 /*   checksum with the changed IP address and port. The packet is then    */
1671 /*   sent to private host.                                                */
1672 /*                                                                        */
1673 /*  INPUT                                                                 */
1674 /*                                                                        */
1675 /*    nat_ptr                            Pointer to the NAT server        */
1676 /*    packet_ptr                         Pointer to the packet to process */
1677 /*    entry_ptr                          Pointer to the entry             */
1678 /*                                                                        */
1679 /*  OUTPUT                                                                */
1680 /*                                                                        */
1681 /*    status                             Actual completion status         */
1682 /*    NX_SUCCESS                         Successful completion status     */
1683 /*    NX_NAT_INVALID_IP_HEADER           Invalid IP header                */
1684 /*    NX_NAT_BAD_UDP_CHECKSUM            UDP checksum is invalid          */
1685 /*                                                                        */
1686 /*  CALLS                                                                 */
1687 /*                                                                        */
1688 /*    _nx_nat_inbound_entry_find        Find inbound entry in entry list  */
1689 /*    _nx_nat_ip_packet_send            Send packet to private interface  */
1690 /*    nx_packet_release                 Release the packet                */
1691 /*                                                                        */
1692 /*  CALLED BY                                                             */
1693 /*                                                                        */
1694 /*    _nx_nat_process_inbound_packet     Process inbound packets          */
1695 /*                                                                        */
1696 /*  RELEASE HISTORY                                                       */
1697 /*                                                                        */
1698 /*    DATE              NAME                      DESCRIPTION             */
1699 /*                                                                        */
1700 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1701 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1702 /*                                            resulting in version 6.1    */
1703 /*                                                                        */
1704 /**************************************************************************/
_nx_nat_process_inbound_UDP_packet(NX_NAT_DEVICE * nat_ptr,NX_PACKET * packet_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr)1705 static UINT  _nx_nat_process_inbound_UDP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr)
1706 {
1707 
1708 UINT                            status;
1709 UINT                            entry_found;
1710 USHORT                          old_port;
1711 USHORT                          new_port;
1712 ULONG                           old_address;
1713 ULONG                           new_address;
1714 USHORT                          checksum;
1715 ULONG                           compute_checksum;
1716 ULONG                           next_hop_address;
1717 NX_UDP_HEADER                   *udp_header_ptr;
1718 NX_NAT_TRANSLATION_ENTRY        *record_entry;
1719 
1720 
1721     /* Initialize local variables. */
1722     compute_checksum = 1;
1723     record_entry = NX_NULL;
1724     entry_found = NX_TRUE;
1725 
1726     /* Pickup the pointer to the head of the UDP packet.  */
1727     packet_ptr -> nx_packet_prepend_ptr += sizeof(NX_IPV4_HEADER);
1728     packet_ptr -> nx_packet_length -= sizeof(NX_IPV4_HEADER);
1729     udp_header_ptr =  (NX_UDP_HEADER *) (packet_ptr -> nx_packet_prepend_ptr);
1730 
1731     /* For little endian processors, adjust byte order for big endianness. */
1732     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0);
1733     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
1734 
1735     /* Find the inbound entry, set the packet private interface and next hop address.  */
1736     status = _nx_nat_inbound_entry_find(nat_ptr, packet_ptr, entry_ptr, &record_entry, &next_hop_address);
1737 
1738     /* Check for error. */
1739     if (status != NX_SUCCESS)
1740     {
1741 
1742 #ifndef NX_DISABLE_NAT_INFO
1743         /* Update the count.  */
1744         nat_ptr -> forwarded_packets_dropped++;
1745 #endif
1746 
1747         /* Check the status.  */
1748         if (status == NX_NAT_ENTRY_NOT_FOUND)
1749         {
1750 
1751             /* Set the entry found flag.  */
1752             entry_found = NX_FALSE;
1753         }
1754         else
1755         {
1756 
1757             /* Release the packet */
1758             nx_packet_release(packet_ptr);
1759 
1760             /* Return completion status. */
1761             return NX_SUCCESS;
1762         }
1763     }
1764     else
1765     {
1766 
1767         /* Update the destination port if the NAT device mapped it to another port. */
1768         if (record_entry -> external_port != record_entry -> local_port)
1769         {
1770 
1771             /* Translate the destination UDP port to the private host port.  If translation
1772                does not involve port number this will essentially be the original port number. */
1773             udp_header_ptr -> nx_udp_header_word_0 =  ((ULONG) (udp_header_ptr -> nx_udp_header_word_0 & ~NX_LOWER_16_MASK)) |
1774                                                        ((ULONG) record_entry -> local_port);
1775         }
1776 
1777 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
1778         if(packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM)
1779             compute_checksum = 0;
1780         else
1781             compute_checksum = 1;
1782 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
1783 
1784         /* Get the checksum.  */
1785         checksum = udp_header_ptr -> nx_udp_header_word_1 & NX_LOWER_16_MASK;
1786 
1787         /*  UDP headers with 0 checksum should not be modified, RFC3022, Section4.1, Page8.  */
1788         if (checksum == 0)
1789             compute_checksum = 0;
1790 
1791         /* Check the checksum.  */
1792         if(compute_checksum)
1793         {
1794 
1795             /* Check whether the port is updated.   */
1796             if (record_entry -> external_port != record_entry -> local_port)
1797             {
1798 
1799                 /* Set the old port and new port.  */
1800                 old_port = record_entry -> external_port;
1801                 new_port = record_entry -> local_port;
1802 
1803                 /* Adjust the checksum for port.  */
1804                 _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_port, sizeof(USHORT), (UCHAR *)&new_port, sizeof(USHORT));
1805             }
1806 
1807             /* Set the old address and new address.  */
1808             old_address = nat_ptr -> nx_nat_ip_ptr -> nx_ip_interface[nat_ptr -> nx_nat_global_interface_index].nx_interface_ip_address;
1809             new_address = record_entry -> local_ip_address;
1810 
1811             /* Adjust the checksum for address.  */
1812             _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_address, sizeof(LONG), (UCHAR *)&new_address, sizeof(LONG));
1813 
1814             /* OK to clear the UDP checksum field to zero before the checksum update. */
1815             udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 & ~NX_LOWER_16_MASK;
1816 
1817             /* Place the checksum into the first header word.  */
1818             udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 | checksum;
1819         }
1820 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
1821         else
1822         {
1823 
1824             /* OK to clear the UDP checksum field to zero before the checksum update. */
1825             udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 & ~NX_LOWER_16_MASK;
1826 
1827             /* Set the flag.  */
1828             packet_ptr -> nx_packet_interface_capability_flag |= NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM;
1829         }
1830 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
1831     }
1832 
1833     /* Swap UDP header byte order back to big endian before sending. For big endian processors,
1834        this will have no effect. */
1835     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0);
1836     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
1837 
1838     /* Check the packet consumed flag.  */
1839     if (entry_found == NX_FALSE)
1840     {
1841 
1842         /* Stop processing, recover packet length to Let NetXDuo process this packet.  */
1843         packet_ptr -> nx_packet_prepend_ptr -= sizeof(NX_IPV4_HEADER);
1844         packet_ptr -> nx_packet_length += sizeof(NX_IPV4_HEADER);
1845 
1846         /* Let NetXDuo process this pcaket. */
1847         return(NX_NAT_PACKET_CONSUMED_FAILED);
1848     }
1849 
1850     /* Send the UDP packet onto the private host. */
1851     _nx_nat_ip_packet_send(nat_ptr, packet_ptr, record_entry, NX_NAT_INBOUND_PACKET, next_hop_address);
1852 
1853     /* Return completion status. */
1854     return NX_SUCCESS;
1855 }
1856 
1857 
1858 /**************************************************************************/
1859 /*                                                                        */
1860 /*  FUNCTION                                               RELEASE        */
1861 /*                                                                        */
1862 /*    _nx_nat_process_inbound_ICMP_packet                 PORTABLE C      */
1863 /*                                                           6.1          */
1864 /*  AUTHOR                                                                */
1865 /*                                                                        */
1866 /*    Yuxin Zhou, Microsoft Corporation                                   */
1867 /*                                                                        */
1868 /*  DESCRIPTION                                                           */
1869 /*                                                                        */
1870 /*   This function finds the local IP address:port for an incoming packet */
1871 /*   in the NAT translation table and replaces the global packet          */
1872 /*   IP address and queryID with the local IP address and queryID.        */
1873 /*   If none is found, rejects the packet. Otherwise it updates the ICMP  */
1874 /*   checksum with the changed IP address and port. The packet is then    */
1875 /*   sent to private host.                                                */
1876 /*                                                                        */
1877 /*  INPUT                                                                 */
1878 /*                                                                        */
1879 /*    nat_ptr                            Pointer to the NAT server        */
1880 /*    packet_ptr                         Pointer to the packet to process */
1881 /*    entry_ptr                          Pointer to the entry             */
1882 /*                                                                        */
1883 /*  OUTPUT                                                                */
1884 /*                                                                        */
1885 /*    status                             Actual completion status         */
1886 /*    NX_SUCCESS                         Successful completion status     */
1887 /*                                        (packet is not necessarily      */
1888 /*                                        forwarded)                      */
1889 /*                                                                        */
1890 /*  CALLS                                                                 */
1891 /*                                                                        */
1892 /*    _nx_nat_inbound_entry_find        Find inbound entry in entry list  */
1893 /*    _nx_nat_ip_packet_send            Send packet to private interface  */
1894 /*    nx_packet_release                 Release the packet                */
1895 /*                                                                        */
1896 /*  CALLED BY                                                             */
1897 /*                                                                        */
1898 /*    _nx_nat_process_inbound_packet     Process inbound packets          */
1899 /*                                                                        */
1900 /*  RELEASE HISTORY                                                       */
1901 /*                                                                        */
1902 /*    DATE              NAME                      DESCRIPTION             */
1903 /*                                                                        */
1904 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1905 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1906 /*                                            resulting in version 6.1    */
1907 /*                                                                        */
1908 /**************************************************************************/
_nx_nat_process_inbound_ICMP_packet(NX_NAT_DEVICE * nat_ptr,NX_PACKET * packet_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr)1909 static UINT  _nx_nat_process_inbound_ICMP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr)
1910 {
1911 UINT                        status;
1912 UINT                        entry_found;
1913 ULONG                       sequence;
1914 UINT                        type;
1915 USHORT                      old_port;
1916 USHORT                      new_port;
1917 USHORT                      checksum;
1918 ULONG                       compute_checksum;
1919 ULONG                       next_hop_address;
1920 NX_ICMP_HEADER              *icmp_header_ptr;
1921 NX_NAT_TRANSLATION_ENTRY    *record_entry;
1922 
1923 
1924     /* Initialize local variables. */
1925     compute_checksum = 1;
1926     record_entry = NX_NULL;
1927     entry_found = NX_TRUE;
1928 
1929     /* Get a pointer to the ICMP header. */
1930     packet_ptr -> nx_packet_prepend_ptr += sizeof(NX_IPV4_HEADER);
1931     packet_ptr -> nx_packet_length -= sizeof(NX_IPV4_HEADER);
1932     icmp_header_ptr = (NX_ICMP_HEADER *)(packet_ptr -> nx_packet_prepend_ptr);
1933 
1934     /* Adjust ICMP header byte order for endianness. */
1935     NX_CHANGE_ULONG_ENDIAN(icmp_header_ptr -> nx_icmp_header_word_0);
1936     NX_CHANGE_ULONG_ENDIAN(icmp_header_ptr -> nx_icmp_header_word_1);
1937 
1938     /* Extract the ICMP type and code. */
1939     type = icmp_header_ptr -> nx_icmp_header_word_0 >> 24;
1940 
1941     /* Find the inbound entry, set the packet private interface and next hop address.  */
1942     status = _nx_nat_inbound_entry_find(nat_ptr, packet_ptr, entry_ptr, &record_entry, &next_hop_address);
1943 
1944     /* Check for error. */
1945     if (status != NX_SUCCESS)
1946     {
1947 
1948 #ifndef NX_DISABLE_NAT_INFO
1949         /* Update the count.  */
1950         nat_ptr -> forwarded_packets_dropped++;
1951 #endif
1952 
1953         /* Check the status.  */
1954         if (status == NX_NAT_ENTRY_NOT_FOUND)
1955         {
1956 
1957             /* Set the entry found flag.  */
1958             entry_found = NX_FALSE;
1959         }
1960         else
1961         {
1962 
1963             /* Release the packet */
1964             nx_packet_release(packet_ptr);
1965 
1966             /* Return completion status. */
1967             return NX_SUCCESS;
1968         }
1969     }
1970     else
1971     {
1972 
1973         /* Check the type.  */
1974         if ((type != NX_ICMP_ECHO_REPLY_TYPE) &&
1975             (type != NX_ICMP_ECHO_REQUEST_TYPE))
1976         {
1977 
1978 #ifndef NX_DISABLE_NAT_INFO
1979             /* Unknown ICMP packet. Drop the packet and bail! */
1980             nat_ptr -> forwarded_packets_dropped++;
1981 #endif
1982 
1983             nx_packet_release(packet_ptr);
1984 
1985             return NX_SUCCESS;
1986         }
1987 
1988         /* Now we have to translate the packet destination for private host address and
1989            update packet header checksum. */
1990         if ((type == NX_ICMP_ECHO_REPLY_TYPE) && (record_entry -> external_port != record_entry -> local_port))
1991         {
1992 
1993             /* Restore the local host ICMP Query ID.  */
1994             sequence = icmp_header_ptr -> nx_icmp_header_word_1 & NX_LOWER_16_MASK;
1995 
1996             /* Restore the local host ICMP Query ID from the 'source port' field in the NAT table entry. */
1997             icmp_header_ptr -> nx_icmp_header_word_1 = (ULONG)(record_entry -> local_port << NX_SHIFT_BY_16) | sequence;
1998 
1999 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
2000             if(packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM)
2001                 compute_checksum = 0;
2002             else
2003                 compute_checksum = 1;
2004 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
2005             if(compute_checksum)
2006             {
2007 
2008                 /* Set the old checksum.  */
2009                 checksum = icmp_header_ptr -> nx_icmp_header_word_0 & NX_LOWER_16_MASK;
2010 
2011                 /* Set the old port and new port.  */
2012                 old_port = entry_ptr -> external_port;
2013                 new_port = record_entry -> local_port;
2014 
2015                 /* Adjust the checksum.  */
2016                 _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_port, sizeof(USHORT), (UCHAR *)&new_port, sizeof(USHORT));
2017 
2018                 /* Ok to zero out the checksum because we'll replace it with an updated checksum. */
2019                 icmp_header_ptr -> nx_icmp_header_word_0 = icmp_header_ptr -> nx_icmp_header_word_0 & ~NX_LOWER_16_MASK;
2020 
2021                 /* Place the checksum into the first header word.  */
2022                 icmp_header_ptr -> nx_icmp_header_word_0 = icmp_header_ptr -> nx_icmp_header_word_0 | checksum;
2023             }
2024 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
2025             else
2026             {
2027 
2028                 /* Set the checksum to zero. */
2029                 icmp_header_ptr -> nx_icmp_header_word_0 = icmp_header_ptr -> nx_icmp_header_word_0 & ~NX_LOWER_16_MASK;
2030 
2031                 /* Set the flag.  */
2032                 packet_ptr -> nx_packet_interface_capability_flag |= NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM;
2033             }
2034 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
2035         }
2036     }
2037 
2038     /* If NX_LITTLE_ENDIAN is defined, the headers need to be swapped to match
2039        that of the data area.  */
2040     NX_CHANGE_ULONG_ENDIAN(icmp_header_ptr -> nx_icmp_header_word_0);
2041     NX_CHANGE_ULONG_ENDIAN(icmp_header_ptr -> nx_icmp_header_word_1);
2042 
2043     /* Check the packet consumed flag.  */
2044     if (entry_found == NX_FALSE)
2045     {
2046 
2047         /* Stop processing, recover packet length to Let NetXDuo process this packet.  */
2048         packet_ptr -> nx_packet_prepend_ptr -= sizeof(NX_IPV4_HEADER);
2049         packet_ptr -> nx_packet_length += sizeof(NX_IPV4_HEADER);
2050 
2051         /* Let NetXDuo process this pcaket. */
2052         return(NX_NAT_PACKET_CONSUMED_FAILED);
2053     }
2054 
2055     /* Send the ICMP packet onto the private host. */
2056     _nx_nat_ip_packet_send(nat_ptr, packet_ptr, record_entry, NX_NAT_INBOUND_PACKET, next_hop_address);
2057 
2058     /* Return packet send completion status. */
2059     return NX_SUCCESS;
2060 }
2061 
2062 
2063 /**************************************************************************/
2064 /*                                                                        */
2065 /*  FUNCTION                                               RELEASE        */
2066 /*                                                                        */
2067 /*    _nx_nat_process_outbound_packet                     PORTABLE C      */
2068 /*                                                           6.1          */
2069 /*  AUTHOR                                                                */
2070 /*                                                                        */
2071 /*    Yuxin Zhou, Microsoft Corporation                                   */
2072 /*                                                                        */
2073 /*  DESCRIPTION                                                           */
2074 /*                                                                        */
2075 /*   This function processes a packet from a local host bound for the     */
2076 /*   external network.  If a matching entry for the private host is not   */
2077 /*   found in the NAT translation table, one is created.  Packets are then*/
2078 /*   directed to protocol specific handlers for detailed processing of the*/
2079 /*   packet before sending out on the external network.                   */
2080 /*                                                                        */
2081 /*  INPUT                                                                 */
2082 /*                                                                        */
2083 /*    nat_ptr                           Pointer to the NAT server         */
2084 /*    packet_ptr                        Pointer to the packet to process  */
2085 /*                                                                        */
2086 /*  OUTPUT                                                                */
2087 /*                                                                        */
2088 /*    status                           Actual completion status           */
2089 /*    NX_SUCCESS                       Successful completion status       */
2090 /*    NX_NAT_INVALID_PROTOCOL          Unknown/unsupported protocol status*/
2091 /*                                                                        */
2092 /*  CALLS                                                                 */
2093 /*                                                                        */
2094 /*   _nx_nat_process_outbound_TCP_packet                                  */
2095 /*                                     Handler for outbound TCP packets   */
2096 /*   _nx_nat_process_outbound_UDP_packet                                  */
2097 /*                                     Handler for outbound UDP packets   */
2098 /*   _nx_nat_process_outbound_ICMP_packet                                 */
2099 /*                                     Handler for outbound ICMP packets  */
2100 /*   nx_packet_release                 Release packet back to packet pool */
2101 /*                                                                        */
2102 /*  CALLED BY                                                             */
2103 /*                                                                        */
2104 /*   _nx_nat_packet_process            Process packets forwarded to NAT by*/
2105 /*                                         Netx                           */
2106 /*                                                                        */
2107 /*  RELEASE HISTORY                                                       */
2108 /*                                                                        */
2109 /*    DATE              NAME                      DESCRIPTION             */
2110 /*                                                                        */
2111 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2112 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2113 /*                                            resulting in version 6.1    */
2114 /*                                                                        */
2115 /**************************************************************************/
_nx_nat_process_outbound_packet(NX_NAT_DEVICE * nat_ptr,NX_PACKET * packet_ptr)2116 static UINT  _nx_nat_process_outbound_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr)
2117 {
2118 
2119 UCHAR                    protocol;
2120 NX_IPV4_HEADER           *ip_header_ptr;
2121 NX_NAT_TRANSLATION_ENTRY translation_entry;
2122 
2123 
2124     /* Set up an actual IP header pointer. */
2125     ip_header_ptr =  (NX_IPV4_HEADER *) (packet_ptr -> nx_packet_prepend_ptr);
2126 
2127     /* Determine what protocol the current IP datagram is.  */
2128     protocol =  (ip_header_ptr -> nx_ip_header_word_2 >> 16) & 0xFF;
2129 
2130     /* Set up the search criteria in the NAT translation table. */
2131     memset(&translation_entry, 0, sizeof(NX_NAT_TRANSLATION_ENTRY));
2132     translation_entry.local_ip_address = ip_header_ptr -> nx_ip_header_source_ip;
2133     translation_entry.peer_ip_address = ip_header_ptr -> nx_ip_header_destination_ip;
2134     translation_entry.protocol = protocol;
2135 
2136     /* Direct the packet to a protocol specific handler. */
2137     switch (protocol)
2138     {
2139 
2140         case  NX_PROTOCOL_TCP:
2141             /* Process the packet for TCP protocol. */
2142             _nx_nat_process_outbound_TCP_packet(nat_ptr, packet_ptr, &translation_entry);
2143             break;
2144 
2145         case  NX_PROTOCOL_UDP:
2146             /* Process the packet for UDP protocol. */
2147             _nx_nat_process_outbound_UDP_packet(nat_ptr, packet_ptr, &translation_entry);
2148             break;
2149 
2150         case  NX_PROTOCOL_ICMP:
2151             /* Process the packet for ICMP (including error message packets) protocol. */
2152             _nx_nat_process_outbound_ICMP_packet(nat_ptr, packet_ptr, &translation_entry);
2153             break;
2154 
2155         default:
2156         {
2157 
2158 #ifndef NX_DISABLE_NAT_INFO
2159             /* Update the count.  */
2160             nat_ptr -> forwarded_packets_dropped++;
2161 #endif
2162 
2163             /* Toss the IP packet since we don't know what to do with it! */
2164             nx_packet_release(packet_ptr);
2165 
2166             return NX_NAT_INVALID_PROTOCOL;
2167         }
2168     }
2169 
2170     /* Return completion status. */
2171     return NX_SUCCESS;
2172 }
2173 
2174 
2175 /**************************************************************************/
2176 /*                                                                        */
2177 /*  FUNCTION                                               RELEASE        */
2178 /*                                                                        */
2179 /*    _nx_nat_process_outbound_TCP_packet                 PORTABLE C      */
2180 /*                                                           6.1          */
2181 /*  AUTHOR                                                                */
2182 /*                                                                        */
2183 /*    Yuxin Zhou, Microsoft Corporation                                   */
2184 /*                                                                        */
2185 /*  DESCRIPTION                                                           */
2186 /*                                                                        */
2187 /*   This function processes a TCP packet from a local host on the private*/
2188 /*   network destined for the external network with a global IP address   */
2189 /*   and port.  The source IP address and port are replaced by NAT with a */
2190 /*   global IP address:port. NAT then updates the TCP header checksum.    */
2191 /*                                                                        */
2192 /*  INPUT                                                                 */
2193 /*                                                                        */
2194 /*    nat_ptr                         Pointer to the NAT server           */
2195 /*    packet_ptr                      Pointer to the packet to process    */
2196 /*    entry_ptr                       Pointer to the entry                */
2197 /*                                                                        */
2198 /*  OUTPUT                                                                */
2199 /*                                                                        */
2200 /*    status                           Actual completion status           */
2201 /*    NX_SUCCESS                       Successful completion status       */
2202 /*                                                                        */
2203 /*  CALLS                                                                 */
2204 /*                                                                        */
2205 /*    _nx_nat_outbound_entry_find       Find outbound entry in entry list */
2206 /*    _nx_nat_ip_packet_send            Send packet to private interface  */
2207 /*    nx_packet_release                 Release the packet                */
2208 /*                                                                        */
2209 /*  CALLED BY                                                             */
2210 /*                                                                        */
2211 /*    Application code                                                    */
2212 /*                                                                        */
2213 /*  RELEASE HISTORY                                                       */
2214 /*                                                                        */
2215 /*    DATE              NAME                      DESCRIPTION             */
2216 /*                                                                        */
2217 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2218 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2219 /*                                            resulting in version 6.1    */
2220 /*                                                                        */
2221 /**************************************************************************/
_nx_nat_process_outbound_TCP_packet(NX_NAT_DEVICE * nat_ptr,NX_PACKET * packet_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr)2222 static UINT  _nx_nat_process_outbound_TCP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr)
2223 {
2224 
2225 UINT                        status;
2226 USHORT                      old_port;
2227 USHORT                      new_port;
2228 ULONG                       old_address;
2229 ULONG                       new_address;
2230 USHORT                      checksum;
2231 ULONG                       compute_checksum;
2232 ULONG                       next_hop_address;
2233 NX_TCP_HEADER               *tcp_header_ptr;
2234 NX_NAT_TRANSLATION_ENTRY    *record_entry;
2235 
2236 
2237     /* Initialize local variables. */
2238     compute_checksum = 1;
2239 
2240     /* Pickup the pointer to the head of the UDP packet.  */
2241     packet_ptr -> nx_packet_prepend_ptr += sizeof(NX_IPV4_HEADER);
2242     packet_ptr -> nx_packet_length -= sizeof(NX_IPV4_HEADER);
2243     tcp_header_ptr =  (NX_TCP_HEADER *) (packet_ptr -> nx_packet_prepend_ptr);
2244 
2245     /* Adjust byte order for endianness.  */
2246     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_0);
2247     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_sequence_number);
2248     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_acknowledgment_number);
2249     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
2250     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_4);
2251 
2252     /* Find the outbound entry, set the packet global interface and next hop address.  */
2253     status = _nx_nat_outbound_entry_find(nat_ptr, packet_ptr, entry_ptr, &record_entry, &next_hop_address);
2254 
2255     /* Check for error. */
2256     if (status != NX_SUCCESS)
2257     {
2258 
2259 #ifndef NX_DISABLE_NAT_INFO
2260         /* Increase the session count of dropped forwarded packets. */
2261         nat_ptr -> forwarded_packets_dropped++;
2262 #endif
2263 
2264         /* Release the packet back to the packet pool. */
2265         nx_packet_release(packet_ptr);
2266 
2267         /* Return the error status. */
2268         return status;
2269     }
2270 
2271     /* Update the source port if the NAT device mapped it to another port. */
2272     if (record_entry -> external_port != record_entry -> local_port)
2273     {
2274 
2275         /* Yes, write to the upper bits of the TCP word. */
2276         tcp_header_ptr -> nx_tcp_header_word_0 = (tcp_header_ptr -> nx_tcp_header_word_0 & NX_LOWER_16_MASK) |
2277                                                  (((ULONG) (record_entry -> external_port)) << NX_SHIFT_BY_16);
2278     }
2279 
2280 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
2281     if(packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM)
2282         compute_checksum = 0;
2283     else
2284         compute_checksum = 1;
2285 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
2286     if(compute_checksum)
2287     {
2288 
2289         /* Get the old checksum.  */
2290         checksum = (USHORT)(tcp_header_ptr -> nx_tcp_header_word_4 >> NX_SHIFT_BY_16);
2291 
2292         /* Check whether the port is updated.   */
2293         if (record_entry -> external_port != record_entry -> local_port)
2294         {
2295 
2296             /* Set the old port and new port.  */
2297             old_port = record_entry -> local_port;
2298             new_port = record_entry -> external_port;
2299 
2300             /* Adjust the checksum for port.  */
2301             _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_port, sizeof(USHORT), (UCHAR *)&new_port, sizeof(USHORT));
2302         }
2303 
2304         /* Set the old address and new address.  */
2305         old_address = record_entry -> local_ip_address;
2306         new_address = nat_ptr -> nx_nat_ip_ptr -> nx_ip_interface[nat_ptr -> nx_nat_global_interface_index].nx_interface_ip_address;
2307 
2308         /* Adjust the checksum for address.  */
2309         _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_address, sizeof(LONG), (UCHAR *)&new_address, sizeof(LONG));
2310 
2311         /* OK to clear the TCP checksum field to zero before the checksum update. */
2312         tcp_header_ptr -> nx_tcp_header_word_4 = tcp_header_ptr -> nx_tcp_header_word_4 & NX_LOWER_16_MASK;
2313 
2314         /* Place the checksum into the first header word.  */
2315         tcp_header_ptr -> nx_tcp_header_word_4 = tcp_header_ptr -> nx_tcp_header_word_4 | (ULONG)(checksum << NX_SHIFT_BY_16);
2316     }
2317 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
2318     else
2319     {
2320 
2321         /* OK to clear the TCP checksum field to zero before the checksum update. */
2322         tcp_header_ptr -> nx_tcp_header_word_4 = tcp_header_ptr -> nx_tcp_header_word_4 & NX_LOWER_16_MASK;
2323 
2324         /* Set the flag.  */
2325         packet_ptr -> nx_packet_interface_capability_flag |= NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM;
2326     }
2327 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
2328 
2329     /* Swap byte order back to big endian before sending if little endian is specified. */
2330     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_0);
2331     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_sequence_number);
2332     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_acknowledgment_number);
2333     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
2334     NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_4);
2335 
2336     /* Send the TCP packet onto the global host. */
2337     _nx_nat_ip_packet_send(nat_ptr,packet_ptr, record_entry, NX_NAT_OUTBOUND_PACKET, next_hop_address);
2338 
2339     return NX_SUCCESS;
2340 }
2341 
2342 
2343 /**************************************************************************/
2344 /*                                                                        */
2345 /*  FUNCTION                                               RELEASE        */
2346 /*                                                                        */
2347 /*    _nx_nat_process_outbound_UDP_packet                 PORTABLE C      */
2348 /*                                                           6.1          */
2349 /*  AUTHOR                                                                */
2350 /*                                                                        */
2351 /*    Yuxin Zhou, Microsoft Corporation                                   */
2352 /*                                                                        */
2353 /*  DESCRIPTION                                                           */
2354 /*                                                                        */
2355 /*   This function processes a UDP packet from a local host destined for  */
2356 /*   the external network; NAT replaces the private IP address:port with a*/
2357 /*   global IP address:port. NAT updates the UDP header checksum field for*/
2358 /*   all packets having a non zero UDP packet checksum.                   */
2359 /*                                                                        */
2360 /*  INPUT                                                                 */
2361 /*                                                                        */
2362 /*    nat_ptr                         Pointer to the NAT server           */
2363 /*    packet_ptr                      Pointer to the packet to process    */
2364 /*    entry_ptr                       Pointer to the entry                */
2365 /*                                                                        */
2366 /*  OUTPUT                                                                */
2367 /*                                                                        */
2368 /*    status                           Actual completion status           */
2369 /*    NX_SUCCESS                       Successful completion status       */
2370 /*    NX_NAT_ZERO_UDP_CHECKSUM         Illegal zero UDP header checksum   */
2371 /*    NX_NAT_BAD_UDP_CHECKSUM          UDP header checksum is invalid     */
2372 /*                                                                        */
2373 /*  CALLS                                                                 */
2374 /*                                                                        */
2375 /*    _nx_nat_outbound_entry_find       Find outbound entry in entry list */
2376 /*    _nx_nat_ip_packet_send            Send packet to private interface  */
2377 /*    nx_packet_release                 Release the packet                */
2378 /*                                                                        */
2379 /*  CALLED BY                                                             */
2380 /*                                                                        */
2381 /*    Application code                                                    */
2382 /*                                                                        */
2383 /*  RELEASE HISTORY                                                       */
2384 /*                                                                        */
2385 /*    DATE              NAME                      DESCRIPTION             */
2386 /*                                                                        */
2387 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2388 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2389 /*                                            resulting in version 6.1    */
2390 /*                                                                        */
2391 /**************************************************************************/
_nx_nat_process_outbound_UDP_packet(NX_NAT_DEVICE * nat_ptr,NX_PACKET * packet_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr)2392 static UINT  _nx_nat_process_outbound_UDP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr)
2393 {
2394 
2395 UINT                        status;
2396 USHORT                      old_port;
2397 USHORT                      new_port;
2398 ULONG                       old_address;
2399 ULONG                       new_address;
2400 USHORT                      checksum;
2401 ULONG                       compute_checksum;
2402 ULONG                       next_hop_address;
2403 NX_UDP_HEADER               *udp_header_ptr;
2404 NX_NAT_TRANSLATION_ENTRY    *record_entry;
2405 
2406     /* Initialize local variables. */
2407     compute_checksum = 1;
2408 
2409     /* Pickup the pointer to the head of the UDP packet.  */
2410     packet_ptr -> nx_packet_prepend_ptr += sizeof(NX_IPV4_HEADER);
2411     packet_ptr -> nx_packet_length -= sizeof(NX_IPV4_HEADER);
2412     udp_header_ptr =  (NX_UDP_HEADER *) (packet_ptr -> nx_packet_prepend_ptr);
2413 
2414     /* For little endian processors, swap byte order to little endian. */
2415     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0);
2416     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
2417 
2418     /* Find the outbound entry, set the packet global interface and next hop address.  */
2419     status = _nx_nat_outbound_entry_find(nat_ptr, packet_ptr, entry_ptr, &record_entry, &next_hop_address);
2420 
2421     /* Check for error. */
2422     if (status != NX_SUCCESS)
2423     {
2424 
2425 #ifndef NX_DISABLE_NAT_INFO
2426         /* Increase the session count of dropped forwarded packets. */
2427         nat_ptr -> forwarded_packets_dropped++;
2428 #endif
2429 
2430         /* Release the packet back to the packet pool. */
2431         nx_packet_release(packet_ptr);
2432 
2433         /* Return the error status. */
2434         return status;
2435     }
2436 
2437     /* OK to zero out the checksum field so we can update the header with a new checksum later. */
2438     udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 & ~NX_LOWER_16_MASK;
2439 
2440     /* Did NAT assign a global UDP source port? */
2441     if (record_entry -> external_port != record_entry -> local_port)
2442     {
2443 
2444         /* Yes, so replace local host UDP port with NAT global inside UDP port in the header.  */
2445         udp_header_ptr -> nx_udp_header_word_0 = (udp_header_ptr -> nx_udp_header_word_0 & NX_LOWER_16_MASK) |
2446                                                  (((ULONG) (record_entry -> external_port)) << NX_SHIFT_BY_16);
2447     }
2448 
2449 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
2450     if(packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM)
2451         compute_checksum = 0;
2452     else
2453         compute_checksum = 1;
2454 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
2455 
2456     /* Get the old checksum.  */
2457     checksum = udp_header_ptr -> nx_udp_header_word_1 & NX_LOWER_16_MASK;
2458 
2459     /*  UDP headers with 0 checksum should not be modified, RFC3022, Section4.1, Page8.  */
2460     if (checksum == 0)
2461         compute_checksum = 0;
2462 
2463     /* Compute the checksum.  */
2464     if(compute_checksum)
2465     {
2466 
2467         /* Check whether the port is updated.   */
2468         if (record_entry -> external_port != record_entry -> local_port)
2469         {
2470 
2471             /* Set the old port and new port.  */
2472             old_port = record_entry -> local_port;
2473             new_port = record_entry -> external_port;
2474 
2475             /* Adjust the checksum for port.  */
2476             _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_port, sizeof(USHORT), (UCHAR *)&new_port, sizeof(USHORT));
2477         }
2478 
2479         /* Set the old address and new address.  */
2480         old_address = record_entry -> local_ip_address;
2481         new_address = nat_ptr -> nx_nat_ip_ptr -> nx_ip_interface[nat_ptr -> nx_nat_global_interface_index].nx_interface_ip_address;
2482 
2483         /* Adjust the checksum for address.  */
2484         _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_address, sizeof(LONG), (UCHAR *)&new_address, sizeof(LONG));
2485 
2486         /* OK to clear the UDP checksum field to zero before the checksum update. */
2487         udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 & ~NX_LOWER_16_MASK;
2488 
2489         /* Place the checksum into the first header word.  */
2490         udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 | checksum;
2491     }
2492 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
2493     else
2494     {
2495 
2496         /* OK to clear the UDP checksum field to zero before the checksum update. */
2497         udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 & ~NX_LOWER_16_MASK;
2498 
2499         /* Set the flag.  */
2500         packet_ptr -> nx_packet_interface_capability_flag |= NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM;
2501     }
2502 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
2503 
2504     /* If NX_LITTLE_ENDIAN is defined, the headers need to be swapped to match
2505        that of the data area.  */
2506     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0);
2507     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
2508 
2509     /* Send the UDP packet onto the global host. */
2510     _nx_nat_ip_packet_send(nat_ptr, packet_ptr, record_entry, NX_NAT_OUTBOUND_PACKET, next_hop_address);
2511 
2512     /* Return packet send completion status. */
2513     return NX_SUCCESS;
2514 }
2515 
2516 
2517 /**************************************************************************/
2518 /*                                                                        */
2519 /*  FUNCTION                                               RELEASE        */
2520 /*                                                                        */
2521 /*    _nx_nat_process_outbound_ICMP_packet                PORTABLE C      */
2522 /*                                                           6.1          */
2523 /*  AUTHOR                                                                */
2524 /*                                                                        */
2525 /*    Yuxin Zhou, Microsoft Corporation                                   */
2526 /*                                                                        */
2527 /*  DESCRIPTION                                                           */
2528 /*                                                                        */
2529 /*   This function processes a ICMP packet from a local network host for  */
2530 /*   sending out onto the external network. NAT replaces the private      */
2531 /*   source IP address and local query ID with a global source IP address */
2532 /*   and query ID.  NAT then recomputes the ICMP header checksum.         */
2533 /*                                                                        */
2534 /*  INPUT                                                                 */
2535 /*                                                                        */
2536 /*    nat_ptr                         Pointer to the NAT server           */
2537 /*    packet_ptr                      Pointer to the packet to process    */
2538 /*    entry_ptr                       Pointer to the entry                */
2539 /*                                                                        */
2540 /*  OUTPUT                                                                */
2541 /*                                                                        */
2542 /*    status                           Actual completion status           */
2543 /*    NX_SUCCESS                       Successful completion status       */
2544 /*    NX_NAT_BAD_ICMP_CHECKSUM         Packet failed ICMP checksum check  */
2545 /*    NX_NAT_INVALID_IP_HEADER         Packet has an invalid IP header    */
2546 /*                                                                        */
2547 /*  CALLS                                                                 */
2548 /*                                                                        */
2549 /*    _nx_nat_outbound_entry_find       Find outbound entry in entry list */
2550 /*    _nx_nat_ip_packet_send            Send packet to private interface  */
2551 /*    nx_packet_release                 Release the packet                */
2552 /*                                                                        */
2553 /*  CALLED BY                                                             */
2554 /*                                                                        */
2555 /*    Application code                                                    */
2556 /*                                                                        */
2557 /*  RELEASE HISTORY                                                       */
2558 /*                                                                        */
2559 /*    DATE              NAME                      DESCRIPTION             */
2560 /*                                                                        */
2561 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2562 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2563 /*                                            resulting in version 6.1    */
2564 /*                                                                        */
2565 /**************************************************************************/
_nx_nat_process_outbound_ICMP_packet(NX_NAT_DEVICE * nat_ptr,NX_PACKET * packet_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr)2566 static UINT  _nx_nat_process_outbound_ICMP_packet(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr)
2567 {
2568 
2569 UINT               status;
2570 ULONG              sequence;
2571 UINT               is_icmp_error_msg;
2572 NX_ICMP_HEADER     *icmp_header_ptr;
2573 UINT               type;
2574 USHORT             old_port;
2575 USHORT             new_port;
2576 USHORT             checksum;
2577 ULONG              compute_checksum;
2578 ULONG              next_hop_address;
2579 NX_NAT_TRANSLATION_ENTRY    *record_entry;
2580 
2581 
2582     /* Initialize local variables. */
2583     compute_checksum = 1;
2584 
2585     /* Pickup the pointer to the head of the ICMP packet.  */
2586     packet_ptr -> nx_packet_prepend_ptr += sizeof(NX_IPV4_HEADER);
2587     packet_ptr -> nx_packet_length -= sizeof(NX_IPV4_HEADER);
2588     icmp_header_ptr =  (NX_ICMP_HEADER *)(packet_ptr -> nx_packet_prepend_ptr);
2589 
2590     /* Swap ENDian-ness for our ICMP header. We've only swapped the IP header data so far. */
2591     NX_CHANGE_ULONG_ENDIAN(icmp_header_ptr -> nx_icmp_header_word_0);
2592     NX_CHANGE_ULONG_ENDIAN(icmp_header_ptr -> nx_icmp_header_word_1);
2593 
2594     /* Extract the ICMP type and code. */
2595     type = icmp_header_ptr -> nx_icmp_header_word_0 >> 24;
2596 
2597     /* Determine if this outbound packet an ICMP error message packet. */
2598     _nx_nat_packet_is_icmp_error_message(packet_ptr, &is_icmp_error_msg);
2599 
2600     /* Is the this an error message packet? */
2601     if (is_icmp_error_msg)
2602     {
2603 
2604 #ifndef NX_DISABLE_NAT_INFO
2605         /* Drop the packet and bail! */
2606         nat_ptr -> forwarded_packets_dropped++;
2607 #endif
2608 
2609         /* Release the packet.  */
2610         nx_packet_release(packet_ptr);
2611 
2612          /* Return completion status. */
2613          return NX_SUCCESS;
2614     }
2615 
2616     /* Find the outbound entry, set the packet global interface and next hop address.  */
2617     status = _nx_nat_outbound_entry_find(nat_ptr, packet_ptr, entry_ptr, &record_entry, &next_hop_address);
2618 
2619     /* Check for error. */
2620     if (status != NX_SUCCESS)
2621     {
2622 
2623 #ifndef NX_DISABLE_NAT_INFO
2624         /* Increase the session count of dropped forwarded packets. */
2625         nat_ptr -> forwarded_packets_dropped++;
2626 #endif
2627 
2628         /* Release the packet back to the packet pool. */
2629         nx_packet_release(packet_ptr);
2630 
2631         /* Return the error status. */
2632         return status;
2633     }
2634 
2635     /* Update the ICMP Query ID ("port") if the NAT device mapped it to another Query ID
2636        but not if this is a local host responding to a REQUEST ICMP packet, in which case
2637        it must keep the same Query ID. */
2638     if ((type != NX_ICMP_ECHO_REPLY_TYPE) && (record_entry -> external_port != record_entry -> local_port))
2639     {
2640 
2641         /* Pick up the ICMP sequence number. */
2642         sequence =  icmp_header_ptr -> nx_icmp_header_word_1 & NX_LOWER_16_MASK;
2643 
2644         /* Set the ICMP Query ID in the ICMP header.  */
2645         icmp_header_ptr -> nx_icmp_header_word_1 = (ULONG) (record_entry -> external_port << NX_SHIFT_BY_16) | sequence;
2646 
2647 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
2648         if(packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM)
2649             compute_checksum = 0;
2650         else
2651             compute_checksum = 1;
2652 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
2653         if(compute_checksum)
2654         {
2655 
2656             /* Set the old checksum.  */
2657             checksum = icmp_header_ptr -> nx_icmp_header_word_0 & NX_LOWER_16_MASK;
2658 
2659             /* Set the old port and new port.  */
2660             old_port = record_entry -> local_port;
2661             new_port = record_entry -> external_port;
2662 
2663             /* Adjust the checksum.  */
2664             _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_port, sizeof(USHORT), (UCHAR *)&new_port, sizeof(USHORT));
2665 
2666             /* Ok to zero out the checksum because we'll replace it with an updated checksum. */
2667             icmp_header_ptr -> nx_icmp_header_word_0 = icmp_header_ptr -> nx_icmp_header_word_0 & ~NX_LOWER_16_MASK;
2668 
2669             /* Place the checksum into the first header word.  */
2670             icmp_header_ptr -> nx_icmp_header_word_0 = icmp_header_ptr -> nx_icmp_header_word_0 | checksum;
2671         }
2672 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
2673         else
2674         {
2675 
2676             /* Set the checksum to zero. */
2677             icmp_header_ptr -> nx_icmp_header_word_0 = icmp_header_ptr -> nx_icmp_header_word_0 & ~NX_LOWER_16_MASK;
2678 
2679             /* Set the flag.  */
2680             packet_ptr -> nx_packet_interface_capability_flag |= NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM;
2681         }
2682 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
2683     }
2684 
2685     /* If NX_LITTLE_ENDIAN is defined, the headers need to be swapped to match
2686        that of the data area.  */
2687     NX_CHANGE_ULONG_ENDIAN(icmp_header_ptr -> nx_icmp_header_word_0);
2688     NX_CHANGE_ULONG_ENDIAN(icmp_header_ptr -> nx_icmp_header_word_1);
2689 
2690     /* Send the ICMP packet onto the global host. */
2691     _nx_nat_ip_packet_send(nat_ptr, packet_ptr, record_entry, NX_NAT_OUTBOUND_PACKET, next_hop_address);
2692 
2693     /* Return completion status. */
2694     return NX_SUCCESS;
2695 }
2696 
2697 
2698 /**************************************************************************/
2699 /*                                                                        */
2700 /*  FUNCTION                                               RELEASE        */
2701 /*                                                                        */
2702 /*    _nx_nat_ip_packet_send                              PORTABLE C      */
2703 /*                                                           6.1          */
2704 /*  AUTHOR                                                                */
2705 /*                                                                        */
2706 /*    Yuxin Zhou, Microsoft Corporation                                   */
2707 /*                                                                        */
2708 /*  DESCRIPTION                                                           */
2709 /*                                                                        */
2710 /*   This function is the NAT equivalent of nx_ip_packet_send. It handles */
2711 /*   all packets inbound or outbound of any protocol and forwards them    */
2712 /*   directly to the driver.                                              */
2713 /*                                                                        */
2714 /*   This function also handles fragmented datagrams.                     */
2715 /*                                                                        */
2716 /*  INPUT                                                                 */
2717 /*                                                                        */
2718 /*    nat_ptr                             Pointer to NAT server           */
2719 /*    packet_ptr                          Pointer to packet               */
2720 /*    entry_ptr                           Pointer to NAT entry            */
2721 /*    packet_type                         Packet type(inbound/outbound)   */
2722 /*    next_hop_address                    Next hop address to target      */
2723 /*                                                                        */
2724 /*  OUTPUT                                                                */
2725 /*                                                                        */
2726 /*    status                              Actual completion status.       */
2727 /*    NX_SUCCESS                          Successful completion status    */
2728 /*    NX_NAT_FRAGMENT_QUEUE_NOT_FOUND     Fragment queue for datagram     */
2729 /*                                            not found                   */
2730 /*  CALLS                                                                 */
2731 /*                                                                        */
2732 /*   nx_packet_release                    Release the packet              */
2733 /*   _nx_packet_data_append               Append the overflow data        */
2734 /*   _nx_nat_checksum_adjust              Adjust checksum for NAT changes */
2735 /*                                            to IP header                */
2736 /*   _nx_ip_driver_packet_send            Forward packet to driver to send*/
2737 /*                                                                        */
2738 /*  CALLED BY                                                             */
2739 /*                                                                        */
2740 /*   _nx_nat_process_outbound_TCP_packet  Process outbound TCP packet     */
2741 /*   _nx_nat_process_outbound_UDP_packet  Process outbound UDP packet     */
2742 /*   _nx_nat_process_outbound_ICMP_packet Process outbound ICMP packet    */
2743 /*   _nx_nat_process_inbound_TCP_packet   Process outbound TCP packet     */
2744 /*   _nx_nat_process_inbound_UDP_packet   Process outbound UDP packet     */
2745 /*   _nx_nat_process_inbound_ICMP_packet  Process outbound ICMP packet    */
2746 /*                                                                        */
2747 /*  RELEASE HISTORY                                                       */
2748 /*                                                                        */
2749 /*    DATE              NAME                      DESCRIPTION             */
2750 /*                                                                        */
2751 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2752 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2753 /*                                            resulting in version 6.1    */
2754 /*                                                                        */
2755 /**************************************************************************/
_nx_nat_ip_packet_send(NX_NAT_DEVICE * nat_ptr,NX_PACKET * packet_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr,UCHAR packet_type,ULONG next_hop_address)2756 static VOID  _nx_nat_ip_packet_send(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr, UCHAR packet_type, ULONG next_hop_address)
2757 {
2758 
2759 ULONG               fragment_bits;
2760 ULONG               old_address;
2761 ULONG               new_address;
2762 ULONG               old_fragment;
2763 ULONG               new_fragment;
2764 USHORT              checksum;
2765 ULONG               compute_checksum = 1;
2766 ULONG               destination_ip;
2767 UINT                status;
2768 NX_IPV4_HEADER      *ip_header_ptr;
2769 
2770 
2771     /* Pickup the pointer to the head of the ICMP packet.  */
2772     packet_ptr -> nx_packet_prepend_ptr -= sizeof(NX_IPV4_HEADER);
2773     packet_ptr -> nx_packet_length += sizeof(NX_IPV4_HEADER);
2774     ip_header_ptr =  (NX_IPV4_HEADER *) (packet_ptr -> nx_packet_prepend_ptr);
2775 
2776     /* Check the packet type.  */
2777     if (packet_type == NX_NAT_OUTBOUND_PACKET)
2778     {
2779 
2780         /* Update the source ip address.  */
2781         ip_header_ptr -> nx_ip_header_source_ip = nat_ptr -> nx_nat_ip_ptr -> nx_ip_interface[nat_ptr -> nx_nat_global_interface_index].nx_interface_ip_address;
2782 
2783         /* Set the local address and external address.  */
2784         old_address = entry_ptr -> local_ip_address;
2785         new_address = nat_ptr -> nx_nat_ip_ptr -> nx_ip_interface[nat_ptr -> nx_nat_global_interface_index].nx_interface_ip_address;
2786     }
2787     else
2788     {
2789         /* Update the destination ip address.  */
2790         ip_header_ptr -> nx_ip_header_destination_ip = entry_ptr -> local_ip_address;
2791 
2792         /* Set the old address and new address.  */
2793         old_address = nat_ptr -> nx_nat_ip_ptr -> nx_ip_interface[nat_ptr -> nx_nat_global_interface_index].nx_interface_ip_address;
2794         new_address = entry_ptr -> local_ip_address;
2795     }
2796 
2797     /* Record the destination IP address.  */
2798     destination_ip = ip_header_ptr -> nx_ip_header_destination_ip;
2799 
2800     /* Record the fragment bit.  */
2801     fragment_bits = (ip_header_ptr -> nx_ip_header_word_1 & NX_IP_DONT_FRAGMENT);
2802     old_fragment = ip_header_ptr -> nx_ip_header_word_1 & NX_LOWER_16_MASK;
2803     new_fragment = old_fragment;
2804 
2805     /* Check if the packet is fragmented and if the fragment field is not zero.  */
2806     if ((fragment_bits != NX_IP_DONT_FRAGMENT) && (old_fragment != 0))
2807     {
2808 
2809         /* Clear the fragment field.  */
2810         ip_header_ptr -> nx_ip_header_word_1 = ip_header_ptr -> nx_ip_header_word_1 & ~NX_LOWER_16_MASK;
2811         new_fragment = 0;
2812     }
2813 
2814 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
2815     if(packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM)
2816         compute_checksum = 0;
2817     else
2818         compute_checksum = 1;
2819 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
2820 
2821     /* Compute the checksum.  */
2822     if(compute_checksum)
2823     {
2824 
2825         /* Get the checksum.  */
2826         checksum = ip_header_ptr -> nx_ip_header_word_2 & NX_LOWER_16_MASK;
2827 
2828         /* Adjust the checksum for address.  */
2829         _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_address, sizeof(LONG), (UCHAR *)&new_address, sizeof(LONG));
2830 
2831         /* Check if the fragment field is updated.  */
2832         if (old_fragment != new_fragment)
2833         {
2834 
2835             /* Adjust the checksum for fragment field.  */
2836             _nx_nat_checksum_adjust((UCHAR *)&checksum, (UCHAR *)&old_fragment, sizeof(LONG), (UCHAR *)&new_fragment, sizeof(LONG));
2837         }
2838 
2839         /* Clear the checksum value.  */
2840         ip_header_ptr -> nx_ip_header_word_2 = ip_header_ptr -> nx_ip_header_word_2 & ~NX_LOWER_16_MASK;
2841 
2842         /* Place the checksum into the header word.  */
2843         ip_header_ptr -> nx_ip_header_word_2 = ip_header_ptr -> nx_ip_header_word_2 | checksum;
2844     }
2845 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
2846     else
2847     {
2848 
2849         /* Clear the checksum value.  */
2850         ip_header_ptr -> nx_ip_header_word_2 = ip_header_ptr -> nx_ip_header_word_2 & ~NX_LOWER_16_MASK;
2851 
2852         /* Set the flag.  */
2853         packet_ptr -> nx_packet_interface_capability_flag |= NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM;
2854     }
2855 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
2856 
2857     /* Endian swapping logic.  If NX_LITTLE_ENDIAN is specified, these macros will
2858     swap the endian of the IP header.  */
2859     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_0);
2860     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_1);
2861     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_2);
2862     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_source_ip);
2863     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_destination_ip);
2864 
2865     /* Check if the packet can fill physical header.  */
2866     status = _nx_packet_data_adjust(packet_ptr, NX_PHYSICAL_HEADER);
2867 
2868     /* Check status.  */
2869     if (status)
2870     {
2871 
2872 #ifndef NX_DISABLE_NAT_INFO
2873         /* Update the count.  */
2874         nat_ptr -> forwarded_packets_dropped ++;
2875 #endif
2876 
2877         /* Release the packet. */
2878         _nx_packet_release(packet_ptr);
2879         return;
2880     }
2881 
2882 #ifndef NX_DISABLE_NAT_INFO
2883     /* Update the packet sent count.  */
2884     nat_ptr -> forwarded_packets_sent++;
2885 #endif
2886 
2887     /* Call the function to directly forward the packet.  */
2888     _nx_ip_driver_packet_send(nat_ptr -> nx_nat_ip_ptr, packet_ptr, destination_ip, fragment_bits, next_hop_address);
2889     return;
2890 }
2891 
2892 
2893 /**************************************************************************/
2894 /*                                                                        */
2895 /*  FUNCTION                                               RELEASE        */
2896 /*                                                                        */
2897 /*    _nx_nat_inbound_entry_find                          PORTABLE C      */
2898 /*                                                           6.1          */
2899 /*  AUTHOR                                                                */
2900 /*                                                                        */
2901 /*    Yuxin Zhou, Microsoft Corporation                                   */
2902 /*                                                                        */
2903 /*  DESCRIPTION                                                           */
2904 /*                                                                        */
2905 /*   This function finds the inbound entry in NAT translation entry list, */
2906 /*                                                                        */
2907 /*  INPUT                                                                 */
2908 /*                                                                        */
2909 /*    nat_ptr                             Pointer to NAT server           */
2910 /*    packet_ptr                          Pointer to packet               */
2911 /*    entry_ptr                           Pointer to NAT entry            */
2912 /*    entry_ptr                           Pointer to the matched entry    */
2913 /*    next_hop_address                    The next hop address for route  */
2914 /*                                                                        */
2915 /*  OUTPUT                                                                */
2916 /*                                                                        */
2917 /*    NX_SUCCESS                        Successful completion status      */
2918 /*                                                                        */
2919 /*  CALLS                                                                 */
2920 /*                                                                        */
2921 /*    _nx_nat_utility_get_source_port   Extract source port from packet   */
2922 /*    _nx_nat_utility_get_destination_port                                */
2923 /*                                      Extract destination port from     */
2924 /*                                           packet                       */
2925 /*    _nx_nat_entry_create              Create entry for packet in NAT    */
2926 /*                                          translation table             */
2927 /*    _nx_nat_entry_find                Find the entry                    */
2928 /*    _nx_ip_route_find                 Find the suitable interface       */
2929 /*                                                                        */
2930 /*  CALLED BY                                                             */
2931 /*                                                                        */
2932 /*   _nx_nat_process_inbound_TCP_packet   Process outbound TCP packet     */
2933 /*   _nx_nat_process_inbound_UDP_packet   Process outbound UDP packet     */
2934 /*   _nx_nat_process_inbound_ICMP_packet  Process outbound ICMP packet    */
2935 /*                                                                        */
2936 /*  RELEASE HISTORY                                                       */
2937 /*                                                                        */
2938 /*    DATE              NAME                      DESCRIPTION             */
2939 /*                                                                        */
2940 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2941 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2942 /*                                            resulting in version 6.1    */
2943 /*                                                                        */
2944 /**************************************************************************/
_nx_nat_inbound_entry_find(NX_NAT_DEVICE * nat_ptr,NX_PACKET * packet_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr,NX_NAT_TRANSLATION_ENTRY ** matched_entry_ptr,ULONG * next_hop_address)2945 static UINT  _nx_nat_inbound_entry_find(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr,
2946                                         NX_NAT_TRANSLATION_ENTRY **matched_entry_ptr, ULONG *next_hop_address)
2947 {
2948 
2949 UINT                            status;
2950 ULONG                           timeout;
2951 NX_NAT_TRANSLATION_ENTRY       *record_entry;
2952 
2953 
2954     /* Check the protocol.  */
2955     if ((entry_ptr -> protocol == NX_PROTOCOL_TCP) || (entry_ptr -> protocol == NX_PROTOCOL_UDP))
2956     {
2957 
2958         /* Get sender's source port. */
2959         _nx_nat_utility_get_source_port(packet_ptr, entry_ptr -> protocol, &entry_ptr -> peer_port);
2960     }
2961 
2962     /* Get the destination port from header data. */
2963     _nx_nat_utility_get_destination_port(packet_ptr, entry_ptr -> protocol, &entry_ptr -> external_port);
2964 
2965     /* Check the timeout for all dynamic entries.  */
2966     _nx_nat_entry_timeout_check(nat_ptr);
2967 
2968     /* Now search the table for a matching NAT translation entry. */
2969     _nx_nat_entry_find(nat_ptr, entry_ptr, &record_entry, NX_NAT_INBOUND_PACKET, NX_TRUE);
2970 
2971     /* Was a matching entry found in our translation table? */
2972     if (!record_entry)
2973     {
2974 
2975         /* Next see if the destination is a local host server.  */
2976 
2977         /* Find a 'server' for packet destination IP address and port */
2978         _nx_nat_entry_find(nat_ptr, entry_ptr, &record_entry, NX_NAT_INBOUND_PACKET, NX_FALSE);
2979 
2980         /* Check the record entry.  */
2981         if (record_entry)
2982         {
2983 
2984             /* We found a matching server entry in the table. Now create an
2985                entry specifically for this packet. */
2986 
2987             /* Get the private IP address from the entry we just found, and apply to the new entry we're creating. */
2988             entry_ptr -> local_ip_address = record_entry -> local_ip_address;
2989 
2990             /* Check the private inside port.  */
2991             if (record_entry -> local_port == 0)
2992             {
2993 
2994                 /* Set the private inside port same as global inside port.  */
2995                 entry_ptr -> local_port = entry_ptr -> external_port;
2996             }
2997             else
2998             {
2999 
3000                 /* Set private inside port. */
3001                 entry_ptr -> local_port = record_entry -> local_port;
3002             }
3003 
3004             /* Set the entry expiration timeout. */
3005             if (entry_ptr -> protocol == NX_PROTOCOL_TCP)
3006             {
3007 
3008                 /* TCP session.  */
3009                 timeout = NX_NAT_TCP_SESSION_TIMEOUT;
3010             }
3011             else
3012             {
3013 
3014                 /* Non-TCP session.  */
3015                 timeout = NX_NAT_NON_TCP_SESSION_TIMEOUT;
3016             }
3017 
3018             /* Now create the entry. */
3019             status = _nx_nat_entry_create(nat_ptr, entry_ptr -> protocol,
3020                                           entry_ptr -> local_ip_address,
3021                                           entry_ptr -> peer_ip_address,
3022                                           entry_ptr -> local_port,
3023                                           entry_ptr -> external_port,
3024                                           entry_ptr -> peer_port,
3025                                           timeout,
3026                                           &record_entry);
3027 
3028             /* Check for error. */
3029             if (status != NX_SUCCESS)
3030             {
3031 
3032                 /* Return status.*/
3033                 return status;
3034             }
3035         }
3036         else
3037         {
3038 
3039             /* Return status.*/
3040             return (NX_NAT_ENTRY_NOT_FOUND);
3041         }
3042     }
3043 
3044     /* Clear the packet interface as private interface.  */
3045     packet_ptr -> nx_packet_address.nx_packet_interface_ptr = NX_NULL;
3046 
3047     /* Set the inbound interface and next hop address.  */
3048     if(_nx_ip_route_find(nat_ptr -> nx_nat_ip_ptr, record_entry -> local_ip_address,
3049                          &packet_ptr -> nx_packet_address.nx_packet_interface_ptr, next_hop_address) != NX_SUCCESS)
3050     {
3051 
3052         /* No suitable private interface configured. */
3053 
3054         /* Return the error status. */
3055         return (NX_NAT_ROUTE_FIND_ERROR);
3056     }
3057 
3058     /* Set the matched entry pointer.  */
3059     *matched_entry_ptr = record_entry;
3060 
3061     /* Return success.  */
3062     return (NX_SUCCESS);
3063 }
3064 
3065 
3066 /**************************************************************************/
3067 /*                                                                        */
3068 /*  FUNCTION                                               RELEASE        */
3069 /*                                                                        */
3070 /*    _nx_nat_outbound_entry_find                         PORTABLE C      */
3071 /*                                                           6.1          */
3072 /*  AUTHOR                                                                */
3073 /*                                                                        */
3074 /*    Yuxin Zhou, Microsoft Corporation                                   */
3075 /*                                                                        */
3076 /*  DESCRIPTION                                                           */
3077 /*                                                                        */
3078 /*   This function finds the outbound entry in NAT translation entry list.*/
3079 /*                                                                        */
3080 /*  INPUT                                                                 */
3081 /*                                                                        */
3082 /*    nat_ptr                             Pointer to NAT server           */
3083 /*    packet_ptr                          Pointer to packet               */
3084 /*    entry_ptr                           Pointer to NAT entry            */
3085 /*    entry_ptr                           Pointer to the matched entry    */
3086 /*    next_hop_address                    The next hop address for route  */
3087 /*                                                                        */
3088 /*  OUTPUT                                                                */
3089 /*                                                                        */
3090 /*    NX_SUCCESS                        Successful completion status      */
3091 /*                                                                        */
3092 /*  CALLS                                                                 */
3093 /*                                                                        */
3094 /*    _nx_nat_utility_get_source_port   Extract source port from packet   */
3095 /*    _nx_nat_utility_get_destination_port                                */
3096 /*                                      Extract destination port from     */
3097 /*                                           packet                       */
3098 /*    _nx_nat_entry_create              Create entry for packet in NAT    */
3099 /*                                          translation table             */
3100 /*    _nx_nat_entry_find                Find the entry                    */
3101 /*    _nx_ip_route_find                 Find the suitable interface       */
3102 /*                                                                        */
3103 /*  CALLED BY                                                             */
3104 /*                                                                        */
3105 /*   _nx_nat_process_outbound_TCP_packet  Process outbound TCP packet     */
3106 /*   _nx_nat_process_outbound_UDP_packet  Process outbound UDP packet     */
3107 /*   _nx_nat_process_outbound_ICMP_packet Process outbound ICMP packet    */
3108 /*                                                                        */
3109 /*  RELEASE HISTORY                                                       */
3110 /*                                                                        */
3111 /*    DATE              NAME                      DESCRIPTION             */
3112 /*                                                                        */
3113 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3114 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3115 /*                                            resulting in version 6.1    */
3116 /*                                                                        */
3117 /**************************************************************************/
_nx_nat_outbound_entry_find(NX_NAT_DEVICE * nat_ptr,NX_PACKET * packet_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr,NX_NAT_TRANSLATION_ENTRY ** matched_entry_ptr,ULONG * next_hop_address)3118 static UINT  _nx_nat_outbound_entry_find(NX_NAT_DEVICE *nat_ptr, NX_PACKET *packet_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr,
3119                                          NX_NAT_TRANSLATION_ENTRY **matched_entry_ptr, ULONG *next_hop_address)
3120 {
3121 
3122 UINT                        status;
3123 ULONG                       timeout;
3124 NX_NAT_TRANSLATION_ENTRY   *record_entry;
3125 
3126 
3127     /* Get source ports from the header. */
3128     _nx_nat_utility_get_source_port(packet_ptr, entry_ptr -> protocol, &(entry_ptr -> local_port));
3129 
3130     /* Check the protocol.  */
3131     if ((entry_ptr -> protocol == NX_PROTOCOL_TCP) || (entry_ptr -> protocol == NX_PROTOCOL_UDP))
3132     {
3133 
3134         /* Get destination port from the header. */
3135         _nx_nat_utility_get_destination_port(packet_ptr, entry_ptr -> protocol, &(entry_ptr -> peer_port));
3136     }
3137 
3138     /* Check the timeout for all dynamic entries.  */
3139     _nx_nat_entry_timeout_check(nat_ptr);
3140 
3141     /* Search the table for a match. */
3142     _nx_nat_entry_find(nat_ptr, entry_ptr, &record_entry, NX_NAT_OUTBOUND_PACKET, NX_TRUE);
3143 
3144     /* Was a matching table entry found? */
3145     if (!record_entry)
3146     {
3147 
3148         /* Find the available port. */
3149         status = _nx_nat_find_available_port(nat_ptr, entry_ptr -> protocol, &entry_ptr -> external_port);
3150 
3151         /* Check for error. */
3152         if (status != NX_SUCCESS)
3153         {
3154 
3155             return status;
3156         }
3157 
3158         /* Set the entry expiration timeout. */
3159         if (entry_ptr -> protocol == NX_PROTOCOL_TCP)
3160         {
3161 
3162             /* TCP session.  */
3163             timeout = NX_NAT_TCP_SESSION_TIMEOUT;
3164         }
3165         else
3166         {
3167 
3168             /* Non-TCP session.  */
3169             timeout = NX_NAT_NON_TCP_SESSION_TIMEOUT;
3170         }
3171 
3172         /* Create an entry with NAT translation for IP address/port. */
3173         status = _nx_nat_entry_create(nat_ptr, entry_ptr -> protocol,
3174                                       entry_ptr -> local_ip_address,
3175                                       entry_ptr -> peer_ip_address,
3176                                       entry_ptr -> local_port,
3177                                       entry_ptr -> external_port,
3178                                       entry_ptr -> peer_port,
3179                                       timeout,
3180                                       &record_entry);
3181 
3182         /* Check for error. */
3183         if (status != NX_SUCCESS)
3184         {
3185 
3186             /* Return error status. */
3187             return status;
3188         }
3189     }
3190 
3191     /* Set the packet interface as global interface.  */
3192     packet_ptr -> nx_packet_address.nx_packet_interface_ptr = &(nat_ptr -> nx_nat_ip_ptr -> nx_ip_interface[nat_ptr -> nx_nat_global_interface_index]);
3193 
3194     /* Set the next hop address.  */
3195     if(_nx_ip_route_find(nat_ptr -> nx_nat_ip_ptr, record_entry -> peer_ip_address, &packet_ptr -> nx_packet_address.nx_packet_interface_ptr, next_hop_address) != NX_SUCCESS)
3196     {
3197 
3198         /* No suitable private interface configured. */
3199 
3200         /* Return the error status. */
3201         return (NX_NAT_ROUTE_FIND_ERROR);
3202     }
3203 
3204     /* Set the matched entry pointer.  */
3205     *matched_entry_ptr = record_entry;
3206 
3207     /* Return success.  */
3208     return (NX_SUCCESS);
3209 }
3210 
3211 
3212 /**************************************************************************/
3213 /*                                                                        */
3214 /*  FUNCTION                                               RELEASE        */
3215 /*                                                                        */
3216 /*    _nx_nat_entry_create                                PORTABLE C      */
3217 /*                                                           6.1          */
3218 /*  AUTHOR                                                                */
3219 /*                                                                        */
3220 /*    Yuxin Zhou, Microsoft Corporation                                   */
3221 /*                                                                        */
3222 /*  DESCRIPTION                                                           */
3223 /*                                                                        */
3224 /*   This function dynamically creates a NAT translation table entry      */
3225 /*   and appends the entry to the  translation list.                      */
3226 /*                                                                        */
3227 /*  INPUT                                                                 */
3228 /*                                                                        */
3229 /*    nat_ptr                           Pointer to NAT instance           */
3230 /*    protocol                          Protocol of packets matching entry*/
3231 /*    local_ip_address                  Entry's private IP address        */
3232 /*    peer_ip_address                   Entry's external host IP          */
3233 /*    local_port                        Entry's private port              */
3234 /*    external_port                     Entry's global port               */
3235 /*    peer_port                         Entry's external port (optional)  */
3236 /*    response_timeout                  Entry expiration timeout          */
3237 /*    match_entry_ptr                   Pointer to entry created          */
3238 /*                                                                        */
3239 /*  OUTPUT                                                                */
3240 /*                                                                        */
3241 /*    status                            Actual completion status          */
3242 /*    NX_SUCCESS                        Successful completion status      */
3243 /*    NX_NAT_TRANSLATION_TABLE_FULL     Table is full (max capacity)      */
3244 /*    NX_NAT_INVALID_TABLE_ENTRY        Invalid criteria for table entry  */
3245 /*                                                                        */
3246 /*  CALLS                                                                 */
3247 /*                                                                        */
3248 /*    _nx_nat_entry_add                Add entry to linked list of entries*/
3249 /*    memset                           Clear specified area of memory     */
3250 /*                                                                        */
3251 /*  CALLED BY                                                             */
3252 /*                                                                        */
3253 /*    _nx_nat_inbound_entry_find        Find inbound entry in entry list  */
3254 /*    _nx_nat_outbound_entry_find       Find outbound entry in entry list */
3255 /*                                                                        */
3256 /*  RELEASE HISTORY                                                       */
3257 /*                                                                        */
3258 /*    DATE              NAME                      DESCRIPTION             */
3259 /*                                                                        */
3260 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3261 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3262 /*                                            resulting in version 6.1    */
3263 /*                                                                        */
3264 /**************************************************************************/
_nx_nat_entry_create(NX_NAT_DEVICE * nat_ptr,UCHAR protocol,ULONG local_ip_address,ULONG peer_ip_address,USHORT local_port,USHORT external_port,USHORT peer_port,ULONG response_timeout,NX_NAT_TRANSLATION_ENTRY ** match_entry_ptr)3265 static UINT  _nx_nat_entry_create(NX_NAT_DEVICE *nat_ptr, UCHAR protocol,
3266                                   ULONG local_ip_address, ULONG peer_ip_address,
3267                                   USHORT local_port, USHORT  external_port, USHORT  peer_port,
3268                                   ULONG response_timeout, NX_NAT_TRANSLATION_ENTRY **match_entry_ptr)
3269 {
3270 
3271 NX_NAT_TRANSLATION_ENTRY *insert_entry_ptr = NX_NULL;
3272 
3273 #ifdef NX_NAT_ENABLE_REPLACEMENT
3274 NX_NAT_TRANSLATION_ENTRY *insert_previous_ptr = NX_NULL;
3275 NX_NAT_TRANSLATION_ENTRY *entry_ptr = NX_NULL;
3276 NX_NAT_TRANSLATION_ENTRY *previous_ptr = NX_NULL;
3277 #endif /* NX_NAT_ENABLE_REPLACEMENT  */
3278 
3279 
3280     /* Initialize result to not found. */
3281     *match_entry_ptr = NX_NULL;
3282 
3283     /* Perform some simple sanity checks on this entry. */
3284 
3285     /* Was an invalid IP address submitted? */
3286     if ((peer_ip_address == 0x0) ||
3287         (local_ip_address == 0x0))
3288     {
3289 
3290         return (NX_NAT_INVALID_ENTRY);
3291     }
3292 
3293     /* Check available entries. */
3294     if (nat_ptr -> nx_nat_dynamic_available_entries)
3295     {
3296 
3297         /* Get one available entry.  */
3298         insert_entry_ptr = nat_ptr -> nx_nat_dynamic_available_entry_head;
3299 
3300         /* Update the entry head.  */
3301         nat_ptr -> nx_nat_dynamic_available_entry_head = insert_entry_ptr -> next_entry_ptr;
3302     }
3303     else
3304     {
3305 #ifdef NX_NAT_ENABLE_REPLACEMENT
3306 
3307         /* Get a pointer to the start of the entries in the translation table. */
3308         entry_ptr = nat_ptr -> nx_nat_dynamic_active_entry_head;
3309 
3310         /* Search the whole entry list to find the oldest non-TCP entry.  */
3311         while (entry_ptr)
3312         {
3313 
3314             /* Check the entry type and protocol.  */
3315             if ((entry_ptr -> translation_type == NX_NAT_STATIC_ENTRY) || (entry_ptr -> protocol == NX_PROTOCOL_TCP))
3316             {
3317 
3318                 /* Ingore this entry, Get the next entry in the table. */
3319                 previous_ptr = entry_ptr;
3320                 entry_ptr = entry_ptr -> next_entry_ptr;
3321                 continue;
3322             }
3323             else
3324             {
3325 
3326                 /* Check if set the insert_entry_ptr(oldest entry).  */
3327                 if (insert_entry_ptr == NX_NULL)
3328                 {
3329 
3330                     /* Assume the first entry is the oldest entry.  */
3331                     insert_entry_ptr = entry_ptr;
3332                     insert_previous_ptr = previous_ptr;
3333                 }
3334                 else
3335                 {
3336 
3337                     /* Compare the timestamp.  */
3338                     if (((INT)insert_entry_ptr -> response_timestamp - (INT)entry_ptr -> response_timestamp) > 0)
3339                     {
3340 
3341                         /* entry_ptr is an older entry, so update the insert_entry_ptr.  */
3342                         insert_entry_ptr = entry_ptr;
3343                         insert_previous_ptr = previous_ptr;
3344                     }
3345                 }
3346 
3347                 /* Get the next entry in the table. */
3348                 previous_ptr = entry_ptr;
3349                 entry_ptr = entry_ptr -> next_entry_ptr;
3350             }
3351         }
3352 
3353         /* Check if found the oldest non-TCP entry.  */
3354         if (insert_entry_ptr)
3355         {
3356 
3357             /* Yes, found it. Check if this is the first entry in the list. */
3358             if (insert_previous_ptr)
3359             {
3360 
3361                 /* It is not, so link the previous entry around the entry we are deleting. */
3362                 insert_previous_ptr -> next_entry_ptr = insert_entry_ptr -> next_entry_ptr;
3363             }
3364             else
3365             {
3366 
3367                 /* It is the first entry, so set the next pointer as the starting translation table entry. */
3368                 nat_ptr -> nx_nat_dynamic_active_entry_head = insert_entry_ptr -> next_entry_ptr;
3369             }
3370 
3371             /* Update the entry count.  */
3372             nat_ptr -> nx_nat_dynamic_active_entries --;
3373             nat_ptr -> nx_nat_dynamic_available_entries ++;
3374         }
3375         else
3376         {
3377 #endif /* NX_NAT_ENABLE_REPLACEMENT  */
3378 
3379             /* This service cache does not have room for the entry. */
3380             /* Invoke user-installed cache full notify function .*/
3381             if(nat_ptr -> nx_nat_cache_full_notify)
3382             {
3383 
3384                 /* Call the callback function.  */
3385                 (nat_ptr -> nx_nat_cache_full_notify)(nat_ptr);
3386             }
3387 
3388             /* Return error status.  */
3389             return (NX_NAT_CACHE_FULL);
3390 
3391 #ifdef NX_NAT_ENABLE_REPLACEMENT
3392         }
3393 #endif /* NX_NAT_ENABLE_REPLACEMENT  */
3394     }
3395 
3396     /* Initialize the allocated memory to NULL. */
3397     memset(insert_entry_ptr, 0, sizeof(NX_NAT_TRANSLATION_ENTRY));
3398 
3399     /* Assign the entry attributes. */
3400     insert_entry_ptr -> protocol = protocol;
3401     insert_entry_ptr -> local_ip_address = local_ip_address;
3402     insert_entry_ptr -> peer_ip_address = peer_ip_address;
3403     insert_entry_ptr -> local_port = local_port;
3404     insert_entry_ptr -> external_port = external_port;
3405     insert_entry_ptr -> peer_port = peer_port;
3406     insert_entry_ptr -> response_timeout = response_timeout;
3407 
3408     /* Set the entry timestamp.  */
3409     insert_entry_ptr -> response_timestamp = tx_time_get();
3410 
3411     /* Set entry type to dynamically created. */
3412     insert_entry_ptr -> translation_type = NX_NAT_DYNAMIC_ENTRY;
3413 
3414     /* Append to the table. */
3415     _nx_nat_entry_add(nat_ptr, insert_entry_ptr);
3416 
3417     /* Set a pointer to the newly created entry. */
3418     *match_entry_ptr = insert_entry_ptr;
3419 
3420     /* Return successful completion status. */
3421     return (NX_SUCCESS);
3422 }
3423 
3424 
3425 /**************************************************************************/
3426 /*                                                                        */
3427 /*  FUNCTION                                               RELEASE        */
3428 /*                                                                        */
3429 /*    _nx_nat_entry_add                                   PORTABLE C      */
3430 /*                                                           6.1          */
3431 /*  AUTHOR                                                                */
3432 /*                                                                        */
3433 /*    Yuxin Zhou, Microsoft Corporation                                   */
3434 /*                                                                        */
3435 /*  DESCRIPTION                                                           */
3436 /*                                                                        */
3437 /*   This function adds a NAT translation entry to the NAT entry list     */
3438 /*                                                                        */
3439 /*  INPUT                                                                 */
3440 /*                                                                        */
3441 /*    nat_ptr                           Pointer to NAT instance           */
3442 /*    entry_ptr                         Pointer to NAT translation entry  */
3443 /*                                                                        */
3444 /*  OUTPUT                                                                */
3445 /*                                                                        */
3446 /*    NX_SUCCESS                        Successful completion status      */
3447 /*                                                                        */
3448 /*  CALLS                                                                 */
3449 /*                                                                        */
3450 /*    None                                                                */
3451 /*                                                                        */
3452 /*  CALLED BY                                                             */
3453 /*                                                                        */
3454 /*    _nx_nat_inbound_entry_create     Create inbound entry to NAT table  */
3455 /*                                       before starting the NAT server   */
3456 /*    _nx_nat_entry_create             Create and add entry to NAT table  */
3457 /*                                         after starting the NAT server  */
3458 /*                                                                        */
3459 /*  RELEASE HISTORY                                                       */
3460 /*                                                                        */
3461 /*    DATE              NAME                      DESCRIPTION             */
3462 /*                                                                        */
3463 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3464 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3465 /*                                            resulting in version 6.1    */
3466 /*                                                                        */
3467 /**************************************************************************/
_nx_nat_entry_add(NX_NAT_DEVICE * nat_ptr,NX_NAT_TRANSLATION_ENTRY * entry_ptr)3468 static UINT  _nx_nat_entry_add(NX_NAT_DEVICE *nat_ptr, NX_NAT_TRANSLATION_ENTRY *entry_ptr)
3469 {
3470 
3471 
3472     /* Add this entry onto the table entry list.  */
3473     entry_ptr -> next_entry_ptr = nat_ptr -> nx_nat_dynamic_active_entry_head;
3474     nat_ptr -> nx_nat_dynamic_active_entry_head = entry_ptr;
3475 
3476     /* Update the entry count.  */
3477     if (entry_ptr -> translation_type == NX_NAT_DYNAMIC_ENTRY)
3478     {
3479 
3480         /* Update the entry count.  */
3481         nat_ptr -> nx_nat_dynamic_active_entries ++;
3482         nat_ptr -> nx_nat_dynamic_available_entries --;
3483     }
3484     else
3485         nat_ptr -> nx_nat_static_active_entries ++;
3486 
3487     /* Return success status. */
3488     return(NX_SUCCESS);
3489 }
3490 
3491 
3492 /**************************************************************************/
3493 /*                                                                        */
3494 /*  FUNCTION                                               RELEASE        */
3495 /*                                                                        */
3496 /*    _nx_nat_entry_find                                  PORTABLE C      */
3497 /*                                                           6.1          */
3498 /*  AUTHOR                                                                */
3499 /*                                                                        */
3500 /*    Yuxin Zhou, Microsoft Corporation                                   */
3501 /*                                                                        */
3502 /*  DESCRIPTION                                                           */
3503 /*                                                                        */
3504 /*    This function attempts to find an entry in the NAT translation list */
3505 /*    that matches the entry submitted by the caller.  If none is found it*/
3506 /*    returns a null pointer. There is an option to skip entries          */
3507 /*    designated for local hosts accepting packets from external hosts    */
3508 /*    (e.g. servers).                                                     */
3509 /*                                                                        */
3510 /*  INPUT                                                                 */
3511 /*                                                                        */
3512 /*    nat_ptr                     Pointer to NAT server                   */
3513 /*    entry_to_match              Pointer to entry to match in the list   */
3514 /*    match_entry_ptr             Pointer to matching entry in the list   */
3515 /*    direction                   Forward direction(inbound/outbound)     */
3516 /*    skip_inbound_init_entries   Skip entries for local hosts allowing   */
3517 /*                                   initial packet from external source  */
3518 /*                                                                        */
3519 /*  OUTPUT                                                                */
3520 /*                                                                        */
3521 /*    NX_SUCCESS                       Successful completion status       */
3522 /*    status                           Actual completion status           */
3523 /*                                                                        */
3524 /*  CALLS                                                                 */
3525 /*                                                                        */
3526 /*    tx_time_get                      Get the system time                */
3527 /*                                                                        */
3528 /*  CALLED BY                                                             */
3529 /*                                                                        */
3530 /*    _nx_nat_inbound_entry_find       Find inbound entry in entry list   */
3531 /*    _nx_nat_outbound_entry_find      Find outbound entry in entry list  */
3532 /*                                                                        */
3533 /*  RELEASE HISTORY                                                       */
3534 /*                                                                        */
3535 /*    DATE              NAME                      DESCRIPTION             */
3536 /*                                                                        */
3537 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3538 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3539 /*                                            resulting in version 6.1    */
3540 /*                                                                        */
3541 /**************************************************************************/
_nx_nat_entry_find(NX_NAT_DEVICE * nat_ptr,NX_NAT_TRANSLATION_ENTRY * entry_to_match,NX_NAT_TRANSLATION_ENTRY ** match_entry_ptr,UCHAR direction,UINT skip_static_entries)3542 static VOID  _nx_nat_entry_find(NX_NAT_DEVICE *nat_ptr, NX_NAT_TRANSLATION_ENTRY *entry_to_match, NX_NAT_TRANSLATION_ENTRY **match_entry_ptr,
3543                                 UCHAR direction, UINT skip_static_entries)
3544 {
3545 
3546 NX_NAT_TRANSLATION_ENTRY    *entry_ptr;
3547 NX_NAT_TRANSLATION_ENTRY    *previous_ptr;
3548 
3549 
3550     /* Initialize the search result to null (no match found). */
3551     *match_entry_ptr = 0x0;
3552 
3553     /* Check the inbound entry.  */
3554     if ((direction == NX_NAT_INBOUND_PACKET) &&
3555         (!entry_to_match -> peer_ip_address))
3556     {
3557 
3558         /* Return. */
3559         return;
3560     }
3561 
3562     /* Check the outbound entry.  */
3563     if ((direction == NX_NAT_OUTBOUND_PACKET) &&
3564         ((!entry_to_match -> local_ip_address) || (!entry_to_match -> peer_ip_address)))
3565     {
3566 
3567         /* Return. */
3568         return ;
3569     }
3570 
3571     /* Initialize the previous pointer.  */
3572     previous_ptr = NX_NULL;
3573 
3574     /* Get a pointer to the start of the entries in the translation table. */
3575     entry_ptr = nat_ptr -> nx_nat_dynamic_active_entry_head;
3576 
3577     /* Search the whole table until a match is found. */
3578     while (entry_ptr)
3579     {
3580 
3581         /* Check the entry type, (e.g. accepts packets from external hosts) ?*/
3582         if ((entry_ptr -> translation_type == NX_NAT_STATIC_ENTRY) && (skip_static_entries == NX_TRUE))
3583         {
3584 
3585             /* Set the previous entry pointer.  */
3586             previous_ptr = entry_ptr;
3587 
3588             /* Ingore the static entry, get the next entry in the table. */
3589             entry_ptr = entry_ptr -> next_entry_ptr;
3590 
3591             continue;
3592         }
3593 
3594         /* Do sender and entry protocols match? */
3595         if (entry_ptr -> protocol != entry_to_match -> protocol)
3596         {
3597 
3598             /* Set the previous entry pointer.  */
3599             previous_ptr = entry_ptr;
3600 
3601             /* Get the next entry in the table. */
3602             entry_ptr = entry_ptr -> next_entry_ptr;
3603 
3604             continue;
3605         }
3606 
3607         /* Continue matching IP address and port criteria. */
3608 
3609         /* Do external IP addresses, if specified, match? */
3610         if ((entry_ptr -> peer_ip_address) &&
3611             (entry_ptr -> peer_ip_address != entry_to_match -> peer_ip_address))
3612         {
3613 
3614             /* Set the previous entry pointer.  */
3615             previous_ptr = entry_ptr;
3616 
3617             /* No, get the next entry. */
3618             entry_ptr = entry_ptr -> next_entry_ptr;
3619 
3620             continue;
3621         }
3622 
3623         /* Do external ports, if specified match? */
3624         if ((entry_ptr -> peer_port) &&
3625             (entry_ptr -> peer_port != entry_to_match -> peer_port))
3626         {
3627 
3628             /* Set the previous entry pointer.  */
3629             previous_ptr = entry_ptr;
3630 
3631             /* No, get the next entry in the table. */
3632             entry_ptr = entry_ptr -> next_entry_ptr;
3633 
3634             continue;
3635         }
3636 
3637         /* Check the inbound entry.  */
3638         if (direction == NX_NAT_INBOUND_PACKET)
3639         {
3640 
3641             /* Does the inside host global port, if specified, match? */
3642             if ((entry_ptr -> external_port) &&
3643                 (entry_ptr -> external_port != entry_to_match -> external_port))
3644             {
3645 
3646                 /* Set the previous entry pointer.  */
3647                 previous_ptr = entry_ptr;
3648 
3649                 /* No, get the next entry in the table. */
3650                 entry_ptr = entry_ptr -> next_entry_ptr;
3651 
3652                 continue;
3653             }
3654         }
3655         else
3656         {
3657 
3658             /* Do private inside IP addresses, if specified, match? */
3659             if ((entry_ptr -> local_ip_address) &&
3660                 (entry_ptr -> local_ip_address != entry_to_match -> local_ip_address))
3661             {
3662 
3663                 /* Set the previous entry pointer.  */
3664                 previous_ptr = entry_ptr;
3665 
3666                 /* No, get the next entry in the table. */
3667                 entry_ptr = entry_ptr -> next_entry_ptr;
3668 
3669                 continue;
3670             }
3671 
3672             /* Does the inside host private port, if specified, match? */
3673             if ((entry_ptr -> local_port) &&
3674                 (entry_ptr -> local_port != entry_to_match -> local_port))
3675             {
3676 
3677                 /* Set the previous entry pointer.  */
3678                 previous_ptr = entry_ptr;
3679 
3680                 /* No, get the next entry in the table. */
3681                 entry_ptr = entry_ptr -> next_entry_ptr;
3682 
3683                 continue;
3684             }
3685         }
3686 
3687         /* If we got this far, all criteria matched up. Set a pointer to
3688            this entry in the table. */
3689         *match_entry_ptr = entry_ptr;
3690 
3691         /* The entry is active, reset the timeout to the present.  */
3692         entry_ptr -> response_timestamp = tx_time_get();
3693 
3694         /* Yes; check if this is the first entry in the list. */
3695         if (previous_ptr)
3696         {
3697 
3698             /* It is not. Put this entry at the head of the list to improve searching effectiveness. */
3699             previous_ptr -> next_entry_ptr = entry_ptr -> next_entry_ptr;
3700             entry_ptr -> next_entry_ptr = nat_ptr -> nx_nat_dynamic_active_entry_head;
3701             nat_ptr -> nx_nat_dynamic_active_entry_head = entry_ptr;
3702         }
3703         break;
3704     }
3705     return;
3706 }
3707 
3708 
3709 /**************************************************************************/
3710 /*                                                                        */
3711 /*  FUNCTION                                               RELEASE        */
3712 /*                                                                        */
3713 /*    _nx_nat_entry_timeout_check                         PORTABLE C      */
3714 /*                                                           6.1          */
3715 /*  AUTHOR                                                                */
3716 /*                                                                        */
3717 /*    Yuxin Zhou, Microsoft Corporation                                   */
3718 /*                                                                        */
3719 /*  DESCRIPTION                                                           */
3720 /*                                                                        */
3721 /*    This function attempts to check the entry's timeout, and remove the */
3722 /*    expiration entries from dynamic active translation list.            */
3723 /*                                                                        */
3724 /*  INPUT                                                                 */
3725 /*                                                                        */
3726 /*    nat_ptr                          Pointer to NAT server              */
3727 /*                                                                        */
3728 /*  OUTPUT                                                                */
3729 /*                                                                        */
3730 /*    NX_SUCCESS                       Successful completion status       */
3731 /*                                                                        */
3732 /*  CALLS                                                                 */
3733 /*                                                                        */
3734 /*    tx_time_get                      Get the system time                */
3735 /*                                                                        */
3736 /*  CALLED BY                                                             */
3737 /*                                                                        */
3738 /*    _nx_nat_inbound_entry_find       Find inbound entry in entry list   */
3739 /*    _nx_nat_outbound_entry_find      Find outbound entry in entry list  */
3740 /*                                                                        */
3741 /*  RELEASE HISTORY                                                       */
3742 /*                                                                        */
3743 /*    DATE              NAME                      DESCRIPTION             */
3744 /*                                                                        */
3745 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3746 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3747 /*                                            resulting in version 6.1    */
3748 /*                                                                        */
3749 /**************************************************************************/
_nx_nat_entry_timeout_check(NX_NAT_DEVICE * nat_ptr)3750 static VOID  _nx_nat_entry_timeout_check(NX_NAT_DEVICE *nat_ptr)
3751 {
3752 
3753 ULONG                       current_time;
3754 ULONG                       elapsed_time;
3755 NX_NAT_TRANSLATION_ENTRY    *entry_ptr;
3756 NX_NAT_TRANSLATION_ENTRY    *previous_ptr;
3757 NX_NAT_TRANSLATION_ENTRY    *next_entry_ptr;
3758 
3759 
3760     /* Get the current time.  */
3761     current_time = tx_time_get();
3762 
3763     /* Get a pointer to the start of the entries in the translation table. */
3764     entry_ptr = nat_ptr -> nx_nat_dynamic_active_entry_head;
3765 
3766     /* Initialize the previous pointer.  */
3767     previous_ptr = NX_NULL;
3768 
3769     /* Search thru the whole entry list. */
3770     while (entry_ptr)
3771     {
3772 
3773         /* Set a pointer to the next entry in the table. */
3774         next_entry_ptr = entry_ptr -> next_entry_ptr;
3775 
3776         /* Check the entry type and update the time.  */
3777         if (entry_ptr -> translation_type == NX_NAT_DYNAMIC_ENTRY)
3778         {
3779 
3780             /* Calculate the elapsed time.  */
3781             elapsed_time = current_time - entry_ptr -> response_timestamp;
3782 
3783             /* Update the time remaining.  */
3784             if (elapsed_time >= entry_ptr -> response_timeout)
3785             {
3786 
3787                 /* Delete this entry from active entry list.  */
3788 
3789                 /* Check if this is the first entry in the list). */
3790                 if (previous_ptr)
3791                 {
3792 
3793                     /* It is not, so link the previous entry around the entry we are deleting. */
3794                     previous_ptr -> next_entry_ptr = next_entry_ptr;
3795                 }
3796                 else
3797                 {
3798 
3799                     /* It is the first entry, so set the next pointer as the starting translation table entry. */
3800                     nat_ptr -> nx_nat_dynamic_active_entry_head = next_entry_ptr;
3801                 }
3802 
3803                 /* Add the entry onto available entry list.  */
3804                 entry_ptr -> next_entry_ptr = nat_ptr -> nx_nat_dynamic_available_entry_head;
3805                 nat_ptr -> nx_nat_dynamic_available_entry_head = entry_ptr;
3806 
3807                 /* Update the entry count.  */
3808                 nat_ptr -> nx_nat_dynamic_active_entries --;
3809                 nat_ptr -> nx_nat_dynamic_available_entries ++;
3810             }
3811             else
3812             {
3813 
3814                 /* Set the previous entry. */
3815                 previous_ptr = entry_ptr;
3816             }
3817         }
3818         else
3819         {
3820 
3821             /* Set the previous entry. */
3822             previous_ptr = entry_ptr;
3823         }
3824 
3825         /* Get the next entry in the table. */
3826         entry_ptr = next_entry_ptr;
3827     }
3828 
3829     return;
3830 }
3831 
3832 
3833 /**************************************************************************/
3834 /*                                                                        */
3835 /*  FUNCTION                                               RELEASE        */
3836 /*                                                                        */
3837 /*    _nx_nat_utility_get_destination_port                PORTABLE C      */
3838 /*                                                           6.1          */
3839 /*  AUTHOR                                                                */
3840 /*                                                                        */
3841 /*    Yuxin Zhou, Microsoft Corporation                                   */
3842 /*                                                                        */
3843 /*  DESCRIPTION                                                           */
3844 /*                                                                        */
3845 /*   This function extracts the destination port from the packet's        */
3846 /*   protocol header. In the case of ICMP packets, it extracts the ICMP   */
3847 /*   header identifier (ID) instead.                                      */
3848 /*                                                                        */
3849 /*  INPUT                                                                 */
3850 /*                                                                        */
3851 /*    packet_ptr                  Pointer to packet with destination port */
3852 /*    protocol                    Packet protocol (TCP, UDP etc)          */
3853 /*    peer_port                   Pointer to external (destination) port  */
3854 /*                                                                        */
3855 /*  OUTPUT                                                                */
3856 /*                                                                        */
3857 /*    NX_SUCCESS                  Successful completion status            */
3858 /*                                                                        */
3859 /*  CALLS                                                                 */
3860 /*                                                                        */
3861 /*    _nx_nat_packet_is_icmp_error_message                                */
3862 /*                                Indicate if ICMP packet is query or     */
3863 /*                                     error message packet               */
3864 /*                                                                        */
3865 /*  CALLED BY                                                             */
3866 /*                                                                        */
3867 /*    _nx_nat_inbound_entry_find       Find inbound entry in entry list   */
3868 /*    _nx_nat_outbound_entry_find      Find outbound entry in entry list  */
3869 /*                                                                        */
3870 /*  RELEASE HISTORY                                                       */
3871 /*                                                                        */
3872 /*    DATE              NAME                      DESCRIPTION             */
3873 /*                                                                        */
3874 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3875 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3876 /*                                            resulting in version 6.1    */
3877 /*                                                                        */
3878 /**************************************************************************/
_nx_nat_utility_get_destination_port(NX_PACKET * packet_ptr,UCHAR protocol,USHORT * peer_port)3879 static UINT  _nx_nat_utility_get_destination_port(NX_PACKET *packet_ptr, UCHAR protocol, USHORT *peer_port)
3880 {
3881 
3882 NX_TCP_HEADER           *tcp_header_ptr;
3883 NX_UDP_HEADER           *udp_header_ptr;
3884 NX_ICMP_HEADER          *icmp_header_ptr;
3885 UINT                    is_icmp_error_msg;
3886 
3887 
3888     /* Is this a TCP packet? */
3889     if (protocol == NX_PROTOCOL_TCP)
3890     {
3891 
3892         /* Pickup the pointer to the head of the TCP packet.  */
3893         tcp_header_ptr =  (NX_TCP_HEADER *)(packet_ptr -> nx_packet_prepend_ptr);
3894 
3895         /* Pickup the destination TCP port.  */
3896         *peer_port =  (USHORT) (tcp_header_ptr -> nx_tcp_header_word_0 & NX_LOWER_16_MASK);
3897     }
3898     /* Is this a UDP packet? */
3899     else if (protocol == NX_PROTOCOL_UDP)
3900     {
3901 
3902         /* Pickup the pointer to the head of the UDP packet.  */
3903         udp_header_ptr =  (NX_UDP_HEADER *)(packet_ptr -> nx_packet_prepend_ptr);
3904 
3905         /* Pickup the destination UDP port.  */
3906         *peer_port =  (USHORT) (udp_header_ptr -> nx_udp_header_word_0 & NX_LOWER_16_MASK);
3907     }
3908     /* Is this an ICMP packet? */
3909     else if (protocol == NX_PROTOCOL_ICMP)
3910     {
3911 
3912         /* Determin type of ICMP message. */
3913         _nx_nat_packet_is_icmp_error_message(packet_ptr, &is_icmp_error_msg);
3914 
3915         /* Is this an ICMP error message? */
3916         if (is_icmp_error_msg )
3917         {
3918 
3919             /* Yes, these don't have query ID fields. */
3920             *peer_port = 0;
3921         }
3922         else
3923         {
3924 
3925             /* Setup the pointer to the ICMP header located in the data area after the IP header.  */
3926             icmp_header_ptr =  (NX_ICMP_HEADER *) (packet_ptr -> nx_packet_prepend_ptr);
3927 
3928             /* Pickup the ICMP identifier which we will call the 'source port'.  */
3929             *peer_port =  (USHORT) (icmp_header_ptr -> nx_icmp_header_word_1 >> NX_SHIFT_BY_16);
3930         }
3931     }
3932     else
3933     {
3934 
3935         /* Unknown or unsupported packet protocol. */
3936         *peer_port = 0;
3937     }
3938 
3939     return NX_SUCCESS;
3940 }
3941 
3942 
3943 /**************************************************************************/
3944 /*                                                                        */
3945 /*  FUNCTION                                               RELEASE        */
3946 /*                                                                        */
3947 /*    _nx_nat_utility_get_source_port                     PORTABLE C      */
3948 /*                                                           6.1          */
3949 /*  AUTHOR                                                                */
3950 /*                                                                        */
3951 /*    Yuxin Zhou, Microsoft Corporation                                   */
3952 /*                                                                        */
3953 /*  DESCRIPTION                                                           */
3954 /*                                                                        */
3955 /*   This function extracts the source port from the packet's protocol    */
3956 /*   header. In the case of ICMP packets, it extracts the query identifier*/
3957 /*   (ID) instead.                                                        */
3958 /*                                                                        */
3959 /*  INPUT                                                                 */
3960 /*                                                                        */
3961 /*    packet_ptr                    Pointer to packet to get source port  */
3962 /*    protocol                      Packet protocol (TCP, UDP etc)        */
3963 /*    source_port                   Pointer to packet source port         */
3964 /*                                                                        */
3965 /*  OUTPUT                                                                */
3966 /*                                                                        */
3967 /*    NX_SUCCESS                     Successful completion status         */
3968 /*                                                                        */
3969 /*  CALLS                                                                 */
3970 /*                                                                        */
3971 /*    _nx_nat_packet_is_icmp_error_message                                */
3972 /*                                   Indicate if ICMP packet is query or  */
3973 /*                                     error message ICMP packet          */
3974 /*                                                                        */
3975 /*  CALLED BY                                                             */
3976 /*                                                                        */
3977 /*    _nx_nat_inbound_entry_find       Find inbound entry in entry list   */
3978 /*    _nx_nat_outbound_entry_find      Find outbound entry in entry list  */
3979 /*                                                                        */
3980 /*  RELEASE HISTORY                                                       */
3981 /*                                                                        */
3982 /*    DATE              NAME                      DESCRIPTION             */
3983 /*                                                                        */
3984 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3985 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3986 /*                                            resulting in version 6.1    */
3987 /*                                                                        */
3988 /**************************************************************************/
_nx_nat_utility_get_source_port(NX_PACKET * packet_ptr,UCHAR protocol,USHORT * source_port)3989 static UINT  _nx_nat_utility_get_source_port(NX_PACKET *packet_ptr, UCHAR protocol, USHORT *source_port)
3990 {
3991 
3992 NX_TCP_HEADER           *tcp_header_ptr;
3993 NX_UDP_HEADER           *udp_header_ptr;
3994 NX_ICMP_HEADER          *icmp_header_ptr;
3995 UINT                    is_icmp_error_msg;
3996 
3997     if (protocol == NX_PROTOCOL_TCP)
3998     {
3999 
4000         /* Pickup the pointer to the head of the TCP packet.  */
4001         tcp_header_ptr =  (NX_TCP_HEADER *)(packet_ptr -> nx_packet_prepend_ptr);
4002 
4003         /* Pickup the source TCP port.  */
4004         *source_port =  (USHORT) (tcp_header_ptr -> nx_tcp_header_word_0 >> NX_SHIFT_BY_16);
4005     }
4006     else if (protocol == NX_PROTOCOL_UDP)
4007     {
4008 
4009         /* Pickup the pointer to the head of the UDP packet.  */
4010         udp_header_ptr =  (NX_UDP_HEADER *)(packet_ptr -> nx_packet_prepend_ptr);
4011 
4012         /* Pickup the source UDP port.  */
4013         *source_port =  (USHORT) (udp_header_ptr -> nx_udp_header_word_0 >> NX_SHIFT_BY_16);
4014     }
4015     else if (protocol == NX_PROTOCOL_ICMP)
4016     {
4017 
4018         /* Determine type of ICMP message. */
4019         _nx_nat_packet_is_icmp_error_message(packet_ptr, &is_icmp_error_msg);
4020 
4021         /* Is this an ICMP error message? */
4022         if (is_icmp_error_msg )
4023         {
4024 
4025             /* Yes, return a zero query ID (error messages have no Query ID). */
4026             *source_port = 0;
4027         }
4028         else
4029         {
4030 
4031             /* Setup the pointer to the ICMP header located in the data area after the IP header.  */
4032             icmp_header_ptr =  (NX_ICMP_HEADER *) (packet_ptr -> nx_packet_prepend_ptr);
4033 
4034             /* Pickup the ICMP Query ID which is used in place of a source port.  */
4035             *source_port =  (USHORT)(icmp_header_ptr -> nx_icmp_header_word_1 >> NX_SHIFT_BY_16);
4036         }
4037     }
4038     else
4039         /* Unknown or unsupported protocol. */
4040         *source_port = 0;
4041 
4042     return NX_SUCCESS;
4043 }
4044 
4045 
4046 /**************************************************************************/
4047 /*                                                                        */
4048 /*  FUNCTION                                               RELEASE        */
4049 /*                                                                        */
4050 /*    _nx_nat_find_available_port                         PORTABLE C      */
4051 /*                                                           6.1          */
4052 /*  AUTHOR                                                                */
4053 /*                                                                        */
4054 /*    Yuxin Zhou, Microsoft Corporation                                   */
4055 /*                                                                        */
4056 /*  DESCRIPTION                                                           */
4057 /*                                                                        */
4058 /*   This function finds an available a ICMP query identifier (ID) or     */
4059 /*   or TCP/UDP port when NAT is configured to share a global IP address  */
4060 /*   among its local hosts and consequently must use the query ID/port    */
4061 /*   field to uniquely identify.                                          */
4062 /*                                                                        */
4063 /*  INPUT                                                                 */
4064 /*                                                                        */
4065 /*    nat_ptr                           Pointer to NAT instance           */
4066 /*    protocol                          Network protocol(TCP, UDP, ICMP)  */
4067 /*    port                              Pointer to an unused port         */
4068 /*                                                                        */
4069 /*  OUTPUT                                                                */
4070 /*                                                                        */
4071 /*    NX_SUCCESS                       Successful completion status       */
4072 /*    NX_NAT_NO_FREE_PORT_AVAILABLE    No free port found status          */
4073 /*    status                           Actual completion status           */
4074 /*                                                                        */
4075 /*  CALLS                                                                 */
4076 /*                                                                        */
4077 /*    None                                                                */
4078 /*                                                                        */
4079 /*  CALLED BY                                                             */
4080 /*                                                                        */
4081 /*    _nx_nat_outbound_entry_find      Find outbound entry in entry list  */
4082 /*                                                                        */
4083 /*  RELEASE HISTORY                                                       */
4084 /*                                                                        */
4085 /*    DATE              NAME                      DESCRIPTION             */
4086 /*                                                                        */
4087 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4088 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4089 /*                                            resulting in version 6.1    */
4090 /*                                                                        */
4091 /**************************************************************************/
_nx_nat_find_available_port(NX_NAT_DEVICE * nat_ptr,UCHAR protocol,USHORT * port)4092 static UINT  _nx_nat_find_available_port(NX_NAT_DEVICE *nat_ptr, UCHAR protocol, USHORT *port)
4093 {
4094 
4095 UINT                     bound;
4096 USHORT                   start_port;
4097 USHORT                   end_port;
4098 NX_NAT_TRANSLATION_ENTRY *entry_ptr;
4099 
4100 
4101     /* Start at the lowest of number for translated query ID/port for NAT. */
4102     if (protocol == NX_PROTOCOL_TCP)
4103     {
4104         start_port = NX_NAT_START_TCP_PORT;
4105         end_port = NX_NAT_END_TCP_PORT;
4106     }
4107     else if(protocol == NX_PROTOCOL_UDP)
4108     {
4109         start_port = NX_NAT_START_UDP_PORT;
4110         end_port = NX_NAT_END_UDP_PORT;
4111     }
4112     else
4113     {
4114         start_port = NX_NAT_START_ICMP_QUERY_ID;
4115         end_port = NX_NAT_END_ICMP_QUERY_ID;
4116     }
4117 
4118     /* Set the start port.  */
4119     *port = start_port;
4120 
4121     /* Search for a Query ID not found in the translation table. */
4122     while(*port < end_port)
4123     {
4124 
4125         /* Initialize the bound flag. */
4126         bound = NX_FALSE;
4127 
4128         /* Serach dynamic entries.  */
4129         entry_ptr = nat_ptr -> nx_nat_dynamic_active_entry_head;
4130 
4131         /* Loop through the whole translation table. */
4132         while(entry_ptr)
4133         {
4134 
4135             /* Check the protocol.  */
4136             if (entry_ptr -> protocol == protocol)
4137             {
4138 
4139                 /* Does this entry have a matching port ID. */
4140                 if (entry_ptr -> external_port == *port)
4141                 {
4142 
4143                     /* Set the flag so we can abort the current search. */
4144                     bound = NX_TRUE;
4145                     break;
4146                 }
4147             }
4148 
4149             /* Get the next entry in the table. */
4150             entry_ptr = entry_ptr -> next_entry_ptr;
4151         }
4152 
4153         /* Check if we got through the entire table with no bound port. */
4154         if ((bound == NX_FALSE) &&
4155             ((protocol == NX_PROTOCOL_TCP) || (protocol == NX_PROTOCOL_UDP)))
4156         {
4157 
4158             /* Yes, check the NetXDuo TCP/UDP socket.   */
4159             bound = _nx_nat_socket_port_verify(nat_ptr -> nx_nat_ip_ptr, protocol, *port);
4160         }
4161 
4162         /* Check if we found a socket with a matching port. */
4163         if (bound == NX_FALSE)
4164         {
4165 
4166             /* We did not. OK to use this port. */
4167             return NX_SUCCESS;
4168         }
4169 
4170         /* Found a match. This port is not available.  */
4171 
4172         /* Bump the port up one. */
4173         (*port)++;
4174     }
4175 
4176     /* If we got here we could not find a free port. */
4177     return (NX_NAT_NO_FREE_PORT_AVAILABLE);
4178 }
4179 
4180 
4181 /**************************************************************************/
4182 /*                                                                        */
4183 /*  FUNCTION                                               RELEASE        */
4184 /*                                                                        */
4185 /*    _nx_nat_entry_port_verify                           PORTABLE C      */
4186 /*                                                           6.1          */
4187 /*  AUTHOR                                                                */
4188 /*                                                                        */
4189 /*    Yuxin Zhou, Microsoft Corporation                                   */
4190 /*                                                                        */
4191 /*  DESCRIPTION                                                           */
4192 /*                                                                        */
4193 /*    This function verifies whether the supplied port is bound. lookup   */
4194 /*    all NAT translation entries, If same ports are found, return        */
4195 /*    NX_TRUE, else return NX_FALSE.                                      */
4196 /*                                                                        */
4197 /*  INPUT                                                                 */
4198 /*                                                                        */
4199 /*    ip_ptr                                IP instance pointer           */
4200 /*    protocol                              Protocol                      */
4201 /*    port                                  Port                          */
4202 /*                                                                        */
4203 /*  OUTPUT                                                                */
4204 /*                                                                        */
4205 /*    bound                                 Completion status             */
4206 /*                                            NX_TRUE: port is bound      */
4207 /*                                            NX_FALSE: port is not bound */
4208 /*                                                                        */
4209 /*  CALLS                                                                 */
4210 /*                                                                        */
4211 /*    none                                                                */
4212 /*                                                                        */
4213 /*  CALLED BY                                                             */
4214 /*                                                                        */
4215 /*    Application Code                                                    */
4216 /*                                                                        */
4217 /*  RELEASE HISTORY                                                       */
4218 /*                                                                        */
4219 /*    DATE              NAME                      DESCRIPTION             */
4220 /*                                                                        */
4221 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4222 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4223 /*                                            resulting in version 6.1    */
4224 /*                                                                        */
4225 /**************************************************************************/
_nx_nat_entry_port_verify(NX_IP * ip_ptr,UINT protocol,UINT port)4226 static UINT  _nx_nat_entry_port_verify(NX_IP *ip_ptr, UINT protocol, UINT port)
4227 {
4228 
4229 UINT                bound;
4230 NX_NAT_TRANSLATION_ENTRY *entry_ptr;
4231 
4232     NX_PARAMETER_NOT_USED(ip_ptr);
4233 
4234     /* Initialize the return value.  */
4235     bound = NX_FALSE;
4236 
4237     /* Serach dynamic entries.  */
4238     entry_ptr = nat_server_ptr -> nx_nat_dynamic_active_entry_head;
4239 
4240     /* Loop through the whole translation table. */
4241     while(entry_ptr)
4242     {
4243 
4244         /* Check the protocol.  */
4245         if (entry_ptr -> protocol == protocol)
4246         {
4247 
4248             /* Does this entry have a matching port ID. */
4249             if (entry_ptr -> external_port == port)
4250             {
4251 
4252                 /* Set the flag so we can abort the current search. */
4253                 bound = NX_TRUE;
4254                 break;
4255             }
4256         }
4257 
4258         /* Get the next entry in the table. */
4259         entry_ptr = entry_ptr -> next_entry_ptr;
4260     }
4261 
4262     /* Return status to the caller.  */
4263     return(bound);
4264 }
4265 
4266 
4267 /**************************************************************************/
4268 /*                                                                        */
4269 /*  FUNCTION                                               RELEASE        */
4270 /*                                                                        */
4271 /*    _nx_nat_socket_port_verify                          PORTABLE C      */
4272 /*                                                           6.1          */
4273 /*  AUTHOR                                                                */
4274 /*                                                                        */
4275 /*    Yuxin Zhou, Microsoft Corporation                                   */
4276 /*                                                                        */
4277 /*  DESCRIPTION                                                           */
4278 /*                                                                        */
4279 /*    This function verifies whether the supplied port is bound. Search   */
4280 /*    all TCP/UDP sockets, and if the port is found, return NX_TRUE,      */
4281 /*    else return NX_TRUE.                                                */
4282 /*                                                                        */
4283 /*  INPUT                                                                 */
4284 /*                                                                        */
4285 /*    ip_ptr                                IP instance pointer           */
4286 /*    protocol                              Protocol                      */
4287 /*    port                                  Port                          */
4288 /*                                                                        */
4289 /*  OUTPUT                                                                */
4290 /*                                                                        */
4291 /*    bound                                 Completion status             */
4292 /*                                            NX_TRUE: port is bound      */
4293 /*                                            NX_FALSE: port is not bound */
4294 /*                                                                        */
4295 /*  CALLS                                                                 */
4296 /*                                                                        */
4297 /*    none                                                                */
4298 /*                                                                        */
4299 /*  CALLED BY                                                             */
4300 /*                                                                        */
4301 /*    Application Code                                                    */
4302 /*                                                                        */
4303 /*  RELEASE HISTORY                                                       */
4304 /*                                                                        */
4305 /*    DATE              NAME                      DESCRIPTION             */
4306 /*                                                                        */
4307 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4308 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4309 /*                                            resulting in version 6.1    */
4310 /*                                                                        */
4311 /**************************************************************************/
_nx_nat_socket_port_verify(NX_IP * ip_ptr,UINT protocol,UINT port)4312 static UINT  _nx_nat_socket_port_verify(NX_IP *ip_ptr, UINT protocol, UINT port)
4313 {
4314 
4315 UINT                index;
4316 UINT                bound;
4317 NX_TCP_SOCKET       *tcp_search_ptr;
4318 NX_TCP_SOCKET       *tcp_end_ptr;
4319 NX_UDP_SOCKET       *udp_search_ptr;
4320 NX_UDP_SOCKET       *udp_end_ptr;
4321 
4322 
4323     /* Initialize the return value.  */
4324     bound = NX_FALSE;
4325 
4326     /* Check the protocol.  */
4327     if (protocol == NX_PROTOCOL_TCP)
4328     {
4329 
4330         /* Calculate the hash index in the TCP port array of the associated IP instance.  */
4331         index =  (UINT) ((port + (port >> 8)) & NX_TCP_PORT_TABLE_MASK);
4332 
4333         /* Pickup the head of the TCP ports bound list.  */
4334         tcp_search_ptr =  ip_ptr -> nx_ip_tcp_port_table[index];
4335 
4336         /* Determine if we need to perform a list search.  */
4337         if (tcp_search_ptr)
4338         {
4339 
4340             /* Walk through the circular list of UDP sockets that are already bound.  */
4341             tcp_end_ptr = tcp_search_ptr;
4342             do
4343             {
4344 
4345                 /* Determine if this entry is the same as the requested port.  */
4346                 if (tcp_search_ptr -> nx_tcp_socket_port == port)
4347                 {
4348 
4349                     /* Yes, the port has already been bound.  */
4350                     bound = NX_TRUE;
4351                     break;
4352                 }
4353 
4354                 /* Move to the next entry in the list.  */
4355                 tcp_search_ptr =  tcp_search_ptr -> nx_tcp_socket_bound_next;
4356 
4357             } while (tcp_search_ptr != tcp_end_ptr);
4358         }
4359     }
4360     else
4361     {
4362 
4363         /* Calculate the hash index in the UDP port array of the associated IP instance.  */
4364         index =  (UINT) ((port + (port >> 8)) & NX_UDP_PORT_TABLE_MASK);
4365 
4366         /* Pickup the head of the UDP ports bound list.  */
4367         udp_search_ptr =  ip_ptr -> nx_ip_udp_port_table[index];
4368 
4369         /* Determine if we need to perform a list search.  */
4370         if (udp_search_ptr)
4371         {
4372 
4373             /* Walk through the circular list of UDP sockets that are already  bound.  */
4374             udp_end_ptr = udp_search_ptr;
4375             do
4376             {
4377 
4378                 /* Determine if this entry is the same as the requested port.  */
4379                 if (udp_search_ptr -> nx_udp_socket_port == port)
4380                 {
4381 
4382                     /* Yes, the port has already been bound.  */
4383                     bound = NX_TRUE;
4384                     break;
4385                 }
4386 
4387                 /* Move to the next entry in the list.  */
4388                 udp_search_ptr =  udp_search_ptr -> nx_udp_socket_bound_next;
4389 
4390             } while (udp_search_ptr != udp_end_ptr);
4391         }
4392     }
4393 
4394     /* Return success to the caller.  */
4395     return(bound);
4396 }
4397 
4398 
4399 /**************************************************************************/
4400 /*                                                                        */
4401 /*  FUNCTION                                               RELEASE        */
4402 /*                                                                        */
4403 /*    _nx_nat_packet_is_icmp_error_message                PORTABLE C      */
4404 /*                                                           6.1          */
4405 /*  AUTHOR                                                                */
4406 /*                                                                        */
4407 /*    Yuxin Zhou, Microsoft Corporation                                   */
4408 /*                                                                        */
4409 /*  DESCRIPTION                                                           */
4410 /*                                                                        */
4411 /*   This function determines if an ICMP packet is a query message or an  */
4412 /*   error message.                                                       */
4413 /*                                                                        */
4414 /*  INPUT                                                                 */
4415 /*                                                                        */
4416 /*    packet_ptr                        Pointer to ICMP packet to parse   */
4417 /*    is_icmp_error_msg                 Indicates if packet is an error   */
4418 /*                                         message packet                 */
4419 /*  OUTPUT                                                                */
4420 /*                                                                        */
4421 /*    NX_SUCCESS                         Successful completion status     */
4422 /*                                                                        */
4423 /*  CALLS                                                                 */
4424 /*                                                                        */
4425 /*   None                                                                 */
4426 /*                                                                        */
4427 /*  CALLED BY                                                             */
4428 /*                                                                        */
4429 /*   _nx_nat_process_inbound_ICMP_packet   Forward inbound ICMP packets   */
4430 /*   _nx_nat_process_outbound_ICMP_packet  Forward outbound ICMP packets  */
4431 /*   _nx_nat_utility_get_source_port       Extract source port from header*/
4432 /*   _nx_nat_utility_get_destination_port  Extract destination port from  */
4433 /*                                             header                     */
4434 /*                                                                        */
4435 /*  RELEASE HISTORY                                                       */
4436 /*                                                                        */
4437 /*    DATE              NAME                      DESCRIPTION             */
4438 /*                                                                        */
4439 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4440 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4441 /*                                            resulting in version 6.1    */
4442 /*                                                                        */
4443 /**************************************************************************/
_nx_nat_packet_is_icmp_error_message(NX_PACKET * packet_ptr,UINT * is_icmp_error_msg)4444 static UINT  _nx_nat_packet_is_icmp_error_message(NX_PACKET *packet_ptr, UINT *is_icmp_error_msg)
4445 {
4446 
4447 UINT            type;
4448 UINT            protocol;
4449 NX_IPV4_HEADER  *ip_header_ptr;
4450 NX_ICMP_HEADER  *icmp_header_ptr;
4451 
4452 
4453     /* Initialize the result to non error message type. */
4454     *is_icmp_error_msg = NX_FALSE;
4455 
4456     /* Set up an IP header pointer to the packet. */
4457     ip_header_ptr =  (NX_IPV4_HEADER *) (packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_IPV4_HEADER));
4458 
4459     /* Set up an ICMP header pointer to the packet. */
4460     icmp_header_ptr = (NX_ICMP_HEADER *) (packet_ptr -> nx_packet_prepend_ptr);
4461 
4462     /* Determine what protocol the current IP datagram is.  */
4463     protocol =  (ip_header_ptr -> nx_ip_header_word_2 >> 16) & 0xFF;
4464 
4465     /* Is this an ICMP packet? */
4466     if (protocol == NX_PROTOCOL_ICMP)
4467     {
4468 
4469         /* Extract the ICMP type and code. */
4470         type = icmp_header_ptr -> nx_icmp_header_word_0 >> 24;
4471 
4472         /* Determine if this is an error message. */
4473         if (type != NX_ICMP_ECHO_REPLY_TYPE     &&
4474             type != NX_ICMP_ECHO_REQUEST_TYPE   &&
4475             type < NX_ICMP_TIMESTAMP_REQ_TYPE)
4476         {
4477 
4478             /* It is. Set the flag to true. */
4479             *is_icmp_error_msg = NX_TRUE;
4480         }
4481     }
4482 
4483     /* Return successful completion status. */
4484     return NX_SUCCESS;
4485 }
4486 
4487 
4488 /**************************************************************************/
4489 /*                                                                        */
4490 /*  FUNCTION                                               RELEASE        */
4491 /*                                                                        */
4492 /*    _nx_nat_checksum_adjust                             PORTABLE C      */
4493 /*                                                           6.1          */
4494 /*  AUTHOR                                                                */
4495 /*                                                                        */
4496 /*    Yuxin Zhou, Microsoft Corporation                                   */
4497 /*                                                                        */
4498 /*  DESCRIPTION                                                           */
4499 /*                                                                        */
4500 /*   This function is an optimization for recomputing a checksum by just  */
4501 /*   computing the difference where a small amount of data has changed.   */
4502 /*   NAT uses this optimization when, for example, it is only changing an */
4503 /*   IP address or port.                                                  */
4504 /*                                                                        */
4505 /*  INPUT                                                                 */
4506 /*    old_checksum                       Pointer to the old checksum      */
4507 /*    old_data                           Pointer to the data being changed*/
4508 /*    new_data                           Pointer to new data replacing the*/
4509 /*                                              old data                  */
4510 /*    data_adjustment_length             Size of data being changed       */
4511 /*    adjusted_checksum                  Pointer to the updated checksum  */
4512 /*                                                                        */
4513 /*  OUTPUT                                                                */
4514 /*                                                                        */
4515 /*    NX_SUCCESS                          Successful completion status    */
4516 /*                                                                        */
4517 /*  CALLS                                                                 */
4518 /*                                                                        */
4519 /*    None                                                                */
4520 /*                                                                        */
4521 /*  CALLED BY                                                             */
4522 /*                                                                        */
4523 /*  _nx_nat_process_inbound_TCP_packet   Send TCP packet to local host    */
4524 /*  _nx_nat_process_inbound_UDP_packet   Send UDP packet to local host    */
4525 /*  _nx_nat_process_inbound_ICMP_packet  Send ICMP packet to local host   */
4526 /*  _nx_nat_process_outbound_TCP_packet  Send TCP packet to external host */
4527 /*  _nx_nat_process_outbound_UDP_packet  Send UDP packet to external host */
4528 /*  _nx_nat_process_outbound_ICMP_packet Send ICMP packet to external host*/
4529 /*                                                                        */
4530 /*  RELEASE HISTORY                                                       */
4531 /*                                                                        */
4532 /*    DATE              NAME                      DESCRIPTION             */
4533 /*                                                                        */
4534 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4535 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4536 /*                                            resulting in version 6.1    */
4537 /*                                                                        */
4538 /**************************************************************************/
_nx_nat_checksum_adjust(UCHAR * checksum,UCHAR * old_data,INT old_data_length,UCHAR * new_data,INT new_data_length)4539 static VOID  _nx_nat_checksum_adjust(UCHAR *checksum, UCHAR *old_data, INT old_data_length, UCHAR *new_data, INT new_data_length)
4540 {
4541 
4542 LONG    x, old_value, new_value;
4543 INT     i,j;
4544 
4545 #ifdef NX_LITTLE_ENDIAN
4546     i = 1;
4547     j = 0;
4548 #else
4549     i = 0;
4550     j = 1;
4551 #endif
4552 
4553     /* Checksum Adjustment, RFC 3022, Section 4.2, Page 9.  */
4554 
4555     /* Get the old checksum.  */
4556     x = checksum[i] * 256 + checksum[j];
4557     x = ~x & 0xFFFF;
4558 
4559     /* Update the checksum for old data.  */
4560     while (old_data_length)
4561     {
4562 
4563         /* Get the old data.  */
4564         old_value = old_data[i] * 256 + old_data[j];
4565 
4566         /* Update the old data pointer.  */
4567         old_data += 2;
4568 
4569         /* Update the checksum.  */
4570         x -= old_value & 0xFFFF;
4571 
4572         /* Check the value.  */
4573         if (x <= 0)
4574         {
4575 
4576             /* Update the value.  */
4577             x --;
4578             x &= 0xFFFF;
4579         }
4580 
4581         /* Update the old data length.  */
4582         old_data_length -= 2;
4583     }
4584 
4585     /* Update the checksum for new data.  */
4586     while (new_data_length)
4587     {
4588 
4589         /* Get the new data.  */
4590         new_value = new_data[i] * 256 + new_data[j];
4591 
4592         /* Update the new data pointer.  */
4593         new_data += 2;
4594 
4595         /* Update the checksum.  */
4596         x += new_value & 0xFFFF;
4597 
4598         /* Check the value.  */
4599         if (x & 0x10000)
4600         {
4601 
4602             /* Update the value.  */
4603             x ++;
4604             x &= 0xFFFF;
4605         }
4606 
4607         /* Update the new data length.  */
4608         new_data_length -= 2;
4609     }
4610 
4611     /* Update the value.  */
4612     x = ~x & 0xFFFF;
4613 
4614     /* Update the checksum.  */
4615     checksum[i] = (UCHAR)(x /256);
4616     checksum[j] = (UCHAR)(x & 0xFF);
4617 
4618     /* Return.  */
4619     return;
4620 }
4621 #endif
4622