INET Framework for OMNeT++/OMNEST
inet::sctp::SctpNatHook Class Reference

#include <SctpNatHook.h>

Inheritance diagram for inet::sctp::SctpNatHook:
inet::NetfilterBase::HookBase

Public Member Functions

 SctpNatHook ()
 
virtual ~SctpNatHook ()
 
virtual Result datagramPreRoutingHook (Packet *packet) override
 This is the first hook called by the network protocol before it routes a datagram that was received from the lower layer. More...
 
virtual Result datagramForwardHook (Packet *packet) override
 This is the second hook called by the network protocol before it sends a datagram to the lower layer. More...
 
virtual Result datagramPostRoutingHook (Packet *packet) override
 This is the last hook called by the network protocol before it sends a datagram to the lower layer. More...
 
virtual Result datagramLocalInHook (Packet *packet) override
 This is the last hook called by the network protocol before it sends a datagram to the upper layer. More...
 
virtual Result datagramLocalOutHook (Packet *packet) override
 This is the first hook called by the network protocol before it routes a datagram that was received from the upper layer. More...
 

Protected Member Functions

void initialize () override
 
void finish () override
 
void sendBackError (SctpHeader *sctp)
 

Protected Attributes

IPv4 * ipLayer
 
ModuleRefByPar< SctpNatTablenatTable
 
ModuleRefByPar< IRoutingTablert
 
ModuleRefByPar< IInterfaceTableift
 
uint64_t nattedPackets
 

Additional Inherited Members

- Private Types inherited from inet::INetfilter::IHook
enum  Type {
  PREROUTING, LOCALIN, FORWARD, POSTROUTING,
  LOCALOUT
}
 
enum  Result { ACCEPT, DROP, QUEUE, STOLEN }
 
- Private Member Functions inherited from inet::NetfilterBase::HookBase
virtual ~HookBase ()
 
void registeredTo (INetfilter *nf)
 
void unregisteredFrom (INetfilter *nf)
 
bool isRegisteredHook (INetfilter *nf)
 
- Private Member Functions inherited from inet::INetfilter::IHook
virtual ~IHook ()
 
- Private Attributes inherited from inet::NetfilterBase::HookBase
std::vector< INetfilter * > netfilters
 

Constructor & Destructor Documentation

◆ SctpNatHook()

inet::sctp::SctpNatHook::SctpNatHook ( )
19 {
20  ipLayer = nullptr;
21  nattedPackets = 0;
22 }

◆ ~SctpNatHook()

inet::sctp::SctpNatHook::~SctpNatHook ( )
virtual
25 {
26 }

Member Function Documentation

◆ datagramForwardHook()

INetfilter::IHook::Result inet::sctp::SctpNatHook::datagramForwardHook ( Packet datagram)
overridevirtual

This is the second hook called by the network protocol before it sends a datagram to the lower layer.

This is done after the datagramPreRoutingHook or the datagramLocalInHook is called and the datagram is routed.

Implements inet::INetfilter::IHook.

