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)