FreeBSD/Linux Kernel Cross Reference
sys/netisdn/i4b_l4.c
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_l4.c - kernel interface to userland
28 * -----------------------------------------
29 *
30 * $Id: i4b_l4.c,v 1.26 2004/03/21 16:29:40 martin 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_l4.c,v 1.26 2004/03/21 16:29:40 martin Exp $");
40
41 #include "isdn.h"
42 #include "irip.h"
43
44 #if NISDN > 0
45
46 #include <sys/param.h>
47 #include <sys/kernel.h>
48 #include <sys/systm.h>
49 #include <sys/conf.h>
50 #include <sys/mbuf.h>
51 #include <sys/proc.h>
52 #include <sys/fcntl.h>
53 #include <sys/socket.h>
54 #include <net/if.h>
55
56 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
57 #include <sys/callout.h>
58 #endif
59
60 #ifdef __FreeBSD__
61 #include <machine/i4b_debug.h>
62 #include <machine/i4b_ioctl.h>
63 #include <machine/i4b_cause.h>
64 #else
65 #include <netisdn/i4b_debug.h>
66 #include <netisdn/i4b_ioctl.h>
67 #include <netisdn/i4b_cause.h>
68 #endif
69
70 #include <netisdn/i4b_global.h>
71 #include <netisdn/i4b_l3l4.h>
72 #include <netisdn/i4b_mbuf.h>
73 #include <netisdn/i4b_l2.h>
74 #include <netisdn/i4b_l3.h>
75 #include <netisdn/i4b_l4.h>
76
77 unsigned int i4b_l4_debug = L4_DEBUG_DEFAULT;
78
79 /*
80 * ISDNs, in userland sometimes called "controllers", but one controller
81 * may have multiple BRIs, for example daic QUAD cards attach four BRIs.
82 * An ISDN may also be a PRI (30 B channels).
83 */
84 static SLIST_HEAD(, isdn_l3_driver) isdnif_list = SLIST_HEAD_INITIALIZER(isdnif_list);
85 static int next_isdnif = 0;
86
87 /*
88 * Attach a new L3 driver instance and return its ISDN identifier
89 */
90 struct isdn_l3_driver *
91 isdn_attach_isdnif(const char *devname, const char *cardname,
92 void *l1_token, const struct isdn_l3_driver_functions *l3driver, int nbch)
93 {
94 int s = splnet();
95 int i, l, isdnif = next_isdnif++;
96 struct isdn_l3_driver *new_ctrl;
97
98 new_ctrl = malloc(sizeof(*new_ctrl), M_DEVBUF, 0);
99 memset(new_ctrl, 0, sizeof *new_ctrl);
100 SLIST_INSERT_HEAD(&isdnif_list, new_ctrl, l3drvq);
101 l = strlen(devname);
102 new_ctrl->devname = malloc(l + 1, M_DEVBUF, 0);
103 strlcpy(new_ctrl->devname, devname, l + 1);
104 l = strlen(cardname);
105 new_ctrl->card_name = malloc(l + 1, M_DEVBUF, 0);
106 strlcpy(new_ctrl->card_name, cardname, l + 1);
107
108 new_ctrl->l3driver = l3driver;
109 new_ctrl->l1_token = l1_token;
110 new_ctrl->isdnif = isdnif;
111 new_ctrl->tei = -1;
112 new_ctrl->dl_est = DL_DOWN;
113 new_ctrl->nbch = nbch;
114
115 new_ctrl->bch_state = malloc(nbch * sizeof(int), M_DEVBUF, 0);
116 for (i = 0; i < nbch; i++)
117 new_ctrl->bch_state[i] = BCH_ST_FREE;
118
119 splx(s);
120
121 return new_ctrl;
122 }
123
124 /*
125 * Detach a L3 driver instance
126 */
127 int
128 isdn_detach_isdnif(struct isdn_l3_driver *l3drv)
129 {
130 struct isdn_l3_driver *sc;
131 int s = splnet();
132 int isdnif = l3drv->isdnif;
133 int max;
134
135 i4b_l4_contr_ev_ind(isdnif, 0);
136 SLIST_REMOVE(&isdnif_list, l3drv, isdn_l3_driver, l3drvq);
137
138 max = -1;
139 SLIST_FOREACH(sc, &isdnif_list, l3drvq)
140 if (sc->isdnif > max)
141 max = sc->isdnif;
142 next_isdnif = max+1;
143
144 free_all_cd_of_isdnif(isdnif);
145
146 splx(s);
147
148 free(l3drv, M_DEVBUF);
149 printf("ISDN %d detached\n", isdnif);
150 return 1;
151 }
152
153 struct isdn_l3_driver *
154 isdn_find_l3_by_isdnif(int isdnif)
155 {
156 struct isdn_l3_driver *sc;
157
158 SLIST_FOREACH(sc, &isdnif_list, l3drvq)
159 if (sc->isdnif == isdnif)
160 return sc;
161 return NULL;
162 }
163
164 int isdn_count_isdnif(int *misdnif)
165 {
166 struct isdn_l3_driver *sc;
167 int count = 0;
168 int max_isdnif = -1;
169
170 SLIST_FOREACH(sc, &isdnif_list, l3drvq) {
171 count++;
172 if (sc->isdnif > max_isdnif)
173 max_isdnif = sc->isdnif;
174 }
175
176 if (misdnif)
177 *misdnif = max_isdnif;
178
179 return count;
180 }
181
182 void *
183 isdn_find_softc_by_isdnif(int isdnif)
184 {
185 struct isdn_l3_driver *sc = isdn_find_l3_by_isdnif(isdnif);
186 if (sc == NULL)
187 return NULL;
188 /*
189 * XXX - hack: do not return a softc for active cards.
190 * all callers of this expecting l2_softc* results
191 * should be fixed!
192 */
193 if (sc->l3driver->N_DOWNLOAD)
194 return NULL;
195 return sc->l1_token;
196 }
197
198 /*---------------------------------------------------------------------------*
199 * daemon is attached
200 *---------------------------------------------------------------------------*/
201 void
202 i4b_l4_daemon_attached(void)
203 {
204 struct isdn_l3_driver *d;
205
206 int x = splnet();
207 SLIST_FOREACH(d, &isdnif_list, l3drvq)
208 {
209 d->l3driver->N_MGMT_COMMAND(d, CMR_DOPEN, 0);
210 }
211 splx(x);
212 }
213
214 /*---------------------------------------------------------------------------*
215 * daemon is detached
216 *---------------------------------------------------------------------------*/
217 void
218 i4b_l4_daemon_detached(void)
219 {
220 struct isdn_l3_driver *d;
221
222 int x = splnet();
223 SLIST_FOREACH(d, &isdnif_list, l3drvq)
224 {
225 d->l3driver->N_MGMT_COMMAND(d, CMR_DCLOSE, 0);
226 }
227 splx(x);
228 }
229
230 /*
231 * B-channel layer 4 drivers and their registry.
232 * (Application drivers connecting to a B-channel)
233 */
234 static int i4b_link_bchandrvr(call_desc_t *cd);
235 static void i4b_unlink_bchandrvr(call_desc_t *cd);
236 static void i4b_l4_setup_timeout(call_desc_t *cd);
237 static void i4b_idle_check_fix_unit(call_desc_t *cd);
238 static void i4b_idle_check_var_unit(call_desc_t *cd);
239 static void i4b_l4_setup_timeout_fix_unit(call_desc_t *cd);
240 static void i4b_l4_setup_timeout_var_unit(call_desc_t *cd);
241 static time_t i4b_get_idletime(call_desc_t *cd);
242
243 static int next_l4_driver_id = 0;
244
245 struct l4_driver_desc {
246 SLIST_ENTRY(l4_driver_desc) l4drvq;
247 char name[L4DRIVER_NAME_SIZ];
248 int driver_id;
249 const struct isdn_l4_driver_functions *driver;
250 int units;
251 };
252 static SLIST_HEAD(, l4_driver_desc) l4_driver_registry
253 = SLIST_HEAD_INITIALIZER(l4_driver_registry);
254
255 int isdn_l4_driver_attach(const char *name, int units, const struct isdn_l4_driver_functions *driver)
256 {
257 struct l4_driver_desc * new_driver;
258
259 new_driver = malloc(sizeof(struct l4_driver_desc), M_DEVBUF, 0);
260 memset(new_driver, 0, sizeof(struct l4_driver_desc));
261 strncpy(new_driver->name, name, L4DRIVER_NAME_SIZ);
262 new_driver->name[L4DRIVER_NAME_SIZ-1] = 0;
263 new_driver->driver_id = next_l4_driver_id++;
264 new_driver->driver = driver;
265 new_driver->units = units;
266 SLIST_INSERT_HEAD(&l4_driver_registry, new_driver, l4drvq);
267 return new_driver->driver_id;
268 }
269
270 int isdn_l4_driver_detatch(const char *name)
271 {
272 /* XXX - not yet implemented */
273 return 0;
274 }
275
276 const struct isdn_l4_driver_functions *isdn_l4_find_driver(const char *name, int unit)
277 {
278 struct l4_driver_desc * d;
279 SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
280 if (strcmp(d->name, name) == 0) {
281 return d->driver;
282 }
283 return NULL;
284 }
285
286 int isdn_l4_find_driverid(const char *name)
287 {
288 struct l4_driver_desc * d;
289 SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
290 if (strcmp(d->name, name) == 0) {
291 return d->driver_id;
292 }
293 return -1;
294 }
295
296 const struct isdn_l4_driver_functions *isdn_l4_get_driver(int driver_id, int unit)
297 {
298 struct l4_driver_desc * d;
299 SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
300 if (d->driver_id == driver_id) {
301 return d->driver;
302 }
303 return NULL;
304 }
305
306 /*---------------------------------------------------------------------------*
307 * send MSG_PDEACT_IND message to userland
308 *---------------------------------------------------------------------------*/
309 void
310 i4b_l4_pdeact(struct isdn_l3_driver *d, int numactive)
311 {
312 struct mbuf *m;
313 int i;
314 call_desc_t *cd;
315
316 for(i=0; i < num_call_desc; i++)
317 {
318 if(call_desc[i].cdid != CDID_UNUSED && call_desc[i].l3drv == d)
319 {
320 cd = &call_desc[i];
321
322 if(cd->timeout_active)
323 {
324 STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
325 }
326
327 if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL)
328 {
329 (*cd->l4_driver->line_disconnected)(cd->l4_driver_softc, (void *)cd);
330 i4b_unlink_bchandrvr(cd);
331 }
332
333 if ((cd->channelid >= 0)
334 && (cd->channelid < d->nbch));
335 d->bch_state[cd->channelid] = BCH_ST_FREE;
336
337 cd->cdid = CDID_UNUSED;
338 }
339 }
340
341 if((m = i4b_Dgetmbuf(sizeof(msg_pdeact_ind_t))) != NULL)
342 {
343 msg_pdeact_ind_t *md = (msg_pdeact_ind_t *)m->m_data;
344
345 md->header.type = MSG_PDEACT_IND;
346 md->header.cdid = -1;
347
348 md->controller = d->isdnif;
349 md->numactive = numactive;
350
351 i4bputqueue_hipri(m); /* URGENT !!! */
352 }
353 }
354
355 /*---------------------------------------------------------------------------*
356 * send MSG_L12STAT_IND message to userland
357 *---------------------------------------------------------------------------*/
358 void
359 i4b_l4_l12stat(struct isdn_l3_driver *d, int layer, int state)
360 {
361 struct mbuf *m;
362
363 if((m = i4b_Dgetmbuf(sizeof(msg_l12stat_ind_t))) != NULL)
364 {
365 msg_l12stat_ind_t *md = (msg_l12stat_ind_t *)m->m_data;
366
367 md->header.type = MSG_L12STAT_IND;
368 md->header.cdid = -1;
369
370 md->controller = d->isdnif;
371 md->layer = layer;
372 md->state = state;
373
374 i4bputqueue(m);
375 }
376 }
377
378 /*---------------------------------------------------------------------------*
379 * send MSG_TEIASG_IND message to userland
380 *---------------------------------------------------------------------------*/
381 void
382 i4b_l4_teiasg(struct isdn_l3_driver *d, int tei)
383 {
384 struct mbuf *m;
385
386 if((m = i4b_Dgetmbuf(sizeof(msg_teiasg_ind_t))) != NULL)
387 {
388 msg_teiasg_ind_t *md = (msg_teiasg_ind_t *)m->m_data;
389
390 md->header.type = MSG_TEIASG_IND;
391 md->header.cdid = -1;
392
393 md->controller = d->isdnif;
394 md->tei = d->tei;
395
396 i4bputqueue(m);
397 }
398 }
399
400 /*---------------------------------------------------------------------------*
401 * send MSG_DIALOUT_IND message to userland
402 *---------------------------------------------------------------------------*/
403 void
404 i4b_l4_dialout(int driver, int driver_unit)
405 {
406 struct mbuf *m;
407
408 if((m = i4b_Dgetmbuf(sizeof(msg_dialout_ind_t))) != NULL)
409 {
410 msg_dialout_ind_t *md = (msg_dialout_ind_t *)m->m_data;
411
412 md->header.type = MSG_DIALOUT_IND;
413 md->header.cdid = -1;
414
415 md->driver = driver;
416 md->driver_unit = driver_unit;
417
418 i4bputqueue(m);
419 }
420 }
421
422 /*---------------------------------------------------------------------------*
423 * send MSG_DIALOUTNUMBER_IND message to userland
424 *---------------------------------------------------------------------------*/
425 void
426 i4b_l4_dialoutnumber(int driver, int driver_unit, int cmdlen, char *cmd)
427 {
428 struct mbuf *m;
429
430 if((m = i4b_Dgetmbuf(sizeof(msg_dialoutnumber_ind_t))) != NULL)
431 {
432 msg_dialoutnumber_ind_t *md = (msg_dialoutnumber_ind_t *)m->m_data;
433
434 md->header.type = MSG_DIALOUTNUMBER_IND;
435 md->header.cdid = -1;
436
437 md->driver = driver;
438 md->driver_unit = driver_unit;
439
440 if(cmdlen > TELNO_MAX)
441 cmdlen = TELNO_MAX;
442
443 md->cmdlen = cmdlen;
444 memcpy(md->cmd, cmd, cmdlen);
445 i4bputqueue(m);
446 }
447 }
448
449 /*---------------------------------------------------------------------------*
450 * send MSG_NEGOTIATION_COMPL message to userland
451 *---------------------------------------------------------------------------*/
452 void
453 i4b_l4_negcomplete(call_desc_t *cd)
454 {
455 struct mbuf *m;
456
457 if((m = i4b_Dgetmbuf(sizeof(msg_negcomplete_ind_t))) != NULL)
458 {
459 msg_negcomplete_ind_t *md = (msg_negcomplete_ind_t *)m->m_data;
460
461 md->header.type = MSG_NEGCOMP_IND;
462 md->header.cdid = cd->cdid;
463
464 i4bputqueue(m);
465 }
466 }
467
468 /*---------------------------------------------------------------------------*
469 * send MSG_IFSTATE_CHANGED_IND message to userland
470 *---------------------------------------------------------------------------*/
471 void
472 i4b_l4_ifstate_changed(call_desc_t *cd, int new_state)
473 {
474 struct mbuf *m;
475
476 if((m = i4b_Dgetmbuf(sizeof(msg_ifstatechg_ind_t))) != NULL)
477 {
478 msg_ifstatechg_ind_t *md = (msg_ifstatechg_ind_t *)m->m_data;
479
480 md->header.type = MSG_IFSTATE_CHANGED_IND;
481 md->header.cdid = cd->cdid;
482 md->state = new_state;
483
484 i4bputqueue(m);
485 }
486 }
487
488 /*---------------------------------------------------------------------------*
489 * send MSG_DRVRDISC_REQ message to userland
490 *---------------------------------------------------------------------------*/
491 void
492 i4b_l4_drvrdisc(int cdid)
493 {
494 struct mbuf *m;
495
496 if((m = i4b_Dgetmbuf(sizeof(msg_drvrdisc_req_t))) != NULL)
497 {
498 msg_drvrdisc_req_t *md = (msg_drvrdisc_req_t *)m->m_data;
499
500 md->header.type = MSG_DRVRDISC_REQ;
501 md->header.cdid = cdid;
502
503 i4bputqueue(m);
504 }
505 }
506
507 /*---------------------------------------------------------------------------*
508 * send MSG_ACCT_IND message to userland
509 *---------------------------------------------------------------------------*/
510 void
511 i4b_l4_accounting(int cdid, int accttype, int ioutbytes,
512 int iinbytes, int ro, int ri, int outbytes, int inbytes)
513 {
514 struct mbuf *m;
515
516 if((m = i4b_Dgetmbuf(sizeof(msg_accounting_ind_t))) != NULL)
517 {
518 msg_accounting_ind_t *md = (msg_accounting_ind_t *)m->m_data;
519
520 md->header.type = MSG_ACCT_IND;
521 md->header.cdid = cdid;
522
523 md->accttype = accttype;
524 md->ioutbytes = ioutbytes;
525 md->iinbytes = iinbytes;
526 md->outbps = ro;
527 md->inbps = ri;
528 md->outbytes = outbytes;
529 md->inbytes = inbytes;
530
531 i4bputqueue(m);
532 }
533 }
534
535 /*---------------------------------------------------------------------------*
536 * send MSG_CONNECT_IND message to userland
537 *---------------------------------------------------------------------------*/
538 void
539 i4b_l4_connect_ind(call_desc_t *cd)
540 {
541 struct mbuf *m;
542
543 if((m = i4b_Dgetmbuf(sizeof(msg_connect_ind_t))) != NULL)
544 {
545 msg_connect_ind_t *mp = (msg_connect_ind_t *)m->m_data;
546
547 mp->header.type = MSG_CONNECT_IND;
548 mp->header.cdid = cd->cdid;
549
550 mp->controller = cd->isdnif;
551 mp->channel = cd->channelid;
552 mp->bprot = cd->bprot;
553
554 cd->dir = DIR_INCOMING;
555
556 if(strlen(cd->dst_telno) > 0)
557 strlcpy(mp->dst_telno, cd->dst_telno,
558 sizeof(mp->dst_telno));
559 else
560 strlcpy(mp->dst_telno, TELNO_EMPTY,
561 sizeof(mp->dst_telno));
562
563 if(strlen(cd->src_telno) > 0)
564 strlcpy(mp->src_telno, cd->src_telno,
565 sizeof(mp->src_telno));
566 else
567 strlcpy(mp->src_telno, TELNO_EMPTY,
568 sizeof(mp->src_telno));
569 mp->type_plan = cd->type_plan;
570 memcpy(mp->src_subaddr, cd->src_subaddr, sizeof(mp->src_subaddr));
571 memcpy(mp->dest_subaddr, cd->dest_subaddr, sizeof(mp->dest_subaddr));
572
573 strlcpy(mp->display, cd->display, sizeof(mp->src_telno));
574
575 mp->scr_ind = cd->scr_ind;
576 mp->prs_ind = cd->prs_ind;
577
578 T400_start(cd);
579
580 i4bputqueue(m);
581 }
582 }
583
584 /*---------------------------------------------------------------------------*
585 * send MSG_CONNECT_ACTIVE_IND message to userland
586 *---------------------------------------------------------------------------*/
587 void
588 i4b_l4_connect_active_ind(call_desc_t *cd)
589 {
590 int s;
591 struct mbuf *m;
592
593 s = splnet();
594
595 cd->last_active_time = cd->connect_time = SECOND;
596
597 NDBGL4(L4_TIMO, "last_active/connect_time=%ld", (long)cd->connect_time);
598
599 i4b_link_bchandrvr(cd);
600
601 update_controller_leds(cd->l3drv);
602
603 if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL)
604 (*cd->l4_driver->line_connected)(cd->l4_driver_softc, cd);
605
606 i4b_l4_setup_timeout(cd);
607
608 splx(s);
609
610 if((m = i4b_Dgetmbuf(sizeof(msg_connect_active_ind_t))) != NULL)
611 {
612 msg_connect_active_ind_t *mp = (msg_connect_active_ind_t *)m->m_data;
613
614 mp->header.type = MSG_CONNECT_ACTIVE_IND;
615 mp->header.cdid = cd->cdid;
616 mp->controller = cd->isdnif;
617 mp->channel = cd->channelid;
618 if(cd->datetime[0] != '\0')
619 strlcpy(mp->datetime, cd->datetime,
620 sizeof(mp->datetime));
621 else
622 mp->datetime[0] = '\0';
623 i4bputqueue(m);
624 }
625 }
626
627 /*---------------------------------------------------------------------------*
628 * send MSG_DISCONNECT_IND message to userland
629 *---------------------------------------------------------------------------*/
630 void
631 i4b_l4_disconnect_ind(call_desc_t *cd)
632 {
633 struct isdn_l3_driver *d;
634 struct mbuf *m;
635
636 if(cd->timeout_active)
637 STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
638
639 if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL)
640 {
641 (*cd->l4_driver->line_disconnected)(cd->l4_driver_softc, (void *)cd);
642 i4b_unlink_bchandrvr(cd);
643 }
644
645 d = cd->l3drv;
646
647 if((cd->channelid >= 0) && (cd->channelid < d->nbch))
648 {
649 d->bch_state[cd->channelid] = BCH_ST_FREE;
650 /*
651 * XXX: don't call l2 function for active cards.
652 */
653 if (d->l3driver->N_DOWNLOAD == NULL)
654 i4b_l2_channel_set_state(d, cd->channelid, BCH_ST_FREE);
655 }
656 else
657 {
658 /* no error, might be hunting call for callback */
659 NDBGL4(L4_MSG, "invalid channel %d for ISDN!", cd->channelid);
660 }
661 update_controller_leds(d);
662
663 if((m = i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t))) != NULL)
664 {
665 msg_disconnect_ind_t *mp = (msg_disconnect_ind_t *)m->m_data;
666
667 mp->header.type = MSG_DISCONNECT_IND;
668 mp->header.cdid = cd->cdid;
669 mp->cause = cd->cause_in;
670
671 i4bputqueue(m);
672 }
673 }
674
675 /*---------------------------------------------------------------------------*
676 * send MSG_IDLE_TIMEOUT_IND message to userland
677 *---------------------------------------------------------------------------*/
678 void
679 i4b_l4_idle_timeout_ind(call_desc_t *cd)
680 {
681 struct mbuf *m;
682
683 if((m = i4b_Dgetmbuf(sizeof(msg_idle_timeout_ind_t))) != NULL)
684 {
685 msg_idle_timeout_ind_t *mp = (msg_idle_timeout_ind_t *)m->m_data;
686
687 mp->header.type = MSG_IDLE_TIMEOUT_IND;
688 mp->header.cdid = cd->cdid;
689
690 i4bputqueue(m);
691 }
692 }
693
694 /*---------------------------------------------------------------------------*
695 * send MSG_CHARGING_IND message to userland
696 *---------------------------------------------------------------------------*/
697 void
698 i4b_l4_charging_ind(call_desc_t *cd)
699 {
700 struct mbuf *m;
701
702 if((m = i4b_Dgetmbuf(sizeof(msg_charging_ind_t))) != NULL)
703 {
704 msg_charging_ind_t *mp = (msg_charging_ind_t *)m->m_data;
705
706 mp->header.type = MSG_CHARGING_IND;
707 mp->header.cdid = cd->cdid;
708 mp->units_type = cd->units_type;
709
710 /*XXX*/ if(mp->units_type == CHARGE_CALC)
711 mp->units = cd->cunits;
712 else
713 mp->units = cd->units;
714
715 i4bputqueue(m);
716 }
717 }
718
719 /*---------------------------------------------------------------------------*
720 * send MSG_STATUS_IND message to userland
721 *---------------------------------------------------------------------------*/
722 void
723 i4b_l4_status_ind(call_desc_t *cd)
724 {
725 }
726
727 /*---------------------------------------------------------------------------*
728 * send MSG_ALERT_IND message to userland
729 *---------------------------------------------------------------------------*/
730 void
731 i4b_l4_alert_ind(call_desc_t *cd)
732 {
733 struct mbuf *m;
734
735 if((m = i4b_Dgetmbuf(sizeof(msg_alert_ind_t))) != NULL)
736 {
737 msg_alert_ind_t *mp = (msg_alert_ind_t *)m->m_data;
738
739 mp->header.type = MSG_ALERT_IND;
740 mp->header.cdid = cd->cdid;
741
742 i4bputqueue(m);
743 }
744 }
745
746 /*---------------------------------------------------------------------------*
747 * send MSG_INFO_IND message to userland
748 *---------------------------------------------------------------------------*/
749 void
750 i4b_l4_info_ind(call_desc_t *cd)
751 {
752 }
753
754 /*---------------------------------------------------------------------------*
755 * send MSG_INFO_IND message to userland
756 *---------------------------------------------------------------------------*/
757 void
758 i4b_l4_proceeding_ind(call_desc_t *cd)
759 {
760 struct mbuf *m;
761
762 if((m = i4b_Dgetmbuf(sizeof(msg_proceeding_ind_t))) != NULL)
763 {
764 msg_proceeding_ind_t *mp = (msg_proceeding_ind_t *)m->m_data;
765
766 mp->header.type = MSG_PROCEEDING_IND;
767 mp->header.cdid = cd->cdid;
768 mp->controller = cd->isdnif;
769 mp->channel = cd->channelid;
770 i4bputqueue(m);
771 }
772 }
773
774 /*---------------------------------------------------------------------------*
775 * send MSG_PACKET_IND message to userland
776 *---------------------------------------------------------------------------*/
777 void
778 i4b_l4_packet_ind(int driver, int driver_unit, int dir, struct mbuf *pkt)
779 {
780 struct mbuf *m;
781 int len = pkt->m_pkthdr.len;
782 unsigned char *ip = pkt->m_data;
783
784 if((m = i4b_Dgetmbuf(sizeof(msg_packet_ind_t))) != NULL)
785 {
786 msg_packet_ind_t *mp = (msg_packet_ind_t *)m->m_data;
787
788 mp->header.type = MSG_PACKET_IND;
789 mp->header.cdid = -1;
790 mp->driver = driver;
791 mp->driver_unit = driver_unit;
792 mp->direction = dir;
793 memcpy(mp->pktdata, ip,
794 len <MAX_PACKET_LOG ? len : MAX_PACKET_LOG);
795 i4bputqueue(m);
796 }
797 }
798
799 /*---------------------------------------------------------------------------*
800 * send MSG_CONTR_EV_IND message to userland
801 *---------------------------------------------------------------------------*/
802 void
803 i4b_l4_contr_ev_ind(int controller, int attach)
804 {
805 struct mbuf *m;
806
807 if((m = i4b_Dgetmbuf(sizeof(msg_ctrl_ev_ind_t))) != NULL)
808 {
809 msg_ctrl_ev_ind_t *ev = (msg_ctrl_ev_ind_t *)m->m_data;
810
811 ev->header.type = MSG_CONTR_EV_IND;
812 ev->header.cdid = -1;
813 ev->controller = controller;
814 ev->event = attach;
815 i4bputqueue(m);
816 }
817 }
818
819 /*---------------------------------------------------------------------------*
820 * link a driver(unit) to a B-channel(controller,unit,channel)
821 *---------------------------------------------------------------------------*/
822 static int
823 i4b_link_bchandrvr(call_desc_t *cd)
824 {
825 struct isdn_l3_driver *d = cd->l3drv;
826
827 if (d == NULL || d->l3driver == NULL || d->l3driver->get_linktab == NULL)
828 {
829 cd->ilt = NULL;
830 return 1;
831 }
832
833 cd->ilt = d->l3driver->get_linktab(d->l1_token,
834 cd->channelid);
835
836 cd->l4_driver = isdn_l4_get_driver(cd->bchan_driver_index, cd->bchan_driver_unit);
837 if (cd->l4_driver != NULL)
838 cd->l4_driver_softc = cd->l4_driver->get_softc(cd->bchan_driver_unit);
839 else
840 cd->l4_driver_softc = NULL;
841
842 if(cd->l4_driver == NULL || cd->l4_driver_softc == NULL || cd->ilt == NULL)
843 return(-1);
844
845 if (d->l3driver->set_l4_driver != NULL)
846 {
847 d->l3driver->set_l4_driver(d->l1_token,
848 cd->channelid, cd->l4_driver, cd->l4_driver_softc);
849 }
850
851 cd->l4_driver->set_linktab(cd->l4_driver_softc, cd->ilt);
852
853 /* activate B channel */
854
855 (*cd->ilt->bchannel_driver->bch_config)(cd->ilt->l1token, cd->ilt->channel, cd->bprot, 1);
856
857 return(0);
858 }
859
860 /*---------------------------------------------------------------------------*
861 * unlink a driver(unit) from a B-channel(controller,unit,channel)
862 *---------------------------------------------------------------------------*/
863 static void
864 i4b_unlink_bchandrvr(call_desc_t *cd)
865 {
866 struct isdn_l3_driver *d = cd->l3drv;
867
868 /*
869 * XXX - what's this *cd manipulation for? Shouldn't we
870 * close the bchannel driver first and then just set ilt to NULL
871 * in *cd?
872 */
873 if (d == NULL || d->l3driver == NULL || d->l3driver->get_linktab == NULL)
874 {
875 cd->ilt = NULL;
876 return;
877 }
878 else
879 {
880 cd->ilt = d->l3driver->get_linktab(
881 d->l1_token, cd->channelid);
882 }
883
884 /* deactivate B channel */
885
886 (*cd->ilt->bchannel_driver->bch_config)(cd->ilt->l1token, cd->ilt->channel, cd->bprot, 0);
887 }
888
889 /*---------------------------------------------------------------------------
890
891 How shorthold mode works for OUTGOING connections
892 =================================================
893
894 |<---- unchecked-window ------->|<-checkwindow->|<-safetywindow>|
895
896 idletime_state: IST_NONCHK IST_CHECK IST_SAFE
897
898 | | | |
899 time>>+-------------------------------+---------------+---------------+-...
900 | | | |
901 | |<--idle_time-->|<--earlyhup--->|
902 |<-----------------------unitlen------------------------------->|
903
904
905 unitlen - specifies the time a charging unit lasts
906 idle_time - specifies the thime the line must be idle at the
907 end of the unit to be elected for hangup
908 earlyhup - is the beginning of a timing safety zone before the
909 next charging unit starts
910
911 The algorithm works as follows: lets assume the unitlen is 100
912 secons, idle_time is 40 seconds and earlyhup is 10 seconds.
913 The line then must be idle 50 seconds after the begin of the
914 current unit and it must then be quiet for 40 seconds. if it
915 has been quiet for this 40 seconds, the line is closed 10
916 seconds before the next charging unit starts. In case there was
917 any traffic within the idle_time, the line is not closed.
918 It does not matter whether there was any traffic between second
919 0 and second 50 or not.
920
921
922 How shorthold mode works for INCOMING connections
923 =================================================
924
925 it is just possible to specify a maximum idle time for incoming
926 connections, after this time of no activity on the line the line
927 is closed.
928
929 ---------------------------------------------------------------------------*/
930
931 static time_t
932 i4b_get_idletime(call_desc_t *cd)
933 {
934 if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL
935 && cd->l4_driver->get_idletime)
936 return cd->l4_driver->get_idletime(cd->l4_driver_softc);
937 return cd->last_active_time;
938 }
939
940 /*---------------------------------------------------------------------------*
941 * B channel idle check timeout setup
942 *---------------------------------------------------------------------------*/
943 static void
944 i4b_l4_setup_timeout(call_desc_t *cd)
945 {
946 NDBGL4(L4_TIMO, "%ld: direction %d, shorthold algorithm %d",
947 (long)SECOND, cd->dir, cd->shorthold_data.shorthold_algorithm);
948
949 cd->timeout_active = 0;
950 cd->idletime_state = IST_IDLE;
951
952 if((cd->dir == DIR_INCOMING) && (cd->max_idle_time > 0))
953 {
954 /* incoming call: simple max idletime check */
955
956 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
957 cd->timeout_active = 1;
958 NDBGL4(L4_TIMO, "%ld: incoming-call, setup max_idle_time to %ld", (long)SECOND, (long)cd->max_idle_time);
959 }
960 else if((cd->dir == DIR_OUTGOING) && (cd->shorthold_data.idle_time > 0))
961 {
962 switch( cd->shorthold_data.shorthold_algorithm )
963 {
964 default: /* fall into the old fix algorithm */
965 case SHA_FIXU:
966 i4b_l4_setup_timeout_fix_unit( cd );
967 break;
968
969 case SHA_VARU:
970 i4b_l4_setup_timeout_var_unit( cd );
971 break;
972 }
973 }
974 else
975 {
976 NDBGL4(L4_TIMO, "no idle_timeout configured");
977 }
978 }
979
980 /*---------------------------------------------------------------------------*
981 * fixed unit algorithm B channel idle check timeout setup
982 *---------------------------------------------------------------------------*/
983 static void
984 i4b_l4_setup_timeout_fix_unit(call_desc_t *cd)
985 {
986 /* outgoing call */
987
988 if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
989 {
990 /* outgoing call: simple max idletime check */
991
992 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
993 cd->timeout_active = 1;
994 NDBGL4(L4_TIMO, "%ld: outgoing-call, setup idle_time to %ld",
995 (long)SECOND, (long)cd->shorthold_data.idle_time);
996 }
997 else if((cd->shorthold_data.unitlen_time > 0) && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
998 {
999 /* outgoing call: full shorthold mode check */
1000
1001 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)));
1002 cd->timeout_active = 1;
1003 cd->idletime_state = IST_NONCHK;
1004 NDBGL4(L4_TIMO, "%ld: outgoing-call, start %ld sec nocheck window",
1005 (long)SECOND, (long)(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)));
1006
1007 if(cd->aocd_flag == 0)
1008 {
1009 cd->units_type = CHARGE_CALC;
1010 cd->cunits++;
1011 i4b_l4_charging_ind(cd);
1012 }
1013 }
1014 else
1015 {
1016 /* parms somehow got wrong .. */
1017
1018 NDBGL4(L4_ERR, "%ld: ERROR: idletime[%ld]+earlyhup[%ld] > unitlength[%ld]!",
1019 (long)SECOND, (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time, (long)cd->shorthold_data.unitlen_time);
1020 }
1021 }
1022
1023 /*---------------------------------------------------------------------------*
1024 * variable unit algorithm B channel idle check timeout setup
1025 *---------------------------------------------------------------------------*/
1026 static void
1027 i4b_l4_setup_timeout_var_unit(call_desc_t *cd)
1028 {
1029 /* outgoing call: variable unit idletime check */
1030
1031 /*
1032 * start checking for an idle connect one second before the end of the unit.
1033 * The one second takes into account of rounding due to the driver only
1034 * using the seconds and not the uSeconds of the current time
1035 */
1036 cd->idletime_state = IST_CHECK; /* move directly to the checking state */
1037
1038 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz * (cd->shorthold_data.unitlen_time - 1) );
1039 cd->timeout_active = 1;
1040 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle time - setup to %ld",
1041 (long)SECOND, (long)cd->shorthold_data.unitlen_time);
1042 }
1043
1044
1045 /*---------------------------------------------------------------------------*
1046 * B channel idle check timeout function
1047 *---------------------------------------------------------------------------*/
1048 void
1049 i4b_idle_check(call_desc_t *cd)
1050 {
1051 int s;
1052
1053 if(cd->cdid == CDID_UNUSED)
1054 return;
1055
1056 s = splnet();
1057
1058 /* failsafe */
1059
1060 if(cd->timeout_active == 0)
1061 {
1062 NDBGL4(L4_ERR, "ERROR: timeout_active == 0 !!!");
1063 }
1064 else
1065 {
1066 cd->timeout_active = 0;
1067 }
1068
1069 /* incoming connections, simple idletime check */
1070
1071 if(cd->dir == DIR_INCOMING)
1072 {
1073 if((i4b_get_idletime(cd) + cd->max_idle_time) <= SECOND)
1074 {
1075 struct isdn_l3_driver *d = cd->l3drv;
1076 NDBGL4(L4_TIMO, "%ld: incoming-call, line idle timeout, disconnecting!", (long)SECOND);
1077 d->l3driver->N_DISCONNECT_REQUEST(cd,
1078 (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1079 i4b_l4_idle_timeout_ind(cd);
1080 }
1081 else
1082 {
1083 NDBGL4(L4_TIMO, "%ld: incoming-call, activity, last_active=%ld, max_idle=%ld", (long)SECOND, (long)i4b_get_idletime(cd), (long)cd->max_idle_time);
1084
1085 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
1086 cd->timeout_active = 1;
1087 }
1088 }
1089
1090 /* outgoing connections */
1091
1092 else if(cd->dir == DIR_OUTGOING)
1093 {
1094 switch( cd->shorthold_data.shorthold_algorithm )
1095 {
1096 case SHA_FIXU:
1097 i4b_idle_check_fix_unit( cd );
1098 break;
1099 case SHA_VARU:
1100 i4b_idle_check_var_unit( cd );
1101 break;
1102 default:
1103 NDBGL4(L4_TIMO, "%ld: bad value for shorthold_algorithm of %d",
1104 (long)SECOND, cd->shorthold_data.shorthold_algorithm);
1105 i4b_idle_check_fix_unit( cd );
1106 break;
1107 }
1108 }
1109 splx(s);
1110 }
1111
1112 /*---------------------------------------------------------------------------*
1113 * fixed unit algorithm B channel idle check timeout function
1114 *---------------------------------------------------------------------------*/
1115 static void
1116 i4b_idle_check_fix_unit(call_desc_t *cd)
1117 {
1118 struct isdn_l3_driver *d = cd->l3drv;
1119
1120 /* simple idletime calculation */
1121
1122 if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
1123 {
1124 if((i4b_get_idletime(cd) + cd->shorthold_data.idle_time) <= SECOND)
1125 {
1126 NDBGL4(L4_TIMO, "%ld: outgoing-call-st, idle timeout, disconnecting!", (long)SECOND);
1127 d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1128 i4b_l4_idle_timeout_ind(cd);
1129 }
1130 else
1131 {
1132 NDBGL4(L4_TIMO, "%ld: outgoing-call-st, activity, last_active=%ld, max_idle=%ld",
1133 (long)SECOND, (long)i4b_get_idletime(cd), (long)cd->shorthold_data.idle_time);
1134 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
1135 cd->timeout_active = 1;
1136 }
1137 }
1138
1139 /* full shorthold mode calculation */
1140
1141 else if((cd->shorthold_data.unitlen_time > 0)
1142 && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
1143 {
1144 switch(cd->idletime_state)
1145 {
1146
1147 case IST_NONCHK: /* end of non-check time */
1148
1149 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.idle_time));
1150 cd->idletimechk_start = SECOND;
1151 cd->idletime_state = IST_CHECK;
1152 cd->timeout_active = 1;
1153 NDBGL4(L4_TIMO, "%ld: outgoing-call, idletime check window reached!", (long)SECOND);
1154 break;
1155
1156 case IST_CHECK: /* end of idletime chk */
1157 if((i4b_get_idletime(cd) > cd->idletimechk_start) &&
1158 (i4b_get_idletime(cd) <= SECOND))
1159 { /* activity detected */
1160 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.earlyhup_time));
1161 cd->timeout_active = 1;
1162 cd->idletime_state = IST_SAFE;
1163 NDBGL4(L4_TIMO, "%ld: outgoing-call, activity at %ld, wait earlyhup-end", (long)SECOND, (long)i4b_get_idletime(cd));
1164 }
1165 else
1166 { /* no activity, hangup */
1167 NDBGL4(L4_TIMO, "%ld: outgoing-call, idle timeout, last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1168 d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1169 i4b_l4_idle_timeout_ind(cd);
1170 cd->idletime_state = IST_IDLE;
1171 }
1172 break;
1173
1174 case IST_SAFE: /* end of earlyhup time */
1175
1176 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time+cd->shorthold_data.earlyhup_time)));
1177 cd->timeout_active = 1;
1178 cd->idletime_state = IST_NONCHK;
1179
1180 if(cd->aocd_flag == 0)
1181 {
1182 cd->units_type = CHARGE_CALC;
1183 cd->cunits++;
1184 i4b_l4_charging_ind(cd);
1185 }
1186
1187 NDBGL4(L4_TIMO, "%ld: outgoing-call, earlyhup end, wait for idletime start", (long)SECOND);
1188 break;
1189
1190 default:
1191 NDBGL4(L4_ERR, "outgoing-call: invalid idletime_state value!");
1192 cd->idletime_state = IST_IDLE;
1193 break;
1194 }
1195 }
1196 }
1197
1198 /*---------------------------------------------------------------------------*
1199 * variable unit algorithm B channel idle check timeout function
1200 *---------------------------------------------------------------------------*/
1201 static void
1202 i4b_idle_check_var_unit(call_desc_t *cd)
1203 {
1204 switch(cd->idletime_state)
1205 {
1206
1207 /* see if there has been any activity within the last idle_time seconds */
1208 case IST_CHECK:
1209 if( i4b_get_idletime(cd) > (SECOND - cd->shorthold_data.idle_time))
1210 { /* activity detected */
1211 #if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
1212 cd->idle_timeout_handle =
1213 #endif
1214 /* check again in one second */
1215 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz);
1216 cd->timeout_active = 1;
1217 cd->idletime_state = IST_CHECK;
1218 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - activity at %ld, continuing", (long)SECOND, (long)i4b_get_idletime(cd));
1219 }
1220 else
1221 { /* no activity, hangup */
1222 struct isdn_l3_driver *d = cd->l3drv;
1223 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1224 d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1225 i4b_l4_idle_timeout_ind(cd);
1226 cd->idletime_state = IST_IDLE;
1227 }
1228 break;
1229
1230 default:
1231 NDBGL4(L4_ERR, "outgoing-call: var idle timeout invalid idletime_state value!");
1232 cd->idletime_state = IST_IDLE;
1233 break;
1234 }
1235 }
1236
1237 #endif /* NISDN > 0 */
Cache object: c8f1cfe093000260cdcaadec35747e3c
|