]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/i4b/isdnd/support.c
This commit was generated by cvs2svn to compensate for changes in r56385,
[FreeBSD/FreeBSD.git] / usr.sbin / i4b / isdnd / support.c
1 /*
2  * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
3  *
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.
12  *
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.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      i4b daemon - misc support routines
28  *      ----------------------------------
29  *
30  *      $Id: support.c,v 1.63 1999/12/13 21:25:25 hm Exp $ 
31  *
32  * $FreeBSD$
33  *
34  *      last edit-date: [Mon Dec 13 21:49:05 1999]
35  *
36  *---------------------------------------------------------------------------*/
37
38 #include "isdnd.h"
39         
40 /*---------------------------------------------------------------------------*
41  *      find an active entry by driver type and driver unit
42  *---------------------------------------------------------------------------*/
43 cfg_entry_t *
44 find_active_entry_by_driver(int drivertype, int driverunit)
45 {
46         cfg_entry_t *cep = NULL;
47         int i;
48
49         for(i=0; i < nentries; i++)
50         {
51                 cep = &cfg_entry_tab[i];        /* ptr to config entry */
52
53                 if(!((cep->usrdevicename == drivertype) &&
54                      (cep->usrdeviceunit == driverunit)))
55                 {
56                         continue;
57                 }
58
59                 /* found */
60                 
61                 if(cep->cdid == CDID_UNUSED)
62                 {
63                         DBGL(DL_MSG, (log(LL_DBG, "find_active_entry_by_driver: entry %d [%s%d], cdid=CDID_UNUSED !",
64                                 i, bdrivername(drivertype), driverunit)));
65                         return(NULL);
66                 }
67                 else if(cep->cdid == CDID_RESERVED)
68                 {
69                         DBGL(DL_MSG, (log(LL_DBG, "find_active_entry_by_driver: entry %d [%s%d], cdid=CDID_RESERVED!",
70                                 i, bdrivername(drivertype), driverunit)));
71                         return(NULL);
72                 }
73                 return(cep);
74         }
75         return(NULL);
76 }
77
78 /*---------------------------------------------------------------------------*
79  *      find entry by drivertype and driverunit and setup for dialing out
80  *---------------------------------------------------------------------------*/
81 cfg_entry_t *
82 find_by_device_for_dialout(int drivertype, int driverunit)
83 {
84         cfg_entry_t *cep = NULL;
85         int i;
86
87         for(i=0; i < nentries; i++)
88         {
89                 cep = &cfg_entry_tab[i];        /* ptr to config entry */
90
91                 /* compare driver type and unit */
92
93                 if(!((cep->usrdevicename == drivertype) &&
94                      (cep->usrdeviceunit == driverunit)))
95                 {
96                         continue;
97                 }
98
99                 /* found, check if already reserved */
100                 
101                 if(cep->cdid == CDID_RESERVED)
102                 {
103                         DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, cdid reserved!", i)));
104                         return(NULL);
105                 }
106
107                 /* check if this entry is already in use ? */
108                 
109                 if(cep->cdid != CDID_UNUSED)    
110                 {
111                         DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, cdid in use", i)));
112                         return(NULL);
113                 }
114
115                 if((setup_dialout(cep)) == GOOD)
116                 {
117                         /* found an entry to be used for calling out */
118                 
119                         DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: found entry %d!", i)));
120                         return(cep);
121                 }
122                 else
123                 {
124                         DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, setup_dialout() failed!", i)));
125                         return(NULL);
126                 }
127         }
128
129         DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: no entry found!")));
130         return(NULL);
131 }
132
133 /*---------------------------------------------------------------------------*
134  *      find entry by drivertype and driverunit and setup for dialing out
135  *---------------------------------------------------------------------------*/
136 cfg_entry_t *
137 find_by_device_for_dialoutnumber(int drivertype, int driverunit, int cmdlen, char *cmd)
138 {
139         cfg_entry_t *cep = NULL;
140         int i, j;
141
142         for(i=0; i < nentries; i++)
143         {
144                 cep = &cfg_entry_tab[i];        /* ptr to config entry */
145
146                 /* compare driver type and unit */
147
148                 if(!((cep->usrdevicename == drivertype) &&
149                      (cep->usrdeviceunit == driverunit)))
150                 {
151                         continue;
152                 }
153
154                 /* found, check if already reserved */
155                 
156                 if(cep->cdid == CDID_RESERVED)
157                 {
158                         DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, cdid reserved!", i)));
159                         return(NULL);
160                 }
161
162                 /* check if this entry is already in use ? */
163                 
164                 if(cep->cdid != CDID_UNUSED)    
165                 {
166                         DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, cdid in use", i)));
167                         return(NULL);
168                 }
169
170                 /* check number and copy to cep->remote_numbers[] */
171                 
172                 for(j = 0; j < cmdlen; j++)
173                 {
174                         if(!(isdigit(*(cmd+j))))
175                         {
176                                 DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, dial string contains non-digit at pos %d", i, j)));
177                                 return(NULL);
178                         }
179                         /* fill in number to dial */
180                         cep->remote_numbers[0].number[j] = *(cmd+j);
181                 }                               
182                 cep->remote_numbers[0].number[j] = '\0';
183                 cep->remote_numbers_count = 1;
184
185                 if((setup_dialout(cep)) == GOOD)
186                 {
187                         /* found an entry to be used for calling out */
188                 
189                         DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: found entry %d!", i)));
190                         return(cep);
191                 }
192                 else
193                 {
194                         DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: entry %d, setup_dialout() failed!", i)));
195                         return(NULL);
196                 }
197         }
198
199         DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialoutnumber: no entry found!")));
200         return(NULL);
201 }
202
203 /*---------------------------------------------------------------------------*
204  *      find entry by drivertype and driverunit and setup for dialing out
205  *---------------------------------------------------------------------------*/
206 int
207 setup_dialout(cfg_entry_t *cep)
208 {
209         /* check controller operational */
210
211         if((get_controller_state(cep->isdncontroller)) != CTRL_UP)
212         {
213                 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, controller is down", cep->name)));
214                 return(ERROR);
215         }
216
217         cep->isdncontrollerused = cep->isdncontroller;
218
219         /* check channel available */
220
221         switch(cep->isdnchannel)
222         {
223                 case CHAN_B1:
224                 case CHAN_B2:
225                         if((ret_channel_state(cep->isdncontroller, cep->isdnchannel)) != CHAN_IDLE)
226                         {
227                                 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, channel not free", cep->name)));
228                                 return(ERROR);
229                         }
230                         cep->isdnchannelused = cep->isdnchannel;
231                         break;
232
233                 case CHAN_ANY:
234                         if(((ret_channel_state(cep->isdncontroller, CHAN_B1)) != CHAN_IDLE) &&
235                            ((ret_channel_state(cep->isdncontroller, CHAN_B2)) != CHAN_IDLE))
236                         {
237                                 DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, no channel free", cep->name)));
238                                 return(ERROR);
239                         }
240                         cep->isdnchannelused = CHAN_ANY;
241                         break;
242
243                 default:
244                         DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, channel undefined", cep->name)));
245                         return(ERROR);
246                         break;
247         }
248
249         DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s ok!", cep->name)));
250
251         /* preset disconnect cause */
252         
253         SET_CAUSE_TYPE(cep->disc_cause, CAUSET_I4B);
254         SET_CAUSE_VAL(cep->disc_cause, CAUSE_I4B_NORMAL);
255         
256         return(GOOD);
257 }
258
259 /*---------------------------------------------------------------------------*
260  *      find entry by drivertype and driverunit
261  *---------------------------------------------------------------------------*/
262 cfg_entry_t *
263 get_cep_by_driver(int drivertype, int driverunit)
264 {
265         cfg_entry_t *cep = NULL;
266         int i;
267
268         for(i=0; i < nentries; i++)
269         {
270                 cep = &cfg_entry_tab[i];        /* ptr to config entry */
271
272                 if(!((cep->usrdevicename == drivertype) &&
273                      (cep->usrdeviceunit == driverunit)))
274                 {
275                         continue;
276                 }
277
278                 DBGL(DL_MSG, (log(LL_DBG, "get_cep_by_driver: found entry %d!", i)));
279                 return(cep);
280         }
281         return(NULL);
282 }
283
284 /*---------------------------------------------------------------------------*
285  *      find a matching entry for an incoming call
286  *
287  *      - not found/no match: log output with LL_CHD and return NULL
288  *      - found/match: make entry in free cep, return address
289  *---------------------------------------------------------------------------*/
290 cfg_entry_t *
291 find_matching_entry_incoming(msg_connect_ind_t *mp)
292 {
293         cfg_entry_t *cep = NULL;
294         int i;
295
296         /* check for CW (call waiting) early */
297
298         if(mp->channel == CHAN_NO)
299         {
300                 if(aliasing)
301                 {
302                         char *src_tela = "ERROR-src_tela";
303                         char *dst_tela = "ERROR-dst_tela";
304         
305                         src_tela = get_alias(mp->src_telno);
306                         dst_tela = get_alias(mp->dst_telno);
307         
308                         log(LL_CHD, "%05d <unknown> CW from %s to %s (no channel free)",
309                                 mp->header.cdid, src_tela, dst_tela);
310                 }
311                 else
312                 {
313                         log(LL_CHD, "%05d <unknown> call waiting from %s to %s (no channel free)",
314                                 mp->header.cdid, mp->src_telno, mp->dst_telno);
315                 }
316                 return(NULL);
317         }
318         
319         for(i=0; i < nentries; i++)
320         {
321                 int n;
322                 cep = &cfg_entry_tab[i];        /* ptr to config entry */
323
324                 /* check my number */
325
326                 if(strncmp(cep->local_phone_incoming, mp->dst_telno, strlen(cep->local_phone_incoming)))
327                 {
328                         DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, myno %s != incomingno %s", i,
329                                 cep->local_phone_incoming, mp->dst_telno)));
330                         continue;
331                 }
332
333                 /* check all allowed remote number's for this entry */
334
335                 for (n = 0; n < cep->incoming_numbers_count; n++)
336                 {
337                         incoming_number_t *in = &cep->remote_phone_incoming[n];
338                         if(in->number[0] == '*')
339                                 break;
340                         if(strncmp(in->number, mp->src_telno, strlen(in->number)))
341                         {
342                                 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, remno %s != incomingfromno %s", i,
343                                         in->number, mp->src_telno)));
344                         }
345                         else
346                                 break;
347                 }
348                 if (n >= cep->incoming_numbers_count)
349                         continue;
350
351                 /* screening indicator XXX */
352                 
353                 switch(mp->scr_ind)
354                 {
355                         case SCR_NONE:
356                                 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - no screening indicator", mp->src_telno)));
357                                 break;
358
359                         case SCR_USR_NOSC:
360                                 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening user provided, not screened", mp->src_telno)));
361                                 break;
362
363                         case SCR_USR_PASS:
364                                 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening user provided, verified & passed", mp->src_telno)));
365                                 break;
366
367                         case SCR_USR_FAIL:
368                                 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening user provided, verified & failed", mp->src_telno)));
369                                 break;
370
371                         case SCR_NET:
372                                 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening network provided", mp->src_telno)));
373                                 break;
374
375                         default:
376                                 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: ERROR %s - invalid screening indicator!", mp->src_telno)));
377                                 break;
378                 }
379                                 
380                 /* check b protocol */
381
382                 if(cep->b1protocol != mp->bprot)
383                 {
384                         DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, bprot %d != incomingprot %d", i,
385                                 cep->b1protocol, mp->bprot)));
386                         continue;
387                 }
388
389                 /* is this entry currently in use ? */
390
391                 if(cep->cdid != CDID_UNUSED)
392                 {
393                         if(cep->cdid == CDID_RESERVED)
394                         {
395                                 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, cdid is reserved", i)));
396                         }
397                         else if (cep->dialin_reaction == REACT_ACCEPT
398                                  && cep->dialouttype == DIALOUT_CALLEDBACK)
399                         {
400                                 /*
401                                  * We might consider doing this even if this is
402                                  * not a calledback config entry - BUT: there are
403                                  * severe race conditions and timinig problems
404                                  * ex. if both sides run I4B with no callback
405                                  * delay - both may shutdown the outgoing call
406                                  * and never be able to establish a connection.
407                                  * In the called-back case this should not happen.
408                                  */
409                                 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, incoming call for callback in progress (cdid %05d)", i, cep->cdid)));
410
411                                 /* save the current call state, we're going to overwrite it with the
412                                  * new incoming state below... */
413                                 cep->saved_call.cdid = cep->cdid;
414                                 cep->saved_call.controller = cep->isdncontrollerused;
415                                 cep->saved_call.channel = cep->isdnchannelused;
416                         }
417                         else
418                         {
419                                 DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, cdid in use", i)));
420                                 continue;       /* yes, next */
421                         }
422                 }
423
424                 /* check controller value ok */
425
426                 if(mp->controller > ncontroller)
427                 {
428                         log(LL_CHD, "%05d %s incoming call with invalid controller %d",
429                                 mp->header.cdid, cep->name, mp->controller);
430                         return(NULL);
431                 }
432
433                 /* check controller marked up */
434
435                 if((get_controller_state(mp->controller)) != CTRL_UP)
436                 {
437                         log(LL_CHD, "%05d %s incoming call, controller %d DOWN!",
438                                 mp->header.cdid, cep->name, mp->controller);
439                         return(NULL);
440                 }
441
442                 /* check channel he wants */
443
444                 switch(mp->channel)
445                 {
446                         case CHAN_B1:
447                         case CHAN_B2:
448                                 if((ret_channel_state(mp->controller, mp->channel)) != CHAN_IDLE)
449                                 {
450                                         log(LL_CHD, "%05d %s incoming call, channel %s not free!",
451                                                 mp->header.cdid, cep->name, mp->channel == CHAN_B1 ? "B1" : "B2");
452                                         return(NULL);
453                                 }
454                                 break;
455
456                         case CHAN_ANY:
457                                 if(((ret_channel_state(mp->controller, CHAN_B1)) != CHAN_IDLE) &&
458                                    ((ret_channel_state(mp->controller, CHAN_B2)) != CHAN_IDLE))
459                                 {
460                                         log(LL_CHD, "%05d %s incoming call, no channel free!",
461                                                 mp->header.cdid, cep->name);
462                                         return(NULL);
463                                 }
464                                 break;
465
466                         case CHAN_NO:
467                                 log(LL_CHD, "%05d %s incoming call, call waiting (no channel available)!",
468                                         mp->header.cdid, cep->name);
469                                 return(NULL);
470                                 break;
471
472                         default:
473                                 log(LL_CHD, "%05d %s incoming call, ERROR, channel undefined!",
474                                         mp->header.cdid, cep->name);
475                                 return(NULL);
476                                 break;
477                 }
478
479                 /* found a matching entry */
480
481                 cep->cdid = mp->header.cdid;
482                 cep->isdncontrollerused = mp->controller;
483                 cep->isdnchannelused = mp->channel;
484 /*XXX*/         cep->disc_cause = 0;
485
486                 /* cp number to real one used */
487                 
488                 strcpy(cep->real_phone_incoming, mp->src_telno);
489
490                 /* copy display string */
491                 
492                 strcpy(cep->display, mp->display);
493                 
494                 /* entry currently down ? */
495                 
496                 if(cep->state == ST_DOWN)
497                 {
498                         msg_updown_ind_t mui;
499                         
500                         /* set interface up */
501         
502                         DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, ", i)));
503         
504                         mui.driver = cep->usrdevicename;
505                         mui.driver_unit = cep->usrdeviceunit;
506                         mui.updown = SOFT_ENA;
507                         
508                         if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
509                         {
510                                 log(LL_ERR, "find_matching_entry_incoming: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
511                                 error_exit(1, "find_matching_entry_incoming: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
512                         }
513
514                         cep->down_retry_count = 0;
515                         cep->state = ST_IDLE;
516                 }
517                 return(cep);
518         }
519
520         if(aliasing)
521         {
522                 char *src_tela = "ERROR-src_tela";
523                 char *dst_tela = "ERROR-dst_tela";
524
525                 src_tela = get_alias(mp->src_telno);
526                 dst_tela = get_alias(mp->dst_telno);
527
528                 log(LL_CHD, "%05d Call from %s to %s",
529                         mp->header.cdid, src_tela, dst_tela);
530         }
531         else
532         {
533                 log(LL_CHD, "%05d <unknown> incoming call from %s to %s",
534                         mp->header.cdid, mp->src_telno, mp->dst_telno);
535         }
536         return(NULL);
537 }
538
539 /*---------------------------------------------------------------------------*
540  *      return address of ACTIVE config entry by controller and channel
541  *---------------------------------------------------------------------------*/
542 cfg_entry_t *
543 get_cep_by_cc(int ctrlr, int chan)
544 {
545         int i;
546
547         if((chan != CHAN_B1) && (chan != CHAN_B2))
548                 return(NULL);
549                 
550         for(i=0; i < nentries; i++)
551         {
552                 if((cfg_entry_tab[i].cdid != CDID_UNUSED)               &&
553                    (cfg_entry_tab[i].cdid != CDID_RESERVED)             &&
554                    (cfg_entry_tab[i].isdnchannelused == chan)           &&
555                    (cfg_entry_tab[i].isdncontrollerused == ctrlr)       &&
556                    ((ret_channel_state(ctrlr, chan)) == CHAN_RUN))
557                 {
558                         return(&cfg_entry_tab[i]);
559                 }
560         }
561         return(NULL);
562 }
563
564 /*---------------------------------------------------------------------------*
565  *      return address of config entry identified by cdid
566  *---------------------------------------------------------------------------*/
567 cfg_entry_t *
568 get_cep_by_cdid(int cdid)
569 {
570         int i;
571
572         for(i=0; i < nentries; i++)
573         {
574                 if(cfg_entry_tab[i].cdid == cdid
575                   || cfg_entry_tab[i].saved_call.cdid == cdid)
576                         return(&cfg_entry_tab[i]);
577         }
578         return(NULL);
579 }
580
581 /*---------------------------------------------------------------------------*
582  *      return b channel driver type name string
583  *---------------------------------------------------------------------------*/
584 char *
585 bdrivername(int drivertype)
586 {
587         static char *bdtab[] = {
588                 "rbch",
589                 "tel",
590                 "ipr",
591                 "isp",
592                 "ibc"
593         };
594
595         if(drivertype >= BDRV_RBCH && drivertype <= BDRV_IBC)
596                 return(bdtab[drivertype]);
597         else
598                 return("unknown");
599 }
600
601 /*---------------------------------------------------------------------------*
602  *      process AOCD charging messages
603  *---------------------------------------------------------------------------*/
604 void
605 handle_charge(cfg_entry_t *cep)
606 {
607         time_t now = time(NULL);
608
609         if(cep->aoc_last == 0)          /* no last timestamp yet ? */
610         {
611                 cep->aoc_last = now;    /* add time stamp */
612         }
613         else if(cep->aoc_now == 0)      /* no current timestamp yet ? */
614         {
615                 cep->aoc_now = now;     /* current timestamp */
616         }
617         else
618         {
619                 cep->aoc_last = cep->aoc_now;
620                 cep->aoc_now = now;
621                 cep->aoc_diff = cep->aoc_now - cep->aoc_last;
622                 cep->aoc_valid = AOC_VALID;
623         }
624         
625 #ifdef USE_CURSES
626         if(do_fullscreen)
627                 display_charge(cep);
628 #endif
629
630 #ifdef I4B_EXTERNAL_MONITOR
631         if(do_monitor && accepted)
632                 monitor_evnt_charge(cep, cep->charge, 0);
633 #endif
634
635         if(cep->aoc_valid == AOC_VALID)
636         {
637                 if(cep->aoc_diff != cep->unitlength)
638                 {
639                         DBGL(DL_MSG, (log(LL_DBG, "handle_charge: AOCD unit length updated %d -> %d secs", cep->unitlength, cep->aoc_diff)));
640
641                         cep->unitlength = cep->aoc_diff;
642
643                         unitlen_chkupd(cep);
644                 }
645                 else
646                 {
647 #ifdef NOTDEF
648                         DBGL(DL_MSG, (log(LL_DBG, "handle_charge: AOCD unit length still %d secs", cep->unitlength)));
649 #endif
650                 }
651         }
652 }
653
654 /*---------------------------------------------------------------------------*
655  *      update kernel idle_time, earlyhup_time and unitlen_time
656  *---------------------------------------------------------------------------*/
657 void
658 unitlen_chkupd(cfg_entry_t *cep)
659 {
660         msg_timeout_upd_t tupd;
661
662         tupd.cdid = cep->cdid;
663
664         /* init the short hold data based on the shorthold algorithm type */
665         
666         switch(cep->shorthold_algorithm)
667         {
668                 case SHA_FIXU:
669                         tupd.shorthold_data.shorthold_algorithm = SHA_FIXU;
670                         tupd.shorthold_data.unitlen_time = cep->unitlength;
671                         tupd.shorthold_data.idle_time = cep->idle_time_out;
672                         tupd.shorthold_data.earlyhup_time = cep->earlyhangup;
673                         break;
674
675                 case SHA_VARU:
676                         tupd.shorthold_data.shorthold_algorithm = SHA_VARU;
677                         tupd.shorthold_data.unitlen_time = cep->unitlength;
678                         tupd.shorthold_data.idle_time = cep->idle_time_out;
679                         tupd.shorthold_data.earlyhup_time = 0;
680                         break;
681                 default:
682                         log(LL_ERR, "unitlen_chkupd bad shorthold_algorithm %d", cep->shorthold_algorithm );
683                         return;
684                         break;                  
685         }
686
687         if((ioctl(isdnfd, I4B_TIMEOUT_UPD, &tupd)) < 0)
688         {
689                 log(LL_ERR, "ioctl I4B_TIMEOUT_UPD failed: %s", strerror(errno));
690                 error_exit(1, "ioctl I4B_TIMEOUT_UPD failed: %s", strerror(errno));
691         }
692 }
693
694 /*--------------------------------------------------------------------------*
695  *      this is intended to be called by do_exit and closes down all
696  *      active connections before the daemon exits or is reconfigured.
697  *--------------------------------------------------------------------------*/
698 void
699 close_allactive(void)
700 {
701         int i, j;
702         cfg_entry_t *cep = NULL;
703
704         j = 0;
705         
706         for (i = 0; i < ncontroller; i++)
707         {
708                 if((get_controller_state(i)) != CTRL_UP)
709                         continue;
710
711                 if((ret_channel_state(i, CHAN_B1)) == CHAN_RUN)
712                 {
713                         if((cep = get_cep_by_cc(i, CHAN_B1)) != NULL)
714                         {
715 #ifdef USE_CURSES
716                                 if(do_fullscreen)
717                                         display_disconnect(cep);
718 #endif
719 #ifdef I4B_EXTERNAL_MONITOR
720                                 monitor_evnt_disconnect(cep);
721 #endif
722                                 next_state(cep, EV_DRQ);
723                                 j++;
724                         }
725                 }
726
727                 if((ret_channel_state(i, CHAN_B2)) == CHAN_RUN)
728                 {
729                         if((cep = get_cep_by_cc(i, CHAN_B2)) != NULL)
730                         {
731 #ifdef USE_CURSES
732                                 if(do_fullscreen)
733                                         display_disconnect(cep);
734 #endif
735 #ifdef I4B_EXTERNAL_MONITOR
736                                 monitor_evnt_disconnect(cep);
737 #endif
738                                 next_state(cep, EV_DRQ);
739                                 j++;                            
740                         }
741                 }
742         }
743
744         if(j)
745         {
746                 log(LL_DMN, "close_allactive: waiting for all connections terminated");
747                 sleep(5);
748         }
749 }
750
751 /*--------------------------------------------------------------------------*
752  *      set an interface up
753  *--------------------------------------------------------------------------*/
754 void
755 if_up(cfg_entry_t *cep)
756 {
757         msg_updown_ind_t mui;
758                         
759         /* set interface up */
760         
761         DBGL(DL_MSG, (log(LL_DBG, "if_up: taking %s%d up", bdrivername(cep->usrdevicename), cep->usrdeviceunit)));
762         
763         mui.driver = cep->usrdevicename;
764         mui.driver_unit = cep->usrdeviceunit;
765         mui.updown = SOFT_ENA;
766                         
767         if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
768         {
769                 log(LL_ERR, "if_up: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
770                 error_exit(1, "if_up: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
771         }
772         cep->down_retry_count = 0;
773
774 #ifdef USE_CURSES
775         if(do_fullscreen)
776                 display_updown(cep, 1);
777 #endif
778 #ifdef I4B_EXTERNAL_MONITOR
779         monitor_evnt_updown(cep, 1);
780 #endif
781         
782 }
783
784 /*--------------------------------------------------------------------------*
785  *      set an interface down
786  *--------------------------------------------------------------------------*/
787 void
788 if_down(cfg_entry_t *cep)
789 {
790         msg_updown_ind_t mui;
791                         
792         /* set interface up */
793         
794         DBGL(DL_MSG, (log(LL_DBG, "if_down: taking %s%d down", bdrivername(cep->usrdevicename), cep->usrdeviceunit)));
795         
796         mui.driver = cep->usrdevicename;
797         mui.driver_unit = cep->usrdeviceunit;
798         mui.updown = SOFT_DIS;
799                         
800         if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0)
801         {
802                 log(LL_ERR, "if_down: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
803                 error_exit(1, "if_down: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno));
804         }
805         cep->went_down_time = time(NULL);
806         cep->down_retry_count = 0;
807
808 #ifdef USE_CURSES
809         if(do_fullscreen)
810                 display_updown(cep, 0);
811 #endif
812 #ifdef I4B_EXTERNAL_MONITOR
813         monitor_evnt_updown(cep, 0);
814 #endif
815
816 }
817
818 /*--------------------------------------------------------------------------*
819  *      send a dial response to (an interface in) the kernel 
820  *--------------------------------------------------------------------------*/
821 void
822 dialresponse(cfg_entry_t *cep, int dstat)
823 {
824         msg_dialout_resp_t mdr;
825
826         static char *stattab[] = {
827                 "normal condition",
828                 "temporary failure",
829                 "permanent failure",
830                 "dialout not allowed"
831         };
832
833         if(dstat < DSTAT_NONE || dstat > DSTAT_INONLY)
834         {
835                 log(LL_ERR, "dialresponse: dstat out of range %d!", dstat);
836                 return;
837         }
838         
839         mdr.driver = cep->usrdevicename;
840         mdr.driver_unit = cep->usrdeviceunit;
841         mdr.stat = dstat;
842         mdr.cause = cep->disc_cause;    
843         
844         if((ioctl(isdnfd, I4B_DIALOUT_RESP, &mdr)) < 0)
845         {
846                 log(LL_ERR, "dialresponse: ioctl I4B_DIALOUT_RESP failed: %s", strerror(errno));
847                 error_exit(1, "dialresponse: ioctl I4B_DIALOUT_RESP failed: %s", strerror(errno));
848         }
849
850         DBGL(DL_DRVR, (log(LL_DBG, "dialresponse: sent [%s]", stattab[dstat])));
851 }
852 /* EOF */
853