INET Framework for OMNeT++/OMNEST
inet::serializer::IPv4Serializer Class Reference

Converts between IPv4Datagram and binary (network byte order) IPv4 header. More...

#include <IPv4Serializer.h>

Inheritance diagram for inet::serializer::IPv4Serializer:
inet::serializer::SerializerBase

Public Member Functions

 IPv4Serializer (const char *name=nullptr)
 
- Public Member Functions inherited from inet::serializer::SerializerBase
 SerializerBase (const char *name=nullptr)
 
void serializePacket (const cPacket *pkt, Buffer &b, Context &context)
 
cPacket * deserializePacket (const Buffer &b, Context &context)
 

Protected Member Functions

virtual void serialize (const cPacket *pkt, Buffer &b, Context &context) override
 Serializes a cPacket for transmission on the wire. More...
 
virtual cPacket * deserialize (const Buffer &b, Context &context) override
 Puts a packet sniffed from the wire into an EtherFrame. More...
 
void serializeOptions (const IPv4Datagram *dgram, Buffer &b, Context &c)
 
void deserializeOptions (IPv4Datagram *dgram, Buffer &b, Context &c)
 

Additional Inherited Members

- Static Public Member Functions inherited from inet::serializer::SerializerBase
static SerializerBaselookupSerializer (const cPacket *pkt, Context &context, ProtocolGroup group, int id)
 
static void lookupAndSerialize (const cPacket *pkt, Buffer &b, Context &context, ProtocolGroup group, int id, unsigned int maxLength=(unsigned int)(-1))
 
static SerializerBaselookupDeserializer (Context &context, ProtocolGroup group, int id)
 
static cPacket * lookupAndDeserialize (const Buffer &b, Context &context, ProtocolGroup group, int id, unsigned int maxLength=(unsigned int)(-1))
 

Detailed Description

Converts between IPv4Datagram and binary (network byte order) IPv4 header.

Constructor & Destructor Documentation

inet::serializer::IPv4Serializer::IPv4Serializer ( const char *  name = nullptr)
inline
88 : SerializerBase(name) {}
SerializerBase(const char *name=nullptr)
Definition: SerializerBase.h:84

Member Function Documentation

cPacket * inet::serializer::IPv4Serializer::deserialize ( const Buffer b,
Context context 
)
overrideprotectedvirtual

Puts a packet sniffed from the wire into an EtherFrame.

Implements inet::serializer::SerializerBase.

