[PATCH 04/13] SCTP: enable per-namespace address handling.

From: Jan Ariyasu
Date: Sat Aug 04 2012 - 17:32:58 EST


Make a separate local_addr_list for each netns, and use that list
to when creating associations.

Signed-off-by: Jan Ariyasu <jan.ariyasu@xxxxxx>
---
include/net/sctp/sctp.h | 8 ++-
include/net/sctp/structs.h | 28 ++++----
net/sctp/associola.c | 6 +-
net/sctp/bind_addr.c | 25 ++++---
net/sctp/ipv6.c | 47 ++++++++------
net/sctp/output.c | 4 +-
net/sctp/protocol.c | 154 ++++++++++++++++++++++++--------------------
net/sctp/sm_make_chunk.c | 8 ++-
net/sctp/sm_sideeffect.c | 3 +-
net/sctp/sm_statefuns.c | 16 +++--
net/sctp/socket.c | 59 ++++++++++-------
net/sctp/transport.c | 15 +++--
12 files changed, 216 insertions(+), 157 deletions(-)

diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 97ba550..bda317a 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -121,10 +121,11 @@ extern int sctp_net_id;
*/
extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
sctp_scope_t, gfp_t gfp,
- int flags);
+ int flags, struct net *);
extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
-extern void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *, int);
+extern void sctp_addr_wq_mgmt(struct net *,
+ struct sctp_sockaddr_entry *, int);

/*
* sctp/socket.c
@@ -139,7 +140,8 @@ void sctp_sock_rfree(struct sk_buff *skb);
void sctp_copy_sock(struct sock *newsk, struct sock *sk,
struct sctp_association *asoc);
extern struct percpu_counter sctp_sockets_allocated;
-extern int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *);
+extern int sctp_asconf_mgmt(struct net *, struct sctp_sock *,
+ struct sctp_sockaddr_entry *);

/*
* sctp/primitive.c
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index bc65718..2034d53 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -718,7 +718,8 @@ struct sctp_af {
int optname,
char __user *optval,
int __user *optlen);
- void (*get_dst) (struct sctp_transport *t,
+ void (*get_dst) (struct net *net,
+ struct sctp_transport *t,
union sctp_addr *saddr,
struct flowi *fl,
struct sock *sk);
@@ -751,7 +752,7 @@ struct sctp_af {
sctp_scope_t (*scope) (union sctp_addr *);
void (*inaddr_any) (union sctp_addr *, __be16);
int (*is_any) (const union sctp_addr *);
- int (*available) (union sctp_addr *,
+ int (*available) (struct net *, union sctp_addr *,
struct sctp_sock *);
int (*skb_iif) (const struct sk_buff *sk);
int (*is_ce) (const struct sk_buff *sk);
@@ -775,8 +776,10 @@ struct sctp_pf {
int (*cmp_addr) (const union sctp_addr *,
const union sctp_addr *,
struct sctp_sock *);
- int (*bind_verify) (struct sctp_sock *, union sctp_addr *);
- int (*send_verify) (struct sctp_sock *, union sctp_addr *);
+ int (*bind_verify) (struct net *, struct sctp_sock *,
+ union sctp_addr *);
+ int (*send_verify) (struct net *, struct sctp_sock *,
+ union sctp_addr *);
int (*supported_addrs)(const struct sctp_sock *, __be16 *);
struct sock *(*create_accept_sk) (struct sock *sk,
struct sctp_association *asoc);
@@ -1220,9 +1223,10 @@ struct sctp_transport *sctp_transport_new(const union sctp_addr *,
gfp_t);
void sctp_transport_set_owner(struct sctp_transport *,
struct sctp_association *);
-void sctp_transport_route(struct sctp_transport *, union sctp_addr *,
- struct sctp_sock *);
-void sctp_transport_pmtu(struct sctp_transport *, struct sock *sk);
+void sctp_transport_route(struct net *, struct sctp_transport *,
+ union sctp_addr *, struct sctp_sock *);
+void sctp_transport_pmtu(struct net *, struct sctp_transport *,
+ struct sock *sk);
void sctp_transport_free(struct sctp_transport *);
void sctp_transport_reset_timers(struct sctp_transport *);
void sctp_transport_hold(struct sctp_transport *);
@@ -1373,6 +1377,7 @@ void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port);
void sctp_bind_addr_free(struct sctp_bind_addr *);
int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
const struct sctp_bind_addr *src,
+ struct net *net,
sctp_scope_t scope, gfp_t gfp,
int flags);
int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
@@ -1398,7 +1403,8 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len,
__u16 port, gfp_t gfp);

sctp_scope_t sctp_scope(const union sctp_addr *);
-int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope);
+int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope,
+ struct net *net);
int sctp_is_any(struct sock *sk, const union sctp_addr *addr);
int sctp_addr_is_valid(const union sctp_addr *addr);
int sctp_is_ep_boundall(struct sock *sk);
@@ -1564,8 +1570,8 @@ int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t,
sctp_init_chunk_t *peer_init, struct sctp_chunk *chunk,
struct sctp_chunk **err_chunk);
int sctp_process_init(struct sctp_association *, struct sctp_chunk *chunk,
- const union sctp_addr *peer,
- sctp_init_chunk_t *init, gfp_t gfp);
+ const union sctp_addr *peer, sctp_init_chunk_t *init,
+ struct net *net, gfp_t gfp);
__u32 sctp_generate_tag(const struct sctp_endpoint *);
__u32 sctp_generate_tsn(const struct sctp_endpoint *);

@@ -2160,7 +2166,7 @@ void sctp_assoc_set_primary(struct sctp_association *,
void sctp_assoc_del_nonprimary_peers(struct sctp_association *,
struct sctp_transport *);
int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *,
- sctp_scope_t, gfp_t);
+ struct net *, sctp_scope_t, gfp_t);
int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
struct sctp_cookie*,
gfp_t gfp);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index ebaef3e..001f44b 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -644,6 +644,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
struct sctp_transport *peer;
struct sctp_sock *sp;
unsigned short port;
+ struct net *net = sock_net(asoc->base.sk);

sp = sctp_sk(asoc->base.sk);

@@ -702,7 +703,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
*/
peer->param_flags = asoc->param_flags;

