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

📄 ns_ip.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1984, 1985, 1986, 1987, 1993 *	The Regents of the University of California.  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. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * *	@(#)ns_ip.c	8.1 (Berkeley) 6/10/93 *//* * Software interface driver for encapsulating ns in ip. */#ifdef NSIP#include <sys/param.h>#include <sys/systm.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/errno.h>#include <sys/ioctl.h>#include <sys/protosw.h>#include <net/if.h>#include <net/netisr.h>#include <net/route.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#include <netinet/ip_var.h>#include <machine/mtpr.h>#include <netns/ns.h>#include <netns/ns_if.h>#include <netns/idp.h>struct ifnet_en {	struct ifnet ifen_ifnet;	struct route ifen_route;	struct in_addr ifen_src;	struct in_addr ifen_dst;	struct ifnet_en *ifen_next;};int	nsipoutput(), nsipioctl(), nsipstart();#define LOMTU	(1024+512);struct ifnet nsipif;struct ifnet_en *nsip_list;		/* list of all hosts and gateways or					broadcast addrs */struct ifnet_en *nsipattach(){	register struct ifnet_en *m;	register struct ifnet *ifp;	if (nsipif.if_mtu == 0) {		ifp = &nsipif;		ifp->if_name = "nsip";		ifp->if_mtu = LOMTU;		ifp->if_ioctl = nsipioctl;		ifp->if_output = nsipoutput;		ifp->if_start = nsipstart;		ifp->if_flags = IFF_POINTOPOINT;	}	MALLOC((m), struct ifnet_en *, sizeof(*m), M_PCB, M_NOWAIT);	if (m == NULL) return (NULL);	m->ifen_next = nsip_list;	nsip_list = m;	ifp = &m->ifen_ifnet;	ifp->if_name = "nsip";	ifp->if_mtu = LOMTU;	ifp->if_ioctl = nsipioctl;	ifp->if_output = nsipoutput;	ifp->if_start = nsipstart;	ifp->if_flags = IFF_POINTOPOINT;	ifp->if_unit = nsipif.if_unit++;	if_attach(ifp);	return (m);}/* * Process an ioctl request. *//* ARGSUSED */nsipioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	int error = 0;	struct ifreq *ifr;	switch (cmd) {	case SIOCSIFADDR:		ifp->if_flags |= IFF_UP;		/* fall into: */	case SIOCSIFDSTADDR:		/*		 * Everything else is done at a higher level.		 */		break;	case SIOCSIFFLAGS:		ifr = (struct ifreq *)data;		if ((ifr->ifr_flags & IFF_UP) == 0)			error = nsip_free(ifp);	default:		error = EINVAL;	}	return (error);}struct mbuf *nsip_badlen;struct mbuf *nsip_lastin;int nsip_hold_input;idpip_input(m, ifp)	register struct mbuf *m;	struct ifnet *ifp;{	register struct ip *ip;	register struct idp *idp;	register struct ifqueue *ifq = &nsintrq;	int len, s;	if (nsip_hold_input) {		if (nsip_lastin) {			m_freem(nsip_lastin);		}		nsip_lastin = m_copym(m, 0, (int)M_COPYALL, M_DONTWAIT);	}	/*	 * Get IP and IDP header together in first mbuf.	 */	nsipif.if_ipackets++;	s = sizeof (struct ip) + sizeof (struct idp);	if (((m->m_flags & M_EXT) || m->m_len < s) &&	    (m = m_pullup(m, s)) == 0) {		nsipif.if_ierrors++;		return;	}	ip = mtod(m, struct ip *);	if (ip->ip_hl > (sizeof (struct ip) >> 2)) {		ip_stripoptions(m, (struct mbuf *)0);		if (m->m_len < s) {			if ((m = m_pullup(m, s)) == 0) {				nsipif.if_ierrors++;				return;			}			ip = mtod(m, struct ip *);		}	}	/*	 * Make mbuf data length reflect IDP length.	 * If not enough data to reflect IDP length, drop.	 */	m->m_data += sizeof (struct ip);	m->m_len -= sizeof (struct ip);	m->m_pkthdr.len -= sizeof (struct ip);	idp = mtod(m, struct idp *);	len = ntohs(idp->idp_len);	if (len & 1) len++;		/* Preserve Garbage Byte */	if (ip->ip_len != len) {		if (len > ip->ip_len) {			nsipif.if_ierrors++;			if (nsip_badlen) m_freem(nsip_badlen);			nsip_badlen = m;			return;		}		/* Any extra will be trimmed off by the NS routines */	}	/*	 * Place interface pointer before the data	 * for the receiving protocol.	 */	m->m_pkthdr.rcvif = ifp;	/*	 * Deliver to NS	 */	s = splimp();	if (IF_QFULL(ifq)) {		IF_DROP(ifq);bad:		m_freem(m);		splx(s);		return;	}	IF_ENQUEUE(ifq, m);	schednetisr(NETISR_NS);	splx(s);	return;}/* ARGSUSED */nsipoutput(ifn, m, dst)	struct ifnet_en *ifn;	register struct mbuf *m;	struct sockaddr *dst;{	register struct ip *ip;	register struct route *ro = &(ifn->ifen_route);	register int len = 0;	register struct idp *idp = mtod(m, struct idp *);	int error;	ifn->ifen_ifnet.if_opackets++;	nsipif.if_opackets++;	/*	 * Calculate data length and make space	 * for IP header.	 */	len =  ntohs(idp->idp_len);	if (len & 1) len++;		/* Preserve Garbage Byte */	/* following clause not necessary on vax */	if (3 & (int)m->m_data) {		/* force longword alignment of ip hdr */		struct mbuf *m0 = m_gethdr(MT_HEADER, M_DONTWAIT);		if (m0 == 0) {			m_freem(m);			return (ENOBUFS);		}		MH_ALIGN(m0, sizeof (struct ip));		m0->m_flags = m->m_flags & M_COPYFLAGS;		m0->m_next = m;		m0->m_len = sizeof (struct ip);		m0->m_pkthdr.len = m0->m_len + m->m_len;		m->m_flags &= ~M_PKTHDR;	} else {		M_PREPEND(m, sizeof (struct ip), M_DONTWAIT);		if (m == 0)			return (ENOBUFS);	}	/*	 * Fill in IP header.	 */	ip = mtod(m, struct ip *);	*(long *)ip = 0;	ip->ip_p = IPPROTO_IDP;	ip->ip_src = ifn->ifen_src;	ip->ip_dst = ifn->ifen_dst;	ip->ip_len = (u_short)len + sizeof (struct ip);	ip->ip_ttl = MAXTTL;	/*	 * Output final datagram.	 */	error =  (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST, NULL));	if (error) {		ifn->ifen_ifnet.if_oerrors++;		ifn->ifen_ifnet.if_ierrors = error;	}	return (error);bad:	m_freem(m);	return (ENETUNREACH);}nsipstart(ifp)struct ifnet *ifp;{	panic("nsip_start called\n");}struct ifreq ifr = {"nsip0"};nsip_route(m)	register struct mbuf *m;{	register struct nsip_req *rq = mtod(m, struct nsip_req *);	struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns;	struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip;	struct route ro;	struct ifnet_en *ifn;	struct sockaddr_in *src;	/*	 * First, make sure we already have an ns address:	 */	if (ns_hosteqnh(ns_thishost, ns_zerohost))		return (EADDRNOTAVAIL);	/*	 * Now, determine if we can get to the destination	 */	bzero((caddr_t)&ro, sizeof (ro));	ro.ro_dst = *(struct sockaddr *)ip_dst;	rtalloc(&ro);	if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) {		return (ENETUNREACH);	}	/*	 * And see how he's going to get back to us:	 * i.e., what return ip address do we use?	 */	{		register struct in_ifaddr *ia;		struct ifnet *ifp = ro.ro_rt->rt_ifp;		for (ia = in_ifaddr; ia; ia = ia->ia_next)			if (ia->ia_ifp == ifp)				break;		if (ia == 0)			ia = in_ifaddr;		if (ia == 0) {			RTFREE(ro.ro_rt);			return (EADDRNOTAVAIL);		}		src = (struct sockaddr_in *)&ia->ia_addr;	}	/*	 * Is there a free (pseudo-)interface or space?	 */	for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {		if ((ifn->ifen_ifnet.if_flags & IFF_UP) == 0)			break;	}	if (ifn == NULL)		ifn = nsipattach();	if (ifn == NULL) {		RTFREE(ro.ro_rt);		return (ENOBUFS);	}	ifn->ifen_route = ro;	ifn->ifen_dst =  ip_dst->sin_addr;	ifn->ifen_src = src->sin_addr;	/*	 * now configure this as a point to point link	 */	ifr.ifr_name[4] = '0' + nsipif.if_unit - 1;	ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst;	(void)ns_control((struct socket *)0, (int)SIOCSIFDSTADDR, (caddr_t)&ifr,			(struct ifnet *)ifn);	satons_addr(ifr.ifr_addr).x_host = ns_thishost;	return (ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr,			(struct ifnet *)ifn));}nsip_free(ifp)struct ifnet *ifp;{	register struct ifnet_en *ifn = (struct ifnet_en *)ifp;	struct route *ro = & ifn->ifen_route;	if (ro->ro_rt) {		RTFREE(ro->ro_rt);		ro->ro_rt = 0;	}	ifp->if_flags &= ~IFF_UP;	return (0);}nsip_ctlinput(cmd, sa)	int cmd;	struct sockaddr *sa;{	extern u_char inetctlerrmap[];	struct sockaddr_in *sin;	int in_rtchange();	if ((unsigned)cmd >= PRC_NCMDS)		return;	if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)		return;	sin = (struct sockaddr_in *)sa;	if (sin->sin_addr.s_addr == INADDR_ANY)		return;	switch (cmd) {	case PRC_ROUTEDEAD:	case PRC_REDIRECT_NET:	case PRC_REDIRECT_HOST:	case PRC_REDIRECT_TOSNET:	case PRC_REDIRECT_TOSHOST:		nsip_rtchange(&sin->sin_addr);		break;	}}nsip_rtchange(dst)	register struct in_addr *dst;{	register struct ifnet_en *ifn;	for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {		if (ifn->ifen_dst.s_addr == dst->s_addr &&			ifn->ifen_route.ro_rt) {				RTFREE(ifn->ifen_route.ro_rt);				ifn->ifen_route.ro_rt = 0;		}	}}#endif

⌨️ 快捷键说明

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