1 /* $Id: isdnl3.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
2 *
3 * Author Karsten Keil
4 * based on the teles driver from Jan den Ouden
5 * Copyright by Karsten Keil <keil@isdn4linux.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 * For changes and modifications please read
11 * ../../../Documentation/isdn/HiSax.cert
12 *
13 * Thanks to Jan den Ouden
14 * Fritz Elfert
15 *
16 */
17
18 #define __NO_VERSION__
19 #include <linux/init.h>
20 #include "hisax.h"
21 #include "isdnl3.h"
22 #include <linux/config.h>
23
24 const char *l3_revision = "$Revision: 1.1.4.1 $";
25
26 static struct Fsm l3fsm;
27
28 enum {
29 ST_L3_LC_REL,
30 ST_L3_LC_ESTAB_WAIT,
31 ST_L3_LC_REL_DELAY,
32 ST_L3_LC_REL_WAIT,
33 ST_L3_LC_ESTAB,
34 };
35
36 #define L3_STATE_COUNT (ST_L3_LC_ESTAB+1)
37
38 static char *strL3State[] =
39 {
40 "ST_L3_LC_REL",
41 "ST_L3_LC_ESTAB_WAIT",
42 "ST_L3_LC_REL_DELAY",
43 "ST_L3_LC_REL_WAIT",
44 "ST_L3_LC_ESTAB",
45 };
46
47 enum {
48 EV_ESTABLISH_REQ,
49 EV_ESTABLISH_IND,
50 EV_ESTABLISH_CNF,
51 EV_RELEASE_REQ,
52 EV_RELEASE_CNF,
53 EV_RELEASE_IND,
54 EV_TIMEOUT,
55 };
56
57 #define L3_EVENT_COUNT (EV_TIMEOUT+1)
58
59 static char *strL3Event[] =
60 {
61 "EV_ESTABLISH_REQ",
62 "EV_ESTABLISH_IND",
63 "EV_ESTABLISH_CNF",
64 "EV_RELEASE_REQ",
65 "EV_RELEASE_CNF",
66 "EV_RELEASE_IND",
67 "EV_TIMEOUT",
68 };
69
70 static void
l3m_debug(struct FsmInst * fi,char * fmt,...)71 l3m_debug(struct FsmInst *fi, char *fmt, ...)
72 {
73 va_list args;
74 struct PStack *st = fi->userdata;
75
76 va_start(args, fmt);
77 VHiSax_putstatus(st->l1.hardware, st->l3.debug_id, fmt, args);
78 va_end(args);
79 }
80
81 u_char *
findie(u_char * p,int size,u_char ie,int wanted_set)82 findie(u_char * p, int size, u_char ie, int wanted_set)
83 {
84 int l, codeset, maincodeset;
85 u_char *pend = p + size;
86
87 /* skip protocol discriminator, callref and message type */
88 p++;
89 l = (*p++) & 0xf;
90 p += l;
91 p++;
92 codeset = 0;
93 maincodeset = 0;
94 /* while there are bytes left... */
95 while (p < pend) {
96 if ((*p & 0xf0) == 0x90) {
97 codeset = *p & 0x07;
98 if (!(*p & 0x08))
99 maincodeset = codeset;
100 }
101 if (*p & 0x80)
102 p++;
103 else {
104 if (codeset == wanted_set) {
105 if (*p == ie)
106 { /* improved length check (Werner Cornelius) */
107 if ((pend - p) < 2)
108 return(NULL);
109 if (*(p+1) > (pend - (p+2)))
110 return(NULL);
111 return (p);
112 }
113
114 if (*p > ie)
115 return (NULL);
116 }
117 p++;
118 l = *p++;
119 p += l;
120 codeset = maincodeset;
121 }
122 }
123 return (NULL);
124 }
125
126 int
getcallref(u_char * p)127 getcallref(u_char * p)
128 {
129 int l, cr = 0;
130
131 p++; /* prot discr */
132 if (*p & 0xfe) /* wrong callref BRI only 1 octet*/
133 return(-2);
134 l = 0xf & *p++; /* callref length */
135 if (!l) /* dummy CallRef */
136 return(-1);
137 cr = *p++;
138 return (cr);
139 }
140
141 static int OrigCallRef = 0;
142
143 int
newcallref(void)144 newcallref(void)
145 {
146 if (OrigCallRef == 127)
147 OrigCallRef = 1;
148 else
149 OrigCallRef++;
150 return (OrigCallRef);
151 }
152
153 void
newl3state(struct l3_process * pc,int state)154 newl3state(struct l3_process *pc, int state)
155 {
156 if (pc->debug & L3_DEB_STATE)
157 l3_debug(pc->st, "newstate cr %d %d --> %d",
158 pc->callref & 0x7F,
159 pc->state, state);
160 pc->state = state;
161 }
162
163 static void
L3ExpireTimer(struct L3Timer * t)164 L3ExpireTimer(struct L3Timer *t)
165 {
166 t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc);
167 }
168
169 void
L3InitTimer(struct l3_process * pc,struct L3Timer * t)170 L3InitTimer(struct l3_process *pc, struct L3Timer *t)
171 {
172 t->pc = pc;
173 t->tl.function = (void *) L3ExpireTimer;
174 t->tl.data = (long) t;
175 init_timer(&t->tl);
176 }
177
178 void
L3DelTimer(struct L3Timer * t)179 L3DelTimer(struct L3Timer *t)
180 {
181 del_timer(&t->tl);
182 }
183
184 int
L3AddTimer(struct L3Timer * t,int millisec,int event)185 L3AddTimer(struct L3Timer *t,
186 int millisec, int event)
187 {
188 if (timer_pending(&t->tl)) {
189 printk(KERN_WARNING "L3AddTimer: timer already active!\n");
190 return -1;
191 }
192 init_timer(&t->tl);
193 t->event = event;
194 t->tl.expires = jiffies + (millisec * HZ) / 1000;
195 add_timer(&t->tl);
196 return 0;
197 }
198
199 void
StopAllL3Timer(struct l3_process * pc)200 StopAllL3Timer(struct l3_process *pc)
201 {
202 L3DelTimer(&pc->timer);
203 }
204
205 struct sk_buff *
l3_alloc_skb(int len)206 l3_alloc_skb(int len)
207 {
208 struct sk_buff *skb;
209
210 if (!(skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC))) {
211 printk(KERN_WARNING "HiSax: No skb for D-channel\n");
212 return (NULL);
213 }
214 skb_reserve(skb, MAX_HEADER_LEN);
215 return (skb);
216 }
217
218 static void
no_l3_proto(struct PStack * st,int pr,void * arg)219 no_l3_proto(struct PStack *st, int pr, void *arg)
220 {
221 struct sk_buff *skb = arg;
222
223 HiSax_putstatus(st->l1.hardware, "L3", "no D protocol");
224 if (skb) {
225 dev_kfree_skb(skb);
226 }
227 }
228
229 static int
no_l3_proto_spec(struct PStack * st,isdn_ctrl * ic)230 no_l3_proto_spec(struct PStack *st, isdn_ctrl *ic)
231 {
232 printk(KERN_WARNING "HiSax: no specific protocol handler for proto %lu\n",ic->arg & 0xFF);
233 return(-1);
234 }
235
236 #ifdef CONFIG_HISAX_EURO
237 extern void setstack_dss1(struct PStack *st);
238 #endif
239
240 #ifdef CONFIG_HISAX_NI1
241 extern void setstack_ni1(struct PStack *st);
242 #endif
243
244 #ifdef CONFIG_HISAX_1TR6
245 extern void setstack_1tr6(struct PStack *st);
246 #endif
247
248 struct l3_process
getl3proc(struct PStack * st,int cr)249 *getl3proc(struct PStack *st, int cr)
250 {
251 struct l3_process *p = st->l3.proc;
252
253 while (p)
254 if (p->callref == cr)
255 return (p);
256 else
257 p = p->next;
258 return (NULL);
259 }
260
261 struct l3_process
new_l3_process(struct PStack * st,int cr)262 *new_l3_process(struct PStack *st, int cr)
263 {
264 struct l3_process *p, *np;
265
266 if (!(p = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
267 printk(KERN_ERR "HiSax can't get memory for cr %d\n", cr);
268 return (NULL);
269 }
270 if (!st->l3.proc)
271 st->l3.proc = p;
272 else {
273 np = st->l3.proc;
274 while (np->next)
275 np = np->next;
276 np->next = p;
277 }
278 p->next = NULL;
279 p->debug = st->l3.debug;
280 p->callref = cr;
281 p->state = 0;
282 p->chan = NULL;
283 p->st = st;
284 p->N303 = st->l3.N303;
285 L3InitTimer(p, &p->timer);
286 return (p);
287 };
288
289 void
release_l3_process(struct l3_process * p)290 release_l3_process(struct l3_process *p)
291 {
292 struct l3_process *np, *pp = NULL;
293
294 if (!p)
295 return;
296 np = p->st->l3.proc;
297 while (np) {
298 if (np == p) {
299 StopAllL3Timer(p);
300 if (pp)
301 pp->next = np->next;
302 else if (!(p->st->l3.proc = np->next) &&
303 !test_bit(FLG_PTP, &p->st->l2.flag)) {
304 if (p->debug)
305 l3_debug(p->st, "release_l3_process: last process");
306 if (!skb_queue_len(&p->st->l3.squeue)) {
307 if (p->debug)
308 l3_debug(p->st, "release_l3_process: release link");
309 if (p->st->protocol != ISDN_PTYPE_NI1)
310 FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL);
311 else
312 FsmEvent(&p->st->l3.l3m, EV_RELEASE_IND, NULL);
313 } else {
314 if (p->debug)
315 l3_debug(p->st, "release_l3_process: not release link");
316 }
317 }
318 kfree(p);
319 return;
320 }
321 pp = np;
322 np = np->next;
323 }
324 printk(KERN_ERR "HiSax internal L3 error CR(%d) not in list\n", p->callref);
325 l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref);
326 };
327
328 static void
l3ml3p(struct PStack * st,int pr)329 l3ml3p(struct PStack *st, int pr)
330 {
331 struct l3_process *p = st->l3.proc;
332 struct l3_process *np;
333
334 while (p) {
335 /* p might be kfreed under us, so we need to save where we want to go on */
336 np = p->next;
337 st->l3.l3ml3(st, pr, p);
338 p = np;
339 }
340 }
341
342 void
setstack_l3dc(struct PStack * st,struct Channel * chanp)343 setstack_l3dc(struct PStack *st, struct Channel *chanp)
344 {
345 char tmp[64];
346
347 st->l3.proc = NULL;
348 st->l3.global = NULL;
349 skb_queue_head_init(&st->l3.squeue);
350 st->l3.l3m.fsm = &l3fsm;
351 st->l3.l3m.state = ST_L3_LC_REL;
352 st->l3.l3m.debug = 1;
353 st->l3.l3m.userdata = st;
354 st->l3.l3m.userint = 0;
355 st->l3.l3m.printdebug = l3m_debug;
356 FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer);
357 strcpy(st->l3.debug_id, "L3DC ");
358 st->lli.l4l3_proto = no_l3_proto_spec;
359
360 #ifdef CONFIG_HISAX_EURO
361 if (st->protocol == ISDN_PTYPE_EURO) {
362 setstack_dss1(st);
363 } else
364 #endif
365 #ifdef CONFIG_HISAX_NI1
366 if (st->protocol == ISDN_PTYPE_NI1) {
367 setstack_ni1(st);
368 } else
369 #endif
370 #ifdef CONFIG_HISAX_1TR6
371 if (st->protocol == ISDN_PTYPE_1TR6) {
372 setstack_1tr6(st);
373 } else
374 #endif
375 if (st->protocol == ISDN_PTYPE_LEASED) {
376 st->lli.l4l3 = no_l3_proto;
377 st->l2.l2l3 = no_l3_proto;
378 st->l3.l3ml3 = no_l3_proto;
379 printk(KERN_INFO "HiSax: Leased line mode\n");
380 } else {
381 st->lli.l4l3 = no_l3_proto;
382 st->l2.l2l3 = no_l3_proto;
383 st->l3.l3ml3 = no_l3_proto;
384 sprintf(tmp, "protocol %s not supported",
385 (st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" :
386 (st->protocol == ISDN_PTYPE_EURO) ? "euro" :
387 (st->protocol == ISDN_PTYPE_NI1) ? "ni1" :
388 "unknown");
389 printk(KERN_WARNING "HiSax: %s\n", tmp);
390 st->protocol = -1;
391 }
392 }
393
394 void
isdnl3_trans(struct PStack * st,int pr,void * arg)395 isdnl3_trans(struct PStack *st, int pr, void *arg) {
396 st->l3.l3l2(st, pr, arg);
397 }
398
399 void
releasestack_isdnl3(struct PStack * st)400 releasestack_isdnl3(struct PStack *st)
401 {
402 while (st->l3.proc)
403 release_l3_process(st->l3.proc);
404 if (st->l3.global) {
405 StopAllL3Timer(st->l3.global);
406 kfree(st->l3.global);
407 st->l3.global = NULL;
408 }
409 FsmDelTimer(&st->l3.l3m_timer, 54);
410 skb_queue_purge(&st->l3.squeue);
411 }
412
413 void
setstack_l3bc(struct PStack * st,struct Channel * chanp)414 setstack_l3bc(struct PStack *st, struct Channel *chanp)
415 {
416
417 st->l3.proc = NULL;
418 st->l3.global = NULL;
419 skb_queue_head_init(&st->l3.squeue);
420 st->l3.l3m.fsm = &l3fsm;
421 st->l3.l3m.state = ST_L3_LC_REL;
422 st->l3.l3m.debug = 1;
423 st->l3.l3m.userdata = st;
424 st->l3.l3m.userint = 0;
425 st->l3.l3m.printdebug = l3m_debug;
426 strcpy(st->l3.debug_id, "L3BC ");
427 st->lli.l4l3 = isdnl3_trans;
428 }
429
430 #define DREL_TIMER_VALUE 40000
431
432 static void
lc_activate(struct FsmInst * fi,int event,void * arg)433 lc_activate(struct FsmInst *fi, int event, void *arg)
434 {
435 struct PStack *st = fi->userdata;
436
437 FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT);
438 st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL);
439 }
440
441 static void
lc_connect(struct FsmInst * fi,int event,void * arg)442 lc_connect(struct FsmInst *fi, int event, void *arg)
443 {
444 struct PStack *st = fi->userdata;
445 struct sk_buff *skb = arg;
446 int dequeued = 0;
447
448 FsmChangeState(fi, ST_L3_LC_ESTAB);
449 while ((skb = skb_dequeue(&st->l3.squeue))) {
450 st->l3.l3l2(st, DL_DATA | REQUEST, skb);
451 dequeued++;
452 }
453 if ((!st->l3.proc) && dequeued) {
454 if (st->l3.debug)
455 l3_debug(st, "lc_connect: release link");
456 FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
457 } else
458 l3ml3p(st, DL_ESTABLISH | INDICATION);
459 }
460
461 static void
lc_connected(struct FsmInst * fi,int event,void * arg)462 lc_connected(struct FsmInst *fi, int event, void *arg)
463 {
464 struct PStack *st = fi->userdata;
465 struct sk_buff *skb = arg;
466 int dequeued = 0;
467
468 FsmDelTimer(&st->l3.l3m_timer, 51);
469 FsmChangeState(fi, ST_L3_LC_ESTAB);
470 while ((skb = skb_dequeue(&st->l3.squeue))) {
471 st->l3.l3l2(st, DL_DATA | REQUEST, skb);
472 dequeued++;
473 }
474 if ((!st->l3.proc) && dequeued) {
475 if (st->l3.debug)
476 l3_debug(st, "lc_connected: release link");
477 FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
478 } else
479 l3ml3p(st, DL_ESTABLISH | CONFIRM);
480 }
481
482 static void
lc_start_delay(struct FsmInst * fi,int event,void * arg)483 lc_start_delay(struct FsmInst *fi, int event, void *arg)
484 {
485 struct PStack *st = fi->userdata;
486
487 FsmChangeState(fi, ST_L3_LC_REL_DELAY);
488 FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
489 }
490
491 static void
lc_start_delay_check(struct FsmInst * fi,int event,void * arg)492 lc_start_delay_check(struct FsmInst *fi, int event, void *arg)
493 /* 20/09/00 - GE timer not user for NI-1 as layer 2 should stay up */
494 {
495 struct PStack *st = fi->userdata;
496
497 FsmChangeState(fi, ST_L3_LC_REL_DELAY);
498 /* 19/09/00 - GE timer not user for NI-1 */
499 if (st->protocol != ISDN_PTYPE_NI1)
500 FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
501 }
502
503 static void
lc_release_req(struct FsmInst * fi,int event,void * arg)504 lc_release_req(struct FsmInst *fi, int event, void *arg)
505 {
506 struct PStack *st = fi->userdata;
507
508 if (test_bit(FLG_L2BLOCK, &st->l2.flag)) {
509 if (st->l3.debug)
510 l3_debug(st, "lc_release_req: l2 blocked");
511 /* restart release timer */
512 FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51);
513 } else {
514 FsmChangeState(fi, ST_L3_LC_REL_WAIT);
515 st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL);
516 }
517 }
518
519 static void
lc_release_ind(struct FsmInst * fi,int event,void * arg)520 lc_release_ind(struct FsmInst *fi, int event, void *arg)
521 {
522 struct PStack *st = fi->userdata;
523
524 FsmDelTimer(&st->l3.l3m_timer, 52);
525 FsmChangeState(fi, ST_L3_LC_REL);
526 skb_queue_purge(&st->l3.squeue);
527 l3ml3p(st, DL_RELEASE | INDICATION);
528 }
529
530 static void
lc_release_cnf(struct FsmInst * fi,int event,void * arg)531 lc_release_cnf(struct FsmInst *fi, int event, void *arg)
532 {
533 struct PStack *st = fi->userdata;
534
535 FsmChangeState(fi, ST_L3_LC_REL);
536 skb_queue_purge(&st->l3.squeue);
537 l3ml3p(st, DL_RELEASE | CONFIRM);
538 }
539
540
541 /* *INDENT-OFF* */
542 static struct FsmNode L3FnList[] __initdata =
543 {
544 {ST_L3_LC_REL, EV_ESTABLISH_REQ, lc_activate},
545 {ST_L3_LC_REL, EV_ESTABLISH_IND, lc_connect},
546 {ST_L3_LC_REL, EV_ESTABLISH_CNF, lc_connect},
547 {ST_L3_LC_ESTAB_WAIT, EV_ESTABLISH_CNF, lc_connected},
548 {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_REQ, lc_start_delay},
549 {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_IND, lc_release_ind},
550 {ST_L3_LC_ESTAB, EV_RELEASE_IND, lc_release_ind},
551 {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay_check},
552 {ST_L3_LC_REL_DELAY, EV_RELEASE_IND, lc_release_ind},
553 {ST_L3_LC_REL_DELAY, EV_ESTABLISH_REQ, lc_connected},
554 {ST_L3_LC_REL_DELAY, EV_TIMEOUT, lc_release_req},
555 {ST_L3_LC_REL_WAIT, EV_RELEASE_CNF, lc_release_cnf},
556 {ST_L3_LC_REL_WAIT, EV_ESTABLISH_REQ, lc_activate},
557 };
558 /* *INDENT-ON* */
559
560 #define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
561
562 void
l3_msg(struct PStack * st,int pr,void * arg)563 l3_msg(struct PStack *st, int pr, void *arg)
564 {
565 switch (pr) {
566 case (DL_DATA | REQUEST):
567 if (st->l3.l3m.state == ST_L3_LC_ESTAB) {
568 st->l3.l3l2(st, pr, arg);
569 } else {
570 struct sk_buff *skb = arg;
571
572 skb_queue_tail(&st->l3.squeue, skb);
573 FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
574 }
575 break;
576 case (DL_ESTABLISH | REQUEST):
577 FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
578 break;
579 case (DL_ESTABLISH | CONFIRM):
580 FsmEvent(&st->l3.l3m, EV_ESTABLISH_CNF, NULL);
581 break;
582 case (DL_ESTABLISH | INDICATION):
583 FsmEvent(&st->l3.l3m, EV_ESTABLISH_IND, NULL);
584 break;
585 case (DL_RELEASE | INDICATION):
586 FsmEvent(&st->l3.l3m, EV_RELEASE_IND, NULL);
587 break;
588 case (DL_RELEASE | CONFIRM):
589 FsmEvent(&st->l3.l3m, EV_RELEASE_CNF, NULL);
590 break;
591 case (DL_RELEASE | REQUEST):
592 FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
593 break;
594 }
595 }
596
597 int __init
Isdnl3New(void)598 Isdnl3New(void)
599 {
600 l3fsm.state_count = L3_STATE_COUNT;
601 l3fsm.event_count = L3_EVENT_COUNT;
602 l3fsm.strEvent = strL3Event;
603 l3fsm.strState = strL3State;
604 return FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
605 }
606
607 void
Isdnl3Free(void)608 Isdnl3Free(void)
609 {
610 FsmFree(&l3fsm);
611 }
612