39 {
40  SctpNatEntry *entry;
41  SctpChunk *chunk;
42  const auto& tag = datagram->findTag<InterfaceReq>();
43  const NetworkInterface *outIE = (tag != nullptr ? ift->getInterfaceById(tag->getInterfaceId()) : nullptr);
44 
45  const auto& inIeTag = datagram->findTag<InterfaceInd>();
46  const NetworkInterface *inIE = (inIeTag != nullptr ? ift->getInterfaceById(inIeTag->getInterfaceId()) : nullptr);
47 
48  const auto& dgram = removeNetworkProtocolHeader<Ipv4Header>(datagram);
49 
50  if (!dgram) {
53  }
54  if (dgram->isFragment()) {
55  // TODO process fragmented packets
58  }
59  if (SctpAssociation::getAddressLevel(dgram->getSrcAddress()) != 3) {
62  }
63  const auto& networkHeader = staticPtrCast<Ipv4Header>(dgram->dupShared());
64  natTable->printNatTable();
65  auto& sctpMsg = datagram->removeAtFront<SctpHeader>();
66  Ptr<SctpHeader> sctp = staticPtrCast<SctpHeader>(sctpMsg->dupShared());
67  unsigned int numberOfChunks = sctpMsg->getSctpChunksArraySize();
68  if (numberOfChunks == 1) {
69  chunk = sctpMsg->peekFirstChunk();
70  }
71  else {
72  chunk = sctpMsg->peekLastChunk();
73  }
74  EV << "findEntry for " << dgram->getSrcAddress() << ":" << sctpMsg->getSrcPort() << " to " << dgram->getDestAddress() << ":" << sctpMsg->getDestPort() << " vTag=" << sctpMsg->getVTag() << "\n";
75  if (chunk->getSctpChunkType() == INIT || chunk->getSctpChunkType() == INIT_ACK || chunk->getSctpChunkType() == ASCONF) {
76  entry = new SctpNatEntry();
77  entry->setLocalAddress(dgram->getSrcAddress());
78  entry->setLocalPort(sctpMsg->getSrcPort());
79  entry->setGlobalAddress(dgram->getDestAddress());
80  entry->setGlobalPort(sctpMsg->getDestPort());
81  entry->setNattedAddress(outIE->getProtocolData<Ipv4InterfaceData>()->getIPAddress());
82  entry->setNattedPort(sctpMsg->getSrcPort());
83  entry->setGlobalVTag(sctpMsg->getVTag());
84  if (chunk->getSctpChunkType() == INIT) {
85  SctpInitChunk *initChunk = check_and_cast<SctpInitChunk *>(chunk);
86  entry->setLocalVTag(initChunk->getInitTag());
87  }
88  else if (chunk->getSctpChunkType() == INIT_ACK) {
89  SctpInitAckChunk *initAckChunk = check_and_cast<SctpInitAckChunk *>(chunk);
90  entry->setLocalVTag(initAckChunk->getInitTag());
91  }
92  else if (chunk->getSctpChunkType() == ASCONF) {
93  SctpAsconfChunk *asconfChunk = check_and_cast<SctpAsconfChunk *>(chunk);
94  entry->setLocalVTag(asconfChunk->getPeerVTag());
95  }
96  networkHeader->setSrcAddress(outIE->getProtocolData<Ipv4InterfaceData>()->getIPAddress());
97  sctp->setSrcPort(entry->getNattedPort());
98  natTable->natEntries.push_back(entry);
99  natTable->printNatTable();
100  }
101  else {
102  EV << "other chunkType: " << (chunk->getSctpChunkType() == COOKIE_ECHO ? "Cookie_Echo" : "other") << ", VTag=" << sctpMsg->getVTag() << "\n";
103  entry = natTable->findNatEntry(networkHeader->getSrcAddress(), sctp->getSrcPort(), networkHeader->getDestAddress(), sctp->getDestPort(), sctp->getVTag());
104  if (entry == nullptr) {
105  EV << "no entry found\n";
106  entry = natTable->findNatEntry(networkHeader->getSrcAddress(), sctp->getSrcPort(), networkHeader->getDestAddress(), sctp->getDestPort(), 0);
107  if (entry == nullptr) {
108  EV << "send back error message dgram=" << networkHeader << "\n";
109  sendBackError(sctp.get());
110  sctp->setSrcPort(sctpMsg->getDestPort());
111  sctp->setDestPort(sctpMsg->getSrcPort());
112  Ipv4Address tmpaddr = dgram->getDestAddress();
113  networkHeader->setDestAddress(dgram->getSrcAddress());
114  if (!tmpaddr.isUnspecified())
115  networkHeader->setSrcAddress(tmpaddr);
116  networkHeader->setTotalLengthField(sctp->getChunkLength() + B(20));
118  insertNetworkProtocolHeader(datagram, Protocol::ipv4, networkHeader);
119  datagram->addTagIfAbsent<NextHopAddressReq>()->setNextHopAddress(networkHeader->getDestAddress());
120  datagram->addTagIfAbsent<InterfaceReq>()->setInterfaceId(CHK(inIE)->getInterfaceId());
122  }
123  else {
124  EV << "VTag doesn't match: old VTag=" << entry->getLocalVTag() << ", new VTag=" << sctpMsg->getVTag() << "\n";
125  entry->setLocalVTag(sctpMsg->getVTag());
126  networkHeader->setSrcAddress(outIE->getProtocolData<Ipv4InterfaceData>()->getIPAddress());
127  sctp->setSrcPort(entry->getNattedPort());
128  EV << "srcAddress set to " << dgram->getSrcAddress() << ", srcPort set to " << sctpMsg->getSrcPort() << "\n";
129  }
130  }
131  else {
132  networkHeader->setSrcAddress(outIE->getProtocolData<Ipv4InterfaceData>()->getIPAddress());
133  sctp->setSrcPort(entry->getNattedPort());
134  EV << "srcAddress set to " << dgram->getSrcAddress() << ", srcPort set to " << sctpMsg->getSrcPort() << "\n";
135  }
136  }
137  nattedPackets++;
139  insertNetworkProtocolHeader(datagram, Protocol::ipv4, networkHeader);
141 }

◆ datagramLocalInHook()

virtual Result inet::sctp::SctpNatHook::datagramLocalInHook ( Packet datagram)
inlineoverridevirtual

This is the last hook called by the network protocol before it sends a datagram to the upper layer.

This is done after the datagramPreRoutingHook is called and the datagram is routed.

Implements inet::INetfilter::IHook.

34 { return ACCEPT; }

◆ datagramLocalOutHook()

virtual Result inet::sctp::SctpNatHook::datagramLocalOutHook ( Packet datagram)
inlineoverridevirtual

This is the first hook called by the network protocol before it routes a datagram that was received from the upper layer.

The nextHopAddress is ignored when the outputNetworkInterface is a nullptr. After this is done

Implements inet::INetfilter::IHook.

35 { return ACCEPT; }

◆ datagramPostRoutingHook()

virtual Result inet::sctp::SctpNatHook::datagramPostRoutingHook ( Packet datagram)
inlineoverridevirtual

This is the last hook called by the network protocol before it sends a datagram to the lower layer.

Implements inet::INetfilter::IHook.

33 { return ACCEPT; }

◆ datagramPreRoutingHook()

INetfilter::IHook::Result inet::sctp::SctpNatHook::datagramPreRoutingHook ( Packet datagram)
overridevirtual

This is the first hook called by the network protocol before it routes a datagram that was received from the lower layer.

The nextHopAddress is ignored when the outputNetworkInterface is nullptr.

Implements inet::INetfilter::IHook.

