Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sys / net / i4b / driver / i4b_ipr.c
1 /*
2  * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      i4b_ipr.c - isdn4bsd IP over raw HDLC ISDN network driver
28  *      ---------------------------------------------------------
29  *
30  * $FreeBSD: src/sys/i4b/driver/i4b_ipr.c,v 1.8.2.3 2001/10/27 15:48:17 hm Exp $
31  * $DragonFly: src/sys/net/i4b/driver/i4b_ipr.c,v 1.2 2003/06/17 04:28:39 dillon Exp $
32  *
33  *      last edit-date: [Fri Oct 26 19:32:38 2001]
34  *
35  *---------------------------------------------------------------------------*
36  *
37  *      statistics counter usage (interface lifetime):
38  *      ----------------------------------------------
39  *      sc->sc_if.if_ipackets   # of received packets
40  *      sc->sc_if.if_ierrors    # of error packets not going to upper layers
41  *      sc->sc_if.if_opackets   # of transmitted packets
42  *      sc->sc_if.if_oerrors    # of error packets not being transmitted
43  *      sc->sc_if.if_collisions # of invalid ip packets after VJ decompression
44  *      sc->sc_if.if_ibytes     # of bytes coming in from the line (before VJ)
45  *      sc->sc_if.if_obytes     # of bytes going out to the line (after VJ)
46  *      sc->sc_if.if_imcasts      (currently unused)
47  *      sc->sc_if.if_omcasts    # of frames sent out of the fastqueue
48  *      sc->sc_if.if_iqdrops    # of frames dropped on input because queue full
49  *      sc->sc_if.if_noproto    # of frames dropped on output because !AF_INET
50  *
51  *      statistics counter usage (connection lifetime):
52  *      -----------------------------------------------
53  *      sc->sc_iinb             # of ISDN incoming bytes from HSCX
54  *      sc->sc_ioutb            # of ISDN outgoing bytes from HSCX
55  *      sc->sc_inb              # of incoming bytes after decompression
56  *      sc->sc_outb             # of outgoing bytes before compression
57  *
58  *---------------------------------------------------------------------------*/ 
59
60 #include "i4bipr.h"
61
62 #if NI4BIPR > 0
63
64 #ifdef __FreeBSD__
65 #include "opt_i4b.h"
66 #endif
67
68 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <sys/mbuf.h>
71 #include <sys/socket.h>
72 #include <sys/errno.h>
73
74 #if defined(__FreeBSD__)
75 #include <sys/ioccom.h>
76 #include <sys/sockio.h>
77 #ifdef IPR_VJ
78 #include <sys/malloc.h>
79 #endif
80 #else
81 #include <sys/ioctl.h>
82 #endif
83
84 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
85 #include <sys/callout.h>
86 #endif
87
88 #include <sys/kernel.h>
89
90 #include <net/if.h>
91 #include <net/if_types.h>
92 #include <net/netisr.h>
93
94 #include <netinet/in.h>
95 #include <netinet/in_systm.h>
96 #include <netinet/in_var.h>
97 #include <netinet/ip.h>
98
99 #ifdef IPR_VJ
100 #include <net/slcompress.h>       
101 #define IPR_COMPRESS IFF_LINK0  /* compress TCP traffic */
102 #define IPR_AUTOCOMP IFF_LINK1  /* auto-enable TCP compression */
103
104 /*---------------------------------------------------------------------------
105  * NOTICE: using NO separate buffer relies on the assumption, that the HSCX
106  * IRQ handler _always_ allocates a single, continuous mbuf cluster large
107  * enough to hold the maximum MTU size if the ipr interface !
108  *
109  * CAUTION: i have re-defined IPR_VJ_USEBUFFER because it makes problems
110  *          with 2 i4b's back to back running cvs over ssh, cvs simply
111  *          aborts because it gets bad data. Everything else (telnet/ftp?etc)
112  *          functions fine. 
113  *---------------------------------------------------------------------------*/
114 #define IPR_VJ_USEBUFFER        /* define to use an allocated separate buffer*/
115                                 /* undef to uncompress in the mbuf itself    */
116 #endif /* IPR_VJ */
117
118 #if defined(__FreeBSD_version) &&  __FreeBSD_version >= 400008
119 #include "bpf.h"
120 #else
121 #include "bpfilter.h"
122 #endif
123
124 #if NBPFILTER > 0 || NBPF > 0
125 #include <sys/time.h>
126 #include <net/bpf.h>
127 #endif
128
129 #ifdef __FreeBSD__
130 #include <machine/i4b_ioctl.h>
131 #include <machine/i4b_debug.h>
132 #else
133 #include <i4b/i4b_debug.h>
134 #include <i4b/i4b_ioctl.h>
135 #endif
136
137 #include <i4b/include/i4b_global.h>
138 #include <i4b/include/i4b_l3l4.h>
139
140 #include <i4b/layer4/i4b_l4.h>
141
142 #ifndef __FreeBSD__
143 #include <machine/cpu.h> /* For softnet */
144 #endif
145
146 #ifdef __FreeBSD__
147 #define IPR_FMT "ipr%d: "
148 #define IPR_ARG(sc)     ((sc)->sc_if.if_unit)
149 #define PDEVSTATIC      static
150 #elif defined(__bsdi__)
151 #define IPR_FMT "ipr%d: "
152 #define IPR_ARG(sc)     ((sc)->sc_if.if_unit)
153 #define PDEVSTATIC      /* not static */
154 #else
155 #define IPR_FMT "%s: "
156 #define IPR_ARG(sc)     ((sc)->sc_if.if_xname)
157 #define PDEVSTATIC      /* not static */
158 #endif
159
160 #define I4BIPRMTU       1500            /* regular MTU */
161 #define I4BIPRMAXMTU    2000            /* max MTU */
162 #define I4BIPRMINMTU    500             /* min MTU */
163
164 #define I4BIPRMAXQLEN   50              /* max queue length */
165
166 #define I4BIPRACCT      1               /* enable accounting messages */
167 #define I4BIPRACCTINTVL 2               /* accounting msg interval in secs */
168 #define I4BIPRADJFRXP   1               /* adjust 1st rxd packet */
169
170 /* initialized by L4 */
171
172 static drvr_link_t ipr_drvr_linktab[NI4BIPR];
173 static isdn_link_t *isdn_linktab[NI4BIPR];
174
175 struct ipr_softc {
176         struct ifnet    sc_if;          /* network-visible interface    */
177         int             sc_state;       /* state of the interface       */
178
179 #ifndef __FreeBSD__
180         int             sc_unit;        /* unit number for Net/OpenBSD  */
181 #endif
182
183         call_desc_t     *sc_cdp;        /* ptr to call descriptor       */
184         int             sc_updown;      /* soft state of interface      */
185         struct ifqueue  sc_fastq;       /* interactive traffic          */
186         int             sc_dialresp;    /* dialresponse                 */
187         int             sc_lastdialresp;/* last dialresponse            */
188         
189 #if I4BIPRACCT
190         int             sc_iinb;        /* isdn driver # of inbytes     */
191         int             sc_ioutb;       /* isdn driver # of outbytes    */
192         int             sc_inb;         /* # of bytes rx'd              */
193         int             sc_outb;        /* # of bytes tx'd              */
194         int             sc_linb;        /* last # of bytes rx'd         */
195         int             sc_loutb;       /* last # of bytes tx'd         */
196         int             sc_fn;          /* flag, first null acct        */
197 #endif  
198
199 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
200         struct callout  sc_callout;
201 #endif
202 #if defined(__FreeBSD__)
203         struct callout_handle   sc_callout;
204 #endif
205
206 #ifdef I4BIPRADJFRXP
207         int             sc_first_pkt;   /* flag, first rxd packet       */
208 #endif
209 #if IPR_LOG
210         int             sc_log_first;   /* log first n packets          */
211 #endif
212
213 #ifdef IPR_VJ
214         struct slcompress sc_compr;     /* tcp compression data         */
215 #ifdef IPR_VJ_USEBUFFER
216         u_char          *sc_cbuf;       /* tcp decompression buffer     */
217 #endif
218 #endif
219
220 } ipr_softc[NI4BIPR];
221
222 enum ipr_states {
223         ST_IDLE,                        /* initialized, ready, idle     */
224         ST_DIALING,                     /* dialling out to remote       */
225         ST_CONNECTED_W,                 /* connected to remote          */
226         ST_CONNECTED_A,                 /* connected to remote          */
227 };
228
229 #if defined(__FreeBSD__) || defined(__bsdi__)
230 #define THE_UNIT        sc->sc_if.if_unit
231 #else
232 #define THE_UNIT        sc->sc_unit
233 #endif
234
235 #if defined __FreeBSD__ || defined __NetBSD__
236 #  define IOCTL_CMD_T u_long
237 #else
238 #  define IOCTL_CMD_T int
239 #endif
240
241 #ifdef __FreeBSD__
242 PDEVSTATIC void i4biprattach(void *);
243 PSEUDO_SET(i4biprattach, i4b_ipr);
244 static int i4biprioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data);
245 #else
246 PDEVSTATIC void i4biprattach __P((void));
247 static int i4biprioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
248 #endif
249
250 #ifdef __bsdi__
251 static int iprwatchdog(int unit);
252 #else
253 static void iprwatchdog(struct ifnet *ifp);
254 #endif
255 static void ipr_init_linktab(int unit);
256 static void ipr_tx_queue_empty(int unit);
257 static int i4biproutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rtp);
258 static void iprclearqueues(struct ipr_softc *sc);
259
260 /*===========================================================================*
261  *                      DEVICE DRIVER ROUTINES
262  *===========================================================================*/
263
264 /*---------------------------------------------------------------------------*
265  *      interface attach routine at kernel boot time
266  *---------------------------------------------------------------------------*/
267 PDEVSTATIC void
268 #ifdef __FreeBSD__
269 i4biprattach(void *dummy)
270 #else
271 i4biprattach()
272 #endif
273 {
274         struct ipr_softc *sc = ipr_softc;
275         int i;
276
277 #ifdef IPR_VJ
278         printf("i4bipr: %d IP over raw HDLC ISDN device(s) attached (VJ header compression)\n", NI4BIPR);
279 #else
280         printf("i4bipr: %d IP over raw HDLC ISDN device(s) attached\n", NI4BIPR);
281 #endif
282         
283         for(i=0; i < NI4BIPR; sc++, i++)
284         {
285                 ipr_init_linktab(i);
286
287                 NDBGL4(L4_DIALST, "setting dial state to ST_IDLE");
288
289                 sc->sc_state = ST_IDLE;
290                 
291 #ifdef __FreeBSD__              
292                 sc->sc_if.if_name = "ipr";
293                 sc->sc_if.if_unit = i;
294 #elif defined(__bsdi__)
295                 sc->sc_if.if_name = "ipr";
296                 sc->sc_if.if_unit = i;
297 #else
298                 sprintf(sc->sc_if.if_xname, "ipr%d", i);
299                 sc->sc_if.if_softc = sc;
300                 sc->sc_unit = i;
301 #endif
302
303 #ifdef  IPR_VJ
304                 sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_SIMPLEX | IPR_AUTOCOMP;
305 #else
306                 sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_SIMPLEX;
307 #endif
308
309 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
310                 callout_init(&sc->sc_callout);
311 #endif
312
313                 sc->sc_if.if_mtu = I4BIPRMTU;
314                 sc->sc_if.if_type = IFT_ISDNBASIC;
315                 sc->sc_if.if_ioctl = i4biprioctl;
316                 sc->sc_if.if_output = i4biproutput;
317
318                 sc->sc_if.if_snd.ifq_maxlen = I4BIPRMAXQLEN;
319                 sc->sc_fastq.ifq_maxlen = I4BIPRMAXQLEN;
320
321 #if defined (__FreeBSD__) && __FreeBSD__ > 4
322                 mtx_init(&sc->sc_fastq.ifq_mtx, "i4b_ipr_fastq", MTX_DEF);
323 #endif          
324                 sc->sc_if.if_ipackets = 0;
325                 sc->sc_if.if_ierrors = 0;
326                 sc->sc_if.if_opackets = 0;
327                 sc->sc_if.if_oerrors = 0;
328                 sc->sc_if.if_collisions = 0;
329                 sc->sc_if.if_ibytes = 0;
330                 sc->sc_if.if_obytes = 0;
331                 sc->sc_if.if_imcasts = 0;
332                 sc->sc_if.if_omcasts = 0;
333                 sc->sc_if.if_iqdrops = 0;
334                 sc->sc_if.if_noproto = 0;
335
336 #if I4BIPRACCT
337                 sc->sc_if.if_timer = 0; 
338                 sc->sc_if.if_watchdog = iprwatchdog;    
339                 sc->sc_iinb = 0;
340                 sc->sc_ioutb = 0;
341                 sc->sc_inb = 0;
342                 sc->sc_outb = 0;
343                 sc->sc_linb = 0;
344                 sc->sc_loutb = 0;
345                 sc->sc_fn = 1;
346 #endif
347 #if IPR_LOG
348                 sc->sc_log_first = IPR_LOG;
349 #endif
350
351 #ifdef  IPR_VJ
352 #ifdef __FreeBSD__
353                 sl_compress_init(&sc->sc_compr, -1);
354 #else
355                 sl_compress_init(&sc->sc_compr);
356 #endif
357
358 #ifdef IPR_VJ_USEBUFFER
359                 if(!((sc->sc_cbuf =
360                    (u_char *)malloc(I4BIPRMAXMTU+128, M_DEVBUF, M_WAITOK))))
361                 {
362                         panic("if_ipr.c, ipr_attach: VJ malloc failed");
363                 }
364 #endif
365 #endif
366                 sc->sc_updown = SOFT_ENA;       /* soft enabled */
367                 sc->sc_dialresp = DSTAT_NONE;   /* no response */
368                 sc->sc_lastdialresp = DSTAT_NONE;
369                 
370                 if_attach(&sc->sc_if);
371
372 #if NBPFILTER > 0 || NBPF > 0
373 #ifdef __FreeBSD__
374                 bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
375 #else
376                 bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_NULL, sizeof(u_int));
377 #endif
378 #endif          
379         }
380 }
381
382 /*---------------------------------------------------------------------------*
383  *      output a packet to the ISDN B-channel
384  *---------------------------------------------------------------------------*/
385 static int
386 i4biproutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
387          struct rtentry *rtp)
388 {
389         struct ipr_softc *sc;
390         int unit;
391         int s;
392         struct ifqueue *ifq;
393         struct ip *ip;
394         
395         s = SPLI4B();
396
397 #if defined(__FreeBSD__) || defined(__bsdi__)
398         unit = ifp->if_unit;
399         sc = &ipr_softc[unit];
400 #else
401         sc = ifp->if_softc;
402         unit = sc->sc_unit;
403 #endif
404
405         /* check for IP */
406         
407         if(dst->sa_family != AF_INET)
408         {
409                 printf(IPR_FMT "af%d not supported\n", IPR_ARG(sc), dst->sa_family);
410                 m_freem(m);
411                 splx(s);
412                 sc->sc_if.if_noproto++;
413                 sc->sc_if.if_oerrors++;
414                 return(EAFNOSUPPORT);
415         }
416
417         /* check interface state = UP */
418         
419         if(!(ifp->if_flags & IFF_UP))
420         {
421                 NDBGL4(L4_IPRDBG, "ipr%d: interface is DOWN!", unit);
422                 m_freem(m);
423                 splx(s);
424                 sc->sc_if.if_oerrors++;
425                 return(ENETDOWN);
426         }
427
428         /* dial if necessary */
429         
430         if(sc->sc_state == ST_IDLE || sc->sc_state == ST_DIALING)
431         {
432
433 #ifdef NOTDEF
434                 switch(sc->sc_dialresp)
435                 {
436                         case DSTAT_TFAIL:       /* transient failure */
437                                 NDBGL4(L4_IPRDBG, "ipr%d: transient dial failure!", unit);
438                                 m_freem(m);
439                                 iprclearqueues(sc);
440                                 sc->sc_dialresp = DSTAT_NONE;
441                                 splx(s);
442                                 sc->sc_if.if_oerrors++;
443                                 return(ENETUNREACH);
444                                 break;
445
446                         case DSTAT_PFAIL:       /* permanent failure */
447                                 NDBGL4(L4_IPRDBG, "ipr%d: permanent dial failure!", unit);
448                                 m_freem(m);
449                                 iprclearqueues(sc);
450                                 sc->sc_dialresp = DSTAT_NONE;
451                                 splx(s);
452                                 sc->sc_if.if_oerrors++;
453                                 return(EHOSTUNREACH);                           
454                                 break;
455
456                         case DSTAT_INONLY:      /* no dialout allowed*/
457                                 NDBGL4(L4_IPRDBG, "ipr%d: dialout not allowed failure!", unit);
458                                 m_freem(m);
459                                 iprclearqueues(sc);
460                                 sc->sc_dialresp = DSTAT_NONE;
461                                 splx(s);
462                                 sc->sc_if.if_oerrors++;
463                                 return(EHOSTUNREACH);                           
464                                 break;
465                 }
466 #endif
467
468                 NDBGL4(L4_IPRDBG, "ipr%d: send dial request message!", unit);
469                 NDBGL4(L4_DIALST, "ipr%d: setting dial state to ST_DIALING", unit);
470                 i4b_l4_dialout(BDRV_IPR, unit);
471                 sc->sc_state = ST_DIALING;
472         }
473
474 #if IPR_LOG
475         if(sc->sc_log_first > 0)
476         {
477                 --(sc->sc_log_first);
478                 i4b_l4_packet_ind(BDRV_IPR, unit, 1, m );
479         }
480 #endif
481
482         /* update access time */
483         
484         microtime(&sc->sc_if.if_lastchange);
485
486         /*
487          * check, if type of service indicates interactive, i.e. telnet,
488          * traffic. in case it is interactive, put it into the fast queue,
489          * else (i.e. ftp traffic) put it into the "normal" queue
490          */
491
492         ip = mtod(m, struct ip *);              /* get ptr to ip header */
493          
494         if(ip->ip_tos & IPTOS_LOWDELAY)
495                 ifq = &sc->sc_fastq;
496         else
497                 ifq = &sc->sc_if.if_snd;
498
499         /* check for space in choosen send queue */
500         
501 #if defined (__FreeBSD__) && __FreeBSD__ > 4
502         if(! IF_HANDOFF(ifq, m, NULL))
503         {
504                 NDBGL4(L4_IPRDBG, "ipr%d: send queue full!", unit);
505                 splx(s);
506                 sc->sc_if.if_oerrors++;
507                 return(ENOBUFS);
508         }
509 #else
510         if(IF_QFULL(ifq))
511         {
512                 NDBGL4(L4_IPRDBG, "ipr%d: send queue full!", unit);
513                 IF_DROP(ifq);
514                 m_freem(m);
515                 splx(s);
516                 sc->sc_if.if_oerrors++;
517                 return(ENOBUFS);
518         }       
519
520         IF_ENQUEUE(ifq, m);
521 #endif
522         
523         NDBGL4(L4_IPRDBG, "ipr%d: add packet to send queue!", unit);
524         
525         ipr_tx_queue_empty(unit);
526
527         splx(s);
528
529         return (0);
530 }
531
532 /*---------------------------------------------------------------------------*
533  *      process ioctl
534  *---------------------------------------------------------------------------*/
535 #ifdef __FreeBSD__
536 static int
537 i4biprioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data)
538 #else
539 static int
540 i4biprioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
541 #endif
542 {
543 #if defined(__FreeBSD__) || defined(__bsdi__)
544         struct ipr_softc *sc = &ipr_softc[ifp->if_unit];
545 #else
546         struct ipr_softc *sc = ifp->if_softc;
547 #endif
548
549         struct ifreq *ifr = (struct ifreq *)data;
550         struct ifaddr *ifa = (struct ifaddr *)data;
551         int s;
552         int error = 0;
553
554         s = SPLI4B();
555         
556         switch (cmd)
557         {
558                 case SIOCAIFADDR:       /* add interface address */
559                 case SIOCSIFADDR:       /* set interface address */
560                 case SIOCSIFDSTADDR:    /* set interface destination address */
561                         if(ifa->ifa_addr->sa_family != AF_INET)
562                                 error = EAFNOSUPPORT;
563                         else
564                                 sc->sc_if.if_flags |= IFF_UP;
565                         microtime(&sc->sc_if.if_lastchange);
566                         break;
567
568                 case SIOCSIFFLAGS:      /* set interface flags */
569                         if(!(ifr->ifr_flags & IFF_UP))
570                         {
571                                 if(sc->sc_if.if_flags & IFF_RUNNING)
572                                 {
573                                         /* disconnect ISDN line */
574 #if defined(__FreeBSD__) || defined(__bsdi__)
575                                         i4b_l4_drvrdisc(BDRV_IPR, ifp->if_unit);
576 #else
577                                         i4b_l4_drvrdisc(BDRV_IPR, sc->sc_unit);
578 #endif
579                                         sc->sc_if.if_flags &= ~IFF_RUNNING;
580                                 }
581
582                                 sc->sc_state = ST_IDLE;
583
584                                 /* empty queues */
585
586                                 iprclearqueues(sc);
587                         }
588
589                         if(ifr->ifr_flags & IFF_DEBUG)
590                         {
591                                 /* enable debug messages */
592                         }
593                         
594                         microtime(&sc->sc_if.if_lastchange);
595                         break;
596
597 #if !defined(__OpenBSD__)                       
598                 case SIOCSIFMTU:        /* set interface MTU */
599                         if(ifr->ifr_mtu > I4BIPRMAXMTU)
600                                 error = EINVAL;
601                         else if(ifr->ifr_mtu < I4BIPRMINMTU)
602                                 error = EINVAL;
603                         else
604                         {
605                                 ifp->if_mtu = ifr->ifr_mtu;
606                                 microtime(&sc->sc_if.if_lastchange);
607                         }
608                         break;
609 #endif /* __OPENBSD__ */
610
611 #if 0
612         /* not needed for FreeBSD, done in sl_compress_init() (-hm) */
613         
614                         /* need to add an ioctl:        set VJ max slot ID
615                          * #define IPRIOCSMAXCID        _IOW('I', XXX, int)
616                          */
617 #ifdef IPR_VJ
618                 case IPRIOCSMAXCID:
619                         {
620                         struct proc *p = curproc;       /* XXX */
621
622 #if defined(__FreeBSD_version) && __FreeBSD_version >= 400005
623                         if((error = suser(p)) != 0)
624 #else
625                         if((error = suser(p->p_ucred, &p->p_acflag)) != 0)
626 #endif
627                                 return (error);
628                         sl_compress_setup(sc->sc_compr, *(int *)data);
629                         }
630                         break;
631 #endif
632 #endif
633                 default:
634                         error = EINVAL;
635                         break;
636         }
637
638         splx(s);
639
640         return(error);
641 }
642
643 /*---------------------------------------------------------------------------*
644  *      clear the interface's send queues
645  *---------------------------------------------------------------------------*/
646 static void
647 iprclearqueues(struct ipr_softc *sc)
648 {
649         int x;
650
651 #if defined (__FreeBSD__) && __FreeBSD__ > 4
652         x = splimp();
653         IF_DRAIN(&sc->sc_fastq);
654         IF_DRAIN(&sc->sc_if.if_snd);
655         splx(x);
656 #else
657         struct mbuf *m;
658
659         for(;;)
660         {
661                 x = splimp();
662                 IF_DEQUEUE(&sc->sc_fastq, m);
663                 splx(x);
664                 if(m)
665                         m_freem(m);
666                 else
667                         break;
668         }
669
670         for(;;)
671         {
672                 x = splimp();
673                 IF_DEQUEUE(&sc->sc_if.if_snd, m);
674                 splx(x);
675                 if(m)
676                         m_freem(m);
677                 else
678                         break;
679         }
680 #endif
681 }
682         
683 #if I4BIPRACCT
684 /*---------------------------------------------------------------------------*
685  *      watchdog routine
686  *---------------------------------------------------------------------------*/
687 #ifdef __bsdi__
688 static int
689 iprwatchdog(int unit)
690 {
691 #else
692 static void
693 iprwatchdog(struct ifnet *ifp)
694 {
695 #endif
696 #ifdef __FreeBSD__
697         int unit = ifp->if_unit;
698         struct ipr_softc *sc = &ipr_softc[unit];
699 #elif defined(__bsdi__)
700         struct ipr_softc *sc = &ipr_softc[unit];
701         struct ifnet *ifp = &ipr_softc[unit].sc_if;
702 #else
703         struct ipr_softc *sc = ifp->if_softc;
704         int unit = sc->sc_unit;
705 #endif
706         bchan_statistics_t bs;
707         
708         /* get # of bytes in and out from the HSCX driver */ 
709         
710         (*isdn_linktab[unit]->bch_stat)
711                 (isdn_linktab[unit]->unit, isdn_linktab[unit]->channel, &bs);
712
713         sc->sc_ioutb += bs.outbytes;
714         sc->sc_iinb += bs.inbytes;
715         
716         if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn) 
717         {
718                 int ri = (sc->sc_iinb - sc->sc_linb)/I4BIPRACCTINTVL;
719                 int ro = (sc->sc_ioutb - sc->sc_loutb)/I4BIPRACCTINTVL;
720
721                 if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb))
722                         sc->sc_fn = 0;
723                 else
724                         sc->sc_fn = 1;
725                         
726                 sc->sc_linb = sc->sc_iinb;
727                 sc->sc_loutb = sc->sc_ioutb;
728
729                 i4b_l4_accounting(BDRV_IPR, unit, ACCT_DURING,
730                          sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_outb, sc->sc_inb);
731         }
732         sc->sc_if.if_timer = I4BIPRACCTINTVL;   
733 #ifdef __bsdi__
734         return 0;
735 #endif
736 }
737 #endif /* I4BIPRACCT */
738
739 /*===========================================================================*
740  *                      ISDN INTERFACE ROUTINES
741  *===========================================================================*/
742
743 /*---------------------------------------------------------------------------*
744  *      start transmitting after connect
745  *---------------------------------------------------------------------------*/
746 static void
747 i4bipr_connect_startio(struct ipr_softc *sc)
748 {
749         int s = SPLI4B();
750         
751         if(sc->sc_state == ST_CONNECTED_W)
752         {
753                 sc->sc_state = ST_CONNECTED_A;
754                 ipr_tx_queue_empty(THE_UNIT);
755         }
756
757         splx(s);
758 }
759  
760 /*---------------------------------------------------------------------------*
761  *      this routine is called from L4 handler at connect time
762  *---------------------------------------------------------------------------*/
763 static void
764 ipr_connect(int unit, void *cdp)
765 {
766         struct ipr_softc *sc = &ipr_softc[unit];
767         int s;
768
769         sc->sc_cdp = (call_desc_t *)cdp;
770
771         s = SPLI4B();
772
773         NDBGL4(L4_DIALST, "ipr%d: setting dial state to ST_CONNECTED", unit);
774
775         sc->sc_if.if_flags |= IFF_RUNNING;
776         sc->sc_state = ST_CONNECTED_W;
777
778         sc->sc_dialresp = DSTAT_NONE;
779         sc->sc_lastdialresp = DSTAT_NONE;       
780         
781 #if I4BIPRACCT
782         sc->sc_iinb = 0;
783         sc->sc_ioutb = 0;
784         sc->sc_inb = 0;
785         sc->sc_outb = 0;
786         sc->sc_linb = 0;
787         sc->sc_loutb = 0;
788         sc->sc_if.if_timer = I4BIPRACCTINTVL;
789 #endif
790
791 #ifdef I4BIPRADJFRXP
792         sc->sc_first_pkt = 1;
793 #endif
794
795         /*
796          * Sometimes ISDN B-channels are switched thru asymmetic. This
797          * means that under such circumstances B-channel data (the first
798          * three packets of a TCP connection in my case) may get lost,
799          * causing a large delay until the connection is started.
800          * When the sending of the very first packet of a TCP connection
801          * is delayed for a to be empirically determined delay (close
802          * to a second in my case) those packets go thru and the TCP
803          * connection comes up "almost" immediately (-hm).
804          */
805
806         if(sc->sc_cdp->isdntxdelay > 0)
807         {
808                 int delay;
809
810                 if (hz == 100) {
811                         delay = sc->sc_cdp->isdntxdelay;        /* avoid any rounding */
812                 } else {
813                         delay = sc->sc_cdp->isdntxdelay*hz;
814                         delay /= 100;
815                 }
816
817                 START_TIMER(sc->sc_callout, (TIMEOUT_FUNC_T)i4bipr_connect_startio, (void *)sc,  delay);
818         }
819         else
820         {
821                 sc->sc_state = ST_CONNECTED_A;
822                 ipr_tx_queue_empty(unit);
823         }
824
825         splx(s);
826
827         /* we don't need any negotiation - pass event back right now */
828         i4b_l4_negcomplete(sc->sc_cdp);
829 }
830         
831 /*---------------------------------------------------------------------------*
832  *      this routine is called from L4 handler at disconnect time
833  *---------------------------------------------------------------------------*/
834 static void
835 ipr_disconnect(int unit, void *cdp)
836 {
837         call_desc_t *cd = (call_desc_t *)cdp;
838         struct ipr_softc *sc = &ipr_softc[unit];
839
840         /* new stuff to check that the active channel is being closed */
841
842         if (cd != sc->sc_cdp)
843         {
844                 NDBGL4(L4_IPRDBG, "ipr%d: channel %d not active",
845                                 cd->driver_unit, cd->channelid);
846                 return;
847         }
848
849 #if I4BIPRACCT
850         sc->sc_if.if_timer = 0;
851 #endif
852 #if IPR_LOG
853         /* show next IPR_LOG packets again */
854         sc->sc_log_first = IPR_LOG;
855 #endif
856
857         i4b_l4_accounting(BDRV_IPR, cd->driver_unit, ACCT_FINAL,
858                  sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb);
859         
860         sc->sc_cdp = (call_desc_t *)0;  
861
862         NDBGL4(L4_DIALST, "setting dial state to ST_IDLE");
863
864         sc->sc_dialresp = DSTAT_NONE;
865         sc->sc_lastdialresp = DSTAT_NONE;       
866
867         sc->sc_if.if_flags &= ~IFF_RUNNING;
868         sc->sc_state = ST_IDLE;
869 }
870
871 /*---------------------------------------------------------------------------*
872  *      this routine is used to give a feedback from userland daemon
873  *      in case of dial problems
874  *---------------------------------------------------------------------------*/
875 static void
876 ipr_dialresponse(int unit, int status, cause_t cause)
877 {
878         struct ipr_softc *sc = &ipr_softc[unit];
879         sc->sc_dialresp = status;
880
881         NDBGL4(L4_IPRDBG, "ipr%d: last=%d, this=%d",
882                 unit, sc->sc_lastdialresp, sc->sc_dialresp);
883
884         if(status != DSTAT_NONE)
885         {
886                 NDBGL4(L4_IPRDBG, "ipr%d: clearing queues", unit);
887                 iprclearqueues(sc);
888         }
889 }
890         
891 /*---------------------------------------------------------------------------*
892  *      interface soft up/down
893  *---------------------------------------------------------------------------*/
894 static void
895 ipr_updown(int unit, int updown)
896 {
897         struct ipr_softc *sc = &ipr_softc[unit];
898         sc->sc_updown = updown;
899 }
900         
901 /*---------------------------------------------------------------------------*
902  *      this routine is called from the HSCX interrupt handler
903  *      when a new frame (mbuf) has been received and was put on
904  *      the rx queue. It is assumed that this routines runs at
905  *      pri level splimp() ! Keep it short !
906  *---------------------------------------------------------------------------*/
907 static void
908 ipr_rx_data_rdy(int unit)
909 {
910         register struct ipr_softc *sc = &ipr_softc[unit];
911         register struct mbuf *m;
912 #ifdef IPR_VJ
913 #ifdef IPR_VJ_USEBUFFER
914         u_char *cp = sc->sc_cbuf;
915 #endif  
916         int len, c;
917 #endif
918         
919         if((m = *isdn_linktab[unit]->rx_mbuf) == NULL)
920                 return;
921
922         m->m_pkthdr.rcvif = &sc->sc_if;
923
924         m->m_pkthdr.len = m->m_len;
925
926         microtime(&sc->sc_if.if_lastchange);
927
928 #ifdef I4BIPRADJFRXP
929
930         /*
931          * The very first packet after the B channel is switched thru
932          * has very often several bytes of random data prepended. This
933          * routine looks where the IP header starts and removes the
934          * the bad data.
935          */
936
937         if(sc->sc_first_pkt)
938         {
939                 unsigned char *mp = m->m_data;
940                 int i;
941                 
942                 sc->sc_first_pkt = 0;
943
944                 for(i = 0; i < m->m_len; i++, mp++)
945                 {
946                         if( ((*mp & 0xf0) == 0x40) &&
947                             ((*mp & 0x0f) >= 0x05) )
948                         {
949                                 m->m_data = mp;
950                                 m->m_pkthdr.len -= i;                           
951                                 break;
952                         }
953                 }
954         }
955 #endif
956                 
957         sc->sc_if.if_ipackets++;
958         sc->sc_if.if_ibytes += m->m_pkthdr.len;
959
960 #ifdef  IPR_VJ
961         if((c = (*(mtod(m, u_char *)) & 0xf0)) != (IPVERSION << 4))
962         {
963                 /* copy data to buffer */
964
965                 len = m->m_len;
966
967 #ifdef IPR_VJ_USEBUFFER
968 /* XXX */       m_copydata(m, 0, len, cp);
969 #endif
970                 
971                 if(c & 0x80)
972                 {
973                         c = TYPE_COMPRESSED_TCP;
974                 }
975                 else if(c == TYPE_UNCOMPRESSED_TCP)
976                 {
977 #ifdef IPR_VJ_USEBUFFER
978                         *cp &= 0x4f;            /* XXX */
979 #else
980                         *(mtod(m, u_char *)) &= 0x4f;                   
981 #endif                  
982                 }
983
984                 /*
985                  * We've got something that's not an IP packet.
986                  * If compression is enabled, try to decompress it.
987                  * Otherwise, if `auto-enable' compression is on and
988                  * it's a reasonable packet, decompress it and then
989                  * enable compression.  Otherwise, drop it.
990                  */
991                 if(sc->sc_if.if_flags & IPR_COMPRESS)
992                 {
993 #ifdef IPR_VJ_USEBUFFER
994                         len = sl_uncompress_tcp(&cp,len,(u_int)c,&sc->sc_compr);
995 #else
996                         len = sl_uncompress_tcp((u_char **)&m->m_data, len,
997                                         (u_int)c, &sc->sc_compr);
998 #endif                  
999
1000                         if(len <= 0)
1001                         {
1002 #ifdef DEBUG_IPR_VJ
1003                                 printf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_COMPRESS!\n");
1004 #endif
1005                                 goto error;
1006                         }
1007                 }
1008                 else if((sc->sc_if.if_flags & IPR_AUTOCOMP) &&
1009                         (c == TYPE_UNCOMPRESSED_TCP) && (len >= 40))
1010                 {
1011 #ifdef IPR_VJ_USEBUFFER
1012                         len = sl_uncompress_tcp(&cp,len,(u_int)c,&sc->sc_compr);
1013 #else
1014                         len = sl_uncompress_tcp((u_char **)&m->m_data, len,
1015                                         (u_int)c, &sc->sc_compr);
1016 #endif
1017
1018                         if(len <= 0)
1019                         {
1020 #ifdef DEBUG_IPR_VJ
1021                                 printf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_AUTOCOMP!\n");
1022 #endif
1023                                 goto error;
1024                         }
1025
1026                         sc->sc_if.if_flags |= IPR_COMPRESS;
1027                 }
1028                 else
1029                 {
1030 #ifdef DEBUG_IPR_VJ
1031                         printf("i4b_ipr, ipr_input: invalid ip packet!\n");
1032 #endif
1033
1034 error:
1035                         sc->sc_if.if_ierrors++;
1036                         sc->sc_if.if_collisions++;
1037                         m_freem(m);
1038                         return;
1039                 }
1040 #ifdef IPR_VJ_USEBUFFER
1041 /* XXX */       m_copyback(m, 0, len, cp);
1042 #else
1043                 m->m_len = m->m_pkthdr.len = len;
1044 #endif
1045         }
1046 #endif
1047
1048 #if I4BIPRACCT
1049         /* NB. do the accounting after decompression!           */
1050         sc->sc_inb += m->m_pkthdr.len;
1051 #endif
1052 #if IPR_LOG
1053         if(sc->sc_log_first > 0)
1054         {
1055                 --(sc->sc_log_first);
1056                 i4b_l4_packet_ind(BDRV_IPR, unit, 0, m );
1057         }
1058 #endif
1059
1060 #if NBPFILTER > 0 || NBPF > 0
1061         if(sc->sc_if.if_bpf)
1062         {
1063                 /* prepend the address family as a four byte field */           
1064                 struct mbuf mm;
1065                 u_int af = AF_INET;
1066                 mm.m_next = m;
1067                 mm.m_len = 4;
1068                 mm.m_data = (char *)&af;
1069
1070 #ifdef __FreeBSD__
1071                 bpf_mtap(&sc->sc_if, &mm);
1072 #else
1073                 bpf_mtap(sc->sc_if.if_bpf, &mm);
1074 #endif
1075         }
1076 #endif /* NBPFILTER > 0  || NBPF > 0 */
1077
1078 #if defined (__FreeBSD__) && __FreeBSD__ > 4
1079         if(! IF_HANDOFF(&ipintrq, m, NULL))
1080         {
1081                 NDBGL4(L4_IPRDBG, "ipr%d: ipintrq full!", unit);
1082                 sc->sc_if.if_ierrors++;
1083                 sc->sc_if.if_iqdrops++;         
1084         }
1085         else
1086         {
1087                 schednetisr(NETISR_IP);
1088         }
1089 #else
1090         if(IF_QFULL(&ipintrq))
1091         {
1092                 NDBGL4(L4_IPRDBG, "ipr%d: ipintrq full!", unit);
1093                 IF_DROP(&ipintrq);
1094                 sc->sc_if.if_ierrors++;
1095                 sc->sc_if.if_iqdrops++;
1096                 m_freem(m);
1097         }
1098         else
1099         {
1100                 IF_ENQUEUE(&ipintrq, m);
1101                 schednetisr(NETISR_IP);
1102         }
1103 #endif  
1104 }
1105
1106 /*---------------------------------------------------------------------------*
1107  *      this routine is called from the HSCX interrupt handler
1108  *      when the last frame has been sent out and there is no
1109  *      further frame (mbuf) in the tx queue.
1110  *---------------------------------------------------------------------------*/
1111 static void
1112 ipr_tx_queue_empty(int unit)
1113 {
1114         register struct ipr_softc *sc = &ipr_softc[unit];
1115         register struct mbuf *m;
1116 #ifdef  IPR_VJ  
1117         struct ip *ip;  
1118 #endif
1119         int x = 0;
1120
1121         if(sc->sc_state != ST_CONNECTED_A)
1122                 return;
1123                 
1124         for(;;)
1125         {
1126                 IF_DEQUEUE(&sc->sc_fastq, m);
1127                 if(m)
1128                 {
1129                         sc->sc_if.if_omcasts++;
1130                 }
1131                 else
1132                 {
1133                         IF_DEQUEUE(&sc->sc_if.if_snd, m);
1134                         if(m == NULL)
1135                                 break;
1136                 }
1137
1138                 microtime(&sc->sc_if.if_lastchange);
1139                 
1140 #if NBPFILTER > 0 || NBPF > 0
1141                 if(sc->sc_if.if_bpf)
1142                 {
1143                         /* prepend the address family as a four byte field */
1144         
1145                         struct mbuf mm;
1146                         u_int af = AF_INET;
1147                         mm.m_next = m;
1148                         mm.m_len = 4;
1149                         mm.m_data = (char *)&af;
1150         
1151 #ifdef __FreeBSD__
1152                         bpf_mtap(&sc->sc_if, &mm);
1153 #else
1154                         bpf_mtap(sc->sc_if.if_bpf, &mm);
1155 #endif
1156                 }
1157 #endif /* NBPFILTER */
1158         
1159 #if I4BIPRACCT
1160                 sc->sc_outb += m->m_pkthdr.len; /* size before compression */
1161 #endif
1162
1163 #ifdef  IPR_VJ  
1164                 if((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP)
1165                 {
1166                         if(sc->sc_if.if_flags & IPR_COMPRESS)
1167                         {
1168                                 *mtod(m, u_char *) |= sl_compress_tcp(m, ip,
1169                                         &sc->sc_compr, 1);
1170                         }
1171                 }
1172 #endif
1173                 x = 1;
1174
1175                 IF_LOCK(isdn_linktab[unit]->tx_queue);
1176                 if(_IF_QFULL(isdn_linktab[unit]->tx_queue))
1177                 {
1178                         NDBGL4(L4_IPRDBG, "ipr%d: tx queue full!", unit);
1179                         m_freem(m);
1180                 }
1181                 else
1182                 {
1183                         sc->sc_if.if_obytes += m->m_pkthdr.len;
1184
1185                         sc->sc_if.if_opackets++;
1186
1187                         _IF_ENQUEUE(isdn_linktab[unit]->tx_queue, m);
1188
1189                 }
1190                 IF_UNLOCK(isdn_linktab[unit]->tx_queue);
1191         }
1192
1193         if(x)
1194                 (*isdn_linktab[unit]->bch_tx_start)(isdn_linktab[unit]->unit, isdn_linktab[unit]->channel);
1195 }
1196
1197 /*---------------------------------------------------------------------------*
1198  *      this routine is called from the HSCX interrupt handler
1199  *      each time a packet is received or transmitted. It should
1200  *      be used to implement an activity timeout mechanism.
1201  *---------------------------------------------------------------------------*/
1202 static void
1203 ipr_activity(int unit, int rxtx)
1204 {
1205         ipr_softc[unit].sc_cdp->last_active_time = SECOND;
1206 }
1207
1208 /*---------------------------------------------------------------------------*
1209  *      return this drivers linktab address
1210  *---------------------------------------------------------------------------*/
1211 drvr_link_t *
1212 ipr_ret_linktab(int unit)
1213 {
1214         return(&ipr_drvr_linktab[unit]);
1215 }
1216
1217 /*---------------------------------------------------------------------------*
1218  *      setup the isdn_linktab for this driver
1219  *---------------------------------------------------------------------------*/
1220 void
1221 ipr_set_linktab(int unit, isdn_link_t *ilt)
1222 {
1223         isdn_linktab[unit] = ilt;
1224 }
1225
1226 /*---------------------------------------------------------------------------*
1227  *      initialize this drivers linktab
1228  *---------------------------------------------------------------------------*/
1229 static void
1230 ipr_init_linktab(int unit)
1231 {
1232         ipr_drvr_linktab[unit].unit = unit;
1233         ipr_drvr_linktab[unit].bch_rx_data_ready = ipr_rx_data_rdy;
1234         ipr_drvr_linktab[unit].bch_tx_queue_empty = ipr_tx_queue_empty;
1235         ipr_drvr_linktab[unit].bch_activity = ipr_activity;
1236         ipr_drvr_linktab[unit].line_connected = ipr_connect;
1237         ipr_drvr_linktab[unit].line_disconnected = ipr_disconnect;
1238         ipr_drvr_linktab[unit].dial_response = ipr_dialresponse;
1239         ipr_drvr_linktab[unit].updown_ind = ipr_updown; 
1240 }
1241
1242 /*===========================================================================*/
1243
1244 #endif /* NI4BIPR > 0 */