int fr_check(ip, hlen, ifp, out
fr_check(ip, hlen, ifp, out
int fr_check(ip, hlen, ifp, out#ifdef _KERNEL# if SOLARIS, qif, q, mb)qif_t *qif;queue_t *q;mblk_t *mb;# else, mp)struct mbuf **mp;# endif#else)#endifip_t *ip;int hlen;struct ifnet *ifp;int out;{	/*	 * The above really sucks, but short of writing a diff	 */	fr_info_t frinfo, *fc;	register fr_info_t *fin = &frinfo;	frentry_t *fr;	int pass;#if !defined(__SVR4) && !defined(__svr4__) && defined(_KERNEL)	register struct mbuf *m = *mp;	struct mbuf *mc = NULL;	if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||	     ip->ip_p == IPPROTO_ICMP)) {		register int up = MIN(hlen + 8, ip->ip_len);		if (up > m->m_len) {			if ((*mp = m_pullup(m, up)) == 0)				return -1;			else {				m = *mp;				ip = mtod(m, struct ip *);			}		}	}#endif#if SOLARIS	mblk_t *mc = NULL;#endif	fr_makefrip(hlen, ip, fin);	fin->fin_ifp = ifp;	fin->fin_out = out;	MUTEX_ENTER(&ipf_mutex);	if (!out) {		ip_natin(ip, hlen, fin);		if ((fin->fin_fr = ipacct[0][fr_active]) &&		    (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))			frstats[0].fr_acct++;	}	if ((pass = ipfr_knownfrag(ip, fin))) {		if ((pass & FR_KEEPSTATE)) {			if (fr_addstate(ip, hlen, pass) == -1)				frstats[out].fr_bads++;			else				frstats[out].fr_ads++;		}	} else if ((pass = fr_checkstate(ip, fin))) {		if ((pass & FR_KEEPFRAG)) {			if (fin->fin_fi.fi_fl & FI_FRAG) {				if (ipfr_newfrag(ip, fin, pass) == -1)					frstats[out].fr_bnfr++;				else					frstats[out].fr_nfr++;			} else				frstats[out].fr_cfr++;		}	} else {		fc = frcache + out;		if (fc->fin_fr && !bcmp((char *)fin, (char *)fc, FI_CSIZE)) {			/*			 * copy cached data so we can unlock the mutex			 * earlier.			 */			bcopy((char *)fc, (char *)fin, sizeof(*fin));			frstats[out].fr_chit++;			pass = fin->fin_fr->fr_flags;		} else {			pass = FR_NOMATCH;			if ((fin->fin_fr = ipfilter[out][fr_active]))				pass = FR_SCANLIST(FR_NOMATCH, ip, fin, m);			bcopy((char *)fin, (char *)fc, FI_CSIZE);			if (pass & FR_NOMATCH) {				frstats[out].fr_nom++;#ifdef	NOMATCH				pass |= NOMATCH;#endif			}		}		if ((pass & FR_KEEPFRAG)) {			if (fin->fin_fi.fi_fl & FI_FRAG) {				if (ipfr_newfrag(ip, fin, pass) == -1)					frstats[out].fr_bnfr++;				else					frstats[out].fr_nfr++;			} else				frstats[out].fr_cfr++;		}		if (pass & FR_KEEPSTATE) {			if (fr_addstate(ip, fin, pass) == -1)				frstats[out].fr_bads++;			else				frstats[out].fr_ads++;		}	}	fr = fin->fin_fr;	if (fr && fr->fr_func)		pass = (*fr->fr_func)(pass, ip, fin);	if (out) {		if ((fin->fin_fr = ipacct[1][fr_active]) &&		    (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))			frstats[1].fr_acct++;		ip_natout(ip, hlen, fin);	}	MUTEX_EXIT(&ipf_mutex);#ifdef	IPFILTER_LOG	if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {		if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {			pass |= FF_LOGNOMATCH;			frstats[out].fr_npkl++;			goto logit;		} else if (((pass & FR_LOGMASK) == FR_LOGP) ||		    ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {			if ((pass & FR_LOGMASK) != FR_LOGP)				pass |= FF_LOGPASS;			frstats[out].fr_ppkl++;			goto logit;		} else if (((pass & FR_LOGMASK) == FR_LOGB) ||			   ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {			if ((pass & FR_LOGMASK) != FR_LOGB)				pass |= FF_LOGBLOCK;			frstats[out].fr_bpkl++;logit:			if (!IPLLOG(pass, ip, fin, m))				frstats[out].fr_skip++;		}	}#endif /* IPFILTER_LOG */	if (pass & FR_PASS)		frstats[out].fr_pass++;	else if (pass & FR_BLOCK) {		frstats[out].fr_block++;		/*		 * Should we return an ICMP packet to indicate error		 * status passing through the packet filter ?		 */#ifdef	_KERNEL		if (pass & FR_RETICMP) {# if SOLARIS			ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,				   qif, ip->ip_src);# else			ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,				   ifp, ip->ip_src);			m = NULL;	/* freed by icmp_error() */# endif			frstats[0].fr_ret++;		} else if ((pass & FR_RETRST) &&			   !(fin->fin_fi.fi_fl & FI_SHORT)) {			if (SEND_RESET(ip, qif, q) == 0)				frstats[1].fr_ret++;		}#else		if (pass & FR_RETICMP) {			verbose("- ICMP unreachable sent\n");			frstats[0].fr_ret++;		} else if ((pass & FR_RETRST) &&			   !(fin->fin_fi.fi_fl & FI_SHORT)) {			verbose("- TCP RST sent\n");			frstats[1].fr_ret++;		}#endif	}#ifdef	_KERNEL# if	!SOLARIS	if (pass & FR_DUP)		mc = m_copy(m, 0, M_COPYALL);	if (fr) {		frdest_t *fdp = &fr->fr_tif;		if ((pass & FR_FASTROUTE) ||		    (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1))			ipfr_fastroute(m, fin, fdp);		if (mc)			ipfr_fastroute(mc, fin, &fr->fr_dif);	}	if (!(pass & FR_PASS) && m)		m_freem(m);# else	/*	if (pass & FR_DUP)		mc = dupmsg(mb);	if (fr) {		frdest_t *fdp = &fr->fr_tif;		if ((pass & FR_FASTROUTE) ||		    (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1))			ipfr_fastroute(mb, fin, fdp);		if (mc)			ipfr_fastroute(mc, fin, &fr->fr_dif);	}	*/# endif	return (pass & FR_PASS) ? 0 : -1;#else	if (pass & FR_NOMATCH)		return 1;	if (pass & FR_PASS)		return 0;	return -1;#endif}