]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/i4b/isdnd/msghdl.c
This commit was generated by cvs2svn to compensate for changes in r53024,
[FreeBSD/FreeBSD.git] / usr.sbin / i4b / isdnd / msghdl.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 - message from kernel handling routines
28  *      --------------------------------------------------
29  *
30  * $FreeBSD$ 
31  *
32  *      last edit-date: [Mon Jul 26 13:55:57 1999]
33  *
34  *---------------------------------------------------------------------------*/
35
36 #include "isdnd.h"
37
38 /*---------------------------------------------------------------------------*
39  *      handle incoming CONNECT_IND (=SETUP) message
40  *---------------------------------------------------------------------------*/
41 void
42 msg_connect_ind(msg_connect_ind_t *mp)
43 {
44         cfg_entry_t *cep;
45         char *src_tela = "ERROR-src_tela";
46         char *dst_tela = "ERROR-dst_tela";
47
48 #define SRC (aliasing == 0 ? mp->src_telno : src_tela)
49 #define DST (aliasing == 0 ? mp->dst_telno : dst_tela)
50
51         if((cep = find_matching_entry_incoming(mp)) == NULL)
52         {
53                 /* log message generated in find_matching_entry_incoming() */
54                 sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
55                 return;
56         }
57
58         if(cep->cdid != CDID_UNUSED && cep->cdid != CDID_RESERVED)
59         {       
60                 /* 
61                  * This is an incoming call on a number we just dialed out.
62                  * Stop our dial-out and accept the incoming call.
63                  */
64                 if(cep->saved_call.cdid != CDID_UNUSED &&
65                    cep->saved_call.cdid != CDID_RESERVED)
66                 {
67                         int cdid;
68
69                         /* disconnect old, not new */
70                         
71                         cdid = cep->cdid;
72                         cep->cdid = cep->saved_call.cdid;
73                         sendm_disconnect_req(cep, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
74                         cep->cdid = cdid;
75
76                         /*
77                          * Shortcut the state machine and mark this
78                          * entry as free
79                          */
80 /* XXX */               cep->state = ST_IDLE;   /* this is an invalid   */
81                                                 /* transition,          */
82                                                 /* so no next_state()   */
83                         /* we have to wait here for an incoming */
84                         /* disconnect message !!! (-hm)         */
85                 }
86         }
87
88         if(aliasing)
89         {
90                 src_tela = get_alias(mp->src_telno);
91                 dst_tela = get_alias(mp->dst_telno);
92         }
93
94         if(cep->inout == DIR_OUTONLY)
95         {
96                 log(LL_CHD, "%05d %s incoming call from %s to %s not allowed by configuration!",
97                         mp->header.cdid, cep->name, SRC, DST);
98                 sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
99                 return;
100         }
101
102         cep->charge = 0;
103         cep->last_charge = 0;
104                 
105         switch(cep->dialin_reaction)
106         {
107                 case REACT_ACCEPT:
108                         log(LL_CHD, "%05d %s accepting: incoming call from %s to %s",
109                                 mp->header.cdid, cep->name, SRC, DST);
110                         decr_free_channels(mp->controller);
111                         next_state(cep, EV_MCI);
112                         break;
113
114                 case REACT_REJECT:
115                         log(LL_CHD, "%05d %s rejecting: incoming call from %s to %s",
116                                 mp->header.cdid, cep->name, SRC, DST);
117                         sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
118                                 (CAUSET_I4B << 8) | CAUSE_I4B_REJECT);
119                         cep->cdid = CDID_UNUSED;
120                         break;
121
122                 case REACT_IGNORE:
123                         log(LL_CHD, "%05d %s ignoring: incoming call from %s to %s",
124                                 mp->header.cdid, cep->name, SRC, DST);
125                         sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
126                         break;
127
128                 case REACT_ANSWER:
129                         decr_free_channels(mp->controller);
130                         if(cep->alert)
131                         {
132                                 if(mp->display)
133                                 {
134                                         log(LL_CHD, "%05d %s alerting: incoming call from %s to %s (%s)",
135                                                 mp->header.cdid, cep->name, SRC, DST, mp->display);
136                                 }
137                                 else
138                                 {
139                                         log(LL_CHD, "%05d %s alerting: incoming call from %s to %s",
140                                                 mp->header.cdid, cep->name, SRC, DST);
141                                 }
142                                 next_state(cep, EV_ALRT);
143                         }
144                         else
145                         {
146                                 if(mp->display)
147                                 {                               
148                                         log(LL_CHD, "%05d %s answering: incoming call from %s to %s (%s)",
149                                                 mp->header.cdid, cep->name, SRC, DST, mp->display);
150                                 }
151                                 else
152                                 {
153                                         log(LL_CHD, "%05d %s answering: incoming call from %s to %s",
154                                                 mp->header.cdid, cep->name, SRC, DST);
155                                 }
156                                 next_state(cep, EV_MCI);
157                         }
158                         break;
159
160                 case REACT_CALLBACK:
161 #ifdef NOTDEF
162 /*XXX reserve channel ??? */    decr_free_channels(mp->controller);
163 #endif
164                         if(cep->cdid == CDID_RESERVED)
165                         {
166                                 log(LL_CHD, "%05d %s reserved: incoming call from %s to %s",
167                                         mp->header.cdid, cep->name, SRC, DST);
168                                 sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
169                                         (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
170                                 /* no state change */
171                         }
172                         else
173                         {
174                                 log(LL_CHD, "%05d %s callback: incoming call from %s to %s",
175                                         mp->header.cdid, cep->name, SRC, DST);
176                                 sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
177                                         (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
178                                 cep->last_release_time = time(NULL);
179                                 cep->cdid = CDID_RESERVED;
180                                 next_state(cep, EV_CBRQ);
181                         }
182                         break;
183                         
184                 default:
185                         log(LL_WRN, "msg_connect_ind: unknown response type, tx SETUP_RESP_DNTCRE");
186                         sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
187                         break;
188         }
189 #undef SRC
190 #undef DST
191 }
192
193 /*---------------------------------------------------------------------------*
194  *      handle incoming CONNECT_ACTIVE_IND message
195  *---------------------------------------------------------------------------*/
196 void
197 msg_connect_active_ind(msg_connect_active_ind_t *mp)
198 {
199         cfg_entry_t *cep;
200         char *device;
201         
202         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
203         {
204                 log(LL_WRN, "msg_connect_active_ind: cdid not found!");
205                 return;
206         }
207
208         cep->isdncontrollerused = mp->controller;
209         cep->isdnchannelused = mp->channel;     
210                                                                                 
211         cep->aoc_now = cep->connect_time = time(NULL);
212         cep->aoc_last = 0;
213         cep->aoc_diff = 0;
214         cep->aoc_valid = AOC_INVALID;
215
216         cep->local_disconnect = DISCON_REM;     
217         
218         cep->inbytes = INVALID;
219         cep->outbytes = INVALID;
220         cep->hangup = 0;
221
222         device = bdrivername(cep->usrdevicename);
223
224         /* set the B-channel to active */
225
226         if((set_channel_busy(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
227                 log(LL_ERR, "msg_connect_active_ind: set_channel_busy failed!");
228
229         if(cep->direction == DIR_OUT)
230         {
231                 log(LL_CHD, "%05d %s outgoing call active (ctl %d, ch %d, %s%d)",
232                         cep->cdid, cep->name,
233                         cep->isdncontrollerused, cep->isdnchannelused,
234                         bdrivername(cep->usrdevicename), cep->usrdeviceunit);
235         }
236         else
237         {
238                 log(LL_CHD, "%05d %s incoming call active (ctl %d, ch %d, %s%d)",
239                         cep->cdid, cep->name,
240                         cep->isdncontrollerused, cep->isdnchannelused,
241                         bdrivername(cep->usrdevicename), cep->usrdeviceunit);
242         }
243         
244 #ifdef USE_CURSES
245         if(do_fullscreen)
246                 display_connect(cep);
247 #endif
248 #ifdef I4B_EXTERNAL_MONITOR
249         if(do_monitor && accepted)
250                 monitor_evnt_connect(cep);
251 #endif
252
253         if(isdntime && (mp->datetime[0] != '\0'))
254         {
255                 log(LL_DMN, "date/time from exchange = %s", mp->datetime);
256         }
257
258         next_state(cep, EV_MCAI);
259 }
260                                                                                 
261 /*---------------------------------------------------------------------------*
262  *      handle incoming PROCEEDING_IND message
263  *---------------------------------------------------------------------------*/
264 void
265 msg_proceeding_ind(msg_proceeding_ind_t *mp)
266 {
267         cfg_entry_t *cep;
268         
269         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
270         {
271                 log(LL_WRN, "msg_proceeding_ind: cdid not found!");
272                 return;
273         }
274
275         cep->isdncontrollerused = mp->controller;
276         cep->isdnchannelused = mp->channel;     
277                                                                                 
278         /* set the B-channels active */
279
280         if((set_channel_busy(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
281                 log(LL_ERR, "msg_proceeding_ind: set_channel_busy failed!");
282         
283         log(LL_CHD, "%05d %s outgoing call proceeding (ctl %d, ch %d)",
284                         cep->cdid, cep->name,
285                         cep->isdncontrollerused, cep->isdnchannelused);
286 }
287                                                                                 
288 /*---------------------------------------------------------------------------*
289  *      handle incoming ALERT_IND message
290  *---------------------------------------------------------------------------*/
291 void
292 msg_alert_ind(msg_alert_ind_t *mp)
293 {
294         cfg_entry_t *cep;
295         
296         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
297         {
298                 log(LL_WRN, "msg_alert_ind: cdid not found!");
299                 return;
300         }
301 #ifdef NOTDEF
302         log(LL_CHD, "%05d %s incoming alert", cep->cdid, cep->name);
303 #endif
304 }
305                                                                                 
306 /*---------------------------------------------------------------------------*
307  *      handle incoming L12STAT_IND message
308  *---------------------------------------------------------------------------*/
309 void
310 msg_l12stat_ind(msg_l12stat_ind_t *ml)
311 {
312 #ifdef USE_CURSES
313         if(do_fullscreen)
314                 display_l12stat(ml->controller, ml->layer, ml->state);
315 #endif
316
317         DBGL(DL_CNST, (log(LL_DBG, "msg_l12stat_ind: unit %d, layer %d, state %d",
318                 ml->controller, ml->layer, ml->state)));
319 }
320                                                                                 
321 /*---------------------------------------------------------------------------*
322  *      handle incoming TEIASG_IND message
323  *---------------------------------------------------------------------------*/
324 void
325 msg_teiasg_ind(msg_teiasg_ind_t *mt)
326 {
327 #ifdef USE_CURSES
328         if(do_fullscreen)
329                 display_tei(mt->controller, mt->tei);
330 #endif
331
332         DBGL(DL_CNST, (log(LL_DBG, "msg_teiasg_ind: unit %d, tei = %d",
333                 mt->controller, mt->tei)));
334 }
335
336 /*---------------------------------------------------------------------------*
337  *      handle incoming L12STAT_IND message
338  *---------------------------------------------------------------------------*/
339 void
340 msg_pdeact_ind(msg_pdeact_ind_t *md)
341 {
342         int i;
343         int ctrl = md->controller;
344         cfg_entry_t *cep;
345
346 #ifdef USE_CURSES
347         if(do_fullscreen)
348         {
349                 display_l12stat(ctrl, LAYER_ONE, LAYER_IDLE);
350                 display_l12stat(ctrl, LAYER_TWO, LAYER_IDLE);
351                 display_tei(ctrl, -1);
352         }
353 #endif
354
355         DBGL(DL_CNST, (log(LL_DBG, "msg_pdeact_ind: unit %d, persistent deactivation", ctrl)));
356
357         for(i=0; i < nentries; i++)
358         {
359                 if((cfg_entry_tab[i].cdid != CDID_UNUSED)       &&
360                    (cfg_entry_tab[i].isdncontrollerused == ctrl))
361                 {
362                         cep = &cfg_entry_tab[i];
363                         
364                         if(cep->cdid == CDID_RESERVED)
365                         {
366                                 cep->cdid = CDID_UNUSED;
367                                 continue;
368                         }
369
370                         cep->cdid = CDID_UNUSED;
371                         
372                         cep->last_release_time = time(NULL);
373
374                         SET_CAUSE_TYPE(cep->disc_cause, CAUSET_I4B);
375                         SET_CAUSE_VAL(cep->disc_cause, CAUSE_I4B_L1ERROR);
376                 
377                         if(cep->direction == DIR_OUT)
378                         {
379                                 log(LL_CHD, "%05d %s outgoing call disconnected (local)",
380                                         cep->cdid, cep->name);
381                         }
382                         else
383                         {
384                                 log(LL_CHD, "%05d %s incoming call disconnected (local)",
385                                         cep->cdid, cep->name);
386                         }
387                 
388                         log(LL_CHD, "%05d %s cause %s",
389                                 cep->cdid, cep->name, print_i4b_cause(cep->disc_cause));
390                 
391 #ifdef USE_CURSES
392                         if(do_fullscreen && (cep->connect_time > 0))
393                                 display_disconnect(cep);
394 #endif
395                 
396 #ifdef I4B_EXTERNAL_MONITOR
397                         if(do_monitor && accepted)
398                                 monitor_evnt_disconnect(cep);
399 #endif
400                         if(cep->disconnectprog)
401                                 exec_connect_prog(cep, cep->disconnectprog, 1);
402                 
403                         if(cep->connect_time > 0)
404                         {
405                                 if(cep->direction == DIR_OUT)
406                                 {
407                                         log(LL_CHD, "%05d %s charging: %d units, %d seconds",
408                                                 cep->cdid, cep->name, cep->charge,
409                                                 (int)difftime(time(NULL), cep->connect_time));
410                                 }
411                                 else
412                                 {
413                                         log(LL_CHD, "%05d %s connected %d seconds",
414                                                 cep->cdid, cep->name,
415                                                 (int)difftime(time(NULL), cep->connect_time));
416                                 }
417                 
418                                 if((cep->inbytes != INVALID) && (cep->outbytes != INVALID))
419                                 {
420                                         if((cep->ioutbytes != cep->outbytes) ||
421                                            (cep->iinbytes != cep->inbytes))
422                                         {
423                                                 log(LL_CHD, "%05d %s accounting: in %d, out %d (in %d, out %d)",
424                                                         cep->cdid, cep->name,
425                                                         cep->inbytes, cep->outbytes,
426                                                         cep->iinbytes, cep->ioutbytes);
427                                         }
428                                         else
429                                         {
430                                                 log(LL_CHD, "%05d %s accounting: in %d, out %d",
431                                                         cep->cdid, cep->name,
432                                                         cep->inbytes, cep->outbytes);
433                                         }
434                                 }
435                         }
436
437                         if(useacctfile && (cep->connect_time > 0))
438                         {
439                                 int con_secs;
440                                 char logdatetime[41];
441                                 struct tm *tp;
442                 
443                                 con_secs = difftime(time(NULL), cep->connect_time);
444                                         
445                                 tp = localtime(&cep->connect_time);
446                                 
447                 strftime(logdatetime,40,I4B_TIME_FORMAT,tp);
448                 
449                                 if(cep->inbytes != INVALID && cep->outbytes != INVALID)
450                                 {
451                                         fprintf(acctfp, "%s - %s %s %d (%d) (%d/%d)\n",
452                                                 logdatetime, getlogdatetime(),
453                                                 cep->name, cep->charge, con_secs,
454                                                 cep->inbytes, cep->outbytes);
455                                 }
456                                 else
457                                 {
458                                         fprintf(acctfp, "%s - %s %s %d (%d)\n",
459                                                 logdatetime, getlogdatetime(),
460                                                 cep->name, cep->charge, con_secs);
461                                 }
462                         }
463                 
464                         /* set the B-channel inactive */
465                 
466                         if((set_channel_idle(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
467                                 log(LL_ERR, "msg_pdeact_ind: set_channel_idle failed!");
468                 
469                         incr_free_channels(cep->isdncontrollerused);
470                         
471                         cep->connect_time = 0;
472                 }
473         }
474 }
475                                                                                 
476 /*---------------------------------------------------------------------------*
477  *      handle incoming NEGCOMP_IND message
478  *---------------------------------------------------------------------------*/
479 void
480 msg_negcomplete_ind(msg_negcomplete_ind_t *mp)
481 {
482         cfg_entry_t *cep;
483
484         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
485         {
486                 log(LL_WRN, "msg_negcomp_ind: cdid not found");
487                 return;
488         }
489
490         if(cep->connectprog)
491                 exec_connect_prog(cep, cep->connectprog, 0);
492 }
493                                                                                 
494 /*---------------------------------------------------------------------------*
495  *      handle incoming IFSTATE_CHANGED indication
496  *---------------------------------------------------------------------------*/
497 void
498 msg_ifstatechg_ind(msg_ifstatechg_ind_t *mp)
499 {
500         cfg_entry_t *cep;
501         char *device;
502
503         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
504         {
505                 log(LL_WRN, "msg_negcomp_ind: cdid not found");
506                 return;
507         }
508
509         device = bdrivername(cep->usrdevicename);
510         log(LL_DBG, "%s%d: switched to state %d", device, cep->usrdeviceunit, mp->state);
511 }
512
513 /*---------------------------------------------------------------------------*
514  *      handle incoming DISCONNECT_IND message
515  *---------------------------------------------------------------------------*/
516 void
517 msg_disconnect_ind(msg_disconnect_ind_t *mp)
518 {
519         cfg_entry_t *cep;
520
521         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
522         {
523                 log(LL_WRN, "msg_disconnect_ind: cdid not found");
524                 return;
525         }
526
527         /* is this an aborted out-call prematurely called back? */
528         if (cep->saved_call.cdid == mp->header.cdid)
529         {
530                 DBGL(DL_CNST, (log(LL_DBG, "aborted outcall %05d disconnected",
531                         mp->header.cdid)));
532                 cep->saved_call.cdid = CDID_UNUSED;
533
534                 set_channel_idle(cep->saved_call.controller, cep->saved_call.channel);
535
536                 incr_free_channels(cep->saved_call.controller);
537                 return;
538         }
539
540         cep->last_release_time = time(NULL);
541         cep->disc_cause = mp->cause;
542
543         if(cep->direction == DIR_OUT)
544         {
545                 log(LL_CHD, "%05d %s outgoing call disconnected %s",
546                         cep->cdid, cep->name, 
547                         cep->local_disconnect == DISCON_LOC ?
548                                                 "(local)" : "(remote)");
549         }
550         else
551         {
552                 log(LL_CHD, "%05d %s incoming call disconnected %s", 
553                         cep->cdid, cep->name,
554                         cep->local_disconnect == DISCON_LOC ?
555                                                 "(local)" : "(remote)");
556         }
557
558         log(LL_CHD, "%05d %s cause %s",
559                 cep->cdid, cep->name, print_i4b_cause(mp->cause));
560
561 #ifdef USE_CURSES
562         if(do_fullscreen && (cep->connect_time > 0))
563                 display_disconnect(cep);
564 #endif
565
566 #ifdef I4B_EXTERNAL_MONITOR
567         if(do_monitor && accepted)
568                 monitor_evnt_disconnect(cep);
569 #endif
570
571         if(cep->disconnectprog)
572                 exec_connect_prog(cep, cep->disconnectprog, 1);
573
574         if(cep->connect_time > 0)
575         {
576                 if(cep->direction == DIR_OUT)
577                 {
578                         log(LL_CHD, "%05d %s charging: %d units, %d seconds",
579                                 cep->cdid, cep->name, cep->charge,
580                                 (int)difftime(time(NULL), cep->connect_time));
581                 }
582                 else
583                 {
584                         log(LL_CHD, "%05d %s connected %d seconds",
585                                 cep->cdid, cep->name,
586                                 (int)difftime(time(NULL), cep->connect_time));
587                 }
588
589                 if((cep->inbytes != INVALID) && (cep->outbytes != INVALID))
590                 {
591                         if((cep->ioutbytes != cep->outbytes) ||
592                            (cep->iinbytes != cep->inbytes))
593                         {
594                                 log(LL_CHD, "%05d %s accounting: in %d, out %d (in %d, out %d)",
595                                         cep->cdid, cep->name,
596                                         cep->inbytes, cep->outbytes,
597                                         cep->iinbytes, cep->ioutbytes);
598                         }
599                         else
600                         {
601                                 log(LL_CHD, "%05d %s accounting: in %d, out %d",
602                                         cep->cdid, cep->name,
603                                         cep->inbytes, cep->outbytes);
604                         }
605                 }
606         }                       
607
608         if(useacctfile && (cep->connect_time > 0))
609         {
610                 int con_secs;
611                 char logdatetime[41];
612                 struct tm *tp;
613
614                 con_secs = difftime(time(NULL), cep->connect_time);
615                         
616                 tp = localtime(&cep->connect_time);
617                 
618                 strftime(logdatetime,40,I4B_TIME_FORMAT,tp);
619
620                 if(cep->inbytes != INVALID && cep->outbytes != INVALID)
621                 {
622                         fprintf(acctfp, "%s - %s %s %d (%d) (%d/%d)\n",
623                                 logdatetime, getlogdatetime(),
624                                 cep->name, cep->charge, con_secs,
625                                 cep->inbytes, cep->outbytes);
626                 }
627                 else
628                 {
629                         fprintf(acctfp, "%s - %s %s %d (%d)\n",
630                                 logdatetime, getlogdatetime(),
631                                 cep->name, cep->charge, con_secs);
632                 }
633         }
634
635         /* set the B-channel inactive */
636
637         set_channel_idle(cep->isdncontrollerused, cep->isdnchannelused);
638
639         incr_free_channels(cep->isdncontrollerused);
640         
641         cep->connect_time = 0;                  
642
643         next_state(cep, EV_MDI);
644 }
645
646 /*---------------------------------------------------------------------------*
647  *      handle incoming DIALOUT message
648  *---------------------------------------------------------------------------*/
649 void
650 msg_dialout(msg_dialout_ind_t *mp)
651 {
652         cfg_entry_t *cep;
653         
654         DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
655
656         if((cep = find_by_device_for_dialout(mp->driver, mp->driver_unit)) == NULL)
657         {
658                 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: config entry reserved or no match")));
659                 return;
660         }
661
662         if(cep->inout == DIR_INONLY)
663         {
664                 dialresponse(cep, DSTAT_INONLY);
665                 return;
666         }
667         
668         if((cep->cdid = get_cdid()) == 0)
669         {
670                 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: get_cdid() returned 0!")));
671                 return;
672         }
673         
674         cep->charge = 0;
675         cep->last_charge = 0;
676
677         next_state(cep, EV_MDO);        
678 }
679
680 /*---------------------------------------------------------------------------*
681  *      handle incoming DIALOUTNUMBER message
682  *---------------------------------------------------------------------------*/
683 void
684 msg_dialoutnumber(msg_dialoutnumber_ind_t *mp)
685 {
686         cfg_entry_t *cep;
687         
688         DBGL(DL_DRVR, (log(LL_DBG, "msg_dialoutnumber: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
689
690         if((cep = find_by_device_for_dialoutnumber(mp->driver, mp->driver_unit, mp->cmdlen, mp->cmd)) == NULL)
691         {
692                 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialoutnumber: config entry reserved or no match")));
693                 return;
694         }
695
696         if(cep->inout == DIR_INONLY)
697         {
698                 dialresponse(cep, DSTAT_INONLY);
699                 return;
700         }
701         
702         if((cep->cdid = get_cdid()) == 0)
703         {
704                 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialoutnumber: get_cdid() returned 0!")));
705                 return;
706         }
707         
708         cep->charge = 0;
709         cep->last_charge = 0;
710
711         next_state(cep, EV_MDO);        
712 }
713
714 /*---------------------------------------------------------------------------*
715  *      handle incoming DRVRDISC_REQ message
716  *---------------------------------------------------------------------------*/
717 void
718 msg_drvrdisc_req(msg_drvrdisc_req_t *mp)
719 {
720         cfg_entry_t *cep;
721         
722         DBGL(DL_DRVR, (log(LL_DBG, "msg_drvrdisc_req: req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
723
724         if((cep = get_cep_by_driver(mp->driver, mp->driver_unit)) == NULL)
725         {
726                 DBGL(DL_DRVR, (log(LL_DBG, "msg_drvrdisc_req: config entry not found")));
727                 return;
728         }
729         next_state(cep, EV_DRQ);
730 }
731
732 /*---------------------------------------------------------------------------*
733  *      handle incoming ACCOUNTING message
734  *---------------------------------------------------------------------------*/
735 void
736 msg_accounting(msg_accounting_ind_t *mp)
737 {
738         cfg_entry_t *cep;
739
740         if((cep = find_active_entry_by_driver(mp->driver, mp->driver_unit)) == NULL)
741         {
742                 log(LL_WRN, "msg_accounting: no config entry found!");  
743                 return;
744         }
745
746         cep->inbytes = mp->inbytes;
747         cep->iinbytes = mp->iinbytes;
748         cep->outbytes = mp->outbytes;
749         cep->ioutbytes = mp->ioutbytes;
750         cep->inbps = mp->inbps;
751         cep->outbps = mp->outbps;
752
753         if(mp->accttype == ACCT_DURING) 
754         {
755 #ifdef USE_CURSES
756                 if(do_fullscreen)
757                         display_acct(cep);
758 #endif
759 #ifdef NOTDEF
760                 else
761                         DBGL(DL_DRVR, (log(LL_DBG, "msg_accounting: %s%d, ioutb=%d, iinb=%d, outb=%d, inb=%d, outbps=%d, inbps=%d",
762                                 bdrivername(mp->driver), mp->driver_unit,
763                                 mp->ioutbytes, mp->iinbytes,
764                                 mp->outbytes, mp->inbytes,
765                                 mp->outbps, mp->inbps)));
766 #endif                          
767         }
768 }
769
770 /*---------------------------------------------------------------------------*
771  *      handle incoming CHARGING message
772  *---------------------------------------------------------------------------*/
773 void
774 msg_charging_ind(msg_charging_ind_t *mp)
775 {
776         static char *cttab[] = {
777                 "invalid",
778                 "AOCD",
779                 "AOCE",
780                 "estimated" };
781                 
782         cfg_entry_t *cep;
783
784         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
785         {
786                 log(LL_WRN, "msg_charging_ind: cdid not found");
787                 return;
788         }
789
790         if(mp->units_type < CHARGE_INVALID || mp->units_type > CHARGE_CALC)
791         { 
792                 log(LL_ERR, "msg_charging: units_type %d out of range!", mp->units_type);
793                 do_exit(1);
794         }
795         
796         DBGL(DL_DRVR, (log(LL_DBG, "msg_charging: %d unit(s) (%s)",
797                         mp->units, cttab[mp->units_type])));
798
799         switch(mp->units_type)
800         {
801                 case CHARGE_AOCD:
802                         cep->charge = mp->units;
803
804                         if((cep->unitlengthsrc == ULSRC_DYN) &&
805                            (cep->charge != cep->last_charge))
806                         {
807                                 cep->last_charge = cep->charge;
808                                 handle_charge(cep);
809                         }
810                         break;
811
812                 case CHARGE_AOCE:
813                         cep->charge = mp->units;
814                         break;
815                         
816                 case CHARGE_CALC:
817                         cep->charge = mp->units;        
818 #ifdef USE_CURSES
819                         if(do_fullscreen)
820                                 display_ccharge(cep, mp->units);
821 #endif
822 #ifdef I4B_EXTERNAL_MONITOR
823                         if(do_monitor && accepted)
824                                 monitor_evnt_charge(cep, mp->units, 1);
825 #endif
826                         break;
827         }
828 }
829
830 /*---------------------------------------------------------------------------*
831  *      handle incoming IDLE_TIMEOUT_IND message
832  *---------------------------------------------------------------------------*/
833 void
834 msg_idle_timeout_ind(msg_idle_timeout_ind_t *mp)
835 {
836         cfg_entry_t *cep;
837         
838         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
839         {
840                 log(LL_WRN, "msg_idle_timeout_ind: cdid not found!");
841                 return;
842         }
843
844         cep->local_disconnect = DISCON_LOC;
845         
846         DBGL(DL_DRVR, (log(LL_DBG, "msg_idle_timeout_ind: idletimeout, kernel sent disconnect!")));
847         
848         check_and_kill(cep);
849 }
850
851 /*---------------------------------------------------------------------------*
852  *      get a cdid from kernel
853  *---------------------------------------------------------------------------*/
854 int
855 get_cdid(void)
856 {
857         msg_cdid_req_t mcr;
858
859         mcr.cdid = 0;
860         
861         if((ioctl(isdnfd, I4B_CDID_REQ, &mcr)) < 0)
862         {
863                 log(LL_ERR, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno));
864                 do_exit(1);
865         }
866
867         return(mcr.cdid);
868 }
869
870 /*---------------------------------------------------------------------------*
871  *      send message "connect request" to kernel
872  *---------------------------------------------------------------------------*/
873 int
874 sendm_connect_req(cfg_entry_t *cep)
875 {
876         msg_connect_req_t mcr;
877         int ret;
878
879         cep->local_disconnect = DISCON_REM;
880         
881         cep->unitlength = get_current_rate(cep, 1);
882         
883         mcr.cdid = cep->cdid;
884
885         mcr.controller = cep->isdncontrollerused;
886         mcr.channel = cep->isdnchannelused;
887         mcr.txdelay = cep->isdntxdelout;
888
889         mcr.bprot = cep->b1protocol;
890
891         mcr.driver = cep->usrdevicename;
892         mcr.driver_unit = cep->usrdeviceunit;
893
894         /* setup the shorthold data */
895         mcr.shorthold_data.shorthold_algorithm = cep->shorthold_algorithm;
896         mcr.shorthold_data.unitlen_time = cep->unitlength;
897         mcr.shorthold_data.idle_time = cep->idle_time_out;              
898         mcr.shorthold_data.earlyhup_time = cep->earlyhangup;
899
900         if(cep->unitlengthsrc == ULSRC_DYN)
901                 mcr.unitlen_method = ULEN_METHOD_DYNAMIC;
902         else
903                 mcr.unitlen_method = ULEN_METHOD_STATIC;
904         
905         strcpy(mcr.dst_telno, cep->remote_phone_dialout);
906         strcpy(mcr.src_telno, cep->local_phone_dialout);
907
908         cep->last_dial_time = time(NULL);
909         cep->direction = DIR_OUT;
910
911         DBGL(DL_CNST, (log(LL_DBG, "sendm_connect_req: ctrl = %d, chan = %d", cep->isdncontrollerused, cep->isdnchannelused)));
912                 
913         if((ret = ioctl(isdnfd, I4B_CONNECT_REQ, &mcr)) < 0)
914         {
915                 log(LL_ERR, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno));
916                 do_exit(1);
917         }
918
919         decr_free_channels(cep->isdncontrollerused);
920         
921         log(LL_CHD, "%05d %s dialing out from %s to %s",
922                 cep->cdid,
923                 cep->name,
924                 aliasing ? get_alias(cep->local_phone_dialout) : cep->local_phone_dialout,
925                 aliasing ? get_alias(cep->remote_phone_dialout) : cep->remote_phone_dialout);
926
927         return(ret);
928 }
929
930 /*---------------------------------------------------------------------------*
931  *      send message "connect response" to kernel
932  *---------------------------------------------------------------------------*/
933 int
934 sendm_connect_resp(cfg_entry_t *cep, int cdid, int response, int cause)
935 {
936         msg_connect_resp_t mcr;
937         int ret;
938
939         mcr.cdid = cdid;
940
941         mcr.response = response;
942
943         if(response == SETUP_RESP_REJECT)
944         {
945                 mcr.cause = cause;
946         }
947         else if(response == SETUP_RESP_ACCEPT)
948         {
949                 cep->direction = DIR_IN;
950
951                 mcr.txdelay = cep->isdntxdelin;
952
953                 mcr.bprot = cep->b1protocol;
954
955                 mcr.driver = cep->usrdevicename;
956                 mcr.driver_unit = cep->usrdeviceunit;
957
958                 mcr.max_idle_time = cep->idle_time_in;
959         }
960         
961         if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &mcr)) < 0)
962         {
963                 log(LL_ERR, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno));
964                 do_exit(1);
965         }
966
967         DBGL(DL_DRVR, (log(LL_DBG, "sendm_connect_resp: sent CONNECT_RESP")));
968
969         return(ret);
970 }
971
972 /*---------------------------------------------------------------------------*
973  *      send message "disconnect request" to kernel
974  *---------------------------------------------------------------------------*/
975 int
976 sendm_disconnect_req(cfg_entry_t *cep, int cause)
977 {
978         msg_discon_req_t mcr;
979         int ret;
980
981         mcr.cdid = cep->cdid;
982
983         mcr.cause = cause;
984
985         cep->local_disconnect = DISCON_LOC;
986         
987         if((ret = ioctl(isdnfd, I4B_DISCONNECT_REQ, &mcr)) < 0)
988         {
989                 log(LL_ERR, "sendm_disconnect_req: ioctl I4B_DISCONNECT_REQ failed: %s", strerror(errno));
990                 do_exit(1);
991         }
992         else
993         {
994                 DBGL(DL_DRVR, (log(LL_DBG, "sendm_disconnect_req: sent DISCONNECT_REQ")));
995         }
996         return(ret);
997 }
998         
999 /*---------------------------------------------------------------------------*
1000  *      send message "alert request" to kernel
1001  *---------------------------------------------------------------------------*/
1002 int
1003 sendm_alert_req(cfg_entry_t *cep)
1004 {
1005         msg_alert_req_t mar;
1006         int ret;
1007
1008         mar.cdid = cep->cdid;
1009         
1010         if((ret = ioctl(isdnfd, I4B_ALERT_REQ, &mar)) < 0)
1011         {
1012                 log(LL_ERR, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno));
1013                 do_exit(1);
1014         }
1015         else
1016         {
1017                 DBGL(DL_DRVR, (log(LL_DBG, "sendm_alert_req: sent ALERT_REQ")));
1018         }
1019         return(ret);
1020 }
1021         
1022 /* EOF */