patch-2.3.4 linux/drivers/isdn/hisax/l3_1tr6.c

Next file: linux/drivers/isdn/hisax/l3_1tr6.h
Previous file: linux/drivers/isdn/hisax/ix1_micro.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.3/linux/drivers/isdn/hisax/l3_1tr6.c linux/drivers/isdn/hisax/l3_1tr6.c
@@ -1,11 +1,29 @@
-/* $Id: l3_1tr6.c,v 2.4 1998/02/12 23:07:57 keil Exp $
+/* $Id: l3_1tr6.c,v 2.8 1998/11/15 23:55:08 keil Exp $
 
  *  German 1TR6 D-channel protocol
  *
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
+ *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
  *
  *
  * $Log: l3_1tr6.c,v $
+ * Revision 2.8  1998/11/15 23:55:08  keil
+ * changes from 2.0
+ *
+ * Revision 2.7  1998/08/13 23:36:45  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.6  1998/05/25 14:10:18  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.5  1998/05/25 12:58:14  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
  * Revision 2.4  1998/02/12 23:07:57  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -38,7 +56,7 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 2.4 $";
+const char *l3_1tr6_revision = "$Revision: 2.8 $";
 
 #define MsgHead(ptr, cref, mty, dis) \
 	*ptr++ = dis; \
@@ -56,66 +74,34 @@
 		return;
 	p = skb_put(skb, 4);
 	MsgHead(p, pc->callref, mt, pd);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 }
 
-static int
-l31tr6_check_messagetype_validity(int mt, int pd) {
-/* verify if a message type exists */
-
-	if (pd == PROTO_DIS_N0)
-		switch(mt) {
-		   case MT_N0_REG_IND:
-		   case MT_N0_CANC_IND:
-		   case MT_N0_FAC_STA:
-		   case MT_N0_STA_ACK:
-		   case MT_N0_STA_REJ:
-		   case MT_N0_FAC_INF:
-		   case MT_N0_INF_ACK:
-		   case MT_N0_INF_REJ:
-		   case MT_N0_CLOSE:
-		   case MT_N0_CLO_ACK:
-			return(1);
-		   default:
-			return(0);
-		}
-	else if (pd == PROTO_DIS_N1)
-		switch(mt) {
-		   case MT_N1_ESC:
-		   case MT_N1_ALERT:
-		   case MT_N1_CALL_SENT:
-		   case MT_N1_CONN:
-		   case MT_N1_CONN_ACK:
-		   case MT_N1_SETUP:
-		   case MT_N1_SETUP_ACK:
-		   case MT_N1_RES:
-		   case MT_N1_RES_ACK:
-		   case MT_N1_RES_REJ:
-		   case MT_N1_SUSP:
-		   case MT_N1_SUSP_ACK:
-		   case MT_N1_SUSP_REJ:
-		   case MT_N1_USER_INFO:
-		   case MT_N1_DET:
-		   case MT_N1_DISC:
-		   case MT_N1_REL:
-		   case MT_N1_REL_ACK:
-		   case MT_N1_CANC_ACK:
-		   case MT_N1_CANC_REJ:
-		   case MT_N1_CON_CON:
-		   case MT_N1_FAC:
-		   case MT_N1_FAC_ACK:
-		   case MT_N1_FAC_CAN:
-		   case MT_N1_FAC_REG:
-		   case MT_N1_FAC_REJ:
-		   case MT_N1_INFO:
-		   case MT_N1_REG_ACK:
-		   case MT_N1_REG_REJ:
-		   case MT_N1_STAT:
-		   	return (1);
-		   default:
-		   	return(0);
-		}
-	return(0);
+static void
+l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
+{
+	StopAllL3Timer(pc);
+	newl3state(pc, 19);
+	l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
+	L3AddTimer(&pc->timer, T308, CC_T308_1);
+}
+
+static void
+l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+
+	dev_kfree_skb(skb);
+	l3_1tr6_release_req(pc, 0, NULL);
+}
+
+static void
+l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
+{
+	dev_kfree_skb(skb);
+	if (pc->st->l3.debug & L3_DEB_WARN)
+		l3_debug(pc->st, msg);
+	l3_1tr6_release_req(pc, 0, NULL);
 }
 
 static void
