2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *---------------------------------------------------------------------------
27 * i4b_l4.c - kernel interface to userland
28 * -----------------------------------------
30 * $Id: i4b_l4.c,v 1.32 2006/11/16 01:33:49 christos Exp $
34 * last edit-date: [Fri Jan 5 11:33:47 2001]
36 *---------------------------------------------------------------------------*/
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: i4b_l4.c,v 1.31 2006/10/16 12:23:00 pooka Exp $");
46 #include <sys/param.h>
47 #include <sys/kernel.h>
48 #include <sys/systm.h>
52 #include <sys/fcntl.h>
53 #include <sys/socket.h>
56 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
57 #include <sys/callout.h>
61 #include <machine/i4b_debug.h>
62 #include <machine/i4b_ioctl.h>
63 #include <machine/i4b_cause.h>
65 #include <netisdn/i4b_debug.h>
66 #include <netisdn/i4b_ioctl.h>
67 #include <netisdn/i4b_cause.h>
70 #include <netisdn/i4b_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>
77 unsigned int i4b_l4_debug
= L4_DEBUG_DEFAULT
;
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).
84 static SLIST_HEAD(, isdn_l3_driver
) isdnif_list
= SLIST_HEAD_INITIALIZER(isdnif_list
);
85 static int next_isdnif
= 0;
88 * Attach a new L3 driver instance and return its ISDN identifier
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
)
95 int i
, l
, isdnif
= next_isdnif
++;
96 struct isdn_l3_driver
*new_ctrl
;
98 new_ctrl
= malloc(sizeof(*new_ctrl
), M_DEVBUF
, M_WAITOK
|M_ZERO
);
99 SLIST_INSERT_HEAD(&isdnif_list
, new_ctrl
, l3drvq
);
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);
107 new_ctrl
->l3driver
= l3driver
;
108 new_ctrl
->l1_token
= l1_token
;
109 new_ctrl
->isdnif
= isdnif
;
111 new_ctrl
->dl_est
= DL_DOWN
;
112 new_ctrl
->nbch
= nbch
;
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
;
124 * Detach a L3 driver instance
127 isdn_detach_isdnif(struct isdn_l3_driver
*l3drv
)
129 struct isdn_l3_driver
*sc
;
131 int isdnif
= l3drv
->isdnif
;
134 i4b_l4_contr_ev_ind(isdnif
, 0);
135 SLIST_REMOVE(&isdnif_list
, l3drv
, isdn_l3_driver
, l3drvq
);
138 SLIST_FOREACH(sc
, &isdnif_list
, l3drvq
)
139 if (sc
->isdnif
> maxidx
)
141 next_isdnif
= maxidx
+1;
143 free_all_cd_of_isdnif(isdnif
);
147 free(l3drv
, M_DEVBUF
);
148 printf("ISDN %d detached\n", isdnif
);
152 struct isdn_l3_driver
*
153 isdn_find_l3_by_isdnif(int isdnif
)
155 struct isdn_l3_driver
*sc
;
157 SLIST_FOREACH(sc
, &isdnif_list
, l3drvq
)
158 if (sc
->isdnif
== isdnif
)
163 int isdn_count_isdnif(int *misdnif
)
165 struct isdn_l3_driver
*sc
;
169 SLIST_FOREACH(sc
, &isdnif_list
, l3drvq
) {
171 if (sc
->isdnif
> max_isdnif
)
172 max_isdnif
= sc
->isdnif
;
176 *misdnif
= max_isdnif
;
182 isdn_find_softc_by_isdnif(int isdnif
)
184 struct isdn_l3_driver
*sc
= isdn_find_l3_by_isdnif(isdnif
);
188 * XXX - hack: do not return a softc for active cards.
189 * all callers of this expecting l2_softc* results
192 if (sc
->l3driver
->N_DOWNLOAD
)
197 /*---------------------------------------------------------------------------*
199 *---------------------------------------------------------------------------*/
201 i4b_l4_daemon_attached(void)
203 struct isdn_l3_driver
*d
;
206 SLIST_FOREACH(d
, &isdnif_list
, l3drvq
)
208 d
->l3driver
->N_MGMT_COMMAND(d
, CMR_DOPEN
, 0);
213 /*---------------------------------------------------------------------------*
215 *---------------------------------------------------------------------------*/
217 i4b_l4_daemon_detached(void)
219 struct isdn_l3_driver
*d
;
222 SLIST_FOREACH(d
, &isdnif_list
, l3drvq
)
224 d
->l3driver
->N_MGMT_COMMAND(d
, CMR_DCLOSE
, 0);
230 * B-channel layer 4 drivers and their registry.
231 * (Application drivers connecting to a B-channel)
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
);
242 static int next_l4_driver_id
= 0;
244 struct l4_driver_desc
{
245 SLIST_ENTRY(l4_driver_desc
) l4drvq
;
246 char name
[L4DRIVER_NAME_SIZ
];
248 const struct isdn_l4_driver_functions
*driver
;
251 static SLIST_HEAD(, l4_driver_desc
) l4_driver_registry
252 = SLIST_HEAD_INITIALIZER(l4_driver_registry
);
254 int isdn_l4_driver_attach(const char *name
, int units
, const struct isdn_l4_driver_functions
*driver
)
256 struct l4_driver_desc
* new_driver
;
258 new_driver
= malloc(sizeof(struct l4_driver_desc
), M_DEVBUF
,
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
;
269 int isdn_l4_driver_detatch(const char *name
)
271 /* XXX - not yet implemented */
276 const struct isdn_l4_driver_functions
*isdn_l4_find_driver(const char *name
, int unit
)
278 struct l4_driver_desc
* d
;
279 SLIST_FOREACH(d
, &l4_driver_registry
, l4drvq
)
280 if (strcmp(d
->name
, name
) == 0) {
286 int isdn_l4_find_driverid(const char *name
)
288 struct l4_driver_desc
* d
;
289 SLIST_FOREACH(d
, &l4_driver_registry
, l4drvq
)
290 if (strcmp(d
->name
, name
) == 0) {
296 const struct isdn_l4_driver_functions
*isdn_l4_get_driver(int driver_id
, int unit
)
298 struct l4_driver_desc
* d
;
299 SLIST_FOREACH(d
, &l4_driver_registry
, l4drvq
)
300 if (d
->driver_id
== driver_id
) {
306 /*---------------------------------------------------------------------------*
307 * send MSG_PDEACT_IND message to userland
308 *---------------------------------------------------------------------------*/
310 i4b_l4_pdeact(struct isdn_l3_driver
*d
, int numactive
)
316 for(i
=0; i
< num_call_desc
; i
++)
318 if(call_desc
[i
].cdid
!= CDID_UNUSED
&& call_desc
[i
].l3drv
== d
)
322 if(cd
->timeout_active
)
324 STOP_TIMER(cd
->idle_timeout_handle
, i4b_idle_check
, cd
);
327 if (cd
->l4_driver
!= NULL
&& cd
->l4_driver_softc
!= NULL
)
329 (*cd
->l4_driver
->line_disconnected
)(cd
->l4_driver_softc
, (void *)cd
);
330 i4b_unlink_bchandrvr(cd
);
333 if ((cd
->channelid
>= 0)
334 && (cd
->channelid
< d
->nbch
))
335 d
->bch_state
[cd
->channelid
] = BCH_ST_FREE
;
337 cd
->cdid
= CDID_UNUSED
;
341 if((m
= i4b_Dgetmbuf(sizeof(msg_pdeact_ind_t
))) != NULL
)
343 msg_pdeact_ind_t
*md
= (msg_pdeact_ind_t
*)m
->m_data
;
345 md
->header
.type
= MSG_PDEACT_IND
;
346 md
->header
.cdid
= -1;
348 md
->controller
= d
->isdnif
;
349 md
->numactive
= numactive
;
351 i4bputqueue_hipri(m
); /* URGENT !!! */
355 /*---------------------------------------------------------------------------*
356 * send MSG_L12STAT_IND message to userland
357 *---------------------------------------------------------------------------*/
359 i4b_l4_l12stat(struct isdn_l3_driver
*d
, int layer
, int state
)
363 if((m
= i4b_Dgetmbuf(sizeof(msg_l12stat_ind_t
))) != NULL
)
365 msg_l12stat_ind_t
*md
= (msg_l12stat_ind_t
*)m
->m_data
;
367 md
->header
.type
= MSG_L12STAT_IND
;
368 md
->header
.cdid
= -1;
370 md
->controller
= d
->isdnif
;
378 /*---------------------------------------------------------------------------*
379 * send MSG_TEIASG_IND message to userland
380 *---------------------------------------------------------------------------*/
382 i4b_l4_teiasg(struct isdn_l3_driver
*d
, int tei
)
386 if((m
= i4b_Dgetmbuf(sizeof(msg_teiasg_ind_t
))) != NULL
)
388 msg_teiasg_ind_t
*md
= (msg_teiasg_ind_t
*)m
->m_data
;
390 md
->header
.type
= MSG_TEIASG_IND
;
391 md
->header
.cdid
= -1;
393 md
->controller
= d
->isdnif
;
400 /*---------------------------------------------------------------------------*
401 * send MSG_DIALOUT_IND message to userland
402 *---------------------------------------------------------------------------*/
404 i4b_l4_dialout(int driver
, int driver_unit
)
408 if((m
= i4b_Dgetmbuf(sizeof(msg_dialout_ind_t
))) != NULL
)
410 msg_dialout_ind_t
*md
= (msg_dialout_ind_t
*)m
->m_data
;
412 md
->header
.type
= MSG_DIALOUT_IND
;
413 md
->header
.cdid
= -1;
416 md
->driver_unit
= driver_unit
;
422 /*---------------------------------------------------------------------------*
423 * send MSG_DIALOUTNUMBER_IND message to userland
424 *---------------------------------------------------------------------------*/
426 i4b_l4_dialoutnumber(int driver
, int driver_unit
, int cmdlen
, char *cmd
)
430 if((m
= i4b_Dgetmbuf(sizeof(msg_dialoutnumber_ind_t
))) != NULL
)
432 msg_dialoutnumber_ind_t
*md
= (msg_dialoutnumber_ind_t
*)m
->m_data
;
434 md
->header
.type
= MSG_DIALOUTNUMBER_IND
;
435 md
->header
.cdid
= -1;
438 md
->driver_unit
= driver_unit
;
440 if(cmdlen
> TELNO_MAX
)
444 memcpy(md
->cmd
, cmd
, cmdlen
);
449 /*---------------------------------------------------------------------------*
450 * send MSG_NEGOTIATION_COMPL message to userland
451 *---------------------------------------------------------------------------*/
453 i4b_l4_negcomplete(call_desc_t
*cd
)
457 if((m
= i4b_Dgetmbuf(sizeof(msg_negcomplete_ind_t
))) != NULL
)
459 msg_negcomplete_ind_t
*md
= (msg_negcomplete_ind_t
*)m
->m_data
;
461 md
->header
.type
= MSG_NEGCOMP_IND
;
462 md
->header
.cdid
= cd
->cdid
;
468 /*---------------------------------------------------------------------------*
469 * send MSG_IFSTATE_CHANGED_IND message to userland
470 *---------------------------------------------------------------------------*/
472 i4b_l4_ifstate_changed(call_desc_t
*cd
, int new_state
)
476 if((m
= i4b_Dgetmbuf(sizeof(msg_ifstatechg_ind_t
))) != NULL
)
478 msg_ifstatechg_ind_t
*md
= (msg_ifstatechg_ind_t
*)m
->m_data
;
480 md
->header
.type
= MSG_IFSTATE_CHANGED_IND
;
481 md
->header
.cdid
= cd
->cdid
;
482 md
->state
= new_state
;
488 /*---------------------------------------------------------------------------*
489 * send MSG_DRVRDISC_REQ message to userland
490 *---------------------------------------------------------------------------*/
492 i4b_l4_drvrdisc(int cdid
)
496 if((m
= i4b_Dgetmbuf(sizeof(msg_drvrdisc_req_t
))) != NULL
)
498 msg_drvrdisc_req_t
*md
= (msg_drvrdisc_req_t
*)m
->m_data
;
500 md
->header
.type
= MSG_DRVRDISC_REQ
;
501 md
->header
.cdid
= cdid
;
507 /*---------------------------------------------------------------------------*
508 * send MSG_ACCT_IND message to userland
509 *---------------------------------------------------------------------------*/
511 i4b_l4_accounting(int cdid
, int accttype
, int ioutbytes
,
512 int iinbytes
, int ro
, int ri
, int outbytes
, int inbytes
)
516 if((m
= i4b_Dgetmbuf(sizeof(msg_accounting_ind_t
))) != NULL
)
518 msg_accounting_ind_t
*md
= (msg_accounting_ind_t
*)m
->m_data
;
520 md
->header
.type
= MSG_ACCT_IND
;
521 md
->header
.cdid
= cdid
;
523 md
->accttype
= accttype
;
524 md
->ioutbytes
= ioutbytes
;
525 md
->iinbytes
= iinbytes
;
528 md
->outbytes
= outbytes
;
529 md
->inbytes
= inbytes
;
535 /*---------------------------------------------------------------------------*
536 * send MSG_CONNECT_IND message to userland
537 *---------------------------------------------------------------------------*/
539 i4b_l4_connect_ind(call_desc_t
*cd
)
543 if((m
= i4b_Dgetmbuf(sizeof(msg_connect_ind_t
))) != NULL
)
545 msg_connect_ind_t
*mp
= (msg_connect_ind_t
*)m
->m_data
;
547 mp
->header
.type
= MSG_CONNECT_IND
;
548 mp
->header
.cdid
= cd
->cdid
;
550 mp
->controller
= cd
->isdnif
;
551 mp
->channel
= cd
->channelid
;
552 mp
->bprot
= cd
->bprot
;
554 cd
->dir
= DIR_INCOMING
;
556 if(strlen(cd
->dst_telno
) > 0)
557 strlcpy(mp
->dst_telno
, cd
->dst_telno
,
558 sizeof(mp
->dst_telno
));
560 strlcpy(mp
->dst_telno
, TELNO_EMPTY
,
561 sizeof(mp
->dst_telno
));
563 if(strlen(cd
->src_telno
) > 0)
564 strlcpy(mp
->src_telno
, cd
->src_telno
,
565 sizeof(mp
->src_telno
));
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
));
573 strlcpy(mp
->display
, cd
->display
, sizeof(mp
->src_telno
));
575 mp
->scr_ind
= cd
->scr_ind
;
576 mp
->prs_ind
= cd
->prs_ind
;
584 /*---------------------------------------------------------------------------*
585 * send MSG_CONNECT_ACTIVE_IND message to userland
586 *---------------------------------------------------------------------------*/
588 i4b_l4_connect_active_ind(call_desc_t
*cd
)
595 cd
->last_active_time
= cd
->connect_time
= SECOND
;
597 NDBGL4(L4_TIMO
, "last_active/connect_time=%ld", (long)cd
->connect_time
);
599 i4b_link_bchandrvr(cd
);
601 update_controller_leds(cd
->l3drv
);
603 if (cd
->l4_driver
!= NULL
&& cd
->l4_driver_softc
!= NULL
)
604 (*cd
->l4_driver
->line_connected
)(cd
->l4_driver_softc
, cd
);
606 i4b_l4_setup_timeout(cd
);
610 if((m
= i4b_Dgetmbuf(sizeof(msg_connect_active_ind_t
))) != NULL
)
612 msg_connect_active_ind_t
*mp
= (msg_connect_active_ind_t
*)m
->m_data
;
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
));
622 mp
->datetime
[0] = '\0';
627 /*---------------------------------------------------------------------------*
628 * send MSG_DISCONNECT_IND message to userland
629 *---------------------------------------------------------------------------*/
631 i4b_l4_disconnect_ind(call_desc_t
*cd
)
633 struct isdn_l3_driver
*d
;
636 if(cd
->timeout_active
)
637 STOP_TIMER(cd
->idle_timeout_handle
, i4b_idle_check
, cd
);
639 if (cd
->l4_driver
!= NULL
&& cd
->l4_driver_softc
!= NULL
)
641 (*cd
->l4_driver
->line_disconnected
)(cd
->l4_driver_softc
, (void *)cd
);
642 i4b_unlink_bchandrvr(cd
);
647 if((cd
->channelid
>= 0) && (cd
->channelid
< d
->nbch
))
649 d
->bch_state
[cd
->channelid
] = BCH_ST_FREE
;
651 * XXX: don't call l2 function for active cards.
653 if (d
->l3driver
->N_DOWNLOAD
== NULL
)
654 i4b_l2_channel_set_state(d
, cd
->channelid
, BCH_ST_FREE
);
658 /* no error, might be hunting call for callback */
659 NDBGL4(L4_MSG
, "invalid channel %d for ISDN!", cd
->channelid
);
661 update_controller_leds(d
);
663 if((m
= i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t
))) != NULL
)
665 msg_disconnect_ind_t
*mp
= (msg_disconnect_ind_t
*)m
->m_data
;
667 mp
->header
.type
= MSG_DISCONNECT_IND
;
668 mp
->header
.cdid
= cd
->cdid
;
669 mp
->cause
= cd
->cause_in
;
675 /*---------------------------------------------------------------------------*
676 * send MSG_IDLE_TIMEOUT_IND message to userland
677 *---------------------------------------------------------------------------*/
679 i4b_l4_idle_timeout_ind(call_desc_t
*cd
)
683 if((m
= i4b_Dgetmbuf(sizeof(msg_idle_timeout_ind_t
))) != NULL
)
685 msg_idle_timeout_ind_t
*mp
= (msg_idle_timeout_ind_t
*)m
->m_data
;
687 mp
->header
.type
= MSG_IDLE_TIMEOUT_IND
;
688 mp
->header
.cdid
= cd
->cdid
;
694 /*---------------------------------------------------------------------------*
695 * send MSG_CHARGING_IND message to userland
696 *---------------------------------------------------------------------------*/
698 i4b_l4_charging_ind(call_desc_t
*cd
)
702 if((m
= i4b_Dgetmbuf(sizeof(msg_charging_ind_t
))) != NULL
)
704 msg_charging_ind_t
*mp
= (msg_charging_ind_t
*)m
->m_data
;
706 mp
->header
.type
= MSG_CHARGING_IND
;
707 mp
->header
.cdid
= cd
->cdid
;
708 mp
->units_type
= cd
->units_type
;
710 /*XXX*/ if(mp
->units_type
== CHARGE_CALC
)
711 mp
->units
= cd
->cunits
;
713 mp
->units
= cd
->units
;
719 /*---------------------------------------------------------------------------*
720 * send MSG_STATUS_IND message to userland
721 *---------------------------------------------------------------------------*/
723 i4b_l4_status_ind(call_desc_t
*cd
)
727 /*---------------------------------------------------------------------------*
728 * send MSG_ALERT_IND message to userland
729 *---------------------------------------------------------------------------*/
731 i4b_l4_alert_ind(call_desc_t
*cd
)
735 if((m
= i4b_Dgetmbuf(sizeof(msg_alert_ind_t
))) != NULL
)
737 msg_alert_ind_t
*mp
= (msg_alert_ind_t
*)m
->m_data
;
739 mp
->header
.type
= MSG_ALERT_IND
;
740 mp
->header
.cdid
= cd
->cdid
;
746 /*---------------------------------------------------------------------------*
747 * send MSG_INFO_IND message to userland
748 *---------------------------------------------------------------------------*/
750 i4b_l4_info_ind(call_desc_t
*cd
)
754 /*---------------------------------------------------------------------------*
755 * send MSG_INFO_IND message to userland
756 *---------------------------------------------------------------------------*/
758 i4b_l4_proceeding_ind(call_desc_t
*cd
)
762 if((m
= i4b_Dgetmbuf(sizeof(msg_proceeding_ind_t
))) != NULL
)
764 msg_proceeding_ind_t
*mp
= (msg_proceeding_ind_t
*)m
->m_data
;
766 mp
->header
.type
= MSG_PROCEEDING_IND
;
767 mp
->header
.cdid
= cd
->cdid
;
768 mp
->controller
= cd
->isdnif
;
769 mp
->channel
= cd
->channelid
;
774 /*---------------------------------------------------------------------------*
775 * send MSG_PACKET_IND message to userland
776 *---------------------------------------------------------------------------*/
778 i4b_l4_packet_ind(int driver
, int driver_unit
, int dir
, struct mbuf
*pkt
)
781 int len
= pkt
->m_pkthdr
.len
;
782 unsigned char *ip
= pkt
->m_data
;
784 if((m
= i4b_Dgetmbuf(sizeof(msg_packet_ind_t
))) != NULL
)
786 msg_packet_ind_t
*mp
= (msg_packet_ind_t
*)m
->m_data
;
788 mp
->header
.type
= MSG_PACKET_IND
;
789 mp
->header
.cdid
= -1;
791 mp
->driver_unit
= driver_unit
;
793 memcpy(mp
->pktdata
, ip
,
794 len
<MAX_PACKET_LOG
? len
: MAX_PACKET_LOG
);
799 /*---------------------------------------------------------------------------*
800 * send MSG_CONTR_EV_IND message to userland
801 *---------------------------------------------------------------------------*/
803 i4b_l4_contr_ev_ind(int controller
, int attach
)
807 if((m
= i4b_Dgetmbuf(sizeof(msg_ctrl_ev_ind_t
))) != NULL
)
809 msg_ctrl_ev_ind_t
*ev
= (msg_ctrl_ev_ind_t
*)m
->m_data
;
811 ev
->header
.type
= MSG_CONTR_EV_IND
;
812 ev
->header
.cdid
= -1;
813 ev
->controller
= controller
;
819 /*---------------------------------------------------------------------------*
820 * link a driver(unit) to a B-channel(controller,unit,channel)
821 *---------------------------------------------------------------------------*/
823 i4b_link_bchandrvr(call_desc_t
*cd
)
825 struct isdn_l3_driver
*d
= cd
->l3drv
;
827 if (d
== NULL
|| d
->l3driver
== NULL
|| d
->l3driver
->get_linktab
== NULL
)
833 cd
->ilt
= d
->l3driver
->get_linktab(d
->l1_token
,
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
);
840 cd
->l4_driver_softc
= NULL
;
842 if(cd
->l4_driver
== NULL
|| cd
->l4_driver_softc
== NULL
|| cd
->ilt
== NULL
)
845 if (d
->l3driver
->set_l4_driver
!= NULL
)
847 d
->l3driver
->set_l4_driver(d
->l1_token
,
848 cd
->channelid
, cd
->l4_driver
, cd
->l4_driver_softc
);
851 cd
->l4_driver
->set_linktab(cd
->l4_driver_softc
, cd
->ilt
);
853 /* activate B channel */
855 (*cd
->ilt
->bchannel_driver
->bch_config
)(cd
->ilt
->l1token
, cd
->ilt
->channel
, cd
->bprot
, 1);
860 /*---------------------------------------------------------------------------*
861 * unlink a driver(unit) from a B-channel(controller,unit,channel)
862 *---------------------------------------------------------------------------*/
864 i4b_unlink_bchandrvr(call_desc_t
*cd
)
866 struct isdn_l3_driver
*d
= cd
->l3drv
;
869 * XXX - what's this *cd manipulation for? Shouldn't we
870 * close the bchannel driver first and then just set ilt to NULL
873 if (d
== NULL
|| d
->l3driver
== NULL
|| d
->l3driver
->get_linktab
== NULL
)
880 cd
->ilt
= d
->l3driver
->get_linktab(
881 d
->l1_token
, cd
->channelid
);
884 /* deactivate B channel */
886 (*cd
->ilt
->bchannel_driver
->bch_config
)(cd
->ilt
->l1token
, cd
->ilt
->channel
, cd
->bprot
, 0);
889 /*---------------------------------------------------------------------------
891 How shorthold mode works for OUTGOING connections
892 =================================================
894 |<---- unchecked-window ------->|<-checkwindow->|<-safetywindow>|
896 idletime_state: IST_NONCHK IST_CHECK IST_SAFE
899 time>>+-------------------------------+---------------+---------------+-...
901 | |<--idle_time-->|<--earlyhup--->|
902 |<-----------------------unitlen------------------------------->|
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
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.
922 How shorthold mode works for INCOMING connections
923 =================================================
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
929 ---------------------------------------------------------------------------*/
932 i4b_get_idletime(call_desc_t
*cd
)
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
;
940 /*---------------------------------------------------------------------------*
941 * B channel idle check timeout setup
942 *---------------------------------------------------------------------------*/
944 i4b_l4_setup_timeout(call_desc_t
*cd
)
946 NDBGL4(L4_TIMO
, "%ld: direction %d, shorthold algorithm %d",
947 (long)SECOND
, cd
->dir
, cd
->shorthold_data
.shorthold_algorithm
);
949 cd
->timeout_active
= 0;
950 cd
->idletime_state
= IST_IDLE
;
952 if((cd
->dir
== DIR_INCOMING
) && (cd
->max_idle_time
> 0))
954 /* incoming call: simple max idletime check */
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
);
960 else if((cd
->dir
== DIR_OUTGOING
) && (cd
->shorthold_data
.idle_time
> 0))
962 switch( cd
->shorthold_data
.shorthold_algorithm
)
964 default: /* fall into the old fix algorithm */
966 i4b_l4_setup_timeout_fix_unit( cd
);
970 i4b_l4_setup_timeout_var_unit( cd
);
976 NDBGL4(L4_TIMO
, "no idle_timeout configured");
980 /*---------------------------------------------------------------------------*
981 * fixed unit algorithm B channel idle check timeout setup
982 *---------------------------------------------------------------------------*/
984 i4b_l4_setup_timeout_fix_unit(call_desc_t
*cd
)
988 if((cd
->shorthold_data
.idle_time
> 0) && (cd
->shorthold_data
.unitlen_time
== 0))
990 /* outgoing call: simple max idletime check */
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
);
997 else if((cd
->shorthold_data
.unitlen_time
> 0) && (cd
->shorthold_data
.unitlen_time
> (cd
->shorthold_data
.idle_time
+ cd
->shorthold_data
.earlyhup_time
)))
999 /* outgoing call: full shorthold mode check */
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
)));
1007 if(cd
->aocd_flag
== 0)
1009 cd
->units_type
= CHARGE_CALC
;
1011 i4b_l4_charging_ind(cd
);
1016 /* parms somehow got wrong .. */
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
);
1023 /*---------------------------------------------------------------------------*
1024 * variable unit algorithm B channel idle check timeout setup
1025 *---------------------------------------------------------------------------*/
1027 i4b_l4_setup_timeout_var_unit(call_desc_t
*cd
)
1029 /* outgoing call: variable unit idletime check */
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
1036 cd
->idletime_state
= IST_CHECK
; /* move directly to the checking state */
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
);
1045 /*---------------------------------------------------------------------------*
1046 * B channel idle check timeout function
1047 *---------------------------------------------------------------------------*/
1049 i4b_idle_check(call_desc_t
*cd
)
1053 if(cd
->cdid
== CDID_UNUSED
)
1060 if(cd
->timeout_active
== 0)
1062 NDBGL4(L4_ERR
, "ERROR: timeout_active == 0 !!!");
1066 cd
->timeout_active
= 0;
1069 /* incoming connections, simple idletime check */
1071 if(cd
->dir
== DIR_INCOMING
)
1073 if((i4b_get_idletime(cd
) + cd
->max_idle_time
) <= SECOND
)
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
);
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
);
1085 START_TIMER(cd
->idle_timeout_handle
, i4b_idle_check
, cd
, hz
/2);
1086 cd
->timeout_active
= 1;
1090 /* outgoing connections */
1092 else if(cd
->dir
== DIR_OUTGOING
)
1094 switch( cd
->shorthold_data
.shorthold_algorithm
)
1097 i4b_idle_check_fix_unit( cd
);
1100 i4b_idle_check_var_unit( cd
);
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
);
1112 /*---------------------------------------------------------------------------*
1113 * fixed unit algorithm B channel idle check timeout function
1114 *---------------------------------------------------------------------------*/
1116 i4b_idle_check_fix_unit(call_desc_t
*cd
)
1118 struct isdn_l3_driver
*d
= cd
->l3drv
;
1120 /* simple idletime calculation */
1122 if((cd
->shorthold_data
.idle_time
> 0) && (cd
->shorthold_data
.unitlen_time
== 0))
1124 if((i4b_get_idletime(cd
) + cd
->shorthold_data
.idle_time
) <= SECOND
)
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
);
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;
1139 /* full shorthold mode calculation */
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
)))
1144 switch(cd
->idletime_state
)
1147 case IST_NONCHK
: /* end of non-check time */
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
);
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
));
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
;
1174 case IST_SAFE
: /* end of earlyhup time */
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
;
1180 if(cd
->aocd_flag
== 0)
1182 cd
->units_type
= CHARGE_CALC
;
1184 i4b_l4_charging_ind(cd
);
1187 NDBGL4(L4_TIMO
, "%ld: outgoing-call, earlyhup end, wait for idletime start", (long)SECOND
);
1191 NDBGL4(L4_ERR
, "outgoing-call: invalid idletime_state value!");
1192 cd
->idletime_state
= IST_IDLE
;
1198 /*---------------------------------------------------------------------------*
1199 * variable unit algorithm B channel idle check timeout function
1200 *---------------------------------------------------------------------------*/
1202 i4b_idle_check_var_unit(call_desc_t
*cd
)
1204 switch(cd
->idletime_state
)
1207 /* see if there has been any activity within the last idle_time seconds */
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
=
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
));
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
;
1231 NDBGL4(L4_ERR
, "outgoing-call: var idle timeout invalid idletime_state value!");
1232 cd
->idletime_state
= IST_IDLE
;
1237 #endif /* NISDN > 0 */