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