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_l2if.c - Layer 3 interface to Layer 2
28 * -------------------------------------------
29 *
30 * $Id: i4b_l2if.c,v 1.11 2005/12/11 12:25:06 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_l2if.c,v 1.11 2005/12/11 12:25:06 christos Exp $");
40
41 #ifdef __FreeBSD__
42 #include "i4bq931.h"
43 #else
44 #define NI4BQ931 1
45 #endif
46 #if NI4BQ931 > 0
47
48 #include <sys/param.h>
49 #include <sys/kernel.h>
50 #include <sys/systm.h>
51 #include <sys/mbuf.h>
52 #include <sys/socket.h>
53 #include <net/if.h>
54
55 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
56 #include <sys/callout.h>
57 #endif
58
59 #ifdef __FreeBSD__
60 #include <machine/i4b_debug.h>
61 #include <machine/i4b_ioctl.h>
62 #include <machine/i4b_cause.h>
63 #else
64 #include <netisdn/i4b_debug.h>
65 #include <netisdn/i4b_ioctl.h>
66 #include <netisdn/i4b_cause.h>
67 #endif
68
69 #include <netisdn/i4b_isdnq931.h>
70 #include <netisdn/i4b_l3l4.h>
71 #include <netisdn/i4b_mbuf.h>
72
73 #include <netisdn/i4b_l2.h>
74 #include <netisdn/i4b_l1l2.h>
75 #include <netisdn/i4b_l3.h>
76 #include <netisdn/i4b_l3fsm.h>
77 #include <netisdn/i4b_q931.h>
78
79 #include <netisdn/i4b_l4.h>
80
81 static unsigned char make_q931_cause(cause_t cause);
82
83 /*---------------------------------------------------------------------------*
84 * this converts our internal state (number) to the number specified
85 * in Q.931 and is used for reporting our state in STATUS messages.
86 *---------------------------------------------------------------------------*/
87 int i4b_status_tab[] = {
88 0, /* ST_U0, */
89 1, /* ST_U1, */
90 3, /* ST_U3, */
91 4, /* ST_U4, */
92 6, /* ST_U6, */
93 7, /* ST_U7, */
94 8, /* ST_U8, */
95 9, /* ST_U9, */
96 10, /* ST_U10, */
97 11, /* ST_U11, */
98 12, /* ST_U12, */
99 19, /* ST_U19, */
100 6, /* ST_IWA, */
101 6, /* ST_IWR, */
102 1, /* ST_OW, */
103 6, /* ST_IWL, */
104 };
105
106 /*---------------------------------------------------------------------------*
107 * return a valid q.931/q.850 cause from any of the internal causes
108 *---------------------------------------------------------------------------*/
109 static unsigned char
110 make_q931_cause(cause_t cause)
111 {
112 register unsigned char ret;
113
114 switch(GET_CAUSE_TYPE(cause))
115 {
116 case CAUSET_Q850:
117 ret = GET_CAUSE_VAL(cause);
118 break;
119 case CAUSET_I4B:
120 ret = cause_tab_q931[GET_CAUSE_VAL(cause)];
121 break;
122 default:
123 panic("make_q931_cause: unknown cause type!");
124 break;
125 }
126 ret |= EXT_LAST;
127 return(ret);
128 }
129
130 /*---------------------------------------------------------------------------*
131 * return status of data link
132 *---------------------------------------------------------------------------*/
133 int
134 i4b_get_dl_stat(call_desc_t *cd)
135 {
136 const struct isdn_l3_driver * drv = cd->l3drv;
137 return drv->dl_est;
138 }
139
140 /*---------------------------------------------------------------------------*
141 * DL ESTABLISH INDICATION from Layer 2
142 *---------------------------------------------------------------------------*/
143 int
144 i4b_dl_establish_ind(struct isdn_l3_driver * drv)
145 {
146 int i, found;
147 NDBGL2(L2_PRIM, "DL-ESTABLISH-IND isdnif %d", drv->isdnif);
148
149 /* first set DL up in controller descriptor */
150 NDBGL3(L3_MSG, "isdnif %d DL established!", drv->isdnif);
151 drv->dl_est = DL_UP;
152
153 found = 0;
154
155 /* second, inform all (!) active call of the event */
156
157 for(i=0; i < num_call_desc; i++)
158 {
159 if( (call_desc[i].cdid != 0)
160 && call_desc[i].isdnif == drv->isdnif) {
161 next_l3state(&call_desc[i], EV_DLESTIN);
162 found++;
163 }
164 }
165
166 if(found == 0)
167 {
168 NDBGL3(L3_ERR, "ERROR, no cdid for isdnif %d found!",
169 drv->isdnif);
170 return(-1);
171 }
172 else
173 {
174 return(0);
175 }
176 }
177
178 /*---------------------------------------------------------------------------*
179 * DL ESTABLISH CONFIRM from Layer 2
180 *---------------------------------------------------------------------------*/
181 int
182 i4b_dl_establish_cnf(struct isdn_l3_driver * drv)
183 {
184 int i;
185 int found = 0;
186
187 NDBGL2(L2_PRIM, "DL-ESTABLISH-CONF isdnif %d", drv->isdnif);
188
189 for(i=0; i < num_call_desc; i++)
190 {
191 if(call_desc[i].cdid != 0
192 && call_desc[i].isdnif == drv->isdnif) {
193 drv->dl_est = DL_UP;
194 next_l3state(&call_desc[i], EV_DLESTCF);
195 found++;
196 }
197 }
198
199 if(found == 0)
200 {
201 NDBGL3(L3_ERR, "ERROR, no cdid for isdnif %d found!",
202 drv->isdnif);
203 return(-1);
204 }
205 else
206 {
207 return(0);
208 }
209 }
210
211 /*---------------------------------------------------------------------------*
212 * DL RELEASE INDICATION from Layer 2
213 *---------------------------------------------------------------------------*/
214 int
215 i4b_dl_release_ind(struct isdn_l3_driver * drv)
216 {
217 int i;
218 int found = 0;
219
220 NDBGL2(L2_PRIM, "DL-RELEASE-IND isdnif %d", drv->isdnif);
221
222 /* first set controller to down */
223
224 drv->dl_est = DL_DOWN;
225
226 found = 0;
227
228 /* second, inform all (!) active calls of the event */
229
230 for(i=0; i < num_call_desc; i++)
231 {
232 if(call_desc[i].cdid != 0
233 && call_desc[i].isdnif == drv->isdnif) {
234 next_l3state(&call_desc[i], EV_DLRELIN);
235 found++;
236 }
237 }
238
239 if(found == 0)
240 {
241 /* this is not an error since it might be a normal call end */
242 NDBGL3(L3_MSG, "no cdid for isdnif %d found", drv->isdnif);
243 }
244 return(0);
245 }
246
247 /*---------------------------------------------------------------------------*
248 * DL RELEASE CONFIRM from Layer 2
249 *---------------------------------------------------------------------------*/
250 int
251 i4b_dl_release_cnf(struct isdn_l3_driver * drv)
252 {
253 NDBGL2(L2_PRIM, "DL-RELEASE-CONF isdnif %d", drv->isdnif);
254
255 drv->dl_est = DL_DOWN;
256 return(0);
257 }
258
259 /*---------------------------------------------------------------------------*
260 * i4b_dl_data_ind - process a rx'd I-frame got from layer 2
261 *---------------------------------------------------------------------------*/
262 int
263 i4b_dl_data_ind(struct isdn_l3_driver *drv, struct mbuf *m)
264 {
265 i4b_decode_q931(drv->isdnif, m->m_len, m->m_data);
266 i4b_Dfreembuf(m);
267 return(0);
268 }
269
270 /*---------------------------------------------------------------------------*
271 * dl_unit_data_ind - process a rx'd U-frame got from layer 2
272 *---------------------------------------------------------------------------*/
273 int
274 i4b_dl_unit_data_ind(struct isdn_l3_driver *drv, struct mbuf *m)
275 {
276 i4b_decode_q931(drv->isdnif, m->m_len, m->m_data);
277 i4b_Dfreembuf(m);
278 return(0);
279 }
280
281 /*---------------------------------------------------------------------------*
282 * send CONNECT message
283 *---------------------------------------------------------------------------*/
284 void
285 i4b_l3_tx_connect(call_desc_t *cd)
286 {
287 struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
288 struct mbuf *m;
289 u_char *ptr;
290
291 NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
292
293 if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_CONNECT_LEN)) == NULL)
294 panic("i4b_l3_tx_connect: can't allocate mbuf");
295
296 ptr = m->m_data + I_FRAME_HDRLEN;
297
298 *ptr++ = PD_Q931; /* protocol discriminator */
299 *ptr++ = 0x01; /* call reference length */
300 *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
301 *ptr++ = CONNECT; /* message type = connect */
302
303 i4b_dl_data_req(l2sc, l2sc->drv, m);
304 }
305
306 /*---------------------------------------------------------------------------*
307 * send RELEASE COMPLETE message
308 *---------------------------------------------------------------------------*/
309 void
310 i4b_l3_tx_release_complete(call_desc_t *cd, int send_cause_flag)
311 {
312 struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
313 struct mbuf *m;
314 u_char *ptr;
315 int len = I_FRAME_HDRLEN + MSG_RELEASE_COMPLETE_LEN;
316
317 if(send_cause_flag == 0)
318 {
319 len -= 4;
320 NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x",
321 cd->isdnif, cd->cr);
322 }
323 else
324 {
325 NDBGL3(L3_PRIM, "isdnif=%d, cr=0x%02x, cause=0x%x",
326 cd->isdnif, cd->cr, cd->cause_out);
327 }
328
329 if((m = i4b_Dgetmbuf(len)) == NULL)
330 panic("i4b_l3_tx_release_complete: can't allocate mbuf");
331
332 ptr = m->m_data + I_FRAME_HDRLEN;
333
334 *ptr++ = PD_Q931; /* protocol discriminator */
335 *ptr++ = 0x01; /* call reference length */
336 *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
337 *ptr++ = RELEASE_COMPLETE; /* message type = release complete */
338
339 if(send_cause_flag)
340 {
341 *ptr++ = IEI_CAUSE; /* cause ie */
342 *ptr++ = CAUSE_LEN;
343 *ptr++ = CAUSE_STD_LOC_OUT;
344 *ptr++ = make_q931_cause(cd->cause_out);
345 }
346
347 i4b_dl_data_req(l2sc, l2sc->drv, m);
348 }
349
350 /*---------------------------------------------------------------------------*
351 * send DISCONNECT message
352 *---------------------------------------------------------------------------*/
353 void
354 i4b_l3_tx_disconnect(call_desc_t *cd)
355 {
356 struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
357 struct mbuf *m;
358 u_char *ptr;
359
360 NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
361
362 if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_DISCONNECT_LEN)) == NULL)
363 panic("i4b_l3_tx_disconnect: can't allocate mbuf");
364
365 ptr = m->m_data + I_FRAME_HDRLEN;
366
367 *ptr++ = PD_Q931; /* protocol discriminator */
368 *ptr++ = 0x01; /* call ref length */
369 *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
370 *ptr++ = DISCONNECT; /* message type = disconnect */
371
372 *ptr++ = IEI_CAUSE; /* cause ie */
373 *ptr++ = CAUSE_LEN;
374 *ptr++ = CAUSE_STD_LOC_OUT;
375 *ptr++ = make_q931_cause(cd->cause_out);
376
377 i4b_dl_data_req(l2sc, l2sc->drv, m);
378 }
379
380 /*---------------------------------------------------------------------------*
381 * send SETUP message
382 *---------------------------------------------------------------------------*/
383 void
384 i4b_l3_tx_setup(call_desc_t *cd)
385 {
386 struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
387 struct mbuf *m;
388 u_char *ptr;
389 int slen = strlen(cd->src_telno);
390 int dlen = strlen(cd->dst_telno);
391 int msglen = I_FRAME_HDRLEN + MSG_SETUP_LEN + slen + dlen +
392 (cd->bprot == BPROT_NONE ? 1 : 0);
393
394 if (slen == 0)
395 msglen -= IEI_CALLINGPN_LEN+2; /* whole IE not send */
396
397 /*
398 * there is one additional octet if cd->bprot == BPROT_NONE
399 * NOTE: the selection of a bearer capability by a B L1
400 * protocol is highly questionable and a better
401 * mechanism should be used in future. (-hm)
402 */
403
404 NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
405
406 if((m = i4b_Dgetmbuf(msglen)) == NULL)
407 {
408 panic("i4b_l3_tx_setup: can't allocate mbuf");
409 }
410
411 cd->crflag = CRF_ORIG; /* we are the originating side */
412
413 ptr = m->m_data + I_FRAME_HDRLEN;
414
415 *ptr++ = PD_Q931; /* protocol discriminator */
416 *ptr++ = 0x01; /* call ref length */
417 *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
418 *ptr++ = SETUP; /* message type = setup */
419
420 *ptr++ = IEI_SENDCOMPL; /* sending complete */
421
422 *ptr++ = IEI_BEARERCAP; /* bearer capability */
423
424 /* XXX
425 * currently i have no idea if this should be switched by
426 * the choosen B channel protocol or if there should be a
427 * separate configuration item for the bearer capability.
428 * For now, it is switched by the choosen b protocol (-hm)
429 */
430
431 switch(cd->bprot)
432 {
433 case BPROT_NONE: /* telephony */
434 *ptr++ = IEI_BEARERCAP_LEN+1;
435 *ptr++ = IT_CAP_SPEECH;
436 *ptr++ = IT_RATE_64K;
437 *ptr++ = IT_UL1_G711A;
438 break;
439
440 case BPROT_RHDLC: /* raw HDLC */
441 *ptr++ = IEI_BEARERCAP_LEN;
442 *ptr++ = IT_CAP_UNR_DIG_INFO;
443 *ptr++ = IT_RATE_64K;
444 break;
445
446 default:
447 *ptr++ = IEI_BEARERCAP_LEN;
448 *ptr++ = IT_CAP_UNR_DIG_INFO;
449 *ptr++ = IT_RATE_64K;
450 break;
451 }
452
453 *ptr++ = IEI_CHANNELID; /* channel id */
454 *ptr++ = IEI_CHANNELID_LEN; /* channel id length */
455
456 switch(cd->channelid)
457 {
458 case CHAN_B1:
459 *ptr++ = CHANNELID_B1;
460 break;
461 case CHAN_B2:
462 *ptr++ = CHANNELID_B2;
463 break;
464 default:
465 *ptr++ = CHANNELID_ANY;
466 break;
467 }
468
469 if (slen) {
470 *ptr++ = IEI_CALLINGPN; /* calling party no */
471 *ptr++ = IEI_CALLINGPN_LEN+slen;/* calling party no length */
472 *ptr++ = NUMBER_TYPEPLAN; /* type of number, number plan id */
473 strncpy(ptr, cd->src_telno, slen);
474 ptr += slen;
475 }
476
477 *ptr++ = IEI_CALLEDPN; /* called party no */
478 *ptr++ = IEI_CALLEDPN_LEN+dlen; /* called party no length */
479 *ptr++ = NUMBER_TYPEPLAN; /* type of number, number plan id */
480 strncpy(ptr, cd->dst_telno, dlen);
481 ptr += dlen;
482
483 i4b_dl_data_req(l2sc, l2sc->drv, m);
484 }
485
486 /*---------------------------------------------------------------------------*
487 * send CONNECT ACKNOWLEDGE message
488 *---------------------------------------------------------------------------*/
489 void
490 i4b_l3_tx_connect_ack(call_desc_t *cd)
491 {
492 struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
493 struct mbuf *m;
494 u_char *ptr;
495
496 NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
497
498 if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_CONNECT_ACK_LEN)) == NULL)
499 panic("i4b_l3_tx_connect_ack: can't allocate mbuf");
500
501 ptr = m->m_data + I_FRAME_HDRLEN;
502
503 *ptr++ = PD_Q931; /* protocol discriminator */
504 *ptr++ = 0x01; /* call reference length */
505 *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
506 *ptr++ = CONNECT_ACKNOWLEDGE; /* message type = connect ack */
507
508 i4b_dl_data_req(l2sc, l2sc->drv, m);
509 }
510
511 /*---------------------------------------------------------------------------*
512 * send STATUS message
513 *---------------------------------------------------------------------------*/
514 void
515 i4b_l3_tx_status(call_desc_t *cd, u_char q850cause)
516 {
517 struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
518 struct mbuf *m;
519 u_char *ptr;
520
521 NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
522
523 if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_STATUS_LEN)) == NULL)
524 panic("i4b_l3_tx_status: can't allocate mbuf");
525
526 ptr = m->m_data + I_FRAME_HDRLEN;
527
528 *ptr++ = PD_Q931; /* protocol discriminator */
529 *ptr++ = 0x01; /* call reference length */
530 *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
531 *ptr++ = STATUS; /* message type = connect ack */
532
533 *ptr++ = IEI_CAUSE; /* cause ie */
534 *ptr++ = CAUSE_LEN;
535 *ptr++ = CAUSE_STD_LOC_OUT;
536 *ptr++ = q850cause | EXT_LAST;
537
538 *ptr++ = IEI_CALLSTATE; /* call state ie */
539 *ptr++ = CALLSTATE_LEN;
540 *ptr++ = i4b_status_tab[cd->Q931state];
541
542 i4b_dl_data_req(l2sc, l2sc->drv, m);
543 }
544
545 /*---------------------------------------------------------------------------*
546 * send RELEASE message
547 *---------------------------------------------------------------------------*/
548 void
549 i4b_l3_tx_release(call_desc_t *cd, int send_cause_flag)
550 {
551 struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
552 struct mbuf *m;
553 u_char *ptr;
554 int len = I_FRAME_HDRLEN + MSG_RELEASE_LEN;
555
556 NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
557
558 if(send_cause_flag == 0)
559 len -= 4;
560
561 if((m = i4b_Dgetmbuf(len)) == NULL)
562 panic("i4b_l3_tx_release: can't allocate mbuf");
563
564 ptr = m->m_data + I_FRAME_HDRLEN;
565
566 *ptr++ = PD_Q931; /* protocol discriminator */
567 *ptr++ = 0x01; /* call reference length */
568 *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
569 *ptr++ = RELEASE; /* message type = release complete */
570
571 if(send_cause_flag)
572 {
573 *ptr++ = IEI_CAUSE; /* cause ie */
574 *ptr++ = CAUSE_LEN;
575 *ptr++ = CAUSE_STD_LOC_OUT;
576 *ptr++ = make_q931_cause(cd->cause_out);
577 }
578
579 i4b_dl_data_req(l2sc, l2sc->drv, m);
580 }
581
582 /*---------------------------------------------------------------------------*
583 * send ALERTING message
584 *---------------------------------------------------------------------------*/
585 void
586 i4b_l3_tx_alert(call_desc_t *cd)
587 {
588 struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
589 struct mbuf *m;
590 u_char *ptr;
591
592 if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_ALERT_LEN)) == NULL)
593 panic("i4b_l3_tx_alert: can't allocate mbuf");
594
595 NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
596
597 ptr = m->m_data + I_FRAME_HDRLEN;
598
599 *ptr++ = PD_Q931; /* protocol discriminator */
600 *ptr++ = 0x01; /* call reference length */
601 *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
602 *ptr++ = ALERT; /* message type = alert */
603
604 i4b_dl_data_req(l2sc, l2sc->drv, m);
605 }
606
607 #endif /* NI4BQ931 > 0 */
Cache object: 9a9bd70f2dbbcc66d4911be703e30073
|