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