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

📄 ip_input.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
			case IPOPT_TS_TSONLY:				break;			case IPOPT_TS_TSANDADDR:				if (ipt->ipt_ptr + sizeof(n_time) +				    sizeof(struct in_addr) > ipt->ipt_len)					goto bad;				ia = ifptoia(ifp);				bcopy((caddr_t)&IA_SIN(ia)->sin_addr,				    (caddr_t)sin, sizeof(struct in_addr));				ipt->ipt_ptr += sizeof(struct in_addr);				break;			case IPOPT_TS_PRESPEC:				if (ipt->ipt_ptr + sizeof(n_time) +				    sizeof(struct in_addr) > ipt->ipt_len)					goto bad;				bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,				    sizeof(struct in_addr));				if (ifa_ifwithaddr((struct sockaddr *)&ipaddr) == 0)					continue;				ipt->ipt_ptr += sizeof(struct in_addr);				break;			default:				goto bad;			}			ntime = iptime();			bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,			    sizeof(n_time));			ipt->ipt_ptr += sizeof(n_time);		}	}	return (0);bad:	ip->ip_len -= sizeof(struct ip);  /* deduct header added by ipintr() */	icmp_error(ip, type, code, ifp, NULL);	/* fallthrough */bad2:	IPSTAT(ips_badoptions++); /* track number of bad options */	return (1);}/* * Given address of next destination (final or next hop), * return internet address info of interface to be used to get there. */struct in_ifaddr *ip_rtaddr(dst)	 struct in_addr dst;{	register struct sockaddr_in *sin;	register struct in_ifaddr *ia;	RTLOCK();	sin = (struct sockaddr_in *) &ipforward_rt.ro_dst;	if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {		if (ipforward_rt.ro_rt) {			rtfree(ipforward_rt.ro_rt);			ipforward_rt.ro_rt = 0;		}		sin->sin_family = AF_INET;		sin->sin_addr = dst;		rtalloc(&ipforward_rt);	}	if (ipforward_rt.ro_rt == 0){		RTUNLOCK();		return ((struct in_ifaddr *)0);	}	/*	 * Find address associated with outgoing interface.	 */	for (ia = in_ifaddr; ia; ia = ia->ia_next)		if (ia->ia_ifp == ipforward_rt.ro_rt->rt_ifp)			break;	RTUNLOCK();	return (ia);}/* * Save incoming source route for use in replies, * to be picked up later by ip_srcroute if the receiver is interested. */save_rte(option, dst)	u_char *option;	struct in_addr dst;{	unsigned olen;	extern ipprintfs;	olen = option[IPOPT_OLEN];	if (olen > sizeof(ip_srcrt) - 1) {		if (ipprintfs)			printf("save_rte: olen %d\n", olen);		return;	}	bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);	ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);	ip_srcrt.route[ip_nhops++] = dst;}/* * Retrieve incoming source route for use in replies, * in the same form used by setsockopt. * The first hop is placed before the options, will be removed later. */struct mbuf *ip_srcroute(){	register struct in_addr *p, *q;	register struct mbuf *m;	if (ip_nhops == 0)		return ((struct mbuf *)0);	m = m_get(M_DONTWAIT, MT_SOOPTS);	if (m == 0)		return ((struct mbuf *)0);	m->m_len = ip_nhops * sizeof(struct in_addr) + IPOPT_OFFSET + 1 + 1;	/*	 * First save first hop for return route	 */	p = &ip_srcrt.route[ip_nhops - 1];	*(mtod(m, struct in_addr *)) = *p--;	/*	 * Copy option fields and padding (nop) to mbuf.	 */	ip_srcrt.nop = IPOPT_NOP;	bcopy((caddr_t)&ip_srcrt, mtod(m, caddr_t) + sizeof(struct in_addr),	    IPOPT_OFFSET + 1 + 1);	q = (struct in_addr *)(mtod(m, caddr_t) +	    sizeof(struct in_addr) + IPOPT_OFFSET + 1 + 1);	/*	 * Record return path as an IP source route,	 * reversing the path (pointers are now aligned).	 */	while (p >= ip_srcrt.route)		*q++ = *p--;	return (m);}/* * Strip out IP options, at higher * level protocol in the kernel. * Second argument is buffer to which options * will be moved, and return value is their length. */ip_stripoptions(ip, mopt)	struct ip *ip;	struct mbuf *mopt;{	register int i;	register struct mbuf *m;	register caddr_t opts;	int olen, optsoff = 0;	olen = (ip->ip_hl<<2) - sizeof (struct ip);	m = dtom(ip);	opts = (caddr_t)(ip + 1);	if (mopt) {		/*		 * If m_len is 0, we're dealing with an option set which		 * ip_srcroute found no source routing in.  So, we've got an		 * empty mbuf, into the * beginning of which we have to coerce		 * a "first hop" address.  In a packet with no source routing,		 * this would be the destination * address.  Otherwise, m_len		 * is real, and we're just appending to the mbuf coming out		 * of ip_srcroute.		 */		if (!mopt->m_len) {			mopt->m_len = sizeof(struct in_addr);			bcopy(&ip->ip_dst, mtod(mopt, caddr_t), mopt->m_len);		}		/*		 * Push the rest of the options in.  We don't have to worry		 * about the other IP level options like we do the source		 * routing, so just search for them and insert them into the		 * mbuf.  Notice that anything dealing with source routing is		 * ignored, since you would want to do that in ip_srcroute		 * instead.		 */		while (optsoff + 1 <= olen) {			switch(opts[optsoff]) {			case IPOPT_LSRR:			case IPOPT_SSRR:				optsoff += opts[optsoff + IPOPT_OLEN];				break;			case IPOPT_EOL:			case IPOPT_NOP:				mopt->m_dat[mopt->m_len++] = opts[optsoff++];				break;			default:				bcopy(&opts[optsoff],&mopt->m_dat[mopt->m_len],					opts[optsoff + IPOPT_OLEN]);				mopt->m_len += opts[optsoff + IPOPT_OLEN];				optsoff += opts[optsoff + IPOPT_OLEN];				break;			}		}		mopt->m_off = MMINOFF;	}  	i = m->m_len - (sizeof (struct ip) + olen);	bcopy(opts  + olen, opts, (unsigned)i);	m->m_len -= olen;	ip->ip_hl = sizeof(struct ip) >> 2;}u_char inetctlerrmap[PRC_NCMDS] = {	0,		0,		0,		0,	0,		0,		EHOSTDOWN,	EHOSTUNREACH,	ENETUNREACH,	EHOSTUNREACH,	ECONNREFUSED,	ECONNREFUSED,	EMSGSIZE,	EHOSTUNREACH,	0,		0,	0,		0,		0,		0,	ENOPROTOOPT};#ifndef IPFORWARDING#define IPFORWARDING	1#endif#ifndef IPSENDREDIRECTS#define IPSENDREDIRECTS 1#endifint	ipprintfs = 0;int	ipforwarding = IPFORWARDING;extern int in_interfaces;int ipsendredirects = IPSENDREDIRECTS;int ipgateway = 0;/* * Forward a packet.  If some error occurs return the sender * an icmp packet.  Note we can't always generate a meaningful * icmp message because icmp doesn't have a large enough repertoire * of codes and types. * * If not forwarding (possibly because we have only a single external * network), just drop the packet.  This could be confusing if ipforwarding * was zero but some routing protocol was advancing us as a gateway * to somewhere.  However, we must let the routing protocol deal with that. *//* * SMP: No smp locks held coming in. * No lock held for call to ip_output. 5.27.87.us */ip_forward(ip, ifp)	register struct ip *ip;	struct ifnet *ifp;{	register int error, type = 0, code;	register struct sockaddr_in *sin;	struct mbuf *mcopy;	struct in_addr dest;	dest.s_addr = 0;	if (ipprintfs)		printf("forward: src %x dst %x ttl %x\n", ip->ip_src,			ip->ip_dst, ip->ip_ttl);	ip->ip_id = htons(ip->ip_id);	if (ipforwarding == 0 || in_interfaces <= 1) {		IPSTAT(ips_cantforward++);		if (ipgateway) {			/* can't tell difference between net and host */			type = ICMP_UNREACH, code = ICMP_UNREACH_NET;			goto sendicmp;		} else {			m_freem(dtom(ip));			return;		}		}	if (in_canforward(ip->ip_dst) == 0) {		m_freem(dtom(ip));		return;	}	if (ip->ip_ttl <= IPTTLDEC) {		type = ICMP_TIMXCEED, code = ICMP_TIMXCEED_INTRANS;		goto sendicmp;	}	ip->ip_ttl -= IPTTLDEC;	/*	 * Save at most 64 bytes of the packet in case	 * we need to generate an ICMP message to the src.	 */	mcopy = m_copy(dtom(ip), 0, imin((int)ip->ip_len, 64));	RTLOCK();	sin = (struct sockaddr_in *)&ipforward_rt.ro_dst;	if (ipforward_rt.ro_rt == 0 ||	    ip->ip_dst.s_addr != sin->sin_addr.s_addr) {		if (ipforward_rt.ro_rt) {			rtfree(ipforward_rt.ro_rt);			ipforward_rt.ro_rt = 0;		}		sin->sin_family = AF_INET;		sin->sin_addr = ip->ip_dst;		rtalloc(&ipforward_rt);	}	/*	 * If forwarding packet using same interface that it came in on,	 * perhaps should send a redirect to sender to shortcut a hop.	 * Only send redirect if source is sending directly to us,	 * and if packet was not source routed (or has any options).	 * Also, don't send redirect if forwarding using a default route	 * or a route modfied by a redirect.	 */#define	satosin(sa)	((struct sockaddr_in *)(sa))	if (ipforward_rt.ro_rt && ipforward_rt.ro_rt->rt_ifp == ifp &&	    (ipforward_rt.ro_rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&	    satosin(&ipforward_rt.ro_rt->rt_dst)->sin_addr.s_addr != 0 &&	    ipsendredirects && ip->ip_hl == (sizeof(struct ip) >> 2)) {		struct in_ifaddr *ia;		u_long src = ntohl(ip->ip_src.s_addr);		u_long dst = ntohl(ip->ip_dst.s_addr);		if ((ia = ifptoia(ifp)) &&		   (src & ia->ia_subnetmask) == ia->ia_subnet) {		    if (ipforward_rt.ro_rt->rt_flags & RTF_GATEWAY)			dest = satosin(&ipforward_rt.ro_rt->rt_gateway)->sin_addr;		    else			dest = ip->ip_dst;		    /*		     * If the destination is reached by a route to host,		     * is on a subnet of a local net, or is directly		     * on the attached net (!), use host redirect.		     * (We may be the correct first hop for other subnets.)		     */		    type = ICMP_REDIRECT;		    code = ICMP_REDIRECT_NET;		    if ((ipforward_rt.ro_rt->rt_flags & RTF_HOST) ||		       (ipforward_rt.ro_rt->rt_flags & RTF_GATEWAY) == 0)			code = ICMP_REDIRECT_HOST;		    else{ 		    for (ia = in_ifaddr; ia = ia->ia_next; )			if ((dst & ia->ia_netmask) == ia->ia_net) {			    if (ia->ia_subnetmask != ia->ia_netmask)				    code = ICMP_REDIRECT_HOST;			    break;			}		    }		    if (ipprintfs)		        printf("redirect (%d) to %x\n", code, dest);		}	}	RTUNLOCK();	/* SMP: call ip_output with no smp lock.  4.21.87.us */	error = ip_output(dtom(ip), (struct mbuf *)0, &ipforward_rt,		IP_FORWARDING, NULL);	if (error) { 		IPSTAT(ips_cantforward++);	} else if (type) {		IPSTAT(ips_redirectsent++);	} else {		if (mcopy)			m_freem(mcopy);		IPSTAT(ips_forward++);		return;	}	if (mcopy == NULL)		return;	ip = mtod(mcopy, struct ip *);	type = ICMP_UNREACH;	switch (error) {	case 0:				/* forwarded, but need redirect */		type = ICMP_REDIRECT;		/* code set above */		break;	case ENETUNREACH:	case ENETDOWN:		if (in_localaddr(ip->ip_dst))			code = ICMP_UNREACH_HOST;		else		code = ICMP_UNREACH_NET;		break;	case EMSGSIZE:		code = ICMP_UNREACH_NEEDFRAG;		break;	case EPERM:		code = ICMP_UNREACH_PORT;		break;	case ENOBUFS:		type = ICMP_SOURCEQUENCH;		break;	case EHOSTDOWN:	case EHOSTUNREACH:		code = ICMP_UNREACH_HOST;		break;	}sendicmp:	icmp_error(ip, type, code, ifp, dest);}

⌨️ 快捷键说明

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