diff options
author | darrenr <darrenr@FreeBSD.org> | 2007-10-18 21:52:14 +0000 |
---|---|---|
committer | darrenr <darrenr@FreeBSD.org> | 2007-10-18 21:52:14 +0000 |
commit | fd172ed3272b523c5499832d7098b6766bac7e4f (patch) | |
tree | 7eb0ed562f560c2289c5b113e742797727d126db /sys/contrib | |
parent | 6f755e940898e80d77f95031600e671c36e0a7a6 (diff) | |
download | FreeBSD-src-fd172ed3272b523c5499832d7098b6766bac7e4f.zip FreeBSD-src-fd172ed3272b523c5499832d7098b6766bac7e4f.tar.gz |
Pullup IPFilter 4.1.28 from the vendor branch into HEAD.
MFC after: 7 days
Diffstat (limited to 'sys/contrib')
-rw-r--r-- | sys/contrib/ipfilter/netinet/fil.c | 285 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_auth.c | 34 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_compat.h | 182 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_fil.h | 51 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_fil_freebsd.c | 283 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_frag.c | 14 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_htable.c | 90 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_log.c | 34 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_nat.c | 254 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_nat.h | 6 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_proxy.c | 10 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_state.c | 172 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_state.h | 8 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_sync.c | 10 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ipl.h | 6 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/mlfk_ipl.c | 9 |
16 files changed, 863 insertions, 585 deletions
diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index 014fb0f..5a083a4 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -82,7 +82,7 @@ struct file; #ifdef sun # include <net/af.h> #endif -#if !defined(_KERNEL) && defined(__FreeBSD__) +#if !defined(_KERNEL) && (defined(__FreeBSD__) || defined(SOLARIS2)) # if (__FreeBSD_version >= 504000) # undef _RADIX_H_ # endif @@ -156,7 +156,7 @@ struct file; #if !defined(lint) static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; static const char rcsid[] = "@(#)$FreeBSD$"; -/* static const char rcsid[] = "@(#)$Id: fil.c,v 2.243.2.78 2006/03/29 11:19:54 darrenr Exp $"; */ +/* static const char rcsid[] = "@(#)$Id: fil.c,v 2.243.2.125 2007/10/10 09:27:20 darrenr Exp $"; */ #endif #ifndef _KERNEL @@ -362,7 +362,7 @@ static INLINE int frpr_hopopts6 __P((fr_info_t *)); static INLINE int frpr_mobility6 __P((fr_info_t *)); static INLINE int frpr_routing6 __P((fr_info_t *)); static INLINE int frpr_dstopts6 __P((fr_info_t *)); -static INLINE void frpr_fragment6 __P((fr_info_t *)); +static INLINE int frpr_fragment6 __P((fr_info_t *)); static INLINE int frpr_ipv6exthdr __P((fr_info_t *, int, int)); @@ -480,8 +480,9 @@ fr_info_t *fin; break; case IPPROTO_FRAGMENT : - frpr_fragment6(fin); - go = 0; + p = frpr_fragment6(fin); + if (fin->fin_off != 0) + go = 0; break; default : @@ -652,7 +653,7 @@ fr_info_t *fin; /* ------------------------------------------------------------------------ */ /* Function: frpr_fragment6 */ -/* Returns: void */ +/* Returns: int - value of the next header or IPPROTO_NONE if error */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* IPv6 Only */ @@ -664,7 +665,7 @@ fr_info_t *fin; /* upper layer header has been seen (or where it ends) and thus we are not */ /* able to continue processing beyond this header with any confidence. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_fragment6(fin) +static INLINE int frpr_fragment6(fin) fr_info_t *fin; { struct ip6_frag *frag; @@ -673,12 +674,12 @@ fr_info_t *fin; fin->fin_flx |= FI_FRAG; if (frpr_ipv6exthdr(fin, 0, IPPROTO_FRAGMENT) == IPPROTO_NONE) - return; + return IPPROTO_NONE; extoff = (char *)fin->fin_exthdr - (char *)fin->fin_dp; if (frpr_pullup(fin, sizeof(*frag)) == -1) - return; + return IPPROTO_NONE; fin->fin_exthdr = (char *)fin->fin_dp + extoff; frag = fin->fin_exthdr; @@ -687,16 +688,18 @@ fr_info_t *fin; */ if (frag->ip6f_offlg == 0) { fin->fin_flx |= FI_BAD; - return; + return IPPROTO_NONE; } - fin->fin_off = frag->ip6f_offlg & IP6F_OFF_MASK; + fin->fin_off = ntohs(frag->ip6f_offlg & IP6F_OFF_MASK); fin->fin_off <<= 3; if (fin->fin_off != 0) fin->fin_flx |= FI_FRAGBODY; fin->fin_dp = (char *)fin->fin_dp + sizeof(*frag); fin->fin_dlen -= sizeof(*frag); + + return frag->ip6f_nxt; } @@ -752,15 +755,15 @@ fr_info_t *fin; case ICMP6_TIME_EXCEEDED : case ICMP6_PARAM_PROB : fin->fin_flx |= FI_ICMPERR; - if ((fin->fin_m != NULL) && - (M_LEN(fin->fin_m) < fin->fin_plen)) { + minicmpsz = ICMP6ERR_IPICMPHLEN - sizeof(ip6_t); + if (fin->fin_plen < ICMP6ERR_IPICMPHLEN) + break; + + if (M_LEN(fin->fin_m) < fin->fin_plen) { if (fr_coalesce(fin) != 1) return; } - if (frpr_pullup(fin, ICMP6ERR_MINPKTLEN) == -1) - return; - /* * If the destination of this packet doesn't match the * source of the original packet then this packet is @@ -772,7 +775,6 @@ fr_info_t *fin; (i6addr_t *)&ip6->ip6_src)) fin->fin_flx |= FI_BAD; - minicmpsz = ICMP6ERR_IPICMPHLEN - sizeof(ip6_t); break; default : break; @@ -913,6 +915,14 @@ fr_info_t *fin; /* Short inline function to cut down on code duplication to perform a call */ /* to fr_pullup to ensure there is the required amount of data, */ /* consecutively in the packet buffer. */ +/* */ +/* This function pulls up 'extra' data at the location of fin_dp. fin_dp */ +/* points to the first byte after the complete layer 3 header, which will */ +/* include all of the known extension headers for IPv6 or options for IPv4. */ +/* */ +/* Since fr_pullup() expects the total length of bytes to be pulled up, it */ +/* is necessary to add those we can already assume to be pulled up (fin_dp */ +/* - fin_ip) to what is passed through. */ /* ------------------------------------------------------------------------ */ static INLINE int frpr_pullup(fin, plen) fr_info_t *fin; @@ -1001,6 +1011,9 @@ fr_info_t *fin; fin->fin_data[0] = *(u_short *)icmp; + if (fin->fin_dlen >= 6) /* ID field */ + fin->fin_data[1] = icmp->icmp_id; + switch (icmp->icmp_type) { case ICMP_ECHOREPLY : @@ -1071,14 +1084,12 @@ fr_info_t *fin; default : break; } - - if (fin->fin_dlen >= 6) /* ID field */ - fin->fin_data[1] = icmp->icmp_id; } frpr_short(fin, minicmpsz); - fr_checkv4sum(fin); + if ((fin->fin_flx & FI_FRAG) == 0) + fr_checkv4sum(fin); } @@ -1194,6 +1205,7 @@ fr_info_t *fin; return -1; #if 0 + tcp = fin->fin_dp; ip = fin->fin_ip; s = (u_char *)(tcp + 1); off = IP_HL(ip) << 2; @@ -1281,8 +1293,10 @@ fr_info_t *fin; frpr_short(fin, sizeof(tcphdr_t)); - if (frpr_tcpcommon(fin) == 0) - fr_checkv4sum(fin); + if (frpr_tcpcommon(fin) == 0) { + if ((fin->fin_flx & FI_FRAG) == 0) + fr_checkv4sum(fin); + } } @@ -1300,8 +1314,10 @@ fr_info_t *fin; frpr_short(fin, sizeof(udphdr_t)); - if (frpr_udpcommon(fin) == 0) - fr_checkv4sum(fin); + if (frpr_udpcommon(fin) == 0) { + if ((fin->fin_flx & FI_FRAG) == 0) + fr_checkv4sum(fin); + } } @@ -1951,7 +1967,7 @@ int fr_scanlist(fin, pass) fr_info_t *fin; u_32_t pass; { - int rulen, portcmp, off, logged, skip; + int rulen, portcmp, off, skip; struct frentry *fr, *fnext; u_32_t passt, passo; @@ -1970,7 +1986,6 @@ u_32_t pass; return pass; skip = 0; - logged = 0; portcmp = 0; fin->fin_depth++; fin->fin_fr = NULL; @@ -2104,7 +2119,7 @@ u_32_t pass; ATOMIC_INCL(frstats[fin->fin_out].fr_skip); } ATOMIC_INCL(frstats[fin->fin_out].fr_pkl); - logged = 1; + fin->fin_flx |= FI_DONTCACHE; } #endif /* IPFILTER_LOG */ fr->fr_bytes += (U_QUAD_T)fin->fin_plen; @@ -2129,8 +2144,6 @@ u_32_t pass; fin->fin_fr = fr; passt = pass; } - if (fin->fin_flx & FI_DONTCACHE) - logged = 1; pass = passt; } @@ -2158,8 +2171,6 @@ u_32_t pass; break; } } - if (logged) - fin->fin_flx |= FI_DONTCACHE; fin->fin_depth--; return pass; } @@ -2410,8 +2421,10 @@ int out; # ifdef MENTAT qpktinfo_t *qpi = qif; +# if !defined(_INET_IP_STACK_H) if ((u_int)ip & 0x3) return 2; +# endif # else SPL_INT(s); # endif @@ -2564,11 +2577,20 @@ int out; if (!out) (void) fr_acctpkt(fin, NULL); - if (fr == NULL) - if ((fin->fin_flx & (FI_FRAG|FI_BAD)) == FI_FRAG) + if (fr == NULL) { + if ((fin->fin_flx & (FI_FRAG|FI_BAD)) == FI_FRAG) { fr = fr_knownfrag(fin, &pass); - if (fr == NULL) - fr = fr_checkstate(fin, &pass); + /* + * Reset the keep state flag here so that we don't + * try and add a new state entry because of it, leading + * to a blocked packet because the add will fail. + */ + if (fr != NULL) + pass &= ~FR_KEEPSTATE; + } + if (fr == NULL) + fr = fr_checkstate(fin, &pass); + } if ((pass & FR_NOMATCH) || (fr == NULL)) fr = fr_firewall(fin, &pass); @@ -2631,7 +2653,14 @@ filterdone: } if (fin->fin_nat != NULL) { - fr_natderef((nat_t **)&fin->fin_nat); + if (FR_ISBLOCK(pass) && (fin->fin_flx & FI_NEWNAT)) { + WRITE_ENTER(&ipf_nat); + nat_delete((nat_t *)fin->fin_nat, NL_DESTROY); + RWLOCK_EXIT(&ipf_nat); + fin->fin_nat = NULL; + } else { + fr_natderef((nat_t **)&fin->fin_nat); + } } /* @@ -3071,8 +3100,8 @@ void *l4hdr; * In case we had to copy the IP & TCP header out of mbufs, * skip over the mbuf bits which are the header */ - if ((caddr_t)ip != mtod(m, caddr_t)) { - hlen = (caddr_t)sp - (caddr_t)ip; + if ((char *)ip != mtod(m, char *)) { + hlen = (char *)sp - (char *)ip; while (hlen) { add = MIN(hlen, m->m_len); sp = (u_short *)(mtod(m, caddr_t) + add); @@ -3095,12 +3124,12 @@ void *l4hdr; goto nodata; while (len > 1) { - if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) { + if (((char *)sp - mtod(m, char *)) >= m->m_len) { m = m->m_next; PANIC((!m),("fr_cksum(2): not enough data")); sp = mtod(m, u_short *); } - if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) { + if (((char *)(sp + 1) - mtod(m, char *)) > m->m_len) { bytes.c[0] = *(u_char *)sp; m = m->m_next; PANIC((!m),("fr_cksum(3): not enough data")); @@ -3178,7 +3207,7 @@ nodata: * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.243.2.109 2007/05/31 12:27:33 darrenr Exp $ + * $Id: fil.c,v 2.243.2.125 2007/10/10 09:27:20 darrenr Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, @@ -3484,7 +3513,7 @@ minor_t unit; int *nfreedp; frentry_t **listp; { - int freed = 0, i; + int freed = 0; frentry_t *fp; while ((fp = *listp) != NULL) { @@ -3495,8 +3524,7 @@ frentry_t **listp; } *listp = fp->fr_next; if (fp->fr_grp != NULL) { - i = frflushlist(set, unit, nfreedp, fp->fr_grp); - fp->fr_ref -= i; + (void) frflushlist(set, unit, nfreedp, fp->fr_grp); } if (fp->fr_grhead != NULL) { @@ -3852,7 +3880,7 @@ size_t size; int error; # if SOLARIS - error = COPYIN(src, (caddr_t)&ca, sizeof(ca)); + error = COPYIN(src, &ca, sizeof(ca)); if (error != 0) return error; # else @@ -3894,22 +3922,27 @@ size_t size; /* ------------------------------------------------------------------------ */ /* Function: fr_lock */ -/* Returns: (void) */ +/* Returns: int - 0 = success, else error */ /* Parameters: data(I) - pointer to lock value to set */ /* lockp(O) - pointer to location to store old lock value */ /* */ /* Get the new value for the lock integer, set it and return the old value */ /* in *lockp. */ /* ------------------------------------------------------------------------ */ -void fr_lock(data, lockp) +int fr_lock(data, lockp) caddr_t data; int *lockp; { - int arg; + int arg, err; - BCOPYIN(data, (caddr_t)&arg, sizeof(arg)); - BCOPYOUT((caddr_t)lockp, data, sizeof(*lockp)); + err = BCOPYIN(data, &arg, sizeof(arg)); + if (err != 0) + return EFAULT; + err = BCOPYOUT(lockp, data, sizeof(*lockp)); + if (err != 0) + return EFAULT; *lockp = arg; + return 0; } @@ -4548,7 +4581,7 @@ caddr_t data; /* * Return EBUSY if the rule is being reference by - * something else (eg state information. + * something else (eg state information.) */ if (f->fr_ref > 1) { error = EBUSY; @@ -4559,8 +4592,6 @@ caddr_t data; (f->fr_isc != (struct ipscan *)-1)) ipsc_detachfr(f); #endif - if ((fg != NULL) && (fg->fg_head != NULL)) - fg->fg_head->fr_ref--; if (unit == IPL_LOGAUTH) { error = fr_preauthcmd(req, f, ftail); goto done; @@ -4588,8 +4619,6 @@ caddr_t data; } else f = fp; if (f != NULL) { - if (fg != NULL && fg->fg_head != NULL) - fg->fg_head->fr_ref++; if (fp != f) bcopy((char *)fp, (char *)f, sizeof(*f)); @@ -4689,8 +4718,11 @@ int fr_resolvefunc(data) void *data; { ipfunc_resolve_t res, *ft; + int err; - BCOPYIN(data, &res, sizeof(res)); + err = BCOPYIN(data, &res, sizeof(res)); + if (err != 0) + return EFAULT; if (res.ipfu_addr == NULL && res.ipfu_name[0] != '\0') { for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++) @@ -5459,7 +5491,9 @@ int type; if ((type < 0) || (type >= IPFOBJ_COUNT)) return EINVAL; - BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + error = BCOPYIN(data, &obj, sizeof(obj)); + if (error != 0) + return EFAULT; if (obj.ipfo_type != type) return EINVAL; @@ -5485,11 +5519,9 @@ int type; #endif if ((fr_objbytes[type][0] & 1) != 0) { - error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, - fr_objbytes[type][1]); + error = COPYIN(obj.ipfo_ptr, ptr, fr_objbytes[type][1]); } else { - error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, - obj.ipfo_size); + error = COPYIN(obj.ipfo_ptr, ptr, obj.ipfo_size); } if (error != 0) error = EFAULT; @@ -5524,7 +5556,9 @@ int type, sz; if (((fr_objbytes[type][0] & 1) == 0) || (sz < fr_objbytes[type][1])) return EINVAL; - BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + error = BCOPYIN(data, &obj, sizeof(obj)); + if (error != 0) + return EFAULT; if (obj.ipfo_type != type) return EINVAL; @@ -5541,7 +5575,7 @@ int type, sz; return EINVAL; #endif - error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, sz); + error = COPYIN(obj.ipfo_ptr, ptr, sz); if (error != 0) error = EFAULT; return error; @@ -5570,12 +5604,14 @@ int type, sz; ipfobj_t obj; int error; - if ((type < 0) || (type > IPFOBJ_COUNT) || + if ((type < 0) || (type >= IPFOBJ_COUNT) || ((fr_objbytes[type][0] & 1) == 0) || (sz < fr_objbytes[type][1])) return EINVAL; - BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + error = BCOPYIN(data, &obj, sizeof(obj)); + if (error != 0) + return EFAULT; if (obj.ipfo_type != type) return EINVAL; @@ -5592,7 +5628,7 @@ int type, sz; return EINVAL; #endif - error = COPYOUT((caddr_t)ptr, (caddr_t)obj.ipfo_ptr, sz); + error = COPYOUT(ptr, obj.ipfo_ptr, sz); if (error != 0) error = EFAULT; return error; @@ -5618,10 +5654,12 @@ int type; ipfobj_t obj; int error; - if ((type < 0) || (type > IPFOBJ_COUNT)) + if ((type < 0) || (type >= IPFOBJ_COUNT)) return EINVAL; - BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + error = BCOPYIN(data, &obj, sizeof(obj)); + if (error != 0) + return EFAULT; if (obj.ipfo_type != type) return EINVAL; @@ -5645,7 +5683,7 @@ int type; return EINVAL; #endif - error = COPYOUT((caddr_t)ptr, (caddr_t)obj.ipfo_ptr, obj.ipfo_size); + error = COPYOUT(ptr, obj.ipfo_ptr, obj.ipfo_size); if (error != 0) error = EFAULT; return error; @@ -5671,6 +5709,12 @@ fr_info_t *fin; if ((fin->fin_flx & FI_NOCKSUM) != 0) return 0; + if (fin->fin_cksum == 1) + return 0; + + if (fin->fin_cksum == -1) + return -1; + /* * If the TCP packet isn't a fragment, isn't too short and otherwise * isn't already considered "bad", then validate the checksum. If @@ -5733,8 +5777,11 @@ fr_info_t *fin; FR_DEBUG(("checkl4sum: %hx != %hx\n", sum, hdrsum)); } #endif - if (hdrsum == sum) + if (hdrsum == sum) { + fin->fin_cksum = 1; return 0; + } + fin->fin_cksum = -1; return -1; } @@ -5987,7 +6034,7 @@ ipftuneable_t ipf_tuneables[] = { { { &ipf_hostmap_sz }, "ipf_hostmap_sz", 1, 0x7fffffff, sizeof(ipf_hostmap_sz), IPFT_WRDISABLED, NULL }, { { &fr_nat_maxbucket }, "fr_nat_maxbucket", 1, 0x7fffffff, - sizeof(fr_nat_maxbucket), IPFT_WRDISABLED, NULL }, + sizeof(fr_nat_maxbucket), 0, NULL }, { { &fr_nat_maxbucket_reset }, "fr_nat_maxbucket_reset", 0, 1, sizeof(fr_nat_maxbucket_reset), IPFT_WRDISABLED, NULL }, { { &nat_logging }, "nat_logging", 0, 1, @@ -6430,7 +6477,7 @@ void fr_deinitialise() /* the copyout may result in paging (ie network activity.) */ /* ------------------------------------------------------------------------ */ int fr_zerostats(data) -caddr_t data; +void *data; { friostat_t fio; int error; @@ -6536,15 +6583,12 @@ ipftoken_t *ipftokenhead = NULL, **ipftokentail = &ipftokenhead; void ipf_expiretokens() { ipftoken_t *it; - void *data; WRITE_ENTER(&ipf_tokens); while ((it = ipftokenhead) != NULL) { if (it->ipt_die > fr_ticks) break; - data = it->ipt_data; - ipf_freetoken(it); } RWLOCK_EXIT(&ipf_tokens); @@ -6721,7 +6765,9 @@ ipftoken_t *token; #endif break; case IPFGENITER_HOSTMAP : + WRITE_ENTER(&ipf_nat); fr_hostmapdel((hostmap_t **)datap); + RWLOCK_EXIT(&ipf_nat); break; default : #ifdef IPFILTER_LOOKUP @@ -6800,30 +6846,27 @@ int ipf_getnextrule(ipftoken_t *t, void *ptr) } dst = (char *)it.iri_rule; + count = it.iri_nrules; /* * The ipfruleiter may ask for more than 1 rule at a time to be * copied out, so long as that many exist in the list to start with! */ - for (count = it.iri_nrules; count > 0; count--) { + for (;;) { if (next != NULL) { - MUTEX_ENTER(&next->fr_lock); - next->fr_ref++; - MUTEX_EXIT(&next->fr_lock); - t->ipt_data = next; + if (count == 1) { + MUTEX_ENTER(&next->fr_lock); + next->fr_ref++; + MUTEX_EXIT(&next->fr_lock); + t->ipt_data = next; + } } else { bzero(&zero, sizeof(zero)); next = &zero; - ipf_freetoken(t); - fr = NULL; - t = NULL; count = 1; + t->ipt_data = NULL; } RWLOCK_EXIT(&ipf_mutex); - if (fr != NULL) { - (void) fr_derefrule(&fr); - } - error = COPYOUT(next, dst, sizeof(*next)); if (error != 0) return EFAULT; @@ -6837,12 +6880,17 @@ int ipf_getnextrule(ipftoken_t *t, void *ptr) dst += next->fr_dsize; } - if ((count == 1) || (next->fr_next == NULL) || (error != 0)) + if ((count == 1) || (error != 0)) break; + count--; + READ_ENTER(&ipf_mutex); - fr = next; - next = fr->fr_next; + next = next->fr_next; + } + + if (fr != NULL) { + (void) fr_derefrule(&fr); } return error; @@ -6970,8 +7018,7 @@ void *ctx; if (!(mode & FWRITE)) error = EPERM; else { - error = BCOPYIN((caddr_t)data, (caddr_t)&tmp, - sizeof(tmp)); + error = BCOPYIN(data, &tmp, sizeof(tmp)); if (error != 0) { error = EFAULT; break; @@ -7011,16 +7058,14 @@ void *ctx; if (!(mode & FWRITE)) error = EPERM; else { - error = BCOPYIN((caddr_t)data, (caddr_t)&fr_flags, - sizeof(fr_flags)); + error = BCOPYIN(data, &fr_flags, sizeof(fr_flags)); if (error != 0) error = EFAULT; } break; case SIOCGETFF : - error = BCOPYOUT((caddr_t)&fr_flags, (caddr_t)data, - sizeof(fr_flags)); + error = BCOPYOUT(&fr_flags, data, sizeof(fr_flags)); if (error != 0) error = EFAULT; break; @@ -7036,8 +7081,7 @@ void *ctx; if (!(mode & FWRITE)) error = EPERM; else - error = frrequest(IPL_LOGIPF, cmd, (caddr_t)data, - fr_active, 1); + error = frrequest(IPL_LOGIPF, cmd, data, fr_active, 1); break; case SIOCINIFR : @@ -7046,7 +7090,7 @@ void *ctx; if (!(mode & FWRITE)) error = EPERM; else - error = frrequest(IPL_LOGIPF, cmd, (caddr_t)data, + error = frrequest(IPL_LOGIPF, cmd, data, 1 - fr_active, 1); break; @@ -7056,8 +7100,7 @@ void *ctx; else { WRITE_ENTER(&ipf_mutex); bzero((char *)frcache, sizeof(frcache[0]) * 2); - error = BCOPYOUT((caddr_t)&fr_active, (caddr_t)data, - sizeof(fr_active)); + error = BCOPYOUT(&fr_active, data, sizeof(fr_active)); if (error != 0) error = EFAULT; else @@ -7075,19 +7118,17 @@ void *ctx; if (!(mode & FWRITE)) error = EPERM; else - error = fr_zerostats((caddr_t)data); + error = fr_zerostats(data); break; case SIOCIPFFL : if (!(mode & FWRITE)) error = EPERM; else { - error = BCOPYIN((caddr_t)data, (caddr_t)&tmp, - sizeof(tmp)); + error = BCOPYIN(data, &tmp, sizeof(tmp)); if (!error) { tmp = frflush(IPL_LOGIPF, 4, tmp); - error = BCOPYOUT((caddr_t)&tmp, (caddr_t)data, - sizeof(tmp)); + error = BCOPYOUT(&tmp, data, sizeof(tmp)); if (error != 0) error = EFAULT; } else @@ -7100,12 +7141,10 @@ void *ctx; if (!(mode & FWRITE)) error = EPERM; else { - error = BCOPYIN((caddr_t)data, (caddr_t)&tmp, - sizeof(tmp)); + error = BCOPYIN(data, &tmp, sizeof(tmp)); if (!error) { tmp = frflush(IPL_LOGIPF, 6, tmp); - error = BCOPYOUT((caddr_t)&tmp, (caddr_t)data, - sizeof(tmp)); + error = BCOPYOUT(&tmp, data, sizeof(tmp)); if (error != 0) error = EFAULT; } else @@ -7115,7 +7154,7 @@ void *ctx; #endif case SIOCSTLCK : - error = BCOPYIN((caddr_t)data, (caddr_t)&tmp, sizeof(tmp)); + error = BCOPYIN(data, &tmp, sizeof(tmp)); if (error == 0) { fr_state_lock = tmp; fr_nat_lock = tmp; @@ -7131,8 +7170,7 @@ void *ctx; error = EPERM; else { tmp = ipflog_clear(IPL_LOGIPF); - error = BCOPYOUT((caddr_t)&tmp, (caddr_t)data, - sizeof(tmp)); + error = BCOPYOUT(&tmp, data, sizeof(tmp)); if (error) error = EFAULT; } @@ -7164,7 +7202,7 @@ void *ctx; case FIONREAD : tmp = (int)iplused[IPL_LOGIPF]; - error = BCOPYOUT((caddr_t)&tmp, (caddr_t)data, sizeof(tmp)); + error = BCOPYOUT(&tmp, data, sizeof(tmp)); break; #endif @@ -7179,16 +7217,14 @@ void *ctx; error = ipf_genericiter(data, uid, ctx); SPL_X(s); break; - break; case SIOCIPFDELTOK : SPL_SCHED(s); - error = BCOPYIN((caddr_t)data, (caddr_t)&tmp, sizeof(tmp)); + error = BCOPYIN(data, &tmp, sizeof(tmp)); if (error == 0) error = ipf_deltoken(tmp, uid, ctx); SPL_X(s); break; - break; default : error = EINVAL; @@ -7264,15 +7300,16 @@ ipftq_t *ipfqs, *userqs; return 0; } if (istart > fr_ticks) { - istart = (fr_ticks / interval) * interval; + if (fr_ticks - interval < interval) + istart = interval; + else + istart = (fr_ticks / interval) * interval; } iend = fr_ticks - interval; - if (istart > iend) - istart = iend - interval; removed = 0; - while (removed == 0) { + for (;;) { u_long try; try = fr_ticks - istart; @@ -7299,8 +7336,9 @@ ipftq_t *ipfqs, *userqs; } } - istart -= interval; if (try >= iend) { + if (removed > 0) + break; if (interval == IPF_TTLVAL(43200)) { interval = IPF_TTLVAL(1800); } else if (interval == IPF_TTLVAL(1800)) { @@ -7313,6 +7351,7 @@ ipftq_t *ipfqs, *userqs; iend = fr_ticks - interval; } + istart -= interval; } return removed; diff --git a/sys/contrib/ipfilter/netinet/ip_auth.c b/sys/contrib/ipfilter/netinet/ip_auth.c index e6d3d50..6884110 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.c +++ b/sys/contrib/ipfilter/netinet/ip_auth.c @@ -121,7 +121,7 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ #if !defined(lint) static const char rcsid[] = "@(#)$FreeBSD$"; -/* static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.73.2.13 2006/03/29 11:19:55 darrenr Exp $"; */ +/* static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.73.2.24 2007/09/09 11:32:04 darrenr Exp $"; */ #endif @@ -328,16 +328,10 @@ fr_info_t *fin; return 0; WRITE_ENTER(&ipf_auth); - if (fr_authstart > fr_authend) { + if (((fr_authend + 1) % fr_authsize) == fr_authstart) { fr_authstats.fas_nospace++; RWLOCK_EXIT(&ipf_auth); return 0; - } else { - if (fr_authused == fr_authsize) { - fr_authstats.fas_nospace++; - RWLOCK_EXIT(&ipf_auth); - return 0; - } } fr_authstats.fas_added++; @@ -374,10 +368,12 @@ fr_info_t *fin; } #endif #if SOLARIS && defined(_KERNEL) - COPYIFNAME(fin->fin_ifp, fra->fra_info.fin_ifname); + COPYIFNAME(fin->fin_v, fin->fin_ifp, fra->fra_info.fin_ifname); m->b_rptr -= qpi->qpi_off; fr_authpkts[i] = *(mblk_t **)fin->fin_mp; +# if !defined(_INET_IP_STACK_H) fra->fra_q = qpi->qpi_q; /* The queue can disappear! */ +# endif fra->fra_m = *fin->fin_mp; fra->fra_info.fin_mp = &fra->fra_m; cv_signal(&ipfauthwait); @@ -448,7 +444,7 @@ void *ctx; error = EPERM; break; } - fr_lock(data, &fr_auth_lock); + error = fr_lock(data, &fr_auth_lock); break; case SIOCATHST: @@ -716,15 +712,15 @@ int fr_authflush() /* ------------------------------------------------------------------------ */ /* Function: fr_auth_waiting */ -/* Returns: int - number of packets in the auth queue */ +/* Returns: int - 0 = no pakcets wiating, 1 = packets waiting. */ /* Parameters: None */ /* */ -/* Returns the numbers of packets queued up, waiting to be processed with */ -/* a pair of SIOCAUTHW and SIOCAUTHR calls. */ +/* Simple truth check to see if there are any packets waiting in the auth */ +/* queue. */ /* ------------------------------------------------------------------------ */ int fr_auth_waiting() { - return (fr_authnext != fr_authend) && fr_authpkts[fr_authnext]; + return (fr_authused != 0); } @@ -861,7 +857,13 @@ fr_authioctlloop: * is a packet waiting to be delt with in the fr_authpkts array. We * copy as much of that out to user space as requested. */ - if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { + if (fr_authused > 0) { + while (fr_authpkts[fr_authnext] == NULL) { + fr_authnext++; + if (fr_authnext == fr_authsize) + fr_authnext = 0; + } + error = fr_outobj(data, &fr_auth[fr_authnext], IPFOBJ_FRAUTH); if (error != 0) return error; @@ -888,8 +890,6 @@ fr_authioctlloop: } } RWLOCK_EXIT(&ipf_auth); - if (error != 0) - return error; SPL_NET(s); WRITE_ENTER(&ipf_auth); diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h index 93ac208..b653007 100644 --- a/sys/contrib/ipfilter/netinet/ip_compat.h +++ b/sys/contrib/ipfilter/netinet/ip_compat.h @@ -5,7 +5,7 @@ * * @(#)ip_compat.h 1.8 1/14/96 * $FreeBSD$ - * Id: ip_compat.h,v 2.142.2.36 2006/03/26 05:50:29 darrenr Exp $ + * Id: ip_compat.h,v 2.142.2.57 2007/10/10 09:51:42 darrenr Exp $ */ #ifndef __IP_COMPAT_H__ @@ -169,6 +169,11 @@ struct file; # ifdef i386 # define _SYS_PROMIF_H # endif +# ifndef _KERNEL +# include "radix_ipf.h" +# else +# include "radix_ipf_local.h" +# endif # include <inet/ip.h> # undef COPYOUT # include <inet/ip_ire.h> @@ -201,9 +206,29 @@ typedef unsigned int u_32_t; # ifdef _KERNEL # define KRWLOCK_T krwlock_t # define KMUTEX_T kmutex_t -# include "qif.h" -# include "pfil.h" -# if defined(SOLARIS2) && SOLARIS2 >= 6 + +# if !defined(FW_HOOKS) +# include "qif.h" +# include "pfil.h" +# else +# include <sys/neti.h> + +extern net_data_t ipfipv4; +extern net_data_t ipfipv6; + +typedef struct qpktinfo { + void *qpi_data; + mblk_t **qpi_mp; + mblk_t *qpi_m; + uintptr_t qpi_real; + int qpi_flags; + int qpi_num; + int qpi_off; +} qpktinfo_t; +# define QF_GROUP 0x01 +# endif + +# if SOLARIS2 >= 6 # if SOLARIS2 == 6 # define ATOMIC_INCL(x) atomic_add_long((uint32_t*)&(x), 1) # define ATOMIC_DECL(x) atomic_add_long((uint32_t*)&(x), -1) @@ -260,10 +285,24 @@ typedef unsigned int u_32_t; # define GET_MINOR(x) getminor(x) extern void *get_unit __P((char *, int)); # define GETIFP(n, v) get_unit(n, v) -# define IFNAME(x) ((qif_t *)x)->qf_name -# define COPYIFNAME(x, b) \ +# if defined(_INET_IP_STACK_H) +# define COPYIFNAME(v, x, b) \ + do { \ + if ((v) == 4) { \ + (void) net_getifname(ipfipv4,\ + (uintptr_t)x, b, \ + LIFNAMSIZ); \ + } else { \ + (void) net_getifname(ipfipv6,\ + (uintptr_t)x, b, \ + LIFNAMSIZ); \ + } \ + } while (0) +# else +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, ((qif_t *)x)->qf_name, \ LIFNAMSIZ) +# endif # define GETKTIME(x) uniqtime((struct timeval *)x) # define MSGDSIZE(x) msgdsize(x) # define M_LEN(x) ((x)->b_wptr - (x)->b_rptr) @@ -272,7 +311,11 @@ extern void *get_unit __P((char *, int)); # define MTYPE(m) ((m)->b_datap->db_type) # define FREE_MB_T(m) freemsg(m) # define m_next b_cont -# define CACHE_HASH(x) (((qpktinfo_t *)(x)->fin_qpi)->qpi_num & 7) +# if !defined(_INET_IP_STACK_H) +# define CACHE_HASH(x) (((qpktinfo_t *)(x)->fin_qpi)->qpi_num & 7) +# else +# define CACHE_HASH(x) ((uintptr_t)(x)->fin_ifp & 7) +# endif # define IPF_PANIC(x,y) if (x) { printf y; cmn_err(CE_PANIC, "ipf_panic"); } typedef mblk_t mb_t; # endif /* _KERNEL */ @@ -424,8 +467,7 @@ typedef struct iplog_select_s { # define SPL_X(x) ; extern void *get_unit __P((char *, int)); # define GETIFP(n, v) get_unit(n, v) -# define IFNAME(x, b) ((ill_t *)x)->ill_name -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, ((qif_t *)x)->qf_name, \ LIFNAMSIZ) # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) @@ -593,6 +635,7 @@ extern void m_copyback __P((struct mbuf *, int, int, caddr_t)); # define M_LEN(x) (x)->m_len # define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) # define GETKTIME(x) microtime((struct timeval *)x) +# define IFNAME(x) ((struct ifnet *)x)->if_name # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } @@ -669,6 +712,7 @@ typedef struct mbuf mb_t; # define M_LEN(x) (x)->m_len # define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) # define GETKTIME(x) microtime((struct timeval *)x) +# define IFNAME(x) ((struct ifnet *)x)->if_name # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } @@ -752,12 +796,13 @@ typedef struct mbuf mb_t; # endif /* _KERNEL */ # if (NetBSD <= 1991011) && (NetBSD >= 199606) # define IFNAME(x) ((struct ifnet *)x)->if_xname -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, \ ((struct ifnet *)x)->if_xname, \ LIFNAMSIZ) # define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index)&7) # else +# define IFNAME(x) ((struct ifnet *)x)->if_name # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # endif @@ -810,24 +855,66 @@ typedef u_int32_t u_32_t; # if (__FreeBSD_version >= 500043) # include <sys/mutex.h> -# include <sys/sx.h> +# if (__FreeBSD_version > 700014) +# include <sys/rwlock.h> +# define KRWLOCK_T struct rwlock +# ifdef _KERNEL +# define READ_ENTER(x) rw_rlock(&(x)->ipf_lk) +# define WRITE_ENTER(x) rw_wlock(&(x)->ipf_lk) +# define MUTEX_DOWNGRADE(x) rw_downgrade(&(x)->ipf_lk) +# define RWLOCK_INIT(x, y) rw_init(&(x)->ipf_lk, (y)) +# define RW_DESTROY(x) rw_destroy(&(x)->ipf_lk) +# define RWLOCK_EXIT(x) do { \ + if (rw_wowned(&(x)->ipf_lk)) \ + rw_wunlock(&(x)->ipf_lk); \ + else \ + rw_runlock(&(x)->ipf_lk); \ + } while (0) +# endif +# else +# include <sys/sx.h> /* * Whilst the sx(9) locks on FreeBSD have the right semantics and interface * for what we want to use them for, despite testing showing they work - * with a WITNESS kernel, it generates LOR messages. */ -# define KMUTEX_T struct mtx -# if (__FreeBSD_version < 700000) -# define KRWLOCK_T struct mtx -# else -# define KRWLOCK_T struct sx +# ifdef _KERNEL +# if (__FreeBSD_version < 700000) +# define KRWLOCK_T struct mtx +# define READ_ENTER(x) mtx_lock(&(x)->ipf_lk) +# define WRITE_ENTER(x) mtx_lock(&(x)->ipf_lk) +# define RWLOCK_EXIT(x) mtx_unlock(&(x)->ipf_lk) +# define MUTEX_DOWNGRADE(x) ; +# define RWLOCK_INIT(x,y) mtx_init(&(x)->ipf_lk, (y), NULL,\ + MTX_DEF) +# define RW_DESTROY(x) mtx_destroy(&(x)->ipf_lk) +# else +# define KRWLOCK_T struct sx +# define READ_ENTER(x) sx_slock(&(x)->ipf_lk) +# define WRITE_ENTER(x) sx_xlock(&(x)->ipf_lk) +# define MUTEX_DOWNGRADE(x) sx_downgrade(&(x)->ipf_lk) +# define RWLOCK_INIT(x, y) sx_init(&(x)->ipf_lk, (y)) +# define RW_DESTROY(x) sx_destroy(&(x)->ipf_lk) +# ifdef sx_unlock +# define RWLOCK_EXIT(x) sx_unlock(&(x)->ipf_lk) +# else +# define RWLOCK_EXIT(x) do { \ + if ((x)->ipf_lk.sx_cnt < 0) \ + sx_xunlock(&(x)->ipf_lk); \ + else \ + sx_sunlock(&(x)->ipf_lk); \ + } while (0) +# endif +# endif +# endif # endif +# define KMUTEX_T struct mtx # endif # if (__FreeBSD_version >= 501113) # include <net/if_var.h> # define IFNAME(x) ((struct ifnet *)x)->if_xname -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, \ ((struct ifnet *)x)->if_xname, \ LIFNAMSIZ) @@ -835,6 +922,7 @@ typedef u_int32_t u_32_t; # if (__FreeBSD_version >= 500043) # define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index) & 7) # else +# define IFNAME(x) ((struct ifnet *)x)->if_name # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # endif @@ -856,36 +944,6 @@ typedef u_int32_t u_32_t; MTX_DEF) # define MUTEX_DESTROY(x) mtx_destroy(&(x)->ipf_lk) # define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) -/* - * Whilst the sx(9) locks on FreeBSD have the right semantics and interface - * for what we want to use them for, despite testing showing they work - - * with a WITNESS kernel, it generates LOR messages. - */ -# if (__FreeBSD_version < 700000) -# define READ_ENTER(x) mtx_lock(&(x)->ipf_lk) -# define WRITE_ENTER(x) mtx_lock(&(x)->ipf_lk) -# define RWLOCK_EXIT(x) mtx_unlock(&(x)->ipf_lk) -# define MUTEX_DOWNGRADE(x) ; -# define RWLOCK_INIT(x,y) mtx_init(&(x)->ipf_lk, (y), NULL,\ - MTX_DEF) -# define RW_DESTROY(x) mtx_destroy(&(x)->ipf_lk) -# else -# define READ_ENTER(x) sx_slock(&(x)->ipf_lk) -# define WRITE_ENTER(x) sx_xlock(&(x)->ipf_lk) -# define MUTEX_DOWNGRADE(x) sx_downgrade(&(x)->ipf_lk) -# define RWLOCK_INIT(x, y) sx_init(&(x)->ipf_lk, (y)) -# define RW_DESTROY(x) sx_destroy(&(x)->ipf_lk) -# ifdef sx_unlock -# define RWLOCK_EXIT(x) sx_unlock(&(x)->ipf_lk) -# else -# define RWLOCK_EXIT(x) do { \ - if ((x)->ipf_lk.sx_cnt < 0) \ - sx_xunlock(&(x)->ipf_lk); \ - else \ - sx_sunlock(&(x)->ipf_lk); \ - } while (0) -# endif -# endif # include <machine/atomic.h> # define ATOMIC_INC(x) { mtx_lock(&ipf_rw.ipf_lk); (x)++; \ mtx_unlock(&ipf_rw.ipf_lk); } @@ -904,6 +962,8 @@ typedef u_int32_t u_32_t; # define SPL_IMP(x) ; # define SPL_SCHED(x) ; extern int in_cksum __P((struct mbuf *, int)); +# else +# define SPL_SCHED(x) x = splhigh() # endif /* __FreeBSD_version >= 500043 */ # define MSGDSIZE(x) mbufchainlen(x) # define M_LEN(x) (x)->m_len @@ -969,12 +1029,13 @@ typedef struct mbuf mb_t; # endif /* _KERNEL */ # if (OpenBSD >= 199603) # define IFNAME(x, b) ((struct ifnet *)x)->if_xname -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, \ ((struct ifnet *)x)->if_xname, \ LIFNAMSIZ) # define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index)&7) # else +# define IFNAME(x, b) ((struct ifnet *)x)->if_name # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # endif @@ -1002,6 +1063,7 @@ typedef u_int32_t u_32_t; # define MSGDSIZE(x) mbufchainlen(x) # define M_LEN(x) (x)->m_len # define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) +# define IFNAME(x, b) ((struct ifnet *)x)->if_name # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) typedef struct mbuf mb_t; @@ -1028,6 +1090,7 @@ typedef u_int32_t u_32_t; # define MSGDSIZE(x) mbufchainlen(x) # define M_LEN(x) (x)->m_len # define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) +# define IFNAME(x, b) ((struct ifnet *)x)->if_name # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # define GETIFP(n, v) ifunit(n, IFNAMSIZ) @@ -1085,7 +1148,7 @@ struct ip6_ext { # define SLEEP(x,s) 0, interruptible_sleep_on(x##_linux) # endif # define WAKEUP(x,y) wake_up(x##_linux + y) -# define UIOMOVE(a,b,c,d) uiomove(a,b,c,d) +# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define USE_MUTEXES # define KRWLOCK_T rwlock_t # define KMUTEX_T spinlock_t @@ -1179,7 +1242,7 @@ struct ifnet { # endif /* _KERNEL */ -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, \ ((struct ifnet *)x)->if_xname, \ LIFNAMSIZ) @@ -1289,6 +1352,7 @@ extern void* getifp __P((char *, int)); # define M_LEN(x) (x)->m_len # define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) # define GETKTIME(x) +# define IFNAME(x, b) ((struct ifnet *)x)->if_name # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # define IPF_PANIC(x,y) @@ -1460,7 +1524,7 @@ typedef struct mb_s { # define COPYBACK(m, o, l, b) bcopy((b), \ MTOD((mb_t *)m, char *) + (o), \ (l)) -# define UIOMOVE(a,b,c,d) ipfuiomove(a,b,c,d) +# define UIOMOVE(a,b,c,d) ipfuiomove((caddr_t)a,b,c,d) extern void m_copydata __P((mb_t *, int, int, caddr_t)); extern int ipfuiomove __P((caddr_t, int, int, struct uio *)); extern int bcopywrap __P((void *, void *, size_t)); @@ -1590,7 +1654,7 @@ MALLOC_DECLARE(M_IPFILTER); # endif # define KFREE(x) FREE((x), _M_IPF) # define KFREES(x,s) FREE((x), _M_IPF) -# define UIOMOVE(a,b,c,d) uiomove(a,b,d) +# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,d) # define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0) # define WAKEUP(id,x) wakeup(id+x) # define POLLWAKEUP(x) selwakeup(ipfselwait+x) @@ -1605,7 +1669,9 @@ MALLOC_DECLARE(M_IPFILTER); # define SPL_IMP(x) x = splimp() # define SPL_NET(x) x = splnet() # endif /* NetBSD && (NetBSD <= 1991011) && (NetBSD >= 199407) */ -# define SPL_SCHED(x) x = splsched() +# if !defined(SPL_SCHED) +# define SPL_SCHED(x) x = splsched() +# endif # define SPL_X(x) (void) splx(x) # endif /* !USE_MUTEXES */ @@ -1634,18 +1700,22 @@ MALLOC_DECLARE(M_IPFILTER); # define PANIC(x,y) if (x) panic y #endif /* _KERNEL */ -#ifndef IFNAME +#if !defined(IFNAME) && !defined(_KERNEL) # define IFNAME(x) ((struct ifnet *)x)->if_name #endif #ifndef COPYIFNAME # define NEED_FRGETIFNAME extern char *fr_getifname __P((struct ifnet *, char *)); -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ fr_getifname((struct ifnet *)x, b) #endif #ifndef ASSERT -# define ASSERT(x) +# ifdef _KERNEL +# define ASSERT(x) +# else +# define ASSERT(x) do { if (!(x)) abort(); } while (0) +# endif #endif #ifndef BCOPYIN diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h index dc5a473..353328c 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.h +++ b/sys/contrib/ipfilter/netinet/ip_fil.h @@ -5,7 +5,7 @@ * * @(#)ip_fil.h 1.35 6/5/96 * $FreeBSD$ - * Id: ip_fil.h,v 2.170.2.29 2006/03/29 11:19:55 darrenr Exp $ + * Id: ip_fil.h,v 2.170.2.51 2007/10/10 09:48:03 darrenr Exp $ */ #ifndef __IP_FIL_H__ @@ -157,14 +157,14 @@ typedef union i6addr { #define iplookupptr vptr[0] #define iplookupfunc lptr[1] -#define I60(x) (((i6addr_t *)(x))->i6[0]) -#define I61(x) (((i6addr_t *)(x))->i6[1]) -#define I62(x) (((i6addr_t *)(x))->i6[2]) -#define I63(x) (((i6addr_t *)(x))->i6[3]) -#define HI60(x) ntohl(((i6addr_t *)(x))->i6[0]) -#define HI61(x) ntohl(((i6addr_t *)(x))->i6[1]) -#define HI62(x) ntohl(((i6addr_t *)(x))->i6[2]) -#define HI63(x) ntohl(((i6addr_t *)(x))->i6[3]) +#define I60(x) (((u_32_t *)(x))[0]) +#define I61(x) (((u_32_t *)(x))[1]) +#define I62(x) (((u_32_t *)(x))[2]) +#define I63(x) (((u_32_t *)(x))[3]) +#define HI60(x) ntohl(((u_32_t *)(x))[0]) +#define HI61(x) ntohl(((u_32_t *)(x))[1]) +#define HI62(x) ntohl(((u_32_t *)(x))[2]) +#define HI63(x) ntohl(((u_32_t *)(x))[3]) #define IP6_EQ(a,b) ((I63(a) == I63(b)) && (I62(a) == I62(b)) && \ (I61(a) == I61(b)) && (I60(a) == I60(b))) @@ -182,14 +182,14 @@ typedef union i6addr { HI63(a) < HI63(b))))))) #define NLADD(n,x) htonl(ntohl(n) + (x)) #define IP6_INC(a) \ - { i6addr_t *_i6 = (i6addr_t *)(a); \ - _i6->i6[0] = NLADD(_i6->i6[0], 1); \ - if (_i6->i6[0] == 0) { \ - _i6->i6[0] = NLADD(_i6->i6[1], 1); \ - if (_i6->i6[1] == 0) { \ - _i6->i6[0] = NLADD(_i6->i6[2], 1); \ - if (_i6->i6[2] == 0) { \ - _i6->i6[0] = NLADD(_i6->i6[3], 1); \ + { u_32_t *_i6 = (u_32_t *)(a); \ + _i6[3] = NLADD(_i6[3], 1); \ + if (_i6[3] == 0) { \ + _i6[2] = NLADD(_i6[2], 1); \ + if (_i6[2] == 0) { \ + _i6[1] = NLADD(_i6[1], 1); \ + if (_i6[1] == 0) { \ + _i6[0] = NLADD(_i6[0], 1); \ } \ } \ } \ @@ -263,11 +263,12 @@ typedef struct fr_ip { #define FI_FRAGBODY 0x2000 #define FI_BADSRC 0x4000 #define FI_LOWTTL 0x8000 -#define FI_CMP 0xcfe3 /* Not FI_FRAG,FI_NATED,FI_FRAGTAIL */ +#define FI_CMP 0xcf03 /* Not FI_FRAG,FI_NATED,FI_FRAGTAIL,broadcast */ #define FI_ICMPCMP 0x0003 /* Flags we can check for ICMP error packets */ #define FI_WITH 0xeffe /* Not FI_TCPUDP */ #define FI_V6EXTHDR 0x10000 #define FI_COALESCE 0x20000 +#define FI_NEWNAT 0x40000 #define FI_NOCKSUM 0x20000000 /* don't do a L4 checksum validation */ #define FI_DONTCACHE 0x40000000 /* don't cache the result */ #define FI_IGNORE 0x80000000 @@ -327,6 +328,7 @@ typedef struct fr_info { u_short fin_off; int fin_depth; /* Group nesting depth */ int fin_error; /* Error code to return */ + int fin_cksum; /* -1 bad, 1 good, 0 not done */ void *fin_nat; void *fin_state; void *fin_nattag; @@ -1204,6 +1206,8 @@ typedef struct ipftable { } ipftable_t; #define IPFTABLE_BUCKETS 1 +#define IPFTABLE_BUCKETS_NATIN 2 +#define IPFTABLE_BUCKETS_NATOUT 3 /* @@ -1405,6 +1409,13 @@ extern int iplwrite __P((dev_t, struct uio *)); # endif /* __ sgi */ # endif /* MENTAT */ +# if defined(__FreeBSD_version) +extern int ipf_pfil_hook __P((void)); +extern int ipf_pfil_unhook __P((void)); +extern void ipf_event_reg __P((void)); +extern void ipf_event_dereg __P((void)); +# endif + #endif /* #ifndef _KERNEL */ extern ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_hostmap; @@ -1491,7 +1502,7 @@ extern void fr_getstat __P((struct friostat *)); extern int fr_ifpaddr __P((int, int, void *, struct in_addr *, struct in_addr *)); extern int fr_initialise __P((void)); -extern void fr_lock __P((caddr_t, int *)); +extern int fr_lock __P((caddr_t, int *)); extern int fr_makefrip __P((int, ip_t *, fr_info_t *)); extern int fr_matchtag __P((ipftag_t *, ipftag_t *)); extern int fr_matchicmpqueryreply __P((int, icmpinfo_t *, @@ -1504,7 +1515,7 @@ extern int fr_scanlist __P((fr_info_t *, u_32_t)); extern frentry_t *fr_srcgrpmap __P((fr_info_t *, u_32_t *)); extern int fr_tcpudpchk __P((fr_info_t *, frtuc_t *)); extern int fr_verifysrc __P((fr_info_t *fin)); -extern int fr_zerostats __P((char *)); +extern int fr_zerostats __P((void *)); extern ipftoken_t *ipf_findtoken __P((int, int, void *)); extern int ipf_getnextrule __P((ipftoken_t *, void *)); extern void ipf_expiretokens __P((void)); diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c index aeefb03..84281ab 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c +++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.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_freebsd.c,v 2.53.2.46 2007/05/11 13:41:53 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.50 2007/09/20 12:51:50 darrenr Exp $"; #endif #if defined(KERNEL) || defined(_KERNEL) @@ -205,15 +205,6 @@ int ipfattach() #ifdef USE_SPL int s; #endif -#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) - int error = 0; -# if __FreeBSD_version >= 501108 - struct pfil_head *ph_inet; -# ifdef USE_INET6 - struct pfil_head *ph_inet6; -# endif -# endif -#endif SPL_NET(s); if (fr_running > 0) { @@ -233,77 +224,6 @@ int ipfattach() } -# ifdef NETBSD_PF -# if __FreeBSD_version >= 500011 -# if __FreeBSD_version >= 501108 - ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); -# ifdef USE_INET6 - ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); -# endif - if (ph_inet == NULL -# ifdef USE_INET6 - && ph_inet6 == NULL -# endif - ) - return ENODEV; - - if (ph_inet != NULL) - error = pfil_add_hook((void *)fr_check_wrapper, NULL, - PFIL_IN|PFIL_OUT, ph_inet); - else - error = 0; -# else - error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif - if (error) { -# ifdef USE_INET6 - goto pfil_error; -# else - fr_deinitialise(); - SPL_X(s); - return error; -# endif - } -# else - pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT); -# endif -# ifdef USE_INET6 -# if __FreeBSD_version >= 501108 - if (ph_inet6 != NULL) - error = pfil_add_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); - else - error = 0; - if (error) { - pfil_remove_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); -# else - error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); - if (error) { - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif -pfil_error: - fr_deinitialise(); - SPL_X(s); - return error; - } -# endif -# endif - -#if (__FreeBSD_version >= 502103) - ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \ - ipf_ifevent, NULL, \ - EVENTHANDLER_PRI_ANY); - ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \ - ipf_ifevent, NULL, \ - EVENTHANDLER_PRI_ANY); - ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \ - NULL, EVENTHANDLER_PRI_ANY); -#endif - if (fr_checkp != fr_check) { fr_savep = fr_checkp; fr_checkp = fr_check; @@ -336,31 +256,9 @@ int ipfdetach() #ifdef USE_SPL int s; #endif -#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) - int error = 0; -# if __FreeBSD_version >= 501108 - struct pfil_head *ph_inet; -# ifdef USE_INET6 - struct pfil_head *ph_inet6; -# endif -# endif -#endif - if (fr_control_forwarding & 2) ipforwarding = 0; -#if (__FreeBSD_version >= 502103) - if (ipf_arrivetag != NULL) { - EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ipf_arrivetag); - } - if (ipf_departtag != NULL) { - EVENTHANDLER_DEREGISTER(ifnet_departure_event, ipf_departtag); - } - if (ipf_clonetag != NULL) { - EVENTHANDLER_DEREGISTER(if_clone_event, ipf_clonetag); - } -#endif - SPL_NET(s); #if (__FreeBSD_version >= 300000) @@ -377,44 +275,6 @@ int ipfdetach() fr_savep = NULL; #endif -#ifdef NETBSD_PF -# if (__FreeBSD_version >= 500011) -# if (__FreeBSD_version >= 501108) - ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); - if (ph_inet != NULL) - error = pfil_remove_hook((void *)fr_check_wrapper, NULL, - PFIL_IN|PFIL_OUT, ph_inet); - else - error = 0; -# else - error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif - if (error) { - SPL_X(s); - return error; - } -# else - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT); -# endif -# ifdef USE_INET6 -# if (__FreeBSD_version >= 501108) - ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); - if (ph_inet6 != NULL) - error = pfil_remove_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); - else - error = 0; -# else - error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); -# endif - if (error) { - SPL_X(s); - return error; - } -# endif -#endif fr_deinitialise(); fr_running = -2; @@ -692,10 +552,8 @@ fr_info_t *fin; if (tcp->th_flags & TH_RST) return -1; /* feedback loop */ -#ifndef IPFILTER_CKSUM if (fr_checkl4sum(fin) == -1) return -1; -#endif tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) + ((tcp->th_flags & TH_SYN) ? 1 : 0) + @@ -854,7 +712,7 @@ int dst; #endif ip_t *ip, *ip2; - if ((type < 0) || (type > ICMP_MAXTYPE)) + if ((type < 0) || (type >= ICMP_MAXTYPE)) return -1; code = fin->fin_icode; @@ -863,10 +721,8 @@ int dst; return -1; #endif -#ifndef IPFILTER_CKSUM if (fr_checkl4sum(fin) == -1) return -1; -#endif #ifdef MGETHDR MGETHDR(m, M_DONTWAIT, MT_HEADER); #else @@ -1470,6 +1326,9 @@ fr_info_t *fin; if ((fin->fin_flx & FI_NOCKSUM) != 0) return; + if (fin->fin_cksum != 0) + return; + m = fin->fin_m; if (m == NULL) { manual = 1; @@ -1485,8 +1344,12 @@ fr_info_t *fin; htonl(m->m_pkthdr.csum_data + fin->fin_ip->ip_len + fin->fin_p)); sum ^= 0xffff; - if (sum != 0) + if (sum != 0) { fin->fin_flx |= FI_BAD; + fin->fin_cksum = -1; + } else { + fin->fin_cksum = 1; + } } else manual = 1; skipauto: @@ -1598,11 +1461,16 @@ int len; m = m_pullup(m, len); } *fin->fin_mp = m; - fin->fin_m = m; if (m == NULL) { + fin->fin_m = NULL; ATOMIC_INCL(frstats[out].fr_pull[1]); return NULL; } + + while (M_LEN(m) == 0) { + m = m->m_next; + } + fin->fin_m = m; ip = MTOD(m, char *) + ipoff; } @@ -1658,3 +1526,122 @@ mb_t *m; return error; } + +int ipf_pfil_unhook(void) { +#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) +# if __FreeBSD_version >= 501108 + struct pfil_head *ph_inet; +# ifdef USE_INET6 + struct pfil_head *ph_inet6; +# endif +# endif +#endif + +#ifdef NETBSD_PF +# if (__FreeBSD_version >= 500011) +# if (__FreeBSD_version >= 501108) + ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); + if (ph_inet != NULL) + pfil_remove_hook((void *)fr_check_wrapper, NULL, + PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet); +# else + pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, + &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); +# endif +# else + pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK); +# endif +# ifdef USE_INET6 +# if (__FreeBSD_version >= 501108) + ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); + if (ph_inet6 != NULL) + pfil_remove_hook((void *)fr_check_wrapper6, NULL, + PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6); +# else + pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, + &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); +# endif +# endif +#endif + + return (0); +} + +int ipf_pfil_hook(void) { +#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) +# if __FreeBSD_version >= 501108 + struct pfil_head *ph_inet; +# ifdef USE_INET6 + struct pfil_head *ph_inet6; +# endif +# endif +#endif + +# ifdef NETBSD_PF +# if __FreeBSD_version >= 500011 +# if __FreeBSD_version >= 501108 + ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); +# ifdef USE_INET6 + ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); +# endif + if (ph_inet == NULL +# ifdef USE_INET6 + && ph_inet6 == NULL +# endif + ) + return ENODEV; + + if (ph_inet != NULL) + pfil_add_hook((void *)fr_check_wrapper, NULL, + PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet); +# else + pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, + &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); +# endif +# else + pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK); +# endif +# ifdef USE_INET6 +# if __FreeBSD_version >= 501108 + if (ph_inet6 != NULL) + pfil_add_hook((void *)fr_check_wrapper6, NULL, + PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6); +# else + pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, + &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); +# endif +# endif +# endif + return (0); +} + +void +ipf_event_reg(void) +{ +#if (__FreeBSD_version >= 502103) + ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \ + ipf_ifevent, NULL, \ + EVENTHANDLER_PRI_ANY); + ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \ + ipf_ifevent, NULL, \ + EVENTHANDLER_PRI_ANY); + ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \ + NULL, EVENTHANDLER_PRI_ANY); +#endif +} + +void +ipf_event_dereg(void) +{ +#if (__FreeBSD_version >= 502103) + if (ipf_arrivetag != NULL) { + EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ipf_arrivetag); + } + if (ipf_departtag != NULL) { + EVENTHANDLER_DEREGISTER(ifnet_departure_event, ipf_departtag); + } + if (ipf_clonetag != NULL) { + EVENTHANDLER_DEREGISTER(if_clone_event, ipf_clonetag); + } +#endif +} diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c index 02e7bd1..fb21bd1 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -103,7 +103,7 @@ extern struct timeout fr_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[] = "@(#)$FreeBSD$"; -/* static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.77.2.5 2006/02/26 08:26:54 darrenr Exp $";*/ +/* static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.77.2.12 2007/09/20 12:51:51 darrenr Exp $"; */ #endif @@ -939,16 +939,16 @@ ipfrwlock_t *lock; } else { bzero(&zero, sizeof(zero)); next = &zero; - token->ipt_data = (void *)-1; + token->ipt_data = NULL; } RWLOCK_EXIT(lock); if (frag != NULL) { - WRITE_ENTER(lock); - frag->ipfr_ref--; - if (frag->ipfr_ref <= 0) - fr_fragfree(frag); - RWLOCK_EXIT(lock); +#ifdef USE_MUTEXES + fr_fragderef(&frag, lock); +#else + fr_fragderef(&frag); +#endif } error = COPYOUT(next, itp->igi_data, sizeof(*next)); diff --git a/sys/contrib/ipfilter/netinet/ip_htable.c b/sys/contrib/ipfilter/netinet/ip_htable.c index 3882156..fc521d8 100644 --- a/sys/contrib/ipfilter/netinet/ip_htable.c +++ b/sys/contrib/ipfilter/netinet/ip_htable.c @@ -53,7 +53,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.9 2007/02/02 23:06:16 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.11 2007/09/20 12:51:51 darrenr Exp $"; #endif #ifdef IPFILTER_LOOKUP @@ -104,31 +104,29 @@ iplookupop_t *op; int err, i, unit; unit = op->iplo_unit; - if ((op->iplo_arg & IPHASH_ANON) == 0) + if ((op->iplo_arg & IPHASH_ANON) == 0) { iph = fr_existshtable(unit, op->iplo_name); - else - iph = NULL; + if (iph != NULL) { + if ((iph->iph_flags & IPHASH_DELETE) == 0) + return EEXIST; + iph->iph_flags &= ~IPHASH_DELETE; + return 0; + } + } + KMALLOC(iph, iphtable_t *); if (iph == NULL) { - KMALLOC(iph, iphtable_t *); - if (iph == NULL) { - ipht_nomem[op->iplo_unit]++; - return ENOMEM; - } - err = COPYIN(op->iplo_struct, iph, sizeof(*iph)); - if (err != 0) { - KFREE(iph); - return EFAULT; - } - } else { - if ((iph->iph_flags & IPHASH_DELETE) == 0) - return EEXIST; + ipht_nomem[op->iplo_unit]++; + return ENOMEM; + } + err = COPYIN(op->iplo_struct, iph, sizeof(*iph)); + if (err != 0) { + KFREE(iph); + return EFAULT; } if (iph->iph_unit != unit) { - if ((iph->iph_flags & IPHASH_DELETE) == 0) { - KFREE(iph); - } + KFREE(iph); return EINVAL; } @@ -153,33 +151,25 @@ iplookupop_t *op; iph->iph_type |= IPHASH_ANON; } - if ((iph->iph_flags & IPHASH_DELETE) == 0) { - KMALLOCS(iph->iph_table, iphtent_t **, - iph->iph_size * sizeof(*iph->iph_table)); - if (iph->iph_table == NULL) { - if ((iph->iph_flags & IPHASH_DELETE) == 0) { - KFREE(iph); - } - ipht_nomem[unit]++; - return ENOMEM; - } - - bzero((char *)iph->iph_table, - iph->iph_size * sizeof(*iph->iph_table)); - iph->iph_masks = 0; - iph->iph_list = NULL; - - iph->iph_ref = 1; - iph->iph_next = ipf_htables[unit]; - iph->iph_pnext = &ipf_htables[unit]; - if (ipf_htables[unit] != NULL) - ipf_htables[unit]->iph_pnext = &iph->iph_next; - ipf_htables[unit] = iph; - - ipf_nhtables[unit]++; + KMALLOCS(iph->iph_table, iphtent_t **, + iph->iph_size * sizeof(*iph->iph_table)); + if (iph->iph_table == NULL) { + KFREE(iph); + ipht_nomem[unit]++; + return ENOMEM; } - iph->iph_flags &= ~IPHASH_DELETE; + bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); + iph->iph_masks = 0; + iph->iph_list = NULL; + + iph->iph_ref = 1; + iph->iph_next = ipf_htables[unit]; + iph->iph_pnext = &ipf_htables[unit]; + if (ipf_htables[unit] != NULL) + ipf_htables[unit]->iph_pnext = &iph->iph_next; + ipf_htables[unit] = iph; + ipf_nhtables[unit]++; return 0; } @@ -551,11 +541,11 @@ ipflookupiter_t *ilp; if (nextiph != NULL) { ATOMIC_INC(nextiph->iph_ref); - if (nextiph->iph_next == NULL) - token->ipt_alive = 0; + token->ipt_data = nextiph; } else { bzero((char *)&zp, sizeof(zp)); nextiph = &zp; + token->ipt_data = NULL; } break; @@ -574,11 +564,11 @@ ipflookupiter_t *ilp; if (nextnode != NULL) { ATOMIC_INC(nextnode->ipe_ref); - if (nextnode->ipe_next == NULL) - token->ipt_alive = 0; + token->ipt_data = nextnode; } else { bzero((char *)&zn, sizeof(zn)); nextnode = &zn; + token->ipt_data = NULL; } break; default : @@ -598,7 +588,6 @@ ipflookupiter_t *ilp; fr_derefhtable(iph); RWLOCK_EXIT(&ip_poolrw); } - token->ipt_data = nextiph; err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph)); if (err != 0) err = EFAULT; @@ -610,7 +599,6 @@ ipflookupiter_t *ilp; fr_derefhtent(node); RWLOCK_EXIT(&ip_poolrw); } - token->ipt_data = nextnode; err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); if (err != 0) err = EFAULT; diff --git a/sys/contrib/ipfilter/netinet/ip_log.c b/sys/contrib/ipfilter/netinet/ip_log.c index 83454f0..583eb63 100644 --- a/sys/contrib/ipfilter/netinet/ip_log.c +++ b/sys/contrib/ipfilter/netinet/ip_log.c @@ -6,7 +6,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * $FreeBSD$ - * Id: ip_log.c,v 2.75.2.11 2006/03/26 13:50:47 darrenr Exp $ + * Id: ip_log.c,v 2.75.2.19 2007/09/09 11:32:06 darrenr Exp $ */ #include <sys/param.h> #if defined(KERNEL) || defined(_KERNEL) @@ -261,7 +261,8 @@ u_int flags; ipflog_t ipfl; u_char p; mb_t *m; -# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) +# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) && \ + !defined(_INET_IP_STACK_H) qif_t *ifp; # else struct ifnet *ifp; @@ -273,7 +274,10 @@ u_int flags; ipfl.fl_nattag.ipt_num[0] = 0; ifp = fin->fin_ifp; - hlen = fin->fin_hlen; + if (fin->fin_exthdr != NULL) + hlen = (char *)fin->fin_dp - (char *)fin->fin_ip; + else + hlen = fin->fin_hlen; /* * calculate header size. */ @@ -334,14 +338,16 @@ u_int flags; * Get the interface number and name to which this packet is * currently associated. */ -# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) +# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) && \ + !defined(_INET_IP_STACK_H) ipfl.fl_unit = (u_int)ifp->qf_ppa; - COPYIFNAME(ifp, ipfl.fl_ifname); + COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname); # else # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ - (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) - COPYIFNAME(ifp, ipfl.fl_ifname); + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \ + (SOLARIS && defined(_INET_IP_STACK_H)) + COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname); # else ipfl.fl_unit = (u_int)ifp->if_unit; # if defined(_KERNEL) @@ -350,7 +356,7 @@ u_int flags; if ((ipfl.fl_ifname[2] = ifp->if_name[2])) ipfl.fl_ifname[3] = ifp->if_name[3]; # else - (void) strncpy(ipfl.fl_ifname, IFNAME(ifp), sizeof(ipfl.fl_ifname)); + COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname); ipfl.fl_ifname[sizeof(ipfl.fl_ifname) - 1] = '\0'; # endif # endif @@ -426,7 +432,7 @@ void **items; size_t *itemsz; int *types, cnt; { - caddr_t buf, ptr; + u_char *buf, *ptr; iplog_t *ipl; size_t len; int i; @@ -463,7 +469,7 @@ int *types, cnt; * check that we have space to record this information and can * allocate that much. */ - KMALLOCS(buf, caddr_t, len); + KMALLOCS(buf, u_char *, len); if (buf == NULL) return -1; SPL_NET(s); @@ -502,7 +508,7 @@ int *types, cnt; if (types[i] == 0) { bcopy(items[i], ptr, itemsz[i]); } else if (types[i] == 1) { - COPYDATA(items[i], 0, itemsz[i], ptr); + COPYDATA(items[i], 0, itemsz[i], (char *)ptr); } ptr += itemsz[i]; } @@ -627,7 +633,7 @@ struct uio *uio; iplused[unit] -= dlen; MUTEX_EXIT(&ipl_mutex); SPL_X(s); - error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio); + error = UIOMOVE(ipl, dlen, UIO_READ, uio); if (error) { SPL_NET(s); MUTEX_ENTER(&ipl_mutex); @@ -637,7 +643,7 @@ struct uio *uio; break; } MUTEX_ENTER(&ipl_mutex); - KFREES((caddr_t)ipl, dlen); + KFREES(ipl, dlen); SPL_NET(s); } if (!iplt[unit]) { @@ -670,7 +676,7 @@ minor_t unit; MUTEX_ENTER(&ipl_mutex); while ((ipl = iplt[unit]) != NULL) { iplt[unit] = ipl->ipl_next; - KFREES((caddr_t)ipl, ipl->ipl_dsize); + KFREES(ipl, ipl->ipl_dsize); } iplh[unit] = &iplt[unit]; ipll[unit] = NULL; diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index a6a77dc..23cb579 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -118,7 +118,7 @@ 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[] = "@(#)$FreeBSD$"; -/* static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.195.2.56 2006/04/01 10:15:34 darrenr Exp $";*/ +/* static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.195.2.102 2007/10/16 10:08:10 darrenr Exp $"; */ #endif @@ -179,7 +179,7 @@ u_long fr_defnatage = DEF_NAT_AGE, natstat_t nat_stats; int fr_nat_lock = 0; int fr_nat_init = 0; -#if SOLARIS +#if SOLARIS && !defined(_INET_IP_STACK_H) extern int pfil_delayed_copy; #endif @@ -188,13 +188,13 @@ static int nat_flushtable __P((void)); static int nat_clearlist __P((void)); static void nat_addnat __P((struct ipnat *)); static void nat_addrdr __P((struct ipnat *)); -static void nat_delete __P((struct nat *, int)); static void nat_delrdr __P((struct ipnat *)); 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, int)); static int nat_extraflush __P((int)); +static int nat_gettable __P((char *)); static void nat_tabmove __P((nat_t *)); static int nat_match __P((fr_info_t *, ipnat_t *)); static INLINE int nat_newmap __P((fr_info_t *, nat_t *, natinfo_t *)); @@ -874,7 +874,7 @@ void *ctx; if (!(mode & FWRITE)) { error = EPERM; } else { - fr_lock(data, &fr_nat_lock); + error = fr_lock(data, &fr_nat_lock); } break; @@ -945,6 +945,10 @@ void *ctx; error = fr_outobj(data, nat_tqb, IPFOBJ_STATETQTAB); break; + case SIOCGTABL : + error = nat_gettable(data); + break; + default : error = EINVAL; break; @@ -1082,7 +1086,7 @@ int getlock; n = NULL; nat_stats.ns_rules++; -#if SOLARIS +#if SOLARIS && !defined(_INET_IP_STACK_H) pfil_delayed_copy = 0; #endif if (getlock) { @@ -1170,9 +1174,10 @@ int getlock; if (n->in_use == 0) { if (n->in_apr) appr_free(n->in_apr); + MUTEX_DESTROY(&n->in_lock); KFREE(n); nat_stats.ns_rules--; -#if SOLARIS +#if SOLARIS && !defined(_INET_IP_STACK_H) if (nat_stats.ns_rules == 0) pfil_delayed_copy = 1; #endif @@ -1646,22 +1651,23 @@ junkput: /* Delete a nat entry from the various lists and table. If NAT logging is */ /* enabled then generate a NAT log record for this event. */ /* ------------------------------------------------------------------------ */ -static void nat_delete(nat, logtype) +void nat_delete(nat, logtype) struct nat *nat; int logtype; { struct ipnat *ipn; + int removed = 0; if (logtype != 0 && nat_logging != 0) nat_log(nat, logtype); - MUTEX_ENTER(&ipf_nat_new); - /* * Take it as a general indication that all the pointers are set if * nat_pnext is set. */ if (nat->nat_pnext != NULL) { + removed = 1; + nat_stats.ns_bucketlen[0][nat->nat_hv[0]]--; nat_stats.ns_bucketlen[1][nat->nat_hv[1]]--; @@ -1701,15 +1707,35 @@ int logtype; if (logtype == NL_EXPIRE) nat_stats.ns_expire++; - nat->nat_ref--; - if (nat->nat_ref > 0) { - MUTEX_EXIT(&ipf_nat_new); + MUTEX_ENTER(&nat->nat_lock); + /* + * NL_DESTROY should only be passed in when we've got nat_ref >= 2. + * This happens when a nat'd packet is blocked and we want to throw + * away the NAT session. + */ + if (logtype == NL_DESTROY) { + if (nat->nat_ref > 2) { + nat->nat_ref -= 2; + MUTEX_EXIT(&nat->nat_lock); + if (removed) + nat_stats.ns_orphans++; + return; + } + } else if (nat->nat_ref > 1) { + nat->nat_ref--; + MUTEX_EXIT(&nat->nat_lock); + if (removed) + nat_stats.ns_orphans++; return; } + MUTEX_EXIT(&nat->nat_lock); /* - * At this point, nat_ref can be either 0 or -1 + * At this point, nat_ref is 1, doing "--" would make it 0.. */ + nat->nat_ref = 0; + if (!removed) + nat_stats.ns_orphans--; #ifdef IPFILTER_SYNC if (nat->nat_sync) @@ -1736,7 +1762,6 @@ int logtype; aps_free(nat->nat_aps); nat_stats.ns_inuse--; - MUTEX_EXIT(&ipf_nat_new); /* * If there's a fragment table entry too for this nat entry, then @@ -1810,6 +1835,7 @@ static int nat_clearlist() if (n->in_use == 0) { if (n->in_apr != NULL) appr_free(n->in_apr); + MUTEX_DESTROY(&n->in_lock); KFREE(n); nat_stats.ns_rules--; } else { @@ -1818,7 +1844,7 @@ static int nat_clearlist() } i++; } -#if SOLARIS +#if SOLARIS && !defined(_INET_IP_STACK_H) pfil_delayed_copy = 1; #endif nat_masks = 0; @@ -2482,10 +2508,12 @@ int direction; } if (nat_finalise(fin, nat, &ni, tcp, natsave, direction) == -1) { + fr_nat_doflush = 1; goto badnat; } if (flags & SI_WILDP) nat_stats.ns_wilds++; + fin->fin_flx |= FI_NEWNAT; goto done; badnat: nat_stats.ns_badnat++; @@ -2528,10 +2556,10 @@ int direction; np = ni->nai_np; if (np->in_ifps[0] != NULL) { - COPYIFNAME(np->in_ifps[0], nat->nat_ifnames[0]); + COPYIFNAME(4, np->in_ifps[0], nat->nat_ifnames[0]); } if (np->in_ifps[1] != NULL) { - COPYIFNAME(np->in_ifps[1], nat->nat_ifnames[1]); + COPYIFNAME(4, np->in_ifps[1], nat->nat_ifnames[1]); } #ifdef IPFILTER_SYNC if ((nat->nat_flags & SI_CLONE) == 0) @@ -2545,6 +2573,8 @@ int direction; nat->nat_ptr = np; nat->nat_p = fin->fin_p; nat->nat_mssclamp = np->in_mssclamp; + if (nat->nat_p == IPPROTO_TCP) + nat->nat_seqnext[0] = ntohl(tcp->th_seq); if ((np->in_apr != NULL) && ((ni->nai_flags & NAT_SLAVE) == 0)) if (appr_new(fin, nat) == -1) @@ -2992,10 +3022,22 @@ int dir; } if (sumd2 != 0) { + ipnat_t *np; + + np = nat->nat_ptr; sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); - fix_incksum(fin, &icmp->icmp_cksum, sumd2); + + if ((odst == 0) && (dir == NAT_OUTBOUND) && + (fin->fin_rev == 0) && (np != NULL) && + (np->in_redir & NAT_REDIRECT)) { + fix_outcksum(fin, &icmp->icmp_cksum, + sumd2); + } else { + fix_incksum(fin, &icmp->icmp_cksum, + sumd2); + } } } } else if (((flags & IPN_ICMPQUERY) != 0) && (dlen >= 8)) { @@ -3622,6 +3664,26 @@ ipnat_t *np; ifq2 = NULL; if (nat->nat_p == IPPROTO_TCP && ifq2 == NULL) { + u_32_t end, ack; + u_char tcpflags; + tcphdr_t *tcp; + int dsize; + + tcp = fin->fin_dp; + tcpflags = tcp->th_flags; + dsize = fin->fin_dlen - (TCP_OFF(tcp) << 2) + + ((tcpflags & TH_SYN) ? 1 : 0) + + ((tcpflags & TH_FIN) ? 1 : 0); + + ack = ntohl(tcp->th_ack); + end = ntohl(tcp->th_seq) + dsize; + + if (SEQ_GT(ack, nat->nat_seqnext[1 - fin->fin_rev])) + nat->nat_seqnext[1 - fin->fin_rev] = ack; + + if (nat->nat_seqnext[fin->fin_rev] == 0) + nat->nat_seqnext[fin->fin_rev] = end; + (void) fr_tcp_age(&nat->nat_tqe, fin, nat_tqb, 0); } else { if (ifq2 == NULL) { @@ -4643,9 +4705,10 @@ ipnat_t **inp; if (in->in_use == 0 && (in->in_flags & IPN_DELETE)) { if (in->in_apr) appr_free(in->in_apr); + MUTEX_DESTROY(&in->in_lock); KFREE(in); nat_stats.ns_rules--; -#if SOLARIS +#if SOLARIS && !defined(_INET_IP_STACK_H) if (nat_stats.ns_rules == 0) pfil_delayed_copy = 1; #endif @@ -4660,6 +4723,14 @@ ipnat_t **inp; /* */ /* Decrement the reference counter for this NAT table entry and free it if */ /* there are no more things using it. */ +/* */ +/* IF nat_ref == 1 when this function is called, then we have an orphan nat */ +/* structure *because* it only gets called on paths _after_ nat_ref has been*/ +/* incremented. If nat_ref == 1 then we shouldn't decrement it here */ +/* because nat_delete() will do that and send nat_ref to -1. */ +/* */ +/* Holding the lock on nat_lock is required to serialise nat_delete() being */ +/* called from a NAT flush ioctl with a deref happening because of a packet.*/ /* ------------------------------------------------------------------------ */ void fr_natderef(natp) nat_t **natp; @@ -4668,10 +4739,17 @@ nat_t **natp; nat = *natp; *natp = NULL; + + MUTEX_ENTER(&nat->nat_lock); + if (nat->nat_ref > 1) { + nat->nat_ref--; + MUTEX_EXIT(&nat->nat_lock); + return; + } + MUTEX_EXIT(&nat->nat_lock); + WRITE_ENTER(&ipf_nat); - nat->nat_ref--; - if (nat->nat_ref == 0) - nat_delete(nat, NL_EXPIRE); + nat_delete(nat, NL_EXPIRE); RWLOCK_EXIT(&ipf_nat); } @@ -4957,10 +5035,11 @@ ipfgeniter_t *itp; ipnat_t *ipn, *nextipnat = NULL, zeroipn; nat_t *nat, *nextnat = NULL, zeronat; int error = 0, count; - ipftoken_t *freet; char *dst; - freet = NULL; + count = itp->igi_nitems; + if (count < 1) + return ENOSPC; READ_ENTER(&ipf_nat); @@ -4998,61 +5077,52 @@ ipfgeniter_t *itp; } dst = itp->igi_data; - for (count = itp->igi_nitems; count > 0; count--) { + for (;;) { switch (itp->igi_type) { case IPFGENITER_HOSTMAP : if (nexthm != NULL) { - if (nexthm->hm_next == NULL) { - freet = t; - count = 1; - hm = NULL; - } if (count == 1) { ATOMIC_INC32(nexthm->hm_ref); + t->ipt_data = nexthm; } } else { bzero(&zerohm, sizeof(zerohm)); nexthm = &zerohm; count = 1; + t->ipt_data = NULL; } break; case IPFGENITER_IPNAT : if (nextipnat != NULL) { - if (nextipnat->in_next == NULL) { - freet = t; - count = 1; - ipn = NULL; - } if (count == 1) { MUTEX_ENTER(&nextipnat->in_lock); nextipnat->in_use++; MUTEX_EXIT(&nextipnat->in_lock); + t->ipt_data = nextipnat; } } else { bzero(&zeroipn, sizeof(zeroipn)); nextipnat = &zeroipn; count = 1; + t->ipt_data = NULL; } break; case IPFGENITER_NAT : if (nextnat != NULL) { - if (nextnat->nat_next == NULL) { - count = 1; - freet = t; - nat = NULL; - } if (count == 1) { MUTEX_ENTER(&nextnat->nat_lock); nextnat->nat_ref++; MUTEX_EXIT(&nextnat->nat_lock); + t->ipt_data = nextnat; } } else { bzero(&zeronat, sizeof(zeronat)); nextnat = &zeronat; count = 1; + t->ipt_data = NULL; } break; default : @@ -5060,20 +5130,12 @@ ipfgeniter_t *itp; } RWLOCK_EXIT(&ipf_nat); - if (freet != NULL) { - ipf_freetoken(freet); - freet = NULL; - } - + /* + * Copying out to user space needs to be done without the lock. + */ switch (itp->igi_type) { case IPFGENITER_HOSTMAP : - if (hm != NULL) { - WRITE_ENTER(&ipf_nat); - fr_hostmapdel(&hm); - RWLOCK_EXIT(&ipf_nat); - } - t->ipt_data = nexthm; error = COPYOUT(nexthm, dst, sizeof(*nexthm)); if (error != 0) error = EFAULT; @@ -5082,9 +5144,6 @@ ipfgeniter_t *itp; break; case IPFGENITER_IPNAT : - if (ipn != NULL) - fr_ipnatderef(&ipn); - t->ipt_data = nextipnat; error = COPYOUT(nextipnat, dst, sizeof(*nextipnat)); if (error != 0) error = EFAULT; @@ -5093,9 +5152,6 @@ ipfgeniter_t *itp; break; case IPFGENITER_NAT : - if (nat != NULL) - fr_natderef(&nat); - t->ipt_data = nextnat; error = COPYOUT(nextnat, dst, sizeof(*nextnat)); if (error != 0) error = EFAULT; @@ -5107,29 +5163,52 @@ ipfgeniter_t *itp; if ((count == 1) || (error != 0)) break; + count--; + READ_ENTER(&ipf_nat); + /* + * We need to have the lock again here to make sure that + * using _next is consistent. + */ switch (itp->igi_type) { case IPFGENITER_HOSTMAP : - hm = nexthm; - nexthm = hm->hm_next; + nexthm = nexthm->hm_next; break; - case IPFGENITER_IPNAT : - ipn = nextipnat; - nextipnat = ipn->in_next; + nextipnat = nextipnat->in_next; break; - case IPFGENITER_NAT : - nat = nextnat; - nextnat = nat->nat_next; - break; - default : + nextnat = nextnat->nat_next; break; } } + + switch (itp->igi_type) + { + case IPFGENITER_HOSTMAP : + if (hm != NULL) { + WRITE_ENTER(&ipf_nat); + fr_hostmapdel(&hm); + RWLOCK_EXIT(&ipf_nat); + } + break; + case IPFGENITER_IPNAT : + if (ipn != NULL) { + fr_ipnatderef(&ipn); + } + break; + case IPFGENITER_NAT : + if (nat != NULL) { + fr_natderef(&nat); + } + break; + default : + break; + } + return error; } @@ -5338,3 +5417,44 @@ void *entry; nat_delete(entry, NL_FLUSH); return 0; } + + +/* ------------------------------------------------------------------------ */ +/* Function: nat_gettable */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - pointer to ioctl data */ +/* */ +/* This function handles ioctl requests for tables of nat information. */ +/* At present the only table it deals with is the hash bucket statistics. */ +/* ------------------------------------------------------------------------ */ +static int nat_gettable(data) +char *data; +{ + ipftable_t table; + int error; + + error = fr_inobj(data, &table, IPFOBJ_GTABLE); + if (error != 0) + return error; + + switch (table.ita_type) + { + case IPFTABLE_BUCKETS_NATIN : + error = COPYOUT(nat_stats.ns_bucketlen[0], table.ita_table, + ipf_nattable_sz * sizeof(u_long)); + break; + + case IPFTABLE_BUCKETS_NATOUT : + error = COPYOUT(nat_stats.ns_bucketlen[1], table.ita_table, + ipf_nattable_sz * sizeof(u_long)); + break; + + default : + return EINVAL; + } + + if (error != 0) { + error = EFAULT; + } + return error; +} diff --git a/sys/contrib/ipfilter/netinet/ip_nat.h b/sys/contrib/ipfilter/netinet/ip_nat.h index 5484eac..3020eb6 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.h +++ b/sys/contrib/ipfilter/netinet/ip_nat.h @@ -7,7 +7,7 @@ * * @(#)ip_nat.h 1.5 2/4/96 * $FreeBSD$ - * Id: ip_nat.h,v 2.90.2.9 2005/03/28 11:09:55 darrenr Exp + * Id: ip_nat.h,v 2.90.2.20 2007/09/25 08:27:32 darrenr Exp $ */ #ifndef __IP_NAT_H__ @@ -125,6 +125,7 @@ typedef struct nat { char nat_ifnames[2][LIFNAMSIZ]; int nat_rev; /* 0 = forward, 1 = reverse */ int nat_redir; /* copy of in_redir */ + u_32_t nat_seqnext[2]; } nat_t; #define nat_inip nat_inip6.in4 @@ -363,6 +364,7 @@ typedef struct natstat { hostmap_t *ns_maplist; u_long *ns_bucketlen[2]; u_long ns_ticks; + u_int ns_orphans; } natstat_t; typedef struct natlog { @@ -384,6 +386,7 @@ typedef struct natlog { #define NL_NEWRDR NAT_REDIRECT #define NL_NEWBIMAP NAT_BIMAP #define NL_NEWBLOCK NAT_MAPBLK +#define NL_DESTROY 0xfffc #define NL_CLONE 0xfffd #define NL_FLUSH 0xfffe #define NL_EXPIRE 0xffff @@ -447,6 +450,7 @@ extern nat_t *nat_maplookup __P((void *, u_int, struct in_addr, extern nat_t *nat_lookupredir __P((natlookup_t *)); extern nat_t *nat_icmperrorlookup __P((fr_info_t *, int)); extern nat_t *nat_icmperror __P((fr_info_t *, u_int *, int)); +extern void nat_delete __P((struct nat *, int)); extern int nat_insert __P((nat_t *, int)); extern int fr_checknatout __P((fr_info_t *, u_32_t *)); diff --git a/sys/contrib/ipfilter/netinet/ip_proxy.c b/sys/contrib/ipfilter/netinet/ip_proxy.c index b04331e..b0490a1 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.c +++ b/sys/contrib/ipfilter/netinet/ip_proxy.c @@ -104,7 +104,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.62.2.20 2007/05/31 12:27:36 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.62.2.21 2007/06/02 21:22:28 darrenr Exp $"; #endif static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int )); @@ -296,7 +296,7 @@ int mode; void *ctx; { ap_ctl_t ctl; - caddr_t ptr; + u_char *ptr; int error; mode = mode; /* LINT */ @@ -304,11 +304,13 @@ void *ctx; switch (cmd) { case SIOCPROXY : - BCOPYIN(data, &ctl, sizeof(ctl)); + error = BCOPYIN(data, &ctl, sizeof(ctl)); + if (error != 0) + return EFAULT; ptr = NULL; if (ctl.apc_dsize > 0) { - KMALLOCS(ptr, caddr_t, ctl.apc_dsize); + KMALLOCS(ptr, u_char *, ctl.apc_dsize); if (ptr == NULL) error = ENOMEM; else { diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index 39a094a..cfb7974 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -113,7 +113,7 @@ struct file; #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.186.2.69 2007/05/26 13:05:14 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.186.2.80 2007/10/16 09:33:23 darrenr Exp $"; #endif static ipstate_t **ips_table = NULL; @@ -550,7 +550,7 @@ void *ctx; if (!(mode & FWRITE)) { error = EPERM; } else { - fr_lock(data, &fr_state_lock); + error = fr_lock(data, &fr_state_lock); } break; @@ -652,8 +652,8 @@ caddr_t data; int error; error = fr_inobj(data, &ips, IPFOBJ_STATESAVE); - if (error) - return EFAULT; + if (error != 0) + return error; isn = ips.ips_next; if (isn == NULL) { @@ -682,9 +682,7 @@ caddr_t data; bcopy((char *)isn->is_rule, (char *)&ips.ips_fr, sizeof(ips.ips_fr)); error = fr_outobj(data, &ips, IPFOBJ_STATESAVE); - if (error) - return EFAULT; - return 0; + return error; } @@ -993,6 +991,16 @@ u_int flags; hv += is->is_src.i6[3]; } #endif + if ((fin->fin_v == 4) && + (fin->fin_flx & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST))) { + if (fin->fin_out == 0) { + flags |= SI_W_DADDR|SI_CLONE; + hv -= is->is_daddr; + } else { + flags |= SI_W_SADDR|SI_CLONE; + hv -= is->is_saddr; + } + } switch (is->is_p) { @@ -1190,7 +1198,8 @@ u_int flags; sizeof(fr->fr_ifnames[0])); } else { is->is_ifp[out << 1] = fin->fin_ifp; - COPYIFNAME(fin->fin_ifp, is->is_ifname[out << 1]); + COPYIFNAME(is->is_v, fin->fin_ifp, + is->is_ifname[out << 1]); } is->is_ifp[(out << 1) + 1] = fr->fr_ifas[1]; @@ -1210,7 +1219,8 @@ u_int flags; if (fin->fin_ifp != NULL) { is->is_ifp[out << 1] = fin->fin_ifp; - COPYIFNAME(fin->fin_ifp, is->is_ifname[out << 1]); + COPYIFNAME(is->is_v, fin->fin_ifp, + is->is_ifname[out << 1]); } } @@ -1439,12 +1449,13 @@ ipstate_t *is; is->is_state[!source] = IPF_TCPS_CLOSED; fr_movequeue(&is->is_sti, is->is_sti.tqe_ifq, &ips_deletetq); - MUTEX_ENTER(&is->is_lock); + MUTEX_EXIT(&is->is_lock); return 0; } } - if (fr_tcpinwindow(fin, fdata, tdata, tcp, is->is_flags)) { + ret = fr_tcpinwindow(fin, fdata, tdata, tcp, is->is_flags); + if (ret > 0) { #ifdef IPFILTER_SCAN if (is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER)) { ipsc_packet(fin, is); @@ -1540,7 +1551,8 @@ ipstate_t *is; /* ------------------------------------------------------------------------ */ /* Function: fr_tcpinwindow */ -/* Returns: int - 1 == packet inside TCP "window", 0 == not inside. */ +/* Returns: int - 1 == packet inside TCP "window", 0 == not inside, */ +/* 2 == packet seq number matches next expected */ /* Parameters: fin(I) - pointer to packet information */ /* fdata(I) - pointer to tcp state informatio (forward) */ /* tdata(I) - pointer to tcp state informatio (reverse) */ @@ -1624,14 +1636,12 @@ int flags; /* * Strict sequencing only allows in-order delivery. */ - if ((flags & IS_STRICT) != 0) { - if (seq != fdata->td_end) { + if (seq != fdata->td_end) { + if ((flags & IS_STRICT) != 0) { return 0; } } -#define SEQ_GE(a,b) ((int)((a) - (b)) >= 0) -#define SEQ_GT(a,b) ((int)((a) - (b)) > 0) inseq = 0; if ((SEQ_GE(fdata->td_maxend, end)) && (SEQ_GE(seq, fdata->td_end - maxwin)) && @@ -2028,7 +2038,7 @@ u_32_t cmask; if (is->is_ifp[idx] == NULL && (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*')) { is->is_ifp[idx] = ifp; - COPYIFNAME(ifp, is->is_ifname[idx]); + COPYIFNAME(is->is_v, ifp, is->is_ifname[idx]); } fin->fin_rev = rev; return is; @@ -2299,8 +2309,6 @@ u_int hv; ipstate_t **isp; u_int hvm; - ASSERT(rw_read_locked(&ipf_state.ipf_lk) == 0); - hvm = is->is_hv; /* * Remove the hash from the old location... @@ -2383,6 +2391,14 @@ ipftq_t **ifqp; } } #endif + if ((v == 4) && + (fin->fin_flx & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST))) { + if (fin->fin_out == 0) { + hv -= src.in4.s_addr; + } else { + hv -= dst.in4.s_addr; + } + } /* * Search the hash table for matching packet header info. @@ -2531,12 +2547,31 @@ retry_tcpudp: } RWLOCK_EXIT(&ipf_state); - if (!tryagain && ips_stats.iss_wild) { - hv -= dport; - hv -= sport; - tryagain = 1; - WRITE_ENTER(&ipf_state); - goto retry_tcpudp; + if (ips_stats.iss_wild) { + if (tryagain == 0) { + hv -= dport; + hv -= sport; + } else if (tryagain == 1) { + hv = fin->fin_fi.fi_p; + /* + * If we try to pretend this is a reply to a + * multicast/broadcast packet then we need to + * exclude part of the address from the hash + * calculation. + */ + if (fin->fin_out == 0) { + hv += src.in4.s_addr; + } else { + hv += dst.in4.s_addr; + } + hv += dport; + hv += sport; + } + tryagain++; + if (tryagain <= 2) { + WRITE_ENTER(&ipf_state); + goto retry_tcpudp; + } } fin->fin_flx |= oow; break; @@ -2888,8 +2923,6 @@ ipstate_t *is; int why; { - ASSERT(rw_read_locked(&ipf_state.ipf_lk) == 0); - /* * Since we want to delete this, remove it from the state table, * where it can be found & used, first. @@ -2937,9 +2970,15 @@ int why; * entry (such as ipfstat), it'll do the deref path that'll bring * us back here to do the real delete & free. */ - is->is_ref--; - if (is->is_ref > 0) + MUTEX_ENTER(&is->is_lock); + if (is->is_ref > 1) { + is->is_ref--; + MUTEX_EXIT(&is->is_lock); return is->is_ref; + } + MUTEX_EXIT(&is->is_lock); + + is->is_ref = 0; if (is->is_tqehead[0] != NULL) { if (fr_deletetimeoutqueue(is->is_tqehead[0]) == 0) @@ -3536,7 +3575,7 @@ int flags; if ((tcpflags & (TH_FIN|TH_ACK)) == TH_ACK) { nstate = IPF_TCPS_TIME_WAIT; } - rval = 1; + rval = 2; break; case IPF_TCPS_LAST_ACK: /* 8 */ @@ -3560,24 +3599,14 @@ int flags; case IPF_TCPS_FIN_WAIT_2: /* 9 */ /* NOT USED */ -#if 0 - rval = 1; - if ((tcpflags & TH_OPENING) == TH_OPENING) { - nstate = IPF_TCPS_SYN_RECEIVED; - } else if (tcpflags & TH_SYN) { - nstate = IPF_TCPS_SYN_SENT; - } else if ((tcpflags & (TH_FIN|TH_ACK)) != 0) { - nstate = IPF_TCPS_TIME_WAIT; - } -#endif break; case IPF_TCPS_TIME_WAIT: /* 10 */ /* we're in 2MSL timeout now */ - rval = 2; if (ostate == IPF_TCPS_LAST_ACK) { nstate = IPF_TCPS_CLOSED; } + rval = 1; break; case IPF_TCPS_CLOSED: /* 11 */ @@ -3932,6 +3961,14 @@ ipftq_t *tqp; /* Decrement the reference counter for this state table entry and free it */ /* if there are no more things using it. */ /* */ +/* This function is only called when cleaning up after increasing is_ref by */ +/* one earlier in the 'code path' so if is_ref is 1 when entering, we do */ +/* have an orphan, otherwise not. However there is a possible race between */ +/* the entry being deleted via flushing with an ioctl call (that calls the */ +/* delete function directly) and the tail end of packet processing so we */ +/* need to grab is_lock before doing the check to synchronise the two code */ +/* paths. */ +/* */ /* When operating in userland (ipftest), we have no timers to clear a state */ /* entry. Therefore, we make a few simple tests before deleting an entry */ /* outright. We compare states on each side looking for a combination of */ @@ -3954,17 +3991,23 @@ ipstate_t **isp; is = *isp; *isp = NULL; - WRITE_ENTER(&ipf_state); - is->is_ref--; - if (is->is_ref == 0) { - is->is_ref++; /* To counter ref-- in fr_delstate() */ - fr_delstate(is, ISL_EXPIRE); + + MUTEX_ENTER(&is->is_lock); + if (is->is_ref > 1) { + is->is_ref--; + MUTEX_EXIT(&is->is_lock); #ifndef _KERNEL - } else if ((is->is_sti.tqe_state[0] > IPF_TCPS_ESTABLISHED) || + if ((is->is_sti.tqe_state[0] > IPF_TCPS_ESTABLISHED) || (is->is_sti.tqe_state[1] > IPF_TCPS_ESTABLISHED)) { - fr_delstate(is, ISL_ORPHAN); + fr_delstate(is, ISL_ORPHAN); + } #endif + return; } + MUTEX_EXIT(&is->is_lock); + + WRITE_ENTER(&ipf_state); + fr_delstate(is, ISL_EXPIRE); RWLOCK_EXIT(&ipf_state); } @@ -4058,7 +4101,7 @@ ipfgeniter_t *itp; if (itp->igi_data == NULL) return EFAULT; - if (itp->igi_nitems == 0) + if (itp->igi_nitems < 1) return ENOSPC; if (itp->igi_type != IPFGENITER_STATE) @@ -4080,33 +4123,29 @@ ipfgeniter_t *itp; next = is->is_next; } - for (count = itp->igi_nitems; count > 0; count--) { + count = itp->igi_nitems; + for (;;) { if (next != NULL) { /* * If we find a state entry to use, bump its * reference count so that it can be used for * is_next when we come back. */ - MUTEX_ENTER(&next->is_lock); - next->is_ref++; - MUTEX_EXIT(&next->is_lock); - token->ipt_data = next; + if (count == 1) { + MUTEX_ENTER(&next->is_lock); + next->is_ref++; + MUTEX_EXIT(&next->is_lock); + token->ipt_data = next; + } } else { bzero(&zero, sizeof(zero)); next = &zero; - token->ipt_data = (void *)-1; count = 1; + token->ipt_data = NULL; } RWLOCK_EXIT(&ipf_state); /* - * If we had a prior pointer to a state entry, release it. - */ - if (is != NULL) { - fr_statederef(&is); - } - - /* * This should arguably be via fr_outobj() so that the state * structure can (if required) be massaged going out. */ @@ -4117,9 +4156,14 @@ ipfgeniter_t *itp; break; dst += sizeof(*next); + count--; + READ_ENTER(&ipf_state); - is = next; - next = is->is_next; + next = next->is_next; + } + + if (is != NULL) { + fr_statederef(&is); } return error; diff --git a/sys/contrib/ipfilter/netinet/ip_state.h b/sys/contrib/ipfilter/netinet/ip_state.h index ca7e454..9c4e814 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.h +++ b/sys/contrib/ipfilter/netinet/ip_state.h @@ -7,7 +7,7 @@ * * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed * $FreeBSD$ - * Id: ip_state.h,v 2.68.2.3 2005/03/03 14:24:11 darrenr Exp + * Id: ip_state.h,v 2.68.2.10 2007/10/16 09:33:24 darrenr Exp $ */ #ifndef __IP_STATE_H__ #define __IP_STATE_H__ @@ -27,10 +27,8 @@ struct ipscan; # define IPSTATE_MAX 4013 /* Maximum number of states held */ #endif -#define PAIRS(s1,d1,s2,d2) ((((s1) == (s2)) && ((d1) == (d2))) ||\ - (((s1) == (d2)) && ((d1) == (s2)))) -#define IPPAIR(s1,d1,s2,d2) PAIRS((s1).s_addr, (d1).s_addr, \ - (s2).s_addr, (d2).s_addr) +#define SEQ_GE(a,b) ((int)((a) - (b)) >= 0) +#define SEQ_GT(a,b) ((int)((a) - (b)) > 0) typedef struct ipstate { diff --git a/sys/contrib/ipfilter/netinet/ip_sync.c b/sys/contrib/ipfilter/netinet/ip_sync.c index 6b277ae..a72f50f 100644 --- a/sys/contrib/ipfilter/netinet/ip_sync.c +++ b/sys/contrib/ipfilter/netinet/ip_sync.c @@ -98,7 +98,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_sync.c,v 2.40.2.8 2006/07/14 06:12:20 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_sync.c,v 2.40.2.9 2007/06/02 21:22:28 darrenr Exp $"; #endif #define SYNC_STATETABSZ 256 @@ -301,7 +301,7 @@ struct uio *uio; if (uio->uio_resid >= sizeof(sh)) { - err = UIOMOVE((caddr_t)&sh, sizeof(sh), UIO_WRITE, uio); + err = UIOMOVE(&sh, sizeof(sh), UIO_WRITE, uio); if (err) { if (ipf_sync_debug > 2) @@ -373,7 +373,7 @@ struct uio *uio; if (uio->uio_resid >= sh.sm_len) { - err = UIOMOVE((caddr_t)data, sh.sm_len, UIO_WRITE, uio); + err = UIOMOVE(data, sh.sm_len, UIO_WRITE, uio); if (err) { if (ipf_sync_debug > 2) @@ -473,7 +473,7 @@ struct uio *uio; READ_ENTER(&ipf_syncstate); while ((sl_tail < sl_idx) && (uio->uio_resid > sizeof(*sl))) { sl = synclog + sl_tail++; - err = UIOMOVE((caddr_t)sl, sizeof(*sl), UIO_READ, uio); + err = UIOMOVE(sl, sizeof(*sl), UIO_READ, uio); if (err != 0) break; } @@ -481,7 +481,7 @@ struct uio *uio; while ((su_tail < su_idx) && (uio->uio_resid > sizeof(*su))) { su = syncupd + su_tail; su_tail++; - err = UIOMOVE((caddr_t)su, sizeof(*su), UIO_READ, uio); + err = UIOMOVE(su, sizeof(*su), UIO_READ, uio); if (err != 0) break; if (su->sup_hdr.sm_sl != NULL) diff --git a/sys/contrib/ipfilter/netinet/ipl.h b/sys/contrib/ipfilter/netinet/ipl.h index 22b8d51..4f2f122 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -7,14 +7,14 @@ * * @(#)ipl.h 1.21 6/5/96 * $FreeBSD$ - * Id: ipl.h,v 2.52.2.14 2006/04/01 20:09:42 darrenr Exp $ + * Id: ipl.h,v 2.52.2.30 2007/10/16 09:41:00 darrenr Exp $ */ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v4.1.23" +#define IPL_VERSION "IP Filter: v4.1.28" -#define IPFILTER_VERSION 4012300 +#define IPFILTER_VERSION 4012800 #endif diff --git a/sys/contrib/ipfilter/netinet/mlfk_ipl.c b/sys/contrib/ipfilter/netinet/mlfk_ipl.c index 9166712..36048e4 100644 --- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c +++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c @@ -207,6 +207,11 @@ ipf_modload() ipf_devs[i] = make_dev(&ipl_cdevsw, i, 0, 0, 0600, c); } + error = ipf_pfil_hook(); + if (error != 0) + return error; + ipf_event_reg(); + if (FR_ISPASS(fr_pass)) defpass = "pass"; else if (FR_ISBLOCK(fr_pass)) @@ -240,7 +245,11 @@ ipf_modunload() return EBUSY; if (fr_running >= 0) { + ipf_pfil_unhook(); + ipf_event_dereg(); + WRITE_ENTER(&ipf_global); error = ipfdetach(); + RWLOCK_EXIT(&ipf_global); if (error != 0) return error; } else |