Q931ToPcap patch

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@628 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
Helmut Kuper
2009-01-30 11:37:11 +00:00
parent e29ec54993
commit eb24f46932
6 changed files with 977 additions and 322 deletions

View File

@@ -49,6 +49,207 @@
#define ZAP_SPAN_IS_NT(x) (((zap_isdn_data_t *)(x)->signal_data)->mode == Q921_NT)
/*-------------------------------------------------------------------------*/
/*Q931ToPcap functions*/
#include <pcap.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <string.h>
#define SNAPLEN 1522
#define MAX_ETHER_PAYLOAD_SIZE 1500
#define MIN_ETHER_PAYLOAD_SIZE 42
#define SIZE_ETHERNET 18
#define VLANID_OFFSET 15
#define SIZE_IP 20
#define SIZE_TCP 20
#define SIZE_TPKT 4
#define SIZE_ETHERNET_CRC 4
#define OVERHEAD SIZE_ETHERNET+SIZE_IP+SIZE_TCP+SIZE_TPKT
#define MAX_Q931_SIZE MAX_ETHER_PAYLOAD_SIZE-SIZE_IP-SIZE_TCP-SIZE_TPKT
#define TPKT_SIZE_OFFSET SIZE_ETHERNET+SIZE_IP+SIZE_TCP+2
#define IP_SIZE_OFFSET SIZE_ETHERNET+2
#define TCP_SEQ_OFFSET SIZE_ETHERNET+SIZE_IP+4
/*Some globals*/
unsigned long pcapfilesize = 0;
unsigned long tcp_next_seq_no_send = 0;
unsigned long tcp_next_seq_no_rec = 0;
pcap_dumper_t *pcapfile = NULL;
struct pcap_pkthdr pcaphdr;
pcap_t *pcaphandle = NULL;
char *pcapfn = NULL;
int do_q931ToPcap= 0;
static zap_status_t openPcapFile(void)
{
if(!pcaphandle)
{
pcaphandle = pcap_open_dead(DLT_EN10MB, SNAPLEN);
if (!pcaphandle)
{
zap_log(ZAP_LOG_ERROR, "Can't open pcap session: (%s)\n", pcap_geterr(pcaphandle));
return ZAP_FAIL;
}
}
if(!pcapfile){
/* Open the dump file */
if(!(pcapfile=pcap_dump_open(pcaphandle, pcapfn))){
zap_log(ZAP_LOG_ERROR, "Error opening output file (%s)\n", pcap_geterr(pcaphandle));
return ZAP_FAIL;
}
}
else{
zap_log(ZAP_LOG_WARNING, "Pcap file is already open!\n");
return ZAP_FAIL;
}
zap_log(ZAP_LOG_DEBUG, "Pcap file '%s' successfully opened!\n", pcapfn);
pcaphdr.ts.tv_sec = 0;
pcaphdr.ts.tv_usec = 0;
pcapfilesize = 24; /*current pcap file header seems to be 24 bytes*/
tcp_next_seq_no_send = 0;
tcp_next_seq_no_rec = 0;
return ZAP_SUCCESS;
}
static zap_status_t closePcapFile(void)
{
if(pcapfile){
pcap_dump_close(pcapfile);
if(pcaphandle) pcap_close(pcaphandle);
zap_log(ZAP_LOG_DEBUG, "Pcap file closed! File size is %lu bytes.\n", pcapfilesize);
pcaphdr.ts.tv_sec = 0;
pcaphdr.ts.tv_usec = 0;
pcapfile = NULL;
pcaphandle = NULL;
pcapfilesize = 0;
tcp_next_seq_no_send = 0;
tcp_next_seq_no_rec = 0;
}
/*We have allways success with this? I think so*/
return ZAP_SUCCESS;
}
static zap_status_t writeQ931PacketToPcap(L3UCHAR* q931buf, L3USHORT q931size, L3ULONG span_id, L3USHORT direction)
{
L3UCHAR *frame = NULL;
u_char spanid = (u_char)span_id;
unsigned long *tcp_next_seq_no = NULL;
spanid=span_id;
/*Predefined Ethernet Frame with Q931-over-IP encapsulated - From remote TDM host to FreeSWITCH*/
L3UCHAR recFrame[SNAPLEN]= {
/*IEEE 802.3 VLAN 802.1q Ethernet Frame Header*/
2,0,1,0xAA,0xAA,0xAA,2,0,1,0xBB,0xBB,0xBB,0x81,0,0xE0,0,0x08,0,
/*IPv4 Header (minimal size; no options)*/
0x45,0,0,44,0,0,0,0,64,6,0,0,2,2,2,2,1,1,1,1,
/*TCP-Header*/
0,0x66,0,0x66,0,0,0,0,0,0,0,0,0x50,0,0,1,0,0,0,0,
/*TPKT-Header RFC 1006*/
3,0,0,0
};
/*Predefined Ethernet Frame with Q931-over-IP encapsulated - Frome FreeSWITCH to remote TDM host*/
L3UCHAR sendFrame[SNAPLEN]= {
/*IEEE 802.3 VLAN 802.1q Ethernet Frame Header*/
2,0,1,0xBB,0xBB,0xBB,2,0,1,0xAA,0xAA,0xAA,0x81,0,0xE0,0,0x08,0,
/*IPv4 Header (minimal size; no options)*/
0x45,0,0,44,0,0,0,0,64,6,0,0,1,1,1,1,2,2,2,2,
/*TCP-Header*/
0,0x66,0,0x66,0,0,0,0,0,0,0,0,0x50,0,0,1,0,0,0,0,
/*TPKT-Header RFC 1006*/
3,0,0,0
};
/*The total length of the ethernet frame generated by this function has a min length of 66
so we don't have to care about padding :)*/
/*FS is sending the packet*/
if(direction==0){
frame=sendFrame;
tcp_next_seq_no = &tcp_next_seq_no_send;
}
/*FS is receiving the packet*/
else{
frame=recFrame;
tcp_next_seq_no = &tcp_next_seq_no_rec;
}
/*Set spanid in VLAN-ID tag*/
frame[VLANID_OFFSET] = spanid;
/*** Write sent packet ***/
if(q931size > MAX_Q931_SIZE)
{
/*WARNING*/
zap_log(ZAP_LOG_WARNING, "Q931 packet size is too big (%u)! Limitting it to %u! Q931 packet will be corrupt.\n", q931size, MAX_Q931_SIZE);
q931size=MAX_Q931_SIZE;
}
/*Copy q931 buffer into frame*/
memcpy(frame+OVERHEAD,q931buf,q931size);
/*Store TCP sequence number in TCP header*/
frame[TCP_SEQ_OFFSET]=(*tcp_next_seq_no>>24)&0xFF;
frame[TCP_SEQ_OFFSET+1]=(*tcp_next_seq_no>>16)&0xFF;
frame[TCP_SEQ_OFFSET+2]=(*tcp_next_seq_no>>8)&0xFF;
frame[TCP_SEQ_OFFSET+3]=*tcp_next_seq_no & 0xFF;
/*Store size of TPKT packet*/
q931size+=4;
frame[TPKT_SIZE_OFFSET]=(q931size>>8)&0xFF;
frame[TPKT_SIZE_OFFSET+1]=q931size&0xFF;
/*Calc next TCP sequence number*/
*tcp_next_seq_no+=q931size;
/*Store size of IP packet*/
q931size+=SIZE_IP+SIZE_TCP;
frame[IP_SIZE_OFFSET]=(q931size>>8)&0xFF;
frame[IP_SIZE_OFFSET+1]=q931size&0xFF;
pcaphdr.caplen = SIZE_ETHERNET+SIZE_ETHERNET_CRC+q931size;
pcaphdr.len = pcaphdr.caplen;
pcap_dump((u_char*)pcapfile, &pcaphdr, frame);
pcap_dump_flush(pcapfile);
/*Increase microsecond timestamp by 1*/
pcaphdr.ts.tv_usec++;
if(pcaphdr.ts.tv_usec==1000000)
{
pcaphdr.ts.tv_sec++;
pcaphdr.ts.tv_usec=0;
}
/*Maintain pcap file size*/
pcapfilesize+=pcaphdr.caplen;
pcapfilesize+=sizeof(struct pcap_pkthdr);
zap_log(ZAP_LOG_DEBUG, "Added %u bytes to pcap file. File size is now %lu, \n", q931size, pcapfilesize);
return ZAP_SUCCESS;
}
static ZIO_IO_UNLOAD_FUNCTION(close_pcap)
{
return closePcapFile();
}
/*Q931ToPcap functions DONE*/
/*-------------------------------------------------------------------------*/
static L2ULONG zap_time_now(void)
{
return (L2ULONG)zap_current_time_in_ms();
@@ -769,12 +970,20 @@ static int zap_isdn_921_23(void *pvt, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *msg
{
int ret, offset = (ind == Q921_DL_DATA) ? 4 : 3;
char bb[4096] = "";
zap_span_t *span = (zap_span_t *) pvt; /*To get access to spanid for Q931ToPcap*/
switch(ind) {
case Q921_DL_DATA:
case Q921_DL_UNIT_DATA:
print_hex_bytes(msg + offset, mlen - offset, bb, sizeof(bb));
zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", (int)mlen - offset, LINE, bb);
/*Q931ToPcap*/
if(do_q931ToPcap==1){
if(writeQ931PacketToPcap(msg + offset, mlen - offset, span->span_id, 1) != ZAP_SUCCESS){
zap_log(ZAP_LOG_WARNING, "Couldn't write Q931 buffer to pcap file!\n");
}
}
/*Q931ToPcap done*/
zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n\n", (int)mlen - offset, LINE, bb);
default:
ret = Q931Rx23(pvt, ind, tei, msg, mlen);
if (ret != 0)
@@ -1519,6 +1728,7 @@ static int q931_rx_32(void *pvt, Q921DLMsg_t ind, L3UCHAR tei, L3UCHAR *msg, L3I
{
int offset = 4;
char bb[4096] = "";
zap_span_t *span = (zap_span_t *) pvt; /*To get access to span_id for Q931ToPcap*/
switch(ind) {
case Q921_DL_UNIT_DATA:
@@ -1526,6 +1736,13 @@ static int q931_rx_32(void *pvt, Q921DLMsg_t ind, L3UCHAR tei, L3UCHAR *msg, L3I
case Q921_DL_DATA:
print_hex_bytes(msg + offset, mlen - offset, bb, sizeof(bb));
/*Q931ToPcap*/
if(do_q931ToPcap==1){
if(writeQ931PacketToPcap(msg + offset, mlen - offset, span->span_id, 0) != ZAP_SUCCESS){
zap_log(ZAP_LOG_WARNING, "Couldn't write Q931 buffer to pcap file!\n");
}
}
/*Q931ToPcap done*/
zap_log(ZAP_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)mlen - offset, LINE, bb);
break;
@@ -1696,8 +1913,38 @@ static ZIO_SIG_CONFIGURE_FUNCTION(zap_isdn_configure_span)
int32_t digit_timeout = 0;
int q921loglevel = -1;
int q931loglevel = -1;
int q931topcap = -1; /*Q931ToPcap*/
int openPcap = 0; /*Flag: open Pcap file please*/
if (span->signal_type) {
/*Q931ToPcap: Get the content of the q931topcap and pcapfilename args given by mod_openzap */
while((var = va_arg(ap, char *))) {
if (!strcasecmp(var, "q931topcap")) {
q931topcap = va_arg(ap, int);
if(q931topcap==1) {
/*PCAP on*/;
openPcap=1;
}
else if(q931topcap==0){
/*PCAP off*/
if(closePcapFile() != ZAP_SUCCESS) return ZAP_FAIL;
do_q931ToPcap=0;
return ZAP_SUCCESS;
}
}
if (!strcasecmp(var, "pcapfilename")) {
/*Put filename into global var*/
pcapfn = va_arg(ap, char*);
}
}
/*We know now, that user wants to enable Q931ToPcap and what file name he wants, so open it please*/
if(openPcap==1){
if(openPcapFile() != ZAP_SUCCESS) return ZAP_FAIL;
do_q931ToPcap=1;
return ZAP_SUCCESS;
}
/*Q931ToPcap done*/
snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling [%d].", span->signal_type);
return ZAP_FAIL;
}
@@ -1863,17 +2110,17 @@ static ZIO_SIG_CONFIGURE_FUNCTION(zap_isdn_configure_span)
return ZAP_SUCCESS;
}
zap_module_t zap_module = {
"isdn",
NULL,
NULL,
close_pcap,
zap_isdn_init,
zap_isdn_configure_span,
NULL
};
/* For Emacs:
* Local Variables:
* mode:c