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

📄 ip_input.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 3 页
字号:
		case IPOPT_TS:			code = cp - (u_char *)ip;			ipt = (struct ip_timestamp *)cp;			if (ipt->ipt_ptr < 5 || ipt->ipt_len < 5)				goto bad;			if (ipt->ipt_ptr - 1 + sizeof(n_time) > ipt->ipt_len) {				if (++ipt->ipt_oflw == 0)					goto bad;				break;			}			sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);			switch (ipt->ipt_flg) {			case IPOPT_TS_TSONLY:				break;			case IPOPT_TS_TSANDADDR:				if (ipt->ipt_ptr - 1 + sizeof(n_time) +				    sizeof(struct in_addr) > ipt->ipt_len)					goto bad;				ipaddr.sin_addr = dst;				ia = (INA)ifaof_ifpforaddr((SA)&ipaddr,							    m->m_pkthdr.rcvif);				if (ia == 0)					continue;				bcopy((caddr_t)&ia->ia_addr.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 - 1 + 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((SA)&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);		}	}#ifndef PMON	if (forward && ipforwarding) {		ip_forward(m, 1);		return (1);	}#endif	return (0);bad:	ip->ip_len -= ip->ip_hl << 2;   /* XXX icmp_error adds in hdr length */	HTONS(ip->ip_len);	/* XXX because ip_input changed these three */	HTONS(ip->ip_id);	HTONS(ip->ip_off);	icmp_error(m, type, code, 0, 0);	ipstat.ips_badoptions++;	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;	sin = satosin(&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_len = sizeof(*sin);		sin->sin_addr = dst;		rtalloc(&ipforward_rt);	}	if (ipforward_rt.ro_rt == 0)		return ((struct in_ifaddr *)0);	return (ifatoia(ipforward_rt.ro_rt->rt_ifa));}/* * Save incoming source route for use in replies, * to be picked up later by ip_srcroute if the receiver is interested. */voidsave_rte(option, dst)	u_char *option;	struct in_addr dst;{	unsigned olen;	olen = option[IPOPT_OLEN];#ifdef DIAGNOSTIC	if (ipprintfs)		printf("save_rte: olen %d\n", olen);#endif	if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))		return;	bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);	ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);	ip_srcrt.dst = dst;}#ifndef PMON/* * Check whether we do proxy ARP for this address and we point to ourselves. * Code shamelessly copied from arplookup(). */static intip_weadvertise(addr)	u_int32_t addr;{	register struct rtentry *rt;	register struct ifnet *ifp;	register struct ifaddr *ifa;	struct sockaddr_inarp sin;	sin.sin_len = sizeof(sin);	sin.sin_family = AF_INET;	sin.sin_addr.s_addr = addr;	sin.sin_other = SIN_PROXY;	rt = rtalloc1(sintosa(&sin), 0);	if (rt == 0)	  return 0;		RTFREE(rt);		if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||	    rt->rt_gateway->sa_family != AF_LINK)	  return 0;	for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)		for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;		    ifa = ifa->ifa_list.tqe_next) {			if (ifa->ifa_addr->sa_family != rt->rt_gateway->sa_family)				continue;			if (!bcmp(LLADDR((struct sockaddr_dl *)ifa->ifa_addr), 			    LLADDR((struct sockaddr_dl *)rt->rt_gateway),			    ETHER_ADDR_LEN))				return 1;		}	return 0;}#endif/* * 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);#define OPTSIZ	(sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))	/* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */	m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +	    OPTSIZ;#ifdef DIAGNOSTIC	if (ipprintfs)		printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);#endif	/*	 * First save first hop for return route	 */	p = &ip_srcrt.route[ip_nhops - 1];	*(mtod(m, struct in_addr *)) = *p--;#ifdef DIAGNOSTIC	if (ipprintfs)		printf(" hops %x", ntohl(mtod(m, struct in_addr *)->s_addr));#endif	/*	 * Copy option fields and padding (nop) to mbuf.	 */	ip_srcrt.nop = IPOPT_NOP;	ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;	bcopy((caddr_t)&ip_srcrt.nop,	    mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ);	q = (struct in_addr *)(mtod(m, caddr_t) +	    sizeof(struct in_addr) + OPTSIZ);#undef OPTSIZ	/*	 * Record return path as an IP source route,	 * reversing the path (pointers are now aligned).	 */	while (p >= ip_srcrt.route) {#ifdef DIAGNOSTIC		if (ipprintfs)			printf(" %x", ntohl(q->s_addr));#endif		*q++ = *p--;	}	/*	 * Last hop goes to final destination.	 */	*q = ip_srcrt.dst;#ifdef DIAGNOSTIC	if (ipprintfs)		printf(" %x\n", ntohl(q->s_addr));#endif	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. * XXX should be deleted; last arg currently ignored. */voidip_stripoptions(m, mopt)	register struct mbuf *m;	struct mbuf *mopt;{	register int i;	struct ip *ip = mtod(m, struct ip *);	register caddr_t opts;	int olen;	olen = (ip->ip_hl<<2) - sizeof (struct ip);	opts = (caddr_t)(ip + 1);	i = m->m_len - (sizeof (struct ip) + olen);	bcopy(opts  + olen, opts, (unsigned)i);	m->m_len -= olen;	if (m->m_flags & M_PKTHDR)		m->m_pkthdr.len -= olen;	ip->ip_hl = sizeof(struct ip) >> 2;}int inetctlerrmap[PRC_NCMDS] = {	0,		0,		0,		0,	0,		EMSGSIZE,	EHOSTDOWN,	EHOSTUNREACH,	EHOSTUNREACH,	EHOSTUNREACH,	ECONNREFUSED,	ECONNREFUSED,	EMSGSIZE,	EHOSTUNREACH,	0,		0,	0,		0,		0,		0,	ENOPROTOOPT};#ifndef PMON/* * 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, 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. * * The srcrt parameter indicates whether the packet is being forwarded * via a source route. */voidip_forward(m, srcrt)	struct mbuf *m;	int srcrt;{	register struct ip *ip = mtod(m, struct ip *);	register struct sockaddr_in *sin;	register struct rtentry *rt;	int error, type = 0, code = 0;	struct mbuf *mcopy;	n_long dest;	struct ifnet *destifp;	dest = 0;#ifdef DIAGNOSTIC	if (ipprintfs)		printf("forward: src %x dst %x ttl %x\n", ip->ip_src.s_addr,		    ip->ip_dst.s_addr, ip->ip_ttl);#endif	if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {		ipstat.ips_cantforward++;		m_freem(m);		return;	}	HTONS(ip->ip_id);	if (ip->ip_ttl <= IPTTLDEC) {		icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0);		return;	}	ip->ip_ttl -= IPTTLDEC;	sin = satosin(&ipforward_rt.ro_dst);	if ((rt = 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_len = sizeof(*sin);		sin->sin_addr = ip->ip_dst;		rtalloc(&ipforward_rt);		if (ipforward_rt.ro_rt == 0) {			icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);			return;		}		rt = ipforward_rt.ro_rt;	}	/*	 * Save at most 68 bytes of the packet in case	 * we need to generate an ICMP message to the src.	 */	mcopy = m_copy(m, 0, imin((int)ip->ip_len, 68));	/*	 * 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 modified by a redirect.	 * Don't send redirect if we advertise destination's arp address	 * as ours (proxy arp).	 */	if (rt->rt_ifp == m->m_pkthdr.rcvif &&	    (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&	    satosin(rt_key(rt))->sin_addr.s_addr != 0 &&	    ipsendredirects && !srcrt &&	    !ip_weadvertise(satosin(rt_key(rt))->sin_addr.s_addr)) {		if (rt->rt_ifa &&		    (ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_subnetmask) ==		    ifatoia(rt->rt_ifa)->ia_subnet) {		    if (rt->rt_flags & RTF_GATEWAY)			dest = satosin(rt->rt_gateway)->sin_addr.s_addr;		    else			dest = ip->ip_dst.s_addr;		    /* Router requirements says to only send host redirects */		    type = ICMP_REDIRECT;		    code = ICMP_REDIRECT_HOST;#ifdef DIAGNOSTIC		    if (ipprintfs)			printf("redirect (%d) to %x\n", code, (u_int32_t)dest);#endif		}	}	error = ip_output(m, (struct mbuf *)0, &ipforward_rt,	    (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), 	    0, NULL, NULL);	if (error)		ipstat.ips_cantforward++;	else {		ipstat.ips_forward++;		if (type)			ipstat.ips_redirectsent++;		else {			if (mcopy)				m_freem(mcopy);			return;		}	}	if (mcopy == NULL)		return;	destifp = NULL;	switch (error) {	case 0:				/* forwarded, but need redirect */		/* type, code set above */		break;	case ENETUNREACH:		/* shouldn't happen, checked above */	case EHOSTUNREACH:	case ENETDOWN:	case EHOSTDOWN:	default:		type = ICMP_UNREACH;		code = ICMP_UNREACH_HOST;		break;	case EMSGSIZE:		type = ICMP_UNREACH;		code = ICMP_UNREACH_NEEDFRAG;		if (ipforward_rt.ro_rt)			destifp = ipforward_rt.ro_rt->rt_ifp;		ipstat.ips_cantfrag++;		break;	case ENOBUFS:		type = ICMP_SOURCEQUENCH;		code = 0;		break;	}	icmp_error(mcopy, type, code, dest, destifp);}#endif /* PMON */intip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)	int *name;	u_int namelen;	void *oldp;	size_t *oldlenp;	void *newp;	size_t newlen;{	/* All sysctl names at this level are terminal. */	if (namelen != 1)		return (ENOTDIR);	switch (name[0]) {#ifndef PMON	case IPCTL_FORWARDING:		return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforwarding));	case IPCTL_SENDREDIRECTS:		return (sysctl_int(oldp, oldlenp, newp, newlen,			&ipsendredirects));	case IPCTL_DEFTTL:		return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl));#ifdef notyet	case IPCTL_DEFMTU:		return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));#endif	case IPCTL_SOURCEROUTE:		/*		 * Don't allow this to change in a secure environment.		 */		if (newp && securelevel > 0)			return (EPERM);		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &ip_dosourceroute));	case IPCTL_DIRECTEDBCAST:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &ip_directedbcast));	case IPCTL_IPPORT_FIRSTAUTO:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &ipport_firstauto));	case IPCTL_IPPORT_LASTAUTO:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &ipport_lastauto));	case IPCTL_IPPORT_HIFIRSTAUTO:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &ipport_hifirstauto));	case IPCTL_IPPORT_HILASTAUTO:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &ipport_hilastauto));	case IPCTL_IPPORT_MAXQUEUE:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &ip_maxqueue));	case IPCTL_ENCDEBUG:		return (sysctl_int(oldp, oldlenp, newp, newlen, &encdebug));#endif	default:		return (EOPNOTSUPP);	}	/* NOTREACHED */}

⌨️ 快捷键说明

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