⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppp_comp.c

📁 经典的ppp程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 HAS 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.12 1999/09/15 23:49:06 masputra Exp $ *//* * This file is used under SVR4, Solaris 2, SunOS 4, and Digital UNIX. */#include <sys/types.h>#include <sys/param.h>#include <sys/errno.h>#include <sys/stream.h>#ifdef SVR4#include <sys/conf.h>#include <sys/cmn_err.h>#include <sys/ddi.h>#else#include <sys/user.h>#ifdef __osf__#include <sys/cmn_err.h>#endif#endif /* SVR4 */#include <net/ppp_defs.h>#include <net/pppio.h>#include "ppp_mod.h"#ifdef __osf__#include <sys/mbuf.h>#include <sys/protosw.h>#endif#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>MOD_OPEN_DECL(ppp_comp_open);MOD_CLOSE_DECL(ppp_comp_close);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 int msg_byte __P((mblk_t *, unsigned int));/* Extract byte i of message mp. */#define MSG_BYTE(mp, i)	((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \			 msg_byte((mp), (i)))/* Is this LCP packet one we have to transmit using LCP defaults? */#define LCP_USE_DFLT(mp)	(1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)#define PPP_COMP_ID 0xbadfstatic struct module_info minfo = {#ifdef PRIOQ    PPP_COMP_ID, "ppp_comp", 0, INFPSZ, 16512, 16384,#else    PPP_COMP_ID, "ppp_comp", 0, INFPSZ, 16384, 4096,#endif};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};#if defined(SVR4) && !defined(SOL2)int pcmpdevflag = 0;#define ppp_compinfo pcmpinfo#endifstruct streamtab ppp_compinfo = {    &r_init, &w_init, NULL, NULL};int ppp_comp_count;		/* number of module instances in use */#ifdef __osf__static void ppp_comp_alloc __P((comp_state_t *));typedef struct memreq {    unsigned char comp_opts[20];    int cmd;    int thread_status;    char *returned_mem;} memreq_t;#endiftypedef 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;#ifdef __osf__    memreq_t	memreq;    thread_t	thread;#endif} comp_state_t;#ifdef __osf__extern task_t first_task;#endif/* 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 DBGLOG		0x2000000	/* log debugging stuff */#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))/* * List of compressors we know about. */#if DO_BSD_COMPRESSextern struct compressor ppp_bsd_compress;#endif#if DO_DEFLATEextern struct compressor ppp_deflate, ppp_deflate_draft;#endifstruct compressor *ppp_compressors[] = {#if DO_BSD_COMPRESS    &ppp_bsd_compress,#endif#if DO_DEFLATE    &ppp_deflate,    &ppp_deflate_draft,#endif    NULL};/* * STREAMS module entry points. */MOD_OPEN(ppp_comp_open){    comp_state_t *cp;#ifdef __osf__    thread_t thread;#endif    if (q->q_ptr == NULL) {	cp = (comp_state_t *) ALLOC_SLEEP(sizeof(comp_state_t));	if (cp == NULL)	    OPEN_ERROR(ENOSR);	bzero((caddr_t)cp, sizeof(comp_state_t));	WR(q)->q_ptr = q->q_ptr = (caddr_t) cp;	cp->mru = PPP_MRU;	cp->mtu = PPP_MTU;	cp->xstate = NULL;	cp->rstate = NULL;	vj_compress_init(&cp->vj_comp, -1);#ifdef __osf__	if (!(thread = kernel_thread_w_arg(first_task, ppp_comp_alloc, (void *)cp)))		OPEN_ERROR(ENOSR);	cp->thread = thread;#endif	++ppp_comp_count;	qprocson(q);    }    return 0;}MOD_CLOSE(ppp_comp_close){    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);#ifdef __osf__	if (!cp->thread)	    printf("ppp_comp_close: NULL thread!\n");	else	    thread_terminate(cp->thread);#endif	FREE(cp, sizeof(comp_state_t));	q->q_ptr = NULL;	OTHERQ(q)->q_ptr = NULL;	--ppp_comp_count;    }    return 0;}#ifdef __osf__/* thread for calling back to a compressor's memory allocator * Needed for Digital UNIX since it's VM can't handle requests * for large amounts of memory without blocking.  The thread * provides a context in which we can call a memory allocator * that may block. */static voidppp_comp_alloc(comp_state_t *cp){    int len, cmd;    unsigned char *compressor_options;    thread_t thread;    void *(*comp_allocator)();#if defined(MAJOR_VERSION) && (MAJOR_VERSION <= 2)    /* In 2.x and earlier the argument gets passed     * in the thread structure itself.  Yuck.     */    thread = current_thread();    cp = thread->reply_port;    thread->reply_port = PORT_NULL;#endif    for (;;) {	assert_wait((vm_offset_t)&cp->memreq.thread_status, TRUE);	thread_block();	if (thread_should_halt(current_thread()))	    thread_halt_self();	cmd = cp->memreq.cmd;	compressor_options = &cp->memreq.comp_opts[0];	len = compressor_options[1];	if (cmd == PPPIO_XCOMP) {	    cp->memreq.returned_mem = cp->xcomp->comp_alloc(compressor_options, len);	    if (!cp->memreq.returned_mem) {		cp->memreq.thread_status = ENOSR;	    } else {		cp->memreq.thread_status = 0;	    }	} else {	    cp->memreq.returned_mem = cp->rcomp->decomp_alloc(compressor_options, len);	    if (!cp->memreq.returned_mem) {	        cp->memreq.thread_status = ENOSR;	    } else {		cp->memreq.thread_status = 0;	    }	}    }}#endif /* __osf__ *//* here's the deal with memory allocation under Digital UNIX. * Some other may also benefit from this... * We can't ask for huge chunks of memory in a context where * the caller can't be put to sleep (like, here.)  The alloc * is likely to fail.  Instead we do this: the first time we * get called, kick off a thread to do the allocation.  Return * immediately to the caller with EAGAIN, as an indication that * they should send down the ioctl again.  By the time the * second call comes in it's likely that the memory allocation * thread will have returned with the requested memory.  We will * continue to return EAGAIN however until the thread has completed. * When it has, we return zero (and the memory) if the allocator * was successful and ENOSR otherwise. * * Callers of the RCOMP and XCOMP ioctls are encouraged (but not * required) to loop for some number of iterations with a small * delay in the loop body (for instance a 1/10-th second "sleep" * via select.) */static intppp_comp_wput(q, mp)    queue_t *q;    mblk_t *mp;{    struct iocblk *iop;    comp_state_t *cp;    int error, len, n;    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;    if (cp == 0) {	DPRINT("cp == 0 in ppp_comp_wput\n");	freemsg(mp);	return 0;    }    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;	    if (mp->b_cont == 0) {		DPRINT1("ppp_comp_wput/%d: PPPIO_CFLAGS b_cont = 0!\n", cp->unit);		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;	    if (mp->b_cont == 0) {		DPRINT1("ppp_comp_wput/%d: PPPIO_VJINIT b_cont = 0!\n", cp->unit);		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;	    if (mp->b_cont == 0) {		DPRINT1("ppp_comp_wput/%d: PPPIO_[XR]COMP b_cont = 0!\n", cp->unit);		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;#ifndef __osf__		    if (iop->ioc_cmd == PPPIO_XCOMP) {			/* A previous call may have fetched memory for a compressor			 * that's now being retired or reset.  Free it using it's			 * mechanism for freeing stuff.			 */			if (cp->xstate != NULL) {			    (*cp->xcomp->comp_free)(cp->xstate);			    cp->xstate = NULL;			}			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->rstate = NULL;			}			cp->rcomp = *comp;			cp->rstate = (*comp)->decomp_alloc(opt_data, len);			if (cp->rstate == NULL)			    error = ENOSR;		    }#else		    if ((error = cp->memreq.thread_status) != EAGAIN)		    if (iop->ioc_cmd == PPPIO_XCOMP) {			if (cp->xstate) {			    (*cp->xcomp->comp_free)(cp->xstate);			    cp->xstate = 0;			}			/* sanity check for compressor options			 */			if (sizeof (cp->memreq.comp_opts) < len) {			    printf("can't handle options for compressor %d (%d)\n", opt_data[0],				opt_data[1]);			    cp->memreq.thread_status = ENOSR;			    cp->memreq.returned_mem = 0;			}			/* fill in request for the thread and kick it off			 */			if (cp->memreq.thread_status == 0 && !cp->memreq.returned_mem) {			    bcopy(opt_data, cp->memreq.comp_opts, len);			    cp->memreq.cmd = PPPIO_XCOMP;			    cp->xcomp = *comp;			    error = cp->memreq.thread_status = EAGAIN;			    thread_wakeup((vm_offset_t)&cp->memreq.thread_status);			} else {			    cp->xstate = cp->memreq.returned_mem;			    cp->memreq.returned_mem = 0;			    cp->memreq.thread_status = 0;			}		    } else {			if (cp->rstate) {			    (*cp->rcomp->decomp_free)(cp->rstate);			    cp->rstate = NULL;			}			if (sizeof (cp->memreq.comp_opts) < len) {			    printf("can't handle options for compressor %d (%d)\n", opt_data[0],				opt_data[1]);			    cp->memreq.thread_status = ENOSR;			    cp->memreq.returned_mem = 0;			}			if (cp->memreq.thread_status == 0 && !cp->memreq.returned_mem) {			    bcopy(opt_data, cp->memreq.comp_opts, len);			    cp->memreq.cmd = PPPIO_RCOMP;			    cp->rcomp = *comp;			    error = cp->memreq.thread_status = EAGAIN;			    thread_wakeup((vm_offset_t)&cp->memreq.thread_status);			} else {			    cp->rstate = cp->memreq.returned_mem;			    cp->memreq.returned_mem = 0;			    cp->memreq.thread_status = 0;			}		    }#endif		    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_DEBUG:	    if (iop->ioc_count != sizeof(int))		break;	    if (mp->b_cont == 0) {		DPRINT1("ppp_comp_wput/%d: PPPIO_DEBUG b_cont = 0!\n", cp->unit);		break;	    }	    n = *(int *)mp->b_cont->b_rptr;	    if (n == PPPDBG_LOG + PPPDBG_COMP) {		DPRINT1("ppp_comp%d: debug log enabled\n", cp->unit);		cp->flags |= DBGLOG;		error = 0;		iop->ioc_count = 0;	    } else {		error = -1;	    }	    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) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -