1/*
2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 *---------------------------------------------------------------------------
26 *
27 *	i4b_q931.c - Q931 received messages handling
28 *	--------------------------------------------
29 *
30 *	$Id: i4b_q931.c,v 1.21 2006/11/16 01:33:49 christos Exp $
31 *
32 * $FreeBSD$
33 *
34 *      last edit-date: [Fri Jan  5 11:33:47 2001]
35 *
36 *---------------------------------------------------------------------------*/
37
38#include <sys/cdefs.h>
39__KERNEL_RCSID(0, "$NetBSD: i4b_q931.c,v 1.20 2006/10/16 12:23:00 pooka Exp $");
40
41#ifdef __FreeBSD__
42#include "i4bq931.h"
43#else
44#define	NI4BQ931	1
45#endif
46
47#if NI4BQ931 > 0
48
49#include <sys/param.h>
50#include <sys/kernel.h>
51#include <sys/systm.h>
52#include <sys/mbuf.h>
53#include <sys/socket.h>
54#include <net/if.h>
55
56#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
57#include <sys/callout.h>
58#endif
59
60#ifdef __FreeBSD__
61#include <machine/i4b_debug.h>
62#include <machine/i4b_ioctl.h>
63#include <machine/i4b_cause.h>
64#else
65#include <netisdn/i4b_debug.h>
66#include <netisdn/i4b_ioctl.h>
67#include <netisdn/i4b_cause.h>
68#endif
69
70#include <netisdn/i4b_isdnq931.h>
71#include <netisdn/i4b_l2.h>
72#include <netisdn/i4b_l3l4.h>
73#include <netisdn/i4b_mbuf.h>
74#include <netisdn/i4b_global.h>
75
76#include <netisdn/i4b_l3.h>
77#include <netisdn/i4b_l3fsm.h>
78#include <netisdn/i4b_q931.h>
79
80#include <netisdn/i4b_l4.h>
81
82unsigned int i4b_l3_debug = L3_DEBUG_DEFAULT;
83
84/* protocol independent causes -> Q.931 causes */
85
86unsigned char cause_tab_q931[CAUSE_I4B_MAX] = {
87	CAUSE_Q850_NCCLR, 	/* CAUSE_I4B_NORMAL -> normal call clearing */
88	CAUSE_Q850_USRBSY,	/* CAUSE_I4B_BUSY -> user busy */
89	CAUSE_Q850_NOCAVAIL,	/* CAUSE_I4B_NOCHAN -> no circuit/channel available*/
90	CAUSE_Q850_INCDEST,	/* CAUSE_I4B_INCOMP -> incompatible destination */
91	CAUSE_Q850_CALLREJ,	/* CAUSE_I4B_REJECT -> call rejected */
92	CAUSE_Q850_DSTOOORDR,	/* CAUSE_I4B_OOO -> destination out of order */
93	CAUSE_Q850_TMPFAIL,	/* CAUSE_I4B_TMPFAIL -> temporary failure */
94	CAUSE_Q850_USRBSY,	/* CAUSE_I4B_L1ERROR -> L1 error / persistent deact XXX */
95	CAUSE_Q850_USRBSY,	/* CAUSE_I4B_LLDIAL -> no dialout on leased line XXX */
96};
97
98/*---------------------------------------------------------------------------*
99 *	setup cr ref flag according to direction
100 *---------------------------------------------------------------------------*/
101unsigned char
102setup_cr(call_desc_t *cd, unsigned char cr)
103{
104	if(cd->crflag == CRF_ORIG)
105		return(cr & 0x7f);	/* clear cr ref flag */
106	else if(cd->crflag == CRF_DEST)
107		return(cr | 0x80);	/* set cr ref flag */
108	else
109		panic("setup_cr: invalid crflag!");
110}
111
112/*---------------------------------------------------------------------------*
113 *	decode and process a Q.931 message
114 *---------------------------------------------------------------------------*/
115void
116i4b_decode_q931(int isdnif, int msg_len, u_char *msg_ptr)
117{
118	call_desc_t *cd = NULL;
119	int codeset = CODESET_0;
120	int old_codeset = CODESET_0;
121	int shift_flag = UNSHIFTED;
122	int crlen = 0;
123	int crval = 0;
124	int crflag = 0;
125	int i;
126	int offset;
127	int s;
128
129	/* check protocol discriminator */
130
131	if(*msg_ptr != PD_Q931)
132	{
133		static int protoflag = -1;	/* print only once .. */
134
135		if(*msg_ptr != protoflag)
136		{
137			NDBGL3(L3_P_MSG, "unknown protocol discriminator 0x%x!", *msg_ptr);
138			protoflag = *msg_ptr;
139		}
140		return;
141	}
142
143	msg_ptr++;
144	msg_len--;
145
146	s = splnet();		/* this has to be protected ! */
147
148	/* extract call reference */
149
150	crlen = *msg_ptr & CRLENGTH_MASK;
151	msg_ptr++;
152	msg_len--;
153
154	if (crlen != 0)
155	{
156		crval += *msg_ptr & 0x7f;
157		crflag = (*msg_ptr >> 7) & 0x01;
158		msg_ptr++;
159		msg_len--;
160
161		for(i=1; i < crlen; i++)
162		{
163			crval += *msg_ptr;
164			msg_ptr++;
165			msg_len--;
166		}
167	}
168	else
169	{
170		crval = 0;
171		crflag = 0;
172	}
173
174	NDBGL3(L3_P_MSG, "Call Ref, len %d, val %d, flag %d", crlen, crval, crflag);
175
176	/* find or allocate calldescriptor */
177
178	if((cd = cd_by_isdnifcr(isdnif, crval,
179			crflag == CRF_DEST ? CRF_ORIG : CRF_DEST)) == NULL)
180	{
181		if(*msg_ptr == SETUP)
182		{
183			struct isdn_l3_driver *drv;
184
185			drv = isdn_find_l3_by_isdnif(isdnif);
186			/* get and init new calldescriptor */
187
188			cd = reserve_cd();	/* cdid filled in */
189			cd->isdnif = isdnif;
190			cd->l3drv = drv;
191			cd->cr = crval;
192			cd->crflag = CRF_DEST;	/* we are the dest side */
193			cd->l4_driver = NULL;		/* reset link tab ptrs */
194			cd->l4_driver_softc = NULL;
195		}
196		else
197		{
198/*XXX*/			if(crval != 0)	/* ignore global call references */
199			{
200				NDBGL3(L3_P_ERR, "cannot find calldescriptor for cr = 0x%x, crflag = 0x%x, msg = 0x%x, frame = ", crval, crflag, *msg_ptr);
201				i4b_print_frame(msg_len, msg_ptr);
202			}
203			splx(s);
204			return;
205		}
206	}
207
208	splx(s);
209
210	/* decode and handle message type */
211
212	i4b_decode_q931_message(cd, *msg_ptr);
213	msg_ptr++;
214	msg_len--;
215
216	/* process information elements */
217
218	while(msg_len > 0)
219	{
220		/* check for shift codeset IE */
221
222		if((*msg_ptr & 0x80) && ((*msg_ptr & 0xf0) == SOIE_SHIFT))
223		{
224			if(!(*msg_ptr & SHIFT_LOCK))
225				shift_flag = SHIFTED;
226
227			old_codeset = codeset;
228			codeset = *msg_ptr & CODESET_MASK;
229
230			if((shift_flag != SHIFTED) &&
231			   (codeset <= old_codeset))
232			{
233				NDBGL3(L3_P_ERR, "Q.931 lockingshift proc violation, shift %d -> %d", old_codeset, codeset);
234				codeset = old_codeset;
235			}
236			msg_len--;
237			msg_ptr++;
238		}
239
240		/* process one IE for selected codeset */
241
242		switch(codeset)
243		{
244			case CODESET_0:
245				offset = i4b_decode_q931_cs0_ie(cd, msg_len, msg_ptr);
246				msg_len -= offset;
247				msg_ptr += offset;
248				break;
249
250			default:
251				NDBGL3(L3_P_ERR, "unknown codeset %d, ", codeset);
252				i4b_print_frame(msg_len, msg_ptr);
253				msg_len = 0;
254				break;
255		}
256
257		/* check for non-locking shifts */
258
259		if(shift_flag == SHIFTED)
260		{
261			shift_flag = UNSHIFTED;
262			codeset = old_codeset;
263		}
264	}
265	next_l3state(cd, cd->event);
266}
267
268/*---------------------------------------------------------------------------*
269 *	decode and process one Q.931 codeset 0 information element
270 *---------------------------------------------------------------------------*/
271int
272i4b_decode_q931_cs0_ie(call_desc_t *cd, int msg_len, u_char *msg_ptr)
273{
274	int i, j;
275	char *p;
276
277	switch(*msg_ptr)
278	{
279
280/*********/
281/* Q.931 */
282/*********/
283		/* single byte IE's */
284
285		case IEI_SENDCOMPL:
286			NDBGL3(L3_P_MSG, "IEI_SENDCOMPL");
287			return(1);
288			break;
289
290		/* multi byte IE's */
291
292		case IEI_SEGMMSG:	/* segmented message */
293			NDBGL3(L3_P_MSG, "IEI_SEGMENTED_MESSAGE");
294			break;
295
296		case IEI_BEARERCAP:	/* bearer capability */
297			switch(msg_ptr[2])
298			{
299				case 0x80:	/* speech */
300				case 0x89:	/* restricted digital info */
301				case 0x90:	/* 3.1 kHz audio */
302/* XXX */				cd->bprot = BPROT_NONE;
303					NDBGL3(L3_P_MSG, "IEI_BEARERCAP - Telephony");
304					break;
305
306				case 0x88:	/* unrestricted digital info */
307/* XXX */				cd->bprot = BPROT_RHDLC;
308					NDBGL3(L3_P_MSG, "IEI_BEARERCAP - Raw HDLC");
309					break;
310
311				default:
312/* XXX */				cd->bprot = BPROT_NONE;
313					NDBGL3(L3_P_ERR, "IEI_BEARERCAP - Unsupported B-Protocol 0x%x", msg_ptr[2]);
314					break;
315			}
316			break;
317
318		case IEI_CAUSE:		/* cause */
319			if(msg_ptr[2] & 0x80)
320			{
321				cd->cause_in = msg_ptr[3] & 0x7f;
322				NDBGL3(L3_P_MSG, "IEI_CAUSE = %d", msg_ptr[3] & 0x7f);
323			}
324			else
325			{
326				cd->cause_in = msg_ptr[4] & 0x7f;
327				NDBGL3(L3_P_MSG, "IEI_CAUSE = %d", msg_ptr[4] & 0x7f);
328			}
329			break;
330
331		case IEI_CALLID:	/* call identity */
332			NDBGL3(L3_P_MSG, "IEI_CALL_IDENTITY");
333			break;
334
335		case IEI_CALLSTATE:	/* call state		*/
336			cd->call_state = msg_ptr[2] & 0x3f;
337			NDBGL3(L3_P_MSG, "IEI_CALLSTATE = %d", cd->call_state);
338			break;
339
340		case IEI_CHANNELID:	/* channel id */
341			if((msg_ptr[2] & 0xf4) != 0x80)
342			{
343				cd->channelid = CHAN_NO;
344				NDBGL3(L3_P_ERR, "IEI_CHANNELID, unsupported value 0x%x", msg_ptr[2]);
345			}
346			else
347			{
348				int old_chanid = cd->channelid;
349				switch(msg_ptr[2] & 0x03)
350				{
351					case IE_CHAN_ID_NO:
352						cd->channelid = CHAN_NO;
353						break;
354					case IE_CHAN_ID_B1:
355						cd->channelid = CHAN_B1;
356						break;
357					case IE_CHAN_ID_B2:
358						cd->channelid = CHAN_B2;
359						break;
360					case IE_CHAN_ID_ANY:
361						cd->channelid = CHAN_ANY;
362						break;
363				}
364				cd->channelexcl = (msg_ptr[2] & 0x08) >> 3;
365
366				NDBGL3(L3_P_MSG, "IEI_CHANNELID - channel %d, exclusive = %d", cd->channelid, cd->channelexcl);
367
368				/* if this is the first time we know the real channel,
369				 * reserve it */
370				if (old_chanid != cd->channelid)
371				{
372					if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2))
373					{
374						struct isdn_l3_driver *d = cd->l3drv;
375
376						if (i4b_l2_channel_get_state(d, cd->channelid) == BCH_ST_FREE) {
377							if (d != NULL) {
378								d->bch_state[cd->channelid] = BCH_ST_RSVD;
379								update_controller_leds(d);
380							}
381							i4b_l2_channel_set_state(d, cd->channelid, BCH_ST_RSVD);
382						} else
383							NDBGL3(L3_P_ERR, "IE ChannelID, Channel NOT free!!");
384					}
385					else if(cd->channelid == CHAN_NO)
386					{
387						NDBGL3(L3_P_MSG, "IE ChannelID, SETUP with channel = No channel (CW)");
388					}
389					else /* cd->channelid == CHAN_ANY */
390					{
391						NDBGL3(L3_P_ERR, "ERROR: IE ChannelID, SETUP with channel = Any channel!");
392					}
393				}
394			}
395			break;
396
397		case IEI_PROGRESSI:	/* progress indicator	*/
398			NDBGL3(L3_P_MSG, "IEI_PROGRESSINDICATOR");
399			break;
400
401		case IEI_NETSPCFAC:	/* network specific fac */
402			NDBGL3(L3_P_MSG, "IEI_NETSPCFAC");
403			break;
404
405		case IEI_NOTIFIND:	/* notification indicator */
406			NDBGL3(L3_P_MSG, "IEI_NOTIFICATION_INDICATOR");
407			break;
408
409		case IEI_DISPLAY:	/* display		*/
410			memcpy(cd->display, &msg_ptr[2], min(DISPLAY_MAX, msg_ptr[1]));
411			cd->display[min(DISPLAY_MAX, msg_ptr[1])] = '\0';
412			NDBGL3(L3_P_MSG, "IEI_DISPLAY = %s", cd->display);
413  			break;
414
415		case IEI_DATETIME:	/* date/time		*/
416			i = 2;
417			j = msg_ptr[1];
418			p = &(cd->datetime[0]);
419			*p = '\0';
420
421			for(j = msg_ptr[1]; j > 0; j--, i++)
422				sprintf(p+strlen(p), "%02d", msg_ptr[i]);
423
424			NDBGL3(L3_P_MSG, "IEI_DATETIME = %s", cd->datetime);
425			break;
426
427		case IEI_KEYPAD:	/* keypad facility */
428			NDBGL3(L3_P_MSG, "IEI_KEYPAD_FACILITY");
429			break;
430
431		case IEI_SIGNAL:	/* signal type */
432			NDBGL3(L3_P_MSG, "IEI_SIGNAL = %d", msg_ptr[2]);
433			break;
434
435		case IEI_INFRATE:	/* information rate */
436			NDBGL3(L3_P_MSG, "IEI_INFORMATION_RATE");
437			break;
438
439		case IEI_ETETDEL:	/* end to end transit delay */
440			NDBGL3(L3_P_MSG, "IEI_END_TO_END_TRANSIT_DELAY");
441			break;
442
443		case IEI_CUG:		/* closed user group */
444			NDBGL3(L3_P_MSG, "IEI_CLOSED_USER_GROUP");
445			break;
446
447		case IEI_CALLINGPN:	/* calling party no */
448			cd->type_plan = msg_ptr[2] & 0x7f;
449			if(msg_ptr[2] & 0x80) /* no presentation/screening indicator ? */
450			{
451				memcpy(cd->src_telno, &msg_ptr[3], min(TELNO_MAX, msg_ptr[1]-1));
452				cd->src_telno[min(TELNO_MAX, msg_ptr[1] - 1)] = '\0';
453				cd->scr_ind = SCR_NONE;
454				cd->prs_ind = PRS_NONE;
455			}
456			else
457			{
458				memcpy(cd->src_telno, &msg_ptr[4], min(TELNO_MAX, msg_ptr[1]-2));
459				cd->src_telno[min(TELNO_MAX, msg_ptr[1] - 2)] = '\0';
460				cd->scr_ind = (msg_ptr[3] & 0x03) + SCR_USR_NOSC;
461				cd->prs_ind = ((msg_ptr[3] >> 5) & 0x03) + PRS_ALLOWED;
462			}
463			NDBGL3(L3_P_MSG, "IEI_CALLINGPN = %s", cd->src_telno);
464			break;
465
466		case IEI_CALLINGPS:	/* calling party subaddress */
467			NDBGL3(L3_P_MSG, "IEI_CALLINGPS");
468			memcpy(cd->src_subaddr, &msg_ptr[1], min(SUBADDR_MAX, msg_ptr[1]-1));
469			break;
470
471		case IEI_CALLEDPN:	/* called party number */
472			memcpy(cd->dst_telno, &msg_ptr[3], min(TELNO_MAX, msg_ptr[1]-1));
473			cd->dst_telno[min(TELNO_MAX, msg_ptr [1] - 1)] = '\0';
474			NDBGL3(L3_P_MSG, "IEI_CALLED = %s", cd->dst_telno);
475			break;
476
477		case IEI_CALLEDPS:	/* called party subaddress */
478			NDBGL3(L3_P_MSG, "IEI_CALLEDPS");
479			memcpy(cd->dest_subaddr, &msg_ptr[1], min(SUBADDR_MAX, msg_ptr[1]-1));
480			break;
481
482		case IEI_REDIRNO:	/* redirecting number */
483			NDBGL3(L3_P_MSG, "IEI_REDIRECTING_NUMBER");
484			break;
485
486		case IEI_TRNSEL:	/* transit network selection */
487			NDBGL3(L3_P_MSG, "IEI_TRANSIT_NETWORK_SELECTION");
488			break;
489
490		case IEI_RESTARTI:	/* restart indicator */
491			NDBGL3(L3_P_MSG, "IEI_RESTART_INDICATOR");
492			break;
493
494		case IEI_LLCOMPAT:	/* low layer compat */
495			NDBGL3(L3_P_MSG, "IEI_LLCOMPAT");
496			break;
497
498		case IEI_HLCOMPAT:	/* high layer compat	*/
499			NDBGL3(L3_P_MSG, "IEI_HLCOMPAT");
500			break;
501
502		case IEI_USERUSER:	/* user-user */
503			NDBGL3(L3_P_MSG, "IEI_USER_USER");
504			break;
505
506		case IEI_ESCAPE:	/* escape for extension */
507			NDBGL3(L3_P_MSG, "IEI_ESCAPE");
508			break;
509
510/*********/
511/* Q.932 */
512/*********/
513		case IEI_FACILITY:	/* facility		*/
514			NDBGL3(L3_P_MSG, "IEI_FACILITY");
515			if(i4b_aoc(msg_ptr, cd) > -1)
516				i4b_l4_charging_ind(cd);
517			break;
518
519/*********/
520/* Q.95x */
521/*********/
522		case IEI_CONCTDNO:	/* connected number	*/
523			NDBGL3(L3_P_MSG, "IEI_CONCTDNO");
524			break;
525
526
527		default:
528			NDBGL3(L3_P_ERR, "Unknown IE %d - ", *msg_ptr);
529			i4b_print_frame(msg_ptr[1]+2, msg_ptr);
530			break;
531	}
532	return(msg_ptr[1] + 2);
533}
534
535/*---------------------------------------------------------------------------*
536 *	decode and process one Q.931 codeset 0 information element
537 *---------------------------------------------------------------------------*/
538void
539i4b_decode_q931_message(call_desc_t *cd, u_char message_type)
540{
541	const char *m = NULL;
542
543	cd->event = EV_ILL;
544
545	switch(message_type)
546	{
547		/* call establishment */
548
549		case ALERT:
550			cd->event = EV_ALERT;
551			m = "ALERT";
552			break;
553
554		case CALL_PROCEEDING:
555			cd->event = EV_CALLPRC;
556			m = "CALL_PROCEEDING";
557			break;
558
559		case PROGRESS:
560			cd->event = EV_PROGIND;
561			m = "PROGRESS";
562			break;
563
564		case SETUP:
565			m = "SETUP";
566			cd->bprot = BPROT_NONE;
567			cd->cause_in = 0;
568			cd->cause_out = 0;
569			cd->dst_telno[0] = '\0';
570			cd->src_telno[0] = '\0';
571			cd->channelid = CHAN_NO;
572			cd->channelexcl = 0;
573			cd->display[0] = '\0';
574			cd->datetime[0] = '\0';
575			cd->event = EV_SETUP;
576			break;
577
578		case CONNECT:
579			m = "CONNECT";
580			cd->datetime[0] = '\0';
581			cd->event = EV_CONNECT;
582			break;
583
584		case SETUP_ACKNOWLEDGE:
585			m = "SETUP_ACKNOWLEDGE";
586			cd->event = EV_SETUPAK;
587			break;
588
589		case CONNECT_ACKNOWLEDGE:
590			m = "CONNECT_ACKNOWLEDGE";
591			cd->event = EV_CONACK;
592			break;
593
594		/* call information */
595
596		case USER_INFORMATION:
597			m = "USER_INFORMATION";
598			break;
599
600		case SUSPEND_REJECT:
601			m = "SUSPEND_REJECT";
602			break;
603
604		case RESUME_REJECT:
605			m = "RESUME_REJECT";
606			break;
607
608		case HOLD:
609			m = "HOLD";
610			break;
611
612		case SUSPEND:
613			m = "SUSPEND";
614			break;
615
616		case RESUME:
617			m = "RESUME";
618			break;
619
620		case HOLD_ACKNOWLEDGE:
621			m = "HOLD_ACKNOWLEDGE";
622			break;
623
624		case SUSPEND_ACKNOWLEDGE:
625			m = "SUSPEND_ACKNOWLEDGE";
626			break;
627
628		case RESUME_ACKNOWLEDGE:
629			m = "RESUME_ACKNOWLEDGE";
630			break;
631
632		case HOLD_REJECT:
633			m = "HOLD_REJECT";
634			break;
635
636		case RETRIEVE:
637			m = "RETRIEVE";
638			break;
639
640		case RETRIEVE_ACKNOWLEDGE:
641			m = "RETRIEVE_ACKNOWLEDGE";
642			break;
643
644		case RETRIEVE_REJECT:
645			m = "RETRIEVE_REJECT";
646			break;
647
648		/* call clearing */
649
650		case DISCONNECT:
651			m = "DISCONNECT";
652			cd->event = EV_DISCONN;
653			break;
654
655		case RESTART:
656			m = "RESTART";
657			break;
658
659		case RELEASE:
660			m = "RELEASE";
661			cd->event = EV_RELEASE;
662			break;
663
664		case RESTART_ACKNOWLEDGE:
665			m = "RESTART_ACKNOWLEDGE";
666			break;
667
668		case RELEASE_COMPLETE:
669			m = "RELEASE_COMPLETE";
670			cd->event = EV_RELCOMP;
671			break;
672
673		/* misc messages */
674
675		case SEGMENT:
676			m = "SEGMENT";
677			break;
678
679		case FACILITY:
680			m = "FACILITY";
681			cd->event = EV_FACILITY;
682			break;
683
684		case REGISTER:
685			m = "REGISTER";
686			break;
687
688		case NOTIFY:
689			m = "NOTIFY";
690			break;
691
692		case STATUS_ENQUIRY:
693			m = "STATUS_ENQUIRY";
694			cd->event = EV_STATENQ;
695			break;
696
697		case CONGESTION_CONTROL:
698			m = "CONGESTION_CONTROL";
699			break;
700
701		case INFORMATION:
702			m = "INFORMATION";
703			cd->event = EV_INFO;
704			break;
705
706		case STATUS:
707			m = "STATUS";
708			cd->event = EV_STATUS;
709			break;
710
711		default:
712			NDBGL3(L3_P_ERR, "isdnif %d, cr = 0x%02x, msg = 0x%02x", cd->isdnif, cd->cr, message_type);
713			break;
714	}
715	if(m)
716	{
717		NDBGL3(L3_PRIM, "%s: isdnif %d, cr = 0x%02x\n", m, cd->isdnif, cd->cr);
718	}
719}
720
721#endif /* NI4BQ931 > 0 */
722