diff --git a/mod_openzap/mod_openzap.c b/mod_openzap/mod_openzap.c
index b93a5ab..0cbd404 100644
--- a/mod_openzap/mod_openzap.c
+++ b/mod_openzap/mod_openzap.c
@@ -698,6 +698,9 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
 				zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
 				zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
 			} else {
+				if (tech_pvt->zchan->state < ZAP_CHANNEL_STATE_PROGRESS) {
+					zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
+				}
 				zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
 			}
 		}
@@ -707,6 +710,12 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
 			if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
 				zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
 			} else {
+				if (tech_pvt->zchan->state < ZAP_CHANNEL_STATE_PROGRESS) {
+					zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
+				}
+				if (tech_pvt->zchan->state < ZAP_CHANNEL_STATE_PROGRESS_MEDIA) {
+					zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
+				}
 				zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP);
 			}
 		}
diff --git a/src/include/zap_types.h b/src/include/zap_types.h
index 3c04b8d..3398f12 100644
--- a/src/include/zap_types.h
+++ b/src/include/zap_types.h
@@ -351,7 +351,8 @@ typedef enum {
 	ZAP_CHANNEL_3WAY = (1 << 20),
 	ZAP_CHANNEL_PROGRESS = (1 << 21),
 	ZAP_CHANNEL_MEDIA = (1 << 22),
-	ZAP_CHANNEL_ANSWERED = (1 << 23)
+	ZAP_CHANNEL_ANSWERED = (1 << 23),
+	ZAP_CHANNEL_OVERLAP_DIAL = (1 << 24)
 } zap_channel_flag_t;
 
 typedef enum {
diff --git a/src/isdn/Q931.c b/src/isdn/Q931.c
index 6591613..90ab46e 100644
--- a/src/isdn/Q931.c
+++ b/src/isdn/Q931.c
@@ -378,6 +378,10 @@ L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3INT ind, L3UCHAR tei, L3UCHAR * buf,
 		/* Message Type */
 		m->MesType = Mes[IOff++];
 
+		/* Store tei */
+		m->Tei = tei;
+
+#if 0
 		/* d'oh a little ugly but this saves us from:
 		 *	a) doing Q.921 work in the lower levels (extracting the TEI ourselves)
 		 *	b) adding a tei parameter to _all_ Proc functions
@@ -391,8 +395,9 @@ L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3INT ind, L3UCHAR tei, L3UCHAR * buf,
 				pTrunk->call[callIndex].Tei = tei;
 			}
 		}
+#endif
 
-		Q931Log(pTrunk, Q931_LOG_DEBUG, "Received message from Q.921 (ind %d, tei %d, size %d)\nMesType: %d, CRVFlag %d (%s), CRV %d (Dialect: %d)\n", ind, tei, Size,
+		Q931Log(pTrunk, Q931_LOG_DEBUG, "Received message from Q.921 (ind %d, tei %d, size %d)\nMesType: %d, CRVFlag %d (%s), CRV %d (Dialect: %d)\n", ind, m->Tei, Size,
 						 m->MesType, m->CRVFlag, m->CRVFlag ? "Terminator" : "Originator", m->CRV, pTrunk->Dialect);
 
 		RetCode = Q931Umes[pTrunk->Dialect][m->MesType](pTrunk, Mes, (Q931mes_Generic *)pTrunk->L3Buf, IOff, Size - L2HSize);
diff --git a/src/isdn/Q931StateNT.c b/src/isdn/Q931StateNT.c
index af74ef0..d1eff42 100644
--- a/src/isdn/Q931StateNT.c
+++ b/src/isdn/Q931StateNT.c
@@ -361,6 +361,9 @@ L3INT Q931ProcSetupNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
             return ret;
         }
 
+	/* store TEI in call */
+	pTrunk->call[callIndex].Tei = pMes->Tei;
+
         /* Send setup indication to user */
         ret = Q931Tx34(pTrunk,(L3UCHAR*)pMes,pMes->Size);
         if(ret != Q931E_NO_ERROR)
diff --git a/src/isdn/include/Q931.h b/src/isdn/include/Q931.h
index 2687930..c9311fa 100644
--- a/src/isdn/include/Q931.h
+++ b/src/isdn/include/Q931.h
@@ -563,9 +563,10 @@ typedef struct
 *****************************************************************************/
 typedef struct
 {
-    L3UINT			Size;           /* Size of message in bytes             */
+    L3UINT          Size;           /* Size of message in bytes             */
     L3UCHAR         ProtDisc;       /* Protocol Discriminator               */
     L3UCHAR         MesType;        /* Message type                         */
+    L3UCHAR         Tei;            /* TEI                                  */
     L3UCHAR         CRVFlag;        /* Call reference value flag            */
     L3INT           CRV;            /* Call reference value                 */
 
diff --git a/src/ozmod/ozmod_isdn/ozmod_isdn.c b/src/ozmod/ozmod_isdn/ozmod_isdn.c
index 78792ba..88cdec8 100644
--- a/src/ozmod/ozmod_isdn/ozmod_isdn.c
+++ b/src/ozmod/ozmod_isdn/ozmod_isdn.c
@@ -299,6 +299,7 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 	zap_isdn_data_t *isdn_data = span->signal_data;
 	Q931mes_Generic *gen = (Q931mes_Generic *) msg;
 	int chan_id = 0;
+	int chan_hunt = 0;
 	zap_channel_t *zchan = NULL;
 	zap_caller_data_t *caller_data = NULL;
 
@@ -309,6 +310,11 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 			chan_id = chanid->ChanSlot;
 		else
 			chan_id = chanid->InfoChanSel;
+
+		/* "any" channel specified */
+		if(chanid->InfoChanSel == 3) {
+			chan_hunt++;
+		}
 	}
 
 	assert(span != NULL);
@@ -346,7 +352,7 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 		zchan = isdn_data->channels_remote_crv[gen->CRV];
 	}
 
