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

📄 if_tap.c

📁 实现vpn网关用来建立 IP虚拟隧道
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1999 Maksim Yevmenkin <m_evmenkin@yahoo.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * BASED ON: * ------------------------------------------------------------------------- * *	$NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ * * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> * Nottingham University 1987. * * This source may be freely distributed, however I would be interested * in any changes that are made. * * This driver takes packets off the IP i/f and hands them up to a * user process to have its wicked way with. This driver has it's * roots in a similar driver written by Phil Cockcroft (formerly) at * UCL. This driver is based much more on read/write/poll mode of * operation though. *//* * $Id: if_tap.c,v 1.3 2000/05/04 17:50:33 maxk Exp $ */#include <sys/param.h>#include <sys/proc.h>#include <sys/systm.h>#include <sys/mbuf.h>#include <sys/malloc.h>#include <sys/socket.h>#include <sys/filio.h>#include <sys/sockio.h>#include <sys/ttycom.h>#include <sys/poll.h>#include <sys/signalvar.h>#include <sys/filedesc.h>#include <sys/kernel.h>#include <sys/sysctl.h>#ifdef DEVFS#include <sys/devfsext.h>#endif /*DEVFS*/#include <sys/conf.h>#include <sys/uio.h>#include <sys/vnode.h>#include <net/ethernet.h>#include <net/if.h>#include <net/if_arp.h>#include <net/netisr.h>#include <net/route.h>#ifdef INET#include <netinet/in.h>#include <netinet/in_var.h>#endif /* INET */#ifdef NS#include <netns/ns.h>#include <netns/ns_if.h>#endif /* NS */#if NBPFILTER > 0#include <net/bpf.h>#endif /* NBPFILTER */#ifdef BRIDGE#include <net/bridge.h>#endif /* BRIDGE */#include "if_tap.h"/* pseudo device */static void tapattach	__P((void *));PSEUDO_SET(tapattach, if_tap);/* network interface */static void tapifstart	__P((struct ifnet *));static int  tapifioctl	__P((struct ifnet *, u_long, caddr_t));static void tapifinit	__P((void *));/* character device */static	d_open_t	tapopen;static	d_close_t	tapclose;static	d_read_t	tapread;static	d_write_t	tapwrite;static	d_ioctl_t	tapioctl;static	d_poll_t	tappoll;#define CDEV_MAJOR 200 /* 52 -- for tun */static struct cdevsw tap_cdevsw = {	tapopen,	tapclose,	tapread,	tapwrite,	tapioctl,	nullstop,	noreset,	nodevtotty,	tappoll,	nommap,		nostrategy,	"tap",	NULL,	-1};/* local storage */static int			 tap_devsw_installed = 0;static struct tap_softc		*tapcntl[NTAP] = { 0, };static int			 tapdebug = 0;#define TAPDEBUG		 if (tapdebug) printfSYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");#define minor_val(n) ((((n) & ~0xff) << 8) | ((n) & 0xff))#define dev_val(n) (((n) >> 8) | ((n) & 0xff))/*** tapattch **** To attach pseudo device */static voidtapattach(dummy)	void	*dummy;{	int		 	 i;	struct ifnet		*ifp;	struct tap_softc	*tp;	dev_t			 dev;	short			 macaddr_hi;	TAPDEBUG(__FUNCTION__": attaching devices. NTAP = %d.\n", NTAP);	if (tap_devsw_installed) {		TAPDEBUG(__FUNCTION__": exiting. Devices already attached. " \			"tap_devsw_installed = %d\n", tap_devsw_installed);		return;	}	dev = makedev(CDEV_MAJOR, 0);	cdevsw_add(&dev, &tap_cdevsw, NULL);	tap_devsw_installed = 1;	/* create network interfaces */	for (i = 0; i < NTAP; i++) {		tp = (struct tap_softc *)malloc(sizeof(*tp),M_DEVBUF,M_WAITOK);		tapcntl[i] = tp;		bzero(tp, sizeof(*tp));		ifp = &tp->tap_if;		tp->tap_flags = TAP_INITED;		/* generate fake MAC address: 00 bd xx xx xx unit_no */		macaddr_hi = htons(0x00bd);		bcopy(&macaddr_hi, &tp->arpcom.ac_enaddr[0], sizeof(short));		bcopy(&ticks, &tp->arpcom.ac_enaddr[2], sizeof(long));		tp->arpcom.ac_enaddr[5] = (u_char)i;		/* fill the rest and attach interface */			ifp->if_softc  = tp;		ifp->if_unit   = i;		ifp->if_name   = "tap";		ifp->if_init   = tapifinit;		ifp->if_output = ether_output;		ifp->if_start  = tapifstart;		ifp->if_ioctl  = tapifioctl;		ifp->if_mtu    = ETHERMTU;		ifp->if_flags  = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;		ifp->if_snd.ifq_maxlen = ifqmaxlen;		tp->if_rcv.ifq_maxlen  = ifqmaxlen;		if_attach(ifp);		ether_ifattach(ifp);#if NBPFILTER > 0		bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));#endif /* NBPFILTER */#ifdef DEVFS		tp->tap_devfs_token = devfs_add_devswf(&tap_cdevsw,minor_val(i),						      DV_CHR, UID_UUCP,						      GID_DIALER, 0600,						      "tap%d", i);#endif /* DEVFS */	}} /* tapattach *//*** tapopen **** To open tunnel. Must be superuser & the device must be configured in*/static inttapopen(dev, flag, mode, p)	dev_t		 dev;	int		 flag;	int		 mode;	struct proc	*p;{	struct ifnet		*ifp;	struct tap_softc	*tp;	register int		 unit, error;	error = suser(p->p_ucred, &p->p_acflag);	if (error) {		return (error);	}	if ((unit = dev_val(minor(dev))) >= NTAP) {		return (ENXIO);	}	tp = tapcntl[unit];	ifp = &tp->tap_if;	if (tp->tap_flags & TAP_OPEN) {		return (EBUSY);	}	tp->tap_flags |= TAP_OPEN;	TAPDEBUG(__FUNCTION__": %s%d device is open\n", 						ifp->if_name, ifp->if_unit);	return (0);} /* tapopen *//*** tapclose**** Close the device - mark i/f down & delete routing info*/static inttapclose(dev, foo, bar, p)	dev_t		 dev;	int		 foo;	int		 bar;	struct proc	*p;{	register int		 unit = dev_val(minor(dev)), s;	struct tap_softc	*tp = tapcntl[unit];	struct ifnet		*ifp = &tp->arpcom.ac_if;	struct mbuf		*m;	tp->tap_flags &= ~TAP_OPEN;	/*	 * junk all pending output	 */	do {		s = splimp();		IF_DEQUEUE(&ifp->if_snd, m);		splx(s);		if (m) {			m_freem(m);		}	} while (m);	do {		s = splimp();		IF_DEQUEUE(&tp->if_rcv, m);		splx(s);		if (m) {			m_freem(m);		}	} while (m);	if (ifp->if_flags & IFF_UP) {		s = splimp();		if_down(ifp);		if (ifp->if_flags & IFF_RUNNING) {			/* find internet addresses and delete routes */			register struct ifaddr *ifa;			for (ifa = ifp->if_addrhead.tqh_first; ifa;						ifa = ifa->ifa_link.tqe_next) {				if (ifa->ifa_addr->sa_family == AF_INET) {					rtinit(ifa, (int)RTM_DELETE, 0);#if 0					rtinit(ifa, (int)RTM_DELETE,						tp->tap_flags & TAP_DSTADDR ? 								RTF_HOST : 0);#endif					/* remove address from interface */					bzero(ifa->ifa_addr, 						   sizeof(*(ifa->ifa_addr)));					bzero(ifa->ifa_dstaddr, 						   sizeof(*(ifa->ifa_dstaddr)));					bzero(ifa->ifa_netmask, 						   sizeof(*(ifa->ifa_netmask)));				}			}			ifp->if_flags &= ~IFF_RUNNING;		}		splx(s);	}	funsetown(tp->tap_sigio);	selwakeup(&tp->tap_rsel);	TAPDEBUG(__FUNCTION__": %s%d device is closed\n", 						ifp->if_name, ifp->if_unit);	return (0);} /* tapclose *//*** tapifinit**** Network interface initialization function*/static voidtapifinit(xtp)	void	*xtp;{	struct tap_softc	*tp = (struct tap_softc *)xtp;	struct ifnet		*ifp = &tp->tap_if;	TAPDEBUG(__FUNCTION__": initializing %s%d...\n", 						ifp->if_name, ifp->if_unit);	ifp->if_flags |= IFF_RUNNING;	ifp->if_flags &= ~IFF_OACTIVE;	/* attempt to start output */	tapifstart(ifp);} /* tapifinit *//*** tapifioctl**** Process an ioctl request on network interface*/inttapifioctl(ifp, cmd, data)	struct ifnet	*ifp;	u_long		 cmd;	caddr_t		 data;{	int	s, error;	s = splimp();	switch (cmd) {		case SIOCSIFADDR:		case SIOCGIFADDR:		case SIOCSIFMTU:			error = ether_ioctl(ifp, cmd, data);		break;		case SIOCSIFFLAGS:			if (ifp->if_flags & IFF_UP) {				if ((ifp->if_flags & IFF_RUNNING) == 0) {					tapifinit(ifp->if_softc);				}			}			else {				if (ifp->if_flags & IFF_RUNNING) {					ifp->if_flags &= ~IFF_RUNNING;				}			}			error = 0;		break;		case SIOCADDMULTI:		case SIOCDELMULTI:			error = 0;		break;		default:

⌨️ 快捷键说明

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