2 * Copyright (c) 1997, 1999 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: [Mon Jul 5 15:29:22 1999]
34 *---------------------------------------------------------------------------*/
38 /*---------------------------------------------------------------------------*
39 * find an active entry by driver type and driver unit
40 *---------------------------------------------------------------------------*/
42 find_active_entry_by_driver(int drivertype, int driverunit)
44 cfg_entry_t *cep = NULL;
47 for(i=0; i < nentries; i++)
49 cep = &cfg_entry_tab[i]; /* ptr to config entry */
51 if(!((cep->usrdevicename == drivertype) &&
52 (cep->usrdeviceunit == driverunit)))
59 if(cep->cdid == CDID_UNUSED)
61 DBGL(DL_MSG, (log(LL_DBG, "find_active_entry_by_driver: entry %d, cdid is CDID_UNUSED!", i)));
64 else if(cep->cdid == CDID_RESERVED)
66 DBGL(DL_MSG, (log(LL_DBG, "find_active_entry_by_driver: entry %d, cdid is CDID_RESERVED!", i)));
74 /*---------------------------------------------------------------------------*
75 * find entry by drivertype and driverunit and setup for dialing out
76 *---------------------------------------------------------------------------*/
78 find_by_device_for_dialout(int drivertype, int driverunit)
80 cfg_entry_t *cep = NULL;
83 for(i=0; i < nentries; i++)
85 cep = &cfg_entry_tab[i]; /* ptr to config entry */
87 /* compare driver type and unit */
89 if(!((cep->usrdevicename == drivertype) &&
90 (cep->usrdeviceunit == driverunit)))
95 /* found, check if already reserved */
97 if(cep->cdid == CDID_RESERVED)
99 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, cdid reserved!", i)));
103 /* check if this entry is already in use ? */
105 if(cep->cdid != CDID_UNUSED)
107 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, cdid in use", i)));
111 if((setup_dialout(cep)) == GOOD)
113 /* found an entry to be used for calling out */
115 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: found entry %d!", i)));
120 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, setup_dialout() failed!", i)));
125 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: no entry found!")));
129 /*---------------------------------------------------------------------------*
130 * find entry by drivertype and driverunit and setup for dialing out
131 *---------------------------------------------------------------------------*/
133 find_by_device_for_dialoutnumber(int drivertype, int driverunit, int cmdlen, char *cmd)
135 cfg_entry_t *cep = NULL;
138 for(i=0; i < nentries; i++)
140 cep = &cfg_entry_tab[i]; /* ptr to config entry */
142 /* compare driver type and unit */
144 if(!((cep->usrdevicename == drivertype) &&
145 (cep->usrdeviceunit == driverunit)))
150 /* found, check if already reserved */
152 if(cep->cdid == CDID_RESERVED)
154 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, cdid reserved!", i)));
158 /* check if this entry is already in use ? */
160 if(cep->cdid != CDID_UNUSED)
162 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, cdid in use", i)));
166 /* check number and copy to cep->remote_numbers[] */
168 for(j = 0; j < cmdlen; j++)
170 if(!(isdigit(*(cmd+j))))
172 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, dial string contains non-digit at pos %d", i, j)));
175 /* fill in number to dial */
176 cep->remote_numbers[0].number[j] = *(cmd+j);
178 cep->remote_numbers[0].number[j] = '\0';
179 cep->remote_numbers_count = 1;
181 if((setup_dialout(cep)) == GOOD)
183 /* found an entry to be used for calling out */
185 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: found entry %d!", i)));
190 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, setup_dialout() failed!", i)));
195 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: no entry found!")));
199 /*---------------------------------------------------------------------------*
200 * find entry by drivertype and driverunit and setup for dialing out
201 *---------------------------------------------------------------------------*/
203 setup_dialout(cfg_entry_t *cep)
205 /* check controller operational */
207 if((get_controller_state(cep->isdncontroller)) != CTRL_UP)
209 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, controller is down", cep->name)));
213 cep->isdncontrollerused = cep->isdncontroller;
215 /* check channel available */
217 switch(cep->isdnchannel)
221 if((ret_channel_state(cep->isdncontroller, cep->isdnchannel)) != CHAN_IDLE)
223 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, channel not free", cep->name)));
226 cep->isdnchannelused = cep->isdnchannel;
230 if(((ret_channel_state(cep->isdncontroller, CHAN_B1)) != CHAN_IDLE) &&
231 ((ret_channel_state(cep->isdncontroller, CHAN_B2)) != CHAN_IDLE))
233 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, no channel free", cep->name)));
236 cep->isdnchannelused = CHAN_ANY;
240 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, channel undefined", cep->name)));
245 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s ok!", cep->name)));
247 /* preset disconnect cause */
249 SET_CAUSE_TYPE(cep->disc_cause, CAUSET_I4B);
250 SET_CAUSE_VAL(cep->disc_cause, CAUSE_I4B_NORMAL);
255 /*---------------------------------------------------------------------------*
256 * find entry by drivertype and driverunit
257 *---------------------------------------------------------------------------*/
259 get_cep_by_driver(int drivertype, int driverunit)
261 cfg_entry_t *cep = NULL;
264 for(i=0; i < nentries; i++)
266 cep = &cfg_entry_tab[i]; /* ptr to config entry */
268 if(!((cep->usrdevicename == drivertype) &&
269 (cep->usrdeviceunit == driverunit)))
274 DBGL(DL_MSG, (log(LL_DBG, "get_cep_by_driver: found entry %d!", i)));
280 /*---------------------------------------------------------------------------*
281 * find a matching entry for an incoming call
283 * - not found/no match: log output with LL_CHD and return NULL
284 * - found/match: make entry in free cep, return address
285 *---------------------------------------------------------------------------*/
287 find_matching_entry_incoming(msg_connect_ind_t *mp)
289 cfg_entry_t *cep = NULL;
292 /* check for CW (call waiting) early */
294 if(mp->channel == CHAN_NO)
298 char *src_tela = "ERROR-src_tela";
299 char *dst_tela = "ERROR-dst_tela";
301 src_tela = get_alias(mp->src_telno);
302 dst_tela = get_alias(mp->dst_telno);
304 log(LL_CHD, "%05d <unknown> CW from %s to %s (no channel free)",
305 mp->header.cdid, src_tela, dst_tela);
309 log(LL_CHD, "%05d <unknown> call waiting from %s to %s (no channel free)",
310 mp->header.cdid, mp->src_telno, mp->dst_telno);
315 for(i=0; i < nentries; i++)
318 cep = &cfg_entry_tab[i]; /* ptr to config entry */
320 /* check my number */
322 if(strncmp(cep->local_phone_incoming, mp->dst_telno, strlen(cep->local_phone_incoming)))
324 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, myno %s != incomingno %s", i,
325 cep->local_phone_incoming, mp->dst_telno)));
329 /* check all allowed remote number's for this entry */
331 for (n = 0; n < cep->incoming_numbers_count; n++)
333 incoming_number_t *in = &cep->remote_phone_incoming[n];
334 if(in->number[0] == '*')
336 if(strncmp(in->number, mp->src_telno, strlen(in->number)))
338 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, remno %s != incomingfromno %s", i,
339 in->number, mp->src_telno)));
344 if (n >= cep->incoming_numbers_count)
347 /* screening indicator XXX */
352 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - no screening indicator", mp->src_telno)));
356 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening user provided, not screened", mp->src_telno)));
360 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening user provided, verified & passed", mp->src_telno)));
364 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening user provided, verified & failed", mp->src_telno)));
368 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening network provided", mp->src_telno)));
372 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: ERROR %s - invalid screening indicator!", mp->src_telno)));
376 /* check b protocol */
378 if(cep->b1protocol != mp->bprot)
380 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, bprot %d != incomingprot %d", i,
381 cep->b1protocol, mp->bprot)));
385 /* is this entry currently in use ? */
387 if(cep->cdid != CDID_UNUSED)
389 if(cep->cdid == CDID_RESERVED)
391 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, cdid is reserved", i)));
393 else if (cep->dialin_reaction == REACT_ACCEPT
394 && cep->dialouttype == DIALOUT_CALLEDBACK)
397 * We might consider doing this even if this is
398 * not a calledback config entry - BUT: there are
399 * severe race conditions and timinig problems
400 * ex. if both sides run I4B with no callback
401 * delay - both may shutdown the outgoing call
402 * and never be able to establish a connection.
403 * In the called-back case this should not happen.
405 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, incoming call for callback in progress (cdid %05d)", i, cep->cdid)));
407 /* save the current call state, we're going to overwrite it with the
408 * new incoming state below... */
409 cep->saved_call.cdid = cep->cdid;
410 cep->saved_call.controller = cep->isdncontrollerused;
411 cep->saved_call.channel = cep->isdnchannelused;
415 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, cdid in use", i)));
416 continue; /* yes, next */
420 /* check controller value ok */
422 if(mp->controller > ncontroller)
424 log(LL_CHD, "%05d %s incoming call with invalid controller %d",
425 mp->header.cdid, cep->name, mp->controller);
429 /* check controller marked up */
431 if((get_controller_state(mp->controller)) != CTRL_UP)
433 log(LL_CHD, "%05d %s incoming call, controller %d DOWN!",
434 mp->header.cdid, cep->name, mp->controller);
438 /* check channel he wants */
444 if((ret_channel_state(mp->controller, mp->channel)) != CHAN_IDLE)
446 log(LL_CHD, "%05d %s incoming call, channel %s not free!",
447 mp->header.cdid, cep->name, mp->channel == CHAN_B1 ? "B1" : "B2");
453 if(((ret_channel_state(mp->controller, CHAN_B1)) != CHAN_IDLE) &&
454 ((ret_channel_state(mp->controller, CHAN_B2)) != CHAN_IDLE))
456 log(LL_CHD, "%05d %s incoming call, no channel free!",
457 mp->header.cdid, cep->name);
463 log(LL_CHD, "%05d %s incoming call, call waiting (no channel available)!",
464 mp->header.cdid, cep->name);
469 log(LL_CHD, "%05d %s incoming call, ERROR, channel undefined!",
470 mp->header.cdid, cep->name);
475 /* found a matching entry */
477 cep->cdid = mp->header.cdid;
478 cep->isdncontrollerused = mp->controller;
479 cep->isdnchannelused = mp->channel;
480 /*XXX*/ cep->disc_cause = 0;
482 /* cp number to real one used */
484 strcpy(cep->real_phone_incoming, mp->src_telno);
486 /* copy display string */
488 strcpy(cep->display, mp->display);
490 /* entry currently down ? */
492 if(cep->state == ST_DOWN)
494 msg_updown_ind_t mui;
496 /* set interface up */
498 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, ", i)));
500 mui.driver = cep->usrdevicename;
501 mui.driver_unit = cep->usrdeviceunit;
502 mui.updown = SOFT_ENA;
504 if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
506 log(LL_ERR, "find_matching_entry_incoming: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
510 cep->down_retry_count = 0;
511 cep->state = ST_IDLE;
518 char *src_tela = "ERROR-src_tela";
519 char *dst_tela = "ERROR-dst_tela";
521 src_tela = get_alias(mp->src_telno);
522 dst_tela = get_alias(mp->dst_telno);
524 log(LL_CHD, "%05d Call from %s to %s",
525 mp->header.cdid, src_tela, dst_tela);
529 log(LL_CHD, "%05d <unknown> incoming call from %s to %s",
530 mp->header.cdid, mp->src_telno, mp->dst_telno);
535 /*---------------------------------------------------------------------------*
536 * return address of ACTIVE config entry by controller and channel
537 *---------------------------------------------------------------------------*/
539 get_cep_by_cc(int ctrlr, int chan)
543 if((chan != CHAN_B1) && (chan != CHAN_B2))
546 for(i=0; i < nentries; i++)
548 if((cfg_entry_tab[i].cdid != CDID_UNUSED) &&
549 (cfg_entry_tab[i].cdid != CDID_RESERVED) &&
550 (cfg_entry_tab[i].isdnchannelused == chan) &&
551 (cfg_entry_tab[i].isdncontrollerused == ctrlr) &&
552 ((ret_channel_state(ctrlr, chan)) == CHAN_RUN))
554 return(&cfg_entry_tab[i]);
560 /*---------------------------------------------------------------------------*
561 * return address of config entry identified by cdid
562 *---------------------------------------------------------------------------*/
564 get_cep_by_cdid(int cdid)
568 for(i=0; i < nentries; i++)
570 if(cfg_entry_tab[i].cdid == cdid
571 || cfg_entry_tab[i].saved_call.cdid == cdid)
572 return(&cfg_entry_tab[i]);
577 /*---------------------------------------------------------------------------*
578 * get name of a controller
579 *---------------------------------------------------------------------------*/
581 name_of_controller(int ctrl_type, int card_type)
583 static char *passive_card[] = {
587 "AVM A1 or Fritz!Card",
590 "USRobotics Sportster ISDN TA",
591 "Dr. Neuhaus NICCY Go@",
592 "Sedlbauer win speed",
594 "ISDN Master, MasterII or Blaster",
595 "AVM PCMCIA Fritz!Card",
596 "ELSA QuickStep 1000pro/ISA",
597 "ELSA QuickStep 1000pro/PCI",
599 "ELSA MicroLink ISDN/MC",
600 "ELSA MicroLink MCall",
602 "AVM Fritz!Card PCI",
604 "AVM Fritz!Card PnP",
605 "Siemens I-Surf 2.0 PnP",
606 "Asuscom ISDNlink 128K PnP"
609 static char *daic_card[] = {
611 "EICON.Diehl SX/SXn",
613 "EICON.Diehl QUADRO",
616 if(ctrl_type == CTRL_PASSIVE)
618 int index = card_type - CARD_TYPEP_8;
619 if (index >= 0 && index < (sizeof passive_card / sizeof passive_card[0]))
620 return passive_card[index];
622 else if(ctrl_type == CTRL_DAIC)
624 int index = card_type - CARD_TYPEA_DAIC_S;
625 if (index >= 0 && index < (sizeof daic_card / sizeof daic_card[0] ))
626 return daic_card[index];
628 else if(ctrl_type == CTRL_TINADD)
630 return "Stollmann tina-dd";
633 return "unknown card type";
636 /*---------------------------------------------------------------------------*
637 * init controller state array
638 *---------------------------------------------------------------------------*/
640 init_controller(void)
644 msg_ctrl_info_req_t mcir;
646 for(i=0; i < max; i++)
650 if((ioctl(isdnfd, I4B_CTRL_INFO_REQ, &mcir)) < 0)
652 log(LL_ERR, "init_controller: ioctl I4B_CTRL_INFO_REQ failed: %s", strerror(errno));
656 if((ncontroller = max = mcir.ncontroller) == 0)
658 log(LL_ERR, "init_controller: no ISDN controller found!");
662 if(mcir.ctrl_type == -1 || mcir.card_type == -1)
664 log(LL_ERR, "init_controller: ctrl/card is invalid!");
668 /* init controller tab */
670 if((init_controller_state(i, mcir.ctrl_type, mcir.card_type, mcir.tei)) == ERROR)
672 log(LL_ERR, "init_controller: init_controller_state for controller %d failed", i);
676 DBGL(DL_RCCF, (log(LL_DBG, "init_controller: found %d ISDN controller(s)", max)));
679 /*---------------------------------------------------------------------------*
680 * return b channel driver type name string
681 *---------------------------------------------------------------------------*/
683 bdrivername(int drivertype)
685 static char *bdtab[] = {
693 if(drivertype >= BDRV_RBCH && drivertype <= BDRV_IBC)
694 return(bdtab[drivertype]);
699 /*---------------------------------------------------------------------------*
700 * process AOCD charging messages
701 *---------------------------------------------------------------------------*/
703 handle_charge(cfg_entry_t *cep)
705 time_t now = time(NULL);
707 if(cep->aoc_last == 0) /* no last timestamp yet ? */
709 cep->aoc_last = now; /* add time stamp */
711 else if(cep->aoc_now == 0) /* no current timestamp yet ? */
713 cep->aoc_now = now; /* current timestamp */
717 cep->aoc_last = cep->aoc_now;
719 cep->aoc_diff = cep->aoc_now - cep->aoc_last;
720 cep->aoc_valid = AOC_VALID;
728 #ifdef I4B_EXTERNAL_MONITOR
729 if(do_monitor && accepted)
730 monitor_evnt_charge(cep, cep->charge, 0);
733 if(cep->aoc_valid == AOC_VALID)
735 if(cep->aoc_diff != cep->unitlength)
737 DBGL(DL_MSG, (log(LL_DBG, "handle_charge: AOCD unit length updated %d -> %d secs", cep->unitlength, cep->aoc_diff)));
739 cep->unitlength = cep->aoc_diff;
746 DBGL(DL_MSG, (log(LL_DBG, "handle_charge: AOCD unit length still %d secs", cep->unitlength)));
752 /*---------------------------------------------------------------------------*
753 * update kernel idle_time, earlyhup_time and unitlen_time
754 *---------------------------------------------------------------------------*/
756 unitlen_chkupd(cfg_entry_t *cep)
758 msg_timeout_upd_t tupd;
760 tupd.cdid = cep->cdid;
762 /* init the short hold data based on the shorthold algorithm type */
764 switch(cep->shorthold_algorithm)
767 tupd.shorthold_data.shorthold_algorithm = SHA_FIXU;
768 tupd.shorthold_data.unitlen_time = cep->unitlength;
769 tupd.shorthold_data.idle_time = cep->idle_time_out;
770 tupd.shorthold_data.earlyhup_time = cep->earlyhangup;
774 tupd.shorthold_data.shorthold_algorithm = SHA_VARU;
775 tupd.shorthold_data.unitlen_time = cep->unitlength;
776 tupd.shorthold_data.idle_time = cep->idle_time_out;
777 tupd.shorthold_data.earlyhup_time = 0;
780 log(LL_ERR, "unitlen_chkupd bad shorthold_algorithm %d", cep->shorthold_algorithm );
785 if((ioctl(isdnfd, I4B_TIMEOUT_UPD, &tupd)) < 0)
787 log(LL_ERR, "ioctl I4B_TIMEOUT_UPD failed: %s", strerror(errno));
792 /*--------------------------------------------------------------------------*
793 * this is intended to be called by do_exit and closes down all
794 * active connections before the daemon exits or is reconfigured.
795 *--------------------------------------------------------------------------*/
797 close_allactive(void)
800 cfg_entry_t *cep = NULL;
804 for (i = 0; i < ncontroller; i++)
806 if((get_controller_state(i)) != CTRL_UP)
809 if((ret_channel_state(i, CHAN_B1)) == CHAN_RUN)
811 if((cep = get_cep_by_cc(i, CHAN_B1)) != NULL)
815 display_disconnect(cep);
817 #ifdef I4B_EXTERNAL_MONITOR
818 monitor_evnt_disconnect(cep);
820 next_state(cep, EV_DRQ);
825 if((ret_channel_state(i, CHAN_B2)) == CHAN_RUN)
827 if((cep = get_cep_by_cc(i, CHAN_B2)) != NULL)
831 display_disconnect(cep);
833 #ifdef I4B_EXTERNAL_MONITOR
834 monitor_evnt_disconnect(cep);
836 next_state(cep, EV_DRQ);
844 log(LL_DMN, "close_allactive: waiting for all connections terminated");
849 /*--------------------------------------------------------------------------*
850 * set an interface up
851 *--------------------------------------------------------------------------*/
853 if_up(cfg_entry_t *cep)
855 msg_updown_ind_t mui;
857 /* set interface up */
859 DBGL(DL_MSG, (log(LL_DBG, "if_up: taking %s%d up", bdrivername(cep->usrdevicename), cep->usrdeviceunit)));
861 mui.driver = cep->usrdevicename;
862 mui.driver_unit = cep->usrdeviceunit;
863 mui.updown = SOFT_ENA;
865 if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
867 log(LL_ERR, "if_up: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
870 cep->down_retry_count = 0;
874 display_updown(cep, 1);
876 #ifdef I4B_EXTERNAL_MONITOR
877 monitor_evnt_updown(cep, 1);
882 /*--------------------------------------------------------------------------*
883 * set an interface down
884 *--------------------------------------------------------------------------*/
886 if_down(cfg_entry_t *cep)
888 msg_updown_ind_t mui;
890 /* set interface up */
892 DBGL(DL_MSG, (log(LL_DBG, "if_down: taking %s%d down", bdrivername(cep->usrdevicename), cep->usrdeviceunit)));
894 mui.driver = cep->usrdevicename;
895 mui.driver_unit = cep->usrdeviceunit;
896 mui.updown = SOFT_DIS;
898 if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
900 log(LL_ERR, "if_down: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
903 cep->went_down_time = time(NULL);
904 cep->down_retry_count = 0;
908 display_updown(cep, 0);
910 #ifdef I4B_EXTERNAL_MONITOR
911 monitor_evnt_updown(cep, 0);
916 /*--------------------------------------------------------------------------*
917 * send a dial response to (an interface in) the kernel
918 *--------------------------------------------------------------------------*/
920 dialresponse(cfg_entry_t *cep, int dstat)
922 msg_dialout_resp_t mdr;
924 static char *stattab[] = {
928 "dialout not allowed"
931 if(dstat < DSTAT_NONE || dstat > DSTAT_INONLY)
933 log(LL_ERR, "dialresponse: dstat out of range %d!", dstat);
937 mdr.driver = cep->usrdevicename;
938 mdr.driver_unit = cep->usrdeviceunit;
940 mdr.cause = cep->disc_cause;
942 if((ioctl(isdnfd, I4B_DIALOUT_RESP, &mdr)) < 0)
944 log(LL_ERR, "dialresponse: ioctl I4B_DIALOUT_RESP failed: %s", strerror(errno));
948 DBGL(DL_DRVR, (log(LL_DBG, "dialresponse: sent [%s]", stattab[dstat])));