decoder/igmp: detect RGMP (RFC 3488)

RGMP is a dialect of IGMP that uses the same protocol structure,
but with some different values for the fields.

Detect this and log it differently.
pull/14921/head
Victor Julien 5 months ago
parent 18f699cb97
commit d652b7ef62

@ -5106,6 +5106,20 @@
},
"optional": true
},
"rgmp": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "integer",
"suricata": {
"keywords": [
"igmp.type"
]
}
}
}
},
"rpc": {
"type": "object",
"additionalProperties": false,

@ -34,6 +34,9 @@
* Divided by 4 bytes per address. */
#define IGMP_V3_MAX_N_SOURCES (65535 - 24 - 12) / 4
/* RGMP requires a specific dest address 224.0.0.25. */
#define RGMP_DEST_ADDRESS 0xe0000019
typedef struct IGMPv3MemberQueryHdr_ {
uint8_t type;
uint8_t max_resp_time;
@ -77,6 +80,22 @@ int DecodeIGMP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *
p->proto = IPPROTO_IGMP;
uint8_t version;
/* see if we're RGMP (RFC 3488):
* "All RGMP messages are sent with TTL 1, to destination address 224.0.0.25."
*/
bool rgmp = false;
if (PacketIsIPv4(p)) {
const IPV4Hdr *ip4h = PacketGetIPv4(p);
const uint8_t pttl = IPV4_GET_RAW_IPTTL(ip4h);
/* if packet is of the correct length (header size 8) to the correct address
* and has a ttl of 1, we consider it RGMP. */
if (len == 8 && RGMP_DEST_ADDRESS == SCNtohl(p->dst.address.address_un_data32[0]) &&
pttl == 1) {
SCLogDebug("RGMP (RFC 3488)");
rgmp = true;
}
}
/* For IGMPv3 Membership Query, we need to handle additional fields */
if (igmp->type == IGMP_TYPE_MEMBERSHIP_QUERY) {
if (len >= 12) {
@ -172,6 +191,7 @@ int DecodeIGMP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *
p->payload_len = (uint16_t)(len - sizeof(IGMPHdr));
}
p->l4.vars.igmp.version = version;
p->l4.vars.igmp.rgmp = rgmp;
return TM_ECODE_OK;
}

@ -32,6 +32,7 @@ typedef struct IGMPHdr_ {
typedef struct IGMPVars_ {
uint16_t hlen; /**< length of the header */
uint8_t version;
bool rgmp; /**< is this really a RFC 3488 RGMP packet */
} IGMPVars;
#endif /* SURICATA_DECODE_IGMP_H */

@ -926,10 +926,17 @@ SCJsonBuilder *CreateEveHeader(const Packet *p, enum SCOutputJsonLogDirection di
break;
case IPPROTO_IGMP:
if (PacketIsIGMP(p)) {
SCJbOpenObject(js, "igmp");
SCJbSetUint(js, "type", PacketGetIGMP(p)->type);
SCJbSetUint(js, "version", p->l4.vars.igmp.version);
SCJbClose(js);
SCLogDebug("rgmp %s", BOOL2STR(p->l4.vars.igmp.rgmp));
if (!p->l4.vars.igmp.rgmp) {
SCJbOpenObject(js, "igmp");
SCJbSetUint(js, "type", PacketGetIGMP(p)->type);
SCJbSetUint(js, "version", p->l4.vars.igmp.version);
SCJbClose(js);
} else {
SCJbOpenObject(js, "rgmp");
SCJbSetUint(js, "type", PacketGetIGMP(p)->type);
SCJbClose(js);
}
}
break;
}

Loading…
Cancel
Save