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 __DECODE_ICMPV4_H__
25 #define __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 */
164 typedef struct ICMPV4Hdr_
165 {
166  uint8_t type;
167  uint8_t code;
168  uint16_t checksum;
169 } __attribute__((__packed__)) ICMPV4Hdr;
170 
171 /* ICMPv4 header structure */
172 typedef 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 */
182 typedef struct ICMPV4Vars_
183 {
184  uint16_t id;
185  uint16_t seq;
186 
187  /** Actual header length **/
188  uint16_t hlen;
189 
190  /** Pointers to the embedded packet headers */
192  TCPHdr *emb_tcph;
193  UDPHdr *emb_udph;
194  ICMPV4Hdr *emb_icmpv4h;
195 
196  /** IPv4 src and dst address */
197  struct in_addr emb_ip4_src;
198  struct in_addr emb_ip4_dst;
199  uint8_t emb_ip4_hlen;
200  uint8_t emb_ip4_proto;
201 
202  /** TCP/UDP ports */
203  uint16_t emb_sport;
204  uint16_t emb_dport;
206 
207 /* ICMPV4 Router Advertisement - fixed components */
208 /* actual size determined by address count and size */
209 typedef struct ICMPV4RtrAdvert_ {
210  /** Number of advertised addresses **/
211  uint8_t naddr;
212 
213  /** Size of each advertised address **/
214  uint8_t addr_sz;
215 } __attribute__((__packed__)) ICMPV4RtrAdvert;
216 
217 /* ICMPV4 TImestamp messages */
218 typedef struct ICMPV4Timestamp_ {
219  uint32_t orig_ts;
220  uint32_t rx_ts;
221  uint32_t tx_ts;
222 } __attribute__((__packed__)) ICMPV4Timestamp;
223 
224 #define CLEAR_ICMPV4_PACKET(p) do { \
225  (p)->level4_comp_csum = -1; \
226  PACKET_CLEAR_L4VARS((p)); \
227  (p)->icmpv4h = NULL; \
228 } while(0)
229 
230 #define ICMPV4_HEADER_PKT_OFFSET 8
231 
232 /** macro for icmpv4 "type" access */
233 #define ICMPV4_GET_TYPE(p) (p)->icmpv4h->type
234 /** macro for icmpv4 "code" access */
235 #define ICMPV4_GET_CODE(p) (p)->icmpv4h->code
236 /** macro for icmpv4 "csum" access */
237 #define ICMPV4_GET_RAW_CSUM(p) SCNtohs((p)->icmpv4h->checksum)
238 #define ICMPV4_GET_CSUM(p) (p)->icmpv4h->checksum
239 
240 /* If message is informational */
241 
242 /** macro for icmpv4 "id" access */
243 #define ICMPV4_GET_ID(p) ((p)->icmpv4vars.id)
244 /** macro for icmpv4 "seq" access */
245 #define ICMPV4_GET_SEQ(p) ((p)->icmpv4vars.seq)
246 
247 /* If message is Error */
248 
249 /** macro for icmpv4 embedded "protocol" access */
250 #define ICMPV4_GET_EMB_PROTO(p) (p)->icmpv4vars.emb_ip4_proto
251 /** macro for icmpv4 embedded "ipv4h" header access */
252 #define ICMPV4_GET_EMB_IPV4(p) (p)->icmpv4vars.emb_ipv4h
253 /** macro for icmpv4 embedded "tcph" header access */
254 #define ICMPV4_GET_EMB_TCP(p) (p)->icmpv4vars.emb_tcph
255 /** macro for icmpv4 embedded "udph" header access */
256 #define ICMPV4_GET_EMB_UDP(p) (p)->icmpv4vars.emb_udph
257 /** macro for icmpv4 embedded "icmpv4h" header access */
258 #define ICMPV4_GET_EMB_ICMPV4H(p) (p)->icmpv4vars.emb_icmpv4h
259 /** macro for icmpv4 header length */
260 #define ICMPV4_GET_HLEN_ICMPV4H(p) (p)->icmpv4vars.hlen
261 
262 /** macro for checking if a ICMP DEST UNREACH packet is valid for use
263  * in other parts of the engine, such as the flow engine.
264  *
265  * \warning use only _after_ the decoder has processed the packet
266  */
267 #define ICMPV4_DEST_UNREACH_IS_VALID(p) ( \
268  (!((p)->flags & PKT_IS_INVALID)) && \
269  ((p)->icmpv4h != NULL) && \
270  (ICMPV4_GET_TYPE((p)) == ICMP_DEST_UNREACH) && \
271  (ICMPV4_GET_EMB_IPV4((p)) != NULL) && \
272  ((ICMPV4_GET_EMB_TCP((p)) != NULL) || \
273  (ICMPV4_GET_EMB_UDP((p)) != NULL)))
274 
275 /**
276  * marco for checking if a ICMP packet is an error message or an
277  * query message.
278  *
279  * \todo This check is used in the flow engine and needs to be as
280  * cheap as possible. Consider setting a bitflag at the decoder
281  * stage so we can to a bit check instead of the more expensive
282  * check below.
283  */
284 #define ICMPV4_IS_ERROR_MSG(p) (ICMPV4_GET_TYPE((p)) == ICMP_DEST_UNREACH || \
285  ICMPV4_GET_TYPE((p)) == ICMP_SOURCE_QUENCH || \
286  ICMPV4_GET_TYPE((p)) == ICMP_REDIRECT || \
287  ICMPV4_GET_TYPE((p)) == ICMP_TIME_EXCEEDED || \
288  ICMPV4_GET_TYPE((p)) == ICMP_PARAMETERPROB)
289 
290 void DecodeICMPV4RegisterTests(void);
291 
292 /** ------ Inline functions ------ */
293 
294 /**
295  * \brief Calculates the checksum for the ICMP packet
296  *
297  * \param pkt Pointer to the start of the ICMP packet
298  * \param hlen Total length of the ICMP packet(header + payload)
299  *
300  * \retval csum Checksum for the ICMP packet
301  */
302 static inline uint16_t ICMPV4CalculateChecksum(const uint16_t *pkt, uint16_t tlen)
303 {
304  uint16_t pad = 0;
305  uint32_t csum = pkt[0];
306 
307  tlen -= 4;
308  pkt += 2;
309 
310  while (tlen >= 32) {
311  csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] +
312  pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] +
313  pkt[14] + pkt[15];
314  tlen -= 32;
315  pkt += 16;
316  }
317 
318  while(tlen >= 8) {
319  csum += pkt[0] + pkt[1] + pkt[2] + pkt[3];
320  tlen -= 8;
321  pkt += 4;
322  }
323 
324  while(tlen >= 4) {
325  csum += pkt[0] + pkt[1];
326  tlen -= 4;
327  pkt += 2;
328  }
329 
330  while (tlen > 1) {
331  csum += pkt[0];
332  tlen -= 2;
333  pkt += 1;
334  }
335 
336  if (tlen == 1) {
337  *(uint8_t *)(&pad) = (*(uint8_t *)pkt);
338  csum += pad;
339  }
340 
341  csum = (csum >> 16) + (csum & 0x0000FFFF);
342  csum += (csum >> 16);
343 
344  return (uint16_t) ~csum;
345 }
346 
347 int ICMPv4GetCounterpart(uint8_t type);
348 
349 #endif /* __DECODE_ICMPV4_H__ */
decode-tcp.h
ICMPV4RtrAdvert_::naddr
uint8_t naddr
Definition: decode-icmpv4.h:211
ICMPV4ExtHdr
struct ICMPV4ExtHdr_ ICMPV4ExtHdr
ICMPV4ExtHdr_
Definition: decode-icmpv4.h:173
ICMPV4Vars_
Definition: decode-icmpv4.h:183
ICMPV4ExtHdr_::checksum
uint16_t checksum
Definition: decode-icmpv4.h:176
decode-udp.h
ICMPV4Vars_::emb_tcph
TCPHdr * emb_tcph
Definition: decode-icmpv4.h:192
ICMPV4ExtHdr_::seq
uint16_t seq
Definition: decode-icmpv4.h:178
ICMPV4Vars_::emb_icmpv4h
ICMPV4Hdr * emb_icmpv4h
Definition: decode-icmpv4.h:194
DecodeICMPV4RegisterTests
void DecodeICMPV4RegisterTests(void)
Registers ICMPV4 unit test.
Definition: decode-icmpv4.c:827
ICMPV4RtrAdvert_::addr_sz
uint8_t addr_sz
Definition: decode-icmpv4.h:214
ICMPV4Vars_::emb_ipv4h
IPV4Hdr * emb_ipv4h
Definition: decode-icmpv4.h:191
pad
uint16_t pad
Definition: source-erf-file.c:61
ICMPv4GetCounterpart
int ICMPv4GetCounterpart(uint8_t type)
Definition: decode-icmpv4.c:360
__attribute__
struct ICMPV4Hdr_ __attribute__((__packed__)) ICMPV4Hdr
DNP3 link header.
Definition: decode-vlan.c:117
type
uint8_t type
Definition: decode-icmpv4.h:0
ICMPV4Vars_::hlen
uint16_t hlen
Definition: decode-icmpv4.h:188
ICMPV4Vars_::emb_ip4_proto
uint8_t emb_ip4_proto
Definition: decode-icmpv4.h:200
ICMPV4Vars_::emb_dport
uint16_t emb_dport
Definition: decode-icmpv4.h:204
ICMPV4Vars_::emb_ip4_hlen
uint8_t emb_ip4_hlen
Definition: decode-icmpv4.h:199
ICMPV4ExtHdr_::code
uint8_t code
Definition: decode-icmpv4.h:175
ICMPV4Vars_::id
uint16_t id
Definition: decode-icmpv4.h:184
ICMPV4Timestamp_::rx_ts
uint32_t rx_ts
Definition: decode-icmpv4.h:220
ICMPV4Hdr_::type
uint8_t type
Definition: decode-icmpv4.h:166
ICMPV4Hdr_
Definition: decode-icmpv4.h:165
ICMPV4Timestamp_
Definition: decode-icmpv4.h:218
ICMPV4Vars_::emb_udph
UDPHdr * emb_udph
Definition: decode-icmpv4.h:193
IPV4Hdr_
Definition: decode-ipv4.h:71
ICMPV4ExtHdr_::type
uint8_t type
Definition: decode-icmpv4.h:174
ICMPV4Hdr_::checksum
uint16_t checksum
Definition: decode-icmpv4.h:168
ICMPV4Vars_::emb_ip4_dst
struct in_addr emb_ip4_dst
Definition: decode-icmpv4.h:198
ICMPV4Vars
struct ICMPV4Vars_ ICMPV4Vars
ICMPV4ExtHdr_::id
uint16_t id
Definition: decode-icmpv4.h:177
ICMPV4Hdr_::code
uint8_t code
Definition: decode-icmpv4.h:167
ICMPV4Timestamp_::orig_ts
uint32_t orig_ts
Definition: decode-icmpv4.h:219
ICMPV4RtrAdvert_
Definition: decode-icmpv4.h:209
ICMPV4Vars_::emb_ip4_src
struct in_addr emb_ip4_src
Definition: decode-icmpv4.h:197
ICMPV4Timestamp_::tx_ts
uint32_t tx_ts
Definition: decode-icmpv4.h:221
ICMPV4Vars_::emb_sport
uint16_t emb_sport
Definition: decode-icmpv4.h:203
ICMPV4Vars_::seq
uint16_t seq
Definition: decode-icmpv4.h:185