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