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