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