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