#
# Makefile for STREAMS modules for Solaris 2.
#
-# $Id: Makefile.sol2,v 1.1 1995/10/27 03:58:30 paulus Exp $
+# $Id: Makefile.sol2,v 1.2 1995/12/11 05:19:29 paulus Exp $
#
-# Note: Sun cc doesn't predefine svr4 or __svr4__, but gcc does
-
-CFLAGS= -D_KERNEL -Dsvr4 -I.. -O
-#CC= gcc
+CFLAGS= -D_KERNEL -DSVR4 -DSOL2 -I.. -O -Xa
all: ppp ppp_ahdl ppp_comp
-ppp: ppp.o
- ld -r -o $@ ppp.o
+ppp: ppp.o ppp_mod.o
+ ld -r -o $@ ppp.o ppp_mod.o
-ppp_ahdl: ppp_ahdlc.o
- ld -r -o $@ ppp_ahdlc.o
+ppp_ahdl: ppp_ahdlc.o ppp_ahdlc_mod.o
+ ld -r -o $@ ppp_ahdlc.o ppp_ahdlc_mod.o
-ppp_comp: ppp_comp.o bsd-comp.o vjcompress.o
- ld -r -o $@ ppp_comp.o bsd-comp.o vjcompress.o
+ppp_comp: ppp_comp.o bsd-comp.o vjcompress.o ppp_comp_mod.o
+ ld -r -o $@ ppp_comp.o bsd-comp.o vjcompress.o ppp_comp_mod.o
bsd-comp.o: ../modules/bsd-comp.c
$(CC) $(CFLAGS) -c $?
+ppp.o: ../modules/ppp.c
+ $(CC) $(CFLAGS) -c $?
+ppp_ahdlc.o: ../modules/ppp_ahdlc.c
+ $(CC) $(CFLAGS) -c $?
+ppp_comp.o: ../modules/ppp_comp.c
+ $(CC) $(CFLAGS) -c $?
vjcompress.o: ../modules/vjcompress.c
$(CC) $(CFLAGS) -c $?
+++ /dev/null
-/*
- * ppp.c - STREAMS multiplexing pseudo-device driver for PPP.
- *
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies. This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
- *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- *
- * $Id: ppp.c,v 1.7 1995/10/27 03:55:56 paulus Exp $
- */
-
-/*
- * This file is used under Solaris 2.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/errno.h>
-#include <sys/cmn_err.h>
-#include <sys/conf.h>
-#include <sys/dlpi.h>
-#include <sys/ioccom.h>
-#include <sys/kmem.h>
-#include <sys/ddi.h>
-#ifdef sun
-#include <sys/modctl.h>
-#include <sys/kstat.h>
-#include <sys/sunddi.h>
-#else
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#endif
-#include <net/ppp_defs.h>
-#include <net/pppio.h>
-
-#ifdef __STDC__
-#define __P(x) x
-#else
-#define __P(x) ()
-#endif
-
-/*
- * The IP module uses this SAP value for IP packets.
- */
-#ifndef ETHERTYPE_IP
-#define ETHERTYPE_IP 0x800
-#endif
-
-#ifndef PPP_MAXMTU
-#define PPP_MAXMTU 65535
-#endif
-
-/*
- * Private information; one per upper stream.
- */
-typedef struct upperstr {
- minor_t mn; /* minor device number */
- struct upperstr *nextmn; /* next minor device */
- queue_t *q; /* read q associated with this upper stream */
- int flags; /* flag bits, see below */
- int state; /* current DLPI state */
- int sap; /* service access point */
- int req_sap; /* which SAP the DLPI client requested */
- struct upperstr *ppa; /* control stream for our ppa */
- struct upperstr *next; /* next stream for this ppa */
- uint ioc_id; /* last ioctl ID for this stream */
- /*
- * There is exactly one control stream for each PPA.
- * The following fields are only used for control streams.
- */
- int ppa_id;
- queue_t *lowerq; /* write queue attached below this PPA */
- struct upperstr *nextppa; /* next control stream */
- int mru;
- int mtu;
- struct pppstat stats; /* statistics */
-#ifdef sun
- kstat_t *kstats; /* stats for netstat */
-#else
- int ifflags;
- char ifname[IFNAMSIZ];
- struct ifstats ifstats;
-#endif
-} upperstr_t;
-
-/* Values for flags */
-#define US_PRIV 1 /* stream was opened by superuser */
-#define US_CONTROL 2 /* stream is a control stream */
-#define US_BLOCKED 4 /* flow ctrl has blocked lower write stream */
-#define US_LASTMOD 8 /* no PPP modules below us */
-#define US_DBGLOG 0x10 /* log various occurrences */
-
-static upperstr_t *minor_devs = NULL;
-static upperstr_t *ppas = NULL;
-
-#ifdef sun
-static int ppp_identify __P((dev_info_t *));
-static int ppp_attach __P((dev_info_t *, ddi_attach_cmd_t));
-static int ppp_detach __P((dev_info_t *, ddi_detach_cmd_t));
-static int ppp_devinfo __P((dev_info_t *, ddi_info_cmd_t, void *, void **));
-#endif
-static int pppopen __P((queue_t *, dev_t *, int, int, cred_t *));
-static int pppclose __P((queue_t *, int, cred_t *));
-static int pppuwput __P((queue_t *, mblk_t *));
-static int pppursrv __P((queue_t *));
-static int pppuwsrv __P((queue_t *));
-static int ppplrput __P((queue_t *, mblk_t *));
-static int ppplwput __P((queue_t *, mblk_t *));
-static int ppplrsrv __P((queue_t *));
-static int ppplwsrv __P((queue_t *));
-static void dlpi_request __P((queue_t *, mblk_t *, upperstr_t *));
-static void dlpi_error __P((queue_t *, int, int, int));
-static void dlpi_ok __P((queue_t *, int));
-static int send_data __P((mblk_t *, upperstr_t *));
-static void new_ppa __P((queue_t *, mblk_t *));
-static void attach_ppa __P((queue_t *, mblk_t *));
-static void detach_ppa __P((queue_t *, mblk_t *));
-static void debug_dump __P((queue_t *, mblk_t *));
-static upperstr_t *find_dest __P((upperstr_t *, int));
-static int putctl2 __P((queue_t *, int, int, int));
-static int putctl4 __P((queue_t *, int, int, int));
-
-static struct module_info ppp_info = {
- 0xb1a6, "ppp", 0, 512, 512, 128
-};
-
-static struct qinit pppurint = {
- NULL, pppursrv, pppopen, pppclose, NULL, &ppp_info, NULL
-};
-
-static struct qinit pppuwint = {
- pppuwput, pppuwsrv, NULL, NULL, NULL, &ppp_info, NULL
-};
-
-static struct qinit ppplrint = {
- ppplrput, ppplrsrv, NULL, NULL, NULL, &ppp_info, NULL
-};
-
-static struct qinit ppplwint = {
- ppplwput, ppplwsrv, NULL, NULL, NULL, &ppp_info, NULL
-};
-
-#ifndef sun
-extern struct ifstats *ifstats;
-int pppdevflag = 0;
-#else
-static
-#endif
-struct streamtab pppinfo = {
- &pppurint, &pppuwint,
- &ppplrint, &ppplwint
-};
-
-#ifdef sun
-static dev_info_t *ppp_dip;
-
-static struct cb_ops cb_ppp_ops = {
- nulldev, nulldev, nodev, nodev, /* cb_open, ... */
- nodev, nodev, nodev, nodev, /* cb_dump, ... */
- nodev, nodev, nodev, nochpoll, /* cb_devmap, ... */
- ddi_prop_op, /* cb_prop_op */
- &pppinfo, /* cb_stream */
- D_NEW|D_MP|D_MTQPAIR|D_MTOUTPERIM|D_MTOCEXCL /* cb_flag */
-};
-
-static struct dev_ops ppp_ops = {
- DEVO_REV, /* devo_rev */
- 0, /* devo_refcnt */
- ppp_devinfo, /* devo_getinfo */
- ppp_identify, /* devo_identify */
- nulldev, /* devo_probe */
- ppp_attach, /* devo_attach */
- ppp_detach, /* devo_detach */
- nodev, /* devo_reset */
- &cb_ppp_ops, /* devo_cb_ops */
- NULL /* devo_bus_ops */
-};
-
-/*
- * Module linkage information
- */
-
-static struct modldrv modldrv = {
- &mod_driverops, /* says this is a pseudo driver */
- "PPP-2.2 multiplexing driver",
- &ppp_ops /* driver ops */
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- (void *) &modldrv,
- NULL
-};
-
-int
-_init(void)
-{
- return mod_install(&modlinkage);
-}
-
-int
-_fini(void)
-{
- return mod_remove(&modlinkage);
-}
-
-int
-_info(mip)
- struct modinfo *mip;
-{
- return mod_info(&modlinkage, mip);
-}
-
-static int
-ppp_identify(dip)
- dev_info_t *dip;
-{
- return strcmp(ddi_get_name(dip), "ppp") == 0? DDI_IDENTIFIED:
- DDI_NOT_IDENTIFIED;
-}
-
-static int
-ppp_attach(dip, cmd)
- dev_info_t *dip;
- ddi_attach_cmd_t cmd;
-{
-
- if (cmd != DDI_ATTACH)
- return DDI_FAILURE;
- if (ddi_create_minor_node(dip, "ppp", S_IFCHR, 0, DDI_PSEUDO, CLONE_DEV)
- == DDI_FAILURE) {
- ddi_remove_minor_node(dip, NULL);
- return DDI_FAILURE;
- }
- return DDI_SUCCESS;
-}
-
-static int
-ppp_detach(dip, cmd)
- dev_info_t *dip;
- ddi_detach_cmd_t cmd;
-{
- ddi_remove_minor_node(dip, NULL);
- return DDI_SUCCESS;
-}
-
-static int
-ppp_devinfo(dip, cmd, arg, result)
- dev_info_t *dip;
- ddi_info_cmd_t cmd;
- void *arg;
- void **result;
-{
- int error;
-
- error = DDI_SUCCESS;
- switch (cmd) {
- case DDI_INFO_DEVT2DEVINFO:
- if (ppp_dip == NULL)
- error = DDI_FAILURE;
- else
- *result = (void *) ppp_dip;
- break;
- case DDI_INFO_DEVT2INSTANCE:
- *result = NULL;
- break;
- default:
- error = DDI_FAILURE;
- }
- return error;
-}
-#endif /* sun */
-
-#ifndef sun
-#define put(q, mp) ((*(q)->q_qinfo->qi_putp)((q), (mp)))
-# define qprocson(q)
-# define qprocsoff(q)
-# define canputnext(q) canput((q)->q_next)
-# define qwriter(q, mp, func, scope) (func)((q), (mp))
-#endif
-
-static int
-pppopen(q, devp, oflag, sflag, credp)
- queue_t *q;
- dev_t *devp;
- int oflag, sflag;
- cred_t *credp;
-{
- upperstr_t *up;
- upperstr_t **prevp;
- minor_t mn;
-
- if (q->q_ptr)
- return 0; /* device is already open */
-
- if (sflag == CLONEOPEN) {
- mn = 0;
- for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
- if (up->mn != mn)
- break;
- ++mn;
- }
- } else {
- mn = getminor(*devp);
- for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
- if (up->mn >= mn)
- break;
- }
- if (up->mn == mn) {
- /* this can't happen */
- q->q_ptr = WR(q)->q_ptr = up;
- return 0;
- }
- }
-
- /*
- * Construct a new minor node.
- */
- up = (upperstr_t *) kmem_zalloc(sizeof(upperstr_t), KM_SLEEP);
- if (up == 0) {
- cmn_err(CE_CONT, "pppopen: out of kernel memory\n");
- return ENXIO;
- }
- up->nextmn = *prevp;
- *prevp = up;
- up->mn = mn;
- *devp = makedevice(getmajor(*devp), mn);
- up->q = q;
- if (drv_priv(credp) == 0)
- up->flags |= US_PRIV;
- up->state = DL_UNATTACHED;
-#ifndef sun
- up->ifflags = IFF_UP | IFF_POINTOPOINT;
-#endif
- up->sap = -1;
- q->q_ptr = up;
- WR(q)->q_ptr = up;
- noenable(WR(q));
-
- qprocson(q);
- return 0;
-}
-
-static int
-pppclose(q, flag, credp)
- queue_t *q;
- int flag;
- cred_t *credp;
-{
- upperstr_t *up, **upp;
- upperstr_t *as, *asnext;
- upperstr_t **prevp;
-
- qprocsoff(q);
-
- up = (upperstr_t *) q->q_ptr;
- if (up->flags & US_DBGLOG)
- cmn_err(CE_CONT, "ppp/%d: close, flags=%x\n", up->mn, up->flags);
- if (up == 0)
- return 0;
- if (up->flags & US_CONTROL) {
-#ifndef sun
- struct ifstats *ifp, *pifp;
-#endif
- /*
- * This stream represents a PPA:
- * For all streams attached to the PPA, clear their
- * references to this PPA.
- * Then remove this PPA from the list of PPAs.
- */
- for (as = up->next; as != 0; as = asnext) {
- asnext = as->next;
- as->next = 0;
- as->ppa = 0;
- if (as->flags & US_BLOCKED) {
- as->flags &= ~US_BLOCKED;
- flushq(WR(as->q), FLUSHDATA);
- }
- }
- for (upp = &ppas; *upp != 0; upp = &(*upp)->nextppa)
- if (*upp == up) {
- *upp = up->nextppa;
- break;
- }
-#ifndef sun
- /* Remove the statistics from the active list. */
- for (ifp = ifstats, pifp = 0; ifp; ifp = ifp->ifs_next) {
- if (ifp == &up->ifstats) {
- if (pifp)
- pifp->ifs_next = ifp->ifs_next;
- else
- ifstats = ifp->ifs_next;
- break;
- }
- pifp = ifp;
- }
-#endif
- } else {
- /*
- * If this stream is attached to a PPA,
- * remove it from the PPA's list.
- */
- if ((as = up->ppa) != 0) {
- for (; as->next != 0; as = as->next)
- if (as->next == up) {
- as->next = up->next;
- break;
- }
- }
- }
-
-#ifdef sun
- if (up->kstats)
- kstat_delete(up->kstats);
-#endif
-
- q->q_ptr = NULL;
- WR(q)->q_ptr = NULL;
-
- for (prevp = &minor_devs; *prevp != 0; prevp = &(*prevp)->nextmn) {
- if (*prevp == up) {
- *prevp = up->nextmn;
- break;
- }
- }
- kmem_free(up, sizeof(upperstr_t));
-
- return 0;
-}
-
-/*
- * A message from on high. We do one of three things:
- * - qreply()
- * - put the message on the lower write stream
- * - queue it for our service routine
- */
-static int
-pppuwput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, *usnext, *ppa;
- struct iocblk *iop;
- struct linkblk *lb;
-#ifndef sun
- struct ifreq *ifr;
- int i;
-#endif
- queue_t *lq;
- int error, n;
- mblk_t *mq;
-
- us = (upperstr_t *) q->q_ptr;
- switch (mp->b_datap->db_type) {
- case M_PCPROTO:
- case M_PROTO:
- dlpi_request(q, mp, us);
- break;
-
- case M_DATA:
- if (us->flags & US_DBGLOG)
- cmn_err(CE_CONT, "ppp/%d: uwput M_DATA len=%d flags=%x\n",
- us->mn, msgdsize(mp), us->flags);
- if ((us->flags & US_CONTROL) == 0
- || msgdsize(mp) > us->mtu + PPP_HDRLEN) {
-#if DEBUG
- cmn_err(CE_CONT, "pppuwput: junk data len=%d\n", msgdsize(mp));
-#endif
- freemsg(mp);
- break;
- }
- if (!send_data(mp, us))
- putq(q, mp);
- break;
-
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- error = EINVAL;
- if (us->flags & US_DBGLOG)
- cmn_err(CE_CONT, "ppp/%d: ioctl %x count=%d\n",
- us->mn, iop->ioc_cmd, iop->ioc_count);
- switch (iop->ioc_cmd) {
- case I_LINK:
- if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0)
- break;
- lb = (struct linkblk *) mp->b_cont->b_rptr;
- us->lowerq = lq = lb->l_qbot;
- lq->q_ptr = us;
- RD(lq)->q_ptr = us;
- noenable(RD(lq));
- iop->ioc_count = 0;
- error = 0;
- us->flags &= ~US_LASTMOD;
- /* Unblock upper streams which now feed this lower stream. */
- qenable(lq);
- /* Send useful information down to the modules which
- are now linked below us. */
- putctl2(lq, M_CTL, PPPCTL_UNIT, us->ppa_id);
- putctl4(lq, M_CTL, PPPCTL_MRU, us->mru);
- putctl4(lq, M_CTL, PPPCTL_MTU, us->mtu);
- break;
-
- case I_UNLINK:
- lb = (struct linkblk *) mp->b_cont->b_rptr;
-#if DEBUG
- if (us->lowerq != lb->l_qbot)
- cmn_err(CE_CONT, "ppp unlink: lowerq=%x qbot=%x\n",
- us->lowerq, lb->l_qbot);
-#endif
- us->lowerq = 0;
- iop->ioc_count = 0;
- error = 0;
- /* Unblock streams which now feed back up the control stream. */
- qenable(us->q);
- break;
-
- case PPPIO_NEWPPA:
- if (us->flags & US_CONTROL)
- break;
- if ((us->flags & US_PRIV) == 0) {
- error = EPERM;
- break;
- }
- /* Arrange to return an int */
- if ((mq = mp->b_cont) == 0
- || mq->b_datap->db_lim - mq->b_rptr < sizeof(int)) {
- mq = allocb(sizeof(int), BPRI_HI);
- if (mq == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = mq;
- mq->b_cont = 0;
- }
- iop->ioc_count = sizeof(int);
- mq->b_wptr = mq->b_rptr + sizeof(int);
- qwriter(q, mp, new_ppa, PERIM_OUTER);
- error = -1;
- break;
-
- case PPPIO_ATTACH:
- /* like dlpi_attach, for programs which can't write to
- the stream (like pppstats) */
- if (iop->ioc_count != sizeof(int) || us->ppa != 0)
- break;
- n = *(int *)mp->b_cont->b_rptr;
- for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
- if (ppa->ppa_id == n)
- break;
- if (ppa == 0)
- break;
- us->ppa = ppa;
- iop->ioc_count = 0;
- qwriter(q, mp, attach_ppa, PERIM_OUTER);
- error = -1;
- break;
-
- case PPPIO_MRU:
- if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
- break;
- n = *(int *)mp->b_cont->b_rptr;
- if (n <= 0 || n > PPP_MAXMTU)
- break;
- if (n < PPP_MRU)
- n = PPP_MRU;
- us->mru = n;
- if (us->lowerq)
- putctl4(us->lowerq, M_CTL, PPPCTL_MRU, n);
- error = 0;
- iop->ioc_count = 0;
- break;
-
- case PPPIO_MTU:
- if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
- break;
- n = *(int *)mp->b_cont->b_rptr;
- if (n <= 0 || n > PPP_MAXMTU)
- break;
- if (n < PPP_MRU)
- n = PPP_MRU;
- us->mtu = n;
-#ifndef sun
- us->ifstats.ifs_mtu = n;
-#endif
- if (us->lowerq)
- putctl4(us->lowerq, M_CTL, PPPCTL_MTU, n);
- error = 0;
- iop->ioc_count = 0;
- break;
-
- case PPPIO_LASTMOD:
- us->flags |= US_LASTMOD;
- error = 0;
- break;
-
- case PPPIO_DEBUG:
- if (iop->ioc_count != sizeof(int))
- break;
- n = *(int *)mp->b_cont->b_rptr;
- if (n == PPPDBG_DUMP + PPPDBG_DRIVER) {
- qwriter(q, NULL, debug_dump, PERIM_OUTER);
- iop->ioc_count = 0;
- error = 0;
- } else if (n == PPPDBG_LOG + PPPDBG_DRIVER) {
- cmn_err(CE_CONT, "ppp/%d: debug log enabled\n", us->mn);
- us->flags |= US_DBGLOG;
- iop->ioc_count = 0;
- error = 0;
- } else {
- if (us->ppa == 0 || us->ppa->lowerq == 0)
- break;
- putnext(us->ppa->lowerq, mp);
- error = -1;
- }
- break;
-
-#ifndef sun
- case SIOCSIFNAME:
- printf("SIOCSIFNAME\n");
- /* Sent from IP down to us. Attach the ifstats structure. */
- if (iop->ioc_count != sizeof(struct ifreq) || us->ppa == 0)
- break;
- ifr = (struct ifreq *)mp->b_cont->b_rptr;
- /* Find the unit number in the interface name. */
- for (i = 0; i < IFNAMSIZ; i++) {
- if (ifr->ifr_name[i] == 0 ||
- (ifr->ifr_name[i] >= '0' &&
- ifr->ifr_name[i] <= '9'))
- break;
- else
- us->ifname[i] = ifr->ifr_name[i];
- }
- us->ifname[i] = 0;
-
- /* Convert the unit number to binary. */
- for (n = 0; i < IFNAMSIZ; i++) {
- if (ifr->ifr_name[i] == 0) {
- break;
- }
- else {
- n = n * 10 + ifr->ifr_name[i] - '0';
- }
- }
-
- /* Verify the ppa. */
- if (us->ppa->ppa_id != n)
- break;
- ppa = us->ppa;
-
- /* Set up the netstat block. */
- strncpy (ppa->ifname, us->ifname, IFNAMSIZ);
-
- ppa->ifstats.ifs_name = ppa->ifname;
- ppa->ifstats.ifs_unit = n;
- ppa->ifstats.ifs_active = us->state != DL_UNBOUND;
- ppa->ifstats.ifs_mtu = ppa->mtu;
-
- /* Link in statistics used by netstat. */
- ppa->ifstats.ifs_next = ifstats;
- ifstats = &ppa->ifstats;
-
- iop->ioc_count = 0;
- error = 0;
- break;
-
- case SIOCGIFFLAGS:
- printf("SIOCGIFFLAGS\n");
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- ((struct iocblk_in *)iop)->ioc_ifflags = us->ifflags;
- error = 0;
- break;
-
- case SIOCSIFFLAGS:
- printf("SIOCSIFFLAGS\n");
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- us->ifflags = ((struct iocblk_in *)iop)->ioc_ifflags;
- error = 0;
- break;
-
- case SIOCSIFADDR:
- printf("SIOCSIFADDR\n");
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- us->ifflags |= IFF_RUNNING;
- ((struct iocblk_in *)iop)->ioc_ifflags |= IFF_RUNNING;
- error = 0;
- break;
-
- case SIOCGIFNETMASK:
- case SIOCSIFNETMASK:
- case SIOCGIFADDR:
- case SIOCGIFDSTADDR:
- case SIOCSIFDSTADDR:
- case SIOCGIFMETRIC:
- error = 0;
- break;
-#endif
-
- default:
- if (us->ppa == 0 || us->ppa->lowerq == 0)
- break;
- us->ioc_id = iop->ioc_id;
- error = -1;
- switch (iop->ioc_cmd) {
- case PPPIO_GETSTAT:
- case PPPIO_GETCSTAT:
- if (us->flags & US_LASTMOD) {
- error = EINVAL;
- break;
- }
- putnext(us->ppa->lowerq, mp);
- break;
- default:
- if (us->flags & US_PRIV)
- putnext(us->ppa->lowerq, mp);
- else {
-#if DEBUG
- cmn_err(CE_CONT, "ppp ioctl %x rejected\n", iop->ioc_cmd);
-#endif
- error = EPERM;
- }
- break;
- }
- break;
- }
-
- if (error > 0) {
- iop->ioc_error = error;
- mp->b_datap->db_type = M_IOCNAK;
- qreply(q, mp);
- } else if (error == 0) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- }
- break;
-
- case M_FLUSH:
- if (us->flags & US_DBGLOG)
- cmn_err(CE_CONT, "ppp/%d: flush %x\n", us->mn, *mp->b_rptr);
- if (*mp->b_rptr & FLUSHW)
- flushq(q, FLUSHDATA);
- if (*mp->b_rptr & FLUSHR) {
- *mp->b_rptr &= ~FLUSHW;
- qreply(q, mp);
- } else
- freemsg(mp);
- break;
-
- default:
- freemsg(mp);
- break;
- }
- return 0;
-}
-
-static void
-dlpi_request(q, mp, us)
- queue_t *q;
- mblk_t *mp;
- upperstr_t *us;
-{
- union DL_primitives *d = (union DL_primitives *) mp->b_rptr;
- int size = mp->b_wptr - mp->b_rptr;
- mblk_t *reply, *np;
- upperstr_t *ppa, *os;
- int sap, *ip, len;
- dl_info_ack_t *info;
- dl_bind_ack_t *ackp;
-
- if (us->flags & US_DBGLOG)
- cmn_err(CE_CONT, "ppp/%d: dlpi prim %x len=%d\n", us->mn,
- d->dl_primitive, size);
- switch (d->dl_primitive) {
- case DL_INFO_REQ:
- if (size < sizeof(dl_info_req_t))
- goto badprim;
- if ((reply = allocb(sizeof(dl_info_ack_t), BPRI_HI)) == 0)
- break; /* should do bufcall */
- reply->b_datap->db_type = M_PCPROTO;
- info = (dl_info_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_info_ack_t);
- bzero((caddr_t) info, sizeof(dl_info_ack_t));
- info->dl_primitive = DL_INFO_ACK;
- info->dl_max_sdu = PPP_MAXMTU;
- info->dl_min_sdu = 1;
- info->dl_addr_length = sizeof(ulong);
-#ifdef DL_OTHER
- info->dl_mac_type = DL_OTHER;
-#else
- info->dl_mac_type = DL_HDLC; /* a lie */
-#endif
- info->dl_current_state = us->state;
- info->dl_service_mode = DL_CLDLS;
- info->dl_provider_style = DL_STYLE2;
-#if DL_CURRENT_VERSION >= 2
- info->dl_sap_length = sizeof(ulong);
- info->dl_version = DL_CURRENT_VERSION;
-#endif
- qreply(q, reply);
- break;
-
- case DL_ATTACH_REQ:
- if (size < sizeof(dl_attach_req_t))
- goto badprim;
- if (us->state != DL_UNATTACHED || us->ppa != 0) {
- dlpi_error(q, DL_ATTACH_REQ, DL_OUTSTATE, 0);
- break;
- }
- for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
- if (ppa->ppa_id == d->attach_req.dl_ppa)
- break;
- if (ppa == 0) {
- dlpi_error(q, DL_ATTACH_REQ, DL_BADPPA, 0);
- break;
- }
- us->ppa = ppa;
- qwriter(q, mp, attach_ppa, PERIM_OUTER);
- break;
-
- case DL_DETACH_REQ:
- if (size < sizeof(dl_detach_req_t))
- goto badprim;
- if (us->state != DL_UNBOUND || us->ppa == 0) {
- dlpi_error(q, DL_DETACH_REQ, DL_OUTSTATE, 0);
- break;
- }
- qwriter(q, mp, detach_ppa, PERIM_OUTER);
- break;
-
- case DL_BIND_REQ:
- if (size < sizeof(dl_bind_req_t))
- goto badprim;
- if (us->state != DL_UNBOUND || us->ppa == 0) {
- dlpi_error(q, DL_BIND_REQ, DL_OUTSTATE, 0);
- break;
- }
- if (d->bind_req.dl_service_mode != DL_CLDLS) {
- dlpi_error(q, DL_BIND_REQ, DL_UNSUPPORTED, 0);
- break;
- }
-
- /* saps must be valid PPP network protocol numbers,
- except that we accept ETHERTYPE_IP in place of PPP_IP. */
- sap = d->bind_req.dl_sap;
- us->req_sap = sap;
-#if DEBUG
- cmn_err(CE_CONT, "ppp bind %x\n", sap);
-#endif
- if (sap == ETHERTYPE_IP)
- sap = PPP_IP;
- if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
- dlpi_error(q, DL_BIND_REQ, DL_BADADDR, 0);
- break;
- }
-
- /* check that no other stream is bound to this sap already. */
- for (os = us->ppa; os != 0; os = os->next)
- if (os->sap == sap)
- break;
- if (os != 0) {
- dlpi_error(q, DL_BIND_REQ, DL_NOADDR, 0);
- break;
- }
-
- us->sap = sap;
- us->state = DL_IDLE;
-
- if ((reply = allocb(sizeof(dl_bind_ack_t) + sizeof(ulong),
- BPRI_HI)) == 0)
- break; /* should do bufcall */
- ackp = (dl_bind_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_bind_ack_t) + sizeof(ulong);
- reply->b_datap->db_type = M_PCPROTO;
- bzero((caddr_t) ackp, sizeof(dl_bind_ack_t));
- ackp->dl_primitive = DL_BIND_ACK;
- ackp->dl_sap = sap;
- ackp->dl_addr_length = sizeof(ulong);
- ackp->dl_addr_offset = sizeof(dl_bind_ack_t);
- *(ulong *)(ackp+1) = sap;
- qreply(q, reply);
- break;
-
- case DL_UNBIND_REQ:
- if (size < sizeof(dl_unbind_req_t))
- goto badprim;
- if (us->state != DL_IDLE) {
- dlpi_error(q, DL_UNBIND_REQ, DL_OUTSTATE, 0);
- break;
- }
- us->sap = -1;
- us->state = DL_UNBOUND;
-#ifndef sun
- us->ppa->ifstats.ifs_active = 0;
-#endif
- dlpi_ok(q, DL_UNBIND_REQ);
- break;
-
- case DL_UNITDATA_REQ:
- if (size < sizeof(dl_unitdata_req_t))
- goto badprim;
- if (us->state != DL_IDLE) {
- dlpi_error(q, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
- break;
- }
- if (us->ppa == 0) {
- cmn_err(CE_CONT, "ppp: in state dl_idle but ppa == 0?\n");
- break;
- }
- len = mp->b_cont == 0? 0: msgdsize(mp->b_cont);
- if (len > us->ppa->mtu) {
-#if DEBUG
- cmn_err(CE_CONT, "dlpi data too large (%d > %d)\n", len, us->mtu);
-#endif
- break;
- }
- /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
- if (mp->b_datap->db_ref > 1) {
- np = allocb(PPP_HDRLEN, BPRI_HI);
- if (np == 0)
- break; /* gak! */
- np->b_cont = mp->b_cont;
- mp->b_cont = 0;
- freeb(mp);
- mp = np;
- } else
- mp->b_datap->db_type = M_DATA;
- /* XXX should use dl_dest_addr_offset/length here,
- but we would have to translate ETHERTYPE_IP -> PPP_IP */
- mp->b_wptr = mp->b_rptr + PPP_HDRLEN;
- mp->b_rptr[0] = PPP_ALLSTATIONS;
- mp->b_rptr[1] = PPP_UI;
- mp->b_rptr[2] = us->sap >> 8;
- mp->b_rptr[3] = us->sap;
- if (!send_data(mp, us))
- putq(q, mp);
- return;
-
-#if DL_CURRENT_VERSION >= 2
- case DL_SUBS_BIND_REQ:
- case DL_SUBS_UNBIND_REQ:
- case DL_ENABMULTI_REQ:
- case DL_DISABMULTI_REQ:
- case DL_PROMISCON_REQ:
- case DL_PROMISCOFF_REQ:
- case DL_PHYS_ADDR_REQ:
- case DL_SET_PHYS_ADDR_REQ:
- case DL_XID_REQ:
- case DL_TEST_REQ:
- case DL_REPLY_UPDATE_REQ:
- case DL_REPLY_REQ:
- case DL_DATA_ACK_REQ:
-#endif
- case DL_CONNECT_REQ:
- case DL_TOKEN_REQ:
- dlpi_error(q, d->dl_primitive, DL_NOTSUPPORTED, 0);
- break;
-
- case DL_CONNECT_RES:
- case DL_DISCONNECT_REQ:
- case DL_RESET_REQ:
- case DL_RESET_RES:
- dlpi_error(q, d->dl_primitive, DL_OUTSTATE, 0);
- break;
-
- case DL_UDQOS_REQ:
- dlpi_error(q, d->dl_primitive, DL_BADQOSTYPE, 0);
- break;
-
-#if DL_CURRENT_VERSION >= 2
- case DL_TEST_RES:
- case DL_XID_RES:
- break;
-#endif
-
- default:
- cmn_err(CE_CONT, "ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);
- /* fall through */
- badprim:
- dlpi_error(q, d->dl_primitive, DL_BADPRIM, 0);
- break;
- }
- freemsg(mp);
-}
-
-static void
-dlpi_error(q, prim, err, uerr)
- queue_t *q;
- int prim, err, uerr;
-{
- mblk_t *reply;
- dl_error_ack_t *errp;
-
- reply = allocb(sizeof(dl_error_ack_t), BPRI_HI);
- if (reply == 0)
- return; /* XXX should do bufcall */
- reply->b_datap->db_type = M_PCPROTO;
- errp = (dl_error_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_error_ack_t);
- errp->dl_primitive = DL_ERROR_ACK;
- errp->dl_error_primitive = prim;
- errp->dl_errno = err;
- errp->dl_unix_errno = uerr;
- qreply(q, reply);
-}
-
-static void
-dlpi_ok(q, prim)
- queue_t *q;
- int prim;
-{
- mblk_t *reply;
- dl_ok_ack_t *okp;
-
- reply = allocb(sizeof(dl_ok_ack_t), BPRI_HI);
- if (reply == 0)
- return; /* XXX should do bufcall */
- reply->b_datap->db_type = M_PCPROTO;
- okp = (dl_ok_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_ok_ack_t);
- okp->dl_primitive = DL_OK_ACK;
- okp->dl_correct_primitive = prim;
- qreply(q, reply);
-}
-
-static int
-send_data(mp, us)
- mblk_t *mp;
- upperstr_t *us;
-{
- queue_t *q;
- upperstr_t *ppa;
-
- if (us->flags & US_BLOCKED)
- return 0;
- ppa = us->ppa;
- if (ppa == 0) {
- freemsg(mp);
- return 1;
- }
- if ((q = ppa->lowerq) == 0) {
- /* try to send it up the control stream */
- if (canputnext(ppa->q)) {
- putnext(ppa->q, mp);
- return 1;
- }
- } else {
- if (canputnext(ppa->lowerq)) {
- /*
- * The lower write queue's put procedure just updates counters
- * and does a putnext. We call it in order to enter the lower
- * queues' perimeter so that the counter updates are serialized.
- */
- put(ppa->lowerq, mp);
- return 1;
- }
- }
- us->flags |= US_BLOCKED;
- return 0;
-}
-
-/*
- * Allocate a new PPA id and link this stream into the list of PPAs.
- * This procedure is called with an exclusive lock on all queues in
- * this driver.
- */
-static void
-new_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, **usp;
- int ppa_id;
-
- usp = &ppas;
- ppa_id = 0;
- while ((us = *usp) != 0 && ppa_id == us->ppa_id) {
- ++ppa_id;
- usp = &us->nextppa;
- }
- us = (upperstr_t *) q->q_ptr;
- us->ppa_id = ppa_id;
- us->ppa = us;
- us->next = 0;
- us->nextppa = *usp;
- *usp = us;
- us->flags |= US_CONTROL;
-
- us->mtu = PPP_MRU;
- us->mru = PPP_MRU;
-
-#ifdef sun
- if (us->kstats == 0) {
- char unit[32];
-
- sprintf(unit, "ppp%d", us->ppa->ppa_id);
- us->kstats = kstat_create("ppp", us->ppa->ppa_id, unit,
- "net", KSTAT_TYPE_NAMED, 4, 0);
- if (us->kstats != 0) {
- kstat_named_t *kn = KSTAT_NAMED_PTR(us->kstats);
-
- strcpy(kn[0].name, "ipackets");
- kn[0].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[1].name, "ierrors");
- kn[1].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[2].name, "opackets");
- kn[2].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[3].name, "oerrors");
- kn[3].data_type = KSTAT_DATA_ULONG;
- kstat_install(us->kstats);
- }
- }
-#endif
-
- *(int *)mp->b_cont->b_rptr = ppa_id;
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
-}
-
-static void
-attach_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, *t;
-
- us = (upperstr_t *) q->q_ptr;
- us->state = DL_UNBOUND;
- for (t = us->ppa; t->next != 0; t = t->next)
- ;
- t->next = us;
- us->next = 0;
- if (mp->b_datap->db_type == M_IOCTL) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- } else {
- dlpi_ok(q, DL_ATTACH_REQ);
- }
-}
-
-static void
-detach_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, *t;
-
- us = (upperstr_t *) q->q_ptr;
- for (t = us->ppa; t->next != 0; t = t->next)
- if (t->next == us) {
- t->next = us->next;
- break;
- }
- us->next = 0;
- us->ppa = 0;
- us->state = DL_UNATTACHED;
- dlpi_ok(q, DL_DETACH_REQ);
-}
-
-static int
-pppuwsrv(q)
- queue_t *q;
-{
- upperstr_t *us;
- struct lowerstr *ls;
- queue_t *lwq;
- mblk_t *mp;
-
- us = (upperstr_t *) q->q_ptr;
- us->flags &= ~US_BLOCKED;
- while ((mp = getq(q)) != 0) {
- if (!send_data(mp, us)) {
- putbq(q, mp);
- break;
- }
- }
- return 0;
-}
-
-static int
-ppplwput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *ppa;
-
- ppa = q->q_ptr;
- if (ppa != 0) { /* why wouldn't it? */
- ppa->stats.ppp_opackets++;
- ppa->stats.ppp_obytes += msgdsize(mp);
-#ifdef sun
- if (ppa->kstats != 0)
- KSTAT_NAMED_PTR(ppa->kstats)[2].value.ul++;
-#else
- ppa->ifstats.ifs_opackets++;
-#endif
- }
- putnext(q, mp);
- return 0;
-}
-
-static int
-ppplwsrv(q)
- queue_t *q;
-{
- upperstr_t *us;
-
- /*
- * Flow control has back-enabled this stream:
- * enable the write service procedures of all upper
- * streams feeding this lower stream.
- */
- for (us = (upperstr_t *) q->q_ptr; us != NULL; us = us->next)
- if (us->flags & US_BLOCKED)
- qenable(WR(us->q));
- return 0;
-}
-
-static int
-pppursrv(q)
- queue_t *q;
-{
- upperstr_t *us, *as;
- mblk_t *mp, *hdr;
- dl_unitdata_ind_t *ud;
- int proto;
-
- us = (upperstr_t *) q->q_ptr;
- if (us->flags & US_CONTROL) {
- /*
- * A control stream.
- * If there is no lower queue attached, run the write service
- * routines of other upper streams attached to this PPA.
- */
- if (us->lowerq == 0) {
- as = us;
- do {
- if (as->flags & US_BLOCKED)
- qenable(WR(as->q));
- as = as->next;
- } while (as != 0);
- }
- } else {
- /*
- * A network protocol stream. Put a DLPI header on each
- * packet and send it on.
- * (Actually, it seems that the IP module will happily
- * accept M_DATA messages without the DL_UNITDATA_IND header.)
- */
- while ((mp = getq(q)) != 0) {
- if (!canputnext(q)) {
- putbq(q, mp);
- break;
- }
- proto = PPP_PROTOCOL(mp->b_rptr);
- mp->b_rptr += PPP_HDRLEN;
- hdr = allocb(sizeof(dl_unitdata_ind_t) + 2 * sizeof(ulong),
- BPRI_MED);
- if (hdr == 0) {
- /* XXX should put it back and use bufcall */
- freemsg(mp);
- continue;
- }
- hdr->b_datap->db_type = M_PROTO;
- ud = (dl_unitdata_ind_t *) hdr->b_wptr;
- hdr->b_wptr += sizeof(dl_unitdata_ind_t) + 2 * sizeof(ulong);
- hdr->b_cont = mp;
- ud->dl_primitive = DL_UNITDATA_IND;
- ud->dl_dest_addr_length = sizeof(ulong);
- ud->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
- ud->dl_src_addr_length = sizeof(ulong);
- ud->dl_src_addr_offset = ud->dl_dest_addr_offset + sizeof(ulong);
-#if DL_CURRENT_VERSION >= 2
- ud->dl_group_address = 0;
-#endif
- /* Send the DLPI client the data with the SAP they requested,
- (e.g. ETHERTYPE_IP) rather than the PPP protocol number
- (e.g. PPP_IP) */
- ((ulong *)(ud + 1))[0] = us->req_sap; /* dest SAP */
- ((ulong *)(ud + 1))[1] = us->req_sap; /* src SAP */
- putnext(q, hdr);
- }
- }
-
- /*
- * If this stream is attached to a PPA with a lower queue pair,
- * enable the read queue's service routine if it has data queued.
- * XXX there is a possibility that packets could get out of order
- * if ppplrput now runs before ppplrsrv.
- */
- if (us->ppa != 0 && us->ppa->lowerq != 0)
- qenable(RD(us->ppa->lowerq));
-
- return 0;
-}
-
-static upperstr_t *
-find_dest(ppa, proto)
- upperstr_t *ppa;
- int proto;
-{
- upperstr_t *us;
-
- for (us = ppa->next; us != 0; us = us->next)
- if (proto == us->sap)
- break;
- return us;
-}
-
-static int
-ppplrput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *ppa, *us;
- queue_t *uq;
- int proto, len;
- mblk_t *np;
- struct iocblk *iop;
-
- ppa = (upperstr_t *) q->q_ptr;
- if (ppa == 0) {
-#if DEBUG
- cmn_err(CE_CONT, "ppplrput: q = %x, ppa = 0??\n", q);
-#endif
- freemsg(mp);
- return 0;
- }
- switch (mp->b_datap->db_type) {
- case M_FLUSH:
- if (*mp->b_rptr & FLUSHW) {
- *mp->b_rptr &= ~FLUSHR;
- qreply(q, mp);
- } else
- freemsg(mp);
- break;
-
- case M_CTL:
- switch (*mp->b_rptr) {
- case PPPCTL_IERROR:
-#ifdef sun
- if (ppa->kstats != 0) {
- KSTAT_NAMED_PTR(ppa->kstats)[1].value.ul++;
- }
-#else
- ppa->ifstats.ifs_ierrors++;
-#endif
- ppa->stats.ppp_ierrors++;
- break;
- case PPPCTL_OERROR:
-#ifdef sun
- if (ppa->kstats != 0) {
- KSTAT_NAMED_PTR(ppa->kstats)[3].value.ul++;
- }
-#else
- ppa->ifstats.ifs_oerrors++;
-#endif
- ppa->stats.ppp_oerrors++;
- break;
- }
- freemsg(mp);
- break;
-
- case M_IOCACK:
- case M_IOCNAK:
- /*
- * Attempt to match up the response with the stream
- * that the request came from.
- */
- iop = (struct iocblk *) mp->b_rptr;
- for (us = ppa; us != 0; us = us->next)
- if (us->ioc_id == iop->ioc_id)
- break;
- if (us == 0)
- freemsg(mp);
- else
- putnext(us->q, mp);
- break;
-
- default:
- if (mp->b_datap->db_type == M_DATA) {
- len = msgdsize(mp);
- if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN) {
-#ifdef USE_MSGPULLUP
- np = msgpullup(mp, PPP_HDRLEN);
- freemsg(mp);
- if (np == 0) {
-#if DEBUG
- cmn_err(CE_CONT, "ppp_lrput: msgpullup failed (len=%d)\n",
- len);
-#endif
- break;
- }
- mp = np;
-#else
- if (!pullupmsg (mp, PPP_HDRLEN)) {
-#if DEBUG
- cmn_err(CE_CONT, "ppp_lrput: pullupmsg failed (len=%d)\n",
- len);
-#endif
- break;
- }
-#endif
- }
- ppa->stats.ppp_ipackets++;
- ppa->stats.ppp_ibytes += len;
-#ifdef sun
- if (ppa->kstats != 0) {
- KSTAT_NAMED_PTR(ppa->kstats)[0].value.ul++;
- }
-#else
- ppa->ifstats.ifs_ipackets++;
-#endif
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
- /*
- * A data packet for some network protocol.
- * Queue it on the upper stream for that protocol.
- */
- if (canput(us->q))
- putq(us->q, mp);
- else
- putq(q, mp);
- break;
- }
- }
- /*
- * A control frame, a frame for an unknown protocol,
- * or some other message type.
- * Send it up to pppd via the control stream.
- */
- if (queclass(mp) == QPCTL || canputnext(ppa->q))
- putnext(ppa->q, mp);
- else
- putq(q, mp);
- break;
- }
-
- return 0;
-}
-
-static int
-ppplrsrv(q)
- queue_t *q;
-{
- mblk_t *mp;
- upperstr_t *ppa, *us;
- int proto;
-
- /*
- * Packets only get queued here for flow control reasons.
- */
- ppa = (upperstr_t *) q->q_ptr;
- while ((mp = getq(q)) != 0) {
- if (mp->b_datap->db_type == M_DATA
- && (proto = PPP_PROTOCOL(mp->b_rptr)) < 0x8000
- && (us = find_dest(ppa, proto)) != 0) {
- if (canput(us->q))
- putq(us->q, mp);
- else {
- putbq(q, mp);
- break;
- }
- } else {
- if (canputnext(ppa->q))
- putnext(ppa->q, mp);
- else {
- putbq(q, mp);
- break;
- }
- }
- }
- return 0;
-}
-
-static int
-putctl2(q, type, code, val)
- queue_t *q;
- int type, code, val;
-{
- mblk_t *mp;
-
- mp = allocb(2, BPRI_HI);
- if (mp == 0)
- return 0;
- mp->b_datap->db_type = type;
- mp->b_wptr[0] = code;
- mp->b_wptr[1] = val;
- mp->b_wptr += 2;
- putnext(q, mp);
- return 1;
-}
-
-static int
-putctl4(q, type, code, val)
- queue_t *q;
- int type, code, val;
-{
- mblk_t *mp;
-
- mp = allocb(4, BPRI_HI);
- if (mp == 0)
- return 0;
- mp->b_datap->db_type = type;
- mp->b_wptr[0] = code;
- ((short *)mp->b_wptr)[1] = val;
- mp->b_wptr += 4;
- putnext(q, mp);
- return 1;
-}
-
-static void
-debug_dump(q, mp)
- queue_t *q; /* not used */
- mblk_t *mp; /* not used either */
-{
- upperstr_t *us;
- queue_t *uq, *lq;
-
- cmn_err(CE_CONT, "ppp upper streams:\n");
- for (us = minor_devs; us != 0; us = us->nextmn) {
- uq = us->q;
- cmn_err(CE_CONT, " %d: q=%x rlev=%d wlev=%d flags=0x%b",
- us->mn, uq, (uq? qsize(uq): 0), (uq? qsize(WR(uq)): 0),
- us->flags, "\020\1priv\2control\3blocked\4last");
- cmn_err(CE_CONT, " state=%x sap=%x req_sap=%x", us->state, us->sap,
- us->req_sap);
- if (us->ppa == 0)
- cmn_err(CE_CONT, " ppa=?\n");
- else
- cmn_err(CE_CONT, " ppa=%d\n", us->ppa->ppa_id);
- if (us->flags & US_CONTROL) {
- lq = us->lowerq;
- cmn_err(CE_CONT, " control for %d lq=%x rlev=%d wlev=%d",
- us->ppa_id, lq, (lq? qsize(RD(lq)): 0),
- (lq? qsize(lq): 0));
- cmn_err(CE_CONT, " mru=%d mtu=%d\n", us->mru, us->mtu);
- }
- }
-}
+++ /dev/null
-/*
- * ppp_ahdlc.c - STREAMS module for doing PPP asynchronous HDLC.
- *
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies. This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
- *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- *
- * $Id: ppp_ahdlc.c,v 1.5 1995/10/27 03:57:10 paulus Exp $
- */
-
-/*
- * This file is used under Solaris 2.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stream.h>
-#include <sys/conf.h>
-#include <sys/kmem.h>
-#include <sys/errno.h>
-#include <sys/cmn_err.h>
-#include <sys/ddi.h>
-#ifdef sun
-#include <sys/modctl.h>
-#include <sys/sunddi.h>
-#endif
-#include <net/ppp_defs.h>
-#include <net/pppio.h>
-
-#define IFRAME_BSIZE 512 /* Block size to allocate for input */
-#define OFRAME_BSIZE 4096 /* Don't allocb more than this for output */
-
-static int ahdlc_open __P((queue_t *, dev_t *, int, int, cred_t *));
-static int ahdlc_close __P((queue_t *, int, cred_t *));
-static int ahdlc_wput __P((queue_t *, mblk_t *));
-static int ahdlc_rput __P((queue_t *, mblk_t *));
-static void stuff_frame __P((queue_t *, mblk_t *));
-static void unstuff_chars __P((queue_t *, mblk_t *));
-static int msg_copy __P((uchar_t *, mblk_t *, int));
-
-static struct module_info minfo = {
- 0x7d23, "ppp_ahdl", 0, INFPSZ, 4096, 128
-};
-
-static struct qinit rinit = {
- ahdlc_rput, NULL, ahdlc_open, ahdlc_close, NULL, &minfo, NULL
-};
-
-static struct qinit winit = {
- ahdlc_wput, NULL, NULL, NULL, NULL, &minfo, NULL
-};
-
-static struct streamtab ahdlc_info = {
- &rinit, &winit, NULL, NULL
-};
-
-#ifdef sun
-static struct fmodsw fsw = {
- "ppp_ahdl",
- &ahdlc_info,
- D_NEW | D_MP | D_MTQPAIR
-};
-
-extern struct mod_ops mod_strmodops;
-
-static struct modlstrmod modlstrmod = {
- &mod_strmodops,
- "PPP async HDLC module",
- &fsw
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- (void *) &modlstrmod,
- NULL
-};
-#endif /* sun */
-
-typedef struct ahdlc_state {
- int flags;
- mblk_t *cur_frame;
- mblk_t *cur_blk;
- int inlen;
- ushort infcs;
- u_int32_t xaccm[8];
- u_int32_t raccm;
- int mtu;
- int mru;
- int unit;
- struct pppstat stats;
-} ahdlc_state_t;
-
-/* Values for flags */
-#define ESCAPED 0x100 /* last saw escape char on input */
-#define IFLUSH 0x200 /* flushing input due to error */
-
-/* RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also. */
-#define RCV_FLAGS (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
-
-#ifndef sun
-# define qprocson(q)
-# define qprocsoff(q)
-#endif
-
-/*
- * FCS lookup table as calculated by genfcstab.
- */
-static u_short fcstab[256] = {
- 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
- 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
- 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
- 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
- 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
- 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
- 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
- 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
- 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
- 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
- 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
- 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
- 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
- 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
- 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
- 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
- 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
- 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
- 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
- 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
- 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
- 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
- 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
- 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
- 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
- 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
- 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
- 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
- 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
- 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
- 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
- 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-};
-
-#ifdef sun
-/*
- * Entry points for modloading.
- */
-int
-_init(void)
-{
- return mod_install(&modlinkage);
-}
-
-int
-_fini(void)
-{
- return mod_remove(&modlinkage);
-}
-
-int
-_info(mip)
- struct modinfo *mip;
-{
- return mod_info(&modlinkage, mip);
-}
-#endif
-
-/*
- * STREAMS module entry points.
- */
-static int
-ahdlc_open(q, devp, flag, sflag, credp)
- queue_t *q;
- dev_t *devp;
- int flag, sflag;
- cred_t *credp;
-{
- ahdlc_state_t *sp;
-
- if (q->q_ptr == 0) {
- sp = (ahdlc_state_t *) kmem_zalloc(sizeof(ahdlc_state_t), KM_SLEEP);
- if (sp == 0)
- return ENOSR;
- q->q_ptr = sp;
- WR(q)->q_ptr = sp;
- sp->xaccm[0] = ~0;
- sp->xaccm[3] = 0x60000000;
- sp->mru = 1500;
- qprocson(q);
- }
- return 0;
-}
-
-static int
-ahdlc_close(q, flag, credp)
- queue_t *q;
- int flag;
- cred_t *credp;
-{
- ahdlc_state_t *state;
-
- qprocsoff(q);
- if (q->q_ptr != 0) {
- state = (ahdlc_state_t *) q->q_ptr;
- if (state->cur_frame != 0) {
- freemsg(state->cur_frame);
- state->cur_frame = 0;
- }
- kmem_free(q->q_ptr, sizeof(ahdlc_state_t));
- }
- return 0;
-}
-
-static int
-ahdlc_wput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- ahdlc_state_t *state;
- struct iocblk *iop;
- int error;
- mblk_t *np;
- struct ppp_stats *psp;
-
- state = (ahdlc_state_t *) q->q_ptr;
- switch (mp->b_datap->db_type) {
- case M_DATA:
- /*
- * A data packet - do character-stuffing and FCS, and
- * send it onwards.
- */
- stuff_frame(q, mp);
- freemsg(mp);
- break;
-
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- error = EINVAL;
- switch (iop->ioc_cmd) {
- case PPPIO_XACCM:
- if (iop->ioc_count < sizeof(u_int32_t)
- || iop->ioc_count > sizeof(ext_accm))
- break;
- bcopy(mp->b_cont->b_rptr, (caddr_t)state->xaccm, iop->ioc_count);
- state->xaccm[2] &= 0x40000000; /* don't escape 0x5e */
- state->xaccm[3] |= 0x60000000; /* do escape 0x7d, 0x7e */
- iop->ioc_count = 0;
- error = 0;
- break;
-
- case PPPIO_RACCM:
- if (iop->ioc_count != sizeof(u_int32_t))
- break;
- bcopy(mp->b_cont->b_rptr, (caddr_t)&state->raccm,
- sizeof(u_int32_t));
- iop->ioc_count = 0;
- error = 0;
- break;
-
- case PPPIO_GCLEAN:
- np = allocb(sizeof(int), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
- *(int *)np->b_wptr = state->flags & RCV_FLAGS;
- np->b_wptr += sizeof(int);
- iop->ioc_count = sizeof(int);
- error = 0;
- break;
-
- case PPPIO_GETSTAT:
- np = allocb(sizeof(struct ppp_stats), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
- psp = (struct ppp_stats *) np->b_wptr;
- np->b_wptr += sizeof(struct ppp_stats);
- bzero((caddr_t)psp, sizeof(struct ppp_stats));
- psp->p = state->stats;
- iop->ioc_count = sizeof(struct ppp_stats);
- error = 0;
- break;
-
- case PPPIO_LASTMOD:
- /* we knew this anyway */
- error = 0;
- break;
-
- default:
- error = -1;
- break;
- }
-
- if (error < 0)
- putnext(q, mp);
- else if (error == 0) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- } else {
- mp->b_datap->db_type = M_IOCNAK;
- iop->ioc_count = 0;
- iop->ioc_error = error;
- qreply(q, mp);
- }
- break;
-
- case M_CTL:
- switch (*mp->b_rptr) {
- case PPPCTL_MTU:
- state->mtu = ((unsigned short *)mp->b_rptr)[1];
- freemsg(mp);
- break;
- case PPPCTL_MRU:
- state->mru = ((unsigned short *)mp->b_rptr)[1];
- freemsg(mp);
- break;
- case PPPCTL_UNIT:
- state->unit = mp->b_rptr[1];
- break;
- default:
- putnext(q, mp);
- }
- break;
-
- default:
- putnext(q, mp);
- }
- return 0;
-}
-
-static int
-ahdlc_rput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- mblk_t *np;
- uchar_t *cp;
- ahdlc_state_t *state;
-
- switch (mp->b_datap->db_type) {
- case M_DATA:
- unstuff_chars(q, mp);
- freemsg(mp);
- break;
-
- case M_HANGUP:
- state = (ahdlc_state_t *) q->q_ptr;
- if (state->cur_frame != 0) {
- /* XXX would like to send this up for debugging */
- freemsg(state->cur_frame);
- state->cur_frame = 0;
- state->cur_blk = 0;
- }
- state->inlen = 0;
- state->flags = IFLUSH;
- putnext(q, mp);
- break;
-
- default:
- putnext(q, mp);
- }
- return 0;
-}
-
-/* Extract bit c from map m, to determine if c needs to be escaped. */
-#define ESCAPE(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
-
-static void
-stuff_frame(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- ahdlc_state_t *state;
- int ilen, olen, c, extra, i;
- mblk_t *omsg, *op, *np;
- uchar_t *sp, *sp0, *dp, *dp0, *spend;
- ushort_t fcs;
- u_int32_t *xaccm, lcp_xaccm[8];
- static uchar_t lcphdr[PPP_HDRLEN] = { 0xff, 0x03, 0xc0, 0x21 };
- uchar_t ppphdr[PPP_HDRLEN];
-
- state = (ahdlc_state_t *) q->q_ptr;
- ilen = msgdsize(mp);
-
- /*
- * We estimate the length of the output packet as
- * 1.25 * input length + 16 (for initial flag, FCS, final flag, slop).
- */
- olen = ilen + (ilen >> 2) + 16;
- if (olen > OFRAME_BSIZE)
- olen = OFRAME_BSIZE;
- omsg = op = allocb(olen, BPRI_MED);
- if (omsg == 0)
- goto bomb;
-
- /*
- * Put in an initial flag for now. We'll remove it later
- * if we decide we don't need it.
- */
- dp = op->b_wptr;
- *dp++ = PPP_FLAG;
- --olen;
-
- /*
- * For LCP packets, we must escape all control characters.
- * Inspect the first PPP_HDRLEN bytes of the message to
- * see whether it is an LCP packet.
- * LCP packets must not be A/C or protocol compressed.
- */
- xaccm = state->xaccm;
- if (msg_copy(ppphdr, mp, PPP_HDRLEN) == PPP_HDRLEN
- && bcmp((caddr_t) ppphdr, (caddr_t) lcphdr, PPP_HDRLEN) == 0) {
- bcopy((caddr_t) state->xaccm, (caddr_t) lcp_xaccm, sizeof(lcp_xaccm));
- lcp_xaccm[0] = ~0;
- xaccm = lcp_xaccm;
- }
-
- sp = mp->b_rptr;
- fcs = PPP_INITFCS;
- for (;;) {
- spend = mp->b_wptr;
- extra = sp + olen - spend;
- if (extra < 0) {
- spend = sp + olen;
- extra = 0;
- }
- /*
- * We can safely process the input up to `spend'
- * without overrunning the output, provided we don't
- * hit more than `extra' characters which need to be escaped.
- */
- sp0 = sp;
- dp0 = dp;
- while (sp < spend) {
- c = *sp;
- if (ESCAPE(c, xaccm)) {
- if (extra > 0)
- --extra;
- else if (sp < spend - 1)
- --spend;
- else
- break;
- fcs = PPP_FCS(fcs, c);
- *dp++ = PPP_ESCAPE;
- c ^= PPP_TRANS;
- } else
- fcs = PPP_FCS(fcs, c);
- *dp++ = c;
- ++sp;
- }
- ilen -= sp - sp0;
- olen -= dp - dp0;
-
- /*
- * At this point, we have emptied an input block
- * and/or filled an output block.
- */
- if (sp >= mp->b_wptr) {
- /*
- * We've emptied an input block. Advance to the next.
- */
- mp = mp->b_cont;
- if (mp == 0)
- break; /* all done */
- sp = mp->b_rptr;
- }
- if (olen < 2) {
- /*
- * The output block is full. Allocate a new one.
- */
- op->b_wptr = dp;
- olen = 2 * ilen + 5;
- if (olen > OFRAME_BSIZE)
- olen = OFRAME_BSIZE;
- np = allocb(olen, BPRI_MED);
- if (np == 0)
- goto bomb;
- op->b_cont = np;
- op = np;
- dp = op->b_wptr;
- }
- }
-
- /*
- * Append the FCS and closing flag.
- * This could require up to 5 characters.
- */
- if (olen < 5) {
- /* Sigh. Need another block. */
- op->b_wptr = dp;
- np = allocb(5, BPRI_MED);
- if (np == 0)
- goto bomb;
- op->b_cont = np;
- op = np;
- dp = op->b_wptr;
- }
- c = ~fcs & 0xff;
- if (ESCAPE(c, xaccm)) {
- *dp++ = PPP_ESCAPE;
- c ^= PPP_TRANS;
- }
- *dp++ = c;
- c = (~fcs >> 8) & 0xff;
- if (ESCAPE(c, xaccm)) {
- *dp++ = PPP_ESCAPE;
- c ^= PPP_TRANS;
- }
- *dp++ = c;
- *dp++ = PPP_FLAG;
- op->b_wptr = dp;
-
- /*
- * Remove the initial flag, if possible.
- */
- if (qsize(q->q_next) > 0)
- ++omsg->b_rptr;
-
- /*
- * Update statistics.
- */
- state->stats.ppp_obytes += msgdsize(omsg);
- state->stats.ppp_opackets++;
-
- /*
- * Send it on.
- */
- putnext(q, omsg);
- return;
-
- bomb:
- if (omsg != 0)
- freemsg(omsg);
- state->stats.ppp_oerrors++;
- putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
-}
-
-static unsigned paritytab[8] = {
- 0x96696996, 0x69969669, 0x69969669, 0x96696996,
- 0x69969669, 0x96696996, 0x96696996, 0x69969669
-};
-
-#define UPDATE_FLAGS(c) { \
- if ((c) & 0x80) \
- state->flags |= RCV_B7_1; \
- else \
- state->flags |= RCV_B7_0; \
- if (paritytab[(c) >> 5] & (1 << ((c) & 0x1F))) \
- state->flags |= RCV_ODDP; \
- else \
- state->flags |= RCV_EVNP; \
-}
-
-/*
- * Process received characters.
- */
-static void
-unstuff_chars(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- ahdlc_state_t *state;
- mblk_t *om;
- uchar_t *cp, *cpend, *dp, *dp0;
- int c, len, extra, offset;
- ushort_t fcs;
-
- state = (ahdlc_state_t *) q->q_ptr;
- state->stats.ppp_ibytes += msgdsize(mp);
- cp = mp->b_rptr;
- for (;;) {
- /*
- * Advance to next input block if necessary.
- */
- if (cp >= mp->b_wptr) {
- mp = mp->b_cont;
- if (mp == 0)
- break;
- cp = mp->b_rptr;
- continue;
- }
-
- if ((state->flags & (IFLUSH|ESCAPED)) == 0
- && state->inlen > 0 && (om = state->cur_blk) != 0) {
- /*
- * Process bulk chars as quickly as possible.
- */
- dp = om->b_wptr;
- len = om->b_datap->db_lim - dp; /* max # output bytes */
- extra = (mp->b_wptr - cp) - len;/* #input chars - #output bytes */
- if (extra < 0) {
- len += extra; /* we'll run out of input first */
- extra = 0;
- }
- cpend = cp + len;
- dp0 = dp;
- fcs = state->infcs;
- while (cp < cpend) {
- c = *cp;
- if (c == PPP_FLAG)
- break;
- ++cp;
- UPDATE_FLAGS(c);
- if (c == PPP_ESCAPE) {
- if (extra > 0) {
- --extra;
- ++cpend;
- }
- if (cp >= cpend || (c = *cp) == PPP_FLAG) {
- state->flags |= ESCAPED;
- break;
- }
- ++cp;
- UPDATE_FLAGS(c);
- c ^= PPP_TRANS;
- }
- *dp++ = c;
- fcs = PPP_FCS(fcs, c);
- }
- state->inlen += dp - dp0;
- state->infcs = fcs;
- om->b_wptr = dp;
- if (cp >= mp->b_wptr)
- continue; /* advance to the next mblk */
- }
-
- c = *cp++;
- UPDATE_FLAGS(c);
- if (c == PPP_FLAG) {
- /*
- * End of a frame.
- * If the ESCAPE flag is set, the frame ended with
- * the frame abort sequence "}~".
- */
- om = state->cur_frame;
- len = state->inlen;
- state->cur_frame = 0;
- state->inlen = 0;
- if (len == 0 && (state->flags & IFLUSH) == 0)
- continue;
- state->stats.ppp_ipackets++;
- if (om != 0 && (state->flags & (IFLUSH|ESCAPED)) == 0
- && len > PPP_FCSLEN) {
- if (state->infcs == PPP_GOODFCS) {
- adjmsg(om, -PPP_FCSLEN); /* chop off fcs */
- putnext(q, om); /* bombs away! */
- continue;
- }
-#if DEBUG
- cmn_err(CE_CONT, "ppp_ahdl: bad fcs %x\n", state->infcs);
-#endif
- }
- if (om != 0)
- freemsg(om);
- state->stats.ppp_ierrors++;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- continue;
- }
-
- if (state->flags & IFLUSH)
- continue;
- if (state->flags & ESCAPED) {
- c ^= PPP_TRANS;
- state->flags &= ~ESCAPED;
- } else if (c == PPP_ESCAPE) {
- state->flags |= ESCAPED;
- continue;
- }
- if (state->inlen == 0) {
- /*
- * First byte of the frame: allocate the first message block.
- */
- om = allocb(IFRAME_BSIZE, BPRI_MED);
- if (om == 0) {
- state->flags |= IFLUSH;
- continue;
- }
- state->cur_frame = om;
- state->cur_blk = om;
- state->infcs = PPP_INITFCS;
- } else {
- om = state->cur_blk;
- if (om->b_wptr >= om->b_datap->db_lim) {
- /*
- * Current message block is full. Allocate another one,
- * unless we have run out of MRU.
- */
- if (state->inlen >= state->mru + PPP_HDRLEN + PPP_FCSLEN) {
-#if DEBUG
- cmn_err(CE_CONT, "ppp_ahdl: frame too long (%d)\n",
- state->inlen);
-#endif
- state->flags |= IFLUSH;
- continue;
- }
- om = allocb(IFRAME_BSIZE, BPRI_MED);
- if (om == 0) {
- state->flags |= IFLUSH;
- continue;
- }
- state->cur_blk->b_cont = om;
- state->cur_blk = om;
- }
- }
-
- if (state->inlen == 0) {
- /*
- * We don't do address/control & protocol decompression here,
- * but we try to put the first byte at an offset such that
- * the info field starts on a word boundary. The code here
- * will do this except for packets with protocol compression
- * but not address/control compression.
- */
- if (c != PPP_ALLSTATIONS) {
- om->b_wptr += 2;
- if (c & 1)
- ++om->b_wptr;
- om->b_rptr = om->b_wptr;
- }
- }
-
- *om->b_wptr++ = c;
- ++state->inlen;
- state->infcs = PPP_FCS(state->infcs, c);
- }
-}
-
-static int
-msg_copy(buf, mp, n)
- uchar_t *buf;
- mblk_t *mp;
- int n;
-{
- int i;
- uchar_t *cp;
-
- cp = mp->b_rptr;
- for (i = 0; i < n; ++i) {
- if (cp >= mp->b_wptr) {
- do {
- if ((mp = mp->b_cont) == 0)
- return i;
- } while (mp->b_rptr >= mp->b_wptr);
- cp = mp->b_rptr;
- }
- buf[i] = *cp++;
- }
- return n;
-}
+++ /dev/null
-/*
- * ppp_comp.c - STREAMS module for kernel-level compression and CCP support.
- *
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies. This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
- *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- *
- * $Id: ppp_comp.c,v 1.5 1995/10/27 03:56:19 paulus Exp $
- */
-
-/*
- * This file is used under SVR4 and Solaris 2.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/errno.h>
-#include <sys/stream.h>
-#include <sys/conf.h>
-#include <sys/kmem.h>
-#include <sys/cmn_err.h>
-#include <sys/ddi.h>
-#ifdef sun
-#include <sys/modctl.h>
-#include <sys/sunddi.h>
-#endif
-#include <net/ppp_defs.h>
-#include <net/pppio.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <net/vjcompress.h>
-
-#define PACKETPTR mblk_t *
-#include <net/ppp-comp.h>
-
-static int ppp_comp_open __P((queue_t *, dev_t *, int, int, cred_t *));
-static int ppp_comp_close __P((queue_t *, int, cred_t *));
-static int ppp_comp_rput __P((queue_t *, mblk_t *));
-static int ppp_comp_rsrv __P((queue_t *));
-static int ppp_comp_wput __P((queue_t *, mblk_t *));
-static int ppp_comp_wsrv __P((queue_t *));
-static void ppp_comp_ccp __P((queue_t *, mblk_t *, int));
-
-static struct module_info minfo = {
- 0xbadf, "ppp_comp", 0, INFPSZ, 16384, 4096,
-};
-
-static struct qinit r_init = {
- ppp_comp_rput, ppp_comp_rsrv, ppp_comp_open, ppp_comp_close,
- NULL, &minfo, NULL
-};
-
-static struct qinit w_init = {
- ppp_comp_wput, ppp_comp_wsrv, NULL, NULL, NULL, &minfo, NULL
-};
-
-static struct streamtab ppp_compinfo = {
- &r_init, &w_init, NULL, NULL
-};
-
-#if defined(sun) && defined(svr4) /* Solaris 2 */
-static struct fmodsw fsw = {
- "ppp_comp",
- &ppp_compinfo,
- D_NEW | D_MP | D_MTQPAIR
-};
-
-extern struct mod_ops mod_strmodops;
-
-static struct modlstrmod modlstrmod = {
- &mod_strmodops,
- "PPP compression module",
- &fsw
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- (void *) &modlstrmod,
- NULL
-};
-#endif
-
-typedef struct comp_state {
- int flags;
- int mru;
- int mtu;
- int unit;
- struct compressor *xcomp;
- void *xstate;
- struct compressor *rcomp;
- void *rstate;
- struct vjcompress vj_comp;
- int vj_last_ierrors;
- struct pppstat stats;
-} comp_state_t;
-
-/* Bits in flags are as defined in pppio.h. */
-#define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
-#define LAST_MOD 0x1000000 /* no ppp modules below us */
-
-#define MAX_IPHDR 128 /* max TCP/IP header size */
-#define MAX_VJHDR 20 /* max VJ compressed header size (?) */
-
-#undef MIN /* just in case */
-#define MIN(a, b) ((a) < (b)? (a): (b))
-
-#ifdef D_MP
-/* Use msgpullup if we have other multithreading support. */
-#define PULLUP(mp, len) \
- do { \
- mblk_t *np = msgpullup((mp), (len)); \
- freemsg(mp); \
- mp = np; \
- } while (0)
-
-#else
-/* Use pullupmsg if we don't have any multithreading support. */
-#define PULLUP(mp, len) \
- do { \
- if (!pullupmsg((mp), (len))) { \
- freemsg(mp); \
- mp = 0; \
- } \
- } while (0)
-
-#endif
-
-
-/*
- * List of compressors we know about.
- */
-
-extern struct compressor ppp_bsd_compress;
-
-struct compressor *ppp_compressors[] = {
-#if DO_BSD_COMPRESS
- &ppp_bsd_compress,
-#endif
- NULL
-};
-
-#ifdef sun
-/*
- * Entry points for modloading.
- */
-int
-_init(void)
-{
- return mod_install(&modlinkage);
-}
-
-int
-_fini(void)
-{
- return mod_remove(&modlinkage);
-}
-
-int
-_info(mip)
- struct modinfo *mip;
-{
- return mod_info(&modlinkage, mip);
-}
-#endif
-
-#ifndef sun
-# define qprocson(q)
-# define qprocsoff(q)
-#define canputnext(q) canput((q)->q_next)
-#endif
-
-/*
- * STREAMS module entry points.
- */
-static int
-ppp_comp_open(q, devp, flag, sflag, credp)
- queue_t *q;
- dev_t *devp;
- int flag, sflag;
- cred_t *credp;
-{
- comp_state_t *cp;
-
- if (q->q_ptr == NULL) {
- cp = (comp_state_t *) kmem_zalloc(sizeof(comp_state_t), KM_SLEEP);
- if (cp == NULL)
- return ENOSR;
- WR(q)->q_ptr = q->q_ptr = cp;
- bzero((caddr_t)cp, sizeof(comp_state_t));
- cp->mru = PPP_MRU;
- cp->mtu = PPP_MRU;
- cp->xstate = NULL;
- cp->rstate = NULL;
- vj_compress_init(&cp->vj_comp, -1);
- qprocson(q);
- }
- return 0;
-}
-
-static int
-ppp_comp_close(q, flag, credp)
- queue_t *q;
- int flag;
- cred_t *credp;
-{
- comp_state_t *cp;
-
- qprocsoff(q);
- cp = (comp_state_t *) q->q_ptr;
- if (cp != NULL) {
- if (cp->xstate != NULL)
- (*cp->xcomp->comp_free)(cp->xstate);
- if (cp->rstate != NULL)
- (*cp->rcomp->decomp_free)(cp->rstate);
- kmem_free(cp, sizeof(comp_state_t));
- q->q_ptr = NULL;
- OTHERQ(q)->q_ptr = NULL;
- }
- return 0;
-}
-
-static int
-ppp_comp_wput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- struct iocblk *iop;
- comp_state_t *cp;
- int error, len;
- int flags, mask;
- mblk_t *np;
- struct compressor **comp;
- struct ppp_stats *psp;
- struct ppp_comp_stats *csp;
- unsigned char *opt_data;
- int nxslots, nrslots;
-
- cp = (comp_state_t *) q->q_ptr;
- switch (mp->b_datap->db_type) {
-
- case M_DATA:
- putq(q, mp);
- break;
-
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- error = EINVAL;
- switch (iop->ioc_cmd) {
-
- case PPPIO_CFLAGS:
- /* set/get CCP state */
- if (iop->ioc_count != 2 * sizeof(int))
- break;
- flags = ((int *) mp->b_cont->b_rptr)[0];
- mask = ((int *) mp->b_cont->b_rptr)[1];
- cp->flags = (cp->flags & ~mask) | (flags & mask);
- if ((mask & CCP_ISOPEN) && (flags & CCP_ISOPEN) == 0) {
- if (cp->xstate != NULL) {
- (*cp->xcomp->comp_free)(cp->xstate);
- cp->xstate = NULL;
- }
- if (cp->rstate != NULL) {
- (*cp->rcomp->decomp_free)(cp->rstate);
- cp->rstate = NULL;
- }
- cp->flags &= ~CCP_ISUP;
- }
- error = 0;
- iop->ioc_count = sizeof(int);
- ((int *) mp->b_cont->b_rptr)[0] = cp->flags;
- mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof(int);
- break;
-
- case PPPIO_VJINIT:
- /*
- * Initialize VJ compressor/decompressor
- */
- if (iop->ioc_count != 2)
- break;
- nxslots = mp->b_cont->b_rptr[0] + 1;
- nrslots = mp->b_cont->b_rptr[1] + 1;
- if (nxslots > MAX_STATES || nrslots > MAX_STATES)
- break;
- vj_compress_init(&cp->vj_comp, nxslots);
- cp->vj_last_ierrors = cp->stats.ppp_ierrors;
- error = 0;
- iop->ioc_count = 0;
- break;
-
- case PPPIO_XCOMP:
- case PPPIO_RCOMP:
- if (iop->ioc_count <= 0)
- break;
- opt_data = mp->b_cont->b_rptr;
- len = mp->b_cont->b_wptr - opt_data;
- if (len > iop->ioc_count)
- len = iop->ioc_count;
- if (opt_data[1] < 2 || opt_data[1] > len)
- break;
- for (comp = ppp_compressors; *comp != NULL; ++comp)
- if ((*comp)->compress_proto == opt_data[0]) {
- /* here's the handler! */
- error = 0;
- if (iop->ioc_cmd == PPPIO_XCOMP) {
- if (cp->xstate != NULL)
- (*cp->xcomp->comp_free)(cp->xstate);
- cp->xcomp = *comp;
- cp->xstate = (*comp)->comp_alloc(opt_data, len);
- if (cp->xstate == NULL)
- error = ENOSR;
- } else {
- if (cp->rstate != NULL)
- (*cp->rcomp->decomp_free)(cp->rstate);
- cp->rcomp = *comp;
- cp->rstate = (*comp)->decomp_alloc(opt_data, len);
- if (cp->rstate == NULL)
- error = ENOSR;
- }
- break;
- }
- iop->ioc_count = 0;
- break;
-
- case PPPIO_GETSTAT:
- if ((cp->flags & LAST_MOD) == 0) {
- error = -1; /* let the ppp_ahdl module handle it */
- break;
- }
- np = allocb(sizeof(struct ppp_stats), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
- psp = (struct ppp_stats *) np->b_wptr;
- np->b_wptr += sizeof(struct ppp_stats);
- iop->ioc_count = sizeof(struct ppp_stats);
- psp->p = cp->stats;
- psp->vj = cp->vj_comp.stats;
- error = 0;
- break;
-
- case PPPIO_GETCSTAT:
- np = allocb(sizeof(struct ppp_comp_stats), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
- csp = (struct ppp_comp_stats *) np->b_wptr;
- np->b_wptr += sizeof(struct ppp_comp_stats);
- iop->ioc_count = sizeof(struct ppp_comp_stats);
- bzero((caddr_t)csp, sizeof(struct ppp_comp_stats));
- if (cp->xstate != 0)
- (*cp->xcomp->comp_stat)(cp->xstate, &csp->c);
- if (cp->rstate != 0)
- (*cp->rcomp->decomp_stat)(cp->rstate, &csp->d);
- error = 0;
- break;
-
- case PPPIO_LASTMOD:
- cp->flags |= LAST_MOD;
- error = 0;
- break;
-
- default:
- error = -1;
- break;
- }
-
- if (error < 0)
- putnext(q, mp);
- else if (error == 0) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- } else {
- mp->b_datap->db_type = M_IOCNAK;
- iop->ioc_error = error;
- iop->ioc_count = 0;
- qreply(q, mp);
- }
- break;
-
- case M_CTL:
- switch (*mp->b_rptr) {
- case PPPCTL_MTU:
- cp->mtu = ((unsigned short *)mp->b_rptr)[1];
- break;
- case PPPCTL_MRU:
- cp->mru = ((unsigned short *)mp->b_rptr)[1];
- break;
- case PPPCTL_UNIT:
- cp->unit = mp->b_rptr[1];
- break;
- }
- putnext(q, mp);
- break;
-
- default:
- putnext(q, mp);
- }
-}
-
-static int
-ppp_comp_wsrv(q)
- queue_t *q;
-{
- mblk_t *mp, *cmp = NULL, *np;
- comp_state_t *cp;
- int len, proto, type;
- struct ip *ip;
- unsigned char *vjhdr, *dp;
-
- cp = (comp_state_t *) q->q_ptr;
- while ((mp = getq(q)) != 0) {
- /* assert(mp->b_datap->db_type == M_DATA) */
- if (!canputnext(q)) {
- putbq(q, mp);
- return;
- }
-
- /*
- * Make sure we've got a reasonable amount in the first
- * mblk and that we are its only user.
- * Then find out what the protocol is.
- */
- len = msgdsize(mp);
- if (len > PPP_HDRLEN + MAX_IPHDR)
- len = PPP_HDRLEN + MAX_IPHDR;
- if (mp->b_wptr < mp->b_rptr + len || mp->b_datap->db_ref > 1) {
- PULLUP(mp, len);
- if (mp == 0) {
-#if DEBUG
- cmn_err(CE_CONT, "ppp_comp_wsrv: pullup failed\n");
-#endif
- cp->stats.ppp_oerrors++;
- putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
- continue;
- }
- }
- proto = PPP_PROTOCOL(mp->b_rptr);
-
- /*
- * Do VJ compression if requested.
- */
- if (proto == PPP_IP && (cp->flags & COMP_VJC)) {
- ip = (struct ip *) (mp->b_rptr + PPP_HDRLEN);
- if (ip->ip_p == IPPROTO_TCP) {
- type = vj_compress_tcp(ip, len - PPP_HDRLEN, &cp->vj_comp,
- (cp->flags & COMP_VJCCID), &vjhdr);
- switch (type) {
- case TYPE_UNCOMPRESSED_TCP:
- mp->b_rptr[3] = proto = PPP_VJC_UNCOMP;
- break;
- case TYPE_COMPRESSED_TCP:
- dp = vjhdr - PPP_HDRLEN;
- dp[1] = mp->b_rptr[1]; /* copy control field */
- dp[0] = mp->b_rptr[0]; /* copy address field */
- dp[2] = 0; /* set protocol field */
- dp[3] = proto = PPP_VJC_COMP;
- mp->b_rptr = dp;
- break;
- }
- }
- }
-
- /*
- * Do packet compression if enabled.
- */
- if (proto == PPP_CCP)
- ppp_comp_ccp(q, mp, 0);
- else if (proto != PPP_LCP && (cp->flags & CCP_COMP_RUN)
- && cp->xstate != NULL) {
- len = msgdsize(mp);
- (*cp->xcomp->compress)(cp->xstate, &cmp, mp, len,
- (cp->flags & CCP_ISUP? cp->mtu: 0));
- if (cmp != NULL) {
- freemsg(mp);
- mp = cmp;
- }
- }
-
- /*
- * Do address/control and protocol compression if enabled.
- */
- if (proto != PPP_LCP && (cp->flags & COMP_AC)) {
- mp->b_rptr += 2; /* drop the address & ctrl fields */
- if (proto < 0x100 && (cp->flags & COMP_PROT))
- ++mp->b_rptr; /* drop the high protocol byte */
- } else if (proto < 0x100 && (cp->flags & COMP_PROT)) {
- /* shuffle up the address & ctrl fields */
- mp->b_rptr[2] = mp->b_rptr[1];
- mp->b_rptr[1] = mp->b_rptr[0];
- ++mp->b_rptr;
- }
-
- cp->stats.ppp_opackets++;
- cp->stats.ppp_obytes += msgdsize(mp);
- putnext(q, mp);
- }
-}
-
-static int
-ppp_comp_rput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- comp_state_t *cp;
- struct iocblk *iop;
- struct ppp_stats *psp;
-
- cp = (comp_state_t *) q->q_ptr;
- switch (mp->b_datap->db_type) {
-
- case M_DATA:
- putq(q, mp);
- break;
-
- case M_IOCACK:
- iop = (struct iocblk *) mp->b_rptr;
- switch (iop->ioc_cmd) {
- case PPPIO_GETSTAT:
- /*
- * Catch this on the way back from the ppp_ahdl module
- * so we can fill in the VJ stats.
- */
- if (mp->b_cont == 0 || iop->ioc_count != sizeof(struct ppp_stats))
- break;
- psp = (struct ppp_stats *) mp->b_cont->b_rptr;
- psp->vj = cp->vj_comp.stats;
- break;
- }
- putnext(q, mp);
- break;
-
- case M_CTL:
- switch (mp->b_rptr[0]) {
- case PPPCTL_IERROR:
- ++cp->stats.ppp_ierrors;
- break;
- case PPPCTL_OERROR:
- ++cp->stats.ppp_oerrors;
- break;
- }
- putnext(q, mp);
- break;
-
- default:
- putnext(q, mp);
- }
-}
-
-static int
-ppp_comp_rsrv(q)
- queue_t *q;
-{
- int proto, rv, i;
- mblk_t *mp, *dmp = NULL, *np;
- uchar_t *dp, *iphdr;
- comp_state_t *cp;
- int len, hlen, vjlen, iphlen;
-
- cp = (comp_state_t *) q->q_ptr;
- while ((mp = getq(q)) != 0) {
- /* assert(mp->b_datap->db_type == M_DATA) */
- if (!canputnext(q)) {
- putbq(q, mp);
- return;
- }
-
- len = msgdsize(mp);
- cp->stats.ppp_ibytes += len;
- cp->stats.ppp_ipackets++;
-
- /*
- * First do address/control and protocol "decompression".
- */
- hlen = MIN(len, PPP_HDRLEN);
- if (mp->b_wptr < mp->b_rptr + hlen) {
- PULLUP(mp, hlen);
- if (mp == 0)
- goto bad;
- }
- dp = mp->b_rptr;
- if (PPP_ADDRESS(dp) == PPP_ALLSTATIONS
- && PPP_CONTROL(dp) == PPP_UI)
- dp += 2; /* skip address/control */
- else if ((cp->flags & DECOMP_AC) == 0) {
- /* count these? */
- goto bad;
- }
- proto = 0;
- if ((*dp & 1) == 0)
- proto = *dp++ << 8; /* grab high byte of protocol */
- else if ((cp->flags & DECOMP_PROT) == 0) {
- /* count these? */
- goto bad;
- }
- proto += *dp++; /* grab low byte of protocol */
- if (dp > mp->b_wptr)
- goto bad; /* short/bogus packet */
- dp -= PPP_HDRLEN;
- if (dp != mp->b_rptr) {
- /*
- * We need to put some bytes on the front of the packet
- * to make a full-length PPP header.
- * If we can put them in *mp, we do, otherwise we
- * tack another mblk on the front.
- * XXX we really shouldn't need to carry around
- * the address and control at this stage.
- */
- if (dp < mp->b_datap->db_base || mp->b_datap->db_ref > 1) {
- np = allocb(PPP_HDRLEN, BPRI_MED);
- if (np == 0)
- goto bad;
- np->b_cont = mp;
- mp->b_rptr = dp + PPP_HDRLEN;
- mp = np;
- dp = mp->b_wptr;
- mp->b_wptr += PPP_HDRLEN;
- } else
- mp->b_rptr = dp;
-
- dp[0] = PPP_ALLSTATIONS;
- dp[1] = PPP_UI;
- dp[2] = proto >> 8;
- dp[3] = proto;
- }
-
- /*
- * Now see if we have a compressed packet to decompress,
- * or a CCP packet to take notice of.
- */
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (proto == PPP_CCP)
- ppp_comp_ccp(q, mp, 1);
- else if (proto == PPP_COMP) {
- if ((cp->flags & CCP_ISUP)
- && (cp->flags & CCP_DECOMP_RUN) && cp->rstate
- && (cp->flags & CCP_ERR) == 0) {
- rv = (*cp->rcomp->decompress)(cp->rstate, mp, &dmp);
- switch (rv) {
- case DECOMP_OK:
- freemsg(mp);
- mp = dmp;
- if (mp == NULL) {
- /* no error, but no packet returned either. */
- continue;
- }
- break;
- case DECOMP_ERROR:
- cp->flags |= CCP_ERROR;
- ++cp->stats.ppp_ierrors;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- break;
- case DECOMP_FATALERROR:
- cp->flags |= CCP_FATALERROR;
- ++cp->stats.ppp_ierrors;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- break;
- }
- }
- } else if (cp->rstate && (cp->flags & CCP_DECOMP_RUN)) {
- (*cp->rcomp->incomp)(cp->rstate, mp);
- }
-
- /*
- * Now do VJ decompression.
- */
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) {
- len = msgdsize(mp) - PPP_HDRLEN;
- if ((cp->flags & DECOMP_VJC) == 0 || len <= 0)
- goto bad;
-
- /*
- * Advance past the ppp header.
- * Here we assume that the whole PPP header is in the first mblk.
- */
- np = mp;
- dp = np->b_rptr + PPP_HDRLEN;
- if (dp >= mp->b_wptr) {
- np = np->b_cont;
- dp = np->b_rptr;
- }
-
- if (proto == PPP_VJC_COMP) {
- hlen = MIN(len, MAX_VJHDR);
- if (np->b_wptr < dp + hlen) {
- PULLUP(mp, hlen + PPP_HDRLEN);
- if (mp == 0)
- goto bad;
- np = mp;
- dp = np->b_rptr + PPP_HDRLEN;
- }
-
- if (cp->stats.ppp_ierrors != cp->vj_last_ierrors) {
- vj_uncompress_err(&cp->vj_comp);
- cp->vj_last_ierrors = cp->stats.ppp_ierrors;
- }
-
- vjlen = vj_uncompress_tcp(dp, np->b_wptr - dp, len,
- &cp->vj_comp, &iphdr, &iphlen);
- if (vjlen < 0)
- goto bad;
-
- /* drop ppp and vj headers off */
- if (mp != np) {
- freeb(mp);
- mp = np;
- }
- mp->b_rptr = dp + vjlen;
-
- /* allocate a new mblk for the ppp and ip headers */
- if ((np = allocb(iphlen + PPP_HDRLEN + 4, BPRI_MED)) == 0)
- goto bad;
- dp = np->b_rptr; /* prepend mblk with TCP/IP hdr */
- dp[0] = PPP_ALLSTATIONS; /* reconstruct PPP header */
- dp[1] = PPP_UI;
- dp[2] = PPP_IP >> 8;
- dp[3] = PPP_IP;
- bcopy(iphdr, dp + PPP_HDRLEN, iphlen);
- np->b_wptr = dp + iphlen + PPP_HDRLEN;
- np->b_cont = mp;
-
- /* XXX there seems to be a bug which causes panics in strread
- if we make an mbuf with only the IP header in it :-( */
- if (mp->b_wptr - mp->b_rptr > 4) {
- bcopy(mp->b_rptr, np->b_wptr, 4);
- mp->b_rptr += 4;
- np->b_wptr += 4;
- } else {
- bcopy(mp->b_rptr, np->b_wptr, mp->b_wptr - mp->b_rptr);
- np->b_wptr += mp->b_wptr - mp->b_rptr;
- np->b_cont = mp->b_cont;
- freeb(mp);
- }
-
- mp = np;
-
- } else {
- hlen = MIN(len, MAX_IPHDR);
- if (np->b_wptr < dp + hlen || np->b_datap->db_ref > 1
- || mp->b_datap->db_ref > 1) {
- PULLUP(mp, hlen + PPP_HDRLEN);
- if (mp == 0)
- goto bad;
- np = mp;
- dp = np->b_rptr + PPP_HDRLEN;
- }
-
- if (!vj_uncompress_uncomp(dp, &cp->vj_comp))
- goto bad;
- mp->b_rptr[3] = PPP_IP; /* fix up the PPP protocol field */
- }
- }
-
- putnext(q, mp);
- continue;
-
- bad:
- if (mp != 0)
- freemsg(mp);
- cp->stats.ppp_ierrors++;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- }
-}
-
-/*
- * Handle a CCP packet being sent or received.
- */
-static void
-ppp_comp_ccp(q, mp, rcvd)
- queue_t *q;
- mblk_t *mp;
- int rcvd;
-{
- int len, clen;
- comp_state_t *cp;
- unsigned char *dp;
- mblk_t *np;
-
- len = msgdsize(mp);
- if (len < PPP_HDRLEN + CCP_HDRLEN)
- return;
- if (mp->b_wptr < mp->b_rptr + len) {
- /* XXX this isn't right, because it may free mp */
- PULLUP(mp, len);
- if (mp == 0) {
- cmn_err(CE_CONT, "ppp_comp_ccp: pullup failed\n");
- return;
- }
- }
- np = mp;
-
- cp = (comp_state_t *) q->q_ptr;
- dp = mp->b_rptr + PPP_HDRLEN;
- len -= PPP_HDRLEN;
- clen = CCP_LENGTH(dp);
- if (clen > len)
- goto bad;
-
- switch (CCP_CODE(dp)) {
- case CCP_CONFREQ:
- case CCP_TERMREQ:
- case CCP_TERMACK:
- cp->flags &= ~CCP_ISUP;
- break;
-
- case CCP_CONFACK:
- if ((cp->flags & (CCP_ISOPEN | CCP_ISUP)) == CCP_ISOPEN
- && clen >= CCP_HDRLEN + CCP_OPT_MINLEN
- && clen >= CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN)) {
- if (!rcvd) {
- if (cp->xstate != NULL
- && (*cp->xcomp->comp_init)
- (cp->xstate, dp + CCP_HDRLEN, clen - CCP_HDRLEN,
- cp->unit, 0, 0))
- cp->flags |= CCP_COMP_RUN;
- } else {
- if (cp->rstate != NULL
- && (*cp->rcomp->decomp_init)
- (cp->rstate, dp + CCP_HDRLEN, clen - CCP_HDRLEN,
- cp->unit, 0, cp->mru, 0))
- cp->flags = (cp->flags & ~CCP_ERR)
- | CCP_DECOMP_RUN;
- }
- }
- break;
-
- case CCP_RESETACK:
- if (cp->flags & CCP_ISUP) {
- if (!rcvd) {
- if (cp->xstate && (cp->flags & CCP_COMP_RUN))
- (*cp->xcomp->comp_reset)(cp->xstate);
- } else {
- if (cp->rstate && (cp->flags & CCP_DECOMP_RUN)) {
- (*cp->rcomp->decomp_reset)(cp->rstate);
- cp->flags &= ~CCP_ERROR;
- }
- }
- }
- break;
- }
-
- bad:
- if (np != mp)
- freemsg(np);
-}
-
-#if DEBUG
-dump_msg(mp)
- mblk_t *mp;
-{
- dblk_t *db;
-
- while (mp != 0) {
- db = mp->b_datap;
- cmn_err(CE_CONT, "mp=%x cont=%x rptr=%x wptr=%x datap=%x\n",
- mp, mp->b_cont, mp->b_rptr, mp->b_wptr, db);
- cmn_err(CE_CONT, " base=%x lim=%x ref=%d type=%d struioflag=%d\n",
- db->db_base, db->db_lim, db->db_ref, db->db_type,
- db->db_struioflag);
- mp = mp->b_cont;
- }
-}
-#endif