forked from Mirrors/sngrep
Support for HEP-EEP packet encapsulation.
This changes allow sending and receiving packets using EEP protocol. EEP (formely HEP) is an encapsulation protocol developed for HOMER SIPCAPTURE project. Additional information can be found at hep repository: - https://github.com/sipcapture/HEP
This commit is contained in:
parent
3ac971b445
commit
ccf80781c7
@ -1,9 +1,10 @@
|
||||
bin_PROGRAMS=sngrep
|
||||
sngrep_SOURCES=capture.c capture_reasm.c capture_ws.c sip.c sip_call.c sip_msg.c sip_attr.c main.c option.c
|
||||
sngrep_SOURCES=capture.c capture_eep.c capture_reasm.c capture_ws.c
|
||||
if WITH_OPENSSL
|
||||
sngrep_SOURCES+=capture_tls.c
|
||||
endif
|
||||
sngrep_SOURCES+=sip.c sip_call.c sip_msg.c sip_attr.c main.c option.c
|
||||
sngrep_SOURCES+=group.c filter.c keybinding.c media.c setting.c rtp.c util.c vector.c
|
||||
sngrep_SOURCES+=ui_manager.c ui_call_list.c ui_call_flow.c ui_call_raw.c
|
||||
sngrep_SOURCES+=ui_filter.c ui_save.c ui_msg_diff.c ui_column_select.c ui_settings.c
|
||||
|
||||
if WITH_OPENSSL
|
||||
sngrep_SOURCES+=capture_tls.c
|
||||
endif
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "capture.h"
|
||||
#include "capture_ws.h"
|
||||
#include "capture_reasm.h"
|
||||
#include "capture_eep.h"
|
||||
#ifdef WITH_OPENSSL
|
||||
#include "capture_tls.h"
|
||||
#endif
|
||||
@ -56,6 +57,17 @@ capture_init(int limit, int rtp_capture)
|
||||
capture_cfg.sources = vector_create(1, 1);
|
||||
capture_cfg.tcp_reasm = vector_create(0, 10);
|
||||
capture_cfg.ip_reasm = vector_create(0, 10);
|
||||
|
||||
// Fixme
|
||||
if (setting_has_value(SETTING_CAPTURE_STORAGE, "none")) {
|
||||
capture_cfg.storage = CAPTURE_STORAGE_NONE;
|
||||
} else if (setting_has_value(SETTING_CAPTURE_STORAGE, "memory")) {
|
||||
capture_cfg.storage = CAPTURE_STORAGE_MEMORY;
|
||||
} else if (setting_has_value(SETTING_CAPTURE_STORAGE, "disk")) {
|
||||
capture_cfg.storage = CAPTURE_STORAGE_DISK;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@ -205,8 +217,6 @@ parse_packet(u_char *info, const struct pcap_pkthdr *header, const u_char *packe
|
||||
uint32_t size_capture = header->caplen;
|
||||
// Packet payload size
|
||||
uint32_t size_payload = size_capture - capinfo->link_hl;
|
||||
// Media structure for RTP packets
|
||||
rtp_stream_t *stream;
|
||||
// Captured packet info
|
||||
capture_packet_t *pkt;
|
||||
|
||||
@ -292,13 +302,30 @@ parse_packet(u_char *info, const struct pcap_pkthdr *header, const u_char *packe
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we can handle this packet
|
||||
if (capture_packet_parse(pkt) == 0) {
|
||||
// Send this packet through eep
|
||||
capture_eep_send(pkt);
|
||||
// Store this packets in output file
|
||||
dump_packet(capture_cfg.pd, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
// Not an interesting packet ...
|
||||
capture_packet_destroy(pkt);
|
||||
}
|
||||
|
||||
int
|
||||
capture_packet_parse(capture_packet_t *pkt)
|
||||
{
|
||||
// Media structure for RTP packets
|
||||
rtp_stream_t *stream;
|
||||
|
||||
// We're only interested in packets with payload
|
||||
if (capture_packet_get_payload_len(pkt)) {
|
||||
// Parse this header and payload
|
||||
if (sip_load_message(pkt, pkt->ip_src, pkt->sport, pkt->ip_dst, pkt->dport)) {
|
||||
// Store this packets in output file
|
||||
dump_packet(capture_cfg.pd, pkt);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if this packet belongs to a RTP stream
|
||||
@ -306,18 +333,15 @@ parse_packet(u_char *info, const struct pcap_pkthdr *header, const u_char *packe
|
||||
if ((stream = rtp_check_stream(pkt, pkt->ip_src, pkt->sport, pkt->ip_dst, pkt->dport))) {
|
||||
// We have an RTP packet!
|
||||
capture_packet_set_type(pkt, CAPTURE_PACKET_RTP);
|
||||
// Store this packets in output file
|
||||
dump_packet(capture_cfg.pd, pkt);
|
||||
// Store this pacekt if capture rtp is enabled
|
||||
if (capture_cfg.rtp_capture) {
|
||||
call_add_rtp_packet(stream_get_call(stream), pkt);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not an interesting packet ...
|
||||
capture_packet_destroy(pkt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
@ -479,11 +503,12 @@ capture_last_error(cap)
|
||||
}
|
||||
|
||||
capture_packet_t *
|
||||
capture_packet_create(uint8_t proto, const char *ip_src, const char *ip_dst, uint32_t id)
|
||||
capture_packet_create(uint8_t ip_ver, uint8_t proto, const char *ip_src, const char *ip_dst, uint32_t id)
|
||||
{
|
||||
// Create a new packet
|
||||
capture_packet_t *packet;
|
||||
packet = sng_malloc(sizeof(capture_packet_t));
|
||||
packet->ip_version = ip_ver;
|
||||
packet->proto = proto;
|
||||
packet->frames = vector_create(1, 1);
|
||||
packet->ip_id = id;
|
||||
@ -537,9 +562,12 @@ capture_packet_add_frame(capture_packet_t *pkt, const struct pcap_pkthdr *header
|
||||
// Add frame to this packet
|
||||
frame = sng_malloc(sizeof(capture_frame_t));
|
||||
frame->header = sng_malloc(sizeof(struct pcap_pkthdr));
|
||||
frame->data = sng_malloc(header->caplen);
|
||||
memcpy(frame->header, header, sizeof(struct pcap_pkthdr));
|
||||
memcpy(frame->data, packet, header->caplen);
|
||||
|
||||
if (capture_cfg.storage != 0) {
|
||||
frame->data = sng_malloc(header->caplen);
|
||||
memcpy(frame->data, packet, header->caplen);
|
||||
}
|
||||
vector_append(pkt->frames, frame);
|
||||
return frame;
|
||||
}
|
||||
|
@ -83,6 +83,12 @@ enum capture_status {
|
||||
CAPTURE_OFFLINE_LOADING,
|
||||
};
|
||||
|
||||
enum capture_storage {
|
||||
CAPTURE_STORAGE_NONE = 0,
|
||||
CAPTURE_STORAGE_MEMORY,
|
||||
CAPTURE_STORAGE_DISK
|
||||
};
|
||||
|
||||
//! Shorter declaration of capture_config structure
|
||||
typedef struct capture_config capture_config_t;
|
||||
//; Shorter declaration of capture_info structure
|
||||
@ -128,6 +134,8 @@ struct capture_config {
|
||||
int limit;
|
||||
//! Also capture RTP packets
|
||||
int rtp_capture;
|
||||
//! Where should we store captured packets
|
||||
int storage;
|
||||
//! Key file for TLS decrypt
|
||||
const char *keyfile;
|
||||
//! The compiled filter expression
|
||||
@ -180,6 +188,8 @@ struct capture_info
|
||||
*/
|
||||
struct capture_packet {
|
||||
// IP protocol
|
||||
uint8_t ip_version;
|
||||
// Transport protocol
|
||||
uint8_t proto;
|
||||
// Packet type as defined in capture_packet_type
|
||||
int type;
|
||||
@ -258,6 +268,17 @@ capture_offline(const char *infile, const char *outfile);
|
||||
void
|
||||
parse_packet(u_char *capinfo, const struct pcap_pkthdr *header, const u_char *packet);
|
||||
|
||||
/**
|
||||
* @brief Check if the given packet structure is SIP/RTP/..
|
||||
*
|
||||
* This function will call parse functions to determine if packet has relevant data
|
||||
*
|
||||
* @return 0 in case this packets has SIP/RTP data
|
||||
* @return 1 otherwise
|
||||
*/
|
||||
int
|
||||
capture_packet_parse(capture_packet_t *pkt);
|
||||
|
||||
/**
|
||||
* @brief Create a capture thread for online mode
|
||||
*
|
||||
@ -355,7 +376,7 @@ capture_last_error();
|
||||
* @brief Allocate memory to store new packet data
|
||||
*/
|
||||
capture_packet_t *
|
||||
capture_packet_create(uint8_t proto, const char *ip_src, const char *ip_dst, uint32_t id);
|
||||
capture_packet_create(uint8_t ip_ver, uint8_t proto, const char *ip_src, const char *ip_dst, uint32_t id);
|
||||
|
||||
/**
|
||||
* @brief Set Transport layer information
|
||||
|
519
src/capture_eep.c
Normal file
519
src/capture_eep.c
Normal file
@ -0,0 +1,519 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** sngrep - SIP Messages flow viewer
|
||||
**
|
||||
** Copyright (C) 2013,2014 Ivan Alonso (Kaian)
|
||||
** Copyright (C) 2013,2014 Irontec SL. All rights reserved.
|
||||
** Copyright (C) 2012 Homer Project (http://www.sipcapture.org)
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @file capture.c
|
||||
*
|
||||
* @author Ivan Alonso [aka Kaian] <kaian@irontec.com>
|
||||
* @author Alexandr Dubovikov <alexandr.dubovikov@gmail.com>
|
||||
*
|
||||
* @brief Functions to manage eep protocol
|
||||
*
|
||||
* This file contains declaration of structure and functions to send and
|
||||
* receive packet information through HEP-EEP (Extensible Encapsulation Protocol)
|
||||
*
|
||||
* Additional information about HEP-EEP protocol can be found in sipcature
|
||||
* repositories at https://github.com/sipcapture/HEP
|
||||
*
|
||||
* @note Most of this code has been taken from hep-c and sipgrep (originally
|
||||
* written by Alexandr Dubovikov). Modifications of sources to work with
|
||||
* sngrep packet structures has been made by Ivan Alonso (Kaian)
|
||||
*
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <pcap.h>
|
||||
#include "capture_eep.h"
|
||||
#include "util.h"
|
||||
#include "setting.h"
|
||||
|
||||
capture_eep_config_t eep_cfg = { 0 };
|
||||
|
||||
void *
|
||||
accept_eep_client(void *data);
|
||||
|
||||
int
|
||||
capture_eep_init()
|
||||
{
|
||||
struct addrinfo *ai, hints[1] = { { 0 } };
|
||||
struct sockaddr_in srvaddr;
|
||||
struct in_addr addr;
|
||||
|
||||
// Setting for EEP client
|
||||
if (setting_enabled(SETTING_EEP_SEND)) {
|
||||
// Fill configuration structure
|
||||
eep_cfg.capt_host = setting_get_value(SETTING_EEP_SEND_ADDR);
|
||||
eep_cfg.capt_port = setting_get_value(SETTING_EEP_SEND_PORT);
|
||||
eep_cfg.capt_password = setting_get_value(SETTING_EEP_SEND_PASS);
|
||||
eep_cfg.capt_id = 2002;
|
||||
|
||||
hints->ai_flags = AI_NUMERICSERV;
|
||||
hints->ai_family = AF_UNSPEC;
|
||||
hints->ai_socktype = SOCK_DGRAM;
|
||||
hints->ai_protocol = IPPROTO_UDP;
|
||||
|
||||
if (getaddrinfo(eep_cfg.capt_host, eep_cfg.capt_port, hints, &ai)) {
|
||||
fprintf(stderr, "capture: getaddrinfo() error\n");
|
||||
return 1;
|
||||
}
|
||||
eep_cfg.client_sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if (eep_cfg.client_sock < 0) {
|
||||
fprintf(stderr, "Sender socket creation failed: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (connect(eep_cfg.client_sock, ai->ai_addr, (socklen_t) (ai->ai_addrlen)) == -1) {
|
||||
if (errno != EINPROGRESS) {
|
||||
fprintf(stderr, "Sender socket creation failed: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (setting_enabled(SETTING_EEP_LISTEN)) {
|
||||
// Fill configuration structure
|
||||
eep_cfg.capt_srv_host = setting_get_value(SETTING_EEP_LISTEN_ADDR);
|
||||
eep_cfg.capt_srv_port = setting_get_value(SETTING_EEP_LISTEN_PORT);
|
||||
eep_cfg.capt_srv_password = setting_get_value(SETTING_EEP_LISTEN_PASS);
|
||||
|
||||
hints->ai_flags = AI_NUMERICSERV;
|
||||
hints->ai_family = AF_UNSPEC;
|
||||
hints->ai_socktype = SOCK_DGRAM;
|
||||
hints->ai_protocol = IPPROTO_UDP;
|
||||
|
||||
// Create a socket for a new TCP IPv4 connection
|
||||
eep_cfg.server_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (eep_cfg.client_sock < 0) {
|
||||
fprintf(stderr, "Error creating server socket: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get network address
|
||||
if (inet_aton(eep_cfg.capt_srv_host, &addr) == 0) {
|
||||
fprintf(stderr, "Error getting network address: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Bind that socket to the requested address and port
|
||||
memset(&srvaddr, 0, sizeof(srvaddr));
|
||||
srvaddr.sin_family = AF_INET;
|
||||
srvaddr.sin_addr = addr;
|
||||
srvaddr.sin_port = htons(atoi(eep_cfg.capt_srv_port));
|
||||
if (bind(eep_cfg.server_sock, (struct sockaddr *) &srvaddr, sizeof(srvaddr)) == -1) {
|
||||
fprintf(stderr, "Error binding address: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create a new thread for accepting client connections
|
||||
if (pthread_create(&eep_cfg.server_thread, NULL, accept_eep_client, NULL) != 0) {
|
||||
fprintf(stderr, "Error creating accept thread: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Settings for EEP server
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
accept_eep_client(void *data)
|
||||
{
|
||||
capture_packet_t *pkt;
|
||||
|
||||
// Begin accepting connections
|
||||
while (eep_cfg.server_sock > 0) {
|
||||
if ((pkt = capture_eep_receive())) {
|
||||
if (capture_packet_parse(pkt) != 0) {
|
||||
capture_packet_destroy(pkt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Leave the thread gracefully
|
||||
pthread_exit(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
capture_eep_deinit()
|
||||
{
|
||||
if (eep_cfg.client_sock)
|
||||
close(eep_cfg.client_sock);
|
||||
|
||||
if (eep_cfg.server_sock) {
|
||||
close(eep_cfg.server_sock);
|
||||
eep_cfg.server_sock = -1;
|
||||
//pthread_join(&eep_cfg.server_thread, &ret);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
capture_eep_send(capture_packet_t *pkt)
|
||||
{
|
||||
|
||||
struct hep_generic *hg = NULL;
|
||||
void* buffer;
|
||||
unsigned int buflen = 0, iplen = 0, tlen = 0;
|
||||
hep_chunk_ip4_t src_ip4, dst_ip4;
|
||||
#ifdef USE_IPV6
|
||||
hep_chunk_ip6_t src_ip6, dst_ip6;
|
||||
#endif
|
||||
hep_chunk_t payload_chunk;
|
||||
hep_chunk_t authkey_chunk;
|
||||
capture_frame_t *frame = vector_first(pkt->frames);
|
||||
unsigned char *data = capture_packet_get_payload(pkt);
|
||||
unsigned int len = capture_packet_get_payload_len(pkt);
|
||||
|
||||
// Check we have a connection established
|
||||
if (!eep_cfg.client_sock)
|
||||
return 1;
|
||||
|
||||
// Dont send RTP packets
|
||||
if (pkt->type == CAPTURE_PACKET_RTP)
|
||||
return 1;
|
||||
|
||||
hg = sng_malloc(sizeof(struct hep_generic));
|
||||
|
||||
/* header set */
|
||||
memcpy(hg->header.id, "\x48\x45\x50\x33", 4);
|
||||
|
||||
/* IP proto */
|
||||
hg->ip_family.chunk.vendor_id = htons(0x0000);
|
||||
hg->ip_family.chunk.type_id = htons(0x0001);
|
||||
hg->ip_family.data = pkt->ip_version == 4 ? AF_INET : AF_INET6;
|
||||
hg->ip_family.chunk.length = htons(sizeof(hg->ip_family));
|
||||
|
||||
/* Proto ID */
|
||||
hg->ip_proto.chunk.vendor_id = htons(0x0000);
|
||||
hg->ip_proto.chunk.type_id = htons(0x0002);
|
||||
hg->ip_proto.data = pkt->proto;
|
||||
hg->ip_proto.chunk.length = htons(sizeof(hg->ip_proto));
|
||||
|
||||
/* IPv4 */
|
||||
if (pkt->ip_version == 4) {
|
||||
/* SRC IP */
|
||||
src_ip4.chunk.vendor_id = htons(0x0000);
|
||||
src_ip4.chunk.type_id = htons(0x0003);
|
||||
inet_pton(AF_INET, pkt->ip_src, &src_ip4.data);
|
||||
src_ip4.chunk.length = htons(sizeof(src_ip4));
|
||||
|
||||
/* DST IP */
|
||||
dst_ip4.chunk.vendor_id = htons(0x0000);
|
||||
dst_ip4.chunk.type_id = htons(0x0004);
|
||||
inet_pton(AF_INET, pkt->ip_dst, &dst_ip4.data);
|
||||
dst_ip4.chunk.length = htons(sizeof(dst_ip4));
|
||||
|
||||
iplen = sizeof(dst_ip4) + sizeof(src_ip4);
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
/* IPv6 */
|
||||
else if(pkt->ip_version == 6) {
|
||||
/* SRC IPv6 */
|
||||
src_ip6.chunk.vendor_id = htons(0x0000);
|
||||
src_ip6.chunk.type_id = htons(0x0005);
|
||||
inet_pton(AF_INET6, pkt->ip_src, &src_ip6.data);
|
||||
src_ip6.chunk.length = htonl(sizeof(src_ip6));
|
||||
|
||||
/* DST IPv6 */
|
||||
dst_ip6.chunk.vendor_id = htons(0x0000);
|
||||
dst_ip6.chunk.type_id = htons(0x0006);
|
||||
inet_pton(AF_INET6, pkt->ip_dst, &dst_ip6.data);
|
||||
dst_ip6.chunk.length = htonl(sizeof(dst_ip6));
|
||||
|
||||
iplen = sizeof(dst_ip6) + sizeof(src_ip6);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* SRC PORT */
|
||||
hg->src_port.chunk.vendor_id = htons(0x0000);
|
||||
hg->src_port.chunk.type_id = htons(0x0007);
|
||||
hg->src_port.data = htons(pkt->sport);
|
||||
hg->src_port.chunk.length = htons(sizeof(hg->src_port));
|
||||
|
||||
/* DST PORT */
|
||||
hg->dst_port.chunk.vendor_id = htons(0x0000);
|
||||
hg->dst_port.chunk.type_id = htons(0x0008);
|
||||
hg->dst_port.data = htons(pkt->dport);
|
||||
hg->dst_port.chunk.length = htons(sizeof(hg->dst_port));
|
||||
|
||||
/* TIMESTAMP SEC */
|
||||
hg->time_sec.chunk.vendor_id = htons(0x0000);
|
||||
hg->time_sec.chunk.type_id = htons(0x0009);
|
||||
hg->time_sec.data = htonl(frame->header->ts.tv_sec);
|
||||
hg->time_sec.chunk.length = htons(sizeof(hg->time_sec));
|
||||
|
||||
/* TIMESTAMP USEC */
|
||||
hg->time_usec.chunk.vendor_id = htons(0x0000);
|
||||
hg->time_usec.chunk.type_id = htons(0x000a);
|
||||
hg->time_usec.data = htonl(frame->header->ts.tv_usec);
|
||||
hg->time_usec.chunk.length = htons(sizeof(hg->time_usec));
|
||||
|
||||
/* Protocol TYPE */
|
||||
hg->proto_t.chunk.vendor_id = htons(0x0000);
|
||||
hg->proto_t.chunk.type_id = htons(0x000b);
|
||||
hg->proto_t.data = 1;
|
||||
hg->proto_t.chunk.length = htons(sizeof(hg->proto_t));
|
||||
|
||||
/* Capture ID */
|
||||
hg->capt_id.chunk.vendor_id = htons(0x0000);
|
||||
hg->capt_id.chunk.type_id = htons(0x000c);
|
||||
hg->capt_id.data = htons(eep_cfg.capt_id);
|
||||
hg->capt_id.chunk.length = htons(sizeof(hg->capt_id));
|
||||
|
||||
/* Payload */
|
||||
payload_chunk.vendor_id = htons(0x0000);
|
||||
payload_chunk.type_id = htons(0x000f);
|
||||
payload_chunk.length = htons(sizeof(payload_chunk) + len);
|
||||
|
||||
tlen = sizeof(struct hep_generic) + len + iplen + sizeof(hep_chunk_t);
|
||||
|
||||
/* auth key */
|
||||
if (eep_cfg.capt_password != NULL) {
|
||||
|
||||
tlen += sizeof(hep_chunk_t);
|
||||
/* Auth key */
|
||||
authkey_chunk.vendor_id = htons(0x0000);
|
||||
authkey_chunk.type_id = htons(0x000e);
|
||||
authkey_chunk.length = htons(sizeof(authkey_chunk) + strlen(eep_cfg.capt_password));
|
||||
tlen += strlen(eep_cfg.capt_password);
|
||||
}
|
||||
|
||||
/* total */
|
||||
hg->header.length = htons(tlen);
|
||||
|
||||
if (!(buffer = sng_malloc(tlen))) {
|
||||
sng_free(hg);
|
||||
return 1;
|
||||
}
|
||||
memcpy((void*) buffer, hg, sizeof(struct hep_generic));
|
||||
buflen = sizeof(struct hep_generic);
|
||||
|
||||
/* IPv4 */
|
||||
if (pkt->ip_version == 4) {
|
||||
/* SRC IP */
|
||||
memcpy((void*) buffer + buflen, &src_ip4, sizeof(struct hep_chunk_ip4));
|
||||
buflen += sizeof(struct hep_chunk_ip4);
|
||||
|
||||
memcpy((void*) buffer + buflen, &dst_ip4, sizeof(struct hep_chunk_ip4));
|
||||
buflen += sizeof(struct hep_chunk_ip4);
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
/* IPv6 */
|
||||
else if(pkt->ip_version == 6) {
|
||||
/* SRC IPv6 */
|
||||
memcpy((void*) buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip6));
|
||||
buflen += sizeof(struct hep_chunk_ip6);
|
||||
|
||||
memcpy((void*) buffer+buflen, &dst_ip6, sizeof(struct hep_chunk_ip6));
|
||||
buflen += sizeof(struct hep_chunk_ip6);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* AUTH KEY CHUNK */
|
||||
if (eep_cfg.capt_password != NULL) {
|
||||
|
||||
memcpy((void*) buffer + buflen, &authkey_chunk, sizeof(struct hep_chunk));
|
||||
buflen += sizeof(struct hep_chunk);
|
||||
|
||||
/* Now copying payload self */
|
||||
memcpy((void*) buffer + buflen, eep_cfg.capt_password, strlen(eep_cfg.capt_password));
|
||||
buflen += strlen(eep_cfg.capt_password);
|
||||
}
|
||||
|
||||
/* PAYLOAD CHUNK */
|
||||
memcpy((void*) buffer + buflen, &payload_chunk, sizeof(struct hep_chunk));
|
||||
buflen += sizeof(struct hep_chunk);
|
||||
|
||||
/* Now copying payload self */
|
||||
memcpy((void*) buffer + buflen, data, len);
|
||||
buflen += len;
|
||||
|
||||
if (send(eep_cfg.client_sock, buffer, buflen, 0) == -1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* FREE */
|
||||
sng_free(buffer);
|
||||
sng_free(hg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
capture_packet_t *
|
||||
capture_eep_receive()
|
||||
{
|
||||
|
||||
struct hep_generic hg;
|
||||
hep_chunk_ip4_t src_ip4, dst_ip4;
|
||||
#ifdef USE_IPV6
|
||||
hep_chunk_ip6_t src_ip6, dst_ip6;
|
||||
#endif
|
||||
hep_chunk_t payload_chunk;
|
||||
hep_chunk_t authkey_chunk;
|
||||
uint8_t family, proto;
|
||||
char password[100];
|
||||
int password_len;
|
||||
unsigned char *payload = 0;
|
||||
unsigned int len, pos;
|
||||
char buffer[MAX_CAPTURE_LEN] ;
|
||||
//! Source and Destination Address
|
||||
char ip_src[ADDRESSLEN], ip_dst[ADDRESSLEN];
|
||||
//! EEP client data
|
||||
struct sockaddr eep_client;
|
||||
socklen_t eep_client_len;
|
||||
|
||||
//! Source and Destination Port
|
||||
u_short sport, dport;
|
||||
//! Packet header
|
||||
struct pcap_pkthdr header;
|
||||
//! New created packet pointer
|
||||
capture_packet_t *pkt;
|
||||
|
||||
/* Receive EEP generic header */
|
||||
if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, &eep_client, &eep_client_len) == -1)
|
||||
return NULL;
|
||||
|
||||
/* Copy initial bytes to EEP Generic header */
|
||||
memcpy(&hg, buffer, sizeof(struct hep_generic));
|
||||
|
||||
/* header set */
|
||||
if (!memcpy(hg.header.id, "\x48\x45\x50\x33", 4))
|
||||
return NULL;
|
||||
|
||||
/* IP proto */
|
||||
family = hg.ip_family.data;
|
||||
/* Proto ID */
|
||||
proto = hg.ip_proto.data;
|
||||
|
||||
len = ntohs(hg.header.length) - sizeof(struct hep_generic);
|
||||
pos = sizeof(struct hep_generic);
|
||||
|
||||
/* 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, ip_src, sizeof(ip_src));
|
||||
pos += sizeof(struct hep_chunk_ip4);
|
||||
|
||||
/* DST IP */
|
||||
memcpy(&dst_ip4, (void*) buffer + pos, sizeof(struct hep_chunk_ip4));
|
||||
inet_ntop(AF_INET, &dst_ip4.data, ip_dst, sizeof(ip_dst));
|
||||
pos += sizeof(struct hep_chunk_ip4);
|
||||
}
|
||||
#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, ip_src, sizeof(ip_src));
|
||||
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, ip_dst, sizeof(ip_dst));
|
||||
pos += sizeof(struct hep_chunk_ip6);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* SRC PORT */
|
||||
sport = ntohs(hg.src_port.data);
|
||||
/* DST PORT */
|
||||
dport = 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 */
|
||||
|
||||
/* auth key */
|
||||
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)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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 = capture_packet_create((family == AF_INET)?4:6, proto, ip_src, ip_dst, 0);
|
||||
capture_packet_add_frame(pkt, &header, payload);
|
||||
capture_packet_set_transport_data(pkt, sport, dport, CAPTURE_PACKET_SIP_UDP);
|
||||
capture_packet_set_payload(pkt, payload, header.caplen);
|
||||
|
||||
/* FREE */
|
||||
sng_free(payload);
|
||||
return pkt;
|
||||
}
|
||||
|
||||
int
|
||||
capture_eep_set_server_url(const char *url)
|
||||
{
|
||||
char urlstr[256];
|
||||
char address[256], port[256];
|
||||
|
||||
strncpy(urlstr, url, strlen(url));
|
||||
if (sscanf(urlstr, "%*[^:]:%[^:]:%s", address, port) == 2) {
|
||||
setting_set_value(SETTING_EEP_LISTEN, SETTING_ON);
|
||||
setting_set_value(SETTING_EEP_LISTEN_ADDR, address);
|
||||
setting_set_value(SETTING_EEP_LISTEN_PORT, port);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
capture_eep_set_client_url(const char *url)
|
||||
{
|
||||
char urlstr[256];
|
||||
char address[256], port[256];
|
||||
|
||||
strncpy(urlstr, url, strlen(url));
|
||||
if (sscanf(urlstr, "%*[^:]:%[^:]:%s", address, port) == 2) {
|
||||
setting_set_value(SETTING_EEP_SEND, SETTING_ON);
|
||||
setting_set_value(SETTING_EEP_SEND_ADDR, address);
|
||||
setting_set_value(SETTING_EEP_SEND_PORT, port);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
214
src/capture_eep.h
Normal file
214
src/capture_eep.h
Normal file
@ -0,0 +1,214 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** sngrep - SIP Messages flow viewer
|
||||
**
|
||||
** Copyright (C) 2013,2014 Ivan Alonso (Kaian)
|
||||
** Copyright (C) 2013,2014 Irontec SL. All rights reserved.
|
||||
** Copyright (C) 2012 Homer Project (http://www.sipcapture.org)
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @file capture.h
|
||||
*
|
||||
* @author Ivan Alonso [aka Kaian] <kaian@irontec.com>
|
||||
* @author Alexandr Dubovikov <alexandr.dubovikov@gmail.com>
|
||||
*
|
||||
* @brief Functions to manage eep protocol
|
||||
*
|
||||
* This file contains declaration of structure and functions to send and
|
||||
* receive packet information through HEP-EEP (Extensible Encapsulation Protocol)
|
||||
*
|
||||
* Additional information about HEP-EEP protocol can be found in sipcature
|
||||
* repositories at https://github.com/sipcapture/HEP
|
||||
*
|
||||
* @note Most of this code has been taken from hep-c and sipgrep (originally
|
||||
* written by Alexandr Dubovikov). Modifications of sources to work with
|
||||
* sngrep packet structures has been made by Ivan Alonso (Kaian)
|
||||
*
|
||||
*/
|
||||
#include <pthread.h>
|
||||
#include "capture.h"
|
||||
|
||||
typedef struct capture_eep_config capture_eep_config_t;
|
||||
typedef struct eep_info eep_info_t;
|
||||
|
||||
struct capture_eep_config
|
||||
{
|
||||
int client_sock;
|
||||
int server_sock;
|
||||
int capt_id;
|
||||
const char *capt_host;
|
||||
const char *capt_port;
|
||||
const char *capt_password;
|
||||
const char *capt_srv_host;
|
||||
const char *capt_srv_port;
|
||||
const char *capt_srv_password;
|
||||
pthread_t server_thread;
|
||||
};
|
||||
|
||||
|
||||
struct eep_info {
|
||||
uint8_t ip_family; /* IP family IPv6 IPv4 */
|
||||
uint8_t ip_proto; /* IP protocol ID : tcp/udp */
|
||||
uint8_t proto_type; /* SIP: 0x001, SDP: 0x03 */
|
||||
const char *ip_src;
|
||||
const char *ip_dst;
|
||||
uint16_t sport;
|
||||
uint16_t dport;
|
||||
uint32_t time_sec;
|
||||
uint32_t time_usec;
|
||||
} ;
|
||||
|
||||
/* HEPv3 types */
|
||||
struct hep_chunk
|
||||
{
|
||||
u_int16_t vendor_id;
|
||||
u_int16_t type_id;
|
||||
u_int16_t length;
|
||||
}__attribute__((packed));
|
||||
|
||||
typedef struct hep_chunk hep_chunk_t;
|
||||
|
||||
struct hep_chunk_uint8
|
||||
{
|
||||
hep_chunk_t chunk;
|
||||
u_int8_t data;
|
||||
}__attribute__((packed));
|
||||
|
||||
typedef struct hep_chunk_uint8 hep_chunk_uint8_t;
|
||||
|
||||
struct hep_chunk_uint16
|
||||
{
|
||||
hep_chunk_t chunk;
|
||||
u_int16_t data;
|
||||
}__attribute__((packed));
|
||||
|
||||
typedef struct hep_chunk_uint16 hep_chunk_uint16_t;
|
||||
|
||||
struct hep_chunk_uint32
|
||||
{
|
||||
hep_chunk_t chunk;
|
||||
u_int32_t data;
|
||||
}__attribute__((packed));
|
||||
|
||||
typedef struct hep_chunk_uint32 hep_chunk_uint32_t;
|
||||
|
||||
struct hep_chunk_str
|
||||
{
|
||||
hep_chunk_t chunk;
|
||||
char *data;
|
||||
}__attribute__((packed));
|
||||
|
||||
typedef struct hep_chunk_str hep_chunk_str_t;
|
||||
|
||||
struct hep_chunk_ip4
|
||||
{
|
||||
hep_chunk_t chunk;
|
||||
struct in_addr data;
|
||||
}__attribute__((packed));
|
||||
|
||||
typedef struct hep_chunk_ip4 hep_chunk_ip4_t;
|
||||
|
||||
struct hep_chunk_ip6
|
||||
{
|
||||
hep_chunk_t chunk;
|
||||
struct in6_addr data;
|
||||
}__attribute__((packed));
|
||||
|
||||
typedef struct hep_chunk_ip6 hep_chunk_ip6_t;
|
||||
|
||||
struct hep_ctrl
|
||||
{
|
||||
char id[4];
|
||||
u_int16_t length;
|
||||
}__attribute__((packed));
|
||||
|
||||
typedef struct hep_ctrl hep_ctrl_t;
|
||||
|
||||
struct hep_chunk_payload
|
||||
{
|
||||
hep_chunk_t chunk;
|
||||
char *data;
|
||||
}__attribute__((packed));
|
||||
|
||||
typedef struct hep_chunk_payload hep_chunk_payload_t;
|
||||
|
||||
/* Structure of HEP */
|
||||
|
||||
struct hep_generic
|
||||
{
|
||||
hep_ctrl_t header;
|
||||
hep_chunk_uint8_t ip_family;
|
||||
hep_chunk_uint8_t ip_proto;
|
||||
hep_chunk_uint16_t src_port;
|
||||
hep_chunk_uint16_t dst_port;
|
||||
hep_chunk_uint32_t time_sec;
|
||||
hep_chunk_uint32_t time_usec;
|
||||
hep_chunk_uint8_t proto_t;
|
||||
hep_chunk_uint32_t capt_id;
|
||||
}__attribute__((packed));
|
||||
|
||||
typedef struct hep_generic hep_generic_t;
|
||||
|
||||
struct hep_hdr
|
||||
{
|
||||
u_int8_t hp_v; /* version */
|
||||
u_int8_t hp_l; /* length */
|
||||
u_int8_t hp_f; /* family */
|
||||
u_int8_t hp_p; /* protocol */
|
||||
u_int16_t hp_sport; /* source port */
|
||||
u_int16_t hp_dport; /* destination port */
|
||||
};
|
||||
|
||||
struct hep_timehdr
|
||||
{
|
||||
u_int32_t tv_sec; /* seconds */
|
||||
u_int32_t tv_usec; /* useconds */
|
||||
u_int16_t captid; /* Capture ID node */
|
||||
};
|
||||
|
||||
struct hep_iphdr
|
||||
{
|
||||
struct in_addr hp_src;
|
||||
struct in_addr hp_dst; /* source and dest address */
|
||||
};
|
||||
|
||||
#ifdef USE_IPV6
|
||||
struct hep_ip6hdr
|
||||
{
|
||||
struct in6_addr hp6_src; /* source address */
|
||||
struct in6_addr hp6_dst; /* destination address */
|
||||
};
|
||||
#endif
|
||||
|
||||
int
|
||||
capture_eep_init();
|
||||
|
||||
void
|
||||
capture_eep_deinit();
|
||||
|
||||
int
|
||||
capture_eep_send(capture_packet_t *pkt);
|
||||
|
||||
capture_packet_t *
|
||||
capture_eep_receive();
|
||||
|
||||
int
|
||||
capture_eep_set_server_url(const char *url);
|
||||
|
||||
int
|
||||
capture_eep_set_client_url(const char *url);
|
||||
|
@ -131,7 +131,7 @@ capture_packet_reasm_ip(capture_info_t *capinfo, const struct pcap_pkthdr *heade
|
||||
// If no fragmentation
|
||||
if (ip_frag == 0) {
|
||||
// Just create a new packet with given network data
|
||||
pkt = capture_packet_create(ip_proto, ip_src, ip_dst, ip_id);
|
||||
pkt = capture_packet_create(ip_ver, ip_proto, ip_src, ip_dst, ip_id);
|
||||
capture_packet_add_frame(pkt, header, packet);
|
||||
return pkt;
|
||||
}
|
||||
@ -148,7 +148,7 @@ capture_packet_reasm_ip(capture_info_t *capinfo, const struct pcap_pkthdr *heade
|
||||
capture_packet_add_frame(pkt, header, packet);
|
||||
} else {
|
||||
// Add To the possible reassembly list
|
||||
pkt = capture_packet_create(ip_proto, ip_src, ip_dst, ip_id);
|
||||
pkt = capture_packet_create(ip_ver, ip_proto, ip_src, ip_dst, ip_id);
|
||||
capture_packet_add_frame(pkt, header, packet);
|
||||
vector_append(capture_cfg.ip_reasm, pkt);
|
||||
return NULL;
|
||||
|
17
src/main.c
17
src/main.c
@ -36,6 +36,7 @@
|
||||
#include "vector.h"
|
||||
#include "ui_manager.h"
|
||||
#include "capture.h"
|
||||
#include "capture_eep.h"
|
||||
#ifdef WITH_OPENSSL
|
||||
#include "capture_tls.h"
|
||||
#endif
|
||||
@ -64,6 +65,8 @@ usage()
|
||||
" -i --icase\t\t Make <match expression> case insensitive\n"
|
||||
" -v --invert\t\t Invert <match expression>\n"
|
||||
" -N --no-interface\t Don't display sngrep interface, just capture\n"
|
||||
" -H --eep-send\t Homer sipcapture url (udp:X.X.X.X:XXXX)\n"
|
||||
" -L --eep-listen\t Listen for encapsulated packets (udp:X.X.X.X:XXXX)\n"
|
||||
" -q --quiet\t\t Don't print captured dialogs in no interface mode\n"
|
||||
#ifdef WITH_OPENSSL
|
||||
" -k --keyfile\t RSA private keyfile to decrypt captured packets\n"
|
||||
@ -128,6 +131,8 @@ main(int argc, char* argv[])
|
||||
{ "invert", no_argument, 0, 'v' },
|
||||
{ "no-interface", no_argument, 0, 'N' },
|
||||
{ "dump-config", no_argument, 0, 'D' },
|
||||
{ "eep-listen", required_argument, 0, 'L' },
|
||||
{ "eep-send", required_argument, 0, 'H' },
|
||||
{ "quiet", no_argument, 0, 'q' },
|
||||
};
|
||||
|
||||
@ -145,7 +150,7 @@ main(int argc, char* argv[])
|
||||
|
||||
// Parse command line arguments
|
||||
opterr = 0;
|
||||
char *options = "hVd:I:O:pqtW:k:crl:ivNqD";
|
||||
char *options = "hVd:I:O:pqtW:k:crl:ivNqDL:H:";
|
||||
while ((opt = getopt_long(argc, argv, options, long_options, &idx)) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
@ -188,6 +193,7 @@ main(int argc, char* argv[])
|
||||
break;
|
||||
case 'N':
|
||||
no_interface = 1;
|
||||
setting_set_value(SETTING_CAPTURE_STORAGE, "none");
|
||||
break;
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
@ -200,6 +206,12 @@ main(int argc, char* argv[])
|
||||
case 't':
|
||||
case 'W':
|
||||
break;
|
||||
case 'L':
|
||||
capture_eep_set_server_url(optarg);
|
||||
break;
|
||||
case 'H':
|
||||
capture_eep_set_client_url(optarg);
|
||||
break;
|
||||
case '?':
|
||||
if (strchr(options, optopt)) {
|
||||
fprintf(stderr, "-%c option requires an argument.\n", optopt);
|
||||
@ -237,6 +249,9 @@ main(int argc, char* argv[])
|
||||
// Set capture options
|
||||
capture_init(limit, rtp_capture);
|
||||
|
||||
// Initialize EEP if enabled
|
||||
capture_eep_init();
|
||||
|
||||
// If we have an input file, load it
|
||||
if (vector_count(infiles)) {
|
||||
for (i = 0; i < vector_count(infiles); i++) {
|
||||
|
@ -36,38 +36,47 @@
|
||||
|
||||
//! Available configurable settings
|
||||
setting_t settings[SETTING_COUNT] = {
|
||||
{ SETTING_BACKGROUND, "background", SETTING_FMT_ENUM, "dark", SETTING_ENUM_BACKGROUND },
|
||||
{ SETTING_COLORMODE, "colormode", SETTING_FMT_ENUM, "request", SETTING_ENUM_COLORMODE },
|
||||
{ SETTING_SYNTAX, "syntax", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_SYNTAX_TAG, "syntax.tag", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_SYNTAX_BRANCH, "syntax.branch", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_ALTKEY_HINT, "hintkeyalt", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_EXITPROMPT, "exitprompt", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CAPTURE_LIMIT, "capture.limit", SETTING_FMT_NUMBER, "20000", NULL },
|
||||
{ SETTING_CAPTURE_LOOKUP, "capture.lookup", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CAPTURE_DEVICE, "capture.device", SETTING_FMT_STRING, "any", NULL },
|
||||
{ SETTING_CAPTURE_OUTFILE, "capture.outfile", SETTING_FMT_STRING, "", NULL },
|
||||
{ SETTING_CAPTURE_KEYFILE, "capture.keyfile", SETTING_FMT_STRING, "", NULL },
|
||||
{ SETTING_CAPTURE_RTP, "capture.rtp", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_SIP_NOINCOMPLETE, "sip.noincomplete", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_SIP_CALLS, "sip.calls", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_SAVEPATH, "savepath", SETTING_FMT_STRING, "", NULL },
|
||||
{ SETTING_DISPLAY_HOST, "displayhost", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_DISPLAY_ALIAS, "displayalias", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CL_FILTER, "cl.filter", SETTING_FMT_STRING, "", NULL },
|
||||
{ SETTING_CL_SCROLLSTEP, "cl.scrollstep", SETTING_FMT_NUMBER, "4", NULL },
|
||||
{ SETTING_CF_FORCERAW, "cf.forceraw", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CF_RAWMINWIDTH, "cf.rawminwidth", SETTING_FMT_NUMBER, "40", NULL },
|
||||
{ SETTING_CF_RAWFIXEDWIDTH, "cf.rawfixedwidth", SETTING_FMT_NUMBER, "", NULL },
|
||||
{ SETTING_CF_SPLITCALLID, "cf.splitcallid", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CF_HIGHTLIGHT, "cf.highlight", SETTING_FMT_ENUM, "bold", SETTING_ENUM_HIGHLIGHT },
|
||||
{ SETTING_CF_SCROLLSTEP, "cf.scrollstep", SETTING_FMT_NUMBER, "4", NULL },
|
||||
{ SETTING_CF_LOCALHIGHLIGHT, "cf.localhighlight", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CF_SDP_INFO, "cf.sdpinfo", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_SDP_INFO },
|
||||
{ SETTING_CF_MEDIA, "cf.media", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CF_DELTA, "cf.deltatime", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CR_SCROLLSTEP, "cr.scrollstep", SETTING_FMT_NUMBER, "10", NULL },
|
||||
{ SETTING_FILTER_METHODS, "filter.methods", SETTING_FMT_STRING, "", NULL },
|
||||
{ SETTING_BACKGROUND, "background", SETTING_FMT_ENUM, "dark", SETTING_ENUM_BACKGROUND },
|
||||
{ SETTING_COLORMODE, "colormode", SETTING_FMT_ENUM, "request", SETTING_ENUM_COLORMODE },
|
||||
{ SETTING_SYNTAX, "syntax", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_SYNTAX_TAG, "syntax.tag", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_SYNTAX_BRANCH, "syntax.branch", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_ALTKEY_HINT, "hintkeyalt", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_EXITPROMPT, "exitprompt", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CAPTURE_LIMIT, "capture.limit", SETTING_FMT_NUMBER, "20000", NULL },
|
||||
{ SETTING_CAPTURE_LOOKUP, "capture.lookup", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CAPTURE_DEVICE, "capture.device", SETTING_FMT_STRING, "any", NULL },
|
||||
{ SETTING_CAPTURE_OUTFILE, "capture.outfile", SETTING_FMT_STRING, "", NULL },
|
||||
{ SETTING_CAPTURE_KEYFILE, "capture.keyfile", SETTING_FMT_STRING, "", NULL },
|
||||
{ SETTING_CAPTURE_RTP, "capture.rtp", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CAPTURE_STORAGE, "capture.storage", SETTING_FMT_ENUM, "memory", SETTING_ENUM_STORAGE },
|
||||
{ SETTING_SIP_NOINCOMPLETE, "sip.noincomplete", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_SIP_CALLS, "sip.calls", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_SAVEPATH, "savepath", SETTING_FMT_STRING, "", NULL },
|
||||
{ SETTING_DISPLAY_HOST, "displayhost", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_DISPLAY_ALIAS, "displayalias", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CL_FILTER, "cl.filter", SETTING_FMT_STRING, "", NULL },
|
||||
{ SETTING_CL_SCROLLSTEP, "cl.scrollstep", SETTING_FMT_NUMBER, "4", NULL },
|
||||
{ SETTING_CF_FORCERAW, "cf.forceraw", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CF_RAWMINWIDTH, "cf.rawminwidth", SETTING_FMT_NUMBER, "40", NULL },
|
||||
{ SETTING_CF_RAWFIXEDWIDTH, "cf.rawfixedwidth", SETTING_FMT_NUMBER, "", NULL },
|
||||
{ SETTING_CF_SPLITCALLID, "cf.splitcallid", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CF_HIGHTLIGHT, "cf.highlight", SETTING_FMT_ENUM, "bold", SETTING_ENUM_HIGHLIGHT },
|
||||
{ SETTING_CF_SCROLLSTEP, "cf.scrollstep", SETTING_FMT_NUMBER, "4", NULL },
|
||||
{ SETTING_CF_LOCALHIGHLIGHT, "cf.localhighlight", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CF_SDP_INFO, "cf.sdpinfo", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_SDP_INFO },
|
||||
{ SETTING_CF_MEDIA, "cf.media", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CF_DELTA, "cf.deltatime", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_CR_SCROLLSTEP, "cr.scrollstep", SETTING_FMT_NUMBER, "10", NULL },
|
||||
{ SETTING_FILTER_METHODS, "filter.methods", SETTING_FMT_STRING, "", NULL },
|
||||
{ SETTING_EEP_SEND, "eep.send", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_EEP_SEND_ADDR, "eep.send.address", SETTING_FMT_STRING, "", NULL },
|
||||
{ SETTING_EEP_SEND_PORT, "eep.send.port", SETTING_FMT_NUMBER, "9060", NULL },
|
||||
{ SETTING_EEP_SEND_PASS, "eep.send.pass", SETTING_FMT_STRING, "myHep", NULL },
|
||||
{ SETTING_EEP_LISTEN, "eep.listen", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF },
|
||||
{ SETTING_EEP_LISTEN_ADDR, "eep.listen.address", SETTING_FMT_STRING, "0.0.0.0", NULL },
|
||||
{ SETTING_EEP_LISTEN_PORT, "eep.listen.port", SETTING_FMT_NUMBER, "9060", NULL },
|
||||
{ SETTING_EEP_LISTEN_PASS, "eep.listen.pass", SETTING_FMT_STRING, "myHep", NULL },
|
||||
};
|
||||
|
||||
setting_t *
|
||||
|
@ -54,6 +54,7 @@ typedef struct setting_option setting_t;
|
||||
#define SETTING_ENUM_COLORMODE (const char *[]){ "request", "cseq", "callid", NULL }
|
||||
#define SETTING_ENUM_HIGHLIGHT (const char *[]){ "bold", "reverse", "reversebold", NULL }
|
||||
#define SETTING_ENUM_SDP_INFO (const char *[]){ "off", "first", "full", NULL}
|
||||
#define SETTING_ENUM_STORAGE (const char *[]){ "none", "memory", NULL }
|
||||
|
||||
//! Other useful defines
|
||||
#define SETTING_ON "on"
|
||||
@ -77,6 +78,7 @@ enum setting_id {
|
||||
SETTING_CAPTURE_OUTFILE,
|
||||
SETTING_CAPTURE_KEYFILE,
|
||||
SETTING_CAPTURE_RTP,
|
||||
SETTING_CAPTURE_STORAGE,
|
||||
SETTING_SIP_NOINCOMPLETE,
|
||||
SETTING_SIP_CALLS,
|
||||
SETTING_SAVEPATH,
|
||||
@ -96,6 +98,14 @@ enum setting_id {
|
||||
SETTING_CF_DELTA,
|
||||
SETTING_CR_SCROLLSTEP,
|
||||
SETTING_FILTER_METHODS,
|
||||
SETTING_EEP_SEND,
|
||||
SETTING_EEP_SEND_ADDR,
|
||||
SETTING_EEP_SEND_PORT,
|
||||
SETTING_EEP_SEND_PASS,
|
||||
SETTING_EEP_LISTEN,
|
||||
SETTING_EEP_LISTEN_ADDR,
|
||||
SETTING_EEP_LISTEN_PORT,
|
||||
SETTING_EEP_LISTEN_PASS,
|
||||
SETTING_COUNT
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user