- sctp_transport_route(peer, NULL, sp);
+ sctp_transport_route(net, peer, NULL, sp);

/* Initialize the pmtu of the transport. */
if (peer->param_flags & SPP_PMTUD_DISABLE) {
@@ -1529,6 +1530,7 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len)
* local endpoint and the remote peer.
*/
int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
+ struct net *net,
sctp_scope_t scope, gfp_t gfp)
{
int flags;
@@ -1543,7 +1545,7 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
flags |= SCTP_ADDR6_PEERSUPP;

return sctp_bind_addr_copy(&asoc->base.bind_addr,
- &asoc->ep->base.bind_addr,
+ &asoc->ep->base.bind_addr, net,
scope, gfp, flags);
}

diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 4ece451..2b18722 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -52,9 +52,10 @@
#include <net/sctp/sm.h>

/* Forward declarations for internal helpers. */
-static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *,
- sctp_scope_t scope, gfp_t gfp,
- int flags);
+static int sctp_copy_one_addr(struct sctp_bind_addr *,
+ union sctp_addr *, struct net *,
+ sctp_scope_t scope,
+ gfp_t gfp, int flags);
static void sctp_bind_addr_clean(struct sctp_bind_addr *);

/* First Level Abstractions. */
@@ -64,6 +65,7 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *);
*/
int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
const struct sctp_bind_addr *src,
+ struct net *net,
sctp_scope_t scope, gfp_t gfp,
int flags)
{
@@ -75,8 +77,8 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,

/* Extract the addresses which are relevant for this scope. */
list_for_each_entry(addr, &src->address_list, list) {
- error = sctp_copy_one_addr(dest, &addr->a, scope,
- gfp, flags);
+ error = sctp_copy_one_addr(dest, &addr->a, net,
+ scope, gfp, flags);
if (error < 0)
goto out;
}
@@ -87,7 +89,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
*/
if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) {
list_for_each_entry(addr, &src->address_list, list) {
- error = sctp_copy_one_addr(dest, &addr->a,
+ error = sctp_copy_one_addr(dest, &addr->a, net,
SCTP_SCOPE_LINK, gfp,
flags);
if (error < 0)
@@ -450,14 +452,15 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp,
/* Copy out addresses from the global local address list. */
static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
union sctp_addr *addr,
+ struct net *net,
sctp_scope_t scope, gfp_t gfp,
int flags)
{
int error = 0;

if (sctp_is_any(NULL, addr)) {
- error = sctp_copy_local_addr_list(dest, scope, gfp, flags);
- } else if (sctp_in_scope(addr, scope)) {
+ error = sctp_copy_local_addr_list(dest, scope, gfp, flags, net);
+ } else if (sctp_in_scope(addr, scope, net)) {
/* Now that the address is in scope, check to see if
* the address type is supported by local sock as
* well as the remote peer.
@@ -494,9 +497,11 @@ int sctp_is_any(struct sock *sk, const union sctp_addr *addr)
}

/* Is 'addr' valid for 'scope'? */
-int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope)
+int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope,
+ struct net *net)
{
sctp_scope_t addr_scope = sctp_scope(addr);
+ struct sctp_net_params *net_params = sctp_get_params(net);

/* The unusable SCTP addresses will not be considered with
* any defined scopes.
@@ -512,7 +517,7 @@ int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope)
* Address scoping can be selectively controlled via sysctl
* option
*/
- switch (sctp_scope_policy) {
+ switch (net_params->ipv4_scope_policy) {
case SCTP_SCOPE_POLICY_DISABLE:
return 1;
case SCTP_SCOPE_POLICY_ENABLE:
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index ed7139e..67cae63 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -88,7 +88,7 @@ static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
const union sctp_addr *addr2);

/* Event handler for inet6 address addition/deletion events.
- * The sctp_local_addr_list needs to be protocted by a spin lock since
+ * The local_addr_list needs to be protocted by a spin lock since
* multiple notifiers (say IPv4 and IPv6) may be running at the same
* time and thus corrupt the list.
* The reader side is protected with RCU.
@@ -100,6 +100,8 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
struct sctp_sockaddr_entry *addr = NULL;
struct sctp_sockaddr_entry *temp;
int found = 0;
+ struct net *net = dev_net(ifa->idev->dev);
+ struct sctp_net_params *net_params = sctp_get_params(net);

switch (ev) {
case NETDEV_UP:
@@ -110,27 +112,28 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
addr->a.v6.sin6_addr = ifa->addr;
addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
addr->valid = 1;
- spin_lock_bh(&sctp_local_addr_lock);
- list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
- sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
- spin_unlock_bh(&sctp_local_addr_lock);
+ spin_lock_bh(&net_params->addr_list_lock);
+ list_add_tail_rcu(&addr->list,
+ &net_params->local_addr_list);
+ sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
+ spin_unlock_bh(&net_params->addr_list_lock);
}
break;
case NETDEV_DOWN:
- spin_lock_bh(&sctp_local_addr_lock);
+ spin_lock_bh(&net_params->addr_list_lock);
list_for_each_entry_safe(addr, temp,
- &sctp_local_addr_list, list) {
+ &net_params->local_addr_list, list) {
if (addr->a.sa.sa_family == AF_INET6 &&
ipv6_addr_equal(&addr->a.v6.sin6_addr,
&ifa->addr)) {
- sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
+ sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
found = 1;
addr->valid = 0;
list_del_rcu(&addr->list);
break;
}
}
- spin_unlock_bh(&sctp_local_addr_lock);
+ spin_unlock_bh(&net_params->addr_list_lock);
if (found)
kfree_rcu(addr, rcu);
break;
@@ -252,8 +255,9 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
/* Returns the dst cache entry for the given source and destination ip
* addresses.
*/
-static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
- struct flowi *fl, struct sock *sk)
+static void sctp_v6_get_dst(struct net *net, struct sctp_transport *t,
+ union sctp_addr *saddr, struct flowi *fl,
+ struct sock *sk)
{
struct sctp_association *asoc = t->asoc;
struct dst_entry *dst = NULL;
@@ -561,7 +565,8 @@ static int sctp_v6_is_any(const union sctp_addr *addr)
}

/* Should this be available for binding? */
-static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
+static int sctp_v6_available(struct net *net, union sctp_addr *addr,
+ struct sctp_sock *sp)
{
int type;
const struct in6_addr *in6 = (const struct in6_addr *)&addr->v6.sin6_addr;
@@ -575,12 +580,12 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
return 0;
sctp_v6_map_v4(addr);
- return sctp_get_af_specific(AF_INET)->available(addr, sp);
+ return sctp_get_af_specific(AF_INET)->available(net, addr, sp);
}
if (!(type & IPV6_ADDR_UNICAST))
return 0;

- return ipv6_chk_addr(&init_net, in6, NULL, 0);
+ return ipv6_chk_addr(net, in6, NULL, 0);
}

/* This function checks if the address is a valid address to be used for
@@ -845,7 +850,8 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
/* Verify that the provided sockaddr looks bindable. Common verification,
* has already been taken care of.
*/
-static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
+static int sctp_inet6_bind_verify(struct net *net, struct sctp_sock *opt,
+ union sctp_addr *addr)
{
struct sctp_af *af;

@@ -860,10 +866,10 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
if (!addr->v6.sin6_scope_id)
return 0;
rcu_read_lock();
- dev = dev_get_by_index_rcu(&init_net,
+ dev = dev_get_by_index_rcu(net,
addr->v6.sin6_scope_id);
if (!dev ||
- !ipv6_chk_addr(&init_net, &addr->v6.sin6_addr,
+ !ipv6_chk_addr(net, &addr->v6.sin6_addr,
dev, 0)) {
rcu_read_unlock();
return 0;
@@ -876,13 +882,14 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)

af = opt->pf->af;
}
- return af->available(addr, opt);
+ return af->available(net, addr, opt);
}

/* Verify that the provided sockaddr looks sendable. Common verification,
* has already been taken care of.
*/
-static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
+static int sctp_inet6_send_verify(struct net *net, struct sctp_sock *opt,
+ union sctp_addr *addr)
{
struct sctp_af *af = NULL;

@@ -897,7 +904,7 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
if (!addr->v6.sin6_scope_id)
return 0;
rcu_read_lock();
- dev = dev_get_by_index_rcu(&init_net,
+ dev = dev_get_by_index_rcu(net,
addr->v6.sin6_scope_id);
rcu_read_unlock();
if (!dev)
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 838e18b..f9c5ffa 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -377,6 +377,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
struct sk_buff *nskb;
struct sctp_chunk *chunk, *tmp;
struct sock *sk;
+ struct net *net;
int err = 0;
int padding; /* How much padding do we need? */
__u8 has_data = 0;
@@ -393,6 +394,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
/* Set up convenience variables... */
chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list);
sk = chunk->skb->sk;
+ net = sock_net(sk);

/* Allocate the new skb. */
nskb = alloc_skb(packet->size + LL_MAX_HEADER, GFP_ATOMIC);
@@ -408,7 +410,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
skb_set_owner_w(nskb, sk);

if (!sctp_transport_dst_check(tp)) {
- sctp_transport_route(tp, NULL, sctp_sk(sk));
+ sctp_transport_route(net, tp, NULL, sctp_sk(sk));
if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) {
sctp_assoc_sync_pmtu(sk, asoc);
}
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 28dbef2..dce07d6 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -196,29 +196,32 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
/* Extract our IP addresses from the system and stash them in the
* protocol structure.
*/
-static void sctp_get_local_addr_list(void)
+static void sctp_get_local_addr_list(struct net *net)
{
struct net_device *dev;
struct list_head *pos;
struct sctp_af *af;
+ struct sctp_net_params *net_params = sctp_get_params(net);

rcu_read_lock();
- for_each_netdev_rcu(&init_net, dev) {
+ for_each_netdev_rcu(net, dev) {
__list_for_each(pos, &sctp_address_families) {
af = list_entry(pos, struct sctp_af, list);
- af->copy_addrlist(&sctp_local_addr_list, dev);
+ af->copy_addrlist(&net_params->local_addr_list, dev);
}
}
rcu_read_unlock();
}

/* Free the existing local addresses. */
-static void sctp_free_local_addr_list(void)
+static void sctp_free_local_addr_list(struct net *net)
{
struct sctp_sockaddr_entry *addr;
struct list_head *pos, *temp;
+ struct sctp_net_params *net_params =
+ sctp_get_params(net);

- list_for_each_safe(pos, temp, &sctp_local_addr_list) {
+ list_for_each_safe(pos, temp, &net_params->local_addr_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
list_del(pos);
kfree(addr);
@@ -227,16 +230,17 @@ static void sctp_free_local_addr_list(void)

/* Copy the local addresses which are valid for 'scope' into 'bp'. */
int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
- gfp_t gfp, int copy_flags)
+ gfp_t gfp, int copy_flags, struct net *net)
{
struct sctp_sockaddr_entry *addr;
int error = 0;
+ struct sctp_net_params *net_params = sctp_get_params(net);

rcu_read_lock();
- list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
+ list_for_each_entry_rcu(addr, &net_params->local_addr_list, list) {
if (!addr->valid)
continue;
- if (sctp_in_scope(&addr->a, scope)) {
+ if (sctp_in_scope(&addr->a, scope, net)) {
/* Now that the address is in scope, check to see if
* the address type is really supported by the local
* sock as well as the remote peer.
@@ -389,11 +393,15 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
return 1;
}

-/* Should this be available for binding? */
-static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
+/* Should this be available for binding?
+ * Note that we could derive struct net *net from the sctp_sock *sp,
+ * but the IPv6 version of this code doesn't have the same information
+ * in the last argument.
+ */
+static int sctp_v4_available(struct net *net, union sctp_addr *addr,
+ struct sctp_sock *sp)
{
- int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr);
-
+ int ret = inet_addr_type(net, addr->v4.sin_addr.s_addr);

if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
ret != RTN_LOCAL &&
@@ -450,8 +458,9 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr)
* addresses. If an association is passed, trys to get a dst entry with a
* source address that matches an address in the bind address list.
*/
-static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
- struct flowi *fl, struct sock *sk)
+static void sctp_v4_get_dst(struct net *net, struct sctp_transport *t,
+ union sctp_addr *saddr, struct flowi *fl,
+ struct sock *sk)
{
struct sctp_association *asoc = t->asoc;
struct rtable *rt;
@@ -479,7 +488,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ",
__func__, &fl4->daddr, &fl4->saddr);

- rt = ip_route_output_key(&init_net, fl4);
+ rt = ip_route_output_key(net, fl4);
if (!IS_ERR(rt))
dst = &rt->dst;

@@ -525,7 +534,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
(AF_INET == laddr->a.sa.sa_family)) {
fl4->saddr = laddr->a.v4.sin_addr.s_addr;
fl4->fl4_sport = laddr->a.v4.sin_port;
- rt = ip_route_output_key(&init_net, fl4);
+ rt = ip_route_output_key(sock_net(asoc->base.sk), fl4);
if (!IS_ERR(rt)) {
dst = &rt->dst;
goto out_unlock;
@@ -624,13 +633,15 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
{
struct sctp_sockaddr_entry *addrw, *temp;
struct sctp_sock *sp;
+ struct net *net = (struct net *)arg;
+ struct sctp_net_params *net_params = sctp_get_params(net);

- spin_lock_bh(&sctp_addr_wq_lock);
+ spin_lock_bh(&net_params->addr_wq_lock);

- list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
+ list_for_each_entry_safe(addrw, temp, &net_params->addr_waitq, list) {
SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ",
- " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state,
- addrw);
+ " for cmd %d at entry %p\n", &net_params->addr_waitq,
+ &addrw->a, addrw->state, addrw);

#if IS_ENABLED(CONFIG_IPV6)
/* Now we send an ASCONF for each association */
@@ -643,7 +654,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
goto free_next;

in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr;
- if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 &&
+ if (ipv6_chk_addr(net, in6, NULL, 0) == 0 &&
addrw->state == SCTP_ADDR_NEW) {
unsigned long timeo_val;

@@ -651,7 +662,8 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
SCTP_ADDRESS_TICK_DELAY);
timeo_val = jiffies;
timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
- mod_timer(&sctp_addr_wq_timer, timeo_val);
+ mod_timer(&net_params->addr_wq_timer,
+ timeo_val);
break;
}
}
@@ -664,7 +676,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
if (!sctp_is_ep_boundall(sk))
continue;
sctp_bh_lock_sock(sk);
- if (sctp_asconf_mgmt(sp, addrw) < 0)
+ if (sctp_asconf_mgmt(net, sp, addrw) < 0)
SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: sctp_asconf_mgmt failed\n");
sctp_bh_unlock_sock(sk);
}
@@ -674,31 +686,35 @@ free_next:
list_del(&addrw->list);
kfree(addrw);
}
- spin_unlock_bh(&sctp_addr_wq_lock);
+ spin_unlock_bh(&net_params->addr_wq_lock);
}

-static void sctp_free_addr_wq(void)
+static void sctp_free_addr_wq(struct net *net)
{
struct sctp_sockaddr_entry *addrw;
struct sctp_sockaddr_entry *temp;
+ struct sctp_net_params *net_params = sctp_get_params(net);

- spin_lock_bh(&sctp_addr_wq_lock);
- del_timer(&sctp_addr_wq_timer);
- list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
+ spin_lock_bh(&net_params->addr_wq_lock);
+ del_timer(&net_params->addr_wq_timer);
+ list_for_each_entry_safe(addrw, temp, &net_params->addr_waitq, list) {
list_del(&addrw->list);
kfree(addrw);
}
- spin_unlock_bh(&sctp_addr_wq_lock);
+ spin_unlock_bh(&net_params->addr_wq_lock);
}

/* lookup the entry for the same address in the addr_waitq
* sctp_addr_wq MUST be locked
*/
-static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entry *addr)
+static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(
+ struct net *net,
+ struct sctp_sockaddr_entry *addr)
{
struct sctp_sockaddr_entry *addrw;
+ struct sctp_net_params *net_params = sctp_get_params(net);

- list_for_each_entry(addrw, &sctp_addr_waitq, list) {
+ list_for_each_entry(addrw, &net_params->addr_waitq, list) {
if (addrw->a.sa.sa_family != addr->a.sa.sa_family)
continue;
if (addrw->a.sa.sa_family == AF_INET) {
@@ -714,10 +730,12 @@ static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entr
return NULL;
}

-void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
+void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr,
+ int cmd)
{
struct sctp_sockaddr_entry *addrw;
unsigned long timeo_val;
+ struct sctp_net_params *net_params = sctp_get_params(net);

/* first, we check if an opposite message already exist in the queue.
* If we found such message, it is removed.
@@ -725,38 +743,38 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
* new address after a couple of addition and deletion of that address
*/

- spin_lock_bh(&sctp_addr_wq_lock);
+ spin_lock_bh(&net_params->addr_wq_lock);
/* Offsets existing events in addr_wq */
- addrw = sctp_addr_wq_lookup(addr);
+ addrw = sctp_addr_wq_lookup(net, addr);
if (addrw) {
if (addrw->state != cmd) {
SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ",
" in wq %p\n", addrw->state, &addrw->a,
- &sctp_addr_waitq);
+ &net_params->addr_waitq);
list_del(&addrw->list);
kfree(addrw);
}
- spin_unlock_bh(&sctp_addr_wq_lock);
+ spin_unlock_bh(&net_params->addr_wq_lock);
return;
}

/* OK, we have to add the new address to the wait queue */
addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
if (addrw == NULL) {
- spin_unlock_bh(&sctp_addr_wq_lock);
+ spin_unlock_bh(&net_params->addr_wq_lock);
return;
}
addrw->state = cmd;
- list_add_tail(&addrw->list, &sctp_addr_waitq);
+ list_add_tail(&addrw->list, &net_params->addr_waitq);
SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ",
- " in wq %p\n", addrw->state, &addrw->a, &sctp_addr_waitq);
+ " in wq %p\n", addrw->state, &addrw->a, &net_params->addr_waitq);

- if (!timer_pending(&sctp_addr_wq_timer)) {
+ if (!timer_pending(&net_params->addr_wq_timer)) {
timeo_val = jiffies;
timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
- mod_timer(&sctp_addr_wq_timer, timeo_val);
+ mod_timer(&net_params->addr_wq_timer, timeo_val);
}
- spin_unlock_bh(&sctp_addr_wq_lock);
+ spin_unlock_bh(&net_params->addr_wq_lock);
}

/* Event handler for inet address addition/deletion events.
@@ -772,9 +790,8 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
struct sctp_sockaddr_entry *addr = NULL;
struct sctp_sockaddr_entry *temp;
int found = 0;
-
- if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net))
- return NOTIFY_DONE;
+ struct net *net = dev_net(ifa->ifa_dev->dev);
+ struct sctp_net_params *net_params = sctp_get_params(net);

switch (ev) {
case NETDEV_UP:
@@ -784,27 +801,28 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
addr->a.v4.sin_port = 0;
addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
addr->valid = 1;
- spin_lock_bh(&sctp_local_addr_lock);
- list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
- sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
- spin_unlock_bh(&sctp_local_addr_lock);
+ spin_lock_bh(&net_params->addr_list_lock);
+ list_add_tail_rcu(&addr->list,
+ &net_params->local_addr_list);
+ sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
+ spin_unlock_bh(&net_params->addr_list_lock);
}
break;
case NETDEV_DOWN:
- spin_lock_bh(&sctp_local_addr_lock);
+ spin_lock_bh(&net_params->addr_list_lock);
list_for_each_entry_safe(addr, temp,
- &sctp_local_addr_list, list) {
+ &net_params->local_addr_list, list) {
if (addr->a.sa.sa_family == AF_INET &&
addr->a.v4.sin_addr.s_addr ==
ifa->ifa_local) {
- sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
+ sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
found = 1;
addr->valid = 0;
list_del_rcu(&addr->list);
break;
}
}
- spin_unlock_bh(&sctp_local_addr_lock);
+ spin_unlock_bh(&net_params->addr_list_lock);
if (found)
kfree_rcu(addr, rcu);
break;
@@ -955,15 +973,17 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1,
/* Verify that provided sockaddr looks bindable. Common verification has
* already been taken care of.
*/
-static int sctp_inet_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
+static int sctp_inet_bind_verify(struct net *net, struct sctp_sock *opt,
+ union sctp_addr *addr)
{
- return sctp_v4_available(addr, opt);
+ return sctp_v4_available(net, addr, opt);
}

/* Verify that sockaddr looks sendable. Common verification has already
* been taken care of.
*/
-static int sctp_inet_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
+static int sctp_inet_send_verify(struct net *net, struct sctp_sock *opt,
+ union sctp_addr *addr)
{
return 1;
}
@@ -1562,6 +1582,8 @@ static int __net_init sctp_net_init(struct net *net)
if (err)
goto err_param_init;

+ sctp_get_local_addr_list(net);
+ goto out;
err_param_init:
sctp_proc_exit(net);
err_proc_init:
@@ -1572,7 +1594,12 @@ out:

static void __net_exit sctp_net_exit(struct net *net)
{
+ sctp_free_addr_wq(net);
+ /* Free the control sock */
sctp_ctl_sock_destroy(net);
+ /* Free the local address list. */
+ sctp_free_local_addr_list(net);
+ /* Clean up procfs */
sctp_proc_exit(net);
}

@@ -1623,17 +1650,7 @@ SCTP_STATIC __init int sctp_init(void)
sctp_v4_pf_init();
sctp_v6_pf_init();

- /* Initialize the local address list. */
- INIT_LIST_HEAD(&sctp_local_addr_list);
- spin_lock_init(&sctp_local_addr_lock);
- sctp_get_local_addr_list();

- /* Initialize the address event list */
- INIT_LIST_HEAD(&sctp_addr_waitq);
- INIT_LIST_HEAD(&sctp_auto_asconf_splist);
- spin_lock_init(&sctp_addr_wq_lock);
- sctp_addr_wq_timer.expires = 0;
- setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0);

/* Register SCTP protocol */
status = sctp_v4_protosw_init();
@@ -1689,7 +1706,6 @@ err_add_protocol:
err_v6_protosw_init:
sctp_v4_protosw_exit();
err_protosw_init:
- sctp_free_local_addr_list();
sctp_v6_pf_exit();
sctp_v4_pf_exit();
sctp_hashtable_globals_free();
@@ -1710,15 +1726,11 @@ SCTP_STATIC __exit void sctp_exit(void)
/* Unregister with inet6/inet layers. */
sctp_v6_del_protocol();
sctp_v4_del_protocol();
- sctp_free_addr_wq();

/* Free protosw registrations */
sctp_v6_protosw_exit();
sctp_v4_protosw_exit();

- /* Free the local address list. */
- sctp_free_local_addr_list();
-
/* Unregister with socket layer. */
sctp_v6_pf_exit();
sctp_v4_pf_exit();
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 479a70e..af02b44 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -79,6 +79,7 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
static int sctp_process_param(struct sctp_association *asoc,
union sctp_params param,
const union sctp_addr *peer_addr,
+ struct net *net,
gfp_t gfp);
static void *sctp_addto_param(struct sctp_chunk *chunk, int len,
const void *data);
@@ -2268,7 +2269,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
*/
int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk,
const union sctp_addr *peer_addr,
- sctp_init_chunk_t *peer_init, gfp_t gfp)
+ sctp_init_chunk_t *peer_init, struct net *net, gfp_t gfp)
{
union sctp_params param;
struct sctp_transport *transport;
@@ -2305,7 +2306,7 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk,
src_match = 1;
}

