1 /*
2 * Copyright (c) 1997 Joerg Wunsch. All rights reserved.
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 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 *---------------------------------------------------------------------------
29 *
30 * i4b_isppp.c - isdn4bsd kernel SyncPPP driver
31 * --------------------------------------------
32 *
33 * Uses Serge Vakulenko's sppp backend (originally contributed with
34 * the "cx" driver for Cronyx's HDLC-in-hardware device). This driver
35 * is only the glue between sppp and i4b.
36 *
37 * $Id: i4b_isppp.c,v 1.18 2005/02/26 22:39:49 perry Exp $
38 *
39 * $FreeBSD$
40 *
41 * last edit-date: [Fri Jan 5 11:33:47 2001]
42 *
43 *---------------------------------------------------------------------------*/
44
45 #include <sys/cdefs.h>
46 __KERNEL_RCSID(0, "$NetBSD: i4b_isppp.c,v 1.18 2005/02/26 22:39:49 perry Exp $");
47
48 #ifndef __NetBSD__
49 #define USE_ISPPP
50 #endif
51 #include "ippp.h"
52
53 #ifndef USE_ISPPP
54
55 #ifdef __FreeBSD__
56 #include "sppp.h"
57 #endif
58
59 #ifndef __NetBSD__
60 #if NI4BISPPP == 0
61 # error "You need to define `pseudo-device sppp <N>' with options ISPPP"
62 #endif
63 #endif
64
65 #endif
66
67 #include <sys/param.h>
68 /*
69 * XXX - sys/param.h on alpha (indirectly) includes sys/signal.h, which
70 * defines sc_sp - interfering with our use of this identifier.
71 * Just undef it for now.
72 */
73 #undef sc_sp
74
75 #include <sys/systm.h>
76 #include <sys/mbuf.h>
77 #include <sys/socket.h>
78 #include <sys/errno.h>
79 #include <sys/ioccom.h>
80 #include <sys/sockio.h>
81 #include <sys/kernel.h>
82 #include <sys/protosw.h>
83 #include <sys/callout.h>
84
85 #include <net/if.h>
86 #include <net/if_types.h>
87 #include <net/netisr.h>
88 #include <net/route.h>
89
90 #include <netinet/in.h>
91 #include <netinet/in_systm.h>
92 #include <netinet/in_var.h>
93 #include <netinet/ip.h>
94
95 #include <net/slcompress.h>
96
97 #include <net/if_spppvar.h>
98
99 #if defined(__FreeBSD_version) && __FreeBSD_version >= 400008
100 #include "bpf.h"
101 #else
102 #include "bpfilter.h"
103 #endif
104 #if NBPFILTER > 0 || NBPF > 0
105 #include <sys/time.h>
106 #include <net/bpf.h>
107 #endif
108
109 #ifdef __FreeBSD__
110 #include <machine/i4b_ioctl.h>
111 #include <machine/i4b_cause.h>
112 #include <machine/i4b_debug.h>
113 #else
114 #include <netisdn/i4b_ioctl.h>
115 #include <netisdn/i4b_cause.h>
116 #include <netisdn/i4b_debug.h>
117 #endif
118
119 #include <netisdn/i4b_global.h>
120 #include <netisdn/i4b_mbuf.h>
121 #include <netisdn/i4b_l3l4.h>
122
123 #include <netisdn/i4b_l4.h>
124
125 #ifdef __FreeBSD__
126 #define ISPPP_FMT "ippp%d: "
127 #define ISPPP_ARG(sc) ((sc)->sc_if.if_unit)
128 #define PDEVSTATIC static
129
130 # if __FreeBSD_version >= 300001
131 # define CALLOUT_INIT(chan) callout_handle_init(chan)
132 # define TIMEOUT(fun, arg, chan, tick) chan = timeout(fun, arg, tick)
133 # define UNTIMEOUT(fun, arg, chan) untimeout(fun, arg, chan)
134 # define IOCTL_CMD_T u_long
135 # else
136 # define CALLOUT_INIT(chan) do {} while(0)
137 # define TIMEOUT(fun, arg, chan, tick) timeout(fun, arg, tick)
138 # define UNTIMEOUT(fun, arg, chan) untimeout(fun, arg)
139 # define IOCTL_CMD_T int
140 # endif
141
142 #elif defined __NetBSD__ || defined __OpenBSD__
143 #define ISPPP_FMT "%s: "
144 #define ISPPP_ARG(sc) ((sc)->sc_sp.pp_if.if_xname)
145 #define PDEVSTATIC /* not static */
146 #define IOCTL_CMD_T u_long
147 #else
148 # error "What system are you using?"
149 #endif
150
151 #ifdef __FreeBSD__
152 PDEVSTATIC void ipppattach(void *);
153 PSEUDO_SET(ipppattach, i4b_isppp);
154 #else
155 PDEVSTATIC void ipppattach(void);
156 #endif
157
158 #define I4BISPPPACCT 1 /* enable accounting messages */
159 #define I4BISPPPACCTINTVL 2 /* accounting msg interval in secs */
160 #define I4BISPPPDISCDEBUG 1
161
162 #define PPP_HDRLEN 4 /* 4 octetts PPP header length */
163
164 struct i4bisppp_softc {
165 struct sppp sc_sp; /* we are derived from struct sppp */
166
167 int sc_state; /* state of the interface */
168
169 #ifndef __FreeBSD__
170 int sc_unit; /* unit number for Net/OpenBSD */
171 #endif
172
173 call_desc_t *sc_cdp; /* ptr to call descriptor */
174 isdn_link_t *sc_ilt; /* B channel driver and state */
175
176 #ifdef I4BISPPPACCT
177 int sc_iinb; /* isdn driver # of inbytes */
178 int sc_ioutb; /* isdn driver # of outbytes */
179 int sc_inb; /* # of bytes rx'd */
180 int sc_outb; /* # of bytes tx'd */
181 int sc_linb; /* last # of bytes rx'd */
182 int sc_loutb; /* last # of bytes tx'd */
183 int sc_fn; /* flag, first null acct */
184 #endif
185
186 #if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
187 struct callout_handle sc_ch;
188 #endif
189
190 } i4bisppp_softc[NIPPP];
191
192 static int i4bisppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data);
193
194 #if 0
195 static void i4bisppp_send(struct ifnet *ifp);
196 #endif
197
198 static void i4bisppp_start(struct ifnet *ifp);
199
200 #if 0 /* never used ??? */
201 static void i4bisppp_timeout(void *cookie);
202 #endif
203
204 static void i4bisppp_tls(struct sppp *sp);
205 static void i4bisppp_tlf(struct sppp *sp);
206 static void i4bisppp_state_changed(struct sppp *sp, int new_state);
207 static void i4bisppp_negotiation_complete(struct sppp *sp);
208 static void i4bisppp_watchdog(struct ifnet *ifp);
209 time_t i4bisppp_idletime(void *softc);
210 static void i4bisppp_rx_data_rdy(void *softc);
211 static void i4bisppp_tx_queue_empty(void *softc);
212 static void i4bisppp_activity(void *softc, int rxtx);
213 static void i4bisppp_connect(void *softc, void *cdp);
214 static void i4bisppp_disconnect(void *softc, void *cdp);
215 static void i4bisppp_dialresponse(void *softc, int status, cause_t cause);
216 static void i4bisppp_updown(void *softc, int updown);
217 static void* i4bisppp_ret_softc(int unit);
218 static void i4bisppp_set_linktab(void *softc, isdn_link_t *ilt);
219
220 static const struct isdn_l4_driver_functions
221 ippp_l4_functions = {
222 /* L4<->B-channel functions */
223 i4bisppp_rx_data_rdy,
224 i4bisppp_tx_queue_empty,
225 i4bisppp_activity,
226 i4bisppp_connect,
227 i4bisppp_disconnect,
228 i4bisppp_dialresponse,
229 i4bisppp_updown,
230 /* Management functions */
231 i4bisppp_ret_softc,
232 i4bisppp_set_linktab,
233 i4bisppp_idletime
234 };
235
236 static int ippp_drvr_id = -1;
237
238 enum i4bisppp_states {
239 ST_IDLE, /* initialized, ready, idle */
240 ST_DIALING, /* dialling out to remote */
241 ST_CONNECTED, /* connected to remote */
242 };
243
244 /*===========================================================================*
245 * DEVICE DRIVER ROUTINES
246 *===========================================================================*/
247
248 /*---------------------------------------------------------------------------*
249 * interface attach routine at kernel boot time
250 *---------------------------------------------------------------------------*/
251 PDEVSTATIC void
252 #ifdef __FreeBSD__
253 ipppattach(void *dummy)
254 #else
255 ipppattach()
256 #endif
257 {
258 struct i4bisppp_softc *sc = i4bisppp_softc;
259 int i;
260
261 ippp_drvr_id = isdn_l4_driver_attach("ippp", NIPPP, &ippp_l4_functions);
262
263 for(i = 0; i < NIPPP; sc++, i++) {
264 sc->sc_sp.pp_if.if_softc = sc;
265 sc->sc_ilt = NULL;
266
267 #ifdef __FreeBSD__
268 sc->sc_sp.pp_if.if_name = "ippp";
269 #if defined(__FreeBSD_version) && __FreeBSD_version < 300001
270 sc->sc_sp.pp_if.if_next = NULL;
271 #endif
272 sc->sc_sp.pp_if.if_unit = i;
273 #else
274 snprintf(sc->sc_sp.pp_if.if_xname,
275 sizeof(sc->sc_sp.pp_if.if_xname), "ippp%d", i);
276 sc->sc_unit = i;
277 #endif
278
279 sc->sc_sp.pp_if.if_mtu = PP_MTU;
280
281 #ifdef __NetBSD__
282 sc->sc_sp.pp_if.if_flags = IFF_SIMPLEX | IFF_POINTOPOINT |
283 IFF_MULTICAST;
284 #else
285 sc->sc_sp.pp_if.if_flags = IFF_SIMPLEX | IFF_POINTOPOINT;
286 #endif
287
288 sc->sc_sp.pp_if.if_type = IFT_ISDNBASIC;
289 sc->sc_state = ST_IDLE;
290
291 sc->sc_sp.pp_if.if_ioctl = i4bisppp_ioctl;
292
293 /* actually initialized by sppp_attach() */
294 /* sc->sc_sp.pp_if.if_output = sppp_output; */
295
296 sc->sc_sp.pp_if.if_start = i4bisppp_start;
297
298 sc->sc_sp.pp_if.if_hdrlen = 0;
299 sc->sc_sp.pp_if.if_addrlen = 0;
300 IFQ_SET_MAXLEN(&sc->sc_sp.pp_if.if_snd, IFQ_MAXLEN);
301 IFQ_SET_READY(&sc->sc_sp.pp_if.if_snd);
302
303 sc->sc_sp.pp_if.if_ipackets = 0;
304 sc->sc_sp.pp_if.if_ierrors = 0;
305 sc->sc_sp.pp_if.if_opackets = 0;
306 sc->sc_sp.pp_if.if_oerrors = 0;
307 sc->sc_sp.pp_if.if_collisions = 0;
308 sc->sc_sp.pp_if.if_ibytes = 0;
309 sc->sc_sp.pp_if.if_obytes = 0;
310 sc->sc_sp.pp_if.if_imcasts = 0;
311 sc->sc_sp.pp_if.if_omcasts = 0;
312 sc->sc_sp.pp_if.if_iqdrops = 0;
313 sc->sc_sp.pp_if.if_noproto = 0;
314
315 #if I4BISPPPACCT
316 sc->sc_sp.pp_if.if_timer = 0;
317 sc->sc_sp.pp_if.if_watchdog = i4bisppp_watchdog;
318 sc->sc_iinb = 0;
319 sc->sc_ioutb = 0;
320 sc->sc_inb = 0;
321 sc->sc_outb = 0;
322 sc->sc_linb = 0;
323 sc->sc_loutb = 0;
324 sc->sc_fn = 1;
325 #endif
326
327 sc->sc_sp.pp_tls = i4bisppp_tls;
328 sc->sc_sp.pp_tlf = i4bisppp_tlf;
329 sc->sc_sp.pp_con = i4bisppp_negotiation_complete;
330 sc->sc_sp.pp_chg = i4bisppp_state_changed;
331 sc->sc_sp.pp_framebytes = 0; /* no framing added by hardware */
332
333 #if defined(__FreeBSD_version) && ((__FreeBSD_version >= 500009) || (410000 <= __FreeBSD_version && __FreeBSD_version < 500000))
334 /* do not call bpfattach in ether_ifattach */
335 ether_ifattach(&sc->sc_sp.pp_if, 0);
336 #else
337 if_attach(&sc->sc_sp.pp_if);
338 #endif
339 #ifndef USE_ISPPP
340 sppp_attach(&sc->sc_sp.pp_if);
341 #else
342 isppp_attach(&sc->sc_sp.pp_if);
343 #endif
344
345 #if NBPFILTER > 0 || NBPF > 0
346 #ifdef __FreeBSD__
347 bpfattach(&sc->sc_sp.pp_if, DLT_PPP, PPP_HDRLEN);
348 CALLOUT_INIT(&sc->sc_ch);
349 #endif /* __FreeBSD__ */
350 #ifdef __NetBSD__
351 bpfattach(&sc->sc_sp.pp_if, DLT_PPP, sizeof(u_int));
352 #endif
353 #endif
354 }
355 }
356
357 /*---------------------------------------------------------------------------*
358 * process ioctl
359 *---------------------------------------------------------------------------*/
360 static int
361 i4bisppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data)
362 {
363 struct i4bisppp_softc *sc = ifp->if_softc;
364 int error;
365
366 #ifndef USE_ISPPP
367 error = sppp_ioctl(&sc->sc_sp.pp_if, cmd, data);
368 #else
369 error = isppp_ioctl(&sc->sc_sp.pp_if, cmd, data);
370 #endif
371 if (error)
372 return error;
373
374 switch(cmd) {
375 case SIOCSIFFLAGS:
376 #if 0 /* never used ??? */
377 x = splnet();
378 if ((ifp->if_flags & IFF_UP) == 0)
379 UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
380 splx(x);
381 #endif
382 break;
383 }
384
385 return 0;
386 }
387
388 /*---------------------------------------------------------------------------*
389 * start output to ISDN B-channel
390 *---------------------------------------------------------------------------*/
391 static void
392 i4bisppp_start(struct ifnet *ifp)
393 {
394 struct i4bisppp_softc *sc = ifp->if_softc;
395 struct mbuf *m;
396
397 #ifndef USE_ISPPP
398 if (sppp_isempty(ifp))
399 #else
400 if (isppp_isempty(ifp))
401 #endif
402 return;
403
404 if(sc->sc_state != ST_CONNECTED)
405 return;
406
407 /*
408 * s = splnet();
409 * ifp->if_flags |= IFF_OACTIVE; // - need to clear this somewhere
410 * splx(s);
411 */
412
413 #ifndef USE_ISPPP
414 while ((m = sppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
415 #else
416 while ((m = isppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
417 #endif
418 {
419
420 #if NBPFILTER > 0 || NBPF > 0
421 #ifdef __FreeBSD__
422 if (ifp->if_bpf)
423 bpf_mtap(ifp, m);
424 #endif /* __FreeBSD__ */
425
426 #ifdef __NetBSD__
427 if (ifp->if_bpf)
428 bpf_mtap(ifp->if_bpf, m);
429 #endif
430 #endif /* NBPFILTER > 0 || NBPF > 0 */
431
432 if(IF_QFULL(sc->sc_ilt->tx_queue))
433 {
434 NDBGL4(L4_ISPDBG, "%s, tx queue full!", sc->sc_sp.pp_if.if_xname);
435 m_freem(m);
436 }
437 else
438 {
439 IF_ENQUEUE(sc->sc_ilt->tx_queue, m);
440 #if 0
441 sc->sc_sp.pp_if.if_obytes += m->m_pkthdr.len;
442 #endif
443 sc->sc_outb += m->m_pkthdr.len;
444 sc->sc_sp.pp_if.if_opackets++;
445 }
446 }
447 sc->sc_ilt->bchannel_driver->bch_tx_start(sc->sc_ilt->l1token,
448 sc->sc_ilt->channel);
449 }
450
451 #ifdef I4BISPPPACCT
452 /*---------------------------------------------------------------------------*
453 * watchdog routine
454 *---------------------------------------------------------------------------*/
455 static void
456 i4bisppp_watchdog(struct ifnet *ifp)
457 {
458 struct i4bisppp_softc *sc = ifp->if_softc;
459 bchan_statistics_t bs;
460
461 (*sc->sc_ilt->bchannel_driver->bch_stat)
462 (sc->sc_ilt->l1token, sc->sc_ilt->channel, &bs);
463
464 sc->sc_ioutb += bs.outbytes;
465 sc->sc_iinb += bs.inbytes;
466
467 if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn)
468 {
469 int ri = (sc->sc_iinb - sc->sc_linb)/I4BISPPPACCTINTVL;
470 int ro = (sc->sc_ioutb - sc->sc_loutb)/I4BISPPPACCTINTVL;
471
472 if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb))
473 sc->sc_fn = 0;
474 else
475 sc->sc_fn = 1;
476
477 sc->sc_linb = sc->sc_iinb;
478 sc->sc_loutb = sc->sc_ioutb;
479
480 if (sc->sc_cdp)
481 i4b_l4_accounting(sc->sc_cdp->cdid, ACCT_DURING,
482 sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_outb, sc->sc_inb);
483 }
484 sc->sc_sp.pp_if.if_timer = I4BISPPPACCTINTVL;
485
486 #if 0 /* old stuff, keep it around */
487 printf(ISPPP_FMT "transmit timeout\n", ISPPP_ARG(sc));
488 i4bisppp_start(ifp);
489 #endif
490 }
491 #endif /* I4BISPPPACCT */
492
493 /*
494 *===========================================================================*
495 * SyncPPP layer interface routines
496 *===========================================================================*
497 */
498
499 /*---------------------------------------------------------------------------*
500 * PPP this-layer-started action
501 *---------------------------------------------------------------------------*
502 */
503 static void
504 i4bisppp_tls(struct sppp *sp)
505 {
506 struct i4bisppp_softc *sc = sp->pp_if.if_softc;
507
508 if(sc->sc_state == ST_CONNECTED)
509 return;
510
511 i4b_l4_dialout(ippp_drvr_id, sc->sc_unit);
512 }
513
514 /*---------------------------------------------------------------------------*
515 * PPP this-layer-finished action
516 *---------------------------------------------------------------------------*
517 */
518 static void
519 i4bisppp_tlf(struct sppp *sp)
520 {
521 struct i4bisppp_softc *sc = sp->pp_if.if_softc;
522
523 if(sc->sc_state != ST_CONNECTED)
524 return;
525
526 i4b_l4_drvrdisc(sc->sc_cdp->cdid);
527 }
528 /*---------------------------------------------------------------------------*
529 * PPP interface phase change
530 *---------------------------------------------------------------------------*
531 */
532 static void
533 i4bisppp_state_changed(struct sppp *sp, int new_state)
534 {
535 struct i4bisppp_softc *sc = sp->pp_if.if_softc;
536
537 i4b_l4_ifstate_changed(sc->sc_cdp, new_state);
538 }
539
540 /*---------------------------------------------------------------------------*
541 * PPP control protocol negotiation complete (run ip-up script now)
542 *---------------------------------------------------------------------------*
543 */
544 static void
545 i4bisppp_negotiation_complete(struct sppp *sp)
546 {
547 struct i4bisppp_softc *sc = sp->pp_if.if_softc;
548
549 i4b_l4_negcomplete(sc->sc_cdp);
550 }
551
552 /*===========================================================================*
553 * ISDN INTERFACE ROUTINES
554 *===========================================================================*/
555
556 /*---------------------------------------------------------------------------*
557 * this routine is called from L4 handler at connect time
558 *---------------------------------------------------------------------------*/
559 static void
560 i4bisppp_connect(void *softc, void *cdp)
561 {
562 struct i4bisppp_softc *sc = softc;
563 struct sppp *sp = &sc->sc_sp;
564 int s = splnet();
565
566 sc->sc_cdp = (call_desc_t *)cdp;
567 sc->sc_state = ST_CONNECTED;
568
569 #if I4BISPPPACCT
570 sc->sc_iinb = 0;
571 sc->sc_ioutb = 0;
572 sc->sc_inb = 0;
573 sc->sc_outb = 0;
574 sc->sc_linb = 0;
575 sc->sc_loutb = 0;
576 sc->sc_sp.pp_if.if_timer = I4BISPPPACCTINTVL;
577 #endif
578
579 #if 0 /* never used ??? */
580 UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
581 #endif
582
583 sp->pp_up(sp); /* tell PPP we are ready */
584 #ifndef __NetBSD__
585 sp->pp_last_sent = sp->pp_last_recv = SECOND;
586 #endif
587 splx(s);
588 }
589
590 /*---------------------------------------------------------------------------*
591 * this routine is called from L4 handler at disconnect time
592 *---------------------------------------------------------------------------*/
593 static void
594 i4bisppp_disconnect(void *softc, void *cdp)
595 {
596 call_desc_t *cd = (call_desc_t *)cdp;
597 struct i4bisppp_softc *sc = softc;
598 struct sppp *sp = &sc->sc_sp;
599
600 int s = splnet();
601
602 /* new stuff to check that the active channel is being closed */
603 if (cd != sc->sc_cdp)
604 {
605 NDBGL4(L4_ISPDBG, "%s: channel%d not active!", sp->pp_if.if_xname,
606 cd->channelid);
607 splx(s);
608 return;
609 }
610
611 #if I4BISPPPACCT
612 sc->sc_sp.pp_if.if_timer = 0;
613 #endif
614
615 i4b_l4_accounting(cd->cdid, ACCT_FINAL,
616 sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb);
617
618 if (sc->sc_state == ST_CONNECTED)
619 {
620 #if 0 /* never used ??? */
621 UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
622 #endif
623 sc->sc_cdp = (call_desc_t *)0;
624 /* do thhis here because pp_down calls i4bisppp_tlf */
625 sc->sc_state = ST_IDLE;
626 sp->pp_down(sp); /* tell PPP we have hung up */
627 }
628
629 splx(s);
630 }
631
632 /*---------------------------------------------------------------------------*
633 * this routine is used to give a feedback from userland demon
634 * in case of dial problems
635 *---------------------------------------------------------------------------*/
636 static void
637 i4bisppp_dialresponse(void *softc, int status, cause_t cause)
638 {
639 struct i4bisppp_softc *sc = softc;
640
641 NDBGL4(L4_ISPDBG, "%s: status=%d, cause=%d", sc->sc_sp.pp_if.if_xname, status, cause);
642
643 if(status != DSTAT_NONE)
644 {
645 struct mbuf *m;
646
647 NDBGL4(L4_ISPDBG, "%s: clearing queues", sc->sc_sp.pp_if.if_xname);
648
649 #ifndef USE_ISPPP
650 if(!(sppp_isempty(&sc->sc_sp.pp_if)))
651 #else
652 if(!(isppp_isempty(&sc->sc_sp.pp_if)))
653 #endif
654 {
655 #ifndef USE_ISPPP
656 while((m = sppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
657 #else
658 while((m = isppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
659 #endif
660 m_freem(m);
661 }
662 }
663 }
664
665 /*---------------------------------------------------------------------------*
666 * interface up/down
667 *---------------------------------------------------------------------------*/
668 static void
669 i4bisppp_updown(void *softc, int updown)
670 {
671 /* could probably do something useful here */
672 }
673
674 /*---------------------------------------------------------------------------*
675 * this routine is called from the HSCX interrupt handler
676 * when a new frame (mbuf) has been received and was put on
677 * the rx queue.
678 *---------------------------------------------------------------------------*/
679 static void
680 i4bisppp_rx_data_rdy(void *softc)
681 {
682 struct i4bisppp_softc *sc = softc;
683 struct mbuf *m;
684 int s;
685
686 if((m = *sc->sc_ilt->rx_mbuf) == NULL)
687 return;
688
689 m->m_pkthdr.rcvif = &sc->sc_sp.pp_if;
690 m->m_pkthdr.len = m->m_len;
691
692 sc->sc_sp.pp_if.if_ipackets++;
693
694 #if I4BISPPPACCT
695 sc->sc_inb += m->m_pkthdr.len;
696 #endif
697
698 #ifdef I4BISPPPDEBUG
699 printf("i4bisppp_rx_data_ready: received packet!\n");
700 #endif
701
702 #if NBPFILTER > 0 || NBPF > 0
703
704 #ifdef __FreeBSD__
705 if(sc->sc_sp.pp_if.if_bpf)
706 bpf_mtap(&sc->sc_sp.pp_if, m);
707 #endif /* __FreeBSD__ */
708
709 #ifdef __NetBSD__
710 if(sc->sc_sp.pp_if.if_bpf)
711 bpf_mtap(sc->sc_sp.pp_if.if_bpf, m);
712 #endif
713
714 #endif /* NBPFILTER > 0 || NBPF > 0 */
715
716 s = splnet();
717
718 #ifndef USE_ISPPP
719 sppp_input(&sc->sc_sp.pp_if, m);
720 #else
721 isppp_input(&sc->sc_sp.pp_if, m);
722 #endif
723
724 splx(s);
725 }
726
727 /*---------------------------------------------------------------------------*
728 * this routine is called from the HSCX interrupt handler
729 * when the last frame has been sent out and there is no
730 * further frame (mbuf) in the tx queue.
731 *---------------------------------------------------------------------------*/
732 static void
733 i4bisppp_tx_queue_empty(void *softc)
734 {
735 struct sppp *sp = &((struct i4bisppp_softc *)softc)->sc_sp;
736 i4bisppp_start(&sp->pp_if);
737 }
738
739 /*---------------------------------------------------------------------------*
740 * THIS should be used instead of last_active_time to implement
741 * an activity timeout mechanism.
742 *
743 * Sending back the time difference unneccessarily complicates the
744 * idletime checks in i4b_l4.c. Return the largest time instead.
745 * That way the code in i4b_l4.c needs only minimal changes.
746 *---------------------------------------------------------------------------*/
747 time_t
748 i4bisppp_idletime(void *softc)
749 {
750 struct sppp *sp = &((struct i4bisppp_softc *)softc)->sc_sp;
751
752 return sp->pp_last_activity;
753 }
754
755 /*---------------------------------------------------------------------------*
756 * this routine is called from the HSCX interrupt handler
757 * each time a packet is received or transmitted. It should
758 * be used to implement an activity timeout mechanism.
759 *---------------------------------------------------------------------------*/
760 static void
761 i4bisppp_activity(void *softc, int rxtx)
762 {
763 struct i4bisppp_softc *sc = softc;
764 sc->sc_cdp->last_active_time = SECOND;
765 }
766
767 /*---------------------------------------------------------------------------*
768 * return this drivers linktab address
769 *---------------------------------------------------------------------------*/
770 static void *
771 i4bisppp_ret_softc(int unit)
772 {
773 return &i4bisppp_softc[unit];
774 }
775
776 /*---------------------------------------------------------------------------*
777 * setup the isdn_linktab for this driver
778 *---------------------------------------------------------------------------*/
779 static void
780 i4bisppp_set_linktab(void *softc, isdn_link_t *ilt)
781 {
782 struct i4bisppp_softc *sc = softc;
783 sc->sc_ilt = ilt;
784 }
785
786 /*===========================================================================*/
Cache object: 652be2fb31f4d8aa69f7c9002288de14
|