Commit 80d74d51 authored by Linus Torvalds's avatar Linus Torvalds

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

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [BRIDGE]: Unaligned access when comparing ethernet addresses
  [SCTP]: Unmap v4mapped addresses during SCTP_BINDX_REM_ADDR operation.
  [SCTP]: Fix assertion (!atomic_read(&sk->sk_rmem_alloc)) failed message
  [NET]: Set a separate lockdep class for neighbour table's proxy_queue
  [NET]: Fix UDP checksum issue in net poll mode.
  [KEY]: Fix conversion between IPSEC_MODE_xxx and XFRM_MODE_xxx.
  [NET]: Get rid of alloc_skb_from_cache
parents 245d95a4 19bb3506
...@@ -514,7 +514,6 @@ ...@@ -514,7 +514,6 @@
*(.text.dentry_open) *(.text.dentry_open)
*(.text.dentry_iput) *(.text.dentry_iput)
*(.text.bio_alloc) *(.text.bio_alloc)
*(.text.alloc_skb_from_cache)
*(.text.wait_on_page_bit) *(.text.wait_on_page_bit)
*(.text.vfs_readdir) *(.text.vfs_readdir)
*(.text.vfs_lstat) *(.text.vfs_lstat)
......
...@@ -346,9 +346,6 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size, ...@@ -346,9 +346,6 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
return __alloc_skb(size, priority, 1, -1); return __alloc_skb(size, priority, 1, -1);
} }
extern struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp,
unsigned int size,
gfp_t priority);
extern void kfree_skbmem(struct sk_buff *skb); extern void kfree_skbmem(struct sk_buff *skb);
extern struct sk_buff *skb_clone(struct sk_buff *skb, extern struct sk_buff *skb_clone(struct sk_buff *skb,
gfp_t priority); gfp_t priority);
...@@ -622,6 +619,13 @@ static inline void skb_queue_head_init(struct sk_buff_head *list) ...@@ -622,6 +619,13 @@ static inline void skb_queue_head_init(struct sk_buff_head *list)
list->qlen = 0; list->qlen = 0;
} }
static inline void skb_queue_head_init_class(struct sk_buff_head *list,
struct lock_class_key *class)
{
skb_queue_head_init(list);
lockdep_set_class(&list->lock, class);
}
/* /*
* Insert an sk_buff at the start of a list. * Insert an sk_buff at the start of a list.
* *
......
...@@ -126,7 +126,9 @@ void br_stp_disable_port(struct net_bridge_port *p) ...@@ -126,7 +126,9 @@ void br_stp_disable_port(struct net_bridge_port *p)
/* called under bridge lock */ /* called under bridge lock */
void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
{ {
unsigned char oldaddr[6]; /* should be aligned on 2 bytes for compare_ether_addr() */
unsigned short oldaddr_aligned[ETH_ALEN >> 1];
unsigned char *oldaddr = (unsigned char *)oldaddr_aligned;
struct net_bridge_port *p; struct net_bridge_port *p;
int wasroot; int wasroot;
...@@ -151,11 +153,14 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) ...@@ -151,11 +153,14 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
br_become_root_bridge(br); br_become_root_bridge(br);
} }
static const unsigned char br_mac_zero[6]; /* should be aligned on 2 bytes for compare_ether_addr() */
static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1];
/* called under bridge lock */ /* called under bridge lock */
void br_stp_recalculate_bridge_id(struct net_bridge *br) void br_stp_recalculate_bridge_id(struct net_bridge *br)
{ {
const unsigned char *br_mac_zero =
(const unsigned char *)br_mac_zero_aligned;
const unsigned char *addr = br_mac_zero; const unsigned char *addr = br_mac_zero;
struct net_bridge_port *p; struct net_bridge_port *p;
......
...@@ -1331,6 +1331,8 @@ void neigh_parms_destroy(struct neigh_parms *parms) ...@@ -1331,6 +1331,8 @@ void neigh_parms_destroy(struct neigh_parms *parms)
kfree(parms); kfree(parms);
} }
static struct lock_class_key neigh_table_proxy_queue_class;
void neigh_table_init_no_netlink(struct neigh_table *tbl) void neigh_table_init_no_netlink(struct neigh_table *tbl)
{ {
unsigned long now = jiffies; unsigned long now = jiffies;
...@@ -1379,7 +1381,8 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) ...@@ -1379,7 +1381,8 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
init_timer(&tbl->proxy_timer); init_timer(&tbl->proxy_timer);
tbl->proxy_timer.data = (unsigned long)tbl; tbl->proxy_timer.data = (unsigned long)tbl;
tbl->proxy_timer.function = neigh_proxy_process; tbl->proxy_timer.function = neigh_proxy_process;
skb_queue_head_init(&tbl->proxy_queue); skb_queue_head_init_class(&tbl->proxy_queue,
&neigh_table_proxy_queue_class);
tbl->last_flush = now; tbl->last_flush = now;
tbl->last_rand = now + tbl->parms.reachable_time * 20; tbl->last_rand = now + tbl->parms.reachable_time * 20;
......
...@@ -471,6 +471,13 @@ int __netpoll_rx(struct sk_buff *skb) ...@@ -471,6 +471,13 @@ int __netpoll_rx(struct sk_buff *skb)
if (skb->len < len || len < iph->ihl*4) if (skb->len < len || len < iph->ihl*4)
goto out; goto out;
/*
* Our transport medium may have padded the buffer out.
* Now We trim to the true length of the frame.
*/
if (pskb_trim_rcsum(skb, len))
goto out;
if (iph->protocol != IPPROTO_UDP) if (iph->protocol != IPPROTO_UDP)
goto out; goto out;
......
...@@ -196,61 +196,6 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, ...@@ -196,61 +196,6 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
goto out; goto out;
} }
/**
* alloc_skb_from_cache - allocate a network buffer
* @cp: kmem_cache from which to allocate the data area
* (object size must be big enough for @size bytes + skb overheads)
* @size: size to allocate
* @gfp_mask: allocation mask
*
* Allocate a new &sk_buff. The returned buffer has no headroom and
* tail room of size bytes. The object has a reference count of one.
* The return is the buffer. On a failure the return is %NULL.
*
* Buffers may only be allocated from interrupts using a @gfp_mask of
* %GFP_ATOMIC.
*/
struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp,
unsigned int size,
gfp_t gfp_mask)
{
struct sk_buff *skb;
u8 *data;
/* Get the HEAD */
skb = kmem_cache_alloc(skbuff_head_cache,
gfp_mask & ~__GFP_DMA);
if (!skb)
goto out;
/* Get the DATA. */
size = SKB_DATA_ALIGN(size);
data = kmem_cache_alloc(cp, gfp_mask);
if (!data)
goto nodata;
memset(skb, 0, offsetof(struct sk_buff, truesize));
skb->truesize = size + sizeof(struct sk_buff);
atomic_set(&skb->users, 1);
skb->head = data;
skb->data = data;
skb->tail = data;
skb->end = data + size;
atomic_set(&(skb_shinfo(skb)->dataref), 1);
skb_shinfo(skb)->nr_frags = 0;
skb_shinfo(skb)->gso_size = 0;
skb_shinfo(skb)->gso_segs = 0;
skb_shinfo(skb)->gso_type = 0;
skb_shinfo(skb)->frag_list = NULL;
out:
return skb;
nodata:
kmem_cache_free(skbuff_head_cache, skb);
skb = NULL;
goto out;
}
/** /**
* __netdev_alloc_skb - allocate an skbuff for rx on a specific device * __netdev_alloc_skb - allocate an skbuff for rx on a specific device
* @dev: network device to receive on * @dev: network device to receive on
......
...@@ -630,6 +630,35 @@ pfkey_sockaddr_size(sa_family_t family) ...@@ -630,6 +630,35 @@ pfkey_sockaddr_size(sa_family_t family)
/* NOTREACHED */ /* NOTREACHED */
} }
static inline int pfkey_mode_from_xfrm(int mode)
{
switch(mode) {
case XFRM_MODE_TRANSPORT:
return IPSEC_MODE_TRANSPORT;
case XFRM_MODE_TUNNEL:
return IPSEC_MODE_TUNNEL;
case XFRM_MODE_BEET:
return IPSEC_MODE_BEET;
default:
return -1;
}
}
static inline int pfkey_mode_to_xfrm(int mode)
{
switch(mode) {
case IPSEC_MODE_ANY: /*XXX*/
case IPSEC_MODE_TRANSPORT:
return XFRM_MODE_TRANSPORT;
case IPSEC_MODE_TUNNEL:
return XFRM_MODE_TUNNEL;
case IPSEC_MODE_BEET:
return XFRM_MODE_BEET;
default:
return -1;
}
}
static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, int hsc) static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, int hsc)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -651,6 +680,7 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, ...@@ -651,6 +680,7 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
int encrypt_key_size = 0; int encrypt_key_size = 0;
int sockaddr_size; int sockaddr_size;
struct xfrm_encap_tmpl *natt = NULL; struct xfrm_encap_tmpl *natt = NULL;
int mode;
/* address family check */ /* address family check */
sockaddr_size = pfkey_sockaddr_size(x->props.family); sockaddr_size = pfkey_sockaddr_size(x->props.family);
...@@ -928,7 +958,11 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, ...@@ -928,7 +958,11 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
sa2 = (struct sadb_x_sa2 *) skb_put(skb, sizeof(struct sadb_x_sa2)); sa2 = (struct sadb_x_sa2 *) skb_put(skb, sizeof(struct sadb_x_sa2));
sa2->sadb_x_sa2_len = sizeof(struct sadb_x_sa2)/sizeof(uint64_t); sa2->sadb_x_sa2_len = sizeof(struct sadb_x_sa2)/sizeof(uint64_t);
sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2; sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
sa2->sadb_x_sa2_mode = x->props.mode + 1; if ((mode = pfkey_mode_from_xfrm(x->props.mode)) < 0) {
kfree_skb(skb);
return ERR_PTR(-EINVAL);
}
sa2->sadb_x_sa2_mode = mode;
sa2->sadb_x_sa2_reserved1 = 0; sa2->sadb_x_sa2_reserved1 = 0;
sa2->sadb_x_sa2_reserved2 = 0; sa2->sadb_x_sa2_reserved2 = 0;
sa2->sadb_x_sa2_sequence = 0; sa2->sadb_x_sa2_sequence = 0;
...@@ -1155,9 +1189,12 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -1155,9 +1189,12 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
if (ext_hdrs[SADB_X_EXT_SA2-1]) { if (ext_hdrs[SADB_X_EXT_SA2-1]) {
struct sadb_x_sa2 *sa2 = (void*)ext_hdrs[SADB_X_EXT_SA2-1]; struct sadb_x_sa2 *sa2 = (void*)ext_hdrs[SADB_X_EXT_SA2-1];
x->props.mode = sa2->sadb_x_sa2_mode; int mode = pfkey_mode_to_xfrm(sa2->sadb_x_sa2_mode);
if (x->props.mode) if (mode < 0) {
x->props.mode--; err = -EINVAL;
goto out;
}
x->props.mode = mode;
x->props.reqid = sa2->sadb_x_sa2_reqid; x->props.reqid = sa2->sadb_x_sa2_reqid;
} }
...@@ -1218,7 +1255,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h ...@@ -1218,7 +1255,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
struct sadb_address *saddr, *daddr; struct sadb_address *saddr, *daddr;
struct sadb_msg *out_hdr; struct sadb_msg *out_hdr;
struct xfrm_state *x = NULL; struct xfrm_state *x = NULL;
u8 mode; int mode;
u32 reqid; u32 reqid;
u8 proto; u8 proto;
unsigned short family; unsigned short family;
...@@ -1233,7 +1270,9 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h ...@@ -1233,7 +1270,9 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
return -EINVAL; return -EINVAL;
if ((sa2 = ext_hdrs[SADB_X_EXT_SA2-1]) != NULL) { if ((sa2 = ext_hdrs[SADB_X_EXT_SA2-1]) != NULL) {
mode = sa2->sadb_x_sa2_mode - 1; mode = pfkey_mode_to_xfrm(sa2->sadb_x_sa2_mode);
if (mode < 0)
return -EINVAL;
reqid = sa2->sadb_x_sa2_reqid; reqid = sa2->sadb_x_sa2_reqid;
} else { } else {
mode = 0; mode = 0;
...@@ -1756,6 +1795,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) ...@@ -1756,6 +1795,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct sockaddr_in6 *sin6; struct sockaddr_in6 *sin6;
#endif #endif
int mode;
if (xp->xfrm_nr >= XFRM_MAX_DEPTH) if (xp->xfrm_nr >= XFRM_MAX_DEPTH)
return -ELOOP; return -ELOOP;
...@@ -1764,7 +1804,9 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) ...@@ -1764,7 +1804,9 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
return -EINVAL; return -EINVAL;
t->id.proto = rq->sadb_x_ipsecrequest_proto; /* XXX check proto */ t->id.proto = rq->sadb_x_ipsecrequest_proto; /* XXX check proto */
t->mode = rq->sadb_x_ipsecrequest_mode-1; if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)
return -EINVAL;
t->mode = mode;
if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE) if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE)
t->optional = 1; t->optional = 1;
else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) { else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
...@@ -1877,7 +1919,7 @@ static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp) ...@@ -1877,7 +1919,7 @@ static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp)
return skb; return skb;
} }
static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, int dir) static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, int dir)
{ {
struct sadb_msg *hdr; struct sadb_msg *hdr;
struct sadb_address *addr; struct sadb_address *addr;
...@@ -2014,6 +2056,7 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i ...@@ -2014,6 +2056,7 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i
struct sadb_x_ipsecrequest *rq; struct sadb_x_ipsecrequest *rq;
struct xfrm_tmpl *t = xp->xfrm_vec + i; struct xfrm_tmpl *t = xp->xfrm_vec + i;
int req_size; int req_size;
int mode;
req_size = sizeof(struct sadb_x_ipsecrequest); req_size = sizeof(struct sadb_x_ipsecrequest);
if (t->mode == XFRM_MODE_TUNNEL) if (t->mode == XFRM_MODE_TUNNEL)
...@@ -2027,7 +2070,9 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i ...@@ -2027,7 +2070,9 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i
memset(rq, 0, sizeof(*rq)); memset(rq, 0, sizeof(*rq));
rq->sadb_x_ipsecrequest_len = req_size; rq->sadb_x_ipsecrequest_len = req_size;
rq->sadb_x_ipsecrequest_proto = t->id.proto; rq->sadb_x_ipsecrequest_proto = t->id.proto;
rq->sadb_x_ipsecrequest_mode = t->mode+1; if ((mode = pfkey_mode_from_xfrm(t->mode)) < 0)
return -EINVAL;
mode = pfkey_mode_from_xfrm(t->mode);
rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE; rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
if (t->reqid) if (t->reqid)
rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE; rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
...@@ -2089,6 +2134,8 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i ...@@ -2089,6 +2134,8 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i
hdr->sadb_msg_len = size / sizeof(uint64_t); hdr->sadb_msg_len = size / sizeof(uint64_t);
hdr->sadb_msg_reserved = atomic_read(&xp->refcnt); hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
return 0;
} }
static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
...@@ -2102,7 +2149,9 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c ...@@ -2102,7 +2149,9 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c
err = PTR_ERR(out_skb); err = PTR_ERR(out_skb);
goto out; goto out;
} }
pfkey_xfrm_policy2msg(out_skb, xp, dir); err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
if (err < 0)
return err;
out_hdr = (struct sadb_msg *) out_skb->data; out_hdr = (struct sadb_msg *) out_skb->data;
out_hdr->sadb_msg_version = PF_KEY_V2; out_hdr->sadb_msg_version = PF_KEY_V2;
...@@ -2327,7 +2376,9 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, struct sadb ...@@ -2327,7 +2376,9 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, struct sadb
err = PTR_ERR(out_skb); err = PTR_ERR(out_skb);
goto out; goto out;
} }
pfkey_xfrm_policy2msg(out_skb, xp, dir); err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
if (err < 0)
goto out;
out_hdr = (struct sadb_msg *) out_skb->data; out_hdr = (struct sadb_msg *) out_skb->data;
out_hdr->sadb_msg_version = hdr->sadb_msg_version; out_hdr->sadb_msg_version = hdr->sadb_msg_version;
...@@ -2409,6 +2460,7 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, ...@@ -2409,6 +2460,7 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
{ {
int err; int err;
struct sadb_x_ipsecrequest *rq2; struct sadb_x_ipsecrequest *rq2;
int mode;
if (len <= sizeof(struct sadb_x_ipsecrequest) || if (len <= sizeof(struct sadb_x_ipsecrequest) ||
len < rq1->sadb_x_ipsecrequest_len) len < rq1->sadb_x_ipsecrequest_len)
...@@ -2439,7 +2491,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, ...@@ -2439,7 +2491,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
return -EINVAL; return -EINVAL;
m->proto = rq1->sadb_x_ipsecrequest_proto; m->proto = rq1->sadb_x_ipsecrequest_proto;
m->mode = rq1->sadb_x_ipsecrequest_mode - 1; if ((mode = pfkey_mode_to_xfrm(rq1->sadb_x_ipsecrequest_mode)) < 0)
return -EINVAL;
m->mode = mode;
m->reqid = rq1->sadb_x_ipsecrequest_reqid; m->reqid = rq1->sadb_x_ipsecrequest_reqid;
return ((int)(rq1->sadb_x_ipsecrequest_len + return ((int)(rq1->sadb_x_ipsecrequest_len +
...@@ -2579,12 +2633,15 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr) ...@@ -2579,12 +2633,15 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
struct pfkey_dump_data *data = ptr; struct pfkey_dump_data *data = ptr;
struct sk_buff *out_skb; struct sk_buff *out_skb;
struct sadb_msg *out_hdr; struct sadb_msg *out_hdr;
int err;
out_skb = pfkey_xfrm_policy2msg_prep(xp); out_skb = pfkey_xfrm_policy2msg_prep(xp);
if (IS_ERR(out_skb)) if (IS_ERR(out_skb))
return PTR_ERR(out_skb); return PTR_ERR(out_skb);
pfkey_xfrm_policy2msg(out_skb, xp, dir); err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
if (err < 0)
return err;
out_hdr = (struct sadb_msg *) out_skb->data; out_hdr = (struct sadb_msg *) out_skb->data;
out_hdr->sadb_msg_version = data->hdr->sadb_msg_version; out_hdr->sadb_msg_version = data->hdr->sadb_msg_version;
...@@ -3513,7 +3570,10 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, ...@@ -3513,7 +3570,10 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
for (i = 0, mp = m; i < num_bundles; i++, mp++) { for (i = 0, mp = m; i < num_bundles; i++, mp++) {
/* old ipsecrequest */ /* old ipsecrequest */
if (set_ipsecrequest(skb, mp->proto, mp->mode + 1, int mode = pfkey_mode_from_xfrm(mp->mode);
if (mode < 0)
return -EINVAL;
if (set_ipsecrequest(skb, mp->proto, mode,
(mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE), (mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE),
mp->reqid, mp->old_family, mp->reqid, mp->old_family,
&mp->old_saddr, &mp->old_daddr) < 0) { &mp->old_saddr, &mp->old_daddr) < 0) {
...@@ -3521,7 +3581,7 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, ...@@ -3521,7 +3581,7 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
} }
/* new ipsecrequest */ /* new ipsecrequest */
if (set_ipsecrequest(skb, mp->proto, mp->mode + 1, if (set_ipsecrequest(skb, mp->proto, mode,
(mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE), (mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE),
mp->reqid, mp->new_family, mp->reqid, mp->new_family,
&mp->new_saddr, &mp->new_daddr) < 0) { &mp->new_saddr, &mp->new_daddr) < 0) {
......
...@@ -627,6 +627,12 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) ...@@ -627,6 +627,12 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
retval = -EINVAL; retval = -EINVAL;
goto err_bindx_rem; goto err_bindx_rem;
} }
if (!af->addr_valid(sa_addr, sp, NULL)) {
retval = -EADDRNOTAVAIL;
goto err_bindx_rem;
}
if (sa_addr->v4.sin_port != htons(bp->port)) { if (sa_addr->v4.sin_port != htons(bp->port)) {
retval = -EINVAL; retval = -EINVAL;
goto err_bindx_rem; goto err_bindx_rem;
...@@ -5638,6 +5644,36 @@ void sctp_wait_for_close(struct sock *sk, long timeout) ...@@ -5638,6 +5644,36 @@ void sctp_wait_for_close(struct sock *sk, long timeout)
finish_wait(sk->sk_sleep, &wait); finish_wait(sk->sk_sleep, &wait);
} }
static void sctp_sock_rfree_frag(struct sk_buff *skb)
{
struct sk_buff *frag;
if (!skb->data_len)
goto done;
/* Don't forget the fragments. */
for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next)
sctp_sock_rfree_frag(frag);
done:
sctp_sock_rfree(skb);
}
static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk)
{
struct sk_buff *frag;
if (!skb->data_len)
goto done;
/* Don't forget the fragments. */
for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next)
sctp_skb_set_owner_r_frag(frag, sk);
done:
sctp_skb_set_owner_r(skb, sk);
}
/* Populate the fields of the newsk from the oldsk and migrate the assoc /* Populate the fields of the newsk from the oldsk and migrate the assoc
* and its messages to the newsk. * and its messages to the newsk.
*/ */
...@@ -5692,10 +5728,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, ...@@ -5692,10 +5728,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
event = sctp_skb2event(skb); event = sctp_skb2event(skb);
if (event->asoc == assoc) { if (event->asoc == assoc) {
sctp_sock_rfree(skb); sctp_sock_rfree_frag(skb);
__skb_unlink(skb, &oldsk->sk_receive_queue); __skb_unlink(skb, &oldsk->sk_receive_queue);
__skb_queue_tail(&newsk->sk_receive_queue, skb); __skb_queue_tail(&newsk->sk_receive_queue, skb);
sctp_skb_set_owner_r(skb, newsk); sctp_skb_set_owner_r_frag(skb, newsk);
} }
} }
...@@ -5723,10 +5759,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, ...@@ -5723,10 +5759,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
event = sctp_skb2event(skb); event = sctp_skb2event(skb);
if (event->asoc == assoc) { if (event->asoc == assoc) {
sctp_sock_rfree(skb); sctp_sock_rfree_frag(skb);
__skb_unlink(skb, &oldsp->pd_lobby); __skb_unlink(skb, &oldsp->pd_lobby);
__skb_queue_tail(queue, skb); __skb_queue_tail(queue, skb);
sctp_skb_set_owner_r(skb, newsk); sctp_skb_set_owner_r_frag(skb, newsk);
} }
} }
...@@ -5738,6 +5774,16 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, ...@@ -5738,6 +5774,16 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
} }
sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) {
sctp_sock_rfree_frag(skb);
sctp_skb_set_owner_r_frag(skb, newsk);
}
sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) {
sctp_sock_rfree_frag(skb);
sctp_skb_set_owner_r_frag(skb, newsk);
}
/* Set the type of socket to indicate that it is peeled off from the /* Set the type of socket to indicate that it is peeled off from the
* original UDP-style socket or created with the accept() call on a * original UDP-style socket or created with the accept() call on a
* TCP-style socket.. * TCP-style socket..
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment