Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / i4b / isdnd / msghdl.c
1 /*
2  * Copyright (c) 1997, 2001 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  *      $Id: msghdl.c,v 1.78 2000/09/21 11:29:51 hm Exp $ 
31  *
32  * $FreeBSD: src/usr.sbin/i4b/isdnd/msghdl.c,v 1.6.2.3 2001/12/16 15:13:38 hm Exp $
33  *
34  *      last edit-date: [Thu Sep 21 11:11:48 2000]
35  *
36  *---------------------------------------------------------------------------*/
37
38 #include "isdnd.h"
39
40 #include <sys/socket.h>
41 #include <net/if.h>
42 #include <net/if_types.h>
43
44 #if defined(__FreeBSD__)
45 #include <net/if_var.h>
46 #endif
47
48 #include <netinet/in.h>
49 #include <netinet/in_systm.h>
50 #include <netinet/in_var.h>
51 #include <netinet/ip.h>
52 #include <netinet/tcp.h>
53 #include <netinet/udp.h>
54 #include <netinet/ip_icmp.h>
55
56 /*---------------------------------------------------------------------------*
57  *      handle incoming CONNECT_IND (=SETUP) message
58  *---------------------------------------------------------------------------*/
59 void
60 msg_connect_ind(msg_connect_ind_t *mp)
61 {
62         cfg_entry_t *cep;
63         char *src_tela = "ERROR-src_tela";
64         char *dst_tela = "ERROR-dst_tela";
65
66 #define SRC (aliasing == 0 ? mp->src_telno : src_tela)
67 #define DST (aliasing == 0 ? mp->dst_telno : dst_tela)
68
69         if(aliasing)
70         {
71                 src_tela = get_alias(mp->src_telno);
72                 dst_tela = get_alias(mp->dst_telno);
73         }
74
75         if((cep = find_matching_entry_incoming(mp)) == NULL)
76         {
77                 /* log message generated in find_matching_entry_incoming() */
78                 sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
79                 handle_scrprs(mp->header.cdid, mp->scr_ind, mp->prs_ind, SRC);
80                 return;
81         }
82
83         if(cep->cdid != CDID_UNUSED && cep->cdid != CDID_RESERVED)
84         {       
85                 /* 
86                  * This is an incoming call on a number we just dialed out.
87                  * Stop our dial-out and accept the incoming call.
88                  */
89                 if(cep->saved_call.cdid != CDID_UNUSED &&
90                    cep->saved_call.cdid != CDID_RESERVED)
91                 {
92                         int cdid;
93
94                         /* disconnect old, not new */
95                         
96                         cdid = cep->cdid;
97                         cep->cdid = cep->saved_call.cdid;
98                         sendm_disconnect_req(cep, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
99                         cep->cdid = cdid;
100
101                         /*
102                          * Shortcut the state machine and mark this
103                          * entry as free
104                          */
105 /* XXX */               cep->state = ST_IDLE;   /* this is an invalid   */
106                                                 /* transition,          */
107                                                 /* so no next_state()   */
108                         /* we have to wait here for an incoming */
109                         /* disconnect message !!! (-hm)         */
110                 }
111         }
112
113         if(cep->inout == DIR_OUTONLY)
114         {
115                 log(LL_CHD, "%05d %s incoming call from %s to %s not allowed by configuration!",
116                         mp->header.cdid, cep->name, SRC, DST);
117                 sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
118                 handle_scrprs(mp->header.cdid, mp->scr_ind, mp->prs_ind, SRC);
119                 return;
120         }
121
122         cep->charge = 0;
123         cep->last_charge = 0;
124                 
125         switch(cep->dialin_reaction)
126         {
127                 case REACT_ACCEPT:
128                         log(LL_CHD, "%05d %s accepting: incoming call from %s to %s",
129                                 mp->header.cdid, cep->name, SRC, DST);
130                         decr_free_channels(mp->controller);
131                         next_state(cep, EV_MCI);
132                         break;
133
134                 case REACT_REJECT:
135                         log(LL_CHD, "%05d %s rejecting: incoming call from %s to %s",
136                                 mp->header.cdid, cep->name, SRC, DST);
137                         sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
138                                 (CAUSET_I4B << 8) | CAUSE_I4B_REJECT);
139                         cep->cdid = CDID_UNUSED;
140                         break;
141
142                 case REACT_IGNORE:
143                         log(LL_CHD, "%05d %s ignoring: incoming call from %s to %s",
144                                 mp->header.cdid, cep->name, SRC, DST);
145                         sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
146                         cep->cdid = CDID_UNUSED;
147                         break;
148
149                 case REACT_ANSWER:
150                         decr_free_channels(mp->controller);
151                         if(cep->alert)
152                         {
153                                 if(mp->display)
154                                 {
155                                         log(LL_CHD, "%05d %s alerting: incoming call from %s to %s (%s)",
156                                                 mp->header.cdid, cep->name, SRC, DST, mp->display);
157                                 }
158                                 else
159                                 {
160                                         log(LL_CHD, "%05d %s alerting: incoming call from %s to %s",
161                                                 mp->header.cdid, cep->name, SRC, DST);
162                                 }
163                                 next_state(cep, EV_ALRT);
164                         }
165                         else
166                         {
167                                 if(mp->display)
168                                 {                               
169                                         log(LL_CHD, "%05d %s answering: incoming call from %s to %s (%s)",
170                                                 mp->header.cdid, cep->name, SRC, DST, mp->display);
171                                 }
172                                 else
173                                 {
174                                         log(LL_CHD, "%05d %s answering: incoming call from %s to %s",
175                                                 mp->header.cdid, cep->name, SRC, DST);
176                                 }
177                                 next_state(cep, EV_MCI);
178                         }
179                         break;
180
181                 case REACT_CALLBACK:
182                 
183 #ifdef NOTDEF
184 /*XXX reserve channel ??? */    decr_free_channels(mp->controller);
185 #endif
186                         if(cep->cdid == CDID_RESERVED)
187                         {
188                                 log(LL_CHD, "%05d %s reserved: incoming call from %s to %s",
189                                         mp->header.cdid, cep->name, SRC, DST);
190                                 sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
191 #if 0
192                                         (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
193 #else
194                                         (CAUSET_I4B << 8) | CAUSE_I4B_REJECT);
195 #endif                                  
196                                 /* no state change */
197                         }
198                         else
199                         {
200                                 sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT,
201 #if 0
202                                         (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
203 #else
204                                         (CAUSET_I4B << 8) | CAUSE_I4B_REJECT);
205 #endif                                  
206                                 if(cep->budget_callbackperiod && cep->budget_callbackncalls)
207                                 {
208                                         cep->budget_callback_req++;
209                                         cep->budget_calltype = 0;
210                                         if(cep->budget_callbackncalls_cnt == 0)
211                                         {
212                                                 log(LL_CHD, "%05d %s no budget: call from %s to %s",
213                                                         mp->header.cdid, cep->name, SRC, DST);
214                                                 cep->cdid = CDID_UNUSED;
215                                                 cep->budget_callback_rej++;
216                                                 break;
217                                         }
218                                         else
219                                         {
220                                                 cep->budget_calltype = BUDGET_TYPE_CBACK;
221                                         }
222                                 }
223
224                                 log(LL_CHD, "%05d %s callback: incoming call from %s to %s",
225                                         mp->header.cdid, cep->name, SRC, DST);
226
227                                 cep->last_release_time = time(NULL);
228                                 cep->cdid = CDID_RESERVED;
229                                 next_state(cep, EV_CBRQ);
230                         }
231                         break;
232                         
233                 default:
234                         log(LL_WRN, "msg_connect_ind: unknown response type, tx SETUP_RESP_DNTCRE");
235                         sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0);
236                         break;
237         }
238         handle_scrprs(mp->header.cdid, mp->scr_ind, mp->prs_ind, SRC);
239 #undef SRC
240 #undef DST
241 }
242
243 /*---------------------------------------------------------------------------*
244  *      handle incoming CONNECT_ACTIVE_IND message
245  *---------------------------------------------------------------------------*/
246 void
247 msg_connect_active_ind(msg_connect_active_ind_t *mp)
248 {
249         cfg_entry_t *cep;
250         char *device;
251         
252         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
253         {
254                 log(LL_WRN, "msg_connect_active_ind: cdid not found!");
255                 return;
256         }
257
258         cep->isdncontrollerused = mp->controller;
259         cep->isdnchannelused = mp->channel;     
260                                                                                 
261         cep->aoc_now = cep->connect_time = time(NULL);
262         cep->aoc_last = 0;
263         cep->aoc_diff = 0;
264         cep->aoc_valid = AOC_INVALID;
265
266         cep->local_disconnect = DISCON_REM;     
267         
268         cep->inbytes = INVALID;
269         cep->outbytes = INVALID;
270         cep->hangup = 0;
271
272         device = bdrivername(cep->usrdevicename);
273
274         /* set the B-channel to active */
275
276         if((set_channel_busy(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
277                 log(LL_ERR, "msg_connect_active_ind: set_channel_busy failed!");
278
279         if(cep->direction == DIR_OUT)
280         {
281                 log(LL_CHD, "%05d %s outgoing call active (ctl %d, ch %d, %s%d)",
282                         cep->cdid, cep->name,
283                         cep->isdncontrollerused, cep->isdnchannelused,
284                         bdrivername(cep->usrdevicename), cep->usrdeviceunit);
285
286                 if(cep->budget_calltype)
287                 {
288                         if(cep->budget_calltype == BUDGET_TYPE_CBACK)
289                         {
290                                 cep->budget_callback_done++;
291                                 cep->budget_callbackncalls_cnt--;
292                                 DBGL(DL_BDGT, (log(LL_DBG, "%s: new cback-budget = %d",
293                                         cep->name, cep->budget_callbackncalls_cnt)));
294                                 if(cep->budget_callbacks_file != NULL)
295                                         upd_callstat_file(cep->budget_callbacks_file, cep->budget_callbacksfile_rotate);
296                         }
297                         else if(cep->budget_calltype == BUDGET_TYPE_COUT)
298                         {
299                                 cep->budget_callout_done++;
300                                 cep->budget_calloutncalls_cnt--;
301                                 DBGL(DL_BDGT, (log(LL_DBG, "%s: new cout-budget = %d",
302                                         cep->name, cep->budget_calloutncalls_cnt)));
303                                 if(cep->budget_callouts_file != NULL)
304                                         upd_callstat_file(cep->budget_callouts_file, cep->budget_calloutsfile_rotate);
305                         }
306                         cep->budget_calltype = 0;
307                 }
308         }
309         else
310         {
311                 log(LL_CHD, "%05d %s incoming call active (ctl %d, ch %d, %s%d)",
312                         cep->cdid, cep->name,
313                         cep->isdncontrollerused, cep->isdnchannelused,
314                         bdrivername(cep->usrdevicename), cep->usrdeviceunit);
315         }
316         
317 #ifdef USE_CURSES
318         if(do_fullscreen)
319                 display_connect(cep);
320 #endif
321 #ifdef I4B_EXTERNAL_MONITOR
322         if(do_monitor && accepted)
323                 monitor_evnt_connect(cep);
324 #endif
325
326         if(isdntime && (mp->datetime[0] != '\0'))
327         {
328                 log(LL_DMN, "date/time from exchange = %s", mp->datetime);
329         }
330
331         next_state(cep, EV_MCAI);
332 }
333                                                                                 
334 /*---------------------------------------------------------------------------*
335  *      handle incoming PROCEEDING_IND message
336  *---------------------------------------------------------------------------*/
337 void
338 msg_proceeding_ind(msg_proceeding_ind_t *mp)
339 {
340         cfg_entry_t *cep;
341         
342         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
343         {
344                 log(LL_WRN, "msg_proceeding_ind: cdid not found!");
345                 return;
346         }
347
348         cep->isdncontrollerused = mp->controller;
349         cep->isdnchannelused = mp->channel;     
350                                                                                 
351         /* set the B-channels active */
352
353         if((set_channel_busy(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
354                 log(LL_ERR, "msg_proceeding_ind: set_channel_busy failed!");
355         
356         log(LL_CHD, "%05d %s outgoing call proceeding (ctl %d, ch %d)",
357                         cep->cdid, cep->name,
358                         cep->isdncontrollerused, cep->isdnchannelused);
359 }
360                                                                                 
361 /*---------------------------------------------------------------------------*
362  *      handle incoming ALERT_IND message
363  *---------------------------------------------------------------------------*/
364 void
365 msg_alert_ind(msg_alert_ind_t *mp)
366 {
367         cfg_entry_t *cep;
368         
369         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
370         {
371                 log(LL_WRN, "msg_alert_ind: cdid not found!");
372                 return;
373         }
374 #ifdef NOTDEF
375         log(LL_CHD, "%05d %s incoming alert", cep->cdid, cep->name);
376 #endif
377 }
378                                                                                 
379 /*---------------------------------------------------------------------------*
380  *      handle incoming L12STAT_IND message
381  *---------------------------------------------------------------------------*/
382 void
383 msg_l12stat_ind(msg_l12stat_ind_t *ml)
384 {
385         if((ml->controller < 0) || (ml->controller >= ncontroller))
386         {
387                 log(LL_ERR, "msg_l12stat_ind: invalid controller number [%d]!", ml->controller);
388                 return;
389         }
390
391 #ifdef USE_CURSES
392         if(do_fullscreen)
393                 display_l12stat(ml->controller, ml->layer, ml->state);
394 #endif
395 #ifdef I4B_EXTERNAL_MONITOR
396         if(do_monitor && accepted)
397                 monitor_evnt_l12stat(ml->controller, ml->layer, ml->state);
398 #endif
399
400         DBGL(DL_CNST, (log(LL_DBG, "msg_l12stat_ind: unit %d, layer %d, state %d",
401                 ml->controller, ml->layer, ml->state)));
402
403         if(ml->layer == LAYER_ONE)
404         {
405                 if(ml->state == LAYER_IDLE)
406                         isdn_ctrl_tab[ml->controller].l2stat = ml->state;
407                 isdn_ctrl_tab[ml->controller].l1stat = ml->state;
408         }
409         else if(ml->layer == LAYER_TWO)
410         {
411                 if(ml->state == LAYER_ACTIVE)
412                         isdn_ctrl_tab[ml->controller].l1stat = ml->state;
413                 isdn_ctrl_tab[ml->controller].l2stat = ml->state;
414         }
415         else
416         {
417                 log(LL_ERR, "msg_l12stat_ind: invalid layer number [%d]!", ml->layer);
418         }
419 }
420                                                                                 
421 /*---------------------------------------------------------------------------*
422  *      handle incoming TEIASG_IND message
423  *---------------------------------------------------------------------------*/
424 void
425 msg_teiasg_ind(msg_teiasg_ind_t *mt)
426 {
427         if((mt->controller < 0) || (mt->controller >= ncontroller))
428         {
429                 log(LL_ERR, "msg_teiasg_ind: invalid controller number [%d]!", mt->controller);
430                 return;
431         }
432
433 #ifdef USE_CURSES
434         if(do_fullscreen)
435                 display_tei(mt->controller, mt->tei);
436 #endif
437 #ifdef I4B_EXTERNAL_MONITOR
438         if(do_monitor && accepted)
439                 monitor_evnt_tei(mt->controller, mt->tei);
440 #endif
441
442         DBGL(DL_CNST, (log(LL_DBG, "msg_teiasg_ind: unit %d, tei = %d",
443                 mt->controller, mt->tei)));
444
445         isdn_ctrl_tab[mt->controller].tei = mt->tei;
446 }
447
448 /*---------------------------------------------------------------------------*
449  *      handle incoming PDEACT_IND message
450  *---------------------------------------------------------------------------*/
451 void
452 msg_pdeact_ind(msg_pdeact_ind_t *md)
453 {
454         int i;
455         int ctrl = md->controller;
456         cfg_entry_t *cep;
457
458 #ifdef USE_CURSES
459         if(do_fullscreen)
460         {
461                 display_l12stat(ctrl, LAYER_ONE, LAYER_IDLE);
462                 display_l12stat(ctrl, LAYER_TWO, LAYER_IDLE);
463                 display_tei(ctrl, -1);
464         }
465 #endif
466 #ifdef I4B_EXTERNAL_MONITOR
467         if(do_monitor && accepted)
468         {
469                 monitor_evnt_l12stat(ctrl, LAYER_ONE, LAYER_IDLE);
470                 monitor_evnt_l12stat(ctrl, LAYER_TWO, LAYER_IDLE);              
471                 monitor_evnt_tei(ctrl, -1);
472         }
473 #endif
474
475         DBGL(DL_CNST, (log(LL_DBG, "msg_pdeact_ind: unit %d, persistent deactivation", ctrl)));
476
477         isdn_ctrl_tab[ctrl].l1stat = LAYER_IDLE;
478         isdn_ctrl_tab[ctrl].l2stat = LAYER_IDLE;
479         isdn_ctrl_tab[ctrl].tei = -1;           
480         
481         for(i=0; i < nentries; i++)
482         {
483                 if((cfg_entry_tab[i].cdid != CDID_UNUSED)       &&
484                    (cfg_entry_tab[i].isdncontrollerused == ctrl))
485                 {
486                         cep = &cfg_entry_tab[i];
487                         
488                         if(cep->cdid == CDID_RESERVED)
489                         {
490                                 cep->state = ST_IDLE;
491                                 cep->cdid = CDID_UNUSED;
492                                 continue;
493                         }
494
495                         cep->cdid = CDID_UNUSED;
496                         
497                         cep->last_release_time = time(NULL);
498
499                         SET_CAUSE_TYPE(cep->disc_cause, CAUSET_I4B);
500                         SET_CAUSE_VAL(cep->disc_cause, CAUSE_I4B_L1ERROR);
501                 
502                         if(cep->direction == DIR_OUT)
503                         {
504                                 log(LL_CHD, "%05d %s outgoing call disconnected (local)",
505                                         cep->cdid, cep->name);
506                         }
507                         else
508                         {
509                                 log(LL_CHD, "%05d %s incoming call disconnected (local)",
510                                         cep->cdid, cep->name);
511                         }
512                 
513                         log(LL_CHD, "%05d %s cause %s",
514                                 cep->cdid, cep->name, print_i4b_cause(cep->disc_cause));
515                 
516 #ifdef USE_CURSES
517                         if(do_fullscreen && (cep->connect_time > 0))
518                                 display_disconnect(cep);
519 #endif
520 #ifdef I4B_EXTERNAL_MONITOR
521                         if(do_monitor && accepted)
522                                 monitor_evnt_disconnect(cep);
523 #endif
524
525                         if(cep->disconnectprog)
526                                 exec_connect_prog(cep, cep->disconnectprog, 1);
527                 
528                         if(cep->connect_time > 0)
529                         {
530                                 if(cep->direction == DIR_OUT)
531                                 {
532                                         log(LL_CHD, "%05d %s charging: %d units, %d seconds",
533                                                 cep->cdid, cep->name, cep->charge,
534                                                 (int)difftime(time(NULL), cep->connect_time));
535                                 }
536                                 else
537                                 {
538                                         log(LL_CHD, "%05d %s connected %d seconds",
539                                                 cep->cdid, cep->name,
540                                                 (int)difftime(time(NULL), cep->connect_time));
541                                 }
542                 
543                                 if((cep->inbytes != INVALID) && (cep->outbytes != INVALID))
544                                 {
545                                         if((cep->ioutbytes != cep->outbytes) ||
546                                            (cep->iinbytes != cep->inbytes))
547                                         {
548                                                 log(LL_CHD, "%05d %s accounting: in %d, out %d (in %d, out %d)",
549                                                         cep->cdid, cep->name,
550                                                         cep->inbytes, cep->outbytes,
551                                                         cep->iinbytes, cep->ioutbytes);
552                                         }
553                                         else
554                                         {
555                                                 log(LL_CHD, "%05d %s accounting: in %d, out %d",
556                                                         cep->cdid, cep->name,
557                                                         cep->inbytes, cep->outbytes);
558                                         }
559                                 }
560                         }
561
562                         if(useacctfile && (cep->connect_time > 0))
563                         {
564                                 int con_secs;
565                                 char logdatetime[41];
566                                 struct tm *tp;
567                 
568                                 con_secs = difftime(time(NULL), cep->connect_time);
569                                         
570                                 tp = localtime(&cep->connect_time);
571                                 
572                                 strftime(logdatetime,40,I4B_TIME_FORMAT,tp);
573                 
574                                 if(cep->inbytes != INVALID && cep->outbytes != INVALID)
575                                 {
576                                         fprintf(acctfp, "%s - %s %s %d (%d) (%d/%d)\n",
577                                                 logdatetime, getlogdatetime(),
578                                                 cep->name, cep->charge, con_secs,
579                                                 cep->inbytes, cep->outbytes);
580                                 }
581                                 else
582                                 {
583                                         fprintf(acctfp, "%s - %s %s %d (%d)\n",
584                                                 logdatetime, getlogdatetime(),
585                                                 cep->name, cep->charge, con_secs);
586                                 }
587                         }
588                 
589                         /* set the B-channel inactive */
590                 
591                         if((set_channel_idle(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR)
592                                 log(LL_ERR, "msg_pdeact_ind: set_channel_idle failed!");
593                 
594                         incr_free_channels(cep->isdncontrollerused);
595                         
596                         cep->connect_time = 0;
597
598                         cep->state = ST_IDLE;
599                 }
600         }
601 }
602                                                                                 
603 /*---------------------------------------------------------------------------*
604  *      handle incoming NEGCOMP_IND message
605  *---------------------------------------------------------------------------*/
606 void
607 msg_negcomplete_ind(msg_negcomplete_ind_t *mp)
608 {
609         cfg_entry_t *cep;
610
611         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
612         {
613                 log(LL_WRN, "msg_negcomp_ind: cdid not found");
614                 return;
615         }
616
617         if(cep->connectprog)
618                 exec_connect_prog(cep, cep->connectprog, 0);
619 }
620                                                                                 
621 /*---------------------------------------------------------------------------*
622  *      handle incoming IFSTATE_CHANGED indication
623  *---------------------------------------------------------------------------*/
624 void
625 msg_ifstatechg_ind(msg_ifstatechg_ind_t *mp)
626 {
627         cfg_entry_t *cep;
628         char *device;
629
630         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
631         {
632                 log(LL_WRN, "msg_negcomp_ind: cdid not found");
633                 return;
634         }
635
636         device = bdrivername(cep->usrdevicename);
637         log(LL_DBG, "%s%d: switched to state %d", device, cep->usrdeviceunit, mp->state);
638 }
639
640 /*---------------------------------------------------------------------------*
641  *      handle incoming DISCONNECT_IND message
642  *---------------------------------------------------------------------------*/
643 void
644 msg_disconnect_ind(msg_disconnect_ind_t *mp)
645 {
646         cfg_entry_t *cep;
647
648         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
649         {
650                 log(LL_WRN, "msg_disconnect_ind: cdid not found");
651                 return;
652         }
653
654         /* is this an aborted out-call prematurely called back? */
655         if (cep->saved_call.cdid == mp->header.cdid)
656         {
657                 DBGL(DL_CNST, (log(LL_DBG, "aborted outcall %05d disconnected",
658                         mp->header.cdid)));
659                 cep->saved_call.cdid = CDID_UNUSED;
660
661                 set_channel_idle(cep->saved_call.controller, cep->saved_call.channel);
662
663                 incr_free_channels(cep->saved_call.controller);
664                 return;
665         }
666
667         cep->last_release_time = time(NULL);
668         cep->disc_cause = mp->cause;
669
670         if(cep->direction == DIR_OUT)
671         {
672                 log(LL_CHD, "%05d %s outgoing call disconnected %s",
673                         cep->cdid, cep->name, 
674                         cep->local_disconnect == DISCON_LOC ?
675                                                 "(local)" : "(remote)");
676         }
677         else
678         {
679                 log(LL_CHD, "%05d %s incoming call disconnected %s", 
680                         cep->cdid, cep->name,
681                         cep->local_disconnect == DISCON_LOC ?
682                                                 "(local)" : "(remote)");
683         }
684
685         log(LL_CHD, "%05d %s cause %s",
686                 cep->cdid, cep->name, print_i4b_cause(mp->cause));
687
688 #ifdef USE_CURSES
689         if(do_fullscreen && (cep->connect_time > 0))
690                 display_disconnect(cep);
691 #endif
692 #ifdef I4B_EXTERNAL_MONITOR
693         if(do_monitor && accepted)
694                 monitor_evnt_disconnect(cep);
695 #endif
696
697         if(cep->disconnectprog)
698                 exec_connect_prog(cep, cep->disconnectprog, 1);
699
700         if(cep->connect_time > 0)
701         {
702                 if(cep->direction == DIR_OUT)
703                 {
704                         log(LL_CHD, "%05d %s charging: %d units, %d seconds",
705                                 cep->cdid, cep->name, cep->charge,
706                                 (int)difftime(time(NULL), cep->connect_time));
707                 }
708                 else
709                 {
710                         log(LL_CHD, "%05d %s connected %d seconds",
711                                 cep->cdid, cep->name,
712                                 (int)difftime(time(NULL), cep->connect_time));
713                 }
714
715                 if((cep->inbytes != INVALID) && (cep->outbytes != INVALID))
716                 {
717                         if((cep->ioutbytes != cep->outbytes) ||
718                            (cep->iinbytes != cep->inbytes))
719                         {
720                                 log(LL_CHD, "%05d %s accounting: in %d, out %d (in %d, out %d)",
721                                         cep->cdid, cep->name,
722                                         cep->inbytes, cep->outbytes,
723                                         cep->iinbytes, cep->ioutbytes);
724                         }
725                         else
726                         {
727                                 log(LL_CHD, "%05d %s accounting: in %d, out %d",
728                                         cep->cdid, cep->name,
729                                         cep->inbytes, cep->outbytes);
730                         }
731                 }
732         }                       
733
734         if(useacctfile && (cep->connect_time > 0))
735         {
736                 int con_secs;
737                 char logdatetime[41];
738                 struct tm *tp;
739
740                 con_secs = difftime(time(NULL), cep->connect_time);
741                         
742                 tp = localtime(&cep->connect_time);
743                 
744                 strftime(logdatetime,40,I4B_TIME_FORMAT,tp);
745
746                 if(cep->inbytes != INVALID && cep->outbytes != INVALID)
747                 {
748                         fprintf(acctfp, "%s - %s %s %d (%d) (%d/%d)\n",
749                                 logdatetime, getlogdatetime(),
750                                 cep->name, cep->charge, con_secs,
751                                 cep->inbytes, cep->outbytes);
752                 }
753                 else
754                 {
755                         fprintf(acctfp, "%s - %s %s %d (%d)\n",
756                                 logdatetime, getlogdatetime(),
757                                 cep->name, cep->charge, con_secs);
758                 }
759         }
760
761         /* set the B-channel inactive */
762
763         set_channel_idle(cep->isdncontrollerused, cep->isdnchannelused);
764
765         incr_free_channels(cep->isdncontrollerused);
766         
767         cep->connect_time = 0;                  
768         cep->cdid = CDID_UNUSED;
769
770         next_state(cep, EV_MDI);
771 }
772
773 /*---------------------------------------------------------------------------*
774  *      handle incoming DIALOUT message
775  *---------------------------------------------------------------------------*/
776 void
777 msg_dialout(msg_dialout_ind_t *mp)
778 {
779         cfg_entry_t *cep;
780         
781         DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
782
783         if((cep = find_by_device_for_dialout(mp->driver, mp->driver_unit)) == NULL)
784         {
785                 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: config entry reserved or no match")));
786                 return;
787         }
788
789         if(cep->inout == DIR_INONLY)
790         {
791                 dialresponse(cep, DSTAT_INONLY);
792                 return;
793         }
794
795         if(cep->budget_calloutperiod && cep->budget_calloutncalls)
796         {
797                 cep->budget_calltype = 0;
798                 cep->budget_callout_req++;
799                 
800                 if(cep->budget_calloutncalls_cnt == 0)
801                 {
802                         log(LL_CHD, "%05d %s no budget for calling out", 0, cep->name);
803                         cep->budget_callout_rej++;
804                         dialresponse(cep, DSTAT_TFAIL);
805                         return;
806                 }
807                 else
808                 {
809                         cep->budget_calltype = BUDGET_TYPE_COUT;
810                 }
811         }
812
813         if((cep->cdid = get_cdid()) == 0)
814         {
815                 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: get_cdid() returned 0!")));
816                 return;
817         }
818         
819         cep->charge = 0;
820         cep->last_charge = 0;
821         cep->hangup = 0;
822
823         next_state(cep, EV_MDO);        
824 }
825
826 /*---------------------------------------------------------------------------*
827  *      handle incoming DIALOUTNUMBER message
828  *---------------------------------------------------------------------------*/
829 void
830 msg_dialoutnumber(msg_dialoutnumber_ind_t *mp)
831 {
832         cfg_entry_t *cep;
833         
834         DBGL(DL_DRVR, (log(LL_DBG, "msg_dialoutnumber: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
835
836         if((cep = find_by_device_for_dialoutnumber(mp->driver, mp->driver_unit, mp->cmdlen, mp->cmd)) == NULL)
837         {
838                 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialoutnumber: config entry reserved or no match")));
839                 return;
840         }
841
842         if(cep->inout == DIR_INONLY)
843         {
844                 dialresponse(cep, DSTAT_INONLY);
845                 return;
846         }
847         
848         if(cep->budget_calloutperiod && cep->budget_calloutncalls)
849         {
850                 cep->budget_calltype = 0;
851                 cep->budget_callout_req++;
852                 
853                 if(cep->budget_calloutncalls_cnt == 0)
854                 {
855                         log(LL_CHD, "%05d %s no budget for calling out", 0, cep->name);
856                         cep->budget_callout_rej++;
857                         dialresponse(cep, DSTAT_TFAIL);
858                         return;
859                 }
860                 else
861                 {
862                         cep->budget_calltype = BUDGET_TYPE_COUT;
863                 }
864         }
865
866         if((cep->cdid = get_cdid()) == 0)
867         {
868                 DBGL(DL_DRVR, (log(LL_DBG, "msg_dialoutnumber: get_cdid() returned 0!")));
869                 return;
870         }
871
872         cep->keypad[0] = '\0';  
873         cep->charge = 0;
874         cep->last_charge = 0;
875         cep->hangup = 0;
876
877         next_state(cep, EV_MDO);        
878 }
879
880 /*---------------------------------------------------------------------------*
881  *      handle incoming KEYPAD message
882  *---------------------------------------------------------------------------*/
883 void
884 msg_keypad(msg_keypad_ind_t *mp)
885 {
886         cfg_entry_t *cep;
887         
888         DBGL(DL_DRVR, (log(LL_DBG, "msg_keypad: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
889
890         if((cep = find_by_device_for_keypad(mp->driver, mp->driver_unit, mp->cmdlen, mp->cmd)) == NULL)
891         {
892                 DBGL(DL_DRVR, (log(LL_DBG, "msg_keypad: config entry reserved or no match")));
893                 return;
894         }
895
896         if(cep->inout == DIR_INONLY)
897         {
898                 dialresponse(cep, DSTAT_INONLY);
899                 return;
900         }
901         
902         if(cep->budget_calloutperiod && cep->budget_calloutncalls)
903         {
904                 cep->budget_calltype = 0;
905                 cep->budget_callout_req++;
906                 
907                 if(cep->budget_calloutncalls_cnt == 0)
908                 {
909                         log(LL_CHD, "%05d %s no budget for calling out", 0, cep->name);
910                         cep->budget_callout_rej++;
911                         dialresponse(cep, DSTAT_TFAIL);
912                         return;
913                 }
914                 else
915                 {
916                         cep->budget_calltype = BUDGET_TYPE_COUT;
917                 }
918         }
919
920         if((cep->cdid = get_cdid()) == 0)
921         {
922                 DBGL(DL_DRVR, (log(LL_DBG, "msg_keypad: get_cdid() returned 0!")));
923                 return;
924         }
925         
926         cep->charge = 0;
927         cep->last_charge = 0;
928         cep->hangup = 0;
929
930         next_state(cep, EV_MDO);        
931 }
932
933 /*---------------------------------------------------------------------------*
934  *      handle incoming DRVRDISC_REQ message
935  *---------------------------------------------------------------------------*/
936 void
937 msg_drvrdisc_req(msg_drvrdisc_req_t *mp)
938 {
939         cfg_entry_t *cep;
940         
941         DBGL(DL_DRVR, (log(LL_DBG, "msg_drvrdisc_req: req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit)));
942
943         if((cep = get_cep_by_driver(mp->driver, mp->driver_unit)) == NULL)
944         {
945                 DBGL(DL_DRVR, (log(LL_DBG, "msg_drvrdisc_req: config entry not found")));
946                 return;
947         }
948         next_state(cep, EV_DRQ);
949 }
950
951 /*---------------------------------------------------------------------------*
952  *      handle incoming ACCOUNTING message
953  *---------------------------------------------------------------------------*/
954 void
955 msg_accounting(msg_accounting_ind_t *mp)
956 {
957         cfg_entry_t *cep;
958
959         if((cep = find_active_entry_by_driver(mp->driver, mp->driver_unit)) == NULL)
960         {
961                 log(LL_WRN, "msg_accounting: no config entry found!");  
962                 return;
963         }
964
965         cep->inbytes = mp->inbytes;
966         cep->iinbytes = mp->iinbytes;
967         cep->outbytes = mp->outbytes;
968         cep->ioutbytes = mp->ioutbytes;
969         cep->inbps = mp->inbps;
970         cep->outbps = mp->outbps;
971
972         if(mp->accttype == ACCT_DURING) 
973         {
974 #ifdef USE_CURSES
975                 if(do_fullscreen)
976                         display_acct(cep);
977 #endif
978 #ifdef I4B_EXTERNAL_MONITOR
979                 if(do_monitor && accepted)
980                         monitor_evnt_acct(cep);
981 #endif
982         }
983 }
984
985 /*---------------------------------------------------------------------------*
986  *      handle incoming CHARGING message
987  *---------------------------------------------------------------------------*/
988 void
989 msg_charging_ind(msg_charging_ind_t *mp)
990 {
991         static char *cttab[] = {
992                 "invalid",
993                 "AOCD",
994                 "AOCE",
995                 "estimated" };
996                 
997         cfg_entry_t *cep;
998
999         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
1000         {
1001                 log(LL_WRN, "msg_charging_ind: cdid not found");
1002                 return;
1003         }
1004
1005         if(mp->units_type < CHARGE_INVALID || mp->units_type > CHARGE_CALC)
1006         { 
1007                 log(LL_ERR, "msg_charging: units_type %d out of range!", mp->units_type);
1008                 error_exit(1, "msg_charging: units_type %d out of range!", mp->units_type);
1009         }
1010         
1011         DBGL(DL_DRVR, (log(LL_DBG, "msg_charging: %d unit(s) (%s)",
1012                         mp->units, cttab[mp->units_type])));
1013
1014         cep->charge = mp->units;
1015
1016         switch(mp->units_type)
1017         {
1018                 case CHARGE_AOCD:
1019                         if((cep->unitlengthsrc == ULSRC_DYN) &&
1020                            (cep->charge != cep->last_charge))
1021                         {
1022                                 cep->last_charge = cep->charge;
1023                                 handle_charge(cep);
1024                         }
1025                         break;
1026                         
1027                 case CHARGE_CALC:
1028 #ifdef USE_CURSES
1029                         if(do_fullscreen)
1030                                 display_ccharge(cep, mp->units);
1031 #endif
1032 #ifdef I4B_EXTERNAL_MONITOR
1033                         if(do_monitor && accepted)
1034                                 monitor_evnt_charge(cep, mp->units, 1);
1035 #endif
1036                         break;
1037         }
1038 }
1039
1040 /*---------------------------------------------------------------------------*
1041  *      handle incoming IDLE_TIMEOUT_IND message
1042  *---------------------------------------------------------------------------*/
1043 void
1044 msg_idle_timeout_ind(msg_idle_timeout_ind_t *mp)
1045 {
1046         cfg_entry_t *cep;
1047         
1048         if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL)
1049         {
1050                 log(LL_WRN, "msg_idle_timeout_ind: cdid not found!");
1051                 return;
1052         }
1053
1054         cep->local_disconnect = DISCON_LOC;
1055         
1056         DBGL(DL_DRVR, (log(LL_DBG, "msg_idle_timeout_ind: idletimeout, kernel sent disconnect!")));
1057         
1058         check_and_kill(cep);
1059 }
1060
1061 /*---------------------------------------------------------------------------*
1062  *    handle incoming MSG_PACKET_IND message
1063  *---------------------------------------------------------------------------*/
1064 static char *
1065 strapp(char *buf, const char *txt)
1066 {
1067         while(*txt)
1068                 *buf++ = *txt++;
1069         *buf = '\0';
1070         return buf;
1071 }
1072
1073 /*---------------------------------------------------------------------------*
1074  *    handle incoming MSG_PACKET_IND message
1075  *---------------------------------------------------------------------------*/
1076 static char *
1077 ipapp(char *buf, unsigned long a )
1078 {
1079         unsigned long ma = ntohl( a );
1080
1081         buf += sprintf(buf, "%lu.%lu.%lu.%lu",
1082                                 (ma>>24)&0xFF,
1083                                 (ma>>16)&0xFF,
1084                                 (ma>>8)&0xFF,
1085                                 (ma)&0xFF);
1086         return buf;
1087 }
1088
1089 /*---------------------------------------------------------------------------*
1090  *    handle incoming MSG_PACKET_IND message
1091  *---------------------------------------------------------------------------*/
1092 void
1093 msg_packet_ind(msg_packet_ind_t *mp)
1094 {
1095         cfg_entry_t *cep;
1096         struct ip *ip;
1097         u_char *proto_hdr;
1098         char tmp[80];
1099         char *cptr = tmp;
1100         char *name = "???";
1101         int i;
1102
1103         for(i=0; i < nentries; i++)
1104         {
1105                 cep = &cfg_entry_tab[i];    /* ptr to config entry */
1106
1107                 if(cep->usrdevicename == mp->driver &&
1108                         cep->usrdeviceunit == mp->driver_unit)
1109                 {
1110                         name = cep->name;
1111                         break;
1112                 }
1113         }
1114
1115         ip = (struct ip*)mp->pktdata;
1116         proto_hdr = mp->pktdata + ((ip->ip_hl)<<2);
1117
1118         if( ip->ip_p == IPPROTO_TCP )
1119         {
1120                 struct tcphdr* tcp = (struct tcphdr*)proto_hdr;
1121
1122                 cptr = strapp( cptr, "TCP " );
1123                 cptr = ipapp( cptr, ip->ip_src.s_addr );
1124                 cptr += sprintf( cptr, ":%u -> ", ntohs( tcp->th_sport ) );
1125                 cptr = ipapp( cptr, ip->ip_dst.s_addr );
1126                 cptr += sprintf( cptr, ":%u", ntohs( tcp->th_dport ) );
1127
1128                 if(tcp->th_flags & TH_FIN)  cptr = strapp( cptr, " FIN" );
1129                 if(tcp->th_flags & TH_SYN)  cptr = strapp( cptr, " SYN" );
1130                 if(tcp->th_flags & TH_RST)  cptr = strapp( cptr, " RST" );
1131                 if(tcp->th_flags & TH_PUSH) cptr = strapp( cptr, " PUSH" );
1132                 if(tcp->th_flags & TH_ACK)  cptr = strapp( cptr, " ACK" );
1133                 if(tcp->th_flags & TH_URG)  cptr = strapp( cptr, " URG" );
1134         }
1135         else if( ip->ip_p == IPPROTO_UDP )
1136         {
1137                 struct udphdr* udp = (struct udphdr*)proto_hdr;
1138
1139                 cptr = strapp( cptr, "UDP " );
1140                 cptr = ipapp( cptr, ip->ip_src.s_addr );
1141                 cptr += sprintf( cptr, ":%u -> ", ntohs( udp->uh_sport ) );
1142                 cptr = ipapp( cptr, ip->ip_dst.s_addr );
1143                 cptr += sprintf( cptr, ":%u", ntohs( udp->uh_dport ) );
1144         }
1145         else if( ip->ip_p == IPPROTO_ICMP )
1146         {
1147                 struct icmp* icmp = (struct icmp*)proto_hdr;
1148
1149                 cptr += sprintf( cptr, "ICMP:%u.%u", icmp->icmp_type, icmp->icmp_code);
1150                 cptr = ipapp( cptr, ip->ip_src.s_addr );
1151                 cptr = strapp( cptr, " -> " );
1152                 cptr = ipapp( cptr, ip->ip_dst.s_addr );
1153         }
1154         else
1155         {
1156                 cptr += sprintf( cptr, "PROTO=%u ", ip->ip_p);
1157                 cptr = ipapp( cptr, ip->ip_src.s_addr);
1158                 cptr = strapp( cptr, " -> " );
1159                 cptr = ipapp( cptr, ip->ip_dst.s_addr);
1160         }
1161
1162         log(LL_PKT, "%s %s %u %s",
1163                 name, mp->direction ? "send" : "recv",
1164                 ntohs( ip->ip_len ), tmp );
1165 }
1166
1167 /*---------------------------------------------------------------------------*
1168  *      get a cdid from kernel
1169  *---------------------------------------------------------------------------*/
1170 int
1171 get_cdid(void)
1172 {
1173         msg_cdid_req_t mcr;
1174
1175         mcr.cdid = 0;
1176         
1177         if((ioctl(isdnfd, I4B_CDID_REQ, &mcr)) < 0)
1178         {
1179                 log(LL_ERR, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno));
1180                 error_exit(1, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno));
1181         }
1182
1183         return(mcr.cdid);
1184 }
1185
1186 /*---------------------------------------------------------------------------*
1187  *      send message "connect request" to kernel
1188  *---------------------------------------------------------------------------*/
1189 int
1190 sendm_connect_req(cfg_entry_t *cep)
1191 {
1192         msg_connect_req_t mcr;
1193         int ret;
1194
1195         cep->local_disconnect = DISCON_REM;
1196         
1197         cep->unitlength = get_current_rate(cep, 1);
1198         
1199         mcr.cdid = cep->cdid;
1200
1201         mcr.controller = cep->isdncontrollerused;
1202         mcr.channel = cep->isdnchannelused;
1203         mcr.txdelay = cep->isdntxdelout;
1204
1205         mcr.bprot = cep->b1protocol;
1206
1207         mcr.driver = cep->usrdevicename;
1208         mcr.driver_unit = cep->usrdeviceunit;
1209
1210         /* setup the shorthold data */
1211         mcr.shorthold_data.shorthold_algorithm = cep->shorthold_algorithm;
1212         mcr.shorthold_data.unitlen_time = cep->unitlength;
1213         mcr.shorthold_data.idle_time = cep->idle_time_out;              
1214         mcr.shorthold_data.earlyhup_time = cep->earlyhangup;
1215
1216         if(cep->unitlengthsrc == ULSRC_DYN)
1217                 mcr.unitlen_method = ULEN_METHOD_DYNAMIC;
1218         else
1219                 mcr.unitlen_method = ULEN_METHOD_STATIC;
1220         
1221         strcpy(mcr.dst_telno, cep->remote_phone_dialout);
1222         strcpy(mcr.src_telno, cep->local_phone_dialout);
1223         strcpy(mcr.keypad, cep->keypad);        
1224
1225         cep->last_dial_time = time(NULL);
1226         cep->direction = DIR_OUT;
1227
1228         DBGL(DL_CNST, (log(LL_DBG, "sendm_connect_req: ctrl = %d, chan = %d", cep->isdncontrollerused, cep->isdnchannelused)));
1229                 
1230         if((ret = ioctl(isdnfd, I4B_CONNECT_REQ, &mcr)) < 0)
1231         {
1232                 log(LL_ERR, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno));
1233                 error_exit(1, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno));
1234         }
1235
1236         decr_free_channels(cep->isdncontrollerused);
1237         
1238         log(LL_CHD, "%05d %s dialing out from %s to %s",
1239                 cep->cdid,
1240                 cep->name,
1241                 aliasing ? get_alias(cep->local_phone_dialout) : cep->local_phone_dialout,
1242                 aliasing ? get_alias(cep->remote_phone_dialout) : cep->remote_phone_dialout);
1243
1244         return(ret);
1245 }
1246
1247 /*---------------------------------------------------------------------------*
1248  *      send message "connect response" to kernel
1249  *---------------------------------------------------------------------------*/
1250 int
1251 sendm_connect_resp(cfg_entry_t *cep, int cdid, int response, cause_t cause)
1252 {
1253         msg_connect_resp_t mcr;
1254         int ret;
1255
1256         mcr.cdid = cdid;
1257
1258         mcr.response = response;
1259
1260         if(response == SETUP_RESP_REJECT)
1261         {
1262                 mcr.cause = cause;
1263                 DBGL(DL_DRVR, (log(LL_DBG, "sendm_connect_resp: reject, cause=0x%x", cause)));
1264         }
1265         else if(response == SETUP_RESP_ACCEPT)
1266         {
1267                 cep->direction = DIR_IN;
1268
1269                 mcr.txdelay = cep->isdntxdelin;
1270
1271                 mcr.bprot = cep->b1protocol;
1272
1273                 mcr.driver = cep->usrdevicename;
1274                 mcr.driver_unit = cep->usrdeviceunit;
1275
1276                 mcr.max_idle_time = cep->idle_time_in;
1277
1278                 DBGL(DL_DRVR, (log(LL_DBG, "sendm_connect_resp: accept")));
1279         }
1280         
1281         if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &mcr)) < 0)
1282         {
1283                 log(LL_ERR, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno));
1284                 error_exit(1, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno));
1285         }
1286         return(ret);
1287 }
1288
1289 /*---------------------------------------------------------------------------*
1290  *      send message "disconnect request" to kernel
1291  *---------------------------------------------------------------------------*/
1292 int
1293 sendm_disconnect_req(cfg_entry_t *cep, cause_t cause)
1294 {
1295         msg_discon_req_t mcr;
1296         int ret = 0;
1297
1298         mcr.cdid = cep->cdid;
1299
1300         mcr.cause = cause;
1301
1302         cep->local_disconnect = DISCON_LOC;
1303         
1304         if((ret = ioctl(isdnfd, I4B_DISCONNECT_REQ, &mcr)) < 0)
1305         {
1306                 log(LL_ERR, "sendm_disconnect_req: ioctl I4B_DISCONNECT_REQ failed: %s", strerror(errno));
1307         }
1308         else
1309         {
1310                 DBGL(DL_DRVR, (log(LL_DBG, "sendm_disconnect_req: sent DISCONNECT_REQ")));
1311         }
1312         return(ret);
1313 }
1314         
1315 /*---------------------------------------------------------------------------*
1316  *      send message "alert request" to kernel
1317  *---------------------------------------------------------------------------*/
1318 int
1319 sendm_alert_req(cfg_entry_t *cep)
1320 {
1321         msg_alert_req_t mar;
1322         int ret;
1323
1324         mar.cdid = cep->cdid;
1325         
1326         if((ret = ioctl(isdnfd, I4B_ALERT_REQ, &mar)) < 0)
1327         {
1328                 log(LL_ERR, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno));
1329                 error_exit(1, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno));
1330         }
1331         else
1332         {
1333                 DBGL(DL_DRVR, (log(LL_DBG, "sendm_alert_req: sent ALERT_REQ")));
1334         }
1335         return(ret);
1336 }
1337         
1338 /* EOF */