void ip_natout(ip, hlen, fin) ip_t *ip; int hlen; fr_info_t *fin;
ip_natout(ip, hlen, fin) ip_t *ip; int hlen; fr_info_t *fin;
void ip_natout(ip, hlen, fin)ip_t *ip;int hlen;fr_info_t *fin;{	register ipnat_t *np;	register u_long ipa;	register u_long sum1;	tcphdr_t *tcp;	nat_t *nat;	u_short nflags = 0, sport = 0;	struct ifnet *ifp = fin->fin_ifp;	if (!(ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT)) {		if (ip->ip_p == IPPROTO_TCP)			nflags = IPN_TCP;		else if (ip->ip_p == IPPROTO_UDP)			nflags = IPN_UDP;	}	if (nflags) {		tcp = (tcphdr_t *)fin->fin_dp;		sport = tcp->th_sport;	}	ipa = ip->ip_src.s_addr;	MUTEX_ENTER(&ipf_nat);	for (np = nat_list; np; np = np->in_next)		if ((np->in_ifp == ifp) && np->in_space &&		    (!np->in_flags || (np->in_flags & nflags)) &&		    ((ipa & np->in_inmsk) == np->in_inip) &&		    (np->in_redir == NAT_MAP ||		     np->in_pnext == sport)) {			/*			 * If there is no current entry in the nat table for			 * this IP#, create one for it.			 */			if (!(nat = nat_lookupinip(ip->ip_src, sport))) {				if (np->in_redir == NAT_REDIRECT)					continue;				/*				 * if it's a redirection, then we don't want				 * to create new outgoing port stuff.				 * Redirections are only for incoming				 * connections.				 */				if (!(nat = nat_new(np, ip, hlen,						    nflags & np->in_flags,						    NAT_OUTBOUND)))					break;			} else				ip->ip_src = nat->nat_outip;			nat->nat_age = 1200;	/* 5 mins */			/*			 * Fix up checksums, not by recalculating them, but			 * simply computing adjustments.			 */			if (nflags && !(ip->ip_off & 0x1fff) &&			    !(fin->fin_fi.fi_fl & FI_SHORT)) {				u_short *sp;				u_short sumshort;				if (nat->nat_outport)					tcp->th_sport = nat->nat_outport;				if (ip->ip_p == IPPROTO_TCP) {					sp = &tcp->th_sum;					sum1 = (~ntohs(*sp)) & 0xffff;					sum1 += nat->nat_sumd;					sum1 = (sum1 >> 16) + (sum1 & 0xffff);					/* Again */					sum1 = (sum1 >> 16) + (sum1 & 0xffff);					sumshort = ~(u_short)sum1;					*sp = htons(sumshort);				} else if (ip->ip_p == IPPROTO_UDP) {					udphdr_t *udp = (udphdr_t *)tcp;					sp = &udp->uh_sum;					if (udp->uh_sum) {						sum1 = (~ntohs(*sp)) & 0xffff;						sum1 += nat->nat_sumd;						sum1 = (sum1 >> 16) +						       (sum1 & 0xffff);						/* Again */						sum1 = (sum1 >> 16) +						       (sum1 & 0xffff);						sumshort = ~(u_short)sum1;						*sp = htons(sumshort);					}				}			}			nat_stats.ns_mapped[1]++;			MUTEX_EXIT(&ipf_nat);			return;		}	MUTEX_EXIT(&ipf_nat);	return;}