diff options
author | Kjell Wooding <kjell@cvs.openbsd.org> | 2000-08-10 05:50:28 +0000 |
---|---|---|
committer | Kjell Wooding <kjell@cvs.openbsd.org> | 2000-08-10 05:50:28 +0000 |
commit | f6f9719d77e16be22cc895846d5a194bedc0a06c (patch) | |
tree | 72ffe5baca00bf7f9e9b21455a0220c82f42babd /sys/netinet/ip_state.c | |
parent | ad4cd1f6669755dfa5db6525909b031b9fee7918 (diff) |
Import ipf 3.3.18. Fixes more problems with the in-kernel FTP proxy,
some nat state bugs, and ups the default state table size.
See sbin/ipf/HISTORY for details.
Diffstat (limited to 'sys/netinet/ip_state.c')
-rw-r--r-- | sys/netinet/ip_state.c | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/sys/netinet/ip_state.c b/sys/netinet/ip_state.c index 983d2ca299b..51cda10dee3 100644 --- a/sys/netinet/ip_state.c +++ b/sys/netinet/ip_state.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_state.c,v 1.22 2000/05/24 21:59:11 kjell Exp $ */ +/* $OpenBSD: ip_state.c,v 1.23 2000/08/10 05:50:26 kjell Exp $ */ /* * Copyright (C) 1995-1998 by Darren Reed. @@ -9,7 +9,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[] = "@(#)$IPFilter: ip_state.c,v 2.3.2.25 2000/05/22 06:57:53 darrenr Exp $"; +static const char rcsid[] = "@(#)$IPFilter: ip_state.c,v 2.3.2.28 2000/08/08 16:00:35 darrenr Exp $"; #endif #include <sys/errno.h> @@ -152,7 +152,7 @@ static ips_stat_t *fr_statetstats() * flush state tables. two actions currently defined: * which == 0 : flush all state table entries * which == 1 : flush TCP connections which have started to close but are - * stuck for some reason. + * stuck for some reason. */ static int fr_state_flush(which) int which; @@ -679,12 +679,12 @@ fr_info_t *fin; register u_char pr; struct icmp *ic; u_short savelen; + icmphdr_t *icmp; fr_info_t ofin; tcphdr_t *tcp; - icmphdr_t *icmp; + int type, len; frentry_t *fr; ip_t *oip; - int type; u_int hv; /* @@ -708,6 +708,38 @@ fr_info_t *fin; if (ip->ip_len < ICMPERR_MAXPKTLEN + ((oip->ip_hl - 5) << 2)) return NULL; + /* + * Sanity Checks. + */ + len = fin->fin_dlen - ICMPERR_ICMPHLEN; + if ((len <= 0) || ((oip->ip_hl << 2) > len)) + return NULL; + + /* + * Is the buffer big enough for all of it ? It's the size of the IP + * header claimed in the encapsulated part which is of concern. It + * may be too big to be in this buffer but not so big that it's + * outside the ICMP packet, leading to TCP deref's causing problems. + * This is possible because we don't know how big oip_hl is when we + * do the pullup early in fr_check() and thus can't gaurantee it is + * all here now. + */ +#ifdef _KERNEL + { + mb_t *m; + +# if SOLARIS + m = fin->fin_qfm; + if ((char *)oip + len > (char *)m->b_wptr) + return NULL; +# else + m = *(mb_t **)fin->fin_mp; + if ((char *)oip + len > (char *)ip + m->m_len) + return NULL; +# endif + } +#endif + if (oip->ip_p == IPPROTO_ICMP) { icmp = (icmphdr_t *)((char *)oip + (oip->ip_hl << 2)); @@ -738,9 +770,10 @@ fr_info_t *fin; } hv %= fr_statesize; - oip->ip_len = ntohs(oip->ip_len); + savelen = oip->ip_len; + oip->ip_len = len; fr_makefrip(oip->ip_hl << 2, oip, &ofin); - oip->ip_len = htons(oip->ip_len); + oip->ip_len = savelen; ofin.fin_ifp = fin->fin_ifp; ofin.fin_out = !fin->fin_out; ofin.fin_mp = NULL; /* if dereferenced, panic XXX */ @@ -795,7 +828,7 @@ fr_info_t *fin; * order. Any change we make must be undone afterwards. */ savelen = oip->ip_len; - oip->ip_len = ip->ip_len - (ip->ip_hl << 2) - ICMPERR_ICMPHLEN; + oip->ip_len = len; fr_makefrip(oip->ip_hl << 2, oip, &ofin); oip->ip_len = savelen; ofin.fin_ifp = fin->fin_ifp; @@ -899,7 +932,15 @@ fr_info_t *fin; case IPPROTO_TCP : { register u_short dport = tcp->th_dport, sport = tcp->th_sport; + register int i; + i = tcp->th_flags; + /* + * Just plain ignore RST flag set with either FIN or SYN. + */ + if ((i & TH_RST) && + ((i & (TH_FIN|TH_SYN|TH_RST)) != TH_RST)) + break; tryagain = 0; retry_tcp: hvm = hv % fr_statesize; |