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.1 1995/12/11 05:06:40 paulus Exp $
31 * This file is used under Solaris 2 and SunOS 4.
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/ioccom.h>
42 #include <sys/cmn_err.h>
47 #include <sys/kstat.h>
48 #include <sys/sunddi.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
53 #include <netinet/in.h>
58 #include <net/ppp_defs.h>
59 #include <net/pppio.h>
69 * The IP module uses this SAP value for IP packets.
72 #define ETHERTYPE_IP 0x800
76 #define PPP_MAXMTU 65535
80 * Private information; one per upper stream.
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 */
94 * There is exactly one control stream for each PPA.
95 * The following fields are only used for control streams.
98 queue_t *lowerq; /* write queue attached below this PPA */
99 struct upperstr *nextppa; /* next control stream */
102 struct pppstat stats; /* statistics */
104 kstat_t *kstats; /* stats for netstat */
108 char ifname[IFNAMSIZ];
109 struct ifstats ifstats;
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 */
120 static upperstr_t *minor_devs = NULL;
121 static upperstr_t *ppas = NULL;
124 static int pppopen __P((queue_t *, dev_t *, int, int, cred_t *));
125 static int pppclose __P((queue_t *, int, cred_t *));
127 static int pppopen __P((queue_t *, int, int, int));
128 static int pppclose __P((queue_t *, int));
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 *));
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));
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));
151 static struct module_info ppp_info = {
152 0xb1a6, "ppp", 0, 512, 512, 128
155 static struct qinit pppurint = {
156 NULL, pppursrv, pppopen, pppclose, NULL, &ppp_info, NULL
159 static struct qinit pppuwint = {
160 pppuwput, pppuwsrv, NULL, NULL, NULL, &ppp_info, NULL
163 static struct qinit ppplrint = {
164 ppplrput, ppplrsrv, NULL, NULL, NULL, &ppp_info, NULL
167 static struct qinit ppplwint = {
168 ppplwput, ppplwsrv, NULL, NULL, NULL, &ppp_info, NULL
172 extern struct ifstats *ifstats;
176 struct streamtab pppinfo = {
177 &pppurint, &pppuwint,
184 * How we maintain statistics.
187 #define INCR_IPACKETS(ppa) \
188 if (ppa->kstats != 0) { \
189 KSTAT_NAMED_PTR(ppa->kstats)[0].value.ul++; \
191 #define INCR_IERRORS(ppa) \
192 if (ppa->kstats != 0) { \
193 KSTAT_NAMED_PTR(ppa->kstats)[1].value.ul++; \
195 #define INCR_OPACKETS(ppa) \
196 if (ppa->kstats != 0) { \
197 KSTAT_NAMED_PTR(ppa->kstats)[2].value.ul++; \
199 #define INCR_OERRORS(ppa) \
200 if (ppa->kstats != 0) { \
201 KSTAT_NAMED_PTR(ppa->kstats)[3].value.ul++; \
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++;
213 * STREAMS driver entry points.
217 pppopen(q, devp, oflag, sflag, credp)
223 pppopen(q, dev, oflag, sflag)
225 int dev; /* really dev_t */
234 DRV_OPEN_OK(dev); /* device is already open */
236 if (sflag == CLONEOPEN) {
238 for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
245 mn = getminor(*devp);
249 for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
254 /* this can't happen */
255 q->q_ptr = WR(q)->q_ptr = (caddr_t) up;
261 * Construct a new minor node.
263 up = (upperstr_t *) ALLOC_SLEEP(sizeof(upperstr_t));
264 bzero((caddr_t) up, sizeof(upperstr_t));
266 DPRINT("pppopen: out of kernel memory\n");
273 *devp = makedevice(getmajor(*devp), mn);
277 up->flags |= US_PRIV;
279 up->state = DL_UNATTACHED;
282 up->ifflags = IFF_UP | IFF_POINTOPOINT;
285 q->q_ptr = (caddr_t) up;
286 WR(q)->q_ptr = (caddr_t) up;
291 DRV_OPEN_OK(makedev(major(dev), mn));
296 pppclose(q, flag, credp)
306 upperstr_t *up, **upp;
307 upperstr_t *as, *asnext;
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);
317 if (up->flags & US_CONTROL) {
319 struct ifstats *ifp, *pifp;
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.
327 for (as = up->next; as != 0; as = asnext) {
331 if (as->flags & US_BLOCKED) {
332 as->flags &= ~US_BLOCKED;
333 flushq(WR(as->q), FLUSHDATA);
336 for (upp = &ppas; *upp != 0; upp = &(*upp)->nextppa)
342 /* Remove the statistics from the active list. */
343 for (ifp = ifstats, pifp = 0; ifp; ifp = ifp->ifs_next) {
344 if (ifp == &up->ifstats) {
346 pifp->ifs_next = ifp->ifs_next;
348 ifstats = ifp->ifs_next;
356 * If this stream is attached to a PPA,
357 * remove it from the PPA's list.
359 if ((as = up->ppa) != 0) {
360 for (; as->next != 0; as = as->next)
361 if (as->next == up) {
370 kstat_delete(up->kstats);
376 for (prevp = &minor_devs; *prevp != 0; prevp = &(*prevp)->nextmn) {
382 kmem_free(up, sizeof(upperstr_t));
389 * A message from on high. We do one of three things:
391 * - put the message on the lower write stream
392 * - queue it for our service routine
399 upperstr_t *us, *usnext, *ppa, *os;
410 us = (upperstr_t *) q->q_ptr;
411 switch (mp->b_datap->db_type) {
415 dlpi_request(q, mp, us);
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
425 || (us->flags & US_CONTROL) == 0
428 DPRINT1("pppuwput: junk data len=%d\n", msgdsize(mp));
432 if (!send_data(mp, us))
437 iop = (struct iocblk *) mp->b_rptr;
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) {
444 if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0)
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;
451 flushq(RD(lq), FLUSHALL);
454 us->flags &= ~US_LASTMOD;
455 /* Unblock upper streams which now feed this lower stream. */
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);
465 lb = (struct linkblk *) mp->b_cont->b_rptr;
467 if (us->lowerq != lb->l_qbot)
468 DPRINT2("ppp unlink: lowerq=%x qbot=%x\n",
469 us->lowerq, lb->l_qbot);
474 /* Unblock streams which now feed back up the control stream. */
479 if (us->flags & US_CONTROL)
481 if ((us->flags & US_PRIV) == 0) {
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);
498 iop->ioc_count = sizeof(int);
499 mq->b_wptr = mq->b_rptr + sizeof(int);
500 qwriter(q, mp, new_ppa, PERIM_OUTER);
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)
509 n = *(int *)mp->b_cont->b_rptr;
510 for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
511 if (ppa->ppa_id == n)
517 qwriter(q, mp, attach_ppa, PERIM_OUTER);
523 /* Attach to a given SAP. */
524 if (iop->ioc_count != sizeof(int) || us->ppa == 0)
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)
530 /* check that no other stream is bound to this sap already. */
531 for (os = us->ppa; os != 0; os = os->next)
543 if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
545 n = *(int *)mp->b_cont->b_rptr;
546 if (n <= 0 || n > PPP_MAXMTU)
552 putctl4(us->lowerq, M_CTL, PPPCTL_MRU, n);
558 if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
560 n = *(int *)mp->b_cont->b_rptr;
561 if (n <= 0 || n > PPP_MAXMTU)
567 us->ifstats.ifs_mtu = n;
570 putctl4(us->lowerq, M_CTL, PPPCTL_MTU, n);
576 us->flags |= US_LASTMOD;
581 if (iop->ioc_count != sizeof(int))
583 n = *(int *)mp->b_cont->b_rptr;
584 if (n == PPPDBG_DUMP + PPPDBG_DRIVER) {
585 qwriter(q, NULL, debug_dump, PERIM_OUTER);
588 } else if (n == PPPDBG_LOG + PPPDBG_DRIVER) {
589 DPRINT1("ppp/%d: debug log enabled\n", us->mn);
590 us->flags |= US_DBGLOG;
594 if (us->ppa == 0 || us->ppa->lowerq == 0)
596 putnext(us->ppa->lowerq, mp);
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)
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'))
615 us->ifname[i] = ifr->ifr_name[i];
619 /* Convert the unit number to binary. */
620 for (n = 0; i < IFNAMSIZ; i++) {
621 if (ifr->ifr_name[i] == 0) {
625 n = n * 10 + ifr->ifr_name[i] - '0';
629 /* Verify the ppa. */
630 if (us->ppa->ppa_id != n)
634 /* Set up the netstat block. */
635 strncpy (ppa->ifname, us->ifname, IFNAMSIZ);
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;
642 /* Link in statistics used by netstat. */
643 ppa->ifstats.ifs_next = ifstats;
644 ifstats = &ppa->ifstats;
651 printf("SIOCGIFFLAGS\n");
652 if (!(us->flags & US_CONTROL)) {
658 ((struct iocblk_in *)iop)->ioc_ifflags = us->ifflags;
663 printf("SIOCSIFFLAGS\n");
664 if (!(us->flags & US_CONTROL)) {
670 us->ifflags = ((struct iocblk_in *)iop)->ioc_ifflags;
675 printf("SIOCSIFADDR\n");
676 if (!(us->flags & US_CONTROL)) {
682 us->ifflags |= IFF_RUNNING;
683 ((struct iocblk_in *)iop)->ioc_ifflags |= IFF_RUNNING;
698 if (us->ppa == 0 || us->ppa->lowerq == 0)
700 us->ioc_id = iop->ioc_id;
702 switch (iop->ioc_cmd) {
705 if (us->flags & US_LASTMOD) {
709 putnext(us->ppa->lowerq, mp);
712 if (us->flags & US_PRIV)
713 putnext(us->ppa->lowerq, mp);
715 DPRINT1("ppp ioctl %x rejected\n", iop->ioc_cmd);
724 iop->ioc_error = error;
725 mp->b_datap->db_type = M_IOCNAK;
727 } else if (error == 0) {
728 mp->b_datap->db_type = M_IOCACK;
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;
754 dlpi_request(q, mp, us)
759 union DL_primitives *d = (union DL_primitives *) mp->b_rptr;
760 int size = mp->b_wptr - mp->b_rptr;
762 upperstr_t *ppa, *os;
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) {
772 if (size < sizeof(dl_info_req_t))
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);
785 info->dl_mac_type = DL_OTHER;
787 info->dl_mac_type = DL_HDLC; /* a lie */
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;
800 if (size < sizeof(dl_attach_req_t))
802 if (us->state != DL_UNATTACHED || us->ppa != 0) {
803 dlpi_error(q, DL_ATTACH_REQ, DL_OUTSTATE, 0);
806 for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
807 if (ppa->ppa_id == d->attach_req.dl_ppa)
810 dlpi_error(q, DL_ATTACH_REQ, DL_BADPPA, 0);
814 qwriter(q, mp, attach_ppa, PERIM_OUTER);
818 if (size < sizeof(dl_detach_req_t))
820 if (us->state != DL_UNBOUND || us->ppa == 0) {
821 dlpi_error(q, DL_DETACH_REQ, DL_OUTSTATE, 0);
824 qwriter(q, mp, detach_ppa, PERIM_OUTER);
828 if (size < sizeof(dl_bind_req_t))
830 if (us->state != DL_UNBOUND || us->ppa == 0) {
831 dlpi_error(q, DL_BIND_REQ, DL_OUTSTATE, 0);
834 if (d->bind_req.dl_service_mode != DL_CLDLS) {
835 dlpi_error(q, DL_BIND_REQ, DL_UNSUPPORTED, 0);
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;
844 cmn_err(CE_CONT, "ppp bind %x\n", sap);
846 if (sap == ETHERTYPE_IP)
848 if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
849 dlpi_error(q, DL_BIND_REQ, DL_BADADDR, 0);
853 /* check that no other stream is bound to this sap already. */
854 for (os = us->ppa; os != 0; os = os->next)
858 dlpi_error(q, DL_BIND_REQ, DL_NOADDR, 0);
865 if ((reply = allocb(sizeof(dl_bind_ack_t) + sizeof(ulong),
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;
874 ackp->dl_addr_length = sizeof(ulong);
875 ackp->dl_addr_offset = sizeof(dl_bind_ack_t);
876 *(ulong *)(ackp+1) = sap;
881 if (size < sizeof(dl_unbind_req_t))
883 if (us->state != DL_IDLE) {
884 dlpi_error(q, DL_UNBIND_REQ, DL_OUTSTATE, 0);
888 us->state = DL_UNBOUND;
890 us->ppa->ifstats.ifs_active = 0;
892 dlpi_ok(q, DL_UNBIND_REQ);
895 case DL_UNITDATA_REQ:
896 if (size < sizeof(dl_unitdata_req_t))
898 if (us->state != DL_IDLE) {
899 dlpi_error(q, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
903 cmn_err(CE_CONT, "ppp: in state dl_idle but ppa == 0?\n");
906 len = mp->b_cont == 0? 0: msgdsize(mp->b_cont);
907 if (len > us->ppa->mtu) {
909 cmn_err(CE_CONT, "dlpi data too large (%d > %d)\n", len, us->mtu);
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);
918 np->b_cont = mp->b_cont;
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))
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:
946 case DL_REPLY_UPDATE_REQ:
948 case DL_DATA_ACK_REQ:
952 dlpi_error(q, d->dl_primitive, DL_NOTSUPPORTED, 0);
956 case DL_DISCONNECT_REQ:
959 dlpi_error(q, d->dl_primitive, DL_OUTSTATE, 0);
963 dlpi_error(q, d->dl_primitive, DL_BADQOSTYPE, 0);
966 #if DL_CURRENT_VERSION >= 2
973 cmn_err(CE_CONT, "ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);
976 dlpi_error(q, d->dl_primitive, DL_BADPRIM, 0);
983 dlpi_error(q, prim, err, uerr)
988 dl_error_ack_t *errp;
990 reply = allocb(sizeof(dl_error_ack_t), BPRI_HI);
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;
1011 reply = allocb(sizeof(dl_ok_ack_t), BPRI_HI);
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;
1021 #endif /* NO_DLPI */
1031 if (us->flags & US_BLOCKED)
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);
1045 if (canputnext(ppa->lowerq)) {
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.
1052 put(ppa->lowerq, mp);
1056 us->flags |= US_BLOCKED;
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
1070 upperstr_t *us, **usp;
1075 while ((us = *usp) != 0 && ppa_id == us->ppa_id) {
1079 us = (upperstr_t *) q->q_ptr;
1080 us->ppa_id = ppa_id;
1085 us->flags |= US_CONTROL;
1092 * Create a kstats record for our statistics, so netstat -i works.
1094 if (us->kstats == 0) {
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);
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);
1116 *(int *)mp->b_cont->b_rptr = ppa_id;
1117 mp->b_datap->db_type = M_IOCACK;
1128 us = (upperstr_t *) q->q_ptr;
1130 us->state = DL_UNBOUND;
1132 for (t = us->ppa; t->next != 0; t = t->next)
1136 if (mp->b_datap->db_type == M_IOCTL) {
1137 mp->b_datap->db_type = M_IOCACK;
1141 dlpi_ok(q, DL_ATTACH_REQ);
1153 us = (upperstr_t *) q->q_ptr;
1154 for (t = us->ppa; t->next != 0; t = t->next)
1155 if (t->next == us) {
1162 us->state = DL_UNATTACHED;
1163 dlpi_ok(q, DL_DETACH_REQ);
1172 struct lowerstr *ls;
1176 us = (upperstr_t *) q->q_ptr;
1177 us->flags &= ~US_BLOCKED;
1178 while ((mp = getq(q)) != 0) {
1179 if (!send_data(mp, us)) {
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
1213 * Flow control has back-enabled this stream:
1214 * enable the write service procedures of all upper
1215 * streams feeding this lower stream.
1217 for (us = (upperstr_t *) q->q_ptr; us != NULL; us = us->next)
1218 if (us->flags & US_BLOCKED)
1227 upperstr_t *us, *as;
1230 dl_unitdata_ind_t *ud;
1234 us = (upperstr_t *) q->q_ptr;
1235 if (us->flags & US_CONTROL) {
1238 * If there is no lower queue attached, run the write service
1239 * routines of other upper streams attached to this PPA.
1241 if (us->lowerq == 0) {
1244 if (as->flags & US_BLOCKED)
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.)
1256 while ((mp = getq(q)) != 0) {
1257 if (!canputnext(q)) {
1262 proto = PPP_PROTOCOL(mp->b_rptr);
1263 mp->b_rptr += PPP_HDRLEN;
1264 hdr = allocb(sizeof(dl_unitdata_ind_t) + 2 * sizeof(ulong),
1267 /* XXX should put it back and use bufcall */
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);
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;
1283 /* Send the DLPI client the data with the SAP they requested,
1284 (e.g. ETHERTYPE_IP) rather than the PPP protocol number
1286 ((ulong *)(ud + 1))[0] = us->req_sap; /* dest SAP */
1287 ((ulong *)(ud + 1))[1] = us->req_sap; /* src SAP */
1291 #endif /* NO_DLPI */
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.
1301 if (us->ppa != 0 && us->ppa->lowerq != 0)
1302 qenable(RD(us->ppa->lowerq));
1308 find_dest(ppa, proto)
1314 for (us = ppa->next; us != 0; us = us->next)
1315 if (proto == us->sap)
1325 upperstr_t *ppa, *us;
1331 ppa = (upperstr_t *) q->q_ptr;
1333 DPRINT1("ppplrput: q = %x, ppa = 0??\n", q);
1337 switch (mp->b_datap->db_type) {
1339 if (*mp->b_rptr & FLUSHW) {
1340 *mp->b_rptr &= ~FLUSHR;
1347 switch (*mp->b_rptr) {
1352 ppa->stats.ppp_ierrors++;
1358 ppa->stats.ppp_oerrors++;
1367 * Attempt to match up the response with the stream
1368 * that the request came from.
1370 iop = (struct iocblk *) mp->b_rptr;
1371 for (us = ppa; us != 0; us = us->next)
1372 if (us->ioc_id == iop->ioc_id)
1381 if (mp->b_datap->db_type == M_DATA) {
1383 if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN) {
1384 PULLUP(mp, PPP_HDRLEN);
1386 DPRINT1("ppp_lrput: msgpullup failed (len=%d)\n", len);
1390 ppa->stats.ppp_ipackets++;
1391 ppa->stats.ppp_ibytes += len;
1392 #ifdef INCR_IPACKETS
1395 proto = PPP_PROTOCOL(mp->b_rptr);
1396 if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
1398 * A data packet for some network protocol.
1399 * Queue it on the upper stream for that protocol.
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.
1413 if (queclass(mp) == QPCTL || canputnext(ppa->q))
1414 putnext(ppa->q, mp);
1428 upperstr_t *ppa, *us;
1432 * Packets only get queued here for flow control reasons.
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) {
1446 if (canputnext(ppa->q))
1447 putnext(ppa->q, mp);
1458 putctl2(q, type, code, val)
1460 int type, code, val;
1464 mp = allocb(2, BPRI_HI);
1467 mp->b_datap->db_type = type;
1468 mp->b_wptr[0] = code;
1469 mp->b_wptr[1] = val;
1476 putctl4(q, type, code, val)
1478 int type, code, val;
1482 mp = allocb(4, BPRI_HI);
1485 mp->b_datap->db_type = type;
1486 mp->b_wptr[0] = code;
1487 ((short *)mp->b_wptr)[1] = val;
1495 queue_t *q; /* not used */
1496 mblk_t *mp; /* not used either */
1501 DPRINT("ppp upper streams:\n");
1502 for (us = minor_devs; us != 0; us = us->nextmn) {
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,
1513 DPRINT1(" ppa=%d\n", us->ppa->ppa_id);
1514 if (us->flags & US_CONTROL) {
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);