From 8e202f8079930a406d5a5923404c860351dcb141 Mon Sep 17 00:00:00 2001 From: darrenr Date: Thu, 18 Oct 2007 21:42:51 +0000 Subject: Import IPFilter 4.1.28 --- sys/contrib/ipfilter/netinet/fil.c | 286 +++++++++++++++----------- sys/contrib/ipfilter/netinet/ip_auth.c | 34 +-- sys/contrib/ipfilter/netinet/ip_compat.h | 180 +++++++++++----- sys/contrib/ipfilter/netinet/ip_fil.h | 51 +++-- sys/contrib/ipfilter/netinet/ip_fil_freebsd.c | 283 ++++++++++++------------- sys/contrib/ipfilter/netinet/ip_frag.c | 18 +- sys/contrib/ipfilter/netinet/ip_htable.c | 90 ++++---- sys/contrib/ipfilter/netinet/ip_log.c | 34 +-- sys/contrib/ipfilter/netinet/ip_lookup.c | 50 ++++- sys/contrib/ipfilter/netinet/ip_lookup.h | 3 +- sys/contrib/ipfilter/netinet/ip_nat.c | 254 +++++++++++++++++------ sys/contrib/ipfilter/netinet/ip_nat.h | 6 +- sys/contrib/ipfilter/netinet/ip_pool.c | 87 ++++---- sys/contrib/ipfilter/netinet/ip_pool.h | 4 +- sys/contrib/ipfilter/netinet/ip_proxy.c | 10 +- sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c | 2 +- sys/contrib/ipfilter/netinet/ip_scan.c | 6 +- sys/contrib/ipfilter/netinet/ip_state.c | 172 ++++++++++------ sys/contrib/ipfilter/netinet/ip_state.h | 8 +- sys/contrib/ipfilter/netinet/ip_sync.c | 10 +- sys/contrib/ipfilter/netinet/ipl.h | 6 +- sys/contrib/ipfilter/netinet/mlfk_ipl.c | 9 + 22 files changed, 953 insertions(+), 650 deletions(-) (limited to 'sys') diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index e2b6e92..3183dd1 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -80,7 +80,7 @@ struct file; #ifdef sun # include #endif -#if !defined(_KERNEL) && defined(__FreeBSD__) +#if !defined(_KERNEL) && (defined(__FreeBSD__) || defined(SOLARIS2)) # if (__FreeBSD_version >= 504000) # undef _RADIX_H_ # endif @@ -151,7 +151,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[] = "@(#)$Id: fil.c,v 2.243.2.109 2007/05/31 12:27:33 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 @@ -357,7 +357,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)); @@ -475,8 +475,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 : @@ -647,7 +648,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 */ @@ -659,7 +660,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; @@ -668,12 +669,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; @@ -682,16 +683,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; } @@ -747,26 +750,26 @@ 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 * not correct. */ + icmp6 = fin->fin_dp; ip6 = (ip6_t *)((char *)icmp6 + ICMPERR_ICMPHLEN); if (IP6_NEQ(&fin->fin_fi.fi_dst, (i6addr_t *)&ip6->ip6_src)) fin->fin_flx |= FI_BAD; - minicmpsz = ICMP6ERR_IPICMPHLEN - sizeof(ip6_t); break; default : break; @@ -907,6 +910,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; @@ -995,6 +1006,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 : @@ -1065,14 +1079,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); } @@ -1188,6 +1200,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; @@ -1275,8 +1288,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); + } } @@ -1294,8 +1309,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); + } } @@ -1945,7 +1962,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; @@ -1964,7 +1981,6 @@ u_32_t pass; return pass; skip = 0; - logged = 0; portcmp = 0; fin->fin_depth++; fin->fin_fr = NULL; @@ -2098,7 +2114,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; @@ -2123,8 +2139,6 @@ u_32_t pass; fin->fin_fr = fr; passt = pass; } - if (fin->fin_flx & FI_DONTCACHE) - logged = 1; pass = passt; } @@ -2152,8 +2166,6 @@ u_32_t pass; break; } } - if (logged) - fin->fin_flx |= FI_DONTCACHE; fin->fin_depth--; return pass; } @@ -2404,8 +2416,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 @@ -2558,11 +2572,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); @@ -2625,7 +2648,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); + } } /* @@ -3065,8 +3095,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); @@ -3089,12 +3119,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")); @@ -3172,7 +3202,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, @@ -3478,7 +3508,7 @@ minor_t unit; int *nfreedp; frentry_t **listp; { - int freed = 0, i; + int freed = 0; frentry_t *fp; while ((fp = *listp) != NULL) { @@ -3489,8 +3519,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) { @@ -3846,7 +3875,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 @@ -3888,22 +3917,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; } @@ -4542,7 +4576,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; @@ -4553,8 +4587,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; @@ -4582,8 +4614,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)); @@ -4683,8 +4713,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++) @@ -5453,7 +5486,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; @@ -5479,11 +5514,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; @@ -5518,7 +5551,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; @@ -5535,7 +5570,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; @@ -5564,12 +5599,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; @@ -5586,7 +5623,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; @@ -5612,10 +5649,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; @@ -5639,7 +5678,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; @@ -5665,6 +5704,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 @@ -5727,8 +5772,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; } @@ -5981,7 +6029,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, @@ -6424,7 +6472,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; @@ -6530,15 +6578,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); @@ -6715,7 +6760,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 @@ -6794,30 +6841,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; @@ -6831,12 +6875,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; @@ -6964,8 +7013,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; @@ -7005,16 +7053,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; @@ -7030,8 +7076,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 : @@ -7040,7 +7085,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; @@ -7050,8 +7095,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 @@ -7069,19 +7113,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 @@ -7094,12 +7136,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 @@ -7109,7 +7149,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; @@ -7125,8 +7165,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; } @@ -7158,7 +7197,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 @@ -7173,16 +7212,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; @@ -7258,15 +7295,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; @@ -7293,8 +7331,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)) { @@ -7307,6 +7346,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 50d6b95..11bd07b 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.c +++ b/sys/contrib/ipfilter/netinet/ip_auth.c @@ -117,7 +117,7 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.73.2.20 2007/05/29 13:48:54 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.73.2.24 2007/09/09 11:32:04 darrenr Exp $"; #endif @@ -324,16 +324,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++; @@ -370,10 +364,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); @@ -444,7 +440,7 @@ void *ctx; error = EPERM; break; } - fr_lock(data, &fr_auth_lock); + error = fr_lock(data, &fr_auth_lock); break; case SIOCATHST: @@ -712,15 +708,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); } @@ -857,7 +853,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; @@ -884,8 +886,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 5dc1d44..901d21b 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.142.2.48 2007/05/31 12:27:34 darrenr Exp $ + * $Id: ip_compat.h,v 2.142.2.57 2007/10/10 09:51:42 darrenr Exp $ */ #ifndef __IP_COMPAT_H__ @@ -168,6 +168,11 @@ struct file; # ifdef i386 # define _SYS_PROMIF_H # endif +# ifndef _KERNEL +# include "radix_ipf.h" +# else +# include "radix_ipf_local.h" +# endif # include # undef COPYOUT # include @@ -200,8 +205,28 @@ 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(FW_HOOKS) +# include "qif.h" +# include "pfil.h" +# else +# include + +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) @@ -259,10 +284,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) @@ -271,7 +310,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 */ @@ -423,8 +466,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) @@ -592,6 +634,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"); } @@ -668,6 +711,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"); } @@ -751,12 +795,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 @@ -809,24 +854,66 @@ typedef u_int32_t u_32_t; # if (__FreeBSD_version >= 500043) # include -# include +# if (__FreeBSD_version > 700014) +# include +# 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 /* * 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 # 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) @@ -834,6 +921,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 @@ -855,36 +943,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 # define ATOMIC_INC(x) { mtx_lock(&ipf_rw.ipf_lk); (x)++; \ mtx_unlock(&ipf_rw.ipf_lk); } @@ -903,6 +961,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 @@ -968,12 +1028,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 @@ -1001,6 +1062,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; @@ -1027,6 +1089,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) @@ -1084,7 +1147,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 @@ -1178,7 +1241,7 @@ struct ifnet { # endif /* _KERNEL */ -# define COPYIFNAME(x, b) \ +# define COPYIFNAME(v, x, b) \ (void) strncpy(b, \ ((struct ifnet *)x)->if_xname, \ LIFNAMSIZ) @@ -1288,6 +1351,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) @@ -1459,7 +1523,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)); @@ -1589,7 +1653,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) @@ -1604,7 +1668,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 */ @@ -1633,18 +1699,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 da710c1..8236cef 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.170.2.45 2007/05/28 11:56:22 darrenr Exp $ + * $Id: ip_fil.h,v 2.170.2.51 2007/10/10 09:48:03 darrenr Exp $ */ #ifndef __IP_FIL_H__ @@ -156,14 +156,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))) @@ -181,14 +181,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); \ } \ } \ } \ @@ -262,11 +262,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 @@ -326,6 +327,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; @@ -1203,6 +1205,8 @@ typedef struct ipftable { } ipftable_t; #define IPFTABLE_BUCKETS 1 +#define IPFTABLE_BUCKETS_NATIN 2 +#define IPFTABLE_BUCKETS_NATOUT 3 /* @@ -1402,6 +1406,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; @@ -1488,7 +1499,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 *, @@ -1501,7 +1512,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 02e0030..fbecdad 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c +++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c @@ -5,7 +5,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) @@ -203,15 +203,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) { @@ -231,77 +222,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; @@ -334,31 +254,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) @@ -375,44 +273,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; @@ -690,10 +550,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) + @@ -852,7 +710,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; @@ -861,10 +719,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 @@ -1468,6 +1324,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; @@ -1483,8 +1342,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: @@ -1596,11 +1459,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; } @@ -1656,3 +1524,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 df75a0d..fd738f2 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -100,7 +100,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[] = "@(#)$Id: ip_frag.c,v 2.77.2.9 2007/05/27 11:13:44 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.77.2.12 2007/09/20 12:51:51 darrenr Exp $"; #endif @@ -400,7 +400,7 @@ u_32_t ipid; WRITE_ENTER(&ipf_ipidfrag); fra = ipfr_newfrag(fin, 0, ipfr_ipidtab); if (fra != NULL) { - fra->ipfr_data = (void *)ipid; + fra->ipfr_data = (void *)((u_long)ipid); *ipfr_ipidtail = fra; fra->ipfr_prev = ipfr_ipidtail; ipfr_ipidtail = &fra->ipfr_next; @@ -585,7 +585,7 @@ fr_info_t *fin; READ_ENTER(&ipf_ipidfrag); ipf = fr_fraglookup(fin, ipfr_ipidtab); if (ipf != NULL) - id = (u_32_t)ipf->ipfr_data; + id = (u_32_t)((u_long)ipf->ipfr_data & 0xffffffff); else id = 0xffffffff; RWLOCK_EXIT(&ipf_ipidfrag); @@ -936,16 +936,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 e5a0ad2..1bed371 100644 --- a/sys/contrib/ipfilter/netinet/ip_htable.c +++ b/sys/contrib/ipfilter/netinet/ip_htable.c @@ -51,7 +51,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 @@ -102,31 +102,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; } @@ -151,33 +149,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; } @@ -549,11 +539,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; @@ -572,11 +562,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 : @@ -596,7 +586,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; @@ -608,7 +597,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 2a0c72e..aed828e 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.75.2.15 2007/02/03 00:49:30 darrenr Exp $ + * $Id: ip_log.c,v 2.75.2.19 2007/09/09 11:32:06 darrenr Exp $ */ #include #if defined(KERNEL) || defined(_KERNEL) @@ -256,7 +256,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; @@ -268,7 +269,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. */ @@ -329,14 +333,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) @@ -345,7 +351,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 @@ -421,7 +427,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; @@ -458,7 +464,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); @@ -497,7 +503,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]; } @@ -622,7 +628,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); @@ -632,7 +638,7 @@ struct uio *uio; break; } MUTEX_ENTER(&ipl_mutex); - KFREES((caddr_t)ipl, dlen); + KFREES(ipl, dlen); SPL_NET(s); } if (!iplt[unit]) { @@ -665,7 +671,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_lookup.c b/sys/contrib/ipfilter/netinet/ip_lookup.c index 12b1f4a..e33a6fe 100644 --- a/sys/contrib/ipfilter/netinet/ip_lookup.c +++ b/sys/contrib/ipfilter/netinet/ip_lookup.c @@ -58,7 +58,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.15 2007/05/26 13:05:13 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.19 2007/10/11 09:05:51 darrenr Exp $"; #endif #ifdef IPFILTER_LOOKUP @@ -70,6 +70,8 @@ static int iplookup_addtable __P((caddr_t)); static int iplookup_deltable __P((caddr_t)); static int iplookup_stats __P((caddr_t)); static int iplookup_flush __P((caddr_t)); +static int iplookup_iterate __P((void *, int, void *)); +static int iplookup_deltok __P((void *, int, void *)); /* ------------------------------------------------------------------------ */ @@ -181,7 +183,11 @@ void *ctx; break; case SIOCLOOKUPITER : - err = ip_lookup_iterate(data, uid, ctx); + err = iplookup_iterate(data, uid, ctx); + break; + + case SIOCIPFDELTOK : + err = iplookup_deltok(data, uid, ctx); break; default : @@ -287,8 +293,9 @@ caddr_t data; ip_pool_t *p; int err; - err = 0; - BCOPYIN(data, &op, sizeof(op)); + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) + return EFAULT; if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) return EINVAL; @@ -558,13 +565,15 @@ void *ptr; /* ------------------------------------------------------------------------ */ -/* Function: ip_lookup_iterate */ +/* Function: iplookup_iterate */ /* Returns: int - 0 = success, else error */ /* Parameters: data(I) - pointer to data from ioctl call */ +/* uid(I) - uid of caller */ +/* ctx(I) - pointer to give the uid context */ /* */ /* Decodes ioctl request to step through either hash tables or pools. */ /* ------------------------------------------------------------------------ */ -int ip_lookup_iterate(data, uid, ctx) +static int iplookup_iterate(data, uid, ctx) void *data; int uid; void *ctx; @@ -578,7 +587,7 @@ void *ctx; if (err != 0) return err; - if (iter.ili_unit < 0 || iter.ili_unit > IPL_LOGMAX) + if (iter.ili_unit > IPL_LOGMAX) return EINVAL; if (iter.ili_ival != IPFGENITER_LOOKUP) @@ -644,6 +653,33 @@ void *data; } +/* ------------------------------------------------------------------------ */ +/* Function: iplookup_deltok */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* uid(I) - uid of caller */ +/* ctx(I) - pointer to give the uid context */ +/* */ +/* Deletes the token identified by the combination of (type,uid,ctx) */ +/* "key" is a combination of the table type, iterator type and the unit for */ +/* which the token was being used. */ +/* ------------------------------------------------------------------------ */ +static int iplookup_deltok(data, uid, ctx) +void *data; +int uid; +void *ctx; +{ + int error, key; + SPL_INT(s); + + SPL_SCHED(s); + error = BCOPYIN(data, &key, sizeof(key)); + if (error == 0) + error = ipf_deltoken(key, uid, ctx); + SPL_X(s); + return error; +} + #else /* IPFILTER_LOOKUP */ diff --git a/sys/contrib/ipfilter/netinet/ip_lookup.h b/sys/contrib/ipfilter/netinet/ip_lookup.h index 4b90655..3886df1 100644 --- a/sys/contrib/ipfilter/netinet/ip_lookup.h +++ b/sys/contrib/ipfilter/netinet/ip_lookup.h @@ -64,7 +64,7 @@ typedef union { char ilik_ival; u_char ilik_type; /* IPLT_* */ u_char ilik_otype; - char ilik_unit; /* IPL_LOG* */ + u_char ilik_unit; /* IPL_LOG* */ } ilik_unstr; u_32_t ilik_key; } iplookupiterkey_t; @@ -90,7 +90,6 @@ extern int ip_lookup_init __P((void)); extern int ip_lookup_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); extern void ip_lookup_unload __P((void)); extern void ip_lookup_deref __P((int, void *)); -extern int ip_lookup_iterate __P((void *, int, void *)); extern void ip_lookup_iterderef __P((u_32_t, void *)); #endif /* __IP_LOOKUP_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index 554fbc8..3df1850 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -115,7 +115,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[] = "@(#)$Id: ip_nat.c,v 2.195.2.87 2007/05/31 10:17:17 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.195.2.102 2007/10/16 10:08:10 darrenr Exp $"; #endif @@ -176,7 +176,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 @@ -185,13 +185,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 *)); @@ -871,7 +871,7 @@ void *ctx; if (!(mode & FWRITE)) { error = EPERM; } else { - fr_lock(data, &fr_nat_lock); + error = fr_lock(data, &fr_nat_lock); } break; @@ -942,6 +942,10 @@ void *ctx; error = fr_outobj(data, nat_tqb, IPFOBJ_STATETQTAB); break; + case SIOCGTABL : + error = nat_gettable(data); + break; + default : error = EINVAL; break; @@ -1079,7 +1083,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) { @@ -1167,9 +1171,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 @@ -1643,22 +1648,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]]--; @@ -1698,15 +1704,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) @@ -1733,7 +1759,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 @@ -1807,6 +1832,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 { @@ -1815,7 +1841,7 @@ static int nat_clearlist() } i++; } -#if SOLARIS +#if SOLARIS && !defined(_INET_IP_STACK_H) pfil_delayed_copy = 1; #endif nat_masks = 0; @@ -2479,10 +2505,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++; @@ -2525,10 +2553,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) @@ -2542,6 +2570,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) @@ -2989,10 +3019,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)) { @@ -3619,6 +3661,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) { @@ -4640,9 +4702,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 @@ -4657,6 +4720,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; @@ -4665,10 +4736,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); } @@ -4954,10 +5032,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); @@ -4995,61 +5074,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 : @@ -5057,20 +5127,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; @@ -5079,9 +5141,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; @@ -5090,9 +5149,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; @@ -5104,29 +5160,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; } @@ -5335,3 +5414,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 d478942..f25c0d8 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.90.2.17 2007/05/11 10:19:11 darrenr Exp $ + * $Id: ip_nat.h,v 2.90.2.20 2007/09/25 08:27:32 darrenr Exp $ */ #ifndef __IP_NAT_H__ @@ -122,6 +122,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 @@ -360,6 +361,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 { @@ -381,6 +383,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 @@ -444,6 +447,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_pool.c b/sys/contrib/ipfilter/netinet/ip_pool.c index b7e9946..eab3310 100644 --- a/sys/contrib/ipfilter/netinet/ip_pool.c +++ b/sys/contrib/ipfilter/netinet/ip_pool.c @@ -53,6 +53,9 @@ struct file; # include #endif +#if defined(SOLARIS2) && !defined(_KERNEL) +# include "radix_ipf.h" +#endif #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \ defined(__hpux) || defined(__sgi)) # include "radix_ipf_local.h" @@ -75,15 +78,16 @@ static int rn_freenode __P((struct radix_node *, void *)); #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_pool.c,v 2.55.2.20 2007/05/31 12:27:35 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.24 2007/10/10 09:45:37 darrenr Exp $"; #endif #ifdef IPFILTER_LOOKUP -# ifndef RADIX_NODE_HEAD_LOCK +# if !defined(RADIX_NODE_HEAD_LOCK) || !defined(RADIX_NODE_HEAD_UNLOCK) || \ + !defined(_KERNEL) +# undef RADIX_NODE_HEAD_LOCK +# undef RADIX_NODE_HEAD_UNLOCK # define RADIX_NODE_HEAD_LOCK(x) ; -# endif -# ifndef RADIX_NODE_HEAD_UNLOCK # define RADIX_NODE_HEAD_UNLOCK(x) ; # endif @@ -264,8 +268,6 @@ void ip_pool_fini() ip_pool_t *p, *q; int i; - ASSERT(rw_read_locked(&ipf_global.ipf_lk) == 0); - for (i = 0; i <= IPL_LOGMAX; i++) { for (q = ip_pool_list[i]; (p = q) != NULL; ) { q = p->ipo_next; @@ -463,8 +465,6 @@ int info; struct radix_node *rn; ip_pool_node_t *x; - ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); - KMALLOC(x, ip_pool_node_t *); if (x == NULL) { return ENOMEM; @@ -529,32 +529,27 @@ iplookupop_t *op; int poolnum, unit; ip_pool_t *h; - ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); - unit = op->iplo_unit; - if ((op->iplo_arg & LOOKUP_ANON) == 0) + if ((op->iplo_arg & LOOKUP_ANON) == 0) { h = ip_pool_exists(unit, op->iplo_name); - else - h = NULL; - - if (h != NULL) { - if ((h->ipo_flags & IPOOL_DELETE) != 0) { + if (h != NULL) { + if ((h->ipo_flags & IPOOL_DELETE) == 0) + return EEXIST; h->ipo_flags &= ~IPOOL_DELETE; return 0; } - return EEXIST; - } else { - KMALLOC(h, ip_pool_t *); - if (h == NULL) - return ENOMEM; - bzero(h, sizeof(*h)); - - if (rn_inithead((void **)&h->ipo_head, - offsetof(addrfamily_t, adf_addr) << 3) == 0) { - KFREE(h); - return ENOMEM; - } + } + + KMALLOC(h, ip_pool_t *); + if (h == NULL) + return ENOMEM; + bzero(h, sizeof(*h)); + + if (rn_inithead((void **)&h->ipo_head, + offsetof(addrfamily_t, adf_addr) << 3) == 0) { + KFREE(h); + return ENOMEM; } if ((op->iplo_arg & LOOKUP_ANON) != 0) { @@ -589,18 +584,16 @@ iplookupop_t *op; (void)strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); } - if ((h->ipo_flags & IPOOL_DELETE) == 0) { - h->ipo_ref = 1; - h->ipo_list = NULL; - h->ipo_unit = unit; - h->ipo_next = ip_pool_list[unit]; - if (ip_pool_list[unit] != NULL) - ip_pool_list[unit]->ipo_pnext = &h->ipo_next; - h->ipo_pnext = &ip_pool_list[unit]; - ip_pool_list[unit] = h; - - ipoolstat.ipls_pools++; - } + h->ipo_ref = 1; + h->ipo_list = NULL; + h->ipo_unit = unit; + h->ipo_next = ip_pool_list[unit]; + if (ip_pool_list[unit] != NULL) + ip_pool_list[unit]->ipo_pnext = &h->ipo_next; + h->ipo_pnext = &ip_pool_list[unit]; + ip_pool_list[unit] = h; + + ipoolstat.ipls_pools++; return 0; } @@ -620,8 +613,6 @@ ip_pool_t *ipo; ip_pool_node_t *ipe; { - ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); - if (ipe->ipn_pnext != NULL) *ipe->ipn_pnext = ipe->ipn_next; if (ipe->ipn_next != NULL) @@ -789,8 +780,6 @@ void ip_pool_deref(ipo) ip_pool_t *ipo; { - ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); - ipo->ipo_ref--; if (ipo->ipo_ref == 0) @@ -858,11 +847,11 @@ ipflookupiter_t *ilp; if (nextipo != NULL) { ATOMIC_INC(nextipo->ipo_ref); - if (nextipo->ipo_next == NULL) - token->ipt_alive = 0; + token->ipt_data = nextipo; } else { bzero((char *)&zp, sizeof(zp)); nextipo = &zp; + token->ipt_data = NULL; } break; @@ -882,11 +871,11 @@ ipflookupiter_t *ilp; if (nextnode != NULL) { ATOMIC_INC(nextnode->ipn_ref); - if (nextnode->ipn_next == NULL) - token->ipt_alive = 0; + token->ipt_data = nextnode; } else { bzero((char *)&zn, sizeof(zn)); nextnode = &zn; + token->ipt_data = NULL; } break; default : @@ -907,7 +896,6 @@ ipflookupiter_t *ilp; ip_pool_deref(ipo); RWLOCK_EXIT(&ip_poolrw); } - token->ipt_data = nextipo; err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo)); if (err != 0) err = EFAULT; @@ -919,7 +907,6 @@ ipflookupiter_t *ilp; ip_pool_node_deref(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_pool.h b/sys/contrib/ipfilter/netinet/ip_pool.h index 927276f..9968ef0 100644 --- a/sys/contrib/ipfilter/netinet/ip_pool.h +++ b/sys/contrib/ipfilter/netinet/ip_pool.h @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_pool.h,v 2.26.2.5 2007/01/14 14:06:12 darrenr Exp $ + * $Id: ip_pool.h,v 2.26.2.6 2007/10/10 09:51:43 darrenr Exp $ */ #ifndef __IP_POOL_H__ @@ -16,7 +16,7 @@ extern void rn_freehead __P((struct radix_node_head *)); # define FreeS(p, z) KFREES(p, z) extern int max_keylen; #else -# if defined(__osf__) || defined(__hpux) +# if defined(__osf__) || defined(__hpux) || defined(sun) # include "radix_ipf_local.h" # define radix_mask ipf_radix_mask # define radix_node ipf_radix_node diff --git a/sys/contrib/ipfilter/netinet/ip_proxy.c b/sys/contrib/ipfilter/netinet/ip_proxy.c index 96eb172..04e9f89 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.c +++ b/sys/contrib/ipfilter/netinet/ip_proxy.c @@ -103,7 +103,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 )); @@ -295,7 +295,7 @@ int mode; void *ctx; { ap_ctl_t ctl; - caddr_t ptr; + u_char *ptr; int error; mode = mode; /* LINT */ @@ -303,11 +303,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_rpcb_pxy.c b/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c index 4350bf4..da76fde 100644 --- a/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c @@ -37,7 +37,7 @@ * o The enclosed hack of STREAMS support is pretty sick and most likely * broken. * - * $Id: ip_rpcb_pxy.c,v 2.25.2.6 2007/01/17 11:34:54 darrenr Exp $ + * $Id: ip_rpcb_pxy.c,v 2.25.2.7 2007/06/04 09:16:31 darrenr Exp $ */ #define IPF_RPCB_PROXY diff --git a/sys/contrib/ipfilter/netinet/ip_scan.c b/sys/contrib/ipfilter/netinet/ip_scan.c index ad37216..54acb2a 100644 --- a/sys/contrib/ipfilter/netinet/ip_scan.c +++ b/sys/contrib/ipfilter/netinet/ip_scan.c @@ -58,7 +58,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_scan.c,v 2.40.2.9 2007/03/13 09:42:05 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_scan.c,v 2.40.2.10 2007/06/02 21:22:28 darrenr Exp $"; #endif #ifdef IPFILTER_SCAN /* endif at bottom of file */ @@ -587,7 +587,9 @@ void *ctx; case SIOCGSCST : bcopy((char *)&ipsc_stat, (char *)&ipscs, sizeof(ipscs)); ipscs.iscs_list = ipsc_list; - BCOPYOUT(&ipscs, data, sizeof(ipscs)); + err = BCOPYOUT(&ipscs, data, sizeof(ipscs)); + if (err != 0) + err = EFAULT; break; default : err = EINVAL; diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index 774dff3..a63f924 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -111,7 +111,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; @@ -548,7 +548,7 @@ void *ctx; if (!(mode & FWRITE)) { error = EPERM; } else { - fr_lock(data, &fr_state_lock); + error = fr_lock(data, &fr_state_lock); } break; @@ -650,8 +650,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) { @@ -680,9 +680,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; } @@ -991,6 +989,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) { @@ -1188,7 +1196,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]; @@ -1208,7 +1217,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]); } } @@ -1437,12 +1447,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); @@ -1538,7 +1549,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) */ @@ -1622,14 +1634,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)) && @@ -2026,7 +2036,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; @@ -2297,8 +2307,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... @@ -2381,6 +2389,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. @@ -2529,12 +2545,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; @@ -2886,8 +2921,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. @@ -2935,9 +2968,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) @@ -3534,7 +3573,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 */ @@ -3558,24 +3597,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 */ @@ -3930,6 +3959,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 */ @@ -3952,17 +3989,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); } @@ -4056,7 +4099,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) @@ -4078,33 +4121,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. */ @@ -4115,9 +4154,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 e19df1e..71dae1d 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.68.2.8 2007/05/11 10:44:14 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__ @@ -24,10 +24,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 c2eff0e..b145539 100644 --- a/sys/contrib/ipfilter/netinet/ip_sync.c +++ b/sys/contrib/ipfilter/netinet/ip_sync.c @@ -96,7 +96,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 @@ -299,7 +299,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) @@ -371,7 +371,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) @@ -471,7 +471,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; } @@ -479,7 +479,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 2bc9a1d..614250a 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -4,14 +4,14 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ipl.h 1.21 6/5/96 - * $Id: ipl.h,v 2.52.2.25 2007/05/31 11:40:43 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 3f04235..7718bd9 100644 --- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c +++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c @@ -204,6 +204,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)) @@ -237,7 +242,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 -- cgit v1.1