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

📄 if_tap.c

📁 实现vpn网关用来建立 IP虚拟隧道
💻 C
📖 第 1 页 / 共 2 页
字号:
			error = EINVAL;		break;	}	splx(s);	return (error);} /* tapifioctl *//*** tapifstart ** ** Queue packets from higher level ready to put out.*/static voidtapifstart(ifp)	struct ifnet	*ifp;{	struct tap_softc	*tp = tapcntl[ifp->if_unit];	struct mbuf		*m0;	int			 s;	TAPDEBUG(__FUNCTION__": %s%d starting...\n", 						ifp->if_name, ifp->if_unit);	if ((tp->tap_flags & TAP_READY) != TAP_READY) {		TAPDEBUG(__FUNCTION__": %s%d not ready. tap_flags = 0x%x\n", 				ifp->if_name, ifp->if_unit, tp->tap_flags);		return;	}	s = splimp();	ifp->if_flags |= IFF_OACTIVE;	for (;;) {		IF_DEQUEUE(&ifp->if_snd, m0);		if (!m0) {			break;		}#if NBPFILTER > 0		if (ifp->if_bpf) {			bpf_mtap(ifp, m0);		}#endif /* NBPFILTER */		if (IF_QFULL(&tp->if_rcv)) {			IF_DROP(&tp->if_rcv); /* XXX: stat */			TAPDEBUG(__FUNCTION__": %s%d if_rcv queue is full. " \				"Dropping packet.\n", 				ifp->if_name, ifp->if_unit);			splx(s);			m_freem(m0);			return;		}		IF_ENQUEUE(&tp->if_rcv, m0);	}	if (tp->tap_flags & TAP_RWAIT) {		tp->tap_flags &= ~TAP_RWAIT;		wakeup((caddr_t)tp);	}	if (tp->tap_flags & TAP_ASYNC && tp->tap_sigio) {		pgsigio(tp->tap_sigio, SIGIO, 0);	}	selwakeup(&tp->tap_rsel);	ifp->if_flags &= ~IFF_OACTIVE;	splx(s);} /* tapifstart *//*** tapioctl**** the cdevsw interface is now pretty minimal.*/static inttapioctl(dev, cmd, data, flag, p)	dev_t		 dev;	u_long		 cmd;	caddr_t		 data;	int		 flag;	struct proc	*p;{	int			 unit = dev_val(minor(dev)), s;	struct tap_softc	*tp = tapcntl[unit];	struct ifnet		*ifp = &tp->tap_if; 	struct tapinfo		*tapp;	switch (cmd) { 		case TAPSIFINFO: 		        tapp = (struct tapinfo *)data; 			ifp->if_mtu = tapp->mtu; 			ifp->if_type = tapp->type; 			ifp->if_baudrate = tapp->baudrate; 		break;	 	case TAPGIFINFO: 			tapp = (struct tapinfo *)data; 			tapp->mtu = ifp->if_mtu; 			tapp->type = ifp->if_type; 			tapp->baudrate = ifp->if_baudrate; 		break;		case TAPSDEBUG:			tapdebug = *(int *)data;		break;		case TAPGDEBUG:			*(int *)data = tapdebug;		break;		case FIONBIO:		break;		case FIOASYNC:			if (*(int *)data) {				tp->tap_flags |= TAP_ASYNC;			}			else {				tp->tap_flags &= ~TAP_ASYNC;			}		break;		case FIONREAD:			s = splimp();			if (tp->if_rcv.ifq_head) {				struct mbuf *mb = tp->if_rcv.ifq_head;				for(*(int *)data = 0; mb != 0; mb = mb->m_next) 					*(int *)data += mb->m_len;			} 			else {				*(int *)data = 0;			}			splx(s);		break;		case FIOSETOWN:			return (fsetown(*(int *)data, &tp->tap_sigio));		case FIOGETOWN:			*(int *)data = fgetown(tp->tap_sigio);			return (0);		/* This is deprecated, FIOSETOWN should be used instead. */		case TIOCSPGRP:			return (fsetown(-(*(int *)data), &tp->tap_sigio));		/* This is deprecated, FIOGETOWN should be used instead. */		case TIOCGPGRP:			*(int *)data = -fgetown(tp->tap_sigio);			return (0);		default:			return (ENOTTY);	}	return (0);} /* tapioctl *//*** tapread**** The cdevsw read interface - reads a packet at a time, or at** least as much of a packet as can be read.*/static inttapread(dev, uio, flag)	dev_t dev;	struct uio *uio;	int flag;{	int			 unit = dev_val(minor(dev));	struct tap_softc	*tp = tapcntl[unit];	struct ifnet		*ifp = &tp->tap_if;	struct mbuf		*m, *m0;	int			 error = 0, len, s;	TAPDEBUG(__FUNCTION__": %s%d reading...\n", ifp->if_name, ifp->if_unit);	if ((tp->tap_flags & TAP_READY) != TAP_READY) {		TAPDEBUG(__FUNCTION__": %s%d not ready. tap_flags = 0x%x\n", 				ifp->if_name, ifp->if_unit, tp->tap_flags);		return (EHOSTDOWN);	}	tp->tap_flags &= ~TAP_RWAIT;	/* sleep until we get a packet */	s = splimp();	do {		IF_DEQUEUE(&tp->if_rcv, m0);		if (m0 == 0) {			if (flag & IO_NDELAY) {				splx(s);				return (EWOULDBLOCK);			}			tp->tap_flags |= TAP_RWAIT;			if (error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1),					"taprd", 0)) {				splx(s);				return (error);			}		}	} while (m0 == 0);	splx(s);	/* xfer packet to user space */	while (m0 && uio->uio_resid > 0 && error == 0) {		len = min(uio->uio_resid, m0->m_len);		if (len == 0) {			break;		}		error = uiomove(mtod(m0, caddr_t), len, uio);		MFREE(m0, m);		m0 = m;	}	if (m0) {		TAPDEBUG(__FUNCTION__": %s%d Dropping mbuf\n", 						ifp->if_name, ifp->if_unit);		m_freem(m0);	}	return (error);} /* tapread *//*** tapwrite**** the cdevsw write interface - an atomic write is a packet - or else!*/static inttapwrite(dev, uio, flag)	dev_t		 dev;	struct uio	*uio;	int		 flag;{	int			 unit = dev_val(minor(dev));	struct ifnet		*ifp = &tapcntl[unit]->tap_if;	struct mbuf		*top, **mp, *m;	int		 	 error = 0, tlen, mlen;	struct ether_header	*eh;	TAPDEBUG(__FUNCTION__": %s%d writting..\n", ifp->if_name, ifp->if_unit);	if (uio->uio_resid == 0) {		return (0); /* do nothing */	}	if (uio->uio_resid < 0 || uio->uio_resid > TAPMRU) {		TAPDEBUG(__FUNCTION__": %s%d len = %d!\n", 				ifp->if_name, ifp->if_unit, uio->uio_resid);		return (EIO);	}	tlen = uio->uio_resid;	/* get a header mbuf */	MGETHDR(m, M_DONTWAIT, MT_DATA);	if (m == NULL) {		return (ENOBUFS);	}	mlen = MHLEN;	top = 0;	mp = &top;	while (error == 0 && uio->uio_resid > 0) {		m->m_len = min(mlen, uio->uio_resid);		error = uiomove(mtod(m, caddr_t), m->m_len, uio);		*mp = m;		mp = &m->m_next;		if (uio->uio_resid > 0) {			MGET(m, M_DONTWAIT, MT_DATA);			if (m == 0) {				error = ENOBUFS;				break;			}			mlen = MLEN;		}	}	if (error) {		if (top) {			m_freem(top);		}		return (error);	}	top->m_pkthdr.len = tlen;	top->m_pkthdr.rcvif = ifp;	eh = mtod(top, struct ether_header *);#if NBPFILTER > 0	if (ifp->if_bpf) {		bpf_mtap(ifp, top);	}#endif /* NBPFILTER */#ifdef BRIDGE	/* Ethernet bridge */	if (do_bridge) {		struct ifnet	*bdg_ifp;		bdg_ifp = bridge_in(top);		if (BDG_DROP == bdg_ifp) { /* drop it */			m_freem(top);			top = 0;			return (0);		}		if (BDG_LOCAL != bdg_ifp) { /* forward it */			bdg_forward(&top, bdg_ifp);		}		if (BDG_LOCAL == bdg_ifp ||		    BDG_BCAST == bdg_ifp || BDG_MCAST == bdg_ifp) {			goto getit;		}		/* drop it */		if (top) {			m_freem(top);			top = 0;		}		return (0);	}getit:#endif /* BRIDGE */	/* adjust mbuf and give packet to the ether_input */	m_adj(top, sizeof(struct ether_header));	ether_input(ifp, eh, top);	return (0);} /* tapwrite *//*** tappoll**** The poll interface, this is only useful on reads** really. The write detect always returns true, write never blocks** anyway, it either accepts the packet or drops it.*/static inttappoll(dev, events, p)	dev_t		 dev;	int		 events;	struct proc	*p;{	int			 unit = dev_val(minor(dev)), s;	struct tap_softc	*tp = tapcntl[unit];	struct ifnet		*ifp = &tp->arpcom.ac_if;	int		 	 revents = 0;	s = splimp();	TAPDEBUG(__FUNCTION__": %s%d polling...\n", ifp->if_name, ifp->if_unit);	if (events & (POLLIN | POLLRDNORM)) {		if (tp->if_rcv.ifq_len > 0) {			TAPDEBUG(__FUNCTION__": %s%d have data! q = %d\n",				ifp->if_name, ifp->if_unit, tp->if_rcv.ifq_len);			revents |= (events & (POLLIN | POLLRDNORM));		} 		else {			TAPDEBUG(__FUNCTION__": %s%d waiting for data\n",				ifp->if_name, ifp->if_unit);			selrecord(p, &tp->tap_rsel);		}	}	if (events & (POLLOUT | POLLWRNORM)) {		revents |= (events & (POLLOUT | POLLWRNORM));	}	splx(s);	return (revents);} /* tappoll */

⌨️ 快捷键说明

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