📄 l3ni1.c
字号:
case 88: // 1200/75 bit/s si2 += 1; break; case 87: // 75/1200 bit/s si2 += 2; break; case 67: // 2400 bit/s si2 += 3; break; case 69: // 4800 bit/s si2 += 4; break; case 72: // 9600 bit/s si2 += 5; break; case 73: // 14400 bit/s si2 += 6; break; case 75: // 19200 bit/s si2 += 7; break; } info = p[7] & 0x7f; if ((info & 16) && (!(info & 8))) // 7 data bits si2 += 32; // else 8 data bits if ((info & 96) == 96) // 2 stop bits si2 += 16; // else 1 stop bit if ((info & 2) && (!(info & 1))) // even parity si2 += 8; // else no parity return si2;}static u_charDecodeSyncParams(u_char si2, u_char info){ info &= 0x7f; switch (info) { case 40: // bit/s negotiation failed ai := 165 not 175! return si2 + 15; case 15: // 56000 bit/s failed, ai := 0 not 169 ! return si2 + 9; case 14: // 48000 bit/s return si2 + 8; case 11: // 19200 bit/s return si2 + 7; case 9: // 14400 bit/s return si2 + 6; case 8: // 9600 bit/s return si2 + 5; case 5: // 4800 bit/s return si2 + 4; case 3: // 2400 bit/s return si2 + 3; case 23: // 75/1200 bit/s return si2 + 2; case 24: // 1200/75 bit/s return si2 + 1; default: // 1200 bit/s return si2; }}static u_charDecodeSI2(struct sk_buff *skb){ u_char *p; //, *pend=skb->data + skb->len; if ((p = findie(skb->data, skb->len, 0x7c, 0))) { switch (p[4] & 0x0f) { case 0x01: if (p[1] == 0x04) // sync. Bitratenadaption return DecodeSyncParams(160, p[5]); // V.110/X.30 else if (p[1] == 0x06) // async. Bitratenadaption return DecodeASyncParams(192, p); // V.110/X.30 break; case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption if (p[1] > 3) return DecodeSyncParams(176, p[5]); // V.120 break; } } return 0;}#endifstatic voidl3ni1_setup_req(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb; u_char tmp[128]; u_char *p = tmp; u_char *teln; u_char *sub; u_char *sp; int l; MsgHead(p, pc->callref, MT_SETUP); teln = pc->para.setup.phone; *p++ = 0xa1; /* complete indicator */ /* * Set Bearer Capability, Map info from 1TR6-convention to NI1 */ switch (pc->para.setup.si1) { case 1: /* Telephony */ *p++ = IE_BEARER; *p++ = 0x3; /* Length */ *p++ = 0x90; /* 3.1khz Audio */ *p++ = 0x90; /* Circuit-Mode 64kbps */ *p++ = 0xa2; /* u-Law Audio */ break; case 5: /* Datatransmission 64k, BTX */ case 7: /* Datatransmission 64k */ default: *p++ = IE_BEARER; *p++ = 0x2; /* Length */ *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */ *p++ = 0x90; /* Circuit-Mode 64kbps */ break; } sub = NULL; sp = teln; while (*sp) { if ('.' == *sp) { sub = sp; *sp = 0; } else sp++; } *p++ = IE_KEYPAD; *p++ = strlen(teln); while (*teln) *p++ = (*teln++) & 0x7F; if (sub) *sub++ = '.'; #if EXT_BEARER_CAPS if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30 *p++ = IE_LLC; *p++ = 0x04; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21; *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80); } else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) { // sync. Bitratenadaption, V.120 *p++ = IE_LLC; *p++ = 0x05; *p++ = 0x88; *p++ = 0x90; *p++ = 0x28; *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0); *p++ = 0x82; } else if (pc->para.setup.si2 >= 192) { // async. Bitratenadaption, V.110/X.30 *p++ = IE_LLC; *p++ = 0x06; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21; p = EncodeASyncParams(p, pc->para.setup.si2 - 192); } else { switch (pc->para.setup.si1) { case 1: /* Telephony */ *p++ = IE_LLC; *p++ = 0x3; /* Length */ *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */ *p++ = 0x90; /* Circuit-Mode 64kbps */ *p++ = 0xa2; /* u-Law Audio */ break; case 5: /* Datatransmission 64k, BTX */ case 7: /* Datatransmission 64k */ default: *p++ = IE_LLC; *p++ = 0x2; /* Length */ *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */ *p++ = 0x90; /* Circuit-Mode 64kbps */ break; } }#endif l = p - tmp; if (!(skb = l3_alloc_skb(l))){ return;} memcpy(skb_put(skb, l), tmp, l); L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T303, CC_T303); newl3state(pc, 1); l3_msg(pc->st, DL_DATA | REQUEST, skb);}static voidl3ni1_call_proc(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int id, ret; if ((id = l3ni1_get_channel_id(pc, skb)) >= 0) { if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup answer with wrong chid %x", id); pc->para.cause = 100; l3ni1_status_send(pc, pr, NULL); return; } pc->para.bchannel = id; } else if (1 == pc->state) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup answer wrong chid (ret %d)", id); if (id == -1) pc->para.cause = 96; else pc->para.cause = 100; l3ni1_status_send(pc, pr, NULL); return; } /* Now we are on none mandatory IEs */ ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING); if (ERR_IE_COMPREHENSION == ret) { l3ni1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); newl3state(pc, 3); L3AddTimer(&pc->timer, T310, CC_T310); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);}static voidl3ni1_setup_ack(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int id, ret; if ((id = l3ni1_get_channel_id(pc, skb)) >= 0) { if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup answer with wrong chid %x", id); pc->para.cause = 100; l3ni1_status_send(pc, pr, NULL); return; } pc->para.bchannel = id; } else { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup answer wrong chid (ret %d)", id); if (id == -1) pc->para.cause = 96; else pc->para.cause = 100; l3ni1_status_send(pc, pr, NULL); return; } /* Now we are on none mandatory IEs */ ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE); if (ERR_IE_COMPREHENSION == ret) { l3ni1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); newl3state(pc, 2); L3AddTimer(&pc->timer, T304, CC_T304); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);}static voidl3ni1_disconnect(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; u_char *p; int ret; u_char cause = 0; StopAllL3Timer(pc); if ((ret = l3ni1_get_cause(pc, skb))) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "DISC get_cause ret(%d)", ret); if (ret < 0) cause = 96; else if (ret > 0) cause = 100; } if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) l3ni1_parse_facility(pc->st, pc, pc->callref, p); ret = check_infoelements(pc, skb, ie_DISCONNECT); if (ERR_IE_COMPREHENSION == ret) cause = 96; else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret)) cause = 99; ret = pc->state; newl3state(pc, 12); if (cause) newl3state(pc, 19); if (11 != ret) pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); else if (!cause) l3ni1_release_req(pc, pr, NULL); if (cause) { l3ni1_message_cause(pc, MT_RELEASE, cause); L3AddTimer(&pc->timer, T308, CC_T308_1); }}static voidl3ni1_connect(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int ret; ret = check_infoelements(pc, skb, ie_CONNECT); if (ERR_IE_COMPREHENSION == ret) { l3ni1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); /* T310 */ newl3state(pc, 10); pc->para.chargeinfo = 0; /* here should inserted COLP handling KKe */ if (ret) l3ni1_std_ie_err(pc, ret); pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);}static voidl3ni1_alerting(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int ret; ret = check_infoelements(pc, skb, ie_ALERTING); if (ERR_IE_COMPREHENSION == ret) { l3ni1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); /* T304 */ newl3state(pc, 4); if (ret) l3ni1_std_ie_err(pc, ret); pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);}static voidl3ni1_setup(struct l3_process *pc, u_char pr, void *arg){ u_char *p; int bcfound = 0; char tmp[80]; struct sk_buff *skb = arg; int id; int err = 0; /* * Bearer Capabilities */ p = skb->data; /* only the first occurence 'll be detected ! */ if ((p = findie(p, skb->len, 0x04, 0))) { if ((p[1] < 2) || (p[1] > 11)) err = 1; else { pc->para.setup.si2 = 0; switch (p[2] & 0x7f) { case 0x00: /* Speech */ case 0x10: /* 3.1 Khz audio */ pc->para.setup.si1 = 1; break; case 0x08: /* Unrestricted digital information */ pc->para.setup.si1 = 7;/* JIM, 05.11.97 I wanna set service indicator 2 */#if EXT_BEARER_CAPS pc->para.setup.si2 = DecodeSI2(skb);#endif break; case 0x09: /* Restricted digital information */ pc->para.setup.si1 = 2; break; case 0x11: /* Unrestr. digital information with * tones/announcements ( or 7 kHz audio */ pc->para.setup.si1 = 3; break; case 0x18: /* Video */ pc->para.setup.si1 = 4; break; default: err = 2; break; } switch (p[3] & 0x7f) { case 0x40: /* packed mode */ pc->para.setup.si1 = 8; break; case 0x10: /* 64 kbit */ case 0x11: /* 2*64 kbit */ case 0x13: /* 384 kbit */ case 0x15: /* 1536 kbit */ case 0x17: /* 1920 kbit */ pc->para.moderate = p[3] & 0x7f; break; default: err = 3; break; } } if (pc->debug & L3_DEB_SI) l3_debug(pc->st, "SI=%d, AI=%d", pc->para.setup.si1, pc->para.setup.si2); if (err) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup with wrong bearer(l=%d:%x,%x)", p[1], p[2], p[3]); pc->para.cause = 100; l3ni1_msg_without_setup(pc, pr, NULL); return; } } else { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup without bearer capabilities"); /* ETS 300-104 1.3.3 */ pc->para.cause = 96; l3ni1_msg_without_setup(pc, pr, NULL); return; } /* * Channel Identification */ if ((id = l3ni1_get_channel_id(pc, skb)) >= 0) { if ((pc->para.bchannel = id)) { if ((3 == id) && (0x10 == pc->para.moderate)) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup with wrong chid %x", id); pc->para.cause = 100; l3ni1_msg_without_setup(pc, pr, NULL); return; } bcfound++; } else { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup without bchannel, call waiting"); bcfound++; } } else { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup with wrong chid ret %d", id); if (id == -1) pc->para.cause = 96; else pc->para.cause = 100; l3ni1_msg_without_setup(pc, pr, NULL); return; } /* Now we are on none mandatory IEs */ err = check_infoelements(pc, skb, ie_SETUP); if (ERR_IE_COMPREHENSION == err) { pc->para.cause = 96; l3ni1_msg_without_setup(pc, pr, NULL); return; } p = skb->data; if ((p = findie(p, skb->len, 0x70, 0))) iecpy(pc->para.setup.eazmsn, p, 1); else pc->para.setup.eazmsn[0] = 0; p = skb->data; if ((p = findie(p, skb->len, 0x71, 0))) { /* Called party subaddress */ if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) { tmp[0] = '.'; iecpy(&tmp[1], p, 2); strcat(pc->para.setup.eazmsn, tmp); } else if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "wrong called subaddress"); } p = skb->data; if ((p = findie(p, skb->len, 0x6c, 0))) { pc->para.setup.plan = p[2]; if (p[2] & 0x80) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -