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