netfilter-2.6/patch-o-matic-ng/trunk/net: Kconfig core/skbuff.c
ipv4/ip_input.c ipv4/ip_output.c ipv...
pluto
cvs at pld-linux.org
Sat Jun 18 16:44:03 CEST 2005
Author: pluto
Date: Sat Jun 18 16:43:43 2005
New Revision: 6146
Added:
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c.orig
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c.rej
Modified:
netfilter-2.6/patch-o-matic-ng/trunk/net/Kconfig
netfilter-2.6/patch-o-matic-ng/trunk/net/core/skbuff.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/ip_input.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/ip_output.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/arp_tables.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_core.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_ftp.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_irc.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_standalone.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_queue.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_tables.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_LOG.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_REJECT.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_TCPMSS.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_hashlimit.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_osf.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ip6_input.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ip6_output.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ipv6_syms.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Kconfig
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/ip6_queue.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/ip6_tables.c
Log:
- 2.6.12 merged, nfy (1 reject needs manual merge).
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/Kconfig
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/Kconfig (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/Kconfig Sat Jun 18 16:43:43 2005
@@ -45,15 +45,6 @@
If unsure, say N.
-config NETLINK_DEV
- tristate "Netlink device emulation"
- help
- This option will be removed soon. Any programs that want to use
- character special nodes like /dev/tap0 or /dev/route (all with major
- number 36) need this option, and need to be rewritten soon to use
- the real netlink socket.
- This is a backward compatibility option, choose Y for now.
-
config UNIX
tristate "Unix domain sockets"
---help---
@@ -107,28 +98,24 @@
# IPv6 as module will cause a CRASH if you try to unload it
config IPV6
- tristate "The IPv6 protocol (EXPERIMENTAL)"
- depends on INET && EXPERIMENTAL
+ tristate "The IPv6 protocol"
+ depends on INET
+ default m
select CRYPTO if IPV6_PRIVACY
select CRYPTO_MD5 if IPV6_PRIVACY
---help---
- This is experimental support for the IP version 6 (formerly called
- IPng "IP next generation"). You will still be able to do
- regular IPv4 networking as well.
-
- Features of this new protocol include: expanded address space,
- authentication and privacy, and seamless interoperability with the
- current version of IP (IP version 4). For general information about
- IPv6, see <http://playground.sun.com/pub/ipng/html/ipng-main.html>;
- for specific information about IPv6 under Linux read the HOWTO at
- <http://www.bieringer.de/linux/IPv6/> and the file net/ipv6/README
- in the kernel source.
+ This is complemental support for the IP version 6.
+ You will still be able to do traditional IPv4 networking as well.
+
+ For general information about IPv6, see
+ <http://playground.sun.com/pub/ipng/html/ipng-main.html>.
+ For Linux IPv6 development information, see <http://www.linux-ipv6.org>.
+ For specific information about IPv6 under Linux, read the HOWTO at
+ <http://www.bieringer.de/linux/IPv6/>.
To compile this protocol support as a module, choose M here: the
module will be called ipv6.
- It is safe to say N here for now.
-
source "net/ipv6/Kconfig"
menuconfig NETFILTER
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/core/skbuff.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/core/skbuff.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/core/skbuff.c Sat Jun 18 16:43:43 2005
@@ -86,8 +86,10 @@
*/
void skb_over_panic(struct sk_buff *skb, int sz, void *here)
{
- printk(KERN_INFO "skput:over: %p:%d put:%d dev:%s",
- here, skb->len, sz, skb->dev ? skb->dev->name : "<NULL>");
+ printk(KERN_EMERG "skb_over_panic: text:%p len:%d put:%d head:%p "
+ "data:%p tail:%p end:%p dev:%s\n",
+ here, skb->len, sz, skb->head, skb->data, skb->tail, skb->end,
+ skb->dev ? skb->dev->name : "<NULL>");
BUG();
}
@@ -102,8 +104,10 @@
void skb_under_panic(struct sk_buff *skb, int sz, void *here)
{
- printk(KERN_INFO "skput:under: %p:%d put:%d dev:%s",
- here, skb->len, sz, skb->dev ? skb->dev->name : "<NULL>");
+ printk(KERN_EMERG "skb_under_panic: text:%p len:%d put:%d head:%p "
+ "data:%p tail:%p end:%p dev:%s\n",
+ here, skb->len, sz, skb->head, skb->data, skb->tail, skb->end,
+ skb->dev ? skb->dev->name : "<NULL>");
BUG();
}
@@ -241,7 +245,8 @@
void skb_release_data(struct sk_buff *skb)
{
if (!skb->cloned ||
- atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) {
+ !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
+ &skb_shinfo(skb)->dataref)) {
if (skb_shinfo(skb)->nr_frags) {
int i;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
@@ -275,20 +280,14 @@
void __kfree_skb(struct sk_buff *skb)
{
- if (skb->list) {
- printk(KERN_WARNING "Warning: kfree_skb passed an skb still "
- "on a list (from %p).\n", NET_CALLER(skb));
- BUG();
- }
+ BUG_ON(skb->list != NULL);
dst_release(skb->dst);
#ifdef CONFIG_XFRM
secpath_put(skb->sp);
#endif
- if(skb->destructor) {
- if (in_irq())
- printk(KERN_WARNING "Warning: kfree_skb on "
- "hard IRQ %p\n", NET_CALLER(skb));
+ if (skb->destructor) {
+ WARN_ON(in_irq());
skb->destructor(skb);
}
#ifdef CONFIG_NETFILTER
@@ -356,6 +355,7 @@
C(csum);
C(local_df);
n->cloned = 1;
+ n->nohdr = 0;
C(pkt_type);
C(ip_summed);
C(priority);
@@ -615,6 +615,7 @@
skb->h.raw += off;
skb->nh.raw += off;
skb->cloned = 0;
+ skb->nohdr = 0;
atomic_set(&skb_shinfo(skb)->dataref, 1);
return 0;
@@ -993,70 +994,94 @@
return -EFAULT;
}
-/* Keep iterating until skb_iter_next returns false. */
-void skb_iter_first(const struct sk_buff *skb, struct skb_iter *i)
+/**
+ * skb_store_bits - store bits from kernel buffer to skb
+ * @skb: destination buffer
+ * @offset: offset in destination
+ * @from: source buffer
+ * @len: number of bytes to copy
+ *
+ * Copy the specified number of bytes from the source buffer to the
+ * destination skb. This function handles all the messy bits of
+ * traversing fragment lists and such.
+ */
+
+int skb_store_bits(const struct sk_buff *skb, int offset, void *from, int len)
{
- i->len = skb_headlen(skb);
- i->data = (unsigned char *)skb->data;
- i->nextfrag = 0;
- i->fraglist = NULL;
-}
-
-int skb_iter_next(const struct sk_buff *skb, struct skb_iter *i)
-{
- /* Unmap previous, if not head fragment. */
- if (i->nextfrag)
- kunmap_skb_frag(i->data);
-
- if (i->fraglist) {
- fraglist:
- /* We're iterating through fraglist. */
- if (i->nextfrag < skb_shinfo(i->fraglist)->nr_frags) {
- i->data = kmap_skb_frag(&skb_shinfo(i->fraglist)
- ->frags[i->nextfrag]);
- i->len = skb_shinfo(i->fraglist)->frags[i->nextfrag]
- .size;
- i->nextfrag++;
- return 1;
+ int i, copy;
+ int start = skb_headlen(skb);
+
+ if (offset > (int)skb->len - len)
+ goto fault;
+
+ if ((copy = start - offset) > 0) {
+ if (copy > len)
+ copy = len;
+ memcpy(skb->data + offset, from, copy);
+ if ((len -= copy) == 0)
+ return 0;
+ offset += copy;
+ from += copy;
+ }
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ int end;
+
+ BUG_TRAP(start <= offset + len);
+
+ end = start + frag->size;
+ if ((copy = end - offset) > 0) {
+ u8 *vaddr;
+
+ if (copy > len)
+ copy = len;
+
+ vaddr = kmap_skb_frag(frag);
+ memcpy(vaddr + frag->page_offset + offset - start,
+ from, copy);
+ kunmap_skb_frag(vaddr);
+
+ if ((len -= copy) == 0)
+ return 0;
+ offset += copy;
+ from += copy;
}
- /* Fragments with fragments? Too hard! */
- BUG_ON(skb_shinfo(i->fraglist)->frag_list);
- i->fraglist = i->fraglist->next;
- if (!i->fraglist)
- goto end;
-
- i->len = skb_headlen(i->fraglist);
- i->data = i->fraglist->data;
- i->nextfrag = 0;
- return 1;
- }
-
- if (i->nextfrag < skb_shinfo(skb)->nr_frags) {
- i->data = kmap_skb_frag(&skb_shinfo(skb)->frags[i->nextfrag]);
- i->len = skb_shinfo(skb)->frags[i->nextfrag].size;
- i->nextfrag++;
- return 1;
- }
-
- i->fraglist = skb_shinfo(skb)->frag_list;
- if (i->fraglist)
- goto fraglist;
-
-end:
- /* Bug trap for callers */
- i->data = NULL;
- return 0;
-}
+ start = end;
+ }
-void skb_iter_abort(const struct sk_buff *skb, struct skb_iter *i)
-{
- /* Unmap previous, if not head fragment. */
- if (i->data && i->nextfrag)
- kunmap_skb_frag(i->data);
- /* Bug trap for callers */
- i->data = NULL;
+ if (skb_shinfo(skb)->frag_list) {
+ struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+ for (; list; list = list->next) {
+ int end;
+
+ BUG_TRAP(start <= offset + len);
+
+ end = start + list->len;
+ if ((copy = end - offset) > 0) {
+ if (copy > len)
+ copy = len;
+ if (skb_store_bits(list, offset - start,
+ from, copy))
+ goto fault;
+ if ((len -= copy) == 0)
+ return 0;
+ offset += copy;
+ from += copy;
+ }
+ start = end;
+ }
+ }
+ if (!len)
+ return 0;
+
+fault:
+ return -EFAULT;
}
+EXPORT_SYMBOL(skb_store_bits);
+
/* Checksum skb data. */
unsigned int skb_checksum(const struct sk_buff *skb, int offset,
@@ -1455,7 +1480,7 @@
if (pos < len) {
/* Split frag.
- * We have to variants in this case:
+ * We have two variants in this case:
* 1. Move all the frag to the second
* part, if it is possible. F.e.
* this approach is mandatory for TUX,
@@ -1478,6 +1503,9 @@
/**
* skb_split - Split fragmented skb to two parts at length len.
+ * @skb: the buffer to split
+ * @skb1: the buffer to receive the second part
+ * @len: new length for skb
*/
void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len)
{
@@ -1527,6 +1555,3 @@
EXPORT_SYMBOL(skb_unlink);
EXPORT_SYMBOL(skb_append);
EXPORT_SYMBOL(skb_split);
-EXPORT_SYMBOL(skb_iter_first);
-EXPORT_SYMBOL(skb_iter_next);
-EXPORT_SYMBOL(skb_iter_abort);
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/ip_input.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/ip_input.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/ip_input.c Sat Jun 18 16:43:43 2005
@@ -7,7 +7,7 @@
*
* Version: $Id: ip_input.c,v 1.55 2002/01/12 07:39:45 davem Exp $
*
- * Authors: Ross Biro, <bir7 at leland.Stanford.Edu>
+ * Authors: Ross Biro
* Fred N. van Kempen, <waltje at uWalt.NL.Mugnet.ORG>
* Donald Becker, <becker at super.org>
* Alan Cox, <Alan.Cox at linux.org>
@@ -410,10 +410,9 @@
* is IP we can trim to the true length of the frame.
* Note this now means skb->len holds ntohs(iph->tot_len).
*/
- if (skb->len > len) {
- __pskb_trim(skb, len);
- if (skb->ip_summed == CHECKSUM_HW)
- skb->ip_summed = CHECKSUM_NONE;
+ if (pskb_trim_rcsum(skb, len)) {
+ IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
+ goto drop;
}
}
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/ip_output.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/ip_output.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/ip_output.c Sat Jun 18 16:43:43 2005
@@ -7,7 +7,7 @@
*
* Version: $Id: ip_output.c,v 1.100 2002/02/01 22:01:03 davem Exp $
*
- * Authors: Ross Biro, <bir7 at leland.Stanford.Edu>
+ * Authors: Ross Biro
* Fred N. van Kempen, <waltje at uWalt.NL.Mugnet.ORG>
* Donald Becker, <becker at super.org>
* Alan Cox, <Alan.Cox at linux.org>
@@ -111,6 +111,7 @@
#ifdef CONFIG_NETFILTER_DEBUG
nf_debug_ip_loopback_xmit(newskb);
#endif
+ nf_reset(newskb);
netif_rx(newskb);
return 0;
}
@@ -195,6 +196,8 @@
nf_debug_ip_finish_output2(skb);
#endif /*CONFIG_NETFILTER_DEBUG*/
+ nf_reset(skb);
+
if (hh) {
int hh_alen;
@@ -278,7 +281,7 @@
newskb->dev, ip_dev_loopback_xmit);
}
- if (skb->len > dst_pmtu(&rt->u.dst))
+ if (skb->len > dst_mtu(&rt->u.dst))
return ip_fragment(skb, ip_finish_output);
else
return ip_finish_output(skb);
@@ -288,7 +291,7 @@
{
IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
- if (skb->len > dst_pmtu(skb->dst) && !skb_shinfo(skb)->tso_size)
+ if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->tso_size)
return ip_fragment(skb, ip_finish_output);
else
return ip_finish_output(skb);
@@ -448,7 +451,7 @@
if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) {
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
- htonl(dst_pmtu(&rt->u.dst)));
+ htonl(dst_mtu(&rt->u.dst)));
kfree_skb(skb);
return -EMSGSIZE;
}
@@ -458,7 +461,7 @@
*/
hlen = iph->ihl * 4;
- mtu = dst_pmtu(&rt->u.dst) - hlen; /* Size of data space */
+ mtu = dst_mtu(&rt->u.dst) - hlen; /* Size of data space */
/* When frag_list is given, use it. First, check its validity:
* some transformers could create wrong frag_list or break existing
@@ -487,6 +490,14 @@
/* Partially cloned skb? */
if (skb_shared(frag))
goto slow_path;
+
+ BUG_ON(frag->sk);
+ if (skb->sk) {
+ sock_hold(skb->sk);
+ frag->sk = skb->sk;
+ frag->destructor = sock_wfree;
+ skb->truesize -= frag->truesize;
+ }
}
/* Everything is OK. Generate! */
@@ -498,7 +509,7 @@
skb->data_len = first_len - skb_headlen(skb);
skb->len = first_len;
iph->tot_len = htons(first_len);
- iph->frag_off |= htons(IP_MF);
+ iph->frag_off = htons(IP_MF);
ip_send_check(iph);
for (;;) {
@@ -746,7 +757,7 @@
inet->cork.addr = ipc->addr;
}
dst_hold(&rt->u.dst);
- inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
+ inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path);
inet->cork.rt = rt;
inet->cork.length = 0;
sk->sk_sndmsg_page = NULL;
@@ -1152,7 +1163,8 @@
* If local_df is set too, we still allow to fragment this frame
* locally. */
if (inet->pmtudisc == IP_PMTUDISC_DO ||
- (!skb_shinfo(skb)->frag_list && ip_dont_fragment(sk, &rt->u.dst)))
+ (skb->len <= dst_mtu(&rt->u.dst) &&
+ ip_dont_fragment(sk, &rt->u.dst)))
df = htons(IP_DF);
if (inet->cork.flags & IPCORK_OPT)
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/arp_tables.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/arp_tables.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/arp_tables.c Sat Jun 18 16:43:43 2005
@@ -717,7 +717,7 @@
}
/* And one copy for every other CPU */
- for (i = 1; i < NR_CPUS; i++) {
+ for (i = 1; i < num_possible_cpus(); i++) {
memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
newinfo->entries,
SMP_ALIGN(newinfo->size));
@@ -768,7 +768,7 @@
unsigned int cpu;
unsigned int i;
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
i = 0;
ARPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
t->size,
@@ -886,7 +886,7 @@
return -ENOMEM;
newinfo = vmalloc(sizeof(struct arpt_table_info)
- + SMP_ALIGN(tmp.size) * NR_CPUS);
+ + SMP_ALIGN(tmp.size) * num_possible_cpus());
if (!newinfo)
return -ENOMEM;
@@ -1159,7 +1159,7 @@
= { 0, 0, 0, { 0 }, { 0 }, { } };
newinfo = vmalloc(sizeof(struct arpt_table_info)
- + SMP_ALIGN(repl->size) * NR_CPUS);
+ + SMP_ALIGN(repl->size) * num_possible_cpus());
if (!newinfo) {
ret = -ENOMEM;
return ret;
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_core.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_core.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_core.c Sat Jun 18 16:43:43 2005
@@ -1032,37 +1032,25 @@
struct sk_buff *
ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
{
- struct sock *sk = skb->sk;
#ifdef CONFIG_NETFILTER_DEBUG
unsigned int olddebug = skb->nf_debug;
#endif
- if (sk) {
- sock_hold(sk);
- skb_orphan(skb);
- }
+ skb_orphan(skb);
local_bh_disable();
skb = ip_defrag(skb, user);
local_bh_enable();
- if (!skb) {
- if (sk)
- sock_put(sk);
- return skb;
- }
-
- if (sk) {
- skb_set_owner_w(skb, sk);
- sock_put(sk);
- }
-
- ip_send_check(skb->nh.iph);
- skb->nfcache |= NFC_ALTERED;
+ if (skb) {
+ ip_send_check(skb->nh.iph);
+ skb->nfcache |= NFC_ALTERED;
#ifdef CONFIG_NETFILTER_DEBUG
- /* Packet path as if nothing had happened. */
- skb->nf_debug = olddebug;
+ /* Packet path as if nothing had happened. */
+ skb->nf_debug = olddebug;
#endif
+ }
+
return skb;
}
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c Sat Jun 18 16:43:43 2005
@@ -252,7 +252,7 @@
}
/* Look up to see if we're just after a \n. */
-static int find_nl_seq(u16 seq, const struct ip_ct_ftp_master *info, int dir)
+static int find_nl_seq(u32 seq, const struct ip_ct_ftp_master *info, int dir)
{
unsigned int i;
@@ -263,7 +263,7 @@
}
/* We don't update if it's older than what we have. */
-static void update_nl_seq(u16 nl_seq, struct ip_ct_ftp_master *info, int dir,
+static void update_nl_seq(u32 nl_seq, struct ip_ct_ftp_master *info, int dir,
struct sk_buff *skb)
{
unsigned int i, oldest = NUM_SEQ_TO_REMEMBER;
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c Sat Jun 18 16:43:43 2005
@@ -400,8 +400,8 @@
return -1;
}
DEBUGP("Setting vtag %x for dir %d\n",
- ih->init_tag, CTINFO2DIR(ctinfo));
- conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = ih->init_tag;
+ ih->init_tag, !CTINFO2DIR(ctinfo));
+ conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag;
}
conntrack->proto.sctp.state = newconntrack;
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Sat Jun 18 16:43:43 2005
@@ -254,7 +254,7 @@
* sSS -> sSR Standard open.
* sSR -> sSR Retransmitted SYN/ACK.
* sES -> sIG Late retransmitted SYN/ACK?
- * sFW -> sIG
+ * sFW -> sIG Might be SYN/ACK answering ignored SYN
* sCW -> sIG
* sLA -> sIG
* sTW -> sIG
@@ -273,10 +273,10 @@
* sCL -> sCL
*/
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
-/*ack*/ { sIV, sIG, sIV, sES, sCW, sCW, sTW, sTW, sCL, sIV },
+/*ack*/ { sIV, sIV, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },
/*
- * sSS -> sIG Might be a half-open connection.
- * sSR -> sIV Simultaneous open.
+ * sSS -> sIV Might be a half-open connection.
+ * sSR -> sSR Might answer late resent SYN.
* sES -> sES :-)
* sFW -> sCW Normal close request answered by ACK.
* sCW -> sCW
@@ -352,14 +352,19 @@
http://www.nluug.nl/events/sane2000/papers.html
http://www.iae.nl/users/guido/papers/tcp_filtering.ps.gz
- The boundaries and the conditions are slightly changed:
-
+ The boundaries and the conditions are changed according to RFC793:
+ the packet must intersect the window (i.e. segments may be
+ after the right or before the left edge) and thus receivers may ACK
+ segments after the right edge of the window.
+
td_maxend = max(sack + max(win,1)) seen in reply packets
td_maxwin = max(max(win, 1)) + (sack - ack) seen in sent packets
+ td_maxwin += seq + len - sender.td_maxend
+ if seq + len > sender.td_maxend
td_end = max(seq + len) seen in sent packets
- I. Upper bound for valid data: seq + len <= sender.td_maxend
- II. Lower bound for valid data: seq >= sender.td_end - receiver.td_maxwin
+ I. Upper bound for valid data: seq <= sender.td_maxend
+ II. Lower bound for valid data: seq + len >= sender.td_end - receiver.td_maxwin
III. Upper bound for valid ack: sack <= receiver.td_end
IV. Lower bound for valid ack: ack >= receiver.td_end - MAXACKWINDOW
@@ -373,7 +378,7 @@
size_t len,
struct iphdr *iph,
struct tcphdr *tcph)
- {
+{
return (seq + len - (iph->ihl + tcph->doff)*4
+ (tcph->syn ? 1 : 0) + (tcph->fin ? 1 : 0));
}
@@ -444,22 +449,33 @@
}
}
-static void tcp_sack(struct tcphdr *tcph, __u32 *sack)
+static void tcp_sack(const struct sk_buff *skb,
+ struct iphdr *iph,
+ struct tcphdr *tcph,
+ __u32 *sack)
{
- __u32 tmp;
+ unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
unsigned char *ptr;
int length = (tcph->doff*4) - sizeof(struct tcphdr);
-
+ __u32 tmp;
+
+ if (!length)
+ return;
+
+ ptr = skb_header_pointer(skb,
+ (iph->ihl * 4) + sizeof(struct tcphdr),
+ length, buff);
+ BUG_ON(ptr == NULL);
+
/* Fast path for timestamp-only option */
if (length == TCPOLEN_TSTAMP_ALIGNED*4
- && *(__u32 *)(tcph + 1) ==
+ && *(__u32 *)ptr ==
__constant_ntohl((TCPOPT_NOP << 24)
| (TCPOPT_NOP << 16)
| (TCPOPT_TIMESTAMP << 8)
| TCPOLEN_TIMESTAMP))
return;
- ptr = (unsigned char *)(tcph + 1);
while (length > 0) {
int opcode=*ptr++;
int opsize, i;
@@ -500,7 +516,7 @@
static int tcp_in_window(struct ip_ct_tcp *state,
enum ip_conntrack_dir dir,
- unsigned int *index,
+ unsigned int index,
const struct sk_buff *skb,
struct iphdr *iph,
struct tcphdr *tcph)
@@ -519,7 +535,7 @@
end = segment_seq_plus_len(seq, skb->len, iph, tcph);
if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
- tcp_sack(tcph, &sack);
+ tcp_sack(skb, iph, tcph, &sack);
DEBUGP("tcp_in_window: START\n");
DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
@@ -598,20 +614,23 @@
ack = sack = receiver->td_end;
}
- if (seq == end)
+ if (seq == end
+ && (!tcph->rst
+ || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
/*
* Packets contains no data: we assume it is valid
* and check the ack value only.
+ * However RST segments are always validated by their
+ * SEQ number, except when seq == 0 (reset sent answering
+ * SYN.
*/
seq = end = sender->td_end;
DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
- "seq=%u ack=%u sack =%u win=%u end=%u trim=%u\n",
+ "seq=%u ack=%u sack =%u win=%u end=%u\n",
NIPQUAD(iph->saddr), ntohs(tcph->source),
NIPQUAD(iph->daddr), ntohs(tcph->dest),
- seq, ack, sack, win, end,
- after(end, sender->td_maxend) && before(seq, sender->td_maxend)
- ? sender->td_maxend : end);
+ seq, ack, sack, win, end);
DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
"receiver end=%u maxend=%u maxwin=%u scale=%i\n",
sender->td_end, sender->td_maxend, sender->td_maxwin,
@@ -619,24 +638,15 @@
receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
receiver->td_scale);
- /* Ignore data over the right edge of the receiver's window. */
- if (after(end, sender->td_maxend) &&
- before(seq, sender->td_maxend)) {
- end = sender->td_maxend;
- if (*index == TCP_FIN_SET)
- *index = TCP_ACK_SET;
- }
DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
- before(end, sender->td_maxend + 1)
- || before(seq, sender->td_maxend + 1),
- after(seq, sender->td_end - receiver->td_maxwin - 1)
- || after(end, sender->td_end - receiver->td_maxwin - 1),
+ before(seq, sender->td_maxend + 1),
+ after(end, sender->td_end - receiver->td_maxwin - 1),
before(sack, receiver->td_end + 1),
after(ack, receiver->td_end - MAXACKWINDOW(sender)));
if (sender->loose || receiver->loose ||
- (before(end, sender->td_maxend + 1) &&
- after(seq, sender->td_end - receiver->td_maxwin - 1) &&
+ (before(seq, sender->td_maxend + 1) &&
+ after(end, sender->td_end - receiver->td_maxwin - 1) &&
before(sack, receiver->td_end + 1) &&
after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
/*
@@ -653,6 +663,11 @@
sender->td_maxwin = swin;
if (after(end, sender->td_end))
sender->td_end = end;
+ /*
+ * Update receiver data.
+ */
+ if (after(end, sender->td_maxend))
+ receiver->td_maxwin += end - sender->td_maxend;
if (after(sack + win, receiver->td_maxend - 1)) {
receiver->td_maxend = sack + win;
if (win == 0)
@@ -662,7 +677,7 @@
/*
* Check retransmissions.
*/
- if (*index == TCP_ACK_SET) {
+ if (index == TCP_ACK_SET) {
if (state->last_dir == dir
&& state->last_seq == seq
&& state->last_ack == ack
@@ -687,16 +702,16 @@
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_tcp: %s ",
- before(end, sender->td_maxend + 1) ?
- after(seq, sender->td_end - receiver->td_maxwin - 1) ?
+ before(seq, sender->td_maxend + 1) ?
+ after(end, sender->td_end - receiver->td_maxwin - 1) ?
before(sack, receiver->td_end + 1) ?
after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG"
- : "ACK is under the lower bound (possibly overly delayed ACK)"
- : "ACK is over the upper bound (ACKed data has never seen yet)"
- : "SEQ is under the lower bound (retransmitted already ACKed data)"
+ : "ACK is under the lower bound (possible overly delayed ACK)"
+ : "ACK is over the upper bound (ACKed data not seen yet)"
+ : "SEQ is under the lower bound (already ACKed data retransmitted)"
: "SEQ is over the upper bound (over the window of the receiver)");
- res = ip_ct_tcp_be_liberal && !tcph->rst;
+ res = ip_ct_tcp_be_liberal;
}
DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
@@ -851,13 +866,12 @@
switch (new_state) {
case TCP_CONNTRACK_IGNORE:
/* Either SYN in ORIGINAL
- * or SYN/ACK in REPLY
- * or ACK in REPLY direction (half-open connection). */
+ * or SYN/ACK in REPLY. */
if (index == TCP_SYNACK_SET
&& conntrack->proto.tcp.last_index == TCP_SYN_SET
&& conntrack->proto.tcp.last_dir != dir
- && after(ntohl(th->ack_seq),
- conntrack->proto.tcp.last_seq)) {
+ && ntohl(th->ack_seq) ==
+ conntrack->proto.tcp.last_end) {
/* This SYN/ACK acknowledges a SYN that we earlier
* ignored as invalid. This means that the client and
* the server are both in sync, while the firewall is
@@ -877,6 +891,8 @@
conntrack->proto.tcp.last_index = index;
conntrack->proto.tcp.last_dir = dir;
conntrack->proto.tcp.last_seq = ntohl(th->seq);
+ conntrack->proto.tcp.last_end =
+ segment_seq_plus_len(ntohl(th->seq), skb->len, iph, th);
WRITE_UNLOCK(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP))
@@ -894,7 +910,12 @@
"ip_ct_tcp: invalid state ");
return -NF_ACCEPT;
case TCP_CONNTRACK_SYN_SENT:
- if (old_state >= TCP_CONNTRACK_TIME_WAIT) {
+ if (old_state < TCP_CONNTRACK_TIME_WAIT)
+ break;
+ if ((conntrack->proto.tcp.seen[dir].flags &
+ IP_CT_TCP_FLAG_CLOSE_INIT)
+ || after(ntohl(th->seq),
+ conntrack->proto.tcp.seen[dir].td_end)) {
/* Attempt to reopen a closed connection.
* Delete this connection and look up again. */
WRITE_UNLOCK(&tcp_lock);
@@ -902,23 +923,23 @@
conntrack->timeout.function((unsigned long)
conntrack);
return -NF_REPEAT;
+ } else {
+ WRITE_UNLOCK(&tcp_lock);
+ if (LOG_INVALID(IPPROTO_TCP))
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ "ip_ct_tcp: invalid SYN");
+ return -NF_ACCEPT;
}
- break;
case TCP_CONNTRACK_CLOSE:
if (index == TCP_RST_SET
- && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
- && conntrack->proto.tcp.last_index <= TCP_SYNACK_SET)
- || (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
- && conntrack->proto.tcp.last_index == TCP_ACK_SET))
- && after(ntohl(th->ack_seq),
- conntrack->proto.tcp.last_seq)) {
- /* Ignore RST closing down invalid SYN or ACK
- we had let trough. */
- WRITE_UNLOCK(&tcp_lock);
- if (LOG_INVALID(IPPROTO_TCP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
- "ip_ct_tcp: invalid RST (ignored) ");
- return NF_ACCEPT;
+ && test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
+ && conntrack->proto.tcp.last_index == TCP_SYN_SET
+ && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
+ /* RST sent to invalid SYN we had let trough
+ * SYN was in window then, tear down connection.
+ * We skip window checking, because packet might ACK
+ * segments we ignored in the SYN. */
+ goto in_window;
}
/* Just fall trough */
default:
@@ -926,16 +947,14 @@
break;
}
- if (!tcp_in_window(&conntrack->proto.tcp, dir, &index,
+ if (!tcp_in_window(&conntrack->proto.tcp, dir, index,
skb, iph, th)) {
WRITE_UNLOCK(&tcp_lock);
return -NF_ACCEPT;
}
- /* From now on we have got in-window packets */
-
- /* If FIN was trimmed off, we don't change state. */
+ in_window:
+ /* From now on we have got in-window packets */
conntrack->proto.tcp.last_index = index;
- new_state = tcp_conntracks[dir][index][old_state];
DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
"syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
@@ -946,6 +965,10 @@
old_state, new_state);
conntrack->proto.tcp.state = new_state;
+ if (old_state != new_state
+ && (new_state == TCP_CONNTRACK_FIN_WAIT
+ || new_state == TCP_CONNTRACK_CLOSE))
+ conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans
&& *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans
? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
@@ -980,7 +1003,7 @@
return NF_ACCEPT;
}
- /* Called when a new connection for this protocol found. */
+/* Called when a new connection for this protocol found. */
static int tcp_new(struct ip_conntrack *conntrack,
const struct sk_buff *skb)
{
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c Sat Jun 18 16:43:43 2005
@@ -77,34 +77,70 @@
#define seq_print_counters(x, y) 0
#endif
-static void *ct_seq_start(struct seq_file *s, loff_t *pos)
+struct ct_iter_state {
+ unsigned int bucket;
+};
+
+static struct list_head *ct_get_first(struct seq_file *seq)
{
- if (*pos >= ip_conntrack_htable_size)
- return NULL;
- return &ip_conntrack_hash[*pos];
+ struct ct_iter_state *st = seq->private;
+
+ for (st->bucket = 0;
+ st->bucket < ip_conntrack_htable_size;
+ st->bucket++) {
+ if (!list_empty(&ip_conntrack_hash[st->bucket]))
+ return ip_conntrack_hash[st->bucket].next;
+ }
+ return NULL;
}
-
-static void ct_seq_stop(struct seq_file *s, void *v)
+
+static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
+{
+ struct ct_iter_state *st = seq->private;
+
+ head = head->next;
+ while (head == &ip_conntrack_hash[st->bucket]) {
+ if (++st->bucket >= ip_conntrack_htable_size)
+ return NULL;
+ head = ip_conntrack_hash[st->bucket].next;
+ }
+ return head;
+}
+
+static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
{
+ struct list_head *head = ct_get_first(seq);
+
+ if (head)
+ while (pos && (head = ct_get_next(seq, head)))
+ pos--;
+ return pos ? NULL : head;
+}
+
+static void *ct_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ READ_LOCK(&ip_conntrack_lock);
+ return ct_get_idx(seq, *pos);
}
static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
(*pos)++;
- if (*pos >= ip_conntrack_htable_size)
- return NULL;
- return &ip_conntrack_hash[*pos];
+ return ct_get_next(s, v);
}
-/* return 0 on success, 1 in case of error */
-static int ct_seq_real_show(const struct ip_conntrack_tuple_hash *hash,
- struct seq_file *s)
+static void ct_seq_stop(struct seq_file *s, void *v)
{
+ READ_UNLOCK(&ip_conntrack_lock);
+}
+
+static int ct_seq_show(struct seq_file *s, void *v)
+{
+ const struct ip_conntrack_tuple_hash *hash = v;
const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);
struct ip_conntrack_protocol *proto;
MUST_BE_READ_LOCKED(&ip_conntrack_lock);
-
IP_NF_ASSERT(conntrack);
/* we only want to print DIR_ORIGINAL */
@@ -187,7 +223,23 @@
static int ct_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &ct_seq_ops);
+ struct seq_file *seq;
+ struct ct_iter_state *st;
+ int ret;
+
+ st = kmalloc(sizeof(struct ct_iter_state), GFP_KERNEL);
+ if (st == NULL)
+ return -ENOMEM;
+ ret = seq_open(file, &ct_seq_ops);
+ if (ret)
+ goto out_free;
+ seq = file->private_data;
+ seq->private = st;
+ memset(st, 0, sizeof(struct ct_iter_state));
+ return ret;
+out_free:
+ kfree(st);
+ return ret;
}
static struct file_operations ct_file_ops = {
@@ -195,7 +247,7 @@
.open = ct_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release
+ .release = seq_release_private,
};
/* expects */
@@ -223,6 +275,7 @@
{
struct list_head *e = v;
+ ++*pos;
e = e->next;
if (e == &ip_conntrack_expect_list)
@@ -241,8 +294,8 @@
struct ip_conntrack_expect *expect = v;
if (expect->timeout.function)
- seq_printf(s, "%lu ", timer_pending(&expect->timeout)
- ? (expect->timeout.expires - jiffies)/HZ : 0);
+ seq_printf(s, "%ld ", timer_pending(&expect->timeout)
+ ? (long)(expect->timeout.expires - jiffies)/HZ : 0);
else
seq_printf(s, "- ");
@@ -378,6 +431,16 @@
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
+ /* We've seen it coming out the other side: confirm it */
+ return ip_conntrack_confirm(pskb);
+}
+
+static unsigned int ip_conntrack_help(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
@@ -398,13 +461,6 @@
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
-#if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
- /* Previously seen (loopback)? Ignore. Do this before
- fragment check. */
- if ((*pskb)->nfct)
- return NF_ACCEPT;
-#endif
-
/* Gather fragments. */
if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
*pskb = ip_ct_gather_frags(*pskb,
@@ -432,7 +488,7 @@
/* Local packets are never produced too large for their
interface. We degfragment them at LOCAL_OUT, however,
so we have to refragment them here. */
- if ((*pskb)->len > dst_pmtu(&rt->u.dst) &&
+ if ((*pskb)->len > dst_mtu(&rt->u.dst) &&
!skb_shinfo(*pskb)->tso_size) {
/* No hook can be after us, so this should be OK. */
ip_fragment(*pskb, okfn);
Added: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c.orig
==============================================================================
--- (empty file)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c.orig Sat Jun 18 16:43:43 2005
@@ -0,0 +1,984 @@
+/* This file contains all the functions required for the standalone
+ ip_conntrack module.
+
+ These are not required by the compatibility layer.
+*/
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2004 Netfilter Core Team <coreteam at netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/ip.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/percpu.h>
+#ifdef CONFIG_SYSCTL
+#include <linux/sysctl.h>
+#endif
+#include <net/checksum.h>
+#include <net/ip.h>
+
+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
+
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/listhelp.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+MODULE_LICENSE("GPL");
+
+extern atomic_t ip_conntrack_count;
+DECLARE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
+
+static int kill_proto(struct ip_conntrack *i, void *data)
+{
+ return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
+ *((u_int8_t *) data));
+}
+
+#ifdef CONFIG_PROC_FS
+static int
+print_tuple(struct seq_file *s, const struct ip_conntrack_tuple *tuple,
+ struct ip_conntrack_protocol *proto)
+{
+ seq_printf(s, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
+ NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
+ return proto->print_tuple(s, tuple);
+}
+
+#ifdef CONFIG_IP_NF_CT_ACCT
+static unsigned int
+seq_print_counters(struct seq_file *s,
+ const struct ip_conntrack_counter *counter)
+{
+ return seq_printf(s, "packets=%llu bytes=%llu ",
+ (unsigned long long)counter->packets,
+ (unsigned long long)counter->bytes);
+}
+#else
+#define seq_print_counters(x, y) 0
+#endif
+
+static void *ct_seq_start(struct seq_file *s, loff_t *pos)
+{
+ if (*pos >= ip_conntrack_htable_size)
+ return NULL;
+ return &ip_conntrack_hash[*pos];
+}
+
+static void ct_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ if (*pos >= ip_conntrack_htable_size)
+ return NULL;
+ return &ip_conntrack_hash[*pos];
+}
+
+/* return 0 on success, 1 in case of error */
+static int ct_seq_real_show(const struct ip_conntrack_tuple_hash *hash,
+ struct seq_file *s)
+{
+ const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);
+ struct ip_conntrack_protocol *proto;
+
+ MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+
+ IP_NF_ASSERT(conntrack);
+
+ /* we only want to print DIR_ORIGINAL */
+ if (DIRECTION(hash))
+ return 0;
+
+ proto = ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+ .tuple.dst.protonum);
+ IP_NF_ASSERT(proto);
+
+ if (seq_printf(s, "%-8s %u %lu ",
+ proto->name,
+ conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
+ timer_pending(&conntrack->timeout)
+ ? (conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
+ return 1;
+
+ if (proto->print_conntrack(s, conntrack))
+ return 1;
+
+ if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+ proto))
+ return 1;
+
+ if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
+ return 1;
+
+ if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
+ if (seq_printf(s, "[UNREPLIED] "))
+ return 1;
+
+ if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
+ proto))
+ return 1;
+
+ if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
+ return 1;
+
+ if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
+ if (seq_printf(s, "[ASSURED] "))
+ return 1;
+
+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+ if (seq_printf(s, "mark=%ld ", conntrack->mark))
+ return 1;
+#endif
+
+#if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE)
+ if(conntrack->layer7.app_proto)
+ if (seq_printf(s, "l7proto=%s ",conntrack->layer7.app_proto))
+ return 1;
+#endif
+
+ if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
+ return 1;
+
+ return 0;
+}
+
+static int ct_seq_show(struct seq_file *s, void *v)
+{
+ struct list_head *list = v;
+ int ret = 0;
+
+ /* FIXME: Simply truncates if hash chain too long. */
+ READ_LOCK(&ip_conntrack_lock);
+ if (LIST_FIND(list, ct_seq_real_show,
+ struct ip_conntrack_tuple_hash *, s))
+ ret = -ENOSPC;
+ READ_UNLOCK(&ip_conntrack_lock);
+ return ret;
+}
+
+static struct seq_operations ct_seq_ops = {
+ .start = ct_seq_start,
+ .next = ct_seq_next,
+ .stop = ct_seq_stop,
+ .show = ct_seq_show
+};
+
+static int ct_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &ct_seq_ops);
+}
+
+static struct file_operations ct_file_ops = {
+ .owner = THIS_MODULE,
+ .open = ct_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+/* expects */
+static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+{
+ struct list_head *e = &ip_conntrack_expect_list;
+ loff_t i;
+
+ /* strange seq_file api calls stop even if we fail,
+ * thus we need to grab lock since stop unlocks */
+ READ_LOCK(&ip_conntrack_lock);
+
+ if (list_empty(e))
+ return NULL;
+
+ for (i = 0; i <= *pos; i++) {
+ e = e->next;
+ if (e == &ip_conntrack_expect_list)
+ return NULL;
+ }
+ return e;
+}
+
+static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ struct list_head *e = v;
+
+ e = e->next;
+
+ if (e == &ip_conntrack_expect_list)
+ return NULL;
+
+ return e;
+}
+
+static void exp_seq_stop(struct seq_file *s, void *v)
+{
+ READ_UNLOCK(&ip_conntrack_lock);
+}
+
+static int exp_seq_show(struct seq_file *s, void *v)
+{
+ struct ip_conntrack_expect *expect = v;
+
+ if (expect->timeout.function)
+ seq_printf(s, "%lu ", timer_pending(&expect->timeout)
+ ? (expect->timeout.expires - jiffies)/HZ : 0);
+ else
+ seq_printf(s, "- ");
+
+ seq_printf(s, "proto=%u ", expect->tuple.dst.protonum);
+
+ print_tuple(s, &expect->tuple,
+ ip_ct_find_proto(expect->tuple.dst.protonum));
+ return seq_putc(s, '\n');
+}
+
+static struct seq_operations exp_seq_ops = {
+ .start = exp_seq_start,
+ .next = exp_seq_next,
+ .stop = exp_seq_stop,
+ .show = exp_seq_show
+};
+
+static int exp_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &exp_seq_ops);
+}
+
+static struct file_operations exp_file_ops = {
+ .owner = THIS_MODULE,
+ .open = exp_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ int cpu;
+
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+
+ for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
+ if (!cpu_possible(cpu))
+ continue;
+ *pos = cpu+1;
+ return &per_cpu(ip_conntrack_stat, cpu);
+ }
+
+ return NULL;
+}
+
+static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ int cpu;
+
+ for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
+ if (!cpu_possible(cpu))
+ continue;
+ *pos = cpu+1;
+ return &per_cpu(ip_conntrack_stat, cpu);
+ }
+
+ return NULL;
+}
+
+static void ct_cpu_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static int ct_cpu_seq_show(struct seq_file *seq, void *v)
+{
+ unsigned int nr_conntracks = atomic_read(&ip_conntrack_count);
+ struct ip_conntrack_stat *st = v;
+
+ if (v == SEQ_START_TOKEN) {
+ seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete\n");
+ return 0;
+ }
+
+ seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x "
+ "%08x %08x %08x %08x %08x %08x %08x %08x \n",
+ nr_conntracks,
+ st->searched,
+ st->found,
+ st->new,
+ st->invalid,
+ st->ignore,
+ st->delete,
+ st->delete_list,
+ st->insert,
+ st->insert_failed,
+ st->drop,
+ st->early_drop,
+ st->error,
+
+ st->expect_new,
+ st->expect_create,
+ st->expect_delete
+ );
+ return 0;
+}
+
+static struct seq_operations ct_cpu_seq_ops = {
+ .start = ct_cpu_seq_start,
+ .next = ct_cpu_seq_next,
+ .stop = ct_cpu_seq_stop,
+ .show = ct_cpu_seq_show,
+};
+
+static int ct_cpu_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &ct_cpu_seq_ops);
+}
+
+static struct file_operations ct_cpu_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = ct_cpu_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+#endif
+
+static unsigned int ip_confirm(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ /* We've seen it coming out the other side: confirm it */
+ return ip_conntrack_confirm(pskb);
+}
+
+static unsigned int ip_conntrack_help(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
+
+ /* This is where we call the helper: as the packet goes out. */
+ ct = ip_conntrack_get(*pskb, &ctinfo);
+ if (ct && ct->helper) {
+ unsigned int ret;
+ ret = ct->helper->help(pskb, ct, ctinfo);
+ if (ret != NF_ACCEPT)
+ return ret;
+ }
+ return NF_ACCEPT;
+}
+
+static unsigned int ip_conntrack_defrag(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+#if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
+ /* Previously seen (loopback)? Ignore. Do this before
+ fragment check. */
+ if ((*pskb)->nfct)
+ return NF_ACCEPT;
+#endif
+
+ /* Gather fragments. */
+ if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+ *pskb = ip_ct_gather_frags(*pskb,
+ hooknum == NF_IP_PRE_ROUTING ?
+ IP_DEFRAG_CONNTRACK_IN :
+ IP_DEFRAG_CONNTRACK_OUT);
+ if (!*pskb)
+ return NF_STOLEN;
+ }
+ return NF_ACCEPT;
+}
+
+static unsigned int ip_refrag(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct rtable *rt = (struct rtable *)(*pskb)->dst;
+
+ /* We've seen it coming out the other side: confirm */
+ if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
+ return NF_DROP;
+
+ /* Local packets are never produced too large for their
+ interface. We degfragment them at LOCAL_OUT, however,
+ so we have to refragment them here. */
+ if ((*pskb)->len > dst_pmtu(&rt->u.dst) &&
+ !skb_shinfo(*pskb)->tso_size) {
+ /* No hook can be after us, so this should be OK. */
+ ip_fragment(*pskb, okfn);
+ return NF_STOLEN;
+ }
+ return NF_ACCEPT;
+}
+
+static unsigned int ip_conntrack_local(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ /* root is playing with raw sockets. */
+ if ((*pskb)->len < sizeof(struct iphdr)
+ || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
+ if (net_ratelimit())
+ printk("ipt_hook: happy cracking.\n");
+ return NF_ACCEPT;
+ }
+ return ip_conntrack_in(hooknum, pskb, in, out, okfn);
+}
+
+/* Connection tracking may drop packets, but never alters them, so
+ make it the first hook. */
+static struct nf_hook_ops ip_conntrack_defrag_ops = {
+ .hook = ip_conntrack_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
+};
+
+static struct nf_hook_ops ip_conntrack_in_ops = {
+ .hook = ip_conntrack_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK,
+};
+
+static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
+ .hook = ip_conntrack_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
+};
+
+static struct nf_hook_ops ip_conntrack_local_out_ops = {
+ .hook = ip_conntrack_local,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_CONNTRACK,
+};
+
+/* helpers */
+static struct nf_hook_ops ip_conntrack_helper_out_ops = {
+ .hook = ip_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+};
+
+static struct nf_hook_ops ip_conntrack_helper_in_ops = {
+ .hook = ip_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+};
+
+/* Refragmenter; last chance. */
+static struct nf_hook_ops ip_conntrack_out_ops = {
+ .hook = ip_refrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+};
+
+static struct nf_hook_ops ip_conntrack_local_in_ops = {
+ .hook = ip_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+};
+
+/* Sysctl support */
+
+#ifdef CONFIG_SYSCTL
+
+/* From ip_conntrack_core.c */
+extern int ip_conntrack_max;
+extern unsigned int ip_conntrack_htable_size;
+
+/* From ip_conntrack_proto_tcp.c */
+extern unsigned long ip_ct_tcp_timeout_syn_sent;
+extern unsigned long ip_ct_tcp_timeout_syn_recv;
+extern unsigned long ip_ct_tcp_timeout_established;
+extern unsigned long ip_ct_tcp_timeout_fin_wait;
+extern unsigned long ip_ct_tcp_timeout_close_wait;
+extern unsigned long ip_ct_tcp_timeout_last_ack;
+extern unsigned long ip_ct_tcp_timeout_time_wait;
+extern unsigned long ip_ct_tcp_timeout_close;
+extern unsigned long ip_ct_tcp_timeout_max_retrans;
+extern int ip_ct_tcp_loose;
+extern int ip_ct_tcp_be_liberal;
+extern int ip_ct_tcp_max_retrans;
+
+/* From ip_conntrack_proto_udp.c */
+extern unsigned long ip_ct_udp_timeout;
+extern unsigned long ip_ct_udp_timeout_stream;
+
+/* From ip_conntrack_proto_icmp.c */
+extern unsigned long ip_ct_icmp_timeout;
+
+/* From ip_conntrack_proto_icmp.c */
+extern unsigned long ip_ct_generic_timeout;
+
+/* Log invalid packets of a given protocol */
+static int log_invalid_proto_min = 0;
+static int log_invalid_proto_max = 255;
+
+static struct ctl_table_header *ip_ct_sysctl_header;
+
+static ctl_table ip_ct_sysctl_table[] = {
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_MAX,
+ .procname = "ip_conntrack_max",
+ .data = &ip_conntrack_max,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_COUNT,
+ .procname = "ip_conntrack_count",
+ .data = &ip_conntrack_count,
+ .maxlen = sizeof(int),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS,
+ .procname = "ip_conntrack_buckets",
+ .data = &ip_conntrack_htable_size,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
+ .procname = "ip_conntrack_tcp_timeout_syn_sent",
+ .data = &ip_ct_tcp_timeout_syn_sent,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
+ .procname = "ip_conntrack_tcp_timeout_syn_recv",
+ .data = &ip_ct_tcp_timeout_syn_recv,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
+ .procname = "ip_conntrack_tcp_timeout_established",
+ .data = &ip_ct_tcp_timeout_established,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
+ .procname = "ip_conntrack_tcp_timeout_fin_wait",
+ .data = &ip_ct_tcp_timeout_fin_wait,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
+ .procname = "ip_conntrack_tcp_timeout_close_wait",
+ .data = &ip_ct_tcp_timeout_close_wait,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
+ .procname = "ip_conntrack_tcp_timeout_last_ack",
+ .data = &ip_ct_tcp_timeout_last_ack,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
+ .procname = "ip_conntrack_tcp_timeout_time_wait",
+ .data = &ip_ct_tcp_timeout_time_wait,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
+ .procname = "ip_conntrack_tcp_timeout_close",
+ .data = &ip_ct_tcp_timeout_close,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT,
+ .procname = "ip_conntrack_udp_timeout",
+ .data = &ip_ct_udp_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
+ .procname = "ip_conntrack_udp_timeout_stream",
+ .data = &ip_ct_udp_timeout_stream,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT,
+ .procname = "ip_conntrack_icmp_timeout",
+ .data = &ip_ct_icmp_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT,
+ .procname = "ip_conntrack_generic_timeout",
+ .data = &ip_ct_generic_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_LOG_INVALID,
+ .procname = "ip_conntrack_log_invalid",
+ .data = &ip_ct_log_invalid,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &log_invalid_proto_min,
+ .extra2 = &log_invalid_proto_max,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
+ .procname = "ip_conntrack_tcp_timeout_max_retrans",
+ .data = &ip_ct_tcp_timeout_max_retrans,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_LOOSE,
+ .procname = "ip_conntrack_tcp_loose",
+ .data = &ip_ct_tcp_loose,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL,
+ .procname = "ip_conntrack_tcp_be_liberal",
+ .data = &ip_ct_tcp_be_liberal,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS,
+ .procname = "ip_conntrack_tcp_max_retrans",
+ .data = &ip_ct_tcp_max_retrans,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ { .ctl_name = 0 }
+};
+
+#define NET_IP_CONNTRACK_MAX 2089
+
+static ctl_table ip_ct_netfilter_table[] = {
+ {
+ .ctl_name = NET_IPV4_NETFILTER,
+ .procname = "netfilter",
+ .mode = 0555,
+ .child = ip_ct_sysctl_table,
+ },
+ {
+ .ctl_name = NET_IP_CONNTRACK_MAX,
+ .procname = "ip_conntrack_max",
+ .data = &ip_conntrack_max,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec
+ },
+ { .ctl_name = 0 }
+};
+
+static ctl_table ip_ct_ipv4_table[] = {
+ {
+ .ctl_name = NET_IPV4,
+ .procname = "ipv4",
+ .mode = 0555,
+ .child = ip_ct_netfilter_table,
+ },
+ { .ctl_name = 0 }
+};
+
+static ctl_table ip_ct_net_table[] = {
+ {
+ .ctl_name = CTL_NET,
+ .procname = "net",
+ .mode = 0555,
+ .child = ip_ct_ipv4_table,
+ },
+ { .ctl_name = 0 }
+};
+
+EXPORT_SYMBOL(ip_ct_log_invalid);
+#endif /* CONFIG_SYSCTL */
+
+static int init_or_cleanup(int init)
+{
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+#endif
+ int ret = 0;
+
+ if (!init) goto cleanup;
+
+ ret = ip_conntrack_init();
+ if (ret < 0)
+ goto cleanup_nothing;
+
+#ifdef CONFIG_PROC_FS
+ ret = -ENOMEM;
+ proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
+ if (!proc) goto cleanup_init;
+
+ proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
+ &exp_file_ops);
+ if (!proc_exp) goto cleanup_proc;
+
+ proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
+ if (!proc_stat)
+ goto cleanup_proc_exp;
+
+ proc_stat->proc_fops = &ct_cpu_seq_fops;
+ proc_stat->owner = THIS_MODULE;
+#endif
+
+ ret = nf_register_hook(&ip_conntrack_defrag_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register pre-routing defrag hook.\n");
+ goto cleanup_proc_stat;
+ }
+ ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register local_out defrag hook.\n");
+ goto cleanup_defragops;
+ }
+ ret = nf_register_hook(&ip_conntrack_in_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register pre-routing hook.\n");
+ goto cleanup_defraglocalops;
+ }
+ ret = nf_register_hook(&ip_conntrack_local_out_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register local out hook.\n");
+ goto cleanup_inops;
+ }
+ ret = nf_register_hook(&ip_conntrack_helper_in_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register local in helper hook.\n");
+ goto cleanup_inandlocalops;
+ }
+ ret = nf_register_hook(&ip_conntrack_helper_out_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register postrouting helper hook.\n");
+ goto cleanup_helperinops;
+ }
+ ret = nf_register_hook(&ip_conntrack_out_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register post-routing hook.\n");
+ goto cleanup_helperoutops;
+ }
+ ret = nf_register_hook(&ip_conntrack_local_in_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register local in hook.\n");
+ goto cleanup_inoutandlocalops;
+ }
+#ifdef CONFIG_SYSCTL
+ ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
+ if (ip_ct_sysctl_header == NULL) {
+ printk("ip_conntrack: can't register to sysctl.\n");
+ ret = -ENOMEM;
+ goto cleanup_localinops;
+ }
+#endif
+
+ return ret;
+
+ cleanup:
+#ifdef CONFIG_SYSCTL
+ unregister_sysctl_table(ip_ct_sysctl_header);
+ cleanup_localinops:
+#endif
+ nf_unregister_hook(&ip_conntrack_local_in_ops);
+ cleanup_inoutandlocalops:
+ nf_unregister_hook(&ip_conntrack_out_ops);
+ cleanup_helperoutops:
+ nf_unregister_hook(&ip_conntrack_helper_out_ops);
+ cleanup_helperinops:
+ nf_unregister_hook(&ip_conntrack_helper_in_ops);
+ cleanup_inandlocalops:
+ nf_unregister_hook(&ip_conntrack_local_out_ops);
+ cleanup_inops:
+ nf_unregister_hook(&ip_conntrack_in_ops);
+ cleanup_defraglocalops:
+ nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
+ cleanup_defragops:
+ nf_unregister_hook(&ip_conntrack_defrag_ops);
+ cleanup_proc_stat:
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("ip_conntrack", proc_net_stat);
+ cleanup_proc_exp:
+ proc_net_remove("ip_conntrack_expect");
+ cleanup_proc:
+ proc_net_remove("ip_conntrack");
+ cleanup_init:
+#endif /* CONFIG_PROC_FS */
+ ip_conntrack_cleanup();
+ cleanup_nothing:
+ return ret;
+}
+
+/* FIXME: Allow NULL functions and sub in pointers to generic for
+ them. --RR */
+int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
+{
+ int ret = 0;
+
+ WRITE_LOCK(&ip_conntrack_lock);
+ if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
+ ret = -EBUSY;
+ goto out;
+ }
+ ip_ct_protos[proto->proto] = proto;
+ out:
+ WRITE_UNLOCK(&ip_conntrack_lock);
+ return ret;
+}
+
+void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
+{
+ WRITE_LOCK(&ip_conntrack_lock);
+ ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
+ WRITE_UNLOCK(&ip_conntrack_lock);
+
+ /* Somebody could be still looking at the proto in bh. */
+ synchronize_net();
+
+ /* Remove all contrack entries for this protocol */
+ ip_ct_iterate_cleanup(kill_proto, &proto->proto);
+}
+
+static int __init init(void)
+{
+ return init_or_cleanup(1);
+}
+
+static void __exit fini(void)
+{
+ init_or_cleanup(0);
+}
+
+module_init(init);
+module_exit(fini);
+
+/* Some modules need us, but don't depend directly on any symbol.
+ They should call this. */
+void need_ip_conntrack(void)
+{
+}
+
+EXPORT_SYMBOL(ip_conntrack_flush);
+EXPORT_SYMBOL(__ip_conntrack_expect_find);
+EXPORT_SYMBOL(__ip_conntrack_find);
+EXPORT_SYMBOL(ip_conntrack_expect_list);
+EXPORT_SYMBOL(ip_ct_generic_change_proto);
+EXPORT_SYMBOL(ip_ct_generic_change_help);
+EXPORT_SYMBOL(ip_conntrack_expect_find_get);
+EXPORT_SYMBOL(ip_conntrack_alloc);
+EXPORT_SYMBOL(ip_conntrack_free);
+EXPORT_SYMBOL(__ip_conntrack_hash_insert);
+EXPORT_SYMBOL(ip_ct_remove_expectations);
+EXPORT_SYMBOL(ip_ct_find_helper);
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+EXPORT_SYMBOL(ip_conntrack_chain);
+EXPORT_SYMBOL(ip_conntrack_expect_chain);
+EXPORT_SYMBOL(ip_conntrack_register_notifier);
+EXPORT_SYMBOL(ip_conntrack_unregister_notifier);
+#endif
+EXPORT_SYMBOL(ip_conntrack_protocol_register);
+EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
+EXPORT_SYMBOL(ip_ct_get_tuple);
+EXPORT_SYMBOL(invert_tuplepr);
+EXPORT_SYMBOL(ip_conntrack_alter_reply);
+EXPORT_SYMBOL(ip_conntrack_destroyed);
+EXPORT_SYMBOL(need_ip_conntrack);
+EXPORT_SYMBOL(ip_conntrack_helper_register);
+EXPORT_SYMBOL(ip_conntrack_helper_unregister);
+EXPORT_SYMBOL(ip_ct_iterate_cleanup);
+EXPORT_SYMBOL(ip_ct_refresh_acct);
+EXPORT_SYMBOL(ip_ct_protos);
+EXPORT_SYMBOL(ip_ct_find_proto);
+EXPORT_SYMBOL(ip_conntrack_expect_alloc);
+EXPORT_SYMBOL(ip_conntrack_expect_free);
+EXPORT_SYMBOL(ip_conntrack_expect_related);
+EXPORT_SYMBOL(ip_conntrack_unexpect_related);
+EXPORT_SYMBOL(ip_conntrack_tuple_taken);
+EXPORT_SYMBOL(ip_ct_gather_frags);
+EXPORT_SYMBOL(ip_conntrack_htable_size);
+EXPORT_SYMBOL(ip_conntrack_lock);
+EXPORT_SYMBOL(ip_conntrack_hash);
+EXPORT_SYMBOL(ip_conntrack_untracked);
+EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+EXPORT_SYMBOL(ip_conntrack_tcp_update);
+#endif
Added: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c.rej
==============================================================================
--- (empty file)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c.rej Sat Jun 18 16:43:43 2005
@@ -0,0 +1,250 @@
+***************
+*** 115,177 ****
+ .tuple.dst.protonum);
+ IP_NF_ASSERT(proto);
+
+- if (seq_printf(s, "%-8s %u %lu ",
+ proto->name,
+ conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
+ timer_pending(&conntrack->timeout)
+- ? (conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
+- return 1;
+
+ if (proto->print_conntrack(s, conntrack))
+- return 1;
+
+ if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+ proto))
+- return 1;
+
+ if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
+- return 1;
+
+ if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
+ if (seq_printf(s, "[UNREPLIED] "))
+- return 1;
+
+ if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
+ proto))
+- return 1;
+
+ if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
+- return 1;
+
+ if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
+ if (seq_printf(s, "[ASSURED] "))
+- return 1;
+
+ #if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+- if (seq_printf(s, "mark=%ld ", conntrack->mark))
+- return 1;
+ #endif
+
+ if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
+- return 1;
+
+ return 0;
+ }
+
+- static int ct_seq_show(struct seq_file *s, void *v)
+- {
+- struct list_head *list = v;
+- int ret = 0;
+-
+- /* FIXME: Simply truncates if hash chain too long. */
+- READ_LOCK(&ip_conntrack_lock);
+- if (LIST_FIND(list, ct_seq_real_show,
+- struct ip_conntrack_tuple_hash *, s))
+- ret = -ENOSPC;
+- READ_UNLOCK(&ip_conntrack_lock);
+- return ret;
+- }
+-
+ static struct seq_operations ct_seq_ops = {
+ .start = ct_seq_start,
+ .next = ct_seq_next,
+--- 151,200 ----
+ .tuple.dst.protonum);
+ IP_NF_ASSERT(proto);
+
++ if (seq_printf(s, "%-8s %u %ld ",
+ proto->name,
+ conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
+ timer_pending(&conntrack->timeout)
++ ? (long)(conntrack->timeout.expires - jiffies)/HZ
++ : 0) != 0)
++ return -ENOSPC;
+
+ if (proto->print_conntrack(s, conntrack))
++ return -ENOSPC;
+
+ if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+ proto))
++ return -ENOSPC;
+
+ if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
++ return -ENOSPC;
+
+ if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
+ if (seq_printf(s, "[UNREPLIED] "))
++ return -ENOSPC;
+
+ if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
+ proto))
++ return -ENOSPC;
+
+ if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
++ return -ENOSPC;
+
+ if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
+ if (seq_printf(s, "[ASSURED] "))
++ return -ENOSPC;
+
+ #if defined(CONFIG_IP_NF_CONNTRACK_MARK)
++ if (seq_printf(s, "mark=%lu ", conntrack->mark))
++ return -ENOSPC;
+ #endif
+
+ if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
++ return -ENOSPC;
+
+ return 0;
+ }
+
+ static struct seq_operations ct_seq_ops = {
+ .start = ct_seq_start,
+ .next = ct_seq_next,
+***************
+*** 389,397 ****
+ if (ret != NF_ACCEPT)
+ return ret;
+ }
+-
+- /* We've seen it coming out the other side: confirm it */
+- return ip_conntrack_confirm(pskb);
+ }
+
+ static unsigned int ip_conntrack_defrag(unsigned int hooknum,
+--- 439,445 ----
+ if (ret != NF_ACCEPT)
+ return ret;
+ }
++ return NF_ACCEPT;
+ }
+
+ static unsigned int ip_conntrack_defrag(unsigned int hooknum,
+***************
+*** 491,503 ****
+ .priority = NF_IP_PRI_CONNTRACK,
+ };
+
+ /* Refragmenter; last chance. */
+ static struct nf_hook_ops ip_conntrack_out_ops = {
+ .hook = ip_refrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+- .priority = NF_IP_PRI_LAST,
+ };
+
+ static struct nf_hook_ops ip_conntrack_local_in_ops = {
+--- 532,561 ----
+ .priority = NF_IP_PRI_CONNTRACK,
+ };
+
++ /* helpers */
++ static struct nf_hook_ops ip_conntrack_helper_out_ops = {
++ .hook = ip_conntrack_help,
++ .owner = THIS_MODULE,
++ .pf = PF_INET,
++ .hooknum = NF_IP_POST_ROUTING,
++ .priority = NF_IP_PRI_CONNTRACK_HELPER,
++ };
++
++ static struct nf_hook_ops ip_conntrack_helper_in_ops = {
++ .hook = ip_conntrack_help,
++ .owner = THIS_MODULE,
++ .pf = PF_INET,
++ .hooknum = NF_IP_LOCAL_IN,
++ .priority = NF_IP_PRI_CONNTRACK_HELPER,
++ };
++
+ /* Refragmenter; last chance. */
+ static struct nf_hook_ops ip_conntrack_out_ops = {
+ .hook = ip_refrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
++ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+ };
+
+ static struct nf_hook_ops ip_conntrack_local_in_ops = {
+***************
+*** 505,511 ****
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+- .priority = NF_IP_PRI_LAST-1,
+ };
+
+ /* Sysctl support */
+--- 563,569 ----
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
++ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+ };
+
+ /* Sysctl support */
+***************
+*** 806,815 ****
+ printk("ip_conntrack: can't register local out hook.\n");
+ goto cleanup_inops;
+ }
+ ret = nf_register_hook(&ip_conntrack_out_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register post-routing hook.\n");
+- goto cleanup_inandlocalops;
+ }
+ ret = nf_register_hook(&ip_conntrack_local_in_ops);
+ if (ret < 0) {
+--- 864,883 ----
+ printk("ip_conntrack: can't register local out hook.\n");
+ goto cleanup_inops;
+ }
++ ret = nf_register_hook(&ip_conntrack_helper_in_ops);
++ if (ret < 0) {
++ printk("ip_conntrack: can't register local in helper hook.\n");
++ goto cleanup_inandlocalops;
++ }
++ ret = nf_register_hook(&ip_conntrack_helper_out_ops);
++ if (ret < 0) {
++ printk("ip_conntrack: can't register postrouting helper hook.\n");
++ goto cleanup_helperinops;
++ }
+ ret = nf_register_hook(&ip_conntrack_out_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register post-routing hook.\n");
++ goto cleanup_helperoutops;
+ }
+ ret = nf_register_hook(&ip_conntrack_local_in_ops);
+ if (ret < 0) {
+***************
+*** 835,840 ****
+ nf_unregister_hook(&ip_conntrack_local_in_ops);
+ cleanup_inoutandlocalops:
+ nf_unregister_hook(&ip_conntrack_out_ops);
+ cleanup_inandlocalops:
+ nf_unregister_hook(&ip_conntrack_local_out_ops);
+ cleanup_inops:
+--- 903,912 ----
+ nf_unregister_hook(&ip_conntrack_local_in_ops);
+ cleanup_inoutandlocalops:
+ nf_unregister_hook(&ip_conntrack_out_ops);
++ cleanup_helperoutops:
++ nf_unregister_hook(&ip_conntrack_helper_out_ops);
++ cleanup_helperinops:
++ nf_unregister_hook(&ip_conntrack_helper_in_ops);
+ cleanup_inandlocalops:
+ nf_unregister_hook(&ip_conntrack_local_out_ops);
+ cleanup_inops:
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_ftp.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_ftp.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_ftp.c Sat Jun 18 16:43:43 2005
@@ -170,5 +170,14 @@
return 0;
}
+/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
+static int warn_set(const char *val, struct kernel_param *kp)
+{
+ printk(KERN_INFO __stringify(KBUILD_MODNAME)
+ ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
+ return 0;
+}
+module_param_call(ports, warn_set, NULL, NULL, 0);
+
module_init(init);
module_exit(fini);
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_irc.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_irc.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_irc.c Sat Jun 18 16:43:43 2005
@@ -112,5 +112,14 @@
return 0;
}
+/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
+static int warn_set(const char *val, struct kernel_param *kp)
+{
+ printk(KERN_INFO __stringify(KBUILD_MODNAME)
+ ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
+ return 0;
+}
+module_param_call(ports, warn_set, NULL, NULL, 0);
+
module_init(init);
module_exit(fini);
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_standalone.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_standalone.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_nat_standalone.c Sat Jun 18 16:43:43 2005
@@ -249,6 +249,25 @@
return NF_ACCEPT;
}
+static unsigned int
+ip_nat_adjust(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
+
+ ct = ip_conntrack_get(*pskb, &ctinfo);
+ if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
+ DEBUGP("ip_nat_standalone: adjusting sequence number\n");
+ if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
+ return NF_DROP;
+ }
+ return NF_ACCEPT;
+}
+
/* We must be after connection tracking and before packet filtering. */
/* Before packet filtering, change destination */
@@ -278,6 +297,15 @@
.priority = NF_IP_PRI_NAT_SEQ_ADJUST,
};
+/* After conntrack, adjust sequence number */
+static struct nf_hook_ops ip_nat_adjust_out_ops = {
+ .hook = ip_nat_adjust,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
+};
+
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_local_out_ops = {
.hook = ip_nat_local_fn,
@@ -306,6 +334,16 @@
};
+/* After conntrack, adjust sequence number */
+static struct nf_hook_ops ip_nat_adjust_in_ops = {
+ .hook = ip_nat_adjust,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
+};
+
+
static int init_or_cleanup(int init)
{
int ret = 0;
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_queue.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_queue.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_queue.c Sat Jun 18 16:43:43 2005
@@ -3,6 +3,7 @@
* communicating with userspace via netlink.
*
* (C) 2000-2002 James Morris <jmorris at intercode.com.au>
+ * (C) 2003-2005 Netfilter Core Team <coreteam at netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,6 +15,10 @@
* Zander).
* 2000-08-01: Added Nick Williams' MAC support.
* 2002-06-25: Code cleanup.
+ * 2005-01-10: Added /proc counter for dropped packets; fixed so
+ * packets aren't delivered to user space if they're going
+ * to be dropped.
+ * 2005-05-26: local_bh_{disable,enable} around nf_reinject (Harald Welte)
*
*/
#include <linux/module.h>
@@ -59,6 +64,8 @@
static int peer_pid;
static unsigned int copy_range;
static unsigned int queue_total;
+static unsigned int queue_dropped = 0;
+static unsigned int queue_user_dropped = 0;
static struct sock *ipqnl;
static LIST_HEAD(queue_list);
static DECLARE_MUTEX(ipqnl_sem);
@@ -66,22 +73,23 @@
static void
ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
{
+ /* TCP input path (and probably other bits) assume to be called
+ * from softirq context, not from syscall, like ipq_issue_verdict is
+ * called. TCP input path deadlocks with locks taken from timer
+ * softirq, e.g. We therefore emulate this by local_bh_disable() */
+
+ local_bh_disable();
nf_reinject(entry->skb, entry->info, verdict);
+ local_bh_enable();
+
kfree(entry);
}
-static inline int
+static inline void
__ipq_enqueue_entry(struct ipq_queue_entry *entry)
{
- if (queue_total >= queue_maxlen) {
- if (net_ratelimit())
- printk(KERN_WARNING "ip_queue: full at %d entries, "
- "dropping packet(s).\n", queue_total);
- return -ENOSPC;
- }
list_add(&entry->list, &queue_list);
queue_total++;
- return 0;
}
/*
@@ -308,14 +316,24 @@
if (!peer_pid)
goto err_out_free_nskb;
+ if (queue_total >= queue_maxlen) {
+ queue_dropped++;
+ status = -ENOSPC;
+ if (net_ratelimit())
+ printk (KERN_WARNING "ip_queue: full at %d entries, "
+ "dropping packets(s). Dropped: %d\n", queue_total,
+ queue_dropped);
+ goto err_out_free_nskb;
+ }
+
/* netlink_unicast will either free the nskb or attach it to a socket */
status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
- if (status < 0)
- goto err_out_unlock;
-
- status = __ipq_enqueue_entry(entry);
- if (status < 0)
+ if (status < 0) {
+ queue_user_dropped++;
goto err_out_unlock;
+ }
+
+ __ipq_enqueue_entry(entry);
write_unlock_bh(&queue_lock);
return status;
@@ -573,20 +591,18 @@
static void
ipq_rcv_sk(struct sock *sk, int len)
{
- do {
- struct sk_buff *skb;
+ struct sk_buff *skb;
+ unsigned int qlen;
- if (down_trylock(&ipqnl_sem))
- return;
+ down(&ipqnl_sem);
- while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
- ipq_rcv_skb(skb);
- kfree_skb(skb);
- }
+ for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
+ skb = skb_dequeue(&sk->sk_receive_queue);
+ ipq_rcv_skb(skb);
+ kfree_skb(skb);
+ }
- up(&ipqnl_sem);
-
- } while (ipqnl && ipqnl->sk_receive_queue.qlen);
+ up(&ipqnl_sem);
}
static int
@@ -672,12 +688,16 @@
"Copy mode : %hu\n"
"Copy range : %u\n"
"Queue length : %u\n"
- "Queue max. length : %u\n",
+ "Queue max. length : %u\n"
+ "Queue dropped : %u\n"
+ "Netlink dropped : %u\n",
peer_pid,
copy_mode,
copy_range,
queue_total,
- queue_maxlen);
+ queue_maxlen,
+ queue_dropped,
+ queue_user_dropped);
read_unlock_bh(&queue_lock);
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_tables.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_tables.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ip_tables.c Sat Jun 18 16:43:43 2005
@@ -923,7 +923,7 @@
}
/* And one copy for every other CPU */
- for (i = 1; i < NR_CPUS; i++) {
+ for (i = 1; i < num_possible_cpus(); i++) {
memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
newinfo->entries,
SMP_ALIGN(newinfo->size));
@@ -945,7 +945,7 @@
struct ipt_entry *table_base;
unsigned int i;
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < num_possible_cpus(); i++) {
table_base =
(void *)newinfo->entries
+ TABLE_OFFSET(newinfo, i);
@@ -992,7 +992,7 @@
unsigned int cpu;
unsigned int i;
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
i = 0;
IPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
t->size,
@@ -1130,7 +1130,7 @@
return -ENOMEM;
newinfo = vmalloc(sizeof(struct ipt_table_info)
- + SMP_ALIGN(tmp.size) * NR_CPUS);
+ + SMP_ALIGN(tmp.size) * num_possible_cpus());
if (!newinfo)
return -ENOMEM;
@@ -1460,7 +1460,7 @@
= { 0, 0, 0, { 0 }, { 0 }, { } };
newinfo = vmalloc(sizeof(struct ipt_table_info)
- + SMP_ALIGN(repl->size) * NR_CPUS);
+ + SMP_ALIGN(repl->size) * num_possible_cpus());
if (!newinfo)
return -ENOMEM;
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_LOG.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_LOG.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_LOG.c Sat Jun 18 16:43:43 2005
@@ -198,16 +198,16 @@
static size_t required_len[NR_ICMP_TYPES+1]
= { [ICMP_ECHOREPLY] = 4,
[ICMP_DEST_UNREACH]
- = 8 + sizeof(struct iphdr) + 8,
+ = 8 + sizeof(struct iphdr),
[ICMP_SOURCE_QUENCH]
- = 8 + sizeof(struct iphdr) + 8,
+ = 8 + sizeof(struct iphdr),
[ICMP_REDIRECT]
- = 8 + sizeof(struct iphdr) + 8,
+ = 8 + sizeof(struct iphdr),
[ICMP_ECHO] = 4,
[ICMP_TIME_EXCEEDED]
- = 8 + sizeof(struct iphdr) + 8,
+ = 8 + sizeof(struct iphdr),
[ICMP_PARAMETERPROB]
- = 8 + sizeof(struct iphdr) + 8,
+ = 8 + sizeof(struct iphdr),
[ICMP_TIMESTAMP] = 20,
[ICMP_TIMESTAMPREPLY] = 20,
[ICMP_ADDRESS] = 12,
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_REJECT.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_REJECT.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_REJECT.c Sat Jun 18 16:43:43 2005
@@ -207,163 +207,22 @@
nskb->nh.iph->ihl);
/* "Never happens" */
- if (nskb->len > dst_pmtu(nskb->dst))
+ if (nskb->len > dst_mtu(nskb->dst))
goto free_nskb;
nf_ct_attach(nskb, oldskb);
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
- ip_finish_output);
+ dst_output);
return;
free_nskb:
kfree_skb(nskb);
}
-static void send_unreach(struct sk_buff *skb_in, int code)
+static inline void send_unreach(struct sk_buff *skb_in, int code)
{
- struct iphdr *iph;
- struct icmphdr *icmph;
- struct sk_buff *nskb;
- u32 saddr;
- u8 tos;
- int hh_len, length;
- struct rtable *rt = (struct rtable*)skb_in->dst;
- unsigned char *data;
-
- if (!rt)
- return;
-
- /* FIXME: Use sysctl number. --RR */
- if (!xrlim_allow(&rt->u.dst, 1*HZ))
- return;
-
- iph = skb_in->nh.iph;
-
- /* No replies to physical multicast/broadcast */
- if (skb_in->pkt_type!=PACKET_HOST)
- return;
-
- /* Now check at the protocol level */
- if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
- return;
-
- /* Only reply to fragment 0. */
- if (iph->frag_off&htons(IP_OFFSET))
- return;
-
- /* Ensure we have at least 8 bytes of proto header. */
- if (skb_in->len < skb_in->nh.iph->ihl*4 + 8)
- return;
-
- /* If we send an ICMP error to an ICMP error a mess would result.. */
- if (iph->protocol == IPPROTO_ICMP) {
- struct icmphdr ihdr;
-
- icmph = skb_header_pointer(skb_in, skb_in->nh.iph->ihl*4,
- sizeof(ihdr), &ihdr);
- if (!icmph)
- return;
-
- /* Between echo-reply (0) and timestamp (13),
- everything except echo-request (8) is an error.
- Also, anything greater than NR_ICMP_TYPES is
- unknown, and hence should be treated as an error... */
- if ((icmph->type < ICMP_TIMESTAMP
- && icmph->type != ICMP_ECHOREPLY
- && icmph->type != ICMP_ECHO)
- || icmph->type > NR_ICMP_TYPES)
- return;
- }
-
- saddr = iph->daddr;
- if (!(rt->rt_flags & RTCF_LOCAL))
- saddr = 0;
-
- tos = (iph->tos & IPTOS_TOS_MASK) | IPTOS_PREC_INTERNETCONTROL;
-
- {
- struct flowi fl = {
- .nl_u = {
- .ip4_u = {
- .daddr = skb_in->nh.iph->saddr,
- .saddr = saddr,
- .tos = RT_TOS(tos)
- }
- },
- .proto = IPPROTO_ICMP,
- .uli_u = {
- .icmpt = {
- .type = ICMP_DEST_UNREACH,
- .code = code
- }
- }
- };
-
- if (ip_route_output_key(&rt, &fl))
- return;
- }
- /* RFC says return as much as we can without exceeding 576 bytes. */
- length = skb_in->len + sizeof(struct iphdr) + sizeof(struct icmphdr);
-
- if (length > dst_pmtu(&rt->u.dst))
- length = dst_pmtu(&rt->u.dst);
- if (length > 576)
- length = 576;
-
- hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
-
- nskb = alloc_skb(hh_len + length, GFP_ATOMIC);
- if (!nskb) {
- ip_rt_put(rt);
- return;
- }
-
- nskb->priority = 0;
- nskb->dst = &rt->u.dst;
- skb_reserve(nskb, hh_len);
-
- /* Set up IP header */
- iph = nskb->nh.iph
- = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
- iph->version=4;
- iph->ihl=5;
- iph->tos=tos;
- iph->tot_len = htons(length);
-
- /* PMTU discovery never applies to ICMP packets. */
- iph->frag_off = 0;
-
- iph->ttl = MAXTTL;
- ip_select_ident(iph, &rt->u.dst, NULL);
- iph->protocol=IPPROTO_ICMP;
- iph->saddr=rt->rt_src;
- iph->daddr=rt->rt_dst;
- iph->check=0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
- /* Set up ICMP header. */
- icmph = nskb->h.icmph
- = (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr));
- icmph->type = ICMP_DEST_UNREACH;
- icmph->code = code;
- icmph->un.gateway = 0;
- icmph->checksum = 0;
-
- /* Copy as much of original packet as will fit */
- data = skb_put(nskb,
- length - sizeof(struct iphdr) - sizeof(struct icmphdr));
-
- skb_copy_bits(skb_in, 0, data,
- length - sizeof(struct iphdr) - sizeof(struct icmphdr));
-
- icmph->checksum = ip_compute_csum((unsigned char *)icmph,
- length - sizeof(struct iphdr));
-
- nf_ct_attach(nskb, skb_in);
-
- NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
- ip_finish_output);
+ icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
}
static unsigned int reject(struct sk_buff **pskb,
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_TCPMSS.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_TCPMSS.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_TCPMSS.c Sat Jun 18 16:43:43 2005
@@ -87,14 +87,14 @@
return NF_DROP; /* or IPT_CONTINUE ?? */
}
- if(dst_pmtu((*pskb)->dst) <= (sizeof(struct iphdr) + sizeof(struct tcphdr))) {
+ if(dst_mtu((*pskb)->dst) <= (sizeof(struct iphdr) + sizeof(struct tcphdr))) {
if (net_ratelimit())
printk(KERN_ERR
- "ipt_tcpmss_target: unknown or invalid path-MTU (%d)\n", dst_pmtu((*pskb)->dst));
+ "ipt_tcpmss_target: unknown or invalid path-MTU (%d)\n", dst_mtu((*pskb)->dst));
return NF_DROP; /* or IPT_CONTINUE ?? */
}
- newmss = dst_pmtu((*pskb)->dst) - sizeof(struct iphdr) - sizeof(struct tcphdr);
+ newmss = dst_mtu((*pskb)->dst) - sizeof(struct iphdr) - sizeof(struct tcphdr);
} else
newmss = tcpmssinfo->mss;
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_hashlimit.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_hashlimit.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_hashlimit.c Sat Jun 18 16:43:43 2005
@@ -91,7 +91,7 @@
struct hlist_head hash[0]; /* hashtable itself */
};
-static DECLARE_LOCK(hashlimit_lock); /* protects htables list */
+static DECLARE_LOCK(hashlimt_lock); /* protects htables list */
static DECLARE_MUTEX(hlimit_mutex); /* additional checkentry protection */
static HLIST_HEAD(hashlimit_htables);
static kmem_cache_t *hashlimit_cachep;
@@ -623,7 +623,7 @@
rateinfo_recalc(ent, jiffies);
return seq_printf(s, "%ld %u.%u.%u.%u:%u->%u.%u.%u.%u:%u %u %u %u\n",
- (ent->expires - jiffies)/HZ,
+ (long)(ent->expires - jiffies)/HZ,
NIPQUAD(ent->dst.src_ip), ntohs(ent->dst.src_port),
NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.dst_port),
ent->rateinfo.credit, ent->rateinfo.credit_cap,
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_osf.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_osf.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_osf.c Sat Jun 18 16:43:43 2005
@@ -90,45 +90,6 @@
.me = THIS_MODULE
};
-
-#ifdef CONFIG_CONNECTOR
-#include <linux/connector.h>
-
-/*
- * They should live in connector.h.
- */
-#define CN_IDX_OSF 0x0001
-#define CN_VAL_OSF 0x0000
-
-static char osf_finger_buf[sizeof(struct ipt_osf_nlmsg) + sizeof(struct cn_msg)];
-static struct cb_id osf_id = {CN_IDX_OSF, CN_VAL_OSF};
-static u32 osf_seq;
-
-static void ipt_osf_send_connector(struct osf_finger *f, const struct sk_buff *sk)
-{
- struct cn_msg *m;
- struct ipt_osf_nlmsg *data;
-
- m = (struct cn_msg *)osf_finger_buf;
- data = (struct ipt_osf_nlmsg *)(m+1);
-
- memcpy(&m->id, &osf_id, sizeof(m->id));
- m->seq = osf_seq++;
- m->ack = 0;
- m->len = sizeof(*data);
-
- memcpy(&data->f, f, sizeof(struct osf_finger));
- memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
- memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
-
- cn_netlink_send(m, m->id.idx, GFP_ATOMIC);
-}
-#else
-static void ipt_osf_send_connector(struct osf_finger *f, const struct sk_buff *sk)
-{
-}
-#endif
-
static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
{
unsigned int size;
@@ -136,9 +97,6 @@
struct ipt_osf_nlmsg *data;
struct nlmsghdr *nlh;
- if (!nts)
- return;
-
size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
skb = alloc_skb(size, GFP_ATOMIC);
@@ -385,18 +343,13 @@
ipt_osf_nlsend(f, skb);
spin_unlock_bh(&ipt_osf_netlink_lock);
}
- if (info->flags & IPT_OSF_CONNECTOR) {
- spin_lock_bh(&ipt_osf_netlink_lock);
- ipt_osf_send_connector(f, skb);
- spin_unlock_bh(&ipt_osf_netlink_lock);
- }
if ((info->flags & IPT_OSF_LOG) &&
info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
break;
}
}
}
- if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK | IPT_OSF_CONNECTOR))) {
+ if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK))) {
unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
unsigned int i, optsize;
struct osf_finger fg;
@@ -427,7 +380,7 @@
NIPQUAD(ip->saddr), ntohs(tcp->source),
NIPQUAD(ip->daddr), ntohs(tcp->dest));
- if (info->flags & (IPT_OSF_NETLINK | IPT_OSF_CONNECTOR)) {
+ if (info->flags & IPT_OSF_NETLINK) {
fg.wss.val = window;
fg.ttl = ip->ttl;
fg.df = df;
@@ -435,10 +388,7 @@
strncpy(fg.genre, "Unknown", MAXGENRELEN);
spin_lock_bh(&ipt_osf_netlink_lock);
- if (info->flags & IPT_OSF_NETLINK)
- ipt_osf_nlsend(&fg, skb);
- if (info->flags & IPT_OSF_CONNECTOR)
- ipt_osf_send_connector(&fg, skb);
+ ipt_osf_nlsend(&fg, skb);
spin_unlock_bh(&ipt_osf_netlink_lock);
}
}
@@ -824,6 +774,9 @@
nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
if (!nts) {
log("netlink_kernel_create() failed\n");
+ remove_proc_entry("sys/net/ipv4/osf", NULL);
+ ipt_unregister_match(&osf_match);
+ return -ENOMEM;
}
return 0;
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ip6_input.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ip6_input.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ip6_input.c Sat Jun 18 16:43:43 2005
@@ -71,10 +71,18 @@
goto out;
}
- /* Store incoming device index. When the packet will
- be queued, we cannot refer to skb->dev anymore.
+ /*
+ * Store incoming device index. When the packet will
+ * be queued, we cannot refer to skb->dev anymore.
+ *
+ * BTW, when we send a packet for our own local address on a
+ * non-loopback interface (e.g. ethX), it is being delivered
+ * via the loopback interface (lo) here; skb->dev = &loopback_dev.
+ * It, however, should be considered as if it is being
+ * arrived via the sending interface (ethX), because of the
+ * nature of scoping architecture. --yoshfuji
*/
- IP6CB(skb)->iif = dev->ifindex;
+ IP6CB(skb)->iif = skb->dst ? ((struct rt6_info *)skb->dst)->rt6i_idev->dev->ifindex : dev->ifindex;
if (skb->len < sizeof(struct ipv6hdr))
goto err;
@@ -95,15 +103,11 @@
if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
goto truncated;
- if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
- if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))){
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
- goto drop;
- }
- hdr = skb->nh.ipv6h;
- if (skb->ip_summed == CHECKSUM_HW)
- skb->ip_summed = CHECKSUM_NONE;
+ if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) {
+ IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ goto drop;
}
+ hdr = skb->nh.ipv6h;
}
if (hdr->nexthdr == NEXTHDR_HOP) {
@@ -138,7 +142,6 @@
unsigned int nhoff;
int nexthdr;
u8 hash;
- int cksum_sub = 0;
skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
@@ -173,11 +176,8 @@
if (ipprot->flags & INET6_PROTO_FINAL) {
struct ipv6hdr *hdr;
- if (!cksum_sub && skb->ip_summed == CHECKSUM_HW) {
- skb->csum = csum_sub(skb->csum,
- csum_partial(skb->nh.raw, skb->h.raw-skb->nh.raw, 0));
- cksum_sub++;
- }
+ skb_postpull_rcsum(skb, skb->nh.raw,
+ skb->h.raw - skb->nh.raw);
hdr = skb->nh.ipv6h;
if (ipv6_addr_is_multicast(&hdr->daddr) &&
!ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ip6_output.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ip6_output.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ip6_output.c Sat Jun 18 16:43:43 2005
@@ -147,7 +147,7 @@
int ip6_output(struct sk_buff *skb)
{
- if (skb->len > dst_pmtu(skb->dst))
+ if (skb->len > dst_mtu(skb->dst) || dst_allfrag(skb->dst))
return ip6_fragment(skb, ip6_output2);
else
return ip6_output2(skb);
@@ -253,6 +253,8 @@
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ if (hlimit < 0)
+ hlimit = ipv6_get_hoplimit(dst->dev);
hdr->payload_len = htons(seg_len);
hdr->nexthdr = proto;
@@ -261,7 +263,7 @@
ipv6_addr_copy(&hdr->saddr, &fl->fl6_src);
ipv6_addr_copy(&hdr->daddr, first_hop);
- mtu = dst_pmtu(dst);
+ mtu = dst_mtu(dst);
if ((skb->len <= mtu) || ipfragok) {
IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
@@ -395,6 +397,7 @@
IP6_INC_STATS(IPSTATS_MIB_INDISCARDS);
goto drop;
}
+ dst = skb->dst;
/* IPv6 specs say nothing about it, but it is clear that we cannot
send redirects to source routed frames.
@@ -426,10 +429,10 @@
goto error;
}
- if (skb->len > dst_pmtu(dst)) {
+ if (skb->len > dst_mtu(dst)) {
/* Again, force OUTPUT device used as source address */
skb->dev = dst->dev;
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_pmtu(dst), skb->dev);
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev);
IP6_INC_STATS_BH(IPSTATS_MIB_INTOOBIGERRORS);
IP6_INC_STATS_BH(IPSTATS_MIB_FRAGFAILS);
kfree_skb(skb);
@@ -538,7 +541,7 @@
hlen = ip6_find_1stfragopt(skb, &prevhdr);
nexthdr = *prevhdr;
- mtu = dst_pmtu(&rt->u.dst) - hlen - sizeof(struct frag_hdr);
+ mtu = dst_mtu(&rt->u.dst) - hlen - sizeof(struct frag_hdr);
if (skb_shinfo(skb)->frag_list) {
int first_len = skb_pagelen(skb);
@@ -555,13 +558,17 @@
skb_headroom(frag) < hlen)
goto slow_path;
- /* Correct socket ownership. */
- if (frag->sk == NULL)
- goto slow_path;
-
/* Partially cloned skb? */
if (skb_shared(frag))
goto slow_path;
+
+ BUG_ON(frag->sk);
+ if (skb->sk) {
+ sock_hold(skb->sk);
+ frag->sk = skb->sk;
+ frag->destructor = sock_wfree;
+ skb->truesize -= frag->truesize;
+ }
}
err = 0;
@@ -853,7 +860,9 @@
np->cork.rt = rt;
inet->cork.fl = *fl;
np->cork.hop_limit = hlimit;
- inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
+ inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path);
+ if (dst_allfrag(rt->u.dst.path))
+ inet->cork.flags |= IPCORK_ALLFRAG;
inet->cork.length = 0;
sk->sk_sndmsg_page = NULL;
sk->sk_sndmsg_off = 0;
@@ -905,7 +914,7 @@
while (length > 0) {
/* Check if the remaining data fits into current packet. */
- copy = mtu - skb->len;
+ copy = (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len;
if (copy < length)
copy = maxfraglen - skb->len;
@@ -930,7 +939,7 @@
* we know we need more fragment(s).
*/
datalen = length + fraggap;
- if (datalen > mtu - fragheaderlen)
+ if (datalen > (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
datalen = maxfraglen - fragheaderlen;
fraglen = datalen + fragheaderlen;
@@ -1117,12 +1126,10 @@
tail_skb = &(tmp_skb->next);
skb->len += tmp_skb->len;
skb->data_len += tmp_skb->len;
-#if 0 /* Logically correct, but useless work, ip_fragment() will have to undo */
skb->truesize += tmp_skb->truesize;
__sock_put(tmp_skb->sk);
tmp_skb->destructor = NULL;
tmp_skb->sk = NULL;
-#endif
}
ipv6_addr_copy(final_dst, &fl->fl6_dst);
@@ -1150,7 +1157,7 @@
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);
if (err) {
if (err > 0)
- err = inet->recverr ? net_xmit_errno(err) : 0;
+ err = np->recverr ? net_xmit_errno(err) : 0;
if (err)
goto error;
}
@@ -1164,6 +1171,7 @@
if (np->cork.rt) {
dst_release(&np->cork.rt->u.dst);
np->cork.rt = NULL;
+ inet->cork.flags &= ~IPCORK_ALLFRAG;
}
memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
return err;
@@ -1191,6 +1199,7 @@
if (np->cork.rt) {
dst_release(&np->cork.rt->u.dst);
np->cork.rt = NULL;
+ inet->cork.flags &= ~IPCORK_ALLFRAG;
}
memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
}
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ipv6_syms.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ipv6_syms.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ipv6_syms.c Sat Jun 18 16:43:43 2005
@@ -38,6 +38,5 @@
#endif
EXPORT_SYMBOL(nd_tbl);
EXPORT_SYMBOL(rt6_lookup);
-EXPORT_SYMBOL(fl6_sock_lookup);
EXPORT_SYMBOL(ipv6_push_nfrag_opts);
EXPORT_SYMBOL(ip6_dst_lookup);
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Kconfig
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Kconfig (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Kconfig Sat Jun 18 16:43:43 2005
@@ -2,8 +2,8 @@
# IP netfilter configuration
#
-menu "IPv6: Netfilter Configuration"
- depends on INET && IPV6 && NETFILTER
+menu "IPv6: Netfilter Configuration (EXPERIMENTAL)"
+ depends on INET && IPV6 && NETFILTER && EXPERIMENTAL
#tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP6_NF_CONNTRACK
#if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/ip6_queue.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/ip6_queue.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/ip6_queue.c Sat Jun 18 16:43:43 2005
@@ -20,6 +20,9 @@
* Few changes needed, mainly the hard_routing code and
* the netlink socket protocol (we're NETLINK_IP6_FW).
* 2002-06-25: Code cleanup. [JM: ported cleanup over from ip_queue.c]
+ * 2005-02-04: Added /proc counter for dropped packets; fixed so
+ * packets aren't delivered to user space if they're going
+ * to be dropped.
*/
#include <linux/module.h>
#include <linux/skbuff.h>
@@ -64,6 +67,8 @@
static int peer_pid;
static unsigned int copy_range;
static unsigned int queue_total;
+static unsigned int queue_dropped = 0;
+static unsigned int queue_user_dropped = 0;
static struct sock *ipqnl;
static LIST_HEAD(queue_list);
static DECLARE_MUTEX(ipqnl_sem);
@@ -75,18 +80,11 @@
kfree(entry);
}
-static inline int
+static inline void
__ipq_enqueue_entry(struct ipq_queue_entry *entry)
{
- if (queue_total >= queue_maxlen) {
- if (net_ratelimit())
- printk(KERN_WARNING "ip6_queue: full at %d entries, "
- "dropping packet(s).\n", queue_total);
- return -ENOSPC;
- }
list_add(&entry->list, &queue_list);
queue_total++;
- return 0;
}
/*
@@ -312,14 +310,24 @@
if (!peer_pid)
goto err_out_free_nskb;
+ if (queue_total >= queue_maxlen) {
+ queue_dropped++;
+ status = -ENOSPC;
+ if (net_ratelimit())
+ printk (KERN_WARNING "ip6_queue: fill at %d entries, "
+ "dropping packet(s). Dropped: %d\n", queue_total,
+ queue_dropped);
+ goto err_out_free_nskb;
+ }
+
/* netlink_unicast will either free the nskb or attach it to a socket */
status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
- if (status < 0)
+ if (status < 0) {
+ queue_user_dropped++;
goto err_out_unlock;
+ }
- status = __ipq_enqueue_entry(entry);
- if (status < 0)
- goto err_out_unlock;
+ __ipq_enqueue_entry(entry);
write_unlock_bh(&queue_lock);
return status;
@@ -541,20 +549,18 @@
static void
ipq_rcv_sk(struct sock *sk, int len)
{
- do {
- struct sk_buff *skb;
+ struct sk_buff *skb;
+ unsigned int qlen;
- if (down_trylock(&ipqnl_sem))
- return;
+ down(&ipqnl_sem);
- while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
- ipq_rcv_skb(skb);
- kfree_skb(skb);
- }
+ for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
+ skb = skb_dequeue(&sk->sk_receive_queue);
+ ipq_rcv_skb(skb);
+ kfree_skb(skb);
+ }
- up(&ipqnl_sem);
-
- } while (ipqnl && ipqnl->sk_receive_queue.qlen);
+ up(&ipqnl_sem);
}
static int
@@ -639,12 +645,16 @@
"Copy mode : %hu\n"
"Copy range : %u\n"
"Queue length : %u\n"
- "Queue max. length : %u\n",
+ "Queue max. length : %u\n"
+ "Queue dropped : %u\n"
+ "Netfilter dropped : %u\n",
peer_pid,
copy_mode,
copy_range,
queue_total,
- queue_maxlen);
+ queue_maxlen,
+ queue_dropped,
+ queue_user_dropped);
read_unlock_bh(&queue_lock);
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/ip6_tables.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/ip6_tables.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/ip6_tables.c Sat Jun 18 16:43:43 2005
@@ -952,7 +952,7 @@
}
/* And one copy for every other CPU */
- for (i = 1; i < NR_CPUS; i++) {
+ for (i = 1; i < num_possible_cpus(); i++) {
memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
newinfo->entries,
SMP_ALIGN(newinfo->size));
@@ -974,7 +974,7 @@
struct ip6t_entry *table_base;
unsigned int i;
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < num_possible_cpus(); i++) {
table_base =
(void *)newinfo->entries
+ TABLE_OFFSET(newinfo, i);
@@ -1021,7 +1021,7 @@
unsigned int cpu;
unsigned int i;
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
i = 0;
IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
t->size,
@@ -1155,7 +1155,7 @@
return -ENOMEM;
newinfo = vmalloc(sizeof(struct ip6t_table_info)
- + SMP_ALIGN(tmp.size) * NR_CPUS);
+ + SMP_ALIGN(tmp.size) * num_possible_cpus());
if (!newinfo)
return -ENOMEM;
@@ -1469,7 +1469,7 @@
= { 0, 0, 0, { 0 }, { 0 }, { } };
newinfo = vmalloc(sizeof(struct ip6t_table_info)
- + SMP_ALIGN(repl->size) * NR_CPUS);
+ + SMP_ALIGN(repl->size) * num_possible_cpus());
if (!newinfo)
return -ENOMEM;
More information about the pld-cvs-commit
mailing list