2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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
25 *---------------------------------------------------------------------------
27 * i4b_q931.c - Q931 received messages handling
28 * --------------------------------------------
30 * $Id: i4b_q931.c,v 1.21 2006/11/16 01:33:49 christos Exp $
34 * last edit-date: [Fri Jan 5 11:33:47 2001]
36 *---------------------------------------------------------------------------*/
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: i4b_q931.c,v 1.20 2006/10/16 12:23:00 pooka Exp $");
49 #include <sys/param.h>
50 #include <sys/kernel.h>
51 #include <sys/systm.h>
53 #include <sys/socket.h>
56 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
57 #include <sys/callout.h>
61 #include <machine/i4b_debug.h>
62 #include <machine/i4b_ioctl.h>
63 #include <machine/i4b_cause.h>
65 #include <netisdn/i4b_debug.h>
66 #include <netisdn/i4b_ioctl.h>
67 #include <netisdn/i4b_cause.h>
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>
76 #include <netisdn/i4b_l3.h>
77 #include <netisdn/i4b_l3fsm.h>
78 #include <netisdn/i4b_q931.h>
80 #include <netisdn/i4b_l4.h>
82 unsigned int i4b_l3_debug
= L3_DEBUG_DEFAULT
;
84 /* protocol independent causes -> Q.931 causes */
86 unsigned 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 */
98 /*---------------------------------------------------------------------------*
99 * setup cr ref flag according to direction
100 *---------------------------------------------------------------------------*/
102 setup_cr(call_desc_t
*cd
, unsigned char cr
)
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 */
109 panic("setup_cr: invalid crflag!");
112 /*---------------------------------------------------------------------------*
113 * decode and process a Q.931 message
114 *---------------------------------------------------------------------------*/
116 i4b_decode_q931(int isdnif
, int msg_len
, u_char
*msg_ptr
)
118 call_desc_t
*cd
= NULL
;
119 int codeset
= CODESET_0
;
120 int old_codeset
= CODESET_0
;
121 int shift_flag
= UNSHIFTED
;
129 /* check protocol discriminator */
131 if(*msg_ptr
!= PD_Q931
)
133 static int protoflag
= -1; /* print only once .. */
135 if(*msg_ptr
!= protoflag
)
137 NDBGL3(L3_P_MSG
, "unknown protocol discriminator 0x%x!", *msg_ptr
);
138 protoflag
= *msg_ptr
;
146 s
= splnet(); /* this has to be protected ! */
148 /* extract call reference */
150 crlen
= *msg_ptr
& CRLENGTH_MASK
;
156 crval
+= *msg_ptr
& 0x7f;
157 crflag
= (*msg_ptr
>> 7) & 0x01;
161 for(i
=1; i
< crlen
; i
++)
174 NDBGL3(L3_P_MSG
, "Call Ref, len %d, val %d, flag %d", crlen
, crval
, crflag
);
176 /* find or allocate calldescriptor */
178 if((cd
= cd_by_isdnifcr(isdnif
, crval
,
179 crflag
== CRF_DEST
? CRF_ORIG
: CRF_DEST
)) == NULL
)
181 if(*msg_ptr
== SETUP
)
183 struct isdn_l3_driver
*drv
;
185 drv
= isdn_find_l3_by_isdnif(isdnif
);
186 /* get and init new calldescriptor */
188 cd
= reserve_cd(); /* cdid filled in */
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
;
198 /*XXX*/ if(crval
!= 0) /* ignore global call references */
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
);
210 /* decode and handle message type */
212 i4b_decode_q931_message(cd
, *msg_ptr
);
216 /* process information elements */
220 /* check for shift codeset IE */
222 if((*msg_ptr
& 0x80) && ((*msg_ptr
& 0xf0) == SOIE_SHIFT
))
224 if(!(*msg_ptr
& SHIFT_LOCK
))
225 shift_flag
= SHIFTED
;
227 old_codeset
= codeset
;
228 codeset
= *msg_ptr
& CODESET_MASK
;
230 if((shift_flag
!= SHIFTED
) &&
231 (codeset
<= old_codeset
))
233 NDBGL3(L3_P_ERR
, "Q.931 lockingshift proc violation, shift %d -> %d", old_codeset
, codeset
);
234 codeset
= old_codeset
;
240 /* process one IE for selected codeset */
245 offset
= i4b_decode_q931_cs0_ie(cd
, msg_len
, msg_ptr
);
251 NDBGL3(L3_P_ERR
, "unknown codeset %d, ", codeset
);
252 i4b_print_frame(msg_len
, msg_ptr
);
257 /* check for non-locking shifts */
259 if(shift_flag
== SHIFTED
)
261 shift_flag
= UNSHIFTED
;
262 codeset
= old_codeset
;
265 next_l3state(cd
, cd
->event
);
268 /*---------------------------------------------------------------------------*
269 * decode and process one Q.931 codeset 0 information element
270 *---------------------------------------------------------------------------*/
272 i4b_decode_q931_cs0_ie(call_desc_t
*cd
, int msg_len
, u_char
*msg_ptr
)
283 /* single byte IE's */
286 NDBGL3(L3_P_MSG
, "IEI_SENDCOMPL");
290 /* multi byte IE's */
292 case IEI_SEGMMSG
: /* segmented message */
293 NDBGL3(L3_P_MSG
, "IEI_SEGMENTED_MESSAGE");
296 case IEI_BEARERCAP
: /* bearer capability */
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");
306 case 0x88: /* unrestricted digital info */
307 /* XXX */ cd
->bprot
= BPROT_RHDLC
;
308 NDBGL3(L3_P_MSG
, "IEI_BEARERCAP - Raw HDLC");
312 /* XXX */ cd
->bprot
= BPROT_NONE
;
313 NDBGL3(L3_P_ERR
, "IEI_BEARERCAP - Unsupported B-Protocol 0x%x", msg_ptr
[2]);
318 case IEI_CAUSE
: /* cause */
319 if(msg_ptr
[2] & 0x80)
321 cd
->cause_in
= msg_ptr
[3] & 0x7f;
322 NDBGL3(L3_P_MSG
, "IEI_CAUSE = %d", msg_ptr
[3] & 0x7f);
326 cd
->cause_in
= msg_ptr
[4] & 0x7f;
327 NDBGL3(L3_P_MSG
, "IEI_CAUSE = %d", msg_ptr
[4] & 0x7f);
331 case IEI_CALLID
: /* call identity */
332 NDBGL3(L3_P_MSG
, "IEI_CALL_IDENTITY");
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
);
340 case IEI_CHANNELID
: /* channel id */
341 if((msg_ptr
[2] & 0xf4) != 0x80)
343 cd
->channelid
= CHAN_NO
;
344 NDBGL3(L3_P_ERR
, "IEI_CHANNELID, unsupported value 0x%x", msg_ptr
[2]);
348 int old_chanid
= cd
->channelid
;
349 switch(msg_ptr
[2] & 0x03)
352 cd
->channelid
= CHAN_NO
;
355 cd
->channelid
= CHAN_B1
;
358 cd
->channelid
= CHAN_B2
;
361 cd
->channelid
= CHAN_ANY
;
364 cd
->channelexcl
= (msg_ptr
[2] & 0x08) >> 3;
366 NDBGL3(L3_P_MSG
, "IEI_CHANNELID - channel %d, exclusive = %d", cd
->channelid
, cd
->channelexcl
);
368 /* if this is the first time we know the real channel,
370 if (old_chanid
!= cd
->channelid
)
372 if((cd
->channelid
== CHAN_B1
) || (cd
->channelid
== CHAN_B2
))
374 struct isdn_l3_driver
*d
= cd
->l3drv
;
376 if (i4b_l2_channel_get_state(d
, cd
->channelid
) == BCH_ST_FREE
) {
378 d
->bch_state
[cd
->channelid
] = BCH_ST_RSVD
;
379 update_controller_leds(d
);
381 i4b_l2_channel_set_state(d
, cd
->channelid
, BCH_ST_RSVD
);
383 NDBGL3(L3_P_ERR
, "IE ChannelID, Channel NOT free!!");
385 else if(cd
->channelid
== CHAN_NO
)
387 NDBGL3(L3_P_MSG
, "IE ChannelID, SETUP with channel = No channel (CW)");
389 else /* cd->channelid == CHAN_ANY */
391 NDBGL3(L3_P_ERR
, "ERROR: IE ChannelID, SETUP with channel = Any channel!");
397 case IEI_PROGRESSI
: /* progress indicator */
398 NDBGL3(L3_P_MSG
, "IEI_PROGRESSINDICATOR");
401 case IEI_NETSPCFAC
: /* network specific fac */
402 NDBGL3(L3_P_MSG
, "IEI_NETSPCFAC");
405 case IEI_NOTIFIND
: /* notification indicator */
406 NDBGL3(L3_P_MSG
, "IEI_NOTIFICATION_INDICATOR");
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
);
415 case IEI_DATETIME
: /* date/time */
418 p
= &(cd
->datetime
[0]);
421 for(j
= msg_ptr
[1]; j
> 0; j
--, i
++)
422 sprintf(p
+strlen(p
), "%02d", msg_ptr
[i
]);
424 NDBGL3(L3_P_MSG
, "IEI_DATETIME = %s", cd
->datetime
);
427 case IEI_KEYPAD
: /* keypad facility */
428 NDBGL3(L3_P_MSG
, "IEI_KEYPAD_FACILITY");
431 case IEI_SIGNAL
: /* signal type */
432 NDBGL3(L3_P_MSG
, "IEI_SIGNAL = %d", msg_ptr
[2]);
435 case IEI_INFRATE
: /* information rate */
436 NDBGL3(L3_P_MSG
, "IEI_INFORMATION_RATE");
439 case IEI_ETETDEL
: /* end to end transit delay */
440 NDBGL3(L3_P_MSG
, "IEI_END_TO_END_TRANSIT_DELAY");
443 case IEI_CUG
: /* closed user group */
444 NDBGL3(L3_P_MSG
, "IEI_CLOSED_USER_GROUP");
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 ? */
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
;
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
;
463 NDBGL3(L3_P_MSG
, "IEI_CALLINGPN = %s", cd
->src_telno
);
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));
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
);
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));
482 case IEI_REDIRNO
: /* redirecting number */
483 NDBGL3(L3_P_MSG
, "IEI_REDIRECTING_NUMBER");
486 case IEI_TRNSEL
: /* transit network selection */
487 NDBGL3(L3_P_MSG
, "IEI_TRANSIT_NETWORK_SELECTION");
490 case IEI_RESTARTI
: /* restart indicator */
491 NDBGL3(L3_P_MSG
, "IEI_RESTART_INDICATOR");
494 case IEI_LLCOMPAT
: /* low layer compat */
495 NDBGL3(L3_P_MSG
, "IEI_LLCOMPAT");
498 case IEI_HLCOMPAT
: /* high layer compat */
499 NDBGL3(L3_P_MSG
, "IEI_HLCOMPAT");
502 case IEI_USERUSER
: /* user-user */
503 NDBGL3(L3_P_MSG
, "IEI_USER_USER");
506 case IEI_ESCAPE
: /* escape for extension */
507 NDBGL3(L3_P_MSG
, "IEI_ESCAPE");
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
);
522 case IEI_CONCTDNO
: /* connected number */
523 NDBGL3(L3_P_MSG
, "IEI_CONCTDNO");
528 NDBGL3(L3_P_ERR
, "Unknown IE %d - ", *msg_ptr
);
529 i4b_print_frame(msg_ptr
[1]+2, msg_ptr
);
532 return(msg_ptr
[1] + 2);
535 /*---------------------------------------------------------------------------*
536 * decode and process one Q.931 codeset 0 information element
537 *---------------------------------------------------------------------------*/
539 i4b_decode_q931_message(call_desc_t
*cd
, u_char message_type
)
541 const char *m
= NULL
;
547 /* call establishment */
550 cd
->event
= EV_ALERT
;
554 case CALL_PROCEEDING
:
555 cd
->event
= EV_CALLPRC
;
556 m
= "CALL_PROCEEDING";
560 cd
->event
= EV_PROGIND
;
566 cd
->bprot
= BPROT_NONE
;
569 cd
->dst_telno
[0] = '\0';
570 cd
->src_telno
[0] = '\0';
571 cd
->channelid
= CHAN_NO
;
573 cd
->display
[0] = '\0';
574 cd
->datetime
[0] = '\0';
575 cd
->event
= EV_SETUP
;
580 cd
->datetime
[0] = '\0';
581 cd
->event
= EV_CONNECT
;
584 case SETUP_ACKNOWLEDGE
:
585 m
= "SETUP_ACKNOWLEDGE";
586 cd
->event
= EV_SETUPAK
;
589 case CONNECT_ACKNOWLEDGE
:
590 m
= "CONNECT_ACKNOWLEDGE";
591 cd
->event
= EV_CONACK
;
594 /* call information */
596 case USER_INFORMATION
:
597 m
= "USER_INFORMATION";
601 m
= "SUSPEND_REJECT";
620 case HOLD_ACKNOWLEDGE
:
621 m
= "HOLD_ACKNOWLEDGE";
624 case SUSPEND_ACKNOWLEDGE
:
625 m
= "SUSPEND_ACKNOWLEDGE";
628 case RESUME_ACKNOWLEDGE
:
629 m
= "RESUME_ACKNOWLEDGE";
640 case RETRIEVE_ACKNOWLEDGE
:
641 m
= "RETRIEVE_ACKNOWLEDGE";
644 case RETRIEVE_REJECT
:
645 m
= "RETRIEVE_REJECT";
652 cd
->event
= EV_DISCONN
;
661 cd
->event
= EV_RELEASE
;
664 case RESTART_ACKNOWLEDGE
:
665 m
= "RESTART_ACKNOWLEDGE";
668 case RELEASE_COMPLETE
:
669 m
= "RELEASE_COMPLETE";
670 cd
->event
= EV_RELCOMP
;
681 cd
->event
= EV_FACILITY
;
693 m
= "STATUS_ENQUIRY";
694 cd
->event
= EV_STATENQ
;
697 case CONGESTION_CONTROL
:
698 m
= "CONGESTION_CONTROL";
708 cd
->event
= EV_STATUS
;
712 NDBGL3(L3_P_ERR
, "isdnif %d, cr = 0x%02x, msg = 0x%02x", cd
->isdnif
, cd
->cr
, message_type
);
717 NDBGL3(L3_PRIM
, "%s: isdnif %d, cr = 0x%02x\n", m
, cd
->isdnif
, cd
->cr
);
721 #endif /* NI4BQ931 > 0 */