Sync usage with man page.
[netbsd-mini2440.git] / usr.sbin / isdn / isdnd / msghdl.c
blob120536e20206e9ce5120c587e6772041e27edb43
1 /*
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
6 * are met:
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
23 * SUCH DAMAGE.
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 $
32 * $FreeBSD$
34 * last edit-date: [Thu Sep 21 11:11:48 2000]
36 *---------------------------------------------------------------------------*/
38 #include "isdnd.h"
40 #include <sys/socket.h>
41 #include <net/if.h>
42 #include <net/if_types.h>
44 #if defined(__FreeBSD__)
45 #include <net/if_var.h>
46 #endif
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 *---------------------------------------------------------------------------*/
59 void
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)
69 if (aliasing)
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);
80 return;
83 if (cep->cdid != CDID_UNUSED && cep->cdid != CDID_RESERVED)
85 /*
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)
92 int cdid;
94 /* disconnect old, not new */
96 cdid = cep->cdid;
97 cep->cdid = cep->saved_call.cdid;
98 sendm_disconnect_req(cep, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
99 cep->cdid = cdid;
102 * Shortcut the state machine and mark this
103 * entry as free
105 /* XXX */ cep->state = ST_IDLE; /* this is an invalid */
106 /* transition, */
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);
119 return;
122 cep->charge = 0;
123 cep->last_charge = 0;
125 switch (cep->dialin_reaction)
127 case REACT_ACCEPT:
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);
132 break;
134 case REACT_REJECT:
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;
140 break;
142 case REACT_IGNORE:
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);
146 break;
148 case REACT_ANSWER:
149 decr_free_channels(find_ctrl_state(mp->controller));
150 if (cep->alert)
152 if (mp->display)
154 logit(LL_CHD, "%05d %s alerting: incoming call from %s to %s (%s)",
155 mp->header.cdid, cep->name, SRC, DST, mp->display);
157 else
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);
164 else
166 if (mp->display)
168 logit(LL_CHD, "%05d %s answering: incoming call from %s to %s (%s)",
169 mp->header.cdid, cep->name, SRC, DST, mp->display);
171 else
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);
178 break;
180 case REACT_CALLBACK:
182 #ifdef NOTDEF
183 /*XXX reserve channel ??? */ decr_free_channels(mp->controller);
184 #endif
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,
190 #if 0
191 (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
192 #else
193 (CAUSET_I4B << 8) | CAUSE_I4B_REJECT);
194 #endif
195 /* no state change */
197 else
199 sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
200 #if 0
201 (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
202 #else
203 (CAUSET_I4B << 8) | CAUSE_I4B_REJECT);
204 #endif
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++;
215 break;
217 else
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);
230 break;
232 default:
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);
235 break;
237 handle_scrprs(mp->header.cdid, mp->scr_ind, mp->prs_ind, SRC);
238 #undef SRC
239 #undef DST
242 /*---------------------------------------------------------------------------*
243 * handle incoming CONNECT_ACTIVE_IND message
244 *---------------------------------------------------------------------------*/
245 void
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!");
253 return;
256 cep->isdncontrollerused = mp->controller;
257 cep->isdnchannelused = mp->channel;
259 cep->aoc_now = cep->connect_time = time(NULL);
260 cep->aoc_last = 0;
261 cep->aoc_diff = 0;
262 cep->aoc_valid = AOC_INVALID;
264 cep->local_disconnect = DISCON_REM;
266 cep->inbytes = INVALID;
267 cep->outbytes = INVALID;
268 cep->hangup = 0;
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;
305 else
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);
313 #ifdef USE_CURSES
314 if (do_fullscreen)
315 display_connect(cep);
316 #endif
317 #ifdef I4B_EXTERNAL_MONITOR
318 if (do_monitor && accepted)
319 monitor_evnt_connect(cep);
320 #endif
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 *---------------------------------------------------------------------------*/
333 void
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!");
341 return;
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 *---------------------------------------------------------------------------*/
360 void
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!");
368 return;
370 #ifdef NOTDEF
371 logit(LL_CHD, "%05d %s incoming alert", cep->cdid, cep->name);
372 #endif
375 /*---------------------------------------------------------------------------*
376 * handle incoming L12STAT_IND message
377 *---------------------------------------------------------------------------*/
378 void
379 msg_l12stat_ind(msg_l12stat_ind_t *ml)
381 struct isdn_ctrl_state * ctrl = find_ctrl_state(ml->controller);
382 if (ctrl == NULL) {
383 logit(LL_ERR, "msg_l12stat_ind: invalid controller number: %d !", ml->controller);
384 return;
387 #ifdef USE_CURSES
388 if (do_fullscreen)
389 display_l12stat(ml->controller, ml->layer, ml->state);
390 #endif
391 #ifdef I4B_EXTERNAL_MONITOR
392 if (do_monitor && accepted)
393 monitor_evnt_l12stat(ml->controller, ml->layer, ml->state);
394 #endif
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;
411 else
413 logit(LL_ERR, "msg_l12stat_ind: invalid layer number [%d]!", ml->layer);
417 /*---------------------------------------------------------------------------*
418 * handle incoming TEIASG_IND message
419 *---------------------------------------------------------------------------*/
420 void
421 msg_teiasg_ind(msg_teiasg_ind_t *mt)
423 struct isdn_ctrl_state *ctrl = find_ctrl_state(mt->controller);
425 if (ctrl == NULL) {
426 logit(LL_ERR, "msg_teiasg_ind: invalid controller number [%d]!", mt->controller);
427 return;
430 #ifdef USE_CURSES
431 if (do_fullscreen)
432 display_tei(mt->controller, mt->tei);
433 #endif
434 #ifdef I4B_EXTERNAL_MONITOR
435 if (do_monitor && accepted)
436 monitor_evnt_tei(mt->controller, mt->tei);
437 #endif
439 DBGL(DL_CNST, (logit(LL_DBG, "msg_teiasg_ind: unit %d, tei = %d",
440 mt->controller, mt->tei)));
442 ctrl->tei = mt->tei;
445 /*---------------------------------------------------------------------------*
446 * handle incoming PDEACT_IND message
447 *---------------------------------------------------------------------------*/
448 void
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);
455 #ifdef USE_CURSES
456 if (do_fullscreen)
458 display_l12stat(isdnif, LAYER_ONE, LAYER_IDLE);
459 display_l12stat(isdnif, LAYER_TWO, LAYER_IDLE);
460 display_tei(isdnif, -1);
462 #endif
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);
470 #endif
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;
476 ctrl->tei = -1;
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;
486 continue;
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);
501 else
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));
510 #ifdef USE_CURSES
511 if (do_fullscreen && (cep->connect_time > 0))
512 display_disconnect(cep);
513 #endif
514 #ifdef I4B_EXTERNAL_MONITOR
515 if (do_monitor && accepted)
516 monitor_evnt_disconnect(cep);
517 #endif
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));
530 else
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);
547 else
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))
558 int con_secs;
559 char logdatetime[41];
560 struct tm *tp;
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);
575 else
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 *---------------------------------------------------------------------------*/
600 void
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");
608 return;
611 if (cep->connectprog)
612 exec_connect_prog(cep, cep->connectprog, 0);
615 /*---------------------------------------------------------------------------*
616 * handle incoming IFSTATE_CHANGED indication
617 *---------------------------------------------------------------------------*/
618 void
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");
626 return;
629 logit(LL_DBG, "%s%d: switched to state %d", cep->usrdevicename, cep->usrdeviceunit, mp->state);
632 /*---------------------------------------------------------------------------*
633 * handle incoming DISCONNECT_IND message
634 *---------------------------------------------------------------------------*/
635 void
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");
644 return;
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",
651 mp->header.cdid)));
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);
658 return;
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)");
671 else
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));
682 #ifdef USE_CURSES
683 if (do_fullscreen && (cep->connect_time > 0))
684 display_disconnect(cep);
685 #endif
686 #ifdef I4B_EXTERNAL_MONITOR
687 if (do_monitor && accepted)
688 monitor_evnt_disconnect(cep);
689 #endif
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));
702 else
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);
719 else
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))
730 int con_secs;
731 char logdatetime[41];
732 struct tm *tp;
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);
747 else
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 *---------------------------------------------------------------------------*/
770 void
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")));
778 return;
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);
786 return;
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);
799 return;
801 else
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!")));
810 return;
813 cep->charge = 0;
814 cep->last_charge = 0;
816 next_state(cep, EV_MDO);
819 /*---------------------------------------------------------------------------*
820 * handle incoming DIALOUTNUMBER message
821 *---------------------------------------------------------------------------*/
822 void
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")));
830 return;
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);
838 return;
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);
851 return;
853 else
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!")));
862 return;
865 cep->charge = 0;
866 cep->last_charge = 0;
868 next_state(cep, EV_MDO);
871 /*---------------------------------------------------------------------------*
872 * handle incoming DRVRDISC_REQ message
873 *---------------------------------------------------------------------------*/
874 void
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")));
884 return;
886 next_state(cep, EV_DRQ);
889 /*---------------------------------------------------------------------------*
890 * handle incoming ACCOUNTING message
891 *---------------------------------------------------------------------------*/
892 void
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!");
900 return;
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)
912 #ifdef USE_CURSES
913 if (do_fullscreen)
914 display_acct(cep);
915 #endif
916 #ifdef I4B_EXTERNAL_MONITOR
917 if (do_monitor && accepted)
918 monitor_evnt_acct(cep);
919 #endif
923 /*---------------------------------------------------------------------------*
924 * handle incoming CHARGING message
925 *---------------------------------------------------------------------------*/
926 void
927 msg_charging_ind(msg_charging_ind_t *mp)
929 static const char *cttab[] = {
930 "invalid",
931 "AOCD",
932 "AOCE",
933 "estimated" };
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");
940 return;
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)
956 case CHARGE_AOCD:
957 if ((cep->unitlengthsrc == ULSRC_DYN) &&
958 (cep->charge != cep->last_charge))
960 cep->last_charge = cep->charge;
961 handle_charge(cep);
963 break;
965 case CHARGE_CALC:
966 #ifdef USE_CURSES
967 if (do_fullscreen)
968 display_ccharge(cep, mp->units);
969 #endif
970 #ifdef I4B_EXTERNAL_MONITOR
971 if (do_monitor && accepted)
972 monitor_evnt_charge(cep, mp->units, 1);
973 #endif
974 break;
978 /*---------------------------------------------------------------------------*
979 * handle incoming IDLE_TIMEOUT_IND message
980 *---------------------------------------------------------------------------*/
981 void
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!");
989 return;
992 cep->local_disconnect = DISCON_LOC;
994 DBGL(DL_DRVR, (logit(LL_DBG, "msg_idle_timeout_ind: idletimeout, kernel sent disconnect!")));
996 check_and_kill(cep);
999 /*---------------------------------------------------------------------------*
1000 * handle incoming MSG_PACKET_IND message
1001 *---------------------------------------------------------------------------*/
1002 static char *
1003 strapp(char *buf, char *lim, const char *txt)
1005 while (*txt && buf < lim - 1)
1006 *buf++ = *txt++;
1007 *buf = '\0';
1008 return buf;
1011 /*---------------------------------------------------------------------------*
1012 * handle incoming MSG_PACKET_IND message
1013 *---------------------------------------------------------------------------*/
1014 static char *
1015 ipapp(char *buf, char *lim, unsigned long a)
1017 unsigned long ma = ntohl(a);
1018 ssize_t n;
1020 n = snprintf(buf, lim - buf, "%lu.%lu.%lu.%lu", (ma>>24)&0xFF,
1021 (ma>>16)&0xFF, (ma>>8)&0xFF, (ma)&0xFF);
1022 if (n > 0)
1023 return buf + n;
1024 else
1025 return NULL;
1028 /*---------------------------------------------------------------------------*
1029 * handle incoming MSG_PACKET_IND message
1030 *---------------------------------------------------------------------------*/
1031 void
1032 msg_packet_ind(msg_packet_ind_t *mp)
1034 struct cfg_entry *cep;
1035 struct ip *ip;
1036 u_char *proto_hdr;
1037 char tmp[80];
1038 char *cptr = tmp;
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)
1045 name = cep->name;
1046 break;
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);
1100 else
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
1116 void
1117 msg_ctrl_ev_ind(msg_ctrl_ev_ind_t *mp)
1119 logit(LL_DMN, "controller %d %s", mp->controller, mp->event?"attached":"detached");
1120 if (mp->event) {
1121 /* new, add to controller list */
1122 init_new_controller(mp->controller);
1123 init_single_controller_protocol(find_ctrl_state(mp->controller));
1124 } else {
1125 /* controller gone, remove */
1126 remove_ctrl_state(mp->controller);
1130 /*---------------------------------------------------------------------------*
1131 * get a cdid from kernel
1132 *---------------------------------------------------------------------------*/
1134 get_cdid(void)
1136 msg_cdid_req_t mcr;
1138 mcr.cdid = 0;
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));
1146 return(mcr.cdid);
1149 /*---------------------------------------------------------------------------*
1150 * send message "connect request" to kernel
1151 *---------------------------------------------------------------------------*/
1153 sendm_connect_req(struct cfg_entry *cep)
1155 msg_connect_req_t mcr;
1156 int ret;
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;
1181 else
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",
1202 cep->cdid,
1203 cep->name,
1204 aliasing ? get_alias(cep->local_phone_dialout) : cep->local_phone_dialout,
1205 aliasing ? get_alias(cep->remote_phone_dialout) : cep->remote_phone_dialout);
1207 return(ret);
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;
1217 int ret;
1219 mcr.cdid = cdid;
1221 mcr.response = response;
1223 if (response == SETUP_RESP_REJECT)
1225 mcr.cause = cause;
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));
1249 return(ret);
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;
1259 int ret = 0;
1261 mcr.cdid = cep->cdid;
1263 mcr.cause = cause;
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));
1271 else
1273 DBGL(DL_DRVR, (logit(LL_DBG, "sendm_disconnect_req: sent DISCONNECT_REQ")));
1275 return(ret);
1278 /*---------------------------------------------------------------------------*
1279 * send message "alert request" to kernel
1280 *---------------------------------------------------------------------------*/
1282 sendm_alert_req(struct cfg_entry *cep)
1284 msg_alert_req_t mar;
1285 int ret;
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));
1294 else
1296 DBGL(DL_DRVR, (logit(LL_DBG, "sendm_alert_req: sent ALERT_REQ")));
1298 return(ret);
1301 /* EOF */