📄 l3dss1.c
字号:
strcpy(pc->prot.dss1.uus1_data,pc->chan->setup.eazmsn); /* copy uus element if available */ if (!pc->chan->setup.phone[0]) { pc->para.cause = -1; l3dss1_disconnect_req(pc,pr,arg); /* disconnect immediately */ return; } /* only uus */ if (pc->prot.dss1.invoke_id) free_invoke_id(pc->st,pc->prot.dss1.invoke_id); if (!(pc->prot.dss1.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.dss1.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);} /* l3dss1_redir_req *//********************************************//* handle deflection request in early state *//********************************************/static void l3dss1_redir_req_early(struct l3_process *pc, u_char pr, void *arg){ l3dss1_proceed_req(pc,pr,arg); l3dss1_redir_req(pc,pr,arg);} /* l3dss1_redir_req_early *//***********************************************//* handle special commands for this protocol. *//* Examples are call independant services like *//* remote operations with dummy callref. *//***********************************************/static int l3dss1_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 DSS1_CMD_INVOKE: if (ic->parm.dss1_io.datalen < 0) return(-2); /* invalid parameter */ for (proc_len = 1, i = ic->parm.dss1_io.proc >> 8; i; i++) i = i >> 8; /* add one byte */ l = ic->parm.dss1_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.dss1_io.proc >> (i-1)) & 0xFF; memcpy(p, ic->parm.dss1_io.data, ic->parm.dss1_io.datalen); /* copy data */ l = (p - temp) + ic->parm.dss1_io.datalen; /* total length */ if (ic->parm.dss1_io.timeout > 0) if (!(pc = dss1_new_l3_process(st, -1))) { free_invoke_id(st, id); return(-2); } pc->prot.dss1.ll_id = ic->parm.dss1_io.ll_id; /* remember id */ pc->prot.dss1.proc = ic->parm.dss1_io.proc; /* and procedure */ if (!(skb = l3_alloc_skb(l))) { free_invoke_id(st, id); if (pc) dss1_release_l3_process(pc); return(-2); } memcpy(skb_put(skb, l), temp, l); if (pc) { pc->prot.dss1.invoke_id = id; /* remember id */ L3AddTimer(&pc->timer, ic->parm.dss1_io.timeout, CC_TDSS1_IO | REQUEST); } l3_msg(st, DL_DATA | REQUEST, skb); ic->parm.dss1_io.hl_id = id; /* return id */ return(0); case DSS1_CMD_INVOKE_ABORT: if ((pc = l3dss1_search_dummy_proc(st, ic->parm.dss1_io.hl_id))) { L3DelTimer(&pc->timer); /* remove timer */ dss1_release_l3_process(pc); return(0); } else { l3_debug(st, "l3dss1_cmd_global abort unknown id"); return(-2); } break; default: l3_debug(st, "l3dss1_cmd_global unknown cmd 0x%lx", ic->arg); return(-1); } /* switch ic-> arg */ return(-1);} /* l3dss1_cmd_global */static void l3dss1_io_timer(struct l3_process *pc){ isdn_ctrl ic; struct IsdnCardState *cs = pc->st->l1.hardware; L3DelTimer(&pc->timer); /* remove timer */ ic.driver = cs->myid; ic.command = ISDN_STAT_PROT; ic.arg = DSS1_STAT_INVOKE_ERR; ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id; ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id; ic.parm.dss1_io.proc = pc->prot.dss1.proc; ic.parm.dss1_io.timeout= -1; ic.parm.dss1_io.datalen = 0; ic.parm.dss1_io.data = NULL; free_invoke_id(pc->st, pc->prot.dss1.invoke_id); pc->prot.dss1.invoke_id = 0; /* reset id */ cs->iif.statcallb(&ic); dss1_release_l3_process(pc); } /* l3dss1_io_timer */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 */ L3L4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc); } else { L3L4(pc->st, CC_IGNORE | INDICATION, pc); }}static voidl3dss1_dummy(struct l3_process *pc, u_char pr, void *arg){}static voidl3dss1_t302(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 28; /* invalid number */ l3dss1_disconnect_req(pc, pr, NULL); L3L4(pc->st, CC_SETUP_ERR, 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); l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, 102); L3L4(pc->st, CC_NOSETUP_RSP, pc); dss1_release_l3_process(pc); }}static voidl3dss1_t304(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); 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 = 16; L3DelTimer(&pc->timer); if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; MsgHead(p, pc->callref, MT_RELEASE); *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, 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.loc = 0; pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); L3L4(pc->st, CC_SETUP_ERR, pc);}static voidl3dss1_t313(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); L3L4(pc->st, CC_CONNECT_ERR, pc);}static voidl3dss1_t308_1(struct l3_process *pc, u_char pr, void *arg){ newl3state(pc, 19); L3DelTimer(&pc->timer); l3dss1_message(pc, MT_RELEASE); L3AddTimer(&pc->timer, T308, CC_T308_2);}static voidl3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); L3L4(pc->st, CC_RELEASE_ERR, pc); dss1_release_l3_process(pc);}static voidl3dss1_t318(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ L3L4(pc->st, CC_RESUME_ERR, pc); newl3state(pc, 19); l3dss1_message(pc, MT_RELEASE); L3AddTimer(&pc->timer, T308, CC_T308_1);}static voidl3dss1_t319(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ L3L4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10);}static voidl3dss1_restart(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); L3L4(pc->st, CC_RELEASE | INDICATION, pc); dss1_release_l3_process(pc);}static voidl3dss1_status(struct l3_process *pc, u_char pr, void *arg){ u_char *p; struct sk_buff *skb = arg; int ret; u_char cause = 0, callState = 0; if ((ret = l3dss1_get_cause(pc, skb))) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "STATUS get_cause ret(%d)",ret); if (ret < 0) cause = 96; else if (ret > 0) cause = 100; } if ((p = findie(skb->data, skb->len, IE_CALL_STATE, 0))) { p++; if (1 == *p++) { callState = *p; if (!ie_in_set(pc, *p, l3_valid_states)) cause = 100; } else cause = 100; } else cause = 96; if (!cause) { /* no error before */ ret = check_infoelements(pc, skb, ie_STATUS); if (ERR_IE_COMPREHENSION == ret) cause = 96; else if (ERR_IE_UNRECOGNIZED == ret) cause = 99; } if (cause) { u_char tmp; if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause); tmp = pc->para.cause; pc->para.cause = cause; l3dss1_status_send(pc, 0, NULL); if (cause == 99) pc->para.cause = tmp; else return; } cause = pc->para.cause; if (((cause & 0x7f) == 111) && (callState == 0)) { /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... * if received MT_STATUS with cause == 111 and call * state == 0, then we must set down layer 3 */ L3L4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc); }}static voidl3dss1_facility(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int ret; ret = check_infoelements(pc, skb, ie_FACILITY); l3dss1_std_ie_err(pc, ret); { u_char *p; if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) l3dss1_parse_facility(pc->st, pc, pc->callref, p); }}static voidl3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb; u_char tmp[32]; u_char *p = tmp; u_char i, l; u_char *msg = pc->chan->setup.phone; MsgHead(p, pc->callref, MT_SUSPEND); l = *msg++; if (l && (l <= 10)) { /* Max length 10 octets */ *p++ = IE_CALL_ID; *p++ = l; for (i = 0; i < l; i++) *p++ = *msg++; } else if (l) { l3_debug(pc->st, "SUS wrong CALL_ID len %d", l); 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); newl3state(pc, 15); L3AddTimer(&pc->timer, T319, CC_T319);}static voidl3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int ret; L3DelTimer(&pc->timer); newl3state(pc, 0); pc->para.cause = NO_CAUSE; L3L4(pc->st, CC_SUSPEND | CONFIRM, pc); /* We don't handle suspend_ack for IE errors now */ if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE))) if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "SUSPACK check ie(%d)",ret); dss1_release_l3_process(pc);}static voidl3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int ret; if ((ret = l3dss1_get_cause(pc, skb))) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "SUSP_REJ get_cause ret(%d)",ret); if (ret < 0) pc->para.cause = 96; else pc->para.cause = 100; l3dss1_status_send(pc, pr, NULL); return; } ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT); if (ERR_IE_COMPREHENSION == ret) { l3dss1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); L3L4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret);}static voidl3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb; u_char tmp[32]; u_char *p = tmp; u_char i, l; u_char *msg = pc->para.setup.phone; MsgHead(p, pc->callref, MT_RESUME); l = *msg++; if (l && (l <= 10)) { /* Max length 10 octets */ *p++ = IE_CALL_ID; *p++ = l; for (i = 0; i < l; i++) *p++ = *msg++; } else if (l) { l3_debug(pc->st, "RES wrong CALL_ID len %d", l); 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); newl3state(pc, 17); L3AddTimer(&pc->timer, T318, CC_T318);}static voidl3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int id, ret; if ((id =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -