diff options
author | peter <peter@FreeBSD.org> | 1998-06-20 18:29:38 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1998-06-20 18:29:38 +0000 |
commit | 9529c38ad8859b9f325867d97f266101f2c4dca3 (patch) | |
tree | 7c9206c000e7ad493db842a3fecdf77deacb096a /contrib/ipfilter/ip_state.c | |
parent | 58e3555d887b6a5b1f460d8ee84ca4e97c0a8217 (diff) | |
download | FreeBSD-src-9529c38ad8859b9f325867d97f266101f2c4dca3.zip FreeBSD-src-9529c38ad8859b9f325867d97f266101f2c4dca3.tar.gz |
Import trimmed version of ipfilter 3.2.7.
Obtained from: Darren Reed via http://cheops.anu.edu.au/~avalon/
Diffstat (limited to 'contrib/ipfilter/ip_state.c')
-rw-r--r-- | contrib/ipfilter/ip_state.c | 148 |
1 files changed, 118 insertions, 30 deletions
diff --git a/contrib/ipfilter/ip_state.c b/contrib/ipfilter/ip_state.c index bffb17b..89a2c3b 100644 --- a/contrib/ipfilter/ip_state.c +++ b/contrib/ipfilter/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 2.0.2.24.2.4 1997/11/19 11:44:09 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.0.2.24.2.14 1998/05/24 03:53:04 darrenr Exp $"; #endif #if !defined(_KERNEL) && !defined(KERNEL) && !defined(__KERNEL__) @@ -85,6 +85,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 */ @@ -97,7 +102,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; @@ -111,7 +116,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; @@ -134,10 +139,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; } @@ -237,7 +242,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; @@ -301,11 +306,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++; @@ -324,12 +351,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; @@ -341,7 +367,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; @@ -385,7 +411,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; @@ -401,14 +427,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. */ @@ -447,13 +540,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++; @@ -473,11 +561,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); @@ -491,7 +579,7 @@ fr_info_t *fin; #endif return pass; } - } + } MUTEX_EXIT(&ipf_state); break; } @@ -508,8 +596,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; |