145 {
146  SctpNatEntry *entry;
147  SctpChunk *chunk;
148 
149  const auto& dgram = removeNetworkProtocolHeader<Ipv4Header>(datagram);
150  const auto& networkHeader = staticPtrCast<Ipv4Header>(dgram->dupShared());
151  if (SctpAssociation::getAddressLevel(dgram->getSourceAddress()) == 3) {
154  }
155 
156  if (dgram->isFragment()) {
157  // TODO process fragmented packets
160  }
161 
162  natTable->printNatTable();
163  bool local = ((rt->isLocalAddress(dgram->getDestinationAddress())) && (SctpAssociation::getAddressLevel(dgram->getSourceAddress()) == 3));
164  auto& sctpMsg = datagram->removeAtFront<SctpHeader>();
165  Ptr<SctpHeader> sctp = staticPtrCast<SctpHeader>(sctpMsg->dupShared());
166  unsigned int numberOfChunks = sctpMsg->getSctpChunksArraySize();
167  if (numberOfChunks == 1)
168  chunk = sctpMsg->peekFirstChunk();
169  else
170  chunk = sctpMsg->peekLastChunk();
171  if (!local) {
172  entry = natTable->getEntry(dgram->getSourceAddress(), sctpMsg->getSrcPort(), dgram->getDestinationAddress(), sctpMsg->getDestPort(), sctpMsg->getVTag());
173  EV_INFO << "getEntry for " << dgram->getSourceAddress() << ":" << sctpMsg->getSrcPort() << " to " << dgram->getDestinationAddress() << ":" << sctpMsg->getDestPort() << " peerVTag=" << sctpMsg->getVTag() << "\n";
174  uint32_t numberOfChunks = sctpMsg->getSctpChunksArraySize();
175  if (entry == nullptr) {
176  EV_INFO << "no entry found\n";
177  if (numberOfChunks == 1)
178  chunk = sctpMsg->peekFirstChunk();
179  else
180  chunk = sctpMsg->peekLastChunk();
181  if (chunk->getSctpChunkType() == INIT || chunk->getSctpChunkType() == ASCONF) {
182  EV_INFO << "could be an Init collision\n";
183  entry = natTable->getSpecialEntry(dgram->getSourceAddress(), sctpMsg->getSrcPort(), dgram->getDestinationAddress(), sctpMsg->getDestPort());
184  if (entry != nullptr) {
185  if (chunk->getSctpChunkType() == INIT) {
186  SctpInitChunk *initChunk = check_and_cast<SctpInitChunk *>(chunk);
187  entry->setLocalVTag(initChunk->getInitTag());
188  EV_INFO << "InitTag=" << initChunk->getInitTag() << "\n";
189  }
190  else if (chunk->getSctpChunkType() == ASCONF) {
191  SctpAsconfChunk *asconfChunk = check_and_cast<SctpAsconfChunk *>(chunk);
192  entry->setLocalVTag(asconfChunk->getPeerVTag());
193  }
194  networkHeader->setDestinationAddress(entry->getLocalAddress().toIpv4());
195  sctp->setDestPort(entry->getLocalPort());
196  EV_INFO << "destAddress set to " << dgram->getDestinationAddress() << ", destPort set to " << sctp->getDestPort() << "\n";
197  }
198  else {
200  insertNetworkProtocolHeader(datagram, Protocol::ipv4, networkHeader);
202  }
203  }
204  else {
205  /* SctpChunk *schunk = nullptr;
206  if (numberOfChunks > 0) {
207  EV << "number of chunks=" << numberOfChunks << "\n";
208  for (uint32_t i = 0; i < numberOfChunks; i++) {
209  schunk = (SctpChunk *)(sctpMsg->removeChunk());
210  if (schunk->getSctpChunkType() == DATA)
211  delete (SctpSimpleMessage *)schunk->decapsulate();
212  EV << "delete chunk " << schunk->getName() << "\n";
213  delete schunk;
214  }
215  }*/
217  insertNetworkProtocolHeader(datagram, Protocol::ipv4, networkHeader);
219  }
220  }
221  else {
222  networkHeader->setDestinationAddress(entry->getLocalAddress().toIpv4());
223  sctp->setDestPort(entry->getLocalPort());
224  if (entry->getGlobalVTag() == 0 && chunk->getSctpChunkType() == INIT_ACK) {
225  SctpInitAckChunk *initAckChunk = check_and_cast<SctpInitAckChunk *>(chunk);
226  entry->setGlobalVTag(initAckChunk->getInitTag());
227  }
228  EV << "destAddress set to " << dgram->getDestinationAddress() << ", destPort set to " << sctpMsg->getDestPort() << "\n";
229  }
230  }
231  else {
232  if (chunk->getSctpChunkType() == INIT) {
233  EV << "getLocALEntry for " << dgram->getSourceAddress() << ":" << sctpMsg->getSrcPort() << " to " << dgram->getDestinationAddress() << ":" << sctpMsg->getDestPort() << " peerVTag=" << sctpMsg->getVTag() << "\n";
234  entry = natTable->getLocalInitEntry(dgram->getDestinationAddress(), sctpMsg->getSrcPort(), sctpMsg->getDestPort());
235  if (entry == nullptr) {
236  entry = new SctpNatEntry();
237  entry->setLocalAddress(dgram->getSourceAddress());
238  entry->setLocalPort(sctpMsg->getSrcPort());
239  entry->setGlobalAddress(dgram->getDestinationAddress());
240  entry->setGlobalPort(sctpMsg->getDestPort());
241  entry->setNattedPort(sctpMsg->getSrcPort());
242  entry->setNattedAddress(dgram->getDestinationAddress());
243  SctpInitChunk *initChunk = check_and_cast<SctpInitChunk *>(chunk);
244  entry->setGlobalVTag(initChunk->getInitTag());
245  natTable->natEntries.push_back(entry);
246  EV << "added entry for local deliver\n";
247  natTable->printNatTable();
249  insertNetworkProtocolHeader(datagram, Protocol::ipv4, networkHeader);
251  }
252  else {
253  SctpNatEntry *entry2 = new SctpNatEntry();
254  entry2->setLocalAddress(dgram->getSourceAddress());
255  entry2->setLocalPort(sctpMsg->getSrcPort());
256  entry2->setGlobalAddress(entry->getGlobalAddress());
257  entry2->setGlobalPort(sctpMsg->getDestPort());
258  entry2->setNattedPort(sctpMsg->getSrcPort());
259  entry2->setNattedAddress(entry->getGlobalAddress());
260  SctpInitChunk *initChunk = check_and_cast<SctpInitChunk *>(chunk);
261  entry2->setGlobalVTag(initChunk->getInitTag());
262  natTable->natEntries.push_back(entry2);
263  networkHeader->setDestinationAddress(entry->getLocalAddress().toIpv4());
264  sctp->setDestPort(entry->getLocalPort());
265  networkHeader->setSourceAddress(entry->getGlobalAddress().toIpv4());
266  sctp->setSrcPort(entry->getGlobalPort());
267  EV << "added additional entry for local deliver\n";
268  natTable->printNatTable();
269  EV << "destAddress set to " << dgram->getDestinationAddress() << ", destPort set to " << sctpMsg->getDestPort() << "\n";
270  }
271  }
272  else {
273  EV << "no INIT: destAddr=" << dgram->getDestinationAddress() << " destPort=" << sctpMsg->getDestPort() << " srcPort=" << sctpMsg->getSrcPort() << " vTag=" << sctpMsg->getVTag() << "\n";
274  entry = natTable->getLocalEntry(dgram->getDestinationAddress(), sctpMsg->getSrcPort(), sctpMsg->getDestPort(), sctpMsg->getVTag());
275  if (entry != nullptr) {
276  networkHeader->setDestinationAddress(entry->getLocalAddress().toIpv4());
277  sctp->setDestPort(entry->getLocalPort());
278  networkHeader->setSourceAddress(entry->getGlobalAddress().toIpv4());
279  sctp->setSrcPort(entry->getGlobalPort());
280  }
281  else {
282  EV << "no entry found\n";
284  insertNetworkProtocolHeader(datagram, Protocol::ipv4, networkHeader);
285 
287  }
288  }
289  }
290 
291  nattedPackets++;
293  insertNetworkProtocolHeader(datagram, Protocol::ipv4, networkHeader);
295 }

◆ finish()

void inet::sctp::SctpNatHook::finish ( )
overrideprotected
316 {
317  auto ipv4 = dynamic_cast<INetfilter *>(getModuleByPath("^.ipv4.ip"));
318  if (isRegisteredHook(ipv4))
319  ipv4->unregisterHook(this);
320  ipLayer = nullptr;
321  EV_INFO << getFullPath() << ": Natted packets: " << nattedPackets << "\n";
322 }

◆ initialize()

void inet::sctp::SctpNatHook::initialize ( )
overrideprotected
29 {
30  rt.reference(this, "routingTableModule", true);
31  ift.reference(this, "interfaceTableModule", true);
32  natTable.reference(this, "natTableModule", true);
33  auto ipv4 = dynamic_cast<INetfilter *>(getModuleByPath("^.ipv4.ip"));
34  ipv4->registerHook(0, this);
35 }

◆ sendBackError()

void inet::sctp::SctpNatHook::sendBackError ( SctpHeader sctp)
protected
298 {
299 // SctpHeader *sctpmsg = new SctpHeader();
300  delete sctp->removeFirstChunk();
301  sctp->setChunkLength(B(SCTP_COMMON_HEADER));
302  SctpErrorChunk *errorChunk = new SctpErrorChunk("NatError");
303  errorChunk->setSctpChunkType(ERRORTYPE);
304  errorChunk->setByteLength(4);
305  SctpSimpleErrorCauseParameter *cause = new SctpSimpleErrorCauseParameter("Cause");
306  cause->setParameterType(MISSING_NAT_ENTRY);
307  cause->setByteLength(4);
308 // cause->encapsulate(dgram->dup());
309  errorChunk->setMBit(true);
310  errorChunk->setTBit(true);
311  errorChunk->addParameters(cause);
312  sctp->appendSctpChunks(errorChunk);
313 }

