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