mirror of
https://github.com/paulusmack/ppp.git
synced 2024-12-04 08:53:43 +08:00
copies from sunos for osf1
This commit is contained in:
parent
cf60450944
commit
252d98000b
896
osf1/ppp_async.c
Normal file
896
osf1/ppp_async.c
Normal file
@ -0,0 +1,896 @@
|
||||
/*
|
||||
ppp_async.c - Streams async functions Also does FCS
|
||||
|
||||
Copyright (C) 1990 Brad K. Clements, All Rights Reserved
|
||||
fcstab and some ideas nicked from if_ppp.c from cmu.
|
||||
See copyright notice in if_ppp.h and NOTES
|
||||
|
||||
$Id: ppp_async.c,v 1.1 1995/12/18 23:45:07 paulus Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is used under SunOS 4.x, and OSF/1 on DEC Alpha.
|
||||
*
|
||||
* Beware that under OSF/1, the ioctl constants (SIOC*) end up
|
||||
* as 64-bit (long) values, so an ioctl constant should be cast to
|
||||
* int (32 bits) before being compared with the ioc_cmd field of
|
||||
* an iocblk structure.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef PPP_VD
|
||||
#include "ppp.h"
|
||||
#endif
|
||||
|
||||
#if NPPP > 0
|
||||
|
||||
#define STREAMS 1
|
||||
#define DEBUGS 1
|
||||
#include <sys/param.h>
|
||||
#include <sys/stream.h>
|
||||
#include <sys/stropts.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifdef __osf__
|
||||
#include <sys/proc.h>
|
||||
#define NOTSUSER (suser(u.u_procp->p_rcred, &u.u_acflag))
|
||||
#else
|
||||
#define NOTSUSER (!suser())
|
||||
#endif
|
||||
|
||||
#include <net/ppp_defs.h>
|
||||
#include <net/ppp_str.h>
|
||||
|
||||
/* how big of a buffer block to allocate for each chunk of the input chain */
|
||||
#define ALLOCBSIZE 64
|
||||
|
||||
#ifdef DEBUGS
|
||||
#include <sys/syslog.h>
|
||||
#define DLOG(s,a) if (p->pai_flags&PAI_FLAGS_DEBUG) log(LOG_DEBUG, s, a)
|
||||
|
||||
int ppp_async_max_dump_bytes = 28;
|
||||
#define MAX_DUMP_BYTES 1504
|
||||
|
||||
static void ppp_dump_frame();
|
||||
|
||||
#else
|
||||
#define DLOG(s) {}
|
||||
#endif
|
||||
|
||||
static int ppp_async_open(), ppp_async_close(), ppp_async_rput(),
|
||||
ppp_async_wput(), ppp_async_wsrv(), ppp_async_rsrv();
|
||||
|
||||
static struct module_info minfo ={
|
||||
0xabcd,"ppp_async",0, INFPSZ, 16384, 4096
|
||||
};
|
||||
|
||||
static struct qinit r_init = {
|
||||
ppp_async_rput, ppp_async_rsrv, ppp_async_open, ppp_async_close,
|
||||
NULL, &minfo, NULL
|
||||
};
|
||||
static struct qinit w_init = {
|
||||
ppp_async_wput, ppp_async_wsrv, ppp_async_open, ppp_async_close,
|
||||
NULL, &minfo, NULL
|
||||
};
|
||||
struct streamtab ppp_asyncinfo = {
|
||||
&r_init, &w_init, NULL, NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* 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
|
||||
};
|
||||
|
||||
|
||||
struct ppp_async_info {
|
||||
u_int pai_flags;
|
||||
int pai_buffsize; /* how big of an input buffer to alloc */
|
||||
int pai_buffcount; /* how many chars currently in input buffer */
|
||||
u_short pai_fcs; /* the current fcs */
|
||||
mblk_t *pai_buffer; /* pointer to the current buffer list */
|
||||
mblk_t *pai_bufftail; /* pointer to the current input block */
|
||||
ext_accm pai_asyncmap; /* current outgoing asyncmap */
|
||||
u_int32_t pai_rasyncmap; /* current receive asyncmap */
|
||||
};
|
||||
|
||||
/* Values for pai_flags */
|
||||
#define PAI_FLAGS_INUSE 0x1
|
||||
#define PAI_FLAGS_FLUSH 0x2
|
||||
#define PAI_FLAGS_ESCAPED 0x4
|
||||
#define PAI_FLAGS_COMPPROT 0x8
|
||||
#define PAI_FLAGS_COMPAC 0x10
|
||||
#define PAI_FLAGS_RCV_COMPPROT 0x20
|
||||
#define PAI_FLAGS_RCV_COMPAC 0x40
|
||||
|
||||
#define PAI_FLAGS_DEBUG 0x1000
|
||||
#define PAI_FLAGS_LOG_INPKT 0x2000
|
||||
#define PAI_FLAGS_LOG_OUTPKT 0x4000
|
||||
#define PAI_FLAGS_ALL_DEBUG 0x7000
|
||||
|
||||
typedef struct ppp_async_info PAI;
|
||||
|
||||
static PAI pai[NPPP*2]; /* our private cache of async ctrl structs */
|
||||
|
||||
/* open might fail if we don't have any more pai elements left free */
|
||||
static int
|
||||
ppp_async_open(q, dev, flag, sflag)
|
||||
queue_t *q;
|
||||
dev_t dev;
|
||||
int flag;
|
||||
int sflag;
|
||||
{
|
||||
register PAI *p;
|
||||
register int x;
|
||||
int s;
|
||||
|
||||
/* only let the superuser or setuid root ppl open this module */
|
||||
if (NOTSUSER) {
|
||||
u.u_error = EPERM;
|
||||
return (OPENFAIL);
|
||||
}
|
||||
|
||||
s = splstr();
|
||||
if (!q->q_ptr) {
|
||||
for (x=0; x < NPPP; x++) /* search for an empty PAI */
|
||||
if (!(pai[x].pai_flags & PAI_FLAGS_INUSE))
|
||||
break;
|
||||
if (x == NPPP) { /* all buffers in use */
|
||||
splx(s); /* restore processor state */
|
||||
u.u_error = ENOBUFS;
|
||||
return (OPENFAIL);
|
||||
}
|
||||
p = &pai[x];
|
||||
DLOG("ppp_async%d: opening\n",x);
|
||||
|
||||
/* initialize the unit to default values */
|
||||
WR(q)->q_ptr = q->q_ptr = (caddr_t) p;
|
||||
bzero(p, sizeof(*p));
|
||||
p->pai_flags = PAI_FLAGS_INUSE | PAI_FLAGS_RCV_COMPAC
|
||||
| PAI_FLAGS_RCV_COMPPROT;
|
||||
p->pai_asyncmap[0] = 0xffffffff; /* default async map */
|
||||
p->pai_asyncmap[3] = 0x60000000; /* escape 7d, 7e */
|
||||
p->pai_buffsize = PPP_MTU + PPP_HDRLEN + PPP_FCSLEN;
|
||||
}
|
||||
else {
|
||||
p = (PAI *) q->q_ptr;
|
||||
DLOG("ppp_async%d: reopen\n", p - pai);
|
||||
}
|
||||
|
||||
splx(s);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
ppp_async_close(q)
|
||||
queue_t *q; /* queue info */
|
||||
{
|
||||
int s;
|
||||
register PAI *p;
|
||||
|
||||
s = splstr();
|
||||
if ((p = (PAI *) q->q_ptr) != NULL) {
|
||||
p->pai_flags = 0; /* clear all flags */
|
||||
if (p->pai_buffer) {
|
||||
/* currently receiving some chars, discard the buffer */
|
||||
freemsg(p->pai_buffer);
|
||||
p->pai_buffer = NULL;
|
||||
}
|
||||
DLOG("ppp_async%d: closing\n", p - pai);
|
||||
}
|
||||
splx(s);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* M_IOCTL processing is performed at this level. There is some
|
||||
weirdness here, but I couldn't think of an easier way to handle it.
|
||||
|
||||
SIOC{G,S}IF{,R,X}ASYNCMAP are handled here.
|
||||
|
||||
SIOCSIFCOMPAC and SIOCSIFCOMPPROT are both handled here.
|
||||
|
||||
SIOCSIFMRU and SIOCGIFMRU (Max Receive Unit) are both handled here.
|
||||
Rather than using the MTU to set the MRU, we have a seperate IOCTL for it.
|
||||
*/
|
||||
|
||||
static int
|
||||
ppp_async_wput(q, mp)
|
||||
queue_t *q;
|
||||
register mblk_t *mp;
|
||||
{
|
||||
register struct iocblk *i;
|
||||
register PAI *p;
|
||||
int x, flags;
|
||||
|
||||
switch (mp->b_datap->db_type) {
|
||||
|
||||
case M_CTL:
|
||||
switch (*(u_char *)mp->b_rptr) {
|
||||
case IF_GET_CSTATS:
|
||||
/* trap this and remove it */
|
||||
freemsg(mp);
|
||||
break;
|
||||
default:
|
||||
putnext(q, mp);
|
||||
}
|
||||
break;
|
||||
|
||||
case M_FLUSH :
|
||||
if (*mp->b_rptr & FLUSHW)
|
||||
flushq(q, FLUSHDATA);
|
||||
putnext(q, mp); /* send it along too */
|
||||
break;
|
||||
|
||||
case M_DATA :
|
||||
putq(q, mp); /* queue it for my service routine */
|
||||
break;
|
||||
|
||||
case M_IOCTL :
|
||||
i = (struct iocblk *) mp->b_rptr;
|
||||
p = (PAI *) q->q_ptr;
|
||||
switch (i->ioc_cmd) {
|
||||
|
||||
case SIOCSIFCOMPAC : /* enable or disable AC compression */
|
||||
if (i->ioc_count != sizeof(u_char)) {
|
||||
i->ioc_error = EINVAL;
|
||||
goto iocnak;
|
||||
}
|
||||
x = *(u_char *) mp->b_cont->b_rptr;
|
||||
DLOG("ppp_async: SIFCOMPAC %d\n", x);
|
||||
flags = (x & 2)? PAI_FLAGS_RCV_COMPAC: PAI_FLAGS_COMPAC;
|
||||
if (x & 1)
|
||||
p->pai_flags |= flags;
|
||||
else
|
||||
p->pai_flags &= ~flags;
|
||||
i->ioc_count = 0;
|
||||
goto iocack;
|
||||
|
||||
case SIOCSIFCOMPPROT: /* enable or disable PROT compression */
|
||||
if (i->ioc_count != sizeof(u_char)) {
|
||||
i->ioc_error = EINVAL;
|
||||
goto iocnak;
|
||||
}
|
||||
x = *(u_char *) mp->b_cont->b_rptr;
|
||||
DLOG("ppp_async: SIFCOMPPROT %d\n", x);
|
||||
flags = (x & 2)? PAI_FLAGS_RCV_COMPPROT: PAI_FLAGS_COMPPROT;
|
||||
if (x & 1)
|
||||
p->pai_flags |= flags;
|
||||
else
|
||||
p->pai_flags &= ~flags;
|
||||
i->ioc_count = 0;
|
||||
goto iocack;
|
||||
|
||||
|
||||
case SIOCSIFMRU :
|
||||
if (i->ioc_count != sizeof(int)) {
|
||||
i->ioc_error = EINVAL;
|
||||
goto iocnak;
|
||||
}
|
||||
x = *(int *) mp->b_cont->b_rptr;
|
||||
if (x < PPP_MTU)
|
||||
x = PPP_MTU;
|
||||
x += PPP_HDRLEN + PPP_FCSLEN;
|
||||
if (x > 4096) { /* couldn't allocb something this big */
|
||||
i->ioc_error = EINVAL;
|
||||
goto iocnak;
|
||||
}
|
||||
p->pai_buffsize = x;
|
||||
i->ioc_count = 0;
|
||||
goto iocack;
|
||||
|
||||
case SIOCGIFMRU :
|
||||
if ((mp->b_cont = allocb(sizeof(int), BPRI_MED)) != NULL) {
|
||||
*(int *) mp->b_cont->b_wptr =
|
||||
p->pai_buffsize - (PPP_HDRLEN + PPP_FCSLEN);
|
||||
mp->b_cont->b_wptr += i->ioc_count = sizeof(int);
|
||||
goto iocack;
|
||||
}
|
||||
i->ioc_error = ENOSR;
|
||||
goto iocnak;
|
||||
|
||||
case SIOCGIFASYNCMAP :
|
||||
if ((mp->b_cont = allocb(sizeof(u_int32_t), BPRI_MED)) != NULL) {
|
||||
*(u_int32_t *) mp->b_cont->b_wptr = p->pai_asyncmap[0];
|
||||
mp->b_cont->b_wptr += i->ioc_count = sizeof(u_int32_t);
|
||||
goto iocack;
|
||||
}
|
||||
i->ioc_error = ENOSR;
|
||||
goto iocnak;
|
||||
|
||||
case SIOCSIFASYNCMAP :
|
||||
if (i->ioc_count != sizeof(u_int32_t)) {
|
||||
i->ioc_error = EINVAL;
|
||||
goto iocnak; /* ugh, goto */
|
||||
}
|
||||
p->pai_asyncmap[0] = *(u_int32_t *) mp->b_cont->b_rptr;
|
||||
DLOG("ppp_async: SIFASYNCMAP %lx\n", p->pai_asyncmap[0]);
|
||||
i->ioc_count = 0;
|
||||
goto iocack;
|
||||
|
||||
case SIOCGIFRASYNCMAP :
|
||||
if ((mp->b_cont = allocb(sizeof(u_int32_t), BPRI_MED)) != NULL) {
|
||||
*(u_int32_t *) mp->b_cont->b_wptr = p->pai_rasyncmap;
|
||||
mp->b_cont->b_wptr += i->ioc_count = sizeof(u_int32_t);
|
||||
goto iocack;
|
||||
}
|
||||
i->ioc_error = ENOSR;
|
||||
goto iocnak;
|
||||
|
||||
case SIOCSIFRASYNCMAP :
|
||||
if (i->ioc_count != sizeof(u_int32_t)) {
|
||||
i->ioc_error = EINVAL;
|
||||
goto iocnak; /* ugh, goto */
|
||||
}
|
||||
p->pai_rasyncmap = *(u_int32_t *) mp->b_cont->b_rptr;
|
||||
DLOG("ppp_async: SIFRASYNCMAP %lx\n", p->pai_rasyncmap);
|
||||
i->ioc_count = 0;
|
||||
goto iocack;
|
||||
|
||||
case SIOCGIFXASYNCMAP :
|
||||
if ((mp->b_cont = allocb(sizeof(ext_accm), BPRI_MED)) != NULL) {
|
||||
bcopy(p->pai_asyncmap, mp->b_cont->b_wptr, sizeof(ext_accm));
|
||||
mp->b_cont->b_wptr += i->ioc_count = sizeof(ext_accm);
|
||||
goto iocack;
|
||||
}
|
||||
i->ioc_error = ENOSR;
|
||||
goto iocnak;
|
||||
|
||||
case SIOCSIFXASYNCMAP :
|
||||
if (i->ioc_count != sizeof(ext_accm)) {
|
||||
i->ioc_error = EINVAL;
|
||||
goto iocnak; /* ugh, goto */
|
||||
}
|
||||
bcopy(mp->b_cont->b_rptr, p->pai_asyncmap, sizeof(ext_accm));
|
||||
p->pai_asyncmap[1] = 0; /* can't escape 20-3f */
|
||||
p->pai_asyncmap[2] &= ~0x40000000; /* can't escape 5e */
|
||||
p->pai_asyncmap[3] |= 0x60000000; /* must escape 7d, 7e */
|
||||
i->ioc_count = 0;
|
||||
goto iocack;
|
||||
|
||||
case SIOCGIFDEBUG :
|
||||
if ((mp->b_cont = allocb(sizeof(int), BPRI_MED)) != NULL) {
|
||||
*(int *)mp->b_cont->b_wptr =
|
||||
(unsigned)(p->pai_flags & PAI_FLAGS_ALL_DEBUG)
|
||||
/ PAI_FLAGS_DEBUG |
|
||||
(p->pai_flags & PAI_FLAGS_HIBITS);
|
||||
mp->b_cont->b_wptr += i->ioc_count = sizeof(int);
|
||||
goto iocack;
|
||||
}
|
||||
i->ioc_error = ENOSR;
|
||||
goto iocnak;
|
||||
|
||||
case SIOCSIFDEBUG :
|
||||
if(i->ioc_count != sizeof(int)) {
|
||||
i->ioc_error = EINVAL;
|
||||
goto iocnak; /* ugh, goto */
|
||||
}
|
||||
flags = *(int *)mp->b_cont->b_rptr;
|
||||
DLOG("ppp_async: SIFIFDEBUG %x\n", flags);
|
||||
p->pai_flags &= ~PAI_FLAGS_ALL_DEBUG | PAI_FLAGS_HIBITS;
|
||||
p->pai_flags |= ((unsigned) flags * PAI_FLAGS_DEBUG)
|
||||
& PAI_FLAGS_ALL_DEBUG;
|
||||
i->ioc_count = 0;
|
||||
goto iocack;
|
||||
|
||||
iocack:;
|
||||
mp->b_datap->db_type = M_IOCACK;
|
||||
qreply(q,mp);
|
||||
break;
|
||||
iocnak:;
|
||||
i->ioc_count = 0;
|
||||
mp->b_datap->db_type = M_IOCNAK;
|
||||
qreply(q, mp);
|
||||
break;
|
||||
default: /* unknown IOCTL call */
|
||||
putnext(q,mp); /* pass it along */
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
putnext(q, mp); /* don't know what to do with this, so send it along*/
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ppp_async_wsrv(q)
|
||||
queue_t *q;
|
||||
{
|
||||
register u_char *cp, *wp;
|
||||
register PAI *p;
|
||||
register u_short fcs;
|
||||
register mblk_t *mp, *m0;
|
||||
mblk_t *cop, *outgoing;
|
||||
int proto, len, olen, c;
|
||||
|
||||
p = (PAI *) q->q_ptr;
|
||||
|
||||
while ((mp = getq(q)) != NULL) {
|
||||
/*
|
||||
* we can only get M_DATA types into our Queue,
|
||||
* due to our Put function
|
||||
*/
|
||||
if (!canput(q->q_next)) {
|
||||
putbq(q, mp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* at least a header required */
|
||||
len = msgdsize(mp);
|
||||
if (len < PPP_HDRLEN
|
||||
|| (mp->b_wptr - mp->b_rptr < PPP_HDRLEN
|
||||
&& !pullupmsg(mp, PPP_HDRLEN))) {
|
||||
freemsg(mp); /* discard the message */
|
||||
DLOG("ppp_async: short message (%d)\n", len);
|
||||
/* indicate output err */
|
||||
putctl1(OTHERQ(q), M_CTL, IF_OUTPUT_ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Do address/control and protocol compression */
|
||||
proto = (mp->b_rptr[2] << 8) + mp->b_rptr[3];
|
||||
if (p->pai_flags & PAI_FLAGS_COMPAC && proto != PPP_LCP
|
||||
&& mp->b_rptr[0] == PPP_ALLSTATIONS && mp->b_rptr[1] == PPP_UI) {
|
||||
mp->b_rptr += 2;
|
||||
if (p->pai_flags & PAI_FLAGS_COMPPROT && proto < 0xff)
|
||||
++mp->b_rptr;
|
||||
} else if (p->pai_flags & PAI_FLAGS_COMPPROT && proto < 0xff) {
|
||||
mp->b_rptr[2] = mp->b_rptr[1];
|
||||
mp->b_rptr[1] = mp->b_rptr[0];
|
||||
++mp->b_rptr;
|
||||
}
|
||||
|
||||
m0 = mp; /* remember first message block */
|
||||
fcs = PPP_INITFCS;
|
||||
|
||||
/*
|
||||
* Estimate the required buffer length as 1.25 * message length
|
||||
* to allow for escaped characters. If this isn't enough, we
|
||||
* allocate another buffer later.
|
||||
*/
|
||||
olen = len + (len >> 2) + 5;
|
||||
if (olen < 32)
|
||||
olen = 32;
|
||||
else if (olen > 2048)
|
||||
olen = 2048;
|
||||
outgoing = cop = allocb(olen, BPRI_MED);
|
||||
if (outgoing == NULL) {
|
||||
DLOG("allocb(%d) failed!\n", olen);
|
||||
/* should do something tricky here */
|
||||
goto nobuffs;
|
||||
}
|
||||
wp = cop->b_wptr;
|
||||
|
||||
/* Put the initial flag in (we'll take it out later if we don't
|
||||
need it). */
|
||||
*wp++ = PPP_FLAG;
|
||||
--olen;
|
||||
|
||||
#define SPECIAL(p, c) (p->pai_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
|
||||
|
||||
/*
|
||||
* Copy the message to the output block, escaping characters
|
||||
* as needed.
|
||||
*/
|
||||
while (mp) {
|
||||
for (cp = mp->b_rptr; cp < mp->b_wptr; ) {
|
||||
c = *cp++;
|
||||
if (olen < 2) {
|
||||
/* grab another message block and put it on the end */
|
||||
cop->b_wptr = wp;
|
||||
olen = 256;
|
||||
cop = allocb(olen, BPRI_MED);
|
||||
if (cop == NULL)
|
||||
goto nobuffs;
|
||||
linkb(outgoing, cop);
|
||||
wp = cop->b_wptr;
|
||||
}
|
||||
if (SPECIAL(p, c)) {
|
||||
*wp++ = PPP_ESCAPE;
|
||||
*wp++ = c ^ PPP_TRANS;
|
||||
olen -= 2;
|
||||
} else {
|
||||
*wp++ = c;
|
||||
--olen;
|
||||
}
|
||||
fcs = PPP_FCS(fcs, c);
|
||||
}
|
||||
mp = mp->b_cont; /* look at the next block */
|
||||
} /* end while(mp) */
|
||||
|
||||
/*
|
||||
* Add the FCS and the trailing flag.
|
||||
*/
|
||||
if (olen < 5) {
|
||||
/* grab another message block for FCS and trailing flag */
|
||||
cop->b_wptr = wp;
|
||||
cop = allocb(5, BPRI_MED);
|
||||
if (cop == NULL)
|
||||
goto nobuffs;
|
||||
linkb(outgoing, cop);
|
||||
wp = cop->b_wptr;
|
||||
}
|
||||
fcs ^= 0xffff; /* XOR the resulting FCS */
|
||||
c = fcs & 0xff;
|
||||
if (SPECIAL(p, c)) {
|
||||
*wp++ = PPP_ESCAPE;
|
||||
*wp++ = c ^ PPP_TRANS;
|
||||
} else
|
||||
*wp++ = c;
|
||||
c = fcs >> 8;
|
||||
if (SPECIAL(p, c)) {
|
||||
*wp++ = PPP_ESCAPE;
|
||||
*wp++ = c ^ PPP_TRANS;
|
||||
} else
|
||||
*wp++ = c;
|
||||
*wp++ = PPP_FLAG; /* add trailing PPP_FLAG */
|
||||
|
||||
cop->b_wptr = wp;
|
||||
freemsg(m0);
|
||||
|
||||
/*
|
||||
* now we check to see if the lower queue has entries, if so,
|
||||
* we assume that we don't need a leading PPP_FLAG because
|
||||
* these packets will be sent back to back.
|
||||
*/
|
||||
if (qsize(q->q_next) > 0) {
|
||||
/* entries in next queue, remove the leading PPP_FLAG */
|
||||
++outgoing->b_rptr;
|
||||
}
|
||||
|
||||
#if DEBUGS
|
||||
if (p->pai_flags & PAI_FLAGS_LOG_OUTPKT)
|
||||
ppp_dump_frame(p, outgoing, " sent output");
|
||||
#endif
|
||||
putnext(q, outgoing);
|
||||
continue;
|
||||
|
||||
nobuffs: /* well, we ran out of memory somewhere */
|
||||
if (outgoing)
|
||||
freemsg(outgoing); /* throw away what we have already */
|
||||
putbq(q, m0); /* put back the original message */
|
||||
putctl1(OTHERQ(q), M_CTL, IF_OUTPUT_ERROR);
|
||||
qenable(q); /* reschedule ourselves for later */
|
||||
return;
|
||||
} /* end while(getq()) */
|
||||
} /* end function */
|
||||
|
||||
static int
|
||||
ppp_async_rput(q, mp)
|
||||
queue_t *q;
|
||||
register mblk_t *mp;
|
||||
{
|
||||
switch (mp->b_datap->db_type) {
|
||||
|
||||
case M_FLUSH:
|
||||
if(*mp->b_rptr & FLUSHR)
|
||||
flushq(q, FLUSHDATA);
|
||||
putnext(q, mp); /* send it along too */
|
||||
break;
|
||||
|
||||
case M_DATA:
|
||||
putq(q, mp); /* queue it for my service routine */
|
||||
break;
|
||||
|
||||
default:
|
||||
putnext(q,mp); /* don't know what to do with this, so send it along */
|
||||
}
|
||||
}
|
||||
|
||||
static u_int32_t paritytab[8] = {
|
||||
0x96696996, 0x69969669, 0x69969669, 0x96696996,
|
||||
0x69969669, 0x96696996, 0x96696996, 0x69969669,
|
||||
};
|
||||
|
||||
static int
|
||||
ppp_async_rsrv(q)
|
||||
queue_t *q;
|
||||
{
|
||||
register mblk_t *mp, *bp;
|
||||
register PAI *p;
|
||||
register u_char *cp,c;
|
||||
mblk_t *m0;
|
||||
register u_char *wptr;
|
||||
int bcount;
|
||||
|
||||
p = (PAI *) q->q_ptr;
|
||||
|
||||
#define INPUT_ERROR(q) putctl1(q, M_CTL, IF_INPUT_ERROR)
|
||||
#define STUFF_CHAR(p,c) (*wptr++ = (c), (p)->pai_buffcount++)
|
||||
#define FLUSHEM(q, p) (INPUT_ERROR(q), (p)->pai_flags |= PAI_FLAGS_FLUSH)
|
||||
|
||||
while ((mp = getq(q)) != NULL) {
|
||||
/* we can only get M_DATA types into our Queue,
|
||||
due to our Put function */
|
||||
if (!canput(q->q_next)) {
|
||||
putbq(q, mp);
|
||||
return;
|
||||
}
|
||||
m0 = mp; /* remember first message block */
|
||||
for (; mp != NULL; mp = mp->b_cont) { /* for each message block */
|
||||
cp = mp->b_rptr;
|
||||
while (cp < mp->b_wptr) {
|
||||
c = *cp++;
|
||||
|
||||
/* Accumulate info to help with detecting
|
||||
non 8-bit clean links. */
|
||||
if (c & 0x80)
|
||||
p->pai_flags |= PAI_FLAGS_B7_1;
|
||||
else
|
||||
p->pai_flags |= PAI_FLAGS_B7_0;
|
||||
if (paritytab[c >> 5] & (1 << (c & 0x1F)))
|
||||
p->pai_flags |= PAI_FLAGS_PAR_ODD;
|
||||
else
|
||||
p->pai_flags |= PAI_FLAGS_PAR_EVEN;
|
||||
|
||||
/* Throw out chars in the receive asyncmap. */
|
||||
if (c < 0x20 && (p->pai_rasyncmap & (1 << c)))
|
||||
continue;
|
||||
|
||||
/* A flag marks the end of a frame. */
|
||||
if (c == PPP_FLAG) {
|
||||
bp = p->pai_buffer;
|
||||
bcount = p->pai_buffcount;
|
||||
p->pai_buffer = NULL;
|
||||
p->pai_buffcount = 0;
|
||||
|
||||
/* if the escape indicator is set, then we have
|
||||
seen the packet abort sequence "}~". */
|
||||
if (p->pai_flags & (PAI_FLAGS_ESCAPED | PAI_FLAGS_FLUSH)) {
|
||||
if ((p->pai_flags & PAI_FLAGS_FLUSH) == 0)
|
||||
DLOG("ppp_async: packet abort\n", 0);
|
||||
p->pai_flags &= ~(PAI_FLAGS_ESCAPED | PAI_FLAGS_FLUSH);
|
||||
if (bp)
|
||||
freemsg(bp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bcount > PPP_FCSLEN) { /* discard FCS */
|
||||
adjmsg(bp, -PPP_FCSLEN);
|
||||
bcount -= PPP_FCSLEN;
|
||||
}
|
||||
|
||||
if (bcount < PPP_HDRLEN) {
|
||||
if (bcount) {
|
||||
INPUT_ERROR(q);
|
||||
DLOG("ppp_async: short input packet (%d)\n",
|
||||
bcount);
|
||||
}
|
||||
if (bp)
|
||||
freemsg(bp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bp) {
|
||||
if (p->pai_fcs == PPP_GOODFCS) {
|
||||
#if DEBUGS
|
||||
if (p->pai_flags & PAI_FLAGS_LOG_INPKT)
|
||||
ppp_dump_frame(p, bp, " got input");
|
||||
#endif /*DEBUGS*/
|
||||
putnext(q, bp);
|
||||
}
|
||||
else {
|
||||
INPUT_ERROR(q);
|
||||
freemsg(bp);
|
||||
DLOG("ppp_async: FCS Error\n", 0);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* here c != PPP_FLAG */
|
||||
if (p->pai_flags & PAI_FLAGS_FLUSH) {
|
||||
while (cp < mp->b_wptr && *cp != PPP_FLAG)
|
||||
++cp;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p->pai_flags & PAI_FLAGS_ESCAPED) {
|
||||
p->pai_flags &= ~PAI_FLAGS_ESCAPED; /* clear esc flag */
|
||||
c ^= PPP_TRANS;
|
||||
} else if (c == PPP_ESCAPE) {
|
||||
if (cp >= mp->b_wptr || (c = *cp) == PPP_FLAG
|
||||
|| c < 0x20 && (p->pai_rasyncmap & (1 << c))) {
|
||||
p->pai_flags |= PAI_FLAGS_ESCAPED;
|
||||
continue;
|
||||
}
|
||||
c ^= PPP_TRANS;
|
||||
++cp;
|
||||
}
|
||||
|
||||
/* here we check to see if we have a buffer.
|
||||
If we don't, we assume that this is the first char
|
||||
for the buffer, and we allocb one */
|
||||
|
||||
if (!p->pai_buffer) {
|
||||
/* we allocate buffer chains in blocks of ALLOCBSIZE */
|
||||
|
||||
if (!(p->pai_buffer = allocb(ALLOCBSIZE, BPRI_MED))) {
|
||||
FLUSHEM(q, p);
|
||||
continue;
|
||||
/* if we don't get a buffer, is there some way
|
||||
to recover and requeue later? rather than flushing
|
||||
the current packet... ? */
|
||||
}
|
||||
p->pai_bufftail = p->pai_buffer;
|
||||
}
|
||||
wptr = p->pai_bufftail->b_wptr;
|
||||
|
||||
if (!p->pai_buffcount) {
|
||||
p->pai_fcs = PPP_INITFCS;
|
||||
if (c != PPP_ALLSTATIONS) {
|
||||
if (p->pai_flags & PAI_FLAGS_RCV_COMPAC) {
|
||||
STUFF_CHAR(p, PPP_ALLSTATIONS);
|
||||
STUFF_CHAR(p, PPP_UI);
|
||||
}
|
||||
else {
|
||||
DLOG("ppp_async: missed ALLSTATIONS (0xff), got 0x%x\n", c);
|
||||
FLUSHEM(q, p);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} /* end if !p->pai_buffcount */
|
||||
|
||||
if (p->pai_buffcount == 1 && c != PPP_UI) {
|
||||
DLOG("ppp_async: missed UI (0x3), got 0x%x\n", c);
|
||||
FLUSHEM(q,p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p->pai_buffcount == 2 && (c & 1) == 1) {
|
||||
if (p->pai_flags & PAI_FLAGS_RCV_COMPPROT)
|
||||
STUFF_CHAR(p, 0);
|
||||
else {
|
||||
DLOG("ppp_async: bad protocol high byte %x\n", c);
|
||||
FLUSHEM(q, p);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (p->pai_buffcount == 3 && (c & 1) == 0) {
|
||||
DLOG("ppp_async: bad protocol low byte %x\n", c);
|
||||
FLUSHEM(q, p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p->pai_buffcount >= p->pai_buffsize) { /* overrun */
|
||||
DLOG("ppp_async: too many chars in input buffer %d\n",
|
||||
p->pai_buffcount);
|
||||
FLUSHEM(q, p);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* determine if we have enough space in the buffer */
|
||||
if (wptr >= p->pai_bufftail->b_datap->db_lim) {
|
||||
p->pai_bufftail->b_wptr = wptr;
|
||||
if (!(p->pai_bufftail = allocb(ALLOCBSIZE, BPRI_MED))) {
|
||||
DLOG("ppp_async: couldn't get buffer for tail\n", 0);
|
||||
FLUSHEM(q, p); /* discard all of it */
|
||||
continue;
|
||||
}
|
||||
linkb(p->pai_buffer, p->pai_bufftail);
|
||||
wptr = p->pai_bufftail->b_wptr;
|
||||
}
|
||||
|
||||
STUFF_CHAR(p, c);
|
||||
p->pai_fcs = PPP_FCS(p->pai_fcs, c);
|
||||
|
||||
if (p->pai_buffcount >= PPP_HDRLEN) {
|
||||
while (cp < mp->b_wptr
|
||||
&& wptr < p->pai_bufftail->b_datap->db_lim
|
||||
&& (c = *cp) != PPP_FLAG && c != PPP_ESCAPE) {
|
||||
if (c >= 0x20 || (p->pai_rasyncmap & (1 << c)) == 0) {
|
||||
STUFF_CHAR(p, c);
|
||||
p->pai_fcs = PPP_FCS(p->pai_fcs, c);
|
||||
}
|
||||
++cp;
|
||||
}
|
||||
}
|
||||
|
||||
p->pai_bufftail->b_wptr = wptr;
|
||||
|
||||
} /* end while cp < wptr */
|
||||
} /* end for each block */
|
||||
/* discard this message now */
|
||||
freemsg(m0);
|
||||
} /* end while getq */
|
||||
|
||||
}
|
||||
|
||||
#if DEBUGS
|
||||
/*
|
||||
* here is where we will dump out a frame in hex using the log()
|
||||
* function if ppp_async_input_debug is non-zero. As this function is
|
||||
* a pig, we only print up to the number of bytes specified by the value of
|
||||
* the ppp_async_max_dump_bytes variable so as to not cause too many
|
||||
* timeouts. <gmc@quotron.com>
|
||||
*/
|
||||
|
||||
static void
|
||||
ppp_dump_frame(p, mptr, msg)
|
||||
register PAI *p;
|
||||
register mblk_t *mptr;
|
||||
char *msg;
|
||||
{
|
||||
register u_char *rptr;
|
||||
register u_int i, mlen, frame_length;
|
||||
char buf[2*MAX_DUMP_BYTES+4]; /* tmp buffer */
|
||||
char *bp = buf;
|
||||
static char digits[] = "0123456789abcdef";
|
||||
|
||||
frame_length = i = msgdsize(mptr);
|
||||
log(LOG_INFO, "ppp_async%d:%s frame of %d bytes\n", p - pai,
|
||||
msg, frame_length);
|
||||
rptr = mptr->b_rptr; /* get pointer to beginning */
|
||||
mlen = mptr->b_wptr - rptr; /* get length of this dblock */
|
||||
|
||||
/* only dump up to MAX_DUMP_BYTES */
|
||||
if (i > ppp_async_max_dump_bytes)
|
||||
i = ppp_async_max_dump_bytes;
|
||||
|
||||
while (i--) { /* convert to ascii hex */
|
||||
while (mlen == 0) { /* get next dblock */
|
||||
mptr = mptr->b_cont;
|
||||
if (mptr) { /* are we done? */
|
||||
rptr = mptr->b_rptr; /* nope, get next dblock */
|
||||
mlen = mptr->b_wptr - rptr;
|
||||
}
|
||||
else { /* no more dblocks */
|
||||
if (i != 0)
|
||||
log(LOG_ERR, "ppp_async: ran out of data! (this shouldn't happen\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
--mlen;
|
||||
*bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
|
||||
*bp++ = digits[*rptr++ & 0xf];
|
||||
}
|
||||
|
||||
/* add a '>' to show that frame was truncated*/
|
||||
if (ppp_async_max_dump_bytes < frame_length)
|
||||
*bp++ = '>';
|
||||
*bp = 0;
|
||||
log(LOG_INFO,"ppp_async: %s\n", buf);
|
||||
}
|
||||
#endif /* DEBUGS */
|
||||
|
||||
#endif /* NPPP > 0 */
|
457
osf1/ppp_comp.c
Normal file
457
osf1/ppp_comp.c
Normal file
@ -0,0 +1,457 @@
|
||||
/*
|
||||
* ppp_comp.c - STREAMS module for kernel-level 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.1 1995/12/18 23:45:09 paulus Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is used under SunOS 4.x, and OSF/1 on DEC Alpha.
|
||||
*
|
||||
* Beware that under OSF/1, the ioctl constants (SIOC*) end up
|
||||
* as 64-bit (long) values, so an ioctl constant should be cast to
|
||||
* int (32 bits) before being compared with the ioc_cmd field of
|
||||
* an iocblk structure.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/stream.h>
|
||||
#include <sys/stropts.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <net/ppp_defs.h>
|
||||
#include <net/ppp_str.h>
|
||||
|
||||
#ifdef __osf__
|
||||
#include <kern/kalloc.h>
|
||||
#ifdef FREE
|
||||
#undef FREE
|
||||
#endif
|
||||
#define ALLOCATE(n) kalloc((n))
|
||||
#define FREE(p, n) kfree((p), (n))
|
||||
#endif
|
||||
|
||||
#ifdef sun
|
||||
#include <sys/kmem_alloc.h>
|
||||
#define ALLOCATE(n) kmem_alloc((n), KMEM_NOSLEEP)
|
||||
#define FREE(p, n) kmem_free((p), (n))
|
||||
#endif
|
||||
|
||||
#define PACKETPTR mblk_t *
|
||||
#include <net/ppp-comp.h>
|
||||
|
||||
static int ppp_comp_open(), ppp_comp_close();
|
||||
static int ppp_comp_rput(), ppp_comp_wput();
|
||||
static void ppp_comp_ccp();
|
||||
|
||||
static struct module_info minfo = {
|
||||
0xbadf, "ppp_compress", 0, INFPSZ, 16384, 4096,
|
||||
};
|
||||
|
||||
static struct qinit r_init = {
|
||||
ppp_comp_rput, NULL, ppp_comp_open, ppp_comp_close,
|
||||
NULL, &minfo, NULL
|
||||
};
|
||||
|
||||
static struct qinit w_init = {
|
||||
ppp_comp_wput, NULL, NULL, NULL, NULL, &minfo, NULL
|
||||
};
|
||||
|
||||
struct streamtab ppp_compinfo = {
|
||||
&r_init, &w_init, NULL, NULL
|
||||
};
|
||||
|
||||
struct ppp_comp_state {
|
||||
int ccp_state;
|
||||
int debug;
|
||||
int mru;
|
||||
struct compressor *xcomp;
|
||||
void *xstate;
|
||||
struct compressor *rcomp;
|
||||
void *rstate;
|
||||
};
|
||||
|
||||
/* Bits in ccp_state are as defined in ppp_str.h. */
|
||||
#define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
|
||||
|
||||
/*
|
||||
* 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
|
||||
};
|
||||
|
||||
static int
|
||||
ppp_comp_open(q, dev, flag, sflag)
|
||||
queue_t *q;
|
||||
dev_t dev;
|
||||
int flag;
|
||||
int sflag;
|
||||
{
|
||||
struct ppp_comp_state *cp;
|
||||
|
||||
if (q->q_ptr == NULL) {
|
||||
cp = (struct ppp_comp_state *) ALLOCATE(sizeof(struct ppp_comp_state));
|
||||
if (cp == NULL) {
|
||||
u.u_error = ENOSR;
|
||||
return OPENFAIL;
|
||||
}
|
||||
OTHERQ(q)->q_ptr = q->q_ptr = (caddr_t) cp;
|
||||
cp->ccp_state = 0;
|
||||
cp->debug = 0;
|
||||
cp->mru = PPP_MRU;
|
||||
cp->xstate = NULL;
|
||||
cp->rstate = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ppp_comp_close(q)
|
||||
queue_t *q;
|
||||
{
|
||||
struct ppp_comp_state *cp;
|
||||
|
||||
cp = (struct ppp_comp_state *) 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);
|
||||
FREE(cp, sizeof(struct ppp_comp_state));
|
||||
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;
|
||||
struct ppp_comp_state *cp;
|
||||
mblk_t *cmp = NULL;
|
||||
int error, len, proto, state;
|
||||
struct ppp_option_data *odp;
|
||||
struct compressor **comp;
|
||||
struct ppp_comp_stats *pcp;
|
||||
|
||||
cp = (struct ppp_comp_state *) q->q_ptr;
|
||||
switch (mp->b_datap->db_type) {
|
||||
|
||||
case M_CTL:
|
||||
switch (*(u_char *) mp->b_rptr) {
|
||||
case IF_GET_CSTATS:
|
||||
freemsg(mp);
|
||||
mp = allocb(sizeof(struct ppp_comp_stats) + sizeof(u_long),
|
||||
BPRI_HI);
|
||||
if (mp != NULL) {
|
||||
mp->b_datap->db_type = M_CTL;
|
||||
*(u_char *) mp->b_wptr = IF_CSTATS;
|
||||
mp->b_wptr += sizeof(u_long); /* should be enough alignment */
|
||||
pcp = (struct ppp_comp_stats *) mp->b_wptr;
|
||||
mp->b_wptr += sizeof(struct ppp_comp_stats);
|
||||
bzero(pcp, sizeof(struct ppp_comp_stats));
|
||||
if (cp->xstate != NULL)
|
||||
(*cp->xcomp->comp_stat)(cp->xstate, &pcp->c);
|
||||
if (cp->rstate != NULL)
|
||||
(*cp->rcomp->decomp_stat)(cp->rstate, &pcp->d);
|
||||
qreply(q, mp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
putnext(q, mp);
|
||||
}
|
||||
break;
|
||||
|
||||
case M_DATA:
|
||||
/* first find out what the protocol is */
|
||||
if (mp->b_wptr - mp->b_rptr >= PPP_HDRLEN
|
||||
|| pullupmsg(mp, PPP_HDRLEN)) {
|
||||
proto = PPP_PROTOCOL(mp->b_rptr);
|
||||
if (proto == PPP_CCP)
|
||||
ppp_comp_ccp(q, mp, 0);
|
||||
else if (proto != PPP_LCP && (cp->ccp_state & CCP_COMP_RUN)
|
||||
&& cp->xstate != NULL) {
|
||||
len = msgdsize(mp);
|
||||
(*cp->xcomp->compress)(cp->xstate, &cmp, mp, len,
|
||||
(cp->ccp_state & CCP_ISUP? len: 0));
|
||||
/* XXX we really want the MTU here, not len */
|
||||
if (cmp != NULL) {
|
||||
freemsg(mp);
|
||||
mp = cmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
putnext(q, mp);
|
||||
break;
|
||||
|
||||
case M_IOCTL:
|
||||
iop = (struct iocblk *) mp->b_rptr;
|
||||
error = -1;
|
||||
switch (iop->ioc_cmd) {
|
||||
|
||||
case SIOCSIFCOMP:
|
||||
/* set CCP state */
|
||||
if (iop->ioc_count != sizeof(int)) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
state = (*(int *) mp->b_cont->b_rptr) & (CCP_ISUP | CCP_ISOPEN);
|
||||
if ((state & 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->ccp_state = 0;
|
||||
} else {
|
||||
cp->ccp_state = (cp->ccp_state & ~CCP_ISUP) | state;
|
||||
}
|
||||
if (cp->debug)
|
||||
log(LOG_DEBUG, "SIOCSIFCOMP %x, state = %x\n",
|
||||
*(int *) mp->b_cont->b_rptr, cp->ccp_state);
|
||||
error = 0;
|
||||
iop->ioc_count = 0;
|
||||
break;
|
||||
|
||||
case SIOCGIFCOMP:
|
||||
if ((mp->b_cont = allocb(sizeof(int), BPRI_MED)) == NULL) {
|
||||
error = ENOSR;
|
||||
break;
|
||||
}
|
||||
*(int *)mp->b_cont->b_wptr = cp->ccp_state;
|
||||
mp->b_cont->b_wptr += iop->ioc_count = sizeof(int);
|
||||
error = 0;
|
||||
break;
|
||||
|
||||
case SIOCSCOMPRESS:
|
||||
error = EINVAL;
|
||||
if (iop->ioc_count != sizeof(struct ppp_option_data))
|
||||
break;
|
||||
odp = (struct ppp_option_data *) mp->b_cont->b_rptr;
|
||||
len = mp->b_cont->b_wptr - (unsigned char *) odp->opt_data;
|
||||
if (len > odp->length)
|
||||
len = odp->length;
|
||||
if (odp->opt_data[1] < 2 || odp->opt_data[1] > len)
|
||||
break;
|
||||
for (comp = ppp_compressors; *comp != NULL; ++comp)
|
||||
if ((*comp)->compress_proto == odp->opt_data[0]) {
|
||||
/* here's the handler! */
|
||||
error = 0;
|
||||
if (odp->transmit) {
|
||||
if (cp->xstate != NULL)
|
||||
(*cp->xcomp->comp_free)(cp->xstate);
|
||||
cp->xcomp = *comp;
|
||||
cp->xstate = (*comp)->comp_alloc(odp->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(odp->opt_data, len);
|
||||
if (cp->rstate == NULL)
|
||||
error = ENOSR;
|
||||
}
|
||||
if (cp->debug)
|
||||
log(LOG_DEBUG, "SIOCSCOMPRESS %s len=%d\n",
|
||||
odp->transmit? "xmit": "recv", len);
|
||||
break;
|
||||
}
|
||||
iop->ioc_count = 0;
|
||||
break;
|
||||
|
||||
case SIOCSIFDEBUG:
|
||||
/* set our debug flag from this */
|
||||
if (iop->ioc_count == sizeof(int)) {
|
||||
cp->debug = *(int *) mp->b_cont->b_rptr & 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIFMRU:
|
||||
/* remember this value */
|
||||
if (iop->ioc_count == sizeof(int)) {
|
||||
cp->mru = *(int *) mp->b_cont->b_rptr;
|
||||
}
|
||||
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;
|
||||
qreply(q, mp);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
putnext(q, mp);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ppp_comp_rput(q, mp)
|
||||
queue_t *q;
|
||||
mblk_t *mp;
|
||||
{
|
||||
int proto, rv;
|
||||
mblk_t *dmp = NULL;
|
||||
struct ppp_comp_state *cp;
|
||||
|
||||
cp = (struct ppp_comp_state *) q->q_ptr;
|
||||
switch (mp->b_datap->db_type) {
|
||||
|
||||
case M_DATA:
|
||||
/* possibly a compressed packet to decompress,
|
||||
or a CCP packet to take notice of. */
|
||||
if (mp->b_wptr - mp->b_rptr >= PPP_HDRLEN
|
||||
|| pullupmsg(mp, PPP_HDRLEN)) {
|
||||
proto = PPP_PROTOCOL(mp->b_rptr);
|
||||
if (proto == PPP_CCP)
|
||||
ppp_comp_ccp(q, mp, 1);
|
||||
else if (proto == PPP_COMP) {
|
||||
if ((cp->ccp_state & CCP_ISUP)
|
||||
&& (cp->ccp_state & CCP_DECOMP_RUN) && cp->rstate
|
||||
&& (cp->ccp_state & CCP_ERR) == 0) {
|
||||
rv = (*cp->rcomp->decompress)(cp->rstate, mp, &dmp);
|
||||
switch (rv) {
|
||||
case DECOMP_OK:
|
||||
freemsg(mp);
|
||||
mp = dmp;
|
||||
/* if mp is now NULL, then there was no error,
|
||||
but no packet returned either. */
|
||||
break;
|
||||
case DECOMP_ERROR:
|
||||
cp->ccp_state |= CCP_ERROR;
|
||||
break;
|
||||
case DECOMP_FATALERROR:
|
||||
cp->ccp_state |= CCP_FATALERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (cp->rstate && (cp->ccp_state & CCP_DECOMP_RUN)) {
|
||||
(*cp->rcomp->incomp)(cp->rstate, mp);
|
||||
}
|
||||
}
|
||||
if (mp != NULL)
|
||||
putnext(q, mp);
|
||||
break;
|
||||
|
||||
default:
|
||||
putnext(q, mp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ppp_comp_ccp(q, mp, rcvd)
|
||||
queue_t *q;
|
||||
mblk_t *mp;
|
||||
int rcvd;
|
||||
{
|
||||
int len, clen;
|
||||
struct ppp_comp_state *cp;
|
||||
unsigned char *dp;
|
||||
|
||||
len = msgdsize(mp);
|
||||
if (len < PPP_HDRLEN + CCP_HDRLEN || !pullupmsg(mp, len))
|
||||
return;
|
||||
cp = (struct ppp_comp_state *) q->q_ptr;
|
||||
dp = mp->b_rptr + PPP_HDRLEN;
|
||||
len -= PPP_HDRLEN;
|
||||
clen = CCP_LENGTH(dp);
|
||||
if (clen > len)
|
||||
return;
|
||||
if (cp->debug)
|
||||
log(LOG_DEBUG, "CCP %s: code=%x len=%d\n", rcvd? "rcvd": "sent",
|
||||
CCP_CODE(dp), clen);
|
||||
|
||||
switch (CCP_CODE(dp)) {
|
||||
case CCP_CONFREQ:
|
||||
case CCP_TERMREQ:
|
||||
case CCP_TERMACK:
|
||||
cp->ccp_state &= ~CCP_ISUP;
|
||||
break;
|
||||
|
||||
case CCP_CONFACK:
|
||||
if ((cp->ccp_state & (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,
|
||||
0, /* XXX: should be unit */ 0,
|
||||
cp->debug))
|
||||
cp->ccp_state |= CCP_COMP_RUN;
|
||||
} else {
|
||||
if (cp->rstate != NULL
|
||||
&& (*cp->rcomp->decomp_init)
|
||||
(cp->rstate, dp + CCP_HDRLEN, clen - CCP_HDRLEN,
|
||||
0/* unit */, 0, cp->mru, cp->debug))
|
||||
cp->ccp_state = (cp->ccp_state & ~CCP_ERR)
|
||||
| CCP_DECOMP_RUN;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CCP_RESETACK:
|
||||
if (cp->ccp_state & CCP_ISUP) {
|
||||
if (!rcvd) {
|
||||
if (cp->xstate && (cp->ccp_state & CCP_COMP_RUN))
|
||||
(*cp->xcomp->comp_reset)(cp->xstate);
|
||||
} else {
|
||||
if (cp->rstate && (cp->ccp_state & CCP_DECOMP_RUN)) {
|
||||
(*cp->rcomp->decomp_reset)(cp->rstate);
|
||||
cp->ccp_state &= ~CCP_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (cp->debug)
|
||||
log(LOG_DEBUG, "ccp_state = %x\n", cp->ccp_state);
|
||||
}
|
1164
osf1/ppp_if.c
Normal file
1164
osf1/ppp_if.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user