-	zap_log(ZAP_LOG_DEBUG, "zchan %x source isdn_data->channels_%s_crv[%#hx]\n", zchan, gen->CRVFlag ? "local" : "remote", gen->CRV);
+	zap_log(ZAP_LOG_DEBUG, "zchan %x (%d:%d) source isdn_data->channels_%s_crv[%#hx]\n", zchan, zchan ? zchan->span_id : -1, zchan ? zchan->chan_id : -1, gen->CRVFlag ? "local" : "remote", gen->CRV);
 
 
 	if (gen->ProtDisc == 3) {
@@ -491,6 +497,8 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 				Q931ie_CallingNum *callingnum = Q931GetIEPtr(gen->CallingNum, gen->buf);
 				Q931ie_CalledNum *callednum = Q931GetIEPtr(gen->CalledNum, gen->buf);
 				int fail = 1;
+				int fail_cause = 0;
+				int overlap_dial = 0;
 				uint32_t cplen = mlen;
 
 				if(zchan && zchan == isdn_data->channels_remote_crv[gen->CRV]) {
@@ -504,8 +512,58 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 				}
 				
 				zchan = NULL;
-				if (chan_id < ZAP_MAX_CHANNELS_SPAN && chan_id <= span->chan_count) {
-					zchan = &span->channels[chan_id];
+				/*
+				 * Channel selection for incoming calls:
+				 */
+				if (ZAP_SPAN_IS_NT(span) && chan_hunt) {
+					int x;
+
+					/*
+					 * In NT-mode with channel selection "any",
+					 * try to find a free channel
+					 */
+					for (x = 1; x <= span->chan_count; x++) {
+						if (!zap_test_flag(&span->channels[x], ZAP_CHANNEL_INUSE)) {
+							zchan = &span->channels[x];
+							break;
+						}
+					}
+				}
+				else if (!ZAP_SPAN_IS_NT(span) && chan_hunt) {
+					/*
+					 * In TE-mode this ("any") is invalid
+					 */
+					fail_cause = ZAP_CAUSE_CHANNEL_UNACCEPTABLE;
+
+					zap_log(ZAP_LOG_ERROR, "Invalid channel selection in incoming call (network side didn't specify a channel)\n");
+				}
+				else {
+					/*
+					 * Otherwise simply try to select the channel we've been told
+					 *
+					 * TODO: NT mode is abled to select a different channel if the one chosen
+					 *       by the TE side is already in use
+					 */
+					if (chan_id > 0 && chan_id < ZAP_MAX_CHANNELS_SPAN && chan_id <= span->chan_count) {
+						zchan = &span->channels[chan_id];
+					}
+					else {
+						/* invalid channel id */
+						fail_cause = ZAP_CAUSE_CHANNEL_UNACCEPTABLE;
+
+						zap_log(ZAP_LOG_ERROR, "Invalid channel selection in incoming call (none selected or out of bounds)\n");
+					}
+				}
+
+				if (!callednum || !strlen(callednum->Digit)) {
+					if (ZAP_SPAN_IS_NT(span)) {
+						zap_log(ZAP_LOG_NOTICE, "No destination number found, assuming overlap dial\n");
+						overlap_dial++;
+					}
+					else {
+						zap_log(ZAP_LOG_ERROR, "No destination number found\n");
+						zchan = NULL;
+					}
 				}
 
 				if (zchan) {
@@ -552,7 +610,6 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 						gen->CRVFlag = !(gen->CRVFlag);
 						memcpy(zchan->caller_data.raw_data, msg, cplen);
 						zchan->caller_data.raw_data_len = cplen;
-						zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING);
 						fail = 0;
 					} 
 				} 
