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 *
28 * i4b_l4.c - kernel interface to userland
29 * -----------------------------------------
30 * last edit-date: [Sun Aug 11 12:43:14 2002]
31 *
32 *---------------------------------------------------------------------------*/
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD: releng/5.4/sys/i4b/layer4/i4b_l4.c 141090 2005-01-31 23:27:04Z imp $");
36
37 #include "i4bipr.h"
38
39 #include <sys/param.h>
40 #include <sys/kernel.h>
41 #include <sys/systm.h>
42 #include <sys/mbuf.h>
43
44 #include "i4bing.h"
45 #include "i4bisppp.h"
46 #include "i4brbch.h"
47 #include "i4btel.h"
48
49 #include <machine/i4b_debug.h>
50 #include <machine/i4b_ioctl.h>
51 #include <machine/i4b_cause.h>
52
53 #include <i4b/include/i4b_global.h>
54 #include <i4b/include/i4b_l3l4.h>
55 #include <i4b/include/i4b_mbuf.h>
56 #include <i4b/layer4/i4b_l4.h>
57
58 unsigned int i4b_l4_debug = L4_DEBUG_DEFAULT;
59
60 struct ctrl_type_desc ctrl_types[CTRL_NUMTYPES] = { { NULL, NULL} };
61
62 static int i4b_link_bchandrvr(call_desc_t *cd);
63 static void i4b_unlink_bchandrvr(call_desc_t *cd);
64 static void i4b_l4_setup_timeout(call_desc_t *cd);
65 static void i4b_idle_check_fix_unit(call_desc_t *cd);
66 static void i4b_idle_check_var_unit(call_desc_t *cd);
67 static void i4b_l4_setup_timeout_fix_unit(call_desc_t *cd);
68 static void i4b_l4_setup_timeout_var_unit(call_desc_t *cd);
69 static time_t i4b_get_idletime(call_desc_t *cd);
70
71 #if NI4BISPPP > 0
72 extern time_t i4bisppp_idletime(int);
73 #endif
74
75 /*---------------------------------------------------------------------------*
76 * send MSG_PDEACT_IND message to userland
77 *---------------------------------------------------------------------------*/
78 void
79 i4b_l4_pdeact(int controller, int numactive)
80 {
81 struct mbuf *m;
82 int i;
83 call_desc_t *cd;
84
85 for(i=0; i < N_CALL_DESC; i++)
86 {
87 if((call_desc[i].cdid != CDID_UNUSED) &&
88 (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
89 (ctrl_desc[call_desc[i].controller].unit == controller))
90 {
91 cd = &call_desc[i];
92
93 if(cd->timeout_active)
94 {
95 STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
96 }
97
98 if(cd->dlt != NULL)
99 {
100 (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd);
101 i4b_unlink_bchandrvr(cd);
102 }
103
104 if((cd->channelid >= 0) & (cd->channelid < ctrl_desc[cd->controller].nbch))
105 {
106 ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE;
107 }
108
109 cd->cdid = CDID_UNUSED;
110 }
111 }
112
113 if((m = i4b_Dgetmbuf(sizeof(msg_pdeact_ind_t))) != NULL)
114 {
115 msg_pdeact_ind_t *md = (msg_pdeact_ind_t *)m->m_data;
116
117 md->header.type = MSG_PDEACT_IND;
118 md->header.cdid = -1;
119
120 md->controller = controller;
121 md->numactive = numactive;
122
123 i4bputqueue_hipri(m); /* URGENT !!! */
124 }
125 }
126
127 /*---------------------------------------------------------------------------*
128 * send MSG_L12STAT_IND message to userland
129 *---------------------------------------------------------------------------*/
130 void
131 i4b_l4_l12stat(int controller, int layer, int state)
132 {
133 struct mbuf *m;
134
135 if((m = i4b_Dgetmbuf(sizeof(msg_l12stat_ind_t))) != NULL)
136 {
137 msg_l12stat_ind_t *md = (msg_l12stat_ind_t *)m->m_data;
138
139 md->header.type = MSG_L12STAT_IND;
140 md->header.cdid = -1;
141
142 md->controller = controller;
143 md->layer = layer;
144 md->state = state;
145
146 i4bputqueue(m);
147 }
148 }
149
150 /*---------------------------------------------------------------------------*
151 * send MSG_TEIASG_IND message to userland
152 *---------------------------------------------------------------------------*/
153 void
154 i4b_l4_teiasg(int controller, int tei)
155 {
156 struct mbuf *m;
157
158 if((m = i4b_Dgetmbuf(sizeof(msg_teiasg_ind_t))) != NULL)
159 {
160 msg_teiasg_ind_t *md = (msg_teiasg_ind_t *)m->m_data;
161
162 md->header.type = MSG_TEIASG_IND;
163 md->header.cdid = -1;
164
165 md->controller = controller;
166 md->tei = ctrl_desc[controller].tei;
167
168 i4bputqueue(m);
169 }
170 }
171
172 /*---------------------------------------------------------------------------*
173 * send MSG_DIALOUT_IND message to userland
174 *---------------------------------------------------------------------------*/
175 void
176 i4b_l4_dialout(int driver, int driver_unit)
177 {
178 struct mbuf *m;
179
180 if((m = i4b_Dgetmbuf(sizeof(msg_dialout_ind_t))) != NULL)
181 {
182 msg_dialout_ind_t *md = (msg_dialout_ind_t *)m->m_data;
183
184 md->header.type = MSG_DIALOUT_IND;
185 md->header.cdid = -1;
186
187 md->driver = driver;
188 md->driver_unit = driver_unit;
189
190 i4bputqueue(m);
191 }
192 }
193
194 /*---------------------------------------------------------------------------*
195 * send MSG_DIALOUTNUMBER_IND message to userland
196 *---------------------------------------------------------------------------*/
197 void
198 i4b_l4_dialoutnumber(int driver, int driver_unit, int cmdlen, char *cmd)
199 {
200 struct mbuf *m;
201
202 if((m = i4b_Dgetmbuf(sizeof(msg_dialoutnumber_ind_t))) != NULL)
203 {
204 msg_dialoutnumber_ind_t *md = (msg_dialoutnumber_ind_t *)m->m_data;
205 int i;
206
207 md->header.type = MSG_DIALOUTNUMBER_IND;
208 md->header.cdid = -1;
209
210 md->driver = driver;
211 md->driver_unit = driver_unit;
212
213 for (i = 0; i < cmdlen; i++)
214 if (cmd[i] == '*')
215 break;
216
217 /* XXX: TELNO_MAX is _with_ tailing '\0', so max is actually TELNO_MAX - 1 */
218 md->cmdlen = (i < TELNO_MAX - 1 ? i : TELNO_MAX - 1);
219 /* skip the (first) '*' */
220 md->subaddrlen = (cmdlen - i - 1 < SUBADDR_MAX - 1 ? cmdlen - i - 1 : SUBADDR_MAX - 1);
221
222 bcopy(cmd, md->cmd, md->cmdlen);
223 if (md->subaddrlen != -1)
224 bcopy(cmd+i+1, md->subaddr, md->subaddrlen);
225
226 NDBGL4(L4_TIMO, "cmd[%d]=%s, subaddr[%d]=%s", md->cmdlen, md->cmd, md->subaddrlen, md->subaddr);
227 i4bputqueue(m);
228 }
229 }
230
231 /*---------------------------------------------------------------------------*
232 * send MSG_KEYPAD_IND message to userland
233 *---------------------------------------------------------------------------*/
234 void
235 i4b_l4_keypad(int driver, int driver_unit, int cmdlen, char *cmd)
236 {
237 struct mbuf *m;
238
239 if((m = i4b_Dgetmbuf(sizeof(msg_keypad_ind_t))) != NULL)
240 {
241 msg_keypad_ind_t *md = (msg_keypad_ind_t *)m->m_data;
242
243 md->header.type = MSG_KEYPAD_IND;
244 md->header.cdid = -1;
245
246 md->driver = driver;
247 md->driver_unit = driver_unit;
248
249 if(cmdlen > KEYPAD_MAX)
250 cmdlen = KEYPAD_MAX;
251
252 md->cmdlen = cmdlen;
253 bcopy(cmd, md->cmd, cmdlen);
254 i4bputqueue(m);
255 }
256 }
257
258 /*---------------------------------------------------------------------------*
259 * send MSG_NEGOTIATION_COMPL message to userland
260 *---------------------------------------------------------------------------*/
261 void
262 i4b_l4_negcomplete(call_desc_t *cd)
263 {
264 struct mbuf *m;
265
266 if((m = i4b_Dgetmbuf(sizeof(msg_negcomplete_ind_t))) != NULL)
267 {
268 msg_negcomplete_ind_t *md = (msg_negcomplete_ind_t *)m->m_data;
269
270 md->header.type = MSG_NEGCOMP_IND;
271 md->header.cdid = cd->cdid;
272
273 i4bputqueue(m);
274 }
275 }
276
277 /*---------------------------------------------------------------------------*
278 * send MSG_IFSTATE_CHANGED_IND message to userland
279 *---------------------------------------------------------------------------*/
280 void
281 i4b_l4_ifstate_changed(call_desc_t *cd, int new_state)
282 {
283 struct mbuf *m;
284
285 if((m = i4b_Dgetmbuf(sizeof(msg_ifstatechg_ind_t))) != NULL)
286 {
287 msg_ifstatechg_ind_t *md = (msg_ifstatechg_ind_t *)m->m_data;
288
289 md->header.type = MSG_IFSTATE_CHANGED_IND;
290 md->header.cdid = cd->cdid;
291 md->state = new_state;
292
293 i4bputqueue(m);
294 }
295 }
296
297 /*---------------------------------------------------------------------------*
298 * send MSG_DRVRDISC_REQ message to userland
299 *---------------------------------------------------------------------------*/
300 void
301 i4b_l4_drvrdisc(int driver, int driver_unit)
302 {
303 struct mbuf *m;
304
305 if((m = i4b_Dgetmbuf(sizeof(msg_drvrdisc_req_t))) != NULL)
306 {
307 msg_drvrdisc_req_t *md = (msg_drvrdisc_req_t *)m->m_data;
308
309 md->header.type = MSG_DRVRDISC_REQ;
310 md->header.cdid = -1;
311
312 md->driver = driver;
313 md->driver_unit = driver_unit;
314
315 i4bputqueue(m);
316 }
317 }
318
319 /*---------------------------------------------------------------------------*
320 * send MSG_ACCT_IND message to userland
321 *---------------------------------------------------------------------------*/
322 void
323 i4b_l4_accounting(int driver, int driver_unit, int accttype, int ioutbytes,
324 int iinbytes, int ro, int ri, int outbytes, int inbytes)
325 {
326 struct mbuf *m;
327
328 if((m = i4b_Dgetmbuf(sizeof(msg_accounting_ind_t))) != NULL)
329 {
330 msg_accounting_ind_t *md = (msg_accounting_ind_t *)m->m_data;
331
332 md->header.type = MSG_ACCT_IND;
333 md->header.cdid = -1;
334
335 md->driver = driver;
336 md->driver_unit = driver_unit;
337
338 md->accttype = accttype;
339 md->ioutbytes = ioutbytes;
340 md->iinbytes = iinbytes;
341 md->outbps = ro;
342 md->inbps = ri;
343 md->outbytes = outbytes;
344 md->inbytes = inbytes;
345
346 i4bputqueue(m);
347 }
348 }
349
350 /*---------------------------------------------------------------------------*
351 * send MSG_CONNECT_IND message to userland
352 *---------------------------------------------------------------------------*/
353 void
354 i4b_l4_connect_ind(call_desc_t *cd)
355 {
356 struct mbuf *m;
357
358 if((m = i4b_Dgetmbuf(sizeof(msg_connect_ind_t))) != NULL)
359 {
360 msg_connect_ind_t *mp = (msg_connect_ind_t *)m->m_data;
361
362 mp->header.type = MSG_CONNECT_IND;
363 mp->header.cdid = cd->cdid;
364
365 mp->controller = cd->controller;
366 mp->channel = cd->channelid;
367 mp->bprot = cd->bprot;
368 mp->bcap = cd->bcap;
369
370 cd->dir = DIR_INCOMING;
371
372 if(strlen(cd->dst_telno) > 0)
373 strcpy(mp->dst_telno, cd->dst_telno);
374 else
375 strcpy(mp->dst_telno, TELNO_EMPTY);
376
377 if(strlen(cd->dst_subaddr) > 0)
378 strcpy(mp->dst_subaddr, cd->dst_subaddr);
379 else
380 strcpy(mp->dst_subaddr, TELNO_EMPTY);
381
382 if(strlen(cd->src_telno) > 0)
383 strcpy(mp->src_telno, cd->src_telno);
384 else
385 strcpy(mp->src_telno, TELNO_EMPTY);
386
387 if(strlen(cd->src_subaddr) > 0)
388 strcpy(mp->src_subaddr, cd->src_subaddr);
389 else
390 strcpy(mp->src_subaddr, TELNO_EMPTY);
391
392 mp->src_ton = cd->src_ton;
393 mp->dst_ton = cd->dst_ton;
394
395 strcpy(mp->display, cd->display);
396
397 mp->scr_ind = cd->scr_ind;
398 mp->prs_ind = cd->prs_ind;
399
400 T400_start(cd);
401
402 i4bputqueue(m);
403 }
404 }
405
406 /*---------------------------------------------------------------------------*
407 * send MSG_CONNECT_ACTIVE_IND message to userland
408 *---------------------------------------------------------------------------*/
409 void
410 i4b_l4_connect_active_ind(call_desc_t *cd)
411 {
412 int s;
413 struct mbuf *m;
414
415 s = SPLI4B();
416
417 cd->last_active_time = cd->connect_time = SECOND;
418
419 NDBGL4(L4_TIMO, "last_active/connect_time=%ld", (long)cd->connect_time);
420
421 i4b_link_bchandrvr(cd);
422
423 (*cd->dlt->line_connected)(cd->driver_unit, (void *)cd);
424
425 i4b_l4_setup_timeout(cd);
426
427 splx(s);
428
429 if((m = i4b_Dgetmbuf(sizeof(msg_connect_active_ind_t))) != NULL)
430 {
431 msg_connect_active_ind_t *mp = (msg_connect_active_ind_t *)m->m_data;
432
433 mp->header.type = MSG_CONNECT_ACTIVE_IND;
434 mp->header.cdid = cd->cdid;
435 mp->controller = cd->controller;
436 mp->channel = cd->channelid;
437 if(cd->datetime[0] != '\0')
438 strcpy(mp->datetime, cd->datetime);
439 else
440 mp->datetime[0] = '\0';
441 i4bputqueue(m);
442 }
443 }
444
445 /*---------------------------------------------------------------------------*
446 * send MSG_DISCONNECT_IND message to userland
447 *---------------------------------------------------------------------------*/
448 void
449 i4b_l4_disconnect_ind(call_desc_t *cd)
450 {
451 struct mbuf *m;
452
453 if(cd->timeout_active)
454 STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
455
456 if(cd->dlt != NULL)
457 {
458 (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd);
459 i4b_unlink_bchandrvr(cd);
460 }
461
462 if((cd->channelid >= 0) && (cd->channelid < ctrl_desc[cd->controller].nbch))
463 {
464 ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE;
465 }
466 else
467 {
468 /* no error, might be hunting call for callback */
469 NDBGL4(L4_MSG, "channel free not valid but %d!", cd->channelid);
470 }
471
472 if((m = i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t))) != NULL)
473 {
474 msg_disconnect_ind_t *mp = (msg_disconnect_ind_t *)m->m_data;
475
476 mp->header.type = MSG_DISCONNECT_IND;
477 mp->header.cdid = cd->cdid;
478 mp->cause = cd->cause_in;
479
480 i4bputqueue(m);
481 }
482 }
483
484 /*---------------------------------------------------------------------------*
485 * send MSG_IDLE_TIMEOUT_IND message to userland
486 *---------------------------------------------------------------------------*/
487 void
488 i4b_l4_idle_timeout_ind(call_desc_t *cd)
489 {
490 struct mbuf *m;
491
492 if((m = i4b_Dgetmbuf(sizeof(msg_idle_timeout_ind_t))) != NULL)
493 {
494 msg_idle_timeout_ind_t *mp = (msg_idle_timeout_ind_t *)m->m_data;
495
496 mp->header.type = MSG_IDLE_TIMEOUT_IND;
497 mp->header.cdid = cd->cdid;
498
499 i4bputqueue(m);
500 }
501 }
502
503 /*---------------------------------------------------------------------------*
504 * send MSG_CHARGING_IND message to userland
505 *---------------------------------------------------------------------------*/
506 void
507 i4b_l4_charging_ind(call_desc_t *cd)
508 {
509 struct mbuf *m;
510
511 if((m = i4b_Dgetmbuf(sizeof(msg_charging_ind_t))) != NULL)
512 {
513 msg_charging_ind_t *mp = (msg_charging_ind_t *)m->m_data;
514
515 mp->header.type = MSG_CHARGING_IND;
516 mp->header.cdid = cd->cdid;
517 mp->units_type = cd->units_type;
518
519 /*XXX*/ if(mp->units_type == CHARGE_CALC)
520 mp->units = cd->cunits;
521 else
522 mp->units = cd->units;
523
524 i4bputqueue(m);
525 }
526 }
527
528 /*---------------------------------------------------------------------------*
529 * send MSG_STATUS_IND message to userland
530 *---------------------------------------------------------------------------*/
531 void
532 i4b_l4_status_ind(call_desc_t *cd)
533 {
534 }
535
536 /*---------------------------------------------------------------------------*
537 * send MSG_ALERT_IND message to userland
538 *---------------------------------------------------------------------------*/
539 void
540 i4b_l4_alert_ind(call_desc_t *cd)
541 {
542 struct mbuf *m;
543
544 if((m = i4b_Dgetmbuf(sizeof(msg_alert_ind_t))) != NULL)
545 {
546 msg_alert_ind_t *mp = (msg_alert_ind_t *)m->m_data;
547
548 mp->header.type = MSG_ALERT_IND;
549 mp->header.cdid = cd->cdid;
550
551 i4bputqueue(m);
552 }
553 }
554
555 /*---------------------------------------------------------------------------*
556 * send MSG_INFO_IND message to userland
557 *---------------------------------------------------------------------------*/
558 void
559 i4b_l4_info_ind(call_desc_t *cd)
560 {
561 }
562
563 /*---------------------------------------------------------------------------*
564 * send MSG_INFO_IND message to userland
565 *---------------------------------------------------------------------------*/
566 void
567 i4b_l4_proceeding_ind(call_desc_t *cd)
568 {
569 struct mbuf *m;
570
571 if((m = i4b_Dgetmbuf(sizeof(msg_proceeding_ind_t))) != NULL)
572 {
573 msg_proceeding_ind_t *mp = (msg_proceeding_ind_t *)m->m_data;
574
575 mp->header.type = MSG_PROCEEDING_IND;
576 mp->header.cdid = cd->cdid;
577 mp->controller = cd->controller;
578 mp->channel = cd->channelid;
579 i4bputqueue(m);
580 }
581 }
582
583 /*---------------------------------------------------------------------------*
584 * send MSG_PACKET_IND message to userland
585 *---------------------------------------------------------------------------*/
586 void
587 i4b_l4_packet_ind(int driver, int driver_unit, int dir, struct mbuf *pkt)
588 {
589 struct mbuf *m;
590 int len = pkt->m_pkthdr.len;
591 unsigned char *ip = pkt->m_data;
592
593 if((m = i4b_Dgetmbuf(sizeof(msg_packet_ind_t))) != NULL)
594 {
595 msg_packet_ind_t *mp = (msg_packet_ind_t *)m->m_data;
596
597 mp->header.type = MSG_PACKET_IND;
598 mp->header.cdid = -1;
599 mp->driver = driver;
600 mp->driver_unit = driver_unit;
601 mp->direction = dir;
602 memcpy(mp->pktdata, ip,
603 len <MAX_PACKET_LOG ? len : MAX_PACKET_LOG);
604 i4bputqueue(m);
605 }
606 }
607
608 /*---------------------------------------------------------------------------*
609 * link a driver(unit) to a B-channel(controller,unit,channel)
610 *---------------------------------------------------------------------------*/
611 static int
612 i4b_link_bchandrvr(call_desc_t *cd)
613 {
614 int t = ctrl_desc[cd->controller].ctrl_type;
615
616 if(t < 0 || t >= CTRL_NUMTYPES || ctrl_types[t].get_linktab == NULL)
617 {
618 cd->ilt = NULL;
619 }
620 else
621 {
622 cd->ilt = ctrl_types[t].get_linktab(
623 ctrl_desc[cd->controller].unit,
624 cd->channelid);
625 }
626
627 switch(cd->driver)
628 {
629 #if NI4BRBCH > 0
630 case BDRV_RBCH:
631 cd->dlt = rbch_ret_linktab(cd->driver_unit);
632 break;
633 #endif
634
635 #if NI4BTEL > 0
636 case BDRV_TEL:
637 cd->dlt = tel_ret_linktab(cd->driver_unit);
638 break;
639 #endif
640
641 #if NI4BIPR > 0
642 case BDRV_IPR:
643 cd->dlt = ipr_ret_linktab(cd->driver_unit);
644 break;
645 #endif
646
647 #if NI4BISPPP > 0
648 case BDRV_ISPPP:
649 cd->dlt = i4bisppp_ret_linktab(cd->driver_unit);
650 break;
651 #endif
652
653 #if NIBC > 0
654 case BDRV_IBC:
655 cd->dlt = ibc_ret_linktab(cd->driver_unit);
656 break;
657 #endif
658
659 #if NI4BING > 0
660 case BDRV_ING:
661 cd->dlt = ing_ret_linktab(cd->driver_unit);
662 break;
663 #endif
664
665 default:
666 cd->dlt = NULL;
667 break;
668 }
669
670 if(cd->dlt == NULL || cd->ilt == NULL)
671 return(-1);
672
673 if(t >= 0 && t < CTRL_NUMTYPES && ctrl_types[t].set_linktab != NULL)
674 {
675 ctrl_types[t].set_linktab(
676 ctrl_desc[cd->controller].unit,
677 cd->channelid,
678 cd->dlt);
679 }
680
681 switch(cd->driver)
682 {
683 #if NI4BRBCH > 0
684 case BDRV_RBCH:
685 rbch_set_linktab(cd->driver_unit, cd->ilt);
686 break;
687 #endif
688
689 #if NI4BTEL > 0
690 case BDRV_TEL:
691 tel_set_linktab(cd->driver_unit, cd->ilt);
692 break;
693 #endif
694
695 #if NI4BIPR > 0
696 case BDRV_IPR:
697 ipr_set_linktab(cd->driver_unit, cd->ilt);
698 break;
699 #endif
700
701 #if NI4BISPPP > 0
702 case BDRV_ISPPP:
703 i4bisppp_set_linktab(cd->driver_unit, cd->ilt);
704 break;
705 #endif
706
707 #if NIBC > 0
708 case BDRV_IBC:
709 ibc_set_linktab(cd->driver_unit, cd->ilt);
710 break;
711 #endif
712
713 #if NI4BING > 0
714 case BDRV_ING:
715 ing_set_linktab(cd->driver_unit, cd->ilt);
716 break;
717 #endif
718
719 default:
720 return(0);
721 break;
722 }
723
724 /* activate B channel */
725
726 (*cd->ilt->bch_config)(cd->ilt->unit, cd->ilt->channel, cd->bprot, 1);
727
728 return(0);
729 }
730
731 /*---------------------------------------------------------------------------*
732 * unlink a driver(unit) from a B-channel(controller,unit,channel)
733 *---------------------------------------------------------------------------*/
734 static void
735 i4b_unlink_bchandrvr(call_desc_t *cd)
736 {
737 int t = ctrl_desc[cd->controller].ctrl_type;
738
739 if(t < 0 || t >= CTRL_NUMTYPES || ctrl_types[t].get_linktab == NULL)
740 {
741 cd->ilt = NULL;
742 return;
743 }
744 else
745 {
746 cd->ilt = ctrl_types[t].get_linktab(
747 ctrl_desc[cd->controller].unit,
748 cd->channelid);
749 }
750
751 /* deactivate B channel */
752
753 (*cd->ilt->bch_config)(cd->ilt->unit, cd->ilt->channel, cd->bprot, 0);
754 }
755
756 /*---------------------------------------------------------------------------
757
758 How shorthold mode works for OUTGOING connections
759 =================================================
760
761 |<---- unchecked-window ------->|<-checkwindow->|<-safetywindow>|
762
763 idletime_state: IST_NONCHK IST_CHECK IST_SAFE
764
765 | | | |
766 time>>+-------------------------------+---------------+---------------+-...
767 | | | |
768 | |<--idle_time-->|<--earlyhup--->|
769 |<-----------------------unitlen------------------------------->|
770
771
772 unitlen - specifies the time a charging unit lasts
773 idle_time - specifies the thime the line must be idle at the
774 end of the unit to be elected for hangup
775 earlyhup - is the beginning of a timing safety zone before the
776 next charging unit starts
777
778 The algorithm works as follows: lets assume the unitlen is 100
779 secons, idle_time is 40 seconds and earlyhup is 10 seconds.
780 The line then must be idle 50 seconds after the begin of the
781 current unit and it must then be quiet for 40 seconds. if it
782 has been quiet for this 40 seconds, the line is closed 10
783 seconds before the next charging unit starts. In case there was
784 any traffic within the idle_time, the line is not closed.
785 It does not matter whether there was any traffic between second
786 0 and second 50 or not.
787
788
789 How shorthold mode works for INCOMING connections
790 =================================================
791
792 it is just possible to specify a maximum idle time for incoming
793 connections, after this time of no activity on the line the line
794 is closed.
795
796 ---------------------------------------------------------------------------*/
797
798 static time_t
799 i4b_get_idletime(call_desc_t *cd)
800 {
801 switch (cd->driver) {
802 #if NI4BISPPP > 0
803 case BDRV_ISPPP:
804 return i4bisppp_idletime(cd->driver_unit);
805 break;
806 #endif
807 default:
808 return cd->last_active_time;
809 break;
810 }
811 }
812 /*---------------------------------------------------------------------------*
813 * B channel idle check timeout setup
814 *---------------------------------------------------------------------------*/
815 static void
816 i4b_l4_setup_timeout(call_desc_t *cd)
817 {
818 NDBGL4(L4_TIMO, "%ld: direction %d, shorthold algorithm %d",
819 (long)SECOND, cd->dir, cd->shorthold_data.shorthold_algorithm);
820
821 cd->timeout_active = 0;
822 cd->idletime_state = IST_IDLE;
823
824 if((cd->dir == DIR_INCOMING) && (cd->max_idle_time > 0))
825 {
826 /* incoming call: simple max idletime check */
827
828 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
829 cd->timeout_active = 1;
830 NDBGL4(L4_TIMO, "%ld: incoming-call, setup max_idle_time to %ld", (long)SECOND, (long)cd->max_idle_time);
831 }
832 else if((cd->dir == DIR_OUTGOING) && (cd->shorthold_data.idle_time > 0))
833 {
834 switch( cd->shorthold_data.shorthold_algorithm )
835 {
836 default: /* fall into the old fix algorithm */
837 case SHA_FIXU:
838 i4b_l4_setup_timeout_fix_unit( cd );
839 break;
840
841 case SHA_VARU:
842 i4b_l4_setup_timeout_var_unit( cd );
843 break;
844 }
845 }
846 else
847 {
848 NDBGL4(L4_TIMO, "no idle_timeout configured");
849 }
850 }
851
852 /*---------------------------------------------------------------------------*
853 * fixed unit algorithm B channel idle check timeout setup
854 *---------------------------------------------------------------------------*/
855 static void
856 i4b_l4_setup_timeout_fix_unit(call_desc_t *cd)
857 {
858 /* outgoing call */
859
860 if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
861 {
862 /* outgoing call: simple max idletime check */
863
864 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
865 cd->timeout_active = 1;
866 NDBGL4(L4_TIMO, "%ld: outgoing-call, setup idle_time to %ld",
867 (long)SECOND, (long)cd->shorthold_data.idle_time);
868 }
869 else if((cd->shorthold_data.unitlen_time > 0) && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
870 {
871 /* outgoing call: full shorthold mode check */
872
873 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)));
874 cd->timeout_active = 1;
875 cd->idletime_state = IST_NONCHK;
876 NDBGL4(L4_TIMO, "%ld: outgoing-call, start %ld sec nocheck window",
877 (long)SECOND, (long)(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)));
878
879 if(cd->aocd_flag == 0)
880 {
881 cd->units_type = CHARGE_CALC;
882 cd->cunits++;
883 i4b_l4_charging_ind(cd);
884 }
885 }
886 else
887 {
888 /* parms somehow got wrong .. */
889
890 NDBGL4(L4_ERR, "%ld: ERROR: idletime[%ld]+earlyhup[%ld] > unitlength[%ld]!",
891 (long)SECOND, (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time, (long)cd->shorthold_data.unitlen_time);
892 }
893 }
894
895 /*---------------------------------------------------------------------------*
896 * variable unit algorithm B channel idle check timeout setup
897 *---------------------------------------------------------------------------*/
898 static void
899 i4b_l4_setup_timeout_var_unit(call_desc_t *cd)
900 {
901 /* outgoing call: variable unit idletime check */
902
903 /*
904 * start checking for an idle connect one second before the end of the unit.
905 * The one second takes into account of rounding due to the driver only
906 * using the seconds and not the uSeconds of the current time
907 */
908 cd->idletime_state = IST_CHECK; /* move directly to the checking state */
909
910 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz * (cd->shorthold_data.unitlen_time - 1) );
911 cd->timeout_active = 1;
912 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle time - setup to %ld",
913 (long)SECOND, (long)cd->shorthold_data.unitlen_time);
914 }
915
916
917 /*---------------------------------------------------------------------------*
918 * B channel idle check timeout function
919 *---------------------------------------------------------------------------*/
920 void
921 i4b_idle_check(call_desc_t *cd)
922 {
923 int s;
924
925 if(cd->cdid == CDID_UNUSED)
926 return;
927
928 s = SPLI4B();
929
930 /* failsafe */
931
932 if(cd->timeout_active == 0)
933 {
934 NDBGL4(L4_ERR, "ERROR: timeout_active == 0 !!!");
935 }
936 else
937 {
938 cd->timeout_active = 0;
939 }
940
941 /* incoming connections, simple idletime check */
942
943 if(cd->dir == DIR_INCOMING)
944 {
945 if((i4b_get_idletime(cd) + cd->max_idle_time) <= SECOND)
946 {
947 NDBGL4(L4_TIMO, "%ld: incoming-call, line idle timeout, disconnecting!", (long)SECOND);
948 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid,
949 (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
950 i4b_l4_idle_timeout_ind(cd);
951 }
952 else
953 {
954 NDBGL4(L4_TIMO, "%ld: incoming-call, activity, last_active=%ld, max_idle=%ld", (long)SECOND, (long)i4b_get_idletime(cd), (long)cd->max_idle_time);
955
956 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
957 cd->timeout_active = 1;
958 }
959 }
960
961 /* outgoing connections */
962
963 else if(cd->dir == DIR_OUTGOING)
964 {
965 switch( cd->shorthold_data.shorthold_algorithm )
966 {
967 case SHA_FIXU:
968 i4b_idle_check_fix_unit( cd );
969 break;
970 case SHA_VARU:
971 i4b_idle_check_var_unit( cd );
972 break;
973 default:
974 NDBGL4(L4_TIMO, "%ld: bad value for shorthold_algorithm of %d",
975 (long)SECOND, cd->shorthold_data.shorthold_algorithm);
976 i4b_idle_check_fix_unit( cd );
977 break;
978 }
979 }
980 splx(s);
981 }
982
983 /*---------------------------------------------------------------------------*
984 * fixed unit algorithm B channel idle check timeout function
985 *---------------------------------------------------------------------------*/
986 static void
987 i4b_idle_check_fix_unit(call_desc_t *cd)
988 {
989
990 /* simple idletime calculation */
991
992 if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
993 {
994 if((i4b_get_idletime(cd) + cd->shorthold_data.idle_time) <= SECOND)
995 {
996 NDBGL4(L4_TIMO, "%ld: outgoing-call-st, idle timeout, disconnecting!", (long)SECOND);
997 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
998 i4b_l4_idle_timeout_ind(cd);
999 }
1000 else
1001 {
1002 NDBGL4(L4_TIMO, "%ld: outgoing-call-st, activity, last_active=%ld, max_idle=%ld",
1003 (long)SECOND, (long)i4b_get_idletime(cd), (long)cd->shorthold_data.idle_time);
1004 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
1005 cd->timeout_active = 1;
1006 }
1007 }
1008
1009 /* full shorthold mode calculation */
1010
1011 else if((cd->shorthold_data.unitlen_time > 0)
1012 && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
1013 {
1014 switch(cd->idletime_state)
1015 {
1016
1017 case IST_NONCHK: /* end of non-check time */
1018
1019 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.idle_time));
1020 cd->idletimechk_start = SECOND;
1021 cd->idletime_state = IST_CHECK;
1022 cd->timeout_active = 1;
1023 NDBGL4(L4_TIMO, "%ld: outgoing-call, idletime check window reached!", (long)SECOND);
1024 break;
1025
1026 case IST_CHECK: /* end of idletime chk */
1027 if((i4b_get_idletime(cd) > cd->idletimechk_start) &&
1028 (i4b_get_idletime(cd) <= SECOND))
1029 { /* activity detected */
1030 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.earlyhup_time));
1031 cd->timeout_active = 1;
1032 cd->idletime_state = IST_SAFE;
1033 NDBGL4(L4_TIMO, "%ld: outgoing-call, activity at %ld, wait earlyhup-end", (long)SECOND, (long)i4b_get_idletime(cd));
1034 }
1035 else
1036 { /* no activity, hangup */
1037 NDBGL4(L4_TIMO, "%ld: outgoing-call, idle timeout, last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1038 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1039 i4b_l4_idle_timeout_ind(cd);
1040 cd->idletime_state = IST_IDLE;
1041 }
1042 break;
1043
1044 case IST_SAFE: /* end of earlyhup time */
1045
1046 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time+cd->shorthold_data.earlyhup_time)));
1047 cd->timeout_active = 1;
1048 cd->idletime_state = IST_NONCHK;
1049
1050 if(cd->aocd_flag == 0)
1051 {
1052 cd->units_type = CHARGE_CALC;
1053 cd->cunits++;
1054 i4b_l4_charging_ind(cd);
1055 }
1056
1057 NDBGL4(L4_TIMO, "%ld: outgoing-call, earlyhup end, wait for idletime start", (long)SECOND);
1058 break;
1059
1060 default:
1061 NDBGL4(L4_ERR, "outgoing-call: invalid idletime_state value!");
1062 cd->idletime_state = IST_IDLE;
1063 break;
1064 }
1065 }
1066 }
1067
1068 /*---------------------------------------------------------------------------*
1069 * variable unit algorithm B channel idle check timeout function
1070 *---------------------------------------------------------------------------*/
1071 static void
1072 i4b_idle_check_var_unit(call_desc_t *cd)
1073 {
1074 switch(cd->idletime_state)
1075 {
1076
1077 /* see if there has been any activity within the last idle_time seconds */
1078 case IST_CHECK:
1079 if( i4b_get_idletime(cd) > (SECOND - cd->shorthold_data.idle_time))
1080 { /* activity detected */
1081 /* check again in one second */
1082 cd->idle_timeout_handle =
1083 START_TIMER (cd->idle_timeout_handle, i4b_idle_check, cd, hz);
1084 cd->timeout_active = 1;
1085 cd->idletime_state = IST_CHECK;
1086 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - activity at %ld, continuing", (long)SECOND, (long)i4b_get_idletime(cd));
1087 }
1088 else
1089 { /* no activity, hangup */
1090 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1091 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1092 i4b_l4_idle_timeout_ind(cd);
1093 cd->idletime_state = IST_IDLE;
1094 }
1095 break;
1096
1097 default:
1098 NDBGL4(L4_ERR, "outgoing-call: var idle timeout invalid idletime_state value!");
1099 cd->idletime_state = IST_IDLE;
1100 break;
1101 }
1102 }
Cache object: 32a5c901a29eebd1194011746b8c3467
|