INET Framework for OMNeT++/OMNEST
inet::Ipv4HeaderSerializer Class Reference

Converts between Ipv4Header and binary (network byte order) Ipv4 header. More...

#include <Ipv4HeaderSerializer.h>

Inheritance diagram for inet::Ipv4HeaderSerializer:
inet::FieldsChunkSerializer inet::ChunkSerializer

Public Member Functions

 Ipv4HeaderSerializer ()
 
- Public Member Functions inherited from inet::FieldsChunkSerializer
virtual void serialize (MemoryOutputStream &stream, const Ptr< const Chunk > &chunk, b offset, b length) const override
 Serializes a chunk into a stream by writing the bytes representing the chunk at the end of the stream. More...
 
virtual const Ptr< Chunkdeserialize (MemoryInputStream &stream, const std::type_info &typeInfo) const override
 Deserializes a chunk from a stream by reading the bytes at the current position of the stream. More...
 

Protected Member Functions

virtual void serializeOption (MemoryOutputStream &stream, const TlvOptionBase *option) const
 
virtual TlvOptionBasedeserializeOption (MemoryInputStream &stream) const
 
virtual void serialize (MemoryOutputStream &stream, const Ptr< const Chunk > &chunk) const override
 Serializes a chunk into a stream by writing all bytes representing the chunk at the end of the stream. More...
 
virtual const Ptr< Chunkdeserialize (MemoryInputStream &stream) const override
 Deserializes a chunk from a stream by reading the bytes at the current position of the stream. More...
 

Additional Inherited Members

- Static Public Attributes inherited from inet::ChunkSerializer
static b totalSerializedLength = b(0)
 
static b totalDeserializedLength = b(0)
 

Detailed Description

Converts between Ipv4Header and binary (network byte order) Ipv4 header.

Constructor & Destructor Documentation

◆ Ipv4HeaderSerializer()

inet::Ipv4HeaderSerializer::Ipv4HeaderSerializer ( )
inline
29 : FieldsChunkSerializer() {}

Member Function Documentation

◆ deserialize()

const Ptr< Chunk > inet::Ipv4HeaderSerializer::deserialize ( MemoryInputStream stream) const
overrideprotectedvirtual

Deserializes a chunk from a stream by reading the bytes at the current position of the stream.

The current stream position is updated according to the length of the returned chunk.

Implements inet::FieldsChunkSerializer.

147 {
148  auto position = stream.getPosition();
149  B bufsize = stream.getRemainingLength();
150  uint8_t buffer[B(IPv4_MIN_HEADER_LENGTH).get()];
151  stream.readBytes(buffer, IPv4_MIN_HEADER_LENGTH);
152  auto ipv4Header = makeShared<Ipv4Header>();
153  const struct ip& iphdr = *static_cast<const struct ip *>((void *)&buffer);
154  B totalLength, headerLength;
155 
156  ipv4Header->setVersion(iphdr.ip_v);
157  ipv4Header->setHeaderLength(IPv4_MIN_HEADER_LENGTH);
158  ipv4Header->setSrcAddress(Ipv4Address(ntohl(iphdr.ip_src.s_addr)));
159  ipv4Header->setDestAddress(Ipv4Address(ntohl(iphdr.ip_dst.s_addr)));
160  ipv4Header->setProtocolId((IpProtocolId)iphdr.ip_p);
161  ipv4Header->setTimeToLive(iphdr.ip_ttl);
162  ipv4Header->setIdentification(ntohs(iphdr.ip_id));
163  uint16_t ip_off = ntohs(iphdr.ip_off);
164  ipv4Header->setReservedBit((ip_off & IP_RF) != 0);
165  ipv4Header->setMoreFragments((ip_off & IP_MF) != 0);
166  ipv4Header->setDontFragment((ip_off & IP_DF) != 0);
167  ipv4Header->setFragmentOffset((ntohs(iphdr.ip_off) & IP_OFFMASK) * 8);
168  ipv4Header->setTypeOfService(iphdr.ip_tos);
169  totalLength = B(ntohs(iphdr.ip_len));
170  ipv4Header->setTotalLengthField(totalLength);
171  headerLength = B(iphdr.ip_hl << 2);
172 
173  if (iphdr.ip_v != 4)
174  ipv4Header->markIncorrect();
175  if (headerLength < IPv4_MIN_HEADER_LENGTH) {
176  ipv4Header->markIncorrect();
177  headerLength = IPv4_MIN_HEADER_LENGTH;
178  }
179  if (totalLength < headerLength)
180  ipv4Header->markIncorrect();
181 
182  ipv4Header->setHeaderLength(headerLength);
183 
184  if (headerLength > IPv4_MIN_HEADER_LENGTH) { // options present?
185  while (stream.getRemainingLength() > B(0) && stream.getPosition() - position < headerLength) {
186  TlvOptionBase *option = deserializeOption(stream);
187  ipv4Header->addOption(option);
188  }
189  }
190  if (headerLength > bufsize) {
191  ipv4Header->markIncomplete();
192  }
193 
194  ipv4Header->setCrc(ntohs(iphdr.ip_sum));
195  ipv4Header->setCrcMode(CRC_COMPUTED);
196 
197  return ipv4Header;
198 }

◆ deserializeOption()

TlvOptionBase * inet::Ipv4HeaderSerializer::deserializeOption ( MemoryInputStream stream) const
protectedvirtual
201 {
202  auto position = stream.getPosition();
203  unsigned char type = stream.readByte();
204  unsigned char length = 1;
205 
206  switch (type) {
207  case IPOPTION_END_OF_OPTIONS: // EOL
208  return new Ipv4OptionEnd();
209 
210  case IPOPTION_NO_OPTION: // NOP
211  return new Ipv4OptionNop();
212 
213  case IPOPTION_STREAM_ID:
214  length = stream.readByte();
215  if (length == 4) {
216  auto *option = new Ipv4OptionStreamId();
217  option->setType(type);
218  option->setLength(length);
219  option->setStreamId(stream.readUint16Be());
220  return option;
221  }
222  break;
223 
224  case IPOPTION_TIMESTAMP: {
225  length = stream.readByte();
226  uint8_t pointer = stream.readByte();
227  uint8_t flagbyte = stream.readByte();
228  uint8_t overflow = flagbyte >> 4;
229  TimestampFlag flag = static_cast<TimestampFlag>(-1);
230  int bytes = 0;
231  switch (flagbyte & 0x0f) {
232  case 0: flag = IP_TIMESTAMP_TIMESTAMP_ONLY; bytes = 4; break;
233  case 1: flag = IP_TIMESTAMP_WITH_ADDRESS; bytes = 8; break;
234  case 3: flag = IP_TIMESTAMP_SENDER_INIT_ADDRESS; bytes = 8; break;
235  default: break;
236  }
237  if (flag != static_cast<TimestampFlag>(-1) && length > 4 && bytes && ((length - 4) % bytes) == 0 && pointer >= 5 && ((pointer - 5) % bytes) == 0) {
238  auto *option = new Ipv4OptionTimestamp();
239  option->setType(type);
240  option->setLength(length);
241  option->setFlag(flag);
242  option->setOverflow(overflow);
243  option->setRecordTimestampArraySize((length - 4) / bytes);
244  if (bytes == 8)
245  option->setRecordAddressArraySize((length - 4) / bytes);
246  option->setNextIdx((pointer - 5) / bytes);
247  for (unsigned int count = 0; count < option->getRecordAddressArraySize(); count++) {
248  if (bytes == 8)
249  option->setRecordAddress(count, stream.readIpv4Address());
250  option->setRecordTimestamp(count, SimTime(stream.readUint32Be(), SIMTIME_MS));
251  }
252  return option;
253  }
254  break;
255  }
256 
260  length = stream.readByte();
261  uint8_t pointer = stream.readByte();
262  if (length > 3 && (length % 4) == 3 && pointer >= 4 && (pointer % 4) == 0) {
263  auto *option = new Ipv4OptionRecordRoute();
264  option->setType(type);
265  option->setLength(length);
266  option->setRecordAddressArraySize((length - 3) / 4);
267  option->setNextAddressIdx((pointer - 4) / 4);
268  for (unsigned int count = 0; count < option->getRecordAddressArraySize(); count++) {
269  option->setRecordAddress(count, stream.readIpv4Address());
270  }
271  return option;
272  }
273  break;
274  }
275 
277  length = stream.readByte();
278  if (length == 4) {
279  auto *option = new Ipv4OptionRouterAlert();
280  option->setType(type);
281  option->setLength(length);
282  option->setRouterAlert(stream.readUint16Be());
283  return option;
284  }
285  break;
286 
287  case IPOPTION_SECURITY:
288  default:
289  length = stream.readByte();
290  break;
291  } // switch
292 
293  auto *option = new TlvOptionRaw();
294  stream.seek(position);
295  type = stream.readByte();
296  length = stream.readByte();
297  option->setType(type);
298  option->setLength(length);
299  if (length > 2)
300  option->setBytesArraySize(length - 2);
301  for (unsigned int i = 2; i < length; i++)
302  option->setBytes(i - 2, stream.readByte());
303  return option;
304 }

Referenced by deserialize().

◆ serialize()

void inet::Ipv4HeaderSerializer::serialize ( MemoryOutputStream stream,
const Ptr< const Chunk > &  chunk 
) const
overrideprotectedvirtual

Serializes a chunk into a stream by writing all bytes representing the chunk at the end of the stream.

Implements inet::FieldsChunkSerializer.

19 {
20  auto startPosition = stream.getLength();
21  struct ip iphdr;
22  const auto& ipv4Header = staticPtrCast<const Ipv4Header>(chunk);
23  B headerLength = ipv4Header->getHeaderLength();
24  ASSERT((headerLength.get() & 3) == 0 && headerLength >= IPv4_MIN_HEADER_LENGTH && headerLength <= IPv4_MAX_HEADER_LENGTH);
25  ASSERT(headerLength <= ipv4Header->getTotalLengthField());
26  iphdr.ip_hl = B(headerLength).get() >> 2;
27  iphdr.ip_v = ipv4Header->getVersion();
28  iphdr.ip_tos = ipv4Header->getTypeOfService();
29  iphdr.ip_id = htons(ipv4Header->getIdentification());
30  ASSERT((ipv4Header->getFragmentOffset() & 7) == 0);
31  uint16_t ip_off = (ipv4Header->getFragmentOffset() / 8) & IP_OFFMASK;
32  if (ipv4Header->getReservedBit())
33  ip_off |= IP_RF;
34  if (ipv4Header->getMoreFragments())
35  ip_off |= IP_MF;
36  if (ipv4Header->getDontFragment())
37  ip_off |= IP_DF;
38  iphdr.ip_off = htons(ip_off);
39  iphdr.ip_ttl = ipv4Header->getTimeToLive();
40  iphdr.ip_p = ipv4Header->getProtocolId();
41  iphdr.ip_src.s_addr = htonl(ipv4Header->getSrcAddress().getInt());
42  iphdr.ip_dst.s_addr = htonl(ipv4Header->getDestAddress().getInt());
43  iphdr.ip_len = htons(B(ipv4Header->getTotalLengthField()).get());
44  if (ipv4Header->getCrcMode() != CRC_COMPUTED)
45  throw cRuntimeError("Cannot serialize Ipv4 header without a properly computed CRC");
46  iphdr.ip_sum = htons(ipv4Header->getCrc());
47  stream.writeBytes((uint8_t *)&iphdr, IPv4_MIN_HEADER_LENGTH);
48 
49  if (headerLength > IPv4_MIN_HEADER_LENGTH) {
50  unsigned short numOptions = ipv4Header->getOptionArraySize();
51  B optionsLength = B(0);
52  if (numOptions > 0) { // options present?
53  for (unsigned short i = 0; i < numOptions; i++) {
54  const TlvOptionBase *option = &ipv4Header->getOption(i);
55  serializeOption(stream, option);
56  optionsLength += B(option->getLength());
57  }
58  } // if options present
59  if (ipv4Header->getHeaderLength() < IPv4_MIN_HEADER_LENGTH + optionsLength)
60  throw cRuntimeError("Serializing an Ipv4 packet with wrong headerLength value: not enough for store options.\n");
61  auto writtenLength = B(stream.getLength() - startPosition);
62  if (writtenLength < headerLength)
63  stream.writeByteRepeatedly(IPOPTION_END_OF_OPTIONS, B(headerLength - writtenLength).get());
64  }
65 }

