Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tei.c
Go to the documentation of this file.
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 <[email protected]>
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 {
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 {
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
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 *
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
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
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
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
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
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
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
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
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
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);
283  }
284 }
285 
286 static void
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);
306  }
307 }
308 
309 static void
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
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
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
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
421 init_tei(struct IsdnCardState *cs, int protocol)
422 {
423 }
424 
425 void
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
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
462 TeiFree(void)
463 {
464  FsmFree(&teifsm);
465 }