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 daemon - message from kernel handling routines
28 * --------------------------------------------------
30 * $Id: msghdl.c,v 1.11 2009/04/16 05:56:32 lukem Exp $
34 * last edit-date: [Thu Sep 21 11:11:48 2000]
36 *---------------------------------------------------------------------------*/
40 #include <sys/socket.h>
42 #include <net/if_types.h>
44 #if defined(__FreeBSD__)
45 #include <net/if_var.h>
48 #include <netinet/in.h>
49 #include <netinet/in_systm.h>
50 #include <netinet/in_var.h>
51 #include <netinet/ip.h>
52 #include <netinet/tcp.h>
53 #include <netinet/udp.h>
54 #include <netinet/ip_icmp.h>
56 /*---------------------------------------------------------------------------*
57 * handle incoming CONNECT_IND (=SETUP) message
58 *---------------------------------------------------------------------------*/
60 msg_connect_ind(msg_connect_ind_t
*mp
, int len
)
62 struct cfg_entry
*cep
;
63 const char *src_tela
= "ERROR-src_tela";
64 const char *dst_tela
= "ERROR-dst_tela";
66 #define SRC (aliasing == 0 ? mp->src_telno : src_tela)
67 #define DST (aliasing == 0 ? mp->dst_telno : dst_tela)
71 src_tela
= get_alias(mp
->src_telno
);
72 dst_tela
= get_alias(mp
->dst_telno
);
75 if ((cep
= find_matching_entry_incoming(mp
, len
)) == NULL
)
77 /* log message generated in find_matching_entry_incoming() */
78 sendm_connect_resp(NULL
, mp
->header
.cdid
, SETUP_RESP_DNTCRE
, 0);
79 handle_scrprs(mp
->header
.cdid
, mp
->scr_ind
, mp
->prs_ind
, SRC
);
83 if (cep
->cdid
!= CDID_UNUSED
&& cep
->cdid
!= CDID_RESERVED
)
86 * This is an incoming call on a number we just dialed out.
87 * Stop our dial-out and accept the incoming call.
89 if (cep
->saved_call
.cdid
!= CDID_UNUSED
&&
90 cep
->saved_call
.cdid
!= CDID_RESERVED
)
94 /* disconnect old, not new */
97 cep
->cdid
= cep
->saved_call
.cdid
;
98 sendm_disconnect_req(cep
, (CAUSET_I4B
<< 8) | CAUSE_I4B_NORMAL
);
102 * Shortcut the state machine and mark this
105 /* XXX */ cep
->state
= ST_IDLE
; /* this is an invalid */
107 /* so no next_state() */
108 /* we have to wait here for an incoming */
109 /* disconnect message !!! (-hm) */
113 if (cep
->inout
== DIR_OUTONLY
)
115 logit(LL_CHD
, "%05d %s incoming call from %s to %s not allowed by configuration!",
116 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
117 sendm_connect_resp(NULL
, mp
->header
.cdid
, SETUP_RESP_DNTCRE
, 0);
118 handle_scrprs(mp
->header
.cdid
, mp
->scr_ind
, mp
->prs_ind
, SRC
);
123 cep
->last_charge
= 0;
125 switch (cep
->dialin_reaction
)
128 logit(LL_CHD
, "%05d %s accepting: incoming call from %s to %s",
129 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
130 decr_free_channels(find_ctrl_state(mp
->controller
));
131 next_state(cep
, EV_MCI
);
135 logit(LL_CHD
, "%05d %s rejecting: incoming call from %s to %s",
136 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
137 sendm_connect_resp(cep
, mp
->header
.cdid
, SETUP_RESP_REJECT
,
138 (CAUSET_I4B
<< 8) | CAUSE_I4B_REJECT
);
139 cep
->cdid
= CDID_UNUSED
;
143 logit(LL_CHD
, "%05d %s ignoring: incoming call from %s to %s",
144 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
145 sendm_connect_resp(NULL
, mp
->header
.cdid
, SETUP_RESP_DNTCRE
, 0);
149 decr_free_channels(find_ctrl_state(mp
->controller
));
154 logit(LL_CHD
, "%05d %s alerting: incoming call from %s to %s (%s)",
155 mp
->header
.cdid
, cep
->name
, SRC
, DST
, mp
->display
);
159 logit(LL_CHD
, "%05d %s alerting: incoming call from %s to %s",
160 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
162 next_state(cep
, EV_ALRT
);
168 logit(LL_CHD
, "%05d %s answering: incoming call from %s to %s (%s)",
169 mp
->header
.cdid
, cep
->name
, SRC
, DST
, mp
->display
);
173 logit(LL_CHD
, "%05d %s answering: incoming call from %s to %s",
174 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
176 next_state(cep
, EV_MCI
);
183 /*XXX reserve channel ??? */ decr_free_channels(mp
->controller
);
185 if (cep
->cdid
== CDID_RESERVED
)
187 logit(LL_CHD
, "%05d %s reserved: incoming call from %s to %s",
188 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
189 sendm_connect_resp(cep
, mp
->header
.cdid
, SETUP_RESP_REJECT
,
191 (CAUSET_I4B
<< 8) | CAUSE_I4B_NORMAL
);
193 (CAUSET_I4B
<< 8) | CAUSE_I4B_REJECT
);
195 /* no state change */
199 sendm_connect_resp(cep
, mp
->header
.cdid
, SETUP_RESP_REJECT
,
201 (CAUSET_I4B
<< 8) | CAUSE_I4B_NORMAL
);
203 (CAUSET_I4B
<< 8) | CAUSE_I4B_REJECT
);
205 if (cep
->budget_callbackperiod
&& cep
->budget_callbackncalls
)
207 cep
->budget_callback_req
++;
208 cep
->budget_calltype
= 0;
209 if (cep
->budget_callbackncalls_cnt
== 0)
211 logit(LL_CHD
, "%05d %s no budget: call from %s to %s",
212 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
213 cep
->cdid
= CDID_UNUSED
;
214 cep
->budget_callback_rej
++;
219 cep
->budget_calltype
= BUDGET_TYPE_CBACK
;
223 logit(LL_CHD
, "%05d %s callback: incoming call from %s to %s",
224 mp
->header
.cdid
, cep
->name
, SRC
, DST
);
226 cep
->last_release_time
= time(NULL
);
227 cep
->cdid
= CDID_RESERVED
;
228 next_state(cep
, EV_CBRQ
);
233 logit(LL_WRN
, "msg_connect_ind: unknown response type, tx SETUP_RESP_DNTCRE");
234 sendm_connect_resp(NULL
, mp
->header
.cdid
, SETUP_RESP_DNTCRE
, 0);
237 handle_scrprs(mp
->header
.cdid
, mp
->scr_ind
, mp
->prs_ind
, SRC
);
242 /*---------------------------------------------------------------------------*
243 * handle incoming CONNECT_ACTIVE_IND message
244 *---------------------------------------------------------------------------*/
246 msg_connect_active_ind(msg_connect_active_ind_t
*mp
)
248 struct cfg_entry
*cep
;
250 if ((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
252 logit(LL_WRN
, "msg_connect_active_ind: cdid not found!");
256 cep
->isdncontrollerused
= mp
->controller
;
257 cep
->isdnchannelused
= mp
->channel
;
259 cep
->aoc_now
= cep
->connect_time
= time(NULL
);
262 cep
->aoc_valid
= AOC_INVALID
;
264 cep
->local_disconnect
= DISCON_REM
;
266 cep
->inbytes
= INVALID
;
267 cep
->outbytes
= INVALID
;
270 /* set the B-channel to active */
272 if ((set_channel_busy(find_ctrl_state(cep
->isdncontrollerused
), cep
->isdnchannelused
)) == ERROR
)
273 logit(LL_ERR
, "msg_connect_active_ind: set_channel_busy failed!");
275 if (cep
->direction
== DIR_OUT
)
277 logit(LL_CHD
, "%05d %s outgoing call active (ctl %d, ch %d, %s%d)",
278 cep
->cdid
, cep
->name
,
279 cep
->isdncontrollerused
, cep
->isdnchannelused
,
280 cep
->usrdevicename
, cep
->usrdeviceunit
);
282 if (cep
->budget_calltype
)
284 if (cep
->budget_calltype
== BUDGET_TYPE_CBACK
)
286 cep
->budget_callback_done
++;
287 cep
->budget_callbackncalls_cnt
--;
288 DBGL(DL_BDGT
, (logit(LL_DBG
, "%s: new cback-budget = %d",
289 cep
->name
, cep
->budget_callbackncalls_cnt
)));
290 if (cep
->budget_callbacks_file
!= NULL
)
291 upd_callstat_file(cep
->budget_callbacks_file
, cep
->budget_callbacksfile_rotate
);
293 else if (cep
->budget_calltype
== BUDGET_TYPE_COUT
)
295 cep
->budget_callout_done
++;
296 cep
->budget_calloutncalls_cnt
--;
297 DBGL(DL_BDGT
, (logit(LL_DBG
, "%s: new cout-budget = %d",
298 cep
->name
, cep
->budget_calloutncalls_cnt
)));
299 if (cep
->budget_callouts_file
!= NULL
)
300 upd_callstat_file(cep
->budget_callouts_file
, cep
->budget_calloutsfile_rotate
);
302 cep
->budget_calltype
= 0;
307 logit(LL_CHD
, "%05d %s incoming call active (ctl %d, ch %d, %s%d)",
308 cep
->cdid
, cep
->name
,
309 cep
->isdncontrollerused
, cep
->isdnchannelused
,
310 cep
->usrdevicename
, cep
->usrdeviceunit
);
315 display_connect(cep
);
317 #ifdef I4B_EXTERNAL_MONITOR
318 if (do_monitor
&& accepted
)
319 monitor_evnt_connect(cep
);
322 if (isdntime
&& (mp
->datetime
[0] != '\0'))
324 logit(LL_DMN
, "date/time from exchange = %s", mp
->datetime
);
327 next_state(cep
, EV_MCAI
);
330 /*---------------------------------------------------------------------------*
331 * handle incoming PROCEEDING_IND message
332 *---------------------------------------------------------------------------*/
334 msg_proceeding_ind(msg_proceeding_ind_t
*mp
)
336 struct cfg_entry
*cep
;
338 if ((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
340 logit(LL_WRN
, "msg_proceeding_ind: cdid not found!");
344 cep
->isdncontrollerused
= mp
->controller
;
345 cep
->isdnchannelused
= mp
->channel
;
347 /* set the B-channels active */
349 if ((set_channel_busy(find_ctrl_state(cep
->isdncontrollerused
), cep
->isdnchannelused
)) == ERROR
)
350 logit(LL_ERR
, "msg_proceeding_ind: set_channel_busy failed!");
352 logit(LL_CHD
, "%05d %s outgoing call proceeding (ctl %d, ch %d)",
353 cep
->cdid
, cep
->name
,
354 cep
->isdncontrollerused
, cep
->isdnchannelused
);
357 /*---------------------------------------------------------------------------*
358 * handle incoming ALERT_IND message
359 *---------------------------------------------------------------------------*/
361 msg_alert_ind(msg_alert_ind_t
*mp
)
363 struct cfg_entry
*cep
;
365 if ((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
367 logit(LL_WRN
, "msg_alert_ind: cdid not found!");
371 logit(LL_CHD
, "%05d %s incoming alert", cep
->cdid
, cep
->name
);
375 /*---------------------------------------------------------------------------*
376 * handle incoming L12STAT_IND message
377 *---------------------------------------------------------------------------*/
379 msg_l12stat_ind(msg_l12stat_ind_t
*ml
)
381 struct isdn_ctrl_state
* ctrl
= find_ctrl_state(ml
->controller
);
383 logit(LL_ERR
, "msg_l12stat_ind: invalid controller number: %d !", ml
->controller
);
389 display_l12stat(ml
->controller
, ml
->layer
, ml
->state
);
391 #ifdef I4B_EXTERNAL_MONITOR
392 if (do_monitor
&& accepted
)
393 monitor_evnt_l12stat(ml
->controller
, ml
->layer
, ml
->state
);
396 DBGL(DL_CNST
, (logit(LL_DBG
, "msg_l12stat_ind: unit %d, layer %d, state %d",
397 ml
->controller
, ml
->layer
, ml
->state
)));
399 if (ml
->layer
== LAYER_ONE
)
401 if (ml
->state
== LAYER_IDLE
)
402 ctrl
->l2stat
= ml
->state
;
403 ctrl
->l1stat
= ml
->state
;
405 else if (ml
->layer
== LAYER_TWO
)
407 if (ml
->state
== LAYER_ACTIVE
)
408 ctrl
->l1stat
= ml
->state
;
409 ctrl
->l2stat
= ml
->state
;
413 logit(LL_ERR
, "msg_l12stat_ind: invalid layer number [%d]!", ml
->layer
);
417 /*---------------------------------------------------------------------------*
418 * handle incoming TEIASG_IND message
419 *---------------------------------------------------------------------------*/
421 msg_teiasg_ind(msg_teiasg_ind_t
*mt
)
423 struct isdn_ctrl_state
*ctrl
= find_ctrl_state(mt
->controller
);
426 logit(LL_ERR
, "msg_teiasg_ind: invalid controller number [%d]!", mt
->controller
);
432 display_tei(mt
->controller
, mt
->tei
);
434 #ifdef I4B_EXTERNAL_MONITOR
435 if (do_monitor
&& accepted
)
436 monitor_evnt_tei(mt
->controller
, mt
->tei
);
439 DBGL(DL_CNST
, (logit(LL_DBG
, "msg_teiasg_ind: unit %d, tei = %d",
440 mt
->controller
, mt
->tei
)));
445 /*---------------------------------------------------------------------------*
446 * handle incoming PDEACT_IND message
447 *---------------------------------------------------------------------------*/
449 msg_pdeact_ind(msg_pdeact_ind_t
*md
)
451 int isdnif
= md
->controller
;
452 struct cfg_entry
*cep
;
453 struct isdn_ctrl_state
* ctrl
= find_ctrl_state(isdnif
);
458 display_l12stat(isdnif
, LAYER_ONE
, LAYER_IDLE
);
459 display_l12stat(isdnif
, LAYER_TWO
, LAYER_IDLE
);
460 display_tei(isdnif
, -1);
463 #ifdef I4B_EXTERNAL_MONITOR
464 if (do_monitor
&& accepted
)
466 monitor_evnt_l12stat(isdnif
, LAYER_ONE
, LAYER_IDLE
);
467 monitor_evnt_l12stat(isdnif
, LAYER_TWO
, LAYER_IDLE
);
468 monitor_evnt_tei(isdnif
, -1);
472 DBGL(DL_CNST
, (logit(LL_DBG
, "msg_pdeact_ind: BRI %d, persistent deactivation", isdnif
)));
474 ctrl
->l1stat
= LAYER_IDLE
;
475 ctrl
->l2stat
= LAYER_IDLE
;
478 for (cep
= get_first_cfg_entry(); cep
; cep
= NEXT_CFE(cep
)) {
479 if (cep
->cdid
!= CDID_UNUSED
&&
480 cep
->isdncontrollerused
== isdnif
) {
482 if (cep
->cdid
== CDID_RESERVED
)
484 cep
->state
= ST_IDLE
;
485 cep
->cdid
= CDID_UNUSED
;
489 cep
->cdid
= CDID_UNUSED
;
491 cep
->last_release_time
= time(NULL
);
493 SET_CAUSE_TYPE(cep
->disc_cause
, CAUSET_I4B
);
494 SET_CAUSE_VAL(cep
->disc_cause
, CAUSE_I4B_L1ERROR
);
496 if (cep
->direction
== DIR_OUT
)
498 logit(LL_CHD
, "%05d %s outgoing call disconnected (local)",
499 cep
->cdid
, cep
->name
);
503 logit(LL_CHD
, "%05d %s incoming call disconnected (local)",
504 cep
->cdid
, cep
->name
);
507 logit(LL_CHD
, "%05d %s cause %s",
508 cep
->cdid
, cep
->name
, print_i4b_cause(cep
->disc_cause
));
511 if (do_fullscreen
&& (cep
->connect_time
> 0))
512 display_disconnect(cep
);
514 #ifdef I4B_EXTERNAL_MONITOR
515 if (do_monitor
&& accepted
)
516 monitor_evnt_disconnect(cep
);
519 if (cep
->disconnectprog
)
520 exec_connect_prog(cep
, cep
->disconnectprog
, 1);
522 if (cep
->connect_time
> 0)
524 if (cep
->direction
== DIR_OUT
)
526 logit(LL_CHD
, "%05d %s charging: %d units, %d seconds",
527 cep
->cdid
, cep
->name
, cep
->charge
,
528 (int)difftime(time(NULL
), cep
->connect_time
));
532 logit(LL_CHD
, "%05d %s connected %d seconds",
533 cep
->cdid
, cep
->name
,
534 (int)difftime(time(NULL
), cep
->connect_time
));
537 if ((cep
->inbytes
!= INVALID
) && (cep
->outbytes
!= INVALID
))
539 if ((cep
->ioutbytes
!= cep
->outbytes
) ||
540 (cep
->iinbytes
!= cep
->inbytes
))
542 logit(LL_CHD
, "%05d %s accounting: in %d, out %d (in %d, out %d)",
543 cep
->cdid
, cep
->name
,
544 cep
->inbytes
, cep
->outbytes
,
545 cep
->iinbytes
, cep
->ioutbytes
);
549 logit(LL_CHD
, "%05d %s accounting: in %d, out %d",
550 cep
->cdid
, cep
->name
,
551 cep
->inbytes
, cep
->outbytes
);
556 if (useacctfile
&& (cep
->connect_time
> 0))
559 char logdatetime
[41];
562 con_secs
= difftime(time(NULL
), cep
->connect_time
);
564 tp
= localtime(&cep
->connect_time
);
566 strftime(logdatetime
,40,I4B_TIME_FORMAT
,tp
);
568 if (cep
->inbytes
!= INVALID
&& cep
->outbytes
!= INVALID
)
570 fprintf(acctfp
, "%s - %s %s %d (%d) (%d/%d)\n",
571 logdatetime
, getlogdatetime(),
572 cep
->name
, cep
->charge
, con_secs
,
573 cep
->inbytes
, cep
->outbytes
);
577 fprintf(acctfp
, "%s - %s %s %d (%d)\n",
578 logdatetime
, getlogdatetime(),
579 cep
->name
, cep
->charge
, con_secs
);
583 /* set the B-channel inactive */
585 if ((set_channel_idle(ctrl
, cep
->isdnchannelused
)) == ERROR
)
586 logit(LL_ERR
, "msg_pdeact_ind: set_channel_idle failed!");
588 incr_free_channels(ctrl
);
590 cep
->connect_time
= 0;
592 cep
->state
= ST_IDLE
;
597 /*---------------------------------------------------------------------------*
598 * handle incoming NEGCOMP_IND message
599 *---------------------------------------------------------------------------*/
601 msg_negcomplete_ind(msg_negcomplete_ind_t
*mp
)
603 struct cfg_entry
*cep
;
605 if ((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
607 logit(LL_WRN
, "msg_negcomp_ind: cdid not found");
611 if (cep
->connectprog
)
612 exec_connect_prog(cep
, cep
->connectprog
, 0);
615 /*---------------------------------------------------------------------------*
616 * handle incoming IFSTATE_CHANGED indication
617 *---------------------------------------------------------------------------*/
619 msg_ifstatechg_ind(msg_ifstatechg_ind_t
*mp
)
621 struct cfg_entry
*cep
;
623 if ((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
625 logit(LL_WRN
, "msg_negcomp_ind: cdid not found");
629 logit(LL_DBG
, "%s%d: switched to state %d", cep
->usrdevicename
, cep
->usrdeviceunit
, mp
->state
);
632 /*---------------------------------------------------------------------------*
633 * handle incoming DISCONNECT_IND message
634 *---------------------------------------------------------------------------*/
636 msg_disconnect_ind(msg_disconnect_ind_t
*mp
)
638 struct cfg_entry
*cep
;
639 struct isdn_ctrl_state
*ctrl
;
641 if ((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
643 logit(LL_WRN
, "msg_disconnect_ind: cdid not found");
647 /* is this an aborted out-call prematurely called back? */
648 if (cep
->saved_call
.cdid
== mp
->header
.cdid
)
650 DBGL(DL_CNST
, (logit(LL_DBG
, "aborted outcall %05d disconnected",
652 cep
->saved_call
.cdid
= CDID_UNUSED
;
654 ctrl
= find_ctrl_state(cep
->saved_call
.controller
);
655 set_channel_idle(ctrl
, cep
->saved_call
.channel
);
657 incr_free_channels(ctrl
);
661 cep
->last_release_time
= time(NULL
);
662 cep
->disc_cause
= mp
->cause
;
664 if (cep
->direction
== DIR_OUT
)
666 logit(LL_CHD
, "%05d %s outgoing call disconnected %s",
667 cep
->cdid
, cep
->name
,
668 cep
->local_disconnect
== DISCON_LOC
?
669 "(local)" : "(remote)");
673 logit(LL_CHD
, "%05d %s incoming call disconnected %s",
674 cep
->cdid
, cep
->name
,
675 cep
->local_disconnect
== DISCON_LOC
?
676 "(local)" : "(remote)");
679 logit(LL_CHD
, "%05d %s cause %s",
680 cep
->cdid
, cep
->name
, print_i4b_cause(mp
->cause
));
683 if (do_fullscreen
&& (cep
->connect_time
> 0))
684 display_disconnect(cep
);
686 #ifdef I4B_EXTERNAL_MONITOR
687 if (do_monitor
&& accepted
)
688 monitor_evnt_disconnect(cep
);
691 if (cep
->disconnectprog
)
692 exec_connect_prog(cep
, cep
->disconnectprog
, 1);
694 if (cep
->connect_time
> 0)
696 if (cep
->direction
== DIR_OUT
)
698 logit(LL_CHD
, "%05d %s charging: %d units, %d seconds",
699 cep
->cdid
, cep
->name
, cep
->charge
,
700 (int)difftime(time(NULL
), cep
->connect_time
));
704 logit(LL_CHD
, "%05d %s connected %d seconds",
705 cep
->cdid
, cep
->name
,
706 (int)difftime(time(NULL
), cep
->connect_time
));
709 if ((cep
->inbytes
!= INVALID
) && (cep
->outbytes
!= INVALID
))
711 if ((cep
->ioutbytes
!= cep
->outbytes
) ||
712 (cep
->iinbytes
!= cep
->inbytes
))
714 logit(LL_CHD
, "%05d %s accounting: in %d, out %d (in %d, out %d)",
715 cep
->cdid
, cep
->name
,
716 cep
->inbytes
, cep
->outbytes
,
717 cep
->iinbytes
, cep
->ioutbytes
);
721 logit(LL_CHD
, "%05d %s accounting: in %d, out %d",
722 cep
->cdid
, cep
->name
,
723 cep
->inbytes
, cep
->outbytes
);
728 if (useacctfile
&& (cep
->connect_time
> 0))
731 char logdatetime
[41];
734 con_secs
= difftime(time(NULL
), cep
->connect_time
);
736 tp
= localtime(&cep
->connect_time
);
738 strftime(logdatetime
,40,I4B_TIME_FORMAT
,tp
);
740 if (cep
->inbytes
!= INVALID
&& cep
->outbytes
!= INVALID
)
742 fprintf(acctfp
, "%s - %s %s %d (%d) (%d/%d)\n",
743 logdatetime
, getlogdatetime(),
744 cep
->name
, cep
->charge
, con_secs
,
745 cep
->inbytes
, cep
->outbytes
);
749 fprintf(acctfp
, "%s - %s %s %d (%d)\n",
750 logdatetime
, getlogdatetime(),
751 cep
->name
, cep
->charge
, con_secs
);
755 /* set the B-channel inactive */
757 ctrl
= find_ctrl_state(cep
->isdncontrollerused
);
758 set_channel_idle(ctrl
, cep
->isdnchannelused
);
760 incr_free_channels(ctrl
);
762 cep
->connect_time
= 0;
764 next_state(cep
, EV_MDI
);
767 /*---------------------------------------------------------------------------*
768 * handle incoming DIALOUT message
769 *---------------------------------------------------------------------------*/
771 msg_dialout(msg_dialout_ind_t
*mp
)
773 struct cfg_entry
*cep
;
775 if ((cep
= find_by_device_for_dialout(mp
->driver
, mp
->driver_unit
)) == NULL
)
777 DBGL(DL_DRVR
, (logit(LL_DBG
, "msg_dialout: config entry reserved or no match")));
781 DBGL(DL_DRVR
, (logit(LL_DBG
, "msg_dialout: dial req from %s%d", cep
->usrdevicename
, mp
->driver_unit
)));
783 if (cep
->inout
== DIR_INONLY
)
785 dialresponse(cep
, DSTAT_INONLY
);
789 if (cep
->budget_calloutperiod
&& cep
->budget_calloutncalls
)
791 cep
->budget_calltype
= 0;
792 cep
->budget_callout_req
++;
794 if (cep
->budget_calloutncalls_cnt
== 0)
796 logit(LL_CHD
, "%05d %s no budget for calling out", 0, cep
->name
);
797 cep
->budget_callout_rej
++;
798 dialresponse(cep
, DSTAT_TFAIL
);
803 cep
->budget_calltype
= BUDGET_TYPE_COUT
;
807 if ((cep
->cdid
= get_cdid()) == 0)
809 DBGL(DL_DRVR
, (logit(LL_DBG
, "msg_dialout: get_cdid() returned 0!")));
814 cep
->last_charge
= 0;
816 next_state(cep
, EV_MDO
);
819 /*---------------------------------------------------------------------------*
820 * handle incoming DIALOUTNUMBER message
821 *---------------------------------------------------------------------------*/
823 msg_dialoutnumber(msg_dialoutnumber_ind_t
*mp
)
825 struct cfg_entry
*cep
;
827 if ((cep
= find_by_device_for_dialoutnumber(mp
->driver
, mp
->driver_unit
, mp
->cmdlen
, mp
->cmd
)) == NULL
)
829 DBGL(DL_DRVR
, (logit(LL_DBG
, "msg_dialoutnumber: config entry reserved or no match")));
833 DBGL(DL_DRVR
, (logit(LL_DBG
, "msg_dialoutnumber: dial req from %s%d", cep
->usrdevicename
, mp
->driver_unit
)));
835 if (cep
->inout
== DIR_INONLY
)
837 dialresponse(cep
, DSTAT_INONLY
);
841 if (cep
->budget_calloutperiod
&& cep
->budget_calloutncalls
)
843 cep
->budget_calltype
= 0;
844 cep
->budget_callout_req
++;
846 if (cep
->budget_calloutncalls_cnt
== 0)
848 logit(LL_CHD
, "%05d %s no budget for calling out", 0, cep
->name
);
849 cep
->budget_callout_rej
++;
850 dialresponse(cep
, DSTAT_TFAIL
);
855 cep
->budget_calltype
= BUDGET_TYPE_COUT
;
859 if ((cep
->cdid
= get_cdid()) == 0)
861 DBGL(DL_DRVR
, (logit(LL_DBG
, "msg_dialoutnumber: get_cdid() returned 0!")));
866 cep
->last_charge
= 0;
868 next_state(cep
, EV_MDO
);
871 /*---------------------------------------------------------------------------*
872 * handle incoming DRVRDISC_REQ message
873 *---------------------------------------------------------------------------*/
875 msg_drvrdisc_req(msg_drvrdisc_req_t
*mp
)
877 struct cfg_entry
*cep
;
879 DBGL(DL_DRVR
, (logit(LL_DBG
, "msg_drvrdisc_req for call %d", mp
->header
.cdid
)));
881 if ((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
883 DBGL(DL_DRVR
, (logit(LL_DBG
, "msg_drvrdisc_req: config entry not found")));
886 next_state(cep
, EV_DRQ
);
889 /*---------------------------------------------------------------------------*
890 * handle incoming ACCOUNTING message
891 *---------------------------------------------------------------------------*/
893 msg_accounting(msg_accounting_ind_t
*mp
)
895 struct cfg_entry
*cep
;
897 if ((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
899 logit(LL_WRN
, "msg_accounting: no config entry found!");
903 cep
->inbytes
= mp
->inbytes
;
904 cep
->iinbytes
= mp
->iinbytes
;
905 cep
->outbytes
= mp
->outbytes
;
906 cep
->ioutbytes
= mp
->ioutbytes
;
907 cep
->inbps
= mp
->inbps
;
908 cep
->outbps
= mp
->outbps
;
910 if (mp
->accttype
== ACCT_DURING
)
916 #ifdef I4B_EXTERNAL_MONITOR
917 if (do_monitor
&& accepted
)
918 monitor_evnt_acct(cep
);
923 /*---------------------------------------------------------------------------*
924 * handle incoming CHARGING message
925 *---------------------------------------------------------------------------*/
927 msg_charging_ind(msg_charging_ind_t
*mp
)
929 static const char *cttab
[] = {
935 struct cfg_entry
*cep
;
937 if ((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
939 logit(LL_WRN
, "msg_charging_ind: cdid not found");
943 if (mp
->units_type
< CHARGE_INVALID
|| mp
->units_type
> CHARGE_CALC
)
945 logit(LL_ERR
, "msg_charging: units_type %d out of range!", mp
->units_type
);
946 error_exit(1, "msg_charging: units_type %d out of range!", mp
->units_type
);
949 DBGL(DL_DRVR
, (logit(LL_DBG
, "msg_charging: %d unit(s) (%s)",
950 mp
->units
, cttab
[mp
->units_type
])));
952 cep
->charge
= mp
->units
;
954 switch (mp
->units_type
)
957 if ((cep
->unitlengthsrc
== ULSRC_DYN
) &&
958 (cep
->charge
!= cep
->last_charge
))
960 cep
->last_charge
= cep
->charge
;
968 display_ccharge(cep
, mp
->units
);
970 #ifdef I4B_EXTERNAL_MONITOR
971 if (do_monitor
&& accepted
)
972 monitor_evnt_charge(cep
, mp
->units
, 1);
978 /*---------------------------------------------------------------------------*
979 * handle incoming IDLE_TIMEOUT_IND message
980 *---------------------------------------------------------------------------*/
982 msg_idle_timeout_ind(msg_idle_timeout_ind_t
*mp
)
984 struct cfg_entry
*cep
;
986 if ((cep
= get_cep_by_cdid(mp
->header
.cdid
)) == NULL
)
988 logit(LL_WRN
, "msg_idle_timeout_ind: cdid not found!");
992 cep
->local_disconnect
= DISCON_LOC
;
994 DBGL(DL_DRVR
, (logit(LL_DBG
, "msg_idle_timeout_ind: idletimeout, kernel sent disconnect!")));
999 /*---------------------------------------------------------------------------*
1000 * handle incoming MSG_PACKET_IND message
1001 *---------------------------------------------------------------------------*/
1003 strapp(char *buf
, char *lim
, const char *txt
)
1005 while (*txt
&& buf
< lim
- 1)
1011 /*---------------------------------------------------------------------------*
1012 * handle incoming MSG_PACKET_IND message
1013 *---------------------------------------------------------------------------*/
1015 ipapp(char *buf
, char *lim
, unsigned long a
)
1017 unsigned long ma
= ntohl(a
);
1020 n
= snprintf(buf
, lim
- buf
, "%lu.%lu.%lu.%lu", (ma
>>24)&0xFF,
1021 (ma
>>16)&0xFF, (ma
>>8)&0xFF, (ma
)&0xFF);
1028 /*---------------------------------------------------------------------------*
1029 * handle incoming MSG_PACKET_IND message
1030 *---------------------------------------------------------------------------*/
1032 msg_packet_ind(msg_packet_ind_t
*mp
)
1034 struct cfg_entry
*cep
;
1039 const char *name
= "???";
1041 for (cep
= get_first_cfg_entry(); cep
; cep
= NEXT_CFE(cep
)) {
1042 if (cep
->usrdevice
== mp
->driver
&&
1043 cep
->usrdeviceunit
== mp
->driver_unit
)
1050 ip
= (struct ip
*)mp
->pktdata
;
1051 proto_hdr
= mp
->pktdata
+ ((ip
->ip_hl
)<<2);
1053 if (ip
->ip_p
== IPPROTO_TCP
)
1055 struct tcphdr
* tcp
= (struct tcphdr
*)proto_hdr
;
1057 cptr
= strapp(cptr
, tmp
+ sizeof(tmp
), "TCP ");
1058 cptr
= ipapp(cptr
, tmp
+ sizeof(tmp
), ip
->ip_src
.s_addr
);
1059 cptr
+= snprintf(cptr
, sizeof(tmp
) - (cptr
- tmp
),
1060 ":%u -> ", ntohs(tcp
->th_sport
));
1061 cptr
= ipapp(cptr
, tmp
+ sizeof(tmp
), ip
->ip_dst
.s_addr
);
1062 cptr
+= snprintf(cptr
, sizeof(tmp
) - (cptr
- tmp
),
1063 ":%u", ntohs(tcp
->th_dport
));
1065 if (tcp
->th_flags
& TH_FIN
)
1066 cptr
= strapp(cptr
, tmp
+ sizeof(tmp
), " FIN");
1067 if (tcp
->th_flags
& TH_SYN
)
1068 cptr
= strapp(cptr
, tmp
+ sizeof(tmp
), " SYN");
1069 if (tcp
->th_flags
& TH_RST
)
1070 cptr
= strapp(cptr
, tmp
+ sizeof(tmp
), " RST");
1071 if (tcp
->th_flags
& TH_PUSH
)
1072 cptr
= strapp(cptr
, tmp
+ sizeof(tmp
), " PUSH");
1073 if (tcp
->th_flags
& TH_ACK
)
1074 cptr
= strapp(cptr
, tmp
+ sizeof(tmp
), " ACK");
1075 if (tcp
->th_flags
& TH_URG
)
1076 cptr
= strapp(cptr
, tmp
+ sizeof(tmp
), " URG");
1078 else if (ip
->ip_p
== IPPROTO_UDP
)
1080 struct udphdr
* udp
= (struct udphdr
*)proto_hdr
;
1082 cptr
= strapp(cptr
, tmp
+ sizeof(tmp
), "UDP ");
1083 cptr
= ipapp(cptr
, tmp
+ sizeof(tmp
), ip
->ip_src
.s_addr
);
1084 cptr
+= snprintf(cptr
, sizeof(tmp
) - (cptr
- tmp
),
1085 ":%u -> ", ntohs(udp
->uh_sport
));
1086 cptr
= ipapp(cptr
, tmp
+ sizeof(tmp
), ip
->ip_dst
.s_addr
);
1087 cptr
+= snprintf(cptr
, sizeof(tmp
) - (cptr
- tmp
),
1088 ":%u", ntohs(udp
->uh_dport
));
1090 else if (ip
->ip_p
== IPPROTO_ICMP
)
1092 struct icmp
* icmp
= (struct icmp
*)proto_hdr
;
1094 cptr
+= snprintf(cptr
, sizeof(tmp
) - (cptr
- tmp
),
1095 "ICMP:%u.%u", icmp
->icmp_type
, icmp
->icmp_code
);
1096 cptr
= ipapp(cptr
, tmp
+ sizeof(tmp
), ip
->ip_src
.s_addr
);
1097 cptr
= strapp(cptr
, tmp
+ sizeof(tmp
), " -> ");
1098 cptr
= ipapp(cptr
, tmp
+ sizeof(tmp
), ip
->ip_dst
.s_addr
);
1102 cptr
+= snprintf(cptr
, sizeof(tmp
) - (cptr
- tmp
),
1103 "PROTO=%u ", ip
->ip_p
);
1104 cptr
= ipapp(cptr
, tmp
+ sizeof(tmp
), ip
->ip_src
.s_addr
);
1105 cptr
= strapp(cptr
, tmp
+ sizeof(tmp
), " -> ");
1106 cptr
= ipapp(cptr
, tmp
+ sizeof(tmp
), ip
->ip_dst
.s_addr
);
1109 logit(LL_PKT
, "%s %s %u %s", name
, mp
->direction
? "send" : "recv",
1110 ntohs(ip
->ip_len
), tmp
);
1114 * A new controller arrived or is gone away
1117 msg_ctrl_ev_ind(msg_ctrl_ev_ind_t
*mp
)
1119 logit(LL_DMN
, "controller %d %s", mp
->controller
, mp
->event
?"attached":"detached");
1121 /* new, add to controller list */
1122 init_new_controller(mp
->controller
);
1123 init_single_controller_protocol(find_ctrl_state(mp
->controller
));
1125 /* controller gone, remove */
1126 remove_ctrl_state(mp
->controller
);
1130 /*---------------------------------------------------------------------------*
1131 * get a cdid from kernel
1132 *---------------------------------------------------------------------------*/
1140 if ((ioctl(isdnfd
, I4B_CDID_REQ
, &mcr
)) < 0)
1142 logit(LL_ERR
, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno
));
1143 error_exit(1, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno
));
1149 /*---------------------------------------------------------------------------*
1150 * send message "connect request" to kernel
1151 *---------------------------------------------------------------------------*/
1153 sendm_connect_req(struct cfg_entry
*cep
)
1155 msg_connect_req_t mcr
;
1158 cep
->local_disconnect
= DISCON_REM
;
1160 cep
->unitlength
= get_current_rate(cep
, 1);
1162 mcr
.cdid
= cep
->cdid
;
1164 mcr
.controller
= cep
->isdncontrollerused
;
1165 mcr
.channel
= cep
->isdnchannelused
;
1166 mcr
.txdelay
= cep
->isdntxdelout
;
1168 mcr
.bprot
= cep
->b1protocol
;
1170 mcr
.driver
= cep
->usrdevice
;
1171 mcr
.driver_unit
= cep
->usrdeviceunit
;
1173 /* setup the shorthold data */
1174 mcr
.shorthold_data
.shorthold_algorithm
= cep
->shorthold_algorithm
;
1175 mcr
.shorthold_data
.unitlen_time
= cep
->unitlength
;
1176 mcr
.shorthold_data
.idle_time
= cep
->idle_time_out
;
1177 mcr
.shorthold_data
.earlyhup_time
= cep
->earlyhangup
;
1179 if (cep
->unitlengthsrc
== ULSRC_DYN
)
1180 mcr
.unitlen_method
= ULEN_METHOD_DYNAMIC
;
1182 mcr
.unitlen_method
= ULEN_METHOD_STATIC
;
1184 strlcpy(mcr
.dst_telno
, cep
->remote_phone_dialout
,
1185 sizeof(mcr
.dst_telno
));
1186 strlcpy(mcr
.src_telno
, cep
->local_phone_dialout
, sizeof(mcr
.src_telno
));
1188 cep
->last_dial_time
= time(NULL
);
1189 cep
->direction
= DIR_OUT
;
1191 DBGL(DL_CNST
, (logit(LL_DBG
, "sendm_connect_req: ctrl = %d, chan = %d", cep
->isdncontrollerused
, cep
->isdnchannelused
)));
1193 if ((ret
= ioctl(isdnfd
, I4B_CONNECT_REQ
, &mcr
)) < 0)
1195 logit(LL_ERR
, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno
));
1196 error_exit(1, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno
));
1199 decr_free_channels(find_ctrl_state(cep
->isdncontrollerused
));
1201 logit(LL_CHD
, "%05d %s dialing out from %s to %s",
1204 aliasing
? get_alias(cep
->local_phone_dialout
) : cep
->local_phone_dialout
,
1205 aliasing
? get_alias(cep
->remote_phone_dialout
) : cep
->remote_phone_dialout
);
1210 /*---------------------------------------------------------------------------*
1211 * send message "connect response" to kernel
1212 *---------------------------------------------------------------------------*/
1214 sendm_connect_resp(struct cfg_entry
*cep
, int cdid
, int response
, cause_t cause
)
1216 msg_connect_resp_t mcr
;
1221 mcr
.response
= response
;
1223 if (response
== SETUP_RESP_REJECT
)
1226 DBGL(DL_DRVR
, (logit(LL_DBG
, "sendm_connect_resp: reject, cause=0x%x", cause
)));
1228 else if (response
== SETUP_RESP_ACCEPT
)
1230 cep
->direction
= DIR_IN
;
1232 mcr
.txdelay
= cep
->isdntxdelin
;
1234 mcr
.bprot
= cep
->b1protocol
;
1236 mcr
.driver
= cep
->usrdevice
;
1237 mcr
.driver_unit
= cep
->usrdeviceunit
;
1239 mcr
.max_idle_time
= cep
->idle_time_in
;
1241 DBGL(DL_DRVR
, (logit(LL_DBG
, "sendm_connect_resp: accept")));
1244 if ((ret
= ioctl(isdnfd
, I4B_CONNECT_RESP
, &mcr
)) < 0)
1246 logit(LL_ERR
, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno
));
1247 error_exit(1, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno
));
1252 /*---------------------------------------------------------------------------*
1253 * send message "disconnect request" to kernel
1254 *---------------------------------------------------------------------------*/
1256 sendm_disconnect_req(struct cfg_entry
*cep
, cause_t cause
)
1258 msg_discon_req_t mcr
;
1261 mcr
.cdid
= cep
->cdid
;
1265 cep
->local_disconnect
= DISCON_LOC
;
1267 if ((ret
= ioctl(isdnfd
, I4B_DISCONNECT_REQ
, &mcr
)) < 0)
1269 logit(LL_ERR
, "sendm_disconnect_req: ioctl I4B_DISCONNECT_REQ failed: %s", strerror(errno
));
1273 DBGL(DL_DRVR
, (logit(LL_DBG
, "sendm_disconnect_req: sent DISCONNECT_REQ")));
1278 /*---------------------------------------------------------------------------*
1279 * send message "alert request" to kernel
1280 *---------------------------------------------------------------------------*/
1282 sendm_alert_req(struct cfg_entry
*cep
)
1284 msg_alert_req_t mar
;
1287 mar
.cdid
= cep
->cdid
;
1289 if ((ret
= ioctl(isdnfd
, I4B_ALERT_REQ
, &mar
)) < 0)
1291 logit(LL_ERR
, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno
));
1292 error_exit(1, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno
));
1296 DBGL(DL_DRVR
, (logit(LL_DBG
, "sendm_alert_req: sent ALERT_REQ")));