SatCat5
router2_basic_nat.cc
1 // Copyright 2025 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
5 
6 #include <satcat5/router2_basic_nat.h>
7 
9 using satcat5::ip::checksum;
12 
13 BasicNat::BasicNat(satcat5::eth::SwitchPort* port)
14  : PluginPort(port)
15  , m_ext(satcat5::ip::DEFAULT_ROUTE)
16  , m_int(satcat5::ip::DEFAULT_ROUTE)
17 {
18  // Nothing else to initialize.
19 }
20 
21 bool BasicNat::config(const Subnet& ip_ext, const Subnet& ip_int) {
22  // Sanity check: Both subnets must be the same size.
23  if (ip_ext.mask != ip_int.mask) return false;
24 
25  // Store the new setting.
26  m_ext = ip_ext;
27  m_int = ip_int;
28 
29  // Normalize the base-address of each subnet.
30  m_ext.addr.value &= m_ext.mask.value;
31  m_int.addr.value &= m_int.mask.value;
32  return true;
33 }
34 
35 static inline u16 upper(u32 x)
36  { return u16(x >> 16); }
37 static inline u16 lower(u32 x)
38  { return u16(x & 0xFFFF); }
39 
40 static void translate_packet(
41  PluginPacket& pkt, const Subnet& src, const Subnet& dst)
42 {
43  unsigned changed = 0;
44  if (pkt.is_arp()) {
45  // ARP header: Adjust the SPA and TPA fields.
46  u32 diff32 = dst.addr.value - src.addr.value;
47  if (src.contains(pkt.arp.spa)) {
48  pkt.arp.spa.value += diff32;
49  changed = 1;
50  }
51  if (src.contains(pkt.arp.tpa)) {
52  pkt.arp.tpa.value += diff32;
53  changed = 1;
54  }
55  } else if (pkt.is_ip()) {
56  // IPv4 header: Adjust source and destination addresses.
57  // Note: Changes to each 16-bit subword must be considered separately
58  // to correctly account for 16-bit vs 32-bit arithmetic rollover.
59  u16 diff_msb = upper(dst.addr.value) - upper(src.addr.value);
60  u16 diff_lsb = lower(dst.addr.value) - lower(src.addr.value);
61  if (src.contains(pkt.ip.src())) {
62  pkt.ip.data[6] += diff_msb;
63  pkt.ip.data[7] += diff_lsb;
64  ++changed;
65  }
66  if (src.contains(pkt.ip.dst())) {
67  pkt.ip.data[8] += diff_msb;
68  pkt.ip.data[9] += diff_lsb;
69  ++changed;
70  }
71  // Apply Update IPv4 and TCP header checksums per RFC1624 Section 3.
72  // The UDP checksum would also be affected, but the udp::Header class
73  // always disables that checksum (writes zero) in outgoing UDP headers.
74  for (unsigned a = 0 ; a < changed ; ++a) {
75  pkt.ip.chk_incr32(src.addr.value, dst.addr.value);
76  if (pkt.is_tcp()) pkt.tcp.chk_incr32(src.addr.value, dst.addr.value);
77  }
78  }
79 
80  // Have header contents changed?
81  if (changed) pkt.adjust();
82 }
83 
85  translate_packet(pkt, m_ext, m_int);
86 }
87 
89  translate_packet(pkt, m_int, m_ext);
90 }
Generic packetized I/O interface for use with SwitchCore.
Definition: eth_switch.h:245
Basic Network Address Translation (NAT) for the IPv4 router.
void ingress(satcat5::eth::PluginPacket &pkt) override
Packet-received callback.
void egress(satcat5::eth::PluginPacket &pkt) override
Packet-transmit callback.
bool config(const satcat5::ip::Subnet &ip_ext, const satcat5::ip::Subnet &ip_int)
Change the NAT configuration.
satcat5::ip::Addr spa
ARP header fields:
Definition: eth_arp.h:28
satcat5::ip::Addr tpa
ARP header fields:
Definition: eth_arp.h:28
Ephemeral data structure provided to plugin callbacks.
Definition: eth_plugin.h:48
satcat5::ip::Header ip
Copy of additional header fields, if present.
Definition: eth_plugin.h:62
bool is_ip() const
Accessors and shortcuts for packet metadata.
Definition: eth_plugin.h:129
satcat5::tcp::Header tcp
Copy of additional header fields, if present.
Definition: eth_plugin.h:63
bool is_arp() const
Accessors and shortcuts for packet metadata.
Definition: eth_plugin.h:131
satcat5::eth::ArpHeader arp
Copy of additional header fields, if present.
Definition: eth_plugin.h:61
bool is_tcp() const
Accessors and shortcuts for packet metadata.
Definition: eth_plugin.h:133
void adjust()
Notify parent that header contents have changed.
Definition: eth_plugin.h:105
u32 value
Raw access to the underlying representation.
Definition: ip_core.h:17
constexpr satcat5::ip::Addr dst() const
< Destination address
Definition: ip_core.h:210
u16 data[HDR_MAX_SHORTS]
Raw access to the underlying header contents.
Definition: ip_core.h:182
constexpr satcat5::ip::Addr src() const
< Source address
Definition: ip_core.h:208
An IPv4 subnet consists of a base address and a subnet mask.
Definition: ip_core.h:87
satcat5::ip::Mask mask
Subnet mask.
Definition: ip_core.h:90
constexpr bool contains(const satcat5::ip::Addr &other) const
Does this subnet contain the given address?
Definition: ip_core.h:97
satcat5::ip::Addr addr
Base address.
Definition: ip_core.h:89