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