- if (!sctp_process_param(asoc, param, peer_addr, gfp))
+ if (!sctp_process_param(asoc, param, peer_addr, net, gfp))
goto clean_up;
}

@@ -2464,6 +2465,7 @@ nomem:
static int sctp_process_param(struct sctp_association *asoc,
union sctp_params param,
const union sctp_addr *peer_addr,
+ struct net *net,
gfp_t gfp)
{
union sctp_addr addr;
@@ -2494,7 +2496,7 @@ do_addr_param:
af = sctp_get_af_specific(param_type2af(param.p->type));
af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0);
scope = sctp_scope(peer_addr);
- if (sctp_in_scope(&addr, scope))
+ if (sctp_in_scope(&addr, scope, net))
if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED))
return 0;
break;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index fe99628..8fe4a25 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -615,7 +615,8 @@ static int sctp_cmd_process_init(sctp_cmd_seq_t *commands,
* fail during INIT processing (due to malloc problems),
* just return the error and stop processing the stack.
*/
- if (!sctp_process_init(asoc, chunk, sctp_source(chunk), peer_init, gfp))
+ if (!sctp_process_init(asoc, chunk, sctp_source(chunk), peer_init,
+ &init_net, gfp))
error = -ENOMEM;
else
error = 0;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 91dcdd6..85a46ac 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -388,6 +388,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
goto nomem;

if (sctp_assoc_set_bind_addr_from_ep(new_asoc,
+ &init_net,
sctp_scope(sctp_source(chunk)),
GFP_ATOMIC) < 0)
goto nomem_init;
@@ -395,7 +396,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
/* The call, sctp_process_init(), can fail on memory allocation. */
if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk),
(sctp_init_chunk_t *)chunk->chunk_hdr,
- GFP_ATOMIC))
+ &init_net, GFP_ATOMIC))
goto nomem_init;

/* B) "Z" shall respond immediately with an INIT ACK chunk. */
@@ -726,7 +727,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,

if (!sctp_process_init(new_asoc, chunk,
&chunk->subh.cookie_hdr->c.peer_addr,
- peer_init, GFP_ATOMIC))
+ peer_init, &init_net, GFP_ATOMIC))
goto nomem_init;

/* SCTP-AUTH: Now that we've populate required fields in
@@ -1444,7 +1445,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
if (!new_asoc)
goto nomem;

- if (sctp_assoc_set_bind_addr_from_ep(new_asoc,
+ if (sctp_assoc_set_bind_addr_from_ep(new_asoc, &init_net,
sctp_scope(sctp_source(chunk)), GFP_ATOMIC) < 0)
goto nomem;

@@ -1454,7 +1455,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
*/
if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk),
(sctp_init_chunk_t *)chunk->chunk_hdr,
- GFP_ATOMIC))
+ &init_net, GFP_ATOMIC))
goto nomem;

/* Make sure no new addresses are being added during the
@@ -1682,7 +1683,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
peer_init = &chunk->subh.cookie_hdr->c.peer_init[0];

if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init,
- GFP_ATOMIC))
+ &init_net, GFP_ATOMIC))
goto nomem;

/* Make sure no new addresses are being added during the
@@ -1777,7 +1778,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
*/
peer_init = &chunk->subh.cookie_hdr->c.peer_init[0];
if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init,
- GFP_ATOMIC))
+ &init_net, GFP_ATOMIC))
goto nomem;

