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