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-2026 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.6.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  NetContext *netContext;
91 
92  //Debug message
93  TRACE_INFO("Initializing NAT...\r\n");
94 
95  //Ensure the parameters are valid
96  if(context == NULL || settings == NULL)
98 
99  //Check parameters
100  if(settings->publicInterface == NULL || settings->numPrivateInterfaces == 0)
102 
103  //Point to the TCP/IP stack context
104  netContext = settings->publicInterface->netContext;
105 
106  //Clear the NAT context
107  osMemset(context, 0, sizeof(NatContext));
108 
109  //Attach TCP/IP stack context
110  context->netContext = netContext;
111 
112  //Save public interface
113  context->publicInterface = settings->publicInterface;
114  //Index of the public IP address to use
115  context->publicIpAddrIndex = settings->publicIpAddrIndex;
116 
117  //Save the number of private interfaces
118  context->numPrivateInterfaces = settings->numPrivateInterfaces;
119 
120  //Save private interfaces
121  for(i = 0; i < context->numPrivateInterfaces; i++)
122  {
123  context->privateInterfaces[i] = settings->privateInterfaces[i];
124  }
125 
126  //Save port redirection rules
127  context->numPortFwdRules = settings->numPortFwdRules;
128  context->portFwdRules = settings->portFwdRules;
129 
130  //Loop through the list of port redirection rules
131  for(i = 0; i < context->numPortFwdRules; i++)
132  {
133  //Initialize the current entry
134  osMemset(&context->portFwdRules[i], 0, sizeof(NatPortFwdRule));
135  }
136 
137  //NAT sessions (initiated from a private host)
138  context->numSessions = settings->numSessions;
139  context->sessions = settings->sessions;
140 
141  //Loop through the NAT sessions
142  for(i = 0; i < context->numSessions; i++)
143  {
144  //Initialize the current entry
145  osMemset(&context->sessions[i], 0, sizeof(NatSession));
146  }
147 
148  //Get exclusive access
149  netLock(netContext);
150  //Attach the NAT context
151  netContext->natContext = context;
152  //Release exclusive access
153  netUnlock(netContext);
154 
155  //Successful initialization
156  return NO_ERROR;
157 }
158 
159 
160 /**
161  * @brief Specify the NAT public interface
162  * @param[in] context Pointer to the NAT context
163  * @param[in] publicInterface NAT public interface
164  * @return Error code
165  **/
166 
167 
169  NetInterface *publicInterface)
170 {
171  uint_t i;
172 
173  //Check parameters
174  if(context == NULL || publicInterface == NULL)
176 
177  //Get exclusive access
178  netLock(context->netContext);
179 
180  //Save public interface
181  context->publicInterface = publicInterface;
182 
183  //Loop through the NAT sessions
184  for(i = 0; i < context->numSessions; i++)
185  {
186  //Terminate session
187  context->sessions[i].protocol = IPV4_PROTOCOL_NONE;
188  }
189 
190  //Release exclusive access
191  netUnlock(context->netContext);
192 
193  //Sucessful processing
194  return NO_ERROR;
195 }
196 
197 
198 /**
199  * @brief Add port redirection rule
200  * @param[in] context Pointer to the NAT context
201  * @param[in] index Zero-based index identifying a given entry
202  * @param[in] protocol Transport protocol (IPV4_PROTOCOL_TCP or IPV4_PROTOCOL_UDP)
203  * @param[in] publicPort Public port to be redirected
204  * @param[in] privateInterface Destination interface
205  * @param[in] privateIpAddr Destination IP address
206  * @param[in] privatePort Destination port
207  * @return Error code
208  **/
209 
211  Ipv4Protocol protocol, uint16_t publicPort, NetInterface *privateInterface,
212  Ipv4Addr privateIpAddr, uint16_t privatePort)
213 {
214  error_t error;
215 
216  //Add port redirection rule
217  error = natSetPortRangeFwdRule(context, index, protocol, publicPort,
218  publicPort, privateInterface, privateIpAddr, privatePort);
219 
220  //Return status code
221  return error;
222 }
223 
224 
225 /**
226  * @brief Add port range redirection rule
227  * @param[in] context Pointer to the NAT context
228  * @param[in] index Zero-based index identifying a given entry
229  * @param[in] protocol Transport protocol (IPV4_PROTOCOL_TCP or IPV4_PROTOCOL_UDP)
230  * @param[in] publicPortMin Public port range to be redirected (lower value)
231  * @param[in] publicPortMax Public port range to be redirected (upper value)
232  * @param[in] privateInterface Destination interface
233  * @param[in] privateIpAddr Destination IP address
234  * @param[in] privatePortMin Destination port (lower value)
235  * @return Error code
236  **/
237 
239  Ipv4Protocol protocol, uint16_t publicPortMin, uint16_t publicPortMax,
240  NetInterface *privateInterface, Ipv4Addr privateIpAddr,
241  uint16_t privatePortMin)
242 {
243  NatPortFwdRule *rule;
244 
245  //Check parameters
246  if(context == NULL || privateInterface == NULL)
248 
249  //The implementation limits the number of port redirection rules
250  if(index >= context->numPortFwdRules)
252 
253  //Only TCP and UDP traffic can be forwarded by the NAT
255  return ERROR_INVALID_PROTOCOL;
256 
257  //Get exclusive access
258  netLock(context->netContext);
259 
260  //Point to the specified rule
261  rule = &context->portFwdRules[index];
262 
263  //Update port redirection rule
264  rule->protocol = protocol;
265  rule->publicPortMin = publicPortMin;
266  rule->publicPortMax = publicPortMax;
267  rule->privateInterface = privateInterface;
268  rule->privateIpAddr = privateIpAddr;
269  rule->privatePortMin = privatePortMin;
270  rule->privatePortMax = privatePortMin + publicPortMax - publicPortMin;
271 
272  //Release exclusive access
273  netUnlock(context->netContext);
274 
275  //Sucessful processing
276  return NO_ERROR;
277 }
278 
279 
280 /**
281  * @brief Remove port redirection rule
282  * @param[in] context Pointer to the NAT context
283  * @param[in] index Zero-based index identifying a given entry
284  * @return Error code
285  **/
286 
288 {
289  //Make sure the NAT context is valid
290  if(context == NULL)
292 
293  //The implementation limits the number of port redirection rules
294  if(index >= context->numPortFwdRules)
296 
297  //Get exclusive access
298  netLock(context->netContext);
299  //Invalidate the specified rule
300  context->portFwdRules[index].protocol = IPV4_PROTOCOL_NONE;
301  //Release exclusive access
302  netUnlock(context->netContext);
303 
304  //Successful processing
305  return NO_ERROR;
306 }
307 
308 
309 /**
310  * @brief Start NAT operation
311  * @param[in] context Pointer to the NAT context
312  * @return Error code
313  **/
314 
316 {
317  error_t error;
318 
319  //Make sure the NAT context is valid
320  if(context == NULL)
322 
323  //Debug message
324  TRACE_INFO("Starting NAT...\r\n");
325 
326  //Get exclusive access
327  netLock(context->netContext);
328 
329  //Check the operational state of the NAT
330  if(!context->running)
331  {
332  //Start NAT operation
333  context->running = TRUE;
334 
335  //Successful processing
336  error = NO_ERROR;
337  }
338  else
339  {
340  //The NAT is already running
341  error = ERROR_ALREADY_RUNNING;
342  }
343 
344  //Release exclusive access
345  netUnlock(context->netContext);
346 
347  //Return status code
348  return error;
349 }
350 
351 
352 /**
353  * @brief Stop NAT operation
354  * @param[in] context Pointer to the NAT context
355  * @return Error code
356  **/
357 
359 {
360  uint_t i;
361 
362  //Make sure the NAT context is valid
363  if(context == NULL)
365 
366  //Debug message
367  TRACE_INFO("Stopping NAT...\r\n");
368 
369  //Get exclusive access
370  netLock(context->netContext);
371 
372  //Check whether the NAT is running
373  if(context->running)
374  {
375  //Loop through the NAT sessions
376  for(i = 0; i < context->numSessions; i++)
377  {
378  //Terminate session
379  context->sessions[i].protocol = IPV4_PROTOCOL_NONE;
380  }
381 
382  //Stop NAT operation
383  context->running = FALSE;
384  }
385 
386  //Release exclusive access
387  netUnlock(context->netContext);
388 
389  //Successful processing
390  return NO_ERROR;
391 }
392 
393 
394 /**
395  * @brief Release NAT context
396  * @param[in] context Pointer to the NAT context
397  **/
398 
399 void natDeinit(NatContext *context)
400 {
401  NetContext *netContext;
402 
403  //Make sure the NAT context is valid
404  if(context != NULL)
405  {
406  //Point to the TCP/IP stack context
407  netContext = context->netContext;
408 
409  //Get exclusive access
410  netLock(netContext);
411  //Detach the NAT context
412  netContext->natContext = NULL;
413  //Release exclusive access
414  netUnlock(netContext);
415 
416  //Clear NAT context
417  osMemset(context, 0, sizeof(NatContext));
418  }
419 }
420 
421 #endif
error_t natStop(NatContext *context)
Stop NAT operation.
Definition: nat.c:358
void netUnlock(NetContext *context)
Release exclusive access to the core of the TCP/IP stack.
Definition: net.c:319
#define NetContext
Definition: net.h:36
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:351
uint_t publicIpAddrIndex
Index of the public IP address to use.
Definition: nat.h:177
#define TRUE
Definition: os_port.h:50
error_t natClearPortFwdRule(NatContext *context, uint_t index)
Remove port redirection rule.
Definition: nat.c:287
uint_t numSessions
Number of NAT sessions.
Definition: nat.h:183
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:322
uint16_t publicPortMax
Public port range to be redirected (upper value)
Definition: nat.h:142
@ IPV4_PROTOCOL_TCP
Definition: ipv4.h:277
#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:40
error_t natSetPublicInterface(NatContext *context, NetInterface *publicInterface)
Specify the NAT public interface.
Definition: nat.c:168
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.
void natGetDefaultSettings(NatSettings *settings)
Initialize settings with default values.
Definition: nat.c:60
@ IPV4_PROTOCOL_NONE
Definition: ipv4.h:274
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:238
@ IPV4_PROTOCOL_UDP
Definition: ipv4.h:278
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
error_t natStart(NatContext *context)
Start NAT operation.
Definition: nat.c:315
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
void netLock(NetContext *context)
Get exclusive access to the core of the TCP/IP stack.
Definition: net.c:307
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:273
NetInterface * publicInterface
Public interface.
Definition: nat.h:176
bool_t running
Operational state of the NAT.
Definition: nat.h:202
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:399
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:210
NetContext * netContext
TCP/IP stack context.
Definition: nat.h:193
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