Asterisk 无法通过 T1 PRI 接口拨打或接听 Cisco 2430 路由器的电话

Asterisk 无法通过 T1 PRI 接口拨打或接听 Cisco 2430 路由器的电话

我有一个带 Digium T1 卡的 Asterisk 1.8 电话交换机。它通过我们目前的电话提供商使用 5ESS PRI 运行,没有问题。但是,我们正在考虑切换到时代华纳的光纤服务(不是 TWTelecom),然后它因 ISDN 协议错误而失败。

他们的服务本质上是 VOIP,尽管我知道它与 Asterisk 配合得很好,但他们不会让你直接接触它 - 我试过了。相反,他们使用 Cisco 2430 路由器来公开它,并且唯一支持的选项是给你某种 T​​1 接口。那么,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 进行一些更广泛的调整才能正确修复。

相关内容