Linux 2.4.0-test7-pre7
[davej-history.git] / drivers / isdn / hisax / l3ni1.c
blobec28539a7503236c12d5c6d98cf923a09a5e980a
1 // $Id: l3ni1.c,v 2.3 2000/06/26 08:59:14 keil Exp $
2 //-----------------------------------------------------------------------------
3 //
4 // NI1 D-channel protocol
5 //
6 // Author Matt Henderson & Guy Ellis - Traverse Tecnologies Pty Ltd
7 // www.traverse.com.au
8 //
9 // 2000.6.6 Initial implementation of routines for US NI1
10 // Layer 3 protocol based on the EURO/DSS1 D-channel protocol
11 // driver written by Karsten Keil et al. Thanks also for the
12 // code provided by Ragnar Paulson and Will Scales.
14 // This file is (c) under GNU PUBLIC LICENSE
16 //-----------------------------------------------------------------------------
18 #define __NO_VERSION__
19 #include "hisax.h"
20 #include "isdnl3.h"
21 #include "l3ni1.h"
22 #include <linux/ctype.h>
24 extern char *HiSax_getrev(const char *revision);
25 const char *ni1_revision = "$Revision: 2.3 $";
27 #define EXT_BEARER_CAPS 1
29 #define MsgHead(ptr, cref, mty) \
30 *ptr++ = 0x8; \
31 if (cref == -1) { \
32 *ptr++ = 0x0; \
33 } else { \
34 *ptr++ = 0x1; \
35 *ptr++ = cref^0x80; \
36 } \
37 *ptr++ = mty
40 /**********************************************/
41 /* get a new invoke id for remote operations. */
42 /* Only a return value != 0 is valid */
43 /**********************************************/
44 static unsigned char new_invoke_id(struct PStack *p)
46 unsigned char retval;
47 int flags,i;
49 i = 32; /* maximum search depth */
51 save_flags(flags);
52 cli();
54 retval = p->prot.ni1.last_invoke_id + 1; /* try new id */
55 while ((i) && (p->prot.ni1.invoke_used[retval >> 3] == 0xFF)) {
56 p->prot.ni1.last_invoke_id = (retval & 0xF8) + 8;
57 i--;
59 if (i) {
60 while (p->prot.ni1.invoke_used[retval >> 3] & (1 << (retval & 7)))
61 retval++;
62 } else
63 retval = 0;
64 p->prot.ni1.last_invoke_id = retval;
65 p->prot.ni1.invoke_used[retval >> 3] |= (1 << (retval & 7));
66 restore_flags(flags);
68 return(retval);
69 } /* new_invoke_id */
71 /*************************/
72 /* free a used invoke id */
73 /*************************/
74 static void free_invoke_id(struct PStack *p, unsigned char id)
75 { int flags;
77 if (!id) return; /* 0 = invalid value */
79 save_flags(flags);
80 cli();
81 p->prot.ni1.invoke_used[id >> 3] &= ~(1 << (id & 7));
82 restore_flags(flags);
83 } /* free_invoke_id */
86 /**********************************************************/
87 /* create a new l3 process and fill in ni1 specific data */
88 /**********************************************************/
89 static struct l3_process
90 *ni1_new_l3_process(struct PStack *st, int cr)
91 { struct l3_process *proc;
93 if (!(proc = new_l3_process(st, cr)))
94 return(NULL);
96 proc->prot.ni1.invoke_id = 0;
97 proc->prot.ni1.remote_operation = 0;
98 proc->prot.ni1.uus1_data[0] = '\0';
100 return(proc);
101 } /* ni1_new_l3_process */
103 /************************************************/
104 /* free a l3 process and all ni1 specific data */
105 /************************************************/
106 static void
107 ni1_release_l3_process(struct l3_process *p)
109 free_invoke_id(p->st,p->prot.ni1.invoke_id);
110 release_l3_process(p);
111 } /* ni1_release_l3_process */
113 /********************************************************/
114 /* search a process with invoke id id and dummy callref */
115 /********************************************************/
116 static struct l3_process *
117 l3ni1_search_dummy_proc(struct PStack *st, int id)
118 { struct l3_process *pc = st->l3.proc; /* start of processes */
120 if (!id) return(NULL);
122 while (pc)
123 { if ((pc->callref == -1) && (pc->prot.ni1.invoke_id == id))
124 return(pc);
125 pc = pc->next;
127 return(NULL);
128 } /* l3ni1_search_dummy_proc */
130 /*******************************************************************/
131 /* called when a facility message with a dummy callref is received */
132 /* and a return result is delivered. id specifies the invoke id. */
133 /*******************************************************************/
134 static void
135 l3ni1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen)
136 { isdn_ctrl ic;
137 struct IsdnCardState *cs;
138 struct l3_process *pc = NULL;
140 if ((pc = l3ni1_search_dummy_proc(st, id)))
141 { L3DelTimer(&pc->timer); /* remove timer */
143 cs = pc->st->l1.hardware;
144 ic.driver = cs->myid;
145 ic.command = ISDN_STAT_PROT;
146 ic.arg = NI1_STAT_INVOKE_RES;
147 ic.parm.ni1_io.hl_id = pc->prot.ni1.invoke_id;
148 ic.parm.ni1_io.ll_id = pc->prot.ni1.ll_id;
149 ic.parm.ni1_io.proc = pc->prot.ni1.proc;
150 ic.parm.ni1_io.timeout= 0;
151 ic.parm.ni1_io.datalen = nlen;
152 ic.parm.ni1_io.data = p;
153 free_invoke_id(pc->st, pc->prot.ni1.invoke_id);
154 pc->prot.ni1.invoke_id = 0; /* reset id */
156 cs->iif.statcallb(&ic);
157 ni1_release_l3_process(pc);
159 else
160 l3_debug(st, "dummy return result id=0x%x result len=%d",id,nlen);
161 } /* l3ni1_dummy_return_result */
163 /*******************************************************************/
164 /* called when a facility message with a dummy callref is received */
165 /* and a return error is delivered. id specifies the invoke id. */
166 /*******************************************************************/
167 static void
168 l3ni1_dummy_error_return(struct PStack *st, int id, ulong error)
169 { isdn_ctrl ic;
170 struct IsdnCardState *cs;
171 struct l3_process *pc = NULL;
173 if ((pc = l3ni1_search_dummy_proc(st, id)))
174 { L3DelTimer(&pc->timer); /* remove timer */
176 cs = pc->st->l1.hardware;
177 ic.driver = cs->myid;
178 ic.command = ISDN_STAT_PROT;
179 ic.arg = NI1_STAT_INVOKE_ERR;
180 ic.parm.ni1_io.hl_id = pc->prot.ni1.invoke_id;
181 ic.parm.ni1_io.ll_id = pc->prot.ni1.ll_id;
182 ic.parm.ni1_io.proc = pc->prot.ni1.proc;
183 ic.parm.ni1_io.timeout= error;
184 ic.parm.ni1_io.datalen = 0;
185 ic.parm.ni1_io.data = NULL;
186 free_invoke_id(pc->st, pc->prot.ni1.invoke_id);
187 pc->prot.ni1.invoke_id = 0; /* reset id */
189 cs->iif.statcallb(&ic);
190 ni1_release_l3_process(pc);
192 else
193 l3_debug(st, "dummy return error id=0x%x error=0x%lx",id,error);
194 } /* l3ni1_error_return */
196 /*******************************************************************/
197 /* called when a facility message with a dummy callref is received */
198 /* and a invoke is delivered. id specifies the invoke id. */
199 /*******************************************************************/
200 static void
201 l3ni1_dummy_invoke(struct PStack *st, int cr, int id,
202 int ident, u_char *p, u_char nlen)
203 { isdn_ctrl ic;
204 struct IsdnCardState *cs;
206 l3_debug(st, "dummy invoke %s id=0x%x ident=0x%x datalen=%d",
207 (cr == -1) ? "local" : "broadcast",id,ident,nlen);
208 if (cr >= -1) return; /* ignore local data */
210 cs = st->l1.hardware;
211 ic.driver = cs->myid;
212 ic.command = ISDN_STAT_PROT;
213 ic.arg = NI1_STAT_INVOKE_BRD;
214 ic.parm.ni1_io.hl_id = id;
215 ic.parm.ni1_io.ll_id = 0;
216 ic.parm.ni1_io.proc = ident;
217 ic.parm.ni1_io.timeout= 0;
218 ic.parm.ni1_io.datalen = nlen;
219 ic.parm.ni1_io.data = p;
221 cs->iif.statcallb(&ic);
222 } /* l3ni1_dummy_invoke */
224 static void
225 l3ni1_parse_facility(struct PStack *st, struct l3_process *pc,
226 int cr, u_char * p)
228 int qd_len = 0;
229 unsigned char nlen = 0, ilen, cp_tag;
230 int ident, id;
231 ulong err_ret;
233 if (pc)
234 st = pc->st; /* valid Stack */
235 else
236 if ((!st) || (cr >= 0)) return; /* neither pc nor st specified */
238 p++;
239 qd_len = *p++;
240 if (qd_len == 0) {
241 l3_debug(st, "qd_len == 0");
242 return;
244 if ((*p & 0x1F) != 0x11) { /* Service discriminator, supplementary service */
245 l3_debug(st, "supplementary service != 0x11");
246 return;
248 while (qd_len > 0 && !(*p & 0x80)) { /* extension ? */
249 p++;
250 qd_len--;
252 if (qd_len < 2) {
253 l3_debug(st, "qd_len < 2");
254 return;
256 p++;
257 qd_len--;
258 if ((*p & 0xE0) != 0xA0) { /* class and form */
259 l3_debug(st, "class and form != 0xA0");
260 return;
263 cp_tag = *p & 0x1F; /* remember tag value */
265 p++;
266 qd_len--;
267 if (qd_len < 1)
268 { l3_debug(st, "qd_len < 1");
269 return;
271 if (*p & 0x80)
272 { /* length format indefinite or limited */
273 nlen = *p++ & 0x7F; /* number of len bytes or indefinite */
274 if ((qd_len-- < ((!nlen) ? 3 : (1 + nlen))) ||
275 (nlen > 1))
276 { l3_debug(st, "length format error or not implemented");
277 return;
279 if (nlen == 1)
280 { nlen = *p++; /* complete length */
281 qd_len--;
283 else
284 { qd_len -= 2; /* trailing null bytes */
285 if ((*(p+qd_len)) || (*(p+qd_len+1)))
286 { l3_debug(st,"length format indefinite error");
287 return;
289 nlen = qd_len;
292 else
293 { nlen = *p++;
294 qd_len--;
296 if (qd_len < nlen)
297 { l3_debug(st, "qd_len < nlen");
298 return;
300 qd_len -= nlen;
302 if (nlen < 2)
303 { l3_debug(st, "nlen < 2");
304 return;
306 if (*p != 0x02)
307 { /* invoke identifier tag */
308 l3_debug(st, "invoke identifier tag !=0x02");
309 return;
311 p++;
312 nlen--;
313 if (*p & 0x80)
314 { /* length format */
315 l3_debug(st, "invoke id length format 2");
316 return;
318 ilen = *p++;
319 nlen--;
320 if (ilen > nlen || ilen == 0)
321 { l3_debug(st, "ilen > nlen || ilen == 0");
322 return;
324 nlen -= ilen;
325 id = 0;
326 while (ilen > 0)
327 { id = (id << 8) | (*p++ & 0xFF); /* invoke identifier */
328 ilen--;
331 switch (cp_tag) { /* component tag */
332 case 1: /* invoke */
333 if (nlen < 2) {
334 l3_debug(st, "nlen < 2 22");
335 return;
337 if (*p != 0x02) { /* operation value */
338 l3_debug(st, "operation value !=0x02");
339 return;
341 p++;
342 nlen--;
343 ilen = *p++;
344 nlen--;
345 if (ilen > nlen || ilen == 0) {
346 l3_debug(st, "ilen > nlen || ilen == 0 22");
347 return;
349 nlen -= ilen;
350 ident = 0;
351 while (ilen > 0) {
352 ident = (ident << 8) | (*p++ & 0xFF);
353 ilen--;
356 if (!pc)
358 l3ni1_dummy_invoke(st, cr, id, ident, p, nlen);
359 return;
361 l3_debug(st, "invoke break");
362 break;
363 case 2: /* return result */
364 /* if no process available handle separately */
365 if (!pc)
366 { if (cr == -1)
367 l3ni1_dummy_return_result(st, id, p, nlen);
368 return;
370 if ((pc->prot.ni1.invoke_id) && (pc->prot.ni1.invoke_id == id))
371 { /* Diversion successfull */
372 free_invoke_id(st,pc->prot.ni1.invoke_id);
373 pc->prot.ni1.remote_result = 0; /* success */
374 pc->prot.ni1.invoke_id = 0;
375 pc->redir_result = pc->prot.ni1.remote_result;
376 st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Diversion successfull */
377 else
378 l3_debug(st,"return error unknown identifier");
379 break;
380 case 3: /* return error */
381 err_ret = 0;
382 if (nlen < 2)
383 { l3_debug(st, "return error nlen < 2");
384 return;
386 if (*p != 0x02)
387 { /* result tag */
388 l3_debug(st, "invoke error tag !=0x02");
389 return;
391 p++;
392 nlen--;
393 if (*p > 4)
394 { /* length format */
395 l3_debug(st, "invoke return errlen > 4 ");
396 return;
398 ilen = *p++;
399 nlen--;
400 if (ilen > nlen || ilen == 0)
401 { l3_debug(st, "error return ilen > nlen || ilen == 0");
402 return;
404 nlen -= ilen;
405 while (ilen > 0)
406 { err_ret = (err_ret << 8) | (*p++ & 0xFF); /* error value */
407 ilen--;
409 /* if no process available handle separately */
410 if (!pc)
411 { if (cr == -1)
412 l3ni1_dummy_error_return(st, id, err_ret);
413 return;
415 if ((pc->prot.ni1.invoke_id) && (pc->prot.ni1.invoke_id == id))
416 { /* Deflection error */
417 free_invoke_id(st,pc->prot.ni1.invoke_id);
418 pc->prot.ni1.remote_result = err_ret; /* result */
419 pc->prot.ni1.invoke_id = 0;
420 pc->redir_result = pc->prot.ni1.remote_result;
421 st->l3.l3l4(st, CC_REDIR | INDICATION, pc);
422 } /* Deflection error */
423 else
424 l3_debug(st,"return result unknown identifier");
425 break;
426 default:
427 l3_debug(st, "facility default break tag=0x%02x",cp_tag);
428 break;
432 static void
433 l3ni1_message(struct l3_process *pc, u_char mt)
435 struct sk_buff *skb;
436 u_char *p;
438 if (!(skb = l3_alloc_skb(4)))
439 return;
440 p = skb_put(skb, 4);
441 MsgHead(p, pc->callref, mt);
442 l3_msg(pc->st, DL_DATA | REQUEST, skb);
445 static void
446 l3ni1_message_cause(struct l3_process *pc, u_char mt, u_char cause)
448 struct sk_buff *skb;
449 u_char tmp[16];
450 u_char *p = tmp;
451 int l;
453 MsgHead(p, pc->callref, mt);
454 *p++ = IE_CAUSE;
455 *p++ = 0x2;
456 *p++ = 0x80;
457 *p++ = cause | 0x80;
459 l = p - tmp;
460 if (!(skb = l3_alloc_skb(l)))
461 return;
462 memcpy(skb_put(skb, l), tmp, l);
463 l3_msg(pc->st, DL_DATA | REQUEST, skb);
466 static void
467 l3ni1_status_send(struct l3_process *pc, u_char pr, void *arg)
469 u_char tmp[16];
470 u_char *p = tmp;
471 int l;
472 struct sk_buff *skb;
474 MsgHead(p, pc->callref, MT_STATUS);
476 *p++ = IE_CAUSE;
477 *p++ = 0x2;
478 *p++ = 0x80;
479 *p++ = pc->para.cause | 0x80;
481 *p++ = IE_CALL_STATE;
482 *p++ = 0x1;
483 *p++ = pc->state & 0x3f;
485 l = p - tmp;
486 if (!(skb = l3_alloc_skb(l)))
487 return;
488 memcpy(skb_put(skb, l), tmp, l);
489 l3_msg(pc->st, DL_DATA | REQUEST, skb);
492 static void
493 l3ni1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
495 /* This routine is called if here was no SETUP made (checks in ni1up and in
496 * l3ni1_setup) and a RELEASE_COMPLETE have to be sent with an error code
497 * MT_STATUS_ENQUIRE in the NULL state is handled too
499 u_char tmp[16];
500 u_char *p = tmp;
501 int l;
502 struct sk_buff *skb;
504 switch (pc->para.cause) {
505 case 81: /* invalid callreference */
506 case 88: /* incomp destination */
507 case 96: /* mandory IE missing */
508 case 100: /* invalid IE contents */
509 case 101: /* incompatible Callstate */
510 MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
511 *p++ = IE_CAUSE;
512 *p++ = 0x2;
513 *p++ = 0x80;
514 *p++ = pc->para.cause | 0x80;
515 break;
516 default:
517 printk(KERN_ERR "HiSax l3ni1_msg_without_setup wrong cause %d\n",
518 pc->para.cause);
519 return;
521 l = p - tmp;
522 if (!(skb = l3_alloc_skb(l)))
523 return;
524 memcpy(skb_put(skb, l), tmp, l);
525 l3_msg(pc->st, DL_DATA | REQUEST, skb);
526 ni1_release_l3_process(pc);
529 static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
530 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_HLC,
531 IE_USER_USER, -1};
532 static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
533 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1};
534 static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
535 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_SIGNAL,
536 IE_CONNECT_PN, IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1};
537 static int ie_CONNECT_ACKNOWLEDGE[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_SIGNAL, -1};
538 static int ie_DISCONNECT[] = {IE_CAUSE | IE_MANDATORY, IE_FACILITY,
539 IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
540 static int ie_INFORMATION[] = {IE_COMPLETE, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL,
541 IE_CALLED_PN, -1};
542 static int ie_NOTIFY[] = {IE_BEARER, IE_NOTIFY | IE_MANDATORY, IE_DISPLAY, -1};
543 static int ie_PROGRESS[] = {IE_BEARER, IE_CAUSE, IE_FACILITY, IE_PROGRESS |
544 IE_MANDATORY, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};
545 static int ie_RELEASE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY, IE_DISPLAY,
546 IE_SIGNAL, IE_USER_USER, -1};
547 /* a RELEASE_COMPLETE with errors don't require special actions
548 static int ie_RELEASE_COMPLETE[] = {IE_CAUSE | IE_MANDATORY_1, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
550 static int ie_RESUME_ACKNOWLEDGE[] = {IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY,
551 IE_DISPLAY, -1};
552 static int ie_RESUME_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
553 static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER | IE_MANDATORY,
554 IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS,
555 IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL, IE_CALLING_PN,
556 IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_REDIR_NR,
557 IE_LLC, IE_HLC, IE_USER_USER, -1};
558 static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY,
559 IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, -1};
560 static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE |
561 IE_MANDATORY, IE_DISPLAY, -1};
562 static int ie_STATUS_ENQUIRY[] = {IE_DISPLAY, -1};
563 static int ie_SUSPEND_ACKNOWLEDGE[] = {IE_DISPLAY, IE_FACILITY, -1};
564 static int ie_SUSPEND_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
565 /* not used
566 * static int ie_CONGESTION_CONTROL[] = {IE_CONGESTION | IE_MANDATORY,
567 * IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
568 * static int ie_USER_INFORMATION[] = {IE_MORE_DATA, IE_USER_USER | IE_MANDATORY, -1};
569 * static int ie_RESTART[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_RESTART_IND |
570 * IE_MANDATORY, -1};
572 static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1};
573 static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};
574 static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1};
576 struct ie_len {
577 int ie;
578 int len;
581 static
582 struct ie_len max_ie_len[] = {
583 {IE_SEGMENT, 4},
584 {IE_BEARER, 12},
585 {IE_CAUSE, 32},
586 {IE_CALL_ID, 10},
587 {IE_CALL_STATE, 3},
588 {IE_CHANNEL_ID, 34},
589 {IE_FACILITY, 255},
590 {IE_PROGRESS, 4},
591 {IE_NET_FAC, 255},
592 {IE_NOTIFY, 3},
593 {IE_DISPLAY, 82},
594 {IE_DATE, 8},
595 {IE_KEYPAD, 34},
596 {IE_SIGNAL, 3},
597 {IE_INFORATE, 6},
598 {IE_E2E_TDELAY, 11},
599 {IE_TDELAY_SEL, 5},
600 {IE_PACK_BINPARA, 3},
601 {IE_PACK_WINSIZE, 4},
602 {IE_PACK_SIZE, 4},
603 {IE_CUG, 7},
604 {IE_REV_CHARGE, 3},
605 {IE_CALLING_PN, 24},
606 {IE_CALLING_SUB, 23},
607 {IE_CALLED_PN, 24},
608 {IE_CALLED_SUB, 23},
609 {IE_REDIR_NR, 255},
610 {IE_TRANS_SEL, 255},
611 {IE_RESTART_IND, 3},
612 {IE_LLC, 18},
613 {IE_HLC, 5},
614 {IE_USER_USER, 131},
615 {-1,0},
618 static int
619 getmax_ie_len(u_char ie) {
620 int i = 0;
621 while (max_ie_len[i].ie != -1) {
622 if (max_ie_len[i].ie == ie)
623 return(max_ie_len[i].len);
624 i++;
626 return(255);
629 static int
630 ie_in_set(struct l3_process *pc, u_char ie, int *checklist) {
631 int ret = 1;
633 while (*checklist != -1) {
634 if ((*checklist & 0xff) == ie) {
635 if (ie & 0x80)
636 return(-ret);
637 else
638 return(ret);
640 ret++;
641 checklist++;
643 return(0);
646 static int
647 check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist)
649 int *cl = checklist;
650 u_char mt;
651 u_char *p, ie;
652 int l, newpos, oldpos;
653 int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0;
654 u_char codeset = 0;
655 u_char old_codeset = 0;
656 u_char codelock = 1;
658 p = skb->data;
659 /* skip cr */
660 p++;
661 l = (*p++) & 0xf;
662 p += l;
663 mt = *p++;
664 oldpos = 0;
665 while ((p - skb->data) < skb->len) {
666 if ((*p & 0xf0) == 0x90) { /* shift codeset */
667 old_codeset = codeset;
668 codeset = *p & 7;
669 if (*p & 0x08)
670 codelock = 0;
671 else
672 codelock = 1;
673 if (pc->debug & L3_DEB_CHECK)
674 l3_debug(pc->st, "check IE shift%scodeset %d->%d",
675 codelock ? " locking ": " ", old_codeset, codeset);
676 p++;
677 continue;
679 if (!codeset) { /* only codeset 0 */
680 if ((newpos = ie_in_set(pc, *p, cl))) {
681 if (newpos > 0) {
682 if (newpos < oldpos)
683 err_seq++;
684 else
685 oldpos = newpos;
687 } else {
688 if (ie_in_set(pc, *p, comp_required))
689 err_compr++;
690 else
691 err_ureg++;
694 ie = *p++;
695 if (ie & 0x80) {
696 l = 1;
697 } else {
698 l = *p++;
699 p += l;
700 l += 2;
702 if (!codeset && (l > getmax_ie_len(ie)))
703 err_len++;
704 if (!codelock) {
705 if (pc->debug & L3_DEB_CHECK)
706 l3_debug(pc->st, "check IE shift back codeset %d->%d",
707 codeset, old_codeset);
708 codeset = old_codeset;
709 codelock = 1;
712 if (err_compr | err_ureg | err_len | err_seq) {
713 if (pc->debug & L3_DEB_CHECK)
714 l3_debug(pc->st, "check IE MT(%x) %d/%d/%d/%d",
715 mt, err_compr, err_ureg, err_len, err_seq);
716 if (err_compr)
717 return(ERR_IE_COMPREHENSION);
718 if (err_ureg)
719 return(ERR_IE_UNRECOGNIZED);
720 if (err_len)
721 return(ERR_IE_LENGTH);
722 if (err_seq)
723 return(ERR_IE_SEQUENCE);
725 return(0);
728 /* verify if a message type exists and contain no IE error */
729 static int
730 l3ni1_check_messagetype_validity(struct l3_process *pc, int mt, void *arg)
732 switch (mt) {
733 case MT_ALERTING:
734 case MT_CALL_PROCEEDING:
735 case MT_CONNECT:
736 case MT_CONNECT_ACKNOWLEDGE:
737 case MT_DISCONNECT:
738 case MT_INFORMATION:
739 case MT_FACILITY:
740 case MT_NOTIFY:
741 case MT_PROGRESS:
742 case MT_RELEASE:
743 case MT_RELEASE_COMPLETE:
744 case MT_SETUP:
745 case MT_SETUP_ACKNOWLEDGE:
746 case MT_RESUME_ACKNOWLEDGE:
747 case MT_RESUME_REJECT:
748 case MT_SUSPEND_ACKNOWLEDGE:
749 case MT_SUSPEND_REJECT:
750 case MT_USER_INFORMATION:
751 case MT_RESTART:
752 case MT_RESTART_ACKNOWLEDGE:
753 case MT_CONGESTION_CONTROL:
754 case MT_STATUS:
755 case MT_STATUS_ENQUIRY:
756 if (pc->debug & L3_DEB_CHECK)
757 l3_debug(pc->st, "l3ni1_check_messagetype_validity mt(%x) OK", mt);
758 break;
759 case MT_RESUME: /* RESUME only in user->net */
760 case MT_SUSPEND: /* SUSPEND only in user->net */
761 default:
762 if (pc->debug & (L3_DEB_CHECK | L3_DEB_WARN))
763 l3_debug(pc->st, "l3ni1_check_messagetype_validity mt(%x) fail", mt);
764 pc->para.cause = 97;
765 l3ni1_status_send(pc, 0, NULL);
766 return(1);
768 return(0);
771 static void
772 l3ni1_std_ie_err(struct l3_process *pc, int ret) {
774 if (pc->debug & L3_DEB_CHECK)
775 l3_debug(pc->st, "check_infoelements ret %d", ret);
776 switch(ret) {
777 case 0:
778 break;
779 case ERR_IE_COMPREHENSION:
780 pc->para.cause = 96;
781 l3ni1_status_send(pc, 0, NULL);
782 break;
783 case ERR_IE_UNRECOGNIZED:
784 pc->para.cause = 99;
785 l3ni1_status_send(pc, 0, NULL);
786 break;
787 case ERR_IE_LENGTH:
788 pc->para.cause = 100;
789 l3ni1_status_send(pc, 0, NULL);
790 break;
791 case ERR_IE_SEQUENCE:
792 default:
793 break;
797 static int
798 l3ni1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) {
799 u_char *p;
801 p = skb->data;
802 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
803 p++;
804 if (*p != 1) { /* len for BRI = 1 */
805 if (pc->debug & L3_DEB_WARN)
806 l3_debug(pc->st, "wrong chid len %d", *p);
807 return (-2);
809 p++;
810 if (*p & 0x60) { /* only base rate interface */
811 if (pc->debug & L3_DEB_WARN)
812 l3_debug(pc->st, "wrong chid %x", *p);
813 return (-3);
815 return(*p & 0x3);
816 } else
817 return(-1);
820 static int
821 l3ni1_get_cause(struct l3_process *pc, struct sk_buff *skb) {
822 u_char l, i=0;
823 u_char *p;
825 p = skb->data;
826 pc->para.cause = 31;
827 pc->para.loc = 0;
828 if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
829 p++;
830 l = *p++;
831 if (l>30)
832 return(1);
833 if (l) {
834 pc->para.loc = *p++;
835 l--;
836 } else {
837 return(2);
839 if (l && !(pc->para.loc & 0x80)) {
840 l--;
841 p++; /* skip recommendation */
843 if (l) {
844 pc->para.cause = *p++;
845 l--;
846 if (!(pc->para.cause & 0x80))
847 return(3);
848 } else
849 return(4);
850 while (l && (i<6)) {
851 pc->para.diag[i++] = *p++;
852 l--;
854 } else
855 return(-1);
856 return(0);
859 static void
860 l3ni1_msg_with_uus(struct l3_process *pc, u_char cmd)
862 struct sk_buff *skb;
863 u_char tmp[16+40];
864 u_char *p = tmp;
865 int l;
867 MsgHead(p, pc->callref, cmd);
869 if (pc->prot.ni1.uus1_data[0])
870 { *p++ = IE_USER_USER; /* UUS info element */
871 *p++ = strlen(pc->prot.ni1.uus1_data) + 1;
872 *p++ = 0x04; /* IA5 chars */
873 strcpy(p,pc->prot.ni1.uus1_data);
874 p += strlen(pc->prot.ni1.uus1_data);
875 pc->prot.ni1.uus1_data[0] = '\0';
878 l = p - tmp;
879 if (!(skb = l3_alloc_skb(l)))
880 return;
881 memcpy(skb_put(skb, l), tmp, l);
882 l3_msg(pc->st, DL_DATA | REQUEST, skb);
883 } /* l3ni1_msg_with_uus */
885 static void
886 l3ni1_release_req(struct l3_process *pc, u_char pr, void *arg)
888 StopAllL3Timer(pc);
889 newl3state(pc, 19);
890 if (!pc->prot.ni1.uus1_data[0])
891 l3ni1_message(pc, MT_RELEASE);
892 else
893 l3ni1_msg_with_uus(pc, MT_RELEASE);
894 L3AddTimer(&pc->timer, T308, CC_T308_1);
897 static void
898 l3ni1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
900 struct sk_buff *skb = arg;
901 int ret;
903 if ((ret = l3ni1_get_cause(pc, skb))>0) {
904 if (pc->debug & L3_DEB_WARN)
905 l3_debug(pc->st, "RELCMPL get_cause ret(%d)",ret);
906 } else if (ret < 0)
907 pc->para.cause = NO_CAUSE;
908 StopAllL3Timer(pc);
909 newl3state(pc, 0);
910 pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
911 ni1_release_l3_process(pc);
914 #if EXT_BEARER_CAPS
916 static u_char *
917 EncodeASyncParams(u_char * p, u_char si2)
918 { // 7c 06 88 90 21 42 00 bb
920 p[0] = 0;
921 p[1] = 0x40; // Intermediate rate: 16 kbit/s jj 2000.02.19
922 p[2] = 0x80;
923 if (si2 & 32) // 7 data bits
925 p[2] += 16;
926 else // 8 data bits
928 p[2] += 24;
930 if (si2 & 16) // 2 stop bits
932 p[2] += 96;
933 else // 1 stop bit
935 p[2] += 32;
937 if (si2 & 8) // even parity
939 p[2] += 2;
940 else // no parity
942 p[2] += 3;
944 switch (si2 & 0x07) {
945 case 0:
946 p[0] = 66; // 1200 bit/s
948 break;
949 case 1:
950 p[0] = 88; // 1200/75 bit/s
952 break;
953 case 2:
954 p[0] = 87; // 75/1200 bit/s
956 break;
957 case 3:
958 p[0] = 67; // 2400 bit/s
960 break;
961 case 4:
962 p[0] = 69; // 4800 bit/s
964 break;
965 case 5:
966 p[0] = 72; // 9600 bit/s
968 break;
969 case 6:
970 p[0] = 73; // 14400 bit/s
972 break;
973 case 7:
974 p[0] = 75; // 19200 bit/s
976 break;
978 return p + 3;
981 static u_char
982 EncodeSyncParams(u_char si2, u_char ai)
985 switch (si2) {
986 case 0:
987 return ai + 2; // 1200 bit/s
989 case 1:
990 return ai + 24; // 1200/75 bit/s
992 case 2:
993 return ai + 23; // 75/1200 bit/s
995 case 3:
996 return ai + 3; // 2400 bit/s
998 case 4:
999 return ai + 5; // 4800 bit/s
1001 case 5:
1002 return ai + 8; // 9600 bit/s
1004 case 6:
1005 return ai + 9; // 14400 bit/s
1007 case 7:
1008 return ai + 11; // 19200 bit/s
1010 case 8:
1011 return ai + 14; // 48000 bit/s
1013 case 9:
1014 return ai + 15; // 56000 bit/s
1016 case 15:
1017 return ai + 40; // negotiate bit/s
1019 default:
1020 break;
1022 return ai;
1026 static u_char
1027 DecodeASyncParams(u_char si2, u_char * p)
1029 u_char info;
1031 switch (p[5]) {
1032 case 66: // 1200 bit/s
1034 break; // si2 don't change
1036 case 88: // 1200/75 bit/s
1038 si2 += 1;
1039 break;
1040 case 87: // 75/1200 bit/s
1042 si2 += 2;
1043 break;
1044 case 67: // 2400 bit/s
1046 si2 += 3;
1047 break;
1048 case 69: // 4800 bit/s
1050 si2 += 4;
1051 break;
1052 case 72: // 9600 bit/s
1054 si2 += 5;
1055 break;
1056 case 73: // 14400 bit/s
1058 si2 += 6;
1059 break;
1060 case 75: // 19200 bit/s
1062 si2 += 7;
1063 break;
1066 info = p[7] & 0x7f;
1067 if ((info & 16) && (!(info & 8))) // 7 data bits
1069 si2 += 32; // else 8 data bits
1071 if ((info & 96) == 96) // 2 stop bits
1073 si2 += 16; // else 1 stop bit
1075 if ((info & 2) && (!(info & 1))) // even parity
1077 si2 += 8; // else no parity
1079 return si2;
1083 static u_char
1084 DecodeSyncParams(u_char si2, u_char info)
1086 info &= 0x7f;
1087 switch (info) {
1088 case 40: // bit/s negotiation failed ai := 165 not 175!
1090 return si2 + 15;
1091 case 15: // 56000 bit/s failed, ai := 0 not 169 !
1093 return si2 + 9;
1094 case 14: // 48000 bit/s
1096 return si2 + 8;
1097 case 11: // 19200 bit/s
1099 return si2 + 7;
1100 case 9: // 14400 bit/s
1102 return si2 + 6;
1103 case 8: // 9600 bit/s
1105 return si2 + 5;
1106 case 5: // 4800 bit/s
1108 return si2 + 4;
1109 case 3: // 2400 bit/s
1111 return si2 + 3;
1112 case 23: // 75/1200 bit/s
1114 return si2 + 2;
1115 case 24: // 1200/75 bit/s
1117 return si2 + 1;
1118 default: // 1200 bit/s
1120 return si2;
1124 static u_char
1125 DecodeSI2(struct sk_buff *skb)
1127 u_char *p; //, *pend=skb->data + skb->len;
1129 if ((p = findie(skb->data, skb->len, 0x7c, 0))) {
1130 switch (p[4] & 0x0f) {
1131 case 0x01:
1132 if (p[1] == 0x04) // sync. Bitratenadaption
1134 return DecodeSyncParams(160, p[5]); // V.110/X.30
1136 else if (p[1] == 0x06) // async. Bitratenadaption
1138 return DecodeASyncParams(192, p); // V.110/X.30
1140 break;
1141 case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption
1142 if (p[1] > 3)
1143 return DecodeSyncParams(176, p[5]); // V.120
1144 break;
1147 return 0;
1150 #endif
1153 static void
1154 l3ni1_setup_req(struct l3_process *pc, u_char pr,
1155 void *arg)
1157 struct sk_buff *skb;
1158 u_char tmp[128];
1159 u_char *p = tmp;
1161 u_char *teln;
1162 u_char *sub;
1163 u_char *sp;
1164 int l;
1166 MsgHead(p, pc->callref, MT_SETUP);
1168 teln = pc->para.setup.phone;
1170 *p++ = 0xa1; /* complete indicator */
1172 * Set Bearer Capability, Map info from 1TR6-convention to NI1
1174 switch (pc->para.setup.si1) {
1175 case 1: /* Telephony */
1176 *p++ = IE_BEARER;
1177 *p++ = 0x3; /* Length */
1178 *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
1179 *p++ = 0x90; /* Circuit-Mode 64kbps */
1180 *p++ = 0xa3; /* A-Law Audio */
1181 break;
1182 case 5: /* Datatransmission 64k, BTX */
1183 case 7: /* Datatransmission 64k */
1184 default:
1185 *p++ = IE_BEARER;
1186 *p++ = 0x2; /* Length */
1187 *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */
1188 *p++ = 0x90; /* Circuit-Mode 64kbps */
1189 break;
1192 sub = NULL;
1193 sp = teln;
1194 while (*sp) {
1195 if ('.' == *sp) {
1196 sub = sp;
1197 *sp = 0;
1198 } else
1199 sp++;
1202 *p++ = IE_KEYPAD;
1203 *p++ = strlen(teln);
1204 while (*teln)
1205 *p++ = (*teln++) & 0x7F;
1207 if (sub)
1208 *sub++ = '.';
1210 #if EXT_BEARER_CAPS
1211 if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30
1213 *p++ = IE_LLC;
1214 *p++ = 0x04;
1215 *p++ = 0x88;
1216 *p++ = 0x90;
1217 *p++ = 0x21;
1218 *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80);
1219 } else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) { // sync. Bitratenadaption, V.120
1221 *p++ = IE_LLC;
1222 *p++ = 0x05;
1223 *p++ = 0x88;
1224 *p++ = 0x90;
1225 *p++ = 0x28;
1226 *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0);
1227 *p++ = 0x82;
1228 } else if (pc->para.setup.si2 >= 192) { // async. Bitratenadaption, V.110/X.30
1230 *p++ = IE_LLC;
1231 *p++ = 0x06;
1232 *p++ = 0x88;
1233 *p++ = 0x90;
1234 *p++ = 0x21;
1235 p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
1236 } else {
1237 switch (pc->para.setup.si1) {
1238 case 1: /* Telephony */
1239 *p++ = IE_LLC;
1240 *p++ = 0x3; /* Length */
1241 *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
1242 *p++ = 0x90; /* Circuit-Mode 64kbps */
1243 *p++ = 0xa3; /* A-Law Audio */
1244 break;
1245 case 5: /* Datatransmission 64k, BTX */
1246 case 7: /* Datatransmission 64k */
1247 default:
1248 *p++ = IE_LLC;
1249 *p++ = 0x2; /* Length */
1250 *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */
1251 *p++ = 0x90; /* Circuit-Mode 64kbps */
1252 break;
1255 #endif
1256 l = p - tmp;
1257 if (!(skb = l3_alloc_skb(l)))
1259 return;
1261 memcpy(skb_put(skb, l), tmp, l);
1262 L3DelTimer(&pc->timer);
1263 L3AddTimer(&pc->timer, T303, CC_T303);
1264 newl3state(pc, 1);
1265 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1268 static void
1269 l3ni1_call_proc(struct l3_process *pc, u_char pr, void *arg)
1271 struct sk_buff *skb = arg;
1272 int id, ret;
1274 if ((id = l3ni1_get_channel_id(pc, skb)) >= 0) {
1275 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
1276 if (pc->debug & L3_DEB_WARN)
1277 l3_debug(pc->st, "setup answer with wrong chid %x", id);
1278 pc->para.cause = 100;
1279 l3ni1_status_send(pc, pr, NULL);
1280 return;
1282 pc->para.bchannel = id;
1283 } else if (1 == pc->state) {
1284 if (pc->debug & L3_DEB_WARN)
1285 l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
1286 if (id == -1)
1287 pc->para.cause = 96;
1288 else
1289 pc->para.cause = 100;
1290 l3ni1_status_send(pc, pr, NULL);
1291 return;
1293 /* Now we are on none mandatory IEs */
1294 ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING);
1295 if (ERR_IE_COMPREHENSION == ret) {
1296 l3ni1_std_ie_err(pc, ret);
1297 return;
1299 L3DelTimer(&pc->timer);
1300 newl3state(pc, 3);
1301 L3AddTimer(&pc->timer, T310, CC_T310);
1302 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
1303 l3ni1_std_ie_err(pc, ret);
1304 pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
1307 static void
1308 l3ni1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
1310 struct sk_buff *skb = arg;
1311 int id, ret;
1313 if ((id = l3ni1_get_channel_id(pc, skb)) >= 0) {
1314 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
1315 if (pc->debug & L3_DEB_WARN)
1316 l3_debug(pc->st, "setup answer with wrong chid %x", id);
1317 pc->para.cause = 100;
1318 l3ni1_status_send(pc, pr, NULL);
1319 return;
1321 pc->para.bchannel = id;
1322 } else {
1323 if (pc->debug & L3_DEB_WARN)
1324 l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
1325 if (id == -1)
1326 pc->para.cause = 96;
1327 else
1328 pc->para.cause = 100;
1329 l3ni1_status_send(pc, pr, NULL);
1330 return;
1332 /* Now we are on none mandatory IEs */
1333 ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE);
1334 if (ERR_IE_COMPREHENSION == ret) {
1335 l3ni1_std_ie_err(pc, ret);
1336 return;
1338 L3DelTimer(&pc->timer);
1339 newl3state(pc, 2);
1340 L3AddTimer(&pc->timer, T304, CC_T304);
1341 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
1342 l3ni1_std_ie_err(pc, ret);
1343 pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
1346 static void
1347 l3ni1_disconnect(struct l3_process *pc, u_char pr, void *arg)
1349 struct sk_buff *skb = arg;
1350 u_char *p;
1351 int ret;
1352 u_char cause = 0;
1354 StopAllL3Timer(pc);
1355 if ((ret = l3ni1_get_cause(pc, skb))) {
1356 if (pc->debug & L3_DEB_WARN)
1357 l3_debug(pc->st, "DISC get_cause ret(%d)", ret);
1358 if (ret < 0)
1359 cause = 96;
1360 else if (ret > 0)
1361 cause = 100;
1363 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
1364 l3ni1_parse_facility(pc->st, pc, pc->callref, p);
1365 ret = check_infoelements(pc, skb, ie_DISCONNECT);
1366 if (ERR_IE_COMPREHENSION == ret)
1367 cause = 96;
1368 else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret))
1369 cause = 99;
1370 ret = pc->state;
1371 newl3state(pc, 12);
1372 if (cause)
1373 newl3state(pc, 19);
1374 if (11 != ret)
1375 pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
1376 else if (!cause)
1377 l3ni1_release_req(pc, pr, NULL);
1378 if (cause) {
1379 l3ni1_message_cause(pc, MT_RELEASE, cause);
1380 L3AddTimer(&pc->timer, T308, CC_T308_1);
1384 static void
1385 l3ni1_connect(struct l3_process *pc, u_char pr, void *arg)
1387 struct sk_buff *skb = arg;
1388 int ret;
1390 ret = check_infoelements(pc, skb, ie_CONNECT);
1391 if (ERR_IE_COMPREHENSION == ret) {
1392 l3ni1_std_ie_err(pc, ret);
1393 return;
1395 L3DelTimer(&pc->timer); /* T310 */
1396 newl3state(pc, 10);
1397 pc->para.chargeinfo = 0;
1398 /* here should inserted COLP handling KKe */
1399 if (ret)
1400 l3ni1_std_ie_err(pc, ret);
1401 pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
1404 static void
1405 l3ni1_alerting(struct l3_process *pc, u_char pr, void *arg)
1407 struct sk_buff *skb = arg;
1408 int ret;
1410 ret = check_infoelements(pc, skb, ie_ALERTING);
1411 if (ERR_IE_COMPREHENSION == ret) {
1412 l3ni1_std_ie_err(pc, ret);
1413 return;
1415 L3DelTimer(&pc->timer); /* T304 */
1416 newl3state(pc, 4);
1417 if (ret)
1418 l3ni1_std_ie_err(pc, ret);
1419 pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
1422 static void
1423 l3ni1_setup(struct l3_process *pc, u_char pr, void *arg)
1425 u_char *p;
1426 int bcfound = 0;
1427 char tmp[80];
1428 struct sk_buff *skb = arg;
1429 int id;
1430 int err = 0;
1433 * Bearer Capabilities
1435 p = skb->data;
1436 /* only the first occurence 'll be detected ! */
1437 if ((p = findie(p, skb->len, 0x04, 0))) {
1438 if ((p[1] < 2) || (p[1] > 11))
1439 err = 1;
1440 else {
1441 pc->para.setup.si2 = 0;
1442 switch (p[2] & 0x7f) {
1443 case 0x00: /* Speech */
1444 case 0x10: /* 3.1 Khz audio */
1445 pc->para.setup.si1 = 1;
1446 break;
1447 case 0x08: /* Unrestricted digital information */
1448 pc->para.setup.si1 = 7;
1449 /* JIM, 05.11.97 I wanna set service indicator 2 */
1450 #if EXT_BEARER_CAPS
1451 pc->para.setup.si2 = DecodeSI2(skb);
1452 #endif
1453 break;
1454 case 0x09: /* Restricted digital information */
1455 pc->para.setup.si1 = 2;
1456 break;
1457 case 0x11:
1458 /* Unrestr. digital information with
1459 * tones/announcements ( or 7 kHz audio
1461 pc->para.setup.si1 = 3;
1462 break;
1463 case 0x18: /* Video */
1464 pc->para.setup.si1 = 4;
1465 break;
1466 default:
1467 err = 2;
1468 break;
1470 switch (p[3] & 0x7f) {
1471 case 0x40: /* packed mode */
1472 pc->para.setup.si1 = 8;
1473 break;
1474 case 0x10: /* 64 kbit */
1475 case 0x11: /* 2*64 kbit */
1476 case 0x13: /* 384 kbit */
1477 case 0x15: /* 1536 kbit */
1478 case 0x17: /* 1920 kbit */
1479 pc->para.moderate = p[3] & 0x7f;
1480 break;
1481 default:
1482 err = 3;
1483 break;
1486 if (pc->debug & L3_DEB_SI)
1487 l3_debug(pc->st, "SI=%d, AI=%d",
1488 pc->para.setup.si1, pc->para.setup.si2);
1489 if (err) {
1490 if (pc->debug & L3_DEB_WARN)
1491 l3_debug(pc->st, "setup with wrong bearer(l=%d:%x,%x)",
1492 p[1], p[2], p[3]);
1493 pc->para.cause = 100;
1494 l3ni1_msg_without_setup(pc, pr, NULL);
1495 return;
1497 } else {
1498 if (pc->debug & L3_DEB_WARN)
1499 l3_debug(pc->st, "setup without bearer capabilities");
1500 /* ETS 300-104 1.3.3 */
1501 pc->para.cause = 96;
1502 l3ni1_msg_without_setup(pc, pr, NULL);
1503 return;
1506 * Channel Identification
1508 if ((id = l3ni1_get_channel_id(pc, skb)) >= 0) {
1509 if ((pc->para.bchannel = id)) {
1510 if ((3 == id) && (0x10 == pc->para.moderate)) {
1511 if (pc->debug & L3_DEB_WARN)
1512 l3_debug(pc->st, "setup with wrong chid %x",
1513 id);
1514 pc->para.cause = 100;
1515 l3ni1_msg_without_setup(pc, pr, NULL);
1516 return;
1518 bcfound++;
1519 } else
1520 { if (pc->debug & L3_DEB_WARN)
1521 l3_debug(pc->st, "setup without bchannel, call waiting");
1522 bcfound++;
1524 } else {
1525 if (pc->debug & L3_DEB_WARN)
1526 l3_debug(pc->st, "setup with wrong chid ret %d", id);
1527 if (id == -1)
1528 pc->para.cause = 96;
1529 else
1530 pc->para.cause = 100;
1531 l3ni1_msg_without_setup(pc, pr, NULL);
1532 return;
1534 /* Now we are on none mandatory IEs */
1535 err = check_infoelements(pc, skb, ie_SETUP);
1536 if (ERR_IE_COMPREHENSION == err) {
1537 pc->para.cause = 96;
1538 l3ni1_msg_without_setup(pc, pr, NULL);
1539 return;
1541 p = skb->data;
1542 if ((p = findie(p, skb->len, 0x70, 0)))
1543 iecpy(pc->para.setup.eazmsn, p, 1);
1544 else
1545 pc->para.setup.eazmsn[0] = 0;
1547 p = skb->data;
1548 if ((p = findie(p, skb->len, 0x71, 0))) {
1549 /* Called party subaddress */
1550 if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1551 tmp[0] = '.';
1552 iecpy(&tmp[1], p, 2);
1553 strcat(pc->para.setup.eazmsn, tmp);
1554 } else if (pc->debug & L3_DEB_WARN)
1555 l3_debug(pc->st, "wrong called subaddress");
1557 p = skb->data;
1558 if ((p = findie(p, skb->len, 0x6c, 0))) {
1559 pc->para.setup.plan = p[2];
1560 if (p[2] & 0x80) {
1561 iecpy(pc->para.setup.phone, p, 1);
1562 pc->para.setup.screen = 0;
1563 } else {
1564 iecpy(pc->para.setup.phone, p, 2);
1565 pc->para.setup.screen = p[3];
1567 } else {
1568 pc->para.setup.phone[0] = 0;
1569 pc->para.setup.plan = 0;
1570 pc->para.setup.screen = 0;
1572 p = skb->data;
1573 if ((p = findie(p, skb->len, 0x6d, 0))) {
1574 /* Calling party subaddress */
1575 if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1576 tmp[0] = '.';
1577 iecpy(&tmp[1], p, 2);
1578 strcat(pc->para.setup.phone, tmp);
1579 } else if (pc->debug & L3_DEB_WARN)
1580 l3_debug(pc->st, "wrong calling subaddress");
1582 newl3state(pc, 6);
1583 if (err) /* STATUS for none mandatory IE errors after actions are taken */
1584 l3ni1_std_ie_err(pc, err);
1585 pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
1588 static void
1589 l3ni1_reset(struct l3_process *pc, u_char pr, void *arg)
1591 ni1_release_l3_process(pc);
1594 static void
1595 l3ni1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
1597 struct sk_buff *skb;
1598 u_char tmp[16+40];
1599 u_char *p = tmp;
1600 int l;
1601 u_char cause = 16;
1603 if (pc->para.cause != NO_CAUSE)
1604 cause = pc->para.cause;
1606 StopAllL3Timer(pc);
1608 MsgHead(p, pc->callref, MT_DISCONNECT);
1610 *p++ = IE_CAUSE;
1611 *p++ = 0x2;
1612 *p++ = 0x80;
1613 *p++ = cause | 0x80;
1615 if (pc->prot.ni1.uus1_data[0])
1616 { *p++ = IE_USER_USER; /* UUS info element */
1617 *p++ = strlen(pc->prot.ni1.uus1_data) + 1;
1618 *p++ = 0x04; /* IA5 chars */
1619 strcpy(p,pc->prot.ni1.uus1_data);
1620 p += strlen(pc->prot.ni1.uus1_data);
1621 pc->prot.ni1.uus1_data[0] = '\0';
1624 l = p - tmp;
1625 if (!(skb = l3_alloc_skb(l)))
1626 return;
1627 memcpy(skb_put(skb, l), tmp, l);
1628 newl3state(pc, 11);
1629 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1630 L3AddTimer(&pc->timer, T305, CC_T305);
1633 static void
1634 l3ni1_setup_rsp(struct l3_process *pc, u_char pr,
1635 void *arg)
1637 if (!pc->para.bchannel)
1638 { if (pc->debug & L3_DEB_WARN)
1639 l3_debug(pc->st, "D-chan connect for waiting call");
1640 l3ni1_disconnect_req(pc, pr, arg);
1641 return;
1643 newl3state(pc, 8);
1644 l3ni1_message(pc, MT_CONNECT);
1645 L3DelTimer(&pc->timer);
1646 L3AddTimer(&pc->timer, T313, CC_T313);
1649 static void
1650 l3ni1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
1652 struct sk_buff *skb = arg;
1653 int ret;
1655 ret = check_infoelements(pc, skb, ie_CONNECT_ACKNOWLEDGE);
1656 if (ERR_IE_COMPREHENSION == ret) {
1657 l3ni1_std_ie_err(pc, ret);
1658 return;
1660 newl3state(pc, 10);
1661 L3DelTimer(&pc->timer);
1662 if (ret)
1663 l3ni1_std_ie_err(pc, ret);
1664 pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
1667 static void
1668 l3ni1_reject_req(struct l3_process *pc, u_char pr, void *arg)
1670 struct sk_buff *skb;
1671 u_char tmp[16];
1672 u_char *p = tmp;
1673 int l;
1674 u_char cause = 21;
1676 if (pc->para.cause != NO_CAUSE)
1677 cause = pc->para.cause;
1679 MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
1681 *p++ = IE_CAUSE;
1682 *p++ = 0x2;
1683 *p++ = 0x80;
1684 *p++ = cause | 0x80;
1686 l = p - tmp;
1687 if (!(skb = l3_alloc_skb(l)))
1688 return;
1689 memcpy(skb_put(skb, l), tmp, l);
1690 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1691 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1692 newl3state(pc, 0);
1693 ni1_release_l3_process(pc);
1696 static void
1697 l3ni1_release(struct l3_process *pc, u_char pr, void *arg)
1699 struct sk_buff *skb = arg;
1700 u_char *p;
1701 int ret, cause=0;
1703 StopAllL3Timer(pc);
1704 if ((ret = l3ni1_get_cause(pc, skb))>0) {
1705 if (pc->debug & L3_DEB_WARN)
1706 l3_debug(pc->st, "REL get_cause ret(%d)", ret);
1707 } else if (ret<0)
1708 pc->para.cause = NO_CAUSE;
1709 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
1710 l3ni1_parse_facility(pc->st, pc, pc->callref, p);
1712 if ((ret<0) && (pc->state != 11))
1713 cause = 96;
1714 else if (ret>0)
1715 cause = 100;
1716 ret = check_infoelements(pc, skb, ie_RELEASE);
1717 if (ERR_IE_COMPREHENSION == ret)
1718 cause = 96;
1719 else if ((ERR_IE_UNRECOGNIZED == ret) && (!cause))
1720 cause = 99;
1721 if (cause)
1722 l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
1723 else
1724 l3ni1_message(pc, MT_RELEASE_COMPLETE);
1725 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1726 newl3state(pc, 0);
1727 ni1_release_l3_process(pc);
1730 static void
1731 l3ni1_alert_req(struct l3_process *pc, u_char pr,
1732 void *arg)
1734 newl3state(pc, 7);
1735 if (!pc->prot.ni1.uus1_data[0])
1736 l3ni1_message(pc, MT_ALERTING);
1737 else
1738 l3ni1_msg_with_uus(pc, MT_ALERTING);
1741 static void
1742 l3ni1_proceed_req(struct l3_process *pc, u_char pr,
1743 void *arg)
1745 newl3state(pc, 9);
1746 l3ni1_message(pc, MT_CALL_PROCEEDING);
1747 pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc);
1750 static void
1751 l3ni1_setup_ack_req(struct l3_process *pc, u_char pr,
1752 void *arg)
1754 newl3state(pc, 25);
1755 L3DelTimer(&pc->timer);
1756 L3AddTimer(&pc->timer, T302, CC_T302);
1757 l3ni1_message(pc, MT_SETUP_ACKNOWLEDGE);
1760 /********************************************/
1761 /* deliver a incoming display message to HL */
1762 /********************************************/
1763 static void
1764 l3ni1_deliver_display(struct l3_process *pc, int pr, u_char *infp)
1765 { u_char len;
1766 isdn_ctrl ic;
1767 struct IsdnCardState *cs;
1768 char *p;
1770 if (*infp++ != IE_DISPLAY) return;
1771 if ((len = *infp++) > 80) return; /* total length <= 82 */
1772 if (!pc->chan) return;
1774 p = ic.parm.display;
1775 while (len--)
1776 *p++ = *infp++;
1777 *p = '\0';
1778 ic.command = ISDN_STAT_DISPLAY;
1779 cs = pc->st->l1.hardware;
1780 ic.driver = cs->myid;
1781 ic.arg = pc->chan->chan;
1782 cs->iif.statcallb(&ic);
1783 } /* l3ni1_deliver_display */
1786 static void
1787 l3ni1_progress(struct l3_process *pc, u_char pr, void *arg)
1789 struct sk_buff *skb = arg;
1790 int err = 0;
1791 u_char *p;
1793 if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) {
1794 if (p[1] != 2) {
1795 err = 1;
1796 pc->para.cause = 100;
1797 } else if (!(p[2] & 0x70)) {
1798 switch (p[2]) {
1799 case 0x80:
1800 case 0x81:
1801 case 0x82:
1802 case 0x84:
1803 case 0x85:
1804 case 0x87:
1805 case 0x8a:
1806 switch (p[3]) {
1807 case 0x81:
1808 case 0x82:
1809 case 0x83:
1810 case 0x84:
1811 case 0x88:
1812 break;
1813 default:
1814 err = 2;
1815 pc->para.cause = 100;
1816 break;
1818 break;
1819 default:
1820 err = 3;
1821 pc->para.cause = 100;
1822 break;
1825 } else {
1826 pc->para.cause = 96;
1827 err = 4;
1829 if (err) {
1830 if (pc->debug & L3_DEB_WARN)
1831 l3_debug(pc->st, "progress error %d", err);
1832 l3ni1_status_send(pc, pr, NULL);
1833 return;
1835 /* Now we are on none mandatory IEs */
1836 err = check_infoelements(pc, skb, ie_PROGRESS);
1837 if (err)
1838 l3ni1_std_ie_err(pc, err);
1839 if (ERR_IE_COMPREHENSION != err)
1840 pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc);
1843 static void
1844 l3ni1_notify(struct l3_process *pc, u_char pr, void *arg)
1846 struct sk_buff *skb = arg;
1847 int err = 0;
1848 u_char *p;
1850 if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) {
1851 if (p[1] != 1) {
1852 err = 1;
1853 pc->para.cause = 100;
1854 } else {
1855 switch (p[2]) {
1856 case 0x80:
1857 case 0x81:
1858 case 0x82:
1859 break;
1860 default:
1861 pc->para.cause = 100;
1862 err = 2;
1863 break;
1866 } else {
1867 pc->para.cause = 96;
1868 err = 3;
1870 if (err) {
1871 if (pc->debug & L3_DEB_WARN)
1872 l3_debug(pc->st, "notify error %d", err);
1873 l3ni1_status_send(pc, pr, NULL);
1874 return;
1876 /* Now we are on none mandatory IEs */
1877 err = check_infoelements(pc, skb, ie_NOTIFY);
1878 if (err)
1879 l3ni1_std_ie_err(pc, err);
1880 if (ERR_IE_COMPREHENSION != err)
1881 pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc);
1884 static void
1885 l3ni1_status_enq(struct l3_process *pc, u_char pr, void *arg)
1887 int ret;
1888 struct sk_buff *skb = arg;
1890 ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY);
1891 l3ni1_std_ie_err(pc, ret);
1892 pc->para.cause = 30; /* response to STATUS_ENQUIRY */
1893 l3ni1_status_send(pc, pr, NULL);
1896 static void
1897 l3ni1_information(struct l3_process *pc, u_char pr, void *arg)
1899 int ret;
1900 struct sk_buff *skb = arg;
1901 u_char *p;
1902 char tmp[32];
1904 ret = check_infoelements(pc, skb, ie_INFORMATION);
1905 if (ret)
1906 l3ni1_std_ie_err(pc, ret);
1907 if (pc->state == 25) { /* overlap receiving */
1908 L3DelTimer(&pc->timer);
1909 p = skb->data;
1910 if ((p = findie(p, skb->len, 0x70, 0))) {
1911 iecpy(tmp, p, 1);
1912 strcat(pc->para.setup.eazmsn, tmp);
1913 pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
1915 L3AddTimer(&pc->timer, T302, CC_T302);
1919 /******************************/
1920 /* handle deflection requests */
1921 /******************************/
1922 static void l3ni1_redir_req(struct l3_process *pc, u_char pr, void *arg)
1924 struct sk_buff *skb;
1925 u_char tmp[128];
1926 u_char *p = tmp;
1927 u_char *subp;
1928 u_char len_phone = 0;
1929 u_char len_sub = 0;
1930 int l;
1933 strcpy(pc->prot.ni1.uus1_data,pc->chan->setup.eazmsn); /* copy uus element if available */
1934 if (!pc->chan->setup.phone[0])
1935 { pc->para.cause = -1;
1936 l3ni1_disconnect_req(pc,pr,arg); /* disconnect immediately */
1937 return;
1938 } /* only uus */
1940 if (pc->prot.ni1.invoke_id)
1941 free_invoke_id(pc->st,pc->prot.ni1.invoke_id);
1943 if (!(pc->prot.ni1.invoke_id = new_invoke_id(pc->st)))
1944 return;
1946 MsgHead(p, pc->callref, MT_FACILITY);
1948 for (subp = pc->chan->setup.phone; (*subp) && (*subp != '.'); subp++) len_phone++; /* len of phone number */
1949 if (*subp++ == '.') len_sub = strlen(subp) + 2; /* length including info subadress element */
1951 *p++ = 0x1c; /* Facility info element */
1952 *p++ = len_phone + len_sub + 2 + 2 + 8 + 3 + 3; /* length of element */
1953 *p++ = 0x91; /* remote operations protocol */
1954 *p++ = 0xa1; /* invoke component */
1956 *p++ = len_phone + len_sub + 2 + 2 + 8 + 3; /* length of data */
1957 *p++ = 0x02; /* invoke id tag, integer */
1958 *p++ = 0x01; /* length */
1959 *p++ = pc->prot.ni1.invoke_id; /* invoke id */
1960 *p++ = 0x02; /* operation value tag, integer */
1961 *p++ = 0x01; /* length */
1962 *p++ = 0x0D; /* Call Deflect */
1964 *p++ = 0x30; /* sequence phone number */
1965 *p++ = len_phone + 2 + 2 + 3 + len_sub; /* length */
1967 *p++ = 0x30; /* Deflected to UserNumber */
1968 *p++ = len_phone+2+len_sub; /* length */
1969 *p++ = 0x80; /* NumberDigits */
1970 *p++ = len_phone; /* length */
1971 for (l = 0; l < len_phone; l++)
1972 *p++ = pc->chan->setup.phone[l];
1974 if (len_sub)
1975 { *p++ = 0x04; /* called party subadress */
1976 *p++ = len_sub - 2;
1977 while (*subp) *p++ = *subp++;
1980 *p++ = 0x01; /* screening identifier */
1981 *p++ = 0x01;
1982 *p++ = pc->chan->setup.screen;
1984 l = p - tmp;
1985 if (!(skb = l3_alloc_skb(l))) return;
1986 memcpy(skb_put(skb, l), tmp, l);
1988 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1989 } /* l3ni1_redir_req */
1991 /********************************************/
1992 /* handle deflection request in early state */
1993 /********************************************/
1994 static void l3ni1_redir_req_early(struct l3_process *pc, u_char pr, void *arg)
1996 l3ni1_proceed_req(pc,pr,arg);
1997 l3ni1_redir_req(pc,pr,arg);
1998 } /* l3ni1_redir_req_early */
2000 /***********************************************/
2001 /* handle special commands for this protocol. */
2002 /* Examples are call independant services like */
2003 /* remote operations with dummy callref. */
2004 /***********************************************/
2005 static int l3ni1_cmd_global(struct PStack *st, isdn_ctrl *ic)
2006 { u_char id;
2007 u_char temp[265];
2008 u_char *p = temp;
2009 int i, l, proc_len;
2010 struct sk_buff *skb;
2011 struct l3_process *pc = NULL;
2013 switch (ic->arg)
2014 { case NI1_CMD_INVOKE:
2015 if (ic->parm.ni1_io.datalen < 0) return(-2); /* invalid parameter */
2017 for (proc_len = 1, i = ic->parm.ni1_io.proc >> 8; i; i++)
2018 i = i >> 8; /* add one byte */
2019 l = ic->parm.ni1_io.datalen + proc_len + 8; /* length excluding ie header */
2020 if (l > 255)
2021 return(-2); /* too long */
2023 if (!(id = new_invoke_id(st)))
2024 return(0); /* first get a invoke id -> return if no available */
2026 i = -1;
2027 MsgHead(p, i, MT_FACILITY); /* build message head */
2028 *p++ = 0x1C; /* Facility IE */
2029 *p++ = l; /* length of ie */
2030 *p++ = 0x91; /* remote operations */
2031 *p++ = 0xA1; /* invoke */
2032 *p++ = l - 3; /* length of invoke */
2033 *p++ = 0x02; /* invoke id tag */
2034 *p++ = 0x01; /* length is 1 */
2035 *p++ = id; /* invoke id */
2036 *p++ = 0x02; /* operation */
2037 *p++ = proc_len; /* length of operation */
2039 for (i = proc_len; i; i--)
2040 *p++ = (ic->parm.ni1_io.proc >> (i-1)) & 0xFF;
2041 memcpy(p, ic->parm.ni1_io.data, ic->parm.ni1_io.datalen); /* copy data */
2042 l = (p - temp) + ic->parm.ni1_io.datalen; /* total length */
2044 if (ic->parm.ni1_io.timeout > 0)
2045 if (!(pc = ni1_new_l3_process(st, -1)))
2046 { free_invoke_id(st, id);
2047 return(-2);
2049 pc->prot.ni1.ll_id = ic->parm.ni1_io.ll_id; /* remember id */
2050 pc->prot.ni1.proc = ic->parm.ni1_io.proc; /* and procedure */
2052 if (!(skb = l3_alloc_skb(l)))
2053 { free_invoke_id(st, id);
2054 if (pc) ni1_release_l3_process(pc);
2055 return(-2);
2057 memcpy(skb_put(skb, l), temp, l);
2059 if (pc)
2060 { pc->prot.ni1.invoke_id = id; /* remember id */
2061 L3AddTimer(&pc->timer, ic->parm.ni1_io.timeout, CC_TNI1_IO | REQUEST);
2064 l3_msg(st, DL_DATA | REQUEST, skb);
2065 ic->parm.ni1_io.hl_id = id; /* return id */
2066 return(0);
2068 case NI1_CMD_INVOKE_ABORT:
2069 if ((pc = l3ni1_search_dummy_proc(st, ic->parm.ni1_io.hl_id)))
2070 { L3DelTimer(&pc->timer); /* remove timer */
2071 ni1_release_l3_process(pc);
2072 return(0);
2074 else
2075 { l3_debug(st, "l3ni1_cmd_global abort unknown id");
2076 return(-2);
2078 break;
2080 default:
2081 l3_debug(st, "l3ni1_cmd_global unknown cmd 0x%lx", ic->arg);
2082 return(-1);
2083 } /* switch ic-> arg */
2084 return(-1);
2085 } /* l3ni1_cmd_global */
2087 static void
2088 l3ni1_io_timer(struct l3_process *pc)
2089 { isdn_ctrl ic;
2090 struct IsdnCardState *cs = pc->st->l1.hardware;
2092 L3DelTimer(&pc->timer); /* remove timer */
2094 ic.driver = cs->myid;
2095 ic.command = ISDN_STAT_PROT;
2096 ic.arg = NI1_STAT_INVOKE_ERR;
2097 ic.parm.ni1_io.hl_id = pc->prot.ni1.invoke_id;
2098 ic.parm.ni1_io.ll_id = pc->prot.ni1.ll_id;
2099 ic.parm.ni1_io.proc = pc->prot.ni1.proc;
2100 ic.parm.ni1_io.timeout= -1;
2101 ic.parm.ni1_io.datalen = 0;
2102 ic.parm.ni1_io.data = NULL;
2103 free_invoke_id(pc->st, pc->prot.ni1.invoke_id);
2104 pc->prot.ni1.invoke_id = 0; /* reset id */
2106 cs->iif.statcallb(&ic);
2108 ni1_release_l3_process(pc);
2109 } /* l3ni1_io_timer */
2111 static void
2112 l3ni1_release_ind(struct l3_process *pc, u_char pr, void *arg)
2114 u_char *p;
2115 struct sk_buff *skb = arg;
2116 int callState = 0;
2117 p = skb->data;
2119 if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
2120 p++;
2121 if (1 == *p++)
2122 callState = *p;
2124 if (callState == 0) {
2125 /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
2126 * set down layer 3 without sending any message
2128 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2129 newl3state(pc, 0);
2130 ni1_release_l3_process(pc);
2131 } else {
2132 pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
2136 static void
2137 l3ni1_dummy(struct l3_process *pc, u_char pr, void *arg)
2141 static void
2142 l3ni1_t302(struct l3_process *pc, u_char pr, void *arg)
2144 L3DelTimer(&pc->timer);
2145 pc->para.loc = 0;
2146 pc->para.cause = 28; /* invalid number */
2147 l3ni1_disconnect_req(pc, pr, NULL);
2148 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2151 static void
2152 l3ni1_t303(struct l3_process *pc, u_char pr, void *arg)
2154 if (pc->N303 > 0) {
2155 pc->N303--;
2156 L3DelTimer(&pc->timer);
2157 l3ni1_setup_req(pc, pr, arg);
2158 } else {
2159 L3DelTimer(&pc->timer);
2160 l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, 102);
2161 pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
2162 ni1_release_l3_process(pc);
2166 static void
2167 l3ni1_t304(struct l3_process *pc, u_char pr, void *arg)
2169 L3DelTimer(&pc->timer);
2170 pc->para.loc = 0;
2171 pc->para.cause = 102;
2172 l3ni1_disconnect_req(pc, pr, NULL);
2173 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2177 static void
2178 l3ni1_t305(struct l3_process *pc, u_char pr, void *arg)
2180 u_char tmp[16];
2181 u_char *p = tmp;
2182 int l;
2183 struct sk_buff *skb;
2184 u_char cause = 16;
2186 L3DelTimer(&pc->timer);
2187 if (pc->para.cause != NO_CAUSE)
2188 cause = pc->para.cause;
2190 MsgHead(p, pc->callref, MT_RELEASE);
2192 *p++ = IE_CAUSE;
2193 *p++ = 0x2;
2194 *p++ = 0x80;
2195 *p++ = cause | 0x80;
2197 l = p - tmp;
2198 if (!(skb = l3_alloc_skb(l)))
2199 return;
2200 memcpy(skb_put(skb, l), tmp, l);
2201 newl3state(pc, 19);
2202 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2203 L3AddTimer(&pc->timer, T308, CC_T308_1);
2206 static void
2207 l3ni1_t310(struct l3_process *pc, u_char pr, void *arg)
2209 L3DelTimer(&pc->timer);
2210 pc->para.loc = 0;
2211 pc->para.cause = 102;
2212 l3ni1_disconnect_req(pc, pr, NULL);
2213 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2216 static void
2217 l3ni1_t313(struct l3_process *pc, u_char pr, void *arg)
2219 L3DelTimer(&pc->timer);
2220 pc->para.loc = 0;
2221 pc->para.cause = 102;
2222 l3ni1_disconnect_req(pc, pr, NULL);
2223 pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
2226 static void
2227 l3ni1_t308_1(struct l3_process *pc, u_char pr, void *arg)
2229 newl3state(pc, 19);
2230 L3DelTimer(&pc->timer);
2231 l3ni1_message(pc, MT_RELEASE);
2232 L3AddTimer(&pc->timer, T308, CC_T308_2);
2235 static void
2236 l3ni1_t308_2(struct l3_process *pc, u_char pr, void *arg)
2238 L3DelTimer(&pc->timer);
2239 pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
2240 ni1_release_l3_process(pc);
2243 static void
2244 l3ni1_t318(struct l3_process *pc, u_char pr, void *arg)
2246 L3DelTimer(&pc->timer);
2247 pc->para.cause = 102; /* Timer expiry */
2248 pc->para.loc = 0; /* local */
2249 pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
2250 newl3state(pc, 19);
2251 l3ni1_message(pc, MT_RELEASE);
2252 L3AddTimer(&pc->timer, T308, CC_T308_1);
2255 static void
2256 l3ni1_t319(struct l3_process *pc, u_char pr, void *arg)
2258 L3DelTimer(&pc->timer);
2259 pc->para.cause = 102; /* Timer expiry */
2260 pc->para.loc = 0; /* local */
2261 pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
2262 newl3state(pc, 10);
2265 static void
2266 l3ni1_restart(struct l3_process *pc, u_char pr, void *arg)
2268 L3DelTimer(&pc->timer);
2269 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2270 ni1_release_l3_process(pc);
2273 static void
2274 l3ni1_status(struct l3_process *pc, u_char pr, void *arg)
2276 u_char *p;
2277 struct sk_buff *skb = arg;
2278 int ret;
2279 u_char cause = 0, callState = 0;
2281 if ((ret = l3ni1_get_cause(pc, skb))) {
2282 if (pc->debug & L3_DEB_WARN)
2283 l3_debug(pc->st, "STATUS get_cause ret(%d)",ret);
2284 if (ret < 0)
2285 cause = 96;
2286 else if (ret > 0)
2287 cause = 100;
2289 if ((p = findie(skb->data, skb->len, IE_CALL_STATE, 0))) {
2290 p++;
2291 if (1 == *p++) {
2292 callState = *p;
2293 if (!ie_in_set(pc, *p, l3_valid_states))
2294 cause = 100;
2295 } else
2296 cause = 100;
2297 } else
2298 cause = 96;
2299 if (!cause) { /* no error before */
2300 ret = check_infoelements(pc, skb, ie_STATUS);
2301 if (ERR_IE_COMPREHENSION == ret)
2302 cause = 96;
2303 else if (ERR_IE_UNRECOGNIZED == ret)
2304 cause = 99;
2306 if (cause) {
2307 u_char tmp;
2309 if (pc->debug & L3_DEB_WARN)
2310 l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause);
2311 tmp = pc->para.cause;
2312 pc->para.cause = cause;
2313 l3ni1_status_send(pc, 0, NULL);
2314 if (cause == 99)
2315 pc->para.cause = tmp;
2316 else
2317 return;
2319 cause = pc->para.cause;
2320 if (((cause & 0x7f) == 111) && (callState == 0)) {
2321 /* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
2322 * if received MT_STATUS with cause == 111 and call
2323 * state == 0, then we must set down layer 3
2325 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2326 newl3state(pc, 0);
2327 ni1_release_l3_process(pc);
2331 static void
2332 l3ni1_facility(struct l3_process *pc, u_char pr, void *arg)
2334 struct sk_buff *skb = arg;
2335 int ret;
2337 ret = check_infoelements(pc, skb, ie_FACILITY);
2338 l3ni1_std_ie_err(pc, ret);
2340 u_char *p;
2341 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
2342 l3ni1_parse_facility(pc->st, pc, pc->callref, p);
2346 static void
2347 l3ni1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
2349 struct sk_buff *skb;
2350 u_char tmp[32];
2351 u_char *p = tmp;
2352 u_char i, l;
2353 u_char *msg = pc->chan->setup.phone;
2355 MsgHead(p, pc->callref, MT_SUSPEND);
2356 l = *msg++;
2357 if (l && (l <= 10)) { /* Max length 10 octets */
2358 *p++ = IE_CALL_ID;
2359 *p++ = l;
2360 for (i = 0; i < l; i++)
2361 *p++ = *msg++;
2362 } else if (l) {
2363 l3_debug(pc->st, "SUS wrong CALL_ID len %d", l);
2364 return;
2366 l = p - tmp;
2367 if (!(skb = l3_alloc_skb(l)))
2368 return;
2369 memcpy(skb_put(skb, l), tmp, l);
2370 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2371 newl3state(pc, 15);
2372 L3AddTimer(&pc->timer, T319, CC_T319);
2375 static void
2376 l3ni1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
2378 struct sk_buff *skb = arg;
2379 int ret;
2381 L3DelTimer(&pc->timer);
2382 newl3state(pc, 0);
2383 pc->para.cause = NO_CAUSE;
2384 pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
2385 /* We don't handle suspend_ack for IE errors now */
2386 if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE)))
2387 if (pc->debug & L3_DEB_WARN)
2388 l3_debug(pc->st, "SUSPACK check ie(%d)",ret);
2389 ni1_release_l3_process(pc);
2392 static void
2393 l3ni1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
2395 struct sk_buff *skb = arg;
2396 int ret;
2398 if ((ret = l3ni1_get_cause(pc, skb))) {
2399 if (pc->debug & L3_DEB_WARN)
2400 l3_debug(pc->st, "SUSP_REJ get_cause ret(%d)",ret);
2401 if (ret < 0)
2402 pc->para.cause = 96;
2403 else
2404 pc->para.cause = 100;
2405 l3ni1_status_send(pc, pr, NULL);
2406 return;
2408 ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT);
2409 if (ERR_IE_COMPREHENSION == ret) {
2410 l3ni1_std_ie_err(pc, ret);
2411 return;
2413 L3DelTimer(&pc->timer);
2414 pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
2415 newl3state(pc, 10);
2416 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2417 l3ni1_std_ie_err(pc, ret);
2420 static void
2421 l3ni1_resume_req(struct l3_process *pc, u_char pr, void *arg)
2423 struct sk_buff *skb;
2424 u_char tmp[32];
2425 u_char *p = tmp;
2426 u_char i, l;
2427 u_char *msg = pc->para.setup.phone;
2429 MsgHead(p, pc->callref, MT_RESUME);
2431 l = *msg++;
2432 if (l && (l <= 10)) { /* Max length 10 octets */
2433 *p++ = IE_CALL_ID;
2434 *p++ = l;
2435 for (i = 0; i < l; i++)
2436 *p++ = *msg++;
2437 } else if (l) {
2438 l3_debug(pc->st, "RES wrong CALL_ID len %d", l);
2439 return;
2441 l = p - tmp;
2442 if (!(skb = l3_alloc_skb(l)))
2443 return;
2444 memcpy(skb_put(skb, l), tmp, l);
2445 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2446 newl3state(pc, 17);
2447 L3AddTimer(&pc->timer, T318, CC_T318);
2450 static void
2451 l3ni1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
2453 struct sk_buff *skb = arg;
2454 int id, ret;
2456 if ((id = l3ni1_get_channel_id(pc, skb)) > 0) {
2457 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
2458 if (pc->debug & L3_DEB_WARN)
2459 l3_debug(pc->st, "resume ack with wrong chid %x", id);
2460 pc->para.cause = 100;
2461 l3ni1_status_send(pc, pr, NULL);
2462 return;
2464 pc->para.bchannel = id;
2465 } else if (1 == pc->state) {
2466 if (pc->debug & L3_DEB_WARN)
2467 l3_debug(pc->st, "resume ack without chid (ret %d)", id);
2468 pc->para.cause = 96;
2469 l3ni1_status_send(pc, pr, NULL);
2470 return;
2472 ret = check_infoelements(pc, skb, ie_RESUME_ACKNOWLEDGE);
2473 if (ERR_IE_COMPREHENSION == ret) {
2474 l3ni1_std_ie_err(pc, ret);
2475 return;
2477 L3DelTimer(&pc->timer);
2478 pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
2479 newl3state(pc, 10);
2480 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2481 l3ni1_std_ie_err(pc, ret);
2484 static void
2485 l3ni1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
2487 struct sk_buff *skb = arg;
2488 int ret;
2490 if ((ret = l3ni1_get_cause(pc, skb))) {
2491 if (pc->debug & L3_DEB_WARN)
2492 l3_debug(pc->st, "RES_REJ get_cause ret(%d)",ret);
2493 if (ret < 0)
2494 pc->para.cause = 96;
2495 else
2496 pc->para.cause = 100;
2497 l3ni1_status_send(pc, pr, NULL);
2498 return;
2500 ret = check_infoelements(pc, skb, ie_RESUME_REJECT);
2501 if (ERR_IE_COMPREHENSION == ret) {
2502 l3ni1_std_ie_err(pc, ret);
2503 return;
2505 L3DelTimer(&pc->timer);
2506 pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
2507 newl3state(pc, 0);
2508 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2509 l3ni1_std_ie_err(pc, ret);
2510 ni1_release_l3_process(pc);
2513 static void
2514 l3ni1_global_restart(struct l3_process *pc, u_char pr, void *arg)
2516 u_char tmp[32];
2517 u_char *p;
2518 u_char ri, ch = 0, chan = 0;
2519 int l;
2520 struct sk_buff *skb = arg;
2521 struct l3_process *up;
2523 newl3state(pc, 2);
2524 L3DelTimer(&pc->timer);
2525 p = skb->data;
2526 if ((p = findie(p, skb->len, IE_RESTART_IND, 0))) {
2527 ri = p[2];
2528 l3_debug(pc->st, "Restart %x", ri);
2529 } else {
2530 l3_debug(pc->st, "Restart without restart IE");
2531 ri = 0x86;
2533 p = skb->data;
2534 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
2535 chan = p[2] & 3;
2536 ch = p[2];
2537 if (pc->st->l3.debug)
2538 l3_debug(pc->st, "Restart for channel %d", chan);
2540 newl3state(pc, 2);
2541 up = pc->st->l3.proc;
2542 while (up) {
2543 if ((ri & 7) == 7)
2544 up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
2545 else if (up->para.bchannel == chan)
2546 up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
2547 up = up->next;
2549 p = tmp;
2550 MsgHead(p, pc->callref, MT_RESTART_ACKNOWLEDGE);
2551 if (chan) {
2552 *p++ = IE_CHANNEL_ID;
2553 *p++ = 1;
2554 *p++ = ch | 0x80;
2556 *p++ = 0x79; /* RESTART Ind */
2557 *p++ = 1;
2558 *p++ = ri;
2559 l = p - tmp;
2560 if (!(skb = l3_alloc_skb(l)))
2561 return;
2562 memcpy(skb_put(skb, l), tmp, l);
2563 newl3state(pc, 0);
2564 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2567 static void
2568 l3ni1_dl_reset(struct l3_process *pc, u_char pr, void *arg)
2570 pc->para.cause = 0x29; /* Temporary failure */
2571 pc->para.loc = 0;
2572 l3ni1_disconnect_req(pc, pr, NULL);
2573 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2576 static void
2577 l3ni1_dl_release(struct l3_process *pc, u_char pr, void *arg)
2579 newl3state(pc, 0);
2580 pc->para.cause = 0x1b; /* Destination out of order */
2581 pc->para.loc = 0;
2582 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2583 release_l3_process(pc);
2586 static void
2587 l3ni1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg)
2589 L3DelTimer(&pc->timer);
2590 L3AddTimer(&pc->timer, T309, CC_T309);
2591 l3_msg(pc->st, DL_ESTABLISH | REQUEST, NULL);
2594 static void
2595 l3ni1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg)
2597 L3DelTimer(&pc->timer);
2599 pc->para.cause = 0x1F; /* normal, unspecified */
2600 l3ni1_status_send(pc, 0, NULL);
2603 static void l3ni1_SendSpid( struct l3_process *pc, u_char pr, struct sk_buff *skb, int iNewState )
2605 u_char * p;
2606 char * pSPID;
2607 struct Channel * pChan = pc->st->lli.userdata;
2608 int l;
2610 if ( skb )
2611 dev_kfree_skb( skb);
2613 if ( !( pSPID = strchr( pChan->setup.eazmsn, ':' ) ) )
2615 printk( KERN_ERR "SPID not supplied in EAZMSN %s\n", pChan->setup.eazmsn );
2616 newl3state( pc, 0 );
2617 pc->st->l3.l3l2( pc->st, DL_RELEASE | REQUEST, NULL );
2618 return;
2621 l = strlen( ++pSPID );
2622 if ( !( skb = l3_alloc_skb( 5+l ) ) )
2624 printk( KERN_ERR "HiSax can't get memory to send SPID\n" );
2625 return;
2628 p = skb_put( skb, 5 );
2629 *p++ = PROTO_DIS_EURO;
2630 *p++ = 0;
2631 *p++ = MT_INFORMATION;
2632 *p++ = IE_SPID;
2633 *p++ = l;
2635 memcpy( skb_put( skb, l ), pSPID, l );
2637 newl3state( pc, iNewState );
2639 L3DelTimer( &pc->timer );
2640 L3AddTimer( &pc->timer, TSPID, CC_TSPID );
2642 pc->st->l3.l3l2( pc->st, DL_DATA | REQUEST, skb );
2645 static void l3ni1_spid_send( struct l3_process *pc, u_char pr, void *arg )
2647 l3ni1_SendSpid( pc, pr, arg, 20 );
2650 void l3ni1_spid_epid( struct l3_process *pc, u_char pr, void *arg )
2652 struct sk_buff *skb = arg;
2654 if ( skb->data[ 1 ] == 0 )
2655 if ( skb->data[ 3 ] == IE_ENDPOINT_ID )
2657 L3DelTimer( &pc->timer );
2658 newl3state( pc, 0 );
2659 l3_msg( pc->st, DL_ESTABLISH | CONFIRM, NULL );
2661 dev_kfree_skb( skb);
2664 static void l3ni1_spid_tout( struct l3_process *pc, u_char pr, void *arg )
2666 if ( pc->state < 22 )
2667 l3ni1_SendSpid( pc, pr, arg, pc->state+1 );
2668 else
2670 L3DelTimer( &pc->timer );
2671 dev_kfree_skb( arg);
2673 printk( KERN_ERR "SPID not accepted\n" );
2674 newl3state( pc, 0 );
2675 pc->st->l3.l3l2( pc->st, DL_RELEASE | REQUEST, NULL );
2679 /* *INDENT-OFF* */
2680 static struct stateentry downstatelist[] =
2682 {SBIT(0),
2683 CC_SETUP | REQUEST, l3ni1_setup_req},
2684 {SBIT(0),
2685 CC_RESUME | REQUEST, l3ni1_resume_req},
2686 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(25),
2687 CC_DISCONNECT | REQUEST, l3ni1_disconnect_req},
2688 {SBIT(12),
2689 CC_RELEASE | REQUEST, l3ni1_release_req},
2690 {ALL_STATES,
2691 CC_RESTART | REQUEST, l3ni1_restart},
2692 {SBIT(6) | SBIT(25),
2693 CC_IGNORE | REQUEST, l3ni1_reset},
2694 {SBIT(6) | SBIT(25),
2695 CC_REJECT | REQUEST, l3ni1_reject_req},
2696 {SBIT(6) | SBIT(25),
2697 CC_PROCEED_SEND | REQUEST, l3ni1_proceed_req},
2698 {SBIT(6),
2699 CC_MORE_INFO | REQUEST, l3ni1_setup_ack_req},
2700 {SBIT(25),
2701 CC_MORE_INFO | REQUEST, l3ni1_dummy},
2702 {SBIT(6) | SBIT(9) | SBIT(25),
2703 CC_ALERTING | REQUEST, l3ni1_alert_req},
2704 {SBIT(6) | SBIT(7) | SBIT(9) | SBIT(25),
2705 CC_SETUP | RESPONSE, l3ni1_setup_rsp},
2706 {SBIT(10),
2707 CC_SUSPEND | REQUEST, l3ni1_suspend_req},
2708 {SBIT(7) | SBIT(9) | SBIT(25),
2709 CC_REDIR | REQUEST, l3ni1_redir_req},
2710 {SBIT(6),
2711 CC_REDIR | REQUEST, l3ni1_redir_req_early},
2712 {SBIT(9) | SBIT(25),
2713 CC_DISCONNECT | REQUEST, l3ni1_disconnect_req},
2714 {SBIT(25),
2715 CC_T302, l3ni1_t302},
2716 {SBIT(1),
2717 CC_T303, l3ni1_t303},
2718 {SBIT(2),
2719 CC_T304, l3ni1_t304},
2720 {SBIT(3),
2721 CC_T310, l3ni1_t310},
2722 {SBIT(8),
2723 CC_T313, l3ni1_t313},
2724 {SBIT(11),
2725 CC_T305, l3ni1_t305},
2726 {SBIT(15),
2727 CC_T319, l3ni1_t319},
2728 {SBIT(17),
2729 CC_T318, l3ni1_t318},
2730 {SBIT(19),
2731 CC_T308_1, l3ni1_t308_1},
2732 {SBIT(19),
2733 CC_T308_2, l3ni1_t308_2},
2734 {SBIT(10),
2735 CC_T309, l3ni1_dl_release},
2736 { SBIT( 20 ) | SBIT( 21 ) | SBIT( 22 ),
2737 CC_TSPID, l3ni1_spid_tout },
2740 #define DOWNSLLEN \
2741 (sizeof(downstatelist) / sizeof(struct stateentry))
2743 static struct stateentry datastatelist[] =
2745 {ALL_STATES,
2746 MT_STATUS_ENQUIRY, l3ni1_status_enq},
2747 {ALL_STATES,
2748 MT_FACILITY, l3ni1_facility},
2749 {SBIT(19),
2750 MT_STATUS, l3ni1_release_ind},
2751 {ALL_STATES,
2752 MT_STATUS, l3ni1_status},
2753 {SBIT(0),
2754 MT_SETUP, l3ni1_setup},
2755 {SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) |
2756 SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2757 MT_SETUP, l3ni1_dummy},
2758 {SBIT(1) | SBIT(2),
2759 MT_CALL_PROCEEDING, l3ni1_call_proc},
2760 {SBIT(1),
2761 MT_SETUP_ACKNOWLEDGE, l3ni1_setup_ack},
2762 {SBIT(2) | SBIT(3),
2763 MT_ALERTING, l3ni1_alerting},
2764 {SBIT(2) | SBIT(3),
2765 MT_PROGRESS, l3ni1_progress},
2766 {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) |
2767 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2768 MT_INFORMATION, l3ni1_information},
2769 {SBIT(10) | SBIT(11) | SBIT(15),
2770 MT_NOTIFY, l3ni1_notify},
2771 {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
2772 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2773 MT_RELEASE_COMPLETE, l3ni1_release_cmpl},
2774 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(25),
2775 MT_RELEASE, l3ni1_release},
2776 {SBIT(19), MT_RELEASE, l3ni1_release_ind},
2777 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(25),
2778 MT_DISCONNECT, l3ni1_disconnect},
2779 {SBIT(19),
2780 MT_DISCONNECT, l3ni1_dummy},
2781 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
2782 MT_CONNECT, l3ni1_connect},
2783 {SBIT(8),
2784 MT_CONNECT_ACKNOWLEDGE, l3ni1_connect_ack},
2785 {SBIT(15),
2786 MT_SUSPEND_ACKNOWLEDGE, l3ni1_suspend_ack},
2787 {SBIT(15),
2788 MT_SUSPEND_REJECT, l3ni1_suspend_rej},
2789 {SBIT(17),
2790 MT_RESUME_ACKNOWLEDGE, l3ni1_resume_ack},
2791 {SBIT(17),
2792 MT_RESUME_REJECT, l3ni1_resume_rej},
2795 #define DATASLLEN \
2796 (sizeof(datastatelist) / sizeof(struct stateentry))
2798 static struct stateentry globalmes_list[] =
2800 {ALL_STATES,
2801 MT_STATUS, l3ni1_status},
2802 {SBIT(0),
2803 MT_RESTART, l3ni1_global_restart},
2804 /* {SBIT(1),
2805 MT_RESTART_ACKNOWLEDGE, l3ni1_restart_ack},
2807 { SBIT( 0 ), MT_DL_ESTABLISHED, l3ni1_spid_send },
2808 { SBIT( 20 ) | SBIT( 21 ) | SBIT( 22 ), MT_INFORMATION, l3ni1_spid_epid },
2810 #define GLOBALM_LEN \
2811 (sizeof(globalmes_list) / sizeof(struct stateentry))
2813 static struct stateentry manstatelist[] =
2815 {SBIT(2),
2816 DL_ESTABLISH | INDICATION, l3ni1_dl_reset},
2817 {SBIT(10),
2818 DL_ESTABLISH | CONFIRM, l3ni1_dl_reest_status},
2819 {SBIT(10),
2820 DL_RELEASE | INDICATION, l3ni1_dl_reestablish},
2821 {ALL_STATES,
2822 DL_RELEASE | INDICATION, l3ni1_dl_release},
2825 #define MANSLLEN \
2826 (sizeof(manstatelist) / sizeof(struct stateentry))
2827 /* *INDENT-ON* */
2830 static void
2831 global_handler(struct PStack *st, int mt, struct sk_buff *skb)
2833 u_char tmp[16];
2834 u_char *p = tmp;
2835 int l;
2836 int i;
2837 struct l3_process *proc = st->l3.global;
2839 if ( skb )
2840 proc->callref = skb->data[2]; /* cr flag */
2841 else
2842 proc->callref = 0;
2843 for (i = 0; i < GLOBALM_LEN; i++)
2844 if ((mt == globalmes_list[i].primitive) &&
2845 ((1 << proc->state) & globalmes_list[i].state))
2846 break;
2847 if (i == GLOBALM_LEN) {
2848 if (st->l3.debug & L3_DEB_STATE) {
2849 l3_debug(st, "ni1 global state %d mt %x unhandled",
2850 proc->state, mt);
2852 MsgHead(p, proc->callref, MT_STATUS);
2853 *p++ = IE_CAUSE;
2854 *p++ = 0x2;
2855 *p++ = 0x80;
2856 *p++ = 81 |0x80; /* invalid cr */
2857 *p++ = 0x14; /* CallState */
2858 *p++ = 0x1;
2859 *p++ = proc->state & 0x3f;
2860 l = p - tmp;
2861 if (!(skb = l3_alloc_skb(l)))
2862 return;
2863 memcpy(skb_put(skb, l), tmp, l);
2864 l3_msg(proc->st, DL_DATA | REQUEST, skb);
2865 } else {
2866 if (st->l3.debug & L3_DEB_STATE) {
2867 l3_debug(st, "ni1 global %d mt %x",
2868 proc->state, mt);
2870 globalmes_list[i].rout(proc, mt, skb);
2874 static void
2875 ni1up(struct PStack *st, int pr, void *arg)
2877 int i, mt, cr, cause, callState;
2878 char *ptr;
2879 u_char *p;
2880 struct sk_buff *skb = arg;
2881 struct l3_process *proc;
2883 switch (pr) {
2884 case (DL_DATA | INDICATION):
2885 case (DL_UNIT_DATA | INDICATION):
2886 break;
2887 case (DL_ESTABLISH | INDICATION):
2888 case (DL_RELEASE | INDICATION):
2889 case (DL_RELEASE | CONFIRM):
2890 l3_msg(st, pr, arg);
2891 return;
2892 break;
2894 case (DL_ESTABLISH | CONFIRM):
2895 global_handler( st, MT_DL_ESTABLISHED, NULL );
2896 return;
2898 default:
2899 printk(KERN_ERR "HiSax ni1up unknown pr=%04x\n", pr);
2900 return;
2902 if (skb->len < 3) {
2903 l3_debug(st, "ni1up frame too short(%d)", skb->len);
2904 dev_kfree_skb(skb);
2905 return;
2908 if (skb->data[0] != PROTO_DIS_EURO) {
2909 if (st->l3.debug & L3_DEB_PROTERR) {
2910 l3_debug(st, "ni1up%sunexpected discriminator %x message len %d",
2911 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
2912 skb->data[0], skb->len);
2914 dev_kfree_skb(skb);
2915 return;
2917 cr = getcallref(skb->data);
2918 if (skb->len < ((skb->data[1] & 0x0f) + 3)) {
2919 l3_debug(st, "ni1up frame too short(%d)", skb->len);
2920 dev_kfree_skb(skb);
2921 return;
2923 mt = skb->data[skb->data[1] + 2];
2924 if (st->l3.debug & L3_DEB_STATE)
2925 l3_debug(st, "ni1up cr %d", cr);
2926 if (cr == -2) { /* wrong Callref */
2927 if (st->l3.debug & L3_DEB_WARN)
2928 l3_debug(st, "ni1up wrong Callref");
2929 dev_kfree_skb(skb);
2930 return;
2931 } else if (cr == -1) { /* Dummy Callref */
2932 if (mt == MT_FACILITY)
2934 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
2935 l3ni1_parse_facility(st, NULL,
2936 (pr == (DL_DATA | INDICATION)) ? -1 : -2, p);
2937 dev_kfree_skb(skb);
2938 return;
2941 else
2943 global_handler(st, mt, skb);
2944 return;
2947 if (st->l3.debug & L3_DEB_WARN)
2948 l3_debug(st, "ni1up dummy Callref (no facility msg or ie)");
2949 dev_kfree_skb(skb);
2950 return;
2951 } else if ((((skb->data[1] & 0x0f) == 1) && (0==(cr & 0x7f))) ||
2952 (((skb->data[1] & 0x0f) == 2) && (0==(cr & 0x7fff)))) { /* Global CallRef */
2953 if (st->l3.debug & L3_DEB_STATE)
2954 l3_debug(st, "ni1up Global CallRef");
2955 global_handler(st, mt, skb);
2956 dev_kfree_skb(skb);
2957 return;
2958 } else if (!(proc = getl3proc(st, cr))) {
2959 /* No transaction process exist, that means no call with
2960 * this callreference is active
2962 if (mt == MT_SETUP) {
2963 /* Setup creates a new transaction process */
2964 if (skb->data[2] & 0x80) {
2965 /* Setup with wrong CREF flag */
2966 if (st->l3.debug & L3_DEB_STATE)
2967 l3_debug(st, "ni1up wrong CRef flag");
2968 dev_kfree_skb(skb);
2969 return;
2971 if (!(proc = ni1_new_l3_process(st, cr))) {
2972 /* May be to answer with RELEASE_COMPLETE and
2973 * CAUSE 0x2f "Resource unavailable", but this
2974 * need a new_l3_process too ... arghh
2976 dev_kfree_skb(skb);
2977 return;
2979 } else if (mt == MT_STATUS) {
2980 cause = 0;
2981 if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
2982 ptr++;
2983 if (*ptr++ == 2)
2984 ptr++;
2985 cause = *ptr & 0x7f;
2987 callState = 0;
2988 if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
2989 ptr++;
2990 if (*ptr++ == 2)
2991 ptr++;
2992 callState = *ptr;
2994 /* ETS 300-104 part 2.4.1
2995 * if setup has not been made and a message type
2996 * MT_STATUS is received with call state == 0,
2997 * we must send nothing
2999 if (callState != 0) {
3000 /* ETS 300-104 part 2.4.2
3001 * if setup has not been made and a message type
3002 * MT_STATUS is received with call state != 0,
3003 * we must send MT_RELEASE_COMPLETE cause 101
3005 if ((proc = ni1_new_l3_process(st, cr))) {
3006 proc->para.cause = 101;
3007 l3ni1_msg_without_setup(proc, 0, NULL);
3010 dev_kfree_skb(skb);
3011 return;
3012 } else if (mt == MT_RELEASE_COMPLETE) {
3013 dev_kfree_skb(skb);
3014 return;
3015 } else {
3016 /* ETS 300-104 part 2
3017 * if setup has not been made and a message type
3018 * (except MT_SETUP and RELEASE_COMPLETE) is received,
3019 * we must send MT_RELEASE_COMPLETE cause 81 */
3020 dev_kfree_skb(skb);
3021 if ((proc = ni1_new_l3_process(st, cr))) {
3022 proc->para.cause = 81;
3023 l3ni1_msg_without_setup(proc, 0, NULL);
3025 return;
3028 if (l3ni1_check_messagetype_validity(proc, mt, skb)) {
3029 dev_kfree_skb(skb);
3030 return;
3032 if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL)
3033 l3ni1_deliver_display(proc, pr, p); /* Display IE included */
3034 for (i = 0; i < DATASLLEN; i++)
3035 if ((mt == datastatelist[i].primitive) &&
3036 ((1 << proc->state) & datastatelist[i].state))
3037 break;
3038 if (i == DATASLLEN) {
3039 if (st->l3.debug & L3_DEB_STATE) {
3040 l3_debug(st, "ni1up%sstate %d mt %#x unhandled",
3041 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
3042 proc->state, mt);
3044 if ((MT_RELEASE_COMPLETE != mt) && (MT_RELEASE != mt)) {
3045 proc->para.cause = 101;
3046 l3ni1_status_send(proc, pr, skb);
3048 } else {
3049 if (st->l3.debug & L3_DEB_STATE) {
3050 l3_debug(st, "ni1up%sstate %d mt %x",
3051 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
3052 proc->state, mt);
3054 datastatelist[i].rout(proc, pr, skb);
3056 dev_kfree_skb(skb);
3057 return;
3060 static void
3061 ni1down(struct PStack *st, int pr, void *arg)
3063 int i, cr;
3064 struct l3_process *proc;
3065 struct Channel *chan;
3067 if ((DL_ESTABLISH | REQUEST) == pr) {
3068 l3_msg(st, pr, NULL);
3069 return;
3070 } else if (((CC_SETUP | REQUEST) == pr) || ((CC_RESUME | REQUEST) == pr)) {
3071 chan = arg;
3072 cr = newcallref();
3073 cr |= 0x80;
3074 if ((proc = ni1_new_l3_process(st, cr))) {
3075 proc->chan = chan;
3076 chan->proc = proc;
3077 memcpy(&proc->para.setup, &chan->setup, sizeof(setup_parm));
3078 proc->callref = cr;
3080 } else {
3081 proc = arg;
3083 if (!proc) {
3084 printk(KERN_ERR "HiSax ni1down without proc pr=%04x\n", pr);
3085 return;
3088 if ( pr == (CC_TNI1_IO | REQUEST)) {
3089 l3ni1_io_timer(proc); /* timer expires */
3090 return;
3093 for (i = 0; i < DOWNSLLEN; i++)
3094 if ((pr == downstatelist[i].primitive) &&
3095 ((1 << proc->state) & downstatelist[i].state))
3096 break;
3097 if (i == DOWNSLLEN) {
3098 if (st->l3.debug & L3_DEB_STATE) {
3099 l3_debug(st, "ni1down state %d prim %#x unhandled",
3100 proc->state, pr);
3102 } else {
3103 if (st->l3.debug & L3_DEB_STATE) {
3104 l3_debug(st, "ni1down state %d prim %#x",
3105 proc->state, pr);
3107 downstatelist[i].rout(proc, pr, arg);
3111 static void
3112 ni1man(struct PStack *st, int pr, void *arg)
3114 int i;
3115 struct l3_process *proc = arg;
3117 if (!proc) {
3118 printk(KERN_ERR "HiSax ni1man without proc pr=%04x\n", pr);
3119 return;
3121 for (i = 0; i < MANSLLEN; i++)
3122 if ((pr == manstatelist[i].primitive) &&
3123 ((1 << proc->state) & manstatelist[i].state))
3124 break;
3125 if (i == MANSLLEN) {
3126 if (st->l3.debug & L3_DEB_STATE) {
3127 l3_debug(st, "cr %d ni1man state %d prim %#x unhandled",
3128 proc->callref & 0x7f, proc->state, pr);
3130 } else {
3131 if (st->l3.debug & L3_DEB_STATE) {
3132 l3_debug(st, "cr %d ni1man state %d prim %#x",
3133 proc->callref & 0x7f, proc->state, pr);
3135 manstatelist[i].rout(proc, pr, arg);
3139 void
3140 setstack_ni1(struct PStack *st)
3142 char tmp[64];
3143 int i;
3145 st->lli.l4l3 = ni1down;
3146 st->lli.l4l3_proto = l3ni1_cmd_global;
3147 st->l2.l2l3 = ni1up;
3148 st->l3.l3ml3 = ni1man;
3149 st->l3.N303 = 1;
3150 st->prot.ni1.last_invoke_id = 0;
3151 st->prot.ni1.invoke_used[0] = 1; /* Bit 0 must always be set to 1 */
3152 i = 1;
3153 while (i < 32)
3154 st->prot.ni1.invoke_used[i++] = 0;
3156 if (!(st->l3.global = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
3157 printk(KERN_ERR "HiSax can't get memory for ni1 global CR\n");
3158 } else {
3159 st->l3.global->state = 0;
3160 st->l3.global->callref = 0;
3161 st->l3.global->next = NULL;
3162 st->l3.global->debug = L3_DEB_WARN;
3163 st->l3.global->st = st;
3164 st->l3.global->N303 = 1;
3165 st->l3.global->prot.ni1.invoke_id = 0;
3167 L3InitTimer(st->l3.global, &st->l3.global->timer);
3169 strcpy(tmp, ni1_revision);
3170 printk(KERN_INFO "HiSax: National ISDN-1 Rev. %s\n", HiSax_getrev(tmp));