libtins  4.4
ip.h
1 /*
2  * Copyright (c) 2017, Matias Fontanini
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 are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #ifndef TINS_IP_H
31 #define TINS_IP_H
32 
33 #include <tins/pdu.h>
34 #include <tins/small_uint.h>
35 #include <tins/endianness.h>
36 #include <tins/ip_address.h>
37 #include <tins/pdu_option.h>
38 #include <tins/macros.h>
39 #include <tins/cxxstd.h>
40 
41 namespace Tins {
42 namespace Memory {
43 
44 class OutputMemoryStream;
45 
46 } // Memory
47 
63 class TINS_API IP : public PDU {
64 public:
68  static const PDU::PDUType pdu_flag = PDU::IP;
69 
74 
78  enum Flags {
79  FLAG_RESERVED = 4,
80  DONT_FRAGMENT = 2,
81  MORE_FRAGMENTS = 1
82  };
83 
90  enum OptionClass {
91  CONTROL = 0,
92  MEASUREMENT = 2
93  };
94 
101  END = 0,
102  NOOP = 1,
103  SEC = 2,
104  LSRR = 3,
105  TIMESTAMP = 4,
106  EXTSEC = 5,
107  RR = 7,
108  SID = 8,
109  SSRR = 9,
110  MTUPROBE = 11,
111  MTUREPLY = 12,
112  EIP = 17,
113  TR = 18,
114  ADDEXT = 19,
115  RTRALT = 20,
116  SDB = 21,
117  DPS = 23,
118  UMP = 24,
119  QS = 25
120  };
121 
125  TINS_BEGIN_PACK
127  #if TINS_IS_LITTLE_ENDIAN
128  uint8_t number:5,
129  op_class:2,
130  copied:1;
131  #elif TINS_IS_BIG_ENDIAN
132  uint8_t copied:1,
133  op_class:2,
134  number:5;
135  #endif
142  #if TINS_IS_LITTLE_ENDIAN
143  : number(0), op_class(0), copied(0) {}
144  #else
145  : copied(0), op_class(0), number(0) {}
146  #endif
147 
157  option_identifier(uint8_t value)
158  #if TINS_IS_LITTLE_ENDIAN
159  : number(value & 0x1f),
160  op_class((value >> 5) & 0x03),
161  copied((value >> 7) & 0x01) {}
162  #elif TINS_IS_BIG_ENDIAN
163  : copied((value >> 7) & 0x01),
164  op_class((value >> 5) & 0x03),
165  number(value & 0x1f) {}
166  #endif
167 
174  option_identifier(OptionNumber number, OptionClass op_class,
175  small_uint<1> copied)
176  #if TINS_IS_LITTLE_ENDIAN
177  : number(static_cast<uint8_t>(number)), op_class(static_cast<uint8_t>(op_class)), copied(copied) {}
178  #else
179  : copied(copied), op_class(static_cast<uint8_t>(op_class)), number(static_cast<uint8_t>(number)) {}
180  #endif
181 
185  bool operator==(const option_identifier& rhs) const {
186  return number == rhs.number && op_class == rhs.op_class && copied == rhs.copied;
187  }
188  } TINS_END_PACK;
189 
194 
198  struct security_type {
199  uint16_t security, compartments;
200  uint16_t handling_restrictions;
201  small_uint<24> transmission_control;
202 
203  security_type(uint16_t sec = 0,
204  uint16_t comp = 0,
205  uint16_t hand_res = 0,
206  small_uint<24> tcc = 0)
207  : security(sec), compartments(comp),
208  handling_restrictions(hand_res), transmission_control(tcc) { }
209 
210  static security_type from_option(const option& opt);
211  };
212 
217  typedef std::vector<address_type> routes_type;
218 
219  uint8_t pointer;
220  routes_type routes;
221 
222  generic_route_option_type(uint8_t ptr = 0, routes_type rts = routes_type())
223  : pointer(ptr), routes(rts) {}
224 
225  static generic_route_option_type from_option(const option& opt);
226  };
227 
232 
237 
242 
246  typedef std::vector<option> options_type;
247 
254  static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
255 
266  IP(address_type ip_dst = address_type(),
267  address_type ip_src = address_type());
268 
280  IP(const uint8_t* buffer, uint32_t total_sz);
281 
282  /* Getters */
283 
284  uint32_t advertised_size() const {
285  return static_cast<uint32_t>(tot_len());
286  }
287 
294  return this->header_.ihl;
295  }
296 
302  uint8_t tos() const {
303  return header_.tos;
304  }
305 
311  uint16_t tot_len() const {
312  return Endian::be_to_host(header_.tot_len);
313  }
314 
320  uint16_t id() const {
321  return Endian::be_to_host(header_.id);
322  }
323 
334  TINS_DEPRECATED(uint16_t frag_off() const) {
335  return Endian::be_to_host(header_.frag_off);
336  }
337 
347  return Endian::be_to_host(header_.frag_off) & 0x1fff;
348  }
349 
355  Flags flags() const {
356  return static_cast<Flags>(Endian::be_to_host(header_.frag_off) >> 13);
357  }
358 
364  uint8_t ttl() const {
365  return header_.ttl;
366  }
367 
373  uint8_t protocol() const {
374  return header_.protocol;
375  }
376 
382  uint16_t checksum() const {
383  return Endian::be_to_host(header_.check);
384  }
385 
392  return address_type(header_.saddr);
393  }
394 
400  return address_type(header_.daddr);
401  }
402 
408  return header_.version;
409  }
410 
415  const options_type& options() const {
416  return options_;
417  }
418 
419  /* Setters */
420 
426  void tos(uint8_t new_tos);
427 
433  void id(uint16_t new_id);
434 
445  TINS_DEPRECATED(void frag_off(uint16_t new_frag_off));
446 
456  void fragment_offset(small_uint<13> new_frag_off);
457 
463  void flags(Flags new_flags);
464 
470  void ttl(uint8_t new_ttl);
471 
488  void protocol(uint8_t new_protocol);
489 
495  void src_addr(address_type ip);
496 
502  void dst_addr(address_type ip);
503 
509  void version(small_uint<4> ver);
510 
519  void add_option(const option& opt);
520 
521  #if TINS_IS_CXX11
529  void add_option(option &&opt) {
530  options_.push_back(std::move(opt));
531  }
532 
541  template<typename... Args>
542  void add_option(Args&&... args) {
543  options_.emplace_back(std::forward<Args>(args)...);
544  }
545  #endif
546 
556  bool remove_option(option_identifier id);
557 
567  const option* search_option(option_identifier id) const;
568 
569  // Option setters
570 
574  void eol();
575 
579  void noop();
580 
586  void security(const security_type& data);
587 
593  void lsrr(const lsrr_type& data) {
594  add_route_option(131, data);
595  }
596 
602  void ssrr(const ssrr_type& data) {
603  add_route_option(137, data);
604  }
605 
611  void record_route(const record_route_type& data) {
612  add_route_option(7, data);
613  }
614 
620  void stream_identifier(uint16_t stream_id);
621 
622  // Option getters
623 
632  security_type security() const;
633 
643  lsrr_type lsrr() const {
644  return search_route_option(131);
645  }
646 
656  ssrr_type ssrr() const {
657  return search_route_option(137);
658  }
659 
669  return search_route_option(7);
670  }
671 
680  uint16_t stream_identifier() const;
681 
682  /* Virtual methods */
683 
689  uint32_t header_size() const;
690 
694  void send(PacketSender& sender, const NetworkInterface &);
695 
703  bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
704 
711  PDU* recv_response(PacketSender& sender, const NetworkInterface &);
712 
718  bool is_fragmented() const;
719 
724  PDUType pdu_type() const {
725  return pdu_flag;
726  }
727 
731  IP* clone() const {
732  return new IP(*this);
733  }
734 private:
735  static const uint8_t DEFAULT_TTL;
736 
737  TINS_BEGIN_PACK
738  struct ip_header {
739  #if TINS_IS_LITTLE_ENDIAN
740  uint8_t ihl:4,
741  version:4;
742  #else
743  uint8_t version:4,
744  ihl:4;
745  #endif
746  uint8_t tos;
747  uint16_t tot_len;
748  uint16_t id;
749  uint16_t frag_off;
750  uint8_t ttl;
751  uint8_t protocol;
752  uint16_t check;
753  uint32_t saddr;
754  uint32_t daddr;
755  } TINS_END_PACK;
756 
757  void head_len(small_uint<4> new_head_len);
758  void tot_len(uint16_t new_tot_len);
759 
760  void prepare_for_serialize();
761  uint32_t calculate_options_size() const;
762  uint32_t pad_options_size(uint32_t size) const;
763  void init_ip_fields();
764  void write_serialization(uint8_t* buffer, uint32_t total_sz);
765  void write_option(const option& opt, Memory::OutputMemoryStream& stream);
766  void add_route_option(option_identifier id, const generic_route_option_type& data);
767  generic_route_option_type search_route_option(option_identifier id) const;
768  void checksum(uint16_t new_check);
769  options_type::const_iterator search_option_iterator(option_identifier id) const;
770  options_type::iterator search_option_iterator(option_identifier id);
771 
772  options_type options_;
773  ip_header header_;
774 };
775 
776 } // Tins
777 
778 #endif // TINS_IP_H
Class that represents an IP PDU.
Definition: ip.h:63
TINS_DEPRECATED(uint16_t frag_off() const)
Getter for the fragment offset field.
Definition: ip.h:334
small_uint< 4 > version() const
Getter for the version field.
Definition: ip.h:407
uint16_t tot_len() const
Getter for the total length field.
Definition: ip.h:311
OptionClass
Enum indicating the option's class.
Definition: ip.h:90
uint16_t checksum() const
Getter for the checksum field.
Definition: ip.h:382
uint8_t protocol() const
Getter for the protocol field.
Definition: ip.h:373
std::vector< option > options_type
Definition: ip.h:246
generic_route_option_type record_route_type
Definition: ip.h:241
Flags
Definition: ip.h:78
uint8_t tos() const
Getter for the type of service field.
Definition: ip.h:302
small_uint< 13 > fragment_offset() const
Getter for the fragment offset field.
Definition: ip.h:346
const options_type & options() const
Getter for the IP options.
Definition: ip.h:415
PDUType pdu_type() const
Getter for the PDU's type.
Definition: ip.h:724
ssrr_type ssrr() const
Searchs and returns a Strict Source and Record Route option.
Definition: ip.h:656
lsrr_type lsrr() const
Searchs and returns a Loose Source and Record Route option.
Definition: ip.h:643
IPv4Address address_type
Definition: ip.h:73
address_type src_addr() const
Getter for the source address field.
Definition: ip.h:391
generic_route_option_type lsrr_type
Definition: ip.h:231
PDUOption< option_identifier, IP > option
Definition: ip.h:193
void ssrr(const ssrr_type &data)
Adds a Strict Source and Record Route option.
Definition: ip.h:602
void add_option(Args &&... args)
Adds an IP option.
Definition: ip.h:542
address_type dst_addr() const
Getter for the destination address field.
Definition: ip.h:399
Flags flags() const
Getter for the flags field.
Definition: ip.h:355
TINS_DEPRECATED(void frag_off(uint16_t new_frag_off))
Setter for the fragment offset field.
void lsrr(const lsrr_type &data)
Adds a Loose Source and Record Route option.
Definition: ip.h:593
small_uint< 4 > head_len() const
Getter for the header length field.
Definition: ip.h:293
OptionNumber
Enum indicating the option's id number.
Definition: ip.h:100
uint8_t ttl() const
Getter for the time to live field.
Definition: ip.h:364
record_route_type record_route() const
Searchs and returns a Record Route option.
Definition: ip.h:668
void record_route(const record_route_type &data)
Adds a Record Route option.
Definition: ip.h:611
uint32_t advertised_size() const
The whole chain of PDU's advertised size, including this one.
Definition: ip.h:284
uint16_t id() const
Getter for the id field.
Definition: ip.h:320
IP * clone() const
Definition: ip.h:731
generic_route_option_type ssrr_type
Definition: ip.h:236
void add_option(option &&opt)
Adds an IP option.
Definition: ip.h:529
Abstraction of an IPv4 address.
Definition: ip_address.h:45
Abstraction of a network interface.
Definition: network_interface.h:47
Represents a PDU option field.
Definition: pdu_option.h:201
Base class for protocol data units.
Definition: pdu.h:107
PDUType
Enum which identifies each type of PDU.
Definition: pdu.h:127
Sends packets through a network interface.
Definition: packet_sender.h:118
The Tins namespace.
Definition: address_range.h:38
The type used to represent an option's type.
Definition: ip.h:126
option_identifier(uint8_t value) option_identifier(OptionNumber number
Constructs this option from a single uint8_t value.
option_identifier()
Default constructor.
Definition: ip.h:141
bool operator==(const option_identifier &rhs) const
Equality operator.
Definition: ip.h:185
Definition: ip.h:198
Type used to store a PDU header's data.
Definition: pdu.h:196