Contiki-NG
Loading...
Searching...
No Matches
nat64.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2026, RISE Research Institutes of Sweden AB.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/**
32 * \defgroup nat64 NAT64 gateway
33 *
34 * Stateful NAT64 service that lets IPv6-only IoT nodes reach IPv4
35 * servers through a Contiki-NG border router. The implementation
36 * targets outbound, client-initiated flows over 6LoWPAN/RPL and
37 * deliberately omits RFC 6146 features that have no practical use in
38 * a constrained network (hairpinning, inbound bindings, full TCP
39 * state machine, ...). See `os/services/nat64/README.md` for the
40 * full design rationale and standards-compliance matrix.
41 *
42 * The module is split into:
43 * - a protocol-agnostic core (\ref nat64.h, nat64.c) that dispatches
44 * IPv6 packets and synthesizes ICMPv6 errors,
45 * - a TCP splice proxy (\ref nat64-tcp.h, nat64-tcp.c),
46 * - an inline DNS64 translator (\ref nat64-dns64.h, nat64-dns64.c),
47 * - and a thin platform layer (\ref nat64-platform.h) implemented for
48 * native Linux/macOS by `native/nat64-sock.c`.
49 *
50 * @{
51 */
52
53/**
54 * \file
55 * NAT64 gateway core API.
56 *
57 * Public entry points used by the platform layer (output
58 * path) and by transport-specific helpers to inject
59 * translated packets back into the uIP stack.
60 * \author
61 * Nicolas Tsiftes <nicolas.tsiftes@ri.se>
62 */
63
64#ifndef NAT64_H_
65#define NAT64_H_
66
67#include <stdbool.h>
68#include <stdint.h>
69#include "net/ipv6/uip.h"
70
71/* Forward declaration — the platform layer defines the full struct. */
72struct nat64_session;
73
74/**
75 * \brief Process an outgoing IPv6 packet destined for an IPv4 host.
76 * \param ipv6_pkt Pointer to the raw IPv6 packet (header + payload).
77 * \param len Total length of the packet in bytes.
78 * \return 1 if the packet was handled, 0 otherwise.
79 *
80 * Dispatches the packet to the appropriate transport handler (UDP or
81 * TCP) based on the IPv6 next-header field. Packets with a NAT64
82 * source address are silently dropped (RFC 6146 Section 3.5).
83 */
84int nat64_output(const uint8_t *ipv6_pkt, uint16_t len);
85
86/**
87 * \brief Check whether an IPv6 address embeds an IPv4 address via
88 * the NAT64 prefix.
89 * \param addr The IPv6 address to check.
90 * \return true if the address matches the configured NAT64 prefix.
91 */
92bool nat64_is_ip64_addr(const uip_ip6addr_t *addr);
93
94/**
95 * \brief Initialize the NAT64 gateway.
96 *
97 * Called by the platform layer after session state has been set up.
98 */
99void nat64_activate(void);
100
101/**
102 * \name Platform-to-core callbacks
103 *
104 * Called by the platform layer (e.g., the select loop in nat64-sock.c)
105 * when data arrives on an IPv4 socket or a TCP connection changes state.
106 * Each callback fabricates the corresponding IPv6 packet and injects it
107 * into the uIP stack via tcpip_input().
108 * @{
109 */
110
111/**
112 * \brief Inject a UDP response from an IPv4 server.
113 * \param s The session that received the data.
114 * \param payload UDP payload bytes (DNS responses are rewritten inline).
115 * \param len Payload length in bytes.
116 */
117void nat64_udp_input(struct nat64_session *s,
118 const uint8_t *payload, uint16_t len);
119
120/**
121 * \brief Notify that a TCP connection to an IPv4 server completed.
122 * \param s The session whose connect() succeeded.
123 *
124 * Sends a SYN-ACK to the IoT node to complete the three-way handshake.
125 */
127
128/**
129 * \brief Forward TCP data from an IPv4 server to the IoT node.
130 * \param s The established TCP session.
131 * \param data Pointer to the received data.
132 * \param len Data length in bytes.
133 *
134 * Data is buffered per session and delivered in NAT64_TCP_SEGMENT_SIZE
135 * (76-byte) ACK-paced segments to fit a single 802.15.4 frame without
136 * 6LoWPAN fragmentation.
137 */
138void nat64_tcp_data_in(struct nat64_session *s,
139 const uint8_t *data, uint16_t len);
140
141/**
142 * \brief Notify that an IPv4 server closed a TCP connection.
143 * \param s The session that was closed.
144 *
145 * Sends a FIN to the IoT node.
146 */
147void nat64_tcp_closed(struct nat64_session *s);
148
149/**
150 * \brief Inject an ICMPv4 Echo Reply received from an IPv4 host.
151 * \param s The ICMP session that received the reply.
152 * \param icmp_pkt ICMPv4 reply bytes (type 0 + code + checksum +
153 * identifier + sequence + data).
154 * \param len Length of icmp_pkt in bytes.
155 *
156 * Translates the ICMPv4 Echo Reply (type 0) into an ICMPv6 Echo
157 * Reply (type 129), preserving the original identifier from the
158 * session, and injects it into the uIP stack.
159 */
160void nat64_icmp_input(struct nat64_session *s,
161 const uint8_t *icmp_pkt, uint16_t len);
162
163/** @} */
164
165/**
166 * \name ICMPv6 Destination Unreachable codes (RFC 4443 §3.1)
167 * @{
168 */
169#define NAT64_ICMP6_NOROUTE 0 /**< No route to destination. */
170#define NAT64_ICMP6_ADMIN 1 /**< Communication administratively prohibited. */
171#define NAT64_ICMP6_ADDR 3 /**< Address unreachable. */
172#define NAT64_ICMP6_PORT 4 /**< Port unreachable. */
173/** @} */
174
175/**
176 * \name ICMPv6 Destination Unreachable synthesis
177 *
178 * The gateway synthesizes ICMPv6 errors toward the IoT node when a
179 * packet cannot be delivered (forbidden destination, connection
180 * refused, host unreachable, session table exhaustion, ...). The
181 * errors are queued and drained by nat64_flush_icmp6() from the
182 * platform layer's select loop, to avoid re-entrancy with
183 * tcpip_input() from output paths.
184 * @{
185 */
186
187/**
188 * \brief Queue an ICMPv6 Destination Unreachable for delivery to the IoT node.
189 * \param invoking_pkt The original IPv6 packet that triggered the error.
190 * \param invoking_len Length of the invoking packet in bytes.
191 * \param code ICMPv6 Code (NAT64_ICMP6_*).
192 *
193 * As much of the invoking packet as fits is embedded in the error,
194 * so the IoT node's transport layer can match the error to the
195 * right socket.
196 */
197void nat64_queue_icmp6_unreach(const uint8_t *invoking_pkt,
198 uint16_t invoking_len, uint8_t code);
199
200/**
201 * \brief Queue an ICMPv6 Destination Unreachable for a 5-tuple whose
202 * connection failed.
203 * \param ip6_src IoT node's IPv6 address.
204 * \param src_port IoT node's transport port (host byte order).
205 * \param ip4_dst IPv4 destination that could not be reached.
206 * \param dst_port Destination port (host byte order).
207 * \param ipproto Transport protocol (6 for TCP, 17 for UDP).
208 * \param code ICMPv6 Code (NAT64_ICMP6_*).
209 *
210 * Used when the original IPv6 packet is no longer available (e.g.,
211 * asynchronous TCP connect failure). Fabricates a minimal invoking
212 * packet from the 5-tuple.
213 */
214void nat64_queue_icmp6_unreach_tuple(const uip_ip6addr_t *ip6_src,
215 uint16_t src_port,
216 const uip_ip4addr_t *ip4_dst,
217 uint16_t dst_port,
218 uint8_t ipproto, uint8_t code);
219
220/**
221 * \brief Drain the queue of pending ICMPv6 errors into the uIP stack.
222 *
223 * Called from the platform layer's select-loop set_fd callback,
224 * outside the uip_buf processing path, to avoid re-entrancy.
225 */
226void nat64_flush_icmp6(void);
227
228/** @} */
229
230/** @} */ /* end of \defgroup nat64 */
231
232#endif /* NAT64_H_ */
void nat64_queue_icmp6_unreach_tuple(const uip_ip6addr_t *ip6_src, uint16_t src_port, const uip_ip4addr_t *ip4_dst, uint16_t dst_port, uint8_t ipproto, uint8_t code)
Queue an ICMPv6 Destination Unreachable for a 5-tuple whose connection failed.
Definition nat64.c:351
bool nat64_is_ip64_addr(const uip_ip6addr_t *addr)
Check whether an IPv6 address embeds an IPv4 address via the NAT64 prefix.
Definition nat64.c:397
void nat64_udp_input(struct nat64_session *s, const uint8_t *payload, uint16_t payload_len)
Inject a UDP response from an IPv4 server.
Definition nat64.c:567
void nat64_tcp_closed(struct nat64_session *s)
Notify that an IPv4 server closed a TCP connection.
Definition nat64-tcp.c:715
void nat64_tcp_data_in(struct nat64_session *s, const uint8_t *data, uint16_t len)
Forward TCP data from an IPv4 server to the IoT node.
Definition nat64-tcp.c:687
void nat64_tcp_established(struct nat64_session *s)
Notify that a TCP connection to an IPv4 server completed.
Definition nat64-tcp.c:672
void nat64_activate(void)
Initialize the NAT64 gateway.
Definition nat64.c:687
int nat64_output(const uint8_t *pkt, uint16_t len)
Process an outgoing IPv6 packet destined for an IPv4 host.
Definition nat64.c:518
void nat64_queue_icmp6_unreach(const uint8_t *invoking_pkt, uint16_t invoking_len, uint8_t code)
Queue an ICMPv6 Destination Unreachable for delivery to the IoT node.
Definition nat64.c:283
void nat64_flush_icmp6(void)
Drain the queue of pending ICMPv6 errors into the uIP stack.
Definition nat64.c:379
void nat64_icmp_input(struct nat64_session *s, const uint8_t *icmp_pkt, uint16_t len)
Inject an ICMPv4 Echo Reply received from an IPv4 host.
Definition nat64.c:630
A NAT64 session binding an IoT node's IPv6 flow to an IPv4 socket.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition uip-nd6.c:107
Header file for the uIP TCP/IP stack.
Representation of an IP address.
Definition uip.h:95