304 {
305  ASSERT(b.getPos() == 0);
306 
307  IPv4Datagram *dest = new IPv4Datagram("parsed-ipv4");
308  unsigned int bufsize = b.getRemainingSize();
309  const struct ip *ip = static_cast<const struct ip *>(b.accessNBytes(IP_HEADER_BYTES));
310  if (!ip ) {
311  delete dest;
312  return nullptr;
313  }
314  unsigned int totalLength, headerLength;
315  c.l3AddressesPtr = &ip->ip_src.s_addr;
316  c.l3AddressesLength = sizeof(ip->ip_src.s_addr) + sizeof(ip->ip_dst.s_addr);
317 
318  dest->setVersion(ip->ip_v);
319  dest->setHeaderLength(IP_HEADER_BYTES);
320  dest->setSrcAddress(IPv4Address(ntohl(ip->ip_src.s_addr)));
321  dest->setDestAddress(IPv4Address(ntohl(ip->ip_dst.s_addr)));
322  dest->setTransportProtocol(ip->ip_p);
323  dest->setTimeToLive(ip->ip_ttl);
324  dest->setIdentification(ntohs(ip->ip_id));
325  uint16_t ip_off = ntohs(ip->ip_off);
326  dest->setMoreFragments((ip_off & IP_MF) != 0);
327  dest->setDontFragment((ip_off & IP_DF) != 0);
328  dest->setFragmentOffset((ntohs(ip->ip_off) & IP_OFFMASK) * 8);
329  dest->setTypeOfService(ip->ip_tos);
330  totalLength = ntohs(ip->ip_len);
331  dest->setTotalLengthField(totalLength);
332  headerLength = ip->ip_hl << 2;
333 
334  if (headerLength < IP_HEADER_BYTES) {
335  dest->setBitError(true);
336  headerLength = IP_HEADER_BYTES;
337  }
338 
339  dest->setHeaderLength(headerLength);
340 
341  if (headerLength > b._getBufSize() || TCPIPchecksum::checksum(ip, headerLength) != 0)
342  dest->setBitError(true);
343 
344  if (headerLength > IP_HEADER_BYTES) { // options present?
345  unsigned short optionBytes = headerLength - IP_HEADER_BYTES;
346  Buffer sb(b, optionBytes);
347  deserializeOptions(dest, sb, c);
348  if (sb.hasError())
349  b.setError();
350  }
351  b.seek(headerLength);
352 
353  if (totalLength > bufsize)
354  EV_ERROR << "Can not handle IPv4 packet of total length " << totalLength << "(captured only " << bufsize << " bytes).\n";
355 
356  dest->setByteLength(headerLength);
357  unsigned int payloadLength = totalLength - headerLength;
358  cPacket *encapPacket = nullptr;
359  if (dest->getMoreFragments() || dest->getFragmentOffset() != 0) { // IP fragment
360  Buffer subBuffer(b, payloadLength);
361  encapPacket = serializers.byteArraySerializer.deserialize(subBuffer, c);
362  b.accessNBytes(subBuffer.getPos());
363  }
364  else
365  encapPacket = SerializerBase::lookupAndDeserialize(b, c, IP_PROT, dest->getTransportProtocol(), payloadLength);
366 
367  if (encapPacket) {
368  dest->encapsulate(encapPacket);
369  dest->setName(encapPacket->getName());
370  }
371  return dest;
372 }
#define IP_MF
Definition: ip.h:73
u16_t ntohs(u16_t n)
static ByteArraySerializer byteArraySerializer
Definition: SerializerBase.h:113
const int IP_HEADER_BYTES
Definition: IPv4Datagram_m.h:41
Definition: SerializerBase.h:38
static uint16_t checksum(const void *addr, unsigned int count)
Definition: TCPIPchecksum.h:44
void deserializeOptions(IPv4Datagram *dgram, Buffer &b, Context &c)
Definition: IPv4Serializer.cc:393
u32_t ntohl(u32_t n)
#define IP_DF
Definition: ip.h:72
virtual cPacket * deserialize(const Buffer &b, Context &context) override
Puts a packet sniffed from the wire into an EtherFrame.
Definition: SerializerBase.cc:146
const value< double, compose< units::m, pow< units::s,-1 > > > c(299792458)
#define IP_OFFMASK
Definition: ip.h:74
SerializerRegistrationList serializers("default")
List of packet serializers (SerializerBase)
Definition: SerializerBase.h:146
static cPacket * lookupAndDeserialize(const Buffer &b, Context &context, ProtocolGroup group, int id, unsigned int maxLength=(unsigned int)(-1))
Definition: SerializerBase.cc:99
value< double, units::m > b
Definition: Units.h:1054
void inet::serializer::IPv4Serializer::deserializeOptions ( IPv4Datagram dgram,
Buffer b,
Context c 
)
protected
394 {
395  while (b.getRemainingSize()) {
396  unsigned int pos = b.getPos();
397  unsigned char type = b.readByte();
398  b.seek(pos);
399  TLVOptionBase *option = ipv4OptionSerializers.lookup(type)->deserializeOption(b, c);
400  dgram->addOption(option);
401  }
402 }
const value< double, compose< units::m, pow< units::s,-1 > > > c(299792458)
virtual TLVOptionBase * deserializeOption(Buffer &b, Context &c)=0
IPv4OptionSerializerRegistrationList ipv4OptionSerializers("IPv4OptionSerializers")
List of IPv4Option serializers (IPv4OptionSerializerBase)
Definition: IPv4Serializer.h:70
virtual IPv4OptionSerializerBase * lookup(int id) const
Returns the object with exactly the given ID.
Definition: IPv4Serializer.cc:428
value< double, units::m > b
Definition: Units.h:1054
void inet::serializer::IPv4Serializer::serialize ( const cPacket *  pkt,
Buffer b,
Context context 
)
overrideprotectedvirtual

Serializes a cPacket for transmission on the wire.

Returns the length of data written into buffer.

Implements inet::serializer::SerializerBase.

