From 6487541f09a7971d8e5e2acea6bb3706348f44a6 Mon Sep 17 00:00:00 2001 From: Kaian Date: Sat, 4 May 2019 19:18:55 +0200 Subject: [PATCH] hep: update parser to handle chunks in any order #270 --- src/capture_eep.c | 185 ++++++++++++++++++++++++++++------------------ src/capture_eep.h | 23 ++++++ 2 files changed, 136 insertions(+), 72 deletions(-) diff --git a/src/capture_eep.c b/src/capture_eep.c index 60b6575..387e649 100644 --- a/src/capture_eep.c +++ b/src/capture_eep.c @@ -589,6 +589,16 @@ capture_eep_receive_v2() } + +/** + * @brief Received a HEP3 packet + * + * This function receives HEP protocol payload and converts it + * to a Packet information. This code has been updated based on + * Kamailio sipcapture module. + * + * @return packet pointer + */ packet_t * capture_eep_receive_v3() { @@ -601,11 +611,10 @@ capture_eep_receive_v3() hep_chunk_t payload_chunk; hep_chunk_t authkey_chunk; hep_chunk_t uuid_chunk; - uint8_t family, proto; char password[100]; - int password_len, uuid_len; + int password_len; unsigned char *payload = 0; - uint32_t len, pos; + uint32_t total_len, pos; char buffer[MAX_CAPTURE_LEN] ; //! Source and Destination Address address_t src, dst; @@ -621,93 +630,125 @@ capture_eep_receive_v3() if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, &eep_client, &eep_client_len) == -1) return NULL; + // Initialize structs + memset(&hg, 0, sizeof(hep_generic_t)); + memset(&password, 0, sizeof(password)); + memset(&src, 0, sizeof(address_t)); + memset(&dst, 0, sizeof(address_t)); + memset(&header, 0, sizeof(struct pcap_pkthdr)); + /* Copy initial bytes to EEP Generic header */ - memcpy(&hg, buffer, sizeof(struct hep_generic)); + memcpy(&hg.header, buffer, sizeof(struct hep_generic)); /* header check */ if (memcmp(hg.header.id, "\x48\x45\x50\x33", 4) != 0) return NULL; - /* IP proto */ - family = hg.ip_family.data; - /* Proto ID */ - proto = hg.ip_proto.data; + total_len = ntohs(hg.header.length); + pos = sizeof(hep_ctrl_t); - len = ntohs(hg.header.length) - sizeof(struct hep_generic); - pos = sizeof(struct hep_generic); + while (pos < total_len) { - /* IPv4 */ - if (family == AF_INET) { - /* SRC IP */ - memcpy(&src_ip4, (void*) buffer + pos, sizeof(struct hep_chunk_ip4)); - inet_ntop(AF_INET, &src_ip4.data, src.ip, sizeof(src.ip)); - pos += sizeof(struct hep_chunk_ip4); + hep_chunk_t *chunk = (struct hep_chunk*) (buffer + pos); + int chunk_vendor = ntohs(chunk->vendor_id); + int chunk_type = ntohs(chunk->type_id); + int chunk_len = ntohs(chunk->length); - /* DST IP */ - memcpy(&dst_ip4, (void*) buffer + pos, sizeof(struct hep_chunk_ip4)); - inet_ntop(AF_INET, &dst_ip4.data, dst.ip, sizeof(src.ip)); - pos += sizeof(struct hep_chunk_ip4); - } + /* Bad length, drop packet */ + if (chunk_len == 0) { + return NULL; + } + + /* Skip not general chunks */ + if (chunk_vendor != 0) { + pos += chunk_len; + continue; + } + + switch (chunk_type) { + case CAPTURE_EEP_CHUNK_INVALID: + return NULL; + case CAPTURE_EEP_CHUNK_FAMILY: + memcpy(&hg.ip_family, (void*) buffer + pos, sizeof(hep_chunk_uint8_t)); + break; + case CAPTURE_EEP_CHUNK_PROTO: + memcpy(&hg.ip_proto, (void*) buffer + pos, sizeof(hep_chunk_uint8_t)); + break; + case CAPTURE_EEP_CHUNK_SRC_IP4: + memcpy(&src_ip4, (void*) buffer + pos, sizeof(struct hep_chunk_ip4)); + inet_ntop(AF_INET, &src_ip4.data, src.ip, sizeof(src.ip)); + break; + case CAPTURE_EEP_CHUNK_DST_IP4: + memcpy(&dst_ip4, (void*) buffer + pos, sizeof(struct hep_chunk_ip4)); + inet_ntop(AF_INET, &dst_ip4.data, dst.ip, sizeof(src.ip)); + break; #ifdef USE_IPV6 - /* IPv6 */ - else if(family == AF_INET6) { - /* SRC IPv6 */ - memcpy(&src_ip6, (void*) buffer + pos, sizeof(struct hep_chunk_ip6)); - inet_ntop(AF_INET6, &src_ip6.data, src.ip, sizeof(src.ip)); - pos += sizeof(struct hep_chunk_ip6); - - /* DST IP */ - memcpy(&src_ip6, (void*) buffer + pos, sizeof(struct hep_chunk_ip6)); - inet_ntop(AF_INET6, &dst_ip6.data, dst.ip, sizeof(dst.ip)); - pos += sizeof(struct hep_chunk_ip6); - } + case CAPTURE_EEP_CHUNK_SRC_IP6: + memcpy(&src_ip6, (void*) buffer + pos, sizeof(struct hep_chunk_ip6)); + inet_ntop(AF_INET6, &src_ip6.data, src.ip, sizeof(src.ip)); + break; + case CAPTURE_EEP_CHUNK_DST_IP6: + memcpy(&dst_ip6, (void*) buffer + pos, sizeof(struct hep_chunk_ip6)); + inet_ntop(AF_INET6, &dst_ip6.data, dst.ip, sizeof(dst.ip)); + break; #endif + case CAPTURE_EEP_CHUNK_SRC_PORT: + memcpy(&hg.src_port, (void*) buffer + pos, sizeof(hep_chunk_uint16_t)); + src.port = ntohs(hg.src_port.data); + break; + case CAPTURE_EEP_CHUNK_DST_PORT: + memcpy(&hg.dst_port, (void*) buffer + pos, sizeof(hep_chunk_uint16_t)); + dst.port = ntohs(hg.dst_port.data); + break; + case CAPTURE_EEP_CHUNK_TS_SEC: + memcpy(&hg.time_sec, (void*) buffer + pos, sizeof(hep_chunk_uint32_t)); + header.ts.tv_sec = ntohl(hg.time_sec.data); + break; + case CAPTURE_EEP_CHUNK_TS_USEC: + memcpy(&hg.time_usec, (void*) buffer + pos, sizeof(hep_chunk_uint32_t)); + header.ts.tv_usec = ntohl(hg.time_usec.data); + break; + case CAPTURE_EEP_CHUNK_PROTO_TYPE: + memcpy(&hg.proto_t, (void*) buffer + pos, sizeof(hep_chunk_uint8_t)); + break; + case CAPTURE_EEP_CHUNK_CAPT_ID: + memcpy(&hg.capt_id, (void*) buffer + pos, sizeof(hep_chunk_uint32_t)); + break; + case CAPTURE_EEP_CHUNK_KEEP_TM: + break; + case CAPTURE_EEP_CHUNK_AUTH_KEY: + memcpy(&authkey_chunk, (void*) buffer + pos, sizeof(authkey_chunk)); + password_len = ntohs(authkey_chunk.length) - sizeof(authkey_chunk); + memcpy(password, (void*) buffer + pos + sizeof(hep_chunk_t), password_len); + break; + case CAPTURE_EEP_CHUNK_PAYLOAD: + memcpy(&payload_chunk, (void*) buffer + pos, sizeof(payload_chunk)); + header.caplen = header.len = chunk_len - sizeof(hep_chunk_t); + payload = sng_malloc(header.caplen); + memcpy(payload, (void*) buffer + pos + sizeof(hep_chunk_t), header.caplen); + break; + case CAPTURE_EEP_CHUNK_CORRELATION_ID: + break; + default: + break; + } - /* SRC PORT */ - src.port = ntohs(hg.src_port.data); - /* DST PORT */ - dst.port = ntohs(hg.dst_port.data); - /* TIMESTAMP*/ - header.ts.tv_sec = ntohl(hg.time_sec.data); - header.ts.tv_usec = ntohl(hg.time_usec.data); - /* Protocol TYPE */ - /* Capture ID */ + // Parse next chunk + pos += chunk_len; + } - /* auth key */ + // Validate password if (eep_cfg.capt_srv_password != NULL) { - memcpy(&authkey_chunk, (void*) buffer + pos, sizeof(authkey_chunk)); - pos += sizeof(authkey_chunk); - - password_len = ntohs(authkey_chunk.length) - sizeof(authkey_chunk); - memcpy(password, (void*) buffer + pos, password_len); - pos += password_len; - - // Validate the password - if (strncmp(password, eep_cfg.capt_srv_password, password_len) != 0) + // No password in packet + if (strlen(password) == 0) + return NULL; + // Check password matches configured + if (strncmp(password, eep_cfg.capt_srv_password, strlen(eep_cfg.capt_srv_password)) != 0) return NULL; } - if (setting_enabled(SETTING_EEP_LISTEN_UUID)) { - memcpy(&uuid_chunk, (void*) buffer + pos, sizeof(uuid_chunk)); - pos += sizeof(uuid_chunk); - - uuid_len = ntohs(uuid_chunk.length) - sizeof(uuid_chunk); - pos += uuid_len; - } - - /* Payload */ - memcpy(&payload_chunk, (void*) buffer + pos, sizeof(payload_chunk)); - pos += sizeof(payload_chunk); - - // Calculate payload size - header.caplen = header.len = ntohs(payload_chunk.length) - sizeof(payload_chunk); - - // Receive packet payload - payload = sng_malloc(header.caplen); - memcpy(payload, (void*) buffer + pos, header.caplen); - // Create a new packet - pkt = packet_create((family == AF_INET)?4:6, proto, src, dst, 0); + pkt = packet_create((hg.ip_family.data == AF_INET)?4:6, hg.ip_proto.data, src, dst, 0); packet_add_frame(pkt, &header, payload); packet_set_type(pkt, PACKET_SIP_UDP); packet_set_payload(pkt, payload, header.caplen); diff --git a/src/capture_eep.h b/src/capture_eep.h index a1f2091..c163533 100644 --- a/src/capture_eep.h +++ b/src/capture_eep.h @@ -44,6 +44,29 @@ #include #include "capture.h" +//! HEP chunk types +enum +{ + CAPTURE_EEP_CHUNK_INVALID = 0, + CAPTURE_EEP_CHUNK_FAMILY, + CAPTURE_EEP_CHUNK_PROTO, + CAPTURE_EEP_CHUNK_SRC_IP4, + CAPTURE_EEP_CHUNK_DST_IP4, + CAPTURE_EEP_CHUNK_SRC_IP6, + CAPTURE_EEP_CHUNK_DST_IP6, + CAPTURE_EEP_CHUNK_SRC_PORT, + CAPTURE_EEP_CHUNK_DST_PORT, + CAPTURE_EEP_CHUNK_TS_SEC, + CAPTURE_EEP_CHUNK_TS_USEC, + CAPTURE_EEP_CHUNK_PROTO_TYPE, + CAPTURE_EEP_CHUNK_CAPT_ID, + CAPTURE_EEP_CHUNK_KEEP_TM, + CAPTURE_EEP_CHUNK_AUTH_KEY, + CAPTURE_EEP_CHUNK_PAYLOAD, + CAPTURE_EEP_CHUNK_CORRELATION_ID +}; + + //! Shorter declaration of capture_eep_config structure typedef struct capture_eep_config capture_eep_config_t;