Skip to content

Commit

Permalink
sipdump: write udp pcap with sip messages if mode param flag 4 is set
Browse files Browse the repository at this point in the history
- udp is always used for packets writen in pcap no matter the transport
layer used for sip messages
  • Loading branch information
miconda committed Jul 15, 2020
1 parent b7ddcfb commit 17bc7cf
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 3 deletions.
187 changes: 187 additions & 0 deletions src/modules/sipdump/sipdump_pcap.c
@@ -0,0 +1,187 @@
/**
* Copyright (C) 2020 Daniel-Constantin Mierla (asipto.com)
*
* This file is part of Kamailio, a free SIP server.
*
* This file 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 2 of the License, or
* (at your option) any later version
*
*
* This file 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

#include "../../core/ip_addr.h"
#include "../../core/resolve.h"

#include "sipdump_write.h"

/* structures related to PCAP headers imported from open source Asterisk project
* fuction to write to PCAP file adapted for internal structures
* source: res_pjsip_logger.c - License GPLv2 - Copyright (C) Digium, Inc.*/

/* PCAP Header */
struct pcap_header {
uint32_t magic_number; /* PCAP file format magic number */
uint16_t version_major; /* Major version number of the file format */
uint16_t version_minor; /* Minor version number of the file format */
int32_t thiszone; /* GMT to local correction */
uint32_t sigfigs; /* Accuracy of timestamps */
uint32_t snaplen; /* The maximum size that can be recorded in the file */
uint32_t network; /* Type of packets held within the file */
};

/* PCAP Packet Record Header */
struct pcap_record_header {
uint32_t ts_sec; /* When the record was created */
uint32_t ts_usec; /* When the record was created */
uint32_t incl_len; /* Length of packet as saved in the file */
uint32_t orig_len; /* Length of packet as sent over network */
};

/* PCAP Ethernet Header */
struct pcap_ethernet_header {
uint8_t dst[6]; /* Destination MAC address */
uint8_t src[6]; /* Source MAC address */
uint16_t type; /*!The type of packet contained within */
} __attribute__((__packed__));

/*! PCAP IPv4 Header */
struct pcap_ipv4_header {
uint8_t ver_ihl; /* IP header version and other bits */
uint8_t ip_tos; /* Type of service details */
uint16_t ip_len; /* Total length of the packet (including IPv4 header) */
uint16_t ip_id; /* Identification value */
uint16_t ip_off; /* Fragment offset */
uint8_t ip_ttl; /* Time to live for the packet */
uint8_t ip_protocol; /* Protocol of the data held within the packet (always UDP) */
uint16_t ip_sum; /* Checksum (not calculated for our purposes */
uint32_t ip_src; /* Source IP address */
uint32_t ip_dst; /* Destination IP address */
};

/* PCAP IPv6 Header */
struct pcap_ipv6_header {
union {
struct ip6_hdrctl {
uint32_t ip6_un1_flow; /* Version, traffic class, flow label */
uint16_t ip6_un1_plen; /* Length of the packet (not including IPv6 header) */
uint8_t ip6_un1_nxt; /* Next header field */
uint8_t ip6_un1_hlim; /* Hop Limit */
} ip6_un1;
uint8_t ip6_un2_vfc; /* Version, traffic class */
} ip6_ctlun;
struct in6_addr ip6_src; /* Source IP address */
struct in6_addr ip6_dst; /* Destination IP address */
};

/* PCAP UDP Header */
struct pcap_udp_header {
uint16_t src; /* Source IP port */
uint16_t dst; /* Destination IP port */
uint16_t length; /* Length of the UDP header plus UDP packet */
uint16_t checksum; /* Packet checksum, left uncalculated for our purposes */
};

void sipdump_init_pcap(FILE *fs)
{
struct pcap_header v_pcap_header = {
.magic_number = 0xa1b2c3d4,
.version_major = 2,
.version_minor = 4,
.snaplen = 65535,
.network = 1, /* use ethernet to combine IPv4 and IPv6 in same pcap */
};

LM_DBG("writing the pcap file header\n");
if(fwrite(&v_pcap_header, sizeof(struct pcap_header), 1, fs) != 1) {
LM_ERR("failed to write the pcap file header\n");
}
}

void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
{
struct pcap_record_header v_pcap_record_header = {
.ts_sec = spd->tv.tv_sec,
.ts_usec = spd->tv.tv_usec,
};
struct pcap_ethernet_header v_pcap_ethernet_header = {
.type = 0,
};
struct pcap_ipv4_header v_pcap_ipv4_header = {
.ver_ihl = 0x45, /* IPv4 + 20 bytes of header */
.ip_ttl = 128, /* We always put a TTL of 128 to keep Wireshark less blue */
};
struct pcap_ipv6_header v_pcap_ipv6_header = {
.ip6_ctlun.ip6_un2_vfc = 0x60,
};
void *pcap_ip_header;
size_t pcap_ip_header_len;
struct pcap_udp_header v_pcap_udp_header;
ip_addr_t src_ip;
ip_addr_t dst_ip;

if(fs == NULL || spd == NULL) {
return;
}

/* always store UDP */
v_pcap_udp_header.src = ntohs(spd->src_port);
v_pcap_udp_header.dst = ntohs(spd->dst_port);
v_pcap_udp_header.length = ntohs(sizeof(struct pcap_udp_header) + spd->data.len);

/* IP header */
if (spd->afid == AF_INET6) {
v_pcap_ethernet_header.type = htons(0x86DD); /* IPv6 packet */
pcap_ip_header = &v_pcap_ipv6_header;
pcap_ip_header_len = sizeof(struct pcap_ipv6_header);
str2ip6buf(&spd->src_ip, &src_ip);
memcpy(&v_pcap_ipv6_header.ip6_src, src_ip.u.addr16, src_ip.len);
str2ip6buf(&spd->dst_ip, &dst_ip);
memcpy(&v_pcap_ipv6_header.ip6_dst, dst_ip.u.addr16, dst_ip.len);
v_pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(struct pcap_udp_header)
+ spd->data.len);
v_pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP;
} else {
v_pcap_ethernet_header.type = htons(0x0800); /* IPv4 packet */
pcap_ip_header = &v_pcap_ipv4_header;
pcap_ip_header_len = sizeof(struct pcap_ipv4_header);
str2ipbuf(&spd->src_ip, &src_ip);
memcpy(&v_pcap_ipv6_header.ip6_src, src_ip.u.addr, src_ip.len);
str2ipbuf(&spd->dst_ip, &dst_ip);
memcpy(&v_pcap_ipv6_header.ip6_dst, dst_ip.u.addr, dst_ip.len);
v_pcap_ipv4_header.ip_len = htons(sizeof(struct pcap_udp_header)
+ sizeof(struct pcap_ipv4_header) + spd->data.len);
v_pcap_ipv4_header.ip_protocol = IPPROTO_UDP; /* UDP */
}

/* add up all the sizes for this record */
v_pcap_record_header.orig_len = sizeof(struct pcap_ethernet_header) + pcap_ip_header_len
+ sizeof(struct pcap_udp_header) + spd->data.len;
v_pcap_record_header.incl_len = v_pcap_record_header.orig_len;

if (fwrite(&v_pcap_record_header, sizeof(struct pcap_record_header), 1, fs) != 1) {
LM_ERR("writing PCAP header failed: %s\n", strerror(errno));
}
if (fwrite(&v_pcap_ethernet_header, sizeof(struct pcap_ethernet_header), 1, fs) != 1) {
LM_ERR("writing ethernet header to pcap failed: %s\n", strerror(errno));
}
if (fwrite(pcap_ip_header, pcap_ip_header_len, 1, fs) != 1) {
LM_ERR("writing IP header to pcap failed: %s\n", strerror(errno));
}
if (fwrite(&v_pcap_udp_header, sizeof(struct pcap_udp_header), 1, fs) != 1) {
LM_ERR("writing UDP header to pcap failed: %s\n", strerror(errno));
}
if (fwrite(spd->data.s, spd->data.len, 1, fs) != 1) {
LM_ERR("writing UDP payload to pcap failed: %s\n", strerror(errno));
}
}
7 changes: 4 additions & 3 deletions src/modules/sipdump/sipdump_write.c
Expand Up @@ -187,10 +187,10 @@ static int sipdump_write_meta(char *fpath)
mpath[len-2] = 't';
mpath[len-1] = 'a';

LM_DBG("writing meta to file: %s\n", mpath);
LM_DBG("writing meta to file: %s (%d)\n", mpath, len);
mfile = fopen( mpath , "w" );
if(mfile==NULL) {
LM_ERR("failed to open meta file %s\n", mpath);
LM_ERR("failed to open meta file %s (%d)\n", mpath, len);
return -1;
}
localtime_r(&up_since, &ti);
Expand Down Expand Up @@ -270,6 +270,7 @@ static int sipdump_rotate_file(void)
LM_ERR("failed to open file %s\n", _sipdump_fpath);
return -1;
}
sipdump_init_pcap(_sipdump_pcap_file);
}

sipdump_write_meta(_sipdump_fpath);
Expand Down Expand Up @@ -393,7 +394,7 @@ void sipdump_timer_exec(unsigned int ticks, void *param)
sipdump_data_print(sdd, &odata);
/* LM_NOTICE("writing: [[%.*s]] (%d)\n", odata.len,
odata.s, odata.len); */
fwrite(odata.s, 1, odata.len, _sipdump_text_file);
fwrite(odata.s, odata.len, 1, _sipdump_text_file);
}
if(sipdump_mode & SIPDUMP_MODE_WPCAP) {
if(_sipdump_pcap_file==NULL) {
Expand Down

0 comments on commit 17bc7cf

Please sign in to comment.