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