1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2002-2013 Sourcefire, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License Version 2 as published
7 // by the Free Software Foundation. You may not use, modify or distribute
8 // this program under any other version of the GNU General Public License.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 //--------------------------------------------------------------------------
19 // cd_icmp4.cc author Josh Rosenbaum <jrosenba@cisco.com>
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <daq.h>
26
27 #include "codecs/codec_module.h"
28 #include "framework/codec.h"
29 #include "log/text_log.h"
30 #include "main/snort_config.h"
31 #include "protocols/icmp4.h"
32
33 #include "checksum.h"
34
35 using namespace snort;
36
37 #define CD_ICMP4_NAME "icmp4"
38 #define CD_ICMP4_HELP "support for Internet control message protocol v4"
39
40 namespace
41 {
42 const PegInfo pegs[]
43 {
44 { CountType::SUM, "bad_checksum", "non-zero icmp checksums" },
45 { CountType::SUM, "checksum_bypassed", "checksum calculations bypassed" },
46 { CountType::END, nullptr, nullptr }
47 };
48
49 struct Stats
50 {
51 PegCount bad_ip4_cksum;
52 PegCount cksum_bypassed;
53 };
54
55 static THREAD_LOCAL Stats stats;
56
57 static const RuleMap icmp4_rules[] =
58 {
59 { DECODE_ICMP_DGRAM_LT_ICMPHDR, "ICMP header truncated" },
60 { DECODE_ICMP_DGRAM_LT_TIMESTAMPHDR, "ICMP timestamp header truncated" },
61 { DECODE_ICMP_DGRAM_LT_ADDRHDR, "ICMP address header truncated" },
62 { DECODE_ICMP_ORIG_IP_TRUNCATED, "ICMP original IP header truncated" },
63 { DECODE_ICMP_ORIG_IP_VER_MISMATCH, "ICMP version and original IP header versions differ" },
64 { DECODE_ICMP_ORIG_DGRAM_LT_ORIG_IP,
65 "ICMP original datagram length < original IP header length" },
66 { DECODE_ICMP_ORIG_PAYLOAD_LT_64, "ICMP original IP payload < 64 bits" },
67 { DECODE_ICMP_ORIG_PAYLOAD_GT_576, "ICMP original IP payload > 576 bytes" },
68 { DECODE_ICMP_ORIG_IP_WITH_FRAGOFFSET, "ICMP original IP fragmented and offset not 0" },
69 { DECODE_ICMP4_DST_MULTICAST, "ICMP4 packet to multicast dest address" },
70 { DECODE_ICMP4_DST_BROADCAST, "ICMP4 packet to broadcast dest address" },
71 { DECODE_ICMP4_TYPE_OTHER, "ICMP4 type other" },
72 { DECODE_ICMP_PING_NMAP, "ICMP ping Nmap" },
73 { DECODE_ICMP_ICMPENUM, "ICMP icmpenum v1.1.1" },
74 { DECODE_ICMP_REDIRECT_HOST, "ICMP redirect host" },
75 { DECODE_ICMP_REDIRECT_NET, "ICMP redirect net" },
76 { DECODE_ICMP_TRACEROUTE_IPOPTS, "ICMP traceroute ipopts" },
77 { DECODE_ICMP_SOURCE_QUENCH, "ICMP source quench" },
78 { DECODE_ICMP_BROADSCAN_SMURF_SCANNER, "broadscan smurf scanner" },
79 { DECODE_ICMP_DST_UNREACH_ADMIN_PROHIBITED,
80 "ICMP destination unreachable communication administratively prohibited" },
81 { DECODE_ICMP_DST_UNREACH_DST_HOST_PROHIBITED,
82 "ICMP destination unreachable communication with destination host is "
83 "administratively prohibited" },
84 { DECODE_ICMP_DST_UNREACH_DST_NET_PROHIBITED,
85 "ICMP destination unreachable communication with destination network is "
86 "administratively prohibited" },
87 { DECODE_ICMP_PATH_MTU_DOS, "ICMP path MTU denial of service attempt" },
88 { DECODE_ICMP_DOS_ATTEMPT, "Linux ICMP header DOS attempt" },
89 { DECODE_ICMP4_HDR_TRUNC, "truncated ICMP4 header" },
90 { 0, nullptr }
91 };
92
93 class Icmp4Module : public BaseCodecModule
94 {
95 public:
Icmp4Module()96 Icmp4Module() : BaseCodecModule(CD_ICMP4_NAME, CD_ICMP4_HELP) { }
97
get_rules() const98 const RuleMap* get_rules() const override
99 { return icmp4_rules; }
100
get_pegs() const101 const PegInfo* get_pegs() const override
102 { return pegs; }
103
get_counts() const104 PegCount* get_counts() const override
105 { return (PegCount*)&stats; }
106 };
107
108 class Icmp4Codec : public Codec
109 {
110 public:
Icmp4Codec()111 Icmp4Codec() : Codec(CD_ICMP4_NAME) { }
112
113 void get_protocol_ids(std::vector<ProtocolId>&) override;
114 bool decode(const RawData&, CodecData&, DecodeData&) override;
115 void update(const ip::IpApi&, const EncodeFlags, uint8_t* raw_pkt,
116 uint16_t lyr_len, uint32_t& updated_len) override;
117 void format(bool reverse, uint8_t* raw_pkt, DecodeData& snort) override;
118 void log(TextLog* const, const uint8_t* pkt, const uint16_t len) override;
119
120 private:
121 bool valid_checksum_from_daq(const RawData&);
122 void ICMP4AddrTests(const DecodeData& snort, const CodecData& codec);
123 void ICMP4MiscTests(const ICMPHdr* const, const CodecData&, const uint16_t);
124 };
125 } // namespace
126
get_protocol_ids(std::vector<ProtocolId> & v)127 void Icmp4Codec::get_protocol_ids(std::vector<ProtocolId>& v)
128 { v.emplace_back(ProtocolId::ICMPV4); }
129
valid_checksum_from_daq(const RawData & raw)130 inline bool Icmp4Codec::valid_checksum_from_daq(const RawData& raw)
131 {
132 const DAQ_PktDecodeData_t* pdd =
133 (const DAQ_PktDecodeData_t*) daq_msg_get_meta(raw.daq_msg, DAQ_PKT_META_DECODE_DATA);
134 if (!pdd || !pdd->flags.bits.l4_checksum || !pdd->flags.bits.icmp || !pdd->flags.bits.l4)
135 return false;
136 // Sanity check to make sure we're talking about the same thing if offset is available
137 if (pdd->l4_offset != DAQ_PKT_DECODE_OFFSET_INVALID)
138 {
139 const uint8_t* data = daq_msg_get_data(raw.daq_msg);
140 if (raw.data - data != pdd->l4_offset)
141 return false;
142 }
143 stats.cksum_bypassed++;
144 return true;
145 }
146
decode(const RawData & raw,CodecData & codec,DecodeData & snort)147 bool Icmp4Codec::decode(const RawData& raw, CodecData& codec,DecodeData& snort)
148 {
149 if (raw.len < icmp::ICMP_BASE_LEN)
150 {
151 codec_event(codec, DECODE_ICMP4_HDR_TRUNC);
152 return false;
153 }
154
155 /* set the header ptr first */
156 const ICMPHdr* const icmph = reinterpret_cast<const ICMPHdr*>(raw.data);
157 uint16_t len = 0;
158
159 if (snort::get_network_policy()->icmp_checksums() && !valid_checksum_from_daq(raw))
160 {
161 uint16_t csum = checksum::cksum_add((const uint16_t*)icmph, raw.len);
162
163 if (csum && !codec.is_cooked())
164 {
165 stats.bad_ip4_cksum++;
166 snort.decode_flags |= DECODE_ERR_CKSUM_ICMP;
167 return false;
168 }
169 }
170
171 switch (icmph->type)
172 {
173 // fall through ...
174 case icmp::IcmpType::SOURCE_QUENCH:
175 case icmp::IcmpType::DEST_UNREACH:
176 case icmp::IcmpType::REDIRECT:
177 case icmp::IcmpType::TIME_EXCEEDED:
178 case icmp::IcmpType::PARAMETERPROB:
179 case icmp::IcmpType::ECHOREPLY:
180 case icmp::IcmpType::ECHO_4:
181 case icmp::IcmpType::ROUTER_ADVERTISE:
182 case icmp::IcmpType::ROUTER_SOLICIT:
183 case icmp::IcmpType::INFO_REQUEST:
184 case icmp::IcmpType::INFO_REPLY:
185 if (raw.len < 8)
186 {
187 codec_event(codec, DECODE_ICMP_DGRAM_LT_ICMPHDR);
188 return false;
189 }
190 break;
191
192 case icmp::IcmpType::TIMESTAMP:
193 case icmp::IcmpType::TIMESTAMPREPLY:
194 if (raw.len < 20)
195 {
196 codec_event(codec, DECODE_ICMP_DGRAM_LT_TIMESTAMPHDR);
197 return false;
198 }
199 break;
200
201 case icmp::IcmpType::ADDRESS:
202 case icmp::IcmpType::ADDRESSREPLY:
203 if (raw.len < 12)
204 {
205 codec_event(codec, DECODE_ICMP_DGRAM_LT_ADDRHDR);
206 return false;
207 }
208 break;
209
210 default:
211 codec_event(codec, DECODE_ICMP4_TYPE_OTHER);
212 break;
213 }
214
215 len = icmp::ICMP_BASE_LEN;
216
217 switch (icmph->type)
218 {
219 case icmp::IcmpType::ECHO_4:
220 ICMP4AddrTests(snort, codec);
221 // fall through ...
222
223 case icmp::IcmpType::ECHOREPLY:
224 /* setup the pkt id and seq numbers */
225 /* add the size of the echo ext to the data
226 * ptr and subtract it from the data size */
227 len += sizeof(ICMPHdr::icmp_hun.idseq);
228 break;
229
230 case icmp::IcmpType::DEST_UNREACH:
231 if ((icmph->code == icmp::IcmpCode::FRAG_NEEDED)
232 && (ntohs(icmph->s_icmp_nextmtu) < 576))
233 {
234 codec_event(codec, DECODE_ICMP_PATH_MTU_DOS);
235 }
236
237 /* Fall through */
238
239 case icmp::IcmpType::SOURCE_QUENCH:
240 case icmp::IcmpType::REDIRECT:
241 case icmp::IcmpType::TIME_EXCEEDED:
242 case icmp::IcmpType::PARAMETERPROB:
243 /* account for extra 4 bytes in header */
244 len += 4;
245 codec.next_prot_id = ProtocolId::IP_EMBEDDED_IN_ICMP4;
246 break;
247
248 default:
249 break;
250 }
251
252 ICMP4MiscTests(icmph, codec, (uint16_t)raw.len - len);
253
254 snort.set_pkt_type(PktType::ICMP);
255 snort.icmph = icmph;
256 codec.proto_bits |= PROTO_BIT__ICMP;
257 codec.lyr_len = len;
258 return true;
259 }
260
ICMP4AddrTests(const DecodeData & snort,const CodecData & codec)261 void Icmp4Codec::ICMP4AddrTests(const DecodeData& snort, const CodecData& codec)
262 {
263 uint32_t dst = snort.ip_api.get_dst()->get_ip4_value();
264
265 // check all 32 bits; all set so byte order is irrelevant ...
266 if ( dst == ip::IP4_BROADCAST )
267 codec_event(codec, DECODE_ICMP4_DST_BROADCAST);
268
269 /* - don't use htonl for speed reasons -
270 * s_addr is always in network order */
271 #ifdef WORDS_BIGENDIAN
272 uint8_t msb_dst = (uint8_t)(dst >> 24);
273 #else
274 uint8_t msb_dst = (uint8_t)(dst & 0xff);
275 #endif
276
277 // check the 'msn' (most significant nibble) ...
278 msb_dst >>= 4;
279
280 if ( msb_dst == ip::IP4_MULTICAST )
281 codec_event(codec, DECODE_ICMP4_DST_MULTICAST);
282 }
283
ICMP4MiscTests(const ICMPHdr * const icmph,const CodecData & codec,const uint16_t dsize)284 void Icmp4Codec::ICMP4MiscTests(const ICMPHdr* const icmph,
285 const CodecData& codec,
286 const uint16_t dsize)
287 {
288 if ((dsize == 0) &&
289 (icmph->type == icmp::IcmpType::ECHO_4))
290 codec_event(codec, DECODE_ICMP_PING_NMAP);
291
292 if ((dsize == 0) &&
293 (icmph->s_icmp_seq == 666))
294 codec_event(codec, DECODE_ICMP_ICMPENUM);
295
296 if ((icmph->type == icmp::IcmpType::REDIRECT) &&
297 (icmph->code == icmp::IcmpCode::REDIR_HOST))
298 codec_event(codec, DECODE_ICMP_REDIRECT_HOST);
299
300 if ((icmph->type == icmp::IcmpType::REDIRECT) &&
301 (icmph->code == icmp::IcmpCode::REDIR_NET))
302 codec_event(codec, DECODE_ICMP_REDIRECT_NET);
303
304 if ((icmph->type == icmp::IcmpType::ECHOREPLY) &&
305 (codec.codec_flags & CODEC_IPOPT_RR_SEEN))
306 codec_event(codec, DECODE_ICMP_TRACEROUTE_IPOPTS);
307
308 if ((icmph->type == icmp::IcmpType::SOURCE_QUENCH) &&
309 (icmph->code == icmp::IcmpCode::SOURCE_QUENCH_CODE))
310 codec_event(codec, DECODE_ICMP_SOURCE_QUENCH);
311
312 if ((dsize == 4) &&
313 (icmph->type == icmp::IcmpType::ECHO_4) &&
314 (icmph->s_icmp_seq == 0) &&
315 (icmph->code == icmp::IcmpCode::ECHO_CODE))
316 codec_event(codec, DECODE_ICMP_BROADSCAN_SMURF_SCANNER);
317
318 if ((icmph->type == icmp::IcmpType::DEST_UNREACH) &&
319 (icmph->code == icmp::IcmpCode::PKT_FILTERED))
320 codec_event(codec, DECODE_ICMP_DST_UNREACH_ADMIN_PROHIBITED);
321
322 if ((icmph->type == icmp::IcmpType::DEST_UNREACH) &&
323 (icmph->code == icmp::IcmpCode::PKT_FILTERED_HOST))
324 codec_event(codec, DECODE_ICMP_DST_UNREACH_DST_HOST_PROHIBITED);
325
326 if ((icmph->type == icmp::IcmpType::DEST_UNREACH) &&
327 (icmph->code == icmp::IcmpCode::PKT_FILTERED_NET))
328 codec_event(codec, DECODE_ICMP_DST_UNREACH_DST_NET_PROHIBITED);
329 }
330
331 /******************************************************************
332 ************************* L O G G E R **************************
333 ******************************************************************/
334
log(TextLog * const log,const uint8_t * raw_pkt,const uint16_t)335 void Icmp4Codec::log(TextLog* const log, const uint8_t* raw_pkt,
336 const uint16_t)
337 {
338 const icmp::ICMPHdr* const icmph = reinterpret_cast<const ICMPHdr*>(raw_pkt);
339
340 /* 32 digits plus 7 colons and a null byte */
341 char buf[8*4 + 7 + 1];
342 TextLog_Print(log, "Type:%d Code:%d ", icmph->type, icmph->code);
343 TextLog_Puts(log, "\n\t");
344
345 switch (icmph->type)
346 {
347 case icmp::IcmpType::ECHOREPLY:
348 TextLog_Print(log, "ID:%d Seq:%d ", ntohs(icmph->s_icmp_id),
349 ntohs(icmph->s_icmp_seq));
350 TextLog_Puts(log, "ECHO REPLY");
351 break;
352
353 case icmp::IcmpType::DEST_UNREACH:
354 TextLog_Puts(log, "DESTINATION UNREACHABLE: ");
355 switch (icmph->code)
356 {
357 case icmp::IcmpCode::NET_UNREACH:
358 TextLog_Puts(log, "NET UNREACHABLE");
359 break;
360
361 case icmp::IcmpCode::HOST_UNREACH:
362 TextLog_Puts(log, "HOST UNREACHABLE");
363 break;
364
365 case icmp::IcmpCode::PROT_UNREACH:
366 TextLog_Puts(log, "PROTOCOL UNREACHABLE");
367 break;
368
369 case icmp::IcmpCode::PORT_UNREACH:
370 TextLog_Puts(log, "PORT UNREACHABLE");
371 break;
372
373 case icmp::IcmpCode::FRAG_NEEDED:
374 TextLog_Print(log, "FRAGMENTATION NEEDED, DF SET,"
375 " NEXT LINK MTU: %u",
376 ntohs(icmph->s_icmp_nextmtu));
377 break;
378
379 case icmp::IcmpCode::SR_FAILED:
380 TextLog_Puts(log, "SOURCE ROUTE FAILED");
381 break;
382
383 case icmp::IcmpCode::NET_UNKNOWN:
384 TextLog_Puts(log, "NET UNKNOWN");
385 break;
386
387 case icmp::IcmpCode::HOST_UNKNOWN:
388 TextLog_Puts(log, "HOST UNKNOWN");
389 break;
390
391 case icmp::IcmpCode::HOST_ISOLATED:
392 TextLog_Puts(log, "HOST ISOLATED");
393 break;
394
395 case icmp::IcmpCode::PKT_FILTERED_NET:
396 TextLog_Puts(log, "ADMINISTRATIVELY PROHIBITED NETWORK FILTERED");
397 break;
398
399 case icmp::IcmpCode::PKT_FILTERED_HOST:
400 TextLog_Puts(log, "ADMINISTRATIVELY PROHIBITED HOST FILTERED");
401 break;
402
403 case icmp::IcmpCode::NET_UNR_TOS:
404 TextLog_Puts(log, "NET UNREACHABLE FOR TOS");
405 break;
406
407 case icmp::IcmpCode::HOST_UNR_TOS:
408 TextLog_Puts(log, "HOST UNREACHABLE FOR TOS");
409 break;
410
411 case icmp::IcmpCode::PKT_FILTERED:
412 TextLog_Puts(log, "ADMINISTRATIVELY PROHIBITED, PACKET FILTERED");
413 break;
414
415 case icmp::IcmpCode::PREC_VIOLATION:
416 TextLog_Puts(log, "PREC VIOLATION");
417 break;
418
419 case icmp::IcmpCode::PREC_CUTOFF:
420 TextLog_Puts(log, "PREC CUTOFF");
421 break;
422
423 default:
424 TextLog_Puts(log, "UNKNOWN");
425 break;
426 }
427 break;
428
429 case icmp::IcmpType::SOURCE_QUENCH:
430 TextLog_Puts(log, "SOURCE QUENCH");
431 break;
432
433 case icmp::IcmpType::REDIRECT:
434 TextLog_Puts(log, "REDIRECT");
435 switch (icmph->code)
436 {
437 case icmp::IcmpCode::REDIR_NET:
438 TextLog_Puts(log, " NET");
439 break;
440
441 case icmp::IcmpCode::REDIR_HOST:
442 TextLog_Puts(log, " HOST");
443 break;
444
445 case icmp::IcmpCode::REDIR_TOS_NET:
446 TextLog_Puts(log, " TOS NET");
447 break;
448
449 case icmp::IcmpCode::REDIR_TOS_HOST:
450 TextLog_Puts(log, " TOS HOST");
451 break;
452
453 default:
454 break;
455 }
456
457 snort_inet_ntop(AF_INET, (const void*)(&icmph->s_icmp_gwaddr.s_addr),
458 buf, sizeof(buf));
459 TextLog_Print(log, " NEW GW: %s", buf);
460 break;
461
462 case icmp::IcmpType::ECHO_4:
463 TextLog_Print(log, "ID:%d Seq:%d ", ntohs(icmph->s_icmp_id),
464 ntohs(icmph->s_icmp_seq));
465 TextLog_Puts(log, "ECHO");
466 break;
467
468 case icmp::IcmpType::ROUTER_ADVERTISE:
469 TextLog_Print(log, "ROUTER ADVERTISEMENT: "
470 "Num addrs: %d Addr entry size: %d Lifetime: %u",
471 icmph->s_icmp_num_addrs, icmph->s_icmp_wpa,
472 ntohs(icmph->s_icmp_lifetime));
473 break;
474
475 case icmp::IcmpType::ROUTER_SOLICIT:
476 TextLog_Puts(log, "ROUTER SOLICITATION");
477 break;
478
479 case icmp::IcmpType::TIME_EXCEEDED:
480 TextLog_Puts(log, "TTL EXCEEDED");
481 switch (icmph->code)
482 {
483 case icmp::IcmpCode::TIMEOUT_TRANSIT:
484 TextLog_Puts(log, " IN TRANSIT");
485 break;
486
487 case icmp::IcmpCode::TIMEOUT_REASSY:
488 TextLog_Puts(log, " TIME EXCEEDED IN FRAG REASSEMBLY");
489 break;
490
491 default:
492 break;
493 }
494
495 break;
496
497 case icmp::IcmpType::PARAMETERPROB:
498 TextLog_Puts(log, "PARAMETER PROBLEM");
499 switch (icmph->code)
500 {
501 case icmp::IcmpCode::PARAM_BADIPHDR:
502 TextLog_Print(log, ": BAD IP HEADER BYTE %u",
503 icmph->s_icmp_pptr);
504 break;
505
506 case icmp::IcmpCode::PARAM_OPTMISSING:
507 TextLog_Puts(log, ": OPTION MISSING");
508 break;
509
510 case icmp::IcmpCode::PARAM_BAD_LENGTH:
511 TextLog_Puts(log, ": BAD LENGTH");
512 break;
513
514 default:
515 break;
516 }
517
518 break;
519
520 case icmp::IcmpType::TIMESTAMP:
521 TextLog_Print(log, "ID: %u Seq: %u TIMESTAMP REQUEST",
522 ntohs(icmph->s_icmp_id), ntohs(icmph->s_icmp_seq));
523 break;
524
525 case icmp::IcmpType::TIMESTAMPREPLY:
526 TextLog_Print(log, "ID: %u Seq: %u TIMESTAMP REPLY: "
527 "Orig: %u Rtime: %u Ttime: %u",
528 ntohs(icmph->s_icmp_id), ntohs(icmph->s_icmp_seq),
529 icmph->s_icmp_otime, icmph->s_icmp_rtime,
530 icmph->s_icmp_ttime);
531 break;
532
533 case icmp::IcmpType::INFO_REQUEST:
534 TextLog_Print(log, "ID: %u Seq: %u INFO REQUEST",
535 ntohs(icmph->s_icmp_id), ntohs(icmph->s_icmp_seq));
536 break;
537
538 case icmp::IcmpType::INFO_REPLY:
539 TextLog_Print(log, "ID: %u Seq: %u INFO REPLY",
540 ntohs(icmph->s_icmp_id), ntohs(icmph->s_icmp_seq));
541 break;
542
543 case icmp::IcmpType::ADDRESS:
544 TextLog_Print(log, "ID: %u Seq: %u ADDRESS REQUEST",
545 ntohs(icmph->s_icmp_id), ntohs(icmph->s_icmp_seq));
546 break;
547
548 case icmp::IcmpType::ADDRESSREPLY:
549 TextLog_Print(log, "ID: %u Seq: %u ADDRESS REPLY: 0x%08X",
550 ntohs(icmph->s_icmp_id), ntohs(icmph->s_icmp_seq),
551 ntohl(icmph->s_icmp_mask));
552 break;
553
554 default:
555 TextLog_Puts(log, "UNKNOWN");
556 break;
557 }
558 }
559
560 /******************************************************************
561 ******************** E N C O D E R ******************************
562 ******************************************************************/
563
564 namespace
565 {
566 struct IcmpHdr
567 {
568 uint8_t type;
569 uint8_t code;
570 uint16_t cksum;
571 uint32_t unused;
572 };
573 } // namespace
574
update(const ip::IpApi &,const EncodeFlags flags,uint8_t * raw_pkt,uint16_t lyr_len,uint32_t & updated_len)575 void Icmp4Codec::update(const ip::IpApi&, const EncodeFlags flags,
576 uint8_t* raw_pkt, uint16_t lyr_len, uint32_t& updated_len)
577 {
578 IcmpHdr* h = reinterpret_cast<IcmpHdr*>(raw_pkt);
579 updated_len += lyr_len;
580
581 if ( !(flags & UPD_COOKED) || (flags & UPD_REBUILT_FRAG) )
582 {
583 h->cksum = 0;
584 h->cksum = checksum::icmp_cksum((uint16_t*)h, updated_len);
585 }
586 }
587
format(bool,uint8_t * raw_pkt,DecodeData & snort)588 void Icmp4Codec::format(bool /*reverse*/, uint8_t* raw_pkt, DecodeData& snort)
589 {
590 // FIXIT-L handle nested icmp4 layers
591 snort.icmph = reinterpret_cast<ICMPHdr*>(raw_pkt);
592 snort.set_pkt_type(PktType::ICMP);
593 }
594
595 //-------------------------------------------------------------------------
596 // api
597 //-------------------------------------------------------------------------
598
mod_ctor()599 static Module* mod_ctor()
600 { return new Icmp4Module; }
601
mod_dtor(Module * m)602 static void mod_dtor(Module* m)
603 { delete m; }
604
ctor(Module *)605 static Codec* ctor(Module*)
606 { return new Icmp4Codec(); }
607
dtor(Codec * cd)608 static void dtor(Codec* cd)
609 { delete cd; }
610
611 static const CodecApi icmp4_api =
612 {
613 {
614 PT_CODEC,
615 sizeof(CodecApi),
616 CDAPI_VERSION,
617 0,
618 API_RESERVED,
619 API_OPTIONS,
620 CD_ICMP4_NAME,
621 CD_ICMP4_HELP,
622 mod_ctor,
623 mod_dtor
624 },
625 nullptr, // pinit
626 nullptr, // pterm
627 nullptr, // tinit
628 nullptr, // tterm
629 ctor, // ctor
630 dtor, // dtor
631 };
632
633 #ifdef BUILDING_SO
634 SO_PUBLIC const BaseApi* snort_plugins[] =
635 #else
636 const BaseApi* cd_icmp4[] =
637 #endif
638 {
639 &icmp4_api.base,
640 nullptr
641 };
642
643