@@ -204,7 +190,7 @@
 	L3DelTimer(&pc->timer);
 	L3AddTimer(&pc->timer, T303, CC_T303);
 	newl3state(pc, 1);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 }
 
 static void
@@ -220,17 +206,29 @@
 	/* Channel Identification */
 	p = skb->data;
 	if ((p = findie(p, skb->len, WE0_chanID, 0))) {
-		pc->para.bchannel = p[2] & 0x3;
-		bcfound++;
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup without bchannel");
+		if (p[1] != 1) {
+			l3_1tr6_error(pc, "setup wrong chanID len", skb);
+			return;
+		}
+		if ((p[2] & 0xf4) != 0x80) {
+			l3_1tr6_error(pc, "setup wrong WE0_chanID", skb);
+			return;
+		}
+		if ((pc->para.bchannel = p[2] & 0x3))
+				bcfound++;
+	} else {
+		l3_1tr6_error(pc, "missing setup chanID", skb);
+		return;
+	}
 
 	p = skb->data;
 	if ((p = findie(p, skb->len, WE6_serviceInd, 6))) {
 		pc->para.setup.si1 = p[2];
 		pc->para.setup.si2 = p[3];
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup without service indicator");
+	} else {
+		l3_1tr6_error(pc, "missing setup SI", skb);
+		return;
+	}
 
 	p = skb->data;
 	if ((p = findie(p, skb->len, WE0_destAddr, 0)))
@@ -261,7 +259,7 @@
 			l3_debug(pc->st, tmp);
 		}
 		newl3state(pc, 6);
-		pc->st->l3.l3l4(pc, CC_SETUP_IND, NULL);
+		pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
 	} else
 		release_l3_process(pc);
 }
@@ -276,12 +274,22 @@
 	p = skb->data;
 	newl3state(pc, 2);
 	if ((p = findie(p, skb->len, WE0_chanID, 0))) {
+		if (p[1] != 1) {
+			l3_1tr6_error(pc, "setup_ack wrong chanID len", skb);
+			return;
+		}
+		if ((p[2] & 0xf4) != 0x80) {
+			l3_1tr6_error(pc, "setup_ack wrong WE0_chanID", skb);
+			return;
+		}
 		pc->para.bchannel = p[2] & 0x3;
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup answer without bchannel");
+	} else {
+		l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb);
+		return;
+	}
 	dev_kfree_skb(skb);
 	L3AddTimer(&pc->timer, T304, CC_T304);
-	pc->st->l3.l3l4(pc, CC_MORE_INFO, NULL);
+	pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
 }
 
 static void
@@ -293,13 +301,27 @@
 	L3DelTimer(&pc->timer);
 	p = skb->data;
 	if ((p = findie(p, skb->len, WE0_chanID, 0))) {
+		if (p[1] != 1) {
+			l3_1tr6_error(pc, "call sent wrong chanID len", skb);
+			return;
+		}
+		if ((p[2] & 0xf4) != 0x80) {
+			l3_1tr6_error(pc, "call sent wrong WE0_chanID", skb);
+			return;
+		}
+		if ((pc->state == 2) && (pc->para.bchannel != (p[2] & 0x3))) {
+			l3_1tr6_error(pc, "call sent wrong chanID value", skb);
+			return;
+		}
 		pc->para.bchannel = p[2] & 0x3;
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup answer without bchannel");
+	} else {
+		l3_1tr6_error(pc, "missing call sent WE0_chanID", skb);
+		return;
+	}
 	dev_kfree_skb(skb);
 	L3AddTimer(&pc->timer, T310, CC_T310);
 	newl3state(pc, 3);
-	pc->st->l3.l3l4(pc, CC_PROCEEDING_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
 }
 
 static void
@@ -310,7 +332,7 @@
 	dev_kfree_skb(skb);
 	L3DelTimer(&pc->timer);	/* T304 */
 	newl3state(pc, 4);
-	pc->st->l3.l3l4(pc, CC_ALERTING_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
 }
 
 static void
@@ -330,7 +352,7 @@
 		}
 		if (tmpcharge > pc->para.chargeinfo) {
 			pc->para.chargeinfo = tmpcharge;
-			pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
+			pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
 		}
 		if (pc->st->l3.debug & L3_DEB_CHARGE) {
 			sprintf(tmp, "charging info %d", pc->para.chargeinfo);
@@ -356,10 +378,14 @@
 	struct sk_buff *skb = arg;
 
 	L3DelTimer(&pc->timer);	/* T310 */
+	if (!findie(skb->data, skb->len, WE6_date, 6)) {
+		l3_1tr6_error(pc, "missing connect date", skb);
+		return;
+	}
 	newl3state(pc, 10);
 	dev_kfree_skb(skb);
 	pc->para.chargeinfo = 0;
-	pc->st->l3.l3l4(pc, CC_SETUP_CNF, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
 }
 
 static void
@@ -380,13 +406,16 @@
 			pc->para.cause = 0;
 			pc->para.loc = 0;
 		}
-	} else
+	} else {
 		pc->para.cause = -1;
+		l3_1tr6_error(pc, "missing REL cause", skb);
+		return;
+	}
 	dev_kfree_skb(skb);
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
 	l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1);
-	pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	release_l3_process(pc);
 }
 
@@ -399,7 +428,7 @@
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
 	pc->para.cause = -1;
-	pc->st->l3.l3l4(pc, CC_RELEASE_CNF, NULL);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
 	release_l3_process(pc);
 }
 
@@ -421,7 +450,7 @@
 		}
 		if (tmpcharge > pc->para.chargeinfo) {
 			pc->para.chargeinfo = tmpcharge;
-			pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
+			pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
 		}
 		if (pc->st->l3.debug & L3_DEB_CHARGE) {
 			sprintf(tmp, "charging info %d", pc->para.chargeinfo);
@@ -448,9 +477,13 @@
 			l3_debug(pc->st, "cause not found");
 		pc->para.cause = -1;
 	}
+	if (!findie(skb->data, skb->len, WE6_date, 6)) {
+		l3_1tr6_error(pc, "missing connack date", skb);
+		return;
+	}
 	dev_kfree_skb(skb);
 	newl3state(pc, 12);
-	pc->st->l3.l3l4(pc, CC_DISCONNECT_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
 }
 
 
@@ -459,11 +492,15 @@
 {
 	struct sk_buff *skb = arg;
 
+	if (!findie(skb->data, skb->len, WE6_date, 6)) {
+		l3_1tr6_error(pc, "missing connack date", skb);
+		return;
+	}
 	dev_kfree_skb(skb);
 	newl3state(pc, 10);
 	pc->para.chargeinfo = 0;
 	L3DelTimer(&pc->timer);
-	pc->st->l3.l3l4(pc, CC_SETUP_COMPLETE_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
 }
 
 static void
@@ -502,7 +539,7 @@
 	if (!(skb = l3_alloc_skb(l)))
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 	L3DelTimer(&pc->timer);
 	L3AddTimer(&pc->timer, T313, CC_T313);
 }
@@ -545,20 +582,11 @@
 	if (!(skb = l3_alloc_skb(l)))
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 	L3AddTimer(&pc->timer, T305, CC_T305);
 }
 
 static void
-l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
-{
-	StopAllL3Timer(pc);
-	newl3state(pc, 19);
-	l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
-	L3AddTimer(&pc->timer, T308, CC_T308_1);
-}
-
-static void
 l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg)
 {
 	if (pc->N303 > 0) {
@@ -567,8 +595,8 @@
 		l3_1tr6_setup_req(pc, pr, arg);
 	} else {
 		L3DelTimer(&pc->timer);
-		pc->st->l3.l3l4(pc, CC_NOSETUP_RSP_ERR, NULL);
-		release_l3_process(pc);
+		pc->para.cause = 0;
+		l3_1tr6_disconnect_req(pc, 0, NULL);
 	}
 }
 
@@ -578,7 +606,7 @@
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 0xE6;
 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
@@ -613,7 +641,7 @@
 	if (!(skb = l3_alloc_skb(l)))
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 	L3AddTimer(&pc->timer, T308, CC_T308_1);
 }
 
@@ -623,7 +651,7 @@
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 0xE6;
 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
@@ -632,7 +660,7 @@
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 0xE6;
 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_CONNECT_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
 }
 
 static void
@@ -648,29 +676,29 @@
 l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->st->l3.l3l4(pc, CC_RELEASE_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
 	release_l3_process(pc);
 }
 /* *INDENT-OFF* */
 static struct stateentry downstl[] =
 {
 	{SBIT(0),
-	 CC_SETUP_REQ, l3_1tr6_setup_req},
+	 CC_SETUP | REQUEST, l3_1tr6_setup_req},
    	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) |
     	 SBIT(10),
-    	 CC_DISCONNECT_REQ, l3_1tr6_disconnect_req},
+    	 CC_DISCONNECT | REQUEST, l3_1tr6_disconnect_req},
 	{SBIT(12),
-	 CC_RELEASE_REQ, l3_1tr6_release_req},
+	 CC_RELEASE | REQUEST, l3_1tr6_release_req},
 	{ALL_STATES,
-	 CC_DLRL, l3_1tr6_reset},
+	 CC_DLRL | REQUEST, l3_1tr6_reset},
 	{SBIT(6),
-	 CC_IGNORE, l3_1tr6_reset},
+	 CC_IGNORE | REQUEST, l3_1tr6_reset},
 	{SBIT(6),
-	 CC_REJECT_REQ, l3_1tr6_disconnect_req},
+	 CC_REJECT | REQUEST, l3_1tr6_disconnect_req},
 	{SBIT(6),
-	 CC_ALERTING_REQ, l3_1tr6_alert_req},
+	 CC_ALERTING | REQUEST, l3_1tr6_alert_req},
 	{SBIT(6) | SBIT(7),
-	 CC_SETUP_RSP, l3_1tr6_setup_rsp},
+	 CC_SETUP | RESPONSE, l3_1tr6_setup_rsp},
 	{SBIT(1),
 	 CC_T303, l3_1tr6_t303},
 	{SBIT(2),
@@ -687,12 +715,14 @@
 	 CC_T308_2, l3_1tr6_t308_2},
 };
 
-static int downstl_len = sizeof(downstl) /
-sizeof(struct stateentry);
+#define DOWNSTL_LEN \
+	(sizeof(downstl) / sizeof(struct stateentry))
 
 static struct stateentry datastln1[] =
 {
 	{SBIT(0),
+	 MT_N1_INVALID, l3_1tr6_invalid},
+	{SBIT(0),
 	 MT_N1_SETUP, l3_1tr6_setup},
 	{SBIT(1),
 	 MT_N1_SETUP_ACK, l3_1tr6_setup_ack},
@@ -711,18 +741,20 @@
 	{SBIT(10),
 	 MT_N1_INFO, l3_1tr6_info},
 	{SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
-	 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19),
+	 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
 	 MT_N1_REL, l3_1tr6_rel},
 	{SBIT(19),
+	 MT_N1_REL, l3_1tr6_rel_ack},
+	{SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
+	 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
+	 MT_N1_REL_ACK, l3_1tr6_invalid},
+	{SBIT(19),
 	 MT_N1_REL_ACK, l3_1tr6_rel_ack}
 };
 /* *INDENT-ON* */
 
-
-
-
-static int datastln1_len = sizeof(datastln1) /
-sizeof(struct stateentry);
+#define DATASTLN1_LEN \
+	(sizeof(datastln1) / sizeof(struct stateentry))
 
 static void
 up1tr6(struct PStack *st, int pr, void *arg)
@@ -732,9 +764,21 @@
 	struct sk_buff *skb = arg;
 	char tmp[80];
 
