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