Browse Source

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

Linus Torvalds 19 years ago
parent
commit
02d31ed258

+ 8 - 4
include/linux/netfilter/nfnetlink.h

@@ -41,11 +41,15 @@ enum nfnetlink_groups {
 struct nfattr
 struct nfattr
 {
 {
 	u_int16_t nfa_len;
 	u_int16_t nfa_len;
-	u_int16_t nfa_type;
+	u_int16_t nfa_type;	/* we use 15 bits for the type, and the highest
+				 * bit to indicate whether the payload is nested */
 } __attribute__ ((packed));
 } __attribute__ ((packed));
 
 
-/* FIXME: Shamelessly copy and pasted from rtnetlink.h, it's time
- * 	  to put this in a generic file */
+/* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from
+ * rtnetlink.h, it's time to put this in a generic file */
+
+#define NFNL_NFA_NEST	0x8000
+#define NFA_TYPE(attr) 	((attr)->nfa_type & 0x7fff)
 
 
 #define NFA_ALIGNTO     4
 #define NFA_ALIGNTO     4
 #define NFA_ALIGN(len)	(((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
 #define NFA_ALIGN(len)	(((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
@@ -59,7 +63,7 @@ struct nfattr
 #define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
 #define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
 #define NFA_NEST(skb, type) \
 #define NFA_NEST(skb, type) \
 ({	struct nfattr *__start = (struct nfattr *) (skb)->tail; \
 ({	struct nfattr *__start = (struct nfattr *) (skb)->tail; \
-	NFA_PUT(skb, type, 0, NULL); \
+	NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \
 	__start;  })
 	__start;  })
 #define NFA_NEST_END(skb, start) \
 #define NFA_NEST_END(skb, start) \
 ({      (start)->nfa_len = ((skb)->tail - (unsigned char *) (start)); \
 ({      (start)->nfa_len = ((skb)->tail - (unsigned char *) (start)); \

+ 12 - 3
include/linux/netfilter/nfnetlink_conntrack.h

@@ -70,15 +70,24 @@ enum ctattr_l4proto {
 
 
 enum ctattr_protoinfo {
 enum ctattr_protoinfo {
 	CTA_PROTOINFO_UNSPEC,
 	CTA_PROTOINFO_UNSPEC,
-	CTA_PROTOINFO_TCP_STATE,
+	CTA_PROTOINFO_TCP,
 	__CTA_PROTOINFO_MAX
 	__CTA_PROTOINFO_MAX
 };
 };
 #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
 #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
 
 
+enum ctattr_protoinfo_tcp {
+	CTA_PROTOINFO_TCP_UNSPEC,
+	CTA_PROTOINFO_TCP_STATE,
+	__CTA_PROTOINFO_TCP_MAX
+};
+#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)
+
 enum ctattr_counters {
 enum ctattr_counters {
 	CTA_COUNTERS_UNSPEC,
 	CTA_COUNTERS_UNSPEC,
-	CTA_COUNTERS_PACKETS,
-	CTA_COUNTERS_BYTES,
+	CTA_COUNTERS_PACKETS,		/* old 64bit counters */
+	CTA_COUNTERS_BYTES,		/* old 64bit counters */
+	CTA_COUNTERS32_PACKETS,
+	CTA_COUNTERS32_BYTES,
 	__CTA_COUNTERS_MAX
 	__CTA_COUNTERS_MAX
 };
 };
 #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
 #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)

+ 6 - 2
include/linux/netfilter_ipv4/ip_conntrack.h

@@ -117,6 +117,10 @@ enum ip_conntrack_events
 	/* NAT info */
 	/* NAT info */
 	IPCT_NATINFO_BIT = 10,
 	IPCT_NATINFO_BIT = 10,
 	IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
 	IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
+
+	/* Counter highest bit has been set */
+	IPCT_COUNTER_FILLING_BIT = 11,
+	IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
 };
 };
 
 
 enum ip_conntrack_expect_events {
 enum ip_conntrack_expect_events {
@@ -192,8 +196,8 @@ do {									\
 
 
 struct ip_conntrack_counter
 struct ip_conntrack_counter
 {
 {
-	u_int64_t packets;
-	u_int64_t bytes;
+	u_int32_t packets;
+	u_int32_t bytes;
 };
 };
 
 
 struct ip_conntrack_helper;
 struct ip_conntrack_helper;

+ 3 - 0
include/linux/netfilter_ipv4/ip_conntrack_protocol.h

@@ -52,6 +52,9 @@ struct ip_conntrack_protocol
 	int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
 	int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
 			 const struct ip_conntrack *ct);
 			 const struct ip_conntrack *ct);
 
 
+	/* convert nfnetlink attributes to protoinfo */
+	int (*from_nfattr)(struct nfattr *tb[], struct ip_conntrack *ct);
+
 	int (*tuple_to_nfattr)(struct sk_buff *skb,
 	int (*tuple_to_nfattr)(struct sk_buff *skb,
 			       const struct ip_conntrack_tuple *t);
 			       const struct ip_conntrack_tuple *t);
 	int (*nfattr_to_tuple)(struct nfattr *tb[],
 	int (*nfattr_to_tuple)(struct nfattr *tb[],

+ 2 - 0
include/linux/netfilter_ipv4/ip_conntrack_tuple.h

@@ -1,6 +1,8 @@
 #ifndef _IP_CONNTRACK_TUPLE_H
 #ifndef _IP_CONNTRACK_TUPLE_H
 #define _IP_CONNTRACK_TUPLE_H
 #define _IP_CONNTRACK_TUPLE_H
 
 
+#include <linux/types.h>
+
 /* A `tuple' is a structure containing the information to uniquely
 /* A `tuple' is a structure containing the information to uniquely
   identify a connection.  ie. if two packets have the same tuple, they
   identify a connection.  ie. if two packets have the same tuple, they
   are in the same connection; if not, they are not.
   are in the same connection; if not, they are not.

+ 0 - 4
include/linux/netfilter_ipv4/ip_nat.h

@@ -58,10 +58,6 @@ extern rwlock_t ip_nat_lock;
 struct ip_nat_info
 struct ip_nat_info
 {
 {
 	struct list_head bysource;
 	struct list_head bysource;
-
-	/* Helper (NULL if none). */
-	struct ip_nat_helper *helper;
-
 	struct ip_nat_seq seq[IP_CT_DIR_MAX];
 	struct ip_nat_seq seq[IP_CT_DIR_MAX];
 };
 };
 
 

+ 1 - 1
include/linux/netpoll.h

@@ -86,7 +86,7 @@ static inline void netpoll_poll_unlock(void *have)
 
 
 #else
 #else
 #define netpoll_rx(a) 0
 #define netpoll_rx(a) 0
-#define netpoll_poll_lock(a) 0
+#define netpoll_poll_lock(a) NULL
 #define netpoll_poll_unlock(a)
 #define netpoll_poll_unlock(a)
 #endif
 #endif
 
 

+ 3 - 0
include/net/inet_timewait_sock.h

@@ -19,6 +19,7 @@
 
 
 #include <linux/ip.h>
 #include <linux/ip.h>
 #include <linux/list.h>
 #include <linux/list.h>
+#include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/timer.h>
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
@@ -193,11 +194,13 @@ static inline u32 inet_rcv_saddr(const struct sock *sk)
 static inline void inet_twsk_put(struct inet_timewait_sock *tw)
 static inline void inet_twsk_put(struct inet_timewait_sock *tw)
 {
 {
 	if (atomic_dec_and_test(&tw->tw_refcnt)) {
 	if (atomic_dec_and_test(&tw->tw_refcnt)) {
+		struct module *owner = tw->tw_prot->owner;
 #ifdef SOCK_REFCNT_DEBUG
 #ifdef SOCK_REFCNT_DEBUG
 		printk(KERN_DEBUG "%s timewait_sock %p released\n",
 		printk(KERN_DEBUG "%s timewait_sock %p released\n",
 		       tw->tw_prot->name, tw);
 		       tw->tw_prot->name, tw);
 #endif
 #endif
 		kmem_cache_free(tw->tw_prot->twsk_slab, tw);
 		kmem_cache_free(tw->tw_prot->twsk_slab, tw);
+		module_put(owner);
 	}
 	}
 }
 }
 
 

+ 1 - 1
net/bridge/br_if.c

@@ -79,7 +79,6 @@ static void destroy_nbp(struct net_bridge_port *p)
 {
 {
 	struct net_device *dev = p->dev;
 	struct net_device *dev = p->dev;
 
 
-	dev->br_port = NULL;
 	p->br = NULL;
 	p->br = NULL;
 	p->dev = NULL;
 	p->dev = NULL;
 	dev_put(dev);
 	dev_put(dev);
@@ -100,6 +99,7 @@ static void del_nbp(struct net_bridge_port *p)
 	struct net_bridge *br = p->br;
 	struct net_bridge *br = p->br;
 	struct net_device *dev = p->dev;
 	struct net_device *dev = p->dev;
 
 
+	dev->br_port = NULL;
 	dev_set_promiscuity(dev, -1);
 	dev_set_promiscuity(dev, -1);
 
 
 	spin_lock_bh(&br->lock);
 	spin_lock_bh(&br->lock);

+ 2 - 2
net/dccp/ccid.h

@@ -110,14 +110,14 @@ static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk)
 
 
 static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk)
 static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk)
 {
 {
-	if (ccid->ccid_hc_rx_exit != NULL &&
+	if (ccid != NULL && ccid->ccid_hc_rx_exit != NULL &&
 	    dccp_sk(sk)->dccps_hc_rx_ccid_private != NULL)
 	    dccp_sk(sk)->dccps_hc_rx_ccid_private != NULL)
 		ccid->ccid_hc_rx_exit(sk);
 		ccid->ccid_hc_rx_exit(sk);
 }
 }
 
 
 static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk)
 static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk)
 {
 {
-	if (ccid->ccid_hc_tx_exit != NULL &&
+	if (ccid != NULL && ccid->ccid_hc_tx_exit != NULL &&
 	    dccp_sk(sk)->dccps_hc_tx_ccid_private != NULL)
 	    dccp_sk(sk)->dccps_hc_tx_ccid_private != NULL)
 		ccid->ccid_hc_tx_exit(sk);
 		ccid->ccid_hc_tx_exit(sk);
 }
 }

+ 5 - 1
net/dccp/input.c

@@ -375,6 +375,9 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
 	case DCCP_PKT_RESET:
 	case DCCP_PKT_RESET:
 		inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
 		inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
 		break;
 		break;
+	case DCCP_PKT_DATA:
+		if (sk->sk_state == DCCP_RESPOND)
+			break;
 	case DCCP_PKT_DATAACK:
 	case DCCP_PKT_DATAACK:
 	case DCCP_PKT_ACK:
 	case DCCP_PKT_ACK:
 		/*
 		/*
@@ -393,7 +396,8 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
 		dccp_sk(sk)->dccps_osr = DCCP_SKB_CB(skb)->dccpd_seq;
 		dccp_sk(sk)->dccps_osr = DCCP_SKB_CB(skb)->dccpd_seq;
 		dccp_set_state(sk, DCCP_OPEN);
 		dccp_set_state(sk, DCCP_OPEN);
 
 
-		if (dh->dccph_type == DCCP_PKT_DATAACK) {
+		if (dh->dccph_type == DCCP_PKT_DATAACK ||
+		    dh->dccph_type == DCCP_PKT_DATA) {
 			dccp_rcv_established(sk, skb, dh, len);
 			dccp_rcv_established(sk, skb, dh, len);
 			queued = 1; /* packet was queued
 			queued = 1; /* packet was queued
 				       (by dccp_rcv_established) */
 				       (by dccp_rcv_established) */

+ 9 - 8
net/ipv4/esp4.c

@@ -5,6 +5,7 @@
 #include <net/esp.h>
 #include <net/esp.h>
 #include <asm/scatterlist.h>
 #include <asm/scatterlist.h>
 #include <linux/crypto.h>
 #include <linux/crypto.h>
+#include <linux/kernel.h>
 #include <linux/pfkeyv2.h>
 #include <linux/pfkeyv2.h>
 #include <linux/random.h>
 #include <linux/random.h>
 #include <net/icmp.h>
 #include <net/icmp.h>
@@ -42,10 +43,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 	esp = x->data;
 	esp = x->data;
 	alen = esp->auth.icv_trunc_len;
 	alen = esp->auth.icv_trunc_len;
 	tfm = esp->conf.tfm;
 	tfm = esp->conf.tfm;
-	blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3;
-	clen = (clen + 2 + blksize-1)&~(blksize-1);
+	blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4);
+	clen = ALIGN(clen + 2, blksize);
 	if (esp->conf.padlen)
 	if (esp->conf.padlen)
-		clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+		clen = ALIGN(clen, esp->conf.padlen);
 
 
 	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0)
 	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0)
 		goto error;
 		goto error;
