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