new portable STREAMS modules
[ppp.git] / modules / ppp.c
1 /*
2  * ppp.c - STREAMS multiplexing pseudo-device driver for PPP.
3  *
4  * Copyright (c) 1994 The Australian National University.
5  * All rights reserved.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation is hereby granted, provided that the above copyright
9  * notice appears in all copies.  This software is provided without any
10  * warranty, express or implied. The Australian National University
11  * makes no representations about the suitability of this software for
12  * any purpose.
13  *
14  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
15  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
17  * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
18  * OF SUCH DAMAGE.
19  *
20  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
21  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
24  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
25  * OR MODIFICATIONS.
26  *
27  * $Id: ppp.c,v 1.1 1995/12/11 05:06:40 paulus Exp $
28  */
29
30 /*
31  * This file is used under Solaris 2 and SunOS 4.
32  */
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/stat.h>
37 #include <sys/stream.h>
38 #include <sys/stropts.h>
39 #include <sys/errno.h>
40 #include <sys/ioccom.h>
41 #ifdef SVR4
42 #include <sys/cmn_err.h>
43 #include <sys/conf.h>
44 #include <sys/dlpi.h>
45 #include <sys/ddi.h>
46 #ifdef SOL2
47 #include <sys/kstat.h>
48 #include <sys/sunddi.h>
49 #else
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 #include <net/if.h>
53 #include <netinet/in.h>
54 #endif /* SOL2 */
55 #else /* not SVR4 */
56 #include <sys/user.h>
57 #endif /* SVR4 */
58 #include <net/ppp_defs.h>
59 #include <net/pppio.h>
60 #include "ppp_mod.h"
61
62 #ifdef __STDC__
63 #define __P(x)  x
64 #else
65 #define __P(x)  ()
66 #endif
67
68 /*
69  * The IP module uses this SAP value for IP packets.
70  */
71 #ifndef ETHERTYPE_IP
72 #define ETHERTYPE_IP    0x800
73 #endif
74
75 #ifndef PPP_MAXMTU
76 #define PPP_MAXMTU      65535
77 #endif
78
79 /*
80  * Private information; one per upper stream.
81  */
82 typedef struct upperstr {
83     minor_t mn;                 /* minor device number */
84     struct upperstr *nextmn;    /* next minor device */
85     queue_t *q;                 /* read q associated with this upper stream */
86     int flags;                  /* flag bits, see below */
87     int state;                  /* current DLPI state */
88     int sap;                    /* service access point */
89     int req_sap;                /* which SAP the DLPI client requested */
90     struct upperstr *ppa;       /* control stream for our ppa */
91     struct upperstr *next;      /* next stream for this ppa */
92     uint ioc_id;                /* last ioctl ID for this stream */
93     /*
94      * There is exactly one control stream for each PPA.
95      * The following fields are only used for control streams.
96      */
97     int ppa_id;
98     queue_t *lowerq;            /* write queue attached below this PPA */
99     struct upperstr *nextppa;   /* next control stream */
100     int mru;
101     int mtu;
102     struct pppstat stats;       /* statistics */
103 #ifdef SOL2
104     kstat_t *kstats;            /* stats for netstat */
105 #endif /* SOL2 */
106 #ifdef LACHTCP
107     int ifflags;
108     char ifname[IFNAMSIZ];
109     struct ifstats ifstats;
110 #endif /* LACHTCP */
111 } upperstr_t;
112
113 /* Values for flags */
114 #define US_PRIV         1       /* stream was opened by superuser */
115 #define US_CONTROL      2       /* stream is a control stream */
116 #define US_BLOCKED      4       /* flow ctrl has blocked lower write stream */
117 #define US_LASTMOD      8       /* no PPP modules below us */
118 #define US_DBGLOG       0x10    /* log various occurrences */
119
120 static upperstr_t *minor_devs = NULL;
121 static upperstr_t *ppas = NULL;
122
123 #ifdef SVR4
124 static int pppopen __P((queue_t *, dev_t *, int, int, cred_t *));
125 static int pppclose __P((queue_t *, int, cred_t *));
126 #else
127 static int pppopen __P((queue_t *, int, int, int));
128 static int pppclose __P((queue_t *, int));
129 #endif /* SVR4 */
130 static int pppuwput __P((queue_t *, mblk_t *));
131 static int pppursrv __P((queue_t *));
132 static int pppuwsrv __P((queue_t *));
133 static int ppplrput __P((queue_t *, mblk_t *));
134 static int ppplwput __P((queue_t *, mblk_t *));
135 static int ppplrsrv __P((queue_t *));
136 static int ppplwsrv __P((queue_t *));
137 #ifndef NO_DLPI
138 static void dlpi_request __P((queue_t *, mblk_t *, upperstr_t *));
139 static void dlpi_error __P((queue_t *, int, int, int));
140 static void dlpi_ok __P((queue_t *, int));
141 #endif
142 static int send_data __P((mblk_t *, upperstr_t *));
143 static void new_ppa __P((queue_t *, mblk_t *));
144 static void attach_ppa __P((queue_t *, mblk_t *));
145 static void detach_ppa __P((queue_t *, mblk_t *));
146 static void debug_dump __P((queue_t *, mblk_t *));
147 static upperstr_t *find_dest __P((upperstr_t *, int));
148 static int putctl2 __P((queue_t *, int, int, int));
149 static int putctl4 __P((queue_t *, int, int, int));
150
151 static struct module_info ppp_info = {
152     0xb1a6, "ppp", 0, 512, 512, 128
153 };
154
155 static struct qinit pppurint = {
156     NULL, pppursrv, pppopen, pppclose, NULL, &ppp_info, NULL
157 };
158
159 static struct qinit pppuwint = {
160     pppuwput, pppuwsrv, NULL, NULL, NULL, &ppp_info, NULL
161 };
162
163 static struct qinit ppplrint = {
164     ppplrput, ppplrsrv, NULL, NULL, NULL, &ppp_info, NULL
165 };
166
167 static struct qinit ppplwint = {
168     ppplwput, ppplwsrv, NULL, NULL, NULL, &ppp_info, NULL
169 };
170
171 #ifdef LACHTCP
172 extern struct ifstats *ifstats;
173 int pppdevflag = 0;
174 #endif
175
176 struct streamtab pppinfo = {
177     &pppurint, &pppuwint,
178     &ppplrint, &ppplwint
179 };
180
181 int ppp_count;
182
183 /*
184  * How we maintain statistics.
185  */
186 #ifdef SOL2
187 #define INCR_IPACKETS(ppa)                              \
188         if (ppa->kstats != 0) {                         \
189             KSTAT_NAMED_PTR(ppa->kstats)[0].value.ul++; \
190         }
191 #define INCR_IERRORS(ppa)                               \
192         if (ppa->kstats != 0) {                         \
193             KSTAT_NAMED_PTR(ppa->kstats)[1].value.ul++; \
194         }
195 #define INCR_OPACKETS(ppa)                              \
196         if (ppa->kstats != 0) {                         \
197             KSTAT_NAMED_PTR(ppa->kstats)[2].value.ul++; \
198         }
199 #define INCR_OERRORS(ppa)                               \
200         if (ppa->kstats != 0) {                         \
201             KSTAT_NAMED_PTR(ppa->kstats)[3].value.ul++; \
202         }
203 #endif
204
205 #ifdef LACHTCP
206 #define INCR_IPACKETS(ppa)      ppa->ifstats.ifs_ipackets++;
207 #define INCR_IERRORS(ppa)       ppa->ifstats.ifs_ierrors++;
208 #define INCR_OPACKETS(ppa)      ppa->ifstats.ifs_opackets++;
209 #define INCR_OERRORS(ppa)       ppa->ifstats.ifs_oerrors++;
210 #endif
211
212 /*
213  * STREAMS driver entry points.
214  */
215 static int
216 #ifdef SVR4
217 pppopen(q, devp, oflag, sflag, credp)
218     queue_t *q;
219     dev_t *devp;
220     int oflag, sflag;
221     cred_t *credp;
222 #else
223 pppopen(q, dev, oflag, sflag)
224     queue_t *q;
225     int dev;                    /* really dev_t */
226     int oflag, sflag;
227 #endif
228 {
229     upperstr_t *up;
230     upperstr_t **prevp;
231     minor_t mn;
232
233     if (q->q_ptr)
234         DRV_OPEN_OK(dev);       /* device is already open */
235
236     if (sflag == CLONEOPEN) {
237         mn = 0;
238         for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
239             if (up->mn != mn)
240                 break;
241             ++mn;
242         }
243     } else {
244 #ifdef SVR4
245         mn = getminor(*devp);
246 #else
247         mn = minor(dev);
248 #endif
249         for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
250             if (up->mn >= mn)
251                 break;
252         }
253         if (up->mn == mn) {
254             /* this can't happen */
255             q->q_ptr = WR(q)->q_ptr = (caddr_t) up;
256             DRV_OPEN_OK(dev);
257         }
258     }
259
260     /*
261      * Construct a new minor node.
262      */
263     up = (upperstr_t *) ALLOC_SLEEP(sizeof(upperstr_t));
264     bzero((caddr_t) up, sizeof(upperstr_t));
265     if (up == 0) {
266         DPRINT("pppopen: out of kernel memory\n");
267         OPEN_ERROR(ENXIO);
268     }
269     up->nextmn = *prevp;
270     *prevp = up;
271     up->mn = mn;
272 #ifdef SVR4
273     *devp = makedevice(getmajor(*devp), mn);
274 #endif
275     up->q = q;
276     if (NOTSUSER() == 0)
277         up->flags |= US_PRIV;
278 #ifndef NO_DLPI
279     up->state = DL_UNATTACHED;
280 #endif
281 #ifdef LACHTCP
282     up->ifflags = IFF_UP | IFF_POINTOPOINT;
283 #endif
284     up->sap = -1;
285     q->q_ptr = (caddr_t) up;
286     WR(q)->q_ptr = (caddr_t) up;
287     noenable(WR(q));
288     ++ppp_count;
289
290     qprocson(q);
291     DRV_OPEN_OK(makedev(major(dev), mn));
292 }
293
294 static int
295 #ifdef SVR4
296 pppclose(q, flag, credp)
297     queue_t *q;
298     int flag;
299     cred_t *credp;
300 #else
301 pppclose(q, flag)
302     queue_t *q;
303     int flag;
304 #endif
305 {
306     upperstr_t *up, **upp;
307     upperstr_t *as, *asnext;
308     upperstr_t **prevp;
309
310     qprocsoff(q);
311
312     up = (upperstr_t *) q->q_ptr;
313     if (up->flags & US_DBGLOG)
314         DPRINT2("ppp/%d: close, flags=%x\n", up->mn, up->flags);
315     if (up == 0)
316         return 0;
317     if (up->flags & US_CONTROL) {
318 #ifdef LACHTCP
319         struct ifstats *ifp, *pifp;
320 #endif
321         /*
322          * This stream represents a PPA:
323          * For all streams attached to the PPA, clear their
324          * references to this PPA.
325          * Then remove this PPA from the list of PPAs.
326          */
327         for (as = up->next; as != 0; as = asnext) {
328             asnext = as->next;
329             as->next = 0;
330             as->ppa = 0;
331             if (as->flags & US_BLOCKED) {
332                 as->flags &= ~US_BLOCKED;
333                 flushq(WR(as->q), FLUSHDATA);
334             }
335         }
336         for (upp = &ppas; *upp != 0; upp = &(*upp)->nextppa)
337             if (*upp == up) {
338                 *upp = up->nextppa;
339                 break;
340             }
341 #ifdef LACHTCP
342         /* Remove the statistics from the active list.  */
343         for (ifp = ifstats, pifp = 0; ifp; ifp = ifp->ifs_next) {
344             if (ifp == &up->ifstats) {
345                 if (pifp)
346                     pifp->ifs_next = ifp->ifs_next;
347                 else
348                     ifstats = ifp->ifs_next;
349                 break;
350             }
351             pifp = ifp;
352         }
353 #endif
354     } else {
355         /*
356          * If this stream is attached to a PPA,
357          * remove it from the PPA's list.
358          */
359         if ((as = up->ppa) != 0) {
360             for (; as->next != 0; as = as->next)
361                 if (as->next == up) {
362                     as->next = up->next;
363                     break;
364                 }
365         }
366     }
367
368 #ifdef SOL2
369     if (up->kstats)
370         kstat_delete(up->kstats);
371 #endif
372
373     q->q_ptr = NULL;
374     WR(q)->q_ptr = NULL;
375
376     for (prevp = &minor_devs; *prevp != 0; prevp = &(*prevp)->nextmn) {
377         if (*prevp == up) {
378             *prevp = up->nextmn;
379             break;
380         }
381     }
382     kmem_free(up, sizeof(upperstr_t));
383     --ppp_count;
384
385     return 0;
386 }
387
388 /*
389  * A message from on high.  We do one of three things:
390  *      - qreply()
391  *      - put the message on the lower write stream
392  *      - queue it for our service routine
393  */
394 static int
395 pppuwput(q, mp)
396     queue_t *q;
397     mblk_t *mp;
398 {
399     upperstr_t *us, *usnext, *ppa, *os;
400     struct iocblk *iop;
401     struct linkblk *lb;
402 #ifdef LACHTCP
403     struct ifreq *ifr;
404     int i;
405 #endif
406     queue_t *lq;
407     int error, n;
408     mblk_t *mq;
409
410     us = (upperstr_t *) q->q_ptr;
411     switch (mp->b_datap->db_type) {
412 #ifndef NO_DLPI
413     case M_PCPROTO:
414     case M_PROTO:
415         dlpi_request(q, mp, us);
416         break;
417 #endif /* NO_DLPI */
418
419     case M_DATA:
420         if (us->flags & US_DBGLOG)
421             DPRINT3("ppp/%d: uwput M_DATA len=%d flags=%x\n",
422                     us->mn, msgdsize(mp), us->flags);
423         if (us->ppa == 0 || msgdsize(mp) > us->ppa->mtu + PPP_HDRLEN
424 #ifndef NO_DLPI
425             || (us->flags & US_CONTROL) == 0
426 #endif /* NO_DLPI */
427             ) {
428             DPRINT1("pppuwput: junk data len=%d\n", msgdsize(mp));
429             freemsg(mp);
430             break;
431         }
432         if (!send_data(mp, us))
433             putq(q, mp);
434         break;
435
436     case M_IOCTL:
437         iop = (struct iocblk *) mp->b_rptr;
438         error = EINVAL;
439         if (us->flags & US_DBGLOG)
440             DPRINT3("ppp/%d: ioctl %x count=%d\n",
441                     us->mn, iop->ioc_cmd, iop->ioc_count);
442         switch (iop->ioc_cmd) {
443         case I_LINK:
444             if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0)
445                 break;
446             lb = (struct linkblk *) mp->b_cont->b_rptr;
447             us->lowerq = lq = lb->l_qbot;
448             lq->q_ptr = (caddr_t) us;
449             RD(lq)->q_ptr = (caddr_t) us;
450             noenable(RD(lq));
451             flushq(RD(lq), FLUSHALL);
452             iop->ioc_count = 0;
453             error = 0;
454             us->flags &= ~US_LASTMOD;
455             /* Unblock upper streams which now feed this lower stream. */
456             qenable(lq);
457             /* Send useful information down to the modules which
458                are now linked below us. */
459             putctl2(lq, M_CTL, PPPCTL_UNIT, us->ppa_id);
460             putctl4(lq, M_CTL, PPPCTL_MRU, us->mru);
461             putctl4(lq, M_CTL, PPPCTL_MTU, us->mtu);
462             break;
463
464         case I_UNLINK:
465             lb = (struct linkblk *) mp->b_cont->b_rptr;
466 #if DEBUG
467             if (us->lowerq != lb->l_qbot)
468                 DPRINT2("ppp unlink: lowerq=%x qbot=%x\n",
469                         us->lowerq, lb->l_qbot);
470 #endif
471             us->lowerq = 0;
472             iop->ioc_count = 0;
473             error = 0;
474             /* Unblock streams which now feed back up the control stream. */
475             qenable(us->q);
476             break;
477
478         case PPPIO_NEWPPA:
479             if (us->flags & US_CONTROL)
480                 break;
481             if ((us->flags & US_PRIV) == 0) {
482                 error = EPERM;
483                 break;
484             }
485             /* Arrange to return an int */
486             if ((mq = mp->b_cont) == 0
487                 || mq->b_datap->db_lim - mq->b_rptr < sizeof(int)) {
488                 mq = allocb(sizeof(int), BPRI_HI);
489                 if (mq == 0) {
490                     error = ENOSR;
491                     break;
492                 }
493                 if (mp->b_cont != 0)
494                     freemsg(mp->b_cont);
495                 mp->b_cont = mq;
496                 mq->b_cont = 0;
497             }
498             iop->ioc_count = sizeof(int);
499             mq->b_wptr = mq->b_rptr + sizeof(int);
500             qwriter(q, mp, new_ppa, PERIM_OUTER);
501             error = -1;
502             break;
503
504         case PPPIO_ATTACH:
505             /* like dlpi_attach, for programs which can't write to
506                the stream (like pppstats) */
507             if (iop->ioc_count != sizeof(int) || us->ppa != 0)
508                 break;
509             n = *(int *)mp->b_cont->b_rptr;
510             for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
511                 if (ppa->ppa_id == n)
512                     break;
513             if (ppa == 0)
514                 break;
515             us->ppa = ppa;
516             iop->ioc_count = 0;
517             qwriter(q, mp, attach_ppa, PERIM_OUTER);
518             error = -1;
519             break;
520
521 #ifdef NO_DLPI
522         case PPPIO_BIND:
523             /* Attach to a given SAP. */
524             if (iop->ioc_count != sizeof(int) || us->ppa == 0)
525                 break;
526             n = *(int *)mp->b_cont->b_rptr;
527             /* n must be a valid PPP network protocol number. */
528             if (n < 0x21 || n > 0x3fff || (n & 0x101) != 1)
529                 break;
530             /* check that no other stream is bound to this sap already. */
531             for (os = us->ppa; os != 0; os = os->next)
532                 if (os->sap == n)
533                     break;
534             if (os != 0)
535                 break;
536             us->sap = n;
537             iop->ioc_count = 0;
538             error = 0;
539             break;
540 #endif /* NO_DLPI */
541
542         case PPPIO_MRU:
543             if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
544                 break;
545             n = *(int *)mp->b_cont->b_rptr;
546             if (n <= 0 || n > PPP_MAXMTU)
547                 break;
548             if (n < PPP_MRU)
549                 n = PPP_MRU;
550             us->mru = n;
551             if (us->lowerq)
552                 putctl4(us->lowerq, M_CTL, PPPCTL_MRU, n);
553             error = 0;
554             iop->ioc_count = 0;
555             break;
556
557         case PPPIO_MTU:
558             if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
559                 break;
560             n = *(int *)mp->b_cont->b_rptr;
561             if (n <= 0 || n > PPP_MAXMTU)
562                 break;
563             if (n < PPP_MRU)
564                 n = PPP_MRU;
565             us->mtu = n;
566 #ifdef LACHTCP
567             us->ifstats.ifs_mtu = n;
568 #endif
569             if (us->lowerq)
570                 putctl4(us->lowerq, M_CTL, PPPCTL_MTU, n);
571             error = 0;
572             iop->ioc_count = 0;
573             break;
574
575         case PPPIO_LASTMOD:
576             us->flags |= US_LASTMOD;
577             error = 0;
578             break;
579
580         case PPPIO_DEBUG:
581             if (iop->ioc_count != sizeof(int))
582                 break;
583             n = *(int *)mp->b_cont->b_rptr;
584             if (n == PPPDBG_DUMP + PPPDBG_DRIVER) {
585                 qwriter(q, NULL, debug_dump, PERIM_OUTER);
586                 iop->ioc_count = 0;
587                 error = 0;
588             } else if (n == PPPDBG_LOG + PPPDBG_DRIVER) {
589                 DPRINT1("ppp/%d: debug log enabled\n", us->mn);
590                 us->flags |= US_DBGLOG;
591                 iop->ioc_count = 0;
592                 error = 0;
593             } else {
594                 if (us->ppa == 0 || us->ppa->lowerq == 0)
595                     break;
596                 putnext(us->ppa->lowerq, mp);
597                 error = -1;
598             }
599             break;
600
601 #ifdef LACHTCP
602         case SIOCSIFNAME:
603             printf("SIOCSIFNAME\n");
604             /* Sent from IP down to us.  Attach the ifstats structure.  */
605             if (iop->ioc_count != sizeof(struct ifreq) || us->ppa == 0)
606                 break;
607             ifr = (struct ifreq *)mp->b_cont->b_rptr;
608             /* Find the unit number in the interface name.  */
609             for (i = 0; i < IFNAMSIZ; i++) {
610                 if (ifr->ifr_name[i] == 0 ||
611                     (ifr->ifr_name[i] >= '0' &&
612                      ifr->ifr_name[i] <= '9'))
613                     break;
614                 else
615                     us->ifname[i] = ifr->ifr_name[i];
616             }
617             us->ifname[i] = 0;
618
619             /* Convert the unit number to binary.  */
620             for (n = 0; i < IFNAMSIZ; i++) {
621                 if (ifr->ifr_name[i] == 0) {
622                     break;
623                 }
624                 else {
625                     n = n * 10 + ifr->ifr_name[i] - '0';
626                 }
627             }
628
629             /* Verify the ppa.  */
630             if (us->ppa->ppa_id != n)
631                 break;
632             ppa = us->ppa;
633
634             /* Set up the netstat block.  */
635             strncpy (ppa->ifname, us->ifname, IFNAMSIZ);
636
637             ppa->ifstats.ifs_name = ppa->ifname;
638             ppa->ifstats.ifs_unit = n;
639             ppa->ifstats.ifs_active = us->state != DL_UNBOUND;
640             ppa->ifstats.ifs_mtu = ppa->mtu;
641
642             /* Link in statistics used by netstat.  */
643             ppa->ifstats.ifs_next = ifstats;
644             ifstats = &ppa->ifstats;
645
646             iop->ioc_count = 0;
647             error = 0;
648             break;
649
650         case SIOCGIFFLAGS:
651             printf("SIOCGIFFLAGS\n");
652             if (!(us->flags & US_CONTROL)) {
653                 if (us->ppa)
654                     us = us->ppa;
655                 else
656                     break;
657             }
658             ((struct iocblk_in *)iop)->ioc_ifflags = us->ifflags;
659             error = 0;
660             break;
661
662         case SIOCSIFFLAGS:
663             printf("SIOCSIFFLAGS\n");
664             if (!(us->flags & US_CONTROL)) {
665                 if (us->ppa)
666                     us = us->ppa;
667                 else
668                     break;
669             }
670             us->ifflags = ((struct iocblk_in *)iop)->ioc_ifflags;
671             error = 0;
672             break;
673
674         case SIOCSIFADDR:
675             printf("SIOCSIFADDR\n");
676             if (!(us->flags & US_CONTROL)) {
677                 if (us->ppa)
678                     us = us->ppa;
679                 else
680                     break;
681             }
682             us->ifflags |= IFF_RUNNING;
683             ((struct iocblk_in *)iop)->ioc_ifflags |= IFF_RUNNING;
684             error = 0;
685             break;
686
687         case SIOCGIFNETMASK:
688         case SIOCSIFNETMASK:
689         case SIOCGIFADDR:
690         case SIOCGIFDSTADDR:
691         case SIOCSIFDSTADDR:
692         case SIOCGIFMETRIC:
693             error = 0;
694             break;
695 #endif /* LACHTCP */
696
697         default:
698             if (us->ppa == 0 || us->ppa->lowerq == 0)
699                 break;
700             us->ioc_id = iop->ioc_id;
701             error = -1;
702             switch (iop->ioc_cmd) {
703             case PPPIO_GETSTAT:
704             case PPPIO_GETCSTAT:
705                 if (us->flags & US_LASTMOD) {
706                     error = EINVAL;
707                     break;
708                 }
709                 putnext(us->ppa->lowerq, mp);
710                 break;
711             default:
712                 if (us->flags & US_PRIV)
713                     putnext(us->ppa->lowerq, mp);
714                 else {
715                     DPRINT1("ppp ioctl %x rejected\n", iop->ioc_cmd);
716                     error = EPERM;
717                 }
718                 break;
719             }
720             break;
721         }
722
723         if (error > 0) {
724             iop->ioc_error = error;
725             mp->b_datap->db_type = M_IOCNAK;
726             qreply(q, mp);
727         } else if (error == 0) {
728             mp->b_datap->db_type = M_IOCACK;
729             qreply(q, mp);
730         }
731         break;
732
733     case M_FLUSH:
734         if (us->flags & US_DBGLOG)
735             DPRINT2("ppp/%d: flush %x\n", us->mn, *mp->b_rptr);
736         if (*mp->b_rptr & FLUSHW)
737             flushq(q, FLUSHDATA);
738         if (*mp->b_rptr & FLUSHR) {
739             *mp->b_rptr &= ~FLUSHW;
740             qreply(q, mp);
741         } else
742             freemsg(mp);
743         break;
744
745     default:
746         freemsg(mp);
747         break;
748     }
749     return 0;
750 }
751
752 #ifndef NO_DLPI
753 static void
754 dlpi_request(q, mp, us)
755     queue_t *q;
756     mblk_t *mp;
757     upperstr_t *us;
758 {
759     union DL_primitives *d = (union DL_primitives *) mp->b_rptr;
760     int size = mp->b_wptr - mp->b_rptr;
761     mblk_t *reply, *np;
762     upperstr_t *ppa, *os;
763     int sap, *ip, len;
764     dl_info_ack_t *info;
765     dl_bind_ack_t *ackp;
766
767     if (us->flags & US_DBGLOG)
768         cmn_err(CE_CONT, "ppp/%d: dlpi prim %x len=%d\n", us->mn,
769                 d->dl_primitive, size);
770     switch (d->dl_primitive) {
771     case DL_INFO_REQ:
772         if (size < sizeof(dl_info_req_t))
773             goto badprim;
774         if ((reply = allocb(sizeof(dl_info_ack_t), BPRI_HI)) == 0)
775             break;              /* should do bufcall */
776         reply->b_datap->db_type = M_PCPROTO;
777         info = (dl_info_ack_t *) reply->b_wptr;
778         reply->b_wptr += sizeof(dl_info_ack_t);
779         bzero((caddr_t) info, sizeof(dl_info_ack_t));
780         info->dl_primitive = DL_INFO_ACK;
781         info->dl_max_sdu = PPP_MAXMTU;
782         info->dl_min_sdu = 1;
783         info->dl_addr_length = sizeof(ulong);
784 #ifdef DL_OTHER
785         info->dl_mac_type = DL_OTHER;
786 #else
787         info->dl_mac_type = DL_HDLC;    /* a lie */
788 #endif
789         info->dl_current_state = us->state;
790         info->dl_service_mode = DL_CLDLS;
791         info->dl_provider_style = DL_STYLE2;
792 #if DL_CURRENT_VERSION >= 2
793         info->dl_sap_length = sizeof(ulong);
794         info->dl_version = DL_CURRENT_VERSION;
795 #endif
796         qreply(q, reply);
797         break;
798
799     case DL_ATTACH_REQ:
800         if (size < sizeof(dl_attach_req_t))
801             goto badprim;
802         if (us->state != DL_UNATTACHED || us->ppa != 0) {
803             dlpi_error(q, DL_ATTACH_REQ, DL_OUTSTATE, 0);
804             break;
805         }
806         for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
807             if (ppa->ppa_id == d->attach_req.dl_ppa)
808                 break;
809         if (ppa == 0) {
810             dlpi_error(q, DL_ATTACH_REQ, DL_BADPPA, 0);
811             break;
812         }
813         us->ppa = ppa;
814         qwriter(q, mp, attach_ppa, PERIM_OUTER);
815         break;
816
817     case DL_DETACH_REQ:
818         if (size < sizeof(dl_detach_req_t))
819             goto badprim;
820         if (us->state != DL_UNBOUND || us->ppa == 0) {
821             dlpi_error(q, DL_DETACH_REQ, DL_OUTSTATE, 0);
822             break;
823         }
824         qwriter(q, mp, detach_ppa, PERIM_OUTER);
825         break;
826
827     case DL_BIND_REQ:
828         if (size < sizeof(dl_bind_req_t))
829             goto badprim;
830         if (us->state != DL_UNBOUND || us->ppa == 0) {
831             dlpi_error(q, DL_BIND_REQ, DL_OUTSTATE, 0);
832             break;
833         }
834         if (d->bind_req.dl_service_mode != DL_CLDLS) {
835             dlpi_error(q, DL_BIND_REQ, DL_UNSUPPORTED, 0);
836             break;
837         }
838
839         /* saps must be valid PPP network protocol numbers,
840            except that we accept ETHERTYPE_IP in place of PPP_IP. */
841         sap = d->bind_req.dl_sap;
842         us->req_sap = sap;
843 #if DEBUG
844         cmn_err(CE_CONT, "ppp bind %x\n", sap);
845 #endif
846         if (sap == ETHERTYPE_IP)
847             sap = PPP_IP;
848         if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
849             dlpi_error(q, DL_BIND_REQ, DL_BADADDR, 0);
850             break;
851         }
852
853         /* check that no other stream is bound to this sap already. */
854         for (os = us->ppa; os != 0; os = os->next)
855             if (os->sap == sap)
856                 break;
857         if (os != 0) {
858             dlpi_error(q, DL_BIND_REQ, DL_NOADDR, 0);
859             break;
860         }
861
862         us->sap = sap;
863         us->state = DL_IDLE;
864
865         if ((reply = allocb(sizeof(dl_bind_ack_t) + sizeof(ulong),
866                             BPRI_HI)) == 0)
867             break;              /* should do bufcall */
868         ackp = (dl_bind_ack_t *) reply->b_wptr;
869         reply->b_wptr += sizeof(dl_bind_ack_t) + sizeof(ulong);
870         reply->b_datap->db_type = M_PCPROTO;
871         bzero((caddr_t) ackp, sizeof(dl_bind_ack_t));
872         ackp->dl_primitive = DL_BIND_ACK;
873         ackp->dl_sap = sap;
874         ackp->dl_addr_length = sizeof(ulong);
875         ackp->dl_addr_offset = sizeof(dl_bind_ack_t);
876         *(ulong *)(ackp+1) = sap;
877         qreply(q, reply);
878         break;
879
880     case DL_UNBIND_REQ:
881         if (size < sizeof(dl_unbind_req_t))
882             goto badprim;
883         if (us->state != DL_IDLE) {
884             dlpi_error(q, DL_UNBIND_REQ, DL_OUTSTATE, 0);
885             break;
886         }
887         us->sap = -1;
888         us->state = DL_UNBOUND;
889 #ifndef sun
890         us->ppa->ifstats.ifs_active = 0;
891 #endif
892         dlpi_ok(q, DL_UNBIND_REQ);
893         break;
894
895     case DL_UNITDATA_REQ:
896         if (size < sizeof(dl_unitdata_req_t))
897             goto badprim;
898         if (us->state != DL_IDLE) {
899             dlpi_error(q, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
900             break;
901         }
902         if (us->ppa == 0) {
903             cmn_err(CE_CONT, "ppp: in state dl_idle but ppa == 0?\n");
904             break;
905         }
906         len = mp->b_cont == 0? 0: msgdsize(mp->b_cont);
907         if (len > us->ppa->mtu) {
908 #if DEBUG
909             cmn_err(CE_CONT, "dlpi data too large (%d > %d)\n", len, us->mtu);
910 #endif
911             break;
912         }
913         /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
914         if (mp->b_datap->db_ref > 1) {
915             np = allocb(PPP_HDRLEN, BPRI_HI);
916             if (np == 0)
917                 break;          /* gak! */
918             np->b_cont = mp->b_cont;
919             mp->b_cont = 0;
920             freeb(mp);
921             mp = np;
922         } else
923             mp->b_datap->db_type = M_DATA;
924         /* XXX should use dl_dest_addr_offset/length here,
925            but we would have to translate ETHERTYPE_IP -> PPP_IP */
926         mp->b_wptr = mp->b_rptr + PPP_HDRLEN;
927         mp->b_rptr[0] = PPP_ALLSTATIONS;
928         mp->b_rptr[1] = PPP_UI;
929         mp->b_rptr[2] = us->sap >> 8;
930         mp->b_rptr[3] = us->sap;
931         if (!send_data(mp, us))
932             putq(q, mp);
933         return;
934
935 #if DL_CURRENT_VERSION >= 2
936     case DL_SUBS_BIND_REQ:
937     case DL_SUBS_UNBIND_REQ:
938     case DL_ENABMULTI_REQ:
939     case DL_DISABMULTI_REQ:
940     case DL_PROMISCON_REQ:
941     case DL_PROMISCOFF_REQ:
942     case DL_PHYS_ADDR_REQ:
943     case DL_SET_PHYS_ADDR_REQ:
944     case DL_XID_REQ:
945     case DL_TEST_REQ:
946     case DL_REPLY_UPDATE_REQ:
947     case DL_REPLY_REQ:
948     case DL_DATA_ACK_REQ:
949 #endif
950     case DL_CONNECT_REQ:
951     case DL_TOKEN_REQ:
952         dlpi_error(q, d->dl_primitive, DL_NOTSUPPORTED, 0);
953         break;
954
955     case DL_CONNECT_RES:
956     case DL_DISCONNECT_REQ:
957     case DL_RESET_REQ:
958     case DL_RESET_RES:
959         dlpi_error(q, d->dl_primitive, DL_OUTSTATE, 0);
960         break;
961
962     case DL_UDQOS_REQ:
963         dlpi_error(q, d->dl_primitive, DL_BADQOSTYPE, 0);
964         break;
965
966 #if DL_CURRENT_VERSION >= 2
967     case DL_TEST_RES:
968     case DL_XID_RES:
969         break;
970 #endif
971
972     default:
973         cmn_err(CE_CONT, "ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);
974         /* fall through */
975     badprim:
976         dlpi_error(q, d->dl_primitive, DL_BADPRIM, 0);
977         break;
978     }
979     freemsg(mp);
980 }
981
982 static void
983 dlpi_error(q, prim, err, uerr)
984     queue_t *q;
985     int prim, err, uerr;
986 {
987     mblk_t *reply;
988     dl_error_ack_t *errp;
989
990     reply = allocb(sizeof(dl_error_ack_t), BPRI_HI);
991     if (reply == 0)
992         return;                 /* XXX should do bufcall */
993     reply->b_datap->db_type = M_PCPROTO;
994     errp = (dl_error_ack_t *) reply->b_wptr;
995     reply->b_wptr += sizeof(dl_error_ack_t);
996     errp->dl_primitive = DL_ERROR_ACK;
997     errp->dl_error_primitive = prim;
998     errp->dl_errno = err;
999     errp->dl_unix_errno = uerr;
1000     qreply(q, reply);
1001 }
1002
1003 static void
1004 dlpi_ok(q, prim)
1005     queue_t *q;
1006     int prim;
1007 {
1008     mblk_t *reply;
1009     dl_ok_ack_t *okp;
1010
1011     reply = allocb(sizeof(dl_ok_ack_t), BPRI_HI);
1012     if (reply == 0)
1013         return;                 /* XXX should do bufcall */
1014     reply->b_datap->db_type = M_PCPROTO;
1015     okp = (dl_ok_ack_t *) reply->b_wptr;
1016     reply->b_wptr += sizeof(dl_ok_ack_t);
1017     okp->dl_primitive = DL_OK_ACK;
1018     okp->dl_correct_primitive = prim;
1019     qreply(q, reply);
1020 }
1021 #endif /* NO_DLPI */
1022
1023 static int
1024 send_data(mp, us)
1025     mblk_t *mp;
1026     upperstr_t *us;
1027 {
1028     queue_t *q;
1029     upperstr_t *ppa;
1030
1031     if (us->flags & US_BLOCKED)
1032         return 0;
1033     ppa = us->ppa;
1034     if (ppa == 0) {
1035         freemsg(mp);
1036         return 1;
1037     }
1038     if ((q = ppa->lowerq) == 0) {
1039         /* try to send it up the control stream */
1040         if (canputnext(ppa->q)) {
1041             putnext(ppa->q, mp);
1042             return 1;
1043         }
1044     } else {
1045         if (canputnext(ppa->lowerq)) {
1046             /*
1047              * The lower write queue's put procedure just updates counters
1048              * and does a putnext.  We call it so that on SMP systems, we
1049              * enter the lower queues' perimeter so that the counter
1050              * updates are serialized.
1051              */
1052             put(ppa->lowerq, mp);
1053             return 1;
1054         }
1055     }
1056     us->flags |= US_BLOCKED;
1057     return 0;
1058 }
1059
1060 /*
1061  * Allocate a new PPA id and link this stream into the list of PPAs.
1062  * This procedure is called with an exclusive lock on all queues in
1063  * this driver.
1064  */
1065 static void
1066 new_ppa(q, mp)
1067     queue_t *q;
1068     mblk_t *mp;
1069 {
1070     upperstr_t *us, **usp;
1071     int ppa_id;
1072
1073     usp = &ppas;
1074     ppa_id = 0;
1075     while ((us = *usp) != 0 && ppa_id == us->ppa_id) {
1076         ++ppa_id;
1077         usp = &us->nextppa;
1078     }
1079     us = (upperstr_t *) q->q_ptr;
1080     us->ppa_id = ppa_id;
1081     us->ppa = us;
1082     us->next = 0;
1083     us->nextppa = *usp;
1084     *usp = us;
1085     us->flags |= US_CONTROL;
1086
1087     us->mtu = PPP_MRU;
1088     us->mru = PPP_MRU;
1089
1090 #ifdef SOL2
1091     /*
1092      * Create a kstats record for our statistics, so netstat -i works.
1093      */
1094     if (us->kstats == 0) {
1095         char unit[32];
1096
1097         sprintf(unit, "ppp%d", us->ppa->ppa_id);
1098         us->kstats = kstat_create("ppp", us->ppa->ppa_id, unit,
1099                                   "net", KSTAT_TYPE_NAMED, 4, 0);
1100         if (us->kstats != 0) {
1101             kstat_named_t *kn = KSTAT_NAMED_PTR(us->kstats);
1102
1103             strcpy(kn[0].name, "ipackets");
1104             kn[0].data_type = KSTAT_DATA_ULONG;
1105             strcpy(kn[1].name, "ierrors");
1106             kn[1].data_type = KSTAT_DATA_ULONG;
1107             strcpy(kn[2].name, "opackets");
1108             kn[2].data_type = KSTAT_DATA_ULONG;
1109             strcpy(kn[3].name, "oerrors");
1110             kn[3].data_type = KSTAT_DATA_ULONG;
1111             kstat_install(us->kstats);
1112         }
1113     }
1114 #endif /* SOL2 */
1115
1116     *(int *)mp->b_cont->b_rptr = ppa_id;
1117     mp->b_datap->db_type = M_IOCACK;
1118     qreply(q, mp);
1119 }
1120
1121 static void
1122 attach_ppa(q, mp)
1123     queue_t *q;
1124     mblk_t *mp;
1125 {
1126     upperstr_t *us, *t;
1127
1128     us = (upperstr_t *) q->q_ptr;
1129 #ifndef NO_DLPI
1130     us->state = DL_UNBOUND;
1131 #endif
1132     for (t = us->ppa; t->next != 0; t = t->next)
1133         ;
1134     t->next = us;
1135     us->next = 0;
1136     if (mp->b_datap->db_type == M_IOCTL) {
1137         mp->b_datap->db_type = M_IOCACK;
1138         qreply(q, mp);
1139     } else {
1140 #ifndef NO_DLPI
1141         dlpi_ok(q, DL_ATTACH_REQ);
1142 #endif
1143     }
1144 }
1145
1146 static void
1147 detach_ppa(q, mp)
1148     queue_t *q;
1149     mblk_t *mp;
1150 {
1151     upperstr_t *us, *t;
1152
1153     us = (upperstr_t *) q->q_ptr;
1154     for (t = us->ppa; t->next != 0; t = t->next)
1155         if (t->next == us) {
1156             t->next = us->next;
1157             break;
1158         }
1159     us->next = 0;
1160     us->ppa = 0;
1161 #ifndef NO_DLPI
1162     us->state = DL_UNATTACHED;
1163     dlpi_ok(q, DL_DETACH_REQ);
1164 #endif
1165 }
1166
1167 static int
1168 pppuwsrv(q)
1169     queue_t *q;
1170 {
1171     upperstr_t *us;
1172     struct lowerstr *ls;
1173     queue_t *lwq;
1174     mblk_t *mp;
1175
1176     us = (upperstr_t *) q->q_ptr;
1177     us->flags &= ~US_BLOCKED;
1178     while ((mp = getq(q)) != 0) {
1179         if (!send_data(mp, us)) {
1180             putbq(q, mp);
1181             break;
1182         }
1183     }
1184     return 0;
1185 }
1186
1187 static int
1188 ppplwput(q, mp)
1189     queue_t *q;
1190     mblk_t *mp;
1191 {
1192     upperstr_t *ppa;
1193
1194     ppa = (upperstr_t *) q->q_ptr;
1195     if (ppa != 0) {             /* why wouldn't it? */
1196         ppa->stats.ppp_opackets++;
1197         ppa->stats.ppp_obytes += msgdsize(mp);
1198 #ifdef INCR_OPACKETS
1199         INCR_OPACKETS(ppa);
1200 #endif
1201     }
1202     putnext(q, mp);
1203     return 0;
1204 }
1205
1206 static int
1207 ppplwsrv(q)
1208     queue_t *q;
1209 {
1210     upperstr_t *us;
1211
1212     /*
1213      * Flow control has back-enabled this stream:
1214      * enable the write service procedures of all upper
1215      * streams feeding this lower stream.
1216      */
1217     for (us = (upperstr_t *) q->q_ptr; us != NULL; us = us->next)
1218         if (us->flags & US_BLOCKED)
1219             qenable(WR(us->q));
1220     return 0;
1221 }
1222
1223 static int
1224 pppursrv(q)
1225     queue_t *q;
1226 {
1227     upperstr_t *us, *as;
1228     mblk_t *mp, *hdr;
1229 #ifndef NO_DLPI
1230     dl_unitdata_ind_t *ud;
1231 #endif
1232     int proto;
1233
1234     us = (upperstr_t *) q->q_ptr;
1235     if (us->flags & US_CONTROL) {
1236         /*
1237          * A control stream.
1238          * If there is no lower queue attached, run the write service
1239          * routines of other upper streams attached to this PPA.
1240          */
1241         if (us->lowerq == 0) {
1242             as = us;
1243             do {
1244                 if (as->flags & US_BLOCKED)
1245                     qenable(WR(as->q));
1246                 as = as->next;
1247             } while (as != 0);
1248         }
1249     } else {
1250         /*
1251          * A network protocol stream.  Put a DLPI header on each
1252          * packet and send it on.
1253          * (Actually, it seems that the IP module will happily
1254          * accept M_DATA messages without the DL_UNITDATA_IND header.)
1255          */
1256         while ((mp = getq(q)) != 0) {
1257             if (!canputnext(q)) {
1258                 putbq(q, mp);
1259                 break;
1260             }
1261 #ifndef NO_DLPI
1262             proto = PPP_PROTOCOL(mp->b_rptr);
1263             mp->b_rptr += PPP_HDRLEN;
1264             hdr = allocb(sizeof(dl_unitdata_ind_t) + 2 * sizeof(ulong),
1265                          BPRI_MED);
1266             if (hdr == 0) {
1267                 /* XXX should put it back and use bufcall */
1268                 freemsg(mp);
1269                 continue;
1270             }
1271             hdr->b_datap->db_type = M_PROTO;
1272             ud = (dl_unitdata_ind_t *) hdr->b_wptr;
1273             hdr->b_wptr += sizeof(dl_unitdata_ind_t) + 2 * sizeof(ulong);
1274             hdr->b_cont = mp;
1275             ud->dl_primitive = DL_UNITDATA_IND;
1276             ud->dl_dest_addr_length = sizeof(ulong);
1277             ud->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
1278             ud->dl_src_addr_length = sizeof(ulong);
1279             ud->dl_src_addr_offset = ud->dl_dest_addr_offset + sizeof(ulong);
1280 #if DL_CURRENT_VERSION >= 2
1281             ud->dl_group_address = 0;
1282 #endif
1283             /* Send the DLPI client the data with the SAP they requested,
1284                (e.g. ETHERTYPE_IP) rather than the PPP protocol number
1285                (e.g. PPP_IP) */
1286             ((ulong *)(ud + 1))[0] = us->req_sap;       /* dest SAP */
1287             ((ulong *)(ud + 1))[1] = us->req_sap;       /* src SAP */
1288             putnext(q, hdr);
1289 #else /* NO_DLPI */
1290             putnext(q, mp);
1291 #endif /* NO_DLPI */
1292         }
1293     }
1294
1295     /*
1296      * If this stream is attached to a PPA with a lower queue pair,
1297      * enable the read queue's service routine if it has data queued.
1298      * XXX there is a possibility that packets could get out of order
1299      * if ppplrput now runs before ppplrsrv.
1300      */
1301     if (us->ppa != 0 && us->ppa->lowerq != 0)
1302         qenable(RD(us->ppa->lowerq));
1303
1304     return 0;
1305 }
1306
1307 static upperstr_t *
1308 find_dest(ppa, proto)
1309     upperstr_t *ppa;
1310     int proto;
1311 {
1312     upperstr_t *us;
1313
1314     for (us = ppa->next; us != 0; us = us->next)
1315         if (proto == us->sap)
1316             break;
1317     return us;
1318 }
1319
1320 static int
1321 ppplrput(q, mp)
1322     queue_t *q;
1323     mblk_t *mp;
1324 {
1325     upperstr_t *ppa, *us;
1326     queue_t *uq;
1327     int proto, len;
1328     mblk_t *np;
1329     struct iocblk *iop;
1330
1331     ppa = (upperstr_t *) q->q_ptr;
1332     if (ppa == 0) {
1333         DPRINT1("ppplrput: q = %x, ppa = 0??\n", q);
1334         freemsg(mp);
1335         return 0;
1336     }
1337     switch (mp->b_datap->db_type) {
1338     case M_FLUSH:
1339         if (*mp->b_rptr & FLUSHW) {
1340             *mp->b_rptr &= ~FLUSHR;
1341             qreply(q, mp);
1342         } else
1343             freemsg(mp);
1344         break;
1345
1346     case M_CTL:
1347         switch (*mp->b_rptr) {
1348         case PPPCTL_IERROR:
1349 #ifdef INCR_IERRORS
1350             INCR_IERRORS(ppa);
1351 #endif
1352             ppa->stats.ppp_ierrors++;
1353             break;
1354         case PPPCTL_OERROR:
1355 #ifdef INCR_OERRORS
1356             INCR_OERRORS(ppa);
1357 #endif
1358             ppa->stats.ppp_oerrors++;
1359             break;
1360         }
1361         freemsg(mp);
1362         break;
1363
1364     case M_IOCACK:
1365     case M_IOCNAK:
1366         /*
1367          * Attempt to match up the response with the stream
1368          * that the request came from.
1369          */
1370         iop = (struct iocblk *) mp->b_rptr;
1371         for (us = ppa; us != 0; us = us->next)
1372             if (us->ioc_id == iop->ioc_id)
1373                 break;
1374         if (us == 0)
1375             freemsg(mp);
1376         else
1377             putnext(us->q, mp);
1378         break;
1379
1380     default:
1381         if (mp->b_datap->db_type == M_DATA) {
1382             len = msgdsize(mp);
1383             if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN) {
1384                 PULLUP(mp, PPP_HDRLEN);
1385                 if (mp == 0) {
1386                     DPRINT1("ppp_lrput: msgpullup failed (len=%d)\n", len);
1387                     break;
1388                 }
1389             }
1390             ppa->stats.ppp_ipackets++;
1391             ppa->stats.ppp_ibytes += len;
1392 #ifdef INCR_IPACKETS
1393             INCR_IPACKETS(ppa);
1394 #endif
1395             proto = PPP_PROTOCOL(mp->b_rptr);
1396             if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
1397                 /*
1398                  * A data packet for some network protocol.
1399                  * Queue it on the upper stream for that protocol.
1400                  */
1401                 if (canput(us->q))
1402                     putq(us->q, mp);
1403                 else
1404                     putq(q, mp);
1405                 break;
1406             }
1407         }
1408         /*
1409          * A control frame, a frame for an unknown protocol,
1410          * or some other message type.
1411          * Send it up to pppd via the control stream.
1412          */
1413         if (queclass(mp) == QPCTL || canputnext(ppa->q))
1414             putnext(ppa->q, mp);
1415         else
1416             putq(q, mp);
1417         break;
1418     }
1419
1420     return 0;
1421 }
1422
1423 static int
1424 ppplrsrv(q)
1425     queue_t *q;
1426 {
1427     mblk_t *mp;
1428     upperstr_t *ppa, *us;
1429     int proto;
1430
1431     /*
1432      * Packets only get queued here for flow control reasons.
1433      */
1434     ppa = (upperstr_t *) q->q_ptr;
1435     while ((mp = getq(q)) != 0) {
1436         if (mp->b_datap->db_type == M_DATA
1437             && (proto = PPP_PROTOCOL(mp->b_rptr)) < 0x8000
1438             && (us = find_dest(ppa, proto)) != 0) {
1439             if (canput(us->q))
1440                 putq(us->q, mp);
1441             else {
1442                 putbq(q, mp);
1443                 break;
1444             }
1445         } else {
1446             if (canputnext(ppa->q))
1447                 putnext(ppa->q, mp);
1448             else {
1449                 putbq(q, mp);
1450                 break;
1451             }
1452         }
1453     }
1454     return 0;
1455 }
1456
1457 static int
1458 putctl2(q, type, code, val)
1459     queue_t *q;
1460     int type, code, val;
1461 {
1462     mblk_t *mp;
1463
1464     mp = allocb(2, BPRI_HI);
1465     if (mp == 0)
1466         return 0;
1467     mp->b_datap->db_type = type;
1468     mp->b_wptr[0] = code;
1469     mp->b_wptr[1] = val;
1470     mp->b_wptr += 2;
1471     putnext(q, mp);
1472     return 1;
1473 }
1474
1475 static int
1476 putctl4(q, type, code, val)
1477     queue_t *q;
1478     int type, code, val;
1479 {
1480     mblk_t *mp;
1481
1482     mp = allocb(4, BPRI_HI);
1483     if (mp == 0)
1484         return 0;
1485     mp->b_datap->db_type = type;
1486     mp->b_wptr[0] = code;
1487     ((short *)mp->b_wptr)[1] = val;
1488     mp->b_wptr += 4;
1489     putnext(q, mp);
1490     return 1;
1491 }
1492
1493 static void
1494 debug_dump(q, mp)
1495     queue_t *q;                 /* not used */
1496     mblk_t *mp;                 /* not used either */
1497 {
1498     upperstr_t *us;
1499     queue_t *uq, *lq;
1500
1501     DPRINT("ppp upper streams:\n");
1502     for (us = minor_devs; us != 0; us = us->nextmn) {
1503         uq = us->q;
1504         DPRINT3(" %d: q=%x rlev=%d",
1505                 us->mn, uq, (uq? qsize(uq): 0));
1506         DPRINT3(" wlev=%d flags=0x%b", (uq? qsize(WR(uq)): 0),
1507                 us->flags, "\020\1priv\2control\3blocked\4last");
1508         DPRINT3(" state=%x sap=%x req_sap=%x", us->state, us->sap,
1509                 us->req_sap);
1510         if (us->ppa == 0)
1511             DPRINT(" ppa=?\n");
1512         else
1513             DPRINT1(" ppa=%d\n", us->ppa->ppa_id);
1514         if (us->flags & US_CONTROL) {
1515             lq = us->lowerq;
1516             DPRINT3("    control for %d lq=%x rlev=%d",
1517                     us->ppa_id, lq, (lq? qsize(RD(lq)): 0));
1518             DPRINT3(" wlev=%d mru=%d mtu=%d\n",
1519                     (lq? qsize(lq): 0), us->mru, us->mtu);
1520         }
1521     }
1522 }