/* Update the content of current association. */
@@ -5918,7 +5919,8 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc
/* Cache a route for the transport with the chunk's destination as
* the source address.
*/
- sctp_transport_route(transport, (union sctp_addr *)&chunk->dest,
+ sctp_transport_route(&init_net, transport,
+ (union sctp_addr *)&chunk->dest,
sctp_sk(*sctp_get_ctl_sock(&init_net)));

packet = sctp_packet_init(&transport->packet, transport, sport, dport);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 5e25981..790e597 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -101,8 +101,10 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
union sctp_addr *addr, int len);
static int sctp_bindx_add(struct sock *, struct sockaddr *, int);
static int sctp_bindx_rem(struct sock *, struct sockaddr *, int);
-static int sctp_send_asconf_add_ip(struct sock *, struct sockaddr *, int);
-static int sctp_send_asconf_del_ip(struct sock *, struct sockaddr *, int);
+static int sctp_send_asconf_add_ip(struct net*, struct sock *,
+ struct sockaddr *, int);
+static int sctp_send_asconf_del_ip(struct net*, struct sock *,
+ struct sockaddr *, int);
static int sctp_send_asconf(struct sctp_association *asoc,
struct sctp_chunk *chunk);
static int sctp_do_bind(struct sock *, union sctp_addr *, int);
@@ -197,7 +199,7 @@ static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
if (!af->addr_valid(addr, sctp_sk(sk), NULL))
return -EINVAL;