+	switch (pr) {
+		case (DL_DATA | INDICATION):
+		case (DL_UNIT_DATA | INDICATION):
+			break;
+		case (DL_ESTABLISH | CONFIRM):
+		case (DL_ESTABLISH | INDICATION):
+		case (DL_RELEASE | INDICATION):
+		case (DL_RELEASE | CONFIRM):
+			l3_msg(st, pr, arg);
+			return;
+			break;
+	}
 	if (skb->len < 4) {
 		if (st->l3.debug & L3_DEB_PROTERR) {
-			sprintf(tmp, "up1tr6 len only %d", skb->len);
+			sprintf(tmp, "up1tr6 len only %ld", skb->len);
 			l3_debug(st, tmp);
 		}
 		dev_kfree_skb(skb);
@@ -742,8 +786,8 @@
 	}
 	if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) {
 		if (st->l3.debug & L3_DEB_PROTERR) {
-			sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %d",
-				(pr == DL_DATA) ? " " : "(broadcast) ",
+			sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %ld",
+				(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 				skb->data[0], skb->len);
 			l3_debug(st, tmp);
 		}
@@ -764,12 +808,33 @@
 		dev_kfree_skb(skb);
 		if (st->l3.debug & L3_DEB_STATE) {
 			sprintf(tmp, "up1tr6%s N0 mt %x unhandled",
-			     (pr == DL_DATA) ? " " : "(broadcast) ", mt);
+			     (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt);
 			l3_debug(st, tmp);
 		}
 	} else if (skb->data[0] == PROTO_DIS_N1) {
 		if (!(proc = getl3proc(st, cr))) {
-			if ((mt == MT_N1_SETUP) && (cr < 128)) {
+			if (mt == MT_N1_SETUP) { 
+				if (cr < 128) {
+					if (!(proc = new_l3_process(st, cr))) {
+						if (st->l3.debug & L3_DEB_PROTERR) {
+							sprintf(tmp, "up1tr6 no roc mem");
+							l3_debug(st, tmp);
+						}
+						dev_kfree_skb(skb);
+						return;
+					}
+				} else {
+					dev_kfree_skb(skb);
+					return;
+				}
+			} else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) ||
+				(mt == MT_N1_CANC_ACK) || (mt == MT_N1_CANC_REJ) ||
+				(mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) ||
+				(mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) ||
+				(mt == MT_N1_INFO)) {
+				dev_kfree_skb(skb);
+				return;
+			} else {
 				if (!(proc = new_l3_process(st, cr))) {
 					if (st->l3.debug & L3_DEB_PROTERR) {
 						sprintf(tmp, "up1tr6 no roc mem");
@@ -778,20 +843,18 @@
 					dev_kfree_skb(skb);
 					return;
 				}
-			} else {
-				dev_kfree_skb(skb);
-				return;
+				mt = MT_N1_INVALID;
 			}
 		}
-		for (i = 0; i < datastln1_len; i++)
+		for (i = 0; i < DATASTLN1_LEN; i++)
 			if ((mt == datastln1[i].primitive) &&
 			    ((1 << proc->state) & datastln1[i].state))
 				break;
-		if (i == datastln1_len) {
+		if (i == DATASTLN1_LEN) {
 			dev_kfree_skb(skb);
 			if (st->l3.debug & L3_DEB_STATE) {
 				sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
-				  (pr == DL_DATA) ? " " : "(broadcast) ",
+				  (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 					proc->state, mt);
 				l3_debug(st, tmp);
 			}
@@ -799,7 +862,7 @@
 		} else {
 			if (st->l3.debug & L3_DEB_STATE) {
 				sprintf(tmp, "up1tr6%sstate %d mt %x",
-				  (pr == DL_DATA) ? " " : "(broadcast) ",
+				  (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 					proc->state, mt);
 				l3_debug(st, tmp);
 			}
@@ -816,7 +879,10 @@
 	struct Channel *chan;
 	char tmp[80];
 
-	if (CC_SETUP_REQ == pr) {
+	if (((DL_ESTABLISH | REQUEST)== pr) || ((DL_RELEASE | REQUEST)== pr)) {
+		l3_msg(st, pr, NULL);
+		return;
+	} else if ((CC_SETUP | REQUEST) == pr) {
 		chan = arg;
 		cr = newcallref();
 		cr |= 0x80;
@@ -832,11 +898,11 @@
 		proc = arg;
 	}
 
-	for (i = 0; i < downstl_len; i++)
+	for (i = 0; i < DOWNSTL_LEN; i++)
 		if ((pr == downstl[i].primitive) &&
 		    ((1 << proc->state) & downstl[i].state))
 			break;
-	if (i == downstl_len) {
+	if (i == DOWNSTL_LEN) {
 		if (st->l3.debug & L3_DEB_STATE) {
 			sprintf(tmp, "down1tr6 state %d prim %d unhandled",
 				proc->state, pr);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)