nat.c
Go to the documentation of this file.
1 /**
2  * @file nat.c
3  * @brief NAT (IP Network Address Translator)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * Network Address Translation (NAT) is a method of mapping one IP address
30  * space to another by modifying network address information in the IP header
31  * of packets. Refer to the following RFCs for complete details:
32  * - RFC 2663: NAT Terminology and Considerations
33  * - RFC 3022: Traditional IP Network Address Translator (Traditional NAT)
34  * - RFC 4787: NAT Behavioral Requirements for Unicast UDP
35  * - RFC 5382: NAT Behavioral Requirements for TCP
36  * - RFC 5508: NAT Behavioral Requirements for ICMP
37  *
38  * @author Oryx Embedded SARL (www.oryx-embedded.com)
39  * @version 2.5.0
40  **/
41 
42 //Switch to the appropriate trace level
43 #define TRACE_LEVEL NAT_TRACE_LEVEL
44 
45 //Dependencies
46 #include "core/net.h"
47 #include "nat/nat.h"
48 #include "nat/nat_misc.h"
49 #include "debug.h"
50 
51 //Check TCP/IP stack configuration
52 #if (NAT_SUPPORT == ENABLED)
53 
54 
55 /**
56  * @brief Initialize settings with default values
57  * @param[out] settings Structure that contains NAT settings
58  **/
59 
61 {
62  //Public interface
63  settings->publicInterface = NULL;
64  //Index of the public IP address to use
65  settings->publicIpAddrIndex = 0;
66 
67  //Private interfaces
68  settings->numPrivateInterfaces = 0;
69 
70  //Port redirection rules
71  settings->numPortFwdRules = 0;
72  settings->portFwdRules = NULL;
73 
74  //NAT sessions (initiated from a private host)
75  settings->numSessions = 0;
76  settings->sessions = NULL;
77 }
78 
79 
80 /**
81  * @brief NAT initialization
82  * @param[in] context Pointer to the NAT context
83  * @param[in] settings NAT specific settings
84  * @return Error code
85  **/
86 
87 error_t natInit(NatContext *context, const NatSettings *settings)
88 {
89  uint_t i;
90 
91  //Debug message
92  TRACE_INFO("Initializing NAT...\r\n");
93 
94  //Ensure the parameters are valid
95  if(context == NULL || settings == NULL)
97 
98  //Check parameters
99  if(settings->publicInterface == NULL || settings->numPrivateInterfaces == 0)
101 
102  //Save public interface
103  context->publicInterface = settings->publicInterface;
104  //Index of the public IP address to use
105  context->publicIpAddrIndex = settings->publicIpAddrIndex;
106 
107  //Save the number of private interfaces
108  context->numPrivateInterfaces = settings->numPrivateInterfaces;
109 
110  //Save private interfaces
111  for(i = 0; i < context->numPrivateInterfaces; i++)
112  {
113  context->privateInterfaces[i] = settings->privateInterfaces[i];
114  }
115 
116  //Save port redirection rules
117  context->numPortFwdRules = settings->numPortFwdRules;
118  context->portFwdRules = settings->portFwdRules;
119 
120  //Loop through the list of port redirection rules
121  for(i = 0; i < context->numPortFwdRules; i++)
122  {
123  //Initialize the current entry
124  osMemset(&context->portFwdRules[i], 0, sizeof(NatPortFwdRule));
125  }
126 
127  //NAT sessions (initiated from a private host)
128  context->numSessions = settings->numSessions;
129  context->sessions = settings->sessions;
130 
131  //Loop through the NAT sessions
132  for(i = 0; i < context->numSessions; i++)
133  {
134  //Initialize the current entry
135  osMemset(&context->sessions[i], 0, sizeof(NatSession));
136  }
137 
138  //Attach the NAT context
139  netContext.natContext = context;
140 
141  //Successful initialization
142  return NO_ERROR;
143 }
144 
145 
146 /**
147  * @brief Specify the NAT public interface
148  * @param[in] context Pointer to the NAT context
149  * @param[in] publicInterface NAT public interface
150  * @return Error code
151  **/
152 
153 
155  NetInterface *publicInterface)
156 {
157  uint_t i;
158 
159  //Check parameters
160  if(context == NULL || publicInterface == NULL)
162 
163  //Get exclusive access
165 
166  //Save public interface
167  context->publicInterface = publicInterface;
168 
169  //Loop through the NAT sessions
170  for(i = 0; i < context->numSessions; i++)
171  {
172  //Terminate session
173  context->sessions[i].protocol = IPV4_PROTOCOL_NONE;
174  }
175 
176  //Release exclusive access
178 
179  //Sucessful processing
180  return NO_ERROR;
181 }
182 
183 
184 /**
185  * @brief Add port redirection rule
186  * @param[in] context Pointer to the NAT context
187  * @param[in] index Zero-based index identifying a given entry
188  * @param[in] protocol Transport protocol (IPV4_PROTOCOL_TCP or IPV4_PROTOCOL_UDP)
189  * @param[in] publicPort Public port to be redirected
190  * @param[in] privateInterface Destination interface
191  * @param[in] privateIpAddr Destination IP address
192  * @param[in] privatePort Destination port
193  * @return Error code
194  **/
195 
197  Ipv4Protocol protocol, uint16_t publicPort, NetInterface *privateInterface,
198  Ipv4Addr privateIpAddr, uint16_t privatePort)
199 {
200  error_t error;
201 
202  //Add port redirection rule
203  error = natSetPortRangeFwdRule(context, index, protocol, publicPort,
204  publicPort, privateInterface, privateIpAddr, privatePort);
205 
206  //Return status code
207  return error;
208 }
209 
210 
211 /**
212  * @brief Add port range redirection rule
213  * @param[in] context Pointer to the NAT context
214  * @param[in] index Zero-based index identifying a given entry
215  * @param[in] protocol Transport protocol (IPV4_PROTOCOL_TCP or IPV4_PROTOCOL_UDP)
216  * @param[in] publicPortMin Public port range to be redirected (lower value)
217  * @param[in] publicPortMax Public port range to be redirected (upper value)
218  * @param[in] privateInterface Destination interface
219  * @param[in] privateIpAddr Destination IP address
220  * @param[in] privatePortMin Destination port (lower value)
221  * @return Error code
222  **/
223 
225  Ipv4Protocol protocol, uint16_t publicPortMin, uint16_t publicPortMax,
226  NetInterface *privateInterface, Ipv4Addr privateIpAddr,
227  uint16_t privatePortMin)
228 {
229  NatPortFwdRule *rule;
230 
231  //Check parameters
232  if(context == NULL || privateInterface == NULL)
234 
235  //The implementation limits the number of port redirection rules
236  if(index >= context->numPortFwdRules)
238 
239  //Only TCP and UDP traffic can be forwarded by the NAT
241  return ERROR_INVALID_PROTOCOL;
242 
243  //Get exclusive access
245 
246  //Point to the specified rule
247  rule = &context->portFwdRules[index];
248 
249  //Update port redirection rule
250  rule->protocol = protocol;
251  rule->publicPortMin = publicPortMin;
252  rule->publicPortMax = publicPortMax;
253  rule->privateInterface = privateInterface;
254  rule->privateIpAddr = privateIpAddr;
255  rule->privatePortMin = privatePortMin;
256  rule->privatePortMax = privatePortMin + publicPortMax - publicPortMin;
257 
258  //Release exclusive access
260 
261  //Sucessful processing
262  return NO_ERROR;
263 }
264 
265 
266 /**
267  * @brief Remove port redirection rule
268  * @param[in] context Pointer to the NAT context
269  * @param[in] index Zero-based index identifying a given entry
270  * @return Error code
271  **/
272 
274 {
275  //Make sure the NAT context is valid
276  if(context == NULL)
278 
279  //The implementation limits the number of port redirection rules
280  if(index >= context->numPortFwdRules)
282 
283  //Get exclusive access
285  //Invalidate the specified rule
286  context->portFwdRules[index].protocol = IPV4_PROTOCOL_NONE;
287  //Release exclusive access
289 
290  //Successful processing
291  return NO_ERROR;
292 }
293 
294 
295 /**
296  * @brief Start NAT operation
297  * @param[in] context Pointer to the NAT context
298  * @return Error code
299  **/
300 
302 {
303  error_t error;
304 
305  //Make sure the NAT context is valid
306  if(context == NULL)
308 
309  //Debug message
310  TRACE_INFO("Starting NAT...\r\n");
311 
312  //Get exclusive access
314 
315  //Check the operational state of the NAT
316  if(!context->running)
317  {
318  //Start NAT operation
319  context->running = TRUE;
320 
321  //Successful processing
322  error = NO_ERROR;
323  }
324  else
325  {
326  //The DHCP client is already running
327  error = ERROR_ALREADY_RUNNING;
328  }
329 
330 
331  //Release exclusive access
333 
334  //Return status code
335  return error;
336 }
337 
338 
339 /**
340  * @brief Stop NAT operation
341  * @param[in] context Pointer to the NAT context
342  * @return Error code
343  **/
344 
346 {
347  uint_t i;
348 
349  //Make sure the NAT context is valid
350  if(context == NULL)
352 
353  //Debug message
354  TRACE_INFO("Stopping NAT...\r\n");
355 
356  //Get exclusive access
358 
359  //Check whether the NAT is running
360  if(context->running)
361  {
362  //Loop through the NAT sessions
363  for(i = 0; i < context->numSessions; i++)
364  {
365  //Terminate session
366  context->sessions[i].protocol = IPV4_PROTOCOL_NONE;
367  }
368 
369  //Stop NAT operation
370  context->running = FALSE;
371  }
372 
373  //Release exclusive access
375 
376  //Successful processing
377  return NO_ERROR;
378 }
379 
380 
381 /**
382  * @brief Release NAT context
383  * @param[in] context Pointer to the NAT context
384  **/
385 
386 void natDeinit(NatContext *context)
387 {
388  //Make sure the NAT context is valid
389  if(context != NULL)
390  {
391  //Clear NAT context
392  osMemset(context, 0, sizeof(NatContext));
393  }
394 }
395 
396 #endif
error_t natStop(NatContext *context)
Stop NAT operation.
Definition: nat.c:345
NatPortFwdRule * portFwdRules
Port redirection rules.
Definition: nat.h:180
Ipv4Protocol protocol
IP protocol (TCP, UDP or ICMP)
Definition: nat.h:156
uint8_t protocol
Definition: ipv4.h:327
uint_t publicIpAddrIndex
Index of the public IP address to use.
Definition: nat.h:177
#define netMutex
Definition: net_legacy.h:195
#define TRUE
Definition: os_port.h:50
error_t natClearPortFwdRule(NatContext *context, uint_t index)
Remove port redirection rule.
Definition: nat.c:273
uint_t numSessions
Number of NAT sessions.
Definition: nat.h:183
NetContext netContext
Definition: net.c:75
NetInterface * privateInterfaces[NAT_MAX_PRIVATE_INTERFACES]
Private interfaces.
Definition: nat.h:178
uint16_t privatePortMin
Destination port (lower value)
Definition: nat.h:145
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:298
uint16_t publicPortMax
Public port range to be redirected (upper value)
Definition: nat.h:142
@ IPV4_PROTOCOL_TCP
Definition: ipv4.h:253
#define FALSE
Definition: os_port.h:46
uint_t numSessions
Number of NAT sessions.
Definition: nat.h:201
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint_t numPortFwdRules
Number of port redirection rules.
Definition: nat.h:199
error_t
Error codes.
Definition: error.h:43
Ipv4Addr privateIpAddr
Destination IP address.
Definition: nat.h:144
error_t natInit(NatContext *context, const NatSettings *settings)
NAT initialization.
Definition: nat.c:87
uint16_t publicPortMin
Public port range to be redirected (lower value)
Definition: nat.h:141
NAT context.
Definition: nat.h:192
Port redirection rule.
Definition: nat.h:139
#define NetInterface
Definition: net.h:36
error_t natSetPublicInterface(NatContext *context, NetInterface *publicInterface)
Specify the NAT public interface.
Definition: nat.c:154
NatPortFwdRule * portFwdRules
Port redirection rules.
Definition: nat.h:198
NAT settings.
Definition: nat.h:175
NAT (IP Network Address Translator)
uint_t numPrivateInterfaces
Number of private interfaces.
Definition: nat.h:197
#define TRACE_INFO(...)
Definition: debug.h:105
@ ERROR_INVALID_PROTOCOL
Definition: error.h:101
Helper functions for NAT.
NatContext * natContext
NAT context.
Definition: net.h:336
void natGetDefaultSettings(NatSettings *settings)
Initialize settings with default values.
Definition: nat.c:60
@ IPV4_PROTOCOL_NONE
Definition: ipv4.h:250
NetInterface * publicInterface
Public interface.
Definition: nat.h:194
error_t natSetPortRangeFwdRule(NatContext *context, uint_t index, Ipv4Protocol protocol, uint16_t publicPortMin, uint16_t publicPortMax, NetInterface *privateInterface, Ipv4Addr privateIpAddr, uint16_t privatePortMin)
Add port range redirection rule.
Definition: nat.c:224
@ IPV4_PROTOCOL_UDP
Definition: ipv4.h:254
NetInterface * privateInterfaces[NAT_MAX_PRIVATE_INTERFACES]
Private interfaces.
Definition: nat.h:196
NatSession * sessions
NAT sessions (initiated from a private host)
Definition: nat.h:182
uint_t numPrivateInterfaces
Number of private interfaces.
Definition: nat.h:179
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
error_t natStart(NatContext *context)
Start NAT operation.
Definition: nat.c:301
Ipv4Protocol protocol
Transport protocol (TCP or UDP)
Definition: nat.h:140
uint_t publicIpAddrIndex
Index of the public IP address to use.
Definition: nat.h:195
NatSession * sessions
NAT sessions (initiated from a private host)
Definition: nat.h:200
NetInterface * privateInterface
Destination interface.
Definition: nat.h:143
Ipv4Protocol
IPv4 protocol field.
Definition: ipv4.h:249
NetInterface * publicInterface
Public interface.
Definition: nat.h:176
bool_t running
This flag tells whether the NAT is running or not.
Definition: nat.h:193
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
void natDeinit(NatContext *context)
Release NAT context.
Definition: nat.c:386
uint16_t privatePortMax
Destination port (upper value)
Definition: nat.h:146
error_t natSetPortFwdRule(NatContext *context, uint_t index, Ipv4Protocol protocol, uint16_t publicPort, NetInterface *privateInterface, Ipv4Addr privateIpAddr, uint16_t privatePort)
Add port redirection rule.
Definition: nat.c:196
uint_t numPortFwdRules
Number of port redirection rules.
Definition: nat.h:181
@ ERROR_ALREADY_RUNNING
Definition: error.h:294
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
NAT session.
Definition: nat.h:155