Skip to content

Commit 5f695be

Browse files
authored
Merge pull request #147 from BonnyAD9/icmp-plugin
Introduce Icmp plugin
2 parents 4ef71db + d95fd4b commit 5f695be

File tree

10 files changed

+294
-115
lines changed

10 files changed

+294
-115
lines changed

.gitignore

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ m4/ltsugar.m4
4545
m4/ltversion.m4
4646
m4/lt~obsolete.m4
4747

48-
# Generated Makefile
49-
# (meta build system like autotools,
48+
# Generated Makefile
49+
# (meta build system like autotools,
5050
# can automatically generate from config.status script
5151
# (which is called by configure script))
5252
Makefile
@@ -94,7 +94,8 @@ libtool
9494
fields.c
9595
fields.h
9696
ipfixprobe-nemea.*
97-
./ipfixprobe
97+
ipfixprobe
98+
ipfixprobe_stats
9899
ipfixprobe-*.tar.gz
99100

100101
# Test Outputs

Makefile.am

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,16 @@ ipfixprobe_process_src=\
126126
process/md5.cpp \
127127
process/common.hpp \
128128
process/ssadetector.hpp \
129-
process/ssadetector.cpp
129+
process/ssadetector.cpp \
130+
process/icmp.hpp \
131+
process/icmp.cpp
130132

131133
if WITH_QUIC
132134
ipfixprobe_process_src+=\
133135
process/quic.hpp \
134136
process/quic.cpp \
135137
process/quic_parser.cpp \
136-
process/quic_parser.hpp
138+
process/quic_parser.hpp
137139

138140
endif
139141

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,14 @@ List of fields exported together with basic flow fields on interface by quic plu
597597
|:------------------:|:------:|:-------------------------------:|
598598
| QUIC_SNI | string | Decrypted server name |
599599

600+
### ICMP
601+
602+
List of fields exported together with basic flow fields on interface by icmp plugin.
603+
604+
| Output field | Type | Description |
605+
|:------------------:|:------:|:-------------------------------:|
606+
| L4_ICMP_TYPE_CODE | uint16 | ICMP type (MSB) and code (LSB) |
607+
600608
### SSADetector
601609

602610
List of fields exported together with basic flow fields on interface by ssadetector plugin.

include/ipfixprobe/ipfix-elements.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,9 @@ namespace ipxp {
487487
F(OSQUERY_KERNEL_VERSION) \
488488
F(OSQUERY_SYSTEM_HOSTNAME)
489489

490+
#define IPFIX_ICMP_TEMPLATE(F) \
491+
F(L4_ICMP_TYPE_CODE)
492+
490493
#ifdef WITH_FLEXPROBE
491494
#define IPFIX_FLEXPROBE_DATA_TEMPLATE(F) F(FX_FRAME_SIGNATURE) F(FX_INPUT_INTERFACE)
492495
#define IPFIX_FLEXPROBE_TCP_TEMPLATE(F) F(FX_TCP_TRACKING)
@@ -529,7 +532,8 @@ namespace ipxp {
529532
IPFIX_FLEXPROBE_DATA_TEMPLATE(F) \
530533
IPFIX_FLEXPROBE_TCP_TEMPLATE(F) \
531534
IPFIX_FLEXPROBE_ENCR_TEMPLATE(F) \
532-
IPFIX_SSADETECTOR_TEMPLATE(F)
535+
IPFIX_SSADETECTOR_TEMPLATE(F) \
536+
IPFIX_ICMP_TEMPLATE(F)
533537

534538
/**
535539
* Helper macro, convert FIELD into its name as a C literal.

input/parser.cpp

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -467,54 +467,6 @@ inline uint16_t parse_udp_hdr(const u_char *data_ptr, uint16_t data_len, Packet
467467
return 8;
468468
}
469469

470-
/**
471-
* \brief Parse specific fields from ICMP header.
472-
* \param [in] data_ptr Pointer to begin of header.
473-
* \param [in] data_len Length of packet data in `data_ptr`.
474-
* \param [out] pkt Pointer to Packet structure where parsed fields will be stored.
475-
* \return Size of header in bytes.
476-
*/
477-
inline uint16_t parse_icmp_hdr(const u_char *data_ptr, uint16_t data_len, Packet *pkt)
478-
{
479-
struct icmphdr *icmp = (struct icmphdr *) data_ptr;
480-
if (sizeof(struct icmphdr) > data_len) {
481-
throw "Parser detected malformed packet";
482-
}
483-
pkt->dst_port = icmp->type * 256 + icmp->code;
484-
485-
DEBUG_MSG("ICMP header:\n");
486-
DEBUG_MSG("\tType:\t\t%u\n", icmp->type);
487-
DEBUG_MSG("\tCode:\t\t%u\n", icmp->code);
488-
DEBUG_MSG("\tChecksum:\t%#06x\n",ntohs(icmp->checksum));
489-
DEBUG_MSG("\tRest:\t\t%#06x\n", ntohl(*(uint32_t *) &icmp->un));
490-
491-
return 0;
492-
}
493-
494-
/**
495-
* \brief Parse specific fields from ICMPv6 header.
496-
* \param [in] data_ptr Pointer to begin of header.
497-
* \param [in] data_len Length of packet data in `data_ptr`.
498-
* \param [out] pkt Pointer to Packet structure where parsed fields will be stored.
499-
* \return Size of header in bytes.
500-
*/
501-
inline uint16_t parse_icmpv6_hdr(const u_char *data_ptr, uint16_t data_len, Packet *pkt)
502-
{
503-
struct icmp6_hdr *icmp6 = (struct icmp6_hdr *) data_ptr;
504-
if (sizeof(struct icmp6_hdr) > data_len) {
505-
throw "Parser detected malformed packet";
506-
}
507-
pkt->dst_port = icmp6->icmp6_type * 256 + icmp6->icmp6_code;
508-
509-
DEBUG_MSG("ICMPv6 header:\n");
510-
DEBUG_MSG("\tType:\t\t%u\n", icmp6->icmp6_type);
511-
DEBUG_MSG("\tCode:\t\t%u\n", icmp6->icmp6_code);
512-
DEBUG_MSG("\tChecksum:\t%#x\n", ntohs(icmp6->icmp6_cksum));
513-
DEBUG_MSG("\tBody:\t\t%#x\n", ntohs(*(uint32_t *) &icmp6->icmp6_dataun));
514-
515-
return 0;
516-
}
517-
518470
/**
519471
* \brief Skip MPLS stack.
520472
* \param [in] data_ptr Pointer to begin of header.
@@ -689,10 +641,6 @@ void parse_packet(parser_opt_t *opt, struct timeval ts, const uint8_t *data, uin
689641
data_offset += parse_tcp_hdr(data + data_offset, caplen - data_offset, pkt);
690642
} else if (pkt->ip_proto == IPPROTO_UDP) {
691643
data_offset += parse_udp_hdr(data + data_offset, caplen - data_offset, pkt);
692-
} else if (pkt->ip_proto == IPPROTO_ICMP) {
693-
data_offset += parse_icmp_hdr(data + data_offset, caplen - data_offset, pkt);
694-
} else if (pkt->ip_proto == IPPROTO_ICMPV6) {
695-
data_offset += parse_icmpv6_hdr(data + data_offset, caplen - data_offset, pkt);
696644
}
697645
} catch (const char *err) {
698646
DEBUG_MSG("%s\n", err);

process/icmp.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* \file icmp.cpp
3+
* \brief Plugin for parsing icmp traffic.
4+
* \author Jakub Antonín Štigler xstigl00@[email protected]
5+
* \date 2023
6+
*/
7+
/*
8+
* Copyright (C) 2023 CESNET
9+
*
10+
* LICENSE TERMS
11+
*
12+
* Redistribution and use in source and binary forms, with or without
13+
* modification, are permitted provided that the following conditions
14+
* are met:
15+
* 1. Redistributions of source code must retain the above copyright
16+
* notice, this list of conditions and the following disclaimer.
17+
* 2. Redistributions in binary form must reproduce the above copyright
18+
* notice, this list of conditions and the following disclaimer in
19+
* the documentation and/or other materials provided with the
20+
* distribution.
21+
* 3. Neither the name of the Company nor the names of its contributors
22+
* may be used to endorse or promote products derived from this
23+
* software without specific prior written permission.
24+
*
25+
* ALTERNATIVELY, provided that this notice is retained in full, this
26+
* product may be distributed under the terms of the GNU General Public
27+
* License (GPL) version 2 or later, in which case the provisions
28+
* of the GPL apply INSTEAD OF those given above.
29+
*
30+
* This software is provided as is'', and any express or implied
31+
* warranties, including, but not limited to, the implied warranties of
32+
* merchantability and fitness for a particular purpose are disclaimed.
33+
* In no event shall the company or contributors be liable for any
34+
* direct, indirect, incidental, special, exemplary, or consequential
35+
* damages (including, but not limited to, procurement of substitute
36+
* goods or services; loss of use, data, or profits; or business
37+
* interruption) however caused and on any theory of liability, whether
38+
* in contract, strict liability, or tort (including negligence or
39+
* otherwise) arising in any way out of the use of this software, even
40+
* if advised of the possibility of such damage.
41+
*
42+
*/
43+
44+
#include <iostream>
45+
46+
#include "icmp.hpp"
47+
48+
#include "../input/headers.hpp"
49+
50+
namespace ipxp {
51+
52+
int RecordExtICMP::REGISTERED_ID = -1;
53+
54+
__attribute__((constructor)) static void register_this_plugin()
55+
{
56+
static PluginRecord rec = PluginRecord("icmp", [](){return new ICMPPlugin();});
57+
register_plugin(&rec);
58+
RecordExtICMP::REGISTERED_ID = register_extension();
59+
}
60+
61+
ProcessPlugin *ICMPPlugin::copy()
62+
{
63+
return new ICMPPlugin(*this);
64+
}
65+
66+
int ICMPPlugin::post_create(Flow &rec, const Packet &pkt)
67+
{
68+
if (pkt.ip_proto == IPPROTO_ICMP ||
69+
pkt.ip_proto == IPPROTO_ICMPV6) {
70+
if (pkt.payload_len < sizeof(RecordExtICMP::type_code))
71+
return 0;
72+
73+
auto ext = new RecordExtICMP();
74+
75+
// the type and code are the first two bytes, type on MSB and code on LSB
76+
// in the network byte order
77+
ext->type_code = *reinterpret_cast<const uint16_t *>(pkt.payload);
78+
79+
rec.add_extension(ext);
80+
}
81+
return 0;
82+
}
83+
84+
}
85+

process/icmp.hpp

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/**
2+
* \file icmp.hpp
3+
* \brief Plugin for parsing icmp traffic.
4+
* \author Jakub Antonín Štigler xstigl00@[email protected]
5+
* \date 2023
6+
*/
7+
/*
8+
* Copyright (C) 2023 CESNET
9+
*
10+
* LICENSE TERMS
11+
*
12+
* Redistribution and use in source and binary forms, with or without
13+
* modification, are permitted provided that the following conditions
14+
* are met:
15+
* 1. Redistributions of source code must retain the above copyright
16+
* notice, this list of conditions and the following disclaimer.
17+
* 2. Redistributions in binary form must reproduce the above copyright
18+
* notice, this list of conditions and the following disclaimer in
19+
* the documentation and/or other materials provided with the
20+
* distribution.
21+
* 3. Neither the name of the Company nor the names of its contributors
22+
* may be used to endorse or promote products derived from this
23+
* software without specific prior written permission.
24+
*
25+
* ALTERNATIVELY, provided that this notice is retained in full, this
26+
* product may be distributed under the terms of the GNU General Public
27+
* License (GPL) version 2 or later, in which case the provisions
28+
* of the GPL apply INSTEAD OF those given above.
29+
*
30+
* This software is provided as is'', and any express or implied
31+
* warranties, including, but not limited to, the implied warranties of
32+
* merchantability and fitness for a particular purpose are disclaimed.
33+
* In no event shall the company or contributors be liable for any
34+
* direct, indirect, incidental, special, exemplary, or consequential
35+
* damages (including, but not limited to, procurement of substitute
36+
* goods or services; loss of use, data, or profits; or business
37+
* interruption) however caused and on any theory of liability, whether
38+
* in contract, strict liability, or tort (including negligence or
39+
* otherwise) arising in any way out of the use of this software, even
40+
* if advised of the possibility of such damage.
41+
*
42+
*/
43+
44+
#ifndef IPXP_PROCESS_ICMP_HPP
45+
#define IPXP_PROCESS_ICMP_HPP
46+
47+
#include <cstring>
48+
49+
#ifdef WITH_NEMEA
50+
#include "fields.h"
51+
#endif
52+
53+
#include <sstream>
54+
55+
#include <ipfixprobe/utils.hpp>
56+
57+
#include <ipfixprobe/process.hpp>
58+
#include <ipfixprobe/flowifc.hpp>
59+
#include <ipfixprobe/packet.hpp>
60+
#include <ipfixprobe/ipfix-elements.hpp>
61+
62+
namespace ipxp {
63+
64+
#define ICMP_UNIREC_TEMPLATE "L4_ICMP_TYPE_CODE"
65+
66+
UR_FIELDS (
67+
uint16 L4_ICMP_TYPE_CODE
68+
)
69+
70+
/**
71+
* \brief Flow record extension header for storing parsed ICMP data.
72+
*/
73+
struct RecordExtICMP : public RecordExt {
74+
static int REGISTERED_ID;
75+
76+
uint16_t type_code;
77+
78+
RecordExtICMP() : RecordExt(REGISTERED_ID)
79+
{
80+
type_code = 0;
81+
}
82+
83+
#ifdef WITH_NEMEA
84+
virtual void fill_unirec(ur_template_t *tmplt, void *record)
85+
{
86+
ur_set(tmplt, record, F_L4_ICMP_TYPE_CODE, type_code);
87+
}
88+
89+
const char *get_unirec_tmplt() const
90+
{
91+
return ICMP_UNIREC_TEMPLATE;
92+
}
93+
#endif
94+
95+
virtual int fill_ipfix(uint8_t *buffer, int size)
96+
{
97+
const int LEN = 2;
98+
99+
if (size < LEN) {
100+
return -1;
101+
}
102+
103+
*reinterpret_cast<uint16_t *>(buffer) = ntohs(type_code);
104+
105+
return LEN;
106+
}
107+
108+
const char **get_ipfix_tmplt() const
109+
{
110+
static const char *ipfix_template[] = {
111+
IPFIX_ICMP_TEMPLATE(IPFIX_FIELD_NAMES)
112+
NULL
113+
};
114+
return ipfix_template;
115+
}
116+
117+
std::string get_text() const
118+
{
119+
// type is on the first byte, code is on the second byte
120+
auto *type_code = reinterpret_cast<const uint8_t *>(&this->type_code);
121+
122+
std::ostringstream out;
123+
out << "type=\"" << static_cast<int>(type_code[0]) << '"'
124+
<< ",code=\"" << static_cast<int>(type_code[1]) << '"';
125+
126+
return out.str();
127+
}
128+
};
129+
130+
/**
131+
* \brief Process plugin for parsing ICMP packets.
132+
*/
133+
class ICMPPlugin : public ProcessPlugin
134+
{
135+
public:
136+
OptionsParser *get_parser() const { return new OptionsParser("icmp", "Parse ICMP traffic"); }
137+
std::string get_name() const { return "icmp"; }
138+
RecordExt *get_ext() const { return new RecordExtICMP(); }
139+
ProcessPlugin *copy();
140+
141+
int post_create(Flow &rec, const Packet &pkt);
142+
};
143+
144+
}
145+
#endif /* IPXP_PROCESS_ICMP_HPP */
146+

0 commit comments

Comments
 (0)