|
|
|
|
@ -21,6 +21,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct pcap_format {
|
|
|
|
|
int linktype;
|
|
|
|
|
int headerlen;
|
|
|
|
|
void (*header)(unsigned char *, struct packet_stream *);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int check_main_spool_dir(const char *spoolpath);
|
|
|
|
|
static char *recording_setup_file(struct recording *recording);
|
|
|
|
|
static char *meta_setup_file(struct recording *recording);
|
|
|
|
|
@ -47,6 +55,8 @@ static void setup_stream_proc(struct packet_stream *);
|
|
|
|
|
static void setup_media_proc(struct call_media *);
|
|
|
|
|
static void kernel_info_proc(struct packet_stream *, struct rtpengine_target_info *);
|
|
|
|
|
|
|
|
|
|
static void pcap_eth_header(unsigned char *, struct packet_stream *);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const struct recording_method methods[] = {
|
|
|
|
|
@ -77,12 +87,22 @@ static const struct recording_method methods[] = {
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct pcap_format pcap_format_raw = {
|
|
|
|
|
.linktype = DLT_RAW,
|
|
|
|
|
.headerlen = 0,
|
|
|
|
|
};
|
|
|
|
|
static const struct pcap_format pcap_format_eth = {
|
|
|
|
|
.linktype = DLT_EN10MB,
|
|
|
|
|
.headerlen = 14,
|
|
|
|
|
.header = pcap_eth_header,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Global file reference to the spool directory.
|
|
|
|
|
static char *spooldir = NULL;
|
|
|
|
|
|
|
|
|
|
const struct recording_method *selected_recording_method;
|
|
|
|
|
int rec_format;
|
|
|
|
|
static const struct pcap_format *pcap_format;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -109,9 +129,9 @@ void recording_fs_init(const char *spoolpath, const char *method_str, const char
|
|
|
|
|
|
|
|
|
|
found:
|
|
|
|
|
if(!strcmp("raw", format_str))
|
|
|
|
|
rec_format = 0;
|
|
|
|
|
pcap_format = &pcap_format_raw;
|
|
|
|
|
else if(!strcmp("eth", format_str))
|
|
|
|
|
rec_format = 1;
|
|
|
|
|
pcap_format = &pcap_format_eth;
|
|
|
|
|
else {
|
|
|
|
|
ilog(LOG_ERR, "Invalid value for recording format \"%s\".", format_str);
|
|
|
|
|
exit(-1);
|
|
|
|
|
@ -408,10 +428,7 @@ static char *recording_setup_file(struct recording *recording) {
|
|
|
|
|
recording_path = file_path_str(recording->meta_prefix, "/pcaps/", ".pcap");
|
|
|
|
|
recording->pcap.recording_path = recording_path;
|
|
|
|
|
|
|
|
|
|
if(rec_format == 1)
|
|
|
|
|
recording->pcap.recording_pd = pcap_open_dead(DLT_EN10MB, 65535);
|
|
|
|
|
else
|
|
|
|
|
recording->pcap.recording_pd = pcap_open_dead(DLT_RAW, 65535);
|
|
|
|
|
recording->pcap.recording_pd = pcap_open_dead(pcap_format->linktype, 65535);
|
|
|
|
|
recording->pcap.recording_pdumper = pcap_dump_open(recording->pcap.recording_pd, recording_path);
|
|
|
|
|
if (recording->pcap.recording_pdumper == NULL) {
|
|
|
|
|
pcap_close(recording->pcap.recording_pd);
|
|
|
|
|
@ -454,6 +471,12 @@ static unsigned int fake_ip_header(unsigned char *out, struct packet_stream *str
|
|
|
|
|
return hdr_len + inp->len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void pcap_eth_header(unsigned char *pkt, struct packet_stream *stream) {
|
|
|
|
|
memset(pkt, 0, 14);
|
|
|
|
|
uint16_t *hdr16 = (void *) pkt;
|
|
|
|
|
hdr16[6] = htons(stream->selected_sfd->socket.local.address.family->ethertype);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Write out a PCAP packet with payload string.
|
|
|
|
|
* A fair amount extraneous of packet data is spoofed.
|
|
|
|
|
@ -462,24 +485,10 @@ static void stream_pcap_dump(pcap_dumper_t *pdumper, struct packet_stream *strea
|
|
|
|
|
if (!pdumper)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
int ether_len = 0;
|
|
|
|
|
if(rec_format == 1)
|
|
|
|
|
ether_len = 14;
|
|
|
|
|
|
|
|
|
|
unsigned char pkt[s->len + MAX_PACKET_HEADER_LEN + ether_len];
|
|
|
|
|
unsigned int pkt_len = fake_ip_header(pkt + ether_len, stream, s);
|
|
|
|
|
if(rec_format == 1) {
|
|
|
|
|
pkt_len += 14;
|
|
|
|
|
memset(pkt, 0, 14);
|
|
|
|
|
switch(stream->selected_sfd->socket.local.address.family->af) {
|
|
|
|
|
case AF_INET:
|
|
|
|
|
pkt[12] = 0x08;
|
|
|
|
|
break;
|
|
|
|
|
case AF_INET6:
|
|
|
|
|
pkt[12] = 0x86;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
unsigned char pkt[s->len + MAX_PACKET_HEADER_LEN + pcap_format->headerlen];
|
|
|
|
|
unsigned int pkt_len = fake_ip_header(pkt + pcap_format->headerlen, stream, s) + pcap_format->headerlen;
|
|
|
|
|
if (pcap_format->header)
|
|
|
|
|
pcap_format->header(pkt, stream);
|
|
|
|
|
|
|
|
|
|
// Set up PCAP packet header
|
|
|
|
|
struct pcap_pkthdr header;
|
|
|
|
|
|