📄 l3dss1.c
字号:
int l; MsgHead(p, pc->callref, mt); *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);}static voidl3dss1_status_send(struct l3_process *pc, u_char pr, void *arg){ u_char tmp[16]; u_char *p = tmp; int l; struct sk_buff *skb; MsgHead(p, pc->callref, MT_STATUS); *p++ = IE_CAUSE; *p++ = 0x2; *p++ = 0x80; *p++ = pc->para.cause | 0x80; *p++ = IE_CALL_STATE; *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_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: /* invalid callreference */ case 88: /* incomp destination */ case 96: /* mandory IE missing */ case 100: /* invalid IE contents */ case 101: /* 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 l3dss1_msg_without_setup wrong cause %d\n", pc->para.cause); 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); dss1_release_l3_process(pc);}static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1, IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_HLC, IE_USER_USER, -1};static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1, IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1};static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1, IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_SIGNAL, IE_CONNECT_PN, IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1};static int ie_CONNECT_ACKNOWLEDGE[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_SIGNAL, -1};static int ie_DISCONNECT[] = {IE_CAUSE | IE_MANDATORY, IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};static int ie_INFORMATION[] = {IE_COMPLETE, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL, IE_CALLED_PN, -1};static int ie_NOTIFY[] = {IE_BEARER, IE_NOTIFY | IE_MANDATORY, IE_DISPLAY, -1};static int ie_PROGRESS[] = {IE_BEARER, IE_CAUSE, IE_FACILITY, IE_PROGRESS | IE_MANDATORY, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};static int ie_RELEASE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};/* a RELEASE_COMPLETE with errors don't require special actions static int ie_RELEASE_COMPLETE[] = {IE_CAUSE | IE_MANDATORY_1, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};*/static int ie_RESUME_ACKNOWLEDGE[] = {IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_DISPLAY, -1};static int ie_RESUME_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER | IE_MANDATORY, IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS, IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL, IE_CALLING_PN, IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_REDIR_NR, IE_LLC, IE_HLC, IE_USER_USER, -1};static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, -1};static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE | IE_MANDATORY, IE_DISPLAY, -1};static int ie_STATUS_ENQUIRY[] = {IE_DISPLAY, -1};static int ie_SUSPEND_ACKNOWLEDGE[] = {IE_DISPLAY, IE_FACILITY, -1};static int ie_SUSPEND_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};/* not used * static int ie_CONGESTION_CONTROL[] = {IE_CONGESTION | IE_MANDATORY, * IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1}; * static int ie_USER_INFORMATION[] = {IE_MORE_DATA, IE_USER_USER | IE_MANDATORY, -1}; * static int ie_RESTART[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_RESTART_IND | * IE_MANDATORY, -1}; */static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1};static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1};struct ie_len { int ie; int len;};staticstruct ie_len max_ie_len[] = { {IE_SEGMENT, 4}, {IE_BEARER, 12}, {IE_CAUSE, 32}, {IE_CALL_ID, 10}, {IE_CALL_STATE, 3}, {IE_CHANNEL_ID, 34}, {IE_FACILITY, 255}, {IE_PROGRESS, 4}, {IE_NET_FAC, 255}, {IE_NOTIFY, 3}, {IE_DISPLAY, 82}, {IE_DATE, 8}, {IE_KEYPAD, 34}, {IE_SIGNAL, 3}, {IE_INFORATE, 6}, {IE_E2E_TDELAY, 11}, {IE_TDELAY_SEL, 5}, {IE_PACK_BINPARA, 3}, {IE_PACK_WINSIZE, 4}, {IE_PACK_SIZE, 4}, {IE_CUG, 7}, {IE_REV_CHARGE, 3}, {IE_CALLING_PN, 24}, {IE_CALLING_SUB, 23}, {IE_CALLED_PN, 24}, {IE_CALLED_SUB, 23}, {IE_REDIR_NR, 255}, {IE_TRANS_SEL, 255}, {IE_RESTART_IND, 3}, {IE_LLC, 18}, {IE_HLC, 5}, {IE_USER_USER, 131}, {-1,0},};static intgetmax_ie_len(u_char ie) { int i = 0; while (max_ie_len[i].ie != -1) { if (max_ie_len[i].ie == ie) return(max_ie_len[i].len); i++; } return(255);}static intie_in_set(struct l3_process *pc, u_char ie, int *checklist) { int ret = 1; while (*checklist != -1) { if ((*checklist & 0xff) == ie) { if (ie & 0x80) return(-ret); else return(ret); } ret++; checklist++; } return(0);}static intcheck_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist){ int *cl = checklist; u_char mt; u_char *p, ie; int l, newpos, oldpos; int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0; u_char codeset = 0; u_char old_codeset = 0; u_char codelock = 1; p = skb->data; /* skip cr */ p++; l = (*p++) & 0xf; p += l; mt = *p++; oldpos = 0; while ((p - skb->data) < skb->len) { if ((*p & 0xf0) == 0x90) { /* shift codeset */ old_codeset = codeset; codeset = *p & 7; if (*p & 0x08) codelock = 0; else codelock = 1; if (pc->debug & L3_DEB_CHECK) l3_debug(pc->st, "check IE shift%scodeset %d->%d", codelock ? " locking ": " ", old_codeset, codeset); p++; continue; } if (!codeset) { /* only codeset 0 */ if ((newpos = ie_in_set(pc, *p, cl))) { if (newpos > 0) { if (newpos < oldpos) err_seq++; else oldpos = newpos; } } else { if (ie_in_set(pc, *p, comp_required)) err_compr++; else err_ureg++; } } ie = *p++; if (ie & 0x80) { l = 1; } else { l = *p++; p += l; l += 2; } if (!codeset && (l > getmax_ie_len(ie))) err_len++; if (!codelock) { if (pc->debug & L3_DEB_CHECK) l3_debug(pc->st, "check IE shift back codeset %d->%d", codeset, old_codeset); codeset = old_codeset; codelock = 1; } } if (err_compr | err_ureg | err_len | err_seq) { if (pc->debug & L3_DEB_CHECK) l3_debug(pc->st, "check IE MT(%x) %d/%d/%d/%d", mt, err_compr, err_ureg, err_len, err_seq); if (err_compr) return(ERR_IE_COMPREHENSION); if (err_ureg) return(ERR_IE_UNRECOGNIZED); if (err_len) return(ERR_IE_LENGTH); if (err_seq) return(ERR_IE_SEQUENCE); } return(0);}/* verify if a message type exists and contain no IE error */static intl3dss1_check_messagetype_validity(struct l3_process *pc, int mt, void *arg){ switch (mt) { case MT_ALERTING: case MT_CALL_PROCEEDING: case MT_CONNECT: case MT_CONNECT_ACKNOWLEDGE: case MT_DISCONNECT: case MT_INFORMATION: case MT_FACILITY: case MT_NOTIFY: case MT_PROGRESS: case MT_RELEASE: case MT_RELEASE_COMPLETE: case MT_SETUP: case MT_SETUP_ACKNOWLEDGE: case MT_RESUME_ACKNOWLEDGE: case MT_RESUME_REJECT: case MT_SUSPEND_ACKNOWLEDGE: case MT_SUSPEND_REJECT: case MT_USER_INFORMATION: case MT_RESTART: case MT_RESTART_ACKNOWLEDGE: case MT_CONGESTION_CONTROL: case MT_STATUS: case MT_STATUS_ENQUIRY: if (pc->debug & L3_DEB_CHECK) l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) OK", mt); break; case MT_RESUME: /* RESUME only in user->net */ case MT_SUSPEND: /* SUSPEND only in user->net */ default: if (pc->debug & (L3_DEB_CHECK | L3_DEB_WARN)) l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) fail", mt); pc->para.cause = 97; l3dss1_status_send(pc, 0, NULL); return(1); } return(0);}static voidl3dss1_std_ie_err(struct l3_process *pc, int ret) { if (pc->debug & L3_DEB_CHECK) l3_debug(pc->st, "check_infoelements ret %d", ret); switch(ret) { case 0: break; case ERR_IE_COMPREHENSION: pc->para.cause = 96; l3dss1_status_send(pc, 0, NULL); break; case ERR_IE_UNRECOGNIZED: pc->para.cause = 99; l3dss1_status_send(pc, 0, NULL); break; case ERR_IE_LENGTH: pc->para.cause = 100; l3dss1_status_send(pc, 0, NULL); break; case ERR_IE_SEQUENCE: default: break; }}static intl3dss1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) { u_char *p; p = skb->data; if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { p++; if (*p != 1) { /* len for BRI = 1 */ if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "wrong chid len %d", *p); return (-2); } p++; if (*p & 0x60) { /* only base rate interface */ if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "wrong chid %x", *p); return (-3); } return(*p & 0x3); } else return(-1);}static intl3dss1_get_cause(struct l3_process *pc, struct sk_buff *skb) { u_char l, i=0; u_char *p; p = skb->data; pc->para.cause = 31; pc->para.loc = 0; if ((p = findie(p, skb->len, IE_CAUSE, 0))) { p++; l = *p++; if (l>30) return(1); if (l) { pc->para.loc = *p++; l--; } else { return(2); } if (l && !(pc->para.loc & 0x80)) { l--; p++; /* skip recommendation */ } if (l) { pc->para.cause = *p++; l--; if (!(pc->para.cause & 0x80)) return(3); } else return(4); while (l && (i<6)) { pc->para.diag[i++] = *p++; l--; } } else return(-1); return(0);}static voidl3dss1_msg_with_uus(struct l3_process *pc, u_char cmd){ struct sk_buff *skb; u_char tmp[16+40]; u_char *p = tmp; int l; MsgHead(p, pc->callref, cmd); 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); l3_msg(pc->st, DL_DATA | REQUEST, skb);} /* l3dss1_msg_with_uus */static voidl3dss1_release_req(struct l3_process *pc, u_char pr, void *arg){ StopAllL3Timer(pc); newl3state(pc, 19); if (!pc->prot.dss1.uus1_data[0]) l3dss1_message(pc, MT_RELEASE); else l3dss1_msg_with_uus(pc, MT_RELEASE); L3AddTimer(&pc->timer, T308, CC_T308_1);}static voidl3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int ret; if ((ret = l3dss1_get_cause(pc, skb))>0) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "RELCMPL get_cause ret(%d)",ret); } else if (ret < 0) pc->para.cause = NO_CAUSE; StopAllL3Timer(pc); newl3state(pc, 0); L3L4(pc->st, CC_RELEASE | CONFIRM, pc); dss1_release_l3_process(pc);}#if EXT_BEARER_CAPSstatic u_char *EncodeASyncParams(u_char * p, u_char si2){ // 7c 06 88 90 21 42 00 bb p[0] = 0; p[1] = 0x40; // Intermediate rate: 16 kbit/s jj 2000.02.19 p[2] = 0x80; if (si2 & 32) // 7 data bits p[2] += 16; else // 8 data bits p[2] += 24; if (si2 & 16) // 2 stop bits p[2] += 96; else // 1 stop bit p[2] += 32; if (si2 & 8) // even parity p[2] += 2; else // no parity p[2] += 3; switch (si2 & 0x07) { case 0: p[0] = 66; // 1200 bit/s break; case 1: p[0] = 88; // 1200/75 bit/s break; case 2: p[0] = 87; // 75/1200 bit/s break; case 3: p[0] = 67; // 2400 bit/s break; case 4: p[0] = 69; // 4800 bit/s break; case 5: p[0] = 72; // 9600 bit/s break; case 6: p[0] = 73; // 14400 bit/s break; case 7: p[0] = 75; // 19200 bit/s break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -