diff -urN linux-2.4.34-wt1-ctt205/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.34-wt1-ctt206/include/linux/netfilter_ipv4/ip_conntrack.h --- linux-2.4.34-wt1-ctt205/include/linux/netfilter_ipv4/ip_conntrack.h Sat Feb 17 20:06:29 2007 +++ linux-2.4.34-wt1-ctt206/include/linux/netfilter_ipv4/ip_conntrack.h Sat Feb 17 20:17:53 2007 @@ -272,7 +272,7 @@ /* Is this tuple taken? (ignoring any belonging to the given conntrack). */ -extern struct ip_conntrack_tuple_hash * +extern int ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple, const struct ip_conntrack *ignored_conntrack); diff -urN linux-2.4.34-wt1-ctt205/include/linux/netfilter_ipv4/ip_tproxy.h linux-2.4.34-wt1-ctt206/include/linux/netfilter_ipv4/ip_tproxy.h --- linux-2.4.34-wt1-ctt205/include/linux/netfilter_ipv4/ip_tproxy.h Sat Feb 17 20:06:29 2007 +++ linux-2.4.34-wt1-ctt206/include/linux/netfilter_ipv4/ip_tproxy.h Sat Feb 17 20:18:20 2007 @@ -30,9 +30,9 @@ #endif #endif -/* - * used in setsockopt(SOL_IP, IP_TPROXY) should not collide - * with values in +/* + * used in setsockopt(SOL_IP, IP_TPROXY) should not collide + * with values in */ #define IP_TPROXY 11274 diff -urN linux-2.4.34-wt1-ctt205/include/net/ip.h linux-2.4.34-wt1-ctt206/include/net/ip.h --- linux-2.4.34-wt1-ctt205/include/net/ip.h Sat Feb 17 20:06:29 2007 +++ linux-2.4.34-wt1-ctt206/include/net/ip.h Sat Feb 17 20:18:20 2007 @@ -50,9 +50,9 @@ #if defined(CONFIG_IP_NF_TPROXY) || defined (CONFIG_IP_NF_TPROXY_MODULE) - /* these fields still fit to the 48 bytes of allocated cb + /* these fields still fit to the 48 bytes of allocated cb * space as the whole structure is 28 bytes */ - + u32 orig_srcaddr; u32 orig_dstaddr; u16 orig_srcport; diff -urN linux-2.4.34-wt1-ctt205/net/ipv4/ip_sockglue.c linux-2.4.34-wt1-ctt206/net/ipv4/ip_sockglue.c --- linux-2.4.34-wt1-ctt205/net/ipv4/ip_sockglue.c Sat Feb 17 20:06:30 2007 +++ linux-2.4.34-wt1-ctt206/net/ipv4/ip_sockglue.c Sat Feb 17 20:18:20 2007 @@ -117,7 +117,7 @@ /* don't return original addresses if they were not set by tproxy*/ if (IPCB(skb)->orig_dstaddr == 0 || IPCB(skb)->orig_dstport == 0) return; - + ioa.ioa_srcaddr.s_addr = IPCB(skb)->orig_srcaddr; ioa.ioa_srcport = IPCB(skb)->orig_srcport; ioa.ioa_dstaddr.s_addr = IPCB(skb)->orig_dstaddr; @@ -415,7 +415,7 @@ (1<nat.info; unsigned int hs, hp; - + if (!info->initialized) return; @@ -172,7 +172,7 @@ { DEBUGP("reserved_manip_cmp: manip proto %u %u.%u.%u.%u:%u, " "reservation proto %u %u.%u.%u.%u:%u\n peer %u.%u.%u.%u:%u\n", - proto, NIPQUAD(manip->ip), ntohs(manip->u.all), + proto, NIPQUAD(manip->ip), ntohs(manip->u.all), i->proto, NIPQUAD(i->manip.ip), ntohs(i->manip.u.all), NIPQUAD(i->peer.ip), ntohs(i->peer.u.all)); return (i->proto == proto && @@ -321,7 +321,7 @@ .ip = manip->ip, .u = {.all = manip->u.all}}}; - h = ip_conntrack_tuple_taken(&t, NULL); + h = ip_conntrack_find_get(&t, NULL); #if defined(CONFIG_IP_NF_TPROXY) || defined (CONFIG_IP_NF_TPROXY_MODULE) if ((h != NULL) && test_bit(IPS_MAY_DELETE_BIT, &h->ctrack->status)) { @@ -330,12 +330,14 @@ h->ctrack->nat.info.initialized = 0; if (del_timer(&h->ctrack->timeout)) h->ctrack->timeout.function((unsigned long)h->ctrack); + ip_conntrack_put(h->ctrack); h = NULL; } #endif if (h) { DEBUGP("__ip_nat_reserved_new_hash: manip clashes with an already existing connection\n"); + ip_conntrack_put(h->ctrack); return NULL; } } else { @@ -415,7 +417,7 @@ /* append to the per-expectation reserved list */ list_append(&expect->reserved_list, &res->exp); - + return 1; } @@ -516,28 +518,32 @@ } /* Unregister all reservations for a given expectation */ -void -ip_nat_reserved_unregister_all(struct ip_conntrack_expect *expect) +static void +__reserved_unregister_all(struct ip_conntrack_expect *expect) { - struct list_head *i; - struct ip_nat_reserved *res; + struct ip_nat_reserved *res, *_res; DEBUGP("ip_nat_reserved_unregister_all: deleting all reservations for expectation %p\n", expect); - WRITE_LOCK(&ip_nat_lock); - - i = expect->reserved_list.next; - while (i != &expect->reserved_list) { - res = list_entry(i, struct ip_nat_reserved, exp); - i = i->next; - + list_for_each_entry_safe(res, _res, &expect->reserved_list, exp) { /* clear from lists */ list_del(&res->hash); list_del(&res->exp); kmem_cache_free(ip_nat_reserved_cachep, res); } +} + +void +ip_nat_reserved_unregister_all(struct ip_conntrack_expect *expect) +{ + if (list_empty(&expect->reserved_list)) + return; + + WRITE_LOCK(&ip_nat_lock); + + __reserved_unregister_all(expect); WRITE_UNLOCK(&ip_nat_lock); } @@ -547,6 +553,23 @@ { ip_nat_reserved_unregister_all(expect); } + +static void +__cleanup_expect_reservations(struct ip_conntrack *ct) +{ + struct ip_conntrack_expect *exp; + + DEBUGP("__cleanup_expect_reservations\n"); + + MUST_BE_WRITE_LOCKED(&ip_nat_lock); + MUST_BE_READ_LOCKED(&ip_conntrack_lock); + + /* iterate through expectations */ + list_for_each_entry(exp, &ct->sibling_list, expected_list) { + /* delete reservations for expectations */ + __reserved_unregister_all(exp); + } +} #endif /* CONFIG_IP_NF_NAT_NRES */ /* Is this tuple already taken? (not by us) */ @@ -578,19 +601,33 @@ /* check if it's taken by an existing connection */ invert_tuplepr(&reply, tuple); - h = ip_conntrack_tuple_taken(&reply, ignored_conntrack); + h = ip_conntrack_find_get(&reply, ignored_conntrack); #if defined(CONFIG_IP_NF_TPROXY) || defined (CONFIG_IP_NF_TPROXY_MODULE) /* check if that conntrack is marked MAY_DELETE, if so, get rid of it... */ if ((h != NULL) && test_bit(IPS_MAY_DELETE_BIT, &h->ctrack->status)) { DEBUGP("Deleting old conntrack entry for NAT\n"); + + /* avoid calling NAT cleanup during destroy_conntrack() */ __ip_nat_cleanup_conntrack(h->ctrack); h->ctrack->nat.info.initialized = 0; + + /* freeing the reservations during expectation cleanup would + * lock ip_nat_lock again so this is tricky, too */ + READ_LOCK(&ip_conntrack_lock); + __cleanup_expect_reservations(h->ctrack); + READ_UNLOCK(&ip_conntrack_lock); + + /* delete the usual way */ if (del_timer(&h->ctrack->timeout)) h->ctrack->timeout.function((unsigned long)h->ctrack); + ip_conntrack_put(h->ctrack); h = NULL; } #endif + + if (h != NULL) + ip_conntrack_put(h->ctrack); return h != NULL; } diff -urN linux-2.4.34-wt1-ctt205/net/ipv4/netfilter/ipt_tproxy.c linux-2.4.34-wt1-ctt206/net/ipv4/netfilter/ipt_tproxy.c --- linux-2.4.34-wt1-ctt205/net/ipv4/netfilter/ipt_tproxy.c Sat Feb 17 20:06:30 2007 +++ linux-2.4.34-wt1-ctt206/net/ipv4/netfilter/ipt_tproxy.c Sat Feb 17 20:18:20 2007 @@ -28,7 +28,7 @@ { enum ip_conntrack_info ctinfo; struct ip_conntrack *ct; - + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); if (ct) return ct->status & IPS_TPROXY; diff -urN linux-2.4.34-wt1-ctt205/net/ipv4/netfilter/iptable_tproxy.c linux-2.4.34-wt1-ctt206/net/ipv4/netfilter/iptable_tproxy.c --- linux-2.4.34-wt1-ctt205/net/ipv4/netfilter/iptable_tproxy.c Sat Feb 17 20:06:30 2007 +++ linux-2.4.34-wt1-ctt206/net/ipv4/netfilter/iptable_tproxy.c Sat Feb 17 20:18:20 2007 @@ -55,7 +55,7 @@ #define TPROXY_MAJOR_VERSION 2 #define TPROXY_MINOR_VERSION 0 -#define TPROXY_PATCH_VERSION 5 +#define TPROXY_PATCH_VERSION 6 #define TPROXY_FULL_VERSION ((TPROXY_MAJOR_VERSION << 24) | \ (TPROXY_MINOR_VERSION << 16) | \ @@ -145,7 +145,7 @@ #define TF_NAT_ONCE 0x00000001 /* this entry is applied only once */ #define TF_LISTEN 0x00000002 /* this entry is meant for listening */ #define TF_CONNECT 0x00000004 /* this entry is meant for connecting */ -#define TF_UNIDIR 0x00000008 /* this entry is a listening UDP socket, +#define TF_UNIDIR 0x00000008 /* this entry is a listening UDP socket, and only an unidirectional nat is to be applied */ /* state flags */ @@ -170,28 +170,28 @@ struct ip_tproxy_sockref *sockref; }; -struct ip_tproxy_sockref +struct ip_tproxy_sockref { int flags; atomic_t references; - + u8 proto; /* foreign address associated with a local socket */ u32 faddr; u16 fport; - + /* local socket address */ u32 laddr; u16 lport; - + /* remote addresses, needed for datagram protocols when the peer * sends the packet triggering the NAT translation. (as there might * be multiple sockrefs on the same foreign address). */ u32 raddr; u16 rport; - + /* hash chains indexed by local and foreign addresses */ struct ip_tproxy_hash bylocal, byforeign; @@ -227,7 +227,7 @@ static u32 ip_tproxy_hash_fn(u32 addr, u16 port, u8 proto) { - return ntohl(addr + (port<<8) + proto) % ip_tproxy_htable_size; + return ntohl(addr + (port<<8) + proto) % ip_tproxy_htable_size; } /* allocate memory and initialize a sockref structure */ @@ -235,7 +235,7 @@ ip_tproxy_sockref_new(void) { struct ip_tproxy_sockref *sr; - + sr = kmem_cache_alloc(ip_tproxy_sockref_table, GFP_ATOMIC); atomic_set(&sr->references, 1); sr->bylocal.sockref = sr; @@ -272,7 +272,7 @@ { u32 fhash = ip_tproxy_hash_fn(sr->faddr, sr->fport, sr->proto); u32 lhash = ip_tproxy_hash_fn(sr->laddr, sr->lport, sr->proto); - + sr->flags |= TF_HASHED; sr->tv_hashed = xtime; @@ -283,7 +283,7 @@ sr->lport, sr->faddr, sr->fport); ip_tproxy_sockref_ref(sr); - + list_append(&ip_tproxy_bylocal[lhash], &sr->bylocal); list_append(&ip_tproxy_byforeign[fhash], &sr->byforeign); ip_tproxy_htable_count++; @@ -297,7 +297,7 @@ DEBUGP(KERN_DEBUG "IP_TPROXY: ip_tproxy_hash(): unhashing sockref, " "%p, %02x, %08x:%04x -> %08x:%04x\n", sr, sr->proto, sr->laddr, sr->lport, sr->faddr, sr->fport); - + if (sr->flags & TF_HASHED) { list_del(&sr->bylocal.list); list_del(&sr->byforeign.list); @@ -307,7 +307,7 @@ } else { printk(KERN_WARNING "IP_TPROXY: unhashing a sockref which was " - "not hashed before, %p, flags=%x\n", + "not hashed before, %p, flags=%x\n", sr, sr->flags); } } @@ -420,7 +420,7 @@ ((rport == 0) || (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all == rport)); } -/* delete matching related connections from the sockref's list and delete them from +/* delete matching related connections from the sockref's list and delete them from * the conntrack hash if requested */ static void ip_tproxy_kill_related(struct ip_tproxy_sockref *sr, u32 raddr, u16 rport, @@ -431,7 +431,7 @@ struct ip_conntrack *ct, *p; spin_lock_bh(&sr->relatedlock); - + list_for_each_entry_safe(ct, p, &sr->relatedct, tproxy.related) { /* if a compare function was given, don't delete unmatched entries */ if (cmpfn && !cmpfn(sr, raddr, rport, ct)) @@ -574,7 +574,7 @@ DEBUGP(KERN_DEBUG "IP_TPROXY: sockref_cmpfn_local(): sr: %08x:%04x " "(foreign: %08x:%04x remote: %08x:%04x), searched: " - "%08x:%04x (remote: %08x:%04x)\n", + "%08x:%04x (remote: %08x:%04x)\n", sr->laddr, sr->lport, sr->faddr, sr->fport, sr->raddr, sr->rport, addr, port, raddr, rport); @@ -597,7 +597,7 @@ } } } - + return best; } @@ -619,7 +619,7 @@ DEBUGP(KERN_DEBUG "IP_TPROXY: sockref_cmpfn_foreign(): sr: %08x:%04x " "(remote: %08x:%04x), searched: %08x:%04x " - "(remote: %08x:%04x)\n", + "(remote: %08x:%04x)\n", sr->faddr, sr->fport, sr->raddr, sr->rport, addr, port, raddr, rport); if (sr->faddr == addr && sr->fport == port && sr->proto == proto) { @@ -666,12 +666,12 @@ { struct in_device *indev; u32 ip; - + if (hooknum == NF_IP_LOCAL_OUT) - return htonl(0x7f000001); - + return htonl(0x7f000001); + indev = in_dev_get(skb->dev); - + if (!indev) { printk(KERN_WARNING "IP_TPROXY: No IP protocol on incoming " "interface during redirect, dropping packet.\n"); @@ -683,10 +683,10 @@ in_dev_put(indev); return 0; } - + ip = indev->ifa_list->ifa_local; in_dev_put(indev); - + return ip; } @@ -700,26 +700,26 @@ u32 newip = 0; u16 newport = 0; int res, initialized = info->initialized; - + if (is_confirmed(ct) || (initialized & (1 << HOOK2MANIP(hooknum)))) { return NF_ACCEPT; } - + DEBUGP(KERN_DEBUG "IP_TPROXY: ip_tproxy_setup_nat(): adding nat " "entry hooknum=%d %08x:%04x -> %08x:%04x\n", hooknum, sr->laddr, sr->lport, sr->faddr, sr->fport); mr.rangesize = 1; mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_BYPASS_HELPERS; - + if (hooknum == NF_IP_POST_ROUTING) { /* in POSTROUTING we perform an SNAT to the foreign address */ newip = sr->faddr; newport = sr->fport; - } + } else if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT) { /* in PREROUTING and LOCAL_OUT we perform a DNAT to our socket address */ - + newip = sr->laddr; newport = sr->lport; } @@ -741,7 +741,7 @@ mr.range[0].flags |= IP_NAT_RANGE_USE_RESERVED; #endif } - + MUST_BE_READ_WRITE_UNLOCKED(&ip_nat_lock); WRITE_LOCK(&ip_nat_lock); @@ -785,13 +785,13 @@ u32 newip = 0; u16 newport = 0; struct ip_conntrack_manip manip; - + /* free the original conntrack entry, and assign the fake one */ nf_conntrack_put(skb->nfct); skb->nfct = &ip_tproxy_fake_ct.infos[IP_CT_NEW]; nf_conntrack_get(skb->nfct); skb->nfcache = NFC_ALTERED; - + /* this is our own conntrack entry now */ if (hooknum == NF_IP_POST_ROUTING) { @@ -799,19 +799,19 @@ newip = sr->faddr; newport = sr->fport; manip_type = IP_NAT_MANIP_SRC; - } + } else if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT) { /* in PREROUTING and LOCAL_OUT we perform a DNAT to our socket address */ - + newip = sr->laddr; newport = sr->lport; manip_type = IP_NAT_MANIP_DST; } - else + else return NF_DROP; manip.ip = newip; manip.u.udp.port = newport; - + /* manipulate packet "by hand" */ READ_LOCK(&ip_nat_lock); /* if the skb is cloned, create a copy before modifying */ @@ -834,11 +834,11 @@ static int ip_tproxy_setup_nat(struct sk_buff **pskb, int hooknum, struct ip_tproxy_sockref *sr, unsigned int flags) { - + if (sr->proto == IPPROTO_TCP || (flags & TN_BIDIR)) { struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; - + ct = ip_conntrack_get(*pskb, &ctinfo); return ip_tproxy_setup_nat_bidir(ct, hooknum, sr, flags); } @@ -851,9 +851,9 @@ static void ip_tproxy_save_orig_addrs(struct sk_buff *skb) { - struct iphdr *iph = skb->nh.iph; + struct iphdr *iph = skb->nh.iph; u16 tports[2]; - + if (skb_copy_bits(skb, iph->ihl * 4, &tports, sizeof(u16) * 2) >= 0) { IPCB(skb)->orig_srcaddr = iph->saddr; IPCB(skb)->orig_srcport = tports[0]; @@ -875,7 +875,7 @@ unsigned int verdict = NF_ACCEPT; ct = ip_conntrack_get(*pskb, &ctinfo); - + if (ct && ctinfo == IP_CT_NEW) { struct iphdr *iph = (*pskb)->nh.iph; u16 tports[2]; @@ -886,7 +886,7 @@ "failed to copy protocol header\n"); return NF_DROP; } - + DEBUGP(KERN_DEBUG "IP_TPROXY: ip_tproxy_fn(): new connection, " "hook=%d, %08x:%04x -> %08x:%04x\n", hooknum, iph->saddr, tports[0], iph->daddr, tports[1]); @@ -894,8 +894,8 @@ ip_tproxy_save_orig_addrs(*pskb); READ_LOCK(&ip_tproxy_lock); if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT) { - - /* + + /* * We either received a connection from the network (PREROUTING case) * or a local process generated one (LOCAL_OUT case). * @@ -904,15 +904,15 @@ * * As a special case we check in LOCAL_OUT whether the * connection was initiated by a local proxy, and if it - * was we mark the connection as such and skip the + * was we mark the connection as such and skip the * tproxy table. */ - + /* destination address is interesting */ - + sr = ip_tproxy_sockref_find_foreign(iph->daddr, tports[1], iph->protocol, iph->saddr, tports[0]); - + if (sr && sr->flags & TF_ORPHAN) { /* This sockref is orphaned, the listening socket is already unassigned, * so it should not be used for setting up NAT for a new connection. */ @@ -925,8 +925,8 @@ sr = NULL; } - if (hooknum == NF_IP_LOCAL_OUT && - !sr && + if (hooknum == NF_IP_LOCAL_OUT && + !sr && (sr = ip_tproxy_sockref_find_local(iph->saddr, tports[0], iph->protocol, 1, iph->daddr, tports[1]))) { @@ -937,7 +937,7 @@ } } else if (hooknum == NF_IP_POST_ROUTING) { - + /* * We detected a new connection just leaving this box, so * we now have a chance to add a translation changing @@ -947,9 +947,9 @@ * * A proxy registered an entry if find_local returns non-NULL. */ - + /* source address is interesting */ - + sr = ip_tproxy_sockref_find_local(iph->saddr, tports[0], iph->protocol, 1, iph->daddr, tports[1]); if (sr && (sr->flags & (TF_CONNECT|TF_MARK_ONLY)) == 0) { @@ -964,10 +964,10 @@ "NF_IP_LOCAL_OUT, hooknum=%d\n", hooknum); verdict = NF_DROP; } - - /* + + /* * sockref will not be freed, as the hash is read locked here - * and by the time we unlock it we own a reference + * and by the time we unlock it we own a reference */ if (sr) { @@ -995,13 +995,13 @@ } } READ_UNLOCK(&ip_tproxy_lock); - + DEBUGP(KERN_DEBUG "IP_TPROXY: ip_tproxy_fn(): sockref looked up, sr=%p\n", sr); if (sr) { - + /* sockref found it is a real translation as * MARK_ONLY was handled above so we apply the - * necessary NAT function + * necessary NAT function */ /* apply NAT mapping */ @@ -1020,35 +1020,35 @@ /* drop reference */ ip_tproxy_sockref_unref(sr); } /* if (sr) */ - else if (!test_bit(IPS_TPROXY_BIT, &ct->status) && + else if (!test_bit(IPS_TPROXY_BIT, &ct->status) && (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT)) { - struct ipt_tproxy_user_info ui; - - /* there was no matching sockref, so we consult the - * TPROXY table - */ - + struct ipt_tproxy_user_info ui; + + /* there was no matching sockref, so we consult the + * TPROXY table + */ + ui.changed = 0; verdict = ipt_do_table(pskb, hooknum, in, out, &tproxy_table, &ui); if (ui.changed && verdict == NF_ACCEPT) { - struct ip_tproxy_sockref sr; - u32 laddr; - u16 lport; - - /* packet was redirected */ + struct ip_tproxy_sockref sr; + u32 laddr; + u16 lport; + + /* packet was redirected */ if (ui.lport == 0) lport = tports[1]; else lport = ui.lport; - + if (ui.laddr == 0) laddr = ip_tproxy_determine_local_ip(*pskb, hooknum); else laddr = ui.laddr; - + memset(&sr, 0, sizeof(sr)); - + DEBUGP(KERN_DEBUG "IP_TPROXY: performing redirect to %08x:%04x\n", sr.laddr, sr.lport); @@ -1060,7 +1060,7 @@ } } } - + return verdict; } @@ -1074,9 +1074,9 @@ if (sk->prot == NULL || sk->prot->name == NULL) return 0; - + if (strcmp(sk->prot->name, "TCP") == 0) - return IPPROTO_TCP; + return IPPROTO_TCP; else if (strcmp(sk->prot->name, "UDP") == 0) return IPPROTO_UDP; else @@ -1138,7 +1138,7 @@ static int ip_tproxy_port_rover = 0; MUST_BE_WRITE_LOCKED(&ip_tproxy_lock); - + DEBUGP(KERN_DEBUG "IP_TPROXY: ip_tproxy_sockref_uniq\n"); min = sysctl_local_port_range[0]; max = sysctl_local_port_range[1]; @@ -1234,14 +1234,14 @@ the same socket while keeping the 'mark as tproxy' packet mechanism. - Maybe we should assign sockrefs to the struct sock * + Maybe we should assign sockrefs to the struct sock * address instead. */ if (sr) { if (itp->v.addr.faddr.s_addr || itp->v.addr.fport) { printk("IP_TPROXY: socket already assigned, reuse=%d, " "%08x:%04x, sr->faddr=%08x:%04x, flags=%x, " - "sr->tv_hashed=%ld:%ld\n", sk->reuse, + "sr->tv_hashed=%ld:%ld\n", sk->reuse, sk->rcv_saddr, sk->sport, sr->faddr, sr->fport, sr->flags, sr->tv_hashed.tv_sec, sr->tv_hashed.tv_usec); res = -EEXIST; @@ -1294,7 +1294,7 @@ /* we store the local address as foreign as well * for mark only connections, so find_foreign * finds this entry as well */ - + sr->flags |= TF_MARK_ONLY; sr->faddr = sr->laddr; sr->fport = sr->lport; @@ -1345,7 +1345,7 @@ WRITE_LOCK(&ip_tproxy_lock); /* here we should check if we've won the race: if a sockref is in the * local hash by the time we acquired the write lock, we've lost */ - if (!(tsr = ip_tproxy_sockref_find_local(sk->rcv_saddr, + if (!(tsr = ip_tproxy_sockref_find_local(sk->rcv_saddr, sk->sport, proto, 0, 0, 0))) ip_tproxy_hash(sr); WRITE_UNLOCK(&ip_tproxy_lock); @@ -1543,7 +1543,7 @@ } /* Set TF_NAT_ONCE and TF_UNIDIR if needed */ - sr->flags |= (flags & ITP_ONCE ? TF_NAT_ONCE : 0) | + sr->flags |= (flags & ITP_ONCE ? TF_NAT_ONCE : 0) | (flags & ITP_UNIDIR ? TF_UNIDIR : 0); #ifdef CONFIG_IP_NF_NAT_NRES @@ -1562,7 +1562,7 @@ write_unlk: WRITE_UNLOCK(&ip_tproxy_lock); - + return res; } @@ -1655,7 +1655,7 @@ return res; } -static int +static int ip_tproxy_setsockopt(struct sock *sk, int optval, void *user, unsigned int len) { int proto; @@ -1666,12 +1666,12 @@ /* get protocol number of the socket */ if ((proto = ip_tproxy_get_sk_proto(sk)) == 0) return -EINVAL; - + if (len < sizeof(itp.op) + sizeof(itp.v.version)) return -EINVAL; mlen = MIN(sizeof(itp), len); - + if (copy_from_user(&itp, user, mlen)) return -EFAULT; @@ -1700,7 +1700,7 @@ } return res; -} +} static int ip_tproxy_getsockopt_version(struct sock *sk, int proto, struct in_tproxy *itp) @@ -1722,7 +1722,7 @@ sk->rcv_saddr, sk->sport); READ_LOCK(&ip_tproxy_lock); - + sr = ip_tproxy_sockref_find_local(sk->rcv_saddr, sk->sport, proto, 0, sk->daddr, sk->dport); if (sr) { @@ -1745,7 +1745,7 @@ u_int32_t flags; struct ip_tproxy_sockref *sr; - DEBUGP(KERN_DEBUG "IP_TPROXY: IP_TPROXY_FLAGS get %08x:%04x\n", + DEBUGP(KERN_DEBUG "IP_TPROXY: IP_TPROXY_FLAGS get %08x:%04x\n", sk->rcv_saddr, sk->sport); READ_LOCK(&ip_tproxy_lock); @@ -1756,7 +1756,7 @@ res = -ENOENT; goto read_unlk; } - + flags = 0; if ((sr->flags & (TF_CONNECT+TF_LISTEN)) == (TF_CONNECT+TF_LISTEN)) flags |= ITP_ESTABLISHED; @@ -1785,7 +1785,7 @@ return res; } -static int +static int ip_tproxy_getsockopt(struct sock *sk, int optval, void *user, int *len) { int proto; @@ -1825,7 +1825,7 @@ res = -EFAULT; return res; -} +} /* callback function: called when a socket gets unhashed by the UDP or TCP * stack */ @@ -1843,27 +1843,27 @@ { printk("IP_TPROXY: Fake timeout called!"); } - -static struct nf_hook_ops ip_tproxy_pre_ops = + +static struct nf_hook_ops ip_tproxy_pre_ops = { { NULL, NULL }, ip_tproxy_fn, PF_INET, NF_IP_PRE_ROUTING, -130 }; -static struct nf_hook_ops ip_tproxy_post_ops = +static struct nf_hook_ops ip_tproxy_post_ops = { { NULL, NULL }, ip_tproxy_fn, PF_INET, NF_IP_POST_ROUTING, -130 }; -static struct nf_hook_ops ip_tproxy_local_out_ops = +static struct nf_hook_ops ip_tproxy_local_out_ops = { { NULL, NULL }, ip_tproxy_fn, PF_INET, NF_IP_LOCAL_OUT, -130 }; - -static struct nf_sockopt_ops ip_tproxy_sockopts = -{ { NULL, NULL }, PF_INET, + +static struct nf_sockopt_ops ip_tproxy_sockopts = +{ { NULL, NULL }, PF_INET, IP_TPROXY, IP_TPROXY+1, ip_tproxy_setsockopt, - IP_TPROXY, IP_TPROXY+1, ip_tproxy_getsockopt, + IP_TPROXY, IP_TPROXY+1, ip_tproxy_getsockopt, 0, NULL }; /* init or cleanup the tproxy module */ -static int +static int init_or_cleanup(int startup) { int ret = 0; @@ -1890,17 +1890,17 @@ ip_tproxy_sockref_table = kmem_cache_create("ip_tproxy", sizeof(struct ip_tproxy_sockref), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - + if (!ip_tproxy_sockref_table) { ret = -ENOMEM; goto clean_nothing; } - + if (hashsize) ip_tproxy_htable_size = hashsize; else ip_tproxy_htable_size = 127; - + ip_tproxy_bylocal = (struct list_head *) vmalloc(sizeof(struct list_head) * ip_tproxy_htable_size * 2); if (!ip_tproxy_bylocal) { @@ -1917,13 +1917,13 @@ proc = proc_net_create("tproxy", 0, NULL); if (!proc) goto clean_sockref_hash; proc->proc_fops = &ip_tproxy_file_ops; - + ret = ipt_register_table(&tproxy_table); if (ret < 0) { printk("IP_TPROXY: can't register tproxy table.\n"); goto clean_proc; } - + ret = nf_register_hook(&ip_tproxy_local_out_ops); if (ret < 0) { printk("IP_TPROXY: can't register local out hook.\n"); @@ -1952,8 +1952,8 @@ ip_conntrack_destroyed_old = ip_conntrack_destroyed; ip_conntrack_destroyed = ip_tproxy_conntrack_destroyed; - printk("IP_TPROXY: Transparent proxy support initialized 2.0.5\n" - "IP_TPROXY: Copyright (c) 2002-2006 BalaBit IT Ltd.\n"); + printk("IP_TPROXY: Transparent proxy support initialized 2.0.6\n" + "IP_TPROXY: Copyright (c) 2002-2007 BalaBit IT Ltd.\n"); return ret; clean_all: @@ -1962,7 +1962,7 @@ ip_conntrack_destroyed = ip_conntrack_destroyed_old; ip_conntrack_confirmed = NULL; - ip_tproxy_udp_unhashed = NULL; + ip_tproxy_udp_unhashed = NULL; ip_tproxy_tcp_unhashed = NULL; nf_unregister_hook(&ip_tproxy_pre_ops); @@ -1982,10 +1982,10 @@ clean_sockref_hash: ip_tproxy_sockref_table_free(); vfree(ip_tproxy_bylocal); - + clean_sockref_table: - kmem_cache_destroy(ip_tproxy_sockref_table); - + kmem_cache_destroy(ip_tproxy_sockref_table); + clean_nothing: return ret; }