📄 l3ni1.c
字号:
return(-1);} /* l3ni1_cmd_global */static void l3ni1_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 = NI1_STAT_INVOKE_ERR; ic.parm.ni1_io.hl_id = pc->prot.ni1.invoke_id; ic.parm.ni1_io.ll_id = pc->prot.ni1.ll_id; ic.parm.ni1_io.proc = pc->prot.ni1.proc; ic.parm.ni1_io.timeout= -1; ic.parm.ni1_io.datalen = 0; ic.parm.ni1_io.data = NULL; free_invoke_id(pc->st, pc->prot.ni1.invoke_id); pc->prot.ni1.invoke_id = 0; /* reset id */ cs->iif.statcallb(&ic); ni1_release_l3_process(pc); } /* l3ni1_io_timer */static voidl3ni1_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); ni1_release_l3_process(pc); } else { pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc); }}static voidl3ni1_dummy(struct l3_process *pc, u_char pr, void *arg){}static voidl3ni1_t302(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 28; /* invalid number */ l3ni1_disconnect_req(pc, pr, NULL); pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);}static voidl3ni1_t303(struct l3_process *pc, u_char pr, void *arg){ if (pc->N303 > 0) { pc->N303--; L3DelTimer(&pc->timer); l3ni1_setup_req(pc, pr, arg); } else { L3DelTimer(&pc->timer); l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, 102); pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc); ni1_release_l3_process(pc); }}static voidl3ni1_t304(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3ni1_disconnect_req(pc, pr, NULL); pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);}static voidl3ni1_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 voidl3ni1_t310(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3ni1_disconnect_req(pc, pr, NULL); pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);}static voidl3ni1_t313(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3ni1_disconnect_req(pc, pr, NULL); pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);}static voidl3ni1_t308_1(struct l3_process *pc, u_char pr, void *arg){ newl3state(pc, 19); L3DelTimer(&pc->timer); l3ni1_message(pc, MT_RELEASE); L3AddTimer(&pc->timer, T308, CC_T308_2);}static voidl3ni1_t308_2(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc); ni1_release_l3_process(pc);}static voidl3ni1_t318(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); newl3state(pc, 19); l3ni1_message(pc, MT_RELEASE); L3AddTimer(&pc->timer, T308, CC_T308_1);}static voidl3ni1_t319(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10);}static voidl3ni1_restart(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); ni1_release_l3_process(pc);}static voidl3ni1_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 = l3ni1_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; l3ni1_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 */ pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); ni1_release_l3_process(pc); }}static voidl3ni1_facility(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int ret; ret = check_infoelements(pc, skb, ie_FACILITY); l3ni1_std_ie_err(pc, ret); { u_char *p; if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) l3ni1_parse_facility(pc->st, pc, pc->callref, p); }}static voidl3ni1_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 voidl3ni1_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; pc->st->l3.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); ni1_release_l3_process(pc);}static voidl3ni1_suspend_rej(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int ret; if ((ret = l3ni1_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; l3ni1_status_send(pc, pr, NULL); return; } ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT); if (ERR_IE_COMPREHENSION == ret) { l3ni1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret);}static voidl3ni1_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 voidl3ni1_resume_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, "resume ack 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, "resume ack without chid (ret %d)", id); pc->para.cause = 96; l3ni1_status_send(pc, pr, NULL); return; } ret = check_infoelements(pc, skb, ie_RESUME_ACKNOWLEDGE); if (ERR_IE_COMPREHENSION == ret) { l3ni1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc); newl3state(pc, 10); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret);}static voidl3ni1_resume_rej(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int ret; if ((ret = l3ni1_get_cause(pc, skb))) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "RES_REJ get_cause ret(%d)",ret); if (ret < 0) pc->para.cause = 96; else pc->para.cause = 100; l3ni1_status_send(pc, pr, NULL); return; } ret = check_infoelements(pc, skb, ie_RESUME_REJECT); if (ERR_IE_COMPREHENSION == ret) { l3ni1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); newl3state(pc, 0); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); ni1_release_l3_process(pc);}static voidl3ni1_global_restart(struct l3_process *pc, u_char pr, void *arg){ u_char tmp[32]; u_char *p; u_char ri, ch = 0, chan = 0; int l; struct sk_buff *skb = arg; struct l3_process *up; newl3state(pc, 2); L3DelTimer(&pc->timer); p = skb->data; if ((p = findie(p, skb->len, IE_RESTART_IND, 0))) { ri = p[2]; l3_debug(pc->st, "Restart %x", ri); } else { l3_debug(pc->st, "Restart without restart IE"); ri = 0x86; } p = skb->data; if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { chan = p[2] & 3; ch = p[2]; if (pc->st->l3.debug) l3_debug(pc->st, "Restart for channel %d", chan); } newl3state(pc, 2); up = pc->st->l3.proc; while (up) { if ((ri & 7) == 7) up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); else if (up->para.bchannel == chan) up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); up = up->next; } p = tmp; MsgHead(p, pc->callref, MT_RESTART_ACKNOWLEDGE); if (chan) { *p++ = IE_CHANNEL_ID; *p++ = 1; *p++ = ch | 0x80; } *p++ = 0x79; /* RESTART Ind */ *p++ = 1; *p++ = ri; l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); newl3state(pc, 0); l3_msg(pc->st, DL_DATA | REQUEST, skb);}static voidl3ni1_dl_reset(struct l3_process *pc, u_char pr, void *arg){ pc->para.cause = 0x29; /* Temporary failure */ pc->para.loc = 0; l3ni1_disconnect_req(pc, pr, NULL); pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);}static voidl3ni1_dl_release(struct l3_process *pc, u_char pr, void *arg){ newl3state(pc, 0); pc->para.cause = 0x1b; /* Destination out of order */ pc->para.loc = 0; pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); release_l3_process(pc);}static voidl3ni1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T309, CC_T309); l3_msg(pc->st, DL_ESTABLISH | REQUEST, NULL);} static voidl3ni1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg){ L3DelTimer(&pc->timer); pc->para.cause = 0x1F; /* normal, unspecified */ l3ni1_status_send(pc, 0, NULL);}static void l3ni1_Send
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -