mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 17:38:59 +00:00
Q931ToPcap patch
git-svn-id: http://svn.openzap.org/svn/openzap/trunk@628 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
@@ -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
|
||||
|
Reference in New Issue
Block a user