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