@@ -567,7 +624,7 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 					cause.Location = 1;
 					cause.Recom = 1;
 					//should we be casting here.. or do we need to translate value?
-					cause.Value = (unsigned char) ZAP_CAUSE_WRONG_CALL_STATE;
+					cause.Value = (unsigned char)((fail_cause) ? fail_cause : ZAP_CAUSE_WRONG_CALL_STATE);
 					*cause.Diag = '\0';
 					gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause);
 					Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size);
@@ -584,6 +641,7 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 					
 				} else {
 					Q931ie_ProgInd progress;
+					Q931ie_ChanID ChanID;
 
 					/*
 					 * Setup Progress indicator
@@ -594,6 +652,37 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 					progress.Location = 1;	/* private network serving the local user */
 					progress.ProgDesc = 1;	/* call is not end-to-end isdn = 1, in-band information available = 8 */
 					gen->ProgInd = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &progress);
+
+					/*
+					 * Update Channel ID IE
+					 */
+					Q931InitIEChanID(&ChanID);
+					ChanID.IntType = ZAP_SPAN_IS_BRI(zchan->span) ? 0 : 1;	/* PRI = 1, BRI = 0 */
+					ChanID.PrefExcl = ZAP_SPAN_IS_NT(zchan->span) ? 1 : 0;  /* Exclusive in NT-mode = 1, Preferred otherwise = 0 */
+					if(ChanID.IntType) {
+						ChanID.InfoChanSel = 1;		/* None = 0, See Slot = 1, Any = 3 */
+						ChanID.ChanMapType = 3;		/* B-Chan */
+						ChanID.ChanSlot = (unsigned char)zchan->chan_id;
+					} else {
+						ChanID.InfoChanSel = (unsigned char)zchan->chan_id & 0x03;	/* None = 0, B1 = 1, B2 = 2, Any = 3 */
+					}
+					gen->ChanID = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &ChanID);
+
+					if (overlap_dial) {
+						/*
+						 * Send SETUP ACK
+						 */
+						gen->MesType = Q931mes_SETUP_ACKNOWLEDGE;
+						gen->CRVFlag = 1;	/* inbound call */
+						Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size);
+
+						zap_set_flag(zchan, ZAP_CHANNEL_OVERLAP_DIAL);
+					} else {
+						/*
+						 * Advance to RING state
+						 */
+						zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING);
+					}
 				}
 			}
 			break;
