hep: update parser to handle chunks in any order #270

This commit is contained in:
Kaian 2019-05-04 19:18:55 +02:00
parent 7628a704be
commit 6487541f09
2 changed files with 136 additions and 72 deletions

View File

@ -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);

View File

@ -44,6 +44,29 @@
#include <pthread.h>
#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;