1 /* $MirOS: src/sys/netisdn/i4b_l4.c,v 1.2 2005/03/06 21:28:27 tg Exp $ */
2
3 /*
4 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *---------------------------------------------------------------------------
28 *
29 * i4b_l4.c - kernel interface to userland
30 *
31 *---------------------------------------------------------------------------*/
32
33 #include <sys/cdefs.h>
34
35 #include "isdn.h"
36 #include "irip.h"
37
38 #if NISDN > 0
39
40 #include <sys/param.h>
41 #include <sys/kernel.h>
42 #include <sys/systm.h>
43 #include <sys/conf.h>
44 #include <sys/mbuf.h>
45 #include <sys/proc.h>
46 #include <sys/fcntl.h>
47 #include <sys/socket.h>
48 #include <net/if.h>
49
50 #include <sys/timeout.h>
51
52 #ifdef __FreeBSD__
53 #include <machine/i4b_debug.h>
54 #include <machine/i4b_ioctl.h>
55 #include <machine/i4b_cause.h>
56 #else
57 #include <netisdn/i4b_debug.h>
58 #include <netisdn/i4b_ioctl.h>
59 #include <netisdn/i4b_cause.h>
60 #endif
61
62 #include <netisdn/i4b_global.h>
63 #include <netisdn/i4b_l3l4.h>
64 #include <netisdn/i4b_mbuf.h>
65 #include <netisdn/i4b_l2.h>
66 #include <netisdn/i4b_l3.h>
67 #include <netisdn/i4b_l4.h>
68
69 unsigned int i4b_l4_debug = L4_DEBUG_DEFAULT;
70
71 /*
72 * ISDNs, in userland sometimes called "controllers", but one controller
73 * may have multiple BRIs, for example daic QUAD cards attach four BRIs.
74 * An ISDN may also be a PRI (30 B channels).
75 */
76 static SLIST_HEAD(, isdn_l3_driver) isdnif_list = SLIST_HEAD_INITIALIZER(isdnif_list);
77 static int next_isdnif = 0;
78
79 /*
80 * Attach a new L3 driver instance and return its ISDN identifier
81 */
82 struct isdn_l3_driver *
isdn_attach_isdnif(const char * devname,const char * cardname,void * l1_token,const struct isdn_l3_driver_functions * l3driver,int nbch)83 isdn_attach_isdnif(const char *devname, const char *cardname,
84 void *l1_token, const struct isdn_l3_driver_functions *l3driver, int nbch)
85 {
86 int s = splnet();
87 int i, l, isdnif = next_isdnif++;
88 struct isdn_l3_driver *new_ctrl;
89
90 new_ctrl = malloc(sizeof(*new_ctrl), M_DEVBUF, 0);
91 memset(new_ctrl, 0, sizeof *new_ctrl);
92 SLIST_INSERT_HEAD(&isdnif_list, new_ctrl, l3drvq);
93 l = strlen(devname);
94 new_ctrl->devname = malloc(l + 1, M_DEVBUF, 0);
95 strlcpy(new_ctrl->devname, devname, l + 1);
96 l = strlen(cardname);
97 new_ctrl->card_name = malloc(l + 1, M_DEVBUF, 0);
98 strlcpy(new_ctrl->card_name, cardname, l + 1);
99
100 new_ctrl->l3driver = l3driver;
101 new_ctrl->l1_token = l1_token;
102 new_ctrl->isdnif = isdnif;
103 new_ctrl->tei = -1;
104 new_ctrl->dl_est = DL_DOWN;
105 new_ctrl->nbch = nbch;
106
107 new_ctrl->bch_state = malloc(nbch * sizeof(int), M_DEVBUF, 0);
108 for (i = 0; i < nbch; i++)
109 new_ctrl->bch_state[i] = BCH_ST_FREE;
110
111 splx(s);
112
113 return new_ctrl;
114 }
115
116 /*
117 * Detach a L3 driver instance
118 */
119 int
isdn_detach_isdnif(struct isdn_l3_driver * l3drv)120 isdn_detach_isdnif(struct isdn_l3_driver *l3drv)
121 {
122 struct isdn_l3_driver *sc;
123 int s = splnet();
124 int isdnif = l3drv->isdnif;
125 int max;
126
127 i4b_l4_contr_ev_ind(isdnif, 0);
128 SLIST_REMOVE(&isdnif_list, l3drv, isdn_l3_driver, l3drvq);
129
130 max = -1;
131 SLIST_FOREACH(sc, &isdnif_list, l3drvq)
132 if (sc->isdnif > max)
133 max = sc->isdnif;
134 next_isdnif = max+1;
135
136 free_all_cd_of_isdnif(isdnif);
137
138 splx(s);
139
140 free(l3drv, M_DEVBUF);
141 printf("ISDN %d detached\n", isdnif);
142 return 1;
143 }
144
145 struct isdn_l3_driver *
isdn_find_l3_by_isdnif(int isdnif)146 isdn_find_l3_by_isdnif(int isdnif)
147 {
148 struct isdn_l3_driver *sc;
149
150 SLIST_FOREACH(sc, &isdnif_list, l3drvq)
151 if (sc->isdnif == isdnif)
152 return sc;
153 return NULL;
154 }
155
isdn_count_isdnif(int * misdnif)156 int isdn_count_isdnif(int *misdnif)
157 {
158 struct isdn_l3_driver *sc;
159 int count = 0;
160 int max_isdnif = -1;
161
162 SLIST_FOREACH(sc, &isdnif_list, l3drvq) {
163 count++;
164 if (sc->isdnif > max_isdnif)
165 max_isdnif = sc->isdnif;
166 }
167
168 if (misdnif)
169 *misdnif = max_isdnif;
170
171 return count;
172 }
173
174 void *
isdn_find_softc_by_isdnif(int isdnif)175 isdn_find_softc_by_isdnif(int isdnif)
176 {
177 struct isdn_l3_driver *sc = isdn_find_l3_by_isdnif(isdnif);
178 if (sc == NULL)
179 return NULL;
180 /*
181 * XXX - hack: do not return a softc for active cards.
182 * all callers of this expecting l2_softc* results
183 * should be fixed!
184 */
185 if (sc->l3driver->N_DOWNLOAD)
186 return NULL;
187 return sc->l1_token;
188 }
189
190 /*---------------------------------------------------------------------------*
191 * daemon is attached
192 *---------------------------------------------------------------------------*/
193 void
i4b_l4_daemon_attached(void)194 i4b_l4_daemon_attached(void)
195 {
196 struct isdn_l3_driver *d;
197
198 int x = splnet();
199 SLIST_FOREACH(d, &isdnif_list, l3drvq)
200 {
201 d->l3driver->N_MGMT_COMMAND(d, CMR_DOPEN, 0);
202 }
203 splx(x);
204 }
205
206 /*---------------------------------------------------------------------------*
207 * daemon is detached
208 *---------------------------------------------------------------------------*/
209 void
i4b_l4_daemon_detached(void)210 i4b_l4_daemon_detached(void)
211 {
212 struct isdn_l3_driver *d;
213
214 int x = splnet();
215 SLIST_FOREACH(d, &isdnif_list, l3drvq)
216 {
217 d->l3driver->N_MGMT_COMMAND(d, CMR_DCLOSE, 0);
218 }
219 splx(x);
220 }
221
222 /*
223 * B-channel layer 4 drivers and their registry.
224 * (Application drivers connecting to a B-channel)
225 */
226 static int i4b_link_bchandrvr(call_desc_t *cd);
227 static void i4b_unlink_bchandrvr(call_desc_t *cd);
228 static void i4b_l4_setup_timeout(call_desc_t *cd);
229 static void i4b_idle_check_fix_unit(call_desc_t *cd);
230 static void i4b_idle_check_var_unit(call_desc_t *cd);
231 static void i4b_l4_setup_timeout_fix_unit(call_desc_t *cd);
232 static void i4b_l4_setup_timeout_var_unit(call_desc_t *cd);
233 static time_t i4b_get_idletime(call_desc_t *cd);
234
235 static int next_l4_driver_id = 0;
236
237 struct l4_driver_desc {
238 SLIST_ENTRY(l4_driver_desc) l4drvq;
239 char name[L4DRIVER_NAME_SIZ];
240 int driver_id;
241 const struct isdn_l4_driver_functions *driver;
242 int units;
243 };
244 static SLIST_HEAD(, l4_driver_desc) l4_driver_registry
245 = SLIST_HEAD_INITIALIZER(l4_driver_registry);
246
isdn_l4_driver_attach(const char * name,int units,const struct isdn_l4_driver_functions * driver)247 int isdn_l4_driver_attach(const char *name, int units, const struct isdn_l4_driver_functions *driver)
248 {
249 struct l4_driver_desc * new_driver;
250
251 new_driver = malloc(sizeof(struct l4_driver_desc), M_DEVBUF, 0);
252 memset(new_driver, 0, sizeof(struct l4_driver_desc));
253 strncpy(new_driver->name, name, L4DRIVER_NAME_SIZ);
254 new_driver->name[L4DRIVER_NAME_SIZ-1] = 0;
255 new_driver->driver_id = next_l4_driver_id++;
256 new_driver->driver = driver;
257 new_driver->units = units;
258 SLIST_INSERT_HEAD(&l4_driver_registry, new_driver, l4drvq);
259 return new_driver->driver_id;
260 }
261
isdn_l4_driver_detatch(const char * name)262 int isdn_l4_driver_detatch(const char *name)
263 {
264 /* XXX - not yet implemented */
265 return 0;
266 }
267
isdn_l4_find_driver(const char * name,int unit)268 const struct isdn_l4_driver_functions *isdn_l4_find_driver(const char *name, int unit)
269 {
270 struct l4_driver_desc * d;
271 SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
272 if (strcmp(d->name, name) == 0) {
273 return d->driver;
274 }
275 return NULL;
276 }
277
isdn_l4_find_driverid(const char * name)278 int isdn_l4_find_driverid(const char *name)
279 {
280 struct l4_driver_desc * d;
281 SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
282 if (strcmp(d->name, name) == 0) {
283 return d->driver_id;
284 }
285 return -1;
286 }
287
isdn_l4_get_driver(int driver_id,int unit)288 const struct isdn_l4_driver_functions *isdn_l4_get_driver(int driver_id, int unit)
289 {
290 struct l4_driver_desc * d;
291 SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
292 if (d->driver_id == driver_id) {
293 return d->driver;
294 }
295 return NULL;
296 }
297
298 /*---------------------------------------------------------------------------*
299 * send MSG_PDEACT_IND message to userland
300 *---------------------------------------------------------------------------*/
301 void
i4b_l4_pdeact(struct isdn_l3_driver * d,int numactive)302 i4b_l4_pdeact(struct isdn_l3_driver *d, int numactive)
303 {
304 struct mbuf *m;
305 int i;
306 call_desc_t *cd;
307
308 for(i=0; i < num_call_desc; i++)
309 {
310 if(call_desc[i].cdid != CDID_UNUSED && call_desc[i].l3drv == d)
311 {
312 cd = &call_desc[i];
313
314 if(cd->timeout_active)
315 {
316 STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
317 }
318
319 if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL)
320 {
321 (*cd->l4_driver->line_disconnected)(cd->l4_driver_softc, (void *)cd);
322 i4b_unlink_bchandrvr(cd);
323 }
324
325 if ((cd->channelid >= 0)
326 && (cd->channelid < d->nbch));
327 d->bch_state[cd->channelid] = BCH_ST_FREE;
328
329 cd->cdid = CDID_UNUSED;
330 }
331 }
332
333 if((m = i4b_Dgetmbuf(sizeof(msg_pdeact_ind_t))) != NULL)
334 {
335 msg_pdeact_ind_t *md = (msg_pdeact_ind_t *)m->m_data;
336
337 md->header.type = MSG_PDEACT_IND;
338 md->header.cdid = -1;
339
340 md->controller = d->isdnif;
341 md->numactive = numactive;
342
343 i4bputqueue_hipri(m); /* URGENT !!! */
344 }
345 }
346
347 /*---------------------------------------------------------------------------*
348 * send MSG_L12STAT_IND message to userland
349 *---------------------------------------------------------------------------*/
350 void
i4b_l4_l12stat(struct isdn_l3_driver * d,int layer,int state)351 i4b_l4_l12stat(struct isdn_l3_driver *d, int layer, int state)
352 {
353 struct mbuf *m;
354
355 if((m = i4b_Dgetmbuf(sizeof(msg_l12stat_ind_t))) != NULL)
356 {
357 msg_l12stat_ind_t *md = (msg_l12stat_ind_t *)m->m_data;
358
359 md->header.type = MSG_L12STAT_IND;
360 md->header.cdid = -1;
361
362 md->controller = d->isdnif;
363 md->layer = layer;
364 md->state = state;
365
366 i4bputqueue(m);
367 }
368 }
369
370 /*---------------------------------------------------------------------------*
371 * send MSG_TEIASG_IND message to userland
372 *---------------------------------------------------------------------------*/
373 void
i4b_l4_teiasg(struct isdn_l3_driver * d,int tei)374 i4b_l4_teiasg(struct isdn_l3_driver *d, int tei)
375 {
376 struct mbuf *m;
377
378 if((m = i4b_Dgetmbuf(sizeof(msg_teiasg_ind_t))) != NULL)
379 {
380 msg_teiasg_ind_t *md = (msg_teiasg_ind_t *)m->m_data;
381
382 md->header.type = MSG_TEIASG_IND;
383 md->header.cdid = -1;
384
385 md->controller = d->isdnif;
386 md->tei = d->tei;
387
388 i4bputqueue(m);
389 }
390 }
391
392 /*---------------------------------------------------------------------------*
393 * send MSG_DIALOUT_IND message to userland
394 *---------------------------------------------------------------------------*/
395 void
i4b_l4_dialout(int driver,int driver_unit)396 i4b_l4_dialout(int driver, int driver_unit)
397 {
398 struct mbuf *m;
399
400 if((m = i4b_Dgetmbuf(sizeof(msg_dialout_ind_t))) != NULL)
401 {
402 msg_dialout_ind_t *md = (msg_dialout_ind_t *)m->m_data;
403
404 md->header.type = MSG_DIALOUT_IND;
405 md->header.cdid = -1;
406
407 md->driver = driver;
408 md->driver_unit = driver_unit;
409
410 i4bputqueue(m);
411 }
412 }
413
414 /*---------------------------------------------------------------------------*
415 * send MSG_DIALOUTNUMBER_IND message to userland
416 *---------------------------------------------------------------------------*/
417 void
i4b_l4_dialoutnumber(int driver,int driver_unit,int cmdlen,char * cmd)418 i4b_l4_dialoutnumber(int driver, int driver_unit, int cmdlen, char *cmd)
419 {
420 struct mbuf *m;
421
422 if((m = i4b_Dgetmbuf(sizeof(msg_dialoutnumber_ind_t))) != NULL)
423 {
424 msg_dialoutnumber_ind_t *md = (msg_dialoutnumber_ind_t *)m->m_data;
425
426 md->header.type = MSG_DIALOUTNUMBER_IND;
427 md->header.cdid = -1;
428
429 md->driver = driver;
430 md->driver_unit = driver_unit;
431
432 if(cmdlen > TELNO_MAX)
433 cmdlen = TELNO_MAX;
434
435 md->cmdlen = cmdlen;
436 memcpy(md->cmd, cmd, cmdlen);
437 i4bputqueue(m);
438 }
439 }
440
441 /*---------------------------------------------------------------------------*
442 * send MSG_NEGOTIATION_COMPL message to userland
443 *---------------------------------------------------------------------------*/
444 void
i4b_l4_negcomplete(call_desc_t * cd)445 i4b_l4_negcomplete(call_desc_t *cd)
446 {
447 struct mbuf *m;
448
449 if((m = i4b_Dgetmbuf(sizeof(msg_negcomplete_ind_t))) != NULL)
450 {
451 msg_negcomplete_ind_t *md = (msg_negcomplete_ind_t *)m->m_data;
452
453 md->header.type = MSG_NEGCOMP_IND;
454 md->header.cdid = cd->cdid;
455
456 i4bputqueue(m);
457 }
458 }
459
460 /*---------------------------------------------------------------------------*
461 * send MSG_IFSTATE_CHANGED_IND message to userland
462 *---------------------------------------------------------------------------*/
463 void
i4b_l4_ifstate_changed(call_desc_t * cd,int new_state)464 i4b_l4_ifstate_changed(call_desc_t *cd, int new_state)
465 {
466 struct mbuf *m;
467
468 if((m = i4b_Dgetmbuf(sizeof(msg_ifstatechg_ind_t))) != NULL)
469 {
470 msg_ifstatechg_ind_t *md = (msg_ifstatechg_ind_t *)m->m_data;
471
472 md->header.type = MSG_IFSTATE_CHANGED_IND;
473 md->header.cdid = cd->cdid;
474 md->state = new_state;
475
476 i4bputqueue(m);
477 }
478 }
479
480 /*---------------------------------------------------------------------------*
481 * send MSG_DRVRDISC_REQ message to userland
482 *---------------------------------------------------------------------------*/
483 void
i4b_l4_drvrdisc(int cdid)484 i4b_l4_drvrdisc(int cdid)
485 {
486 struct mbuf *m;
487
488 if((m = i4b_Dgetmbuf(sizeof(msg_drvrdisc_req_t))) != NULL)
489 {
490 msg_drvrdisc_req_t *md = (msg_drvrdisc_req_t *)m->m_data;
491
492 md->header.type = MSG_DRVRDISC_REQ;
493 md->header.cdid = cdid;
494
495 i4bputqueue(m);
496 }
497 }
498
499 /*---------------------------------------------------------------------------*
500 * send MSG_ACCT_IND message to userland
501 *---------------------------------------------------------------------------*/
502 void
i4b_l4_accounting(int cdid,int accttype,int ioutbytes,int iinbytes,int ro,int ri,int outbytes,int inbytes)503 i4b_l4_accounting(int cdid, int accttype, int ioutbytes,
504 int iinbytes, int ro, int ri, int outbytes, int inbytes)
505 {
506 struct mbuf *m;
507
508 if((m = i4b_Dgetmbuf(sizeof(msg_accounting_ind_t))) != NULL)
509 {
510 msg_accounting_ind_t *md = (msg_accounting_ind_t *)m->m_data;
511
512 md->header.type = MSG_ACCT_IND;
513 md->header.cdid = cdid;
514
515 md->accttype = accttype;
516 md->ioutbytes = ioutbytes;
517 md->iinbytes = iinbytes;
518 md->outbps = ro;
519 md->inbps = ri;
520 md->outbytes = outbytes;
521 md->inbytes = inbytes;
522
523 i4bputqueue(m);
524 }
525 }
526
527 /*---------------------------------------------------------------------------*
528 * send MSG_CONNECT_IND message to userland
529 *---------------------------------------------------------------------------*/
530 void
i4b_l4_connect_ind(call_desc_t * cd)531 i4b_l4_connect_ind(call_desc_t *cd)
532 {
533 struct mbuf *m;
534
535 if((m = i4b_Dgetmbuf(sizeof(msg_connect_ind_t))) != NULL)
536 {
537 msg_connect_ind_t *mp = (msg_connect_ind_t *)m->m_data;
538
539 mp->header.type = MSG_CONNECT_IND;
540 mp->header.cdid = cd->cdid;
541
542 mp->controller = cd->isdnif;
543 mp->channel = cd->channelid;
544 mp->bprot = cd->bprot;
545
546 cd->dir = DIR_INCOMING;
547
548 if(strlen(cd->dst_telno) > 0)
549 strlcpy(mp->dst_telno, cd->dst_telno, sizeof mp->dst_telno);
550 else
551 strlcpy(mp->dst_telno, TELNO_EMPTY, sizeof mp->dst_telno);
552
553 if(strlen(cd->src_telno) > 0)
554 strlcpy(mp->src_telno, cd->src_telno, sizeof mp->src_telno);
555 else
556 strlcpy(mp->src_telno, TELNO_EMPTY, sizeof mp->src_telno);
557 mp->type_plan = cd->type_plan;
558 memcpy(mp->src_subaddr, cd->src_subaddr, sizeof(mp->src_subaddr));
559 memcpy(mp->dest_subaddr, cd->dest_subaddr, sizeof(mp->dest_subaddr));
560
561 strlcpy(mp->display, cd->display, sizeof mp->src_telno);
562
563 mp->scr_ind = cd->scr_ind;
564 mp->prs_ind = cd->prs_ind;
565
566 T400_start(cd);
567
568 i4bputqueue(m);
569 }
570 }
571
572 /*---------------------------------------------------------------------------*
573 * send MSG_CONNECT_ACTIVE_IND message to userland
574 *---------------------------------------------------------------------------*/
575 void
i4b_l4_connect_active_ind(call_desc_t * cd)576 i4b_l4_connect_active_ind(call_desc_t *cd)
577 {
578 int s;
579 struct mbuf *m;
580
581 s = splnet();
582
583 cd->last_active_time = cd->connect_time = SECOND;
584
585 NDBGL4(L4_TIMO, "last_active/connect_time=%ld", (long)cd->connect_time);
586
587 i4b_link_bchandrvr(cd);
588
589 update_controller_leds(cd->l3drv);
590
591 (*cd->l4_driver->line_connected)(cd->l4_driver_softc, cd);
592
593 i4b_l4_setup_timeout(cd);
594
595 splx(s);
596
597 if((m = i4b_Dgetmbuf(sizeof(msg_connect_active_ind_t))) != NULL)
598 {
599 msg_connect_active_ind_t *mp = (msg_connect_active_ind_t *)m->m_data;
600
601 mp->header.type = MSG_CONNECT_ACTIVE_IND;
602 mp->header.cdid = cd->cdid;
603 mp->controller = cd->isdnif;
604 mp->channel = cd->channelid;
605 if(cd->datetime[0] != '\0')
606 strlcpy(mp->datetime, cd->datetime, sizeof mp->datetime);
607 else
608 mp->datetime[0] = '\0';
609 i4bputqueue(m);
610 }
611 }
612
613 /*---------------------------------------------------------------------------*
614 * send MSG_DISCONNECT_IND message to userland
615 *---------------------------------------------------------------------------*/
616 void
i4b_l4_disconnect_ind(call_desc_t * cd)617 i4b_l4_disconnect_ind(call_desc_t *cd)
618 {
619 struct isdn_l3_driver *d;
620 struct mbuf *m;
621
622 if(cd->timeout_active)
623 STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
624
625 if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL)
626 {
627 (*cd->l4_driver->line_disconnected)(cd->l4_driver_softc, (void *)cd);
628 i4b_unlink_bchandrvr(cd);
629 }
630
631 d = cd->l3drv;
632
633 if((cd->channelid >= 0) && (cd->channelid < d->nbch))
634 {
635 d->bch_state[cd->channelid] = BCH_ST_FREE;
636 /*
637 * XXX: don't call l2 function for active cards.
638 */
639 if (d->l3driver->N_DOWNLOAD == NULL)
640 i4b_l2_channel_set_state(d, cd->channelid, BCH_ST_FREE);
641 }
642 else
643 {
644 /* no error, might be hunting call for callback */
645 NDBGL4(L4_MSG, "invalid channel %d for ISDN!", cd->channelid);
646 }
647 update_controller_leds(d);
648
649 if((m = i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t))) != NULL)
650 {
651 msg_disconnect_ind_t *mp = (msg_disconnect_ind_t *)m->m_data;
652
653 mp->header.type = MSG_DISCONNECT_IND;
654 mp->header.cdid = cd->cdid;
655 mp->cause = cd->cause_in;
656
657 i4bputqueue(m);
658 }
659 }
660
661 /*---------------------------------------------------------------------------*
662 * send MSG_IDLE_TIMEOUT_IND message to userland
663 *---------------------------------------------------------------------------*/
664 void
i4b_l4_idle_timeout_ind(call_desc_t * cd)665 i4b_l4_idle_timeout_ind(call_desc_t *cd)
666 {
667 struct mbuf *m;
668
669 if((m = i4b_Dgetmbuf(sizeof(msg_idle_timeout_ind_t))) != NULL)
670 {
671 msg_idle_timeout_ind_t *mp = (msg_idle_timeout_ind_t *)m->m_data;
672
673 mp->header.type = MSG_IDLE_TIMEOUT_IND;
674 mp->header.cdid = cd->cdid;
675
676 i4bputqueue(m);
677 }
678 }
679
680 /*---------------------------------------------------------------------------*
681 * send MSG_CHARGING_IND message to userland
682 *---------------------------------------------------------------------------*/
683 void
i4b_l4_charging_ind(call_desc_t * cd)684 i4b_l4_charging_ind(call_desc_t *cd)
685 {
686 struct mbuf *m;
687
688 if((m = i4b_Dgetmbuf(sizeof(msg_charging_ind_t))) != NULL)
689 {
690 msg_charging_ind_t *mp = (msg_charging_ind_t *)m->m_data;
691
692 mp->header.type = MSG_CHARGING_IND;
693 mp->header.cdid = cd->cdid;
694 mp->units_type = cd->units_type;
695
696 /*XXX*/ if(mp->units_type == CHARGE_CALC)
697 mp->units = cd->cunits;
698 else
699 mp->units = cd->units;
700
701 i4bputqueue(m);
702 }
703 }
704
705 /*---------------------------------------------------------------------------*
706 * send MSG_STATUS_IND message to userland
707 *---------------------------------------------------------------------------*/
708 void
i4b_l4_status_ind(call_desc_t * cd)709 i4b_l4_status_ind(call_desc_t *cd)
710 {
711 }
712
713 /*---------------------------------------------------------------------------*
714 * send MSG_ALERT_IND message to userland
715 *---------------------------------------------------------------------------*/
716 void
i4b_l4_alert_ind(call_desc_t * cd)717 i4b_l4_alert_ind(call_desc_t *cd)
718 {
719 struct mbuf *m;
720
721 if((m = i4b_Dgetmbuf(sizeof(msg_alert_ind_t))) != NULL)
722 {
723 msg_alert_ind_t *mp = (msg_alert_ind_t *)m->m_data;
724
725 mp->header.type = MSG_ALERT_IND;
726 mp->header.cdid = cd->cdid;
727
728 i4bputqueue(m);
729 }
730 }
731
732 /*---------------------------------------------------------------------------*
733 * send MSG_INFO_IND message to userland
734 *---------------------------------------------------------------------------*/
735 void
i4b_l4_info_ind(call_desc_t * cd)736 i4b_l4_info_ind(call_desc_t *cd)
737 {
738 }
739
740 /*---------------------------------------------------------------------------*
741 * send MSG_INFO_IND message to userland
742 *---------------------------------------------------------------------------*/
743 void
i4b_l4_proceeding_ind(call_desc_t * cd)744 i4b_l4_proceeding_ind(call_desc_t *cd)
745 {
746 struct mbuf *m;
747
748 if((m = i4b_Dgetmbuf(sizeof(msg_proceeding_ind_t))) != NULL)
749 {
750 msg_proceeding_ind_t *mp = (msg_proceeding_ind_t *)m->m_data;
751
752 mp->header.type = MSG_PROCEEDING_IND;
753 mp->header.cdid = cd->cdid;
754 mp->controller = cd->isdnif;
755 mp->channel = cd->channelid;
756 i4bputqueue(m);
757 }
758 }
759
760 /*---------------------------------------------------------------------------*
761 * send MSG_PACKET_IND message to userland
762 *---------------------------------------------------------------------------*/
763 void
i4b_l4_packet_ind(int driver,int driver_unit,int dir,struct mbuf * pkt)764 i4b_l4_packet_ind(int driver, int driver_unit, int dir, struct mbuf *pkt)
765 {
766 struct mbuf *m;
767 int len = pkt->m_pkthdr.len;
768 unsigned char *ip = pkt->m_data;
769
770 if((m = i4b_Dgetmbuf(sizeof(msg_packet_ind_t))) != NULL)
771 {
772 msg_packet_ind_t *mp = (msg_packet_ind_t *)m->m_data;
773
774 mp->header.type = MSG_PACKET_IND;
775 mp->header.cdid = -1;
776 mp->driver = driver;
777 mp->driver_unit = driver_unit;
778 mp->direction = dir;
779 memcpy(mp->pktdata, ip,
780 len <MAX_PACKET_LOG ? len : MAX_PACKET_LOG);
781 i4bputqueue(m);
782 }
783 }
784
785 /*---------------------------------------------------------------------------*
786 * send MSG_CONTR_EV_IND message to userland
787 *---------------------------------------------------------------------------*/
788 void
i4b_l4_contr_ev_ind(int controller,int attach)789 i4b_l4_contr_ev_ind(int controller, int attach)
790 {
791 struct mbuf *m;
792
793 if((m = i4b_Dgetmbuf(sizeof(msg_ctrl_ev_ind_t))) != NULL)
794 {
795 msg_ctrl_ev_ind_t *ev = (msg_ctrl_ev_ind_t *)m->m_data;
796
797 ev->header.type = MSG_CONTR_EV_IND;
798 ev->header.cdid = -1;
799 ev->controller = controller;
800 ev->event = attach;
801 i4bputqueue(m);
802 }
803 }
804
805 /*---------------------------------------------------------------------------*
806 * link a driver(unit) to a B-channel(controller,unit,channel)
807 *---------------------------------------------------------------------------*/
808 static int
i4b_link_bchandrvr(call_desc_t * cd)809 i4b_link_bchandrvr(call_desc_t *cd)
810 {
811 struct isdn_l3_driver *d = cd->l3drv;
812
813 if (d == NULL || d->l3driver == NULL || d->l3driver->get_linktab == NULL)
814 {
815 cd->ilt = NULL;
816 return 1;
817 }
818
819 cd->ilt = d->l3driver->get_linktab(d->l1_token,
820 cd->channelid);
821
822 cd->l4_driver = isdn_l4_get_driver(cd->bchan_driver_index, cd->bchan_driver_unit);
823 if (cd->l4_driver != NULL)
824 cd->l4_driver_softc = cd->l4_driver->get_softc(cd->bchan_driver_unit);
825 else
826 cd->l4_driver_softc = NULL;
827
828 if(cd->l4_driver == NULL || cd->l4_driver_softc == NULL || cd->ilt == NULL)
829 return(-1);
830
831 if (d->l3driver->set_l4_driver != NULL)
832 {
833 d->l3driver->set_l4_driver(d->l1_token,
834 cd->channelid, cd->l4_driver, cd->l4_driver_softc);
835 }
836
837 cd->l4_driver->set_linktab(cd->l4_driver_softc, cd->ilt);
838
839 /* activate B channel */
840
841 (*cd->ilt->bchannel_driver->bch_config)(cd->ilt->l1token, cd->ilt->channel, cd->bprot, 1);
842
843 return(0);
844 }
845
846 /*---------------------------------------------------------------------------*
847 * unlink a driver(unit) from a B-channel(controller,unit,channel)
848 *---------------------------------------------------------------------------*/
849 static void
i4b_unlink_bchandrvr(call_desc_t * cd)850 i4b_unlink_bchandrvr(call_desc_t *cd)
851 {
852 struct isdn_l3_driver *d = cd->l3drv;
853
854 /*
855 * XXX - what's this *cd manipulation for? Shouldn't we
856 * close the bchannel driver first and then just set ilt to NULL
857 * in *cd?
858 */
859 if (d == NULL || d->l3driver == NULL || d->l3driver->get_linktab == NULL)
860 {
861 cd->ilt = NULL;
862 return;
863 }
864 else
865 {
866 cd->ilt = d->l3driver->get_linktab(
867 d->l1_token, cd->channelid);
868 }
869
870 /* deactivate B channel */
871
872 (*cd->ilt->bchannel_driver->bch_config)(cd->ilt->l1token, cd->ilt->channel, cd->bprot, 0);
873 }
874
875 /*---------------------------------------------------------------------------
876
877 How shorthold mode works for OUTGOING connections
878 =================================================
879
880 |<---- unchecked-window ------->|<-checkwindow->|<-safetywindow>|
881
882 idletime_state: IST_NONCHK IST_CHECK IST_SAFE
883
884 | | | |
885 time>>+-------------------------------+---------------+---------------+-...
886 | | | |
887 | |<--idle_time-->|<--earlyhup--->|
888 |<-----------------------unitlen------------------------------->|
889
890
891 unitlen - specifies the time a charging unit lasts
892 idle_time - specifies the thime the line must be idle at the
893 end of the unit to be elected for hangup
894 earlyhup - is the beginning of a timing safety zone before the
895 next charging unit starts
896
897 The algorithm works as follows: lets assume the unitlen is 100
898 secons, idle_time is 40 seconds and earlyhup is 10 seconds.
899 The line then must be idle 50 seconds after the begin of the
900 current unit and it must then be quiet for 40 seconds. if it
901 has been quiet for this 40 seconds, the line is closed 10
902 seconds before the next charging unit starts. In case there was
903 any traffic within the idle_time, the line is not closed.
904 It does not matter whether there was any traffic between second
905 0 and second 50 or not.
906
907
908 How shorthold mode works for INCOMING connections
909 =================================================
910
911 it is just possible to specify a maximum idle time for incoming
912 connections, after this time of no activity on the line the line
913 is closed.
914
915 ---------------------------------------------------------------------------*/
916
917 static time_t
i4b_get_idletime(call_desc_t * cd)918 i4b_get_idletime(call_desc_t *cd)
919 {
920 if (cd->l4_driver->get_idletime)
921 return cd->l4_driver->get_idletime(cd->l4_driver_softc);
922 return cd->last_active_time;
923 }
924
925 /*---------------------------------------------------------------------------*
926 * B channel idle check timeout setup
927 *---------------------------------------------------------------------------*/
928 static void
i4b_l4_setup_timeout(call_desc_t * cd)929 i4b_l4_setup_timeout(call_desc_t *cd)
930 {
931 NDBGL4(L4_TIMO, "%ld: direction %d, shorthold algorithm %d",
932 (long)SECOND, cd->dir, cd->shorthold_data.shorthold_algorithm);
933
934 cd->timeout_active = 0;
935 cd->idletime_state = IST_IDLE;
936
937 if((cd->dir == DIR_INCOMING) && (cd->max_idle_time > 0))
938 {
939 /* incoming call: simple max idletime check */
940
941 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
942 cd->timeout_active = 1;
943 NDBGL4(L4_TIMO, "%ld: incoming-call, setup max_idle_time to %ld", (long)SECOND, (long)cd->max_idle_time);
944 }
945 else if((cd->dir == DIR_OUTGOING) && (cd->shorthold_data.idle_time > 0))
946 {
947 switch( cd->shorthold_data.shorthold_algorithm )
948 {
949 default: /* fall into the old fix algorithm */
950 case SHA_FIXU:
951 i4b_l4_setup_timeout_fix_unit( cd );
952 break;
953
954 case SHA_VARU:
955 i4b_l4_setup_timeout_var_unit( cd );
956 break;
957 }
958 }
959 else
960 {
961 NDBGL4(L4_TIMO, "no idle_timeout configured");
962 }
963 }
964
965 /*---------------------------------------------------------------------------*
966 * fixed unit algorithm B channel idle check timeout setup
967 *---------------------------------------------------------------------------*/
968 static void
i4b_l4_setup_timeout_fix_unit(call_desc_t * cd)969 i4b_l4_setup_timeout_fix_unit(call_desc_t *cd)
970 {
971 /* outgoing call */
972
973 if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
974 {
975 /* outgoing call: simple max idletime check */
976
977 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
978 cd->timeout_active = 1;
979 NDBGL4(L4_TIMO, "%ld: outgoing-call, setup idle_time to %ld",
980 (long)SECOND, (long)cd->shorthold_data.idle_time);
981 }
982 else if((cd->shorthold_data.unitlen_time > 0) && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
983 {
984 /* outgoing call: full shorthold mode check */
985
986 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)));
987 cd->timeout_active = 1;
988 cd->idletime_state = IST_NONCHK;
989 NDBGL4(L4_TIMO, "%ld: outgoing-call, start %ld sec nocheck window",
990 (long)SECOND, (long)(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)));
991
992 if(cd->aocd_flag == 0)
993 {
994 cd->units_type = CHARGE_CALC;
995 cd->cunits++;
996 i4b_l4_charging_ind(cd);
997 }
998 }
999 else
1000 {
1001 /* parms somehow got wrong .. */
1002
1003 NDBGL4(L4_ERR, "%ld: ERROR: idletime[%ld]+earlyhup[%ld] > unitlength[%ld]!",
1004 (long)SECOND, (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time, (long)cd->shorthold_data.unitlen_time);
1005 }
1006 }
1007
1008 /*---------------------------------------------------------------------------*
1009 * variable unit algorithm B channel idle check timeout setup
1010 *---------------------------------------------------------------------------*/
1011 static void
i4b_l4_setup_timeout_var_unit(call_desc_t * cd)1012 i4b_l4_setup_timeout_var_unit(call_desc_t *cd)
1013 {
1014 /* outgoing call: variable unit idletime check */
1015
1016 /*
1017 * start checking for an idle connect one second before the end of the unit.
1018 * The one second takes into account of rounding due to the driver only
1019 * using the seconds and not the uSeconds of the current time
1020 */
1021 cd->idletime_state = IST_CHECK; /* move directly to the checking state */
1022
1023 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz * (cd->shorthold_data.unitlen_time - 1) );
1024 cd->timeout_active = 1;
1025 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle time - setup to %ld",
1026 (long)SECOND, (long)cd->shorthold_data.unitlen_time);
1027 }
1028
1029
1030 /*---------------------------------------------------------------------------*
1031 * B channel idle check timeout function
1032 *---------------------------------------------------------------------------*/
1033 void
i4b_idle_check(call_desc_t * cd)1034 i4b_idle_check(call_desc_t *cd)
1035 {
1036 int s;
1037
1038 if(cd->cdid == CDID_UNUSED)
1039 return;
1040
1041 s = splnet();
1042
1043 /* failsafe */
1044
1045 if(cd->timeout_active == 0)
1046 {
1047 NDBGL4(L4_ERR, "ERROR: timeout_active == 0 !!!");
1048 }
1049 else
1050 {
1051 cd->timeout_active = 0;
1052 }
1053
1054 /* incoming connections, simple idletime check */
1055
1056 if(cd->dir == DIR_INCOMING)
1057 {
1058 if((i4b_get_idletime(cd) + cd->max_idle_time) <= SECOND)
1059 {
1060 struct isdn_l3_driver *d = cd->l3drv;
1061 NDBGL4(L4_TIMO, "%ld: incoming-call, line idle timeout, disconnecting!", (long)SECOND);
1062 d->l3driver->N_DISCONNECT_REQUEST(cd,
1063 (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1064 i4b_l4_idle_timeout_ind(cd);
1065 }
1066 else
1067 {
1068 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);
1069
1070 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
1071 cd->timeout_active = 1;
1072 }
1073 }
1074
1075 /* outgoing connections */
1076
1077 else if(cd->dir == DIR_OUTGOING)
1078 {
1079 switch( cd->shorthold_data.shorthold_algorithm )
1080 {
1081 case SHA_FIXU:
1082 i4b_idle_check_fix_unit( cd );
1083 break;
1084 case SHA_VARU:
1085 i4b_idle_check_var_unit( cd );
1086 break;
1087 default:
1088 NDBGL4(L4_TIMO, "%ld: bad value for shorthold_algorithm of %d",
1089 (long)SECOND, cd->shorthold_data.shorthold_algorithm);
1090 i4b_idle_check_fix_unit( cd );
1091 break;
1092 }
1093 }
1094 splx(s);
1095 }
1096
1097 /*---------------------------------------------------------------------------*
1098 * fixed unit algorithm B channel idle check timeout function
1099 *---------------------------------------------------------------------------*/
1100 static void
i4b_idle_check_fix_unit(call_desc_t * cd)1101 i4b_idle_check_fix_unit(call_desc_t *cd)
1102 {
1103 struct isdn_l3_driver *d = cd->l3drv;
1104
1105 /* simple idletime calculation */
1106
1107 if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
1108 {
1109 if((i4b_get_idletime(cd) + cd->shorthold_data.idle_time) <= SECOND)
1110 {
1111 NDBGL4(L4_TIMO, "%ld: outgoing-call-st, idle timeout, disconnecting!", (long)SECOND);
1112 d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1113 i4b_l4_idle_timeout_ind(cd);
1114 }
1115 else
1116 {
1117 NDBGL4(L4_TIMO, "%ld: outgoing-call-st, activity, last_active=%ld, max_idle=%ld",
1118 (long)SECOND, (long)i4b_get_idletime(cd), (long)cd->shorthold_data.idle_time);
1119 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
1120 cd->timeout_active = 1;
1121 }
1122 }
1123
1124 /* full shorthold mode calculation */
1125
1126 else if((cd->shorthold_data.unitlen_time > 0)
1127 && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
1128 {
1129 switch(cd->idletime_state)
1130 {
1131
1132 case IST_NONCHK: /* end of non-check time */
1133
1134 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.idle_time));
1135 cd->idletimechk_start = SECOND;
1136 cd->idletime_state = IST_CHECK;
1137 cd->timeout_active = 1;
1138 NDBGL4(L4_TIMO, "%ld: outgoing-call, idletime check window reached!", (long)SECOND);
1139 break;
1140
1141 case IST_CHECK: /* end of idletime chk */
1142 if((i4b_get_idletime(cd) > cd->idletimechk_start) &&
1143 (i4b_get_idletime(cd) <= SECOND))
1144 { /* activity detected */
1145 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.earlyhup_time));
1146 cd->timeout_active = 1;
1147 cd->idletime_state = IST_SAFE;
1148 NDBGL4(L4_TIMO, "%ld: outgoing-call, activity at %ld, wait earlyhup-end", (long)SECOND, (long)i4b_get_idletime(cd));
1149 }
1150 else
1151 { /* no activity, hangup */
1152 NDBGL4(L4_TIMO, "%ld: outgoing-call, idle timeout, last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1153 d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1154 i4b_l4_idle_timeout_ind(cd);
1155 cd->idletime_state = IST_IDLE;
1156 }
1157 break;
1158
1159 case IST_SAFE: /* end of earlyhup time */
1160
1161 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)));
1162 cd->timeout_active = 1;
1163 cd->idletime_state = IST_NONCHK;
1164
1165 if(cd->aocd_flag == 0)
1166 {
1167 cd->units_type = CHARGE_CALC;
1168 cd->cunits++;
1169 i4b_l4_charging_ind(cd);
1170 }
1171
1172 NDBGL4(L4_TIMO, "%ld: outgoing-call, earlyhup end, wait for idletime start", (long)SECOND);
1173 break;
1174
1175 default:
1176 NDBGL4(L4_ERR, "outgoing-call: invalid idletime_state value!");
1177 cd->idletime_state = IST_IDLE;
1178 break;
1179 }
1180 }
1181 }
1182
1183 /*---------------------------------------------------------------------------*
1184 * variable unit algorithm B channel idle check timeout function
1185 *---------------------------------------------------------------------------*/
1186 static void
i4b_idle_check_var_unit(call_desc_t * cd)1187 i4b_idle_check_var_unit(call_desc_t *cd)
1188 {
1189 switch(cd->idletime_state)
1190 {
1191
1192 /* see if there has been any activity within the last idle_time seconds */
1193 case IST_CHECK:
1194 if( i4b_get_idletime(cd) > (SECOND - cd->shorthold_data.idle_time))
1195 { /* activity detected */
1196 #if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
1197 cd->idle_timeout_handle =
1198 #endif
1199 /* check again in one second */
1200 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz);
1201 cd->timeout_active = 1;
1202 cd->idletime_state = IST_CHECK;
1203 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - activity at %ld, continuing", (long)SECOND, (long)i4b_get_idletime(cd));
1204 }
1205 else
1206 { /* no activity, hangup */
1207 struct isdn_l3_driver *d = cd->l3drv;
1208 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1209 d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1210 i4b_l4_idle_timeout_ind(cd);
1211 cd->idletime_state = IST_IDLE;
1212 }
1213 break;
1214
1215 default:
1216 NDBGL4(L4_ERR, "outgoing-call: var idle timeout invalid idletime_state value!");
1217 cd->idletime_state = IST_IDLE;
1218 break;
1219 }
1220 }
1221
1222 #endif /* NISDN > 0 */
1223