4 #include <sys/stream.h>
5 #include <sys/stropts.h>
7 #include <sys/cmn_err.h>
8 #include <sys/modctl.h>
11 #include <sys/sunddi.h>
13 #include <sys/ioccom.h>
14 #include <net/ppp_defs.h>
15 #include <net/pppio.h>
24 * The IP module uses this SAP value for IP packets.
27 #define ETHERTYPE_IP 0x800
31 #define PPP_MAXMTU 65536
35 * Private information; one per upper stream.
38 minor_t mn; /* minor device number */
39 queue_t *q; /* read q associated with this upper stream */
40 int flags; /* flag bits, see below */
41 int state; /* current DLPI state */
42 int sap; /* service access point */
43 struct upperstr *ppa; /* control stream for our ppa */
44 struct upperstr *next; /* next stream for this ppa */
46 * There is exactly one control stream for each PPA.
47 * The following fields are only used for control streams.
50 queue_t *lowerq; /* write queue attached below this PPA */
51 struct upperstr *nextppa; /* next control stream */
54 /* Values for flags */
55 #define US_PRIV 1 /* stream was opened by superuser */
56 #define US_CONTROL 2 /* stream is a control stream */
57 #define US_BLOCKED 4 /* flow ctrl has blocked lower stream */
59 static void *upper_states;
60 static struct upperstr *ppas;
62 static int ppp_identify __P((dev_info_t *));
63 static int ppp_attach __P((dev_info_t *, ddi_attach_cmd_t));
64 static int ppp_detach __P((dev_info_t *, ddi_detach_cmd_t));
65 static int ppp_devinfo __P((dev_info_t *, ddi_info_cmd_t, void *, void **));
66 static int pppopen __P((queue_t *, dev_t *, int, int, cred_t *));
67 static int pppclose __P((queue_t *, int, cred_t *));
68 static int pppuwput __P((queue_t *, mblk_t *));
69 static int pppursrv __P((queue_t *));
70 static int pppuwsrv __P((queue_t *));
71 static int ppplrput __P((queue_t *, mblk_t *));
72 static int ppplrsrv __P((queue_t *));
73 static int ppplwsrv __P((queue_t *));
74 static void dlpi_request __P((queue_t *, mblk_t *, struct upperstr *));
75 static void dlpi_error __P((queue_t *, int, int, int));
76 static void dlpi_ok __P((queue_t *, int));
77 static int send_data __P((mblk_t *, struct upperstr *));
78 static void new_ppa __P((queue_t *, mblk_t *));
79 static struct upperstr *find_dest __P((struct upperstr *, int));
81 static struct module_info ppp_info = {
82 0xb1a6, "ppp", 0, 512, 512, 128
85 static struct qinit pppurint = {
86 NULL, pppursrv, pppopen, pppclose, NULL, &ppp_info, NULL
89 static struct qinit pppuwint = {
90 pppuwput, pppuwsrv, NULL, NULL, NULL, &ppp_info, NULL
93 static struct qinit ppplrint = {
94 ppplrput, ppplrsrv, NULL, NULL, NULL, &ppp_info, NULL
97 static struct qinit ppplwint = {
98 NULL, ppplwsrv, NULL, NULL, NULL, &ppp_info, NULL
101 static struct streamtab pppinfo = {
102 &pppurint, &pppuwint,
106 static dev_info_t *ppp_dip;
108 static struct cb_ops cb_ppp_ops = {
109 nulldev, nulldev, nodev, nodev, /* cb_open, ... */
110 nodev, nodev, nodev, nodev, /* cb_dump, ... */
111 nodev, nodev, nodev, nochpoll, /* cb_devmap, ... */
112 ddi_prop_op, /* cb_prop_op */
113 &pppinfo, /* cb_stream */
114 D_NEW|D_MP|D_MTQPAIR|D_MTOUTPERIM|D_MTOCEXCL /* cb_flag */
117 static struct dev_ops ppp_ops = {
118 DEVO_REV, /* devo_rev */
120 ppp_devinfo, /* devo_getinfo */
121 ppp_identify, /* devo_identify */
122 nulldev, /* devo_probe */
123 ppp_attach, /* devo_attach */
124 ppp_detach, /* devo_detach */
125 nodev, /* devo_reset */
126 &cb_ppp_ops, /* devo_cb_ops */
127 NULL /* devo_bus_ops */
131 * Module linkage information
134 static struct modldrv modldrv = {
135 &mod_driverops, /* says this is a pseudo driver */
136 "PPP-2.2 multiplexing driver",
137 &ppp_ops /* driver ops */
140 static struct modlinkage modlinkage = {
151 error = ddi_soft_state_init(&upper_states, sizeof(struct upperstr), 4);
153 error = mod_install(&modlinkage);
156 ddi_soft_state_fini(&upper_states);
166 error = mod_remove(&modlinkage);
169 ddi_soft_state_fini(&upper_states);
177 return mod_info(&modlinkage, mip);
184 return strcmp(ddi_get_name(dip), "ppp") == 0? DDI_IDENTIFIED:
191 ddi_attach_cmd_t cmd;
194 if (cmd != DDI_ATTACH)
196 if (ddi_create_minor_node(dip, "ppp", S_IFCHR, 0, DDI_PSEUDO, CLONE_DEV)
198 ddi_remove_minor_node(dip, NULL);
207 ddi_detach_cmd_t cmd;
209 ddi_remove_minor_node(dip, NULL);
214 ppp_devinfo(dip, cmd, arg, result)
224 case DDI_INFO_DEVT2DEVINFO:
228 *result = (void *) ppp_dip;
230 case DDI_INFO_DEVT2INSTANCE:
240 pppopen(q, devp, oflag, sflag, credp)
250 return 0; /* device is already open */
252 if (sflag == CLONEOPEN) {
253 for (mn = 0; ddi_get_soft_state(upper_states, mn) != NULL; ++mn)
256 mn = getminor(*devp);
258 cmn_err(CE_CONT, "pppopen: minor %d\n", mn);
261 * Construct a new minor node.
263 if (ddi_soft_state_zalloc(upper_states, mn) != DDI_SUCCESS)
265 up = ddi_get_soft_state(upper_states, mn);
266 *devp = makedevice(getmajor(*devp), mn);
270 if (drv_priv(credp) == 0)
271 up->flags |= US_PRIV;
272 up->state = DL_UNATTACHED;
286 pppclose(q, flag, credp)
291 struct upperstr *up, **upp;
292 struct upperstr *as, *asnext;
297 up = (struct upperstr *) q->q_ptr;
298 cmn_err(CE_CONT, "pppclose: minor %d\n", up->mn);
299 if (up->flags & US_CONTROL) {
301 * This stream represents a PPA:
302 * For all streams attached to the PPA, clear their
303 * references to this PPA.
304 * Then remove this PPA from the list of PPAs.
306 for (as = up->next; as != 0; as = asnext) {
310 if (as->flags & US_BLOCKED) {
311 as->flags &= ~US_BLOCKED;
312 flushq(WR(as->q), FLUSHDATA);
315 for (upp = &ppas; *upp != 0; upp = &(*upp)->nextppa)
323 * If this stream is attached to a PPA,
324 * remove it from the PPA's list.
326 if ((as = up->ppa) != 0) {
327 for (; as->next != 0; as = as->next)
328 if (as->next == up) {
337 ddi_soft_state_free(upper_states, up->mn);
343 * A message from on high. We do one of three things:
345 * - put the message on the lower write stream
346 * - queue it for our service routine
353 struct upperstr *us, *usnext;
360 us = (struct upperstr *) q->q_ptr;
361 switch (mp->b_datap->db_type) {
364 dlpi_request(q, mp, us);
368 if (!send_data(mp, us))
373 iop = (struct iocblk *) mp->b_rptr;
374 cmn_err(CE_CONT, "ppp%d ioctl %x count=%d\n", us->mn, iop->ioc_cmd,
376 switch (iop->ioc_cmd) {
378 if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0)
380 lb = (struct linkblk *) mp->b_cont->b_rptr;
381 us->lowerq = lq = lb->l_qbot;
385 mp->b_datap->db_type = M_IOCACK;
387 /* Unblock upper streams which now feed this lower stream. */
392 lb = (struct linkblk *) mp->b_cont->b_rptr;
393 if (us->lowerq != lb->l_qbot)
394 cmn_err(CE_CONT, "ppp unlink: lowerq=%x qbot=%x\n",
395 us->lowerq, lb->l_qbot);
398 mp->b_datap->db_type = M_IOCACK;
400 /* Unblock streams which now feed back up the control stream. */
405 if (us->flags & US_CONTROL)
407 if ((us->flags & US_PRIV) == 0) {
408 iop->ioc_error = EPERM;
411 /* Arrange to return an int */
412 if ((mq = mp->b_cont) == 0
413 || mq->b_datap->db_lim - mq->b_rptr < sizeof(int)) {
414 mq = allocb(sizeof(int), BPRI_HI);
416 iop->ioc_error = ENOSR;
424 iop->ioc_count = sizeof(int);
425 mq->b_wptr = mq->b_rptr + sizeof(int);
426 qwriter(q, mp, new_ppa, PERIM_OUTER);
430 if (us->ppa == 0 || us->ppa->lowerq == 0)
432 switch (iop->ioc_cmd) {
437 if ((us->flags & US_PRIV) == 0) {
438 iop->ioc_error = EPERM;
442 putnext(us->ppa->lowerq, mp);
446 mp->b_datap->db_type = M_IOCNAK;
453 if (*mp->b_rptr & FLUSHW)
454 flushq(q, FLUSHDATA);
455 if (*mp->b_rptr & FLUSHR) {
456 *mp->b_rptr &= ~FLUSHW;
470 dlpi_request(q, mp, us)
475 union DL_primitives *d = (union DL_primitives *) mp->b_rptr;
476 int size = mp->b_wptr - mp->b_rptr;
478 struct upperstr *t, *ppa;
482 dl_phys_addr_ack_t *adrp;
484 cmn_err(CE_CONT, "ppp%d dlpi prim %x, state=%x\n", us->mn,
485 d->dl_primitive, us->state);
486 switch (d->dl_primitive) {
488 if (size < sizeof(dl_info_req_t))
490 if ((reply = allocb(sizeof(dl_info_ack_t), BPRI_HI)) == 0)
491 break; /* should do bufcall */
492 reply->b_datap->db_type = M_PCPROTO;
493 info = (dl_info_ack_t *) reply->b_wptr;
494 reply->b_wptr += sizeof(dl_info_ack_t);
495 bzero((caddr_t) info, sizeof(dl_info_ack_t));
496 info->dl_primitive = DL_INFO_ACK;
497 info->dl_max_sdu = PPP_MAXMTU;
498 info->dl_min_sdu = 1;
499 info->dl_addr_length = sizeof(ulong);
500 info->dl_mac_type = DL_OTHER;
501 info->dl_current_state = us->state;
502 info->dl_sap_length = sizeof(ulong);
503 info->dl_service_mode = DL_CLDLS;
504 info->dl_provider_style = DL_STYLE2;
505 info->dl_version = DL_CURRENT_VERSION;
510 if (size < sizeof(dl_attach_req_t))
512 if (us->state != DL_UNATTACHED || us->ppa != 0) {
513 dlpi_error(q, DL_ATTACH_REQ, DL_OUTSTATE, 0);
516 for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
517 if (ppa->ppa_id == d->attach_req.dl_ppa)
520 dlpi_error(q, DL_ATTACH_REQ, DL_BADPPA, 0);
524 us->state = DL_UNBOUND;
525 for (t = ppa; t->next != 0; t = t->next)
529 dlpi_ok(q, DL_ATTACH_REQ);
533 if (size < sizeof(dl_detach_req_t))
535 if (us->state != DL_UNBOUND || us->ppa == 0) {
536 dlpi_error(q, DL_DETACH_REQ, DL_OUTSTATE, 0);
539 for (t = us->ppa; t->next != 0; t = t->next)
546 us->state = DL_UNATTACHED;
547 dlpi_ok(q, DL_DETACH_REQ);
551 if (size < sizeof(dl_bind_req_t))
553 if (us->state != DL_UNBOUND) {
554 dlpi_error(q, DL_BIND_REQ, DL_OUTSTATE, 0);
557 if (d->bind_req.dl_service_mode != DL_CLDLS) {
558 dlpi_error(q, DL_BIND_REQ, DL_UNSUPPORTED, 0);
561 /* saps must be valid PPP network protocol numbers */
562 sap = d->bind_req.dl_sap;
563 cmn_err(CE_CONT, "ppp bind %x\n", sap);
564 if (sap == ETHERTYPE_IP)
566 if (sap < 0x21 || sap > 0x3fff
567 || (sap & 1) == 0 || (sap & 0x100) != 0) {
568 dlpi_error(q, DL_BIND_REQ, DL_BADADDR, 0);
573 if ((reply = allocb(sizeof(dl_bind_ack_t) + sizeof(ulong),
575 break; /* should do bufcall */
576 ackp = (dl_bind_ack_t *) reply->b_wptr;
577 reply->b_wptr += sizeof(dl_bind_ack_t) + sizeof(ulong);
578 reply->b_datap->db_type = M_PCPROTO;
579 bzero((caddr_t) ackp, sizeof(dl_bind_ack_t));
580 ackp->dl_primitive = DL_BIND_ACK;
582 ackp->dl_addr_length = sizeof(ulong);
583 ackp->dl_addr_offset = sizeof(dl_bind_ack_t);
584 *(ulong *)(ackp+1) = sap;
589 if (size < sizeof(dl_unbind_req_t))
591 if (us->state != DL_IDLE) {
592 dlpi_error(q, DL_UNBIND_REQ, DL_OUTSTATE, 0);
596 us->state = DL_UNBOUND;
597 dlpi_ok(q, DL_UNBIND_REQ);
600 case DL_UNITDATA_REQ:
601 if (size < sizeof(dl_unitdata_req_t))
603 if (us->state != DL_IDLE) {
604 dlpi_error(q, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
607 /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
608 if (mp->b_datap->db_ref > 1) {
609 np = allocb(PPP_HDRLEN, BPRI_HI);
612 np->b_cont = mp->b_cont;
617 /* XXX should use dl_dest_addr_offset/length here */
618 mp->b_wptr = mp->b_rptr + PPP_HDRLEN;
619 mp->b_rptr[0] = PPP_ALLSTATIONS;
620 mp->b_rptr[1] = PPP_UI;
621 mp->b_rptr[2] = us->sap >> 8;
622 mp->b_rptr[3] = us->sap;
623 if (!send_data(mp, us))
627 case DL_SUBS_BIND_REQ:
628 case DL_SUBS_UNBIND_REQ:
629 case DL_ENABMULTI_REQ:
630 case DL_DISABMULTI_REQ:
631 case DL_PROMISCON_REQ:
632 case DL_PROMISCOFF_REQ:
633 case DL_PHYS_ADDR_REQ:
634 case DL_SET_PHYS_ADDR_REQ:
639 case DL_REPLY_UPDATE_REQ:
640 case DL_GET_STATISTICS_REQ:
642 case DL_DATA_ACK_REQ:
643 dlpi_error(q, d->dl_primitive, DL_NOTSUPPORTED, 0);
647 case DL_DISCONNECT_REQ:
650 dlpi_error(q, d->dl_primitive, DL_OUTSTATE, 0);
654 dlpi_error(q, d->dl_primitive, DL_BADQOSTYPE, 0);
663 dlpi_error(q, d->dl_primitive, DL_BADPRIM, 0);
670 dlpi_error(q, prim, err, uerr)
675 dl_error_ack_t *errp;
677 reply = allocb(sizeof(dl_error_ack_t), BPRI_HI);
679 return; /* XXX should do bufcall */
680 reply->b_datap->db_type = M_PCPROTO;
681 errp = (dl_error_ack_t *) reply->b_wptr;
682 reply->b_wptr += sizeof(dl_error_ack_t);
683 errp->dl_primitive = DL_ERROR_ACK;
684 errp->dl_error_primitive = prim;
685 errp->dl_errno = err;
686 errp->dl_unix_errno = uerr;
698 reply = allocb(sizeof(dl_ok_ack_t), BPRI_HI);
700 return; /* XXX should do bufcall */
701 reply->b_datap->db_type = M_PCPROTO;
702 okp = (dl_ok_ack_t *) reply->b_wptr;
703 reply->b_wptr += sizeof(dl_ok_ack_t);
704 okp->dl_primitive = DL_OK_ACK;
705 okp->dl_correct_primitive = prim;
715 struct upperstr *ppa;
717 if (us->flags & US_BLOCKED)
724 if ((q = ppa->lowerq) == 0) {
725 /* try to send it up the control stream */
732 us->flags |= US_BLOCKED;
741 struct upperstr *us, **usp;
745 * Allocate a new PPA id and link this stream into
750 while ((us = *usp) != 0 && ppa_id == us->ppa_id) {
754 us = (struct upperstr *) q->q_ptr;
760 us->flags |= US_CONTROL;
762 *(int *)mp->b_cont->b_rptr = ppa_id;
763 mp->b_datap->db_type = M_IOCACK;
776 us = (struct upperstr *) q->q_ptr;
777 while ((mp = getq(q)) != 0) {
778 if (!send_data(mp, us)) {
793 * Flow control has back-enabled this stream:
794 * enable the write service procedures of all upper
795 * streams feeding this lower stream.
797 for (us = (struct upperstr *) q->q_ptr; us != NULL; us = us->next)
798 if (us->flags & US_BLOCKED)
807 struct upperstr *us, *as;
809 dl_unitdata_ind_t *ud;
813 * If this is a control stream and we don't have a lower queue attached,
814 * run the write service routines of other streams attached to this PPA.
816 us = (struct upperstr *) q->q_ptr;
817 if (us->flags & US_CONTROL) {
820 * If there is no lower queue attached, run the write service
821 * routines of other upper streams attached to this PPA.
823 if (us->lowerq == 0) {
826 if (as->flags & US_BLOCKED)
833 * A network protocol stream. Put a DLPI header on each
834 * packet and send it on.
836 while ((mp = getq(q)) != 0) {
837 if (!canputnext(q)) {
841 proto = PPP_PROTOCOL(mp->b_rptr);
842 mp->b_rptr += PPP_HDRLEN;
843 hdr = allocb(sizeof(dl_unitdata_ind_t) + 2 * sizeof(ulong),
846 /* XXX should put it back and use bufcall */
850 ud = (dl_unitdata_ind_t *) hdr->b_wptr;
851 hdr->b_wptr += sizeof(dl_unitdata_ind_t) + 2 * sizeof(ulong);
853 ud->dl_primitive = DL_UNITDATA_IND;
854 ud->dl_dest_addr_length = sizeof(ulong);
855 ud->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
856 ud->dl_src_addr_length = sizeof(ulong);
857 ud->dl_src_addr_offset = ud->dl_dest_addr_offset + sizeof(ulong);
858 ud->dl_group_address = 0;
859 ((ulong *)(ud + 1))[0] = proto; /* dest SAP */
860 ((ulong *)(ud + 1))[1] = proto; /* src SAP */
867 static struct upperstr *
868 find_dest(ppa, proto)
869 struct upperstr *ppa;
874 for (us = ppa->next; us != 0; us = us->next)
875 if (proto == us->sap)
885 struct upperstr *ppa, *us;
889 ppa = (struct upperstr *) q->q_ptr;
890 switch (mp->b_datap->db_type) {
892 if (*mp->b_rptr & FLUSHW) {
893 *mp->b_rptr &= ~FLUSHR;
900 if (mp->b_datap->db_type == M_DATA
901 && (proto = PPP_PROTOCOL(mp->b_rptr)) < 0x8000
902 && (us = find_dest(ppa, proto)) != 0) {
904 * A data packet for some network protocol.
905 * Queue it on the upper stream for that protocol.
914 * A control frame, a frame for an unknown protocol,
915 * or some other message type.
916 * Send it up to pppd via the control stream.
918 if (mp->b_datap->db_type >= QPCTL || canputnext(ppa->q))
934 struct upperstr *ppa, *us;
938 * Packets only get queued here for flow control reasons.
940 ppa = (struct upperstr *) q->q_ptr;
941 while ((mp = getq(q)) != 0) {
942 if (mp->b_datap->db_type == M_DATA
943 && (proto = PPP_PROTOCOL(mp->b_rptr)) < 0x8000
944 && (us = find_dest(ppa, proto)) != 0) {
952 if (canputnext(ppa->q))