📄 l3dss1.c
字号:
teln++; } } if (channel) { *p++ = IE_CHANNEL_ID; *p++ = 1; *p++ = channel; } msn = pc->para.setup.eazmsn; sub = NULL; sp = msn; while (*sp) { if ('.' == *sp) { sub = sp; *sp = 0; } else sp++; } if (*msn) { *p++ = 0x6c; *p++ = strlen(msn) + (screen ? 2 : 1); /* Classify as AnyPref. */ if (screen) { *p++ = 0x01; /* Ext = '0'B, Type = '000'B, Plan = '0001'B. */ *p++ = screen; } else *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */ while (*msn) *p++ = *msn++ & 0x7f; } if (sub) { *sub++ = '.'; *p++ = 0x6d; /* Calling party subaddress */ *p++ = strlen(sub) + 2; *p++ = 0x80; /* NSAP coded */ *p++ = 0x50; /* local IDI format */ while (*sub) *p++ = *sub++ & 0x7f; } sub = NULL; sp = teln; while (*sp) { if ('.' == *sp) { sub = sp; *sp = 0; } else sp++; } *p++ = 0x70; *p++ = strlen(teln) + 1; /* Classify as AnyPref. */ *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */ while (*teln) *p++ = *teln++ & 0x7f; if (sub) { *sub++ = '.'; *p++ = 0x71; /* Called party subaddress */ *p++ = strlen(sub) + 2; *p++ = 0x80; /* NSAP coded */ *p++ = 0x50; /* local IDI format */ while (*sub) *p++ = *sub++ & 0x7f; }#if EXT_BEARER_CAPS if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30 *p++ = 0x7c; *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++ = 0x7c; *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++ = 0x7c; *p++ = 0x06; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21; p = EncodeASyncParams(p, pc->para.setup.si2 - 192);#if HISAX_SEND_STD_LLC_IE } else { *p++ = 0x7c; *p++ = 0x02; *p++ = 0x88; *p++ = 0x90;#endif }#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 voidl3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg){ u_char *p; struct sk_buff *skb = arg; L3DelTimer(&pc->timer); p = skb->data; if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { pc->para.bchannel = p[2] & 0x3; if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN)) l3_debug(pc->st, "setup answer without bchannel"); } else if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup answer without bchannel"); dev_kfree_skb(skb, FREE_READ); newl3state(pc, 3); L3AddTimer(&pc->timer, T310, CC_T310); pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);}static voidl3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg){ u_char *p; struct sk_buff *skb = arg; L3DelTimer(&pc->timer); p = skb->data; if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { pc->para.bchannel = p[2] & 0x3; if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN)) l3_debug(pc->st, "setup answer without bchannel"); } else if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup answer without bchannel"); dev_kfree_skb(skb, FREE_READ); newl3state(pc, 2); L3AddTimer(&pc->timer, T304, CC_T304); pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);}static voidl3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg){ u_char *p; struct sk_buff *skb = arg; int cause = -1; StopAllL3Timer(pc); p = skb->data; pc->para.loc = 0; if ((p = findie(p, skb->len, IE_CAUSE, 0))) { p++; if (*p++ == 2) pc->para.loc = *p++; cause = *p & 0x7f; } dev_kfree_skb(skb, FREE_READ); newl3state(pc, 12); pc->para.cause = cause; pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);}static voidl3dss1_connect(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; dev_kfree_skb(skb, FREE_READ); L3DelTimer(&pc->timer); /* T310 */ newl3state(pc, 10); pc->para.chargeinfo = 0; pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);}static voidl3dss1_alerting(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; dev_kfree_skb(skb, FREE_READ); L3DelTimer(&pc->timer); /* T304 */ newl3state(pc, 4); pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);}static voidl3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg){ /* This routine is called if here was no SETUP made (checks in dss1up and in * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code * MT_STATUS_ENQUIRE in the NULL state is handled too */ u_char tmp[16]; u_char *p = tmp; int l; struct sk_buff *skb; switch (pc->para.cause) { case 81: /* 0x51 invalid callreference */ case 88: /* 0x58 incomp destination */ case 96: /* 0x60 mandory IE missing */ case 101: /* 0x65 incompatible Callstate */ MsgHead(p, pc->callref, MT_RELEASE_COMPLETE); *p++ = IE_CAUSE; *p++ = 0x2; *p++ = 0x80; *p++ = pc->para.cause | 0x80; break; default: printk(KERN_ERR "HiSax internal error l3dss1_msg_without_setup\n"); return; } l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); l3_msg(pc->st, DL_DATA | REQUEST, skb); release_l3_process(pc);}static voidl3dss1_setup(struct l3_process *pc, u_char pr, void *arg){ u_char *p, *ptmp[8]; int i; int bcfound = 0; char tmp[80]; struct sk_buff *skb = arg; /* ETS 300-104 1.3.4 and 1.3.5 * we need to detect unknown inform. element from 0 to 7 */ p = skb->data; for (i = 0; i < 8; i++) ptmp[i] = skb->data; if (findie(ptmp[1], skb->len, 0x01, 0) || findie(ptmp[2], skb->len, 0x02, 0) || findie(ptmp[3], skb->len, 0x03, 0) || findie(ptmp[5], skb->len, 0x05, 0) || findie(ptmp[6], skb->len, 0x06, 0) || findie(ptmp[7], skb->len, 0x07, 0)) { /* if ie is < 8 and not 0 nor 4, send RELEASE_COMPLETE * cause 0x60 */ pc->para.cause = 0x60; dev_kfree_skb(skb, FREE_READ); l3dss1_msg_without_setup(pc, pr, NULL); return; } /* * Channel Identification */ p = skb->data; if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { pc->para.bchannel = p[2] & 0x3; if (pc->para.bchannel) bcfound++; else if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup without bchannel"); } else { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup without bchannel"); pc->para.cause = 0x60; dev_kfree_skb(skb, FREE_READ); l3dss1_msg_without_setup(pc, pr, NULL); return; } /* * Bearer Capabilities */ p = skb->data; if ((p = findie(p, skb->len, 0x04, 0))) { pc->para.setup.si2 = 0; switch (p[2] & 0x1f) { 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); printk(KERN_DEBUG "HiSax: SI=%d, AI=%d\n", pc->para.setup.si1, pc->para.setup.si2);#endif break; case 0x09: /* Restricted digital information */ pc->para.setup.si1 = 2; break; case 0x11: /* Unrestr. digital information with tones/announcements */ pc->para.setup.si1 = 3; break; case 0x18: /* Video */ pc->para.setup.si1 = 4; break; default: pc->para.setup.si1 = 0; } } else { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup without bearer capabilities"); /* ETS 300-104 1.3.3 */ pc->para.cause = 0x60; dev_kfree_skb(skb, FREE_READ); l3dss1_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) { iecpy(pc->para.setup.phone, p, 1); pc->para.setup.screen = 0; } else { iecpy(pc->para.setup.phone, p, 2); pc->para.setup.screen = p[3]; } } else { pc->para.setup.phone[0] = 0; pc->para.setup.plan = 0; pc->para.setup.screen = 0; } p = skb->data; if ((p = findie(p, skb->len, 0x6d, 0))) { /* Calling party subaddress */ if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) { tmp[0] = '.'; iecpy(&tmp[1], p, 2); strcat(pc->para.setup.phone, tmp); } else if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "wrong calling subaddress"); } dev_kfree_skb(skb, FREE_READ); if (bcfound) { if ((pc->para.setup.si1 != 7) && (pc->debug & L3_DEB_WARN)) { l3_debug(pc->st, "non-digital call: %s -> %s", pc->para.setup.phone, pc->para.setup.eazmsn); } if ((pc->para.setup.si1 != 7) && test_bit(FLG_PTP, &pc->st->l2.flag)) { pc->para.cause = 0x58; l3dss1_msg_without_setup(pc, pr, NULL); return; } newl3state(pc, 6); pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); } else release_l3_process(pc);}static voidl3dss1_reset(struct l3_process *pc, u_char pr, void *arg){ release_l3_process(pc);}static voidl3dss1_setup_rsp(struct l3_process *pc, u_char pr, void *arg){ newl3state(pc, 8); l3dss1_message(pc, MT_CONNECT); L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T313, CC_T313);}static voidl3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; dev_kfree_skb(skb, FREE_READ); newl3state(pc, 10); L3DelTimer(&pc->timer); pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);}static voidl3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb; u_char tmp[16]; u_char *p = tmp; int l; u_char cause = 0x10; if (pc->para.cause > 0) cause = pc->para.cause; StopAllL3Timer(pc); MsgHead(p, pc->callref, MT_DISCONNECT); *p++ = IE_CAUSE; *p++ = 0x2; *p++ = 0x80; *p++ = cause | 0x80; l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); newl3state(pc, 11); l3_msg(pc->st, DL_DATA | REQUEST, skb); L3AddTimer(&pc->timer, T305, CC_T305);}static voidl3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb; u_char tmp[16]; u_char *p = tmp; int l; u_char cause = 0x95; if (pc->para.cause > 0) cause = pc->para.cause; MsgHead(p, pc->callref, MT_RELEASE_COMPLETE); *p++ = IE_CAUSE; *p++ = 0x2; *p++ = 0x80; *p++ = cause; l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); l3_msg(pc->st, DL_DATA | REQUEST, skb); pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); release_l3_process(pc);}static voidl3dss1_release(struct l3_process *pc, u_char pr, void *arg){ u_char *p; struct sk_buff *skb = arg; int cause = -1; p = skb->data; if ((p = findie(p, skb->len, IE_CAUSE, 0))) { p++; if (*p++ == 2) pc->para.loc = *p++; cause = *p & 0x7f; } p = skb->data; if ((p = findie(p, skb->len, IE_FACILITY, 0))) {#if HISAX_DE_AOC l3dss1_parse_facility(pc, p);#else p = NULL;#endif } dev_kfree_skb(skb, FREE_READ); StopAllL3Timer(pc); pc->para.cause = cause; l3dss1_message(pc, MT_RELEASE_COMPLETE); pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); release_l3_process(pc);}static voidl3dss1_alert_req(struct l3_process *pc, u_char pr, void *arg){ newl3state(pc, 7); l3dss1_message(pc, MT_ALERTING);}static voidl3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg){ u_char tmp[16]; u_char *p = tmp; int l; struct sk_buff *skb = arg; dev_kfree_skb(skb, FREE_READ); MsgHead(p, pc->callref, MT_STATUS); *p++ = IE_CAUSE; *p++ = 0x2; *p++ = 0x80; *p++ = 0x9E; /* answer status enquire */ *p++ = 0x14; /* CallState */ *p++ = 0x1; *p++ = pc->state & 0x3f; l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); l3_msg(pc->st, DL_DATA | REQUEST, skb);}static voidl3dss1_status_req(struct l3_process *pc, u_char pr, void *arg){ /* ETS 300-104 7.4.1, 8.4.1, 10.3.1, 11.4.1, 12.4.1, 13.4.1, 14.4.1... if setup has been made and a non expected message type is received, we must send MT_STATUS cause 0x62 */ u_char tmp[16]; u_char *p = tmp; int l; struct sk_buff *skb = arg; dev_kfree_skb(skb, FREE_READ); MsgHead(p, pc->callref, MT_STATUS); *p++ = IE_CAUSE; *p++ = 0x2; *p++ = 0x80; *p++ = 0x62 | 0x80; /* status sending */ *p++ = 0x14; /* CallState */ *p++ = 0x1; *p++ = pc->state & 0x3f; l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); l3_msg(pc->st, DL_DATA | REQUEST, skb);}static voidl3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg){ u_char *p; struct sk_buff *skb = arg; int callState = 0; p = skb->data; if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) { p++; if (1 == *p++) callState = *p; } if (callState == 0) { /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1 * set down layer 3 without sending any message */ pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); release_l3_process(pc); } else { pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc); }}static voidl3dss1_t303(struct l3_process *pc, u_char pr, void *arg){ if (pc->N303 > 0) { pc->N303--; L3DelTimer(&pc->timer); l3dss1_setup_req(pc, pr, arg); } else { L3DelTimer(&pc->timer); pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc); release_l3_process(pc); }}static voidl3dss1_t304(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.cause = 0xE6; l3dss1_disconnect_req(pc, pr, NULL); pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);}static voidl3dss1_t305(struct l3_process *pc, u_char pr, void *arg){ u_char tmp[16]; u_char *p = tmp; int l; struct sk_buff *skb; u_char cause = 0x90; L3DelTimer(&pc->timer); if (pc->para.cause > 0) cause = pc->para.cause | 0x80; MsgHead(p, pc->callref, MT_RELEASE); *p++ = IE_CAUSE; *p++ = 0x2; *p++ = 0x80; *p++ = cause; l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); newl3state(pc, 19); l3_msg(pc->st, DL_DATA | REQUEST, skb); L3AddTimer(&pc->timer, T308, CC_T308_1);}static voidl3dss1_t310(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.cause = 0xE6; l3dss1_disconnect_req(pc, pr, NULL); pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -