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

📄 ppp.c

📁 经典的ppp程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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 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.c,v 1.1 2000/04/18 23:51:28 masputra Exp $ *//* * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX. */#include <sys/types.h>#include <sys/param.h>#include <sys/stat.h>#include <sys/stream.h>#include <sys/stropts.h>#include <sys/errno.h>#ifdef __osf__#include <sys/ioctl.h>#include <sys/cmn_err.h>#define queclass(mp)	((mp)->b_band & QPCTL)#else#include <sys/ioccom.h>#endif#include <sys/time.h>#ifdef SVR4#include <sys/cmn_err.h>#include <sys/conf.h>#include <sys/dlpi.h>#include <sys/ddi.h>#ifdef SOL2#include <sys/ksynch.h>#include <sys/kstat.h>#include <sys/sunddi.h>#include <sys/ethernet.h>#else#include <sys/socket.h>#include <sys/sockio.h>#include <net/if.h>#include <netinet/in.h>#endif /* SOL2 */#else /* not SVR4 */#include <sys/user.h>#endif /* SVR4 */#include <net/ppp_defs.h>#include <net/pppio.h>#include "ppp_mod.h"/* * Modifications marked with #ifdef PRIOQ are for priority queueing of * interactive traffic, and are due to Marko Zec <zec@japa.tel.fer.hr>. */#ifdef PRIOQ#endif	/* PRIOQ */#include <netinet/in.h>	/* leave this outside of PRIOQ for htons */#ifdef __STDC__#define __P(x)	x#else#define __P(x)	()#endif/* * The IP module may use this SAP value for IP packets. */#ifndef ETHERTYPE_IP#define ETHERTYPE_IP	0x800#endif#if !defined(ETHERTYPE_IPV6) #define ETHERTYPE_IPV6	0x86dd#endif /* !defined(ETHERTYPE_IPV6) */#if !defined(ETHERTYPE_ALLSAP) && defined(SOL2)#define ETHERTYPE_ALLSAP   0#endif /* !defined(ETHERTYPE_ALLSAP) && defined(SOL2) */#if !defined(PPP_ALLSAP) && defined(SOL2)#define PPP_ALLSAP  PPP_ALLSTATIONS#endif /* !defined(PPP_ALLSAP) && defined(SOL2) */extern time_t time;#ifdef SOL2/* * We use this reader-writer lock to ensure that the lower streams * stay connected to the upper streams while the lower-side put and * service procedures are running.  Essentially it is an existence * lock for the upper stream associated with each lower stream. */krwlock_t ppp_lower_lock;#define LOCK_LOWER_W	rw_enter(&ppp_lower_lock, RW_WRITER)#define LOCK_LOWER_R	rw_enter(&ppp_lower_lock, RW_READER)#define TRYLOCK_LOWER_R	rw_tryenter(&ppp_lower_lock, RW_READER)#define UNLOCK_LOWER	rw_exit(&ppp_lower_lock)#define MT_ENTER(x)	mutex_enter(x)#define MT_EXIT(x)	mutex_exit(x)/* * Notes on multithreaded implementation for Solaris 2: * * We use an inner perimeter around each queue pair and an outer * perimeter around the whole driver.  The inner perimeter is * entered exclusively for all entry points (open, close, put, * service).  The outer perimeter is entered exclusively for open * and close and shared for put and service.  This is all done for * us by the streams framework. * * I used to think that the perimeters were entered for the lower * streams' put and service routines as well as for the upper streams'. * Because of problems experienced by people, and after reading the * documentation more closely, I now don't think that is true.  So we * now use ppp_lower_lock to give us an existence guarantee on the * upper stream controlling each lower stream. * * Shared entry to the outer perimeter protects the existence of all * the upper streams and their upperstr_t structures, and guarantees * that the following fields of any upperstr_t won't change: * nextmn, next, nextppa.  It guarantees that the lowerq field of an * upperstr_t won't go from non-zero to zero, that the global `ppas' * won't change and that the no lower stream will get unlinked. * * Shared (reader) access to ppa_lower_lock guarantees that no lower * stream will be unlinked and that the lowerq field of all upperstr_t * structures won't change. */#else /* SOL2 */#define LOCK_LOWER_W	0#define LOCK_LOWER_R	0#define TRYLOCK_LOWER_R	1#define UNLOCK_LOWER	0#define MT_ENTER(x)	0#define MT_EXIT(x)	0#endif /* SOL2 *//* * 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 */    enum NPmode npmode;		/* what to do with packets on this SAP */    unsigned char rblocked;	/* flow control has blocked upper read strm */	/* N.B. rblocked is only changed by control stream's put/srv procs */    /*     * 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 */    time_t last_sent;		/* time last NP packet sent */    time_t last_recv;		/* time last NP packet rcvd */#ifdef SOL2    kmutex_t stats_lock;	/* lock for stats updates */    kstat_t *kstats;		/* stats for netstat */#endif /* SOL2 */#ifdef LACHTCP    int ifflags;    char ifname[IFNAMSIZ];    struct ifstats ifstats;#endif /* LACHTCP */} 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 */#define US_RBLOCKED	0x20	/* flow ctrl has blocked upper read stream */#if defined(SOL2)#if DL_CURRENT_VERSION >= 2#define US_PROMISC	0x40	/* stream is promiscuous */#endif /* DL_CURRENT_VERSION >= 2 */#define US_RAWDATA	0x80	/* raw M_DATA, no DLPI header */#endif /* defined(SOL2) */#ifdef PRIOQstatic u_char max_band=0;static u_char def_band=0;#define IPPORT_DEFAULT		65535/* * Port priority table * Highest priority ports are listed first, lowest are listed last. * ICMP & packets using unlisted ports will be treated as "default". * If IPPORT_DEFAULT is not listed here, "default" packets will be  * assigned lowest priority. * Each line should be terminated with "0". * Line containing only "0" marks the end of the list. */static u_short prioq_table[]= {    113, 53, 0,    22, 23, 513, 517, 518, 0,    514, 21, 79, 111, 0,    25, 109, 110, 0,    IPPORT_DEFAULT, 0,    20, 70, 80, 8001, 8008, 8080, 0, /* 8001,8008,8080 - common proxy ports */0 };#endif	/* PRIOQ */static upperstr_t *minor_devs = NULL;static upperstr_t *ppas = NULL;#ifdef SVR4static int pppopen __P((queue_t *, dev_t *, int, int, cred_t *));static int pppclose __P((queue_t *, int, cred_t *));#elsestatic int pppopen __P((queue_t *, int, int, int));static int pppclose __P((queue_t *, int));#endif /* SVR4 */static int pppurput __P((queue_t *, mblk_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 *));#ifndef NO_DLPIstatic void dlpi_request __P((queue_t *, mblk_t *, upperstr_t *));static void dlpi_error __P((queue_t *, upperstr_t *, int, int, int));static void dlpi_ok __P((queue_t *, int));#endifstatic 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 detach_lower __P((queue_t *, mblk_t *));static void debug_dump __P((queue_t *, mblk_t *));static upperstr_t *find_dest __P((upperstr_t *, int));#if defined(SOL2)static upperstr_t *find_promisc __P((upperstr_t *, int));static mblk_t *prepend_ether __P((upperstr_t *, mblk_t *, int));static mblk_t *prepend_udind __P((upperstr_t *, mblk_t *, int));static void promisc_sendup __P((upperstr_t *, mblk_t *, int, int));#endif /* defined(SOL2) */static int putctl2 __P((queue_t *, int, int, int));static int putctl4 __P((queue_t *, int, int, int));static int pass_packet __P((upperstr_t *ppa, mblk_t *mp, int outbound));#ifdef FILTER_PACKETSstatic int ip_hard_filter __P((upperstr_t *ppa, mblk_t *mp, int outbound));#endif /* FILTER_PACKETS */#define PPP_ID 0xb1a6static struct module_info ppp_info = {#ifdef PRIOQ    PPP_ID, "ppp", 0, 512, 512, 384#else    PPP_ID, "ppp", 0, 512, 512, 128#endif	/* PRIOQ */};static struct qinit pppurint = {    pppurput, 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};#ifdef LACHTCPextern struct ifstats *ifstats;int pppdevflag = 0;#endifstruct streamtab pppinfo = {    &pppurint, &pppuwint,    &ppplrint, &ppplwint};int ppp_count;/* * How we maintain statistics. */#ifdef SOL2#define INCR_IPACKETS(ppa)				\	if (ppa->kstats != 0) {				\	    KSTAT_NAMED_PTR(ppa->kstats)[0].value.ul++;	\	}#define INCR_IERRORS(ppa)				\	if (ppa->kstats != 0) {				\	    KSTAT_NAMED_PTR(ppa->kstats)[1].value.ul++;	\	}#define INCR_OPACKETS(ppa)				\	if (ppa->kstats != 0) {				\	    KSTAT_NAMED_PTR(ppa->kstats)[2].value.ul++;	\	}#define INCR_OERRORS(ppa)				\	if (ppa->kstats != 0) {				\	    KSTAT_NAMED_PTR(ppa->kstats)[3].value.ul++;	\	}#endif#ifdef LACHTCP#define INCR_IPACKETS(ppa)	ppa->ifstats.ifs_ipackets++;#define INCR_IERRORS(ppa)	ppa->ifstats.ifs_ierrors++;#define INCR_OPACKETS(ppa)	ppa->ifstats.ifs_opackets++;#define INCR_OERRORS(ppa)	ppa->ifstats.ifs_oerrors++;#endif/* * STREAMS driver entry points. */static int#ifdef SVR4pppopen(q, devp, oflag, sflag, credp)    queue_t *q;    dev_t *devp;    int oflag, sflag;    cred_t *credp;#elsepppopen(q, dev, oflag, sflag)    queue_t *q;    int dev;			/* really dev_t */    int oflag, sflag;#endif{    upperstr_t *up;    upperstr_t **prevp;    minor_t mn;#ifdef PRIOQ    u_short *ptr;    u_char new_band;#endif	/* PRIOQ */    if (q->q_ptr)	DRV_OPEN_OK(dev);	/* device is already open */#ifdef PRIOQ    /* Calculate max_bband & def_band from definitions in prioq.h       This colud be done at some more approtiate time (less often)       but this way it works well so I'll just leave it here */    max_band = 1;    def_band = 0;    ptr = prioq_table;    while (*ptr) {        new_band = 1;        while (*ptr)	    if (*ptr++ == IPPORT_DEFAULT) {		new_band = 0;		def_band = max_band;	    }        max_band += new_band;        ptr++;    }    if (def_band)        def_band = max_band - def_band;    --max_band;#endif	/* PRIOQ */    if (sflag == CLONEOPEN) {	mn = 0;	for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {	    if (up->mn != mn)		break;	    ++mn;	}    } else {#ifdef SVR4	mn = getminor(*devp);#else	mn = minor(dev);#endif	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 = (caddr_t) up;	    DRV_OPEN_OK(dev);	}    }    /*     * Construct a new minor node.     */    up = (upperstr_t *) ALLOC_SLEEP(sizeof(upperstr_t));    bzero((caddr_t) up, sizeof(upperstr_t));    if (up == 0) {	DPRINT("pppopen: out of kernel memory\n");	OPEN_ERROR(ENXIO);    }    up->nextmn = *prevp;    *prevp = up;    up->mn = mn;#ifdef SVR4    *devp = makedevice(getmajor(*devp), mn);#endif    up->q = q;    if (NOTSUSER() == 0)	up->flags |= US_PRIV;#ifndef NO_DLPI    up->state = DL_UNATTACHED;#endif#ifdef LACHTCP    up->ifflags = IFF_UP | IFF_POINTOPOINT;#endif    up->sap = -1;    up->last_sent = up->last_recv = time;    up->npmode = NPMODE_DROP;    q->q_ptr = (caddr_t) up;    WR(q)->q_ptr = (caddr_t) up;    noenable(WR(q));#ifdef SOL2    mutex_init(&up->stats_lock, NULL, MUTEX_DRIVER, NULL);#endif    ++ppp_count;    qprocson(q);    DRV_OPEN_OK(makedev(major(dev), mn));}static int#ifdef SVR4pppclose(q, flag, credp)    queue_t *q;    int flag;    cred_t *credp;#elsepppclose(q, flag)    queue_t *q;    int flag;#endif{    upperstr_t *up, **upp;    upperstr_t *as, *asnext;    upperstr_t **prevp;    qprocsoff(q);    up = (upperstr_t *) q->q_ptr;    if (up == 0) {	DPRINT("pppclose: q_ptr = 0\n");	return 0;    }    if (up->flags & US_DBGLOG)	DPRINT2("ppp/%d: close, flags=%x\n", up->mn, up->flags);    if (up->flags & US_CONTROL) {#ifdef LACHTCP	struct ifstats *ifp, *pifp;#endif	if (up->lowerq != 0) {	    /* Gack! the lower stream should have be unlinked earlier! */

⌨️ 快捷键说明

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