blob: f3a94ad2e5942ee15a0ab6c0dc278e6e91ae3d1f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
|
/* Copyright (C) 2007-2022 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Victor Julien <victor@inliniac.net>
*/
#ifndef __DECODE_ICMPV4_H__
#define __DECODE_ICMPV4_H__
#include "decode-tcp.h"
#include "decode-udp.h"
#define ICMPV4_HEADER_LEN 8
#ifndef ICMP_ECHOREPLY
#define ICMP_ECHOREPLY 0 /* Echo Reply */
#endif
#ifndef ICMP_DEST_UNREACH
#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
#endif
#ifndef ICMP_SOURCE_QUENCH
#define ICMP_SOURCE_QUENCH 4 /* Source Quench */
#endif
#ifndef ICMP_REDIRECT
#define ICMP_REDIRECT 5 /* Redirect (change route) */
#endif
#ifndef ICMP_ECHO
#define ICMP_ECHO 8 /* Echo Request */
#endif
#ifndef ICMP_ROUTERADVERT
#define ICMP_ROUTERADVERT 9
#endif
#ifndef ICMP_ROUTERSOLICIT
#define ICMP_ROUTERSOLICIT 10
#endif
#ifndef ICMP_TIME_EXCEEDED
#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */
#endif
#ifndef ICMP_PARAMETERPROB
#define ICMP_PARAMETERPROB 12 /* Parameter Problem */
#endif
#ifndef ICMP_TIMESTAMP
#define ICMP_TIMESTAMP 13 /* Timestamp Request */
#endif
#ifndef ICMP_TIMESTAMPREPLY
#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */
#endif
#ifndef ICMP_INFO_REQUEST
#define ICMP_INFO_REQUEST 15 /* Information Request */
#endif
#ifndef ICMP_INFO_REPLY
#define ICMP_INFO_REPLY 16 /* Information Reply */
#endif
#ifndef ICMP_ADDRESS
#define ICMP_ADDRESS 17 /* Address Mask Request */
#endif
#ifndef ICMP_ADDRESSREPLY
#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */
#endif
#ifndef NR_ICMP_TYPES
#define NR_ICMP_TYPES 18
#endif
/* Codes for UNREACH. */
#ifndef ICMP_NET_UNREACH
#define ICMP_NET_UNREACH 0 /* Network Unreachable */
#endif
#ifndef ICMP_HOST_UNREACH
#define ICMP_HOST_UNREACH 1 /* Host Unreachable */
#endif
#ifndef ICMP_PROT_UNREACH
#define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
#endif
#ifndef ICMP_PORT_UNREACH
#define ICMP_PORT_UNREACH 3 /* Port Unreachable */
#endif
#ifndef ICMP_FRAG_NEEDED
#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
#endif
#ifndef ICMP_SR_FAILED
#define ICMP_SR_FAILED 5 /* Source Route failed */
#endif
#ifndef ICMP_NET_UNKNOWN
#define ICMP_NET_UNKNOWN 6
#endif
#ifndef ICMP_HOST_UNKNOWN
#define ICMP_HOST_UNKNOWN 7
#endif
#ifndef ICMP_HOST_ISOLATED
#define ICMP_HOST_ISOLATED 8
#endif
#ifndef ICMP_NET_ANO
#define ICMP_NET_ANO 9
#endif
#ifndef ICMP_HOST_ANO
#define ICMP_HOST_ANO 10
#endif
#ifndef ICMP_NET_UNR_TOS
#define ICMP_NET_UNR_TOS 11
#endif
#ifndef ICMP_HOST_UNR_TOS
#define ICMP_HOST_UNR_TOS 12
#endif
#ifndef ICMP_PKT_FILTERED
#define ICMP_PKT_FILTERED 13 /* Packet filtered */
#endif
#ifndef ICMP_PREC_VIOLATION
#define ICMP_PREC_VIOLATION 14 /* Precedence violation */
#endif
#ifndef ICMP_PREC_CUTOFF
#define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
#endif
#ifndef NR_ICMP_UNREACH
#define NR_ICMP_UNREACH 15 /* instead of hardcoding immediate value */
#endif
/* Codes for REDIRECT. */
#ifndef ICMP_REDIR_NET
#define ICMP_REDIR_NET 0 /* Redirect Net */
#endif
#ifndef ICMP_REDIR_HOST
#define ICMP_REDIR_HOST 1 /* Redirect Host */
#endif
#ifndef ICMP_REDIR_NETTOS
#define ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */
#endif
#ifndef ICMP_REDIR_HOSTTOS
#define ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */
#endif
/* Codes for TIME_EXCEEDED. */
#ifndef ICMP_EXC_TTL
#define ICMP_EXC_TTL 0 /* TTL count exceeded */
#endif
#ifndef ICMP_EXC_FRAGTIME
#define ICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */
#endif
/** marco for icmpv4 type access */
#define ICMPV4_GET_TYPE(p) (p)->icmpv4h->type
/** marco for icmpv4 code access */
#define ICMPV4_GET_CODE(p) (p)->icmpv4h->code
/* ICMPv4 header structure */
typedef struct ICMPV4Hdr_
{
uint8_t type;
uint8_t code;
uint16_t checksum;
} __attribute__((__packed__)) ICMPV4Hdr;
/* ICMPv4 header structure */
typedef struct ICMPV4ExtHdr_
{
uint8_t type;
uint8_t code;
uint16_t checksum;
uint16_t id;
uint16_t seq;
} ICMPV4ExtHdr;
/* ICMPv4 vars */
typedef struct ICMPV4Vars_
{
uint16_t id;
uint16_t seq;
/** Actual header length **/
uint16_t hlen;
/** Pointers to the embedded packet headers */
IPV4Hdr *emb_ipv4h;
TCPHdr *emb_tcph;
UDPHdr *emb_udph;
ICMPV4Hdr *emb_icmpv4h;
/** IPv4 src and dst address */
struct in_addr emb_ip4_src;
struct in_addr emb_ip4_dst;
uint8_t emb_ip4_hlen;
uint8_t emb_ip4_proto;
/** TCP/UDP ports */
uint16_t emb_sport;
uint16_t emb_dport;
} ICMPV4Vars;
/* ICMPV4 Router Advertisement - fixed components */
/* actual size determined by address count and size */
typedef struct ICMPV4RtrAdvert_ {
/** Number of advertised addresses **/
uint8_t naddr;
/** Size of each advertised address **/
uint8_t addr_sz;
} __attribute__((__packed__)) ICMPV4RtrAdvert;
/* ICMPV4 TImestamp messages */
typedef struct ICMPV4Timestamp_ {
uint32_t orig_ts;
uint32_t rx_ts;
uint32_t tx_ts;
} __attribute__((__packed__)) ICMPV4Timestamp;
#define CLEAR_ICMPV4_PACKET(p) do { \
(p)->level4_comp_csum = -1; \
PACKET_CLEAR_L4VARS((p)); \
(p)->icmpv4h = NULL; \
} while(0)
#define ICMPV4_HEADER_PKT_OFFSET 8
/** macro for icmpv4 "type" access */
#define ICMPV4_GET_TYPE(p) (p)->icmpv4h->type
/** macro for icmpv4 "code" access */
#define ICMPV4_GET_CODE(p) (p)->icmpv4h->code
/** macro for icmpv4 "csum" access */
#define ICMPV4_GET_RAW_CSUM(p) SCNtohs((p)->icmpv4h->checksum)
#define ICMPV4_GET_CSUM(p) (p)->icmpv4h->checksum
/* If message is informational */
/** macro for icmpv4 "id" access */
#define ICMPV4_GET_ID(p) ((p)->icmpv4vars.id)
/** macro for icmpv4 "seq" access */
#define ICMPV4_GET_SEQ(p) ((p)->icmpv4vars.seq)
/* If message is Error */
/** macro for icmpv4 embedded "protocol" access */
#define ICMPV4_GET_EMB_PROTO(p) (p)->icmpv4vars.emb_ip4_proto
/** macro for icmpv4 embedded "ipv4h" header access */
#define ICMPV4_GET_EMB_IPV4(p) (p)->icmpv4vars.emb_ipv4h
/** macro for icmpv4 embedded "tcph" header access */
#define ICMPV4_GET_EMB_TCP(p) (p)->icmpv4vars.emb_tcph
/** macro for icmpv4 embedded "udph" header access */
#define ICMPV4_GET_EMB_UDP(p) (p)->icmpv4vars.emb_udph
/** macro for icmpv4 embedded "icmpv4h" header access */
#define ICMPV4_GET_EMB_ICMPV4H(p) (p)->icmpv4vars.emb_icmpv4h
/** macro for icmpv4 header length */
#define ICMPV4_GET_HLEN_ICMPV4H(p) (p)->icmpv4vars.hlen
/** macro for checking if a ICMP DEST UNREACH packet is valid for use
* in other parts of the engine, such as the flow engine.
*
* \warning use only _after_ the decoder has processed the packet
*/
#define ICMPV4_DEST_UNREACH_IS_VALID(p) ( \
(!((p)->flags & PKT_IS_INVALID)) && \
((p)->icmpv4h != NULL) && \
(ICMPV4_GET_TYPE((p)) == ICMP_DEST_UNREACH) && \
(ICMPV4_GET_EMB_IPV4((p)) != NULL) && \
((ICMPV4_GET_EMB_TCP((p)) != NULL) || \
(ICMPV4_GET_EMB_UDP((p)) != NULL)))
/**
* marco for checking if a ICMP packet is an error message or an
* query message.
*
* \todo This check is used in the flow engine and needs to be as
* cheap as possible. Consider setting a bitflag at the decoder
* stage so we can to a bit check instead of the more expensive
* check below.
*/
#define ICMPV4_IS_ERROR_MSG(p) (ICMPV4_GET_TYPE((p)) == ICMP_DEST_UNREACH || \
ICMPV4_GET_TYPE((p)) == ICMP_SOURCE_QUENCH || \
ICMPV4_GET_TYPE((p)) == ICMP_REDIRECT || \
ICMPV4_GET_TYPE((p)) == ICMP_TIME_EXCEEDED || \
ICMPV4_GET_TYPE((p)) == ICMP_PARAMETERPROB)
void DecodeICMPV4RegisterTests(void);
/** ------ Inline functions ------ */
/**
* \brief Calculates the checksum for the ICMP packet
*
* \param pkt Pointer to the start of the ICMP packet
* \param hlen Total length of the ICMP packet(header + payload)
*
* \retval csum Checksum for the ICMP packet
*/
static inline uint16_t ICMPV4CalculateChecksum(const uint16_t *pkt, uint16_t tlen)
{
uint16_t pad = 0;
uint32_t csum = pkt[0];
tlen -= 4;
pkt += 2;
while (tlen >= 32) {
csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] +
pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] +
pkt[14] + pkt[15];
tlen -= 32;
pkt += 16;
}
while(tlen >= 8) {
csum += pkt[0] + pkt[1] + pkt[2] + pkt[3];
tlen -= 8;
pkt += 4;
}
while(tlen >= 4) {
csum += pkt[0] + pkt[1];
tlen -= 4;
pkt += 2;
}
while (tlen > 1) {
csum += pkt[0];
tlen -= 2;
pkt += 1;
}
if (tlen == 1) {
*(uint8_t *)(&pad) = (*(uint8_t *)pkt);
csum += pad;
}
csum = (csum >> 16) + (csum & 0x0000FFFF);
csum += (csum >> 16);
return (uint16_t) ~csum;
}
int ICMPv4GetCounterpart(uint8_t type);
#endif /* __DECODE_ICMPV4_H__ */
|