📄 l3ni1.c
字号:
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 */ l3ni1_std_ie_err(pc, err); pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);}static voidl3ni1_reset(struct l3_process *pc, u_char pr, void *arg){ ni1_release_l3_process(pc);}static voidl3ni1_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.ni1.uus1_data[0]) { *p++ = IE_USER_USER; /* UUS info element */ *p++ = strlen(pc->prot.ni1.uus1_data) + 1; *p++ = 0x04; /* IA5 chars */ strcpy(p,pc->prot.ni1.uus1_data); p += strlen(pc->prot.ni1.uus1_data); pc->prot.ni1.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 voidl3ni1_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"); l3ni1_disconnect_req(pc, pr, arg); return; } newl3state(pc, 8); if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "D-chan connect for waiting call"); l3ni1_message_plus_chid(pc, MT_CONNECT); /* GE 05/09/00 */ L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T313, CC_T313);}static voidl3ni1_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) { l3ni1_std_ie_err(pc, ret); return; } newl3state(pc, 10); L3DelTimer(&pc->timer); if (ret) l3ni1_std_ie_err(pc, ret); pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);}static voidl3ni1_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); pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); ni1_release_l3_process(pc);}static voidl3ni1_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 = l3ni1_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))) { l3ni1_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) l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, cause); else l3ni1_message(pc, MT_RELEASE_COMPLETE); pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); ni1_release_l3_process(pc);}static voidl3ni1_alert_req(struct l3_process *pc, u_char pr, void *arg){ newl3state(pc, 7); if (!pc->prot.ni1.uus1_data[0]) l3ni1_message(pc, MT_ALERTING); else l3ni1_msg_with_uus(pc, MT_ALERTING); }static voidl3ni1_proceed_req(struct l3_process *pc, u_char pr, void *arg){ newl3state(pc, 9); l3ni1_message(pc, MT_CALL_PROCEEDING); pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc); }static voidl3ni1_setup_ack_req(struct l3_process *pc, u_char pr, void *arg){ newl3state(pc, 25); L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T302, CC_T302); l3ni1_message(pc, MT_SETUP_ACKNOWLEDGE);}/********************************************//* deliver a incoming display message to HL *//********************************************/static voidl3ni1_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);} /* l3ni1_deliver_display */static voidl3ni1_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); l3ni1_status_send(pc, pr, NULL); return; } /* Now we are on none mandatory IEs */ err = check_infoelements(pc, skb, ie_PROGRESS); if (err) l3ni1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc);}static voidl3ni1_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); l3ni1_status_send(pc, pr, NULL); return; } /* Now we are on none mandatory IEs */ err = check_infoelements(pc, skb, ie_NOTIFY); if (err) l3ni1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc);}static voidl3ni1_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); l3ni1_std_ie_err(pc, ret); pc->para.cause = 30; /* response to STATUS_ENQUIRY */ l3ni1_status_send(pc, pr, NULL);}static voidl3ni1_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) l3ni1_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); pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } L3AddTimer(&pc->timer, T302, CC_T302); }}/******************************//* handle deflection requests *//******************************/static void l3ni1_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; strcpy(pc->prot.ni1.uus1_data,pc->chan->setup.eazmsn); /* copy uus element if available */ if (!pc->chan->setup.phone[0]) { pc->para.cause = -1; l3ni1_disconnect_req(pc,pr,arg); /* disconnect immediately */ return; } /* only uus */ if (pc->prot.ni1.invoke_id) free_invoke_id(pc->st,pc->prot.ni1.invoke_id); if (!(pc->prot.ni1.invoke_id = new_invoke_id(pc->st))) return; MsgHead(p, pc->callref, MT_FACILITY); for (subp = pc->chan->setup.phone; (*subp) && (*subp != '.'); subp++) len_phone++; /* len of phone number */ if (*subp++ == '.') len_sub = strlen(subp) + 2; /* length including info subaddress element */ *p++ = 0x1c; /* Facility info element */ *p++ = len_phone + len_sub + 2 + 2 + 8 + 3 + 3; /* length of element */ *p++ = 0x91; /* remote operations protocol */ *p++ = 0xa1; /* invoke component */ *p++ = len_phone + len_sub + 2 + 2 + 8 + 3; /* length of data */ *p++ = 0x02; /* invoke id tag, integer */ *p++ = 0x01; /* length */ *p++ = pc->prot.ni1.invoke_id; /* invoke id */ *p++ = 0x02; /* operation value tag, integer */ *p++ = 0x01; /* length */ *p++ = 0x0D; /* Call Deflect */ *p++ = 0x30; /* sequence phone number */ *p++ = len_phone + 2 + 2 + 3 + len_sub; /* length */ *p++ = 0x30; /* Deflected to UserNumber */ *p++ = len_phone+2+len_sub; /* length */ *p++ = 0x80; /* NumberDigits */ *p++ = len_phone; /* length */ for (l = 0; l < len_phone; l++) *p++ = pc->chan->setup.phone[l]; if (len_sub) { *p++ = 0x04; /* called party subaddress */ *p++ = len_sub - 2; while (*subp) *p++ = *subp++; } *p++ = 0x01; /* screening identifier */ *p++ = 0x01; *p++ = pc->chan->setup.screen; 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);} /* l3ni1_redir_req *//********************************************//* handle deflection request in early state *//********************************************/static void l3ni1_redir_req_early(struct l3_process *pc, u_char pr, void *arg){ l3ni1_proceed_req(pc,pr,arg); l3ni1_redir_req(pc,pr,arg);} /* l3ni1_redir_req_early *//***********************************************//* handle special commands for this protocol. *//* Examples are call independant services like *//* remote operations with dummy callref. *//***********************************************/static int l3ni1_cmd_global(struct PStack *st, isdn_ctrl *ic){ u_char id; u_char temp[265]; u_char *p = temp; int i, l, proc_len; struct sk_buff *skb; struct l3_process *pc = NULL; switch (ic->arg) { case NI1_CMD_INVOKE: if (ic->parm.ni1_io.datalen < 0) return(-2); /* invalid parameter */ for (proc_len = 1, i = ic->parm.ni1_io.proc >> 8; i; i++) i = i >> 8; /* add one byte */ l = ic->parm.ni1_io.datalen + proc_len + 8; /* length excluding ie header */ if (l > 255) return(-2); /* too long */ if (!(id = new_invoke_id(st))) return(0); /* first get a invoke id -> return if no available */ i = -1; MsgHead(p, i, MT_FACILITY); /* build message head */ *p++ = 0x1C; /* Facility IE */ *p++ = l; /* length of ie */ *p++ = 0x91; /* remote operations */ *p++ = 0xA1; /* invoke */ *p++ = l - 3; /* length of invoke */ *p++ = 0x02; /* invoke id tag */ *p++ = 0x01; /* length is 1 */ *p++ = id; /* invoke id */ *p++ = 0x02; /* operation */ *p++ = proc_len; /* length of operation */ for (i = proc_len; i; i--) *p++ = (ic->parm.ni1_io.proc >> (i-1)) & 0xFF; memcpy(p, ic->parm.ni1_io.data, ic->parm.ni1_io.datalen); /* copy data */ l = (p - temp) + ic->parm.ni1_io.datalen; /* total length */ if (ic->parm.ni1_io.timeout > 0) if (!(pc = ni1_new_l3_process(st, -1))) { free_invoke_id(st, id); return(-2); } pc->prot.ni1.ll_id = ic->parm.ni1_io.ll_id; /* remember id */ pc->prot.ni1.proc = ic->parm.ni1_io.proc; /* and procedure */ if (!(skb = l3_alloc_skb(l))) { free_invoke_id(st, id); if (pc) ni1_release_l3_process(pc); return(-2); } memcpy(skb_put(skb, l), temp, l); if (pc) { pc->prot.ni1.invoke_id = id; /* remember id */ L3AddTimer(&pc->timer, ic->parm.ni1_io.timeout, CC_TNI1_IO | REQUEST); } l3_msg(st, DL_DATA | REQUEST, skb); ic->parm.ni1_io.hl_id = id; /* return id */ return(0); case NI1_CMD_INVOKE_ABORT: if ((pc = l3ni1_search_dummy_proc(st, ic->parm.ni1_io.hl_id))) { L3DelTimer(&pc->timer); /* remove timer */ ni1_release_l3_process(pc); return(0); } else { l3_debug(st, "l3ni1_cmd_global abort unknown id"); return(-2); } break; default: l3_debug(st, "l3ni1_cmd_global unknown cmd 0x%lx", ic->arg); return(-1); } /* switch ic-> arg */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -