diff options
author | darrenr <darrenr@FreeBSD.org> | 2000-10-26 12:28:47 +0000 |
---|---|---|
committer | darrenr <darrenr@FreeBSD.org> | 2000-10-26 12:28:47 +0000 |
commit | e04f9f34d2852385979f4c5287f6ab24ff055648 (patch) | |
tree | 9727add6dfa453c100100eb6a8d1f625e7c6d2d0 /sys/contrib/ipfilter/netinet | |
parent | 15d169cdfcc633be9595e83cac604b7637123f9b (diff) | |
download | FreeBSD-src-e04f9f34d2852385979f4c5287f6ab24ff055648.zip FreeBSD-src-e04f9f34d2852385979f4c5287f6ab24ff055648.tar.gz |
Import IP Filter 3.4.12 into kernel source tree
Diffstat (limited to 'sys/contrib/ipfilter/netinet')
-rw-r--r-- | sys/contrib/ipfilter/netinet/fil.c | 61 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_auth.h | 4 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_compat.h | 38 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_fil.c | 39 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_frag.c | 23 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_frag.h | 4 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_ftp_pxy.c | 24 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_nat.c | 439 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_nat.h | 14 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_raudio_pxy.c | 4 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_state.c | 144 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_state.h | 3 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ipl.h | 4 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/mlfk_ipl.c | 4 |
14 files changed, 613 insertions, 192 deletions
diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index 91b5108..b85dcf4 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -7,7 +7,7 @@ */ #if !defined(lint) 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.35.2.20 2000/08/13 04:15:43 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: fil.c,v 2.35.2.26 2000/10/24 11:58:17 darrenr Exp $"; #endif #include <sys/errno.h> @@ -274,6 +274,16 @@ fr_info_t *fin; int minicmpsz = sizeof(struct icmp); icmphdr_t *icmp; + if (fin->fin_dlen > 1) + fin->fin_data[0] = *(u_short *)tcp; + + if ((!(plen >= hlen + minicmpsz) && !off) || + (off && off < sizeof(struct icmp))) { + fi->fi_fl |= FI_SHORT; + if (fin->fin_dlen < 2) + break; + } + icmp = (icmphdr_t *)tcp; if (!off && (icmp->icmp_type == ICMP_ECHOREPLY || @@ -291,11 +301,6 @@ fr_info_t *fin; icmp->icmp_type == ICMP_MASKREPLY)) minicmpsz = 12; - if ((!(plen >= 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 : @@ -740,6 +745,7 @@ int out; #ifdef _KERNEL 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]; @@ -764,13 +770,26 @@ int out; } # endif /* CSUM_DELAY_DATA */ +# ifdef USE_INET6 + if (v == 6) { + len = ntohs(((ip6_t*)ip)->ip6_plen); + p = ((ip6_t *)ip)->ip6_nxt; + } else +# endif + { + p = ip->ip_p; + len = ip->ip_len; + } - if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP || - ip->ip_p == IPPROTO_ICMP)) { + if ((p == IPPROTO_TCP || p == IPPROTO_UDP || p == IPPROTO_ICMP +# ifdef USE_INET6 + || (v == 6 && p == IPPROTO_ICMPV6) +# endif + )) { int plen = 0; - if ((ip->ip_off & IP_OFFMASK) == 0) - switch(ip->ip_p) + if ((v == 6) || (ip->ip_off & IP_OFFMASK) == 0) + switch(p) { case IPPROTO_TCP: plen = sizeof(tcphdr_t); @@ -780,10 +799,13 @@ int out; break; /* 96 - enough for complete ICMP error IP header */ case IPPROTO_ICMP: +# ifdef USE_INET6 + case IPPROTO_ICMPV6 : +# endif plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); break; } - up = MIN(hlen + plen, ip->ip_len); + up = MIN(hlen + plen, len); if (up > m->m_len) { # ifdef __sgi @@ -830,8 +852,8 @@ int out; ip->ip_id = ntohs(ip->ip_id); changed = 0; - fin->fin_v = v; fin->fin_ifp = ifp; + fin->fin_v = v; fin->fin_out = out; fin->fin_mp = mp; fr_makefrip(hlen, ip, fin); @@ -1376,7 +1398,7 @@ nodata: * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.35.2.20 2000/08/13 04:15:43 darrenr Exp $ + * $Id: fil.c,v 2.35.2.26 2000/10/24 11:58:17 darrenr Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, @@ -1855,7 +1877,7 @@ size_t c; int err; #if SOLARIS - if (copyin(a, &ca, sizeof(ca))) + if (copyin(a, (char *)&ca, sizeof(ca))) return EFAULT; #else bcopy(a, &ca, sizeof(ca)); @@ -1875,7 +1897,7 @@ size_t c; int err; #if SOLARIS - if (copyin(b, &ca, sizeof(ca))) + if (copyin(b, (char *)&ca, sizeof(ca))) return EFAULT; #else bcopy(b, &ca, sizeof(ca)); @@ -1969,6 +1991,15 @@ friostat_t *fiop; fiop->f_acctin6[1] = ipacct6[0][1]; fiop->f_acctout6[0] = ipacct6[1][0]; fiop->f_acctout6[1] = ipacct6[1][1]; +#else + fiop->f_fin6[0] = NULL; + fiop->f_fin6[1] = NULL; + fiop->f_fout6[0] = NULL; + fiop->f_fout6[1] = NULL; + fiop->f_acctin6[0] = NULL; + fiop->f_acctin6[1] = NULL; + fiop->f_acctout6[0] = NULL; + fiop->f_acctout6[1] = NULL; #endif fiop->f_active = fr_active; fiop->f_froute[0] = ipl_frouteok[0]; diff --git a/sys/contrib/ipfilter/netinet/ip_auth.h b/sys/contrib/ipfilter/netinet/ip_auth.h index b543318..681a6e5 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.h +++ b/sys/contrib/ipfilter/netinet/ip_auth.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_auth.h,v 2.3.2.1 2000/05/22 10:26:11 darrenr Exp $ + * $Id: ip_auth.h,v 2.3.2.2 2000/10/19 15:38:44 darrenr Exp $ * */ #ifndef __IP_AUTH_H__ @@ -46,8 +46,6 @@ typedef struct fr_authstat { extern frentry_t *ipauth; extern struct fr_authstat fr_authstats; extern int fr_defaultauthage; -extern int fr_authstart; -extern int fr_authend; extern int fr_authsize; extern int fr_authused; extern int fr_auth_lock; diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h index ba9e014..2369cf0 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.26.2.4 2000/08/13 03:51:03 darrenr Exp $ + * $Id: ip_compat.h,v 2.26.2.6 2000/10/19 15:39:05 darrenr Exp $ */ #ifndef __IP_COMPAT_H__ @@ -263,6 +263,12 @@ union i6addr { #if defined(__FreeBSD__) && (defined(KERNEL) || defined(_KERNEL)) +# ifdef IPFILTER_LKM +# include <osreldate.h> +# define ACTUALLY_LKM_NOT_KERNEL +# else +# include <sys/osreldate.h> +# endif # if __FreeBSD__ < 3 # include <machine/spl.h> # else @@ -288,6 +294,19 @@ union i6addr { # define ATOMIC_DEC32 ATOMIC_DEC # define ATOMIC_DEC16 ATOMIC_DEC #endif +#ifdef __sgi +# define hz HZ +# include <sys/ksynch.h> +# define IPF_LOCK_PL plhi +# include <sys/sema.h> +#undef kmutex_t +typedef struct { + lock_t *l; + int pl; +} kmutex_t; +# undef MUTEX_INIT +# undef MUTEX_DESTROY +#endif #ifdef KERNEL # if SOLARIS # if SOLARIS2 >= 6 @@ -337,8 +356,8 @@ union i6addr { # define MUTEX_DESTROY(x) mutex_destroy(x) # define MUTEX_EXIT(x) mutex_exit(x) # define MTOD(m,t) (t)((m)->b_rptr) -# define IRCOPY(a,b,c) copyin((a), (b), (c)) -# define IWCOPY(a,b,c) copyout((a), (b), (c)) +# define IRCOPY(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) +# define IWCOPY(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) # define IRCOPYPTR ircopyptr # define IWCOPYPTR iwcopyptr # define FREE_MB_T(m) freemsg(m) @@ -383,15 +402,6 @@ extern ill_t *get_unit __P((char *, int)); # define IFNAME(x) ((ill_t *)x)->ill_name # else /* SOLARIS */ # if defined(__sgi) -# define hz HZ -# include <sys/ksynch.h> -# define IPF_LOCK_PL plhi -# include <sys/sema.h> -#undef kmutex_t -typedef struct { - lock_t *l; - int pl; -} kmutex_t; # define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); \ (x)++; MUTEX_EXIT(&ipf_rw); } # define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); \ @@ -404,8 +414,8 @@ typedef struct { # define MUTEX_DOWNGRADE(x) ; # define RWLOCK_EXIT(x) MUTEX_EXIT(x) # define MUTEX_EXIT(x) UNLOCK((x)->l, (x)->pl); -# define MUTEX_INIT(x,y,z) (x).l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP) -# define MUTEX_DESTROY(x) LOCK_DEALLOC((x).l) +# define MUTEX_INIT(x,y,z) (x)->l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP) +# define MUTEX_DESTROY(x) LOCK_DEALLOC((x)->l) # else /* __sgi */ # define ATOMIC_INC(x) (x)++ # define ATOMIC_DEC(x) (x)-- diff --git a/sys/contrib/ipfilter/netinet/ip_fil.c b/sys/contrib/ipfilter/netinet/ip_fil.c index 2e8af26..9253775 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.c +++ b/sys/contrib/ipfilter/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-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.15 2000/08/05 14:49:08 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.17 2000/10/19 15:39:42 darrenr Exp $"; #endif #ifndef SOLARIS @@ -171,6 +171,9 @@ struct callout_handle ipfr_slowtimer_ch; # include <sys/callout.h> struct callout ipfr_slowtimer_ch; #endif +#if defined(__sgi) && defined(_KERNEL) +toid_t ipfr_slowtimer_ch; +#endif #if (_BSDI_VERSION >= 199510) && defined(_KERNEL) # include <sys/device.h> @@ -318,7 +321,7 @@ pfil_error: callout_init(&ipfr_slowtimer_ch); callout_reset(&ipfr_slowtimer_ch, hz / 2, ipfr_slowtimer, NULL); # else -# if (__FreeBSD_version >= 300000) && defined(_KERNEL) +# if (__FreeBSD_version >= 300000) || defined(__sgi) ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2); # else timeout(ipfr_slowtimer, NULL, hz/2); @@ -348,7 +351,7 @@ int ipldetach() untimeout(ipfr_slowtimer, NULL, ipfr_slowtimer_ch); # else # ifdef __sgi - untimeout(ipfr_slowtimer); + untimeout(ipfr_slowtimer_ch); # else untimeout(ipfr_slowtimer, NULL); # endif @@ -975,8 +978,10 @@ fr_info_t *fin; if (m == NULL) return -1; - if (tcp->th_flags & TH_SYN) - tlen = 1; + tlen = oip->ip_len - fin->fin_hlen - (tcp->th_off << 2) + + ((tcp->th_flags & TH_SYN) ? 1 : 0) + + ((tcp->th_flags & TH_FIN) ? 1 : 0); + #ifdef USE_INET6 hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t); #else @@ -997,11 +1002,16 @@ fr_info_t *fin; tcp2->th_sport = tcp->th_dport; tcp2->th_dport = tcp->th_sport; - tcp2->th_ack = ntohl(tcp->th_seq); - tcp2->th_ack += tlen; - tcp2->th_ack = htonl(tcp2->th_ack); + if (tcp->th_flags & TH_ACK) { + tcp2->th_seq = tcp->th_ack; + tcp2->th_flags = TH_RST; + } else { + tcp2->th_ack = ntohl(tcp->th_seq); + tcp2->th_ack += tlen; + tcp2->th_ack = htonl(tcp2->th_ack); + tcp2->th_flags = TH_RST|TH_ACK; + } tcp2->th_off = sizeof(*tcp2) >> 2; - tcp2->th_flags = TH_RST|TH_ACK; # ifdef USE_INET6 if (fin->fin_v == 6) { ip6->ip6_plen = htons(sizeof(struct tcphdr)); @@ -1143,7 +1153,12 @@ int dst; m_freem(m); return ENOBUFS; } +# ifdef M_TRAILINGSPACE + m->m_len = 0; + avail = M_TRAILINGSPACE(m); +# else avail = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN; +# endif xtra = MIN(ntohs(oip6->ip6_plen) + sizeof(ip6_t), avail - hlen - sizeof(*icmp) - max_linkhdr); if (dst == 0) { @@ -1177,6 +1192,12 @@ int dst; icmp->icmp_type = type; icmp->icmp_code = fin->fin_icode; icmp->icmp_cksum = 0; +#ifdef icmp_nextmtu + if (type == ICMP_UNREACH && + fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp) + icmp->icmp_nextmtu = htons(((struct ifnet *) ifp)->if_mtu); +#endif + if (avail) { bcopy((char *)oip, (char *)&icmp->icmp_ip, MIN(ohlen, avail)); avail -= MIN(ohlen, avail); diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c index 5019c60..1cb86c1 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -7,7 +7,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 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[] = "@(#)$Id: ip_frag.c,v 2.10.2.5 2000/10/19 15:39:58 darrenr Exp $"; #endif #if defined(KERNEL) && !defined(_KERNEL) @@ -214,7 +214,7 @@ u_int pass; ipfr_t *ipf; if ((ip->ip_v != 4) || (fr_frag_lock)) - return NULL; + return -1; WRITE_ENTER(&ipf_frag); ipf = ipfr_new(ip, fin, pass, ipfr_heads); RWLOCK_EXIT(&ipf_frag); @@ -231,7 +231,7 @@ nat_t *nat; ipfr_t *ipf; if ((ip->ip_v != 4) || (fr_frag_lock)) - return NULL; + return -1; WRITE_ENTER(&ipf_natfrag); ipf = ipfr_new(ip, fin, pass, ipfr_nattab); if (ipf != NULL) { @@ -328,13 +328,16 @@ fr_info_t *fin; ipf = ipfr_lookup(ip, fin, ipfr_nattab); if (ipf != NULL) { nat = ipf->ipfr_data; - /* - * This is the last fragment for this packet. - */ - if ((ipf->ipfr_ttl == 1) && (nat != NULL)) { - nat->nat_data = NULL; - ipf->ipfr_data = NULL; - } + 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; } 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 6a3bd2c..61b88aa 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.4 2000/03/13 22:10:21 darrenr Exp $ + * $Id: ip_frag.h,v 2.4.2.1 2000/10/19 15:40:13 darrenr Exp $ */ #ifndef __IP_FRAG_H__ @@ -60,6 +60,6 @@ extern void ipfr_slowtimer __P((void *)); # endif #else extern int ipfr_slowtimer __P((void)); -#endif +#endif /* (BSD >= 199306) || SOLARIS */ #endif /* __IP_FIL_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c index 84dc8b9..ffa7c1b 100644 --- a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c @@ -2,7 +2,7 @@ * Simple FTP transparent proxy for in-kernel use. For use with the NAT * code. * - * $Id: ip_ftp_pxy.c,v 2.7.2.13 2000/08/07 12:35:27 darrenr Exp $ + * $Id: ip_ftp_pxy.c,v 2.7.2.17 2000/10/19 15:40:40 darrenr Exp $ */ #if SOLARIS && defined(_KERNEL) extern kmutex_t ipf_rw; @@ -146,6 +146,7 @@ int dlen; } else return 0; a5 >>= 8; + a5 &= 0xff; /* * Calculate new address parts for PORT command */ @@ -214,7 +215,7 @@ int dlen; sum2 -= sum1; sum2 = (sum2 & 0xffff) + (sum2 >> 16); - fix_outcksum(&ip->ip_sum, sum2, 0); + fix_outcksum(&ip->ip_sum, sum2); #endif ip->ip_len += inc; } @@ -441,7 +442,7 @@ int dlen; sum2 -= sum1; sum2 = (sum2 & 0xffff) + (sum2 >> 16); - fix_outcksum(&ip->ip_sum, sum2, 0); + fix_outcksum(&ip->ip_sum, sum2); #endif /* SOLARIS || defined(__sgi) */ ip->ip_len += inc; } @@ -670,15 +671,18 @@ int rv; while ((rptr < wptr) && (*rptr != '\r')) rptr++; - if ((*rptr == '\r') && (rptr + 1 < wptr)) { - if (*(rptr + 1) == '\n') { - rptr += 2; - f->ftps_junk = 0; + if (*rptr == '\r') { + if (rptr + 1 < wptr) { + if (*(rptr + 1) == '\n') { + rptr += 2; + f->ftps_junk = 0; + } else + rptr++; } else - rptr++; + break; } - f->ftps_rptr = rptr; } + f->ftps_rptr = rptr; if (rptr == wptr) { rptr = wptr = f->ftps_buf; @@ -762,5 +766,7 @@ char **ptr; j += c - '0'; } *ptr = s; + i &= 0xff; + j &= 0xff; return (i << 8) | j; } diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index bbcff77..d52f48d 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/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 2.37.2.21 2000/08/12 07:32:40 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.37.2.25 2000/10/25 10:38:47 darrenr Exp $"; #endif #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL) @@ -118,6 +118,7 @@ u_int ipf_nattable_sz = NAT_TABLE_SZ; u_int ipf_natrules_sz = NAT_SIZE; u_int ipf_rdrrules_sz = RDR_SIZE; u_int ipf_hostmap_sz = HOSTMAP_SIZE; +int nat_wilds = 0; u_32_t nat_masks = 0; u_32_t rdr_masks = 0; ipnat_t **nat_rules = NULL; @@ -143,6 +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 *, u_int)); 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)); @@ -300,10 +302,9 @@ struct hostmap *hm; } -void fix_outcksum(sp, n , len) +void fix_outcksum(sp, n) u_short *sp; u_32_t n; -int len; { register u_short sumshort; register u_32_t sum1; @@ -326,10 +327,9 @@ int len; } -void fix_incksum(sp, n , len) +void fix_incksum(sp, n) u_short *sp; u_32_t n; -int len; { register u_short sumshort; register u_32_t sum1; @@ -357,6 +357,38 @@ int len; /* + * fix_datacksum is used *only* for the adjustments of checksums in the data + * section of an IP packet. + * + * The only situation in which you need to do this is when NAT'ing an + * ICMP error message. Such a message, contains in its body the IP header + * of the original IP packet, that causes the error. + * + * You can't use fix_incksum or fix_outcksum in that case, because for the + * kernel the data section of the ICMP error is just data, and no special + * processing like hardware cksum or ntohs processing have been done by the + * kernel on the data section. + */ +void fix_datacksum(sp, n) +u_short *sp; +u_32_t n; +{ + register u_short sumshort; + register u_32_t sum1; + + if (!n) + return; + + sum1 = (~ntohs(*sp)) & 0xffff; + sum1 += (n); + sum1 = (sum1 >> 16) + (sum1 & 0xffff); + /* Again */ + sum1 = (sum1 >> 16) + (sum1 & 0xffff); + sumshort = ~(u_short)sum1; + *(sp) = htons(sumshort); +} + +/* * How the NAT is organised and works. * * Inside (interface y) NAT Outside (interface x) @@ -856,8 +888,8 @@ caddr_t data; /* * Initialize all these so that nat_delete() doesn't cause a crash. */ - nat->nat_hstart[0] = NULL; - nat->nat_hstart[1] = NULL; + nat->nat_phnext[0] = NULL; + nat->nat_phnext[1] = NULL; fr = nat->nat_fr; nat->nat_fr = NULL; aps = nat->nat_aps; @@ -969,22 +1001,16 @@ junkput: static void nat_delete(natd) struct nat *natd; { - register struct nat **natp, *nat; struct ipnat *ipn; - for (natp = natd->nat_hstart[0]; natp && (nat = *natp); - natp = &nat->nat_hnext[0]) - if (nat == natd) { - *natp = nat->nat_hnext[0]; - break; - } - - for (natp = natd->nat_hstart[1]; natp && (nat = *natp); - natp = &nat->nat_hnext[1]) - if (nat == natd) { - *natp = nat->nat_hnext[1]; - break; - } + if (natd->nat_flags & FI_WILDP) + nat_wilds--; + if (natd->nat_hnext[0]) + natd->nat_hnext[0]->nat_phnext[0] = natd->nat_phnext[0]; + *natd->nat_phnext[0] = natd->nat_hnext[0]; + if (natd->nat_hnext[1]) + natd->nat_hnext[1]->nat_phnext[1] = natd->nat_phnext[1]; + *natd->nat_phnext[1] = natd->nat_hnext[1]; if (natd->nat_fr != NULL) { ATOMIC_DEC32(natd->nat_fr->fr_ref); @@ -1029,7 +1055,7 @@ static int nat_flushtable() { register nat_t *nat, **natp; register int j = 0; - + /* * ALL NAT mappings deleted, so lets just make the deletions * quicker. @@ -1121,6 +1147,8 @@ int direction; bzero((char *)nat, sizeof(*nat)); nat->nat_flags = flags; + if (flags & FI_WILDP) + nat_wilds++; /* * Search the current table for a match. */ @@ -1443,16 +1471,22 @@ nat_t *nat; nat->nat_next = nat_instances; nat_instances = nat; + hv = NAT_HASH_FN(nat->nat_inip.s_addr, nat->nat_inport, ipf_nattable_sz); natp = &nat_table[0][hv]; - nat->nat_hstart[0] = natp; + if (*natp) + (*natp)->nat_phnext[0] = &nat->nat_hnext[0]; + nat->nat_phnext[0] = natp; nat->nat_hnext[0] = *natp; *natp = nat; + hv = NAT_HASH_FN(nat->nat_outip.s_addr, nat->nat_outport, ipf_nattable_sz); natp = &nat_table[1][hv]; - nat->nat_hstart[1] = natp; + if (*natp) + (*natp)->nat_phnext[1] = &nat->nat_hnext[1]; + nat->nat_phnext[1] = natp; nat->nat_hnext[1] = *natp; *natp = nat; @@ -1560,12 +1594,16 @@ int dir; u_32_t sum1, sum2, sumd; struct in_addr in; icmphdr_t *icmp; + udphdr_t *udp; nat_t *nat; ip_t *oip; int flags = 0; if ((fin->fin_fi.fi_fl & FI_SHORT) || (ip->ip_off & IP_OFFMASK)) return NULL; + /* + * nat_icmplookup() will return NULL for `defective' packets. + */ if ((ip->ip_v != 4) || !(nat = nat_icmplookup(ip, fin, dir))) return NULL; *nflags = IPN_ICMPERR; @@ -1575,16 +1613,33 @@ int dir; flags = IPN_TCP; else if (oip->ip_p == IPPROTO_UDP) flags = IPN_UDP; + udp = (udphdr_t *)((((char *)oip) + (oip->ip_hl << 2))); /* * Need to adjust ICMP header to include the real IP#'s and * port #'s. Only apply a checksum change relative to the - * IP address change is it will be modified again in ip_natout + * IP address change as it will be modified again in ip_natout * for both address and port. Two checksum changes are * necessary for the two header address changes. Be careful * to only modify the checksum once for the port # and twice * for the IP#. */ + /* + * Step 1 + * Fix the IP addresses in the offending IP packet. You also need + * to adjust the IP header checksum of that offending IP packet + * and the ICMP checksum of the ICMP error message itself. + * + * Unfortunately, for UDP and TCP, the IP addresses are also contained + * in the pseudo header that is used to compute the UDP resp. TCP + * checksum. So, we must compensate that as well. Even worse, the + * change in the UDP and TCP checksums require yet another + * adjustment of the ICMP checksum of the ICMP error message. + * + * For the moment we forget about TCP, because that checksum is not + * in the first 8 bytes, so it will not be available in most cases. + */ + if (nat->nat_dir == NAT_OUTBOUND) { sum1 = LONG_SUM(ntohl(oip->ip_src.s_addr)); in = nat->nat_inip; @@ -1600,19 +1655,117 @@ int dir; CALC_SUMD(sum1, sum2, sumd); if (nat->nat_dir == NAT_OUTBOUND) { - fix_incksum(&oip->ip_sum, sumd, 0); + /* + * Fix IP checksum of the offending IP packet to adjust for + * the change in the IP address. + * + * Normally, you would expect that the ICMP checksum of the + * ICMP error message needs to be adjusted as well for the + * IP address change in oip. + * However, this is a NOP, because the ICMP checksum is + * calculated over the complete ICMP packet, which includes the + * changed oip IP addresses and oip->ip_sum. However, these + * two changes cancel each other out (if the delta for + * the IP address is x, then the delta for ip_sum is minus x), + * so no change in the icmp_cksum is necessary. + * + * Be careful that nat_dir refers to the direction of the + * offending IP packet (oip), not to its ICMP response (icmp) + */ + fix_datacksum(&oip->ip_sum, sumd); - sumd += (sumd & 0xffff); - while (sumd > 0xffff) - sumd = (sumd & 0xffff) + (sumd >> 16); - fix_outcksum(&icmp->icmp_cksum, sumd, 0); + /* + * Fix UDP pseudo header checksum to compensate for the + * IP address change. + */ + if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) { + /* + * The UDP checksum is optional, only adjust it + * if it has been set. + */ + sum1 = ntohs(udp->uh_sum); + fix_datacksum(&udp->uh_sum, sumd); + sum2 = ntohs(udp->uh_sum); + + /* + * Fix ICMP checksum to compensate the UDP + * checksum adjustment. + */ + CALC_SUMD(sum1, sum2, sumd); + fix_outcksum(&icmp->icmp_cksum, sumd); + } + +#if 0 + /* + * Fix TCP pseudo header checksum to compensate for the + * IP address change. Before we can do the change, we + * must make sure that oip is sufficient large to hold + * the TCP checksum (normally it does not!). + */ + if (oip->ip_p == IPPROTO_TCP) { + + } +#endif } else { - fix_outcksum(&oip->ip_sum, sumd, 0); + + /* + * Fix IP checksum of the offending IP packet to adjust for + * the change in the IP address. + * + * Normally, you would expect that the ICMP checksum of the + * ICMP error message needs to be adjusted as well for the + * IP address change in oip. + * However, this is a NOP, because the ICMP checksum is + * calculated over the complete ICMP packet, which includes the + * changed oip IP addresses and oip->ip_sum. However, these + * two changes cancel each other out (if the delta for + * the IP address is x, then the delta for ip_sum is minus x), + * so no change in the icmp_cksum is necessary. + * + * Be careful that nat_dir refers to the direction of the + * offending IP packet (oip), not to its ICMP response (icmp) + */ + fix_datacksum(&oip->ip_sum, sumd); + +/* XXX FV : without having looked at Solaris source code, it seems unlikely + * that SOLARIS would compensate this in the kernel (a body of an IP packet + * in the data section of an ICMP packet). I have the feeling that this should + * be unconditional, but I'm not in a position to check. + */ #if !SOLARIS && !defined(__sgi) - sumd += (sumd & 0xffff); - while (sumd > 0xffff) - sumd = (sumd & 0xffff) + (sumd >> 16); - fix_incksum(&icmp->icmp_cksum, sumd, 0); + /* + * Fix UDP pseudo header checksum to compensate for the + * IP address change. + */ + if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) { + /* + * The UDP checksum is optional, only adjust it + * if it has been set + */ + sum1 = ntohs(udp->uh_sum); + fix_datacksum(&udp->uh_sum, sumd); + sum2 = ntohs(udp->uh_sum); + + /* + * Fix ICMP checksum to compensate the UDP + * checksum adjustment. + */ + CALC_SUMD(sum1, sum2, sumd); + fix_incksum(&icmp->icmp_cksum, sumd); + } + +#if 0 + /* + * Fix TCP pseudo header checksum to compensate for the + * IP address change. Before we can do the change, we + * must make sure that oip is sufficient large to hold + * the TCP checksum (normally it does not!). + */ + if (oip->ip_p == IPPROTO_TCP) { + + }; +#endif + #endif } @@ -1623,23 +1776,98 @@ int dir; * XXX - what if this is bogus hl and we go off the end ? * In this case, nat_icmpinlookup() will have returned NULL. */ - tcp = (tcphdr_t *)((((char *)oip) + (oip->ip_hl << 2))); + tcp = (tcphdr_t *)udp; + + /* + * Step 2 : + * For offending TCP/UDP IP packets, translate the ports as + * well, based on the NAT specification. Of course such + * a change must be reflected in the ICMP checksum as well. + * + * Advance notice : Now it becomes complicated :-) + * + * Since the port fields are part of the TCP/UDP checksum + * of the offending IP packet, you need to adjust that checksum + * as well... but, if you change, you must change the icmp + * checksum *again*, to reflect that change. + * + * To further complicate: the TCP checksum is not in the first + * 8 bytes of the offending ip packet, so it most likely is not + * available (we might have to fix that if the encounter a + * device that returns more than 8 data bytes on icmp error) + */ if (nat->nat_dir == NAT_OUTBOUND) { if (tcp->th_sport != nat->nat_inport) { + /* + * Fix ICMP checksum to compensate port + * adjustment. + */ sum1 = ntohs(tcp->th_sport); sum2 = ntohs(nat->nat_inport); CALC_SUMD(sum1, sum2, sumd); tcp->th_sport = nat->nat_inport; - fix_outcksum(&icmp->icmp_cksum, sumd, 0); + fix_outcksum(&icmp->icmp_cksum, sumd); + + /* + * Fix udp checksum to compensate port + * adjustment. NOTE : the offending IP packet + * flows the other direction compared to the + * ICMP message. + * + * The UDP checksum is optional, only adjust + * it if it has been set. + */ + if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) { + + sum1 = ntohs(udp->uh_sum); + fix_datacksum(&udp->uh_sum, sumd); + sum2 = ntohs(udp->uh_sum); + + /* + * Fix ICMP checksum to + * compensate UDP checksum + * adjustment. + */ + CALC_SUMD(sum1, sum2, sumd); + fix_outcksum(&icmp->icmp_cksum, sumd); + } } } else { + if (tcp->th_dport != nat->nat_outport) { + /* + * Fix ICMP checksum to compensate port + * adjustment. + */ sum1 = ntohs(tcp->th_dport); sum2 = ntohs(nat->nat_outport); CALC_SUMD(sum1, sum2, sumd); tcp->th_dport = nat->nat_outport; - fix_incksum(&icmp->icmp_cksum, sumd, 0); + fix_incksum(&icmp->icmp_cksum, sumd); + + /* + * Fix udp checksum to compensate port + * adjustment. NOTE : the offending IP + * packet flows the other direction compared + * to the ICMP message. + * + * The UDP checksum is optional, only adjust + * it if it has been set. + */ + if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) { + + sum1 = ntohs(udp->uh_sum); + fix_datacksum(&udp->uh_sum, sumd); + sum2 = ntohs(udp->uh_sum); + + /* + * Fix ICMP checksum to compensate + * UDP checksum adjustment. + */ + CALC_SUMD(sum1, sum2, sumd); + fix_incksum(&icmp->icmp_cksum, sumd); + } } } } @@ -1664,30 +1892,92 @@ register u_int flags, p; struct in_addr src , mapdst; u_32_t ports; { - register u_short sport, mapdport; + register u_short sport, dport; register nat_t *nat; register int nflags; + register u_32_t dst; u_int hv; - mapdport = ports >> 16; + dst = mapdst.s_addr; + dport = ports >> 16; sport = ports & 0xffff; flags &= IPN_TCPUDP; - hv = NAT_HASH_FN(mapdst.s_addr, mapdport, ipf_nattable_sz); + hv = NAT_HASH_FN(dst, dport, ipf_nattable_sz); nat = nat_table[1][hv]; for (; nat; nat = nat->nat_hnext[1]) { nflags = nat->nat_flags; if ((!ifp || ifp == nat->nat_ifp) && nat->nat_oip.s_addr == src.s_addr && - nat->nat_outip.s_addr == mapdst.s_addr && + nat->nat_outip.s_addr == dst && (((p == 0) && (flags == (nat->nat_flags & IPN_TCPUDP))) || (p == nat->nat_p)) && (!flags || (((nat->nat_oport == sport) || (nflags & FI_W_DPORT)) && - ((nat->nat_outport == mapdport) || - (nflags & FI_W_SPORT))))) + ((nat->nat_outport == dport) || (nflags & FI_W_SPORT))))) return nat; } - return NULL; + if (!nat_wilds || !(flags & IPN_TCPUDP)) + return NULL; + RWLOCK_EXIT(&ipf_nat); + hv = NAT_HASH_FN(dst, 0, ipf_nattable_sz); + WRITE_ENTER(&ipf_nat); + nat = nat_table[1][hv]; + for (; nat; nat = nat->nat_hnext[1]) { + nflags = nat->nat_flags; + if (ifp && ifp != nat->nat_ifp) + continue; + if (!(nflags & IPN_TCPUDP)) + continue; + if (!(nflags & FI_WILDP)) + continue; + if (nat->nat_oip.s_addr != src.s_addr || + nat->nat_outip.s_addr != dst) + continue; + if (((nat->nat_oport == sport) || (nflags & FI_W_DPORT)) && + ((nat->nat_outport == dport) || (nflags & FI_W_SPORT))) { + hv = NAT_HASH_FN(dst, dport, ipf_nattable_sz); + nat_tabmove(nat, hv); + break; + } + } + MUTEX_DOWNGRADE(&ipf_nat); + return nat; +} + + +static void nat_tabmove(nat, hv) +nat_t *nat; +u_int hv; +{ + nat_t **natp; + + /* + * Remove the NAT entry from the old location + */ + if (nat->nat_hnext[0]) + nat->nat_hnext[0]->nat_phnext[0] = nat->nat_phnext[0]; + *nat->nat_phnext[0] = nat->nat_hnext[0]; + + if (nat->nat_hnext[1]) + nat->nat_hnext[0]->nat_phnext[1] = nat->nat_phnext[1]; + *nat->nat_phnext[1] = nat->nat_hnext[1]; + + natp = &nat_table[0][hv]; + if (*natp) + (*natp)->nat_phnext[0] = &nat->nat_hnext[0]; + nat->nat_phnext[0] = natp; + nat->nat_hnext[0] = *natp; + *natp = nat; + + /* + * Add into the NAT table in the new position + */ + natp = &nat_table[1][hv]; + if (*natp) + (*natp)->nat_phnext[1] = &nat->nat_hnext[1]; + nat->nat_phnext[1] = natp; + nat->nat_hnext[1] = *natp; + *natp = nat; } @@ -1706,19 +1996,21 @@ u_32_t ports; register u_short sport, dport; register nat_t *nat; register int nflags; + u_32_t srcip; u_int hv; sport = ports & 0xffff; dport = ports >> 16; flags &= IPN_TCPUDP; + srcip = src.s_addr; - hv = NAT_HASH_FN(src.s_addr, sport, ipf_nattable_sz); + hv = NAT_HASH_FN(srcip, sport, ipf_nattable_sz); nat = nat_table[0][hv]; for (; nat; nat = nat->nat_hnext[0]) { nflags = nat->nat_flags; if ((!ifp || ifp == nat->nat_ifp) && - nat->nat_inip.s_addr == src.s_addr && + nat->nat_inip.s_addr == srcip && nat->nat_oip.s_addr == dst.s_addr && (((p == 0) && (flags == (nat->nat_flags & IPN_TCPUDP))) || (p == nat->nat_p)) && (!flags || @@ -1726,7 +2018,32 @@ u_32_t ports; (nat->nat_oport == dport || nflags & FI_W_DPORT)))) return nat; } - return NULL; + if (!nat_wilds || !(flags & IPN_TCPUDP)) + return NULL; + RWLOCK_EXIT(&ipf_nat); + hv = NAT_HASH_FN(srcip, 0, ipf_nattable_sz); + WRITE_ENTER(&ipf_nat); + nat = nat_table[0][hv]; + for (; nat; nat = nat->nat_hnext[0]) { + nflags = nat->nat_flags; + if (ifp && ifp != nat->nat_ifp) + continue; + if (!(nflags & IPN_TCPUDP)) + continue; + if (!(nflags & FI_WILDP)) + continue; + 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))) { + hv = NAT_HASH_FN(srcip, sport, ipf_nattable_sz); + nat_tabmove(nat, hv); + break; + } + } + MUTEX_DOWNGRADE(&ipf_nat); + return nat; } @@ -1862,6 +2179,7 @@ fr_info_t *fin; nat->nat_outport = sport; nat->nat_flags &= ~(FI_W_DPORT|FI_W_SPORT); nflags = nat->nat_flags; + nat_wilds--; } } else { RWLOCK_EXIT(&ipf_nat); @@ -1942,16 +2260,16 @@ maskloop: CALC_SUMD(s1, s2, sumd); if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(&ip->ip_sum, sumd, 0); + fix_incksum(&ip->ip_sum, sumd); else - fix_outcksum(&ip->ip_sum, sumd, 0); + fix_outcksum(&ip->ip_sum, sumd); } #if SOLARIS || defined(__sgi) else { if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(&ip->ip_sum, nat->nat_ipsumd, 0); + fix_outcksum(&ip->ip_sum, nat->nat_ipsumd); else - fix_incksum(&ip->ip_sum, nat->nat_ipsumd, 0); + fix_incksum(&ip->ip_sum, nat->nat_ipsumd); } #endif ip->ip_src = nat->nat_outip; @@ -1995,11 +2313,9 @@ maskloop: if (csump) { if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(csump, nat->nat_sumd[1], - ip->ip_len); + fix_outcksum(csump, nat->nat_sumd[1]); else - fix_incksum(csump, nat->nat_sumd[1], - ip->ip_len); + fix_incksum(csump, nat->nat_sumd[1]); } } @@ -2076,6 +2392,7 @@ fr_info_t *fin; nat->nat_outport = dport; nat->nat_flags &= ~(FI_W_SPORT|FI_W_DPORT); nflags = nat->nat_flags; + nat_wilds--; } } else { RWLOCK_EXIT(&ipf_nat); @@ -2153,9 +2470,9 @@ maskloop: */ #if SOLARIS || defined(__sgi) if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(&ip->ip_sum, nat->nat_ipsumd, 0); + fix_incksum(&ip->ip_sum, nat->nat_ipsumd); else - fix_outcksum(&ip->ip_sum, nat->nat_ipsumd, 0); + fix_outcksum(&ip->ip_sum, nat->nat_ipsumd); #endif if (!(ip->ip_off & IP_OFFMASK) && !(fin->fin_fi.fi_fl & FI_SHORT)) { @@ -2196,11 +2513,9 @@ maskloop: if (csump) { if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(csump, nat->nat_sumd[0], - 0); + fix_incksum(csump, nat->nat_sumd[0]); else - fix_outcksum(csump, nat->nat_sumd[0], - 0); + fix_outcksum(csump, nat->nat_sumd[0]); } } ATOMIC_INCL(nat_stats.ns_mapped[0]); diff --git a/sys/contrib/ipfilter/netinet/ip_nat.h b/sys/contrib/ipfilter/netinet/ip_nat.h index 26fed25..c2ff100 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.9 2000/10/19 15:44:04 darrenr Exp $ */ #ifndef __IP_NAT_H__ @@ -81,7 +81,7 @@ typedef struct nat { struct hostmap *nat_hm; struct nat *nat_next; struct nat *nat_hnext[2]; - struct nat **nat_hstart[2]; + struct nat **nat_phnext[2]; void *nat_ifp; int nat_dir; char nat_ifname[IFNAMSIZ]; @@ -141,6 +141,11 @@ typedef struct ipnat { #define NAT_REDIRECT 0x02 #define NAT_BIMAP (NAT_MAP|NAT_REDIRECT) #define NAT_MAPBLK 0x04 +/* 0x100 reserved for FI_W_SPORT */ +/* 0x200 reserved for FI_W_DPORT */ +/* 0x400 reserved for FI_W_SADDR */ +/* 0x800 reserved for FI_W_DADDR */ +/* 0x1000 reserved for FI_W_NEWFR */ #define MAPBLK_MINPORT 1024 /* don't use reserved ports for src port */ #define USABLE_PORTS (65536 - MAPBLK_MINPORT) @@ -293,7 +298,8 @@ extern int ip_natout __P((ip_t *, fr_info_t *)); extern int ip_natin __P((ip_t *, fr_info_t *)); extern void ip_natunload __P((void)), ip_natexpire __P((void)); extern void nat_log __P((struct nat *, u_int)); -extern void fix_incksum __P((u_short *, u_32_t, int)); -extern void fix_outcksum __P((u_short *, u_32_t, int)); +extern void fix_incksum __P((u_short *, u_32_t)); +extern void fix_outcksum __P((u_short *, u_32_t)); +extern void fix_datacksum __P((u_short *, u_32_t)); #endif /* __IP_NAT_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c b/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c index 18ca474..d801410 100644 --- a/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c @@ -1,5 +1,5 @@ /* - * $Id: ip_raudio_pxy.c,v 1.7.2.1 2000/05/06 11:19:33 darrenr Exp $ + * $Id: ip_raudio_pxy.c,v 1.7.2.2 2000/09/03 00:23:12 darrenr Exp $ */ #if SOLARIS && defined(_KERNEL) extern kmutex_t ipf_rw; @@ -171,8 +171,8 @@ nat_t *nat; tcphdr_t *tcp, tcph, *tcp2 = &tcph; raudio_t *rap = aps->aps_data; struct in_addr swa, swb; - u_int a1, a2, a3, a4; int off, dlen, slen; + int a1, a2, a3, a4; u_short sp, dp; fr_info_t fi; tcp_seq seq; diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index f05c887..4f7460e 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/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-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.17 2000/08/08 16:01:03 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.22 2000/10/26 10:41:29 darrenr Exp $"; #endif #include <sys/errno.h> @@ -106,6 +106,7 @@ static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.17 2000/08/08 16:01:03 static ipstate_t **ips_table = NULL; static ipstate_t *ips_list = NULL; static int ips_num = 0; +static int ips_wild = 0; static ips_stat_t ips_stats; #if (SOLARIS || defined(__sgi)) && defined(_KERNEL) extern KRWLOCK_T ipf_state, ipf_mutex; @@ -123,6 +124,7 @@ static int fr_state_flush __P((int)); static ips_stat_t *fr_statetstats __P((void)); static void fr_delstate __P((ipstate_t *)); static int fr_state_remove __P((caddr_t)); +static void fr_ipsmove __P((ipstate_t **, ipstate_t *, u_int)); int fr_stputent __P((caddr_t)); int fr_stgetent __P((caddr_t)); void fr_stinsert __P((ipstate_t *)); @@ -135,7 +137,8 @@ u_long fr_tcpidletimeout = FIVE_DAYS, fr_tcpclosewait = 2 * TCP_MSL, fr_tcplastack = 2 * TCP_MSL, fr_tcptimeout = 2 * TCP_MSL, - fr_tcpclosed = 1, + fr_tcpclosed = 120, + fr_tcphalfclosed = 2 * 2 * 3600, /* 2 hours */ fr_udptimeout = 240, fr_icmptimeout = 120; int fr_statemax = IPSTATE_MAX, @@ -240,9 +243,12 @@ caddr_t data; for (sp = ips_list; sp; sp = sp->is_next) if ((sp->is_p == st.is_p) && (sp->is_v == st.is_v) && - !bcmp(&sp->is_src, &st.is_src, sizeof(st.is_src)) && - !bcmp(&sp->is_dst, &st.is_src, sizeof(st.is_dst)) && - !bcmp(&sp->is_ps, &st.is_ps, sizeof(st.is_ps))) { + !bcmp((char *)&sp->is_src, (char *)&st.is_src, + sizeof(st.is_src)) && + !bcmp((char *)&sp->is_dst, (char *)&st.is_src, + sizeof(st.is_dst)) && + !bcmp((char *)&sp->is_ps, (char *)&st.is_ps, + sizeof(st.is_ps))) { WRITE_ENTER(&ipf_state); #ifdef IPFILTER_LOG ipstate_log(sp, ISL_REMOVE); @@ -590,8 +596,8 @@ u_int flags; hv += tcp->th_dport; hv += tcp->th_sport; } - is->is_send = ntohl(tcp->th_seq) + ip->ip_len - - fin->fin_hlen - (tcp->th_off << 2) + + is->is_send = ntohl(tcp->th_seq) + fin->fin_dlen - + (tcp->th_off << 2) + ((tcp->th_flags & TH_SYN) ? 1 : 0) + ((tcp->th_flags & TH_FIN) ? 1 : 0); is->is_maxsend = is->is_send; @@ -660,6 +666,8 @@ u_int flags; is->is_flags = fin->fin_fi.fi_fl & FI_CMP; is->is_flags |= FI_CMP << 4; is->is_flags |= flags & (FI_WILDP|FI_WILDA); + if (flags & (FI_WILDP|FI_WILDA)) + ips_wild++; is->is_ifp[1 - out] = NULL; is->is_ifp[out] = fin->fin_ifp; #ifdef _KERNEL @@ -718,6 +726,7 @@ tcphdr_t *tcp; ((tcp->th_flags & TH_SYN) ? 1 : 0) + ((tcp->th_flags & TH_FIN) ? 1 : 0); + MUTEX_ENTER(&is->is_lock); if (fdata->td_end == 0) { /* * Must be a (outgoing) SYN-ACK in reply to a SYN. @@ -783,12 +792,11 @@ tcphdr_t *tcp; /* * Nearing end of connection, start timeout. */ - MUTEX_ENTER(&is->is_lock); /* source ? 0 : 1 -> !source */ fr_tcp_age(&is->is_age, is->is_state, fin, !source); - MUTEX_EXIT(&is->is_lock); ret = 1; } + MUTEX_EXIT(&is->is_lock); return ret; } @@ -892,6 +900,7 @@ tcphdr_t *tcp; is->is_maxdend = is->is_dend + 1; } is->is_flags &= ~(FI_W_SPORT|FI_W_DPORT); + ips_wild--; } ret = -1; @@ -983,7 +992,7 @@ fr_info_t *fin; * Only a basic IP header (no options) should be with * an ICMP error header. */ - if (((ip->ip_v != 4) && (ip->ip_hl != 5)) || + if (((ip->ip_v != 4) || (ip->ip_hl != 5)) || (fin->fin_plen < ICMPERR_MINPKTLEN)) return NULL; ic = (struct icmp *)fin->fin_dp; @@ -1037,8 +1046,8 @@ fr_info_t *fin; * the IP6EQ and IP6NEQ macros produce the wrong results because * of the 'junk' in the unused part of the union */ - bzero(&src, sizeof(src)); - bzero(&dst, sizeof(dst)); + bzero((char *)&src, sizeof(src)); + bzero((char *)&dst, sizeof(dst)); if (oip->ip_p == IPPROTO_ICMP) { icmp = (icmphdr_t *)((char *)oip + (oip->ip_hl << 2)); @@ -1158,6 +1167,38 @@ fr_info_t *fin; return NULL; } + +static void fr_ipsmove(isp, is, hv) +ipstate_t **isp, *is; +u_int hv; +{ + u_int hvm; + + hvm = is->is_hv; + /* + * Remove the hash from the old location... + */ + if (is->is_hnext) + is->is_hnext->is_phnext = isp; + *isp = is->is_hnext; + if (ips_table[hvm] == NULL) + ips_stats.iss_inuse--; + + /* + * ...and put the hash in the new one. + */ + hvm = hv % fr_statesize; + isp = &ips_table[hvm]; + if (*isp) + (*isp)->is_phnext = &is->is_hnext; + else + ips_stats.iss_inuse++; + is->is_phnext = isp; + is->is_hnext = *isp; + *isp = is; +} + + /* * Check if a packet has a registered state. */ @@ -1240,7 +1281,7 @@ fr_info_t *fin; break; case IPPROTO_TCP : { - register u_short dport = tcp->th_dport, sport = tcp->th_sport; + register u_short dport, sport; register int i; i = tcp->th_flags; @@ -1250,57 +1291,42 @@ fr_info_t *fin; if ((i & TH_RST) && ((i & (TH_FIN|TH_SYN|TH_RST)) != TH_RST)) break; + case IPPROTO_UDP : + dport = tcp->th_dport; + sport = tcp->th_sport; tryagain = 0; -retry_tcp: - hvm = hv % fr_statesize; - WRITE_ENTER(&ipf_state); - for (isp = &ips_table[hvm]; (is = *isp); - isp = &is->is_hnext) - - - if ((is->is_p == pr) && (is->is_v == v) && - fr_matchsrcdst(is, src, dst, fin, tcp)) { - if (fr_tcpstate(is, fin, ip, tcp)) - break; - is = NULL; - break; - } - if (is != NULL) - break; - RWLOCK_EXIT(&ipf_state); hv += dport; hv += sport; - if (tryagain == 0) { - tryagain = 1; - goto retry_tcp; - } - break; - } - case IPPROTO_UDP : - { - register u_short dport = tcp->th_dport, sport = tcp->th_sport; - - tryagain = 0; -retry_udp: - hvm = hv % fr_statesize; - /* - * Nothing else to match on but ports. and IP#'s - */ READ_ENTER(&ipf_state); - for (is = ips_table[hvm]; is; is = is->is_hnext) +retry_tcpudp: + hvm = hv % fr_statesize; + for (isp = &ips_table[hvm]; (is = *isp); isp = &is->is_hnext) if ((is->is_p == pr) && (is->is_v == v) && fr_matchsrcdst(is, src, dst, fin, tcp)) { - is->is_age = fr_udptimeout; + if ((pr == IPPROTO_TCP)) { + if (!fr_tcpstate(is, fin, ip, tcp)) { + continue; + } + } break; } - if (is != NULL) + if (is != NULL) { + if (tryagain && + !(is->is_flags & (FI_WILDP|FI_WILDA))) { + hv += dport; + hv += sport; + fr_ipsmove(isp, is, hv); + MUTEX_DOWNGRADE(&ipf_state); + } break; + } RWLOCK_EXIT(&ipf_state); - hv += dport; - hv += sport; - if (tryagain == 0) { + if (!tryagain && ips_wild) { + hv -= dport; + hv -= sport; tryagain = 1; - goto retry_udp; + WRITE_ENTER(&ipf_state); + goto retry_tcpudp; } break; } @@ -1357,6 +1383,8 @@ ipstate_t *is; { frentry_t *fr; + if (is->is_flags & (FI_WILDP|FI_WILDA)) + ips_wild--; if (is->is_next) is->is_next->is_pnext = is->is_pnext; *is->is_pnext = is->is_next; @@ -1566,7 +1594,7 @@ int dir; * SYN_RECEIVED -> FIN_WAIT_1 */ state[dir] = TCPS_FIN_WAIT_1; - *age = fr_tcpidletimeout; /* or fr_tcptimeout? */ + *age = fr_tcpidletimeout; } break; @@ -1578,7 +1606,7 @@ int dir; * ESTABLISHED -> FIN_WAIT_1 */ state[dir] = TCPS_FIN_WAIT_1; - *age = fr_tcpidletimeout; + *age = fr_tcphalfclosed; } else if (flags & TH_ACK) { /* an ACK, should we exclude other flags here? */ if (ostate == TCPS_FIN_WAIT_1) { @@ -1590,7 +1618,7 @@ int dir; * a half-closed connection */ state[dir] = TCPS_CLOSE_WAIT; - *age = fr_tcpidletimeout; + *age = fr_tcphalfclosed; } else if (ostate < TCPS_CLOSE_WAIT) /* * Still a fully established connection, @@ -1614,7 +1642,7 @@ int dir; * closed already and we did not close our side yet; * reset timeout */ - *age = fr_tcpidletimeout; + *age = fr_tcphalfclosed; } break; @@ -1638,7 +1666,7 @@ int dir; * other side is still active (ESTABLISHED/CLOSE_WAIT); * continue with this half-closed connection */ - *age = fr_tcpidletimeout; + *age = fr_tcphalfclosed; break; case TCPS_CLOSING: /* 7 */ diff --git a/sys/contrib/ipfilter/netinet/ip_state.h b/sys/contrib/ipfilter/netinet/ip_state.h index a5643af..1d1bc00 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.h +++ b/sys/contrib/ipfilter/netinet/ip_state.h @@ -6,7 +6,7 @@ * to the original author and the contributors. * * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed - * $Id: ip_state.h,v 2.13.2.1 2000/07/08 02:15:35 darrenr Exp $ + * $Id: ip_state.h,v 2.13.2.2 2000/08/23 11:01:31 darrenr Exp $ */ #ifndef __IP_STATE_H__ #define __IP_STATE_H__ @@ -173,6 +173,7 @@ extern u_long fr_tcpclosewait; extern u_long fr_tcplastack; extern u_long fr_tcptimeout; extern u_long fr_tcpclosed; +extern u_long fr_tcphalfclosed; extern u_long fr_udptimeout; extern u_long fr_icmptimeout; extern int fr_state_lock; diff --git a/sys/contrib/ipfilter/netinet/ipl.h b/sys/contrib/ipfilter/netinet/ipl.h index 866d34d..cfec734 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -6,12 +6,12 @@ * to the original author and the contributors. * * @(#)ipl.h 1.21 6/5/96 - * $Id: ipl.h,v 2.15.2.10 2000/08/07 15:10:09 darrenr Exp $ + * $Id: ipl.h,v 2.15.2.13 2000/10/25 11:08:41 darrenr Exp $ */ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v3.4.9" +#define IPL_VERSION "IP Filter: v3.4.12" #endif diff --git a/sys/contrib/ipfilter/netinet/mlfk_ipl.c b/sys/contrib/ipfilter/netinet/mlfk_ipl.c index f869149..f96c57e 100644 --- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c +++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mlfk_ipl.c,v 2.1.2.3 2000/08/13 03:42:42 darrenr Exp $ + * $Id: mlfk_ipl.c,v 2.1.2.4 2000/08/23 11:02:33 darrenr Exp $ */ @@ -65,6 +65,8 @@ SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RW, &fr_tcptimeout, 0, ""); SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RW, &fr_tcpclosed, 0, ""); +SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RW, + &fr_tcphalfclosed, 0, ""); SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RW, &fr_udptimeout, 0, ""); SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RW, |