- if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr)))
+ if (!sctp_sk(sk)->pf->send_verify(sock_net(sk), sctp_sk(sk), (addr)))
return -EINVAL;

return 0;
@@ -360,7 +362,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
len);

/* PF specific bind() address verification. */
- if (!sp->pf->bind_verify(sp, addr))
+ if (!sp->pf->bind_verify(sock_net(sk), sp, addr))
return -EADDRNOTAVAIL;

/* We must either be unbound, or bind to the same port.
@@ -511,7 +513,8 @@ err_bindx_add:
*
* Only sctp_setsockopt_bindx() is supposed to call this function.
*/
-static int sctp_send_asconf_add_ip(struct sock *sk,
+static int sctp_send_asconf_add_ip(struct net *net,
+ struct sock *sk,
struct sockaddr *addrs,
int addrcnt)
{
@@ -608,7 +611,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
trans->ssthresh = asoc->peer.i.a_rwnd;
trans->rto = asoc->rto_initial;
trans->rtt = trans->srtt = trans->rttvar = 0;
- sctp_transport_route(trans, NULL,
+ sctp_transport_route(net, trans, NULL,
sctp_sk(asoc->base.sk));
}
}
@@ -713,7 +716,8 @@ err_bindx_rem:
*
* Only sctp_setsockopt_bindx() is supposed to call this function.
*/
-static int sctp_send_asconf_del_ip(struct sock *sk,
+static int sctp_send_asconf_del_ip(struct net *net,
+ struct sock *sk,
struct sockaddr *addrs,
int addrcnt)
{
@@ -847,7 +851,7 @@ skip_mkasconf:
list_for_each_entry(transport, &asoc->peer.transport_addr_list,
transports) {
dst_release(transport->dst);
- sctp_transport_route(transport, NULL,
+ sctp_transport_route(net, transport, NULL,
sctp_sk(asoc->base.sk));
}

@@ -861,7 +865,8 @@ out:
}

/* set addr events to assocs in the endpoint. ep and addr_wq must be locked */
-int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw)
+int sctp_asconf_mgmt(struct net *net, struct sctp_sock *sp,
+ struct sctp_sockaddr_entry *addrw)
{
struct sock *sk = sctp_opt2sk(sp);
union sctp_addr *addr;
@@ -877,9 +882,11 @@ int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw)
return -EINVAL;

if (addrw->state == SCTP_ADDR_NEW)
- return sctp_send_asconf_add_ip(sk, (struct sockaddr *)addr, 1);
+ return sctp_send_asconf_add_ip(net, sk,
+ (struct sockaddr *)addr, 1);
else
- return sctp_send_asconf_del_ip(sk, (struct sockaddr *)addr, 1);
+ return sctp_send_asconf_del_ip(net, sk,
+ (struct sockaddr *)addr, 1);
}

/* Helper for tunneling sctp_bindx() requests through sctp_setsockopt()
@@ -969,6 +976,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
struct sockaddr *sa_addr;
void *addr_buf;
struct sctp_af *af;
+ struct net *net = sock_net(sk);

SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p"
" addrs_size %d opt %d\n", sk, addrs, addrs_size, op);
@@ -1019,14 +1027,14 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
err = sctp_bindx_add(sk, kaddrs, addrcnt);
if (err)
goto out;
- err = sctp_send_asconf_add_ip(sk, kaddrs, addrcnt);
+ err = sctp_send_asconf_add_ip(net, sk, kaddrs, addrcnt);
break;

case SCTP_BINDX_REM_ADDR:
err = sctp_bindx_rem(sk, kaddrs, addrcnt);
if (err)
goto out;
- err = sctp_send_asconf_del_ip(sk, kaddrs, addrcnt);
+ err = sctp_send_asconf_del_ip(net, sk, kaddrs, addrcnt);
break;

default:
@@ -1170,8 +1178,9 @@ static int __sctp_connect(struct sock* sk,
goto out_free;
}

- err = sctp_assoc_set_bind_addr_from_ep(asoc, scope,
- GFP_KERNEL);
+ err = sctp_assoc_set_bind_addr_from_ep(asoc,
+ sock_net(sk),
+ scope, GFP_KERNEL);
if (err < 0) {
goto out_free;
}
@@ -1797,7 +1806,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
goto out_unlock;
}
asoc = new_asoc;
- err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL);
+ err = sctp_assoc_set_bind_addr_from_ep(asoc, sock_net(sk),
+ scope, GFP_KERNEL);
if (err < 0) {
err = -ENOMEM;
goto out_free;
@@ -2309,7 +2319,8 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
* SPP_SACKDELAY_ENABLE, setting both will have undefined
* results.
*/
-static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
+static int sctp_apply_peer_addr_params(struct net *net,
+ struct sctp_paddrparams *params,
struct sctp_transport *trans,
struct sctp_association *asoc,
struct sctp_sock *sp,
@@ -2389,7 +2400,8 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
trans->param_flags =
(trans->param_flags & ~SPP_PMTUD) | pmtud_change;
if (update) {
- sctp_transport_pmtu(trans, sctp_opt2sk(sp));
+ sctp_transport_pmtu(net, trans,
+ sctp_opt2sk(sp));
sctp_assoc_sync_pmtu(sctp_opt2sk(sp), asoc);
}
} else if (asoc) {
@@ -2457,6 +2469,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
struct sctp_transport *trans = NULL;
struct sctp_association *asoc = NULL;
struct sctp_sock *sp = sctp_sk(sk);
+ struct net *net = sock_net(sk);
int error;
int hb_change, pmtud_change, sackdelay_change;

@@ -2504,7 +2517,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
return -EINVAL;

/* Process parameters. */
- error = sctp_apply_peer_addr_params(&params, trans, asoc, sp,
+ error = sctp_apply_peer_addr_params(net, &params, trans, asoc, sp,
hb_change, pmtud_change,
sackdelay_change);

@@ -2517,8 +2530,8 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
if (!trans && asoc) {
list_for_each_entry(trans, &asoc->peer.transport_addr_list,
transports) {
- sctp_apply_peer_addr_params(&params, trans, asoc, sp,
- hb_change, pmtud_change,
+ sctp_apply_peer_addr_params(net, &params, trans, asoc,
+ sp, hb_change, pmtud_change,
sackdelay_change);
}
}
@@ -4653,9 +4666,11 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
union sctp_addr temp;
int cnt = 0;
int addrlen;
+ struct sctp_net_params *net_params =
+ sctp_get_params(sock_net(sk));

rcu_read_lock();
- list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
+ list_for_each_entry_rcu(addr, &net_params->local_addr_list, list) {
if (!addr->valid)
continue;

diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index c97472b..856ba86 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -214,12 +214,14 @@ void sctp_transport_set_owner(struct sctp_transport *transport,
}

/* Initialize the pmtu of a transport. */
-void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk)
+void sctp_transport_pmtu(struct net *net, struct sctp_transport *transport,
+ struct sock *sk)
{
/* If we don't have a fresh route, look one up */
if (!transport->dst || transport->dst->obsolete) {
dst_release(transport->dst);
- transport->af_specific->get_dst(transport, &transport->saddr,
+ transport->af_specific->get_dst(net, transport,
+ &transport->saddr,
&transport->fl, sk);
}

@@ -247,27 +249,28 @@ void sctp_transport_update_pmtu(struct sock *sk, struct sctp_transport *t, u32 p

dst = sctp_transport_dst_check(t);
if (!dst)
- t->af_specific->get_dst(t, &t->saddr, &t->fl, sk);
+ t->af_specific->get_dst(sock_net(sk), t, &t->saddr, &t->fl, sk);

if (dst) {
dst->ops->update_pmtu(dst, sk, NULL, pmtu);

dst = sctp_transport_dst_check(t);
if (!dst)
- t->af_specific->get_dst(t, &t->saddr, &t->fl, sk);
+ t->af_specific->get_dst(sock_net(sk), t, &t->saddr,
+ &t->fl, sk);
}
}

/* Caches the dst entry and source address for a transport's destination
* address.
*/
-void sctp_transport_route(struct sctp_transport *transport,
+void sctp_transport_route(struct net *net, struct sctp_transport *transport,
union sctp_addr *saddr, struct sctp_sock *opt)
{
struct sctp_association *asoc = transport->asoc;
struct sctp_af *af = transport->af_specific;

- af->get_dst(transport, saddr, &transport->fl, sctp_opt2sk(opt));
+ af->get_dst(net, transport, saddr, &transport->fl, sctp_opt2sk(opt));

if (saddr)
memcpy(&transport->saddr, saddr, sizeof(union sctp_addr));
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/