1 /* $Id: tei.c,v 2.20.2.3 2004/01/13 14:31:26 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 "hisax.h"
19 #include "isdnl2.h"
20 #include <linux/gfp.h>
21 #include <linux/init.h>
22 #include <linux/random.h>
23 
24 const char *tei_revision = "$Revision: 2.20.2.3 $";
25 
26 #define ID_REQUEST	1
27 #define ID_ASSIGNED	2
28 #define ID_DENIED	3
29 #define ID_CHK_REQ	4
30 #define ID_CHK_RES	5
31 #define ID_REMOVE	6
32 #define ID_VERIFY	7
33 
34 #define TEI_ENTITY_ID	0xf
35 
36 static struct Fsm teifsm;
37 
38 void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb);
39 
40 enum {
41 	ST_TEI_NOP,
42 	ST_TEI_IDREQ,
43 	ST_TEI_IDVERIFY,
44 };
45 
46 #define TEI_STATE_COUNT (ST_TEI_IDVERIFY + 1)
47 
48 static char *strTeiState[] =
49 {
50 	"ST_TEI_NOP",
51 	"ST_TEI_IDREQ",
52 	"ST_TEI_IDVERIFY",
53 };
54 
55 enum {
56 	EV_IDREQ,
57 	EV_ASSIGN,
58 	EV_DENIED,
59 	EV_CHKREQ,
60 	EV_REMOVE,
61 	EV_VERIFY,
62 	EV_T202,
63 };
64 
65 #define TEI_EVENT_COUNT (EV_T202 + 1)
66 
67 static char *strTeiEvent[] =
68 {
69 	"EV_IDREQ",
70 	"EV_ASSIGN",
71 	"EV_DENIED",
72 	"EV_CHKREQ",
73 	"EV_REMOVE",
74 	"EV_VERIFY",
75 	"EV_T202",
76 };
77 
78 static unsigned int
random_ri(void)79 random_ri(void)
80 {
81 	unsigned int x;
82 
83 	get_random_bytes(&x, sizeof(x));
84 	return (x & 0xffff);
85 }
86 
87 static struct PStack *
findtei(struct PStack * st,int tei)88 findtei(struct PStack *st, int tei)
89 {
90 	struct PStack *ptr = *(st->l1.stlistp);
91 
92 	if (tei == 127)
93 		return (NULL);
94 
95 	while (ptr)
96 		if (ptr->l2.tei == tei)
97 			return (ptr);
98 		else
99 			ptr = ptr->next;
100 	return (NULL);
101 }
102 
103 static void
put_tei_msg(struct PStack * st,u_char m_id,unsigned int ri,u_char tei)104 put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei)
105 {
106 	struct sk_buff *skb;
107 	u_char *bp;
108 
109 	if (!(skb = alloc_skb(8, GFP_ATOMIC))) {
110 		printk(KERN_WARNING "HiSax: No skb for TEI manager\n");
111 		return;
112 	}
113 	bp = skb_put(skb, 3);
114 	bp[0] = (TEI_SAPI << 2);
115 	bp[1] = (GROUP_TEI << 1) | 0x1;
116 	bp[2] = UI;
117 	bp = skb_put(skb, 5);
118 	bp[0] = TEI_ENTITY_ID;
119 	bp[1] = ri >> 8;
120 	bp[2] = ri & 0xff;
121 	bp[3] = m_id;
122 	bp[4] = (tei << 1) | 1;
123 	st->l2.l2l1(st, PH_DATA | REQUEST, skb);
124 }
125 
126 static void
tei_id_request(struct FsmInst * fi,int event,void * arg)127 tei_id_request(struct FsmInst *fi, int event, void *arg)
128 {
129 	struct PStack *st = fi->userdata;
130 
131 	if (st->l2.tei != -1) {
132 		st->ma.tei_m.printdebug(&st->ma.tei_m,
133 					"assign request for already assigned tei %d",
134 					st->l2.tei);
135 		return;
136 	}
137 	st->ma.ri = random_ri();
138 	if (st->ma.debug)
139 		st->ma.tei_m.printdebug(&st->ma.tei_m,
140 					"assign request ri %d", st->ma.ri);
141 	put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
142 	FsmChangeState(&st->ma.tei_m, ST_TEI_IDREQ);
143 	FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 1);
144 	st->ma.N202 = 3;
145 }
146 
147 static void
tei_id_assign(struct FsmInst * fi,int event,void * arg)148 tei_id_assign(struct FsmInst *fi, int event, void *arg)
149 {
150 	struct PStack *ost, *st = fi->userdata;
151 	struct sk_buff *skb = arg;
152 	struct IsdnCardState *cs;
153 	int ri, tei;
154 
155 	ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
156 	tei = skb->data[4] >> 1;
157 	if (st->ma.debug)
158 		st->ma.tei_m.printdebug(&st->ma.tei_m,
159 					"identity assign ri %d tei %d", ri, tei);
160 	if ((ost = findtei(st, tei))) {	/* same tei is in use */
161 		if (ri != ost->ma.ri) {
162 			st->ma.tei_m.printdebug(&st->ma.tei_m,
163 						"possible duplicate assignment tei %d", tei);
164 			ost->l2.l2tei(ost, MDL_ERROR | RESPONSE, NULL);
165 		}
166 	} else if (ri == st->ma.ri) {
167 		FsmDelTimer(&st->ma.t202, 1);
168 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
169 		st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei);
170 		cs = (struct IsdnCardState *) st->l1.hardware;
171 		cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
172 	}
173 }
174 
175 static void
tei_id_test_dup(struct FsmInst * fi,int event,void * arg)176 tei_id_test_dup(struct FsmInst *fi, int event, void *arg)
177 {
178 	struct PStack *ost, *st = fi->userdata;
179 	struct sk_buff *skb = arg;
180 	int tei, ri;
181 
182 	ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
183 	tei = skb->data[4] >> 1;
184 	if (st->ma.debug)
185 		st->ma.tei_m.printdebug(&st->ma.tei_m,
186 					"foreign identity assign ri %d tei %d", ri, tei);
187 	if ((ost = findtei(st, tei))) {	/* same tei is in use */
188 		if (ri != ost->ma.ri) {	/* and it wasn't our request */
189 			st->ma.tei_m.printdebug(&st->ma.tei_m,
190 						"possible duplicate assignment tei %d", tei);
191 			FsmEvent(&ost->ma.tei_m, EV_VERIFY, NULL);
192 		}
193 	}
194 }
195 
196 static void
tei_id_denied(struct FsmInst * fi,int event,void * arg)197 tei_id_denied(struct FsmInst *fi, int event, void *arg)
198 {
199 	struct PStack *st = fi->userdata;
200 	struct sk_buff *skb = arg;
201 	int ri, tei;
202 
203 	ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
204 	tei = skb->data[4] >> 1;
205 	if (st->ma.debug)
206 		st->ma.tei_m.printdebug(&st->ma.tei_m,
207 					"identity denied ri %d tei %d", ri, tei);
208 }
209 
210 static void
tei_id_chk_req(struct FsmInst * fi,int event,void * arg)211 tei_id_chk_req(struct FsmInst *fi, int event, void *arg)
212 {
213 	struct PStack *st = fi->userdata;
214 	struct sk_buff *skb = arg;
215 	int tei;
216 
217 	tei = skb->data[4] >> 1;
218 	if (st->ma.debug)
219 		st->ma.tei_m.printdebug(&st->ma.tei_m,
220 					"identity check req tei %d", tei);
221 	if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
222 		FsmDelTimer(&st->ma.t202, 4);
223 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
224 		put_tei_msg(st, ID_CHK_RES, random_ri(), st->l2.tei);
225 	}
226 }
227 
228 static void
tei_id_remove(struct FsmInst * fi,int event,void * arg)229 tei_id_remove(struct FsmInst *fi, int event, void *arg)
230 {
231 	struct PStack *st = fi->userdata;
232 	struct sk_buff *skb = arg;
233 	struct IsdnCardState *cs;
234 	int tei;
235 
236 	tei = skb->data[4] >> 1;
237 	if (st->ma.debug)
238 		st->ma.tei_m.printdebug(&st->ma.tei_m,
239 					"identity remove tei %d", tei);
240 	if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
241 		FsmDelTimer(&st->ma.t202, 5);
242 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
243 		st->l3.l3l2(st, MDL_REMOVE | REQUEST, NULL);
244 		cs = (struct IsdnCardState *) st->l1.hardware;
245 		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
246 	}
247 }
248 
249 static void
tei_id_verify(struct FsmInst * fi,int event,void * arg)250 tei_id_verify(struct FsmInst *fi, int event, void *arg)
251 {
252 	struct PStack *st = fi->userdata;
253 
254 	if (st->ma.debug)
255 		st->ma.tei_m.printdebug(&st->ma.tei_m,
256 					"id verify request for tei %d", st->l2.tei);
257 	put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
258 	FsmChangeState(&st->ma.tei_m, ST_TEI_IDVERIFY);
259 	FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 2);
260 	st->ma.N202 = 2;
261 }
262 
263 static void
tei_id_req_tout(struct FsmInst * fi,int event,void * arg)264 tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
265 {
266 	struct PStack *st = fi->userdata;
267 	struct IsdnCardState *cs;
268 
269 	if (--st->ma.N202) {
270 		st->ma.ri = random_ri();
271 		if (st->ma.debug)
272 			st->ma.tei_m.printdebug(&st->ma.tei_m,
273 						"assign req(%d) ri %d", 4 - st->ma.N202,
274 						st->ma.ri);
275 		put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
276 		FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3);
277 	} else {
278 		st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed");
279 		st->l3.l3l2(st, MDL_ERROR | RESPONSE, NULL);
280 		cs = (struct IsdnCardState *) st->l1.hardware;
281 		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
282 		FsmChangeState(fi, ST_TEI_NOP);
283 	}
284 }
285 
286 static void
tei_id_ver_tout(struct FsmInst * fi,int event,void * arg)287 tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
288 {
289 	struct PStack *st = fi->userdata;
290 	struct IsdnCardState *cs;
291 
292 	if (--st->ma.N202) {
293 		if (st->ma.debug)
294 			st->ma.tei_m.printdebug(&st->ma.tei_m,
295 						"id verify req(%d) for tei %d",
296 						3 - st->ma.N202, st->l2.tei);
297 		put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
298 		FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 4);
299 	} else {
300 		st->ma.tei_m.printdebug(&st->ma.tei_m,
301 					"verify req for tei %d failed", st->l2.tei);
302 		st->l3.l3l2(st, MDL_REMOVE | REQUEST, NULL);
303 		cs = (struct IsdnCardState *) st->l1.hardware;
304 		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
305 		FsmChangeState(fi, ST_TEI_NOP);
306 	}
307 }
308 
309 static void
tei_l1l2(struct PStack * st,int pr,void * arg)310 tei_l1l2(struct PStack *st, int pr, void *arg)
311 {
312 	struct sk_buff *skb = arg;
313 	int mt;
314 
315 	if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
316 		dev_kfree_skb(skb);
317 		return;
318 	}
319 
320 	if (pr == (PH_DATA | INDICATION)) {
321 		if (skb->len < 3) {
322 			st->ma.tei_m.printdebug(&st->ma.tei_m,
323 						"short mgr frame %ld/3", skb->len);
324 		} else if ((skb->data[0] != ((TEI_SAPI << 2) | 2)) ||
325 			   (skb->data[1] != ((GROUP_TEI << 1) | 1))) {
326 			st->ma.tei_m.printdebug(&st->ma.tei_m,
327 						"wrong mgr sapi/tei %x/%x",
328 						skb->data[0], skb->data[1]);
329 		} else if ((skb->data[2] & 0xef) != UI) {
330 			st->ma.tei_m.printdebug(&st->ma.tei_m,
331 						"mgr frame is not ui %x", skb->data[2]);
332 		} else {
333 			skb_pull(skb, 3);
334 			if (skb->len < 5) {
335 				st->ma.tei_m.printdebug(&st->ma.tei_m,
336 							"short mgr frame %ld/5", skb->len);
337 			} else if (skb->data[0] != TEI_ENTITY_ID) {
338 				/* wrong management entity identifier, ignore */
339 				st->ma.tei_m.printdebug(&st->ma.tei_m,
340 							"tei handler wrong entity id %x",
341 							skb->data[0]);
342 			} else {
343 				mt = skb->data[3];
344 				if (mt == ID_ASSIGNED)
345 					FsmEvent(&st->ma.tei_m, EV_ASSIGN, skb);
346 				else if (mt == ID_DENIED)
347 					FsmEvent(&st->ma.tei_m, EV_DENIED, skb);
348 				else if (mt == ID_CHK_REQ)
349 					FsmEvent(&st->ma.tei_m, EV_CHKREQ, skb);
350 				else if (mt == ID_REMOVE)
351 					FsmEvent(&st->ma.tei_m, EV_REMOVE, skb);
352 				else {
353 					st->ma.tei_m.printdebug(&st->ma.tei_m,
354 								"tei handler wrong mt %x\n", mt);
355 				}
356 			}
357 		}
358 	} else {
359 		st->ma.tei_m.printdebug(&st->ma.tei_m,
360 					"tei handler wrong pr %x\n", pr);
361 	}
362 	dev_kfree_skb(skb);
363 }
364 
365 static void
tei_l2tei(struct PStack * st,int pr,void * arg)366 tei_l2tei(struct PStack *st, int pr, void *arg)
367 {
368 	struct IsdnCardState *cs;
369 
370 	if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
371 		if (pr == (MDL_ASSIGN | INDICATION)) {
372 			if (st->ma.debug)
373 				st->ma.tei_m.printdebug(&st->ma.tei_m,
374 							"fixed assign tei %d", st->l2.tei);
375 			st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei);
376 			cs = (struct IsdnCardState *) st->l1.hardware;
377 			cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
378 		}
379 		return;
380 	}
381 	switch (pr) {
382 	case (MDL_ASSIGN | INDICATION):
383 		FsmEvent(&st->ma.tei_m, EV_IDREQ, arg);
384 		break;
385 	case (MDL_ERROR | REQUEST):
386 		FsmEvent(&st->ma.tei_m, EV_VERIFY, arg);
387 		break;
388 	default:
389 		break;
390 	}
391 }
392 
393 static void
tei_debug(struct FsmInst * fi,char * fmt,...)394 tei_debug(struct FsmInst *fi, char *fmt, ...)
395 {
396 	va_list args;
397 	struct PStack *st = fi->userdata;
398 
399 	va_start(args, fmt);
400 	VHiSax_putstatus(st->l1.hardware, "tei ", fmt, args);
401 	va_end(args);
402 }
403 
404 void
setstack_tei(struct PStack * st)405 setstack_tei(struct PStack *st)
406 {
407 	st->l2.l2tei = tei_l2tei;
408 	st->ma.T202 = 2000;	/* T202  2000 milliseconds */
409 	st->l1.l1tei = tei_l1l2;
410 	st->ma.debug = 1;
411 	st->ma.tei_m.fsm = &teifsm;
412 	st->ma.tei_m.state = ST_TEI_NOP;
413 	st->ma.tei_m.debug = 1;
414 	st->ma.tei_m.userdata = st;
415 	st->ma.tei_m.userint = 0;
416 	st->ma.tei_m.printdebug = tei_debug;
417 	FsmInitTimer(&st->ma.tei_m, &st->ma.t202);
418 }
419 
420 void
init_tei(struct IsdnCardState * cs,int protocol)421 init_tei(struct IsdnCardState *cs, int protocol)
422 {
423 }
424 
425 void
release_tei(struct IsdnCardState * cs)426 release_tei(struct IsdnCardState *cs)
427 {
428 	struct PStack *st = cs->stlist;
429 
430 	while (st) {
431 		FsmDelTimer(&st->ma.t202, 1);
432 		st = st->next;
433 	}
434 }
435 
436 static struct FsmNode TeiFnList[] __initdata =
437 {
438 	{ST_TEI_NOP, EV_IDREQ, tei_id_request},
439 	{ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup},
440 	{ST_TEI_NOP, EV_VERIFY, tei_id_verify},
441 	{ST_TEI_NOP, EV_REMOVE, tei_id_remove},
442 	{ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req},
443 	{ST_TEI_IDREQ, EV_T202, tei_id_req_tout},
444 	{ST_TEI_IDREQ, EV_ASSIGN, tei_id_assign},
445 	{ST_TEI_IDREQ, EV_DENIED, tei_id_denied},
446 	{ST_TEI_IDVERIFY, EV_T202, tei_id_ver_tout},
447 	{ST_TEI_IDVERIFY, EV_REMOVE, tei_id_remove},
448 	{ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req},
449 };
450 
451 int __init
TeiNew(void)452 TeiNew(void)
453 {
454 	teifsm.state_count = TEI_STATE_COUNT;
455 	teifsm.event_count = TEI_EVENT_COUNT;
456 	teifsm.strEvent = strTeiEvent;
457 	teifsm.strState = strTeiState;
458 	return FsmNew(&teifsm, TeiFnList, ARRAY_SIZE(TeiFnList));
459 }
460 
461 void
TeiFree(void)462 TeiFree(void)
463 {
464 	FsmFree(&teifsm);
465 }
466