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