我有一个带 Digium T1 卡的 Asterisk 1.8 电话交换机。它通过我们目前的电话提供商使用 5ESS PRI 运行,没有问题。但是,我们正在考虑切换到时代华纳的光纤服务(不是 TWTelecom),然后它因 ISDN 协议错误而失败。
他们的服务本质上是 VOIP,尽管我知道它与 Asterisk 配合得很好,但他们不会让你直接接触它 - 我试过了。相反,他们使用 Cisco 2430 路由器来公开它,并且唯一支持的选项是给你某种 T1 接口。那么,PRI 是最明智的选择。一旦我们将插头从现有电话提供商的 T1 分界点转移到 Cisco 路由器,就不会有任何电话接通 - 无论是出站还是入站。
启用密集 pri 调试后,很明显 libpri 发出的第一个数据包会出问题 - 无论是传入还是传出呼叫。以下是传入呼叫的示例 - 前三个数据包。Cisco 路由器对 libpri 发出的某些内容感到厌烦。问题是:是什么问题,以及如何解决它。
思科路由器运行固件c2430-ik9o3s-mz.124-15.T9.bin
——这显然是 TWC 的企业标准,他们无法更改它。
< TEI: 0 State 7(Multi-frame established)
< V(A)=2, V(S)=2, V(R)=2
< K=7, RC=0, l3_initiated=0, reject_except=0, ack_pend=0
< T200_id=0, N200=3, T203_id=8192
< [ 02 01 04 04 08 02 00 91 05 .... ]
< 59 bytes of data
< Protocol Discriminator: Q.931 (8) len=59
< TEI=0 Call Ref: len= 2 (reference 145/0x91) (Sent from originator)
< Message Type: SETUP (5)
< [04 03 80 90 a2]
< Bearer Capability (len= 5) [ Ext: 1 Coding-Std: 0 Info transfer capability: Speech (0)
< Ext: 1 Trans mode/rate: 64kbps, circuit-mode (16)
< User information layer 1: u-Law (34)
< [18 03 a9 83 81]
< Channel ID (len= 5) [ Ext: 1 IntID: Implicit Other(PRI) Spare: 0 Exclusive Dchan: 0
< ChanSel: As indicated in following octets
< Ext: 1 Coding: 0 Number Specified Channel Type: 3
< Ext: 1 Channel: 1 Type: CPE]
< [28 0f ...]
< Display (len=15) [ ... ]
< [6c 0c 21 80 ...]
< Calling Party Number (len=14) [ Ext: 0 TON: National Number (2) NPI: ISDN/Telephony Numbering Plan (E.164/E.163) (1)
< Presentation: Presentation allowed, User-provided, not screened (0) '...' ]
< [70 0b a1 ...]
< Called Party Number (len=13) [ Ext: 1 TON: National Number (2) NPI: ISDN/Telephony Numbering Plan (E.164/E.163) (1) '...' ]
> DL-DATA request
> Protocol Discriminator: Q.931 (8) len=11
> TEI=0 Call Ref: len= 2 (reference 145/0x91) (Sent to originator)
> Message Type: CALL PROCEEDING (2)
TEI=0 Transmitting N(S)=2, window is open V(A)=2 K=7
> TEI: 0 State 7(Multi-frame established)
> V(A)=2, V(S)=2, V(R)=3
> K=7, RC=0, l3_initiated=0, reject_except=0, ack_pend=0
> T200_id=0, N200=3, T203_id=8192
> [ 00 01 04 06 08 02 80 91 02 18 04 e9 81 83 81 ]
> Informational frame:
> SAPI: 00 C/R: 0 EA: 0
> TEI: 000 EA: 1
> N(S): 002 0: 0
> N(R): 003 P: 0
> 11 bytes of data
> Protocol Discriminator: Q.931 (8) len=11
> TEI=0 Call Ref: len= 2 (reference 145/0x91) (Sent to originator)
> Message Type: CALL PROCEEDING (2)
> [18 04 e9 81 83 81]
> Channel ID (len= 6) [ Ext: 1 IntID: Explicit Other(PRI) Spare: 0 Exclusive Dchan: 0
> ChanSel: As indicated in following octets
> Ext: 1 DS1 Identifier: 1
> Ext: 1 Coding: 0 Number Specified Channel Type: 3
> Ext: 1 Channel: 1 Type: CPE]
< TEI: 0 State 7(Multi-frame established)
< V(A)=3, V(S)=4, V(R)=3
< K=7, RC=0, l3_initiated=0, reject_except=0, ack_pend=0
< T200_id=8192, N200=3, T203_id=0
< [ 02 01 06 06 08 02 00 91 7d 08 03 80 e4 18 14 01 01 ]
< Informational frame:
< SAPI: 00 C/R: 1 EA: 0
< TEI: 000 EA: 1
< N(S): 003 0: 0
< N(R): 003 P: 0
< 13 bytes of data
< Protocol Discriminator: Q.931 (8) len=13
< TEI=0 Call Ref: len= 2 (reference 145/0x91) (Sent from originator)
< Message Type: STATUS (125)
< [08 03 80 e4 18]
< Cause (len= 5) [ Ext: 1 Coding: CCITT (ITU) standard (0) Spare: 0 Location: User (0)
< Ext: 1 Cause: Invalid information element contents (100), class = Protocol Error (e.g. unknown message) (6) ]
< Cause data 1: 18 (24)
< [14 01 01]
< Call State (len= 3) [ Ext: 0 Coding: CCITT (ITU) standard (0) Call state: Call Initiated (1)
答案1
因為數據?因為數據!
libpri 在指示原因信息元素 (IE) 中的原因数据的含义方面不是很聪明 - 事实上,截至 1.4.13,它只能处理给出的一百种情况中的两种情况Q.850!值得庆幸的是,它不仅仅是一些随机的专有诊断数据。
参照Q.850 原因和地点的使用...,表 1,我们需要检查原因 100 存在哪些诊断信息元素内容无效。瞧,这就是信息元素标识符!因此,libpri 发出的 Call Proceeding 消息中的 IE 0x18 (24) 存在问题。碰巧的是,IE 0x18 是 Channel ID 元素。因此,至少我们知道问题出在那个特定元素上。作为参考,以下是我们从 Cisco 收到的 Cause IE:
< [08 03 80 e4 18]
< Cause (len= 5) [ Ext: 1 Coding: CCITT (ITU) standard (0) Spare: 0 Location: User (0)
< Ext: 1 Cause: Invalid information element contents (100), class = Protocol Error (e.g. unknown message) (6) ]
< Cause data 1: 18 (24)
渠道识别 IE——是否识别
现在我们已经将范围缩小到 IE,指的是Q.931, 4.5.13 信道识别[IE],我们注意到,如果像这里的情况一样,用户设备只想使用网络明确请求的唯一信道(这里:思科路由器),则整个元素在响应呼叫建立时是可选的。
唉,libpri 的内部 API 用于发送调用进程消息,q931_call_proceeding
唉,libpri 的内部 API用于q931.c,实际上并不容易不发送完整的通道 ID IE。事实上,libpristruct q931_call
不会保留最近收到的明确通道 ID,因此无法决定发送通道 ID IE 是否合适。哎呀,这是一个包含错误call_proceeding_ies[]
——Q931_CHANNEL_IDENT
呼叫处理消息并不总是需要这个 IE。
因此,一个解决方法就是不要发送频道 ID。
但什么是存在什么问题?
唉,我们可能需要尝试深入挖掘,并检查频道 ID IE 中的哪些内容确实扰乱了思科的固件。
让我们比较一下从 Cisco 收到的频道 ID IE 和回复的频道 ID IE:
< [18 03 a9 83 81]
< Channel ID (len= 5) [ Ext: 1 IntID: Implicit Other(PRI) Spare: 0 Exclusive Dchan: 0
< ChanSel: As indicated in following octets
< Ext: 1 Coding: 0 Number Specified Channel Type: 3
< Ext: 1 Channel: 1 Type: CPE]
> [18 04 e9 81 83 81]
> Channel ID (len= 6) [ Ext: 1 IntID: Explicit Other(PRI) Spare: 0 Exclusive Dchan: 0
> ChanSel: As indicated in following octets
> Ext: 1 DS1 Identifier: 1
> Ext: 1 Coding: 0 Number Specified Channel Type: 3
> Ext: 1 Channel: 1 Type: CPE]
区别相当明显:libpri 使用完全免费的 DS1 标识符八位字节进行回复。DS1 标识符是特定 PRI 跨度的标识符,用于使用多个链路的系统。这里根本不需要这个,因为 libpri 和 Cisco 路由器之间只有一个 T1 跨度。
这似乎是 Cisco 固件的一个错误——没有理由不接受 DS1 标识符——它是可选的,但标准允许。除非 DS1 标识符有误——我还没有调查过。
让 libpri 发挥作用所需的 hack 是 中的一行代码transmit_channel_id
。我们需要做的就是抑制 DS1 标识符八位字节 3.1 的传输。此补丁可以做到这一点:
--- libpri-1.4.14/q931.c.org 2013-04-16 15:22:24.910001979 -0400
+++ libpri-1.4.14/q931.c 2013-04-16 15:22:49.454001959 -0400
@@ -1441,7 +1441,7 @@
return 0;
}
- if (!ctrl->bri && (((ctrl->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit)) {
+ if (0 && !ctrl->bri && (((ctrl->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit)) {
/* We are specifying the interface. Octet 3.1 */
ie->data[pos++] |= 0x40;
ie->data[pos++] = 0x80 | call->ds1no;
需要补充的是,这绝不是一个旨在纳入 libpri 的永久修复,而只是一个临时的破解,需要对 libpri 进行一些更广泛的调整才能正确修复。