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 24const 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 36static struct Fsm teifsm; 37 38void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb); 39 40enum { 41 ST_TEI_NOP, 42 ST_TEI_IDREQ, 43 ST_TEI_IDVERIFY, 44}; 45 46#define TEI_STATE_COUNT (ST_TEI_IDVERIFY + 1) 47 48static char *strTeiState[] = 49{ 50 "ST_TEI_NOP", 51 "ST_TEI_IDREQ", 52 "ST_TEI_IDVERIFY", 53}; 54 55enum { 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 67static 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 78static unsigned int 79random_ri(void) 80{ 81 unsigned int x; 82 83 get_random_bytes(&x, sizeof(x)); 84 return (x & 0xffff); 85} 86 87static struct PStack * 88findtei(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 103static void 104put_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 126static void 127tei_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 147static void 148tei_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 175static void 176tei_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 196static void 197tei_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 210static void 211tei_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 228static void 229tei_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 249static void 250tei_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 263static void 264tei_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 286static void 287tei_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 309static void 310tei_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 365static void 366tei_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 393static void 394tei_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 404void 405setstack_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 420void 421init_tei(struct IsdnCardState *cs, int protocol) 422{ 423} 424 425void 426release_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 436static 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 451int __init 452TeiNew(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 461void 462TeiFree(void) 463{ 464 FsmFree(&teifsm); 465} 466