From 88e219ce9d353ae6b1fa86f63f33960bbc7dfbc5 Mon Sep 17 00:00:00 2001 From: darrenr Date: Mon, 21 Jun 2004 22:26:10 +0000 Subject: Import ipfilter 3.4.35 (destinated for RELENG_4) to vendor branch --- sys/contrib/ipfilter/netinet/fil.c | 297 ++++++++++++++++++--- sys/contrib/ipfilter/netinet/ip_auth.c | 16 +- sys/contrib/ipfilter/netinet/ip_compat.h | 20 +- sys/contrib/ipfilter/netinet/ip_fil.c | 109 +++++--- sys/contrib/ipfilter/netinet/ip_fil.h | 6 +- sys/contrib/ipfilter/netinet/ip_frag.c | 27 +- sys/contrib/ipfilter/netinet/ip_frag.h | 3 +- sys/contrib/ipfilter/netinet/ip_ftp_pxy.c | 38 +-- sys/contrib/ipfilter/netinet/ip_log.c | 13 +- sys/contrib/ipfilter/netinet/ip_nat.c | 386 ++++++++++++--------------- sys/contrib/ipfilter/netinet/ip_nat.h | 43 +-- sys/contrib/ipfilter/netinet/ip_raudio_pxy.c | 8 +- sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c | 5 +- sys/contrib/ipfilter/netinet/ip_state.c | 172 ++++++++---- sys/contrib/ipfilter/netinet/ip_state.h | 3 +- sys/contrib/ipfilter/netinet/ipl.h | 4 +- 16 files changed, 736 insertions(+), 414 deletions(-) diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index a981fcb..1a1da36 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -42,6 +42,7 @@ # include # endif #else +# include # include # if SOLARIS2 < 5 # include @@ -97,7 +98,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.67 2002/12/06 13:28:05 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: fil.c,v 2.35.2.82 2004/06/20 10:27:47 darrenr Exp $"; #endif #ifndef _KERNEL @@ -144,6 +145,9 @@ fr_info_t frcache[2]; static int frflushlist __P((int, minor_t, int *, frentry_t **)); #ifdef _KERNEL static void frsynclist __P((frentry_t *)); +# ifndef __sgi +static void *ipf_pullup __P((mb_t *, fr_info_t *, int, void *)); +# endif #endif @@ -192,19 +196,27 @@ struct optlist secopt[8] = { * compact the IP header into a structure which contains just the info. * which is useful for comparing IP headers with. */ -void fr_makefrip(hlen, ip, fin) +int fr_makefrip(hlen, ip, fin) int hlen; ip_t *ip; fr_info_t *fin; { u_short optmsk = 0, secmsk = 0, auth = 0; int i, mv, ol, off, p, plen, v; +#if defined(_KERNEL) +# if SOLARIS + mb_t *m = fin->fin_qfm; +# else + mb_t *m = fin->fin_mp ? *fin->fin_mp : NULL; +# endif +#endif fr_ip_t *fi = &fin->fin_fi; struct optlist *op; u_char *s, opt; tcphdr_t *tcp; fin->fin_rev = 0; + fin->fin_dp = NULL; fin->fin_fr = NULL; fin->fin_tcpf = 0; fin->fin_data[0] = 0; @@ -218,8 +230,10 @@ fr_info_t *fin; if (v == 4) { fin->fin_id = ip->ip_id; fi->fi_tos = ip->ip_tos; +#if (OpenBSD >= 200311) && defined(_KERNEL) + ip->ip_off = ntohs(ip->ip_off); +#endif off = (ip->ip_off & IP_OFFMASK); - tcp = (tcphdr_t *)((char *)ip + hlen); (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); fi->fi_src.i6[1] = 0; fi->fi_src.i6[2] = 0; @@ -233,6 +247,9 @@ fr_info_t *fin; fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0; if (ip->ip_off & (IP_MF|IP_OFFMASK)) fi->fi_fl |= FI_FRAG; +#if (OpenBSD >= 200311) && defined(_KERNEL) + ip->ip_len = ntohs(ip->ip_len); +#endif plen = ip->ip_len; fin->fin_dlen = plen - hlen; } @@ -244,7 +261,6 @@ fr_info_t *fin; p = ip6->ip6_nxt; fi->fi_p = p; fi->fi_ttl = ip6->ip6_hlim; - tcp = (tcphdr_t *)(ip6 + 1); fi->fi_src.in6 = ip6->ip6_src; fi->fi_dst.in6 = ip6->ip6_dst; fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff); @@ -256,14 +272,23 @@ fr_info_t *fin; } #endif else - return; + return -1; fin->fin_off = off; fin->fin_plen = plen; - fin->fin_dp = (char *)tcp; + tcp = (tcphdr_t *)((char *)ip + hlen); fin->fin_misc = 0; off <<= 3; + /* + * For both ICMPV6 & ICMP, we attempt to pullup the entire packet into + * a single buffer for recognised error return packets. Why? Because + * the entire data section of the ICMP payload is considered to be of + * significance and maybe required in NAT/state processing, so rather + * than be careful later, attempt to get it all in one buffeer first. + * For TCP we just make sure the _entire_ TCP header is in the first + * buffer for convienience. + */ switch (p) { #ifdef USE_INET6 @@ -272,7 +297,7 @@ fr_info_t *fin; int minicmpsz = sizeof(struct icmp6_hdr); struct icmp6_hdr *icmp6; - if (fin->fin_dlen > 1) { + if (!(fin->fin_fl & FI_SHORT) && (fin->fin_dlen > 1)) { fin->fin_data[0] = *(u_short *)tcp; icmp6 = (struct icmp6_hdr *)tcp; @@ -287,6 +312,14 @@ fr_info_t *fin; case ICMP6_PACKET_TOO_BIG : case ICMP6_TIME_EXCEEDED : case ICMP6_PARAM_PROB : +# if defined(KERNEL) && !defined(__sgi) + if ((m != NULL) && (M_BLEN(m) < plen)) { + ip = ipf_pullup(m, fin, plen, ip); + if (ip == NULL) + return -1; + tcp = (tcphdr_t *)((char *)ip + hlen); + } +# endif /* KERNEL && !__sgi */ minicmpsz = ICMP6ERR_IPICMPHLEN; break; default : @@ -294,22 +327,27 @@ fr_info_t *fin; } } - if (!(plen >= minicmpsz)) + if (!(fin->fin_dlen >= minicmpsz)) fi->fi_fl |= FI_SHORT; break; } -#endif +#endif /* USE_INET6 */ + case IPPROTO_ICMP : { int minicmpsz = sizeof(struct icmp); icmphdr_t *icmp; - if (!off && (fin->fin_dlen > 1)) { + if (!off && (fin->fin_dlen > 1) && !(fin->fin_fl & FI_SHORT)) { fin->fin_data[0] = *(u_short *)tcp; icmp = (icmphdr_t *)tcp; + /* + * Minimum ICMP packet is type(1) code(1) cksum(2) + * plus 4 bytes following, totalling 8 bytes. + */ switch (icmp->icmp_type) { case ICMP_ECHOREPLY : @@ -325,7 +363,7 @@ fr_info_t *fin; */ case ICMP_TSTAMP : case ICMP_TSTAMPREPLY : - minicmpsz = 20; + minicmpsz = ICMP_MINLEN + 12; break; /* * type(1) + code(1) + cksum(2) + id(2) seq(2) + @@ -333,9 +371,28 @@ fr_info_t *fin; */ case ICMP_MASKREQ : case ICMP_MASKREPLY : - minicmpsz = 12; + minicmpsz = ICMP_MINLEN + 4; + break; + /* + * type(1) + code(1) + cksum(2) + arg(4) ip(20+) + */ + case ICMP_UNREACH : + case ICMP_SOURCEQUENCH : + case ICMP_REDIRECT : + case ICMP_TIMXCEED : + case ICMP_PARAMPROB : +#if defined(KERNEL) && !defined(__sgi) + if ((m != NULL) && (M_BLEN(m) < plen)) { + ip = ipf_pullup(m, fin, plen, ip); + if (ip == NULL) + return -1; + tcp = (tcphdr_t *)((char *)ip + hlen); + } +#endif /* KERNEL && !__sgi */ + minicmpsz = ICMPERR_MINPKTLEN - sizeof(ip_t); break; default : + minicmpsz = ICMP_MINLEN; break; } } @@ -343,9 +400,9 @@ fr_info_t *fin; if ((!(plen >= hlen + minicmpsz) && !off) || (off && off < sizeof(struct icmp))) fi->fi_fl |= FI_SHORT; - break; } + case IPPROTO_TCP : fi->fi_fl |= FI_TCPUDP; #ifdef USE_INET6 @@ -359,6 +416,20 @@ fr_info_t *fin; (off && off < sizeof(struct tcphdr))) fi->fi_fl |= FI_SHORT; } + +#if defined(KERNEL) && !defined(__sgi) + if (!off && !(fi->fi_fl & FI_SHORT)) { + int tlen = hlen + (tcp->th_off << 2); + + if ((m != NULL) && (M_BLEN(m) < tlen)) { + ip = ipf_pullup(m, fin, tlen, ip); + if (ip == NULL) + return -1; + tcp = (tcphdr_t *)((char *)ip + hlen); + } + } +#endif /* _KERNEL && !_sgi */ + if (!(fi->fi_fl & FI_SHORT) && !off) fin->fin_tcpf = tcp->th_flags; goto getports; @@ -398,12 +469,14 @@ getports: break; } + fin->fin_dp = (char *)tcp; + #ifdef USE_INET6 if (v == 6) { fi->fi_optmsk = 0; fi->fi_secmsk = 0; fi->fi_auth = 0; - return; + return 0; } #endif @@ -460,6 +533,7 @@ getports: fi->fi_optmsk = optmsk; fi->fi_secmsk = secmsk; fi->fi_auth = auth; + return 0; } @@ -747,7 +821,7 @@ void *m; #endif /* IPFILTER_LOG */ ATOMIC_INCL(fr->fr_hits); if (passt & FR_ACCOUNT) - fr->fr_bytes += (U_QUAD_T)ip->ip_len; + fr->fr_bytes += (U_QUAD_T)fin->fin_plen; else fin->fin_icode = fr->fr_icode; fin->fin_rule = rulen; @@ -810,12 +884,17 @@ int out; int p, len, drop = 0, logit = 0; mb_t *mc = NULL; # if !defined(__SVR4) && !defined(__svr4__) + /* + * We don't do this section for Solaris because fr_precheck() does a + * pullupmsg() instead, effectively achieving the same result as here + * so no need to duplicate it. + */ # ifdef __sgi char hbuf[128]; # endif int up; -# if !SOLARIS && !defined(NETBSD_PF) && \ +# if !defined(NETBSD_PF) && \ ((defined(__FreeBSD__) && (__FreeBSD_version < 500011)) || \ defined(__OpenBSD__) || defined(_BSDI_VERSION)) if (fr_checkp != fr_check && fr_running > 0) { @@ -853,7 +932,7 @@ int out; } # endif /* CSUM_DELAY_DATA */ -# ifdef USE_INET6 +# ifdef USE_INET6 if (v == 6) { len = ntohs(((ip6_t*)ip)->ip6_plen); if (!len) @@ -861,17 +940,20 @@ int out; len += sizeof(ip6_t); p = ((ip6_t *)ip)->ip6_nxt; } else -# endif +# endif { p = ip->ip_p; len = ip->ip_len; } + fin->fin_mp = mp; + fin->fin_out = out; + if ((p == IPPROTO_TCP || p == IPPROTO_UDP || (v == 4 && p == IPPROTO_ICMP) -# ifdef USE_INET6 +# ifdef USE_INET6 || (v == 6 && p == IPPROTO_ICMPV6) -# endif +# endif )) { int plen = 0; @@ -891,7 +973,7 @@ int out; case IPPROTO_ESP: plen = 8; break; -# ifdef USE_INET6 +# ifdef USE_INET6 case IPPROTO_ICMPV6 : /* * XXX does not take intermediate header @@ -899,8 +981,10 @@ int out; */ plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t); break; -# endif +# endif } + if ((plen > 0) && (len < hlen + plen)) + fin->fin_fl |= FI_SHORT; up = MIN(hlen + plen, len); if (up > m->m_len) { @@ -915,14 +999,34 @@ int out; ip = (ip_t *)hbuf; # else /* __ sgi */ # ifndef linux - if ((*mp = m_pullup(m, up)) == 0) { - ATOMIC_INCL(frstats[out].fr_pull[1]); + /* + * Having determined that we need to pullup some data, + * try to bring as much of the packet up into a single + * buffer with the first pullup. This hopefully means + * less need for doing futher pullups. Not needed for + * Solaris because fr_precheck() does it anyway. + * + * The main potential for trouble here is if MLEN/MHLEN + * become quite small, lets say < 64 bytes...but if + * that did happen, BSD networking as a whole would be + * slow/inefficient. + */ +# ifdef MHLEN + /* + * Assume that M_PKTHDR is set and just work with what + * is left rather than check.. Should not make any + * real difference, anyway. + */ + if ((MHLEN > up) && (len > up)) + up = MIN(len, MHLEN); +# else + if ((MLEN > up) && (len > up)) + up = MIN(len, MLEN); +# endif + ip = ipf_pullup(m, fin, up, ip); + if (ip == NULL) return -1; - } else { - ATOMIC_INCL(frstats[out].fr_pull[0]); - m = *mp; - ip = mtod(m, ip_t *); - } + m = *mp; # endif /* !linux */ # endif /* __sgi */ } else @@ -935,17 +1039,21 @@ int out; if ((u_int)ip & 0x3) return 2; + fin->fin_mp = mp; + fin->fin_out = out; fin->fin_qfm = m; fin->fin_qif = qif; # endif +#else + fin->fin_mp = mp; + fin->fin_out = out; #endif /* _KERNEL */ changed = 0; - fin->fin_ifp = ifp; fin->fin_v = v; - fin->fin_out = out; - fin->fin_mp = mp; - fr_makefrip(hlen, ip, fin); + fin->fin_ifp = ifp; + if (fr_makefrip(hlen, ip, fin) == -1) + return -1; #ifdef _KERNEL # ifdef USE_INET6 @@ -1109,6 +1217,10 @@ int out; if (pass & FR_KEEPSTATE) { if (fr_addstate(ip, fin, NULL, 0) == NULL) { ATOMIC_INCL(frstats[out].fr_bads); + if (pass & FR_PASS) { + pass &= ~FR_PASS; + pass |= FR_BLOCK; + } } else { ATOMIC_INCL(frstats[out].fr_ads); } @@ -1290,6 +1402,12 @@ logit: (void) ipfr_fastroute(ip, mc, &mc, fin, &fr->fr_dif); } # endif /* !SOLARIS */ +#if (OpenBSD >= 200311) && defined(_KERNEL) + if (pass & FR_PASS) { + ip->ip_len = htons(ip->ip_len); + ip->ip_off = htons(ip->ip_off); + } +#endif return (pass & FR_PASS) ? 0 : error; #else /* _KERNEL */ if (pass & FR_NOMATCH) @@ -1387,10 +1505,10 @@ tcphdr_t *tcp; /* * Both sum and sum2 are partial sums, so combine them together. */ - sum = (sum & 0xffff) + (sum >> 16); - sum = ~sum & 0xffff; - sum2 += sum; - sum2 = (sum2 & 0xffff) + (sum2 >> 16); + sum += ~sum2 & 0xffff; + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + sum2 = ~sum & 0xffff; # else /* defined(BSD) || defined(sun) */ { union { @@ -1531,7 +1649,7 @@ nodata: * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.35.2.67 2002/12/06 13:28:05 darrenr Exp $ + * $Id: fil.c,v 2.35.2.82 2004/06/20 10:27:47 darrenr Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, @@ -1963,12 +2081,40 @@ struct in_addr *inp; static void frsynclist(fr) register frentry_t *fr; { + frdest_t *fdp; + int i; + for (; fr; fr = fr->fr_next) { - if (fr->fr_ifa != NULL) { - fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_ip.fi_v); - if (fr->fr_ifa == NULL) - fr->fr_ifa = (void *)-1; + for (i = 0; i < 4; i++) { + if ((fr->fr_ifnames[i][1] == '\0') && + ((fr->fr_ifnames[i][0] == '-') || + (fr->fr_ifnames[i][0] == '*'))) { + fr->fr_ifas[i] = NULL; + } else if (*fr->fr_ifnames[i]) { + fr->fr_ifas[i] = GETUNIT(fr->fr_ifnames[i], + fr->fr_v); + if (!fr->fr_ifas[i]) + fr->fr_ifas[i] = (void *)-1; + } + } + + fdp = &fr->fr_dif; + fr->fr_flags &= ~FR_DUP; + if (*fdp->fd_ifname) { + fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fr->fr_v); + if (!fdp->fd_ifp) + fdp->fd_ifp = (struct ifnet *)-1; + else + fr->fr_flags |= FR_DUP; } + + fdp = &fr->fr_tif; + if (*fdp->fd_ifname) { + fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fr->fr_v); + if (!fdp->fd_ifp) + fdp->fd_ifp = (struct ifnet *)-1; + } + if (fr->fr_grp) frsynclist(fr->fr_grp); } @@ -1984,6 +2130,9 @@ void frsync() (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)) # if (NetBSD >= 199905) || defined(__OpenBSD__) for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) +# elif defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) + IFNET_RLOCK(); + TAILQ_FOREACH(ifp, &ifnet, if_link); # else for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) # endif @@ -1995,6 +2144,9 @@ void frsync() ip_statesync(ifp); } ip_natsync((struct ifnet *)-1); +# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) + IFNET_RUNLOCK(); +# endif # endif /* !SOLARIS */ WRITE_ENTER(&ipf_mutex); @@ -2223,3 +2375,64 @@ mb_t *buf; return ip->ip_len; } #endif + + +#if defined(_KERNEL) && !defined(__sgi) +void *ipf_pullup(m, fin, len, ipin) +mb_t *m; +fr_info_t *fin; +int len; +void *ipin; +{ +# if SOLARIS + qif_t *qf = fin->fin_qif; +# endif + int out = fin->fin_out, dpoff, ipoff; + char *ip; + + if (m == NULL) + return NULL; + + ipoff = (char *)ipin - MTOD(m, char *); + if (fin->fin_dp != NULL) + dpoff = (char *)fin->fin_dp - (char *)ipin; + else + dpoff = 0; + + if (M_BLEN(m) < len) { +# if SOLARIS + qif_t *qf = fin->fin_qif; + int inc = 0; + + if (ipoff > 0) { + if ((ipoff & 3) != 0) { + inc = 4 - (ipoff & 3); + if (m->b_rptr - inc >= m->b_datap->db_base) + m->b_rptr -= inc; + else + inc = 0; + } + } + if (!pullupmsg(m, len + ipoff + inc)) { + ATOMIC_INCL(frstats[out].fr_pull[1]); + return NULL; + } + m->b_rptr += inc; + ATOMIC_INCL(frstats[out].fr_pull[0]); + qf->qf_data = MTOD(m, char *) + ipoff; +# else + m = m_pullup(m, len); + *fin->fin_mp = m; + if (m == NULL) { + ATOMIC_INCL(frstats[out].fr_pull[1]); + return NULL; + } + ATOMIC_INCL(frstats[out].fr_pull[0]); +# endif /* SOLARIS */ + } + ip = MTOD(m, char *) + ipoff; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)ip + dpoff; + return ip; +} +#endif /* _KERNEL */ diff --git a/sys/contrib/ipfilter/netinet/ip_auth.c b/sys/contrib/ipfilter/netinet/ip_auth.c index 604d754..566f203 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.c +++ b/sys/contrib/ipfilter/netinet/ip_auth.c @@ -104,7 +104,7 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ #endif #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.11.2.24 2002/12/06 11:40:21 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.11.2.26 2003/09/22 12:37:04 darrenr Exp $"; #endif @@ -314,7 +314,8 @@ int cmd; #endif { mb_t *m; -#if defined(_KERNEL) && !SOLARIS +#if defined(_KERNEL) && !SOLARIS && \ + (!defined(__FreeBSD_version) || (__FreeBSD_version < 501000)) struct ifqueue *ifq; int s; #endif @@ -418,7 +419,8 @@ fr_authioctlloop: bzero((char *)&ro, sizeof(ro)); # if ((_BSDI_VERSION >= 199802) && (_BSDI_VERSION < 200005)) || \ - defined(__OpenBSD__) || (defined(IRIX) && (IRIX >= 605)) + defined(__OpenBSD__) || (defined(IRIX) && (IRIX >= 605)) || \ + (__FreeBSD_version >= 470102) error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL, NULL); # else @@ -436,6 +438,9 @@ fr_authioctlloop: # if SOLARIS error = (fr_qin(fra->fra_q, m) == 0) ? EINVAL : 0; # else /* SOLARIS */ +# if __FreeBSD_version >= 501104 + netisr_dispatch(NETISR_IP, m); +# else ifq = &ipintrq; if (IF_QFULL(ifq)) { IF_DROP(ifq); @@ -443,10 +448,11 @@ fr_authioctlloop: error = ENOBUFS; } else { IF_ENQUEUE(ifq, m); -# if IRIX < 605 +# if IRIX < 605 schednetisr(NETISR_IP); -# endif +# endif } +# endif # endif /* SOLARIS */ if (error) fr_authstats.fas_quefail++; diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h index 3eacc73..7674424 100644 --- a/sys/contrib/ipfilter/netinet/ip_compat.h +++ b/sys/contrib/ipfilter/netinet/ip_compat.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_compat.h 1.8 1/14/96 - * $Id: ip_compat.h,v 2.26.2.47 2002/10/26 06:24:42 darrenr Exp $ + * $Id: ip_compat.h,v 2.26.2.52 2004/06/09 00:01:14 darrenr Exp $ */ #ifndef __IP_COMPAT_H__ @@ -65,7 +65,7 @@ #if defined(__sgi) || defined(bsdi) struct ether_addr { - u_char ether_addr_octet[6]; + u_char ether_addr_octet[6]; }; #endif @@ -163,6 +163,7 @@ struct file; # define V4_PART_OF_V6(v6) v6.s6_addr32[3] # endif # endif +# define M_BLEN(m) ((m)->b_wptr - (m)->b_rptr) typedef struct qif { struct qif *qf_next; @@ -172,6 +173,7 @@ typedef struct qif { void *qf_optr; queue_t *qf_in; queue_t *qf_out; + void *qf_data; /* layer 3 header pointer */ struct qinit *qf_wqinfo; struct qinit *qf_rqinfo; struct qinit qf_wqinit; @@ -260,7 +262,8 @@ typedef u_int32_t u_32_t; # endif # endif # if !defined(_KERNEL) && !defined(IPFILTER_LKM) && !defined(USE_INET6) -# if (defined(__FreeBSD_version) && (__FreeBSD_version >= 400000)) || \ +# if (defined(__FreeBSD_version) && (__FreeBSD_version >= 400000) && \ + !defined(NOINET6)) || \ (defined(OpenBSD) && (OpenBSD >= 200111)) || \ (defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105000000)) # define USE_INET6 @@ -523,6 +526,7 @@ extern ill_t *get_unit __P((char *, int)); # ifndef linux # define FREE_MB_T(m) m_freem(m) # define MTOD(m,t) mtod(m,t) +# define M_BLEN(m) (m)->m_len # define IRCOPY(a,b,c) (bcopy((a), (b), (c)), 0) # define IWCOPY(a,b,c) (bcopy((a), (b), (c)), 0) # define IRCOPYPTR ircopyptr @@ -541,7 +545,7 @@ extern ill_t *get_unit __P((char *, int)); # ifndef linux # define GETUNIT(n, v) ifunit(n) # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) + (defined(OpenBSD) && (OpenBSD >= 199603)) # define IFNAME(x) ((struct ifnet *)x)->if_xname # else # define USE_GETIFNAME 1 @@ -960,7 +964,7 @@ typedef struct { __u32 th_seq; __u32 th_ack; # if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ - defined(vax) + defined(__vax__) __u8 th_res:4; __u8 th_off:4; #else @@ -982,7 +986,7 @@ typedef struct { typedef struct { # if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ - defined(vax) + defined(__vax__) __u8 ip_hl:4; __u8 ip_v:4; # else @@ -1206,8 +1210,8 @@ struct ether_addr { #define ICMPERR_MINPKTLEN (20 + 8 + 20) #define ICMPERR_MAXPKTLEN (20 + 8 + 20 + 8) #define ICMP6_MINLEN 8 -#define ICMP6ERR_MINPKTLEN (40 + 8) -#define ICMP6ERR_IPICMPHLEN (40 + 8 + 40) +#define ICMP6ERR_IPICMPHLEN (40 + 8) +#define ICMP6ERR_MINPKTLEN (40 + 8 + 40) #ifndef ICMP6_DST_UNREACH # define ICMP6_DST_UNREACH 1 diff --git a/sys/contrib/ipfilter/netinet/ip_fil.c b/sys/contrib/ipfilter/netinet/ip_fil.c index 8fcd05d..00e8565 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.c +++ b/sys/contrib/ipfilter/netinet/ip_fil.c @@ -124,7 +124,7 @@ extern int ip6_getpmtu(struct route_in6 *, struct route_in6 *, #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.64 2002/12/06 11:45:45 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.76 2004/05/12 23:21:03 darrenr Exp $"; #endif @@ -504,9 +504,9 @@ int ipldetach() ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011)) int error = 0; # if __NetBSD_Version__ >= 105150000 - struct pfil_head *ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); + struct pfil_head *ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); # ifdef USE_INET6 - struct pfil_head *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); + struct pfil_head *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); # endif # endif #endif @@ -651,7 +651,7 @@ int mode; int error = 0, unit = 0, tmp; #if (BSD >= 199306) && defined(_KERNEL) - if ((securelevel >= 2) && (mode & FWRITE)) + if ((securelevel >= 3) && (mode & FWRITE)) return EPERM; #endif #ifdef _KERNEL @@ -1020,8 +1020,8 @@ caddr_t data; while ((f = *ftail)) ftail = &f->fr_next; else { + ftail = fprev; if (fp->fr_hits) { - ftail = fprev; while (--fp->fr_hits && (f = *ftail)) ftail = &f->fr_next; } @@ -1275,7 +1275,7 @@ struct mbuf **mp; frn.fin_ifp = fin->fin_ifp; frn.fin_v = fin->fin_v; frn.fin_out = fin->fin_out; - frn.fin_mp = fin->fin_mp; + frn.fin_mp = mp; ip = mtod(m, ip_t *); hlen = sizeof(*ip); @@ -1319,9 +1319,10 @@ struct mbuf **mp; m->m_pkthdr.rcvif = NULL; # endif - fr_makefrip(hlen, ip, &frn); - - error = ipfr_fastroute(m, mp, &frn, NULL); + if (fr_makefrip(hlen, ip, &frn) == 0) + error = ipfr_fastroute(m, mp, &frn, NULL); + else + error = EINVAL; return error; } @@ -1454,7 +1455,13 @@ int dst; #endif if (avail) { + slen = oip->ip_len; + oip->ip_len = htons(oip->ip_len); + soff = oip->ip_off; + oip->ip_off = htons(oip->ip_off); bcopy((char *)oip, (char *)&icmp->icmp_ip, MIN(ohlen, avail)); + oip->ip_len = slen; + oip->ip_off = soff; avail -= MIN(ohlen, avail); } @@ -1475,10 +1482,6 @@ int dst; } else #endif { - slen = oip->ip_len; - oip->ip_len = htons(oip->ip_len); - soff = oip->ip_off; - oip->ip_off = htons(ip->ip_off); ip->ip_src.s_addr = dst4.s_addr; ip->ip_dst.s_addr = oip->ip_src.s_addr; @@ -1498,13 +1501,7 @@ int dst; fin->fin_hlen = hlen; err = send_ip(oip, fin, &m); fin->fin_hlen = shlen; -#ifdef USE_INET6 - if (fin->fin_v == 4) -#endif - { - oip->ip_len = slen; - oip->ip_off = soff; - } + return err; } @@ -1562,7 +1559,7 @@ frdest_t *fdp; register struct ip *ip, *mhip; register struct mbuf *m = m0; register struct route *ro; - int len, off, error = 0, hlen, code; + int len, off, error = 0, hlen, code, sout; struct ifnet *ifp, *sifp; struct sockaddr_in *dst; struct route iproute; @@ -1628,7 +1625,7 @@ frdest_t *fdp; /* * Route packet. */ -#if defined(__sgi) && (IRIX >= 605) +#if (defined(IRIX) && (IRIX >= 605)) ROUTE_RDLOCK(); #endif bzero((caddr_t)ro, sizeof (*ro)); @@ -1647,8 +1644,12 @@ frdest_t *fdp; * check that we're going in the correct direction. */ if ((fr != NULL) && (fin->fin_rev != 0)) { - if ((ifp != NULL) && (fdp == &fr->fr_tif)) + if ((ifp != NULL) && (fdp == &fr->fr_tif)) { +# if (defined(IRIX) && (IRIX >= 605)) + ROUTE_UNLOCK(); +# endif return 0; + } } else if (fdp != NULL) { if (fdp->fd_ip.s_addr != 0) dst->sin_addr = fdp->fd_ip; @@ -1668,13 +1669,12 @@ frdest_t *fdp; rtalloc(ro); # endif -#if defined(__sgi) && (IRIX > 602) - ROUTE_UNLOCK(); -#endif - if (!ifp) { if (!fr || !(fr->fr_flags & FR_FASTROUTE)) { error = -2; +# if (defined(IRIX) && (IRIX >= 605)) + ROUTE_UNLOCK(); +# endif goto bad; } } @@ -1687,11 +1687,14 @@ frdest_t *fdp; error = EHOSTUNREACH; else error = ENETUNREACH; +# if (defined(IRIX) && (IRIX >= 605)) + ROUTE_UNLOCK(); +# endif goto bad; } if (ro->ro_rt->rt_flags & RTF_GATEWAY) { -#if BSD >= 199306 +#if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605)) dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; #else dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway; @@ -1699,6 +1702,10 @@ frdest_t *fdp; } ro->ro_rt->rt_use++; +#if (defined(IRIX) && (IRIX > 602)) + ROUTE_UNLOCK(); +#endif + /* * For input packets which are being "fastrouted", they won't * go back through output filtering and miss their chance to get @@ -1706,6 +1713,7 @@ frdest_t *fdp; */ if (fin->fin_out == 0) { sifp = fin->fin_ifp; + sout = fin->fin_out; fin->fin_ifp = ifp; fin->fin_out = 1; if ((fin->fin_fr = ipacct[1][fr_active]) && @@ -1715,10 +1723,25 @@ frdest_t *fdp; fin->fin_fr = NULL; if (!fr || !(fr->fr_flags & FR_RETMASK)) (void) fr_checkstate(ip, fin); - (void) ip_natout(ip, fin); + + switch (ip_natout(ip, fin)) + { + case 0 : + break; + case 1 : + ip->ip_sum = 0; + break; + case -1 : + error = EINVAL; + goto done; + break; + } + fin->fin_ifp = sifp; + fin->fin_out = sout; } else ip->ip_sum = 0; + /* * If small enough for interface, can just send directly. */ @@ -1748,8 +1771,14 @@ frdest_t *fdp; ip->ip_sum = in_cksum(m, hlen); # endif /* __NetBSD__ && M_CSUM_IPv4 */ # if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605)) +# ifdef IRIX + IFNET_UPPERLOCK(ifp); +# endif error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); +# ifdef IRIX + IFNET_UPPERUNLOCK(ifp); +# endif # else error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); # endif @@ -1895,7 +1924,7 @@ void *ifp; dst->sin_family = AF_INET; dst->sin_addr = ipa; # if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \ - !defined(__OpenBSD__) + !defined(__OpenBSD__) # ifdef RTF_CLONING rtalloc_ign(&iproute, RTF_CLONING); # else @@ -1947,17 +1976,18 @@ frdest_t *fdp; u_long mtu; int error; - ifp = NULL; ro = &ip6route; fr = fin->fin_fr; bzero((caddr_t)ro, sizeof(*ro)); dst6 = (struct sockaddr_in6 *)&ro->ro_dst; dst6->sin6_family = AF_INET6; dst6->sin6_len = sizeof(struct sockaddr_in6); - dst6->sin6_addr = fin->fin_fi.fi_src.in6; + dst6->sin6_addr = fin->fin_fi.fi_dst.in6; if (fdp != NULL) ifp = fdp->fd_ifp; + else + ifp = fin->fin_ifp; if ((fr != NULL) && (fin->fin_rev != 0)) { if ((ifp != NULL) && (fdp == &fr->fr_tif)) @@ -1966,9 +1996,14 @@ frdest_t *fdp; if (IP6_NOTZERO(&fdp->fd_ip6)) dst6->sin6_addr = fdp->fd_ip6.in6; } - if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) + if (ifp == NULL) return -2; +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + /* KAME */ + if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) + dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index); +#endif rtalloc((struct route *)ro); if ((ifp == NULL) && (ro->ro_rt != NULL)) @@ -1989,7 +2024,15 @@ frdest_t *fdp; error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu); if (error == 0) { #else +# ifdef IN6_LINKMTU + mtu = IN6_LINKMTU(ifp); +# else +# ifdef ND_IFINFO + mtu = ND_IFINFO(ifp)->linkmtu; +# else mtu = nd_ifinfo[ifp->if_index].linkmtu; +# endif +# endif #endif if (m0->m_pkthdr.len <= mtu) error = nd6_output(ifp, fin->fin_ifp, m0, diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h index b97c796..73099ec 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.h +++ b/sys/contrib/ipfilter/netinet/ip_fil.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ip_fil.h,v 2.29.2.34 2002/10/01 15:23:37 darrenr Exp $ + * $Id: ip_fil.h,v 2.29.2.35 2003/06/07 11:56:02 darrenr Exp $ */ #ifndef __IP_FIL_H__ @@ -151,7 +151,7 @@ typedef struct fr_info { u_short fin_dlen; /* length of data portion of packet */ u_short fin_id; /* IP packet id field */ u_int fin_misc; - void *fin_mp; /* pointer to pointer to mbuf */ + mb_t **fin_mp; /* pointer to pointer to mbuf */ #if SOLARIS void *fin_qfm; /* pointer to mblk where pkt starts */ void *fin_qif; @@ -628,7 +628,7 @@ extern void fr_forgetifp __P((void *)); extern void fr_getstat __P((struct friostat *)); extern int fr_ifpaddr __P((int, void *, struct in_addr *)); extern int fr_lock __P((caddr_t, int *)); -extern void fr_makefrip __P((int, ip_t *, fr_info_t *)); +extern int fr_makefrip __P((int, ip_t *, fr_info_t *)); extern u_short fr_tcpsum __P((mb_t *, ip_t *, tcphdr_t *)); extern int fr_scanlist __P((u_32_t, ip_t *, fr_info_t *, void *)); extern int fr_tcpudpchk __P((frtuc_t *, fr_info_t *)); diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c index 0f3b818..73f98c4 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -90,7 +90,7 @@ extern struct timeout ipfr_slowtimer_ch; #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.25 2002/12/06 11:40:21 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.10.2.28 2003/06/11 22:28:15 darrenr Exp $"; #endif @@ -195,7 +195,7 @@ ipfr_t *table[]; /* - * Instert the fragment into the fragment table, copy the struct used + * Insert the fragment into the fragment table, copy the struct used * in the search using bcopy rather than reassign each field. * Set the ttl to the default. */ @@ -423,7 +423,26 @@ fr_info_t *fin; /* * forget any references to this external object. */ -void ipfr_forget(nat) +void ipfr_forget(ptr) +void *ptr; +{ + ipfr_t *fr; + int idx; + + WRITE_ENTER(&ipf_frag); + for (idx = IPFT_SIZE - 1; idx >= 0; idx--) + for (fr = ipfr_heads[idx]; fr; fr = fr->ipfr_next) + if (fr->ipfr_data == ptr) + fr->ipfr_data = NULL; + + RWLOCK_EXIT(&ipf_frag); +} + + +/* + * forget any references to this external object. + */ +void ipfr_forgetnat(nat) void *nat; { ipfr_t *fr; @@ -431,7 +450,7 @@ void *nat; WRITE_ENTER(&ipf_natfrag); for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fr = ipfr_heads[idx]; fr; fr = fr->ipfr_next) + for (fr = ipfr_nattab[idx]; fr; fr = fr->ipfr_next) if (fr->ipfr_data == nat) fr->ipfr_data = NULL; diff --git a/sys/contrib/ipfilter/netinet/ip_frag.h b/sys/contrib/ipfilter/netinet/ip_frag.h index 4bd6b52..925f285 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.h +++ b/sys/contrib/ipfilter/netinet/ip_frag.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_frag.h 1.5 3/24/96 - * $Id: ip_frag.h,v 2.4.2.7 2002/07/06 14:17:51 darrenr Exp $ + * $Id: ip_frag.h,v 2.4.2.8 2003/06/11 22:28:16 darrenr Exp $ */ #ifndef __IP_FRAG_H__ @@ -53,6 +53,7 @@ extern int ipfr_nat_newfrag __P((ip_t *, fr_info_t *, struct nat *)); extern nat_t *ipfr_nat_knownfrag __P((ip_t *, fr_info_t *)); extern frentry_t *ipfr_knownfrag __P((ip_t *, fr_info_t *)); extern void ipfr_forget __P((void *)); +extern void ipfr_forgetnat __P((void *)); extern void ipfr_unload __P((void)); extern void ipfr_fragexpire __P((void)); diff --git a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c index 0108410..ae158de 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.42 2002/11/25 21:42:35 darrenr Exp $ + * $Id: ip_ftp_pxy.c,v 2.7.2.47 2004/06/21 11:48:07 darrenr Exp $ */ #if SOLARIS && defined(_KERNEL) extern kmutex_t ipf_rw; @@ -121,7 +121,7 @@ int dlen; int inc, off; nat_t *ipn; mb_t *m; -#if SOLARIS +#if SOLARIS && defined(_KERNEL) mb_t *m1; #endif @@ -207,8 +207,13 @@ int dlen; a1 >>= 24; olen = s - f->ftps_rptr; /* DO NOT change this to snprintf! */ +#if defined(OpenBSD) && (200311 >= 200311) + (void) snprintf(newbuf, sizeof(newbuf), "%s %u,%u,%u,%u,%u,%u\r\n", + "PORT", a1, a2, a3, a4, a5, a6); +#else (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n", "PORT", a1, a2, a3, a4, a5, a6); +#endif nlen = strlen(newbuf); inc = nlen - olen; @@ -221,7 +226,7 @@ int dlen; } #if !defined(_KERNEL) - m = *((mb_t **)fin->fin_mp); + m = *fin->fin_mp; bcopy(newbuf, (char *)m + off, nlen); #else # if SOLARIS @@ -251,7 +256,7 @@ int dlen; } copyin_mblk(m, off, nlen, newbuf); # else - m = *((mb_t **)fin->fin_mp); + m = *fin->fin_mp; if (inc < 0) m_adj(m, inc); /* the mbuf chain will be extended if necessary by m_copyback() */ @@ -263,7 +268,7 @@ int dlen; # endif #endif if (inc != 0) { -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) +#if ((SOLARIS || defined(__sgi)) && defined(_KERNEL)) || !defined(_KERNEL) register u_32_t sum1, sum2; sum1 = ip->ip_len; @@ -542,7 +547,7 @@ int dlen; return 0; #if !defined(_KERNEL) - m = *((mb_t **)fin->fin_mp); + m = *fin->fin_mp; m_copyback(m, off, nlen, newbuf); #else # if SOLARIS @@ -569,7 +574,7 @@ int dlen; } /*copyin_mblk(m, off, nlen, newbuf);*/ # else /* SOLARIS */ - m = *((mb_t **)fin->fin_mp); + m = *fin->fin_mp; if (inc < 0) m_adj(m, inc); /* the mbuf chain will be extended if necessary by m_copyback() */ @@ -577,7 +582,7 @@ int dlen; # endif /* SOLARIS */ #endif /* _KERNEL */ if (inc != 0) { -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) +#if ((SOLARIS || defined(__sgi)) && defined(_KERNEL)) || !defined(_KERNEL) register u_32_t sum1, sum2; sum1 = ip->ip_len; @@ -714,7 +719,8 @@ size_t len; if (i < 5) { #if !defined(_KERNEL) && !defined(KERNEL) - fprintf(stdout, "ippr_ftp_client_valid:i(%d) < 5\n", i); + fprintf(stdout, "ippr_ftp_client_valid:i(%lu) < 5\n", + (u_long)i); #endif return 2; } @@ -750,8 +756,8 @@ size_t len; bad_client_command: #if !defined(_KERNEL) && !defined(KERNEL) fprintf(stdout, - "ippr_ftp_client_valid:bad cmd:len %d i %d c 0x%x\n", - i, len, c); + "ippr_ftp_client_valid:bad cmd:len %lu i %lu c 0x%x\n", + (u_long)i, (u_long)len, c); #endif return 1; } @@ -812,8 +818,8 @@ size_t len; bad_server_command: #if !defined(_KERNEL) && !defined(KERNEL) fprintf(stdout, - "ippr_ftp_server_valid:bad cmd:len %d i %d c 0x%x\n", - i, len, c); + "ippr_ftp_server_valid:bad cmd:len %lu i %lu c 0x%x\n", + (u_long)i, (u_long)len, c); #endif return 1; } @@ -875,7 +881,7 @@ int rv; #if SOLARIS && defined(_KERNEL) m = fin->fin_qfm; #else - m = *((mb_t **)fin->fin_mp); + m = *fin->fin_mp; #endif #ifndef _KERNEL @@ -1025,9 +1031,9 @@ int rv; printf("inc %d sel %d rv %d\n", inc, sel, rv); printf("th_seq %x ftps_seq %x/%x\n", thseq, f->ftps_seq[0], f->ftps_seq[1]); - printf("ackmin %x ackoff %d\n", aps->aps_ackmin[sel], + printf("ackmin %x ackoff %d\n", (u_int)aps->aps_ackmin[sel], aps->aps_ackoff[sel]); - printf("seqmin %x seqoff %d\n", aps->aps_seqmin[sel], + printf("seqmin %x seqoff %d\n", (u_int)aps->aps_seqmin[sel], aps->aps_seqoff[sel]); #endif diff --git a/sys/contrib/ipfilter/netinet/ip_log.c b/sys/contrib/ipfilter/netinet/ip_log.c index e57bd69..3628a58 100644 --- a/sys/contrib/ipfilter/netinet/ip_log.c +++ b/sys/contrib/ipfilter/netinet/ip_log.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_log.c,v 2.5.2.21 2002/10/26 06:21:30 darrenr Exp $ + * $Id: ip_log.c,v 2.5.2.26 2004/06/20 01:59:01 darrenr Exp $ */ #include #if defined(KERNEL) && !defined(_KERNEL) @@ -241,16 +241,17 @@ mb_t *m; */ bzero((char *)ipfl.fl_ifname, sizeof(ipfl.fl_ifname)); # if SOLARIS && defined(_KERNEL) - ipfl.fl_unit = (u_char)ifp->ill_ppa; + ipfl.fl_unit = (u_int)ifp->ill_ppa; bcopy(ifp->ill_name, ipfl.fl_ifname, MIN(ifp->ill_name_length, sizeof(ipfl.fl_ifname))); mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0; # else # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) + (defined(OpenBSD) && (OpenBSD >= 199603)) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) strncpy(ipfl.fl_ifname, ifp->if_xname, IFNAMSIZ); # else - ipfl.fl_unit = (u_char)ifp->if_unit; + ipfl.fl_unit = (u_int)ifp->if_unit; strncpy(ipfl.fl_ifname, ifp->if_name, MIN(sizeof(ipfl.fl_ifname), sizeof(ifp->if_name))); # endif @@ -312,7 +313,7 @@ int *types, cnt; * rather than create a new one. */ MUTEX_ENTER(&ipl_mutex); - if (fin != NULL) { + if ((fin != NULL) && (fin->fin_off == 0)) { if ((ipll[dev] != NULL) && bcmp((char *)fin, (char *)&iplcrc[dev], FI_LCSIZE) == 0) { ipll[dev]->ipl_count++; @@ -428,7 +429,7 @@ struct uio *uio; SPL_NET(s); MUTEX_ENTER(&ipl_mutex); - while (!iplused[unit] || !iplt[unit]) { + while (iplt[unit] == NULL) { # if SOLARIS && defined(_KERNEL) if (!cv_wait_sig(&iplwait, &ipl_mutex)) { MUTEX_EXIT(&ipl_mutex); diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index d8c8622..4193933 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -109,12 +109,13 @@ extern struct ifnet vpnif; #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.74 2002/12/06 11:40:21 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.37.2.82 2004/05/30 17:56:52 darrenr Exp $"; #endif nat_t **nat_table[2] = { NULL, NULL }, *nat_instances = NULL; ipnat_t *nat_list = NULL; +u_int ipf_nattable_max = NAT_TABLE_MAX; u_int ipf_nattable_sz = NAT_TABLE_SZ; u_int ipf_natrules_sz = NAT_SIZE; u_int ipf_rdrrules_sz = RDR_SIZE; @@ -778,6 +779,8 @@ caddr_t data; if ((aps != NULL) && (aps->aps_data != 0)) { ng.ng_sz += sizeof(ap_session_t); ng.ng_sz += aps->aps_psiz; + if (aps->aps_psiz > 4) /* XXX - sizeof(ipn_data) */ + ng.ng_sz -= 4; } error = IWCOPY((caddr_t)&ng, data, sizeof(ng)); @@ -793,6 +796,7 @@ caddr_t data; nat_save_t ipn, *ipnp, *ipnn = NULL; register nat_t *n, *nat; ap_session_t *aps; + size_t dsz; int error; error = IRCOPY(data, (caddr_t)&ipnp, sizeof(ipnp)); @@ -824,7 +828,6 @@ caddr_t data; } ipn.ipn_next = nat->nat_next; - ipn.ipn_dsize = 0; bcopy((char *)nat, (char *)&ipn.ipn_nat, sizeof(ipn.ipn_nat)); ipn.ipn_nat.nat_data = NULL; @@ -838,10 +841,13 @@ caddr_t data; sizeof(ipn.ipn_rule)); if ((aps = nat->nat_aps)) { - ipn.ipn_dsize = sizeof(*aps); + dsz = sizeof(*aps); if (aps->aps_data) - ipn.ipn_dsize += aps->aps_psiz; - KMALLOCS(ipnn, nat_save_t *, sizeof(*ipnn) + ipn.ipn_dsize); + dsz += aps->aps_psiz; + ipn.ipn_dsize = dsz; + if (dsz > sizeof(ipn.ipn_data)) + dsz -= sizeof(ipn.ipn_data); + KMALLOCS(ipnn, nat_save_t *, sizeof(*ipnn) + dsz); if (ipnn == NULL) return ENOMEM; bcopy((char *)&ipn, (char *)ipnn, sizeof(ipn)); @@ -850,14 +856,14 @@ caddr_t data; if (aps->aps_data) { bcopy(aps->aps_data, ipnn->ipn_data + sizeof(*aps), aps->aps_psiz); - ipnn->ipn_dsize += aps->aps_psiz; } error = IWCOPY((caddr_t)ipnn, ipnp, - sizeof(ipn) + ipn.ipn_dsize); + sizeof(ipn) + dsz); if (error) error = EFAULT; - KFREES(ipnn, sizeof(*ipnn) + ipn.ipn_dsize); + KFREES(ipnn, sizeof(*ipnn) + dsz); } else { + ipn.ipn_dsize = 0; error = IWCOPY((caddr_t)&ipn, ipnp, sizeof(ipn)); if (error) error = EFAULT; @@ -885,12 +891,12 @@ caddr_t data; return EFAULT; nat = NULL; if (ipn.ipn_dsize) { - KMALLOCS(ipnn, nat_save_t *, sizeof(ipn) + ipn.ipn_dsize); + KMALLOCS(ipnn, nat_save_t *, sizeof(*ipnn) + ipn.ipn_dsize); if (ipnn == NULL) return ENOMEM; bcopy((char *)&ipn, (char *)ipnn, sizeof(ipn)); - error = IRCOPY((caddr_t)ipnp, (caddr_t)ipn.ipn_data, - ipn.ipn_dsize); + error = IRCOPY((caddr_t)ipnp + offsetof(nat_save_t, ipn_data), + (caddr_t)ipnn->ipn_data, ipn.ipn_dsize); if (error) { error = EFAULT; goto junkput; @@ -1065,7 +1071,7 @@ struct nat *natd; * If there's a fragment table entry too for this nat entry, then * dereference that as well. */ - ipfr_forget((void *)natd); + ipfr_forgetnat((void *)natd); aps_free(natd->nat_aps); nat_stats.ns_inuse--; KFREE(natd); @@ -1163,6 +1169,11 @@ int direction; qif_t *qf = fin->fin_qif; #endif + if (nat_stats.ns_inuse >= ipf_nattable_max) { + nat_stats.ns_memfail++; + return NULL; + } + nflags = flags & np->in_flags; if (flags & IPN_TCPUDP) { tcp = (tcphdr_t *)fin->fin_dp; @@ -1174,6 +1185,17 @@ int direction; KMALLOC(nat, nat_t *); if (nat == NULL) { nat_stats.ns_memfail++; + /* + * Try to automatically tune the max # of entries in the + * table allowed to be less than what will cause kmem_alloc() + * to fail and try to eliminate panics due to out of memory + * conditions arising. + */ + if (ipf_nattable_max > ipf_nattable_sz) { + ipf_nattable_max = nat_stats.ns_inuse - 100; + printf("ipf_nattable_max reduced to %d\n", + ipf_nattable_max); + } return NULL; } @@ -1430,7 +1452,7 @@ int direction; CALC_SUMD(sum1, sum2, sumd); nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) - if ((flags & IPN_TCPUDP) && dohwcksum && + if ((flags & IPN_TCP) && dohwcksum && (qf->qf_ill->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) { if (direction == NAT_OUTBOUND) sum1 = LONG_SUM(ntohl(in.s_addr)); @@ -1682,6 +1704,7 @@ int dir; return NULL; flags = 0; + sumd2 = 0; *nflags = IPN_ICMPERR; icmp = (icmphdr_t *)fin->fin_dp; oip = (ip_t *)&icmp->icmp_ip; @@ -1735,137 +1758,75 @@ int dir; CALC_SUMD(sum1, sum2, sumd); - if (nat->nat_dir == NAT_OUTBOUND) { - /* - * 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); + /* + * 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); + /* Fix icmp cksum : IP Addr + Cksum */ + /* + * Fix UDP pseudo header checksum to compensate for the + * IP address change. + */ + if ((oip->ip_p == IPPROTO_UDP) && (dlen >= 8) && udp->uh_sum) { /* - * Fix UDP pseudo header checksum to compensate for the - * IP address change. + * The UDP checksum is optional, only adjust it + * if it has been set. */ - 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); - sumd2 = sumd; - } + sum1 = ntohs(udp->uh_sum); + fix_datacksum(&udp->uh_sum, sumd); + sum2 = ntohs(udp->uh_sum); /* - * 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!). + * Fix ICMP checksum to compensate the UDP + * checksum adjustment. */ - if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { - - sum1 = ntohs(tcp->th_sum); - fix_datacksum(&tcp->th_sum, sumd); - sum2 = ntohs(tcp->th_sum); - - /* - * Fix ICMP checksum to compensate the TCP - * checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 = sumd; - } - } else { + sumd2 = sumd << 1; + CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; + } - /* - * 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); + /* + * 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!). + */ + else if ((oip->ip_p == IPPROTO_TCP) && (dlen >= 18)) { + sum1 = ntohs(tcp->th_sum); + fix_datacksum(&tcp->th_sum, sumd); + sum2 = ntohs(tcp->th_sum); -/* 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) /* - * Fix UDP pseudo header checksum to compensate for the - * IP address change. + * Fix ICMP checksum to compensate the TCP + * checksum adjustment. */ - 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); - sumd2 = sumd; - } - - /* - * 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 && dlen >= 18) { - - sum1 = ntohs(tcp->th_sum); - fix_datacksum(&tcp->th_sum, sumd); - sum2 = ntohs(tcp->th_sum); - - /* - * Fix ICMP checksum to compensate the TCP - * checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 = sumd; - } -#endif + sumd2 = sumd << 1; + CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; + } else { + sumd2 = (sumd >> 16); + if (nat->nat_dir == NAT_OUTBOUND) + sumd2 = ~sumd2; + else + sumd2 = ~sumd2 + 1; } - if ((flags & IPN_TCPUDP) != 0) { + if (((flags & IPN_TCPUDP) != 0) && (dlen >= 4)) { /* * Step 2 : * For offending TCP/UDP IP packets, translate the ports as @@ -1885,17 +1846,14 @@ int dir; * include the TCP checksum. So we have to check if the * ip->ip_len actually holds the TCP checksum of the oip! */ - if (nat->nat_oport == tcp->th_dport) { 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); - sumd2 += sumd; + sum1 = ntohs(nat->nat_inport); + sum2 = ntohs(tcp->th_sport); tcp->th_sport = nat->nat_inport; /* @@ -1907,16 +1865,18 @@ int dir; * The UDP checksum is optional, only adjust * it if it has been set. */ - if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) { + if ((oip->ip_p == IPPROTO_UDP) && + (dlen >= 8) && udp->uh_sum) { + sumd = sum1 - sum2; + sumd2 += sumd; sum1 = ntohs(udp->uh_sum); fix_datacksum(&udp->uh_sum, sumd); sum2 = ntohs(udp->uh_sum); /* - * Fix ICMP checksum to - * compensate UDP checksum - * adjustment. + * Fix ICMP checksum to compensate + * UDP checksum adjustment. */ CALC_SUMD(sum1, sum2, sumd); sumd2 += sumd; @@ -1928,63 +1888,73 @@ int dir; * packet flows the other direction compared to * the ICMP message. */ - if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { - - sum1 = ntohs(tcp->th_sum); - fix_datacksum(&tcp->th_sum, sumd); - sum2 = ntohs(tcp->th_sum); - - /* - * Fix ICMP checksum to - * compensate TCP checksum - * adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; + if (oip->ip_p == IPPROTO_TCP) { + if (dlen >= 18) { + sumd = sum1 - sum2; + sumd2 += sumd; + + sum1 = ntohs(tcp->th_sum); + fix_datacksum(&tcp->th_sum, + sumd); + sum2 = ntohs(tcp->th_sum); + + /* + * Fix ICMP checksum to + * compensate TCP checksum + * adjustment. + */ + CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; + } else { + sumd = sum2 - sum1 + 1; + sumd2 += 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); + } else if (tcp->th_dport != nat->nat_outport) { + /* + * Fix ICMP checksum to compensate port + * adjustment. + */ + sum1 = ntohs(nat->nat_outport); + sum2 = ntohs(tcp->th_dport); + tcp->th_dport = nat->nat_outport; + + /* + * 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) && + (dlen >= 8) && udp->uh_sum) { + sumd = sum1 - sum2; sumd2 += sumd; - tcp->th_dport = nat->nat_outport; + + sum1 = ntohs(udp->uh_sum); + fix_datacksum(&udp->uh_sum, sumd); + sum2 = ntohs(udp->uh_sum); /* - * 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. + * Fix ICMP checksum to compensate + * UDP checksum adjustment. */ - 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); + CALC_SUMD(sum1, sum2, sumd); + } - /* - * Fix ICMP checksum to compensate - * UDP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); + /* + * Fix tcp checksum (if present) to compensate + * port adjustment. NOTE : the offending IP + * packet flows the other direction compared to + * the ICMP message. + */ + if (oip->ip_p == IPPROTO_TCP) { + if (dlen >= 18) { + sumd = sum1 - sum2; sumd2 += sumd; - } - - /* - * Fix tcp checksum (if present) to compensate - * port adjustment. NOTE : the offending IP - * packet flows the other direction compared to - * the ICMP message. - */ - if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { sum1 = ntohs(tcp->th_sum); fix_datacksum(&tcp->th_sum, sumd); @@ -1995,18 +1965,18 @@ int dir; * UDP checksum adjustment. */ CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; + } else { + sumd = sum2 - sum1; + if (nat->nat_dir == NAT_OUTBOUND) + sumd++; } } + sumd2 += sumd; } if (sumd2) { sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); - if (nat->nat_dir == NAT_OUTBOUND) { - fix_outcksum(fin, &icmp->icmp_cksum, sumd2); - } else { - fix_incksum(fin, &icmp->icmp_cksum, sumd2); - } + fix_incksum(fin, &icmp->icmp_cksum, sumd2); } } if (oip->ip_p == IPPROTO_ICMP) @@ -2476,13 +2446,9 @@ maskloop: s1 = LONG_SUM(ntohl(fin->fin_saddr)); s2 = LONG_SUM(ntohl(nat->nat_outip.s_addr)); CALC_SUMD(s1, s2, sumd); - - if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(fin, &ip->ip_sum, sumd); - else - fix_incksum(fin, &ip->ip_sum, sumd); + fix_outcksum(fin, &ip->ip_sum, sumd); } -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) +#if (SOLARIS || defined(__sgi)) || !defined(_KERNEL) else { if (nat->nat_dir == NAT_OUTBOUND) fix_outcksum(fin, &ip->ip_sum, nat->nat_ipsumd); @@ -2510,7 +2476,8 @@ maskloop: if (nat->nat_age < fr_defnaticmpage) nat->nat_age = fr_defnaticmpage; #ifdef LARGE_NAT - else if (nat->nat_age > fr_defnatage) + else if ((!np || !np->in_age[1]) && + (nat->nat_age > fr_defnatage)) nat->nat_age = fr_defnatage; #endif /* @@ -2703,19 +2670,19 @@ maskloop: nat->nat_bytes += ip->ip_len; nat->nat_pkts++; MUTEX_EXIT(&nat->nat_lock); - ip->ip_dst = nat->nat_inip; - fin->fin_fi.fi_daddr = nat->nat_inip.s_addr; /* * Fix up checksums, not by recalculating them, but * simply computing adjustments. */ -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) if (nat->nat_dir == NAT_OUTBOUND) fix_incksum(fin, &ip->ip_sum, nat->nat_ipsumd); else fix_outcksum(fin, &ip->ip_sum, nat->nat_ipsumd); -#endif + + ip->ip_dst = nat->nat_inip; + fin->fin_fi.fi_daddr = nat->nat_inip.s_addr; + if ((fin->fin_off == 0) && !(fin->fin_fl & FI_SHORT)) { if ((nat->nat_inport != 0) && (tcp != NULL)) { @@ -2731,7 +2698,8 @@ maskloop: if (nat->nat_age < fr_defnaticmpage) nat->nat_age = fr_defnaticmpage; #ifdef LARGE_NAT - else if (nat->nat_age > fr_defnatage) + else if ((!np || !np->in_age[0]) && + (nat->nat_age > fr_defnatage)) nat->nat_age = fr_defnatage; #endif /* @@ -2983,7 +2951,7 @@ u_short *csump; if (&cp[1] >= ep) break; advance = cp[1]; - if (&cp[advance] >= ep) + if (&cp[advance] > ep) break; switch (opt) { case TCPOPT_MAXSEG: diff --git a/sys/contrib/ipfilter/netinet/ip_nat.h b/sys/contrib/ipfilter/netinet/ip_nat.h index e052449..14e9d25 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.h +++ b/sys/contrib/ipfilter/netinet/ip_nat.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_nat.h 1.5 2/4/96 - * $Id: ip_nat.h,v 2.17.2.28 2002/11/03 13:06:21 darrenr Exp $ + * $Id: ip_nat.h,v 2.17.2.32 2004/02/11 15:16:37 darrenr Exp $ */ #ifndef __IP_NAT_H__ @@ -34,26 +34,39 @@ * a setup with 1000-2000 networks to NAT. */ #ifndef NAT_SIZE -# define NAT_SIZE 127 +# ifdef LARGE_NAT +# define NAT_SIZE 2047 +# else +# define NAT_SIZE 127 +# endif #endif #ifndef RDR_SIZE -# define RDR_SIZE 127 +# ifdef LARGE_NAT +# define RDR_SIZE 2047 +# else +# define RDR_SIZE 127 +# endif #endif #ifndef HOSTMAP_SIZE -# define HOSTMAP_SIZE 127 +# ifdef LARGE_NAT +# define HOSTMAP_SIZE 8191 +# else +# define HOSTMAP_SIZE 2047 +# endif #endif -#ifndef NAT_TABLE_SZ -# define NAT_TABLE_SZ 127 +#ifndef NAT_TABLE_MAX +# ifdef LARGE_NAT +# define NAT_TABLE_MAX 180000 +# else +# define NAT_TABLE_MAX 30000 +# endif #endif -#ifdef LARGE_NAT -#undef NAT_SIZE -#undef RDR_SIZE -#undef NAT_TABLE_SZ -#undef HOSTMAP_SIZE 127 -#define NAT_SIZE 2047 -#define RDR_SIZE 2047 -#define NAT_TABLE_SZ 16383 -#define HOSTMAP_SIZE 8191 +#ifndef NAT_TABLE_SZ +# ifdef LARGE_NAT +# define NAT_TABLE_SZ 16383 +# else +# define NAT_TABLE_SZ 2047 +# endif #endif #ifndef APR_LABELLEN #define APR_LABELLEN 16 diff --git a/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c b/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c index ddd5ea3..12d3981 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.8 2002/01/13 04:58:29 darrenr Exp $ + * $Id: ip_raudio_pxy.c,v 1.7.2.9 2003/04/26 05:59:39 darrenr Exp $ */ #if SOLARIS && defined(_KERNEL) extern kmutex_t ipf_rw; @@ -66,9 +66,6 @@ nat_t *nat; tcphdr_t *tcp; int len = 0; mb_t *m; -#if SOLARIS - mb_t *m1; -#endif /* * If we've already processed the start messages, then nothing left @@ -181,9 +178,6 @@ nat_t *nat; nat_t *ipn; u_char swp; mb_t *m; -#if SOLARIS - mb_t *m1; -#endif /* * Wait until we've seen the end of the start messages and even then diff --git a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c index 3fecf49..93cd32b 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.6 2002/10/01 15:24:59 darrenr Exp $ + * $Id: ip_rcmd_pxy.c,v 1.4.2.7 2003/04/26 05:59:39 darrenr Exp $ */ /* * Simple RCMD transparent proxy for in-kernel use. For use with the NAT @@ -88,9 +88,6 @@ nat_t *nat; u_short sp; nat_t *ipn; mb_t *m; -#if SOLARIS - mb_t *m1; -#endif tcp = (tcphdr_t *)fin->fin_dp; diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index 5ab78cc..4934279 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -93,7 +93,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.77 2002/12/06 11:40:24 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.88 2004/01/05 12:46:05 darrenr Exp $"; #endif #ifndef MIN @@ -921,7 +921,8 @@ tcphdr_t *tcp; fdata->td_wscale = wscale; else if (wscale == -2) fdata->td_wscale = tdata->td_wscale = 0; - win <<= fdata->td_wscale; + if (!(tcp->th_flags & TH_SYN)) + win <<= fdata->td_wscale; if ((fdata->td_end == 0) && (!is->is_fsm || ((tcp->th_flags & TH_OPENING) == TH_OPENING))) { @@ -955,14 +956,15 @@ tcphdr_t *tcp; (SEQ_GE(seq, fdata->td_end - maxwin)) && /* XXX what about big packets */ #define MAXACKWINDOW 66000 - (ackskew >= -MAXACKWINDOW) && - (ackskew <= MAXACKWINDOW)) { - /* if ackskew < 0 then this should be due to fragented + (-ackskew <= (MAXACKWINDOW << tdata->td_wscale)) && + ( ackskew <= (MAXACKWINDOW << tdata->td_wscale))) { + + /* if ackskew < 0 then this should be due to fragmented * packets. There is no way to know the length of the * total packet in advance. * We do know the total length from the fragment cache though. * Note however that there might be more sessions with - * exactly the same source and destination paramters in the + * exactly the same source and destination parameters in the * state cache (and source and destination is the only stuff * that is saved in the fragment cache). Note further that * some TCP connections in the state cache are hashed with @@ -1208,6 +1210,10 @@ fr_info_t *fin; oip = (ip_t *)((char *)ic + ICMPERR_ICMPHLEN); ohlen = oip->ip_hl << 2; + /* + * Check if the at least the old IP header (with options) and + * 8 bytes of payload is present. + */ if (fin->fin_plen < ICMPERR_MAXPKTLEN + ohlen - sizeof(*oip)) return NULL; @@ -1224,7 +1230,7 @@ fr_info_t *fin; * may be too big to be in this buffer but not so big that it's * outside the ICMP packet, leading to TCP deref's causing problems. * This is possible because we don't know how big oip_hl is when we - * do the pullup early in fr_check() and thus can't gaurantee it is + * do the pullup early in fr_check() and thus can't guarantee it is * all here now. */ #ifdef _KERNEL @@ -1251,9 +1257,43 @@ fr_info_t *fin; bzero((char *)&src, sizeof(src)); bzero((char *)&dst, sizeof(dst)); bzero((char *)&ofin, sizeof(ofin)); + /* + * We make an fin entry to be able to feed it to + * matchsrcdst. Note that not all fields are encessary + * but this is the cleanest way. Note further that we + * fill in fin_mp such that if someone uses it we'll get + * a kernel panic. fr_matchsrcdst does not use this. + */ ofin.fin_ifp = fin->fin_ifp; ofin.fin_out = !fin->fin_out; + ofin.fin_mp = NULL; ofin.fin_v = 4; + /* + * watch out here, as ip is in host order and oip in network + * order. Any change we make must be undone afterwards, like + * oip->ip_off - it is still in network byte order so fix it. + */ + savelen = oip->ip_len; + oip->ip_len = len; + oip->ip_off = ntohs(oip->ip_off); + (void) fr_makefrip(ohlen, oip, &ofin); + /* + * Reset the short flag here because in fr_matchsrcdst() the flags + * for the current packet (fin_fl) are compared against * those for + * the existing session. + */ + ofin.fin_fl &= ~FI_SHORT; + + /* + * Put old values of ip_len and ip_off back as we don't know + * if we have to forward the packet (or process it again. + */ + oip->ip_len = savelen; + oip->ip_off = htons(oip->ip_off); + +#if SOLARIS + ofin.fin_qfm = NULL; +#endif fr = NULL; switch (oip->ip_p) @@ -1262,7 +1302,7 @@ fr_info_t *fin; icmp = (icmphdr_t *)((char *)oip + ohlen); /* - * a ICMP error can only be generated as a result of an + * an ICMP error can only be generated as a result of an * ICMP query, not as the response on an ICMP error * * XXX theoretically ICMP_ECHOREP and the other reply's are @@ -1286,18 +1326,15 @@ fr_info_t *fin; hv += icmp->icmp_seq; hv %= fr_statesize; - savelen = oip->ip_len; - oip->ip_len = len; - fr_makefrip(ohlen, oip, &ofin); - oip->ip_len = savelen; - READ_ENTER(&ipf_state); for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) if ((is->is_p == pr) && (is->is_v == 4) && + (is->is_icmppkts < is->is_pkts) && fr_matchsrcdst(is, src, dst, &ofin, NULL) && - fr_matchicmpqueryreply(is->is_v, is, icmp, fin->fin_rev)) { + fr_matchicmpqueryreply(is->is_v, is, icmp, + fin->fin_rev)) { ips_stats.iss_hits++; - is->is_pkts++; + is->is_icmppkts++; is->is_bytes += ip->ip_len; fr = is->is_rule; break; @@ -1326,20 +1363,7 @@ fr_info_t *fin; hv += dport; hv += sport; hv %= fr_statesize; - /* - * we make an fin entry to be able to feed it to - * matchsrcdst note that not all fields are encessary - * but this is the cleanest way. Note further we fill - * in fin_mp such that if someone uses it we'll get - * a kernel panic. fr_matchsrcdst does not use this. - * - * watch out here, as ip is in host order and oip in network - * order. Any change we make must be undone afterwards. - */ - savelen = oip->ip_len; - oip->ip_len = len; - fr_makefrip(ohlen, oip, &ofin); - oip->ip_len = savelen; + READ_ENTER(&ipf_state); for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) { /* @@ -1347,13 +1371,16 @@ fr_info_t *fin; * encapsulated packet was allowed through the * other way around. Note that the minimal amount * of info present does not allow for checking against - * tcp internals such as seq and ack numbers. + * tcp internals such as seq and ack numbers. Only the + * ports are known to be present and can be even if the + * short flag is set. */ if ((is->is_p == pr) && (is->is_v == 4) && + (is->is_icmppkts < is->is_pkts) && fr_matchsrcdst(is, src, dst, &ofin, tcp)) { fr = is->is_rule; ips_stats.iss_hits++; - is->is_pkts++; + is->is_icmppkts++; is->is_bytes += fin->fin_plen; /* * we deliberately do not touch the timeouts @@ -1675,8 +1702,8 @@ void *ifp; for (is = ips_list; is; is = is->is_next) { for (i = 0; i < 4; i++) { if (is->is_ifp[i] == ifp) { - is->is_ifpin = GETUNIT(is->is_ifname[i], - is->is_v); + is->is_ifp[i] = GETUNIT(is->is_ifname[i], + is->is_v); if (!is->is_ifp[i]) is->is_ifp[i] = (void *)-1; } @@ -1843,17 +1870,41 @@ int dir, fsm; state[dir] = TCPS_SYN_SENT; newage = fr_tcptimeout; } + + /* + * It is apparently possible that a hosts sends two syncs + * before the remote party is able to respond with a SA. In + * such a case the remote server sometimes ACK's the second + * sync, and then responds with a SA. The following code + * is used to prevent this ack from being blocked. + * + * We do not reset the timeout here to fr_tcptimeout because + * a connection connect timeout does not renew after every + * packet that is sent. We need to set newage to something + * to indicate the packet has passed the check for its flags + * being valid in the TCP FSM. + */ + else if ((ostate == TCPS_SYN_SENT) && + ((flags & (TH_FIN|TH_SYN|TH_RST|TH_ACK)) == TH_ACK)) { + newage = *age; + } + /* * The next piece of code makes it possible to get * already established connections into the state table * after a restart or reload of the filter rules; this * does not work when a strict 'flags S keep state' is - * used for tcp connections of course + * used for tcp connections of course, however, use a + * lower time-out so the state disappears quickly if + * the other side does not pick it up. */ - if (!fsm && (flags & (TH_FIN|TH_SYN|TH_RST|TH_ACK)) == TH_ACK) { + else if (!fsm && + (flags & (TH_FIN|TH_SYN|TH_RST|TH_ACK)) == TH_ACK) { /* we saw an A, guess 'dir' is in ESTABLISHED mode */ - if (state[1 - dir] == TCPS_CLOSED || - state[1 - dir] == TCPS_ESTABLISHED) { + if (ostate == TCPS_CLOSED) { + state[dir] = TCPS_ESTABLISHED; + newage = fr_tcptimeout; + } else if (ostate == TCPS_ESTABLISHED) { state[dir] = TCPS_ESTABLISHED; newage = fr_tcpidletimeout; } @@ -2056,7 +2107,7 @@ u_int type; int types[1]; ipsl.isl_type = type; - ipsl.isl_pkts = is->is_pkts; + ipsl.isl_pkts = is->is_pkts + is->is_icmppkts; ipsl.isl_bytes = is->is_bytes; ipsl.isl_src = is->is_src; ipsl.isl_dst = is->is_dst; @@ -2084,7 +2135,11 @@ u_int type; sizes[0] = sizeof(ipsl); types[0] = 0; - (void) ipllog(IPL_LOGSTATE, NULL, items, sizes, types, 1); + if (ipllog(IPL_LOGSTATE, NULL, items, sizes, types, 1)) { + ATOMIC_INCL(ips_stats.iss_logged); + } else { + ATOMIC_INCL(ips_stats.iss_logfail); + } } #endif @@ -2134,12 +2189,30 @@ fr_info_t *fin; bzero((char *)&ofin, sizeof(ofin)); ofin.fin_out = !fin->fin_out; ofin.fin_ifp = fin->fin_ifp; + ofin.fin_mp = NULL; ofin.fin_v = 6; +#if SOLARIS + ofin.fin_qfm = NULL; +#endif + /* + * We make a fin entry to be able to feed it to + * matchsrcdst. Note that not all fields are necessary + * but this is the cleanest way. Note further we fill + * in fin_mp such that if someone uses it we'll get + * a kernel panic. fr_matchsrcdst does not use this. + * + * watch out here, as ip is in host order and oip in network + * order. Any change we make must be undone afterwards. + */ + savelen = oip->ip6_plen; + oip->ip6_plen = ip->ip6_plen - sizeof(*ip) - ICMPERR_ICMPHLEN; + fr_makefrip(sizeof(*oip), (ip_t *)oip, &ofin); + oip->ip6_plen = savelen; if (oip->ip6_nxt == IPPROTO_ICMPV6) { oic = (struct icmp6_hdr *)(oip + 1); /* - * a ICMP error can only be generated as a result of an + * an ICMP error can only be generated as a result of an * ICMP query, not as the response on an ICMP error * * XXX theoretically ICMP_ECHOREP and the other reply's are @@ -2160,10 +2233,6 @@ fr_info_t *fin; hv += oic->icmp6_seq; hv %= fr_statesize; - oip->ip6_plen = ntohs(oip->ip6_plen); - fr_makefrip(sizeof(*oip), (ip_t *)oip, &ofin); - oip->ip6_plen = htons(oip->ip6_plen); - READ_ENTER(&ipf_state); for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) if ((is->is_p == pr) && @@ -2207,20 +2276,7 @@ fr_info_t *fin; hv += dport; hv += sport; hv %= fr_statesize; - /* - * we make an fin entry to be able to feed it to - * matchsrcdst note that not all fields are encessary - * but this is the cleanest way. Note further we fill - * in fin_mp such that if someone uses it we'll get - * a kernel panic. fr_matchsrcdst does not use this. - * - * watch out here, as ip is in host order and oip in network - * order. Any change we make must be undone afterwards. - */ - savelen = oip->ip6_plen; - oip->ip6_plen = ip->ip6_plen - sizeof(*ip) - ICMPERR_ICMPHLEN; - fr_makefrip(sizeof(*oip), (ip_t *)oip, &ofin); - oip->ip6_plen = savelen; + READ_ENTER(&ipf_state); for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) { /* diff --git a/sys/contrib/ipfilter/netinet/ip_state.h b/sys/contrib/ipfilter/netinet/ip_state.h index 35368c4..d155302 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.h +++ b/sys/contrib/ipfilter/netinet/ip_state.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed - * $Id: ip_state.h,v 2.13.2.13 2002/06/27 14:40:29 darrenr Exp $ + * $Id: ip_state.h,v 2.13.2.14 2003/11/15 11:47:46 darrenr Exp $ */ #ifndef __IP_STATE_H__ #define __IP_STATE_H__ @@ -62,6 +62,7 @@ typedef struct ipstate { frentry_t *is_rule; U_QUAD_T is_pkts; U_QUAD_T is_bytes; + U_QUAD_T is_icmppkts; union i6addr is_src; union i6addr is_dst; void *is_ifp[4]; diff --git a/sys/contrib/ipfilter/netinet/ipl.h b/sys/contrib/ipfilter/netinet/ipl.h index 2a23a44..b975ee9 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -4,12 +4,12 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ipl.h 1.21 6/5/96 - * $Id: ipl.h,v 2.15.2.38 2002/12/07 02:40:05 darrenr Exp $ + * $Id: ipl.h,v 2.15.2.44 2004/06/03 17:28:20 darrenr Exp $ */ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v3.4.31" +#define IPL_VERSION "IP Filter: v3.4.35" #endif -- cgit v1.1