Hi,
I don't know if something similar exists already but I've created a
patch to add the ability to do pcap capturing on dahdi cards. So I'm
posting it here just in case it might be useful to someone. It
consists of 2 parts
1. changes to the dahdi driver to add ioctls to mirror reads/writes
from a signaling channel to a pseudo channel
2. a corresponding user app to set up the mirroring and record the
traffic in a pcap
This seems to work though I'm not sure if it's the best solution design-wise.
I might be abusing the pseudo channel concept and wanted to ask if you ever
felt the need for similar functionality.
to compile the app do the following
gcc dahdi_pcap.c -o dahdi_pcap -lpcap
and the syntax to run it is
./dahdi_pcap chan1 [chan2]* pcap.pcap
e.g.
./dahdi_pcap 16 47 test.pcap
Regards,
Torrey
#include <stdio.h>
#include <fcntl.h>
#include <dahdi/user.h>
#include <sys/time.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <pcap.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define BLOCK_SIZE 512
struct mtp2_phdr {
u_int8_t sent;
u_int8_t annex_a_used;
u_int16_t link_number;
};
struct chan_fds {
int rfd;
int tfd;
int chan_id;
};
int make_mirror(long type, int chan)
{
int res = 0;
int fd = 0;
int x = BLOCK_SIZE;
struct dahdi_bufferinfo bi;
fd = open("/dev/dahdi/pseudo", O_RDONLY);
memset(&bi, 0, sizeof(bi));
bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
bi.numbufs = 32;
bi.bufsize = BLOCK_SIZE;
ioctl(fd, DAHDI_SET_BUFINFO, &bi);
res = ioctl(fd, type, &chan);
if(res)
{
printf("error setting channel err=%d!\n", res);
return -1;
}
return fd;
}
void log_packet(struct chan_fds * fd, char is_read, pcap_dumper_t * dump)
{
char buf[BLOCK_SIZE * 4];
int res = 0;
struct pcap_pkthdr hdr;
struct mtp2_phdr * mtp2 = (struct mtp2_phdr *)buf;
memset(buf, 0, sizeof(buf));
if(is_read)
{
res = read(fd->rfd, buf+sizeof(struct mtp2_phdr), sizeof(buf)-sizeof(struct mtp2_phdr));
}
else
{
res = read(fd->tfd, buf+sizeof(struct mtp2_phdr), sizeof(buf)-sizeof(struct mtp2_phdr));
}
gettimeofday(&hdr.ts, NULL);
if(res > 0)
{
hdr.caplen = res+sizeof(struct mtp2_phdr);
hdr.len = res+sizeof(struct mtp2_phdr);
int i = 0;
if(is_read)
{
mtp2->sent = 0;
mtp2->annex_a_used = 0;
}
else
{
mtp2->sent = 1;
mtp2->annex_a_used = 0;
}
mtp2->link_number = htons(fd->chan_id);
pcap_dump((u_char*)dump, &hdr, buf);
pcap_dump_flush(dump);
}
}
int main(int argc, char *argv[])
{
struct chan_fds chans[10];
int num_chans = argc - 2;
int max_fd = 0;
int i;
for(i = 0; i < num_chans; i++)
{
int chan = atoi(argv[i+1]);
chans[i].tfd = make_mirror(DAHDI_TXMIRROR, chan);
chans[i].rfd = make_mirror(DAHDI_RXMIRROR, chan);
chans[i].chan_id = chan;
if(chans[i].tfd > max_fd)
{
max_fd = chans[i].tfd;
}
if(chans[i].rfd > max_fd)
{
max_fd = chans[i].rfd;
}
}
max_fd++;
pcap_t * pcap = pcap_open_dead(DLT_MTP2_WITH_PHDR, BLOCK_SIZE*4);
pcap_dumper_t * dump = pcap_dump_open(pcap, argv[argc - 1]);
while(1)
{
fd_set rd_set;
FD_ZERO(&rd_set);
for(i = 0; i < num_chans; i++)
{
FD_SET(chans[i].tfd, &rd_set);
FD_SET(chans[i].rfd, &rd_set);
}
select(max_fd, &rd_set, NULL, NULL, NULL);
for(i = 0; i < num_chans; i++)
{
if(FD_ISSET(chans[i].rfd, &rd_set))
{
log_packet(&chans[i], 1, dump);
}
if(FD_ISSET(chans[i].tfd, &rd_set))
{
log_packet(&chans[i], 0, dump);
}
}
}
return 0;
}
Index: include/dahdi/user.h
===================================================================
--- include/dahdi/user.h (revision 7730)
+++ include/dahdi/user.h (working copy)
@@ -1027,6 +1027,12 @@
#define DAHDI_ECHOCANCEL_FAX_MODE _IOW(DAHDI_CODE, 102, int)
+/*
+ * Defines which channel to receive mirrored traffic from
+ */
+#define DAHDI_RXMIRROR _IOW(DAHDI_CODE, 103, int)
+#define DAHDI_TXMIRROR _IOW(DAHDI_CODE, 104, int)
+
/* Get current status IOCTL */
/* Defines for Radio Status (dahdi_radio_stat.radstat) bits */
Index: include/dahdi/kernel.h
===================================================================
--- include/dahdi/kernel.h (revision 7730)
+++ include/dahdi/kernel.h (working copy)
@@ -436,6 +436,9 @@
struct file *file; /*!< File structure */
+ struct dahdi_chan *rxmirror; /*!< channel we mirror reads to */
+ struct dahdi_chan *txmirror; /*!< channel we mirror writes to */
+ struct dahdi_chan *srcmirror; /*!< channel we mirror from */
struct dahdi_span *span; /*!< Span we're a member of */
int sig; /*!< Signalling */
int sigcap; /*!< Capability for signalling */
Index: drivers/dahdi/dahdi-base.c
===================================================================
--- drivers/dahdi/dahdi-base.c (revision 7730)
+++ drivers/dahdi/dahdi-base.c (working copy)
@@ -2729,8 +2729,27 @@
if (chan) {
/* Chan lock protects contents against potentially non atomic accesses.
* So if the pointer setting is not atomic, we should protect */
+
+ if(chan->srcmirror)
+ {
+ spin_lock_irqsave(&chan->srcmirror->lock, flags);
+ if(chan == chan->srcmirror->txmirror)
+ {
+ module_printk(KERN_INFO, "Chan %d tx mirror to %d stopped\n", chan->srcmirror->txmirror->channo, chan->srcmirror->channo);
+ chan->srcmirror->txmirror = NULL;
+ }
+ if(chan == chan->srcmirror->rxmirror)
+ {
+ module_printk(KERN_INFO, "Chan %d rx mirror to %d stopped\n", chan->srcmirror->rxmirror->channo, chan->srcmirror->channo);
+ chan->srcmirror->rxmirror = NULL;
+ }
+ spin_unlock_irqrestore(&chan->srcmirror->lock, flags);
+ }
+
spin_lock_irqsave(&chan->lock, flags);
chan->file = NULL;
+ chan->srcmirror = NULL;
+
spin_unlock_irqrestore(&chan->lock, flags);
close_channel(chan);
if (chan->span) {
@@ -4536,6 +4555,56 @@
if (!chan)
return -EINVAL;
switch(cmd) {
+
+ case DAHDI_RXMIRROR:
+ get_user(i, (int*)data);
+ if(i > 0 && i < DAHDI_MAX_CHANNELS)
+ {
+ module_printk(KERN_INFO, "Chan %d rxmirrored to %d\n", i, unit);
+ spin_lock_irqsave(&chans[i]->lock, flags);
+ if(chans[i]->rxmirror == NULL)
+ {
+ chans[i]->rxmirror = chan;
+ }
+ spin_unlock_irqrestore(&chans[i]->lock, flags);
+ if(chans[i]->rxmirror != chan)
+ {
+ module_printk(KERN_INFO, "Chan %d cannot be rxmirrored, already in use\n", i);
+ return -EFAULT;
+ }
+ spin_lock_irqsave(&chan->lock, flags);
+ chan->srcmirror = chans[i];
+ chan->flags = chans[i]->flags;
+ chan->sig = chans[i]->sig;
+ clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
+ spin_unlock_irqrestore(&chan->lock, flags);
+ }
+ break;
+ case DAHDI_TXMIRROR:
+ get_user(i, (int*)data);
+ if(i > 0 && i < DAHDI_MAX_CHANNELS)
+ {
+ module_printk(KERN_INFO, "Chan %d tx mirrored to %d\n", i, unit);
+ spin_lock_irqsave(&chans[i]->lock, flags);
+ chans[i]->txmirror = chan;
+ if(chans[i]->txmirror == NULL)
+ {
+ chans[i]->txmirror = chan;
+ }
+ spin_unlock_irqrestore(&chans[i]->lock, flags);
+ if(chans[i]->txmirror != chan)
+ {
+ module_printk(KERN_INFO, "Chan %d cannot be txmirrored, already in use\n", i);
+ return -EFAULT;
+ }
+ spin_lock_irqsave(&chan->lock, flags);
+ chan->srcmirror = chans[i];
+ chan->flags = chans[i]->flags;
+ chan->sig = chans[i]->sig;
+ clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
+ spin_unlock_irqrestore(&chan->lock, flags);
+ }
+ break;
case DAHDI_DIALING:
spin_lock_irqsave(&chan->lock, flags);
j = chan->dialing;
@@ -6229,8 +6298,14 @@
txb[x] = ms->txgain[txb[x]];
}
+static inline void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, int bytes);
+
static inline void __dahdi_getbuf_chunk(struct dahdi_chan *ss, unsigned char *txb)
{
+
+
+ unsigned char *orig_txb = txb;
+
/* Called with ss->lock held */
/* We transmit data from our master channel */
struct dahdi_chan *ms = ss->master;
@@ -6391,6 +6466,12 @@
bytes = 0;
}
}
+ if(ss->txmirror)
+ {
+ spin_lock(&ss->txmirror->lock);
+ __putbuf_chunk(ss->txmirror, orig_txb, DAHDI_CHUNKSIZE);
+ spin_unlock(&ss->txmirror->lock);
+ }
}
static inline void rbs_itimer_expire(struct dahdi_chan *chan)
@@ -7281,7 +7362,6 @@
int res;
int left, x;
-
while(bytes) {
#if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP)
skb = NULL;
@@ -7554,11 +7634,19 @@
}
#endif
}
+
}
static inline void __dahdi_putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb)
{
__putbuf_chunk(ss, rxb, DAHDI_CHUNKSIZE);
+
+ if(ss->rxmirror)
+ {
+ spin_lock(&ss->rxmirror->lock);
+ __putbuf_chunk(ss->rxmirror, rxb, DAHDI_CHUNKSIZE);
+ spin_unlock(&ss->rxmirror->lock);
+ }
}
static void __dahdi_hdlc_abort(struct dahdi_chan *ss, int event)
--
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --
asterisk-ss7 mailing list
To UNSUBSCRIBE or update options visit:
http://lists.digium.com/mailman/listinfo/asterisk-ss7