HTONS(ip->ip_off); HTONS(ip->ip_len);
ip_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) {		HTONS(ip->ip_off);		HTONS(ip->ip_len);		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) {			HTONS(ip->ip_off);			HTONS(ip->ip_len);			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;	}	ip = mtod(mcopy, struct ip *);	HTONS(ip->ip_off);	HTONS(ip->ip_len);	icmp_error(mcopy, type, code, dest, destifp);}