Referenced by datagramForwardHook().

Member Data Documentation

◆ ift

ModuleRefByPar<IInterfaceTable> inet::sctp::SctpNatHook::ift
protected

Referenced by datagramForwardHook(), and initialize().

◆ ipLayer

IPv4* inet::sctp::SctpNatHook::ipLayer
protected

Referenced by finish(), and SctpNatHook().

◆ natTable

ModuleRefByPar<SctpNatTable> inet::sctp::SctpNatHook::natTable
protected

◆ nattedPackets

uint64_t inet::sctp::SctpNatHook::nattedPackets
protected

◆ rt

ModuleRefByPar<IRoutingTable> inet::sctp::SctpNatHook::rt
protected

The documentation for this class was generated from the following files:
CHK
#define CHK(x)
Definition: INETDefs.h:87
inet::sctp::SctpNatHook::rt
ModuleRefByPar< IRoutingTable > rt
Definition: SctpNatHook.h:18
inet::sctp::SctpNatHook::natTable
ModuleRefByPar< SctpNatTable > natTable
Definition: SctpNatHook.h:17
inet::Protocol::ipv4
static const Protocol ipv4
Definition: Protocol.h:93
inet::sctp::SctpNatHook::sendBackError
void sendBackError(SctpHeader *sctp)
Definition: SctpNatHook.cc:297
InterfaceReq
removed InterfaceReq
Definition: IUdp-gates.txt:11
inet::sctp::SctpNatHook::ift
ModuleRefByPar< IInterfaceTable > ift
Definition: SctpNatHook.h:19
inet::sctp::SctpNatHook::ipLayer
IPv4 * ipLayer
Definition: SctpNatHook.h:16
inet::sctp::MISSING_NAT_ENTRY
@ MISSING_NAT_ENTRY
Definition: SctpAssociation.h:183
inet::sctp::ASCONF
@ ASCONF
Definition: SctpAssociation.h:121
inet::NetfilterBase::HookBase::isRegisteredHook
bool isRegisteredHook(INetfilter *nf)
Definition: INetfilter.h:125
inet::insertNetworkProtocolHeader
void insertNetworkProtocolHeader(Packet *packet, const Protocol &protocol, const Ptr< NetworkHeaderBase > &header)
Definition: L3Tools.cc:70
SCTP_COMMON_HEADER
#define SCTP_COMMON_HEADER
Definition: SctpAssociation.h:203
inet::units::units::B
intscale< b, 1, 8 > B
Definition: Units.h:1168
inet::sctp::INIT
@ INIT
Definition: SctpAssociation.h:103
inet::insertTransportProtocolHeader
void insertTransportProtocolHeader(Packet *packet, const Protocol &protocol, const Ptr< TransportHeaderBase > &header)
Definition: L4Tools.cc:77
inet::sctp::ERRORTYPE
@ ERRORTYPE
Definition: SctpAssociation.h:111
inet::Protocol::sctp
static const Protocol sctp
Definition: Protocol.h:108
inet::sctp::SctpAssociation::getAddressLevel
static int getAddressLevel(const L3Address &addr)
Utility: return IPv4 or IPv6 address level.
Definition: SctpAssociationUtil.cc:2895
inet::INetfilter::IHook::DROP
@ DROP
doesn't allow the datagram to pass to the next hook, will be deleted
Definition: INetfilter.h:41
inet::sctp::COOKIE_ECHO
@ COOKIE_ECHO
Definition: SctpAssociation.h:112
inet::sctp::SctpNatHook::nattedPackets
uint64_t nattedPackets
Definition: SctpNatHook.h:20
inet::INetfilter::IHook::ACCEPT
@ ACCEPT
allows the datagram to pass to the next hook
Definition: INetfilter.h:40
inet::sctp::INIT_ACK
@ INIT_ACK
Definition: SctpAssociation.h:104