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 $
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)
63 char *src_tela = "ERROR-src_tela";
64 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)) == 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 log(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 log(LL_CHD, "%05d %s accepting: incoming call from %s to %s",
129 mp->header.cdid, cep->name, SRC, DST);
130 decr_free_channels(mp->controller);
131 next_state(cep, EV_MCI);
135 log(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 log(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);
146 cep->cdid = CDID_UNUSED;
150 decr_free_channels(mp->controller);
155 log(LL_CHD, "%05d %s alerting: incoming call from %s to %s (%s)",
156 mp->header.cdid, cep->name, SRC, DST, mp->display);
160 log(LL_CHD, "%05d %s alerting: incoming call from %s to %s",
161 mp->header.cdid, cep->name, SRC, DST);
163 next_state(cep, EV_ALRT);
169 log(LL_CHD, "%05d %s answering: incoming call from %s to %s (%s)",
170 mp->header.cdid, cep->name, SRC, DST, mp->display);
174 log(LL_CHD, "%05d %s answering: incoming call from %s to %s",
175 mp->header.cdid, cep->name, SRC, DST);
177 next_state(cep, EV_MCI);
184 /*XXX reserve channel ??? */ decr_free_channels(mp->controller);
186 if(cep->cdid == CDID_RESERVED)
188 log(LL_CHD, "%05d %s reserved: incoming call from %s to %s",
189 mp->header.cdid, cep->name, SRC, DST);
190 sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
192 (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
194 (CAUSET_I4B << 8) | CAUSE_I4B_REJECT);
196 /* no state change */
200 sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
202 (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
204 (CAUSET_I4B << 8) | CAUSE_I4B_REJECT);
206 if(cep->budget_callbackperiod && cep->budget_callbackncalls)
208 cep->budget_callback_req++;
209 cep->budget_calltype = 0;
210 if(cep->budget_callbackncalls_cnt == 0)
212 log(LL_CHD, "%05d %s no budget: call from %s to %s",
213 mp->header.cdid, cep->name, SRC, DST);
214 cep->cdid = CDID_UNUSED;
215 cep->budget_callback_rej++;
220 cep->budget_calltype = BUDGET_TYPE_CBACK;
224 log(LL_CHD, "%05d %s callback: incoming call from %s to %s",
225 mp->header.cdid, cep->name, SRC, DST);
227 cep->last_release_time = time(NULL);
228 cep->cdid = CDID_RESERVED;
229 next_state(cep, EV_CBRQ);
234 log(LL_WRN, "msg_connect_ind: unknown response type, tx SETUP_RESP_DNTCRE");
235 sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
238 handle_scrprs(mp->header.cdid, mp->scr_ind, mp->prs_ind, SRC);
243 /*---------------------------------------------------------------------------*
244 * handle incoming CONNECT_ACTIVE_IND message
245 *---------------------------------------------------------------------------*/
247 msg_connect_active_ind(msg_connect_active_ind_t *mp)
252 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
254 log(LL_WRN, "msg_connect_active_ind: cdid not found!");
258 cep->isdncontrollerused = mp->controller;
259 cep->isdnchannelused = mp->channel;
261 cep->aoc_now = cep->connect_time = time(NULL);
264 cep->aoc_valid = AOC_INVALID;
266 cep->local_disconnect = DISCON_REM;
268 cep->inbytes = INVALID;
269 cep->outbytes = INVALID;
272 device = bdrivername(cep->usrdevicename);
274 /* set the B-channel to active */
276 if((set_channel_busy(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
277 log(LL_ERR, "msg_connect_active_ind: set_channel_busy failed!");
279 if(cep->direction == DIR_OUT)
281 log(LL_CHD, "%05d %s outgoing call active (ctl %d, ch %d, %s%d)",
282 cep->cdid, cep->name,
283 cep->isdncontrollerused, cep->isdnchannelused,
284 bdrivername(cep->usrdevicename), cep->usrdeviceunit);
286 if(cep->budget_calltype)
288 if(cep->budget_calltype == BUDGET_TYPE_CBACK)
290 cep->budget_callback_done++;
291 cep->budget_callbackncalls_cnt--;
292 DBGL(DL_BDGT, (log(LL_DBG, "%s: new cback-budget = %d",
293 cep->name, cep->budget_callbackncalls_cnt)));
294 if(cep->budget_callbacks_file != NULL)
295 upd_callstat_file(cep->budget_callbacks_file, cep->budget_callbacksfile_rotate);
297 else if(cep->budget_calltype == BUDGET_TYPE_COUT)
299 cep->budget_callout_done++;
300 cep->budget_calloutncalls_cnt--;
301 DBGL(DL_BDGT, (log(LL_DBG, "%s: new cout-budget = %d",
302 cep->name, cep->budget_calloutncalls_cnt)));
303 if(cep->budget_callouts_file != NULL)
304 upd_callstat_file(cep->budget_callouts_file, cep->budget_calloutsfile_rotate);
306 cep->budget_calltype = 0;
311 log(LL_CHD, "%05d %s incoming call active (ctl %d, ch %d, %s%d)",
312 cep->cdid, cep->name,
313 cep->isdncontrollerused, cep->isdnchannelused,
314 bdrivername(cep->usrdevicename), cep->usrdeviceunit);
319 display_connect(cep);
321 #ifdef I4B_EXTERNAL_MONITOR
322 if(do_monitor && accepted)
323 monitor_evnt_connect(cep);
326 if(isdntime && (mp->datetime[0] != '\0'))
328 log(LL_DMN, "date/time from exchange = %s", mp->datetime);
331 next_state(cep, EV_MCAI);
334 /*---------------------------------------------------------------------------*
335 * handle incoming PROCEEDING_IND message
336 *---------------------------------------------------------------------------*/
338 msg_proceeding_ind(msg_proceeding_ind_t *mp)
342 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
344 log(LL_WRN, "msg_proceeding_ind: cdid not found!");
348 cep->isdncontrollerused = mp->controller;
349 cep->isdnchannelused = mp->channel;
351 /* set the B-channels active */
353 if((set_channel_busy(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
354 log(LL_ERR, "msg_proceeding_ind: set_channel_busy failed!");
356 log(LL_CHD, "%05d %s outgoing call proceeding (ctl %d, ch %d)",
357 cep->cdid, cep->name,
358 cep->isdncontrollerused, cep->isdnchannelused);
361 /*---------------------------------------------------------------------------*
362 * handle incoming ALERT_IND message
363 *---------------------------------------------------------------------------*/
365 msg_alert_ind(msg_alert_ind_t *mp)
369 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
371 log(LL_WRN, "msg_alert_ind: cdid not found!");
375 log(LL_CHD, "%05d %s incoming alert", cep->cdid, cep->name);
379 /*---------------------------------------------------------------------------*
380 * handle incoming L12STAT_IND message
381 *---------------------------------------------------------------------------*/
383 msg_l12stat_ind(msg_l12stat_ind_t *ml)
385 if((ml->controller < 0) || (ml->controller >= ncontroller))
387 log(LL_ERR, "msg_l12stat_ind: invalid controller number [%d]!", ml->controller);
393 display_l12stat(ml->controller, ml->layer, ml->state);
395 #ifdef I4B_EXTERNAL_MONITOR
396 if(do_monitor && accepted)
397 monitor_evnt_l12stat(ml->controller, ml->layer, ml->state);
400 DBGL(DL_CNST, (log(LL_DBG, "msg_l12stat_ind: unit %d, layer %d, state %d",
401 ml->controller, ml->layer, ml->state)));
403 if(ml->layer == LAYER_ONE)
405 if(ml->state == LAYER_IDLE)
406 isdn_ctrl_tab[ml->controller].l2stat = ml->state;
407 isdn_ctrl_tab[ml->controller].l1stat = ml->state;
409 else if(ml->layer == LAYER_TWO)
411 if(ml->state == LAYER_ACTIVE)
412 isdn_ctrl_tab[ml->controller].l1stat = ml->state;
413 isdn_ctrl_tab[ml->controller].l2stat = ml->state;
417 log(LL_ERR, "msg_l12stat_ind: invalid layer number [%d]!", ml->layer);
421 /*---------------------------------------------------------------------------*
422 * handle incoming TEIASG_IND message
423 *---------------------------------------------------------------------------*/
425 msg_teiasg_ind(msg_teiasg_ind_t *mt)
427 if((mt->controller < 0) || (mt->controller >= ncontroller))
429 log(LL_ERR, "msg_teiasg_ind: invalid controller number [%d]!", mt->controller);
435 display_tei(mt->controller, mt->tei);
437 #ifdef I4B_EXTERNAL_MONITOR
438 if(do_monitor && accepted)
439 monitor_evnt_tei(mt->controller, mt->tei);
442 DBGL(DL_CNST, (log(LL_DBG, "msg_teiasg_ind: unit %d, tei = %d",
443 mt->controller, mt->tei)));
445 isdn_ctrl_tab[mt->controller].tei = mt->tei;
448 /*---------------------------------------------------------------------------*
449 * handle incoming PDEACT_IND message
450 *---------------------------------------------------------------------------*/
452 msg_pdeact_ind(msg_pdeact_ind_t *md)
455 int ctrl = md->controller;
461 display_l12stat(ctrl, LAYER_ONE, LAYER_IDLE);
462 display_l12stat(ctrl, LAYER_TWO, LAYER_IDLE);
463 display_tei(ctrl, -1);
466 #ifdef I4B_EXTERNAL_MONITOR
467 if(do_monitor && accepted)
469 monitor_evnt_l12stat(ctrl, LAYER_ONE, LAYER_IDLE);
470 monitor_evnt_l12stat(ctrl, LAYER_TWO, LAYER_IDLE);
471 monitor_evnt_tei(ctrl, -1);
475 DBGL(DL_CNST, (log(LL_DBG, "msg_pdeact_ind: unit %d, persistent deactivation", ctrl)));
477 isdn_ctrl_tab[ctrl].l1stat = LAYER_IDLE;
478 isdn_ctrl_tab[ctrl].l2stat = LAYER_IDLE;
479 isdn_ctrl_tab[ctrl].tei = -1;
481 for(i=0; i < nentries; i++)
483 if((cfg_entry_tab[i].cdid != CDID_UNUSED) &&
484 (cfg_entry_tab[i].isdncontrollerused == ctrl))
486 cep = &cfg_entry_tab[i];
488 if(cep->cdid == CDID_RESERVED)
490 cep->state = ST_IDLE;
491 cep->cdid = CDID_UNUSED;
495 cep->cdid = CDID_UNUSED;
497 cep->last_release_time = time(NULL);
499 SET_CAUSE_TYPE(cep->disc_cause, CAUSET_I4B);
500 SET_CAUSE_VAL(cep->disc_cause, CAUSE_I4B_L1ERROR);
502 if(cep->direction == DIR_OUT)
504 log(LL_CHD, "%05d %s outgoing call disconnected (local)",
505 cep->cdid, cep->name);
509 log(LL_CHD, "%05d %s incoming call disconnected (local)",
510 cep->cdid, cep->name);
513 log(LL_CHD, "%05d %s cause %s",
514 cep->cdid, cep->name, print_i4b_cause(cep->disc_cause));
517 if(do_fullscreen && (cep->connect_time > 0))
518 display_disconnect(cep);
520 #ifdef I4B_EXTERNAL_MONITOR
521 if(do_monitor && accepted)
522 monitor_evnt_disconnect(cep);
525 if(cep->disconnectprog)
526 exec_connect_prog(cep, cep->disconnectprog, 1);
528 if(cep->connect_time > 0)
530 if(cep->direction == DIR_OUT)
532 log(LL_CHD, "%05d %s charging: %d units, %d seconds",
533 cep->cdid, cep->name, cep->charge,
534 (int)difftime(time(NULL), cep->connect_time));
538 log(LL_CHD, "%05d %s connected %d seconds",
539 cep->cdid, cep->name,
540 (int)difftime(time(NULL), cep->connect_time));
543 if((cep->inbytes != INVALID) && (cep->outbytes != INVALID))
545 if((cep->ioutbytes != cep->outbytes) ||
546 (cep->iinbytes != cep->inbytes))
548 log(LL_CHD, "%05d %s accounting: in %d, out %d (in %d, out %d)",
549 cep->cdid, cep->name,
550 cep->inbytes, cep->outbytes,
551 cep->iinbytes, cep->ioutbytes);
555 log(LL_CHD, "%05d %s accounting: in %d, out %d",
556 cep->cdid, cep->name,
557 cep->inbytes, cep->outbytes);
562 if(useacctfile && (cep->connect_time > 0))
565 char logdatetime[41];
568 con_secs = difftime(time(NULL), cep->connect_time);
570 tp = localtime(&cep->connect_time);
572 strftime(logdatetime,40,I4B_TIME_FORMAT,tp);
574 if(cep->inbytes != INVALID && cep->outbytes != INVALID)
576 fprintf(acctfp, "%s - %s %s %d (%d) (%d/%d)\n",
577 logdatetime, getlogdatetime(),
578 cep->name, cep->charge, con_secs,
579 cep->inbytes, cep->outbytes);
583 fprintf(acctfp, "%s - %s %s %d (%d)\n",
584 logdatetime, getlogdatetime(),
585 cep->name, cep->charge, con_secs);
589 /* set the B-channel inactive */
591 if((set_channel_idle(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
592 log(LL_ERR, "msg_pdeact_ind: set_channel_idle failed!");
594 incr_free_channels(cep->isdncontrollerused);
596 cep->connect_time = 0;
598 cep->state = ST_IDLE;
603 /*---------------------------------------------------------------------------*
604 * handle incoming NEGCOMP_IND message
605 *---------------------------------------------------------------------------*/
607 msg_negcomplete_ind(msg_negcomplete_ind_t *mp)
611 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
613 log(LL_WRN, "msg_negcomp_ind: cdid not found");
618 exec_connect_prog(cep, cep->connectprog, 0);
621 /*---------------------------------------------------------------------------*
622 * handle incoming IFSTATE_CHANGED indication
623 *---------------------------------------------------------------------------*/
625 msg_ifstatechg_ind(msg_ifstatechg_ind_t *mp)
630 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
632 log(LL_WRN, "msg_negcomp_ind: cdid not found");
636 device = bdrivername(cep->usrdevicename);
637 log(LL_DBG, "%s%d: switched to state %d", device, cep->usrdeviceunit, mp->state);
640 /*---------------------------------------------------------------------------*
641 * handle incoming DISCONNECT_IND message
642 *---------------------------------------------------------------------------*/
644 msg_disconnect_ind(msg_disconnect_ind_t *mp)
648 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
650 log(LL_WRN, "msg_disconnect_ind: cdid not found");
654 /* is this an aborted out-call prematurely called back? */
655 if (cep->saved_call.cdid == mp->header.cdid)
657 DBGL(DL_CNST, (log(LL_DBG, "aborted outcall %05d disconnected",
659 cep->saved_call.cdid = CDID_UNUSED;
661 set_channel_idle(cep->saved_call.controller, cep->saved_call.channel);
663 incr_free_channels(cep->saved_call.controller);
667 cep->last_release_time = time(NULL);
668 cep->disc_cause = mp->cause;
670 if(cep->direction == DIR_OUT)
672 log(LL_CHD, "%05d %s outgoing call disconnected %s",
673 cep->cdid, cep->name,
674 cep->local_disconnect == DISCON_LOC ?
675 "(local)" : "(remote)");
679 log(LL_CHD, "%05d %s incoming call disconnected %s",
680 cep->cdid, cep->name,
681 cep->local_disconnect == DISCON_LOC ?
682 "(local)" : "(remote)");
685 log(LL_CHD, "%05d %s cause %s",
686 cep->cdid, cep->name, print_i4b_cause(mp->cause));
689 if(do_fullscreen && (cep->connect_time > 0))
690 display_disconnect(cep);
692 #ifdef I4B_EXTERNAL_MONITOR
693 if(do_monitor && accepted)
694 monitor_evnt_disconnect(cep);
697 if(cep->disconnectprog)
698 exec_connect_prog(cep, cep->disconnectprog, 1);
700 if(cep->connect_time > 0)
702 if(cep->direction == DIR_OUT)
704 log(LL_CHD, "%05d %s charging: %d units, %d seconds",
705 cep->cdid, cep->name, cep->charge,
706 (int)difftime(time(NULL), cep->connect_time));
710 log(LL_CHD, "%05d %s connected %d seconds",
711 cep->cdid, cep->name,
712 (int)difftime(time(NULL), cep->connect_time));
715 if((cep->inbytes != INVALID) && (cep->outbytes != INVALID))
717 if((cep->ioutbytes != cep->outbytes) ||
718 (cep->iinbytes != cep->inbytes))
720 log(LL_CHD, "%05d %s accounting: in %d, out %d (in %d, out %d)",
721 cep->cdid, cep->name,
722 cep->inbytes, cep->outbytes,
723 cep->iinbytes, cep->ioutbytes);
727 log(LL_CHD, "%05d %s accounting: in %d, out %d",
728 cep->cdid, cep->name,
729 cep->inbytes, cep->outbytes);
734 if(useacctfile && (cep->connect_time > 0))
737 char logdatetime[41];
740 con_secs = difftime(time(NULL), cep->connect_time);
742 tp = localtime(&cep->connect_time);
744 strftime(logdatetime,40,I4B_TIME_FORMAT,tp);
746 if(cep->inbytes != INVALID && cep->outbytes != INVALID)
748 fprintf(acctfp, "%s - %s %s %d (%d) (%d/%d)\n",
749 logdatetime, getlogdatetime(),
750 cep->name, cep->charge, con_secs,
751 cep->inbytes, cep->outbytes);
755 fprintf(acctfp, "%s - %s %s %d (%d)\n",
756 logdatetime, getlogdatetime(),
757 cep->name, cep->charge, con_secs);
761 /* set the B-channel inactive */
763 set_channel_idle(cep->isdncontrollerused, cep->isdnchannelused);
765 incr_free_channels(cep->isdncontrollerused);
767 cep->connect_time = 0;
768 cep->cdid = CDID_UNUSED;
770 next_state(cep, EV_MDI);
773 /*---------------------------------------------------------------------------*
774 * handle incoming DIALOUT message
775 *---------------------------------------------------------------------------*/
777 msg_dialout(msg_dialout_ind_t *mp)
781 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
783 if((cep = find_by_device_for_dialout(mp->driver, mp->driver_unit)) == NULL)
785 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: config entry reserved or no match")));
789 if(cep->inout == DIR_INONLY)
791 dialresponse(cep, DSTAT_INONLY);
795 if(cep->budget_calloutperiod && cep->budget_calloutncalls)
797 cep->budget_calltype = 0;
798 cep->budget_callout_req++;
800 if(cep->budget_calloutncalls_cnt == 0)
802 log(LL_CHD, "%05d %s no budget for calling out", 0, cep->name);
803 cep->budget_callout_rej++;
804 dialresponse(cep, DSTAT_TFAIL);
809 cep->budget_calltype = BUDGET_TYPE_COUT;
813 if((cep->cdid = get_cdid()) == 0)
815 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: get_cdid() returned 0!")));
820 cep->last_charge = 0;
823 next_state(cep, EV_MDO);
826 /*---------------------------------------------------------------------------*
827 * handle incoming DIALOUTNUMBER message
828 *---------------------------------------------------------------------------*/
830 msg_dialoutnumber(msg_dialoutnumber_ind_t *mp)
834 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialoutnumber: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
836 if((cep = find_by_device_for_dialoutnumber(mp->driver, mp->driver_unit, mp->cmdlen, mp->cmd)) == NULL)
838 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialoutnumber: config entry reserved or no match")));
842 if(cep->inout == DIR_INONLY)
844 dialresponse(cep, DSTAT_INONLY);
848 if(cep->budget_calloutperiod && cep->budget_calloutncalls)
850 cep->budget_calltype = 0;
851 cep->budget_callout_req++;
853 if(cep->budget_calloutncalls_cnt == 0)
855 log(LL_CHD, "%05d %s no budget for calling out", 0, cep->name);
856 cep->budget_callout_rej++;
857 dialresponse(cep, DSTAT_TFAIL);
862 cep->budget_calltype = BUDGET_TYPE_COUT;
866 if((cep->cdid = get_cdid()) == 0)
868 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialoutnumber: get_cdid() returned 0!")));
872 cep->keypad[0] = '\0';
874 cep->last_charge = 0;
877 next_state(cep, EV_MDO);
880 /*---------------------------------------------------------------------------*
881 * handle incoming KEYPAD message
882 *---------------------------------------------------------------------------*/
884 msg_keypad(msg_keypad_ind_t *mp)
888 DBGL(DL_DRVR, (log(LL_DBG, "msg_keypad: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
890 if((cep = find_by_device_for_keypad(mp->driver, mp->driver_unit, mp->cmdlen, mp->cmd)) == NULL)
892 DBGL(DL_DRVR, (log(LL_DBG, "msg_keypad: config entry reserved or no match")));
896 if(cep->inout == DIR_INONLY)
898 dialresponse(cep, DSTAT_INONLY);
902 if(cep->budget_calloutperiod && cep->budget_calloutncalls)
904 cep->budget_calltype = 0;
905 cep->budget_callout_req++;
907 if(cep->budget_calloutncalls_cnt == 0)
909 log(LL_CHD, "%05d %s no budget for calling out", 0, cep->name);
910 cep->budget_callout_rej++;
911 dialresponse(cep, DSTAT_TFAIL);
916 cep->budget_calltype = BUDGET_TYPE_COUT;
920 if((cep->cdid = get_cdid()) == 0)
922 DBGL(DL_DRVR, (log(LL_DBG, "msg_keypad: get_cdid() returned 0!")));
927 cep->last_charge = 0;
930 next_state(cep, EV_MDO);
933 /*---------------------------------------------------------------------------*
934 * handle incoming DRVRDISC_REQ message
935 *---------------------------------------------------------------------------*/
937 msg_drvrdisc_req(msg_drvrdisc_req_t *mp)
941 DBGL(DL_DRVR, (log(LL_DBG, "msg_drvrdisc_req: req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
943 if((cep = get_cep_by_driver(mp->driver, mp->driver_unit)) == NULL)
945 DBGL(DL_DRVR, (log(LL_DBG, "msg_drvrdisc_req: config entry not found")));
948 next_state(cep, EV_DRQ);
951 /*---------------------------------------------------------------------------*
952 * handle incoming ACCOUNTING message
953 *---------------------------------------------------------------------------*/
955 msg_accounting(msg_accounting_ind_t *mp)
959 if((cep = find_active_entry_by_driver(mp->driver, mp->driver_unit)) == NULL)
961 log(LL_WRN, "msg_accounting: no config entry found!");
965 cep->inbytes = mp->inbytes;
966 cep->iinbytes = mp->iinbytes;
967 cep->outbytes = mp->outbytes;
968 cep->ioutbytes = mp->ioutbytes;
969 cep->inbps = mp->inbps;
970 cep->outbps = mp->outbps;
972 if(mp->accttype == ACCT_DURING)
978 #ifdef I4B_EXTERNAL_MONITOR
979 if(do_monitor && accepted)
980 monitor_evnt_acct(cep);
985 /*---------------------------------------------------------------------------*
986 * handle incoming CHARGING message
987 *---------------------------------------------------------------------------*/
989 msg_charging_ind(msg_charging_ind_t *mp)
991 static char *cttab[] = {
999 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
1001 log(LL_WRN, "msg_charging_ind: cdid not found");
1005 if(mp->units_type < CHARGE_INVALID || mp->units_type > CHARGE_CALC)
1007 log(LL_ERR, "msg_charging: units_type %d out of range!", mp->units_type);
1008 error_exit(1, "msg_charging: units_type %d out of range!", mp->units_type);
1011 DBGL(DL_DRVR, (log(LL_DBG, "msg_charging: %d unit(s) (%s)",
1012 mp->units, cttab[mp->units_type])));
1014 cep->charge = mp->units;
1016 switch(mp->units_type)
1019 if((cep->unitlengthsrc == ULSRC_DYN) &&
1020 (cep->charge != cep->last_charge))
1022 cep->last_charge = cep->charge;
1030 display_ccharge(cep, mp->units);
1032 #ifdef I4B_EXTERNAL_MONITOR
1033 if(do_monitor && accepted)
1034 monitor_evnt_charge(cep, mp->units, 1);
1040 /*---------------------------------------------------------------------------*
1041 * handle incoming IDLE_TIMEOUT_IND message
1042 *---------------------------------------------------------------------------*/
1044 msg_idle_timeout_ind(msg_idle_timeout_ind_t *mp)
1048 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
1050 log(LL_WRN, "msg_idle_timeout_ind: cdid not found!");
1054 cep->local_disconnect = DISCON_LOC;
1056 DBGL(DL_DRVR, (log(LL_DBG, "msg_idle_timeout_ind: idletimeout, kernel sent disconnect!")));
1058 check_and_kill(cep);
1061 /*---------------------------------------------------------------------------*
1062 * handle incoming MSG_PACKET_IND message
1063 *---------------------------------------------------------------------------*/
1065 strapp(char *buf, const char *txt)
1073 /*---------------------------------------------------------------------------*
1074 * handle incoming MSG_PACKET_IND message
1075 *---------------------------------------------------------------------------*/
1077 ipapp(char *buf, unsigned long a )
1079 unsigned long ma = ntohl( a );
1081 buf += sprintf(buf, "%lu.%lu.%lu.%lu",
1089 /*---------------------------------------------------------------------------*
1090 * handle incoming MSG_PACKET_IND message
1091 *---------------------------------------------------------------------------*/
1093 msg_packet_ind(msg_packet_ind_t *mp)
1103 for(i=0; i < nentries; i++)
1105 cep = &cfg_entry_tab[i]; /* ptr to config entry */
1107 if(cep->usrdevicename == mp->driver &&
1108 cep->usrdeviceunit == mp->driver_unit)
1115 ip = (struct ip*)mp->pktdata;
1116 proto_hdr = mp->pktdata + ((ip->ip_hl)<<2);
1118 if( ip->ip_p == IPPROTO_TCP )
1120 struct tcphdr* tcp = (struct tcphdr*)proto_hdr;
1122 cptr = strapp( cptr, "TCP " );
1123 cptr = ipapp( cptr, ip->ip_src.s_addr );
1124 cptr += sprintf( cptr, ":%u -> ", ntohs( tcp->th_sport ) );
1125 cptr = ipapp( cptr, ip->ip_dst.s_addr );
1126 cptr += sprintf( cptr, ":%u", ntohs( tcp->th_dport ) );
1128 if(tcp->th_flags & TH_FIN) cptr = strapp( cptr, " FIN" );
1129 if(tcp->th_flags & TH_SYN) cptr = strapp( cptr, " SYN" );
1130 if(tcp->th_flags & TH_RST) cptr = strapp( cptr, " RST" );
1131 if(tcp->th_flags & TH_PUSH) cptr = strapp( cptr, " PUSH" );
1132 if(tcp->th_flags & TH_ACK) cptr = strapp( cptr, " ACK" );
1133 if(tcp->th_flags & TH_URG) cptr = strapp( cptr, " URG" );
1135 else if( ip->ip_p == IPPROTO_UDP )
1137 struct udphdr* udp = (struct udphdr*)proto_hdr;
1139 cptr = strapp( cptr, "UDP " );
1140 cptr = ipapp( cptr, ip->ip_src.s_addr );
1141 cptr += sprintf( cptr, ":%u -> ", ntohs( udp->uh_sport ) );
1142 cptr = ipapp( cptr, ip->ip_dst.s_addr );
1143 cptr += sprintf( cptr, ":%u", ntohs( udp->uh_dport ) );
1145 else if( ip->ip_p == IPPROTO_ICMP )
1147 struct icmp* icmp = (struct icmp*)proto_hdr;
1149 cptr += sprintf( cptr, "ICMP:%u.%u", icmp->icmp_type, icmp->icmp_code);
1150 cptr = ipapp( cptr, ip->ip_src.s_addr );
1151 cptr = strapp( cptr, " -> " );
1152 cptr = ipapp( cptr, ip->ip_dst.s_addr );
1156 cptr += sprintf( cptr, "PROTO=%u ", ip->ip_p);
1157 cptr = ipapp( cptr, ip->ip_src.s_addr);
1158 cptr = strapp( cptr, " -> " );
1159 cptr = ipapp( cptr, ip->ip_dst.s_addr);
1162 log(LL_PKT, "%s %s %u %s",
1163 name, mp->direction ? "send" : "recv",
1164 ntohs( ip->ip_len ), tmp );
1167 /*---------------------------------------------------------------------------*
1168 * get a cdid from kernel
1169 *---------------------------------------------------------------------------*/
1177 if((ioctl(isdnfd, I4B_CDID_REQ, &mcr)) < 0)
1179 log(LL_ERR, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno));
1180 error_exit(1, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno));
1186 /*---------------------------------------------------------------------------*
1187 * send message "connect request" to kernel
1188 *---------------------------------------------------------------------------*/
1190 sendm_connect_req(cfg_entry_t *cep)
1192 msg_connect_req_t mcr;
1195 cep->local_disconnect = DISCON_REM;
1197 cep->unitlength = get_current_rate(cep, 1);
1199 mcr.cdid = cep->cdid;
1201 mcr.controller = cep->isdncontrollerused;
1202 mcr.channel = cep->isdnchannelused;
1203 mcr.txdelay = cep->isdntxdelout;
1205 mcr.bprot = cep->b1protocol;
1207 mcr.driver = cep->usrdevicename;
1208 mcr.driver_unit = cep->usrdeviceunit;
1210 /* setup the shorthold data */
1211 mcr.shorthold_data.shorthold_algorithm = cep->shorthold_algorithm;
1212 mcr.shorthold_data.unitlen_time = cep->unitlength;
1213 mcr.shorthold_data.idle_time = cep->idle_time_out;
1214 mcr.shorthold_data.earlyhup_time = cep->earlyhangup;
1216 if(cep->unitlengthsrc == ULSRC_DYN)
1217 mcr.unitlen_method = ULEN_METHOD_DYNAMIC;
1219 mcr.unitlen_method = ULEN_METHOD_STATIC;
1221 strcpy(mcr.dst_telno, cep->remote_phone_dialout);
1222 strcpy(mcr.src_telno, cep->local_phone_dialout);
1223 strcpy(mcr.keypad, cep->keypad);
1225 cep->last_dial_time = time(NULL);
1226 cep->direction = DIR_OUT;
1228 DBGL(DL_CNST, (log(LL_DBG, "sendm_connect_req: ctrl = %d, chan = %d", cep->isdncontrollerused, cep->isdnchannelused)));
1230 if((ret = ioctl(isdnfd, I4B_CONNECT_REQ, &mcr)) < 0)
1232 log(LL_ERR, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno));
1233 error_exit(1, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno));
1236 decr_free_channels(cep->isdncontrollerused);
1238 log(LL_CHD, "%05d %s dialing out from %s to %s",
1241 aliasing ? get_alias(cep->local_phone_dialout) : cep->local_phone_dialout,
1242 aliasing ? get_alias(cep->remote_phone_dialout) : cep->remote_phone_dialout);
1247 /*---------------------------------------------------------------------------*
1248 * send message "connect response" to kernel
1249 *---------------------------------------------------------------------------*/
1251 sendm_connect_resp(cfg_entry_t *cep, int cdid, int response, cause_t cause)
1253 msg_connect_resp_t mcr;
1258 mcr.response = response;
1260 if(response == SETUP_RESP_REJECT)
1263 DBGL(DL_DRVR, (log(LL_DBG, "sendm_connect_resp: reject, cause=0x%x", cause)));
1265 else if(response == SETUP_RESP_ACCEPT)
1267 cep->direction = DIR_IN;
1269 mcr.txdelay = cep->isdntxdelin;
1271 mcr.bprot = cep->b1protocol;
1273 mcr.driver = cep->usrdevicename;
1274 mcr.driver_unit = cep->usrdeviceunit;
1276 mcr.max_idle_time = cep->idle_time_in;
1278 DBGL(DL_DRVR, (log(LL_DBG, "sendm_connect_resp: accept")));
1281 if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &mcr)) < 0)
1283 log(LL_ERR, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno));
1284 error_exit(1, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno));
1289 /*---------------------------------------------------------------------------*
1290 * send message "disconnect request" to kernel
1291 *---------------------------------------------------------------------------*/
1293 sendm_disconnect_req(cfg_entry_t *cep, cause_t cause)
1295 msg_discon_req_t mcr;
1298 mcr.cdid = cep->cdid;
1302 cep->local_disconnect = DISCON_LOC;
1304 if((ret = ioctl(isdnfd, I4B_DISCONNECT_REQ, &mcr)) < 0)
1306 log(LL_ERR, "sendm_disconnect_req: ioctl I4B_DISCONNECT_REQ failed: %s", strerror(errno));
1310 DBGL(DL_DRVR, (log(LL_DBG, "sendm_disconnect_req: sent DISCONNECT_REQ")));
1315 /*---------------------------------------------------------------------------*
1316 * send message "alert request" to kernel
1317 *---------------------------------------------------------------------------*/
1319 sendm_alert_req(cfg_entry_t *cep)
1321 msg_alert_req_t mar;
1324 mar.cdid = cep->cdid;
1326 if((ret = ioctl(isdnfd, I4B_ALERT_REQ, &mar)) < 0)
1328 log(LL_ERR, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno));
1329 error_exit(1, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno));
1333 DBGL(DL_DRVR, (log(LL_DBG, "sendm_alert_req: sent ALERT_REQ")));