2 * ppp.c - STREAMS multiplexing pseudo-device driver for PPP.
4 * Copyright (c) 1994 The Australian National University.
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
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
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,
27 * $Id: ppp.c,v 1.4 1995/06/01 02:22:12 paulus Exp $
31 * This file is used under Solaris 2.
34 #include <sys/types.h>
35 #include <sys/param.h>
37 #include <sys/stream.h>
38 #include <sys/stropts.h>
39 #include <sys/errno.h>
40 #include <sys/cmn_err.h>
43 #include <sys/ioccom.h>
47 #include <sys/modctl.h>
48 #include <sys/kstat.h>
49 #include <sys/sunddi.h>
51 #include <net/ppp_defs.h>
52 #include <net/pppio.h>
61 * The IP module uses this SAP value for IP packets.
64 #define ETHERTYPE_IP 0x800
68 #define PPP_MAXMTU 65535
72 * Private information; one per upper stream.
74 typedef struct upperstr {
75 minor_t mn; /* minor device number */
76 struct upperstr *nextmn; /* next minor device */
77 queue_t *q; /* read q associated with this upper stream */
78 int flags; /* flag bits, see below */
79 int state; /* current DLPI state */
80 int sap; /* service access point */
81 int req_sap; /* which SAP the DLPI client requested */
82 struct upperstr *ppa; /* control stream for our ppa */
83 struct upperstr *next; /* next stream for this ppa */
84 uint ioc_id; /* last ioctl ID for this stream */
86 * There is exactly one control stream for each PPA.
87 * The following fields are only used for control streams.
90 queue_t *lowerq; /* write queue attached below this PPA */
91 struct upperstr *nextppa; /* next control stream */
94 struct pppstat stats; /* statistics */
96 kstat_t *kstats; /* stats for netstat */
100 /* Values for flags */
101 #define US_PRIV 1 /* stream was opened by superuser */
102 #define US_CONTROL 2 /* stream is a control stream */
103 #define US_BLOCKED 4 /* flow ctrl has blocked lower write stream */
104 #define US_LASTMOD 8 /* no PPP modules below us */
106 static upperstr_t *minor_devs = NULL;
107 static upperstr_t *ppas = NULL;
110 static int ppp_identify __P((dev_info_t *));
111 static int ppp_attach __P((dev_info_t *, ddi_attach_cmd_t));
112 static int ppp_detach __P((dev_info_t *, ddi_detach_cmd_t));
113 static int ppp_devinfo __P((dev_info_t *, ddi_info_cmd_t, void *, void **));
115 static int pppopen __P((queue_t *, dev_t *, int, int, cred_t *));
116 static int pppclose __P((queue_t *, int, cred_t *));
117 static int pppuwput __P((queue_t *, mblk_t *));
118 static int pppursrv __P((queue_t *));
119 static int pppuwsrv __P((queue_t *));
120 static int ppplrput __P((queue_t *, mblk_t *));
121 static int ppplwput __P((queue_t *, mblk_t *));
122 static int ppplrsrv __P((queue_t *));
123 static int ppplwsrv __P((queue_t *));
124 static void dlpi_request __P((queue_t *, mblk_t *, upperstr_t *));
125 static void dlpi_error __P((queue_t *, int, int, int));
126 static void dlpi_ok __P((queue_t *, int));
127 static int send_data __P((mblk_t *, upperstr_t *));
128 static void new_ppa __P((queue_t *, mblk_t *));
129 static void attach_ppa __P((queue_t *, mblk_t *));
130 static void detach_ppa __P((queue_t *, mblk_t *));
131 static upperstr_t *find_dest __P((upperstr_t *, int));
132 static int putctl2 __P((queue_t *, int, int, int));
133 static int putctl4 __P((queue_t *, int, int, int));
135 static struct module_info ppp_info = {
136 0xb1a6, "ppp", 0, 512, 512, 128
139 static struct qinit pppurint = {
140 NULL, pppursrv, pppopen, pppclose, NULL, &ppp_info, NULL
143 static struct qinit pppuwint = {
144 pppuwput, pppuwsrv, NULL, NULL, NULL, &ppp_info, NULL
147 static struct qinit ppplrint = {
148 ppplrput, ppplrsrv, NULL, NULL, NULL, &ppp_info, NULL
151 static struct qinit ppplwint = {
152 ppplwput, ppplwsrv, NULL, NULL, NULL, &ppp_info, NULL
155 static struct streamtab pppinfo = {
156 &pppurint, &pppuwint,
161 static dev_info_t *ppp_dip;
163 static struct cb_ops cb_ppp_ops = {
164 nulldev, nulldev, nodev, nodev, /* cb_open, ... */
165 nodev, nodev, nodev, nodev, /* cb_dump, ... */
166 nodev, nodev, nodev, nochpoll, /* cb_devmap, ... */
167 ddi_prop_op, /* cb_prop_op */
168 &pppinfo, /* cb_stream */
169 D_NEW|D_MP|D_MTQPAIR|D_MTOUTPERIM|D_MTOCEXCL /* cb_flag */
172 static struct dev_ops ppp_ops = {
173 DEVO_REV, /* devo_rev */
175 ppp_devinfo, /* devo_getinfo */
176 ppp_identify, /* devo_identify */
177 nulldev, /* devo_probe */
178 ppp_attach, /* devo_attach */
179 ppp_detach, /* devo_detach */
180 nodev, /* devo_reset */
181 &cb_ppp_ops, /* devo_cb_ops */
182 NULL /* devo_bus_ops */
186 * Module linkage information
189 static struct modldrv modldrv = {
190 &mod_driverops, /* says this is a pseudo driver */
191 "PPP-2.2 multiplexing driver",
192 &ppp_ops /* driver ops */
195 static struct modlinkage modlinkage = {
204 return mod_install(&modlinkage);
210 return mod_remove(&modlinkage);
217 return mod_info(&modlinkage, mip);
224 return strcmp(ddi_get_name(dip), "ppp") == 0? DDI_IDENTIFIED:
231 ddi_attach_cmd_t cmd;
234 if (cmd != DDI_ATTACH)
236 if (ddi_create_minor_node(dip, "ppp", S_IFCHR, 0, DDI_PSEUDO, CLONE_DEV)
238 ddi_remove_minor_node(dip, NULL);
247 ddi_detach_cmd_t cmd;
249 ddi_remove_minor_node(dip, NULL);
254 ppp_devinfo(dip, cmd, arg, result)
264 case DDI_INFO_DEVT2DEVINFO:
268 *result = (void *) ppp_dip;
270 case DDI_INFO_DEVT2INSTANCE:
282 # define qprocsoff(q)
283 # define canputnext(q) canput((q)->q_next)
284 # define qwriter(q, mp, func, scope) (func)((q), (mp))
288 pppopen(q, devp, oflag, sflag, credp)
299 return 0; /* device is already open */
301 if (sflag == CLONEOPEN) {
303 for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
309 mn = getminor(*devp);
310 for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
315 /* this can't happen */
316 q->q_ptr = WR(q)->q_ptr = up;
322 * Construct a new minor node.
324 up = (upperstr_t *) kmem_zalloc(sizeof(upperstr_t), KM_SLEEP);
326 cmn_err(CE_CONT, "pppopen: out of kernel memory\n");
332 *devp = makedevice(getmajor(*devp), mn);
334 if (drv_priv(credp) == 0)
335 up->flags |= US_PRIV;
336 up->state = DL_UNATTACHED;
347 pppclose(q, flag, credp)
352 upperstr_t *up, **upp;
353 upperstr_t *as, *asnext;
358 up = (upperstr_t *) q->q_ptr;
361 if (up->flags & US_CONTROL) {
363 * This stream represents a PPA:
364 * For all streams attached to the PPA, clear their
365 * references to this PPA.
366 * Then remove this PPA from the list of PPAs.
368 for (as = up->next; as != 0; as = asnext) {
372 if (as->flags & US_BLOCKED) {
373 as->flags &= ~US_BLOCKED;
374 flushq(WR(as->q), FLUSHDATA);
377 for (upp = &ppas; *upp != 0; upp = &(*upp)->nextppa)
385 * If this stream is attached to a PPA,
386 * remove it from the PPA's list.
388 if ((as = up->ppa) != 0) {
389 for (; as->next != 0; as = as->next)
390 if (as->next == up) {
398 kstat_delete(up->kstats);
403 for (prevp = &minor_devs; *prevp != 0; prevp = &(*prevp)->nextmn) {
409 kmem_free(up, sizeof(upperstr_t));
415 * A message from on high. We do one of three things:
417 * - put the message on the lower write stream
418 * - queue it for our service routine
425 upperstr_t *us, *usnext, *ppa;
432 us = (upperstr_t *) q->q_ptr;
433 switch (mp->b_datap->db_type) {
436 dlpi_request(q, mp, us);
440 if ((us->flags & US_CONTROL) == 0
441 || msgdsize(mp) > us->mtu + PPP_HDRLEN) {
443 cmn_err(CE_CONT, "pppuwput: junk data len=%d\n", msgdsize(mp));
448 if (!send_data(mp, us))
453 iop = (struct iocblk *) mp->b_rptr;
455 switch (iop->ioc_cmd) {
457 if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0)
459 lb = (struct linkblk *) mp->b_cont->b_rptr;
460 us->lowerq = lq = lb->l_qbot;
465 us->flags &= ~US_LASTMOD;
466 /* Unblock upper streams which now feed this lower stream. */
468 /* Send useful information down to the modules which
469 are now linked below us. */
470 putctl2(lq, M_CTL, PPPCTL_UNIT, us->ppa_id);
471 putctl4(lq, M_CTL, PPPCTL_MRU, us->mru);
472 putctl4(lq, M_CTL, PPPCTL_MTU, us->mtu);
476 lb = (struct linkblk *) mp->b_cont->b_rptr;
478 if (us->lowerq != lb->l_qbot)
479 cmn_err(CE_CONT, "ppp unlink: lowerq=%x qbot=%x\n",
480 us->lowerq, lb->l_qbot);
485 /* Unblock streams which now feed back up the control stream. */
490 if (us->flags & US_CONTROL)
492 if ((us->flags & US_PRIV) == 0) {
496 /* Arrange to return an int */
497 if ((mq = mp->b_cont) == 0
498 || mq->b_datap->db_lim - mq->b_rptr < sizeof(int)) {
499 mq = allocb(sizeof(int), BPRI_HI);
509 iop->ioc_count = sizeof(int);
510 mq->b_wptr = mq->b_rptr + sizeof(int);
511 qwriter(q, mp, new_ppa, PERIM_OUTER);
516 /* like dlpi_attach, for programs which can't write to
517 the stream (like pppstats) */
518 if (iop->ioc_count != sizeof(int) || us->ppa != 0)
520 n = *(int *)mp->b_cont->b_rptr;
521 for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
522 if (ppa->ppa_id == n)
528 qwriter(q, mp, attach_ppa, PERIM_OUTER);
533 if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
535 n = *(int *)mp->b_cont->b_rptr;
536 if (n <= 0 || n > PPP_MAXMTU)
542 putctl4(us->lowerq, M_CTL, PPPCTL_MRU, n);
548 if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
550 n = *(int *)mp->b_cont->b_rptr;
551 if (n <= 0 || n > PPP_MAXMTU)
557 putctl4(us->lowerq, M_CTL, PPPCTL_MTU, n);
563 us->flags |= US_LASTMOD;
568 if (us->ppa == 0 || us->ppa->lowerq == 0)
570 us->ioc_id = iop->ioc_id;
572 switch (iop->ioc_cmd) {
575 if (us->flags & US_LASTMOD) {
579 putnext(us->ppa->lowerq, mp);
582 if (us->flags & US_PRIV)
583 putnext(us->ppa->lowerq, mp);
586 cmn_err(CE_CONT, "ppp ioctl %x rejected\n", iop->ioc_cmd);
596 iop->ioc_error = error;
597 mp->b_datap->db_type = M_IOCNAK;
599 } else if (error == 0) {
600 mp->b_datap->db_type = M_IOCACK;
606 if (*mp->b_rptr & FLUSHW)
607 flushq(q, FLUSHDATA);
608 if (*mp->b_rptr & FLUSHR) {
609 *mp->b_rptr &= ~FLUSHW;
623 dlpi_request(q, mp, us)
628 union DL_primitives *d = (union DL_primitives *) mp->b_rptr;
629 int size = mp->b_wptr - mp->b_rptr;
631 upperstr_t *ppa, *os;
636 switch (d->dl_primitive) {
638 if (size < sizeof(dl_info_req_t))
640 if ((reply = allocb(sizeof(dl_info_ack_t), BPRI_HI)) == 0)
641 break; /* should do bufcall */
642 reply->b_datap->db_type = M_PCPROTO;
643 info = (dl_info_ack_t *) reply->b_wptr;
644 reply->b_wptr += sizeof(dl_info_ack_t);
645 bzero((caddr_t) info, sizeof(dl_info_ack_t));
646 info->dl_primitive = DL_INFO_ACK;
647 info->dl_max_sdu = PPP_MAXMTU;
648 info->dl_min_sdu = 1;
649 info->dl_addr_length = sizeof(ulong);
651 info->dl_mac_type = DL_OTHER;
653 info->dl_mac_type = DL_HDLC; /* a lie */
655 info->dl_current_state = us->state;
656 info->dl_service_mode = DL_CLDLS;
657 info->dl_provider_style = DL_STYLE2;
658 #if DL_CURRENT_VERSION >= 2
659 info->dl_sap_length = sizeof(ulong);
660 info->dl_version = DL_CURRENT_VERSION;
666 if (size < sizeof(dl_attach_req_t))
668 if (us->state != DL_UNATTACHED || us->ppa != 0) {
669 dlpi_error(q, DL_ATTACH_REQ, DL_OUTSTATE, 0);
672 for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
673 if (ppa->ppa_id == d->attach_req.dl_ppa)
676 dlpi_error(q, DL_ATTACH_REQ, DL_BADPPA, 0);
680 qwriter(q, mp, attach_ppa, PERIM_OUTER);
684 if (size < sizeof(dl_detach_req_t))
686 if (us->state != DL_UNBOUND || us->ppa == 0) {
687 dlpi_error(q, DL_DETACH_REQ, DL_OUTSTATE, 0);
690 qwriter(q, mp, detach_ppa, PERIM_OUTER);
694 if (size < sizeof(dl_bind_req_t))
696 if (us->state != DL_UNBOUND || us->ppa == 0) {
697 dlpi_error(q, DL_BIND_REQ, DL_OUTSTATE, 0);
700 if (d->bind_req.dl_service_mode != DL_CLDLS) {
701 dlpi_error(q, DL_BIND_REQ, DL_UNSUPPORTED, 0);
705 /* saps must be valid PPP network protocol numbers,
706 except that we accept ETHERTYPE_IP in place of PPP_IP. */
707 sap = d->bind_req.dl_sap;
710 cmn_err(CE_CONT, "ppp bind %x\n", sap);
712 if (sap == ETHERTYPE_IP)
714 if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
715 dlpi_error(q, DL_BIND_REQ, DL_BADADDR, 0);
719 /* check that no other stream is bound to this sap already. */
720 for (os = us->ppa; os != 0; os = os->next)
724 dlpi_error(q, DL_BIND_REQ, DL_NOADDR, 0);
731 if ((reply = allocb(sizeof(dl_bind_ack_t) + sizeof(ulong),
733 break; /* should do bufcall */
734 ackp = (dl_bind_ack_t *) reply->b_wptr;
735 reply->b_wptr += sizeof(dl_bind_ack_t) + sizeof(ulong);
736 reply->b_datap->db_type = M_PCPROTO;
737 bzero((caddr_t) ackp, sizeof(dl_bind_ack_t));
738 ackp->dl_primitive = DL_BIND_ACK;
740 ackp->dl_addr_length = sizeof(ulong);
741 ackp->dl_addr_offset = sizeof(dl_bind_ack_t);
742 *(ulong *)(ackp+1) = sap;
747 if (size < sizeof(dl_unbind_req_t))
749 if (us->state != DL_IDLE) {
750 dlpi_error(q, DL_UNBIND_REQ, DL_OUTSTATE, 0);
754 us->state = DL_UNBOUND;
755 dlpi_ok(q, DL_UNBIND_REQ);
758 case DL_UNITDATA_REQ:
759 if (size < sizeof(dl_unitdata_req_t))
761 if (us->state != DL_IDLE) {
762 dlpi_error(q, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
766 cmn_err(CE_CONT, "ppp: in state dl_idle but ppa == 0?\n");
769 len = mp->b_cont == 0? 0: msgdsize(mp->b_cont);
770 if (len > us->ppa->mtu) {
772 cmn_err(CE_CONT, "dlpi data too large (%d > %d)\n", len, us->mtu);
776 /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
777 if (mp->b_datap->db_ref > 1) {
778 np = allocb(PPP_HDRLEN, BPRI_HI);
781 np->b_cont = mp->b_cont;
786 mp->b_datap->db_type = M_DATA;
787 /* XXX should use dl_dest_addr_offset/length here,
788 but we would have to translate ETHERTYPE_IP -> PPP_IP */
789 mp->b_wptr = mp->b_rptr + PPP_HDRLEN;
790 mp->b_rptr[0] = PPP_ALLSTATIONS;
791 mp->b_rptr[1] = PPP_UI;
792 mp->b_rptr[2] = us->sap >> 8;
793 mp->b_rptr[3] = us->sap;
794 if (!send_data(mp, us))
798 #if DL_CURRENT_VERSION >= 2
799 case DL_SUBS_BIND_REQ:
800 case DL_SUBS_UNBIND_REQ:
801 case DL_ENABMULTI_REQ:
802 case DL_DISABMULTI_REQ:
803 case DL_PROMISCON_REQ:
804 case DL_PROMISCOFF_REQ:
805 case DL_SET_PHYS_ADDR_REQ:
808 case DL_REPLY_UPDATE_REQ:
810 case DL_DATA_ACK_REQ:
814 dlpi_error(q, d->dl_primitive, DL_NOTSUPPORTED, 0);
818 case DL_DISCONNECT_REQ:
821 dlpi_error(q, d->dl_primitive, DL_OUTSTATE, 0);
825 dlpi_error(q, d->dl_primitive, DL_BADQOSTYPE, 0);
828 #if DL_CURRENT_VERSION >= 2
835 cmn_err(CE_CONT, "ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);
838 dlpi_error(q, d->dl_primitive, DL_BADPRIM, 0);
845 dlpi_error(q, prim, err, uerr)
850 dl_error_ack_t *errp;
852 reply = allocb(sizeof(dl_error_ack_t), BPRI_HI);
854 return; /* XXX should do bufcall */
855 reply->b_datap->db_type = M_PCPROTO;
856 errp = (dl_error_ack_t *) reply->b_wptr;
857 reply->b_wptr += sizeof(dl_error_ack_t);
858 errp->dl_primitive = DL_ERROR_ACK;
859 errp->dl_error_primitive = prim;
860 errp->dl_errno = err;
861 errp->dl_unix_errno = uerr;
873 reply = allocb(sizeof(dl_ok_ack_t), BPRI_HI);
875 return; /* XXX should do bufcall */
876 reply->b_datap->db_type = M_PCPROTO;
877 okp = (dl_ok_ack_t *) reply->b_wptr;
878 reply->b_wptr += sizeof(dl_ok_ack_t);
879 okp->dl_primitive = DL_OK_ACK;
880 okp->dl_correct_primitive = prim;
892 if (us->flags & US_BLOCKED)
899 if ((q = ppa->lowerq) == 0) {
900 /* try to send it up the control stream */
901 if (canputnext(ppa->q)) {
906 if (canputnext(ppa->lowerq)) {
908 * The lower write queue's put procedure just updates counters
909 * and does a putnext. We call it in order to enter the lower
910 * queues' perimeter so that the counter updates are serialized.
912 put(ppa->lowerq, mp);
916 us->flags |= US_BLOCKED;
921 * Allocate a new PPA id and link this stream into the list of PPAs.
922 * This procedure is called with an exclusive lock on all queues in
930 upperstr_t *us, **usp;
935 while ((us = *usp) != 0 && ppa_id == us->ppa_id) {
939 us = (upperstr_t *) q->q_ptr;
945 us->flags |= US_CONTROL;
951 if (us->kstats == 0) {
954 sprintf(unit, "ppp%d", us->ppa->ppa_id);
955 us->kstats = kstat_create("ppp", us->ppa->ppa_id, unit,
956 "net", KSTAT_TYPE_NAMED, 4, 0);
957 if (us->kstats != 0) {
958 kstat_named_t *kn = KSTAT_NAMED_PTR(us->kstats);
960 strcpy(kn[0].name, "ipackets");
961 kn[0].data_type = KSTAT_DATA_ULONG;
962 strcpy(kn[1].name, "ierrors");
963 kn[1].data_type = KSTAT_DATA_ULONG;
964 strcpy(kn[2].name, "opackets");
965 kn[2].data_type = KSTAT_DATA_ULONG;
966 strcpy(kn[3].name, "oerrors");
967 kn[3].data_type = KSTAT_DATA_ULONG;
968 kstat_install(us->kstats);
973 *(int *)mp->b_cont->b_rptr = ppa_id;
974 mp->b_datap->db_type = M_IOCACK;
985 us = (upperstr_t *) q->q_ptr;
986 us->state = DL_UNBOUND;
987 for (t = us->ppa; t->next != 0; t = t->next)
991 if (mp->b_datap->db_type == M_IOCTL) {
992 mp->b_datap->db_type = M_IOCACK;
995 dlpi_ok(q, DL_ATTACH_REQ);
1006 us = (upperstr_t *) q->q_ptr;
1007 for (t = us->ppa; t->next != 0; t = t->next)
1008 if (t->next == us) {
1014 us->state = DL_UNATTACHED;
1015 dlpi_ok(q, DL_DETACH_REQ);
1023 struct lowerstr *ls;
1027 us = (upperstr_t *) q->q_ptr;
1028 while ((mp = getq(q)) != 0) {
1029 if (!send_data(mp, us)) {
1035 us->flags &= ~US_BLOCKED;
1047 if (ppa != 0) { /* why wouldn't it? */
1048 ppa->stats.ppp_opackets++;
1049 ppa->stats.ppp_obytes += msgdsize(mp);
1050 if (ppa->kstats != 0)
1051 KSTAT_NAMED_PTR(ppa->kstats)[2].value.ul++;
1064 * Flow control has back-enabled this stream:
1065 * enable the write service procedures of all upper
1066 * streams feeding this lower stream.
1068 for (us = (upperstr_t *) q->q_ptr; us != NULL; us = us->next)
1069 if (us->flags & US_BLOCKED)
1078 upperstr_t *us, *as;
1080 dl_unitdata_ind_t *ud;
1084 * If this is a control stream and we don't have a lower queue attached,
1085 * run the write service routines of other streams attached to this PPA.
1087 us = (upperstr_t *) q->q_ptr;
1088 if (us->flags & US_CONTROL) {
1091 * If there is no lower queue attached, run the write service
1092 * routines of other upper streams attached to this PPA.
1094 if (us->lowerq == 0) {
1097 if (as->flags & US_BLOCKED)
1104 * A network protocol stream. Put a DLPI header on each
1105 * packet and send it on.
1107 while ((mp = getq(q)) != 0) {
1108 if (!canputnext(q)) {
1112 proto = PPP_PROTOCOL(mp->b_rptr);
1113 mp->b_rptr += PPP_HDRLEN;
1114 hdr = allocb(sizeof(dl_unitdata_ind_t) + 2 * sizeof(ulong),
1117 /* XXX should put it back and use bufcall */
1121 ud = (dl_unitdata_ind_t *) hdr->b_wptr;
1122 hdr->b_wptr += sizeof(dl_unitdata_ind_t) + 2 * sizeof(ulong);
1124 ud->dl_primitive = DL_UNITDATA_IND;
1125 ud->dl_dest_addr_length = sizeof(ulong);
1126 ud->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
1127 ud->dl_src_addr_length = sizeof(ulong);
1128 ud->dl_src_addr_offset = ud->dl_dest_addr_offset + sizeof(ulong);
1129 #if DL_CURRENT_VERSION >= 2
1130 ud->dl_group_address = 0;
1132 /* Send the DLPI client the data with the SAP they requested,
1133 (e.g. ETHERTYPE_IP) rather than the PPP protocol number
1135 ((ulong *)(ud + 1))[0] = us->req_sap; /* dest SAP */
1136 ((ulong *)(ud + 1))[1] = us->req_sap; /* src SAP */
1144 find_dest(ppa, proto)
1150 for (us = ppa->next; us != 0; us = us->next)
1151 if (proto == us->sap)
1161 upperstr_t *ppa, *us;
1167 ppa = (upperstr_t *) q->q_ptr;
1170 cmn_err(CE_CONT, "ppplrput: q = %x, ppa = 0??\n", q);
1175 switch (mp->b_datap->db_type) {
1177 if (*mp->b_rptr & FLUSHW) {
1178 *mp->b_rptr &= ~FLUSHR;
1185 switch (*mp->b_rptr) {
1187 if (ppa->kstats != 0) {
1188 KSTAT_NAMED_PTR(ppa->kstats)[1].value.ul++;
1190 ppa->stats.ppp_ierrors++;
1193 if (ppa->kstats != 0) {
1194 KSTAT_NAMED_PTR(ppa->kstats)[3].value.ul++;
1196 ppa->stats.ppp_oerrors++;
1205 * Attempt to match up the response with the stream
1206 * that the request came from.
1208 iop = (struct iocblk *) mp->b_rptr;
1209 for (us = ppa; us != 0; us = us->next)
1210 if (us->ioc_id == iop->ioc_id)
1219 if (mp->b_datap->db_type == M_DATA) {
1221 if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN) {
1222 np = msgpullup(mp, PPP_HDRLEN);
1226 cmn_err(CE_CONT, "ppp_lrput: msgpullup failed (len=%d)\n",
1233 ppa->stats.ppp_ipackets++;
1234 ppa->stats.ppp_ibytes += len;
1235 if (ppa->kstats != 0) {
1236 KSTAT_NAMED_PTR(ppa->kstats)[0].value.ul++;
1238 proto = PPP_PROTOCOL(mp->b_rptr);
1239 if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
1241 * A data packet for some network protocol.
1242 * Queue it on the upper stream for that protocol.
1252 * A control frame, a frame for an unknown protocol,
1253 * or some other message type.
1254 * Send it up to pppd via the control stream.
1256 if (queclass(mp) == QPCTL || canputnext(ppa->q))
1257 putnext(ppa->q, mp);
1271 upperstr_t *ppa, *us;
1275 * Packets only get queued here for flow control reasons.
1277 ppa = (upperstr_t *) q->q_ptr;
1278 while ((mp = getq(q)) != 0) {
1279 if (mp->b_datap->db_type == M_DATA
1280 && (proto = PPP_PROTOCOL(mp->b_rptr)) < 0x8000
1281 && (us = find_dest(ppa, proto)) != 0) {
1289 if (canputnext(ppa->q))
1290 putnext(ppa->q, mp);
1301 putctl2(q, type, code, val)
1303 int type, code, val;
1307 mp = allocb(2, BPRI_HI);
1310 mp->b_datap->db_type = type;
1311 mp->b_wptr[0] = code;
1312 mp->b_wptr[1] = val;
1319 putctl4(q, type, code, val)
1321 int type, code, val;
1325 mp = allocb(4, BPRI_HI);
1328 mp->b_datap->db_type = type;
1329 mp->b_wptr[0] = code;
1330 ((short *)mp->b_wptr)[1] = val;