提交 02d31ed2 编写于 作者: L Linus Torvalds

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

...@@ -41,11 +41,15 @@ enum nfnetlink_groups { ...@@ -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 /* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from
* to put this in a generic file */ * 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 ...@@ -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)); \
......
...@@ -70,15 +70,24 @@ enum ctattr_l4proto { ...@@ -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_PACKETS, /* old 64bit counters */
CTA_COUNTERS_BYTES, 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)
......
...@@ -117,6 +117,10 @@ enum ip_conntrack_events ...@@ -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 { \ ...@@ -192,8 +196,8 @@ do { \
struct ip_conntrack_counter struct ip_conntrack_counter
{ {
u_int64_t packets; u_int32_t packets;
u_int64_t bytes; u_int32_t bytes;
}; };
struct ip_conntrack_helper; struct ip_conntrack_helper;
......
...@@ -52,6 +52,9 @@ struct ip_conntrack_protocol ...@@ -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[],
......
#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.
......
...@@ -58,10 +58,6 @@ extern rwlock_t ip_nat_lock; ...@@ -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];
}; };
......
...@@ -86,7 +86,7 @@ static inline void netpoll_poll_unlock(void *have) ...@@ -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
......
...@@ -19,6 +19,7 @@ ...@@ -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) ...@@ -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);
} }
} }
......
...@@ -79,7 +79,6 @@ static void destroy_nbp(struct net_bridge_port *p) ...@@ -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) ...@@ -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);
......
...@@ -110,14 +110,14 @@ static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk) ...@@ -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);
} }
......
...@@ -375,6 +375,9 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk, ...@@ -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, ...@@ -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) */
......
...@@ -5,6 +5,7 @@ ...@@ -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) ...@@ -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; blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4);
clen = (clen + 2 + blksize-1)&~(blksize-1); 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 ...@@ -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, ...@@ -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;
} }
......
...@@ -111,6 +111,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat ...@@ -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;
......
...@@ -139,6 +139,7 @@ config IP_NF_AMANDA ...@@ -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 ...@@ -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
......
...@@ -1119,7 +1119,7 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct, ...@@ -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, ...@@ -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, ...@@ -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) if (event)
ip_conntrack_event_cache(IPCT_REFRESH, skb); ip_conntrack_event_cache(event, skb);
} }
#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
......
...@@ -177,11 +177,11 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct ip_conntrack *ct, ...@@ -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); tmp = htonl(ct->counters[dir].packets);
NFA_PUT(skb, CTA_COUNTERS_PACKETS, sizeof(u_int64_t), &tmp); NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
tmp = cpu_to_be64(ct->counters[dir].bytes); tmp = htonl(ct->counters[dir].bytes);
NFA_PUT(skb, CTA_COUNTERS_BYTES, sizeof(u_int64_t), &tmp); 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 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, ...@@ -833,7 +833,8 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
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[]) ...@@ -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[]) ...@@ -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[], ...@@ -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);
......
...@@ -296,8 +296,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], ...@@ -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_CODE-1])
|| !tb[CTA_PROTO_ICMP_ID-1])
return -1; return -1;
tuple->dst.u.icmp.type = tuple->dst.u.icmp.type =
......
...@@ -341,17 +341,43 @@ static int tcp_print_conntrack(struct seq_file *s, ...@@ -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 = ...@@ -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
......
...@@ -435,7 +435,14 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss ...@@ -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)
......
...@@ -31,6 +31,7 @@ ...@@ -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) ...@@ -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; blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4);
clen = (clen + 2 + blksize-1)&~(blksize-1); 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 ...@@ -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 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru ...@@ -235,16 +236,17 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru
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;
} }
......
...@@ -133,7 +133,7 @@ int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len) ...@@ -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, ...@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册