137 {
138  ASSERT(b.getPos() == 0);
139 
140  if (typeid(*pkt) != typeid(IPv4Datagram)) {
141  if (c.throwOnSerializerNotFound)
142  throw cRuntimeError("IPv4Serializer: class '%s' not accepted", pkt->getClassName());
143  EV_ERROR << "IPv4Serializer: class '" << pkt->getClassName() << "' not accepted.\n";
144  b.fillNBytes(pkt->getByteLength(), '?');
145  return;
146  }
147 
148  struct ip *ip = (struct ip *)b.accessNBytes(IP_HEADER_BYTES);
149  if (!ip) {
150  EV_ERROR << "IPv4Serializer: not enough space for IPv4 header.\n";
151  return;
152  }
153  const IPv4Datagram *dgram = check_and_cast<const IPv4Datagram *>(pkt);
154  unsigned int headerLength = dgram->getHeaderLength();
155  ASSERT((headerLength & 3) == 0);
156  ip->ip_hl = headerLength >> 2;
157  ip->ip_v = dgram->getVersion();
158  ip->ip_tos = dgram->getTypeOfService();
159  ip->ip_id = htons(dgram->getIdentification());
160  ASSERT((dgram->getFragmentOffset() & 7) == 0);
161  uint16_t ip_off = dgram->getFragmentOffset() / 8;
162  if (dgram->getMoreFragments())
163  ip_off |= IP_MF;
164  if (dgram->getDontFragment())
165  ip_off |= IP_DF;
166  ip->ip_off = htons(ip_off);
167  ip->ip_ttl = dgram->getTimeToLive();
168  ip->ip_p = dgram->getTransportProtocol();
169  ip->ip_src.s_addr = htonl(dgram->getSrcAddress().getInt());
170  ip->ip_dst.s_addr = htonl(dgram->getDestAddress().getInt());
171  ip->ip_len = htons(dgram->getTotalLengthField());
172  ip->ip_sum = 0;
173  c.l3AddressesPtr = &ip->ip_src.s_addr;
174  c.l3AddressesLength = sizeof(ip->ip_src.s_addr) + sizeof(ip->ip_dst.s_addr);
175 
176  if (headerLength > IP_HEADER_BYTES) {
177  Buffer sb(b, headerLength - IP_HEADER_BYTES);
178  serializeOptions(dgram, sb, c);
179  b.accessNBytes(sb.getPos());
180  if (sb.hasError())
181  b.setError();
182  }
183 
184  const cPacket *encapPacket = dgram->getEncapsulatedPacket();
185  unsigned int payloadLength = dgram->getByteLength() - b.getPos();
186 
187  if (encapPacket) {
188  unsigned int totalLength = encapPacket->getByteLength();
189  int fragmentOffset = dgram->getFragmentOffset();
190  if ((dgram->getMoreFragments() || fragmentOffset != 0) && (payloadLength < totalLength)) { // IP fragment //FIXME hack: encapsulated packet contains entire packet if payloadLength < totalLength
191  char *buf = new char[totalLength];
192  Buffer tmpBuffer(buf, totalLength);
193  SerializerBase::lookupAndSerialize(encapPacket, tmpBuffer, c, IP_PROT, dgram->getTransportProtocol());
194  tmpBuffer.seek(fragmentOffset);
195  b.writeNBytes(tmpBuffer, payloadLength);
196  delete [] buf;
197  }
198  else // no fragmentation, or the encapsulated packet is represents only the fragment
199  SerializerBase::lookupAndSerialize(encapPacket, b, c, IP_PROT, dgram->getTransportProtocol());
200  }
201  else {
202  b.fillNBytes(payloadLength, '?');
203  }
204 
205  ip->ip_sum = htons(TCPIPchecksum::checksum(ip, IP_HEADER_BYTES));
206 }
#define IP_MF
Definition: ip.h:73
const int IP_HEADER_BYTES
Definition: IPv4Datagram_m.h:41
Definition: SerializerBase.h:38
static uint16_t checksum(const void *addr, unsigned int count)
Definition: TCPIPchecksum.h:44
#define IP_DF
Definition: ip.h:72
u16_t htons(u16_t n)
const value< double, compose< units::m, pow< units::s,-1 > > > c(299792458)
void serializeOptions(const IPv4Datagram *dgram, Buffer &b, Context &c)
Definition: IPv4Serializer.cc:374
u32_t htonl(u32_t n)
static void lookupAndSerialize(const cPacket *pkt, Buffer &b, Context &context, ProtocolGroup group, int id, unsigned int maxLength=(unsigned int)(-1))
Definition: SerializerBase.cc:88
value< double, units::m > b
Definition: Units.h:1054
void inet::serializer::IPv4Serializer::serializeOptions ( const IPv4Datagram dgram,
Buffer b,
Context c 
)
protected
375 {
376  unsigned short numOptions = dgram->getOptionArraySize();
377  unsigned int optionsLength = 0;
378  if (numOptions > 0) { // options present?
379  for (unsigned short i = 0; i < numOptions; i++) {
380  const TLVOptionBase *option = &dgram->getOption(i);
381  ipv4OptionSerializers.lookup(option->getType())->serializeOption(option, b, c);
382  optionsLength += option->getLength();
383  }
384  } // if options present
385  if (dgram->getHeaderLength() < (int)(IP_HEADER_BYTES + optionsLength))
386  throw cRuntimeError("Serializing an IPv4 packet with wrong headerLength value: not enough for store options.\n");
387  //padding:
388  if (b.getRemainingSize()) {
389  b.fillNBytes(b.getRemainingSize(), IPOPTION_END_OF_OPTIONS);
390  }
391 }
const int IP_HEADER_BYTES
Definition: IPv4Datagram_m.h:41
Definition: IPv4Datagram_m.h:105
const value< double, compose< units::m, pow< units::s,-1 > > > c(299792458)
IPv4OptionSerializerRegistrationList ipv4OptionSerializers("IPv4OptionSerializers")
List of IPv4Option serializers (IPv4OptionSerializerBase)
Definition: IPv4Serializer.h:70
virtual IPv4OptionSerializerBase * lookup(int id) const
Returns the object with exactly the given ID.
Definition: IPv4Serializer.cc:428
value< double, units::m > b
Definition: Units.h:1054

The documentation for this class was generated from the following files: