2 * Copyright (c) 1997, 2003 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 - misc support routines
28 * ----------------------------------
32 * last edit-date: [Sat May 13 13:19:23 2006]
34 *---------------------------------------------------------------------------*/
38 static int isvalidtime(cfg_entry_t *cep);
40 /*---------------------------------------------------------------------------*
41 * find an active entry by driver type and driver unit
42 *---------------------------------------------------------------------------*/
44 find_active_entry_by_driver(int drivertype, int driverunit)
46 cfg_entry_t *cep = NULL;
49 for(i=0; i < nentries; i++)
51 cep = &cfg_entry_tab[i]; /* ptr to config entry */
53 if(!((cep->usrdevicename == drivertype) &&
54 (cep->usrdeviceunit == driverunit)))
59 /* check time interval */
61 if(isvalidtime(cep) == 0)
63 DBGL(DL_VALID, (llog(LL_DBG, "find_active_entry_by_driver: entry %d, time not valid!", i)));
69 if(cep->cdid == CDID_UNUSED)
71 DBGL(DL_MSG, (llog(LL_DBG, "find_active_entry_by_driver: entry %d [%s%d], cdid=CDID_UNUSED !",
72 i, bdrivername(drivertype), driverunit)));
75 else if(cep->cdid == CDID_RESERVED)
77 DBGL(DL_MSG, (llog(LL_DBG, "find_active_entry_by_driver: entry %d [%s%d], cdid=CDID_RESERVED!",
78 i, bdrivername(drivertype), driverunit)));
86 /*---------------------------------------------------------------------------*
87 * find entry by drivertype and driverunit and setup for dialing out
88 *---------------------------------------------------------------------------*/
90 find_by_device_for_dialout(int drivertype, int driverunit)
92 cfg_entry_t *cep = NULL;
95 for(i=0; i < nentries; i++)
97 cep = &cfg_entry_tab[i]; /* ptr to config entry */
99 /* compare driver type and unit */
101 if(!((cep->usrdevicename == drivertype) &&
102 (cep->usrdeviceunit == driverunit)))
107 /* check time interval */
109 if(isvalidtime(cep) == 0)
111 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialout: entry %d, time not valid!", i)));
115 /* found, check if already reserved */
117 if(cep->cdid == CDID_RESERVED)
119 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialout: entry %d, cdid reserved!", i)));
123 /* check if this entry is already in use ? */
125 if(cep->cdid != CDID_UNUSED)
127 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialout: entry %d, cdid in use", i)));
131 if((setup_dialout(cep)) == GOOD)
133 /* found an entry to be used for calling out */
135 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialout: found entry %d!", i)));
140 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialout: entry %d, setup_dialout() failed!", i)));
145 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialout: no entry found!")));
149 /*---------------------------------------------------------------------------*
150 * find entry by drivertype and driverunit and setup for dialing out
151 *---------------------------------------------------------------------------*/
153 find_by_device_for_dialoutnumber(msg_dialoutnumber_ind_t *mp)
155 cfg_entry_t *cep = NULL;
158 for(i=0; i < nentries; i++)
160 cep = &cfg_entry_tab[i]; /* ptr to config entry */
162 /* compare driver type and unit */
164 if(!((cep->usrdevicename == mp->driver) &&
165 (cep->usrdeviceunit == mp->driver_unit)))
170 /* check time interval */
172 if(isvalidtime(cep) == 0)
174 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, time not valid!", i)));
178 /* found, check if already reserved */
180 if(cep->cdid == CDID_RESERVED)
182 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, cdid reserved!", i)));
186 /* check if this entry is already in use ? */
188 if(cep->cdid != CDID_UNUSED)
190 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, cdid in use", i)));
194 cep->keypad[0] = '\0';
196 /* check number and copy to cep->remote_numbers[] */
198 for(j = 0; j < mp->cmdlen; j++)
200 if(!(isdigit(*(mp->cmd+j))))
202 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, dial string contains non-digit at pos %d", i, j)));
205 /* fill in number to dial */
206 cep->remote_numbers[0].number[j] = *(mp->cmd+j);
208 cep->remote_numbers[0].number[j] = '\0';
210 /* XXX subaddr does not have to be a digit! isgraph() would be a better idea */
211 for(j = 0; j < mp->subaddrlen; j++)
213 if(!(isdigit(*(mp->subaddr+j))))
215 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, subaddr string contains non-digit at pos %d", i, j)));
218 /* fill in number to dial */
219 cep->remote_numbers[0].subaddr[j] = *(mp->subaddr+j);
221 cep->remote_numbers[0].subaddr[j] = '\0';
223 cep->remote_numbers_count = 1;
225 if((setup_dialout(cep)) == GOOD)
227 /* found an entry to be used for calling out */
229 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialoutnumber: found entry %d!", i)));
234 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, setup_dialout() failed!", i)));
239 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_dialoutnumber: no entry found!")));
243 /*---------------------------------------------------------------------------*
244 * find entry by drivertype and driverunit and setup for send keypad
245 *---------------------------------------------------------------------------*/
247 find_by_device_for_keypad(int drivertype, int driverunit, int cmdlen, char *cmd)
249 cfg_entry_t *cep = NULL;
252 for(i=0; i < nentries; i++)
254 cep = &cfg_entry_tab[i]; /* ptr to config entry */
256 /* compare driver type and unit */
258 if(!((cep->usrdevicename == drivertype) &&
259 (cep->usrdeviceunit == driverunit)))
264 /* check time interval */
266 if(isvalidtime(cep) == 0)
268 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_keypad: entry %d, time not valid!", i)));
272 /* found, check if already reserved */
274 if(cep->cdid == CDID_RESERVED)
276 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_keypad: entry %d, cdid reserved!", i)));
280 /* check if this entry is already in use ? */
282 if(cep->cdid != CDID_UNUSED)
284 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_keypad: entry %d, cdid in use", i)));
288 cep->remote_numbers[0].number[0] = '\0';
289 cep->remote_numbers_count = 0;
290 cep->remote_phone_dialout.number[0] = '\0';
292 bzero(cep->keypad, KEYPAD_MAX);
293 strncpy(cep->keypad, cmd, cmdlen);
295 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_keypad: entry %d, keypad string is %s", i, cep->keypad)));
297 if((setup_dialout(cep)) == GOOD)
299 /* found an entry to be used for calling out */
301 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_keypad: found entry %d!", i)));
306 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_keypad: entry %d, setup_dialout() failed!", i)));
311 DBGL(DL_MSG, (llog(LL_DBG, "find_by_device_for_keypad: no entry found!")));
315 /*---------------------------------------------------------------------------*
316 * find entry by drivertype and driverunit and setup for dialing out
317 *---------------------------------------------------------------------------*/
319 setup_dialout(cfg_entry_t *cep)
323 /* check controller operational */
325 if((get_controller_state(cep->isdncontroller)) != CTRL_UP)
327 DBGL(DL_MSG, (llog(LL_DBG, "setup_dialout: entry %s, controller is down", cep->name)));
331 cep->isdncontrollerused = cep->isdncontroller;
333 /* check channel available */
335 switch(cep->isdnchannel)
338 for (i = 0; i < isdn_ctrl_tab[cep->isdncontroller].nbch; i++)
340 if(ret_channel_state(cep->isdncontroller, i) == CHAN_IDLE)
344 if (i == isdn_ctrl_tab[cep->isdncontroller].nbch)
346 DBGL(DL_MSG, (llog(LL_DBG, "setup_dialout: entry %s, no channel free", cep->name)));
349 cep->isdnchannelused = CHAN_ANY;
353 if((ret_channel_state(cep->isdncontroller, cep->isdnchannel)) != CHAN_IDLE)
355 DBGL(DL_MSG, (llog(LL_DBG, "setup_dialout: entry %s, channel not free", cep->name)));
358 cep->isdnchannelused = cep->isdnchannel;
362 DBGL(DL_MSG, (llog(LL_DBG, "setup_dialout: entry %s ok!", cep->name)));
364 /* preset disconnect cause */
366 SET_CAUSE_TYPE(cep->disc_cause, CAUSET_I4B);
367 SET_CAUSE_VAL(cep->disc_cause, CAUSE_I4B_NORMAL);
372 /*---------------------------------------------------------------------------*
373 * find entry by drivertype and driverunit
374 *---------------------------------------------------------------------------*/
376 get_cep_by_driver(int drivertype, int driverunit)
378 cfg_entry_t *cep = NULL;
381 for(i=0; i < nentries; i++)
383 cep = &cfg_entry_tab[i]; /* ptr to config entry */
385 if(!((cep->usrdevicename == drivertype) &&
386 (cep->usrdeviceunit == driverunit)))
391 /* check time interval */
393 if(isvalidtime(cep) == 0)
395 DBGL(DL_MSG, (llog(LL_DBG, "get_cep_by_driver: entry %d, time not valid!", i)));
399 DBGL(DL_MSG, (llog(LL_DBG, "get_cep_by_driver: found entry %d!", i)));
405 /*---------------------------------------------------------------------------*
406 * find a matching entry for an incoming call
408 * - not found/no match: log output with LL_CHD and return NULL
409 * - found/match: make entry in free cep, return address
410 *---------------------------------------------------------------------------*/
412 find_matching_entry_incoming(msg_connect_ind_t *mp)
414 cfg_entry_t *cep = NULL;
417 /* check for CW (call waiting) early */
419 if(mp->channel == CHAN_NO)
423 char *src_tela = "ERROR-src_tela";
424 char *dst_tela = "ERROR-dst_tela";
426 src_tela = get_alias(mp->src_telno);
427 dst_tela = get_alias(mp->dst_telno);
429 llog(LL_CHD, "%05d <unknown> CW from %s to %s (no channel free)",
430 mp->header.cdid, src_tela, dst_tela);
434 llog(LL_CHD, "%05d <unknown> call waiting from %s to %s (no channel free)",
435 mp->header.cdid, mp->src_telno, mp->dst_telno);
440 for(i=0; i < nentries; i++)
443 cep = &cfg_entry_tab[i]; /* ptr to config entry */
445 /* check my number */
447 if(strncmp(cep->local_phone_incoming.number, mp->dst_telno, strlen(cep->local_phone_incoming.number)))
449 DBGL(DL_MSG, (llog(LL_DBG, "find_matching_entry_incoming: entry %d, myno %s != incomingno %s", i,
450 cep->local_phone_incoming.number, mp->dst_telno)));
454 if (cep->usesubaddr && strncmp(cep->local_phone_incoming.subaddr, mp->dst_subaddr, strlen(cep->local_phone_incoming.subaddr)))
456 DBGL(DL_MSG, (llog(LL_DBG, "find_matching_entry_incoming: entry %d, mysubno %s != incomingsubno %s", i,
457 cep->local_phone_incoming.subaddr, mp->dst_subaddr)));
461 /* check all allowed remote numbers for this entry */
463 for (n = 0; n < cep->incoming_numbers_count; n++)
465 incoming_number_t *in = &cep->remote_phone_incoming[n];
468 * An incoming number matches whenever the main
469 * phone number either matches or is a wildcard AND
470 * subaddresses are either not in use or match as
471 * well (or the required subaddress is a wildcard).
472 * This means that if subaddresses are in use and
473 * the main phone number is a wildcard, the
474 * subaddress is still required to match.
476 * At first glance, this does not seem logical,
477 * but since subaddress usage can be configured per
478 * entry, disregarding the subaddress if the main
479 * number matches would needlessly limit the user's
483 if ((in->number[0] == '*') || (!strncmp(in->number, mp->src_telno, strlen(in->number))))
485 if ((!cep->usesubaddr) || (in->subaddr[0] == '*') || (!strncmp(in->subaddr, mp->src_subaddr, strlen(in->subaddr))))
487 DBGL(DL_MSG, (llog(LL_DBG, "find_matching_entry_incoming: entry %d, match: remno %s = incomingfromno %s", i,
488 in->number, mp->src_telno)));
494 DBGL(DL_MSG, (llog(LL_DBG, "find_matching_entry_incoming: entry %d, remno %s != incomingfromno %s", i,
495 in->number, mp->src_telno)));
499 /* If all configured remote numbers have been tested without success, proceed to the next entry. */
500 if (n >= cep->incoming_numbers_count)
503 /* check b protocol */
505 if(cep->b1protocol != mp->bprot)
507 DBGL(DL_MSG, (llog(LL_DBG, "find_matching_entry_incoming: entry %d, bprot %d != incomingprot %d", i,
508 cep->b1protocol, mp->bprot)));
512 /* is this entry currently in use ? */
514 if(cep->cdid != CDID_UNUSED)
516 if(cep->cdid == CDID_RESERVED)
518 DBGL(DL_MSG, (llog(LL_DBG, "find_matching_entry_incoming: entry %d, cdid is reserved", i)));
520 else if (cep->dialin_reaction == REACT_ACCEPT
521 && cep->dialouttype == DIALOUT_CALLEDBACK)
524 * We might consider doing this even if this is
525 * not a calledback config entry - BUT: there are
526 * severe race conditions and timinig problems
527 * ex. if both sides run I4B with no callback
528 * delay - both may shutdown the outgoing call
529 * and never be able to establish a connection.
530 * In the called-back case this should not happen.
532 DBGL(DL_MSG, (llog(LL_DBG, "find_matching_entry_incoming: entry %d, incoming call for callback in progress (cdid %05d)", i, cep->cdid)));
534 /* save the current call state, we're going to overwrite it with the
535 * new incoming state below... */
536 cep->saved_call.cdid = cep->cdid;
537 cep->saved_call.controller = cep->isdncontrollerused;
538 cep->saved_call.channel = cep->isdnchannelused;
542 DBGL(DL_MSG, (llog(LL_DBG, "find_matching_entry_incoming: entry %d, cdid in use", i)));
543 continue; /* yes, next */
547 /* check controller value ok */
549 if(mp->controller > ncontroller)
551 llog(LL_CHD, "%05d %s incoming call with invalid controller %d",
552 mp->header.cdid, cep->name, mp->controller);
556 /* check controller marked up */
558 if((get_controller_state(mp->controller)) != CTRL_UP)
560 llog(LL_CHD, "%05d %s incoming call, controller %d DOWN!",
561 mp->header.cdid, cep->name, mp->controller);
566 * check controller he wants, check for any
567 * controller or specific controller
570 if( (mp->controller != -1) &&
571 (mp->controller != cep->isdncontroller) )
573 llog(LL_CHD, "%05d %s incoming call, controller %d != incoming %d",
574 mp->header.cdid, cep->name,
575 cep->isdncontroller, mp->controller);
579 /* check channel he wants */
584 for (i = 0; i < isdn_ctrl_tab[mp->controller].nbch; i++)
586 if(ret_channel_state(mp->controller, i) == CHAN_IDLE)
590 if (i == isdn_ctrl_tab[mp->controller].nbch)
592 llog(LL_CHD, "%05d %s incoming call, no channel free!",
593 mp->header.cdid, cep->name);
599 llog(LL_CHD, "%05d %s incoming call, call waiting (no channel available)!",
600 mp->header.cdid, cep->name);
605 if((ret_channel_state(mp->controller, mp->channel)) != CHAN_IDLE)
607 llog(LL_CHD, "%05d %s incoming call, channel B%d not free!",
608 mp->header.cdid, cep->name, mp->channel+1);
614 /* check time interval */
616 if(isvalidtime(cep) == 0)
618 DBGL(DL_MSG, (llog(LL_DBG, "find_matching_entry_incoming: entry %d, time not valid!", i)));
622 /* found a matching entry */
624 cep->cdid = mp->header.cdid;
625 cep->isdncontrollerused = mp->controller;
626 cep->isdnchannelused = mp->channel;
627 /*XXX*/ cep->disc_cause = 0;
629 /* cp number to real one used */
631 strcpy(cep->real_phone_incoming.number, mp->src_telno);
633 /* copy display string */
635 strcpy(cep->display, mp->display);
637 /* entry currently down ? */
639 if(cep->state == ST_DOWN)
641 msg_updown_ind_t mui;
643 /* set interface up */
645 DBGL(DL_MSG, (llog(LL_DBG, "find_matching_entry_incoming: entry %d, ", i)));
647 mui.driver = cep->usrdevicename;
648 mui.driver_unit = cep->usrdeviceunit;
649 mui.updown = SOFT_ENA;
651 if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
653 llog(LL_ERR, "find_matching_entry_incoming: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
654 error_exit(1, "find_matching_entry_incoming: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
657 cep->down_retry_count = 0;
658 cep->state = ST_IDLE;
665 char *src_tela = "ERROR-src_tela";
666 char *dst_tela = "ERROR-dst_tela";
668 src_tela = get_alias(mp->src_telno);
669 dst_tela = get_alias(mp->dst_telno);
671 llog(LL_CHD, "%05d Call from %s to %s",
672 mp->header.cdid, src_tela, dst_tela);
676 llog(LL_CHD, "%05d <unknown> incoming call from %s to %s ctrl %d",
677 mp->header.cdid, mp->src_telno, mp->dst_telno, mp->controller);
682 /*---------------------------------------------------------------------------*
683 * return address of ACTIVE config entry by controller and channel
684 *---------------------------------------------------------------------------*/
686 get_cep_by_cc(int ctrlr, int chan)
690 if((chan < 0) || (chan >= isdn_ctrl_tab[ctrlr].nbch))
693 for(i=0; i < nentries; i++)
695 if((cfg_entry_tab[i].cdid != CDID_UNUSED) &&
696 (cfg_entry_tab[i].cdid != CDID_RESERVED) &&
697 (cfg_entry_tab[i].isdnchannelused == chan) &&
698 (cfg_entry_tab[i].isdncontrollerused == ctrlr) &&
699 ((ret_channel_state(ctrlr, chan)) == CHAN_RUN))
701 return(&cfg_entry_tab[i]);
707 /*---------------------------------------------------------------------------*
708 * return address of config entry identified by cdid
709 *---------------------------------------------------------------------------*/
711 get_cep_by_cdid(int cdid)
715 for(i=0; i < nentries; i++)
717 if(cfg_entry_tab[i].cdid == cdid
718 || cfg_entry_tab[i].saved_call.cdid == cdid)
719 return(&cfg_entry_tab[i]);
724 /*---------------------------------------------------------------------------*
725 * return b channel driver type name string
726 *---------------------------------------------------------------------------*/
728 bdrivername(int drivertype)
730 static char *bdtab[] = {
739 if(drivertype >= BDRV_RBCH && drivertype <= BDRV_ING)
740 return(bdtab[drivertype]);
745 /*---------------------------------------------------------------------------*
746 * process AOCD charging messages
747 *---------------------------------------------------------------------------*/
749 handle_charge(cfg_entry_t *cep)
751 time_t now = time(NULL);
753 if(cep->aoc_last == 0) /* no last timestamp yet ? */
755 cep->aoc_last = now; /* add time stamp */
757 else if(cep->aoc_now == 0) /* no current timestamp yet ? */
759 cep->aoc_now = now; /* current timestamp */
763 cep->aoc_last = cep->aoc_now;
765 cep->aoc_diff = cep->aoc_now - cep->aoc_last;
766 cep->aoc_valid = AOC_VALID;
774 #ifdef I4B_EXTERNAL_MONITOR
775 if(do_monitor && accepted)
776 monitor_evnt_charge(cep, cep->charge, 0);
779 if(cep->aoc_valid == AOC_VALID)
781 if(cep->aoc_diff != cep->unitlength)
783 DBGL(DL_MSG, (llog(LL_DBG, "handle_charge: AOCD unit length updated %d -> %d secs", cep->unitlength, cep->aoc_diff)));
785 cep->unitlength = cep->aoc_diff;
792 DBGL(DL_MSG, (llog(LL_DBG, "handle_charge: AOCD unit length still %d secs", cep->unitlength)));
798 /*---------------------------------------------------------------------------*
799 * update kernel idle_time, earlyhup_time and unitlen_time
800 *---------------------------------------------------------------------------*/
802 unitlen_chkupd(cfg_entry_t *cep)
804 msg_timeout_upd_t tupd;
806 tupd.cdid = cep->cdid;
808 /* init the short hold data based on the shorthold algorithm type */
810 switch(cep->shorthold_algorithm)
813 tupd.shorthold_data.shorthold_algorithm = SHA_FIXU;
814 tupd.shorthold_data.unitlen_time = cep->unitlength;
815 tupd.shorthold_data.idle_time = cep->idle_time_out;
816 tupd.shorthold_data.earlyhup_time = cep->earlyhangup;
820 tupd.shorthold_data.shorthold_algorithm = SHA_VARU;
821 tupd.shorthold_data.unitlen_time = cep->unitlength;
822 tupd.shorthold_data.idle_time = cep->idle_time_out;
823 tupd.shorthold_data.earlyhup_time = 0;
826 llog(LL_ERR, "unitlen_chkupd bad shorthold_algorithm %d", cep->shorthold_algorithm );
831 if((ioctl(isdnfd, I4B_TIMEOUT_UPD, &tupd)) < 0)
833 llog(LL_ERR, "ioctl I4B_TIMEOUT_UPD failed: %s", strerror(errno));
834 error_exit(1, "ioctl I4B_TIMEOUT_UPD failed: %s", strerror(errno));
838 /*--------------------------------------------------------------------------*
839 * this is intended to be called by do_exit and closes down all
840 * active connections before the daemon exits or is reconfigured.
841 *--------------------------------------------------------------------------*/
843 close_allactive(void)
846 cfg_entry_t *cep = NULL;
850 for (i = 0; i < ncontroller; i++)
852 if((get_controller_state(i)) != CTRL_UP)
855 for (k = 0; k < isdn_ctrl_tab[i].nbch; k++)
857 if((ret_channel_state(i, k)) == CHAN_RUN)
859 if((cep = get_cep_by_cc(i, k)) != NULL)
863 display_disconnect(cep);
865 #ifdef I4B_EXTERNAL_MONITOR
866 monitor_evnt_disconnect(cep);
868 next_state(cep, EV_DRQ);
877 llog(LL_DMN, "close_allactive: waiting for all connections terminated");
882 /*--------------------------------------------------------------------------*
883 * set an interface up
884 *--------------------------------------------------------------------------*/
886 if_up(cfg_entry_t *cep)
888 msg_updown_ind_t mui;
890 /* set interface up */
892 DBGL(DL_MSG, (llog(LL_DBG, "if_up: taking %s%d up", bdrivername(cep->usrdevicename), cep->usrdeviceunit)));
894 mui.driver = cep->usrdevicename;
895 mui.driver_unit = cep->usrdeviceunit;
896 mui.updown = SOFT_ENA;
898 if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
900 llog(LL_ERR, "if_up: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
901 error_exit(1, "if_up: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
903 cep->down_retry_count = 0;
907 display_updown(cep, 1);
909 #ifdef I4B_EXTERNAL_MONITOR
910 monitor_evnt_updown(cep, 1);
915 /*--------------------------------------------------------------------------*
916 * set an interface down
917 *--------------------------------------------------------------------------*/
919 if_down(cfg_entry_t *cep)
921 msg_updown_ind_t mui;
923 /* set interface up */
925 DBGL(DL_MSG, (llog(LL_DBG, "if_down: taking %s%d down", bdrivername(cep->usrdevicename), cep->usrdeviceunit)));
927 mui.driver = cep->usrdevicename;
928 mui.driver_unit = cep->usrdeviceunit;
929 mui.updown = SOFT_DIS;
931 if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
933 llog(LL_ERR, "if_down: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
934 error_exit(1, "if_down: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
936 cep->went_down_time = time(NULL);
937 cep->down_retry_count = 0;
941 display_updown(cep, 0);
943 #ifdef I4B_EXTERNAL_MONITOR
944 monitor_evnt_updown(cep, 0);
949 /*--------------------------------------------------------------------------*
950 * send a dial response to (an interface in) the kernel
951 *--------------------------------------------------------------------------*/
953 dialresponse(cfg_entry_t *cep, int dstat)
955 msg_dialout_resp_t mdr;
957 static char *stattab[] = {
961 "dialout not allowed"
964 if(dstat < DSTAT_NONE || dstat > DSTAT_INONLY)
966 llog(LL_ERR, "dialresponse: dstat out of range %d!", dstat);
970 mdr.driver = cep->usrdevicename;
971 mdr.driver_unit = cep->usrdeviceunit;
973 mdr.cause = cep->disc_cause;
975 if((ioctl(isdnfd, I4B_DIALOUT_RESP, &mdr)) < 0)
977 llog(LL_ERR, "dialresponse: ioctl I4B_DIALOUT_RESP failed: %s", strerror(errno));
978 error_exit(1, "dialresponse: ioctl I4B_DIALOUT_RESP failed: %s", strerror(errno));
981 DBGL(DL_DRVR, (llog(LL_DBG, "dialresponse: sent [%s]", stattab[dstat])));
984 /*--------------------------------------------------------------------------*
985 * screening/presentation indicator
986 *--------------------------------------------------------------------------*/
988 handle_scrprs(int cdid, int scr, int prs, char *caller)
990 /* screening indicator */
992 if(scr < SCR_NONE || scr > SCR_NET)
994 llog(LL_ERR, "msg_connect_ind: invalid screening indicator value %d!", scr);
998 static char *scrtab[] = {
999 "no screening indicator",
1000 "sreening user provided, not screened",
1001 "screening user provided, verified & passed",
1002 "screening user provided, verified & failed",
1003 "screening network provided", };
1007 llog(LL_CHD, "%05d %s %s", cdid, caller, scrtab[scr]);
1011 DBGL(DL_MSG, (llog(LL_DBG, "%s - %s", caller, scrtab[scr])));
1015 /* presentation indicator */
1017 if(prs < PRS_NONE || prs > PRS_RESERVED)
1019 llog(LL_ERR, "msg_connect_ind: invalid presentation indicator value %d!", prs);
1023 static char *prstab[] = {
1024 "no presentation indicator",
1025 "presentation allowed",
1026 "presentation restricted",
1027 "number not available due to interworking",
1028 "reserved presentation value" };
1032 llog(LL_CHD, "%05d %s %s", cdid, caller, prstab[prs]);
1036 DBGL(DL_MSG, (llog(LL_DBG, "%s - %s", caller, prstab[prs])));
1041 /*--------------------------------------------------------------------------*
1042 * check if the time is valid for an entry
1043 *--------------------------------------------------------------------------*/
1045 isvalidtime(cfg_entry_t *cep)
1058 if(isholiday(tp->tm_mday, (tp->tm_mon)+1, (tp->tm_year)+1900))
1060 DBGL(DL_VALID, (llog(LL_DBG, "isvalidtime: holiday %d.%d.%d", tp->tm_mday, (tp->tm_mon)+1, (tp->tm_year)+1900)));
1065 if(cep->day & (1 << tp->tm_wday))
1067 DBGL(DL_VALID, (llog(LL_DBG, "isvalidtime: day match")));
1074 if(cep->fromhr==0 && cep->frommin==0 && cep->tohr==0 && cep->tomin==0)
1076 DBGL(DL_VALID, (llog(LL_DBG, "isvalidtime: no time specified, match!")));
1080 if(cep->tohr < cep->fromhr)
1084 if( (tp->tm_hour > cep->fromhr) ||
1085 (tp->tm_hour == cep->fromhr && tp->tm_min > cep->frommin) )
1087 DBGL(DL_VALID, (llog(LL_DBG, "isvalidtime: t<f-1, spec=%02d:%02d-%02d:%02d, curr=%02d:%02d, match!",
1088 cep->fromhr, cep->frommin,
1089 cep->tohr, cep->tomin,
1090 tp->tm_hour, tp->tm_min)));
1097 if( (tp->tm_hour < cep->tohr) ||
1098 (tp->tm_hour == cep->tohr && tp->tm_min < cep->tomin) )
1100 DBGL(DL_VALID, (llog(LL_DBG, "isvalidtime: t<f-2, spec=%02d:%02d-%02d:%02d, curr=%02d:%02d, match!",
1101 cep->fromhr, cep->frommin,
1102 cep->tohr, cep->tomin,
1103 tp->tm_hour, tp->tm_min)));
1108 else if(cep->fromhr == cep->tohr)
1110 if(tp->tm_min >= cep->frommin && tp->tm_min < cep->tomin)
1112 DBGL(DL_VALID, (llog(LL_DBG, "isvalidtime: f=t, spec=%02d:%02d-%02d:%02d, curr=%02d:%02d, match!",
1113 cep->fromhr, cep->frommin,
1114 cep->tohr, cep->tomin,
1115 tp->tm_hour, tp->tm_min)));
1122 if((tp->tm_hour > cep->fromhr && tp->tm_hour < cep->tohr) ||
1123 (tp->tm_hour == cep->fromhr && tp->tm_min >= cep->frommin) ||
1124 (tp->tm_hour == cep->tohr && tp->tm_min < cep->tomin) )
1126 DBGL(DL_VALID, (llog(LL_DBG, "isvalidtime: t>f, spec=%02d:%02d-%02d:%02d, curr=%02d:%02d, match!",
1127 cep->fromhr, cep->frommin,
1128 cep->tohr, cep->tomin,
1129 tp->tm_hour, tp->tm_min)));
1133 DBGL(DL_VALID, (llog(LL_DBG, "isvalidtime: spec=%02d:%02d-%02d:%02d, curr=%02d:%02d, no match!",
1134 cep->fromhr, cep->frommin,
1135 cep->tohr, cep->tomin,
1136 tp->tm_hour, tp->tm_min)));
1141 /*--------------------------------------------------------------------------*
1142 * prepend national or international prefix to a number
1143 *--------------------------------------------------------------------------*/
1144 int add_number_prefix(char *number, int type_of_number)
1146 char tmp[TELNO_MAX];
1150 if (type_of_number == TON_NATIONAL || type_of_number == TON_INTERNAT)
1152 if (type_of_number == TON_NATIONAL)
1153 prefix = prefixnational;
1155 prefix = prefixinternational;
1157 /* Add prefix only if not already there */
1158 if (strncmp(number, prefix, strlen(prefix)) != 0)
1160 snprintf(tmp, sizeof(tmp)-1, "%s%s", prefix, number);
1161 strncpy(number, tmp, TELNO_MAX-1);