@@ -143,7 +144,7 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
 	struct ip_esp_hdr *esph;
 	struct ip_esp_hdr *esph;
 	struct esp_data *esp = x->data;
 	struct esp_data *esp = x->data;
 	struct sk_buff *trailer;
 	struct sk_buff *trailer;
-	int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+	int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
 	int alen = esp->auth.icv_trunc_len;
 	int alen = esp->auth.icv_trunc_len;
 	int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
 	int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
 	int nfrags;
 	int nfrags;
@@ -304,16 +305,16 @@ static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap,
 static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)
 static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)
 {
 {
 	struct esp_data *esp = x->data;
 	struct esp_data *esp = x->data;
-	u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+	u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
 
 
 	if (x->props.mode) {
 	if (x->props.mode) {
-		mtu = (mtu + 2 + blksize-1)&~(blksize-1);
+		mtu = ALIGN(mtu + 2, blksize);
 	} else {
 	} else {
 		/* The worst case. */
 		/* The worst case. */
-		mtu += 2 + blksize;
+		mtu = ALIGN(mtu + 2, 4) + blksize - 4;
 	}
 	}
 	if (esp->conf.padlen)
 	if (esp->conf.padlen)
-		mtu = (mtu + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+		mtu = ALIGN(mtu, esp->conf.padlen);
 
 
 	return mtu + x->props.header_len + esp->auth.icv_trunc_len;
 	return mtu + x->props.header_len + esp->auth.icv_trunc_len;
 }
 }

+ 1 - 0
net/ipv4/inet_timewait_sock.c

@@ -111,6 +111,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
 		tw->tw_prot	    = sk->sk_prot_creator;
 		tw->tw_prot	    = sk->sk_prot_creator;
 		atomic_set(&tw->tw_refcnt, 1);
 		atomic_set(&tw->tw_refcnt, 1);
 		inet_twsk_dead_node_init(tw);
 		inet_twsk_dead_node_init(tw);
+		__module_get(tw->tw_prot->owner);
 	}
 	}
 
 
 	return tw;
 	return tw;

+ 7 - 1
net/ipv4/netfilter/Kconfig

@@ -139,6 +139,7 @@ config IP_NF_AMANDA
 
 
 config IP_NF_PPTP
 config IP_NF_PPTP
 	tristate  'PPTP protocol support'
 	tristate  'PPTP protocol support'
+	depends on IP_NF_CONNTRACK
 	help
 	help
 	  This module adds support for PPTP (Point to Point Tunnelling
 	  This module adds support for PPTP (Point to Point Tunnelling
 	  Protocol, RFC2637) connection tracking and NAT. 
 	  Protocol, RFC2637) connection tracking and NAT. 
@@ -498,9 +499,14 @@ config IP_NF_TARGET_LOG
 	  To compile it as a module, choose M here.  If unsure, say N.
 	  To compile it as a module, choose M here.  If unsure, say N.
 
 
 config IP_NF_TARGET_ULOG
 config IP_NF_TARGET_ULOG
-	tristate "ULOG target support"
+	tristate "ULOG target support (OBSOLETE)"
 	depends on IP_NF_IPTABLES
 	depends on IP_NF_IPTABLES
 	---help---
 	---help---
+
+	  This option enables the old IPv4-only "ipt_ULOG" implementation
+	  which has been obsoleted by the new "nfnetlink_log" code (see
+	  CONFIG_NETFILTER_NETLINK_LOG).
+
 	  This option adds a `ULOG' target, which allows you to create rules in
 	  This option adds a `ULOG' target, which allows you to create rules in
 	  any iptables table. The packet is passed to a userspace logging
 	  any iptables table. The packet is passed to a userspace logging
 	  daemon using netlink multicast sockets; unlike the LOG target
 	  daemon using netlink multicast sockets; unlike the LOG target

