Haka
ipv4.h
Go to the documentation of this file.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
10 #ifndef HAKA_PROTO_IPV4_IPV4_H
11 #define HAKA_PROTO_IPV4_IPV4_H
12 
13 #include <haka/packet.h>
14 #include <haka/types.h>
15 #include <haka/compiler.h>
16 #include <haka/error.h>
17 #include <haka/vbuffer_stream.h>
18 #include <haka/lua/object.h>
19 #include <haka/container/list2.h>
20 
21 #include "haka/ipv4-addr.h"
22 #include "haka/ipv4-network.h"
23 
25 #define SWAP_TO_IPV4(type, x) SWAP_TO_BE(type, x)
26 #define SWAP_FROM_IPV4(type, x) SWAP_FROM_BE(type, x)
27 #define IPV4_GET_BIT(type, v, i) GET_BIT(SWAP_FROM_BE(type, v), i)
28 #define IPV4_SET_BIT(type, v, i, x) SWAP_TO_BE(type, SET_BIT(SWAP_FROM_BE(type, v), i, x))
29 #define IPV4_GET_BITS(type, v, r) GET_BITS(SWAP_FROM_BE(type, v), r)
30 #define IPV4_SET_BITS(type, v, r, x) SWAP_TO_BE(type, SET_BITS(SWAP_FROM_BE(type, v), r, x))
31 
32 #define IPV4_CHECK(ip, ...) if (!(ip) || !(ip)->packet) { error("invalid ipv4 packet"); return __VA_ARGS__; }
33 
34 #define IPV4_FLAG_RB 15
35 #define IPV4_FLAG_DF 15-1
36 #define IPV4_FLAG_MF 15-2
37 #define IPV4_FLAG_BITS 16-3, 16
38 #define IPV4_FRAGMENTOFFSET_BITS 0, 16-3
39 #define IPV4_FRAGMENTOFFSET_OFFSET 3 /* Fragment offset is a multiple of 8 bytes */
40 #define IPV4_HDR_LEN_OFFSET 2 /* Header length is a multiple of 4 bytes */
41 
42 
43 struct ipv4_header {
44 #ifdef HAKA_LITTLEENDIAN
45  uint8 hdr_len:4;
46  uint8 version:4;
47 #else
48  uint8 version:4;
49  uint8 hdr_len:4;
50 #endif
51  uint8 tos;
52  uint16 len;
53  uint16 id;
54  uint16 fragment;
55  uint8 ttl;
56  uint8 proto;
57  uint16 checksum;
58  ipv4addr src;
59  ipv4addr dst;
60 };
66 struct ipv4 {
67  struct packet *packet;
68  struct lua_object lua_object;
69  struct list2_elem frag_list;
70  struct vbuffer_iterator select;
71  struct vbuffer *payload;
72  struct vbuffer packet_payload;
73  struct vbuffer_stream reassembled_payload;
74  size_t reassembled_offset;
75  bool invalid_checksum:1;
76  bool reassembled:1;
77 };
78 
80 struct ipv4 *ipv4_dissect(struct packet *packet);
81 struct ipv4 *ipv4_reassemble(struct ipv4 *ip);
82 struct ipv4 *ipv4_create(struct packet *packet);
83 struct packet *ipv4_forge(struct ipv4 *ip);
84 struct ipv4_header *ipv4_header(struct ipv4 *ip, bool write);
85 void ipv4_release(struct ipv4 *ip);
86 bool ipv4_verify_checksum(struct ipv4 *ip);
87 void ipv4_compute_checksum(struct ipv4 *ip);
88 size_t ipv4_get_payload_length(struct ipv4 *ip);
89 const char *ipv4_get_proto_dissector(struct ipv4 *ip);
90 void ipv4_register_proto_dissector(uint8 proto, const char *dissector);
91 void ipv4_action_drop(struct ipv4 *ip);
92 
93 struct checksum_partial {
94  bool odd;
95  uint8 leftover;
96  int32 csum;
97 };
98 
99 extern struct checksum_partial checksum_partial_init;
100 
101 int16 inet_checksum(const uint8 *ptr, size_t size);
102 int16 inet_checksum_vbuffer(struct vbuffer_sub *buf);
103 void inet_checksum_partial(struct checksum_partial *csum, const uint8 *ptr, size_t size);
104 void inet_checksum_vbuffer_partial(struct checksum_partial *csum, struct vbuffer_sub *buf);
105 int16 inet_checksum_reduce(struct checksum_partial *csum);
106 
107 
108 #define IPV4_GETSET_FIELD(type, field) \
109  INLINE type ipv4_get_##field(struct ipv4 *ip) { IPV4_CHECK(ip, 0); return SWAP_FROM_IPV4(type, ipv4_header(ip, false)->field); } \
110  INLINE void ipv4_set_##field(struct ipv4 *ip, type v) { IPV4_CHECK(ip); \
111  struct ipv4_header *header = ipv4_header(ip, true); if (header) { header->field = SWAP_TO_IPV4(type, v); } }
112 
113 IPV4_GETSET_FIELD(uint8, version);
114 IPV4_GETSET_FIELD(uint8, tos);
115 IPV4_GETSET_FIELD(uint16, len);
116 IPV4_GETSET_FIELD(uint16, id);
117 IPV4_GETSET_FIELD(uint8, ttl);
118 IPV4_GETSET_FIELD(uint8, proto);
119 IPV4_GETSET_FIELD(uint16, checksum);
120 IPV4_GETSET_FIELD(ipv4addr, src);
121 IPV4_GETSET_FIELD(ipv4addr, dst);
122 
123 INLINE uint8 ipv4_get_hdr_len(struct ipv4 *ip)
124 {
125  IPV4_CHECK(ip, 0);
126  return ipv4_header(ip, false)->hdr_len << IPV4_HDR_LEN_OFFSET;
127 }
128 
129 INLINE void ipv4_set_hdr_len(struct ipv4 *ip, uint8 v)
130 {
131  IPV4_CHECK(ip);
132  struct ipv4_header *header = ipv4_header(ip, true);
133  if (header)
134  ipv4_header(ip, true)->hdr_len = v >> IPV4_HDR_LEN_OFFSET;
135 }
136 
137 INLINE uint16 ipv4_get_frag_offset(struct ipv4 *ip)
138 {
139  struct ipv4_header *header;
140  IPV4_CHECK(ip, 0);
141  header = ipv4_header(ip, false);
142  return (IPV4_GET_BITS(uint16, header->fragment, IPV4_FRAGMENTOFFSET_BITS)) << IPV4_FRAGMENTOFFSET_OFFSET;
143 }
144 
145 INLINE void ipv4_set_frag_offset(struct ipv4 *ip, uint16 v)
146 {
147  IPV4_CHECK(ip);
148  struct ipv4_header *header = ipv4_header(ip, true);
149  if (header)
150  header->fragment = IPV4_SET_BITS(uint16, header->fragment, IPV4_FRAGMENTOFFSET_BITS, v >> IPV4_FRAGMENTOFFSET_OFFSET);
151 }
152 
153 INLINE uint16 ipv4_get_flags(struct ipv4 *ip)
154 {
155  struct ipv4_header *header;
156  IPV4_CHECK(ip, 0);
157  header = ipv4_header(ip, false);
158  return IPV4_GET_BITS(uint16, header->fragment, IPV4_FLAG_BITS);
159 }
160 
161 INLINE void ipv4_set_flags(struct ipv4 *ip, uint16 v)
162 {
163  IPV4_CHECK(ip);
164  struct ipv4_header *header = ipv4_header(ip, true);
165  if (header)
166  header->fragment = IPV4_SET_BITS(uint16, header->fragment, IPV4_FLAG_BITS, v);
167 }
168 
169 #define IPV4_GETSET_FLAG(name, flag) \
170  INLINE bool ipv4_get_flags_##name(struct ipv4 *ip) { \
171  struct ipv4_header *header; \
172  IPV4_CHECK(ip, 0); \
173  header = ipv4_header(ip, false); \
174  return IPV4_GET_BIT(uint16, header->fragment, flag); \
175  } \
176  INLINE void ipv4_set_flags_##name(struct ipv4 *ip, bool v) { \
177  IPV4_CHECK(ip); \
178  struct ipv4_header *header = ipv4_header(ip, true); \
179  if (header) { \
180  header->fragment = IPV4_SET_BIT(uint16, header->fragment, flag, v); \
181  } \
182  }
183 
184 IPV4_GETSET_FLAG(df, IPV4_FLAG_DF);
185 IPV4_GETSET_FLAG(mf, IPV4_FLAG_MF);
186 IPV4_GETSET_FLAG(rb, IPV4_FLAG_RB);
189 #endif /* HAKA_PROTO_IPV4_IPV4_H */
Definition: ipv4.h:66
Definition: vbuffer.h:64
Definition: vbuffer.h:77
uint32 ipv4addr
Definition: ipv4-addr.h:25
unsigned HAKA_16BIT_TYPE uint16
Definition: types.h:28
Definition: vbuffer_stream.h:23
Definition: packet.h:24
HAKA_16BIT_TYPE int16
Definition: types.h:23
HAKA_32BIT_TYPE int32
Definition: types.h:24
unsigned char uint8
Definition: types.h:27
Definition: vbuffer.h:91