📄 if_tap.c
字号:
/* * 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 + -