◆ serializeOption()

void inet::Ipv4HeaderSerializer::serializeOption ( MemoryOutputStream stream,
const TlvOptionBase option 
) const
protectedvirtual
68 {
69  unsigned short type = option->getType();
70  unsigned short length = option->getLength(); // length >= 1
71 
72  stream.writeByte(type);
73  if (length > 1)
74  stream.writeByte(length);
75 
76  auto *opt = dynamic_cast<const TlvOptionRaw *>(option);
77  if (opt) {
78  unsigned int datalen = opt->getBytesArraySize();
79  ASSERT(length == 2 + datalen);
80  for (unsigned int i = 0; i < datalen; i++)
81  stream.writeByte(opt->getBytes(i));
82  return;
83  }
84 
85  switch (type) {
87  check_and_cast<const Ipv4OptionEnd *>(option);
88  ASSERT(length == 1);
89  break;
90 
91  case IPOPTION_NO_OPTION:
92  check_and_cast<const Ipv4OptionNop *>(option);
93  ASSERT(length == 1);
94  break;
95 
96  case IPOPTION_STREAM_ID: {
97  auto *opt = check_and_cast<const Ipv4OptionStreamId *>(option);
98  ASSERT(length == 4);
99  stream.writeUint16Be(opt->getStreamId());
100  break;
101  }
102 
103  case IPOPTION_TIMESTAMP: {
104  auto *opt = check_and_cast<const Ipv4OptionTimestamp *>(option);
105  int bytes = (opt->getFlag() == IP_TIMESTAMP_TIMESTAMP_ONLY) ? 4 : 8;
106  ASSERT(length == 4 + bytes * opt->getRecordTimestampArraySize());
107  uint8_t pointer = 5 + opt->getNextIdx() * bytes;
108  stream.writeByte(pointer);
109  uint8_t flagbyte = opt->getOverflow() << 4 | opt->getFlag();
110  stream.writeByte(flagbyte);
111  for (unsigned int count = 0; count < opt->getRecordTimestampArraySize(); count++) {
112  if (bytes == 8)
113  stream.writeIpv4Address(opt->getRecordAddress(count));
114  stream.writeUint32Be(opt->getRecordTimestamp(count).inUnit(SIMTIME_MS));
115  }
116  break;
117  }
118 
122  auto *opt = check_and_cast<const Ipv4OptionRecordRoute *>(option);
123  ASSERT(length == 3 + 4 * opt->getRecordAddressArraySize());
124  uint8_t pointer = 4 + opt->getNextAddressIdx() * 4;
125  stream.writeByte(pointer);
126  for (unsigned int count = 0; count < opt->getRecordAddressArraySize(); count++) {
127  stream.writeIpv4Address(opt->getRecordAddress(count));
128  }
129  break;
130  }
131  case IPOPTION_ROUTER_ALERT: {
132  auto *opt = check_and_cast<const Ipv4OptionRouterAlert *>(option);
133  ASSERT(length == 4);
134  stream.writeUint16Be(opt->getRouterAlert());
135  break;
136  }
137 
138  case IPOPTION_SECURITY:
139  default: {
140  throw cRuntimeError("Unknown Ipv4Option type=%d (not in an TlvOptionRaw option)", type);
141  break;
142  }
143  }
144 }

