From 6054307b92d4e96bd06946f2d4cac16f5f08d034 Mon Sep 17 00:00:00 2001 From: Peter Wemm Date: Sat, 20 Jun 1998 18:37:51 +0000 Subject: [PATCH] Merge ipfilter 3.2.3 -> 3.2.7 changes onto mainline. --- sys/netinet/fil.c | 62 ++++++++++------ sys/netinet/ip_auth.c | 5 +- sys/netinet/ip_fil.c | 7 +- sys/netinet/ip_fil.h | 3 +- sys/netinet/ip_ftp_pxy.c | 14 ++-- sys/netinet/ip_nat.c | 20 +++--- sys/netinet/ip_proxy.c | 46 ++++++++---- sys/netinet/ip_state.c | 148 +++++++++++++++++++++++++++++++-------- 8 files changed, 218 insertions(+), 87 deletions(-) diff --git a/sys/netinet/fil.c b/sys/netinet/fil.c index 57190a99dcd0..d634bbb74655 100644 --- a/sys/netinet/fil.c +++ b/sys/netinet/fil.c @@ -7,7 +7,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed"; -static const char rcsid[] = "@(#)$Id: fil.c,v 1.1.1.6 1998/03/21 10:11:28 peter Exp $"; +static const char rcsid[] = "@(#)$Id: fil.c,v 1.2 1998/03/21 11:33:54 peter Exp $"; #endif #include "opt_ipfilter.h" @@ -25,6 +25,7 @@ static const char rcsid[] = "@(#)$Id: fil.c,v 1.1.1.6 1998/03/21 10:11:28 peter #else # include # include +# include #endif #include #if !defined(__SVR4) && !defined(__svr4__) @@ -201,6 +202,7 @@ fr_info_t *fin; { struct optlist *op; tcphdr_t *tcp; + icmphdr_t *icmp; fr_ip_t *fi = &fin->fin_fi; u_short optmsk = 0, secmsk = 0, auth = 0; int i, mv, ol, off; @@ -221,6 +223,7 @@ fr_info_t *fin; fin->fin_hlen = hlen; fin->fin_dlen = ip->ip_len - hlen; tcp = (tcphdr_t *)((char *)ip + hlen); + icmp = (icmphdr_t *)tcp; fin->fin_dp = (void *)tcp; (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); (*(((u_32_t *)fi) + 1)) = (*(((u_32_t *)ip) + 3)); @@ -233,12 +236,20 @@ fr_info_t *fin; switch (ip->ip_p) { case IPPROTO_ICMP : - if ((!IPMINLEN(ip, icmp) && !off) || + { + int minicmpsz = sizeof(struct icmp); + + if (!off && ip->ip_len > ICMP_MINLEN + hlen && + (icmp->icmp_type == ICMP_ECHOREPLY || + icmp->icmp_type == ICMP_UNREACH)) + minicmpsz = ICMP_MINLEN; + if ((!(ip->ip_len >= hlen + minicmpsz) && !off) || (off && off < sizeof(struct icmp))) fi->fi_fl |= FI_SHORT; if (fin->fin_dlen > 1) fin->fin_data[0] = *(u_short *)tcp; break; + } case IPPROTO_TCP : fi->fi_fl |= FI_TCPUDP; if ((!IPMINLEN(ip, tcphdr) && !off) || @@ -425,7 +436,7 @@ void *m; off = ip->ip_off & 0x1fff; pass |= (fi->fi_fl << 24); - if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off) + if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off) portcmp = 1; for (rulen = 0; fr; fr = fr->fr_next, rulen++) { @@ -482,24 +493,22 @@ void *m; * If a fragment, then only the first has what we're looking * for here... */ + if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf || + fr->fr_tcpfm)) + continue; if (fi->fi_fl & FI_TCPUDP) { - if (portcmp) { - if (!fr_tcpudpchk(fr, fin)) - continue; - } else if (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf || - fr->fr_tcpfm) + if (!fr_tcpudpchk(fr, fin)) continue; - } else if (fi->fi_p == IPPROTO_ICMP) { - if (!off && (fin->fin_dlen > 1)) { - if ((fin->fin_data[0] & fr->fr_icmpm) != - fr->fr_icmp) { - FR_DEBUG(("i. %#x & %#x != %#x\n", - fin->fin_data[0], - fr->fr_icmpm, fr->fr_icmp)); - continue; - } - } else if (fr->fr_icmpm || fr->fr_icmp) + } else if (fr->fr_icmpm || fr->fr_icmp) { + if ((fi->fi_p != IPPROTO_ICMP) || off || + (fin->fin_dlen < 2)) continue; + if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) { + FR_DEBUG(("i. %#x & %#x != %#x\n", + fin->fin_data[0], fr->fr_icmpm, + fr->fr_icmp)); + continue; + } } FR_VERBOSE(("*")); /* @@ -578,6 +587,15 @@ int out; # endif int up; +#ifdef M_CANFASTFWD + /* + * XXX For now, IP Filter and fast-forwarding of cached flows + * XXX are mutually exclusive. Eventually, IP Filter should + * XXX get a "can-fast-forward" filter rule. + */ + m->m_flags &= ~M_CANFASTFWD; +#endif /* M_CANFASTFWD */ + if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_ICMP)) { int plen = 0; @@ -894,7 +912,7 @@ u_short ipf_cksum(addr, len) register u_short *addr; register int len; { - register u_long sum = 0; + register u_32_t sum = 0; for (sum = 0; len > 1; len -= 2) sum += *addr++; @@ -927,7 +945,7 @@ int len; u_char c[2]; u_short s; } bytes; - u_long sum; + u_32_t sum; u_short *sp; # if SOLARIS || defined(__sgi) int add, hlen; @@ -1026,7 +1044,7 @@ int len; #endif /* SOLARIS */ if (len < 2) break; - if((u_long)sp & 1) { + if((u_32_t)sp & 1) { bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s)); sum += bytes.s; } else @@ -1080,7 +1098,7 @@ int len; * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 1.1.1.6 1998/03/21 10:11:28 peter Exp $ + * $Id: fil.c,v 1.2 1998/03/21 11:33:54 peter Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, diff --git a/sys/netinet/ip_auth.c b/sys/netinet/ip_auth.c index 40ffc88c03ad..3eb1a635b015 100644 --- a/sys/netinet/ip_auth.c +++ b/sys/netinet/ip_auth.c @@ -6,7 +6,7 @@ * to the original author and the contributors. */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_auth.c,v 1.2 1998/03/21 11:33:59 peter Exp $"; +static const char rcsid[] = "@(#)$Id: ip_auth.c,v 1.3 1998/03/21 13:37:42 peter Exp $"; #endif #if defined(KERNEL) && !defined(_KERNEL) @@ -97,6 +97,9 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ #include "netinet/ip_auth.h" #if !SOLARIS && !defined(linux) # include +# ifdef __FreeBSD__ +# include +# endif #endif diff --git a/sys/netinet/ip_fil.c b/sys/netinet/ip_fil.c index d657b7f20f0c..d930811bb7b6 100644 --- a/sys/netinet/ip_fil.c +++ b/sys/netinet/ip_fil.c @@ -7,7 +7,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_fil.c,v 1.3 1998/03/27 18:03:13 peter Exp $"; +static const char rcsid[] = "@(#)$Id: ip_fil.c,v 1.4 1998/06/08 06:04:12 bde Exp $"; #endif #include "opt_ipfilter.h" @@ -167,7 +167,7 @@ struct devsw iplsw = { }; #endif /* _BSDI_VERSION >= 199510 && _KERNEL */ -#if defined(__NetBSD__) || defined(__OpenBSD__) +#if defined(__NetBSD__) || defined(__OpenBSD__) || (_BSDI_VERSION >= 199701) # include # if defined(NETBSD_PF) # include @@ -939,7 +939,8 @@ frdest_t *fdp; if (ro->ro_rt->rt_flags & RTF_GATEWAY) dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway; } - ro->ro_rt->rt_use++; + if (ro->ro_rt) + ro->ro_rt->rt_use++; /* * For input packets which are being "fastrouted", they won't diff --git a/sys/netinet/ip_fil.h b/sys/netinet/ip_fil.h index ebaab4c1309c..e40ef555ae92 100644 --- a/sys/netinet/ip_fil.h +++ b/sys/netinet/ip_fil.h @@ -6,7 +6,7 @@ * to the original author and the contributors. * * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ip_fil.h,v 1.4 1998/06/08 06:04:11 bde Exp $ + * $Id: ip_fil.h,v 1.5 1998/06/08 09:47:41 bde Exp $ */ #ifndef __IP_FIL_H__ @@ -521,4 +521,5 @@ extern int iplused[IPL_LOGMAX + 1]; extern struct frentry *ipfilter[2][2], *ipacct[2][2]; extern struct frgroup *ipfgroups[3][2]; extern struct filterstats frstats[]; + #endif /* __IP_FIL_H__ */ diff --git a/sys/netinet/ip_ftp_pxy.c b/sys/netinet/ip_ftp_pxy.c index 2d218e9af519..1a66a9ba0c42 100644 --- a/sys/netinet/ip_ftp_pxy.c +++ b/sys/netinet/ip_ftp_pxy.c @@ -43,18 +43,18 @@ tcphdr_t *tcp; ap_session_t *aps; nat_t *nat; { - u_long sum1, sum2; + u_32_t sum1, sum2; short sel; if (tcp->th_sport == aps->aps_dport) { - sum2 = (u_long)ntohl(tcp->th_ack); + sum2 = (u_32_t)ntohl(tcp->th_ack); sel = aps->aps_sel; if ((aps->aps_after[!sel] > aps->aps_after[sel]) && (sum2 > aps->aps_after[!sel])) { sel = aps->aps_sel = !sel; /* switch to other set */ } if (aps->aps_seqoff[sel] && (sum2 > aps->aps_after[sel])) { - sum1 = (u_long)aps->aps_seqoff[sel]; + sum1 = (u_32_t)aps->aps_seqoff[sel]; tcp->th_ack = htonl(sum2 - sum1); return 2; } @@ -99,7 +99,7 @@ tcphdr_t *tcp; ap_session_t *aps; nat_t *nat; { - register u_long sum1, sum2; + register u_32_t sum1, sum2; char newbuf[IPF_MAXPORTLEN+1]; char portbuf[IPF_MAXPORTLEN+1], *s; int ch = 0, off = (ip->ip_hl << 2) + (tcp->th_off << 2); @@ -232,17 +232,17 @@ nat_t *nat; adjust_seqack: if (tcp->th_dport == aps->aps_dport) { - sum2 = (u_long)ntohl(tcp->th_seq); + sum2 = (u_32_t)ntohl(tcp->th_seq); off = aps->aps_sel; if ((aps->aps_after[!off] > aps->aps_after[off]) && (sum2 > aps->aps_after[!off])) { off = aps->aps_sel = !off; /* switch to other set */ } if (aps->aps_seqoff[off]) { - sum1 = (u_long)aps->aps_after[off] - + sum1 = (u_32_t)aps->aps_after[off] - aps->aps_seqoff[off]; if (sum2 > sum1) { - sum1 = (u_long)aps->aps_seqoff[off]; + sum1 = (u_32_t)aps->aps_seqoff[off]; sum2 += sum1; tcp->th_seq = htonl(sum2); ch = 1; diff --git a/sys/netinet/ip_nat.c b/sys/netinet/ip_nat.c index 447fb7a32c40..008da1b94b19 100644 --- a/sys/netinet/ip_nat.c +++ b/sys/netinet/ip_nat.c @@ -9,7 +9,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_nat.c,v 1.1.1.6 1998/03/21 10:11:15 peter Exp $"; +static const char rcsid[] = "@(#)$Id: ip_nat.c,v 1.2 1998/03/21 11:34:17 peter Exp $"; #endif #include "opt_ipfilter.h" @@ -134,10 +134,10 @@ static int nat_ifpaddr __P((nat_t *, void *, struct in_addr *)); void fix_outcksum(sp, n) u_short *sp; -u_long n; +u_32_t n; { register u_short sumshort; - register u_long sum1; + register u_32_t sum1; if (!n) return; @@ -153,10 +153,10 @@ u_long n; void fix_incksum(sp, n) u_short *sp; -u_long n; +u_32_t n; { register u_short sumshort; - register u_long sum1; + register u_32_t sum1; if (!n) return; @@ -460,7 +460,7 @@ struct in_addr *inp; struct in_addr in; #if SOLARIS - in.s_addr = ill->ill_ipif->ipif_local_addr; + in.s_addr = ntohl(ill->ill_ipif->ipif_local_addr); #else /* SOLARIS */ # if linux ; @@ -525,7 +525,7 @@ fr_info_t *fin; u_short flags; int direction; { - register u_long sum1, sum2, sumd, l; + register u_32_t sum1, sum2, sumd, l; u_short port = 0, sport = 0, dport = 0, nport = 0; struct in_addr in; tcphdr_t *tcp = NULL; @@ -783,7 +783,7 @@ int *nflags; */ if (flags & IPN_TCPUDP) { tcphdr_t *tcp = (tcphdr_t *)(oip + 1); - u_long sum1, sum2, sumd; + u_32_t sum1, sum2, sumd; struct in_addr in; if (nat->nat_dir == NAT_OUTBOUND) { @@ -968,7 +968,7 @@ int hlen; fr_info_t *fin; { register ipnat_t *np; - register u_long ipa; + register u_32_t ipa; tcphdr_t *tcp = NULL; u_short nflags = 0, sport = 0, dport = 0, *csump = NULL; struct ifnet *ifp; @@ -1285,7 +1285,7 @@ void *ifp; #endif { register nat_t *nat; - register u_long sum1, sum2, sumd; + register u_32_t sum1, sum2, sumd; struct in_addr in; ipnat_t *np; #if defined(_KERNEL) && !SOLARIS diff --git a/sys/netinet/ip_proxy.c b/sys/netinet/ip_proxy.c index 8bb86c074848..fe18abb60d97 100644 --- a/sys/netinet/ip_proxy.c +++ b/sys/netinet/ip_proxy.c @@ -6,7 +6,7 @@ * to the original author and the contributors. */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 1.1.1.3 1998/03/21 10:11:30 peter Exp $"; +static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 1.2 1998/03/21 11:34:23 peter Exp $"; #endif #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL) @@ -82,6 +82,10 @@ static ap_session_t *ap_find __P((ip_t *, tcphdr_t *)); static ap_session_t *ap_new_session __P((aproxy_t *, ip_t *, tcphdr_t *, fr_info_t *, nat_t *)); +static int ap_matchsrcdst __P((ap_session_t *aps, struct in_addr src, + struct in_addr dst, void *tcp, u_short sport, + u_short dport)); + #define AP_SESS_SIZE 53 #if defined(_KERNEL) && !defined(linux) @@ -114,15 +118,37 @@ ipnat_t *nat; } +static int +ap_matchsrcdst(aps, src, dst, tcp, sport, dport) +ap_session_t *aps; +struct in_addr src, dst; +void *tcp; +u_short sport, dport; +{ + if (aps->aps_dst.s_addr == dst.s_addr) { + if ((aps->aps_src.s_addr == src.s_addr) && + (!tcp || (sport == aps->aps_sport) && + (dport == aps->aps_dport))) + return 1; + } else if (aps->aps_dst.s_addr == src.s_addr) { + if ((aps->aps_src.s_addr == dst.s_addr) && + (!tcp || (sport == aps->aps_dport) && + (dport == aps->aps_sport))) + return 1; + } + return 0; +} + + static ap_session_t *ap_find(ip, tcp) ip_t *ip; tcphdr_t *tcp; { - struct in_addr src, dst; - register u_long hv; - register u_short sp, dp; - register ap_session_t *aps; register u_char p = ip->ip_p; + register ap_session_t *aps; + register u_short sp, dp; + register u_long hv; + struct in_addr src, dst; src = ip->ip_src, dst = ip->ip_dst; sp = dp = 0; /* XXX gcc -Wunitialized */ @@ -139,14 +165,8 @@ tcphdr_t *tcp; for (aps = ap_sess_tab[hv]; aps; aps = aps->aps_next) if ((aps->aps_p == p) && - IPPAIR(aps->aps_src, aps->aps_dst, src, dst)) { - if (tcp) { - if (PAIRS(aps->aps_sport, aps->aps_dport, - sp, dp)) - break; - } else - break; - } + ap_matchsrcdst(aps, src, dst, tcp, sp, dp)) + break; return aps; } diff --git a/sys/netinet/ip_state.c b/sys/netinet/ip_state.c index 2a7de77863d7..98cc86295ade 100644 --- a/sys/netinet/ip_state.c +++ b/sys/netinet/ip_state.c @@ -7,7 +7,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_state.c,v 1.1.1.6 1998/03/21 10:11:25 peter Exp $"; +static const char rcsid[] = "@(#)$Id: ip_state.c,v 1.2 1998/03/21 11:34:27 peter Exp $"; #endif #include "opt_ipfilter.h" @@ -92,6 +92,11 @@ ips_stat_t ips_stats; extern kmutex_t ipf_state; #endif +static int fr_matchsrcdst __P((ipstate_t *, struct in_addr, struct in_addr, + fr_info_t *, void *, u_short, u_short)); +static int fr_state_flush __P((int)); +static ips_stat_t *fr_statetstats __P((void)); + #define FIVE_DAYS (2 * 5 * 86400) /* 5 days: half closed session */ @@ -104,7 +109,7 @@ u_long fr_tcpidletimeout = FIVE_DAYS, fr_icmptimeout = 120; -ips_stat_t *fr_statetstats() +static ips_stat_t *fr_statetstats() { ips_stats.iss_active = ips_num; ips_stats.iss_table = ips_table; @@ -118,7 +123,7 @@ ips_stat_t *fr_statetstats() * which == 1 : flush TCP connections which have started to close but are * stuck for some reason. */ -int fr_state_flush(which) +static int fr_state_flush(which) int which; { register int i; @@ -141,10 +146,10 @@ int which; break; case 1 : if ((is->is_p == IPPROTO_TCP) && - ((is->is_state[0] <= TCPS_ESTABLISHED) && - (is->is_state[1] > TCPS_ESTABLISHED)) || - ((is->is_state[1] <= TCPS_ESTABLISHED) && - (is->is_state[0] > TCPS_ESTABLISHED))) + (((is->is_state[0] <= TCPS_ESTABLISHED) && + (is->is_state[1] > TCPS_ESTABLISHED)) || + ((is->is_state[1] <= TCPS_ESTABLISHED) && + (is->is_state[0] > TCPS_ESTABLISHED)))) delete = 1; break; } @@ -244,7 +249,7 @@ u_int pass; switch (ic->icmp_type) { case ICMP_ECHO : - is->is_icmp.ics_type = 0; + is->is_icmp.ics_type = ICMP_ECHOREPLY; /* XXX */ hv += (is->is_icmp.ics_id = ic->icmp_id); hv += (is->is_icmp.ics_seq = ic->icmp_seq); break; @@ -308,11 +313,33 @@ u_int pass; bcopy((char *)&ips, (char *)is, sizeof(*is)); hv %= IPSTATE_SIZE; MUTEX_ENTER(&ipf_state); - is->is_next = ips_table[hv]; - ips_table[hv] = is; + is->is_pass = pass; is->is_pkts = 1; is->is_bytes = ip->ip_len; + /* + * Copy these from the rule itself. + */ + is->is_opt = fin->fin_fr->fr_ip.fi_optmsk; + is->is_optmsk = fin->fin_fr->fr_mip.fi_optmsk; + is->is_sec = fin->fin_fr->fr_ip.fi_secmsk; + is->is_secmsk = fin->fin_fr->fr_mip.fi_secmsk; + is->is_auth = fin->fin_fr->fr_ip.fi_auth; + is->is_authmsk = fin->fin_fr->fr_mip.fi_auth; + is->is_flags = fin->fin_fr->fr_ip.fi_fl; + is->is_flags |= fin->fin_fr->fr_mip.fi_fl << 4; + /* + * add into table. + */ + is->is_next = ips_table[hv]; + ips_table[hv] = is; + if (fin->fin_out) { + is->is_ifpin = NULL; + is->is_ifpout = fin->fin_ifp; + } else { + is->is_ifpin = fin->fin_ifp; + is->is_ifpout = NULL; + } if (pass & FR_LOGFIRST) is->is_pass &= ~(FR_LOGFIRST|FR_LOG); ips_num++; @@ -331,12 +358,11 @@ u_int pass; * change timeout depending on whether new packet is a SYN-ACK returning for a * SYN or a RST or FIN which indicate time to close up shop. */ -int fr_tcpstate(is, fin, ip, tcp, sport) +int fr_tcpstate(is, fin, ip, tcp) register ipstate_t *is; fr_info_t *fin; ip_t *ip; tcphdr_t *tcp; -u_short sport; { register int seqskew, ackskew; register u_short swin, dwin; @@ -348,7 +374,7 @@ u_short sport; */ seq = ntohl(tcp->th_seq); ack = ntohl(tcp->th_ack); - source = (sport == is->is_sport); + source = (ip->ip_src.s_addr == is->is_src.s_addr); if (!(tcp->th_flags & TH_ACK)) /* Pretend an ack was sent */ ack = source ? is->is_ack : is->is_seq; @@ -392,7 +418,7 @@ u_short sport; swin = is->is_dwin; } - if ((seqskew <= swin) && (ackskew <= dwin)) { + if ((seqskew <= dwin) && (ackskew <= swin)) { if (source) { is->is_seq = seq; is->is_ack = ack; @@ -408,14 +434,81 @@ u_short sport; /* * Nearing end of connection, start timeout. */ - fr_tcp_age(&is->is_age, is->is_state, ip, fin, - tcp->th_sport == is->is_sport); + fr_tcp_age(&is->is_age, is->is_state, ip, fin, source); return 1; } return 0; } +static int fr_matchsrcdst(is, src, dst, fin, tcp, sp, dp) +ipstate_t *is; +struct in_addr src, dst; +fr_info_t *fin; +void *tcp; +u_short sp, dp; +{ + int ret = 0, rev, out; + void *ifp; + + rev = (is->is_dst.s_addr != dst.s_addr); + ifp = fin->fin_ifp; + out = fin->fin_out; + + if (!rev) { + if (out) { + if (!is->is_ifpout) + is->is_ifpout = ifp; + } else { + if (!is->is_ifpin) + is->is_ifpin = ifp; + } + } else { + if (out) { + if (!is->is_ifpin) + is->is_ifpin = ifp; + } else { + if (!is->is_ifpout) + is->is_ifpout = ifp; + } + } + + if (!rev) { + if (((out && is->is_ifpout == ifp) || + (!out && is->is_ifpin == ifp)) && + (is->is_dst.s_addr == dst.s_addr) && + (is->is_src.s_addr == src.s_addr) && + (!tcp || (sp == is->is_sport) && + (dp == is->is_dport))) { + ret = 1; + } + } else { + if (((out && is->is_ifpin == ifp) || + (!out && is->is_ifpout == ifp)) && + (is->is_dst.s_addr == src.s_addr) && + (is->is_src.s_addr == dst.s_addr) && + (!tcp || (sp == is->is_dport) && + (dp == is->is_sport))) { + ret = 1; + } + } + + /* + * Whether or not this should be here, is questionable, but the aim + * is to get this out of the main line. + */ + if (ret) { + if (((fin->fin_fi.fi_optmsk & is->is_optmsk) != is->is_opt) || + ((fin->fin_fi.fi_secmsk & is->is_secmsk) != is->is_sec) || + ((fin->fin_fi.fi_auth & is->is_authmsk) != is->is_auth) || + ((fin->fin_fi.fi_fl & (is->is_flags >> 4)) != + (is->is_flags & 0xf))) + ret = 0; + } + return ret; +} + + /* * Check if a packet has a registered state. */ @@ -454,13 +547,8 @@ fr_info_t *fin; if ((is->is_p == pr) && (ic->icmp_id == is->is_icmp.ics_id) && (ic->icmp_seq == is->is_icmp.ics_seq) && - IPPAIR(src, dst, is->is_src, is->is_dst)) { - /* - * If we have type 0 stored, allow any icmp - * replies through. - */ - if (is->is_icmp.ics_type && - is->is_icmp.ics_type != ic->icmp_type) + fr_matchsrcdst(is, src, dst, fin, NULL, 0, 0)) { + if (is->is_icmp.ics_type != ic->icmp_type) continue; is->is_age = fr_icmptimeout; is->is_pkts++; @@ -480,11 +568,11 @@ fr_info_t *fin; hv += sport; hv %= IPSTATE_SIZE; MUTEX_ENTER(&ipf_state); - for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_next) { + for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_next) if ((is->is_p == pr) && - PAIRS(sport, dport, is->is_sport, is->is_dport) && - IPPAIR(src, dst, is->is_src, is->is_dst)) - if (fr_tcpstate(is, fin, ip, tcp, sport)) { + fr_matchsrcdst(is, src, dst, fin, tcp, + sport, dport)) { + if (fr_tcpstate(is, fin, ip, tcp)) { pass = is->is_pass; #ifdef _KERNEL MUTEX_EXIT(&ipf_state); @@ -498,7 +586,7 @@ fr_info_t *fin; #endif return pass; } - } + } MUTEX_EXIT(&ipf_state); break; } @@ -515,8 +603,8 @@ fr_info_t *fin; MUTEX_ENTER(&ipf_state); for (is = ips_table[hv]; is; is = is->is_next) if ((is->is_p == pr) && - PAIRS(sport, dport, is->is_sport, is->is_dport) && - IPPAIR(src, dst, is->is_src, is->is_dst)) { + fr_matchsrcdst(is, src, dst, fin, + tcp, sport, dport)) { ips_stats.iss_hits++; is->is_pkts++; is->is_bytes += ip->ip_len;