diff options
author | darrenr <darrenr@FreeBSD.org> | 2001-02-04 14:26:56 +0000 |
---|---|---|
committer | darrenr <darrenr@FreeBSD.org> | 2001-02-04 14:26:56 +0000 |
commit | 48b4ca8e6a57c62a30178ad743504003bfd60b92 (patch) | |
tree | b47e8b2fc77a6ae3122c2f25213a7861e67eee2f | |
parent | 53b25e2c4c7f67b0a0f4809050fb478bd1ff2d88 (diff) | |
download | FreeBSD-src-48b4ca8e6a57c62a30178ad743504003bfd60b92.zip FreeBSD-src-48b4ca8e6a57c62a30178ad743504003bfd60b92.tar.gz |
fix conflicts
34 files changed, 611 insertions, 247 deletions
diff --git a/contrib/ipfilter/fil.c b/contrib/ipfilter/fil.c index 9accee8..2315a93 100644 --- a/contrib/ipfilter/fil.c +++ b/contrib/ipfilter/fil.c @@ -136,6 +136,8 @@ struct frgroup *ipfgroups[3][2]; int fr_flags = IPF_LOGGING; int fr_active = 0; int fr_chksrc = 0; +int fr_minttl = 3; +int fr_minttllog = 1; #if defined(IPFILTER_DEFAULT_BLOCK) int fr_pass = FR_NOMATCH|FR_BLOCK; #else @@ -269,6 +271,40 @@ fr_info_t *fin; switch (p) { +#ifdef USE_INET6 + case IPPROTO_ICMPV6 : + { + int minicmpsz = sizeof(struct icmp6_hdr); + struct icmp6_hdr *icmp6; + + if (fin->fin_dlen > 1) { + fin->fin_data[0] = *(u_short *)tcp; + + icmp6 = (struct icmp6_hdr *)tcp; + + switch (icmp6->icmp6_type) + { + case ICMP6_ECHO_REPLY : + case ICMP6_ECHO_REQUEST : + minicmpsz = ICMP6ERR_MINPKTLEN; + break; + case ICMP6_DST_UNREACH : + case ICMP6_PACKET_TOO_BIG : + case ICMP6_TIME_EXCEEDED : + case ICMP6_PARAM_PROB : + minicmpsz = ICMP6ERR_IPICMPHLEN; + break; + default : + break; + } + } + + if (!(plen >= hlen + minicmpsz)) + fi->fi_fl |= FI_SHORT; + + break; + } +#endif case IPPROTO_ICMP : { int minicmpsz = sizeof(struct icmp); @@ -747,8 +783,8 @@ int out; #endif #ifdef _KERNEL + int p, len, drop = 0, logit = 0; mb_t *mc = NULL; - int p, len; # if !defined(__SVR4) && !defined(__svr4__) # ifdef __sgi char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8]; @@ -802,11 +838,17 @@ int out; break; /* 96 - enough for complete ICMP error IP header */ case IPPROTO_ICMP: + plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); + break; # ifdef USE_INET6 case IPPROTO_ICMPV6 : -# endif - plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); + /* + * XXX does not take intermediate header + * into account + */ + plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t); break; +# endif } up = MIN(hlen + plen, len); @@ -865,22 +907,37 @@ int out; # ifdef USE_INET6 if (v == 6) { ATOMIC_INCL(frstats[0].fr_ipv6[out]); + if (((ip6_t *)ip)->ip6_hlim < fr_minttl) { + ATOMIC_INCL(frstats[0].fr_badttl); + if (fr_minttllog) + logit = -2; + } } else # endif - if (!out && fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { + if (!out) { + if (fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { ATOMIC_INCL(frstats[0].fr_badsrc); + if (fr_chksrc == 2) + logit = -2; + } else if (ip->ip_ttl < fr_minttl) { + ATOMIC_INCL(frstats[0].fr_badttl); + if (fr_minttllog) + logit = -3; + } + } + if (drop) { # ifdef IPFILTER_LOG - if (fr_chksrc == 2) { - fin->fin_group = -2; - pass = FR_INQUE|FR_NOMATCH|FR_LOGB; - (void) IPLLOG(pass, ip, fin, m); - } + if (logit) { + fin->fin_group = logit; + pass = FR_INQUE|FR_NOMATCH|FR_LOGB; + (void) IPLLOG(pass, ip, fin, m); + } # endif # if !SOLARIS - m_freem(m); + m_freem(m); # endif - return error; - } + return error; + } #endif pass = fr_pass; if (fin->fin_fi.fi_fl & FI_SHORT) { @@ -1401,7 +1458,7 @@ nodata: * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.35.2.27 2000/10/26 21:20:54 darrenr Exp $ + * $Id: fil.c,v 2.35.2.30 2000/12/17 05:49:22 darrenr Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, diff --git a/contrib/ipfilter/ip_fil.h b/contrib/ipfilter/ip_fil.h index 487fe90..9dd75f0 100644 --- a/contrib/ipfilter/ip_fil.h +++ b/contrib/ipfilter/ip_fil.h @@ -335,6 +335,7 @@ typedef struct filterstats { u_long fr_tcpbad; /* TCP checksum check failures */ u_long fr_pull[2]; /* good and bad pullup attempts */ u_long fr_badsrc; /* source received doesn't match route */ + u_long fr_badttl; /* TTL in packet doesn't reach minimum */ #if SOLARIS u_long fr_notdata; /* PROTO/PCPROTO that have no data */ u_long fr_nodata; /* mblks that have no data */ @@ -612,6 +613,8 @@ extern int fr_pass; extern int fr_flags; extern int fr_active; extern int fr_chksrc; +extern int fr_minttl; +extern int fr_minttllog; extern fr_info_t frcache[2]; extern char ipfilter_version[]; extern iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1]; diff --git a/contrib/ipfilter/ipmon.c b/contrib/ipfilter/ipmon.c index ebc67a3..57edc7f 100644 --- a/contrib/ipfilter/ipmon.c +++ b/contrib/ipfilter/ipmon.c @@ -91,6 +91,8 @@ struct flags tcpfl[] = { { TH_FIN, 'F' }, { TH_URG, 'U' }, { TH_PUSH,'P' }, + { TH_ECN, 'E' }, + { TH_CWR, 'C' }, { 0, '\0' } }; @@ -144,6 +146,7 @@ static char **tcp_ports = NULL; #define OPT_FILTER 0x200 #define OPT_PORTNUM 0x400 #define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER) +#define OPT_LOGBODY 0x800 #define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b)) @@ -401,6 +404,8 @@ int blen; strcpy(t, "NAT:RDR "); else if (nl->nl_type == NL_EXPIRE) strcpy(t, "NAT:EXPIRE "); + else if (nl->nl_type == NL_FLUSH) + strcpy(t, "NAT:FLUSH "); else if (nl->nl_type == NL_NEWBIMAP) strcpy(t, "NAT:BIMAP "); else if (nl->nl_type == NL_NEWBLOCK) @@ -834,6 +839,8 @@ printipflog: dumphex(log, (u_char *)buf, sizeof(iplog_t) + sizeof(*ipf)); if (opts & OPT_HEXBODY) dumphex(log, (u_char *)ip, ipf->fl_plen + ipf->fl_hlen); + else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY)) + dumphex(log, (u_char *)ip + ipf->fl_hlen, ipf->fl_plen); } @@ -945,7 +952,7 @@ char *argv[]; iplfile[1] = IPNAT_NAME; iplfile[2] = IPSTATE_NAME; - while ((c = getopt(argc, argv, "?aDf:FhnN:o:O:pP:sS:tvxX")) != -1) + while ((c = getopt(argc, argv, "?abDf:FhnN:o:O:pP:sS:tvxX")) != -1) switch (c) { case 'a' : @@ -954,6 +961,9 @@ char *argv[]; fdt[1] = IPL_LOGNAT; fdt[2] = IPL_LOGSTATE; break; + case 'b' : + opts |= OPT_LOGBODY; + break; case 'D' : make_daemon = 1; break; diff --git a/contrib/ipfilter/ipsend/ipsend.c b/contrib/ipfilter/ipsend/ipsend.c index f0d1a3f..b047dd0 100644 --- a/contrib/ipfilter/ipsend/ipsend.c +++ b/contrib/ipfilter/ipsend/ipsend.c @@ -348,6 +348,12 @@ char **argv; printf("Options: %d\n", olen); ti = (struct tcpiphdr *)malloc(olen + ip->ip_len); + if(!ti) + { + fprintf(stderr,"malloc failed\n"); + exit(2); + } + bcopy((char *)ip, (char *)ti, sizeof(*ip)); ip = (ip_t *)ti; ip->ip_hl = (olen >> 2); diff --git a/contrib/ipfilter/ipsend/sock.c b/contrib/ipfilter/ipsend/sock.c index a641592..6907a08 100644 --- a/contrib/ipfilter/ipsend/sock.c +++ b/contrib/ipfilter/ipsend/sock.c @@ -8,7 +8,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: sock.c,v 2.1 1999/08/04 17:31:16 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: sock.c,v 2.1.4.1 2000/12/16 21:05:44 darrenr Exp $"; #endif #include <stdio.h> #include <unistd.h> diff --git a/contrib/ipfilter/man/ipfstat.8 b/contrib/ipfilter/man/ipfstat.8 index c0c751b..f36e31b 100644 --- a/contrib/ipfilter/man/ipfstat.8 +++ b/contrib/ipfilter/man/ipfstat.8 @@ -140,14 +140,22 @@ kernel. .SH STATE TOP Using the \fB\-t\fP option \fBipfstat\fP will enter the state top mode. In this mode the state table is displayed similar to the way \fBtop\fP displays -the process table. The \fB\-C\fP, \fB\-D\fP, \fB\-P\fP, \fB\-S\fP and\fB\-T\fP +the process table. The \fB\-C\fP, \fB\-D\fP, \fB\-P\fP, \fB\-S\fP and \fB\-T\fP commandline options can be used to restrict the state entries that will be shown and to specify the frequency of display updates. .PP In state top mode, the following keys can be used to influence the displayed -information. \fBl\fP can be used to redraw the screen. \fBq\fP is used to -quit the program. \fBs\fP can be used to change the sorting criterion and -\fBr\fP can be used to reverse the sorting criterion. +information: +.TP +\fBd\fP select information to display. +.TP +\fBl\fP redraw the screen. +.TP +\fBq\fP quit the program. +.TP +\fBs\fP switch between different sorting criterion. +.TP +\fBr\fP reverse the sorting criterion. .PP States can be sorted by protocol number, by number of IP packets, by number of bytes and by time-to-live of the state entry. The default is to sort by diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index dcfd65d..6d4622e 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -6,7 +6,7 @@ * to the original author and the contributors. */ #if !defined(lint) -static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed"; +static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; /* static const char rcsid[] = "@(#)$Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $"; */ static const char rcsid[] = "@(#)$FreeBSD$"; #endif @@ -139,6 +139,8 @@ struct frgroup *ipfgroups[3][2]; int fr_flags = IPF_LOGGING; int fr_active = 0; int fr_chksrc = 0; +int fr_minttl = 3; +int fr_minttllog = 1; #if defined(IPFILTER_DEFAULT_BLOCK) int fr_pass = FR_NOMATCH|FR_BLOCK; #else @@ -272,6 +274,40 @@ fr_info_t *fin; switch (p) { +#ifdef USE_INET6 + case IPPROTO_ICMPV6 : + { + int minicmpsz = sizeof(struct icmp6_hdr); + struct icmp6_hdr *icmp6; + + if (fin->fin_dlen > 1) { + fin->fin_data[0] = *(u_short *)tcp; + + icmp6 = (struct icmp6_hdr *)tcp; + + switch (icmp6->icmp6_type) + { + case ICMP6_ECHO_REPLY : + case ICMP6_ECHO_REQUEST : + minicmpsz = ICMP6ERR_MINPKTLEN; + break; + case ICMP6_DST_UNREACH : + case ICMP6_PACKET_TOO_BIG : + case ICMP6_TIME_EXCEEDED : + case ICMP6_PARAM_PROB : + minicmpsz = ICMP6ERR_IPICMPHLEN; + break; + default : + break; + } + } + + if (!(plen >= hlen + minicmpsz)) + fi->fi_fl |= FI_SHORT; + + break; + } +#endif case IPPROTO_ICMP : { int minicmpsz = sizeof(struct icmp); @@ -750,8 +786,8 @@ int out; #endif #ifdef _KERNEL + int p, len, drop = 0, logit = 0; mb_t *mc = NULL; - int p, len; # if !defined(__SVR4) && !defined(__svr4__) # ifdef __sgi char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8]; @@ -805,11 +841,17 @@ int out; break; /* 96 - enough for complete ICMP error IP header */ case IPPROTO_ICMP: + plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); + break; # ifdef USE_INET6 case IPPROTO_ICMPV6 : -# endif - plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); + /* + * XXX does not take intermediate header + * into account + */ + plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t); break; +# endif } up = MIN(hlen + plen, len); @@ -870,22 +912,37 @@ int out; # ifdef USE_INET6 if (v == 6) { ATOMIC_INCL(frstats[0].fr_ipv6[out]); + if (((ip6_t *)ip)->ip6_hlim < fr_minttl) { + ATOMIC_INCL(frstats[0].fr_badttl); + if (fr_minttllog) + logit = -2; + } } else # endif - if (!out && fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { + if (!out) { + if (fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { ATOMIC_INCL(frstats[0].fr_badsrc); + if (fr_chksrc == 2) + logit = -2; + } else if (ip->ip_ttl < fr_minttl) { + ATOMIC_INCL(frstats[0].fr_badttl); + if (fr_minttllog) + logit = -3; + } + } + if (drop) { # ifdef IPFILTER_LOG - if (fr_chksrc == 2) { - fin->fin_group = -2; - pass = FR_INQUE|FR_NOMATCH|FR_LOGB; - (void) IPLLOG(pass, ip, fin, m); - } + if (logit) { + fin->fin_group = logit; + pass = FR_INQUE|FR_NOMATCH|FR_LOGB; + (void) IPLLOG(pass, ip, fin, m); + } # endif # if !SOLARIS - m_freem(m); + m_freem(m); # endif - return error; - } + return error; + } #endif pass = fr_pass; if (fin->fin_fi.fi_fl & FI_SHORT) { @@ -1408,7 +1465,7 @@ nodata: * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.35.2.27 2000/10/26 21:20:54 darrenr Exp $ + * $Id: fil.c,v 2.35.2.30 2000/12/17 05:49:22 darrenr Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, diff --git a/sys/contrib/ipfilter/netinet/ip_auth.c b/sys/contrib/ipfilter/netinet/ip_auth.c index 7fb9d21..2931cc6 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.c +++ b/sys/contrib/ipfilter/netinet/ip_auth.c @@ -350,7 +350,7 @@ fr_authioctlloop: READ_ENTER(&ipf_auth); if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { error = IWCOPYPTR((char *)&fr_auth[fr_authnext], data, - sizeof(fr_info_t)); + sizeof(frauth_t)); RWLOCK_EXIT(&ipf_auth); if (error) break; diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h index c94dbbc..aefd50d 100644 --- a/sys/contrib/ipfilter/netinet/ip_compat.h +++ b/sys/contrib/ipfilter/netinet/ip_compat.h @@ -6,7 +6,7 @@ * to the original author and the contributors. * * @(#)ip_compat.h 1.8 1/14/96 - * $Id: ip_compat.h,v 2.1.2.3 1999/11/18 13:55:26 darrenr Exp $ + * $Id: ip_compat.h,v 2.26.2.9 2001/01/14 14:58:01 darrenr Exp $ * $FreeBSD$ */ @@ -975,8 +975,6 @@ struct ether_addr { #define A_A & #endif -#define TCPF_ALL (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) - #ifndef ICMP_ROUTERADVERT # define ICMP_ROUTERADVERT 9 #endif @@ -996,6 +994,20 @@ struct ether_addr { #define ICMPERR_IPICMPHLEN (20 + 8) #define ICMPERR_MINPKTLEN (20 + 8 + 20) #define ICMPERR_MAXPKTLEN (20 + 8 + 20 + 8) -#define ICMP6ERR_MINPKTLEN (20 + 8) +#define ICMP6ERR_MINPKTLEN (40 + 8) +#define ICMP6ERR_IPICMPHLEN (40 + 8 + 40) + +/* + * ECN is a new addition to TCP - RFC 2481 + */ +#ifndef TH_ECN +# define TH_ECN 0x40 +#endif +#ifndef TH_CWR +# define TH_CWR 0x80 +#endif +#define TH_ECNALL (TH_ECN|TH_CWR) + +#define TCPF_ALL (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|TH_ECN|TH_CWR) #endif /* __IP_COMPAT_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h index 4c24f9c..a960349 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.h +++ b/sys/contrib/ipfilter/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 2.29.2.3 2000/06/05 13:12:42 darrenr Exp $ + * $Id: ip_fil.h,v 2.29.2.4 2000/11/12 11:54:53 darrenr Exp $ * $FreeBSD$ */ @@ -336,6 +336,7 @@ typedef struct filterstats { u_long fr_tcpbad; /* TCP checksum check failures */ u_long fr_pull[2]; /* good and bad pullup attempts */ u_long fr_badsrc; /* source received doesn't match route */ + u_long fr_badttl; /* TTL in packet doesn't reach minimum */ #if SOLARIS u_long fr_notdata; /* PROTO/PCPROTO that have no data */ u_long fr_nodata; /* mblks that have no data */ @@ -615,6 +616,8 @@ extern int fr_pass; extern int fr_flags; extern int fr_active; extern int fr_chksrc; +extern int fr_minttl; +extern int fr_minttllog; extern fr_info_t frcache[2]; extern char ipfilter_version[]; extern iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1]; diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c index 2a10988..7e1b8be 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -7,7 +7,6 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed"; -/*static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.10.2.4 2000/06/06 15:49:15 darrenr Exp $";*/ static const char rcsid[] = "@(#)$FreeBSD$"; #endif @@ -157,6 +156,7 @@ ipfr_t *table[]; idx += ip->ip_src.s_addr; frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; idx += ip->ip_dst.s_addr; + frag.ipfr_ifp = fin->fin_ifp; idx *= 127; idx %= IPFT_SIZE; @@ -271,6 +271,7 @@ ipfr_t *table[]; idx += ip->ip_src.s_addr; frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; idx += ip->ip_dst.s_addr; + frag.ipfr_ifp = fin->fin_ifp; idx *= 127; idx %= IPFT_SIZE; @@ -329,16 +330,13 @@ fr_info_t *fin; ipf = ipfr_lookup(ip, fin, ipfr_nattab); if (ipf != NULL) { nat = ipf->ipfr_data; - if (nat->nat_ifp == fin->fin_ifp) { - /* - * This is the last fragment for this packet. - */ - if ((ipf->ipfr_ttl == 1) && (nat != NULL)) { - nat->nat_data = NULL; - ipf->ipfr_data = NULL; - } - } else - nat = NULL; + /* + * This is the last fragment for this packet. + */ + if ((ipf->ipfr_ttl == 1) && (nat != NULL)) { + nat->nat_data = NULL; + ipf->ipfr_data = NULL; + } } else nat = NULL; RWLOCK_EXIT(&ipf_natfrag); diff --git a/sys/contrib/ipfilter/netinet/ip_frag.h b/sys/contrib/ipfilter/netinet/ip_frag.h index 48144af..92e3e23 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.h +++ b/sys/contrib/ipfilter/netinet/ip_frag.h @@ -6,7 +6,7 @@ * to the original author and the contributors. * * @(#)ip_frag.h 1.5 3/24/96 - * $Id: ip_frag.h,v 2.2 1999/08/06 06:26:38 darrenr Exp $ + * $Id: ip_frag.h,v 2.4.2.2 2000/11/10 13:10:54 darrenr Exp $ * $FreeBSD$ */ @@ -20,6 +20,7 @@ typedef struct ipfr { void *ipfr_data; struct in_addr ipfr_src; struct in_addr ipfr_dst; + void *ipfr_ifp; u_short ipfr_id; u_char ipfr_p; u_char ipfr_tos; diff --git a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c index 42966fe..6e4fe53 100644 --- a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c @@ -1,6 +1,7 @@ /* * Simple FTP transparent proxy for in-kernel use. For use with the NAT * code. + * * $FreeBSD$ */ #if SOLARIS && defined(_KERNEL) @@ -237,7 +238,7 @@ int dlen; */ dp = htons(fin->fin_data[1] - 1); ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, - ip->ip_dst, (dp << 16) | sp); + ip->ip_dst, (dp << 16) | sp, 0); if (ipn == NULL) { int slen; @@ -253,7 +254,9 @@ int dlen; fi.fin_data[1] = 0; fi.fin_dlen = sizeof(*tcp2); fi.fin_dp = (char *)tcp2; + fi.fin_fr = &natfr; swip = ip->ip_src; + fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; ip->ip_src = nat->nat_inip; ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_DPORT, NAT_OUTBOUND); @@ -455,7 +458,7 @@ int dlen; sp = 0; dp = htons(fin->fin_data[1] - 1); ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, - ip->ip_dst, (dp << 16) | sp); + ip->ip_dst, (dp << 16) | sp, 0); if (ipn == NULL) { int slen; @@ -466,13 +469,16 @@ int dlen; tcp2->th_win = htons(8192); tcp2->th_sport = 0; /* XXX - fake it for nat_new */ tcp2->th_off = 5; - fi.fin_data[0] = a5 << 8 | a6; + fi.fin_data[1] = a5 << 8 | a6; fi.fin_dlen = sizeof(*tcp2); - tcp2->th_dport = htons(fi.fin_data[0]); - fi.fin_data[1] = 0; + tcp2->th_dport = htons(fi.fin_data[1]); + fi.fin_data[0] = 0; fi.fin_dp = (char *)tcp2; + fi.fin_fr = &natfr; swip = ip->ip_src; swip2 = ip->ip_dst; + fi.fin_fi.fi_daddr = ip->ip_src.s_addr; + fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; ip->ip_dst = ip->ip_src; ip->ip_src = nat->nat_inip; ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_SPORT, @@ -613,14 +619,18 @@ int rv; #else mlen = mbufchainlen(m) - off; #endif + t = &ftp->ftp_side[1 - rv]; + f = &ftp->ftp_side[rv]; if (!mlen) { - t->ftps_seq = ntohl(tcp->th_ack); + if (!t->ftps_seq || + (int)ntohl(tcp->th_ack) - (int)t->ftps_seq > 0) + t->ftps_seq = ntohl(tcp->th_ack); + f->ftps_len = 0; return 0; } inc = 0; - f = &ftp->ftp_side[rv]; rptr = f->ftps_rptr; wptr = f->ftps_wptr; @@ -634,9 +644,12 @@ int rv; * that it is out of order (and there is no real danger in doing so * apart from causing packets to go through here ordered). */ - if (ntohl(tcp->th_seq) + i != f->ftps_seq) { + if (f->ftps_len + f->ftps_seq == ntohl(tcp->th_seq)) + f->ftps_seq = ntohl(tcp->th_seq); + else if (ntohl(tcp->th_seq) + i != f->ftps_seq) { return APR_ERR(-1); } + f->ftps_len = mlen; while (mlen > 0) { len = MIN(mlen, FTP_BUFSZ / 2); diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index aa25ff3..55afed3 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -8,7 +8,7 @@ * Added redirect stuff and a LOT of bug fixes. (mcn@EnGarde.com) */ #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 2.37.2.32 2001/01/10 06:19:11 darrenr Exp $"; /*static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.37.2.16 2000/07/18 13:57:40 darrenr Exp $";*/ static const char rcsid[] = "@(#)$FreeBSD$"; #endif @@ -130,7 +130,7 @@ u_long fr_defnatage = DEF_NAT_AGE, natstat_t nat_stats; int fr_nat_lock = 0; #if (SOLARIS || defined(__sgi)) && defined(_KERNEL) -extern kmutex_t ipf_rw, ipf_hostmap; +extern kmutex_t ipf_rw; extern KRWLOCK_T ipf_nat; #endif @@ -144,7 +144,7 @@ static void nat_delnat __P((struct ipnat *)); static int fr_natgetent __P((caddr_t)); static int fr_natgetsz __P((caddr_t)); static int fr_natputent __P((caddr_t)); -static void nat_tabmove __P((nat_t *)); +static void nat_tabmove __P((nat_t *, u_32_t)); static int nat_match __P((fr_info_t *, ipnat_t *, ip_t *)); static hostmap_t *nat_hostmap __P((ipnat_t *, struct in_addr, struct in_addr)); @@ -251,6 +251,8 @@ ipnat_t *n; /* * check if an ip address has already been allocated for a given mapping that * is not doing port based translation. + * + * Must be called with ipf_nat held as a write lock. */ static struct hostmap *nat_hostmap(np, real, map) ipnat_t *np; @@ -260,13 +262,11 @@ struct in_addr map; hostmap_t *hm; u_int hv; - MUTEX_ENTER(&ipf_hostmap); hv = real.s_addr % HOSTMAP_SIZE; for (hm = maptable[hv]; hm; hm = hm->hm_next) if ((hm->hm_realip.s_addr == real.s_addr) && (np == hm->hm_ipnat)) { hm->hm_ref++; - MUTEX_EXIT(&ipf_hostmap); return hm; } @@ -282,15 +282,16 @@ struct in_addr map; hm->hm_mapip = map; hm->hm_ref = 1; } - MUTEX_EXIT(&ipf_hostmap); return hm; } +/* + * Must be called with ipf_nat held as a write lock. + */ static void nat_hostmapdel(hm) struct hostmap *hm; { - MUTEX_ENTER(&ipf_hostmap); ATOMIC_DEC32(hm->hm_ref); if (hm->hm_ref == 0) { if (hm->hm_next) @@ -298,7 +299,6 @@ struct hostmap *hm; *hm->hm_pnext = hm->hm_next; KFREE(hm); } - MUTEX_EXIT(&ipf_hostmap); } @@ -699,9 +699,9 @@ int mode; break; case FIONREAD : #ifdef IPFILTER_LOG + arg = (int)iplused[IPL_LOGNAT]; MUTEX_DOWNGRADE(&ipf_nat); - error = IWCOPY((caddr_t)&iplused[IPL_LOGNAT], (caddr_t)data, - sizeof(iplused[IPL_LOGNAT])); + error = IWCOPY((caddr_t)&arg, (caddr_t)data, sizeof(arg)); if (error) error = EFAULT; #endif @@ -1069,6 +1069,9 @@ static int nat_flushtable() for (natp = &nat_instances; (nat = *natp); ) { *natp = nat->nat_next; +#ifdef IPFILTER_LOG + nat_log(nat, NL_FLUSH); +#endif nat_delete(nat); j++; } @@ -1296,7 +1299,7 @@ int direction; inb.s_addr = htonl(in.s_addr); natl = nat_inlookup(fin->fin_ifp, flags & ~FI_WILDP, (u_int)ip->ip_p, ip->ip_dst, inb, - (port << 16) | dport); + (port << 16) | dport, 1); /* * Has the search wrapped around and come back to the @@ -1445,6 +1448,9 @@ int direction; tcp->th_dport = nport; } np->in_use++; +#ifdef IPFILTER_LOG + nat_log(nat, (u_int)np->in_redir); +#endif return nat; badnat: nat_stats.ns_badnat++; @@ -1566,18 +1572,18 @@ int dir; if (dir == NAT_INBOUND) return nat_inlookup(fin->fin_ifp, flags, (u_int)oip->ip_p, oip->ip_dst, oip->ip_src, - (tcp->th_sport << 16) | tcp->th_dport); + (tcp->th_sport << 16) | tcp->th_dport, 0); else return nat_outlookup(fin->fin_ifp, flags, (u_int)oip->ip_p, oip->ip_dst, oip->ip_src, - (tcp->th_sport << 16) | tcp->th_dport); + (tcp->th_sport << 16) | tcp->th_dport, 0); } if (dir == NAT_INBOUND) return nat_inlookup(fin->fin_ifp, 0, (u_int)oip->ip_p, - oip->ip_dst, oip->ip_src, 0); + oip->ip_dst, oip->ip_src, 0, 0); else return nat_outlookup(fin->fin_ifp, 0, (u_int)oip->ip_p, - oip->ip_dst, oip->ip_src, 0); + oip->ip_dst, oip->ip_src, 0, 0); } @@ -1591,7 +1597,7 @@ fr_info_t *fin; u_int *nflags; int dir; { - u_32_t sum1, sum2, sumd; + u_32_t sum1, sum2, sumd, sumd2 = 0; struct in_addr in; icmphdr_t *icmp; udphdr_t *udp; @@ -1640,7 +1646,7 @@ int dir; * in the first 8 bytes, so it will not be available in most cases. */ - if (nat->nat_dir == NAT_OUTBOUND) { + if (oip->ip_dst.s_addr == nat->nat_oip.s_addr) { sum1 = LONG_SUM(ntohl(oip->ip_src.s_addr)); in = nat->nat_inip; oip->ip_src = in; @@ -1692,7 +1698,7 @@ int dir; * checksum adjustment. */ CALC_SUMD(sum1, sum2, sumd); - fix_outcksum(&icmp->icmp_cksum, sumd); + sumd2 = sumd; } #if 0 @@ -1751,7 +1757,7 @@ int dir; * checksum adjustment. */ CALC_SUMD(sum1, sum2, sumd); - fix_incksum(&icmp->icmp_cksum, sumd); + sumd2 = sumd; } #if 0 @@ -1797,7 +1803,7 @@ int dir; * device that returns more than 8 data bytes on icmp error) */ - if (nat->nat_dir == NAT_OUTBOUND) { + if (nat->nat_oport == tcp->th_dport) { if (tcp->th_sport != nat->nat_inport) { /* * Fix ICMP checksum to compensate port @@ -1806,8 +1812,8 @@ int dir; sum1 = ntohs(tcp->th_sport); sum2 = ntohs(nat->nat_inport); CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; tcp->th_sport = nat->nat_inport; - fix_outcksum(&icmp->icmp_cksum, sumd); /* * Fix udp checksum to compensate port @@ -1830,11 +1836,10 @@ int dir; * adjustment. */ CALC_SUMD(sum1, sum2, sumd); - fix_outcksum(&icmp->icmp_cksum, sumd); + sumd2 += sumd; } } } else { - if (tcp->th_dport != nat->nat_outport) { /* * Fix ICMP checksum to compensate port @@ -1843,8 +1848,8 @@ int dir; sum1 = ntohs(tcp->th_dport); sum2 = ntohs(nat->nat_outport); CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; tcp->th_dport = nat->nat_outport; - fix_incksum(&icmp->icmp_cksum, sumd); /* * Fix udp checksum to compensate port @@ -1866,10 +1871,19 @@ int dir; * UDP checksum adjustment. */ CALC_SUMD(sum1, sum2, sumd); - fix_incksum(&icmp->icmp_cksum, sumd); + sumd2 += sumd; } } } + if (sumd2) { + sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); + sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); + if (nat->nat_dir == NAT_OUTBOUND) { + fix_outcksum(&icmp->icmp_cksum, sumd2); + } else { + fix_incksum(&icmp->icmp_cksum, sumd2); + } + } } nat->nat_age = fr_defnaticmpage; return nat; @@ -1886,11 +1900,12 @@ int dir; * we're looking for a table entry, based on the destination address. * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. */ -nat_t *nat_inlookup(ifp, flags, p, src, mapdst, ports) +nat_t *nat_inlookup(ifp, flags, p, src, mapdst, ports, rw) void *ifp; register u_int flags, p; struct in_addr src , mapdst; u_32_t ports; +int rw; { register u_short sport, dport; register nat_t *nat; @@ -1918,9 +1933,13 @@ u_32_t ports; } if (!nat_stats.ns_wilds || !(flags & IPN_TCPUDP)) return NULL; - RWLOCK_EXIT(&ipf_nat); + if (!rw) { + RWLOCK_EXIT(&ipf_nat); + } hv = NAT_HASH_FN(dst, 0, ipf_nattable_sz); - WRITE_ENTER(&ipf_nat); + if (!rw) { + WRITE_ENTER(&ipf_nat); + } nat = nat_table[1][hv]; for (; nat; nat = nat->nat_hnext[1]) { nflags = nat->nat_flags; @@ -1935,21 +1954,38 @@ u_32_t ports; continue; if (((nat->nat_oport == sport) || (nflags & FI_W_DPORT)) && ((nat->nat_outport == dport) || (nflags & FI_W_SPORT))) { - nat_tabmove(nat); + nat_tabmove(nat, ports); break; } } - MUTEX_DOWNGRADE(&ipf_nat); + if (!rw) { + MUTEX_DOWNGRADE(&ipf_nat); + } return nat; } -static void nat_tabmove(nat) +/* + * This function is only called for TCP/UDP NAT table entries where the + * original was placed in the table without hashing on the ports and we now + * want to include hashing on port numbers. + */ +static void nat_tabmove(nat, ports) nat_t *nat; +u_32_t ports; { + register u_short sport, dport; nat_t **natp; u_int hv; + dport = ports >> 16; + sport = ports & 0xffff; + + if (nat->nat_oport == dport) { + nat->nat_inport = sport; + nat->nat_outport = sport; + } + /* * Remove the NAT entry from the old location */ @@ -1964,8 +2000,7 @@ nat_t *nat; /* * Add into the NAT table in the new position */ - hv = NAT_HASH_FN(nat->nat_inip.s_addr, nat->nat_inport, - ipf_nattable_sz); + hv = NAT_HASH_FN(nat->nat_inip.s_addr, sport, ipf_nattable_sz); natp = &nat_table[0][hv]; if (*natp) (*natp)->nat_phnext[0] = &nat->nat_hnext[0]; @@ -1973,8 +2008,7 @@ nat_t *nat; nat->nat_hnext[0] = *natp; *natp = nat; - hv = NAT_HASH_FN(nat->nat_outip.s_addr, nat->nat_outport, - ipf_nattable_sz); + hv = NAT_HASH_FN(nat->nat_outip.s_addr, sport, ipf_nattable_sz); natp = &nat_table[1][hv]; if (*natp) (*natp)->nat_phnext[1] = &nat->nat_hnext[1]; @@ -1990,11 +2024,12 @@ nat_t *nat; * we're looking for a table entry, based on the source address. * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. */ -nat_t *nat_outlookup(ifp, flags, p, src, dst, ports) +nat_t *nat_outlookup(ifp, flags, p, src, dst, ports, rw) void *ifp; register u_int flags, p; struct in_addr src , dst; u_32_t ports; +int rw; { register u_short sport, dport; register nat_t *nat; @@ -2015,7 +2050,7 @@ u_32_t ports; if ((!ifp || ifp == nat->nat_ifp) && nat->nat_inip.s_addr == srcip && nat->nat_oip.s_addr == dst.s_addr && - (((p == 0) && (flags == (nat->nat_flags & IPN_TCPUDP))) + (((p == 0) && (flags == (nflags & IPN_TCPUDP))) || (p == nat->nat_p)) && (!flags || ((nat->nat_inport == sport || nflags & FI_W_SPORT) && (nat->nat_oport == dport || nflags & FI_W_DPORT)))) @@ -2023,9 +2058,13 @@ u_32_t ports; } if (!nat_stats.ns_wilds || !(flags & IPN_TCPUDP)) return NULL; - RWLOCK_EXIT(&ipf_nat); + if (!rw) { + RWLOCK_EXIT(&ipf_nat); + } hv = NAT_HASH_FN(srcip, 0, ipf_nattable_sz); - WRITE_ENTER(&ipf_nat); + if (!rw) { + WRITE_ENTER(&ipf_nat); + } nat = nat_table[0][hv]; for (; nat; nat = nat->nat_hnext[0]) { nflags = nat->nat_flags; @@ -2038,13 +2077,15 @@ u_32_t ports; if ((nat->nat_inip.s_addr != srcip) || (nat->nat_oip.s_addr != dst.s_addr)) continue; - if (((nat->nat_inport == sport) || (nflags & FI_W_DPORT)) && - ((nat->nat_oport == dport) || (nflags & FI_W_SPORT))) { - nat_tabmove(nat); + if (((nat->nat_inport == sport) || (nflags & FI_W_SPORT)) && + ((nat->nat_oport == dport) || (nflags & FI_W_DPORT))) { + nat_tabmove(nat, ports); break; } } - MUTEX_DOWNGRADE(&ipf_nat); + if (!rw) { + MUTEX_DOWNGRADE(&ipf_nat); + } return nat; } @@ -2064,7 +2105,7 @@ register natlookup_t *np; * ip address. Else, we use the fake. */ if ((nat = nat_outlookup(NULL, np->nl_flags, 0, np->nl_inip, - np->nl_outip, ports))) { + np->nl_outip, ports, 0))) { np->nl_realip = nat->nat_outip; np->nl_realport = nat->nat_outport; } @@ -2165,10 +2206,11 @@ fr_info_t *fin; (nat = nat_icmp(ip, fin, &nflags, NAT_OUTBOUND))) ; else if ((ip->ip_off & (IP_OFFMASK|IP_MF)) && - (nat = ipfr_nat_knownfrag(ip, fin))) + (nat = ipfr_nat_knownfrag(ip, fin))) natadd = 0; - else if ((nat = nat_outlookup(ifp, nflags, (u_int)ip->ip_p, ip->ip_src, - ip->ip_dst, (dport << 16) | sport))) { + else if ((nat = nat_outlookup(ifp, nflags, (u_int)ip->ip_p, + ip->ip_src, ip->ip_dst, + (dport << 16) | sport, 0))) { nflags = nat->nat_flags; if ((nflags & (FI_W_SPORT|FI_W_DPORT)) != 0) { if ((nflags & FI_W_SPORT) && @@ -2222,9 +2264,6 @@ maskloop: if ((nat = nat_new(np, ip, fin, (u_int)nflags, NAT_OUTBOUND))) { np->in_hits++; -#ifdef IPFILTER_LOG - nat_log(nat, (u_int)np->in_redir); -#endif break; } } @@ -2240,6 +2279,9 @@ maskloop: MUTEX_DOWNGRADE(&ipf_nat); } + /* + * NOTE: ipf_nat must now only be held as a read lock + */ if (nat) { np = nat->nat_ptr; if (natadd && fin->fin_fi.fi_fl & FI_FRAG) @@ -2384,7 +2426,8 @@ fr_info_t *fin; (nat = ipfr_nat_knownfrag(ip, fin))) natadd = 0; else if ((nat = nat_inlookup(fin->fin_ifp, nflags, (u_int)ip->ip_p, - ip->ip_src, in, (dport << 16) | sport))) { + ip->ip_src, in, (dport << 16) | sport, + 0))) { nflags = nat->nat_flags; if ((nflags & (FI_W_SPORT|FI_W_DPORT)) != 0) { if ((nat->nat_oport != sport) && (nflags & FI_W_DPORT)) @@ -2425,9 +2468,6 @@ maskloop: if ((nat = nat_new(np, ip, fin, nflags, NAT_INBOUND))) { np->in_hits++; -#ifdef IPFILTER_LOG - nat_log(nat, (u_int)np->in_redir); -#endif break; } } @@ -2442,6 +2482,10 @@ maskloop: } MUTEX_DOWNGRADE(&ipf_nat); } + + /* + * NOTE: ipf_nat must now only be held as a read lock + */ if (nat) { np = nat->nat_ptr; fin->fin_fr = nat->nat_fr; diff --git a/sys/contrib/ipfilter/netinet/ip_nat.h b/sys/contrib/ipfilter/netinet/ip_nat.h index da192b3..374a20b 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.h +++ b/sys/contrib/ipfilter/netinet/ip_nat.h @@ -6,7 +6,7 @@ * to the original author and the contributors. * * @(#)ip_nat.h 1.5 2/4/96 - * $Id: ip_nat.h,v 2.17.2.6 2000/07/15 14:50:06 darrenr Exp $ + * $Id: ip_nat.h,v 2.17.2.14 2000/11/18 03:58:04 darrenr Exp $ * $FreeBSD$ */ @@ -86,7 +86,7 @@ typedef struct nat { void *nat_ifp; int nat_dir; char nat_ifname[IFNAMSIZ]; -#if SOLARIS || defined(_sgi) +#if SOLARIS || defined(__sgi) kmutex_t nat_lock; #endif } nat_t; @@ -248,6 +248,7 @@ typedef struct natlog { #define NL_NEWRDR NAT_REDIRECT #define NL_NEWBIMAP NAT_BIMAP #define NL_NEWBLOCK NAT_MAPBLK +#define NL_FLUSH 0xfffe #define NL_EXPIRE 0xffff #define NAT_HASH_FN(k,l,m) (((k) + ((k) >> 12) + l) % (m)) @@ -286,9 +287,9 @@ extern int nat_ioctl __P((caddr_t, int, int)); extern int nat_init __P((void)); extern nat_t *nat_new __P((ipnat_t *, ip_t *, fr_info_t *, u_int, int)); extern nat_t *nat_outlookup __P((void *, u_int, u_int, struct in_addr, - struct in_addr, u_32_t)); + struct in_addr, u_32_t, int)); extern nat_t *nat_inlookup __P((void *, u_int, u_int, struct in_addr, - struct in_addr, u_32_t)); + struct in_addr, u_32_t, int)); extern nat_t *nat_maplookup __P((void *, u_int, struct in_addr, struct in_addr)); extern nat_t *nat_lookupredir __P((natlookup_t *)); diff --git a/sys/contrib/ipfilter/netinet/ip_proxy.h b/sys/contrib/ipfilter/netinet/ip_proxy.h index edee695..f22c709 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.h +++ b/sys/contrib/ipfilter/netinet/ip_proxy.h @@ -5,7 +5,7 @@ * provided that this notice is preserved and due credit is given * to the original author and the contributors. * - * $Id: ip_proxy.h,v 2.1.2.1 1999/09/19 12:18:20 darrenr Exp $ + * $Id: ip_proxy.h,v 2.8.2.4 2000/12/02 00:15:03 darrenr Exp $ * $FreeBSD$ */ @@ -97,6 +97,7 @@ typedef struct ftpside { char *ftps_rptr; char *ftps_wptr; u_32_t ftps_seq; + u_32_t ftps_len; int ftps_junk; char ftps_buf[FTP_BUFSZ]; } ftpside_t; diff --git a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c index 5baabbf..0ae0210 100644 --- a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c @@ -1,5 +1,5 @@ /* - * $Id: ip_rcmd_pxy.c,v 1.4.2.3 2000/10/27 22:54:04 darrenr Exp $ + * $Id: ip_rcmd_pxy.c,v 1.4.2.4 2000/11/01 14:34:20 darrenr Exp $ */ /* * Simple RCMD transparent proxy for in-kernel use. For use with the NAT @@ -132,7 +132,7 @@ nat_t *nat; sp = htons(sp); dp = htons(fin->fin_data[1]); ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, - ip->ip_dst, (dp << 16) | sp); + ip->ip_dst, (dp << 16) | sp, 0); if (ipn == NULL) { int slen; diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index 1e4c851..c051c9e 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -307,8 +307,8 @@ int mode; break; case FIONREAD : #ifdef IPFILTER_LOG - error = IWCOPY((caddr_t)&iplused[IPL_LOGSTATE], (caddr_t)data, - sizeof(iplused[IPL_LOGSTATE])); + arg = (int)iplused[IPL_LOGSTATE]; + error = IWCOPY((caddr_t)&arg, (caddr_t)data, sizeof(arg)); #endif break; case SIOCSTLCK : @@ -787,8 +787,6 @@ tcphdr_t *tcp; } ATOMIC_INCL(ips_stats.iss_hits); - is->is_pkts++; - is->is_bytes += fin->fin_dlen + fin->fin_hlen; /* * Nearing end of connection, start timeout. */ @@ -1148,10 +1146,6 @@ fr_info_t *fin; fr_matchsrcdst(is, src, dst, &ofin, tcp)) { fr = is->is_rule; ips_stats.iss_hits++; - /* - * we must swap src and dst here because the icmp - * comes the other way around - */ is->is_pkts++; is->is_bytes += fin->fin_plen; /* @@ -1379,6 +1373,9 @@ void *ifp; } +/* + * Must always be called with fr_ipfstate held as a write lock. + */ static void fr_delstate(is) ipstate_t *is; { @@ -1397,9 +1394,10 @@ ipstate_t *is; fr = is->is_rule; if (fr != NULL) { - ATOMIC_DEC32(fr->fr_ref); - if (fr->fr_ref == 0) + fr->fr_ref--; + if (fr->fr_ref == 0) { KFREE(fr); + } } #ifdef _KERNEL MUTEX_DESTROY(&is->is_lock); @@ -1452,12 +1450,12 @@ void fr_timeoutstate() fr_delstate(is); } else isp = &is->is_next; - RWLOCK_EXIT(&ipf_state); - SPL_X(s); if (fr_state_doflush) { (void) fr_state_flush(1); fr_state_doflush = 0; } + RWLOCK_EXIT(&ipf_state); + SPL_X(s); } diff --git a/sys/contrib/ipfilter/netinet/ipl.h b/sys/contrib/ipfilter/netinet/ipl.h index 94bae8d..79d0bd3 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -12,6 +12,6 @@ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v3.4.13" +#define IPL_VERSION "IP Filter: v3.4.16" #endif diff --git a/sys/contrib/ipfilter/netinet/mlfk_ipl.c b/sys/contrib/ipfilter/netinet/mlfk_ipl.c index 1be8916..7a7971f 100644 --- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c +++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c @@ -38,6 +38,12 @@ #include <netinet/in_systm.h> #include <netinet/in.h> #include <netinet/ip.h> +#if (__FreeBSD_version >= 199511) +# include <net/route.h> +# include <netinet/ip_var.h> +# include <netinet/tcp.h> +# include <netinet/tcpip.h> +#endif #include <netinet/ipl.h> @@ -47,6 +53,7 @@ #include <netinet/ip_nat.h> #include <netinet/ip_auth.h> #include <netinet/ip_frag.h> +#include <netinet/ip_proxy.h> static dev_t ipf_devs[IPL_LOGMAX + 1]; @@ -86,6 +93,11 @@ SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD, SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW, &fr_defaultauthage, 0, ""); SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, ""); +SYSCTL_INT(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW, + &ippr_ftp_pasvonly, 0, ""); +SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, ""); +SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttllog, CTLFLAG_RW, + &fr_minttllog, 0, ""); #define CDEV_MAJOR 79 static struct cdevsw ipl_cdevsw = { diff --git a/sys/netinet/fil.c b/sys/netinet/fil.c index dcfd65d..6d4622e 100644 --- a/sys/netinet/fil.c +++ b/sys/netinet/fil.c @@ -6,7 +6,7 @@ * to the original author and the contributors. */ #if !defined(lint) -static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed"; +static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; /* static const char rcsid[] = "@(#)$Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $"; */ static const char rcsid[] = "@(#)$FreeBSD$"; #endif @@ -139,6 +139,8 @@ struct frgroup *ipfgroups[3][2]; int fr_flags = IPF_LOGGING; int fr_active = 0; int fr_chksrc = 0; +int fr_minttl = 3; +int fr_minttllog = 1; #if defined(IPFILTER_DEFAULT_BLOCK) int fr_pass = FR_NOMATCH|FR_BLOCK; #else @@ -272,6 +274,40 @@ fr_info_t *fin; switch (p) { +#ifdef USE_INET6 + case IPPROTO_ICMPV6 : + { + int minicmpsz = sizeof(struct icmp6_hdr); + struct icmp6_hdr *icmp6; + + if (fin->fin_dlen > 1) { + fin->fin_data[0] = *(u_short *)tcp; + + icmp6 = (struct icmp6_hdr *)tcp; + + switch (icmp6->icmp6_type) + { + case ICMP6_ECHO_REPLY : + case ICMP6_ECHO_REQUEST : + minicmpsz = ICMP6ERR_MINPKTLEN; + break; + case ICMP6_DST_UNREACH : + case ICMP6_PACKET_TOO_BIG : + case ICMP6_TIME_EXCEEDED : + case ICMP6_PARAM_PROB : + minicmpsz = ICMP6ERR_IPICMPHLEN; + break; + default : + break; + } + } + + if (!(plen >= hlen + minicmpsz)) + fi->fi_fl |= FI_SHORT; + + break; + } +#endif case IPPROTO_ICMP : { int minicmpsz = sizeof(struct icmp); @@ -750,8 +786,8 @@ int out; #endif #ifdef _KERNEL + int p, len, drop = 0, logit = 0; mb_t *mc = NULL; - int p, len; # if !defined(__SVR4) && !defined(__svr4__) # ifdef __sgi char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8]; @@ -805,11 +841,17 @@ int out; break; /* 96 - enough for complete ICMP error IP header */ case IPPROTO_ICMP: + plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); + break; # ifdef USE_INET6 case IPPROTO_ICMPV6 : -# endif - plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); + /* + * XXX does not take intermediate header + * into account + */ + plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t); break; +# endif } up = MIN(hlen + plen, len); @@ -870,22 +912,37 @@ int out; # ifdef USE_INET6 if (v == 6) { ATOMIC_INCL(frstats[0].fr_ipv6[out]); + if (((ip6_t *)ip)->ip6_hlim < fr_minttl) { + ATOMIC_INCL(frstats[0].fr_badttl); + if (fr_minttllog) + logit = -2; + } } else # endif - if (!out && fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { + if (!out) { + if (fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { ATOMIC_INCL(frstats[0].fr_badsrc); + if (fr_chksrc == 2) + logit = -2; + } else if (ip->ip_ttl < fr_minttl) { + ATOMIC_INCL(frstats[0].fr_badttl); + if (fr_minttllog) + logit = -3; + } + } + if (drop) { # ifdef IPFILTER_LOG - if (fr_chksrc == 2) { - fin->fin_group = -2; - pass = FR_INQUE|FR_NOMATCH|FR_LOGB; - (void) IPLLOG(pass, ip, fin, m); - } + if (logit) { + fin->fin_group = logit; + pass = FR_INQUE|FR_NOMATCH|FR_LOGB; + (void) IPLLOG(pass, ip, fin, m); + } # endif # if !SOLARIS - m_freem(m); + m_freem(m); # endif - return error; - } + return error; + } #endif pass = fr_pass; if (fin->fin_fi.fi_fl & FI_SHORT) { @@ -1408,7 +1465,7 @@ nodata: * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.35.2.27 2000/10/26 21:20:54 darrenr Exp $ + * $Id: fil.c,v 2.35.2.30 2000/12/17 05:49:22 darrenr 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 7fb9d21..2931cc6 100644 --- a/sys/netinet/ip_auth.c +++ b/sys/netinet/ip_auth.c @@ -350,7 +350,7 @@ fr_authioctlloop: READ_ENTER(&ipf_auth); if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { error = IWCOPYPTR((char *)&fr_auth[fr_authnext], data, - sizeof(fr_info_t)); + sizeof(frauth_t)); RWLOCK_EXIT(&ipf_auth); if (error) break; diff --git a/sys/netinet/ip_compat.h b/sys/netinet/ip_compat.h index c94dbbc..aefd50d 100644 --- a/sys/netinet/ip_compat.h +++ b/sys/netinet/ip_compat.h @@ -6,7 +6,7 @@ * to the original author and the contributors. * * @(#)ip_compat.h 1.8 1/14/96 - * $Id: ip_compat.h,v 2.1.2.3 1999/11/18 13:55:26 darrenr Exp $ + * $Id: ip_compat.h,v 2.26.2.9 2001/01/14 14:58:01 darrenr Exp $ * $FreeBSD$ */ @@ -975,8 +975,6 @@ struct ether_addr { #define A_A & #endif -#define TCPF_ALL (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) - #ifndef ICMP_ROUTERADVERT # define ICMP_ROUTERADVERT 9 #endif @@ -996,6 +994,20 @@ struct ether_addr { #define ICMPERR_IPICMPHLEN (20 + 8) #define ICMPERR_MINPKTLEN (20 + 8 + 20) #define ICMPERR_MAXPKTLEN (20 + 8 + 20 + 8) -#define ICMP6ERR_MINPKTLEN (20 + 8) +#define ICMP6ERR_MINPKTLEN (40 + 8) +#define ICMP6ERR_IPICMPHLEN (40 + 8 + 40) + +/* + * ECN is a new addition to TCP - RFC 2481 + */ +#ifndef TH_ECN +# define TH_ECN 0x40 +#endif +#ifndef TH_CWR +# define TH_CWR 0x80 +#endif +#define TH_ECNALL (TH_ECN|TH_CWR) + +#define TCPF_ALL (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|TH_ECN|TH_CWR) #endif /* __IP_COMPAT_H__ */ diff --git a/sys/netinet/ip_fil.h b/sys/netinet/ip_fil.h index 4c24f9c..a960349 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 2.29.2.3 2000/06/05 13:12:42 darrenr Exp $ + * $Id: ip_fil.h,v 2.29.2.4 2000/11/12 11:54:53 darrenr Exp $ * $FreeBSD$ */ @@ -336,6 +336,7 @@ typedef struct filterstats { u_long fr_tcpbad; /* TCP checksum check failures */ u_long fr_pull[2]; /* good and bad pullup attempts */ u_long fr_badsrc; /* source received doesn't match route */ + u_long fr_badttl; /* TTL in packet doesn't reach minimum */ #if SOLARIS u_long fr_notdata; /* PROTO/PCPROTO that have no data */ u_long fr_nodata; /* mblks that have no data */ @@ -615,6 +616,8 @@ extern int fr_pass; extern int fr_flags; extern int fr_active; extern int fr_chksrc; +extern int fr_minttl; +extern int fr_minttllog; extern fr_info_t frcache[2]; extern char ipfilter_version[]; extern iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1]; diff --git a/sys/netinet/ip_frag.c b/sys/netinet/ip_frag.c index 2a10988..7e1b8be 100644 --- a/sys/netinet/ip_frag.c +++ b/sys/netinet/ip_frag.c @@ -7,7 +7,6 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed"; -/*static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.10.2.4 2000/06/06 15:49:15 darrenr Exp $";*/ static const char rcsid[] = "@(#)$FreeBSD$"; #endif @@ -157,6 +156,7 @@ ipfr_t *table[]; idx += ip->ip_src.s_addr; frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; idx += ip->ip_dst.s_addr; + frag.ipfr_ifp = fin->fin_ifp; idx *= 127; idx %= IPFT_SIZE; @@ -271,6 +271,7 @@ ipfr_t *table[]; idx += ip->ip_src.s_addr; frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; idx += ip->ip_dst.s_addr; + frag.ipfr_ifp = fin->fin_ifp; idx *= 127; idx %= IPFT_SIZE; @@ -329,16 +330,13 @@ fr_info_t *fin; ipf = ipfr_lookup(ip, fin, ipfr_nattab); if (ipf != NULL) { nat = ipf->ipfr_data; - if (nat->nat_ifp == fin->fin_ifp) { - /* - * This is the last fragment for this packet. - */ - if ((ipf->ipfr_ttl == 1) && (nat != NULL)) { - nat->nat_data = NULL; - ipf->ipfr_data = NULL; - } - } else - nat = NULL; + /* + * This is the last fragment for this packet. + */ + if ((ipf->ipfr_ttl == 1) && (nat != NULL)) { + nat->nat_data = NULL; + ipf->ipfr_data = NULL; + } } else nat = NULL; RWLOCK_EXIT(&ipf_natfrag); diff --git a/sys/netinet/ip_frag.h b/sys/netinet/ip_frag.h index 48144af..92e3e23 100644 --- a/sys/netinet/ip_frag.h +++ b/sys/netinet/ip_frag.h @@ -6,7 +6,7 @@ * to the original author and the contributors. * * @(#)ip_frag.h 1.5 3/24/96 - * $Id: ip_frag.h,v 2.2 1999/08/06 06:26:38 darrenr Exp $ + * $Id: ip_frag.h,v 2.4.2.2 2000/11/10 13:10:54 darrenr Exp $ * $FreeBSD$ */ @@ -20,6 +20,7 @@ typedef struct ipfr { void *ipfr_data; struct in_addr ipfr_src; struct in_addr ipfr_dst; + void *ipfr_ifp; u_short ipfr_id; u_char ipfr_p; u_char ipfr_tos; diff --git a/sys/netinet/ip_ftp_pxy.c b/sys/netinet/ip_ftp_pxy.c index 42966fe..6e4fe53 100644 --- a/sys/netinet/ip_ftp_pxy.c +++ b/sys/netinet/ip_ftp_pxy.c @@ -1,6 +1,7 @@ /* * Simple FTP transparent proxy for in-kernel use. For use with the NAT * code. + * * $FreeBSD$ */ #if SOLARIS && defined(_KERNEL) @@ -237,7 +238,7 @@ int dlen; */ dp = htons(fin->fin_data[1] - 1); ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, - ip->ip_dst, (dp << 16) | sp); + ip->ip_dst, (dp << 16) | sp, 0); if (ipn == NULL) { int slen; @@ -253,7 +254,9 @@ int dlen; fi.fin_data[1] = 0; fi.fin_dlen = sizeof(*tcp2); fi.fin_dp = (char *)tcp2; + fi.fin_fr = &natfr; swip = ip->ip_src; + fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; ip->ip_src = nat->nat_inip; ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_DPORT, NAT_OUTBOUND); @@ -455,7 +458,7 @@ int dlen; sp = 0; dp = htons(fin->fin_data[1] - 1); ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, - ip->ip_dst, (dp << 16) | sp); + ip->ip_dst, (dp << 16) | sp, 0); if (ipn == NULL) { int slen; @@ -466,13 +469,16 @@ int dlen; tcp2->th_win = htons(8192); tcp2->th_sport = 0; /* XXX - fake it for nat_new */ tcp2->th_off = 5; - fi.fin_data[0] = a5 << 8 | a6; + fi.fin_data[1] = a5 << 8 | a6; fi.fin_dlen = sizeof(*tcp2); - tcp2->th_dport = htons(fi.fin_data[0]); - fi.fin_data[1] = 0; + tcp2->th_dport = htons(fi.fin_data[1]); + fi.fin_data[0] = 0; fi.fin_dp = (char *)tcp2; + fi.fin_fr = &natfr; swip = ip->ip_src; swip2 = ip->ip_dst; + fi.fin_fi.fi_daddr = ip->ip_src.s_addr; + fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; ip->ip_dst = ip->ip_src; ip->ip_src = nat->nat_inip; ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_SPORT, @@ -613,14 +619,18 @@ int rv; #else mlen = mbufchainlen(m) - off; #endif + t = &ftp->ftp_side[1 - rv]; + f = &ftp->ftp_side[rv]; if (!mlen) { - t->ftps_seq = ntohl(tcp->th_ack); + if (!t->ftps_seq || + (int)ntohl(tcp->th_ack) - (int)t->ftps_seq > 0) + t->ftps_seq = ntohl(tcp->th_ack); + f->ftps_len = 0; return 0; } inc = 0; - f = &ftp->ftp_side[rv]; rptr = f->ftps_rptr; wptr = f->ftps_wptr; @@ -634,9 +644,12 @@ int rv; * that it is out of order (and there is no real danger in doing so * apart from causing packets to go through here ordered). */ - if (ntohl(tcp->th_seq) + i != f->ftps_seq) { + if (f->ftps_len + f->ftps_seq == ntohl(tcp->th_seq)) + f->ftps_seq = ntohl(tcp->th_seq); + else if (ntohl(tcp->th_seq) + i != f->ftps_seq) { return APR_ERR(-1); } + f->ftps_len = mlen; while (mlen > 0) { len = MIN(mlen, FTP_BUFSZ / 2); diff --git a/sys/netinet/ip_nat.c b/sys/netinet/ip_nat.c index aa25ff3..55afed3 100644 --- a/sys/netinet/ip_nat.c +++ b/sys/netinet/ip_nat.c @@ -8,7 +8,7 @@ * Added redirect stuff and a LOT of bug fixes. (mcn@EnGarde.com) */ #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 2.37.2.32 2001/01/10 06:19:11 darrenr Exp $"; /*static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.37.2.16 2000/07/18 13:57:40 darrenr Exp $";*/ static const char rcsid[] = "@(#)$FreeBSD$"; #endif @@ -130,7 +130,7 @@ u_long fr_defnatage = DEF_NAT_AGE, natstat_t nat_stats; int fr_nat_lock = 0; #if (SOLARIS || defined(__sgi)) && defined(_KERNEL) -extern kmutex_t ipf_rw, ipf_hostmap; +extern kmutex_t ipf_rw; extern KRWLOCK_T ipf_nat; #endif @@ -144,7 +144,7 @@ static void nat_delnat __P((struct ipnat *)); static int fr_natgetent __P((caddr_t)); static int fr_natgetsz __P((caddr_t)); static int fr_natputent __P((caddr_t)); -static void nat_tabmove __P((nat_t *)); +static void nat_tabmove __P((nat_t *, u_32_t)); static int nat_match __P((fr_info_t *, ipnat_t *, ip_t *)); static hostmap_t *nat_hostmap __P((ipnat_t *, struct in_addr, struct in_addr)); @@ -251,6 +251,8 @@ ipnat_t *n; /* * check if an ip address has already been allocated for a given mapping that * is not doing port based translation. + * + * Must be called with ipf_nat held as a write lock. */ static struct hostmap *nat_hostmap(np, real, map) ipnat_t *np; @@ -260,13 +262,11 @@ struct in_addr map; hostmap_t *hm; u_int hv; - MUTEX_ENTER(&ipf_hostmap); hv = real.s_addr % HOSTMAP_SIZE; for (hm = maptable[hv]; hm; hm = hm->hm_next) if ((hm->hm_realip.s_addr == real.s_addr) && (np == hm->hm_ipnat)) { hm->hm_ref++; - MUTEX_EXIT(&ipf_hostmap); return hm; } @@ -282,15 +282,16 @@ struct in_addr map; hm->hm_mapip = map; hm->hm_ref = 1; } - MUTEX_EXIT(&ipf_hostmap); return hm; } +/* + * Must be called with ipf_nat held as a write lock. + */ static void nat_hostmapdel(hm) struct hostmap *hm; { - MUTEX_ENTER(&ipf_hostmap); ATOMIC_DEC32(hm->hm_ref); if (hm->hm_ref == 0) { if (hm->hm_next) @@ -298,7 +299,6 @@ struct hostmap *hm; *hm->hm_pnext = hm->hm_next; KFREE(hm); } - MUTEX_EXIT(&ipf_hostmap); } @@ -699,9 +699,9 @@ int mode; break; case FIONREAD : #ifdef IPFILTER_LOG + arg = (int)iplused[IPL_LOGNAT]; MUTEX_DOWNGRADE(&ipf_nat); - error = IWCOPY((caddr_t)&iplused[IPL_LOGNAT], (caddr_t)data, - sizeof(iplused[IPL_LOGNAT])); + error = IWCOPY((caddr_t)&arg, (caddr_t)data, sizeof(arg)); if (error) error = EFAULT; #endif @@ -1069,6 +1069,9 @@ static int nat_flushtable() for (natp = &nat_instances; (nat = *natp); ) { *natp = nat->nat_next; +#ifdef IPFILTER_LOG + nat_log(nat, NL_FLUSH); +#endif nat_delete(nat); j++; } @@ -1296,7 +1299,7 @@ int direction; inb.s_addr = htonl(in.s_addr); natl = nat_inlookup(fin->fin_ifp, flags & ~FI_WILDP, (u_int)ip->ip_p, ip->ip_dst, inb, - (port << 16) | dport); + (port << 16) | dport, 1); /* * Has the search wrapped around and come back to the @@ -1445,6 +1448,9 @@ int direction; tcp->th_dport = nport; } np->in_use++; +#ifdef IPFILTER_LOG + nat_log(nat, (u_int)np->in_redir); +#endif return nat; badnat: nat_stats.ns_badnat++; @@ -1566,18 +1572,18 @@ int dir; if (dir == NAT_INBOUND) return nat_inlookup(fin->fin_ifp, flags, (u_int)oip->ip_p, oip->ip_dst, oip->ip_src, - (tcp->th_sport << 16) | tcp->th_dport); + (tcp->th_sport << 16) | tcp->th_dport, 0); else return nat_outlookup(fin->fin_ifp, flags, (u_int)oip->ip_p, oip->ip_dst, oip->ip_src, - (tcp->th_sport << 16) | tcp->th_dport); + (tcp->th_sport << 16) | tcp->th_dport, 0); } if (dir == NAT_INBOUND) return nat_inlookup(fin->fin_ifp, 0, (u_int)oip->ip_p, - oip->ip_dst, oip->ip_src, 0); + oip->ip_dst, oip->ip_src, 0, 0); else return nat_outlookup(fin->fin_ifp, 0, (u_int)oip->ip_p, - oip->ip_dst, oip->ip_src, 0); + oip->ip_dst, oip->ip_src, 0, 0); } @@ -1591,7 +1597,7 @@ fr_info_t *fin; u_int *nflags; int dir; { - u_32_t sum1, sum2, sumd; + u_32_t sum1, sum2, sumd, sumd2 = 0; struct in_addr in; icmphdr_t *icmp; udphdr_t *udp; @@ -1640,7 +1646,7 @@ int dir; * in the first 8 bytes, so it will not be available in most cases. */ - if (nat->nat_dir == NAT_OUTBOUND) { + if (oip->ip_dst.s_addr == nat->nat_oip.s_addr) { sum1 = LONG_SUM(ntohl(oip->ip_src.s_addr)); in = nat->nat_inip; oip->ip_src = in; @@ -1692,7 +1698,7 @@ int dir; * checksum adjustment. */ CALC_SUMD(sum1, sum2, sumd); - fix_outcksum(&icmp->icmp_cksum, sumd); + sumd2 = sumd; } #if 0 @@ -1751,7 +1757,7 @@ int dir; * checksum adjustment. */ CALC_SUMD(sum1, sum2, sumd); - fix_incksum(&icmp->icmp_cksum, sumd); + sumd2 = sumd; } #if 0 @@ -1797,7 +1803,7 @@ int dir; * device that returns more than 8 data bytes on icmp error) */ - if (nat->nat_dir == NAT_OUTBOUND) { + if (nat->nat_oport == tcp->th_dport) { if (tcp->th_sport != nat->nat_inport) { /* * Fix ICMP checksum to compensate port @@ -1806,8 +1812,8 @@ int dir; sum1 = ntohs(tcp->th_sport); sum2 = ntohs(nat->nat_inport); CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; tcp->th_sport = nat->nat_inport; - fix_outcksum(&icmp->icmp_cksum, sumd); /* * Fix udp checksum to compensate port @@ -1830,11 +1836,10 @@ int dir; * adjustment. */ CALC_SUMD(sum1, sum2, sumd); - fix_outcksum(&icmp->icmp_cksum, sumd); + sumd2 += sumd; } } } else { - if (tcp->th_dport != nat->nat_outport) { /* * Fix ICMP checksum to compensate port @@ -1843,8 +1848,8 @@ int dir; sum1 = ntohs(tcp->th_dport); sum2 = ntohs(nat->nat_outport); CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; tcp->th_dport = nat->nat_outport; - fix_incksum(&icmp->icmp_cksum, sumd); /* * Fix udp checksum to compensate port @@ -1866,10 +1871,19 @@ int dir; * UDP checksum adjustment. */ CALC_SUMD(sum1, sum2, sumd); - fix_incksum(&icmp->icmp_cksum, sumd); + sumd2 += sumd; } } } + if (sumd2) { + sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); + sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); + if (nat->nat_dir == NAT_OUTBOUND) { + fix_outcksum(&icmp->icmp_cksum, sumd2); + } else { + fix_incksum(&icmp->icmp_cksum, sumd2); + } + } } nat->nat_age = fr_defnaticmpage; return nat; @@ -1886,11 +1900,12 @@ int dir; * we're looking for a table entry, based on the destination address. * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. */ -nat_t *nat_inlookup(ifp, flags, p, src, mapdst, ports) +nat_t *nat_inlookup(ifp, flags, p, src, mapdst, ports, rw) void *ifp; register u_int flags, p; struct in_addr src , mapdst; u_32_t ports; +int rw; { register u_short sport, dport; register nat_t *nat; @@ -1918,9 +1933,13 @@ u_32_t ports; } if (!nat_stats.ns_wilds || !(flags & IPN_TCPUDP)) return NULL; - RWLOCK_EXIT(&ipf_nat); + if (!rw) { + RWLOCK_EXIT(&ipf_nat); + } hv = NAT_HASH_FN(dst, 0, ipf_nattable_sz); - WRITE_ENTER(&ipf_nat); + if (!rw) { + WRITE_ENTER(&ipf_nat); + } nat = nat_table[1][hv]; for (; nat; nat = nat->nat_hnext[1]) { nflags = nat->nat_flags; @@ -1935,21 +1954,38 @@ u_32_t ports; continue; if (((nat->nat_oport == sport) || (nflags & FI_W_DPORT)) && ((nat->nat_outport == dport) || (nflags & FI_W_SPORT))) { - nat_tabmove(nat); + nat_tabmove(nat, ports); break; } } - MUTEX_DOWNGRADE(&ipf_nat); + if (!rw) { + MUTEX_DOWNGRADE(&ipf_nat); + } return nat; } -static void nat_tabmove(nat) +/* + * This function is only called for TCP/UDP NAT table entries where the + * original was placed in the table without hashing on the ports and we now + * want to include hashing on port numbers. + */ +static void nat_tabmove(nat, ports) nat_t *nat; +u_32_t ports; { + register u_short sport, dport; nat_t **natp; u_int hv; + dport = ports >> 16; + sport = ports & 0xffff; + + if (nat->nat_oport == dport) { + nat->nat_inport = sport; + nat->nat_outport = sport; + } + /* * Remove the NAT entry from the old location */ @@ -1964,8 +2000,7 @@ nat_t *nat; /* * Add into the NAT table in the new position */ - hv = NAT_HASH_FN(nat->nat_inip.s_addr, nat->nat_inport, - ipf_nattable_sz); + hv = NAT_HASH_FN(nat->nat_inip.s_addr, sport, ipf_nattable_sz); natp = &nat_table[0][hv]; if (*natp) (*natp)->nat_phnext[0] = &nat->nat_hnext[0]; @@ -1973,8 +2008,7 @@ nat_t *nat; nat->nat_hnext[0] = *natp; *natp = nat; - hv = NAT_HASH_FN(nat->nat_outip.s_addr, nat->nat_outport, - ipf_nattable_sz); + hv = NAT_HASH_FN(nat->nat_outip.s_addr, sport, ipf_nattable_sz); natp = &nat_table[1][hv]; if (*natp) (*natp)->nat_phnext[1] = &nat->nat_hnext[1]; @@ -1990,11 +2024,12 @@ nat_t *nat; * we're looking for a table entry, based on the source address. * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. */ -nat_t *nat_outlookup(ifp, flags, p, src, dst, ports) +nat_t *nat_outlookup(ifp, flags, p, src, dst, ports, rw) void *ifp; register u_int flags, p; struct in_addr src , dst; u_32_t ports; +int rw; { register u_short sport, dport; register nat_t *nat; @@ -2015,7 +2050,7 @@ u_32_t ports; if ((!ifp || ifp == nat->nat_ifp) && nat->nat_inip.s_addr == srcip && nat->nat_oip.s_addr == dst.s_addr && - (((p == 0) && (flags == (nat->nat_flags & IPN_TCPUDP))) + (((p == 0) && (flags == (nflags & IPN_TCPUDP))) || (p == nat->nat_p)) && (!flags || ((nat->nat_inport == sport || nflags & FI_W_SPORT) && (nat->nat_oport == dport || nflags & FI_W_DPORT)))) @@ -2023,9 +2058,13 @@ u_32_t ports; } if (!nat_stats.ns_wilds || !(flags & IPN_TCPUDP)) return NULL; - RWLOCK_EXIT(&ipf_nat); + if (!rw) { + RWLOCK_EXIT(&ipf_nat); + } hv = NAT_HASH_FN(srcip, 0, ipf_nattable_sz); - WRITE_ENTER(&ipf_nat); + if (!rw) { + WRITE_ENTER(&ipf_nat); + } nat = nat_table[0][hv]; for (; nat; nat = nat->nat_hnext[0]) { nflags = nat->nat_flags; @@ -2038,13 +2077,15 @@ u_32_t ports; if ((nat->nat_inip.s_addr != srcip) || (nat->nat_oip.s_addr != dst.s_addr)) continue; - if (((nat->nat_inport == sport) || (nflags & FI_W_DPORT)) && - ((nat->nat_oport == dport) || (nflags & FI_W_SPORT))) { - nat_tabmove(nat); + if (((nat->nat_inport == sport) || (nflags & FI_W_SPORT)) && + ((nat->nat_oport == dport) || (nflags & FI_W_DPORT))) { + nat_tabmove(nat, ports); break; } } - MUTEX_DOWNGRADE(&ipf_nat); + if (!rw) { + MUTEX_DOWNGRADE(&ipf_nat); + } return nat; } @@ -2064,7 +2105,7 @@ register natlookup_t *np; * ip address. Else, we use the fake. */ if ((nat = nat_outlookup(NULL, np->nl_flags, 0, np->nl_inip, - np->nl_outip, ports))) { + np->nl_outip, ports, 0))) { np->nl_realip = nat->nat_outip; np->nl_realport = nat->nat_outport; } @@ -2165,10 +2206,11 @@ fr_info_t *fin; (nat = nat_icmp(ip, fin, &nflags, NAT_OUTBOUND))) ; else if ((ip->ip_off & (IP_OFFMASK|IP_MF)) && - (nat = ipfr_nat_knownfrag(ip, fin))) + (nat = ipfr_nat_knownfrag(ip, fin))) natadd = 0; - else if ((nat = nat_outlookup(ifp, nflags, (u_int)ip->ip_p, ip->ip_src, - ip->ip_dst, (dport << 16) | sport))) { + else if ((nat = nat_outlookup(ifp, nflags, (u_int)ip->ip_p, + ip->ip_src, ip->ip_dst, + (dport << 16) | sport, 0))) { nflags = nat->nat_flags; if ((nflags & (FI_W_SPORT|FI_W_DPORT)) != 0) { if ((nflags & FI_W_SPORT) && @@ -2222,9 +2264,6 @@ maskloop: if ((nat = nat_new(np, ip, fin, (u_int)nflags, NAT_OUTBOUND))) { np->in_hits++; -#ifdef IPFILTER_LOG - nat_log(nat, (u_int)np->in_redir); -#endif break; } } @@ -2240,6 +2279,9 @@ maskloop: MUTEX_DOWNGRADE(&ipf_nat); } + /* + * NOTE: ipf_nat must now only be held as a read lock + */ if (nat) { np = nat->nat_ptr; if (natadd && fin->fin_fi.fi_fl & FI_FRAG) @@ -2384,7 +2426,8 @@ fr_info_t *fin; (nat = ipfr_nat_knownfrag(ip, fin))) natadd = 0; else if ((nat = nat_inlookup(fin->fin_ifp, nflags, (u_int)ip->ip_p, - ip->ip_src, in, (dport << 16) | sport))) { + ip->ip_src, in, (dport << 16) | sport, + 0))) { nflags = nat->nat_flags; if ((nflags & (FI_W_SPORT|FI_W_DPORT)) != 0) { if ((nat->nat_oport != sport) && (nflags & FI_W_DPORT)) @@ -2425,9 +2468,6 @@ maskloop: if ((nat = nat_new(np, ip, fin, nflags, NAT_INBOUND))) { np->in_hits++; -#ifdef IPFILTER_LOG - nat_log(nat, (u_int)np->in_redir); -#endif break; } } @@ -2442,6 +2482,10 @@ maskloop: } MUTEX_DOWNGRADE(&ipf_nat); } + + /* + * NOTE: ipf_nat must now only be held as a read lock + */ if (nat) { np = nat->nat_ptr; fin->fin_fr = nat->nat_fr; diff --git a/sys/netinet/ip_nat.h b/sys/netinet/ip_nat.h index da192b3..374a20b 100644 --- a/sys/netinet/ip_nat.h +++ b/sys/netinet/ip_nat.h @@ -6,7 +6,7 @@ * to the original author and the contributors. * * @(#)ip_nat.h 1.5 2/4/96 - * $Id: ip_nat.h,v 2.17.2.6 2000/07/15 14:50:06 darrenr Exp $ + * $Id: ip_nat.h,v 2.17.2.14 2000/11/18 03:58:04 darrenr Exp $ * $FreeBSD$ */ @@ -86,7 +86,7 @@ typedef struct nat { void *nat_ifp; int nat_dir; char nat_ifname[IFNAMSIZ]; -#if SOLARIS || defined(_sgi) +#if SOLARIS || defined(__sgi) kmutex_t nat_lock; #endif } nat_t; @@ -248,6 +248,7 @@ typedef struct natlog { #define NL_NEWRDR NAT_REDIRECT #define NL_NEWBIMAP NAT_BIMAP #define NL_NEWBLOCK NAT_MAPBLK +#define NL_FLUSH 0xfffe #define NL_EXPIRE 0xffff #define NAT_HASH_FN(k,l,m) (((k) + ((k) >> 12) + l) % (m)) @@ -286,9 +287,9 @@ extern int nat_ioctl __P((caddr_t, int, int)); extern int nat_init __P((void)); extern nat_t *nat_new __P((ipnat_t *, ip_t *, fr_info_t *, u_int, int)); extern nat_t *nat_outlookup __P((void *, u_int, u_int, struct in_addr, - struct in_addr, u_32_t)); + struct in_addr, u_32_t, int)); extern nat_t *nat_inlookup __P((void *, u_int, u_int, struct in_addr, - struct in_addr, u_32_t)); + struct in_addr, u_32_t, int)); extern nat_t *nat_maplookup __P((void *, u_int, struct in_addr, struct in_addr)); extern nat_t *nat_lookupredir __P((natlookup_t *)); diff --git a/sys/netinet/ip_proxy.h b/sys/netinet/ip_proxy.h index edee695..f22c709 100644 --- a/sys/netinet/ip_proxy.h +++ b/sys/netinet/ip_proxy.h @@ -5,7 +5,7 @@ * provided that this notice is preserved and due credit is given * to the original author and the contributors. * - * $Id: ip_proxy.h,v 2.1.2.1 1999/09/19 12:18:20 darrenr Exp $ + * $Id: ip_proxy.h,v 2.8.2.4 2000/12/02 00:15:03 darrenr Exp $ * $FreeBSD$ */ @@ -97,6 +97,7 @@ typedef struct ftpside { char *ftps_rptr; char *ftps_wptr; u_32_t ftps_seq; + u_32_t ftps_len; int ftps_junk; char ftps_buf[FTP_BUFSZ]; } ftpside_t; diff --git a/sys/netinet/ip_rcmd_pxy.c b/sys/netinet/ip_rcmd_pxy.c index 5baabbf..0ae0210 100644 --- a/sys/netinet/ip_rcmd_pxy.c +++ b/sys/netinet/ip_rcmd_pxy.c @@ -1,5 +1,5 @@ /* - * $Id: ip_rcmd_pxy.c,v 1.4.2.3 2000/10/27 22:54:04 darrenr Exp $ + * $Id: ip_rcmd_pxy.c,v 1.4.2.4 2000/11/01 14:34:20 darrenr Exp $ */ /* * Simple RCMD transparent proxy for in-kernel use. For use with the NAT @@ -132,7 +132,7 @@ nat_t *nat; sp = htons(sp); dp = htons(fin->fin_data[1]); ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, - ip->ip_dst, (dp << 16) | sp); + ip->ip_dst, (dp << 16) | sp, 0); if (ipn == NULL) { int slen; diff --git a/sys/netinet/ip_state.c b/sys/netinet/ip_state.c index 1e4c851..c051c9e 100644 --- a/sys/netinet/ip_state.c +++ b/sys/netinet/ip_state.c @@ -307,8 +307,8 @@ int mode; break; case FIONREAD : #ifdef IPFILTER_LOG - error = IWCOPY((caddr_t)&iplused[IPL_LOGSTATE], (caddr_t)data, - sizeof(iplused[IPL_LOGSTATE])); + arg = (int)iplused[IPL_LOGSTATE]; + error = IWCOPY((caddr_t)&arg, (caddr_t)data, sizeof(arg)); #endif break; case SIOCSTLCK : @@ -787,8 +787,6 @@ tcphdr_t *tcp; } ATOMIC_INCL(ips_stats.iss_hits); - is->is_pkts++; - is->is_bytes += fin->fin_dlen + fin->fin_hlen; /* * Nearing end of connection, start timeout. */ @@ -1148,10 +1146,6 @@ fr_info_t *fin; fr_matchsrcdst(is, src, dst, &ofin, tcp)) { fr = is->is_rule; ips_stats.iss_hits++; - /* - * we must swap src and dst here because the icmp - * comes the other way around - */ is->is_pkts++; is->is_bytes += fin->fin_plen; /* @@ -1379,6 +1373,9 @@ void *ifp; } +/* + * Must always be called with fr_ipfstate held as a write lock. + */ static void fr_delstate(is) ipstate_t *is; { @@ -1397,9 +1394,10 @@ ipstate_t *is; fr = is->is_rule; if (fr != NULL) { - ATOMIC_DEC32(fr->fr_ref); - if (fr->fr_ref == 0) + fr->fr_ref--; + if (fr->fr_ref == 0) { KFREE(fr); + } } #ifdef _KERNEL MUTEX_DESTROY(&is->is_lock); @@ -1452,12 +1450,12 @@ void fr_timeoutstate() fr_delstate(is); } else isp = &is->is_next; - RWLOCK_EXIT(&ipf_state); - SPL_X(s); if (fr_state_doflush) { (void) fr_state_flush(1); fr_state_doflush = 0; } + RWLOCK_EXIT(&ipf_state); + SPL_X(s); } diff --git a/sys/netinet/ipl.h b/sys/netinet/ipl.h index 94bae8d..79d0bd3 100644 --- a/sys/netinet/ipl.h +++ b/sys/netinet/ipl.h @@ -12,6 +12,6 @@ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v3.4.13" +#define IPL_VERSION "IP Filter: v3.4.16" #endif diff --git a/sys/netinet/mlfk_ipl.c b/sys/netinet/mlfk_ipl.c index 1be8916..7a7971f 100644 --- a/sys/netinet/mlfk_ipl.c +++ b/sys/netinet/mlfk_ipl.c @@ -38,6 +38,12 @@ #include <netinet/in_systm.h> #include <netinet/in.h> #include <netinet/ip.h> +#if (__FreeBSD_version >= 199511) +# include <net/route.h> +# include <netinet/ip_var.h> +# include <netinet/tcp.h> +# include <netinet/tcpip.h> +#endif #include <netinet/ipl.h> @@ -47,6 +53,7 @@ #include <netinet/ip_nat.h> #include <netinet/ip_auth.h> #include <netinet/ip_frag.h> +#include <netinet/ip_proxy.h> static dev_t ipf_devs[IPL_LOGMAX + 1]; @@ -86,6 +93,11 @@ SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD, SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW, &fr_defaultauthage, 0, ""); SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, ""); +SYSCTL_INT(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW, + &ippr_ftp_pasvonly, 0, ""); +SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, ""); +SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttllog, CTLFLAG_RW, + &fr_minttllog, 0, ""); #define CDEV_MAJOR 79 static struct cdevsw ipl_cdevsw = { |