diff --git a/etc/schema.json b/etc/schema.json index a9d6afdd30..c3ec340679 100644 --- a/etc/schema.json +++ b/etc/schema.json @@ -5641,6 +5641,59 @@ } } }, + "sctp": { + "type": "object", + "description": "SCTP protocol information", + "additionalProperties": false, + "properties": { + "chunk_cnt": { + "type": "integer", + "description": "Number of SCTP chunks in the packet", + "suricata": { + "keywords": [ + "sctp.chunk_cnt" + ] + } + }, + "chunk_types": { + "type": "array", + "description": "Array of SCTP chunk type names present in the packet", + "items": { + "type": "string" + }, + "suricata": { + "keywords": [ + "sctp.chunk_type" + ] + } + }, + "has_abort": { + "type": "boolean", + "description": "Whether the packet contains an ABORT chunk" + }, + "has_data": { + "type": "boolean", + "description": "Whether the packet contains a DATA chunk" + }, + "has_init": { + "type": "boolean", + "description": "Whether the packet contains an INIT chunk" + }, + "has_init_ack": { + "type": "boolean", + "description": "Whether the packet contains an INIT_ACK chunk" + }, + "vtag": { + "type": "integer", + "description": "SCTP verification tag", + "suricata": { + "keywords": [ + "sctp.vtag" + ] + } + } + } + }, "sip": { "type": "object", "additionalProperties": false, diff --git a/src/output-json.c b/src/output-json.c index f1a4a29cec..b6c6436ec9 100644 --- a/src/output-json.c +++ b/src/output-json.c @@ -925,6 +925,32 @@ SCJsonBuilder *CreateEveHeader(const Packet *p, enum SCOutputJsonLogDirection di } } break; + case IPPROTO_SCTP: + if (PacketIsSCTP(p)) { + SCJbOpenObject(js, "sctp"); + SCJbSetUint(js, "vtag", SCTP_GET_RAW_VTAG(PacketGetSCTP(p))); + SCJbSetUint(js, "chunk_cnt", p->l4.vars.sctp.chunk_cnt); + const uint8_t cnt = p->l4.vars.sctp.tracked_chunk_cnt; + SCJbOpenArray(js, "chunk_types"); + for (uint8_t i = 0; i < cnt; i++) { + const char *name = SCSctpChunkTypeToString(p->l4.vars.sctp.chunk_types[i]); + if (name) { + SCJbAppendString(js, name); + } else { + char unknown[16]; + snprintf(unknown, sizeof(unknown), "unknown(%u)", + p->l4.vars.sctp.chunk_types[i]); + SCJbAppendString(js, unknown); + } + } + SCJbClose(js); + SCJbSetBool(js, "has_init", p->l4.vars.sctp.has_init); + SCJbSetBool(js, "has_init_ack", p->l4.vars.sctp.has_init_ack); + SCJbSetBool(js, "has_data", p->l4.vars.sctp.has_data); + SCJbSetBool(js, "has_abort", p->l4.vars.sctp.has_abort); + SCJbClose(js); + } + break; } SCJbSetString(js, "pkt_src", PktSrcToString(p->pkt_src));