Referenced by serialize().


The documentation for this class was generated from the following files:
inet::IPOPTION_END_OF_OPTIONS
@ IPOPTION_END_OF_OPTIONS
Definition: Ipv4Header_m.h:133
inet::IPOPTION_LOOSE_SOURCE_ROUTING
@ IPOPTION_LOOSE_SOURCE_ROUTING
Definition: Ipv4Header_m.h:138
inet::IPOPTION_TIMESTAMP
@ IPOPTION_TIMESTAMP
Definition: Ipv4Header_m.h:136
ntohs
u16_t ntohs(u16_t n)
inet::count
int count(const std::vector< T > &v, const Tk &a)
Definition: stlutils.h:54
inet::CRC_COMPUTED
@ CRC_COMPUTED
Definition: CrcMode_m.h:59
inet::IPOPTION_STRICT_SOURCE_ROUTING
@ IPOPTION_STRICT_SOURCE_ROUTING
Definition: Ipv4Header_m.h:140
htonl
u32_t htonl(u32_t n)
ntohl
u32_t ntohl(u32_t n)
inet::IPOPTION_ROUTER_ALERT
@ IPOPTION_ROUTER_ALERT
Definition: Ipv4Header_m.h:141
htons
u16_t htons(u16_t n)
inet::units::units::B
intscale< b, 1, 8 > B
Definition: Units.h:1168
inet::IPOPTION_RECORD_ROUTE
@ IPOPTION_RECORD_ROUTE
Definition: Ipv4Header_m.h:139
inet::IPOPTION_NO_OPTION
@ IPOPTION_NO_OPTION
Definition: Ipv4Header_m.h:134
IP_MF
#define IP_MF
Definition: ip.h:71
type
removed type
Definition: IUdp-gates.txt:7
inet::IPOPTION_SECURITY
@ IPOPTION_SECURITY
Definition: Ipv4Header_m.h:137
IP_RF
#define IP_RF
Definition: ip.h:69
inet::TimestampFlag
TimestampFlag
Enum generated from inet/networklayer/ipv4/Ipv4Header.msg:75 by opp_msgtool.
Definition: Ipv4Header_m.h:162
inet::IPOPTION_STREAM_ID
@ IPOPTION_STREAM_ID
Definition: Ipv4Header_m.h:135
IP_DF
#define IP_DF
Definition: ip.h:70
inet::IP_TIMESTAMP_TIMESTAMP_ONLY
@ IP_TIMESTAMP_TIMESTAMP_ONLY
Definition: Ipv4Header_m.h:163
IP_OFFMASK
#define IP_OFFMASK
Definition: ip.h:72
inet::Ipv4HeaderSerializer::deserializeOption
virtual TlvOptionBase * deserializeOption(MemoryInputStream &stream) const
Definition: Ipv4HeaderSerializer.cc:200
inet::Ipv4HeaderSerializer::serializeOption
virtual void serializeOption(MemoryOutputStream &stream, const TlvOptionBase *option) const
Definition: Ipv4HeaderSerializer.cc:67
inet::IPv4_MAX_HEADER_LENGTH
const B IPv4_MAX_HEADER_LENGTH
Definition: Ipv4Header_m.h:71
inet::IP_TIMESTAMP_SENDER_INIT_ADDRESS
@ IP_TIMESTAMP_SENDER_INIT_ADDRESS
Definition: Ipv4Header_m.h:165
inet::IP_TIMESTAMP_WITH_ADDRESS
@ IP_TIMESTAMP_WITH_ADDRESS
Definition: Ipv4Header_m.h:164
inet::IpProtocolId
IpProtocolId
Enum generated from inet/networklayer/common/IpProtocolId.msg:17 by opp_msgtool.
Definition: IpProtocolId_m.h:90
inet::IPv4_MIN_HEADER_LENGTH
const B IPv4_MIN_HEADER_LENGTH
Definition: Ipv4Header_m.h:68