2 * Copyright (c) 1997, 2002 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 * --------------------------------------------------
32 * last edit-date: [Sat May 13 13:09:33 2006]
34 *---------------------------------------------------------------------------*/
38 #include <sys/socket.h>
40 #include <net/if_types.h>
42 #if defined(__FreeBSD__)
43 #include <net/if_var.h>
46 #include <netinet/in.h>
47 #include <netinet/in_systm.h>
48 #include <netinet/in_var.h>
49 #include <netinet/ip.h>
50 #include <netinet/tcp.h>
51 #include <netinet/udp.h>
52 #include <netinet/ip_icmp.h>
54 /*---------------------------------------------------------------------------*
55 * handle incoming CONNECT_IND (=SETUP) message
56 *---------------------------------------------------------------------------*/
58 msg_connect_ind(msg_connect_ind_t *mp)
61 char *src_tela = "ERROR-src_tela";
62 char *dst_tela = "ERROR-dst_tela";
64 #define SRC (aliasing == 0 ? mp->src_telno : src_tela)
65 #define DST (aliasing == 0 ? mp->dst_telno : dst_tela)
67 /* Add prefixes. All preexisting alias files are useless
71 add_number_prefix(mp->src_telno, mp->src_ton);
72 add_number_prefix(mp->dst_telno, mp->dst_ton);
77 src_tela = get_alias(mp->src_telno);
78 dst_tela = get_alias(mp->dst_telno);
81 if((cep = find_matching_entry_incoming(mp)) == NULL)
83 /* log message generated in find_matching_entry_incoming() */
84 sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
85 handle_scrprs(mp->header.cdid, mp->scr_ind, mp->prs_ind, SRC);
89 if(cep->cdid != CDID_UNUSED && cep->cdid != CDID_RESERVED)
92 * This is an incoming call on a number we just dialed out.
93 * Stop our dial-out and accept the incoming call.
95 if(cep->saved_call.cdid != CDID_UNUSED &&
96 cep->saved_call.cdid != CDID_RESERVED)
100 /* disconnect old, not new */
103 cep->cdid = cep->saved_call.cdid;
104 sendm_disconnect_req(cep, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
108 * Shortcut the state machine and mark this
111 /* XXX */ cep->state = ST_IDLE; /* this is an invalid */
113 /* so no next_state() */
114 /* we have to wait here for an incoming */
115 /* disconnect message !!! (-hm) */
119 if(cep->inout == DIR_OUTONLY)
121 llog(LL_CHD, "%05d %s incoming call from %s to %s not allowed by configuration!",
122 mp->header.cdid, cep->name, SRC, DST);
123 sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
124 handle_scrprs(mp->header.cdid, mp->scr_ind, mp->prs_ind, SRC);
129 cep->last_charge = 0;
131 switch(cep->dialin_reaction)
134 llog(LL_CHD, "%05d %s accepting: incoming call from %s to %s",
135 mp->header.cdid, cep->name, SRC, DST);
136 decr_free_channels(mp->controller);
137 next_state(cep, EV_MCI);
141 llog(LL_CHD, "%05d %s rejecting: incoming call from %s to %s",
142 mp->header.cdid, cep->name, SRC, DST);
143 sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
144 (CAUSET_I4B << 8) | CAUSE_I4B_REJECT);
145 cep->cdid = CDID_UNUSED;
149 llog(LL_CHD, "%05d %s ignoring: incoming call from %s to %s",
150 mp->header.cdid, cep->name, SRC, DST);
151 sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
152 cep->cdid = CDID_UNUSED;
156 decr_free_channels(mp->controller);
161 llog(LL_CHD, "%05d %s alerting: incoming call from %s to %s (%s)",
162 mp->header.cdid, cep->name, SRC, DST, mp->display);
166 llog(LL_CHD, "%05d %s alerting: incoming call from %s to %s",
167 mp->header.cdid, cep->name, SRC, DST);
169 next_state(cep, EV_ALRT);
175 llog(LL_CHD, "%05d %s answering: incoming call from %s to %s (%s)",
176 mp->header.cdid, cep->name, SRC, DST, mp->display);
180 llog(LL_CHD, "%05d %s answering: incoming call from %s to %s",
181 mp->header.cdid, cep->name, SRC, DST);
183 next_state(cep, EV_MCI);
190 /*XXX reserve channel ??? */ decr_free_channels(mp->controller);
192 if(cep->cdid == CDID_RESERVED)
194 llog(LL_CHD, "%05d %s reserved: incoming call from %s to %s",
195 mp->header.cdid, cep->name, SRC, DST);
196 sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
198 (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
200 (CAUSET_I4B << 8) | CAUSE_I4B_REJECT);
202 /* no state change */
206 sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
208 (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
210 (CAUSET_I4B << 8) | CAUSE_I4B_REJECT);
212 if(cep->budget_callbackperiod && cep->budget_callbackncalls)
214 cep->budget_callback_req++;
215 cep->budget_calltype = 0;
216 if(cep->budget_callbackncalls_cnt == 0)
218 llog(LL_CHD, "%05d %s no budget: call from %s to %s",
219 mp->header.cdid, cep->name, SRC, DST);
220 cep->cdid = CDID_UNUSED;
221 cep->budget_callback_rej++;
226 cep->budget_calltype = BUDGET_TYPE_CBACK;
230 llog(LL_CHD, "%05d %s callback: incoming call from %s to %s",
231 mp->header.cdid, cep->name, SRC, DST);
233 cep->last_release_time = time(NULL);
234 cep->cdid = CDID_RESERVED;
235 next_state(cep, EV_CBRQ);
240 llog(LL_WRN, "msg_connect_ind: unknown response type, tx SETUP_RESP_DNTCRE");
241 sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
244 handle_scrprs(mp->header.cdid, mp->scr_ind, mp->prs_ind, SRC);
249 /*---------------------------------------------------------------------------*
250 * handle incoming CONNECT_ACTIVE_IND message
251 *---------------------------------------------------------------------------*/
253 msg_connect_active_ind(msg_connect_active_ind_t *mp)
258 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
260 llog(LL_WRN, "msg_connect_active_ind: cdid not found!");
264 cep->isdncontrollerused = mp->controller;
265 cep->isdnchannelused = mp->channel;
267 cep->aoc_now = cep->connect_time = time(NULL);
270 cep->aoc_valid = AOC_INVALID;
272 cep->local_disconnect = DISCON_REM;
274 cep->inbytes = INVALID;
275 cep->outbytes = INVALID;
278 device = bdrivername(cep->usrdevicename);
280 /* set the B-channel to active */
282 if((set_channel_busy(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
283 llog(LL_ERR, "msg_connect_active_ind: set_channel_busy failed!");
285 if(cep->direction == DIR_OUT)
287 llog(LL_CHD, "%05d %s outgoing call active (ctl %d, ch %d, %s%d)",
288 cep->cdid, cep->name,
289 cep->isdncontrollerused, cep->isdnchannelused,
290 bdrivername(cep->usrdevicename), cep->usrdeviceunit);
292 if(cep->budget_calltype)
294 if(cep->budget_calltype == BUDGET_TYPE_CBACK)
296 cep->budget_callback_done++;
297 cep->budget_callbackncalls_cnt--;
298 DBGL(DL_BDGT, (llog(LL_DBG, "%s: new cback-budget = %d",
299 cep->name, cep->budget_callbackncalls_cnt)));
300 if(cep->budget_callbacks_file != NULL)
301 upd_callstat_file(cep->budget_callbacks_file, cep->budget_callbacksfile_rotate);
303 else if(cep->budget_calltype == BUDGET_TYPE_COUT)
305 cep->budget_callout_done++;
306 cep->budget_calloutncalls_cnt--;
307 DBGL(DL_BDGT, (llog(LL_DBG, "%s: new cout-budget = %d",
308 cep->name, cep->budget_calloutncalls_cnt)));
309 if(cep->budget_callouts_file != NULL)
310 upd_callstat_file(cep->budget_callouts_file, cep->budget_calloutsfile_rotate);
312 cep->budget_calltype = 0;
317 llog(LL_CHD, "%05d %s incoming call active (ctl %d, ch %d, %s%d)",
318 cep->cdid, cep->name,
319 cep->isdncontrollerused, cep->isdnchannelused,
320 bdrivername(cep->usrdevicename), cep->usrdeviceunit);
325 display_connect(cep);
327 #ifdef I4B_EXTERNAL_MONITOR
328 if(do_monitor && accepted)
329 monitor_evnt_connect(cep);
332 if(isdntime && (mp->datetime[0] != '\0'))
334 llog(LL_DMN, "date/time from exchange = %s", mp->datetime);
337 next_state(cep, EV_MCAI);
340 /*---------------------------------------------------------------------------*
341 * handle incoming PROCEEDING_IND message
342 *---------------------------------------------------------------------------*/
344 msg_proceeding_ind(msg_proceeding_ind_t *mp)
348 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
350 llog(LL_WRN, "msg_proceeding_ind: cdid not found!");
354 cep->isdncontrollerused = mp->controller;
355 cep->isdnchannelused = mp->channel;
357 /* set the B-channels active */
359 if((set_channel_busy(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
360 llog(LL_ERR, "msg_proceeding_ind: set_channel_busy failed!");
362 llog(LL_CHD, "%05d %s outgoing call proceeding (ctl %d, ch %d)",
363 cep->cdid, cep->name,
364 cep->isdncontrollerused, cep->isdnchannelused);
367 /*---------------------------------------------------------------------------*
368 * handle incoming ALERT_IND message
369 *---------------------------------------------------------------------------*/
371 msg_alert_ind(msg_alert_ind_t *mp)
375 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
377 llog(LL_WRN, "msg_alert_ind: cdid not found!");
381 llog(LL_CHD, "%05d %s incoming alert", cep->cdid, cep->name);
385 /*---------------------------------------------------------------------------*
386 * handle incoming L12STAT_IND message
387 *---------------------------------------------------------------------------*/
389 msg_l12stat_ind(msg_l12stat_ind_t *ml)
391 if((ml->controller < 0) || (ml->controller >= ncontroller))
393 llog(LL_ERR, "msg_l12stat_ind: invalid controller number [%d]!", ml->controller);
399 display_l12stat(ml->controller, ml->layer, ml->state);
401 #ifdef I4B_EXTERNAL_MONITOR
402 if(do_monitor && accepted)
403 monitor_evnt_l12stat(ml->controller, ml->layer, ml->state);
406 DBGL(DL_CNST, (llog(LL_DBG, "msg_l12stat_ind: unit %d, layer %d, state %d",
407 ml->controller, ml->layer, ml->state)));
409 if(ml->layer == LAYER_ONE)
411 if(ml->state == LAYER_IDLE)
412 isdn_ctrl_tab[ml->controller].l2stat = ml->state;
413 isdn_ctrl_tab[ml->controller].l1stat = ml->state;
415 else if(ml->layer == LAYER_TWO)
417 if(ml->state == LAYER_ACTIVE)
418 isdn_ctrl_tab[ml->controller].l1stat = ml->state;
419 isdn_ctrl_tab[ml->controller].l2stat = ml->state;
423 llog(LL_ERR, "msg_l12stat_ind: invalid layer number [%d]!", ml->layer);
427 /*---------------------------------------------------------------------------*
428 * handle incoming TEIASG_IND message
429 *---------------------------------------------------------------------------*/
431 msg_teiasg_ind(msg_teiasg_ind_t *mt)
433 if((mt->controller < 0) || (mt->controller >= ncontroller))
435 llog(LL_ERR, "msg_teiasg_ind: invalid controller number [%d]!", mt->controller);
441 display_tei(mt->controller, mt->tei);
443 #ifdef I4B_EXTERNAL_MONITOR
444 if(do_monitor && accepted)
445 monitor_evnt_tei(mt->controller, mt->tei);
448 DBGL(DL_CNST, (llog(LL_DBG, "msg_teiasg_ind: unit %d, tei = %d",
449 mt->controller, mt->tei)));
451 isdn_ctrl_tab[mt->controller].tei = mt->tei;
454 /*---------------------------------------------------------------------------*
455 * handle incoming PDEACT_IND message
456 *---------------------------------------------------------------------------*/
458 msg_pdeact_ind(msg_pdeact_ind_t *md)
461 int ctrl = md->controller;
467 display_l12stat(ctrl, LAYER_ONE, LAYER_IDLE);
468 display_l12stat(ctrl, LAYER_TWO, LAYER_IDLE);
469 display_tei(ctrl, -1);
472 #ifdef I4B_EXTERNAL_MONITOR
473 if(do_monitor && accepted)
475 monitor_evnt_l12stat(ctrl, LAYER_ONE, LAYER_IDLE);
476 monitor_evnt_l12stat(ctrl, LAYER_TWO, LAYER_IDLE);
477 monitor_evnt_tei(ctrl, -1);
481 DBGL(DL_CNST, (llog(LL_DBG, "msg_pdeact_ind: unit %d, persistent deactivation", ctrl)));
483 isdn_ctrl_tab[ctrl].l1stat = LAYER_IDLE;
484 isdn_ctrl_tab[ctrl].l2stat = LAYER_IDLE;
485 isdn_ctrl_tab[ctrl].tei = -1;
487 for(i=0; i < nentries; i++)
489 if((cfg_entry_tab[i].cdid != CDID_UNUSED) &&
490 (cfg_entry_tab[i].isdncontrollerused == ctrl))
492 cep = &cfg_entry_tab[i];
494 if(cep->cdid == CDID_RESERVED)
496 cep->state = ST_IDLE;
497 cep->cdid = CDID_UNUSED;
501 cep->cdid = CDID_UNUSED;
503 cep->last_release_time = time(NULL);
505 SET_CAUSE_TYPE(cep->disc_cause, CAUSET_I4B);
506 SET_CAUSE_VAL(cep->disc_cause, CAUSE_I4B_L1ERROR);
508 if(cep->direction == DIR_OUT)
510 llog(LL_CHD, "%05d %s outgoing call disconnected (local)",
511 cep->cdid, cep->name);
515 llog(LL_CHD, "%05d %s incoming call disconnected (local)",
516 cep->cdid, cep->name);
519 llog(LL_CHD, "%05d %s cause %s",
520 cep->cdid, cep->name, print_i4b_cause(cep->disc_cause));
523 if(do_fullscreen && (cep->connect_time > 0))
524 display_disconnect(cep);
526 #ifdef I4B_EXTERNAL_MONITOR
527 if(do_monitor && accepted)
528 monitor_evnt_disconnect(cep);
531 if(cep->disconnectprog)
532 exec_connect_prog(cep, cep->disconnectprog, 1);
534 if(cep->connect_time > 0)
536 if(cep->direction == DIR_OUT)
538 llog(LL_CHD, "%05d %s charging: %d units, %d seconds",
539 cep->cdid, cep->name, cep->charge,
540 (int)difftime(time(NULL), cep->connect_time));
544 llog(LL_CHD, "%05d %s connected %d seconds",
545 cep->cdid, cep->name,
546 (int)difftime(time(NULL), cep->connect_time));
549 if((cep->inbytes != INVALID) && (cep->outbytes != INVALID))
551 if((cep->ioutbytes != cep->outbytes) ||
552 (cep->iinbytes != cep->inbytes))
554 llog(LL_CHD, "%05d %s accounting: in %d, out %d (in %d, out %d)",
555 cep->cdid, cep->name,
556 cep->inbytes, cep->outbytes,
557 cep->iinbytes, cep->ioutbytes);
561 llog(LL_CHD, "%05d %s accounting: in %d, out %d",
562 cep->cdid, cep->name,
563 cep->inbytes, cep->outbytes);
568 if(useacctfile && (cep->connect_time > 0))
571 char logdatetime[41];
574 con_secs = difftime(time(NULL), cep->connect_time);
576 tp = localtime(&cep->connect_time);
578 strftime(logdatetime,40,I4B_TIME_FORMAT,tp);
580 if(cep->inbytes != INVALID && cep->outbytes != INVALID)
582 fprintf(acctfp, "%s - %s %s %d (%d) (%d/%d)\n",
583 logdatetime, getlogdatetime(),
584 cep->name, cep->charge, con_secs,
585 cep->inbytes, cep->outbytes);
589 fprintf(acctfp, "%s - %s %s %d (%d)\n",
590 logdatetime, getlogdatetime(),
591 cep->name, cep->charge, con_secs);
595 /* set the B-channel inactive */
597 if((set_channel_idle(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
598 llog(LL_ERR, "msg_pdeact_ind: set_channel_idle failed!");
600 incr_free_channels(cep->isdncontrollerused);
602 cep->connect_time = 0;
604 cep->state = ST_IDLE;
609 /*---------------------------------------------------------------------------*
610 * handle incoming NEGCOMP_IND message
611 *---------------------------------------------------------------------------*/
613 msg_negcomplete_ind(msg_negcomplete_ind_t *mp)
617 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
619 llog(LL_WRN, "msg_negcomp_ind: cdid not found");
624 exec_connect_prog(cep, cep->connectprog, 0);
627 /*---------------------------------------------------------------------------*
628 * handle incoming IFSTATE_CHANGED indication
629 *---------------------------------------------------------------------------*/
631 msg_ifstatechg_ind(msg_ifstatechg_ind_t *mp)
636 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
638 llog(LL_WRN, "msg_negcomp_ind: cdid not found");
642 device = bdrivername(cep->usrdevicename);
643 llog(LL_DBG, "%s%d: switched to state %d", device, cep->usrdeviceunit, mp->state);
646 /*---------------------------------------------------------------------------*
647 * handle incoming DISCONNECT_IND message
648 *---------------------------------------------------------------------------*/
650 msg_disconnect_ind(msg_disconnect_ind_t *mp)
654 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
656 llog(LL_WRN, "msg_disconnect_ind: cdid not found");
660 /* is this an aborted out-call prematurely called back? */
661 if (cep->saved_call.cdid == mp->header.cdid)
663 DBGL(DL_CNST, (llog(LL_DBG, "aborted outcall %05d disconnected",
665 cep->saved_call.cdid = CDID_UNUSED;
667 set_channel_idle(cep->saved_call.controller, cep->saved_call.channel);
669 incr_free_channels(cep->saved_call.controller);
673 cep->last_release_time = time(NULL);
674 cep->disc_cause = mp->cause;
676 if(cep->direction == DIR_OUT)
678 llog(LL_CHD, "%05d %s outgoing call disconnected %s",
679 cep->cdid, cep->name,
680 cep->local_disconnect == DISCON_LOC ?
681 "(local)" : "(remote)");
685 llog(LL_CHD, "%05d %s incoming call disconnected %s",
686 cep->cdid, cep->name,
687 cep->local_disconnect == DISCON_LOC ?
688 "(local)" : "(remote)");
691 llog(LL_CHD, "%05d %s cause %s",
692 cep->cdid, cep->name, print_i4b_cause(mp->cause));
695 if(do_fullscreen && (cep->connect_time > 0))
696 display_disconnect(cep);
698 #ifdef I4B_EXTERNAL_MONITOR
699 if(do_monitor && accepted)
700 monitor_evnt_disconnect(cep);
703 if(cep->disconnectprog)
704 exec_connect_prog(cep, cep->disconnectprog, 1);
706 if(cep->connect_time > 0)
708 if(cep->direction == DIR_OUT)
710 llog(LL_CHD, "%05d %s charging: %d units, %d seconds",
711 cep->cdid, cep->name, cep->charge,
712 (int)difftime(time(NULL), cep->connect_time));
716 llog(LL_CHD, "%05d %s connected %d seconds",
717 cep->cdid, cep->name,
718 (int)difftime(time(NULL), cep->connect_time));
721 if((cep->inbytes != INVALID) && (cep->outbytes != INVALID))
723 if((cep->ioutbytes != cep->outbytes) ||
724 (cep->iinbytes != cep->inbytes))
726 llog(LL_CHD, "%05d %s accounting: in %d, out %d (in %d, out %d)",
727 cep->cdid, cep->name,
728 cep->inbytes, cep->outbytes,
729 cep->iinbytes, cep->ioutbytes);
733 llog(LL_CHD, "%05d %s accounting: in %d, out %d",
734 cep->cdid, cep->name,
735 cep->inbytes, cep->outbytes);
740 if(useacctfile && (cep->connect_time > 0))
743 char logdatetime[41];
746 con_secs = difftime(time(NULL), cep->connect_time);
748 tp = localtime(&cep->connect_time);
750 strftime(logdatetime,40,I4B_TIME_FORMAT,tp);
752 if(cep->inbytes != INVALID && cep->outbytes != INVALID)
754 fprintf(acctfp, "%s - %s %s %d (%d) (%d/%d)\n",
755 logdatetime, getlogdatetime(),
756 cep->name, cep->charge, con_secs,
757 cep->inbytes, cep->outbytes);
761 fprintf(acctfp, "%s - %s %s %d (%d)\n",
762 logdatetime, getlogdatetime(),
763 cep->name, cep->charge, con_secs);
767 /* set the B-channel inactive */
769 set_channel_idle(cep->isdncontrollerused, cep->isdnchannelused);
771 incr_free_channels(cep->isdncontrollerused);
773 cep->connect_time = 0;
774 cep->cdid = CDID_UNUSED;
776 next_state(cep, EV_MDI);
779 /*---------------------------------------------------------------------------*
780 * handle incoming DIALOUT message
781 *---------------------------------------------------------------------------*/
783 msg_dialout(msg_dialout_ind_t *mp)
787 DBGL(DL_DRVR, (llog(LL_DBG, "msg_dialout: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
789 if((cep = find_by_device_for_dialout(mp->driver, mp->driver_unit)) == NULL)
791 DBGL(DL_DRVR, (llog(LL_DBG, "msg_dialout: config entry reserved or no match")));
795 if(cep->inout == DIR_INONLY)
797 dialresponse(cep, DSTAT_INONLY);
801 if(cep->budget_calloutperiod && cep->budget_calloutncalls)
803 cep->budget_calltype = 0;
804 cep->budget_callout_req++;
806 if(cep->budget_calloutncalls_cnt == 0)
808 llog(LL_CHD, "%05d %s no budget for calling out", 0, cep->name);
809 cep->budget_callout_rej++;
810 dialresponse(cep, DSTAT_TFAIL);
815 cep->budget_calltype = BUDGET_TYPE_COUT;
819 if((cep->cdid = get_cdid()) == 0)
821 DBGL(DL_DRVR, (llog(LL_DBG, "msg_dialout: get_cdid() returned 0!")));
826 cep->last_charge = 0;
829 next_state(cep, EV_MDO);
832 /*---------------------------------------------------------------------------*
833 * handle incoming DIALOUTNUMBER message
834 *---------------------------------------------------------------------------*/
836 msg_dialoutnumber(msg_dialoutnumber_ind_t *mp)
840 DBGL(DL_DRVR, (llog(LL_DBG, "msg_dialoutnumber: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
842 if((cep = find_by_device_for_dialoutnumber(mp)) == NULL)
844 DBGL(DL_DRVR, (llog(LL_DBG, "msg_dialoutnumber: config entry reserved or no match")));
848 if(cep->inout == DIR_INONLY)
850 dialresponse(cep, DSTAT_INONLY);
854 if(cep->budget_calloutperiod && cep->budget_calloutncalls)
856 cep->budget_calltype = 0;
857 cep->budget_callout_req++;
859 if(cep->budget_calloutncalls_cnt == 0)
861 llog(LL_CHD, "%05d %s no budget for calling out", 0, cep->name);
862 cep->budget_callout_rej++;
863 dialresponse(cep, DSTAT_TFAIL);
868 cep->budget_calltype = BUDGET_TYPE_COUT;
872 if((cep->cdid = get_cdid()) == 0)
874 DBGL(DL_DRVR, (llog(LL_DBG, "msg_dialoutnumber: get_cdid() returned 0!")));
878 cep->keypad[0] = '\0';
880 cep->last_charge = 0;
883 next_state(cep, EV_MDO);
886 /*---------------------------------------------------------------------------*
887 * handle incoming KEYPAD message
888 *---------------------------------------------------------------------------*/
890 msg_keypad(msg_keypad_ind_t *mp)
894 DBGL(DL_DRVR, (llog(LL_DBG, "msg_keypad: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
896 if((cep = find_by_device_for_keypad(mp->driver, mp->driver_unit, mp->cmdlen, mp->cmd)) == NULL)
898 DBGL(DL_DRVR, (llog(LL_DBG, "msg_keypad: config entry reserved or no match")));
902 if(cep->inout == DIR_INONLY)
904 dialresponse(cep, DSTAT_INONLY);
908 if(cep->budget_calloutperiod && cep->budget_calloutncalls)
910 cep->budget_calltype = 0;
911 cep->budget_callout_req++;
913 if(cep->budget_calloutncalls_cnt == 0)
915 llog(LL_CHD, "%05d %s no budget for calling out", 0, cep->name);
916 cep->budget_callout_rej++;
917 dialresponse(cep, DSTAT_TFAIL);
922 cep->budget_calltype = BUDGET_TYPE_COUT;
926 if((cep->cdid = get_cdid()) == 0)
928 DBGL(DL_DRVR, (llog(LL_DBG, "msg_keypad: get_cdid() returned 0!")));
933 cep->last_charge = 0;
936 next_state(cep, EV_MDO);
939 /*---------------------------------------------------------------------------*
940 * handle incoming DRVRDISC_REQ message
941 *---------------------------------------------------------------------------*/
943 msg_drvrdisc_req(msg_drvrdisc_req_t *mp)
947 DBGL(DL_DRVR, (llog(LL_DBG, "msg_drvrdisc_req: req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
949 if((cep = get_cep_by_driver(mp->driver, mp->driver_unit)) == NULL)
951 DBGL(DL_DRVR, (llog(LL_DBG, "msg_drvrdisc_req: config entry not found")));
954 next_state(cep, EV_DRQ);
957 /*---------------------------------------------------------------------------*
958 * handle incoming ACCOUNTING message
959 *---------------------------------------------------------------------------*/
961 msg_accounting(msg_accounting_ind_t *mp)
965 if((cep = find_active_entry_by_driver(mp->driver, mp->driver_unit)) == NULL)
967 llog(LL_WRN, "msg_accounting: no config entry found!");
971 cep->inbytes = mp->inbytes;
972 cep->iinbytes = mp->iinbytes;
973 cep->outbytes = mp->outbytes;
974 cep->ioutbytes = mp->ioutbytes;
975 cep->inbps = mp->inbps;
976 cep->outbps = mp->outbps;
978 if(mp->accttype == ACCT_DURING)
984 #ifdef I4B_EXTERNAL_MONITOR
985 if(do_monitor && accepted)
986 monitor_evnt_acct(cep);
991 /*---------------------------------------------------------------------------*
992 * handle incoming CHARGING message
993 *---------------------------------------------------------------------------*/
995 msg_charging_ind(msg_charging_ind_t *mp)
997 static char *cttab[] = {
1005 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
1007 llog(LL_WRN, "msg_charging_ind: cdid not found");
1011 if(mp->units_type < CHARGE_INVALID || mp->units_type > CHARGE_CALC)
1013 llog(LL_ERR, "msg_charging: units_type %d out of range!", mp->units_type);
1014 error_exit(1, "msg_charging: units_type %d out of range!", mp->units_type);
1017 DBGL(DL_DRVR, (llog(LL_DBG, "msg_charging: %d unit(s) (%s)",
1018 mp->units, cttab[mp->units_type])));
1020 cep->charge = mp->units;
1022 switch(mp->units_type)
1025 if((cep->unitlengthsrc == ULSRC_DYN) &&
1026 (cep->charge != cep->last_charge))
1028 cep->last_charge = cep->charge;
1036 display_ccharge(cep, mp->units);
1038 #ifdef I4B_EXTERNAL_MONITOR
1039 if(do_monitor && accepted)
1040 monitor_evnt_charge(cep, mp->units, 1);
1046 /*---------------------------------------------------------------------------*
1047 * handle incoming IDLE_TIMEOUT_IND message
1048 *---------------------------------------------------------------------------*/
1050 msg_idle_timeout_ind(msg_idle_timeout_ind_t *mp)
1054 if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
1056 llog(LL_WRN, "msg_idle_timeout_ind: cdid not found!");
1060 cep->local_disconnect = DISCON_LOC;
1062 DBGL(DL_DRVR, (llog(LL_DBG, "msg_idle_timeout_ind: idletimeout, kernel sent disconnect!")));
1064 check_and_kill(cep);
1067 /*---------------------------------------------------------------------------*
1068 * handle incoming MSG_PACKET_IND message
1069 *---------------------------------------------------------------------------*/
1071 strapp(char *buf, const char *txt)
1079 /*---------------------------------------------------------------------------*
1080 * handle incoming MSG_PACKET_IND message
1081 *---------------------------------------------------------------------------*/
1083 ipapp(char *buf, unsigned long a )
1085 unsigned long ma = ntohl( a );
1087 buf += sprintf(buf, "%lu.%lu.%lu.%lu",
1095 /*---------------------------------------------------------------------------*
1096 * handle incoming MSG_PACKET_IND message
1097 *---------------------------------------------------------------------------*/
1099 msg_packet_ind(msg_packet_ind_t *mp)
1109 for(i=0; i < nentries; i++)
1111 cep = &cfg_entry_tab[i]; /* ptr to config entry */
1113 if(cep->usrdevicename == mp->driver &&
1114 cep->usrdeviceunit == mp->driver_unit)
1121 ip = (struct ip*)mp->pktdata;
1122 proto_hdr = mp->pktdata + ((ip->ip_hl)<<2);
1124 if( ip->ip_p == IPPROTO_TCP )
1126 struct tcphdr* tcp = (struct tcphdr*)proto_hdr;
1128 cptr = strapp( cptr, "TCP " );
1129 cptr = ipapp( cptr, ip->ip_src.s_addr );
1130 cptr += sprintf( cptr, ":%u -> ", ntohs( tcp->th_sport ) );
1131 cptr = ipapp( cptr, ip->ip_dst.s_addr );
1132 cptr += sprintf( cptr, ":%u", ntohs( tcp->th_dport ) );
1134 if(tcp->th_flags & TH_FIN) cptr = strapp( cptr, " FIN" );
1135 if(tcp->th_flags & TH_SYN) cptr = strapp( cptr, " SYN" );
1136 if(tcp->th_flags & TH_RST) cptr = strapp( cptr, " RST" );
1137 if(tcp->th_flags & TH_PUSH) cptr = strapp( cptr, " PUSH" );
1138 if(tcp->th_flags & TH_ACK) cptr = strapp( cptr, " ACK" );
1139 if(tcp->th_flags & TH_URG) cptr = strapp( cptr, " URG" );
1141 else if( ip->ip_p == IPPROTO_UDP )
1143 struct udphdr* udp = (struct udphdr*)proto_hdr;
1145 cptr = strapp( cptr, "UDP " );
1146 cptr = ipapp( cptr, ip->ip_src.s_addr );
1147 cptr += sprintf( cptr, ":%u -> ", ntohs( udp->uh_sport ) );
1148 cptr = ipapp( cptr, ip->ip_dst.s_addr );
1149 cptr += sprintf( cptr, ":%u", ntohs( udp->uh_dport ) );
1151 else if( ip->ip_p == IPPROTO_ICMP )
1153 struct icmp* icmp = (struct icmp*)proto_hdr;
1155 cptr += sprintf( cptr, "ICMP:%u.%u", icmp->icmp_type, icmp->icmp_code);
1156 cptr = ipapp( cptr, ip->ip_src.s_addr );
1157 cptr = strapp( cptr, " -> " );
1158 cptr = ipapp( cptr, ip->ip_dst.s_addr );
1162 cptr += sprintf( cptr, "PROTO=%u ", ip->ip_p);
1163 cptr = ipapp( cptr, ip->ip_src.s_addr);
1164 cptr = strapp( cptr, " -> " );
1165 cptr = ipapp( cptr, ip->ip_dst.s_addr);
1168 llog(LL_PKT, "%s %s %u %s",
1169 name, mp->direction ? "send" : "recv",
1170 ntohs( ip->ip_len ), tmp );
1173 /*---------------------------------------------------------------------------*
1174 * get a cdid from kernel
1175 *---------------------------------------------------------------------------*/
1183 if((ioctl(isdnfd, I4B_CDID_REQ, &mcr)) < 0)
1185 llog(LL_ERR, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno));
1186 error_exit(1, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno));
1192 /*---------------------------------------------------------------------------*
1193 * send message "connect request" to kernel
1194 *---------------------------------------------------------------------------*/
1196 sendm_connect_req(cfg_entry_t *cep)
1198 msg_connect_req_t mcr;
1201 cep->local_disconnect = DISCON_REM;
1203 cep->unitlength = get_current_rate(cep, 1);
1205 mcr.cdid = cep->cdid;
1207 mcr.controller = cep->isdncontrollerused;
1208 mcr.channel = cep->isdnchannelused;
1209 mcr.txdelay = cep->isdntxdelout;
1211 mcr.bprot = cep->b1protocol;
1212 mcr.bcap = cep->bcap;
1214 mcr.driver = cep->usrdevicename;
1215 mcr.driver_unit = cep->usrdeviceunit;
1217 /* setup the shorthold data */
1218 mcr.shorthold_data.shorthold_algorithm = cep->shorthold_algorithm;
1219 mcr.shorthold_data.unitlen_time = cep->unitlength;
1220 mcr.shorthold_data.idle_time = cep->idle_time_out;
1221 mcr.shorthold_data.earlyhup_time = cep->earlyhangup;
1223 if(cep->unitlengthsrc == ULSRC_DYN)
1224 mcr.unitlen_method = ULEN_METHOD_DYNAMIC;
1226 mcr.unitlen_method = ULEN_METHOD_STATIC;
1228 strcpy(mcr.dst_telno, cep->remote_phone_dialout.number);
1230 strcpy(mcr.dst_subaddr, cep->remote_phone_dialout.subaddr);
1231 strcpy(mcr.src_telno, cep->local_phone_dialout.number);
1233 strcpy(mcr.src_subaddr, cep->local_phone_dialout.subaddr);
1234 strcpy(mcr.keypad, cep->keypad);
1236 cep->last_dial_time = time(NULL);
1237 cep->direction = DIR_OUT;
1239 DBGL(DL_CNST, (llog(LL_DBG, "sendm_connect_req: ctrl = %d, chan = %d", cep->isdncontrollerused, cep->isdnchannelused)));
1241 if((ret = ioctl(isdnfd, I4B_CONNECT_REQ, &mcr)) < 0)
1243 llog(LL_ERR, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno));
1244 error_exit(1, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno));
1247 decr_free_channels(cep->isdncontrollerused);
1249 llog(LL_CHD, "%05d %s dialing out from %s to %s",
1252 aliasing ? get_alias(cep->local_phone_dialout.number) : cep->local_phone_dialout.number,
1253 aliasing ? get_alias(cep->remote_phone_dialout.number) : cep->remote_phone_dialout.number);
1258 /*---------------------------------------------------------------------------*
1259 * send message "connect response" to kernel
1260 *---------------------------------------------------------------------------*/
1262 sendm_connect_resp(cfg_entry_t *cep, int cdid, int response, cause_t cause)
1264 msg_connect_resp_t mcr;
1269 mcr.response = response;
1271 if(response == SETUP_RESP_REJECT)
1274 DBGL(DL_DRVR, (llog(LL_DBG, "sendm_connect_resp: reject, cause=0x%x", cause)));
1276 else if(response == SETUP_RESP_ACCEPT)
1278 cep->direction = DIR_IN;
1280 mcr.txdelay = cep->isdntxdelin;
1282 mcr.bprot = cep->b1protocol;
1283 mcr.bcap = cep->bcap;
1285 mcr.driver = cep->usrdevicename;
1286 mcr.driver_unit = cep->usrdeviceunit;
1288 mcr.max_idle_time = cep->idle_time_in;
1290 DBGL(DL_DRVR, (llog(LL_DBG, "sendm_connect_resp: accept")));
1293 if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &mcr)) < 0)
1295 llog(LL_ERR, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno));
1296 error_exit(1, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno));
1301 /*---------------------------------------------------------------------------*
1302 * send message "disconnect request" to kernel
1303 *---------------------------------------------------------------------------*/
1305 sendm_disconnect_req(cfg_entry_t *cep, cause_t cause)
1307 msg_discon_req_t mcr;
1310 mcr.cdid = cep->cdid;
1314 cep->local_disconnect = DISCON_LOC;
1316 if((ret = ioctl(isdnfd, I4B_DISCONNECT_REQ, &mcr)) < 0)
1318 llog(LL_ERR, "sendm_disconnect_req: ioctl I4B_DISCONNECT_REQ failed: %s", strerror(errno));
1322 DBGL(DL_DRVR, (llog(LL_DBG, "sendm_disconnect_req: sent DISCONNECT_REQ")));
1327 /*---------------------------------------------------------------------------*
1328 * send message "alert request" to kernel
1329 *---------------------------------------------------------------------------*/
1331 sendm_alert_req(cfg_entry_t *cep)
1333 msg_alert_req_t mar;
1336 mar.cdid = cep->cdid;
1338 if((ret = ioctl(isdnfd, I4B_ALERT_REQ, &mar)) < 0)
1340 llog(LL_ERR, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno));
1341 error_exit(1, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno));
1345 DBGL(DL_DRVR, (llog(LL_DBG, "sendm_alert_req: sent ALERT_REQ")));