Merge branch 'master' of ssh://swildner@crater.dragonflybsd.org/repository/git/dragonfly
[dragonfly.git] / usr.sbin / i4b / isdnd / support.c
blobe9ea0c4f533698409670853d08352ef9293d1e3f
1 /*
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
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 - misc support routines
28 * ----------------------------------
30 * $FreeBSD: src/usr.sbin/i4b/isdnd/support.c,v 1.6.2.2 2001/12/16 15:13:38 hm Exp $
31 * $DragonFly: src/usr.sbin/i4b/isdnd/support.c,v 1.2 2003/06/17 04:29:54 dillon Exp $
33 * last edit-date: [Thu May 3 17:15:00 2001]
35 *---------------------------------------------------------------------------*/
37 #include "isdnd.h"
39 static int isvalidtime(cfg_entry_t *cep);
41 /*---------------------------------------------------------------------------*
42 * find an active entry by driver type and driver unit
43 *---------------------------------------------------------------------------*/
44 cfg_entry_t *
45 find_active_entry_by_driver(int drivertype, int driverunit)
47 cfg_entry_t *cep = NULL;
48 int i;
50 for(i=0; i < nentries; i++)
52 cep = &cfg_entry_tab[i]; /* ptr to config entry */
54 if(!((cep->usrdevicename == drivertype) &&
55 (cep->usrdeviceunit == driverunit)))
57 continue;
60 /* check time interval */
62 if(isvalidtime(cep) == 0)
64 DBGL(DL_VALID, (log(LL_DBG, "find_active_entry_by_driver: entry %d, time not valid!", i)));
65 continue;
68 /* found */
70 if(cep->cdid == CDID_UNUSED)
72 DBGL(DL_MSG, (log(LL_DBG, "find_active_entry_by_driver: entry %d [%s%d], cdid=CDID_UNUSED !",
73 i, bdrivername(drivertype), driverunit)));
74 return(NULL);
76 else if(cep->cdid == CDID_RESERVED)
78 DBGL(DL_MSG, (log(LL_DBG, "find_active_entry_by_driver: entry %d [%s%d], cdid=CDID_RESERVED!",
79 i, bdrivername(drivertype), driverunit)));
80 return(NULL);
82 return(cep);
84 return(NULL);
87 /*---------------------------------------------------------------------------*
88 * find entry by drivertype and driverunit and setup for dialing out
89 *---------------------------------------------------------------------------*/
90 cfg_entry_t *
91 find_by_device_for_dialout(int drivertype, int driverunit)
93 cfg_entry_t *cep = NULL;
94 int i;
96 for(i=0; i < nentries; i++)
98 cep = &cfg_entry_tab[i]; /* ptr to config entry */
100 /* compare driver type and unit */
102 if(!((cep->usrdevicename == drivertype) &&
103 (cep->usrdeviceunit == driverunit)))
105 continue;
108 /* check time interval */
110 if(isvalidtime(cep) == 0)
112 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, time not valid!", i)));
113 continue;
116 /* found, check if already reserved */
118 if(cep->cdid == CDID_RESERVED)
120 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, cdid reserved!", i)));
121 return(NULL);
124 /* check if this entry is already in use ? */
126 if(cep->cdid != CDID_UNUSED)
128 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, cdid in use", i)));
129 return(NULL);
132 if((setup_dialout(cep)) == GOOD)
134 /* found an entry to be used for calling out */
136 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: found entry %d!", i)));
137 return(cep);
139 else
141 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, setup_dialout() failed!", i)));
142 return(NULL);
146 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: no entry found!")));
147 return(NULL);
150 /*---------------------------------------------------------------------------*
151 * find entry by drivertype and driverunit and setup for dialing out
152 *---------------------------------------------------------------------------*/
153 cfg_entry_t *
154 find_by_device_for_dialoutnumber(int drivertype, int driverunit, int cmdlen, char *cmd)
156 cfg_entry_t *cep = NULL;
157 int i, j;
159 for(i=0; i < nentries; i++)
161 cep = &cfg_entry_tab[i]; /* ptr to config entry */
163 /* compare driver type and unit */
165 if(!((cep->usrdevicename == drivertype) &&
166 (cep->usrdeviceunit == driverunit)))
168 continue;
171 /* check time interval */
173 if(isvalidtime(cep) == 0)
175 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, time not valid!", i)));
176 continue;
179 /* found, check if already reserved */
181 if(cep->cdid == CDID_RESERVED)
183 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, cdid reserved!", i)));
184 return(NULL);
187 /* check if this entry is already in use ? */
189 if(cep->cdid != CDID_UNUSED)
191 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, cdid in use", i)));
192 return(NULL);
195 cep->keypad[0] = '\0';
197 /* check number and copy to cep->remote_numbers[] */
199 for(j = 0; j < cmdlen; j++)
201 if(!(isdigit(*(cmd+j))))
203 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, dial string contains non-digit at pos %d", i, j)));
204 return(NULL);
206 /* fill in number to dial */
207 cep->remote_numbers[0].number[j] = *(cmd+j);
209 cep->remote_numbers[0].number[j] = '\0';
210 cep->remote_numbers_count = 1;
212 if((setup_dialout(cep)) == GOOD)
214 /* found an entry to be used for calling out */
216 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: found entry %d!", i)));
217 return(cep);
219 else
221 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, setup_dialout() failed!", i)));
222 return(NULL);
226 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: no entry found!")));
227 return(NULL);
230 /*---------------------------------------------------------------------------*
231 * find entry by drivertype and driverunit and setup for send keypad
232 *---------------------------------------------------------------------------*/
233 cfg_entry_t *
234 find_by_device_for_keypad(int drivertype, int driverunit, int cmdlen, char *cmd)
236 cfg_entry_t *cep = NULL;
237 int i, j;
239 for(i=0; i < nentries; i++)
241 cep = &cfg_entry_tab[i]; /* ptr to config entry */
243 /* compare driver type and unit */
245 if(!((cep->usrdevicename == drivertype) &&
246 (cep->usrdeviceunit == driverunit)))
248 continue;
251 /* check time interval */
253 if(isvalidtime(cep) == 0)
255 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_keypad: entry %d, time not valid!", i)));
256 continue;
259 /* found, check if already reserved */
261 if(cep->cdid == CDID_RESERVED)
263 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_keypad: entry %d, cdid reserved!", i)));
264 return(NULL);
267 /* check if this entry is already in use ? */
269 if(cep->cdid != CDID_UNUSED)
271 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_keypad: entry %d, cdid in use", i)));
272 return(NULL);
275 cep->remote_numbers[0].number[0] = '\0';
276 cep->remote_numbers_count = 0;
277 cep->remote_phone_dialout[0] = '\0';
279 bzero(cep->keypad, KEYPAD_MAX);
280 strncpy(cep->keypad, cmd, cmdlen);
282 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_keypad: entry %d, keypad string is %s", i, cep->keypad)));
284 if((setup_dialout(cep)) == GOOD)
286 /* found an entry to be used for calling out */
288 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_keypad: found entry %d!", i)));
289 return(cep);
291 else
293 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_keypad: entry %d, setup_dialout() failed!", i)));
294 return(NULL);
298 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_keypad: no entry found!")));
299 return(NULL);
302 /*---------------------------------------------------------------------------*
303 * find entry by drivertype and driverunit and setup for dialing out
304 *---------------------------------------------------------------------------*/
306 setup_dialout(cfg_entry_t *cep)
308 int i;
310 /* check controller operational */
312 if((get_controller_state(cep->isdncontroller)) != CTRL_UP)
314 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, controller is down", cep->name)));
315 return(ERROR);
318 cep->isdncontrollerused = cep->isdncontroller;
320 /* check channel available */
322 switch(cep->isdnchannel)
324 case CHAN_ANY:
325 for (i = 0; i < isdn_ctrl_tab[cep->isdncontroller].nbch; i++)
327 if(ret_channel_state(cep->isdncontroller, i) == CHAN_IDLE)
328 break;
331 if (i == isdn_ctrl_tab[cep->isdncontroller].nbch)
333 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, no channel free", cep->name)));
334 return(ERROR);
336 cep->isdnchannelused = CHAN_ANY;
337 break;
339 default:
340 if((ret_channel_state(cep->isdncontroller, cep->isdnchannel)) != CHAN_IDLE)
342 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, channel not free", cep->name)));
343 return(ERROR);
345 cep->isdnchannelused = cep->isdnchannel;
346 break;
349 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s ok!", cep->name)));
351 /* preset disconnect cause */
353 SET_CAUSE_TYPE(cep->disc_cause, CAUSET_I4B);
354 SET_CAUSE_VAL(cep->disc_cause, CAUSE_I4B_NORMAL);
356 return(GOOD);
359 /*---------------------------------------------------------------------------*
360 * find entry by drivertype and driverunit
361 *---------------------------------------------------------------------------*/
362 cfg_entry_t *
363 get_cep_by_driver(int drivertype, int driverunit)
365 cfg_entry_t *cep = NULL;
366 int i;
368 for(i=0; i < nentries; i++)
370 cep = &cfg_entry_tab[i]; /* ptr to config entry */
372 if(!((cep->usrdevicename == drivertype) &&
373 (cep->usrdeviceunit == driverunit)))
375 continue;
378 /* check time interval */
380 if(isvalidtime(cep) == 0)
382 DBGL(DL_MSG, (log(LL_DBG, "get_cep_by_driver: entry %d, time not valid!", i)));
383 continue;
386 DBGL(DL_MSG, (log(LL_DBG, "get_cep_by_driver: found entry %d!", i)));
387 return(cep);
389 return(NULL);
392 /*---------------------------------------------------------------------------*
393 * find a matching entry for an incoming call
395 * - not found/no match: log output with LL_CHD and return NULL
396 * - found/match: make entry in free cep, return address
397 *---------------------------------------------------------------------------*/
398 cfg_entry_t *
399 find_matching_entry_incoming(msg_connect_ind_t *mp)
401 cfg_entry_t *cep = NULL;
402 int i;
404 /* check for CW (call waiting) early */
406 if(mp->channel == CHAN_NO)
408 if(aliasing)
410 char *src_tela = "ERROR-src_tela";
411 char *dst_tela = "ERROR-dst_tela";
413 src_tela = get_alias(mp->src_telno);
414 dst_tela = get_alias(mp->dst_telno);
416 log(LL_CHD, "%05d <unknown> CW from %s to %s (no channel free)",
417 mp->header.cdid, src_tela, dst_tela);
419 else
421 log(LL_CHD, "%05d <unknown> call waiting from %s to %s (no channel free)",
422 mp->header.cdid, mp->src_telno, mp->dst_telno);
424 return(NULL);
427 for(i=0; i < nentries; i++)
429 int n;
430 cep = &cfg_entry_tab[i]; /* ptr to config entry */
432 /* check my number */
434 if(strncmp(cep->local_phone_incoming, mp->dst_telno, strlen(cep->local_phone_incoming)))
436 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, myno %s != incomingno %s", i,
437 cep->local_phone_incoming, mp->dst_telno)));
438 continue;
441 /* check all allowed remote number's for this entry */
443 for (n = 0; n < cep->incoming_numbers_count; n++)
445 incoming_number_t *in = &cep->remote_phone_incoming[n];
446 if(in->number[0] == '*')
447 break;
448 if(strncmp(in->number, mp->src_telno, strlen(in->number)))
450 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, remno %s != incomingfromno %s", i,
451 in->number, mp->src_telno)));
453 else
454 break;
456 if (n >= cep->incoming_numbers_count)
457 continue;
459 /* check b protocol */
461 if(cep->b1protocol != mp->bprot)
463 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, bprot %d != incomingprot %d", i,
464 cep->b1protocol, mp->bprot)));
465 continue;
468 /* is this entry currently in use ? */
470 if(cep->cdid != CDID_UNUSED)
472 if(cep->cdid == CDID_RESERVED)
474 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, cdid is reserved", i)));
476 else if (cep->dialin_reaction == REACT_ACCEPT
477 && cep->dialouttype == DIALOUT_CALLEDBACK)
480 * We might consider doing this even if this is
481 * not a calledback config entry - BUT: there are
482 * severe race conditions and timinig problems
483 * ex. if both sides run I4B with no callback
484 * delay - both may shutdown the outgoing call
485 * and never be able to establish a connection.
486 * In the called-back case this should not happen.
488 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, incoming call for callback in progress (cdid %05d)", i, cep->cdid)));
490 /* save the current call state, we're going to overwrite it with the
491 * new incoming state below... */
492 cep->saved_call.cdid = cep->cdid;
493 cep->saved_call.controller = cep->isdncontrollerused;
494 cep->saved_call.channel = cep->isdnchannelused;
496 else
498 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, cdid in use", i)));
499 continue; /* yes, next */
503 /* check controller value ok */
505 if(mp->controller > ncontroller)
507 log(LL_CHD, "%05d %s incoming call with invalid controller %d",
508 mp->header.cdid, cep->name, mp->controller);
509 return(NULL);
512 /* check controller marked up */
514 if((get_controller_state(mp->controller)) != CTRL_UP)
516 log(LL_CHD, "%05d %s incoming call, controller %d DOWN!",
517 mp->header.cdid, cep->name, mp->controller);
518 return(NULL);
522 * check controller he wants, check for any
523 * controller or specific controller
526 if( (mp->controller != -1) &&
527 (mp->controller != cep->isdncontroller) )
529 log(LL_CHD, "%05d %s incoming call, controller %d != incoming %d",
530 mp->header.cdid, cep->name,
531 cep->isdncontroller, mp->controller);
532 continue;
535 /* check channel he wants */
537 switch(mp->channel)
539 case CHAN_ANY:
540 for (i = 0; i < isdn_ctrl_tab[mp->controller].nbch; i++)
542 if(ret_channel_state(mp->controller, i) == CHAN_IDLE)
543 break;
546 if (i == isdn_ctrl_tab[mp->controller].nbch)
548 log(LL_CHD, "%05d %s incoming call, no channel free!",
549 mp->header.cdid, cep->name);
550 return(NULL);
552 break;
554 case CHAN_NO:
555 log(LL_CHD, "%05d %s incoming call, call waiting (no channel available)!",
556 mp->header.cdid, cep->name);
557 return(NULL);
558 break;
560 default:
561 if((ret_channel_state(mp->controller, mp->channel)) != CHAN_IDLE)
563 log(LL_CHD, "%05d %s incoming call, channel B%d not free!",
564 mp->header.cdid, cep->name, mp->channel+1);
565 return(NULL);
567 break;
570 /* check time interval */
572 if(isvalidtime(cep) == 0)
574 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, time not valid!", i)));
575 continue;
578 /* found a matching entry */
580 cep->cdid = mp->header.cdid;
581 cep->isdncontrollerused = mp->controller;
582 cep->isdnchannelused = mp->channel;
583 /*XXX*/ cep->disc_cause = 0;
585 /* cp number to real one used */
587 strcpy(cep->real_phone_incoming, mp->src_telno);
589 /* copy display string */
591 strcpy(cep->display, mp->display);
593 /* entry currently down ? */
595 if(cep->state == ST_DOWN)
597 msg_updown_ind_t mui;
599 /* set interface up */
601 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, ", i)));
603 mui.driver = cep->usrdevicename;
604 mui.driver_unit = cep->usrdeviceunit;
605 mui.updown = SOFT_ENA;
607 if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
609 log(LL_ERR, "find_matching_entry_incoming: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
610 error_exit(1, "find_matching_entry_incoming: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
613 cep->down_retry_count = 0;
614 cep->state = ST_IDLE;
616 return(cep);
619 if(aliasing)
621 char *src_tela = "ERROR-src_tela";
622 char *dst_tela = "ERROR-dst_tela";
624 src_tela = get_alias(mp->src_telno);
625 dst_tela = get_alias(mp->dst_telno);
627 log(LL_CHD, "%05d Call from %s to %s",
628 mp->header.cdid, src_tela, dst_tela);
630 else
632 log(LL_CHD, "%05d <unknown> incoming call from %s to %s ctrl %d",
633 mp->header.cdid, mp->src_telno, mp->dst_telno, mp->controller);
635 return(NULL);
638 /*---------------------------------------------------------------------------*
639 * return address of ACTIVE config entry by controller and channel
640 *---------------------------------------------------------------------------*/
641 cfg_entry_t *
642 get_cep_by_cc(int ctrlr, int chan)
644 int i;
646 if((chan < 0) || (chan >= isdn_ctrl_tab[ctrlr].nbch))
647 return(NULL);
649 for(i=0; i < nentries; i++)
651 if((cfg_entry_tab[i].cdid != CDID_UNUSED) &&
652 (cfg_entry_tab[i].cdid != CDID_RESERVED) &&
653 (cfg_entry_tab[i].isdnchannelused == chan) &&
654 (cfg_entry_tab[i].isdncontrollerused == ctrlr) &&
655 ((ret_channel_state(ctrlr, chan)) == CHAN_RUN))
657 return(&cfg_entry_tab[i]);
660 return(NULL);
663 /*---------------------------------------------------------------------------*
664 * return address of config entry identified by cdid
665 *---------------------------------------------------------------------------*/
666 cfg_entry_t *
667 get_cep_by_cdid(int cdid)
669 int i;
671 for(i=0; i < nentries; i++)
673 if(cfg_entry_tab[i].cdid == cdid
674 || cfg_entry_tab[i].saved_call.cdid == cdid)
675 return(&cfg_entry_tab[i]);
677 return(NULL);
680 /*---------------------------------------------------------------------------*
681 * return b channel driver type name string
682 *---------------------------------------------------------------------------*/
683 char *
684 bdrivername(int drivertype)
686 static char *bdtab[] = {
687 "rbch",
688 "tel",
689 "ipr",
690 "isp",
691 "ibc",
692 "ing"
695 if(drivertype >= BDRV_RBCH && drivertype <= BDRV_ING)
696 return(bdtab[drivertype]);
697 else
698 return("unknown");
701 /*---------------------------------------------------------------------------*
702 * process AOCD charging messages
703 *---------------------------------------------------------------------------*/
704 void
705 handle_charge(cfg_entry_t *cep)
707 time_t now = time(NULL);
709 if(cep->aoc_last == 0) /* no last timestamp yet ? */
711 cep->aoc_last = now; /* add time stamp */
713 else if(cep->aoc_now == 0) /* no current timestamp yet ? */
715 cep->aoc_now = now; /* current timestamp */
717 else
719 cep->aoc_last = cep->aoc_now;
720 cep->aoc_now = now;
721 cep->aoc_diff = cep->aoc_now - cep->aoc_last;
722 cep->aoc_valid = AOC_VALID;
725 #ifdef USE_CURSES
726 if(do_fullscreen)
727 display_charge(cep);
728 #endif
730 #ifdef I4B_EXTERNAL_MONITOR
731 if(do_monitor && accepted)
732 monitor_evnt_charge(cep, cep->charge, 0);
733 #endif
735 if(cep->aoc_valid == AOC_VALID)
737 if(cep->aoc_diff != cep->unitlength)
739 DBGL(DL_MSG, (log(LL_DBG, "handle_charge: AOCD unit length updated %d -> %d secs", cep->unitlength, cep->aoc_diff)));
741 cep->unitlength = cep->aoc_diff;
743 unitlen_chkupd(cep);
745 else
747 #ifdef NOTDEF
748 DBGL(DL_MSG, (log(LL_DBG, "handle_charge: AOCD unit length still %d secs", cep->unitlength)));
749 #endif
754 /*---------------------------------------------------------------------------*
755 * update kernel idle_time, earlyhup_time and unitlen_time
756 *---------------------------------------------------------------------------*/
757 void
758 unitlen_chkupd(cfg_entry_t *cep)
760 msg_timeout_upd_t tupd;
762 tupd.cdid = cep->cdid;
764 /* init the short hold data based on the shorthold algorithm type */
766 switch(cep->shorthold_algorithm)
768 case SHA_FIXU:
769 tupd.shorthold_data.shorthold_algorithm = SHA_FIXU;
770 tupd.shorthold_data.unitlen_time = cep->unitlength;
771 tupd.shorthold_data.idle_time = cep->idle_time_out;
772 tupd.shorthold_data.earlyhup_time = cep->earlyhangup;
773 break;
775 case SHA_VARU:
776 tupd.shorthold_data.shorthold_algorithm = SHA_VARU;
777 tupd.shorthold_data.unitlen_time = cep->unitlength;
778 tupd.shorthold_data.idle_time = cep->idle_time_out;
779 tupd.shorthold_data.earlyhup_time = 0;
780 break;
781 default:
782 log(LL_ERR, "unitlen_chkupd bad shorthold_algorithm %d", cep->shorthold_algorithm );
783 return;
784 break;
787 if((ioctl(isdnfd, I4B_TIMEOUT_UPD, &tupd)) < 0)
789 log(LL_ERR, "ioctl I4B_TIMEOUT_UPD failed: %s", strerror(errno));
790 error_exit(1, "ioctl I4B_TIMEOUT_UPD failed: %s", strerror(errno));
794 /*--------------------------------------------------------------------------*
795 * this is intended to be called by do_exit and closes down all
796 * active connections before the daemon exits or is reconfigured.
797 *--------------------------------------------------------------------------*/
798 void
799 close_allactive(void)
801 int i, j, k;
802 cfg_entry_t *cep = NULL;
804 j = 0;
806 for (i = 0; i < ncontroller; i++)
808 if((get_controller_state(i)) != CTRL_UP)
809 continue;
811 for (k = 0; k < isdn_ctrl_tab[i].nbch; k++)
813 if((ret_channel_state(i, k)) == CHAN_RUN)
815 if((cep = get_cep_by_cc(i, k)) != NULL)
817 #ifdef USE_CURSES
818 if(do_fullscreen)
819 display_disconnect(cep);
820 #endif
821 #ifdef I4B_EXTERNAL_MONITOR
822 monitor_evnt_disconnect(cep);
823 #endif
824 next_state(cep, EV_DRQ);
825 j++;
831 if(j)
833 log(LL_DMN, "close_allactive: waiting for all connections terminated");
834 sleep(5);
838 /*--------------------------------------------------------------------------*
839 * set an interface up
840 *--------------------------------------------------------------------------*/
841 void
842 if_up(cfg_entry_t *cep)
844 msg_updown_ind_t mui;
846 /* set interface up */
848 DBGL(DL_MSG, (log(LL_DBG, "if_up: taking %s%d up", bdrivername(cep->usrdevicename), cep->usrdeviceunit)));
850 mui.driver = cep->usrdevicename;
851 mui.driver_unit = cep->usrdeviceunit;
852 mui.updown = SOFT_ENA;
854 if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
856 log(LL_ERR, "if_up: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
857 error_exit(1, "if_up: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
859 cep->down_retry_count = 0;
861 #ifdef USE_CURSES
862 if(do_fullscreen)
863 display_updown(cep, 1);
864 #endif
865 #ifdef I4B_EXTERNAL_MONITOR
866 monitor_evnt_updown(cep, 1);
867 #endif
871 /*--------------------------------------------------------------------------*
872 * set an interface down
873 *--------------------------------------------------------------------------*/
874 void
875 if_down(cfg_entry_t *cep)
877 msg_updown_ind_t mui;
879 /* set interface up */
881 DBGL(DL_MSG, (log(LL_DBG, "if_down: taking %s%d down", bdrivername(cep->usrdevicename), cep->usrdeviceunit)));
883 mui.driver = cep->usrdevicename;
884 mui.driver_unit = cep->usrdeviceunit;
885 mui.updown = SOFT_DIS;
887 if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
889 log(LL_ERR, "if_down: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
890 error_exit(1, "if_down: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
892 cep->went_down_time = time(NULL);
893 cep->down_retry_count = 0;
895 #ifdef USE_CURSES
896 if(do_fullscreen)
897 display_updown(cep, 0);
898 #endif
899 #ifdef I4B_EXTERNAL_MONITOR
900 monitor_evnt_updown(cep, 0);
901 #endif
905 /*--------------------------------------------------------------------------*
906 * send a dial response to (an interface in) the kernel
907 *--------------------------------------------------------------------------*/
908 void
909 dialresponse(cfg_entry_t *cep, int dstat)
911 msg_dialout_resp_t mdr;
913 static char *stattab[] = {
914 "normal condition",
915 "temporary failure",
916 "permanent failure",
917 "dialout not allowed"
920 if(dstat < DSTAT_NONE || dstat > DSTAT_INONLY)
922 log(LL_ERR, "dialresponse: dstat out of range %d!", dstat);
923 return;
926 mdr.driver = cep->usrdevicename;
927 mdr.driver_unit = cep->usrdeviceunit;
928 mdr.stat = dstat;
929 mdr.cause = cep->disc_cause;
931 if((ioctl(isdnfd, I4B_DIALOUT_RESP, &mdr)) < 0)
933 log(LL_ERR, "dialresponse: ioctl I4B_DIALOUT_RESP failed: %s", strerror(errno));
934 error_exit(1, "dialresponse: ioctl I4B_DIALOUT_RESP failed: %s", strerror(errno));
937 DBGL(DL_DRVR, (log(LL_DBG, "dialresponse: sent [%s]", stattab[dstat])));
940 /*--------------------------------------------------------------------------*
941 * screening/presentation indicator
942 *--------------------------------------------------------------------------*/
943 void
944 handle_scrprs(int cdid, int scr, int prs, char *caller)
946 /* screening indicator */
948 if(scr < SCR_NONE || scr > SCR_NET)
950 log(LL_ERR, "msg_connect_ind: invalid screening indicator value %d!", scr);
952 else
954 static char *scrtab[] = {
955 "no screening indicator",
956 "sreening user provided, not screened",
957 "screening user provided, verified & passed",
958 "screening user provided, verified & failed",
959 "screening network provided", };
961 if(extcallattr)
963 log(LL_CHD, "%05d %s %s", cdid, caller, scrtab[scr]);
965 else
967 DBGL(DL_MSG, (log(LL_DBG, "%s - %s", caller, scrtab[scr])));
971 /* presentation indicator */
973 if(prs < PRS_NONE || prs > PRS_RESERVED)
975 log(LL_ERR, "msg_connect_ind: invalid presentation indicator value %d!", prs);
977 else
979 static char *prstab[] = {
980 "no presentation indicator",
981 "presentation allowed",
982 "presentation restricted",
983 "number not available due to interworking",
984 "reserved presentation value" };
986 if(extcallattr)
988 log(LL_CHD, "%05d %s %s", cdid, caller, prstab[prs]);
990 else
992 DBGL(DL_MSG, (log(LL_DBG, "%s - %s", caller, prstab[prs])));
997 /*--------------------------------------------------------------------------*
998 * check if the time is valid for an entry
999 *--------------------------------------------------------------------------*/
1000 static int
1001 isvalidtime(cfg_entry_t *cep)
1003 time_t t;
1004 struct tm *tp;
1006 if(cep->day == 0)
1007 return(1);
1009 t = time(NULL);
1010 tp = localtime(&t);
1012 if(cep->day & HD)
1014 if(isholiday(tp->tm_mday, (tp->tm_mon)+1, (tp->tm_year)+1900))
1016 DBGL(DL_VALID, (log(LL_DBG, "isvalidtime: holiday %d.%d.%d", tp->tm_mday, (tp->tm_mon)+1, (tp->tm_year)+1900)));
1017 goto dayok;
1021 if(cep->day & (1 << tp->tm_wday))
1023 DBGL(DL_VALID, (log(LL_DBG, "isvalidtime: day match")));
1024 goto dayok;
1027 return(0);
1029 dayok:
1030 if(cep->fromhr==0 && cep->frommin==0 && cep->tohr==0 && cep->tomin==0)
1032 DBGL(DL_VALID, (log(LL_DBG, "isvalidtime: no time specified, match!")));
1033 return(1);
1036 if(cep->tohr < cep->fromhr)
1038 /* before 00:00 */
1040 if( (tp->tm_hour > cep->fromhr) ||
1041 (tp->tm_hour == cep->fromhr && tp->tm_min > cep->frommin) )
1043 DBGL(DL_VALID, (log(LL_DBG, "isvalidtime: t<f-1, spec=%02d:%02d-%02d:%02d, curr=%02d:%02d, match!",
1044 cep->fromhr, cep->frommin,
1045 cep->tohr, cep->tomin,
1046 tp->tm_hour, tp->tm_min)));
1048 return(1);
1051 /* after 00:00 */
1053 if( (tp->tm_hour < cep->tohr) ||
1054 (tp->tm_hour == cep->tohr && tp->tm_min < cep->tomin) )
1056 DBGL(DL_VALID, (log(LL_DBG, "isvalidtime: t<f-2, spec=%02d:%02d-%02d:%02d, curr=%02d:%02d, match!",
1057 cep->fromhr, cep->frommin,
1058 cep->tohr, cep->tomin,
1059 tp->tm_hour, tp->tm_min)));
1061 return(1);
1064 else if(cep->fromhr == cep->tohr)
1066 if(tp->tm_min >= cep->frommin && tp->tm_min < cep->tomin)
1068 DBGL(DL_VALID, (log(LL_DBG, "isvalidtime: f=t, spec=%02d:%02d-%02d:%02d, curr=%02d:%02d, match!",
1069 cep->fromhr, cep->frommin,
1070 cep->tohr, cep->tomin,
1071 tp->tm_hour, tp->tm_min)));
1073 return(1);
1076 else
1078 if((tp->tm_hour > cep->fromhr && tp->tm_hour < cep->tohr) ||
1079 (tp->tm_hour == cep->fromhr && tp->tm_min >= cep->frommin) ||
1080 (tp->tm_hour == cep->tohr && tp->tm_min < cep->tomin) )
1082 DBGL(DL_VALID, (log(LL_DBG, "isvalidtime: t>f, spec=%02d:%02d-%02d:%02d, curr=%02d:%02d, match!",
1083 cep->fromhr, cep->frommin,
1084 cep->tohr, cep->tomin,
1085 tp->tm_hour, tp->tm_min)));
1086 return(1);
1089 DBGL(DL_VALID, (log(LL_DBG, "isvalidtime: spec=%02d:%02d-%02d:%02d, curr=%02d:%02d, no match!",
1090 cep->fromhr, cep->frommin,
1091 cep->tohr, cep->tomin,
1092 tp->tm_hour, tp->tm_min)));
1094 return(0);
1097 /* EOF */