@@ -609,6 +698,49 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 			}
 			break;
 
+		case Q931mes_INFORMATION:
+			{
+				if (zchan) {
+					zap_log(ZAP_LOG_CRIT, "Received INFORMATION message for channel %d\n", zchan->chan_id);
+
+					if (!zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND) && zap_test_flag(zchan, ZAP_CHANNEL_OVERLAP_DIAL)) {
+						char digit = '\0';
+
+						/*
+						 * overlap dial digit indication
+						 */
+						if (Q931IsIEPresent(gen->CalledNum)) {
+							Q931ie_CalledNum *callednum = Q931GetIEPtr(gen->CalledNum, gen->buf);
+							int pos;
+
+							digit = callednum->Digit[strlen(callednum->Digit) - 1];
+							if (digit == '#') {
+								callednum->Digit[strlen(callednum->Digit) - 1] = '\0';
+							}
+
+							/* TODO: make this more safe with strncat() */
+							pos = strlen(zchan->caller_data.cid_num.digits);
+							strcat(&zchan->caller_data.cid_num.digits[pos], callednum->Digit);
+							strcat(&zchan->caller_data.cid_name[pos],       callednum->Digit);
+							strcat(&zchan->caller_data.ani.digits[pos],     callednum->Digit);
+							strcat(&zchan->caller_data.dnis.digits[pos],    callednum->Digit);
+
+							zap_log(ZAP_LOG_DEBUG, "Received new overlap digit (%s), destination number: %s\n", callednum->Digit, zchan->caller_data.cid_num.digits);
+						}
+
+						if (Q931IsIEPresent(gen->SendComplete) || digit == '#') {
+							zap_log(ZAP_LOG_DEBUG, "Leaving overlap dial mode\n");
+
+							zap_clear_flag(zchan, ZAP_CHANNEL_OVERLAP_DIAL);
+							zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING);
+						}
+					}
+				} else {
+					zap_log(ZAP_LOG_CRIT, "Received INFORMATION message with no matching channel\n");
+				}
+			}
+			break;
+
 		default:
 			zap_log(ZAP_LOG_CRIT, "Received unhandled message %d (%#x)\n", (int)gen->MesType, (int)gen->MesType);
 			break;
@@ -696,6 +828,26 @@ static __inline__ void state_advance(zap_channel_t *zchan)
 				gen->MesType = Q931mes_CALL_PROCEEDING;
 				gen->CRVFlag = 1;	/* inbound */
 
+				if (ZAP_SPAN_IS_NT(zchan->span)) {
+					Q931ie_ChanID ChanID;
+
+					/*
+					 * Set new Channel ID
+					 */
+					Q931InitIEChanID(&ChanID);
+					ChanID.IntType = ZAP_SPAN_IS_BRI(zchan->span) ? 0 : 1;		/* PRI = 1, BRI = 0 */
+					ChanID.PrefExcl = 1;	/* always exclusive in NT-mode */
+
+					if(ChanID.IntType) {
+						ChanID.InfoChanSel = 1;		/* None = 0, See Slot = 1, Any = 3 */
+						ChanID.ChanMapType = 3; 	/* B-Chan */
+						ChanID.ChanSlot = (unsigned char)zchan->chan_id;
+					} else {
+						ChanID.InfoChanSel = (unsigned char)zchan->chan_id & 0x03;	/* None = 0, B1 = 1, B2 = 2, Any = 3 */
+					}
+					gen->ChanID = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &ChanID);
+				}
+
 				Q931Rx43(&isdn_data->q931, (void *)gen, gen->Size);
 			}
 		}
