#include <sys/time.h>
#endif
- #include "ftdm_isdn.h"
+ #include "ftmod_isdn.h"
#define LINE "--------------------------------------------------------------------------------"
- //#define IODEBUG
/* helper macros */
-#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP)
#define FTDM_SPAN_IS_NT(x) (((ftdm_isdn_data_t *)(x)->signal_data)->mode == Q921_NT)
+ #define DEFAULT_NATIONAL_PREFIX "0"
+ #define DEFAULT_INTERNATIONAL_PREFIX "00"
- #ifdef HAVE_LIBPCAP
- /*-------------------------------------------------------------------------*/
- /*Q931ToPcap functions*/
+ /*****************************************************************************************
+ * PCAP
+ * Based on Helmut Kuper's (<helmut.kuper@ewetel.de>) implementation,
+ * but using a different approach (needs a recent libpcap + wireshark)
+ *****************************************************************************************/
+ #ifdef HAVE_PCAP
+ #include <arpa/inet.h> /* htons() */
#include <pcap.h>
- #endif
- #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
-
- #ifdef HAVE_LIBPCAP
- /*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;
-
- /*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
- };
+ #define PCAP_SNAPLEN 1500
- /**
- * \brief Opens a pcap file for capture
- * \return Success or failure
- */
- static ftdm_status_t openPcapFile(void)
+ struct pcap_context {
+ pcap_dumper_t *dump; /*!< pcap file handle */
+ pcap_t *handle; /*!< pcap lib context */
+ char *filename; /*!< capture file name */
+ };
+
+ static inline ftdm_status_t isdn_pcap_is_open(struct ftdm_isdn_data *isdn)
{
- if(!pcaphandle)
- {
- pcaphandle = pcap_open_dead(DLT_EN10MB, SNAPLEN);
- if (!pcaphandle)
- {
- ftdm_log(FTDM_LOG_ERROR, "Can't open pcap session: (%s)\n", pcap_geterr(pcaphandle));
- return FTDM_FAIL;
- }
- }
+ return (isdn->pcap) ? 1 : 0;
+ }
- if(!pcapfile){
- /* Open the dump file */
- if(!(pcapfile=pcap_dump_open(pcaphandle, pcapfn))){
- ftdm_log(FTDM_LOG_ERROR, "Error opening output file (%s)\n", pcap_geterr(pcaphandle));
- return FTDM_FAIL;
- }
- }
- else{
- ftdm_log(FTDM_LOG_WARNING, "Pcap file is already open!\n");
- return FTDM_FAIL;
- }
+ static inline ftdm_status_t isdn_pcap_capture_both(struct ftdm_isdn_data *isdn)
+ {
+ return ((isdn->flags & (FTDM_ISDN_CAPTURE | FTDM_ISDN_CAPTURE_L3ONLY)) == FTDM_ISDN_CAPTURE) ? 1 : 0;
+ }
- ftdm_log(FTDM_LOG_DEBUG, "Pcap file '%s' successfully opened!\n", pcapfn);
+ static inline ftdm_status_t isdn_pcap_capture_l3only(struct ftdm_isdn_data *isdn)
+ {
+ return ((isdn->flags & FTDM_ISDN_CAPTURE) && (isdn->flags & FTDM_ISDN_CAPTURE_L3ONLY)) ? 1 : 0;
+ }
- 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;
+ static ftdm_status_t isdn_pcap_open(struct ftdm_isdn_data *isdn, char *filename)
+ {
+ struct pcap_context *pcap = NULL;
- return FTDM_SUCCESS;
+ if (!isdn) {
+ return FTDM_FAIL;
+ }
+
+ if (ftdm_strlen_zero(filename)) {
+ return FTDM_FAIL;
+ }
+
+ pcap = malloc(sizeof(struct pcap_context));
+ if (!pcap) {
+ ftdm_log(FTDM_LOG_ERROR, "Failed to allocate isdn pcap context\n");
+ return FTDM_FAIL;
+ }
+
+ memset(pcap, 0, sizeof(struct pcap_context));
+
+ pcap->filename = strdup(filename);
+
+ pcap->handle = pcap_open_dead(DLT_LINUX_LAPD, PCAP_SNAPLEN);
+ if (!pcap->handle) {
+ ftdm_log(FTDM_LOG_ERROR, "Failed to open pcap handle\n");
+ goto error;
+ }
+
+ pcap->dump = pcap_dump_open(pcap->handle, pcap->filename);
+ if (!pcap->dump) {
+ ftdm_log(FTDM_LOG_ERROR, "Failed to open capture file: %s\n", pcap_geterr(pcap->handle));
+ goto error;
+ }
+
+ ftdm_log(FTDM_LOG_INFO, "Capture file \"%s\" opened\n", pcap->filename);
+
+ isdn->pcap = pcap;
+
+ return FTDM_SUCCESS;
+
+ error:
+ if (pcap->handle) {
+ pcap_close(pcap->handle);
+ }
+ if (pcap->filename) {
+ free(pcap->filename);
+ }
+
+ free(pcap);
+
+ return FTDM_FAIL;
}
- /**
- * \brief Closes a pcap file
- * \return Success
- */
- static ftdm_status_t closePcapFile(void)
+ static ftdm_status_t isdn_pcap_close(struct ftdm_isdn_data *isdn)
{
- if (pcapfile) {
- pcap_dump_close(pcapfile);
- if (pcaphandle) pcap_close(pcaphandle);
-
- ftdm_log(FTDM_LOG_DEBUG, "Pcap file closed! File size is %lu bytes.\n", pcapfilesize);
+ struct pcap_context *pcap = NULL;
+ long size;
- 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;
+ if (!isdn || !isdn->pcap) {
+ return FTDM_FAIL;
}
+ pcap = isdn->pcap;
+
+ isdn->flags &= ~(FTDM_ISDN_CAPTURE | FTDM_ISDN_CAPTURE_L3ONLY);
+ isdn->pcap = NULL;
+
+ pcap_dump_flush(pcap->dump);
+
+ size = pcap_dump_ftell(pcap->dump);
+ ftdm_log(FTDM_LOG_INFO, "File \"%s\" captured %ld bytes of data\n", pcap->filename, size);
+
+ pcap_dump_close(pcap->dump);
+ pcap_close(pcap->handle);
+
+ free(pcap->filename);
+ free(pcap);
- /*We have allways success with this? I think so*/
return FTDM_SUCCESS;
}