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