1 /* $Id: l3_1tr6.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
2 *
3 * German 1TR6 D-channel protocol
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
10 *
11 * For changes and modifications please read
12 * ../../../Documentation/isdn/HiSax.cert
13 *
14 */
15
16 #define __NO_VERSION__
17 #include "hisax.h"
18 #include "l3_1tr6.h"
19 #include "isdnl3.h"
20 #include <linux/ctype.h>
21
22 extern char *HiSax_getrev(const char *revision);
23 const char *l3_1tr6_revision = "$Revision: 1.1.4.1 $";
24
25 #define MsgHead(ptr, cref, mty, dis) \
26 *ptr++ = dis; \
27 *ptr++ = 0x1; \
28 *ptr++ = cref ^ 0x80; \
29 *ptr++ = mty
30
31 static void
l3_1TR6_message(struct l3_process * pc,u_char mt,u_char pd)32 l3_1TR6_message(struct l3_process *pc, u_char mt, u_char pd)
33 {
34 struct sk_buff *skb;
35 u_char *p;
36
37 if (!(skb = l3_alloc_skb(4)))
38 return;
39 p = skb_put(skb, 4);
40 MsgHead(p, pc->callref, mt, pd);
41 l3_msg(pc->st, DL_DATA | REQUEST, skb);
42 }
43
44 static void
l3_1tr6_release_req(struct l3_process * pc,u_char pr,void * arg)45 l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
46 {
47 StopAllL3Timer(pc);
48 newl3state(pc, 19);
49 l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
50 L3AddTimer(&pc->timer, T308, CC_T308_1);
51 }
52
53 static void
l3_1tr6_invalid(struct l3_process * pc,u_char pr,void * arg)54 l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg)
55 {
56 struct sk_buff *skb = arg;
57
58 dev_kfree_skb(skb);
59 l3_1tr6_release_req(pc, 0, NULL);
60 }
61
62 static void
l3_1tr6_error(struct l3_process * pc,u_char * msg,struct sk_buff * skb)63 l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
64 {
65 dev_kfree_skb(skb);
66 if (pc->st->l3.debug & L3_DEB_WARN)
67 l3_debug(pc->st, msg);
68 l3_1tr6_release_req(pc, 0, NULL);
69 }
70
71 static void
l3_1tr6_setup_req(struct l3_process * pc,u_char pr,void * arg)72 l3_1tr6_setup_req(struct l3_process *pc, u_char pr, void *arg)
73 {
74 struct sk_buff *skb;
75 u_char tmp[128];
76 u_char *p = tmp;
77 u_char *teln;
78 u_char *eaz;
79 u_char channel = 0;
80 int l;
81
82 MsgHead(p, pc->callref, MT_N1_SETUP, PROTO_DIS_N1);
83 teln = pc->para.setup.phone;
84 pc->para.spv = 0;
85 if (!isdigit(*teln)) {
86 switch (0x5f & *teln) {
87 case 'S':
88 pc->para.spv = 1;
89 break;
90 case 'C':
91 channel = 0x08;
92 case 'P':
93 channel |= 0x80;
94 teln++;
95 if (*teln == '1')
96 channel |= 0x01;
97 else
98 channel |= 0x02;
99 break;
100 default:
101 if (pc->st->l3.debug & L3_DEB_WARN)
102 l3_debug(pc->st, "Wrong MSN Code");
103 break;
104 }
105 teln++;
106 }
107 if (channel) {
108 *p++ = 0x18; /* channel indicator */
109 *p++ = 1;
110 *p++ = channel;
111 }
112 if (pc->para.spv) { /* SPV ? */
113 /* NSF SPV */
114 *p++ = WE0_netSpecFac;
115 *p++ = 4; /* Laenge */
116 *p++ = 0;
117 *p++ = FAC_SPV; /* SPV */
118 *p++ = pc->para.setup.si1; /* 0 for all Services */
119 *p++ = pc->para.setup.si2; /* 0 for all Services */
120 *p++ = WE0_netSpecFac;
121 *p++ = 4; /* Laenge */
122 *p++ = 0;
123 *p++ = FAC_Activate; /* aktiviere SPV (default) */
124 *p++ = pc->para.setup.si1; /* 0 for all Services */
125 *p++ = pc->para.setup.si2; /* 0 for all Services */
126 }
127 eaz = pc->para.setup.eazmsn;
128 if (*eaz) {
129 *p++ = WE0_origAddr;
130 *p++ = strlen(eaz) + 1;
131 /* Classify as AnyPref. */
132 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
133 while (*eaz)
134 *p++ = *eaz++ & 0x7f;
135 }
136 *p++ = WE0_destAddr;
137 *p++ = strlen(teln) + 1;
138 /* Classify as AnyPref. */
139 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
140 while (*teln)
141 *p++ = *teln++ & 0x7f;
142
143 *p++ = WE_Shift_F6;
144 /* Codesatz 6 fuer Service */
145 *p++ = WE6_serviceInd;
146 *p++ = 2; /* len=2 info,info2 */
147 *p++ = pc->para.setup.si1;
148 *p++ = pc->para.setup.si2;
149
150 l = p - tmp;
151 if (!(skb = l3_alloc_skb(l)))
152 return;
153 memcpy(skb_put(skb, l), tmp, l);
154 L3DelTimer(&pc->timer);
155 L3AddTimer(&pc->timer, T303, CC_T303);
156 newl3state(pc, 1);
157 l3_msg(pc->st, DL_DATA | REQUEST, skb);
158 }
159
160 static void
l3_1tr6_setup(struct l3_process * pc,u_char pr,void * arg)161 l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
162 {
163 u_char *p;
164 int bcfound = 0;
165 char tmp[80];
166 struct sk_buff *skb = arg;
167
168 p = skb->data;
169
170 /* Channel Identification */
171 p = skb->data;
172 if ((p = findie(p, skb->len, WE0_chanID, 0))) {
173 if (p[1] != 1) {
174 l3_1tr6_error(pc, "setup wrong chanID len", skb);
175 return;
176 }
177 if ((p[2] & 0xf4) != 0x80) {
178 l3_1tr6_error(pc, "setup wrong WE0_chanID", skb);
179 return;
180 }
181 if ((pc->para.bchannel = p[2] & 0x3))
182 bcfound++;
183 } else {
184 l3_1tr6_error(pc, "missing setup chanID", skb);
185 return;
186 }
187
188 p = skb->data;
189 if ((p = findie(p, skb->len, WE6_serviceInd, 6))) {
190 pc->para.setup.si1 = p[2];
191 pc->para.setup.si2 = p[3];
192 } else {
193 l3_1tr6_error(pc, "missing setup SI", skb);
194 return;
195 }
196
197 p = skb->data;
198 if ((p = findie(p, skb->len, WE0_destAddr, 0)))
199 iecpy(pc->para.setup.eazmsn, p, 1);
200 else
201 pc->para.setup.eazmsn[0] = 0;
202
203 p = skb->data;
204 if ((p = findie(p, skb->len, WE0_origAddr, 0))) {
205 iecpy(pc->para.setup.phone, p, 1);
206 } else
207 pc->para.setup.phone[0] = 0;
208
209 p = skb->data;
210 pc->para.spv = 0;
211 if ((p = findie(p, skb->len, WE0_netSpecFac, 0))) {
212 if ((FAC_SPV == p[3]) || (FAC_Activate == p[3]))
213 pc->para.spv = 1;
214 }
215 dev_kfree_skb(skb);
216
217 /* Signal all services, linklevel takes care of Service-Indicator */
218 if (bcfound) {
219 if ((pc->para.setup.si1 != 7) && (pc->st->l3.debug & L3_DEB_WARN)) {
220 sprintf(tmp, "non-digital call: %s -> %s",
221 pc->para.setup.phone,
222 pc->para.setup.eazmsn);
223 l3_debug(pc->st, tmp);
224 }
225 newl3state(pc, 6);
226 pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
227 } else
228 release_l3_process(pc);
229 }
230
231 static void
l3_1tr6_setup_ack(struct l3_process * pc,u_char pr,void * arg)232 l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg)
233 {
234 u_char *p;
235 struct sk_buff *skb = arg;
236
237 L3DelTimer(&pc->timer);
238 p = skb->data;
239 newl3state(pc, 2);
240 if ((p = findie(p, skb->len, WE0_chanID, 0))) {
241 if (p[1] != 1) {
242 l3_1tr6_error(pc, "setup_ack wrong chanID len", skb);
243 return;
244 }
245 if ((p[2] & 0xf4) != 0x80) {
246 l3_1tr6_error(pc, "setup_ack wrong WE0_chanID", skb);
247 return;
248 }
249 pc->para.bchannel = p[2] & 0x3;
250 } else {
251 l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb);
252 return;
253 }
254 dev_kfree_skb(skb);
255 L3AddTimer(&pc->timer, T304, CC_T304);
256 pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
257 }
258
259 static void
l3_1tr6_call_sent(struct l3_process * pc,u_char pr,void * arg)260 l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg)
261 {
262 u_char *p;
263 struct sk_buff *skb = arg;
264
265 L3DelTimer(&pc->timer);
266 p = skb->data;
267 if ((p = findie(p, skb->len, WE0_chanID, 0))) {
268 if (p[1] != 1) {
269 l3_1tr6_error(pc, "call sent wrong chanID len", skb);
270 return;
271 }
272 if ((p[2] & 0xf4) != 0x80) {
273 l3_1tr6_error(pc, "call sent wrong WE0_chanID", skb);
274 return;
275 }
276 if ((pc->state == 2) && (pc->para.bchannel != (p[2] & 0x3))) {
277 l3_1tr6_error(pc, "call sent wrong chanID value", skb);
278 return;
279 }
280 pc->para.bchannel = p[2] & 0x3;
281 } else {
282 l3_1tr6_error(pc, "missing call sent WE0_chanID", skb);
283 return;
284 }
285 dev_kfree_skb(skb);
286 L3AddTimer(&pc->timer, T310, CC_T310);
287 newl3state(pc, 3);
288 pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
289 }
290
291 static void
l3_1tr6_alert(struct l3_process * pc,u_char pr,void * arg)292 l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg)
293 {
294 struct sk_buff *skb = arg;
295
296 dev_kfree_skb(skb);
297 L3DelTimer(&pc->timer); /* T304 */
298 newl3state(pc, 4);
299 pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
300 }
301
302 static void
l3_1tr6_info(struct l3_process * pc,u_char pr,void * arg)303 l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg)
304 {
305 u_char *p;
306 int i, tmpcharge = 0;
307 char a_charge[8], tmp[32];
308 struct sk_buff *skb = arg;
309
310 p = skb->data;
311 if ((p = findie(p, skb->len, WE6_chargingInfo, 6))) {
312 iecpy(a_charge, p, 1);
313 for (i = 0; i < strlen(a_charge); i++) {
314 tmpcharge *= 10;
315 tmpcharge += a_charge[i] & 0xf;
316 }
317 if (tmpcharge > pc->para.chargeinfo) {
318 pc->para.chargeinfo = tmpcharge;
319 pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
320 }
321 if (pc->st->l3.debug & L3_DEB_CHARGE) {
322 sprintf(tmp, "charging info %d", pc->para.chargeinfo);
323 l3_debug(pc->st, tmp);
324 }
325 } else if (pc->st->l3.debug & L3_DEB_CHARGE)
326 l3_debug(pc->st, "charging info not found");
327 dev_kfree_skb(skb);
328
329 }
330
331 static void
l3_1tr6_info_s2(struct l3_process * pc,u_char pr,void * arg)332 l3_1tr6_info_s2(struct l3_process *pc, u_char pr, void *arg)
333 {
334 struct sk_buff *skb = arg;
335
336 dev_kfree_skb(skb);
337 }
338
339 static void
l3_1tr6_connect(struct l3_process * pc,u_char pr,void * arg)340 l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg)
341 {
342 struct sk_buff *skb = arg;
343
344 L3DelTimer(&pc->timer); /* T310 */
345 if (!findie(skb->data, skb->len, WE6_date, 6)) {
346 l3_1tr6_error(pc, "missing connect date", skb);
347 return;
348 }
349 newl3state(pc, 10);
350 dev_kfree_skb(skb);
351 pc->para.chargeinfo = 0;
352 pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
353 }
354
355 static void
l3_1tr6_rel(struct l3_process * pc,u_char pr,void * arg)356 l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg)
357 {
358 struct sk_buff *skb = arg;
359 u_char *p;
360
361 p = skb->data;
362 if ((p = findie(p, skb->len, WE0_cause, 0))) {
363 if (p[1] > 0) {
364 pc->para.cause = p[2];
365 if (p[1] > 1)
366 pc->para.loc = p[3];
367 else
368 pc->para.loc = 0;
369 } else {
370 pc->para.cause = 0;
371 pc->para.loc = 0;
372 }
373 } else {
374 pc->para.cause = NO_CAUSE;
375 l3_1tr6_error(pc, "missing REL cause", skb);
376 return;
377 }
378 dev_kfree_skb(skb);
379 StopAllL3Timer(pc);
380 newl3state(pc, 0);
381 l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1);
382 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
383 release_l3_process(pc);
384 }
385
386 static void
l3_1tr6_rel_ack(struct l3_process * pc,u_char pr,void * arg)387 l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg)
388 {
389 struct sk_buff *skb = arg;
390
391 dev_kfree_skb(skb);
392 StopAllL3Timer(pc);
393 newl3state(pc, 0);
394 pc->para.cause = NO_CAUSE;
395 pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
396 release_l3_process(pc);
397 }
398
399 static void
l3_1tr6_disc(struct l3_process * pc,u_char pr,void * arg)400 l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
401 {
402 struct sk_buff *skb = arg;
403 u_char *p;
404 int i, tmpcharge = 0;
405 char a_charge[8], tmp[32];
406
407 StopAllL3Timer(pc);
408 p = skb->data;
409 if ((p = findie(p, skb->len, WE6_chargingInfo, 6))) {
410 iecpy(a_charge, p, 1);
411 for (i = 0; i < strlen(a_charge); i++) {
412 tmpcharge *= 10;
413 tmpcharge += a_charge[i] & 0xf;
414 }
415 if (tmpcharge > pc->para.chargeinfo) {
416 pc->para.chargeinfo = tmpcharge;
417 pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
418 }
419 if (pc->st->l3.debug & L3_DEB_CHARGE) {
420 sprintf(tmp, "charging info %d", pc->para.chargeinfo);
421 l3_debug(pc->st, tmp);
422 }
423 } else if (pc->st->l3.debug & L3_DEB_CHARGE)
424 l3_debug(pc->st, "charging info not found");
425
426
427 p = skb->data;
428 if ((p = findie(p, skb->len, WE0_cause, 0))) {
429 if (p[1] > 0) {
430 pc->para.cause = p[2];
431 if (p[1] > 1)
432 pc->para.loc = p[3];
433 else
434 pc->para.loc = 0;
435 } else {
436 pc->para.cause = 0;
437 pc->para.loc = 0;
438 }
439 } else {
440 if (pc->st->l3.debug & L3_DEB_WARN)
441 l3_debug(pc->st, "cause not found");
442 pc->para.cause = NO_CAUSE;
443 }
444 if (!findie(skb->data, skb->len, WE6_date, 6)) {
445 l3_1tr6_error(pc, "missing connack date", skb);
446 return;
447 }
448 dev_kfree_skb(skb);
449 newl3state(pc, 12);
450 pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
451 }
452
453
454 static void
l3_1tr6_connect_ack(struct l3_process * pc,u_char pr,void * arg)455 l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg)
456 {
457 struct sk_buff *skb = arg;
458
459 if (!findie(skb->data, skb->len, WE6_date, 6)) {
460 l3_1tr6_error(pc, "missing connack date", skb);
461 return;
462 }
463 dev_kfree_skb(skb);
464 newl3state(pc, 10);
465 pc->para.chargeinfo = 0;
466 L3DelTimer(&pc->timer);
467 pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
468 }
469
470 static void
l3_1tr6_alert_req(struct l3_process * pc,u_char pr,void * arg)471 l3_1tr6_alert_req(struct l3_process *pc, u_char pr, void *arg)
472 {
473 newl3state(pc, 7);
474 l3_1TR6_message(pc, MT_N1_ALERT, PROTO_DIS_N1);
475 }
476
477 static void
l3_1tr6_setup_rsp(struct l3_process * pc,u_char pr,void * arg)478 l3_1tr6_setup_rsp(struct l3_process *pc, u_char pr, void *arg)
479 {
480 struct sk_buff *skb;
481 u_char tmp[24];
482 u_char *p = tmp;
483 int l;
484
485 MsgHead(p, pc->callref, MT_N1_CONN, PROTO_DIS_N1);
486 if (pc->para.spv) { /* SPV ? */
487 /* NSF SPV */
488 *p++ = WE0_netSpecFac;
489 *p++ = 4; /* Laenge */
490 *p++ = 0;
491 *p++ = FAC_SPV; /* SPV */
492 *p++ = pc->para.setup.si1;
493 *p++ = pc->para.setup.si2;
494 *p++ = WE0_netSpecFac;
495 *p++ = 4; /* Laenge */
496 *p++ = 0;
497 *p++ = FAC_Activate; /* aktiviere SPV */
498 *p++ = pc->para.setup.si1;
499 *p++ = pc->para.setup.si2;
500 }
501 newl3state(pc, 8);
502 l = p - tmp;
503 if (!(skb = l3_alloc_skb(l)))
504 return;
505 memcpy(skb_put(skb, l), tmp, l);
506 l3_msg(pc->st, DL_DATA | REQUEST, skb);
507 L3DelTimer(&pc->timer);
508 L3AddTimer(&pc->timer, T313, CC_T313);
509 }
510
511 static void
l3_1tr6_reset(struct l3_process * pc,u_char pr,void * arg)512 l3_1tr6_reset(struct l3_process *pc, u_char pr, void *arg)
513 {
514 release_l3_process(pc);
515 }
516
517 static void
l3_1tr6_disconnect_req(struct l3_process * pc,u_char pr,void * arg)518 l3_1tr6_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
519 {
520 struct sk_buff *skb;
521 u_char tmp[16];
522 u_char *p = tmp;
523 int l;
524 u_char cause = 0x10;
525 u_char clen = 1;
526
527 if (pc->para.cause > 0)
528 cause = pc->para.cause;
529 /* Map DSS1 causes */
530 switch (cause & 0x7f) {
531 case 0x10:
532 clen = 0;
533 break;
534 case 0x11:
535 cause = CAUSE_UserBusy;
536 break;
537 case 0x15:
538 cause = CAUSE_CallRejected;
539 break;
540 }
541 StopAllL3Timer(pc);
542 MsgHead(p, pc->callref, MT_N1_DISC, PROTO_DIS_N1);
543 *p++ = WE0_cause;
544 *p++ = clen; /* Laenge */
545 if (clen)
546 *p++ = cause | 0x80;
547 newl3state(pc, 11);
548 l = p - tmp;
549 if (!(skb = l3_alloc_skb(l)))
550 return;
551 memcpy(skb_put(skb, l), tmp, l);
552 l3_msg(pc->st, DL_DATA | REQUEST, skb);
553 L3AddTimer(&pc->timer, T305, CC_T305);
554 }
555
556 static void
l3_1tr6_t303(struct l3_process * pc,u_char pr,void * arg)557 l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg)
558 {
559 if (pc->N303 > 0) {
560 pc->N303--;
561 L3DelTimer(&pc->timer);
562 l3_1tr6_setup_req(pc, pr, arg);
563 } else {
564 L3DelTimer(&pc->timer);
565 pc->para.cause = 0;
566 l3_1tr6_disconnect_req(pc, 0, NULL);
567 }
568 }
569
570 static void
l3_1tr6_t304(struct l3_process * pc,u_char pr,void * arg)571 l3_1tr6_t304(struct l3_process *pc, u_char pr, void *arg)
572 {
573 L3DelTimer(&pc->timer);
574 pc->para.cause = 0xE6;
575 l3_1tr6_disconnect_req(pc, pr, NULL);
576 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
577 }
578
579 static void
l3_1tr6_t305(struct l3_process * pc,u_char pr,void * arg)580 l3_1tr6_t305(struct l3_process *pc, u_char pr, void *arg)
581 {
582 struct sk_buff *skb;
583 u_char tmp[16];
584 u_char *p = tmp;
585 int l;
586 u_char cause = 0x90;
587 u_char clen = 1;
588
589 L3DelTimer(&pc->timer);
590 if (pc->para.cause != NO_CAUSE)
591 cause = pc->para.cause;
592 /* Map DSS1 causes */
593 switch (cause & 0x7f) {
594 case 0x10:
595 clen = 0;
596 break;
597 case 0x15:
598 cause = CAUSE_CallRejected;
599 break;
600 }
601 MsgHead(p, pc->callref, MT_N1_REL, PROTO_DIS_N1);
602 *p++ = WE0_cause;
603 *p++ = clen; /* Laenge */
604 if (clen)
605 *p++ = cause;
606 newl3state(pc, 19);
607 l = p - tmp;
608 if (!(skb = l3_alloc_skb(l)))
609 return;
610 memcpy(skb_put(skb, l), tmp, l);
611 l3_msg(pc->st, DL_DATA | REQUEST, skb);
612 L3AddTimer(&pc->timer, T308, CC_T308_1);
613 }
614
615 static void
l3_1tr6_t310(struct l3_process * pc,u_char pr,void * arg)616 l3_1tr6_t310(struct l3_process *pc, u_char pr, void *arg)
617 {
618 L3DelTimer(&pc->timer);
619 pc->para.cause = 0xE6;
620 l3_1tr6_disconnect_req(pc, pr, NULL);
621 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
622 }
623
624 static void
l3_1tr6_t313(struct l3_process * pc,u_char pr,void * arg)625 l3_1tr6_t313(struct l3_process *pc, u_char pr, void *arg)
626 {
627 L3DelTimer(&pc->timer);
628 pc->para.cause = 0xE6;
629 l3_1tr6_disconnect_req(pc, pr, NULL);
630 pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
631 }
632
633 static void
l3_1tr6_t308_1(struct l3_process * pc,u_char pr,void * arg)634 l3_1tr6_t308_1(struct l3_process *pc, u_char pr, void *arg)
635 {
636 L3DelTimer(&pc->timer);
637 l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
638 L3AddTimer(&pc->timer, T308, CC_T308_2);
639 newl3state(pc, 19);
640 }
641
642 static void
l3_1tr6_t308_2(struct l3_process * pc,u_char pr,void * arg)643 l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg)
644 {
645 L3DelTimer(&pc->timer);
646 pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
647 release_l3_process(pc);
648 }
649
650 static void
l3_1tr6_dl_reset(struct l3_process * pc,u_char pr,void * arg)651 l3_1tr6_dl_reset(struct l3_process *pc, u_char pr, void *arg)
652 {
653 pc->para.cause = CAUSE_LocalProcErr;
654 l3_1tr6_disconnect_req(pc, pr, NULL);
655 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
656 }
657
658 static void
l3_1tr6_dl_release(struct l3_process * pc,u_char pr,void * arg)659 l3_1tr6_dl_release(struct l3_process *pc, u_char pr, void *arg)
660 {
661 newl3state(pc, 0);
662 pc->para.cause = 0x1b; /* Destination out of order */
663 pc->para.loc = 0;
664 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
665 release_l3_process(pc);
666 }
667
668 /* *INDENT-OFF* */
669 static struct stateentry downstl[] =
670 {
671 {SBIT(0),
672 CC_SETUP | REQUEST, l3_1tr6_setup_req},
673 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) |
674 SBIT(10),
675 CC_DISCONNECT | REQUEST, l3_1tr6_disconnect_req},
676 {SBIT(12),
677 CC_RELEASE | REQUEST, l3_1tr6_release_req},
678 {SBIT(6),
679 CC_IGNORE | REQUEST, l3_1tr6_reset},
680 {SBIT(6),
681 CC_REJECT | REQUEST, l3_1tr6_disconnect_req},
682 {SBIT(6),
683 CC_ALERTING | REQUEST, l3_1tr6_alert_req},
684 {SBIT(6) | SBIT(7),
685 CC_SETUP | RESPONSE, l3_1tr6_setup_rsp},
686 {SBIT(1),
687 CC_T303, l3_1tr6_t303},
688 {SBIT(2),
689 CC_T304, l3_1tr6_t304},
690 {SBIT(3),
691 CC_T310, l3_1tr6_t310},
692 {SBIT(8),
693 CC_T313, l3_1tr6_t313},
694 {SBIT(11),
695 CC_T305, l3_1tr6_t305},
696 {SBIT(19),
697 CC_T308_1, l3_1tr6_t308_1},
698 {SBIT(19),
699 CC_T308_2, l3_1tr6_t308_2},
700 };
701
702 #define DOWNSTL_LEN \
703 (sizeof(downstl) / sizeof(struct stateentry))
704
705 static struct stateentry datastln1[] =
706 {
707 {SBIT(0),
708 MT_N1_INVALID, l3_1tr6_invalid},
709 {SBIT(0),
710 MT_N1_SETUP, l3_1tr6_setup},
711 {SBIT(1),
712 MT_N1_SETUP_ACK, l3_1tr6_setup_ack},
713 {SBIT(1) | SBIT(2),
714 MT_N1_CALL_SENT, l3_1tr6_call_sent},
715 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10),
716 MT_N1_DISC, l3_1tr6_disc},
717 {SBIT(2) | SBIT(3) | SBIT(4),
718 MT_N1_ALERT, l3_1tr6_alert},
719 {SBIT(2) | SBIT(3) | SBIT(4),
720 MT_N1_CONN, l3_1tr6_connect},
721 {SBIT(2),
722 MT_N1_INFO, l3_1tr6_info_s2},
723 {SBIT(8),
724 MT_N1_CONN_ACK, l3_1tr6_connect_ack},
725 {SBIT(10),
726 MT_N1_INFO, l3_1tr6_info},
727 {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
728 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
729 MT_N1_REL, l3_1tr6_rel},
730 {SBIT(19),
731 MT_N1_REL, l3_1tr6_rel_ack},
732 {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
733 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
734 MT_N1_REL_ACK, l3_1tr6_invalid},
735 {SBIT(19),
736 MT_N1_REL_ACK, l3_1tr6_rel_ack}
737 };
738
739 #define DATASTLN1_LEN \
740 (sizeof(datastln1) / sizeof(struct stateentry))
741
742 static struct stateentry manstatelist[] =
743 {
744 {SBIT(2),
745 DL_ESTABLISH | INDICATION, l3_1tr6_dl_reset},
746 {ALL_STATES,
747 DL_RELEASE | INDICATION, l3_1tr6_dl_release},
748 };
749
750 #define MANSLLEN \
751 (sizeof(manstatelist) / sizeof(struct stateentry))
752 /* *INDENT-ON* */
753
754 static void
up1tr6(struct PStack * st,int pr,void * arg)755 up1tr6(struct PStack *st, int pr, void *arg)
756 {
757 int i, mt, cr;
758 struct l3_process *proc;
759 struct sk_buff *skb = arg;
760 char tmp[80];
761
762 switch (pr) {
763 case (DL_DATA | INDICATION):
764 case (DL_UNIT_DATA | INDICATION):
765 break;
766 case (DL_ESTABLISH | CONFIRM):
767 case (DL_ESTABLISH | INDICATION):
768 case (DL_RELEASE | INDICATION):
769 case (DL_RELEASE | CONFIRM):
770 l3_msg(st, pr, arg);
771 return;
772 break;
773 }
774 if (skb->len < 4) {
775 if (st->l3.debug & L3_DEB_PROTERR) {
776 sprintf(tmp, "up1tr6 len only %d", skb->len);
777 l3_debug(st, tmp);
778 }
779 dev_kfree_skb(skb);
780 return;
781 }
782 if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) {
783 if (st->l3.debug & L3_DEB_PROTERR) {
784 sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %d",
785 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
786 skb->data[0], skb->len);
787 l3_debug(st, tmp);
788 }
789 dev_kfree_skb(skb);
790 return;
791 }
792 if (skb->data[1] != 1) {
793 if (st->l3.debug & L3_DEB_PROTERR) {
794 sprintf(tmp, "up1tr6 CR len not 1");
795 l3_debug(st, tmp);
796 }
797 dev_kfree_skb(skb);
798 return;
799 }
800 cr = skb->data[2];
801 mt = skb->data[3];
802 if (skb->data[0] == PROTO_DIS_N0) {
803 dev_kfree_skb(skb);
804 if (st->l3.debug & L3_DEB_STATE) {
805 sprintf(tmp, "up1tr6%s N0 mt %x unhandled",
806 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt);
807 l3_debug(st, tmp);
808 }
809 } else if (skb->data[0] == PROTO_DIS_N1) {
810 if (!(proc = getl3proc(st, cr))) {
811 if (mt == MT_N1_SETUP) {
812 if (cr < 128) {
813 if (!(proc = new_l3_process(st, cr))) {
814 if (st->l3.debug & L3_DEB_PROTERR) {
815 sprintf(tmp, "up1tr6 no roc mem");
816 l3_debug(st, tmp);
817 }
818 dev_kfree_skb(skb);
819 return;
820 }
821 } else {
822 dev_kfree_skb(skb);
823 return;
824 }
825 } else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) ||
826 (mt == MT_N1_CANC_ACK) || (mt == MT_N1_CANC_REJ) ||
827 (mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) ||
828 (mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) ||
829 (mt == MT_N1_INFO)) {
830 dev_kfree_skb(skb);
831 return;
832 } else {
833 if (!(proc = new_l3_process(st, cr))) {
834 if (st->l3.debug & L3_DEB_PROTERR) {
835 sprintf(tmp, "up1tr6 no roc mem");
836 l3_debug(st, tmp);
837 }
838 dev_kfree_skb(skb);
839 return;
840 }
841 mt = MT_N1_INVALID;
842 }
843 }
844 for (i = 0; i < DATASTLN1_LEN; i++)
845 if ((mt == datastln1[i].primitive) &&
846 ((1 << proc->state) & datastln1[i].state))
847 break;
848 if (i == DATASTLN1_LEN) {
849 dev_kfree_skb(skb);
850 if (st->l3.debug & L3_DEB_STATE) {
851 sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
852 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
853 proc->state, mt);
854 l3_debug(st, tmp);
855 }
856 return;
857 } else {
858 if (st->l3.debug & L3_DEB_STATE) {
859 sprintf(tmp, "up1tr6%sstate %d mt %x",
860 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
861 proc->state, mt);
862 l3_debug(st, tmp);
863 }
864 datastln1[i].rout(proc, pr, skb);
865 }
866 }
867 }
868
869 static void
down1tr6(struct PStack * st,int pr,void * arg)870 down1tr6(struct PStack *st, int pr, void *arg)
871 {
872 int i, cr;
873 struct l3_process *proc;
874 struct Channel *chan;
875 char tmp[80];
876
877 if ((DL_ESTABLISH | REQUEST)== pr) {
878 l3_msg(st, pr, NULL);
879 return;
880 } else if ((CC_SETUP | REQUEST) == pr) {
881 chan = arg;
882 cr = newcallref();
883 cr |= 0x80;
884 if (!(proc = new_l3_process(st, cr))) {
885 return;
886 } else {
887 proc->chan = chan;
888 chan->proc = proc;
889 memcpy(&proc->para.setup, &chan->setup, sizeof(setup_parm));
890 proc->callref = cr;
891 }
892 } else {
893 proc = arg;
894 }
895
896 for (i = 0; i < DOWNSTL_LEN; i++)
897 if ((pr == downstl[i].primitive) &&
898 ((1 << proc->state) & downstl[i].state))
899 break;
900 if (i == DOWNSTL_LEN) {
901 if (st->l3.debug & L3_DEB_STATE) {
902 sprintf(tmp, "down1tr6 state %d prim %d unhandled",
903 proc->state, pr);
904 l3_debug(st, tmp);
905 }
906 } else {
907 if (st->l3.debug & L3_DEB_STATE) {
908 sprintf(tmp, "down1tr6 state %d prim %d",
909 proc->state, pr);
910 l3_debug(st, tmp);
911 }
912 downstl[i].rout(proc, pr, arg);
913 }
914 }
915
916 static void
man1tr6(struct PStack * st,int pr,void * arg)917 man1tr6(struct PStack *st, int pr, void *arg)
918 {
919 int i;
920 struct l3_process *proc = arg;
921
922 if (!proc) {
923 printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr);
924 return;
925 }
926 for (i = 0; i < MANSLLEN; i++)
927 if ((pr == manstatelist[i].primitive) &&
928 ((1 << proc->state) & manstatelist[i].state))
929 break;
930 if (i == MANSLLEN) {
931 if (st->l3.debug & L3_DEB_STATE) {
932 l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled",
933 proc->callref & 0x7f, proc->state, pr);
934 }
935 } else {
936 if (st->l3.debug & L3_DEB_STATE) {
937 l3_debug(st, "cr %d man1tr6 state %d prim %d",
938 proc->callref & 0x7f, proc->state, pr);
939 }
940 manstatelist[i].rout(proc, pr, arg);
941 }
942 }
943
944 void
setstack_1tr6(struct PStack * st)945 setstack_1tr6(struct PStack *st)
946 {
947 char tmp[64];
948
949 st->lli.l4l3 = down1tr6;
950 st->l2.l2l3 = up1tr6;
951 st->l3.l3ml3 = man1tr6;
952 st->l3.N303 = 0;
953
954 strcpy(tmp, l3_1tr6_revision);
955 printk(KERN_INFO "HiSax: 1TR6 Rev. %s\n", HiSax_getrev(tmp));
956 }
957