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 */
164 typedef struct ICMPV4Hdr_
165 {
166  uint8_t type;
167  uint8_t code;
168  uint16_t checksum;
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 emb_ip4h_offset;
185 
186  uint16_t id;
187  uint16_t seq;
188 
189  /** Actual header length **/
190  uint16_t hlen;
191 
192  uint8_t emb_ip4_proto;
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 */
202 typedef 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 */
211 typedef 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 
271 void DecodeICMPV4RegisterTests(void);
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  */
283 static 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 
328 int ICMPv4GetCounterpart(uint8_t type);
329 
330 #endif /* SURICATA_DECODE_ICMPV4_H */
decode-tcp.h
ICMPV4RtrAdvert_::naddr
uint8_t naddr
Definition: decode-icmpv4.h:204
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
ICMPV4ExtHdr_::seq
uint16_t seq
Definition: decode-icmpv4.h:178
DecodeICMPV4RegisterTests
void DecodeICMPV4RegisterTests(void)
Registers ICMPV4 unit test.
Definition: decode-icmpv4.c:793
ICMPV4Hdr
struct ICMPV4Hdr_ ICMPV4Hdr
ICMPV4RtrAdvert_::addr_sz
uint8_t addr_sz
Definition: decode-icmpv4.h:207
pad
uint16_t pad
Definition: source-erf-file.c:61
ICMPV4Vars_::emb_ip4h_offset
uint16_t emb_ip4h_offset
Definition: decode-icmpv4.h:184
ICMPv4GetCounterpart
int ICMPv4GetCounterpart(uint8_t type)
Definition: decode-icmpv4.c:345
__attribute__
struct ICMPV4RtrAdvert_ __attribute__((__packed__)) ICMPV4RtrAdvert
DNP3 link header.
Definition: decode-vlan.c:103
ICMPV4Vars_::hlen
uint16_t hlen
Definition: decode-icmpv4.h:190
ICMPV4Vars_::emb_ip4_proto
uint8_t emb_ip4_proto
Definition: decode-icmpv4.h:192
ICMPV4Vars_::emb_dport
uint16_t emb_dport
Definition: decode-icmpv4.h:197
ICMPV4ExtHdr_::code
uint8_t code
Definition: decode-icmpv4.h:175
ICMPV4Vars_::id
uint16_t id
Definition: decode-icmpv4.h:186
ICMPV4Vars_::emb_ports_set
bool emb_ports_set
Definition: decode-icmpv4.h:194
ICMPV4Timestamp_::rx_ts
uint32_t rx_ts
Definition: decode-icmpv4.h:213
ICMPV4Hdr_::type
uint8_t type
Definition: decode-icmpv4.h:166
type
uint16_t type
Definition: decode-vlan.c:107
ICMPV4Hdr_
Definition: decode-icmpv4.h:165
ICMPV4Timestamp_
Definition: decode-icmpv4.h:211
ICMPV4ExtHdr_::type
uint8_t type
Definition: decode-icmpv4.h:174
ICMPV4Hdr_::checksum
uint16_t checksum
Definition: decode-icmpv4.h:168
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:212
ICMPV4RtrAdvert_
Definition: decode-icmpv4.h:202
ICMPV4Timestamp_::tx_ts
uint32_t tx_ts
Definition: decode-icmpv4.h:214
ICMPV4Vars_::emb_sport
uint16_t emb_sport
Definition: decode-icmpv4.h:196
ICMPV4Vars_::seq
uint16_t seq
Definition: decode-icmpv4.h:187