2 * Copyright (c) 1997, 2001 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 daemon - message from kernel handling routines
28 * --------------------------------------------------
30 * $Id: msghdl.c,v 1.78 2000/09/21 11:29:51 hm Exp $
32 * $FreeBSD: src/usr.sbin/i4b/isdnd/msghdl.c,v 1.6.2.3 2001/12/16 15:13:38 hm Exp $
33 * $DragonFly: src/usr.sbin/i4b/isdnd/msghdl.c,v 1.3 2004/02/10 02:59:42 rob Exp $
35 * last edit-date: [Thu Sep 21 11:11:48 2000]
37 *---------------------------------------------------------------------------*/
41 #include <sys/socket.h>
43 #include <net/if_types.h>
45 #if defined(__DragonFly__)
46 #include <net/if_var.h>
49 #include <netinet/in.h>
50 #include <netinet/in_systm.h>
51 #include <netinet/in_var.h>
52 #include <netinet/ip.h>
53 #include <netinet/tcp.h>
54 #include <netinet/udp.h>
55 #include <netinet/ip_icmp.h>
57 /*---------------------------------------------------------------------------*
58 * handle incoming CONNECT_IND (=SETUP) message
59 *---------------------------------------------------------------------------*/
61 msg_connect_ind(msg_connect_ind_t
*mp
)
64 char *src_tela
= "ERROR-src_tela";
65 char *dst_tela
= "ERROR-dst_tela";
67 #define SRC (aliasing == 0 ? mp->src_telno : src_tela)
68 #define DST (aliasing == 0 ? mp->dst_telno : dst_tela)
72 src_tela
= get_alias(mp
->src_telno
);
73 dst_tela
= get_alias(mp
->dst_telno
);
76 if((cep
= find_matching_entry_incoming(mp
)) == NULL
)
78 /* log message generated in find_matching_entry_incoming() */
79 sendm_connect_resp(NULL
, mp
->header
.cdid
, SETUP_RESP_DNTCRE
, 0);
80 handle_scrprs(mp
->header
.cdid
, mp
->scr_ind
, mp
->prs_ind
, SRC
);
84 if(cep
->cdid
!= CDID_UNUSED
&& cep
->cdid
!= CDID_RESERVED
)
87 * This is an incoming call on a number we just dialed out.
88 * Stop our dial-out and accept the incoming call.
90 if(cep
->saved_call
.cdid
!= CDID_UNUSED
&&
91 cep
->saved_call
.cdid
!= CDID_RESERVED
)
95 /* disconnect old, not new */
98 cep
->cdid
= cep
->saved_call
.cdid
;
99 sendm_disconnect_req(cep
, (CAUSET_I4B
<< 8) | CAUSE_I4B_NORMAL
);
103 * Shortcut the state machine and mark this
106 /* XXX */ cep
->state
= ST_IDLE
; /* this is an invalid */
108 /* so no next_state() */
109 /* we have to wait here for an incoming */
110 /* disconnect message !!! (-hm) */
114 if(cep
->inout
== DIR_OUTONLY
)
116 dolog(LL_CHD
, "%05d %s incoming call from %s to %s not allowed by configuration!",
117 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
118 sendm_connect_resp(NULL
, mp
->header
.cdid
, SETUP_RESP_DNTCRE
, 0);
119 handle_scrprs(mp
->header
.cdid
, mp
->scr_ind
, mp
->prs_ind
, SRC
);
124 cep
->last_charge
= 0;
126 switch(cep
->dialin_reaction
)
129 dolog(LL_CHD
, "%05d %s accepting: incoming call from %s to %s",
130 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
131 decr_free_channels(mp
->controller
);
132 next_state(cep
, EV_MCI
);
136 dolog(LL_CHD
, "%05d %s rejecting: incoming call from %s to %s",
137 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
138 sendm_connect_resp(cep
, mp
->header
.cdid
, SETUP_RESP_REJECT
,
139 (CAUSET_I4B
<< 8) | CAUSE_I4B_REJECT
);
140 cep
->cdid
= CDID_UNUSED
;
144 dolog(LL_CHD
, "%05d %s ignoring: incoming call from %s to %s",
145 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
146 sendm_connect_resp(NULL
, mp
->header
.cdid
, SETUP_RESP_DNTCRE
, 0);
147 cep
->cdid
= CDID_UNUSED
;
151 decr_free_channels(mp
->controller
);
156 dolog(LL_CHD
, "%05d %s alerting: incoming call from %s to %s (%s)",
157 mp
->header
.cdid
, cep
->name
, SRC
, DST
, mp
->display
);
161 dolog(LL_CHD
, "%05d %s alerting: incoming call from %s to %s",
162 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
164 next_state(cep
, EV_ALRT
);
170 dolog(LL_CHD
, "%05d %s answering: incoming call from %s to %s (%s)",
171 mp
->header
.cdid
, cep
->name
, SRC
, DST
, mp
->display
);
175 dolog(LL_CHD
, "%05d %s answering: incoming call from %s to %s",
176 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
178 next_state(cep
, EV_MCI
);
185 /*XXX reserve channel ??? */ decr_free_channels(mp
->controller
);
187 if(cep
->cdid
== CDID_RESERVED
)
189 dolog(LL_CHD
, "%05d %s reserved: incoming call from %s to %s",
190 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
191 sendm_connect_resp(cep
, mp
->header
.cdid
, SETUP_RESP_REJECT
,
193 (CAUSET_I4B
<< 8) | CAUSE_I4B_NORMAL
);
195 (CAUSET_I4B
<< 8) | CAUSE_I4B_REJECT
);
197 /* no state change */
201 sendm_connect_resp(cep
, mp
->header
.cdid
, SETUP_RESP_REJECT
,
203 (CAUSET_I4B
<< 8) | CAUSE_I4B_NORMAL
);
205 (CAUSET_I4B
<< 8) | CAUSE_I4B_REJECT
);
207 if(cep
->budget_callbackperiod
&& cep
->budget_callbackncalls
)
209 cep
->budget_callback_req
++;
210 cep
->budget_calltype
= 0;
211 if(cep
->budget_callbackncalls_cnt
== 0)
213 dolog(LL_CHD
, "%05d %s no budget: call from %s to %s",
214 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
215 cep
->cdid
= CDID_UNUSED
;
216 cep
->budget_callback_rej
++;
221 cep
->budget_calltype
= BUDGET_TYPE_CBACK
;
225 dolog(LL_CHD
, "%05d %s callback: incoming call from %s to %s",
226 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
228 cep
->last_release_time
= time(NULL
);
229 cep
->cdid
= CDID_RESERVED
;
230 next_state(cep
, EV_CBRQ
);
235 dolog(LL_WRN
, "msg_connect_ind: unknown response type, tx SETUP_RESP_DNTCRE");
236 sendm_connect_resp(NULL
, mp
->header
.cdid
, SETUP_RESP_DNTCRE
, 0);
239 handle_scrprs(mp
->header
.cdid
, mp
->scr_ind
, mp
->prs_ind
, SRC
);
244 /*---------------------------------------------------------------------------*
245 * handle incoming CONNECT_ACTIVE_IND message
246 *---------------------------------------------------------------------------*/
248 msg_connect_active_ind(msg_connect_active_ind_t
*mp
)
253 if((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
255 dolog(LL_WRN
, "msg_connect_active_ind: cdid not found!");
259 cep
->isdncontrollerused
= mp
->controller
;
260 cep
->isdnchannelused
= mp
->channel
;
262 cep
->aoc_now
= cep
->connect_time
= time(NULL
);
265 cep
->aoc_valid
= AOC_INVALID
;
267 cep
->local_disconnect
= DISCON_REM
;
269 cep
->inbytes
= INVALID
;
270 cep
->outbytes
= INVALID
;
273 device
= bdrivername(cep
->usrdevicename
);
275 /* set the B-channel to active */
277 if((set_channel_busy(cep
->isdncontrollerused
, cep
->isdnchannelused
)) == ERROR
)
278 dolog(LL_ERR
, "msg_connect_active_ind: set_channel_busy failed!");
280 if(cep
->direction
== DIR_OUT
)
282 dolog(LL_CHD
, "%05d %s outgoing call active (ctl %d, ch %d, %s%d)",
283 cep
->cdid
, cep
->name
,
284 cep
->isdncontrollerused
, cep
->isdnchannelused
,
285 bdrivername(cep
->usrdevicename
), cep
->usrdeviceunit
);
287 if(cep
->budget_calltype
)
289 if(cep
->budget_calltype
== BUDGET_TYPE_CBACK
)
291 cep
->budget_callback_done
++;
292 cep
->budget_callbackncalls_cnt
--;
293 DBGL(DL_BDGT
, (dolog(LL_DBG
, "%s: new cback-budget = %d",
294 cep
->name
, cep
->budget_callbackncalls_cnt
)));
295 if(cep
->budget_callbacks_file
!= NULL
)
296 upd_callstat_file(cep
->budget_callbacks_file
, cep
->budget_callbacksfile_rotate
);
298 else if(cep
->budget_calltype
== BUDGET_TYPE_COUT
)
300 cep
->budget_callout_done
++;
301 cep
->budget_calloutncalls_cnt
--;
302 DBGL(DL_BDGT
, (dolog(LL_DBG
, "%s: new cout-budget = %d",
303 cep
->name
, cep
->budget_calloutncalls_cnt
)));
304 if(cep
->budget_callouts_file
!= NULL
)
305 upd_callstat_file(cep
->budget_callouts_file
, cep
->budget_calloutsfile_rotate
);
307 cep
->budget_calltype
= 0;
312 dolog(LL_CHD
, "%05d %s incoming call active (ctl %d, ch %d, %s%d)",
313 cep
->cdid
, cep
->name
,
314 cep
->isdncontrollerused
, cep
->isdnchannelused
,
315 bdrivername(cep
->usrdevicename
), cep
->usrdeviceunit
);
320 display_connect(cep
);
322 #ifdef I4B_EXTERNAL_MONITOR
323 if(do_monitor
&& accepted
)
324 monitor_evnt_connect(cep
);
327 if(isdntime
&& (mp
->datetime
[0] != '\0'))
329 dolog(LL_DMN
, "date/time from exchange = %s", mp
->datetime
);
332 next_state(cep
, EV_MCAI
);
335 /*---------------------------------------------------------------------------*
336 * handle incoming PROCEEDING_IND message
337 *---------------------------------------------------------------------------*/
339 msg_proceeding_ind(msg_proceeding_ind_t
*mp
)
343 if((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
345 dolog(LL_WRN
, "msg_proceeding_ind: cdid not found!");
349 cep
->isdncontrollerused
= mp
->controller
;
350 cep
->isdnchannelused
= mp
->channel
;
352 /* set the B-channels active */
354 if((set_channel_busy(cep
->isdncontrollerused
, cep
->isdnchannelused
)) == ERROR
)
355 dolog(LL_ERR
, "msg_proceeding_ind: set_channel_busy failed!");
357 dolog(LL_CHD
, "%05d %s outgoing call proceeding (ctl %d, ch %d)",
358 cep
->cdid
, cep
->name
,
359 cep
->isdncontrollerused
, cep
->isdnchannelused
);
362 /*---------------------------------------------------------------------------*
363 * handle incoming ALERT_IND message
364 *---------------------------------------------------------------------------*/
366 msg_alert_ind(msg_alert_ind_t
*mp
)
370 if((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
372 dolog(LL_WRN
, "msg_alert_ind: cdid not found!");
376 dolog(LL_CHD
, "%05d %s incoming alert", cep
->cdid
, cep
->name
);
380 /*---------------------------------------------------------------------------*
381 * handle incoming L12STAT_IND message
382 *---------------------------------------------------------------------------*/
384 msg_l12stat_ind(msg_l12stat_ind_t
*ml
)
386 if((ml
->controller
< 0) || (ml
->controller
>= ncontroller
))
388 dolog(LL_ERR
, "msg_l12stat_ind: invalid controller number [%d]!", ml
->controller
);
394 display_l12stat(ml
->controller
, ml
->layer
, ml
->state
);
396 #ifdef I4B_EXTERNAL_MONITOR
397 if(do_monitor
&& accepted
)
398 monitor_evnt_l12stat(ml
->controller
, ml
->layer
, ml
->state
);
401 DBGL(DL_CNST
, (dolog(LL_DBG
, "msg_l12stat_ind: unit %d, layer %d, state %d",
402 ml
->controller
, ml
->layer
, ml
->state
)));
404 if(ml
->layer
== LAYER_ONE
)
406 if(ml
->state
== LAYER_IDLE
)
407 isdn_ctrl_tab
[ml
->controller
].l2stat
= ml
->state
;
408 isdn_ctrl_tab
[ml
->controller
].l1stat
= ml
->state
;
410 else if(ml
->layer
== LAYER_TWO
)
412 if(ml
->state
== LAYER_ACTIVE
)
413 isdn_ctrl_tab
[ml
->controller
].l1stat
= ml
->state
;
414 isdn_ctrl_tab
[ml
->controller
].l2stat
= ml
->state
;
418 dolog(LL_ERR
, "msg_l12stat_ind: invalid layer number [%d]!", ml
->layer
);
422 /*---------------------------------------------------------------------------*
423 * handle incoming TEIASG_IND message
424 *---------------------------------------------------------------------------*/
426 msg_teiasg_ind(msg_teiasg_ind_t
*mt
)
428 if((mt
->controller
< 0) || (mt
->controller
>= ncontroller
))
430 dolog(LL_ERR
, "msg_teiasg_ind: invalid controller number [%d]!", mt
->controller
);
436 display_tei(mt
->controller
, mt
->tei
);
438 #ifdef I4B_EXTERNAL_MONITOR
439 if(do_monitor
&& accepted
)
440 monitor_evnt_tei(mt
->controller
, mt
->tei
);
443 DBGL(DL_CNST
, (dolog(LL_DBG
, "msg_teiasg_ind: unit %d, tei = %d",
444 mt
->controller
, mt
->tei
)));
446 isdn_ctrl_tab
[mt
->controller
].tei
= mt
->tei
;
449 /*---------------------------------------------------------------------------*
450 * handle incoming PDEACT_IND message
451 *---------------------------------------------------------------------------*/
453 msg_pdeact_ind(msg_pdeact_ind_t
*md
)
456 int ctrl
= md
->controller
;
462 display_l12stat(ctrl
, LAYER_ONE
, LAYER_IDLE
);
463 display_l12stat(ctrl
, LAYER_TWO
, LAYER_IDLE
);
464 display_tei(ctrl
, -1);
467 #ifdef I4B_EXTERNAL_MONITOR
468 if(do_monitor
&& accepted
)
470 monitor_evnt_l12stat(ctrl
, LAYER_ONE
, LAYER_IDLE
);
471 monitor_evnt_l12stat(ctrl
, LAYER_TWO
, LAYER_IDLE
);
472 monitor_evnt_tei(ctrl
, -1);
476 DBGL(DL_CNST
, (dolog(LL_DBG
, "msg_pdeact_ind: unit %d, persistent deactivation", ctrl
)));
478 isdn_ctrl_tab
[ctrl
].l1stat
= LAYER_IDLE
;
479 isdn_ctrl_tab
[ctrl
].l2stat
= LAYER_IDLE
;
480 isdn_ctrl_tab
[ctrl
].tei
= -1;
482 for(i
=0; i
< nentries
; i
++)
484 if((cfg_entry_tab
[i
].cdid
!= CDID_UNUSED
) &&
485 (cfg_entry_tab
[i
].isdncontrollerused
== ctrl
))
487 cep
= &cfg_entry_tab
[i
];
489 if(cep
->cdid
== CDID_RESERVED
)
491 cep
->state
= ST_IDLE
;
492 cep
->cdid
= CDID_UNUSED
;
496 cep
->cdid
= CDID_UNUSED
;
498 cep
->last_release_time
= time(NULL
);
500 SET_CAUSE_TYPE(cep
->disc_cause
, CAUSET_I4B
);
501 SET_CAUSE_VAL(cep
->disc_cause
, CAUSE_I4B_L1ERROR
);
503 if(cep
->direction
== DIR_OUT
)
505 dolog(LL_CHD
, "%05d %s outgoing call disconnected (local)",
506 cep
->cdid
, cep
->name
);
510 dolog(LL_CHD
, "%05d %s incoming call disconnected (local)",
511 cep
->cdid
, cep
->name
);
514 dolog(LL_CHD
, "%05d %s cause %s",
515 cep
->cdid
, cep
->name
, print_i4b_cause(cep
->disc_cause
));
518 if(do_fullscreen
&& (cep
->connect_time
> 0))
519 display_disconnect(cep
);
521 #ifdef I4B_EXTERNAL_MONITOR
522 if(do_monitor
&& accepted
)
523 monitor_evnt_disconnect(cep
);
526 if(cep
->disconnectprog
)
527 exec_connect_prog(cep
, cep
->disconnectprog
, 1);
529 if(cep
->connect_time
> 0)
531 if(cep
->direction
== DIR_OUT
)
533 dolog(LL_CHD
, "%05d %s charging: %d units, %d seconds",
534 cep
->cdid
, cep
->name
, cep
->charge
,
535 (int)difftime(time(NULL
), cep
->connect_time
));
539 dolog(LL_CHD
, "%05d %s connected %d seconds",
540 cep
->cdid
, cep
->name
,
541 (int)difftime(time(NULL
), cep
->connect_time
));
544 if((cep
->inbytes
!= INVALID
) && (cep
->outbytes
!= INVALID
))
546 if((cep
->ioutbytes
!= cep
->outbytes
) ||
547 (cep
->iinbytes
!= cep
->inbytes
))
549 dolog(LL_CHD
, "%05d %s accounting: in %d, out %d (in %d, out %d)",
550 cep
->cdid
, cep
->name
,
551 cep
->inbytes
, cep
->outbytes
,
552 cep
->iinbytes
, cep
->ioutbytes
);
556 dolog(LL_CHD
, "%05d %s accounting: in %d, out %d",
557 cep
->cdid
, cep
->name
,
558 cep
->inbytes
, cep
->outbytes
);
563 if(useacctfile
&& (cep
->connect_time
> 0))
566 char logdatetime
[41];
569 con_secs
= difftime(time(NULL
), cep
->connect_time
);
571 tp
= localtime(&cep
->connect_time
);
573 strftime(logdatetime
,40,I4B_TIME_FORMAT
,tp
);
575 if(cep
->inbytes
!= INVALID
&& cep
->outbytes
!= INVALID
)
577 fprintf(acctfp
, "%s - %s %s %d (%d) (%d/%d)\n",
578 logdatetime
, getlogdatetime(),
579 cep
->name
, cep
->charge
, con_secs
,
580 cep
->inbytes
, cep
->outbytes
);
584 fprintf(acctfp
, "%s - %s %s %d (%d)\n",
585 logdatetime
, getlogdatetime(),
586 cep
->name
, cep
->charge
, con_secs
);
590 /* set the B-channel inactive */
592 if((set_channel_idle(cep
->isdncontrollerused
, cep
->isdnchannelused
)) == ERROR
)
593 dolog(LL_ERR
, "msg_pdeact_ind: set_channel_idle failed!");
595 incr_free_channels(cep
->isdncontrollerused
);
597 cep
->connect_time
= 0;
599 cep
->state
= ST_IDLE
;
604 /*---------------------------------------------------------------------------*
605 * handle incoming NEGCOMP_IND message
606 *---------------------------------------------------------------------------*/
608 msg_negcomplete_ind(msg_negcomplete_ind_t
*mp
)
612 if((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
614 dolog(LL_WRN
, "msg_negcomp_ind: cdid not found");
619 exec_connect_prog(cep
, cep
->connectprog
, 0);
622 /*---------------------------------------------------------------------------*
623 * handle incoming IFSTATE_CHANGED indication
624 *---------------------------------------------------------------------------*/
626 msg_ifstatechg_ind(msg_ifstatechg_ind_t
*mp
)
631 if((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
633 dolog(LL_WRN
, "msg_negcomp_ind: cdid not found");
637 device
= bdrivername(cep
->usrdevicename
);
638 dolog(LL_DBG
, "%s%d: switched to state %d", device
, cep
->usrdeviceunit
, mp
->state
);
641 /*---------------------------------------------------------------------------*
642 * handle incoming DISCONNECT_IND message
643 *---------------------------------------------------------------------------*/
645 msg_disconnect_ind(msg_disconnect_ind_t
*mp
)
649 if((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
651 dolog(LL_WRN
, "msg_disconnect_ind: cdid not found");
655 /* is this an aborted out-call prematurely called back? */
656 if (cep
->saved_call
.cdid
== mp
->header
.cdid
)
658 DBGL(DL_CNST
, (dolog(LL_DBG
, "aborted outcall %05d disconnected",
660 cep
->saved_call
.cdid
= CDID_UNUSED
;
662 set_channel_idle(cep
->saved_call
.controller
, cep
->saved_call
.channel
);
664 incr_free_channels(cep
->saved_call
.controller
);
668 cep
->last_release_time
= time(NULL
);
669 cep
->disc_cause
= mp
->cause
;
671 if(cep
->direction
== DIR_OUT
)
673 dolog(LL_CHD
, "%05d %s outgoing call disconnected %s",
674 cep
->cdid
, cep
->name
,
675 cep
->local_disconnect
== DISCON_LOC
?
676 "(local)" : "(remote)");
680 dolog(LL_CHD
, "%05d %s incoming call disconnected %s",
681 cep
->cdid
, cep
->name
,
682 cep
->local_disconnect
== DISCON_LOC
?
683 "(local)" : "(remote)");
686 dolog(LL_CHD
, "%05d %s cause %s",
687 cep
->cdid
, cep
->name
, print_i4b_cause(mp
->cause
));
690 if(do_fullscreen
&& (cep
->connect_time
> 0))
691 display_disconnect(cep
);
693 #ifdef I4B_EXTERNAL_MONITOR
694 if(do_monitor
&& accepted
)
695 monitor_evnt_disconnect(cep
);
698 if(cep
->disconnectprog
)
699 exec_connect_prog(cep
, cep
->disconnectprog
, 1);
701 if(cep
->connect_time
> 0)
703 if(cep
->direction
== DIR_OUT
)
705 dolog(LL_CHD
, "%05d %s charging: %d units, %d seconds",
706 cep
->cdid
, cep
->name
, cep
->charge
,
707 (int)difftime(time(NULL
), cep
->connect_time
));
711 dolog(LL_CHD
, "%05d %s connected %d seconds",
712 cep
->cdid
, cep
->name
,
713 (int)difftime(time(NULL
), cep
->connect_time
));
716 if((cep
->inbytes
!= INVALID
) && (cep
->outbytes
!= INVALID
))
718 if((cep
->ioutbytes
!= cep
->outbytes
) ||
719 (cep
->iinbytes
!= cep
->inbytes
))
721 dolog(LL_CHD
, "%05d %s accounting: in %d, out %d (in %d, out %d)",
722 cep
->cdid
, cep
->name
,
723 cep
->inbytes
, cep
->outbytes
,
724 cep
->iinbytes
, cep
->ioutbytes
);
728 dolog(LL_CHD
, "%05d %s accounting: in %d, out %d",
729 cep
->cdid
, cep
->name
,
730 cep
->inbytes
, cep
->outbytes
);
735 if(useacctfile
&& (cep
->connect_time
> 0))
738 char logdatetime
[41];
741 con_secs
= difftime(time(NULL
), cep
->connect_time
);
743 tp
= localtime(&cep
->connect_time
);
745 strftime(logdatetime
,40,I4B_TIME_FORMAT
,tp
);
747 if(cep
->inbytes
!= INVALID
&& cep
->outbytes
!= INVALID
)
749 fprintf(acctfp
, "%s - %s %s %d (%d) (%d/%d)\n",
750 logdatetime
, getlogdatetime(),
751 cep
->name
, cep
->charge
, con_secs
,
752 cep
->inbytes
, cep
->outbytes
);
756 fprintf(acctfp
, "%s - %s %s %d (%d)\n",
757 logdatetime
, getlogdatetime(),
758 cep
->name
, cep
->charge
, con_secs
);
762 /* set the B-channel inactive */
764 set_channel_idle(cep
->isdncontrollerused
, cep
->isdnchannelused
);
766 incr_free_channels(cep
->isdncontrollerused
);
768 cep
->connect_time
= 0;
769 cep
->cdid
= CDID_UNUSED
;
771 next_state(cep
, EV_MDI
);
774 /*---------------------------------------------------------------------------*
775 * handle incoming DIALOUT message
776 *---------------------------------------------------------------------------*/
778 msg_dialout(msg_dialout_ind_t
*mp
)
782 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_dialout: dial req from %s, unit %d", bdrivername(mp
->driver
), mp
->driver_unit
)));
784 if((cep
= find_by_device_for_dialout(mp
->driver
, mp
->driver_unit
)) == NULL
)
786 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_dialout: config entry reserved or no match")));
790 if(cep
->inout
== DIR_INONLY
)
792 dialresponse(cep
, DSTAT_INONLY
);
796 if(cep
->budget_calloutperiod
&& cep
->budget_calloutncalls
)
798 cep
->budget_calltype
= 0;
799 cep
->budget_callout_req
++;
801 if(cep
->budget_calloutncalls_cnt
== 0)
803 dolog(LL_CHD
, "%05d %s no budget for calling out", 0, cep
->name
);
804 cep
->budget_callout_rej
++;
805 dialresponse(cep
, DSTAT_TFAIL
);
810 cep
->budget_calltype
= BUDGET_TYPE_COUT
;
814 if((cep
->cdid
= get_cdid()) == 0)
816 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_dialout: get_cdid() returned 0!")));
821 cep
->last_charge
= 0;
824 next_state(cep
, EV_MDO
);
827 /*---------------------------------------------------------------------------*
828 * handle incoming DIALOUTNUMBER message
829 *---------------------------------------------------------------------------*/
831 msg_dialoutnumber(msg_dialoutnumber_ind_t
*mp
)
835 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_dialoutnumber: dial req from %s, unit %d", bdrivername(mp
->driver
), mp
->driver_unit
)));
837 if((cep
= find_by_device_for_dialoutnumber(mp
->driver
, mp
->driver_unit
, mp
->cmdlen
, mp
->cmd
)) == NULL
)
839 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_dialoutnumber: config entry reserved or no match")));
843 if(cep
->inout
== DIR_INONLY
)
845 dialresponse(cep
, DSTAT_INONLY
);
849 if(cep
->budget_calloutperiod
&& cep
->budget_calloutncalls
)
851 cep
->budget_calltype
= 0;
852 cep
->budget_callout_req
++;
854 if(cep
->budget_calloutncalls_cnt
== 0)
856 dolog(LL_CHD
, "%05d %s no budget for calling out", 0, cep
->name
);
857 cep
->budget_callout_rej
++;
858 dialresponse(cep
, DSTAT_TFAIL
);
863 cep
->budget_calltype
= BUDGET_TYPE_COUT
;
867 if((cep
->cdid
= get_cdid()) == 0)
869 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_dialoutnumber: get_cdid() returned 0!")));
873 cep
->keypad
[0] = '\0';
875 cep
->last_charge
= 0;
878 next_state(cep
, EV_MDO
);
881 /*---------------------------------------------------------------------------*
882 * handle incoming KEYPAD message
883 *---------------------------------------------------------------------------*/
885 msg_keypad(msg_keypad_ind_t
*mp
)
889 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_keypad: dial req from %s, unit %d", bdrivername(mp
->driver
), mp
->driver_unit
)));
891 if((cep
= find_by_device_for_keypad(mp
->driver
, mp
->driver_unit
, mp
->cmdlen
, mp
->cmd
)) == NULL
)
893 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_keypad: config entry reserved or no match")));
897 if(cep
->inout
== DIR_INONLY
)
899 dialresponse(cep
, DSTAT_INONLY
);
903 if(cep
->budget_calloutperiod
&& cep
->budget_calloutncalls
)
905 cep
->budget_calltype
= 0;
906 cep
->budget_callout_req
++;
908 if(cep
->budget_calloutncalls_cnt
== 0)
910 dolog(LL_CHD
, "%05d %s no budget for calling out", 0, cep
->name
);
911 cep
->budget_callout_rej
++;
912 dialresponse(cep
, DSTAT_TFAIL
);
917 cep
->budget_calltype
= BUDGET_TYPE_COUT
;
921 if((cep
->cdid
= get_cdid()) == 0)
923 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_keypad: get_cdid() returned 0!")));
928 cep
->last_charge
= 0;
931 next_state(cep
, EV_MDO
);
934 /*---------------------------------------------------------------------------*
935 * handle incoming DRVRDISC_REQ message
936 *---------------------------------------------------------------------------*/
938 msg_drvrdisc_req(msg_drvrdisc_req_t
*mp
)
942 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_drvrdisc_req: req from %s, unit %d", bdrivername(mp
->driver
), mp
->driver_unit
)));
944 if((cep
= get_cep_by_driver(mp
->driver
, mp
->driver_unit
)) == NULL
)
946 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_drvrdisc_req: config entry not found")));
949 next_state(cep
, EV_DRQ
);
952 /*---------------------------------------------------------------------------*
953 * handle incoming ACCOUNTING message
954 *---------------------------------------------------------------------------*/
956 msg_accounting(msg_accounting_ind_t
*mp
)
960 if((cep
= find_active_entry_by_driver(mp
->driver
, mp
->driver_unit
)) == NULL
)
962 dolog(LL_WRN
, "msg_accounting: no config entry found!");
966 cep
->inbytes
= mp
->inbytes
;
967 cep
->iinbytes
= mp
->iinbytes
;
968 cep
->outbytes
= mp
->outbytes
;
969 cep
->ioutbytes
= mp
->ioutbytes
;
970 cep
->inbps
= mp
->inbps
;
971 cep
->outbps
= mp
->outbps
;
973 if(mp
->accttype
== ACCT_DURING
)
979 #ifdef I4B_EXTERNAL_MONITOR
980 if(do_monitor
&& accepted
)
981 monitor_evnt_acct(cep
);
986 /*---------------------------------------------------------------------------*
987 * handle incoming CHARGING message
988 *---------------------------------------------------------------------------*/
990 msg_charging_ind(msg_charging_ind_t
*mp
)
992 static char *cttab
[] = {
1000 if((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
1002 dolog(LL_WRN
, "msg_charging_ind: cdid not found");
1006 if(mp
->units_type
< CHARGE_INVALID
|| mp
->units_type
> CHARGE_CALC
)
1008 dolog(LL_ERR
, "msg_charging: units_type %d out of range!", mp
->units_type
);
1009 error_exit(1, "msg_charging: units_type %d out of range!", mp
->units_type
);
1012 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_charging: %d unit(s) (%s)",
1013 mp
->units
, cttab
[mp
->units_type
])));
1015 cep
->charge
= mp
->units
;
1017 switch(mp
->units_type
)
1020 if((cep
->unitlengthsrc
== ULSRC_DYN
) &&
1021 (cep
->charge
!= cep
->last_charge
))
1023 cep
->last_charge
= cep
->charge
;
1031 display_ccharge(cep
, mp
->units
);
1033 #ifdef I4B_EXTERNAL_MONITOR
1034 if(do_monitor
&& accepted
)
1035 monitor_evnt_charge(cep
, mp
->units
, 1);
1041 /*---------------------------------------------------------------------------*
1042 * handle incoming IDLE_TIMEOUT_IND message
1043 *---------------------------------------------------------------------------*/
1045 msg_idle_timeout_ind(msg_idle_timeout_ind_t
*mp
)
1049 if((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
1051 dolog(LL_WRN
, "msg_idle_timeout_ind: cdid not found!");
1055 cep
->local_disconnect
= DISCON_LOC
;
1057 DBGL(DL_DRVR
, (dolog(LL_DBG
, "msg_idle_timeout_ind: idletimeout, kernel sent disconnect!")));
1059 check_and_kill(cep
);
1062 /*---------------------------------------------------------------------------*
1063 * handle incoming MSG_PACKET_IND message
1064 *---------------------------------------------------------------------------*/
1066 strapp(char *buf
, const char *txt
)
1074 /*---------------------------------------------------------------------------*
1075 * handle incoming MSG_PACKET_IND message
1076 *---------------------------------------------------------------------------*/
1078 ipapp(char *buf
, unsigned long a
)
1080 unsigned long ma
= ntohl( a
);
1082 buf
+= sprintf(buf
, "%lu.%lu.%lu.%lu",
1090 /*---------------------------------------------------------------------------*
1091 * handle incoming MSG_PACKET_IND message
1092 *---------------------------------------------------------------------------*/
1094 msg_packet_ind(msg_packet_ind_t
*mp
)
1104 for(i
=0; i
< nentries
; i
++)
1106 cep
= &cfg_entry_tab
[i
]; /* ptr to config entry */
1108 if(cep
->usrdevicename
== mp
->driver
&&
1109 cep
->usrdeviceunit
== mp
->driver_unit
)
1116 ip
= (struct ip
*)mp
->pktdata
;
1117 proto_hdr
= mp
->pktdata
+ ((ip
->ip_hl
)<<2);
1119 if( ip
->ip_p
== IPPROTO_TCP
)
1121 struct tcphdr
* tcp
= (struct tcphdr
*)proto_hdr
;
1123 cptr
= strapp( cptr
, "TCP " );
1124 cptr
= ipapp( cptr
, ip
->ip_src
.s_addr
);
1125 cptr
+= sprintf( cptr
, ":%u -> ", ntohs( tcp
->th_sport
) );
1126 cptr
= ipapp( cptr
, ip
->ip_dst
.s_addr
);
1127 cptr
+= sprintf( cptr
, ":%u", ntohs( tcp
->th_dport
) );
1129 if(tcp
->th_flags
& TH_FIN
) cptr
= strapp( cptr
, " FIN" );
1130 if(tcp
->th_flags
& TH_SYN
) cptr
= strapp( cptr
, " SYN" );
1131 if(tcp
->th_flags
& TH_RST
) cptr
= strapp( cptr
, " RST" );
1132 if(tcp
->th_flags
& TH_PUSH
) cptr
= strapp( cptr
, " PUSH" );
1133 if(tcp
->th_flags
& TH_ACK
) cptr
= strapp( cptr
, " ACK" );
1134 if(tcp
->th_flags
& TH_URG
) cptr
= strapp( cptr
, " URG" );
1136 else if( ip
->ip_p
== IPPROTO_UDP
)
1138 struct udphdr
* udp
= (struct udphdr
*)proto_hdr
;
1140 cptr
= strapp( cptr
, "UDP " );
1141 cptr
= ipapp( cptr
, ip
->ip_src
.s_addr
);
1142 cptr
+= sprintf( cptr
, ":%u -> ", ntohs( udp
->uh_sport
) );
1143 cptr
= ipapp( cptr
, ip
->ip_dst
.s_addr
);
1144 cptr
+= sprintf( cptr
, ":%u", ntohs( udp
->uh_dport
) );
1146 else if( ip
->ip_p
== IPPROTO_ICMP
)
1148 struct icmp
* icmp
= (struct icmp
*)proto_hdr
;
1150 cptr
+= sprintf( cptr
, "ICMP:%u.%u", icmp
->icmp_type
, icmp
->icmp_code
);
1151 cptr
= ipapp( cptr
, ip
->ip_src
.s_addr
);
1152 cptr
= strapp( cptr
, " -> " );
1153 cptr
= ipapp( cptr
, ip
->ip_dst
.s_addr
);
1157 cptr
+= sprintf( cptr
, "PROTO=%u ", ip
->ip_p
);
1158 cptr
= ipapp( cptr
, ip
->ip_src
.s_addr
);
1159 cptr
= strapp( cptr
, " -> " );
1160 cptr
= ipapp( cptr
, ip
->ip_dst
.s_addr
);
1163 dolog(LL_PKT
, "%s %s %u %s",
1164 name
, mp
->direction
? "send" : "recv",
1165 ntohs( ip
->ip_len
), tmp
);
1168 /*---------------------------------------------------------------------------*
1169 * get a cdid from kernel
1170 *---------------------------------------------------------------------------*/
1178 if((ioctl(isdnfd
, I4B_CDID_REQ
, &mcr
)) < 0)
1180 dolog(LL_ERR
, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno
));
1181 error_exit(1, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno
));
1187 /*---------------------------------------------------------------------------*
1188 * send message "connect request" to kernel
1189 *---------------------------------------------------------------------------*/
1191 sendm_connect_req(cfg_entry_t
*cep
)
1193 msg_connect_req_t mcr
;
1196 cep
->local_disconnect
= DISCON_REM
;
1198 cep
->unitlength
= get_current_rate(cep
, 1);
1200 mcr
.cdid
= cep
->cdid
;
1202 mcr
.controller
= cep
->isdncontrollerused
;
1203 mcr
.channel
= cep
->isdnchannelused
;
1204 mcr
.txdelay
= cep
->isdntxdelout
;
1206 mcr
.bprot
= cep
->b1protocol
;
1208 mcr
.driver
= cep
->usrdevicename
;
1209 mcr
.driver_unit
= cep
->usrdeviceunit
;
1211 /* setup the shorthold data */
1212 mcr
.shorthold_data
.shorthold_algorithm
= cep
->shorthold_algorithm
;
1213 mcr
.shorthold_data
.unitlen_time
= cep
->unitlength
;
1214 mcr
.shorthold_data
.idle_time
= cep
->idle_time_out
;
1215 mcr
.shorthold_data
.earlyhup_time
= cep
->earlyhangup
;
1217 if(cep
->unitlengthsrc
== ULSRC_DYN
)
1218 mcr
.unitlen_method
= ULEN_METHOD_DYNAMIC
;
1220 mcr
.unitlen_method
= ULEN_METHOD_STATIC
;
1222 strcpy(mcr
.dst_telno
, cep
->remote_phone_dialout
);
1223 strcpy(mcr
.src_telno
, cep
->local_phone_dialout
);
1224 strcpy(mcr
.keypad
, cep
->keypad
);
1226 cep
->last_dial_time
= time(NULL
);
1227 cep
->direction
= DIR_OUT
;
1229 DBGL(DL_CNST
, (dolog(LL_DBG
, "sendm_connect_req: ctrl = %d, chan = %d", cep
->isdncontrollerused
, cep
->isdnchannelused
)));
1231 if((ret
= ioctl(isdnfd
, I4B_CONNECT_REQ
, &mcr
)) < 0)
1233 dolog(LL_ERR
, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno
));
1234 error_exit(1, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno
));
1237 decr_free_channels(cep
->isdncontrollerused
);
1239 dolog(LL_CHD
, "%05d %s dialing out from %s to %s",
1242 aliasing
? get_alias(cep
->local_phone_dialout
) : cep
->local_phone_dialout
,
1243 aliasing
? get_alias(cep
->remote_phone_dialout
) : cep
->remote_phone_dialout
);
1248 /*---------------------------------------------------------------------------*
1249 * send message "connect response" to kernel
1250 *---------------------------------------------------------------------------*/
1252 sendm_connect_resp(cfg_entry_t
*cep
, int cdid
, int response
, cause_t cause
)
1254 msg_connect_resp_t mcr
;
1259 mcr
.response
= response
;
1261 if(response
== SETUP_RESP_REJECT
)
1264 DBGL(DL_DRVR
, (dolog(LL_DBG
, "sendm_connect_resp: reject, cause=0x%x", cause
)));
1266 else if(response
== SETUP_RESP_ACCEPT
)
1268 cep
->direction
= DIR_IN
;
1270 mcr
.txdelay
= cep
->isdntxdelin
;
1272 mcr
.bprot
= cep
->b1protocol
;
1274 mcr
.driver
= cep
->usrdevicename
;
1275 mcr
.driver_unit
= cep
->usrdeviceunit
;
1277 mcr
.max_idle_time
= cep
->idle_time_in
;
1279 DBGL(DL_DRVR
, (dolog(LL_DBG
, "sendm_connect_resp: accept")));
1282 if((ret
= ioctl(isdnfd
, I4B_CONNECT_RESP
, &mcr
)) < 0)
1284 dolog(LL_ERR
, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno
));
1285 error_exit(1, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno
));
1290 /*---------------------------------------------------------------------------*
1291 * send message "disconnect request" to kernel
1292 *---------------------------------------------------------------------------*/
1294 sendm_disconnect_req(cfg_entry_t
*cep
, cause_t cause
)
1296 msg_discon_req_t mcr
;
1299 mcr
.cdid
= cep
->cdid
;
1303 cep
->local_disconnect
= DISCON_LOC
;
1305 if((ret
= ioctl(isdnfd
, I4B_DISCONNECT_REQ
, &mcr
)) < 0)
1307 dolog(LL_ERR
, "sendm_disconnect_req: ioctl I4B_DISCONNECT_REQ failed: %s", strerror(errno
));
1311 DBGL(DL_DRVR
, (dolog(LL_DBG
, "sendm_disconnect_req: sent DISCONNECT_REQ")));
1316 /*---------------------------------------------------------------------------*
1317 * send message "alert request" to kernel
1318 *---------------------------------------------------------------------------*/
1320 sendm_alert_req(cfg_entry_t
*cep
)
1322 msg_alert_req_t mar
;
1325 mar
.cdid
= cep
->cdid
;
1327 if((ret
= ioctl(isdnfd
, I4B_ALERT_REQ
, &mar
)) < 0)
1329 dolog(LL_ERR
, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno
));
1330 error_exit(1, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno
));
1334 DBGL(DL_DRVR
, (dolog(LL_DBG
, "sendm_alert_req: sent ALERT_REQ")));