+ 8 - 5
net/ipv4/netfilter/ip_conntrack_core.c

@@ -1119,7 +1119,7 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct,
 			unsigned long extra_jiffies,
 			unsigned long extra_jiffies,
 			int do_acct)
 			int do_acct)
 {
 {
-	int do_event = 0;
+	int event = 0;
 
 
 	IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
 	IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
 	IP_NF_ASSERT(skb);
 	IP_NF_ASSERT(skb);
@@ -1129,13 +1129,13 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct,
 	/* If not in hash table, timer will not be active yet */
 	/* If not in hash table, timer will not be active yet */
 	if (!is_confirmed(ct)) {
 	if (!is_confirmed(ct)) {
 		ct->timeout.expires = extra_jiffies;
 		ct->timeout.expires = extra_jiffies;
-		do_event = 1;
+		event = IPCT_REFRESH;
 	} else {
 	} else {
 		/* Need del_timer for race avoidance (may already be dying). */
 		/* Need del_timer for race avoidance (may already be dying). */
 		if (del_timer(&ct->timeout)) {
 		if (del_timer(&ct->timeout)) {
 			ct->timeout.expires = jiffies + extra_jiffies;
 			ct->timeout.expires = jiffies + extra_jiffies;
 			add_timer(&ct->timeout);
 			add_timer(&ct->timeout);
-			do_event = 1;
+			event = IPCT_REFRESH;
 		}
 		}
 	}
 	}
 
 
@@ -1144,14 +1144,17 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct,
 		ct->counters[CTINFO2DIR(ctinfo)].packets++;
 		ct->counters[CTINFO2DIR(ctinfo)].packets++;
 		ct->counters[CTINFO2DIR(ctinfo)].bytes += 
 		ct->counters[CTINFO2DIR(ctinfo)].bytes += 
 						ntohs(skb->nh.iph->tot_len);
 						ntohs(skb->nh.iph->tot_len);
+		if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
+		    || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
+			event |= IPCT_COUNTER_FILLING;
 	}
 	}
 #endif
 #endif
 
 
 	write_unlock_bh(&ip_conntrack_lock);
 	write_unlock_bh(&ip_conntrack_lock);
 
 
 	/* must be unlocked when calling event cache */
 	/* must be unlocked when calling event cache */
-	if (do_event)
-		ip_conntrack_event_cache(IPCT_REFRESH, skb);
+	if (event)
+		ip_conntrack_event_cache(event, skb);
 }
 }
 
 
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \

+ 43 - 5
net/ipv4/netfilter/ip_conntrack_netlink.c

@@ -177,11 +177,11 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct ip_conntrack *ct,
 	struct nfattr *nest_count = NFA_NEST(skb, type);
 	struct nfattr *nest_count = NFA_NEST(skb, type);
 	u_int64_t tmp;
 	u_int64_t tmp;
 
 
-	tmp = cpu_to_be64(ct->counters[dir].packets);
-	NFA_PUT(skb, CTA_COUNTERS_PACKETS, sizeof(u_int64_t), &tmp);
+	tmp = htonl(ct->counters[dir].packets);
+	NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
 
 
-	tmp = cpu_to_be64(ct->counters[dir].bytes);
-	NFA_PUT(skb, CTA_COUNTERS_BYTES, sizeof(u_int64_t), &tmp);
+	tmp = htonl(ct->counters[dir].bytes);
+	NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp);
 
 
 	NFA_NEST_END(skb, nest_count);
 	NFA_NEST_END(skb, nest_count);
 
 
@@ -833,7 +833,8 @@ out:
 static inline int
 static inline int
 ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[])
 ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[])
 {
 {
-	unsigned long d, status = *(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]);
+	unsigned long d;
+	unsigned status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]));
 	d = ct->status ^ status;
 	d = ct->status ^ status;
 
 
 	if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
 	if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
@@ -948,6 +949,31 @@ ctnetlink_change_timeout(struct ip_conntrack *ct, struct nfattr *cda[])
 	return 0;
 	return 0;
 }
 }
 
 
+static inline int
+ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[])
+{
+	struct nfattr *tb[CTA_PROTOINFO_MAX], *attr = cda[CTA_PROTOINFO-1];
+	struct ip_conntrack_protocol *proto;
+	u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
+	int err = 0;
+
+	if (nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr) < 0)
+		goto nfattr_failure;
+
+	proto = ip_conntrack_proto_find_get(npt);
+	if (!proto)
+		return -EINVAL;
+
+	if (proto->from_nfattr)
+		err = proto->from_nfattr(tb, ct);
+	ip_conntrack_proto_put(proto); 
+
+	return err;
+
+nfattr_failure:
+	return -ENOMEM;
+}
+
 static int
 static int
 ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
 ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
 {
 {
@@ -973,6 +999,12 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
 			return err;
 			return err;
 	}
 	}
 
 
+	if (cda[CTA_PROTOINFO-1]) {
+		err = ctnetlink_change_protoinfo(ct, cda);
+		if (err < 0)
+			return err;
+	}
+
 	DEBUGP("all done\n");
 	DEBUGP("all done\n");
 	return 0;
 	return 0;
 }
 }
@@ -1002,6 +1034,12 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
 	if (err < 0)
 	if (err < 0)
 		goto err;
 		goto err;
 
 
+	if (cda[CTA_PROTOINFO-1]) {
+		err = ctnetlink_change_protoinfo(ct, cda);
+		if (err < 0)
+			return err;
+	}
+
 	ct->helper = ip_conntrack_helper_find_get(rtuple);
 	ct->helper = ip_conntrack_helper_find_get(rtuple);
 
 
 	add_timer(&ct->timeout);
 	add_timer(&ct->timeout);

+ 1 - 2
net/ipv4/netfilter/ip_conntrack_proto_icmp.c

@@ -296,8 +296,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[],
 				struct ip_conntrack_tuple *tuple)
 				struct ip_conntrack_tuple *tuple)
 {
 {
 	if (!tb[CTA_PROTO_ICMP_TYPE-1]
 	if (!tb[CTA_PROTO_ICMP_TYPE-1]
-	    || !tb[CTA_PROTO_ICMP_CODE-1]
-	    || !tb[CTA_PROTO_ICMP_ID-1])
+	    || !tb[CTA_PROTO_ICMP_CODE-1])
 		return -1;
 		return -1;
 
 
 	tuple->dst.u.icmp.type = 
 	tuple->dst.u.icmp.type = 

+ 27 - 0
net/ipv4/netfilter/ip_conntrack_proto_tcp.c

@@ -341,17 +341,43 @@ static int tcp_print_conntrack(struct seq_file *s,
 static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
 static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
 			 const struct ip_conntrack *ct)
 			 const struct ip_conntrack *ct)
 {
 {
+	struct nfattr *nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
+	
 	read_lock_bh(&tcp_lock);
 	read_lock_bh(&tcp_lock);
 	NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
 	NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
 		&ct->proto.tcp.state);
 		&ct->proto.tcp.state);
 	read_unlock_bh(&tcp_lock);
 	read_unlock_bh(&tcp_lock);
 
 
+	NFA_NEST_END(skb, nest_parms);
+
 	return 0;
 	return 0;
 
 
 nfattr_failure:
 nfattr_failure:
 	read_unlock_bh(&tcp_lock);
 	read_unlock_bh(&tcp_lock);
 	return -1;
 	return -1;
 }
 }
+
+static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct)
+{
+	struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1];
+	struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];
+
+        if (nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr) < 0)
+                goto nfattr_failure;
+
+	if (!tb[CTA_PROTOINFO_TCP_STATE-1])
+		return -EINVAL;
+
+	write_lock_bh(&tcp_lock);
+	ct->proto.tcp.state = 
+		*(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
+	write_unlock_bh(&tcp_lock);
+
+	return 0;
+
+nfattr_failure:
+	return -1;
+}
 #endif
 #endif
 
 
 static unsigned int get_conntrack_index(const struct tcphdr *tcph)
 static unsigned int get_conntrack_index(const struct tcphdr *tcph)
@@ -1123,6 +1149,7 @@ struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
     defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
     defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
 	.to_nfattr		= tcp_to_nfattr,
 	.to_nfattr		= tcp_to_nfattr,
+	.from_nfattr		= nfattr_to_tcp,
 	.tuple_to_nfattr	= ip_ct_port_tuple_to_nfattr,
 	.tuple_to_nfattr	= ip_ct_port_tuple_to_nfattr,
 	.nfattr_to_tuple	= ip_ct_port_nfattr_to_tuple,
 	.nfattr_to_tuple	= ip_ct_port_nfattr_to_tuple,
 #endif
 #endif

+ 8 - 1
net/ipv4/tcp_output.c

@@ -435,7 +435,14 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
 	int nsize, old_factor;
 	int nsize, old_factor;
 	u16 flags;
 	u16 flags;
 
 
-	BUG_ON(len >= skb->len);
+	if (unlikely(len >= skb->len)) {
+		printk(KERN_DEBUG "TCP: seg_size=%u, mss=%u, seq=%u, "
+		       "end_seq=%u, skb->len=%u.\n", len, mss_now,
+		       TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
+		       skb->len);
+		WARN_ON(1);
+		return 0;
+	}
 
 
 	nsize = skb_headlen(skb) - len;
 	nsize = skb_headlen(skb) - len;
 	if (nsize < 0)
 	if (nsize < 0)

+ 10 - 8
net/ipv6/esp6.c

@@ -31,6 +31,7 @@
 #include <net/esp.h>
 #include <net/esp.h>
 #include <asm/scatterlist.h>
 #include <asm/scatterlist.h>
 #include <linux/crypto.h>
 #include <linux/crypto.h>
+#include <linux/kernel.h>
 #include <linux/pfkeyv2.h>
 #include <linux/pfkeyv2.h>
 #include <linux/random.h>
 #include <linux/random.h>
 #include <net/icmp.h>
 #include <net/icmp.h>
@@ -66,10 +67,10 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
 
 
 	alen = esp->auth.icv_trunc_len;
 	alen = esp->auth.icv_trunc_len;
 	tfm = esp->conf.tfm;
 	tfm = esp->conf.tfm;
-	blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3;
-	clen = (clen + 2 + blksize-1)&~(blksize-1);
+	blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4);
+	clen = ALIGN(clen + 2, blksize);
 	if (esp->conf.padlen)
 	if (esp->conf.padlen)
-		clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+		clen = ALIGN(clen, esp->conf.padlen);
 
 
 	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) {
 	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) {
 		goto error;
 		goto error;
@@ -133,7 +134,7 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru
 	struct ipv6_esp_hdr *esph;
 	struct ipv6_esp_hdr *esph;
 	struct esp_data *esp = x->data;
 	struct esp_data *esp = x->data;
 	struct sk_buff *trailer;
 	struct sk_buff *trailer;
-	int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+	int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
 	int alen = esp->auth.icv_trunc_len;
 	int alen = esp->auth.icv_trunc_len;
 	int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen;
 	int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen;
 
 
@@ -235,16 +236,17 @@ out_nofree:
 static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
 static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
 {
 {
 	struct esp_data *esp = x->data;
 	struct esp_data *esp = x->data;
-	u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+	u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
 
 
 	if (x->props.mode) {
 	if (x->props.mode) {
-		mtu = (mtu + 2 + blksize-1)&~(blksize-1);
+		mtu = ALIGN(mtu + 2, blksize);
 	} else {
 	} else {
 		/* The worst case. */
 		/* The worst case. */
-		mtu += 2 + blksize;
+		u32 padsize = ((blksize - 1) & 7) + 1;
+		mtu = ALIGN(mtu + 2, padsize) + blksize - padsize;
 	}
 	}
 	if (esp->conf.padlen)
 	if (esp->conf.padlen)
-		mtu = (mtu + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+		mtu = ALIGN(mtu, esp->conf.padlen);
 
 
 	return mtu + x->props.header_len + esp->auth.icv_full_len;
 	return mtu + x->props.header_len + esp->auth.icv_full_len;
 }
 }

+ 2 - 2
net/netfilter/nfnetlink.c

@@ -133,7 +133,7 @@ int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len)
 	memset(tb, 0, sizeof(struct nfattr *) * maxattr);
 	memset(tb, 0, sizeof(struct nfattr *) * maxattr);
 
 
 	while (NFA_OK(nfa, len)) {
 	while (NFA_OK(nfa, len)) {
-		unsigned flavor = nfa->nfa_type;
+		unsigned flavor = NFA_TYPE(nfa);
 		if (flavor && flavor <= maxattr)
 		if (flavor && flavor <= maxattr)
 			tb[flavor-1] = nfa;
 			tb[flavor-1] = nfa;
 		nfa = NFA_NEXT(nfa, len);
 		nfa = NFA_NEXT(nfa, len);
@@ -177,7 +177,7 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
 		int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
 		int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
 
 
 		while (NFA_OK(attr, attrlen)) {
 		while (NFA_OK(attr, attrlen)) {
-			unsigned flavor = attr->nfa_type;
+			unsigned flavor = NFA_TYPE(attr);
 			if (flavor) {
 			if (flavor) {
 				if (flavor > attr_count)
 				if (flavor > attr_count)
 					return -EINVAL;
 					return -EINVAL;