📄 l3dss1.c
字号:
struct sk_buff *skb = arg; int ret; ret = check_infoelements(pc, skb, ie_ALERTING); if (ERR_IE_COMPREHENSION == ret) { l3dss1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); /* T304 */ newl3state(pc, 4); if (ret) l3dss1_std_ie_err(pc, ret); L3L4(pc->st, CC_ALERTING | INDICATION, pc);}static voidl3dss1_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; l3dss1_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; l3dss1_msg_without_setup(pc, pr, NULL); return; } /* * Channel Identification */ if ((id = l3dss1_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; l3dss1_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; l3dss1_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; 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"); } newl3state(pc, 6); if (err) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, err); L3L4(pc->st, CC_SETUP | INDICATION, pc);}static voidl3dss1_reset(struct l3_process *pc, u_char pr, void *arg){ dss1_release_l3_process(pc);}static voidl3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb; u_char tmp[16+40]; u_char *p = tmp; int l; u_char cause = 16; if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; StopAllL3Timer(pc); MsgHead(p, pc->callref, MT_DISCONNECT); *p++ = IE_CAUSE; *p++ = 0x2; *p++ = 0x80; *p++ = cause | 0x80; if (pc->prot.dss1.uus1_data[0]) { *p++ = IE_USER_USER; /* UUS info element */ *p++ = strlen(pc->prot.dss1.uus1_data) + 1; *p++ = 0x04; /* IA5 chars */ strcpy(p,pc->prot.dss1.uus1_data); p += strlen(pc->prot.dss1.uus1_data); pc->prot.dss1.uus1_data[0] = '\0'; } 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_setup_rsp(struct l3_process *pc, u_char pr, void *arg){ if (!pc->para.bchannel) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "D-chan connect for waiting call"); l3dss1_disconnect_req(pc, pr, arg); return; } 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; int ret; ret = check_infoelements(pc, skb, ie_CONNECT_ACKNOWLEDGE); if (ERR_IE_COMPREHENSION == ret) { l3dss1_std_ie_err(pc, ret); return; } newl3state(pc, 10); L3DelTimer(&pc->timer); if (ret) l3dss1_std_ie_err(pc, ret); L3L4(pc->st, CC_SETUP_COMPL | INDICATION, pc);}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 = 21; if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; MsgHead(p, pc->callref, MT_RELEASE_COMPLETE); *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); l3_msg(pc->st, DL_DATA | REQUEST, skb); L3L4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc);}static voidl3dss1_release(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; u_char *p; int ret, cause=0; StopAllL3Timer(pc); if ((ret = l3dss1_get_cause(pc, skb))>0) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "REL get_cause ret(%d)", ret); } else if (ret<0) pc->para.cause = NO_CAUSE; if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) { l3dss1_parse_facility(pc->st, pc, pc->callref, p); } if ((ret<0) && (pc->state != 11)) cause = 96; else if (ret>0) cause = 100; ret = check_infoelements(pc, skb, ie_RELEASE); if (ERR_IE_COMPREHENSION == ret) cause = 96; else if ((ERR_IE_UNRECOGNIZED == ret) && (!cause)) cause = 99; if (cause) l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause); else l3dss1_message(pc, MT_RELEASE_COMPLETE); L3L4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc);}static voidl3dss1_alert_req(struct l3_process *pc, u_char pr, void *arg){ newl3state(pc, 7); if (!pc->prot.dss1.uus1_data[0]) l3dss1_message(pc, MT_ALERTING); else l3dss1_msg_with_uus(pc, MT_ALERTING); }static voidl3dss1_proceed_req(struct l3_process *pc, u_char pr, void *arg){ newl3state(pc, 9); l3dss1_message(pc, MT_CALL_PROCEEDING); L3L4(pc->st, CC_PROCEED_SEND | INDICATION, pc); }static voidl3dss1_setup_ack_req(struct l3_process *pc, u_char pr, void *arg){ newl3state(pc, 25); L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T302, CC_T302); l3dss1_message(pc, MT_SETUP_ACKNOWLEDGE);}/********************************************//* deliver a incoming display message to HL *//********************************************/static voidl3dss1_deliver_display(struct l3_process *pc, int pr, u_char *infp){ u_char len; isdn_ctrl ic; struct IsdnCardState *cs; char *p; if (*infp++ != IE_DISPLAY) return; if ((len = *infp++) > 80) return; /* total length <= 82 */ if (!pc->chan) return; p = ic.parm.display; while (len--) *p++ = *infp++; *p = '\0'; ic.command = ISDN_STAT_DISPLAY; cs = pc->st->l1.hardware; ic.driver = cs->myid; ic.arg = pc->chan->chan; cs->iif.statcallb(&ic);} /* l3dss1_deliver_display */static voidl3dss1_progress(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int err = 0; u_char *p; if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) { if (p[1] != 2) { err = 1; pc->para.cause = 100; } else if (!(p[2] & 0x70)) { switch (p[2]) { case 0x80: case 0x81: case 0x82: case 0x84: case 0x85: case 0x87: case 0x8a: switch (p[3]) { case 0x81: case 0x82: case 0x83: case 0x84: case 0x88: break; default: err = 2; pc->para.cause = 100; break; } break; default: err = 3; pc->para.cause = 100; break; } } } else { pc->para.cause = 96; err = 4; } if (err) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "progress error %d", err); l3dss1_status_send(pc, pr, NULL); return; } /* Now we are on none mandatory IEs */ err = check_infoelements(pc, skb, ie_PROGRESS); if (err) l3dss1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) L3L4(pc->st, CC_PROGRESS | INDICATION, pc);}static voidl3dss1_notify(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int err = 0; u_char *p; if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) { if (p[1] != 1) { err = 1; pc->para.cause = 100; } else { switch (p[2]) { case 0x80: case 0x81: case 0x82: break; default: pc->para.cause = 100; err = 2; break; } } } else { pc->para.cause = 96; err = 3; } if (err) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "notify error %d", err); l3dss1_status_send(pc, pr, NULL); return; } /* Now we are on none mandatory IEs */ err = check_infoelements(pc, skb, ie_NOTIFY); if (err) l3dss1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) L3L4(pc->st, CC_NOTIFY | INDICATION, pc);}static voidl3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg){ int ret; struct sk_buff *skb = arg; ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY); l3dss1_std_ie_err(pc, ret); pc->para.cause = 30; /* response to STATUS_ENQUIRY */ l3dss1_status_send(pc, pr, NULL);}static voidl3dss1_information(struct l3_process *pc, u_char pr, void *arg){ int ret; struct sk_buff *skb = arg; u_char *p; char tmp[32]; ret = check_infoelements(pc, skb, ie_INFORMATION); if (ret) l3dss1_std_ie_err(pc, ret); if (pc->state == 25) { /* overlap receiving */ L3DelTimer(&pc->timer); p = skb->data; if ((p = findie(p, skb->len, 0x70, 0))) { iecpy(tmp, p, 1); strcat(pc->para.setup.eazmsn, tmp); L3L4(pc->st, CC_MORE_INFO | INDICATION, pc); } L3AddTimer(&pc->timer, T302, CC_T302); }}/******************************//* handle deflection requests *//******************************/static void l3dss1_redir_req(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb; u_char tmp[128]; u_char *p = tmp; u_char *subp; u_char len_phone = 0; u_char len_sub = 0; int l;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -