The following set of patches enable network-namespaces for the SCTP protocol.
The multitude of global parameters are stored in a net_generic
structure, and the bulk of the patches enable the protocol to access
the parameters on a per-namespace basis. The first five patches
enable netns handling of the protocol, procfs and sysfs.
Signed-off-by: Jan Ariyasu <[email protected]>
---
From: Jan Ariyasu <[email protected]>
Date: Sat, 4 Aug 2012 15:30:37 -0600
> The following set of patches enable network-namespaces for the SCTP protocol.
>
> The multitude of global parameters are stored in a net_generic
> structure, and the bulk of the patches enable the protocol to access
> the parameters on a per-namespace basis. The first five patches
> enable netns handling of the protocol, procfs and sysfs.
>
> Signed-off-by: Jan Ariyasu <[email protected]>
Patch 02/13 didn't show up at all.
Jan Ariyasu <[email protected]> writes:
> The following set of patches enable network-namespaces for the SCTP protocol.
>
> The multitude of global parameters are stored in a net_generic
> structure, and the bulk of the patches enable the protocol to access
> the parameters on a per-namespace basis. The first five patches
> enable netns handling of the protocol, procfs and sysfs.
I am going to do something to muddy the waters here, that I had hoped to
avoid when I saw your patchset.
A few weeks ago I wanted to play with sctp and also made a network
namespace enabled version. I am not deeply attached to my changes,
however when comparing the differences I realized that your code fails
to make the lookup of associations per network namespace.
Given that we only have source and destination port to lookup
assoications by this almost guarantees one network namespace can
accidentially use the association of another network namespace meerly
by reusing the same ports.
The downside with my version is that it does not make all of the sctp
tunables per network namespace the way yours does, but making all of
the tunables per network namespace should be straight forward from
my base.
My patchset also misses some nice to haves like making the association
id allocation per network namespace. It is not important for
correctness of the code but it might allow an information leak between
namespaces.
So Jan I am going to send my patchset and hopefully you can rebase your
changes to make all of the tunables per network namespace on top of
mine.
Since my patchset is half the size of your I think that is the most
reasonable way to go.
Eric
The other day I wanted to play around with sctp and did a basic pass to
make sctp per network namespace, so that I could play more conviniently.
Apparently this is an idea who's time has come because Jan Ariyasu also
made a similar set of changes.
I have played around some with these changes and have confirmed that
sctp_test from lksctp-tools works without problems.
Compared to Jan's changes I have per network namespace association and
endpoint hash table lookups, my patch has per network namespace mib
statistics, my changes don't contiain per network namespace tunables
and my patchset only touches about half as many lines as Jan's change.
So for both correctness and simplicity reasons it looks like the
practical way to handle this is to merge my changes and get Jan rebase
his tunable changes on top.
include/net/net_namespace.h | 4 +
include/net/netns/sctp.h | 37 +++++
include/net/sctp/sctp.h | 44 +++----
include/net/sctp/structs.h | 28 +----
net/sctp/associola.c | 9 +-
net/sctp/bind_addr.c | 14 +-
net/sctp/chunk.c | 2 +-
net/sctp/endpointola.c | 12 +-
net/sctp/input.c | 109 +++++++++------
net/sctp/ipv6.c | 36 +++---
net/sctp/output.c | 2 +-
net/sctp/outqueue.c | 18 ++-
net/sctp/proc.c | 58 +++++---
net/sctp/protocol.c | 305 ++++++++++++++++++++++---------------------
net/sctp/sm_statefuns.c | 208 ++++++++++++++++++-----------
net/sctp/socket.c | 29 +++--
net/sctp/ulpqueue.c | 18 ++-
17 files changed, 533 insertions(+), 400 deletions(-)
Eric W. Biederman (9):
sctp: Make the port hash table use struct net in it's key.
sctp: Make the endpoint hashtable handle multiple network namespaces
sctp: Make the association hashtable handle multiple network namespaces
sctp: Make the address lists per network namespace
sctp: Make the ctl_sock per network namespace
sctp: Move the percpu sockets counter out of sctp_proc_init
sctp: Make the proc files per network namespace.
sctp: Enable sctp in all network namespaces
sctp: Make the mib per network namespace
- Add struct net into the port hash table hash calculation
- Add struct net inot the struct sctp_bind_bucket so there
is a memory of which network namespace a port is allocated in.
No need for a ref count because sctp_bind_bucket only exists
when there are sockets in the hash table and sockets can not
change their network namspace, and sockets already ref count
their network namespace.
- Add struct net into the key comparison when we are testing
to see if we have found the port hash table entry we are
looking for.
With these changes lookups in the port hash table becomes
safe to use in multiple network namespaces.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/sctp/sctp.h | 4 ++--
include/net/sctp/structs.h | 1 +
net/sctp/socket.c | 22 +++++++++++++---------
3 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index ff49964..7c05040 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -632,9 +632,9 @@ static inline int sctp_sanity_check(void)
/* Warning: The following hash functions assume a power of two 'size'. */
/* This is the hash function for the SCTP port hash table. */
-static inline int sctp_phashfn(__u16 lport)
+static inline int sctp_phashfn(struct net *net, __u16 lport)
{
- return lport & (sctp_port_hashsize - 1);
+ return (net_hash_mix(net) + lport) & (sctp_port_hashsize - 1);
}
/* This is the hash function for the endpoint hash table. */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index fc5e600..c089bb1 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -102,6 +102,7 @@ struct sctp_bind_bucket {
unsigned short fastreuse;
struct hlist_node node;
struct hlist_head owner;
+ struct net *net;
};
struct sctp_bind_hashbucket {
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 5e25981..4316b0f 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5769,7 +5769,7 @@ static void sctp_unhash(struct sock *sk)
* a fastreuse flag (FIXME: NPI ipg).
*/
static struct sctp_bind_bucket *sctp_bucket_create(
- struct sctp_bind_hashbucket *head, unsigned short snum);
+ struct sctp_bind_hashbucket *head, struct net *, unsigned short snum);
static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
{
@@ -5799,11 +5799,12 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
rover = low;
if (inet_is_reserved_local_port(rover))
continue;
- index = sctp_phashfn(rover);
+ index = sctp_phashfn(sock_net(sk), rover);
head = &sctp_port_hashtable[index];
sctp_spin_lock(&head->lock);
sctp_for_each_hentry(pp, node, &head->chain)
- if (pp->port == rover)
+ if ((pp->port == rover) &&
+ net_eq(sock_net(sk), pp->net))
goto next;
break;
next:
@@ -5827,10 +5828,10 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
* to the port number (snum) - we detect that with the
* port iterator, pp being NULL.
*/
- head = &sctp_port_hashtable[sctp_phashfn(snum)];
+ head = &sctp_port_hashtable[sctp_phashfn(sock_net(sk), snum)];
sctp_spin_lock(&head->lock);
sctp_for_each_hentry(pp, node, &head->chain) {
- if (pp->port == snum)
+ if ((pp->port == snum) && net_eq(pp->net, sock_net(sk)))
goto pp_found;
}
}
@@ -5881,7 +5882,7 @@ pp_found:
pp_not_found:
/* If there was a hash table miss, create a new port. */
ret = 1;
- if (!pp && !(pp = sctp_bucket_create(head, snum)))
+ if (!pp && !(pp = sctp_bucket_create(head, sock_net(sk), snum)))
goto fail_unlock;
/* In either case (hit or miss), make sure fastreuse is 1 only
@@ -6113,7 +6114,7 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
********************************************************************/
static struct sctp_bind_bucket *sctp_bucket_create(
- struct sctp_bind_hashbucket *head, unsigned short snum)
+ struct sctp_bind_hashbucket *head, struct net *net, unsigned short snum)
{
struct sctp_bind_bucket *pp;
@@ -6123,6 +6124,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
pp->port = snum;
pp->fastreuse = 0;
INIT_HLIST_HEAD(&pp->owner);
+ pp->net = net;
hlist_add_head(&pp->node, &head->chain);
}
return pp;
@@ -6142,7 +6144,8 @@ static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
static inline void __sctp_put_port(struct sock *sk)
{
struct sctp_bind_hashbucket *head =
- &sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->inet_num)];
+ &sctp_port_hashtable[sctp_phashfn(sock_net(sk),
+ inet_sk(sk)->inet_num)];
struct sctp_bind_bucket *pp;
sctp_spin_lock(&head->lock);
@@ -6809,7 +6812,8 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
newsp->hmac = NULL;
/* Hook this new socket in to the bind_hash list. */
- head = &sctp_port_hashtable[sctp_phashfn(inet_sk(oldsk)->inet_num)];
+ head = &sctp_port_hashtable[sctp_phashfn(sock_net(oldsk),
+ inet_sk(oldsk)->inet_num)];
sctp_local_bh_disable();
sctp_spin_lock(&head->lock);
pp = sctp_sk(oldsk)->bind_hash;
--
1.7.5.4
- Use struct net in the hash calculation
- Use sock_net(endpoint.base.sk) in the endpoint lookups.
- On receive calculate the network namespace from skb->dev.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/sctp/sctp.h | 4 ++--
include/net/sctp/structs.h | 2 +-
net/sctp/endpointola.c | 4 +++-
net/sctp/input.c | 19 ++++++++++++-------
4 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 7c05040..87b119f 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -638,9 +638,9 @@ static inline int sctp_phashfn(struct net *net, __u16 lport)
}
/* This is the hash function for the endpoint hash table. */
-static inline int sctp_ep_hashfn(__u16 lport)
+static inline int sctp_ep_hashfn(struct net *net, __u16 lport)
{
- return lport & (sctp_ep_hashsize - 1);
+ return (net_hash_mix(net) + lport) & (sctp_ep_hashsize - 1);
}
/* This is the hash function for the association hash table. */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index c089bb1..9f9de55 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1426,7 +1426,7 @@ struct sctp_association *sctp_endpoint_lookup_assoc(
int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
const union sctp_addr *);
struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
- const union sctp_addr *);
+ struct net *, const union sctp_addr *);
int sctp_has_association(const union sctp_addr *laddr,
const union sctp_addr *paddr);
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 68a385d..50c87b4 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -302,11 +302,13 @@ void sctp_endpoint_put(struct sctp_endpoint *ep)
/* Is this the endpoint we are looking for? */
struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
+ struct net *net,
const union sctp_addr *laddr)
{
struct sctp_endpoint *retval = NULL;
- if (htons(ep->base.bind_addr.port) == laddr->v4.sin_port) {
+ if ((htons(ep->base.bind_addr.port) == laddr->v4.sin_port) &&
+ net_eq(sock_net(ep->base.sk), net)) {
if (sctp_bind_addr_match(&ep->base.bind_addr, laddr,
sctp_sk(ep->base.sk)))
retval = ep;
diff --git a/net/sctp/input.c b/net/sctp/input.c
index e64d521..c0ca893 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -70,7 +70,8 @@ static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
const union sctp_addr *laddr,
const union sctp_addr *paddr,
struct sctp_transport **transportp);
-static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
+ const union sctp_addr *laddr);
static struct sctp_association *__sctp_lookup_association(
const union sctp_addr *local,
const union sctp_addr *peer,
@@ -129,6 +130,7 @@ int sctp_rcv(struct sk_buff *skb)
union sctp_addr dest;
int family;
struct sctp_af *af;
+ struct net *net = dev_net(skb->dev);
if (skb->pkt_type!=PACKET_HOST)
goto discard_it;
@@ -181,7 +183,7 @@ int sctp_rcv(struct sk_buff *skb)
asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
if (!asoc)
- ep = __sctp_rcv_lookup_endpoint(&dest);
+ ep = __sctp_rcv_lookup_endpoint(net, &dest);
/* Retrieve the common input handling substructure. */
rcvr = asoc ? &asoc->base : &ep->base;
@@ -723,12 +725,13 @@ discard:
/* Insert endpoint into the hash table. */
static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
{
+ struct net *net = sock_net(ep->base.sk);
struct sctp_ep_common *epb;
struct sctp_hashbucket *head;
epb = &ep->base;
- epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
+ epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port);
head = &sctp_ep_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
@@ -747,12 +750,13 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep)
/* Remove endpoint from the hash table. */
static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
{
+ struct net *net = sock_net(ep->base.sk);
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
epb = &ep->base;
- epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
+ epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port);
head = &sctp_ep_hashtable[epb->hashent];
@@ -770,7 +774,8 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
}
/* Look up an endpoint. */
-static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
+ const union sctp_addr *laddr)
{
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
@@ -778,12 +783,12 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
struct hlist_node *node;
int hash;
- hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port));
+ hash = sctp_ep_hashfn(net, ntohs(laddr->v4.sin_port));
head = &sctp_ep_hashtable[hash];
read_lock(&head->lock);
sctp_for_each_hentry(epb, node, &head->chain) {
ep = sctp_ep(epb);
- if (sctp_endpoint_is_match(ep, laddr))
+ if (sctp_endpoint_is_match(ep, net, laddr))
goto hit;
}
--
1.7.5.4
- Use struct net in the hash calculation
- Use sock_net(association.base.sk) in the association lookups.
- On receive calculate the network namespace from skb->dev.
- Pass struct net from receive down to the functions that actually
do the association lookup.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/sctp/sctp.h | 6 ++--
include/net/sctp/structs.h | 3 +-
net/sctp/associola.c | 4 ++-
net/sctp/endpointola.c | 6 +++-
net/sctp/input.c | 64 +++++++++++++++++++++++++++----------------
net/sctp/ipv6.c | 3 +-
6 files changed, 54 insertions(+), 32 deletions(-)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 87b119f..640915a 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -156,7 +156,7 @@ void sctp_hash_established(struct sctp_association *);
void sctp_unhash_established(struct sctp_association *);
void sctp_hash_endpoint(struct sctp_endpoint *);
void sctp_unhash_endpoint(struct sctp_endpoint *);
-struct sock *sctp_err_lookup(int family, struct sk_buff *,
+struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
struct sctphdr *, struct sctp_association **,
struct sctp_transport **);
void sctp_err_finish(struct sock *, struct sctp_association *);
@@ -644,9 +644,9 @@ static inline int sctp_ep_hashfn(struct net *net, __u16 lport)
}
/* This is the hash function for the association hash table. */
-static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport)
+static inline int sctp_assoc_hashfn(struct net *net, __u16 lport, __u16 rport)
{
- int h = (lport << 16) + rport;
+ int h = (lport << 16) + rport + net_hash_mix(net);
h ^= h>>8;
return h & (sctp_assoc_hashsize - 1);
}
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 9f9de55..c0563d1 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1427,7 +1427,7 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
const union sctp_addr *);
struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
struct net *, const union sctp_addr *);
-int sctp_has_association(const union sctp_addr *laddr,
+int sctp_has_association(struct net *net, const union sctp_addr *laddr,
const union sctp_addr *paddr);
int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t,
@@ -2014,6 +2014,7 @@ void sctp_assoc_control_transport(struct sctp_association *,
sctp_transport_cmd_t, sctp_sn_error_t);
struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *, __u32);
struct sctp_transport *sctp_assoc_is_match(struct sctp_association *,
+ struct net *,
const union sctp_addr *,
const union sctp_addr *);
void sctp_assoc_migrate(struct sctp_association *, struct sock *);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index ebaef3e..a3601f3 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1089,13 +1089,15 @@ out:
/* Is this the association we are looking for? */
struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc,
+ struct net *net,
const union sctp_addr *laddr,
const union sctp_addr *paddr)
{
struct sctp_transport *transport;
if ((htons(asoc->base.bind_addr.port) == laddr->v4.sin_port) &&
- (htons(asoc->peer.port) == paddr->v4.sin_port)) {
+ (htons(asoc->peer.port) == paddr->v4.sin_port) &&
+ net_eq(sock_net(asoc->base.sk), net)) {
transport = sctp_assoc_lookup_paddr(asoc, paddr);
if (!transport)
goto out;
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 50c87b4..6b76393 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -345,7 +345,8 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
rport = ntohs(paddr->v4.sin_port);
- hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport);
+ hash = sctp_assoc_hashfn(sock_net(ep->base.sk), ep->base.bind_addr.port,
+ rport);
head = &sctp_assoc_hashtable[hash];
read_lock(&head->lock);
sctp_for_each_hentry(epb, node, &head->chain) {
@@ -388,13 +389,14 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
{
struct sctp_sockaddr_entry *addr;
struct sctp_bind_addr *bp;
+ struct net *net = sock_net(ep->base.sk);
bp = &ep->base.bind_addr;
/* This function is called with the socket lock held,
* so the address_list can not change.
*/
list_for_each_entry(addr, &bp->address_list, list) {
- if (sctp_has_association(&addr->a, paddr))
+ if (sctp_has_association(net, &addr->a, paddr))
return 1;
}
diff --git a/net/sctp/input.c b/net/sctp/input.c
index c0ca893..a7e9a85 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -66,13 +66,15 @@
/* Forward declarations for internal helpers. */
static int sctp_rcv_ootb(struct sk_buff *);
-static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_lookup(struct net *net,
+ struct sk_buff *skb,
const union sctp_addr *laddr,
const union sctp_addr *paddr,
struct sctp_transport **transportp);
static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
const union sctp_addr *laddr);
static struct sctp_association *__sctp_lookup_association(
+ struct net *net,
const union sctp_addr *local,
const union sctp_addr *peer,
struct sctp_transport **pt);
@@ -180,7 +182,7 @@ int sctp_rcv(struct sk_buff *skb)
!af->addr_valid(&dest, NULL, skb))
goto discard_it;
- asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
+ asoc = __sctp_rcv_lookup(net, skb, &src, &dest, &transport);
if (!asoc)
ep = __sctp_rcv_lookup_endpoint(net, &dest);
@@ -476,7 +478,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
}
/* Common lookup code for icmp/icmpv6 error handler. */
-struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
+struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
struct sctphdr *sctphdr,
struct sctp_association **app,
struct sctp_transport **tpp)
@@ -505,7 +507,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
/* Look for an association that matches the incoming ICMP error
* packet.
*/
- asoc = __sctp_lookup_association(&saddr, &daddr, &transport);
+ asoc = __sctp_lookup_association(net, &saddr, &daddr, &transport);
if (!asoc)
return NULL;
@@ -588,6 +590,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
struct inet_sock *inet;
sk_buff_data_t saveip, savesctp;
int err;
+ struct net *net = dev_net(skb->dev);
if (skb->len < ihlen + 8) {
ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
@@ -599,7 +602,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
savesctp = skb->transport_header;
skb_reset_network_header(skb);
skb_set_transport_header(skb, ihlen);
- sk = sctp_err_lookup(AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
+ sk = sctp_err_lookup(net, AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
/* Put back, the original values. */
skb->network_header = saveip;
skb->transport_header = savesctp;
@@ -803,13 +806,15 @@ hit:
/* Insert association into the hash table. */
static void __sctp_hash_established(struct sctp_association *asoc)
{
+ struct net *net = sock_net(asoc->base.sk);
struct sctp_ep_common *epb;
struct sctp_hashbucket *head;
epb = &asoc->base;
/* Calculate which chain this entry will belong to. */
- epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port, asoc->peer.port);
+ epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port,
+ asoc->peer.port);
head = &sctp_assoc_hashtable[epb->hashent];
@@ -832,12 +837,13 @@ void sctp_hash_established(struct sctp_association *asoc)
/* Remove association from the hash table. */
static void __sctp_unhash_established(struct sctp_association *asoc)
{
+ struct net *net = sock_net(asoc->base.sk);
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
epb = &asoc->base;
- epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port,
+ epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port,
asoc->peer.port);
head = &sctp_assoc_hashtable[epb->hashent];
@@ -860,6 +866,7 @@ void sctp_unhash_established(struct sctp_association *asoc)
/* Look up an association. */
static struct sctp_association *__sctp_lookup_association(
+ struct net *net,
const union sctp_addr *local,
const union sctp_addr *peer,
struct sctp_transport **pt)
@@ -874,12 +881,13 @@ static struct sctp_association *__sctp_lookup_association(
/* Optimize here for direct hit, only listening connections can
* have wildcards anyways.
*/
- hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port));
+ hash = sctp_assoc_hashfn(net, ntohs(local->v4.sin_port),
+ ntohs(peer->v4.sin_port));
head = &sctp_assoc_hashtable[hash];
read_lock(&head->lock);
sctp_for_each_hentry(epb, node, &head->chain) {
asoc = sctp_assoc(epb);
- transport = sctp_assoc_is_match(asoc, local, peer);
+ transport = sctp_assoc_is_match(asoc, net, local, peer);
if (transport)
goto hit;
}
@@ -897,27 +905,29 @@ hit:
/* Look up an association. BH-safe. */
SCTP_STATIC
-struct sctp_association *sctp_lookup_association(const union sctp_addr *laddr,
+struct sctp_association *sctp_lookup_association(struct net *net,
+ const union sctp_addr *laddr,
const union sctp_addr *paddr,
struct sctp_transport **transportp)
{
struct sctp_association *asoc;
sctp_local_bh_disable();
- asoc = __sctp_lookup_association(laddr, paddr, transportp);
+ asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
sctp_local_bh_enable();
return asoc;
}
/* Is there an association matching the given local and peer addresses? */
-int sctp_has_association(const union sctp_addr *laddr,
+int sctp_has_association(struct net *net,
+ const union sctp_addr *laddr,
const union sctp_addr *paddr)
{
struct sctp_association *asoc;
struct sctp_transport *transport;
- if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) {
+ if ((asoc = sctp_lookup_association(net, laddr, paddr, &transport))) {
sctp_association_put(asoc);
return 1;
}
@@ -943,7 +953,8 @@ int sctp_has_association(const union sctp_addr *laddr,
* in certain circumstances.
*
*/
-static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
+ struct sk_buff *skb,
const union sctp_addr *laddr, struct sctp_transport **transportp)
{
struct sctp_association *asoc;
@@ -983,7 +994,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
af->from_addr_param(paddr, params.addr, sh->source, 0);
- asoc = __sctp_lookup_association(laddr, paddr, &transport);
+ asoc = __sctp_lookup_association(net, laddr, paddr, &transport);
if (asoc)
return asoc;
}
@@ -1006,6 +1017,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
* subsequent ASCONF Chunks. If found, proceed to rule D4.
*/
static struct sctp_association *__sctp_rcv_asconf_lookup(
+ struct net *net,
sctp_chunkhdr_t *ch,
const union sctp_addr *laddr,
__be16 peer_port,
@@ -1025,7 +1037,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
af->from_addr_param(&paddr, param, peer_port, 0);
- return __sctp_lookup_association(laddr, &paddr, transportp);
+ return __sctp_lookup_association(net, laddr, &paddr, transportp);
}
@@ -1038,7 +1050,8 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
* This means that any chunks that can help us identify the association need
* to be looked at to find this association.
*/
-static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
+ struct sk_buff *skb,
const union sctp_addr *laddr,
struct sctp_transport **transportp)
{
@@ -1080,7 +1093,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
case SCTP_CID_ASCONF:
if (have_auth || sctp_addip_noauth)
- asoc = __sctp_rcv_asconf_lookup(ch, laddr,
+ asoc = __sctp_rcv_asconf_lookup(
+ net, ch, laddr,
sctp_hdr(skb)->source,
transportp);
default:
@@ -1103,7 +1117,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
* include looking inside of INIT/INIT-ACK chunks or after the AUTH
* chunks.
*/
-static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
+ struct sk_buff *skb,
const union sctp_addr *laddr,
struct sctp_transport **transportp)
{
@@ -1123,11 +1138,11 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
switch (ch->type) {
case SCTP_CID_INIT:
case SCTP_CID_INIT_ACK:
- return __sctp_rcv_init_lookup(skb, laddr, transportp);
+ return __sctp_rcv_init_lookup(net, skb, laddr, transportp);
break;
default:
- return __sctp_rcv_walk_lookup(skb, laddr, transportp);
+ return __sctp_rcv_walk_lookup(net, skb, laddr, transportp);
break;
}
@@ -1136,21 +1151,22 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
}
/* Lookup an association for an inbound skb. */
-static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_lookup(struct net *net,
+ struct sk_buff *skb,
const union sctp_addr *paddr,
const union sctp_addr *laddr,
struct sctp_transport **transportp)
{
struct sctp_association *asoc;
- asoc = __sctp_lookup_association(laddr, paddr, transportp);
+ asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
/* Further lookup for INIT/INIT-ACK packets.
* SCTP Implementors Guide, 2.18 Handling of address
* parameters within the INIT or INIT-ACK.
*/
if (!asoc)
- asoc = __sctp_rcv_lookup_harder(skb, laddr, transportp);
+ asoc = __sctp_rcv_lookup_harder(net, skb, laddr, transportp);
return asoc;
}
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index ed7139e..2165a7e 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -154,6 +154,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
struct ipv6_pinfo *np;
sk_buff_data_t saveip, savesctp;
int err;
+ struct net *net = dev_net(skb->dev);
idev = in6_dev_get(skb->dev);
@@ -162,7 +163,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
savesctp = skb->transport_header;
skb_reset_network_header(skb);
skb_set_transport_header(skb, offset);
- sk = sctp_err_lookup(AF_INET6, skb, sctp_hdr(skb), &asoc, &transport);
+ sk = sctp_err_lookup(net, AF_INET6, skb, sctp_hdr(skb), &asoc, &transport);
/* Put back, the original pointers. */
skb->network_header = saveip;
skb->transport_header = savesctp;
--
1.7.5.4
- Move the address lists into struct net
- Add per network namespace initialization and cleanup
- Pass around struct net so it is everywhere I need it.
- Rename all of the global variable references into references
to the variables moved into struct net
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/net_namespace.h | 4 +
include/net/netns/sctp.h | 21 +++++++
include/net/sctp/sctp.h | 4 +-
include/net/sctp/structs.h | 22 +-------
net/sctp/associola.c | 3 +-
net/sctp/bind_addr.c | 14 ++--
net/sctp/ipv6.c | 17 +++---
net/sctp/protocol.c | 141 +++++++++++++++++++++++++------------------
net/sctp/socket.c | 7 +-
9 files changed, 131 insertions(+), 102 deletions(-)
create mode 100644 include/net/netns/sctp.h
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index ae1cd6c..8ab5250 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -15,6 +15,7 @@
#include <net/netns/packet.h>
#include <net/netns/ipv4.h>
#include <net/netns/ipv6.h>
+#include <net/netns/sctp.h>
#include <net/netns/dccp.h>
#include <net/netns/x_tables.h>
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
@@ -80,6 +81,9 @@ struct net {
#if IS_ENABLED(CONFIG_IPV6)
struct netns_ipv6 ipv6;
#endif
+#if defined(CONFIG_IP_SCTP) || defined(CONFIG_IP_SCTP_MODULE)
+ struct netns_sctp sctp;
+#endif
#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
struct netns_dccp dccp;
#endif
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
new file mode 100644
index 0000000..cbd684e
--- /dev/null
+++ b/include/net/netns/sctp.h
@@ -0,0 +1,21 @@
+#ifndef __NETNS_SCTP_H__
+#define __NETNS_SCTP_H__
+
+struct netns_sctp {
+ /* This is the global local address list.
+ * We actively maintain this complete list of addresses on
+ * the system by catching address add/delete events.
+ *
+ * It is a list of sctp_sockaddr_entry.
+ */
+ struct list_head local_addr_list;
+ struct list_head addr_waitq;
+ struct timer_list addr_wq_timer;
+ struct list_head auto_asconf_splist;
+ spinlock_t addr_wq_lock;
+
+ /* Lock that protects the local_addr_list writers */
+ spinlock_t local_addr_lock;
+};
+
+#endif /* __NETNS_SCTP_H__ */
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 640915a..00c9205 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -115,12 +115,12 @@
* sctp/protocol.c
*/
extern struct sock *sctp_get_ctl_sock(void);
-extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
+extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
sctp_scope_t, gfp_t gfp,
int flags);
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
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index c0563d1..6bdfcab 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -205,21 +205,7 @@ extern struct sctp_globals {
int port_hashsize;
struct sctp_bind_hashbucket *port_hashtable;
- /* This is the global local address list.
- * We actively maintain this complete list of addresses on
- * the system by catching address add/delete events.
- *
- * It is a list of sctp_sockaddr_entry.
- */
- struct list_head local_addr_list;
int default_auto_asconf;
- struct list_head addr_waitq;
- struct timer_list addr_wq_timer;
- struct list_head auto_asconf_splist;
- spinlock_t addr_wq_lock;
-
- /* Lock that protects the local_addr_list writers */
- spinlock_t addr_list_lock;
/* Flag to indicate if addip is enabled. */
int addip_enable;
@@ -278,12 +264,6 @@ extern struct sctp_globals {
#define sctp_assoc_hashtable (sctp_globals.assoc_hashtable)
#define sctp_port_hashsize (sctp_globals.port_hashsize)
#define sctp_port_hashtable (sctp_globals.port_hashtable)
-#define sctp_local_addr_list (sctp_globals.local_addr_list)
-#define sctp_local_addr_lock (sctp_globals.addr_list_lock)
-#define sctp_auto_asconf_splist (sctp_globals.auto_asconf_splist)
-#define sctp_addr_waitq (sctp_globals.addr_waitq)
-#define sctp_addr_wq_timer (sctp_globals.addr_wq_timer)
-#define sctp_addr_wq_lock (sctp_globals.addr_wq_lock)
#define sctp_default_auto_asconf (sctp_globals.default_auto_asconf)
#define sctp_scope_policy (sctp_globals.ipv4_scope_policy)
#define sctp_addip_enable (sctp_globals.addip_enable)
@@ -1241,7 +1221,7 @@ struct sctp_bind_addr {
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,
+int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
const struct sctp_bind_addr *src,
sctp_scope_t scope, gfp_t gfp,
int flags);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index a3601f3..ed4930b 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1544,7 +1544,8 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
if (asoc->peer.ipv6_address)
flags |= SCTP_ADDR6_PEERSUPP;
- return sctp_bind_addr_copy(&asoc->base.bind_addr,
+ return sctp_bind_addr_copy(sock_net(asoc->base.sk),
+ &asoc->base.bind_addr,
&asoc->ep->base.bind_addr,
scope, gfp, flags);
}
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 4ece451..a85ce4b 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -52,8 +52,8 @@
#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,
+static int sctp_copy_one_addr(struct net *, struct sctp_bind_addr *,
+ union sctp_addr *, sctp_scope_t scope, gfp_t gfp,
int flags);
static void sctp_bind_addr_clean(struct sctp_bind_addr *);
@@ -62,7 +62,7 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *);
/* Copy 'src' to 'dest' taking 'scope' into account. Omit addresses
* in 'src' which have a broader scope than 'scope'.
*/
-int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
+int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
const struct sctp_bind_addr *src,
sctp_scope_t scope, gfp_t gfp,
int flags)
@@ -75,7 +75,7 @@ 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,
+ error = sctp_copy_one_addr(net, dest, &addr->a, scope,
gfp, flags);
if (error < 0)
goto out;
@@ -87,7 +87,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(net, dest, &addr->a,
SCTP_SCOPE_LINK, gfp,
flags);
if (error < 0)
@@ -448,7 +448,7 @@ 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,
+static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
union sctp_addr *addr,
sctp_scope_t scope, gfp_t gfp,
int flags)
@@ -456,7 +456,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
int error = 0;
if (sctp_is_any(NULL, addr)) {
- error = sctp_copy_local_addr_list(dest, scope, gfp, flags);
+ error = sctp_copy_local_addr_list(net, dest, scope, gfp, flags);
} else if (sctp_in_scope(addr, scope)) {
/* Now that the address is in scope, check to see if
* the address type is supported by local sock as
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 2165a7e..bbf1534 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -99,6 +99,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
struct sctp_sockaddr_entry *addr = NULL;
struct sctp_sockaddr_entry *temp;
+ struct net *net = dev_net(ifa->idev->dev);
int found = 0;
switch (ev) {
@@ -110,27 +111,27 @@ 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->sctp.local_addr_lock);
+ list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
+ sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
+ spin_unlock_bh(&net->sctp.local_addr_lock);
}
break;
case NETDEV_DOWN:
- spin_lock_bh(&sctp_local_addr_lock);
+ spin_lock_bh(&net->sctp.local_addr_lock);
list_for_each_entry_safe(addr, temp,
- &sctp_local_addr_list, list) {
+ &net->sctp.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->sctp.local_addr_lock);
if (found)
kfree_rcu(addr, rcu);
break;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 1f89c4e..291e682 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -201,29 +201,29 @@ 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;
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->sctp.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;
- list_for_each_safe(pos, temp, &sctp_local_addr_list) {
+ list_for_each_safe(pos, temp, &net->sctp.local_addr_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
list_del(pos);
kfree(addr);
@@ -231,14 +231,14 @@ 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)
+int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
+ sctp_scope_t scope, gfp_t gfp, int copy_flags)
{
struct sctp_sockaddr_entry *addr;
int error = 0;
rcu_read_lock();
- list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
+ list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
if (!addr->valid)
continue;
if (sctp_in_scope(&addr->a, scope)) {
@@ -627,14 +627,15 @@ static void sctp_v4_ecn_capable(struct sock *sk)
void sctp_addr_wq_timeout_handler(unsigned long arg)
{
+ struct net *net = (struct net *)arg;
struct sctp_sockaddr_entry *addrw, *temp;
struct sctp_sock *sp;
- spin_lock_bh(&sctp_addr_wq_lock);
+ spin_lock_bh(&net->sctp.addr_wq_lock);
- list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
+ list_for_each_entry_safe(addrw, temp, &net->sctp.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,
+ " for cmd %d at entry %p\n", &net->sctp.addr_waitq, &addrw->a, addrw->state,
addrw);
#if IS_ENABLED(CONFIG_IPV6)
@@ -648,7 +649,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;
@@ -656,12 +657,12 @@ 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->sctp.addr_wq_timer, timeo_val);
break;
}
}
#endif
- list_for_each_entry(sp, &sctp_auto_asconf_splist, auto_asconf_list) {
+ list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) {
struct sock *sk;
sk = sctp_opt2sk(sp);
@@ -679,31 +680,32 @@ free_next:
list_del(&addrw->list);
kfree(addrw);
}
- spin_unlock_bh(&sctp_addr_wq_lock);
+ spin_unlock_bh(&net->sctp.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;
- 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->sctp.addr_wq_lock);
+ del_timer(&net->sctp.addr_wq_timer);
+ list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
list_del(&addrw->list);
kfree(addrw);
}
- spin_unlock_bh(&sctp_addr_wq_lock);
+ spin_unlock_bh(&net->sctp.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;
- list_for_each_entry(addrw, &sctp_addr_waitq, list) {
+ list_for_each_entry(addrw, &net->sctp.addr_waitq, list) {
if (addrw->a.sa.sa_family != addr->a.sa.sa_family)
continue;
if (addrw->a.sa.sa_family == AF_INET) {
@@ -719,7 +721,7 @@ 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;
@@ -730,9 +732,9 @@ 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->sctp.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 ",
@@ -741,27 +743,27 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
list_del(&addrw->list);
kfree(addrw);
}
- spin_unlock_bh(&sctp_addr_wq_lock);
+ spin_unlock_bh(&net->sctp.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->sctp.addr_wq_lock);
return;
}
addrw->state = cmd;
- list_add_tail(&addrw->list, &sctp_addr_waitq);
+ list_add_tail(&addrw->list, &net->sctp.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->sctp.addr_waitq);
- if (!timer_pending(&sctp_addr_wq_timer)) {
+ if (!timer_pending(&net->sctp.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->sctp.addr_wq_timer, timeo_val);
}
- spin_unlock_bh(&sctp_addr_wq_lock);
+ spin_unlock_bh(&net->sctp.addr_wq_lock);
}
/* Event handler for inet address addition/deletion events.
@@ -776,11 +778,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
struct sctp_sockaddr_entry *addr = NULL;
struct sctp_sockaddr_entry *temp;
+ struct net *net = dev_net(ifa->ifa_dev->dev);
int found = 0;
- if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net))
- return NOTIFY_DONE;
-
switch (ev) {
case NETDEV_UP:
addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
@@ -789,27 +789,27 @@ 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->sctp.local_addr_lock);
+ list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
+ sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
+ spin_unlock_bh(&net->sctp.local_addr_lock);
}
break;
case NETDEV_DOWN:
- spin_lock_bh(&sctp_local_addr_lock);
+ spin_lock_bh(&net->sctp.local_addr_lock);
list_for_each_entry_safe(addr, temp,
- &sctp_local_addr_list, list) {
+ &net->sctp.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->sctp.local_addr_lock);
if (found)
kfree_rcu(addr, rcu);
break;
@@ -1194,6 +1194,36 @@ static void sctp_v4_del_protocol(void)
unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
}
+static int sctp_net_init(struct net *net)
+{
+ /* Initialize the local address list. */
+ INIT_LIST_HEAD(&net->sctp.local_addr_list);
+ spin_lock_init(&net->sctp.local_addr_lock);
+ sctp_get_local_addr_list(net);
+
+ /* Initialize the address event list */
+ INIT_LIST_HEAD(&net->sctp.addr_waitq);
+ INIT_LIST_HEAD(&net->sctp.auto_asconf_splist);
+ spin_lock_init(&net->sctp.addr_wq_lock);
+ net->sctp.addr_wq_timer.expires = 0;
+ setup_timer(&net->sctp.addr_wq_timer, sctp_addr_wq_timeout_handler,
+ (unsigned long)net);
+
+ return 0;
+}
+
+static void sctp_net_exit(struct net *net)
+{
+ /* Free the local address list */
+ sctp_free_addr_wq(net);
+ sctp_free_local_addr_list(net);
+}
+
+static struct pernet_operations sctp_net_ops = {
+ .init = sctp_net_init,
+ .exit = sctp_net_exit,
+};
+
/* Initialize the universe into something sensible. */
SCTP_STATIC __init int sctp_init(void)
{
@@ -1399,18 +1429,6 @@ 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);
-
status = sctp_v4_protosw_init();
if (status)
@@ -1426,6 +1444,10 @@ SCTP_STATIC __init int sctp_init(void)
goto err_ctl_sock_init;
}
+ status = register_pernet_subsys(&sctp_net_ops);
+ if (status)
+ goto err_register_pernet_subsys;
+
status = sctp_v4_add_protocol();
if (status)
goto err_add_protocol;
@@ -1441,13 +1463,14 @@ out:
err_v6_add_protocol:
sctp_v4_del_protocol();
err_add_protocol:
+ unregister_pernet_subsys(&sctp_net_ops);
+err_register_pernet_subsys:
inet_ctl_sock_destroy(sctp_ctl_sock);
err_ctl_sock_init:
sctp_v6_protosw_exit();
err_v6_protosw_init:
sctp_v4_protosw_exit();
err_protosw_init:
- sctp_free_local_addr_list();
sctp_v4_pf_exit();
sctp_v6_pf_exit();
sctp_sysctl_unregister();
@@ -1482,18 +1505,16 @@ 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 the control endpoint. */
inet_ctl_sock_destroy(sctp_ctl_sock);
+ unregister_pernet_subsys(&sctp_net_ops);
+
/* 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/socket.c b/net/sctp/socket.c
index 4316b0f..5b6dd0e 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3471,7 +3471,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
sp->do_auto_asconf = 0;
} else if (val && !sp->do_auto_asconf) {
list_add_tail(&sp->auto_asconf_list,
- &sctp_auto_asconf_splist);
+ &sock_net(sk)->sctp.auto_asconf_splist);
sp->do_auto_asconf = 1;
}
return 0;
@@ -3964,7 +3964,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
if (sctp_default_auto_asconf) {
list_add_tail(&sp->auto_asconf_list,
- &sctp_auto_asconf_splist);
+ &sock_net(sk)->sctp.auto_asconf_splist);
sp->do_auto_asconf = 1;
} else
sp->do_auto_asconf = 0;
@@ -4653,9 +4653,10 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
union sctp_addr temp;
int cnt = 0;
int addrlen;
+ struct net *net = sock_net(sk);
rcu_read_lock();
- list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
+ list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
if (!addr->valid)
continue;
--
1.7.5.4
- Kill sctp_get_ctl_sock, it is useless now.
- Pass struct net where needed so net->sctp.ctl_sock is accessible.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/netns/sctp.h | 8 +++++++
include/net/sctp/sctp.h | 1 -
net/sctp/input.c | 4 +-
net/sctp/protocol.c | 47 ++++++++++++++++++---------------------------
net/sctp/sm_statefuns.c | 45 ++++++++++++++++++++++++++++++-------------
5 files changed, 60 insertions(+), 45 deletions(-)
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
index cbd684e..29e36b4 100644
--- a/include/net/netns/sctp.h
+++ b/include/net/netns/sctp.h
@@ -1,7 +1,15 @@
#ifndef __NETNS_SCTP_H__
#define __NETNS_SCTP_H__
+struct sock;
+
struct netns_sctp {
+ /* This is the global socket data structure used for responding to
+ * the Out-of-the-blue (OOTB) packets. A control sock will be created
+ * for this socket at the initialization time.
+ */
+ struct sock *ctl_sock;
+
/* This is the global local address list.
* We actively maintain this complete list of addresses on
* the system by catching address add/delete events.
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 00c9205..550a81b 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -114,7 +114,6 @@
/*
* sctp/protocol.c
*/
-extern struct sock *sctp_get_ctl_sock(void);
extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
sctp_scope_t, gfp_t gfp,
int flags);
diff --git a/net/sctp/input.c b/net/sctp/input.c
index a7e9a85..c9a0449 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -204,7 +204,7 @@ int sctp_rcv(struct sk_buff *skb)
sctp_endpoint_put(ep);
ep = NULL;
}
- sk = sctp_get_ctl_sock();
+ sk = net->sctp.ctl_sock;
ep = sctp_sk(sk)->ep;
sctp_endpoint_hold(ep);
rcvr = &ep->base;
@@ -795,7 +795,7 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
goto hit;
}
- ep = sctp_sk((sctp_get_ctl_sock()))->ep;
+ ep = sctp_sk(net->sctp.ctl_sock)->ep;
hit:
sctp_endpoint_hold(ep);
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 291e682..6193d20 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -78,12 +78,6 @@ struct proc_dir_entry *proc_net_sctp;
struct idr sctp_assocs_id;
DEFINE_SPINLOCK(sctp_assocs_id_lock);
-/* This is the global socket data structure used for responding to
- * the Out-of-the-blue (OOTB) packets. A control sock will be created
- * for this socket at the initialization time.
- */
-static struct sock *sctp_ctl_sock;
-
static struct sctp_pf *sctp_pf_inet6_specific;
static struct sctp_pf *sctp_pf_inet_specific;
static struct sctp_af *sctp_af_v4_specific;
@@ -96,12 +90,6 @@ long sysctl_sctp_mem[3];
int sysctl_sctp_rmem[3];
int sysctl_sctp_wmem[3];
-/* Return the address of the control sock. */
-struct sock *sctp_get_ctl_sock(void)
-{
- return sctp_ctl_sock;
-}
-
/* Set up the proc fs entry for the SCTP protocol. */
static __init int sctp_proc_init(void)
{
@@ -822,7 +810,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
* Initialize the control inode/socket with a control endpoint data
* structure. This endpoint is reserved exclusively for the OOTB processing.
*/
-static int sctp_ctl_sock_init(void)
+static int sctp_ctl_sock_init(struct net *net)
{
int err;
sa_family_t family = PF_INET;
@@ -830,14 +818,14 @@ static int sctp_ctl_sock_init(void)
if (sctp_get_pf_specific(PF_INET6))
family = PF_INET6;
- err = inet_ctl_sock_create(&sctp_ctl_sock, family,
- SOCK_SEQPACKET, IPPROTO_SCTP, &init_net);
+ err = inet_ctl_sock_create(&net->sctp.ctl_sock, family,
+ SOCK_SEQPACKET, IPPROTO_SCTP, net);
/* If IPv6 socket could not be created, try the IPv4 socket */
if (err < 0 && family == PF_INET6)
- err = inet_ctl_sock_create(&sctp_ctl_sock, AF_INET,
+ err = inet_ctl_sock_create(&net->sctp.ctl_sock, AF_INET,
SOCK_SEQPACKET, IPPROTO_SCTP,
- &init_net);
+ net);
if (err < 0) {
pr_err("Failed to create the SCTP control socket\n");
@@ -1196,6 +1184,14 @@ static void sctp_v4_del_protocol(void)
static int sctp_net_init(struct net *net)
{
+ int status;
+
+ /* Initialize the control inode/socket for handling OOTB packets. */
+ if ((status = sctp_ctl_sock_init(net))) {
+ pr_err("Failed to initialize the SCTP control sock\n");
+ goto err_ctl_sock_init;
+ }
+
/* Initialize the local address list. */
INIT_LIST_HEAD(&net->sctp.local_addr_list);
spin_lock_init(&net->sctp.local_addr_lock);
@@ -1210,6 +1206,9 @@ static int sctp_net_init(struct net *net)
(unsigned long)net);
return 0;
+
+err_ctl_sock_init:
+ return status;
}
static void sctp_net_exit(struct net *net)
@@ -1217,6 +1216,9 @@ static void sctp_net_exit(struct net *net)
/* Free the local address list */
sctp_free_addr_wq(net);
sctp_free_local_addr_list(net);
+
+ /* Free the control endpoint. */
+ inet_ctl_sock_destroy(net->sctp.ctl_sock);
}
static struct pernet_operations sctp_net_ops = {
@@ -1438,12 +1440,6 @@ SCTP_STATIC __init int sctp_init(void)
if (status)
goto err_v6_protosw_init;
- /* Initialize the control inode/socket for handling OOTB packets. */
- if ((status = sctp_ctl_sock_init())) {
- pr_err("Failed to initialize the SCTP control sock\n");
- goto err_ctl_sock_init;
- }
-
status = register_pernet_subsys(&sctp_net_ops);
if (status)
goto err_register_pernet_subsys;
@@ -1465,8 +1461,6 @@ err_v6_add_protocol:
err_add_protocol:
unregister_pernet_subsys(&sctp_net_ops);
err_register_pernet_subsys:
- inet_ctl_sock_destroy(sctp_ctl_sock);
-err_ctl_sock_init:
sctp_v6_protosw_exit();
err_v6_protosw_init:
sctp_v4_protosw_exit();
@@ -1506,9 +1500,6 @@ SCTP_STATIC __exit void sctp_exit(void)
sctp_v6_del_protocol();
sctp_v4_del_protocol();
- /* Free the control endpoint. */
- inet_ctl_sock_destroy(sctp_ctl_sock);
-
unregister_pernet_subsys(&sctp_net_ops);
/* Free protosw registrations */
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 9fca103..f2daf61 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -74,7 +74,8 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
static int sctp_eat_data(const struct sctp_association *asoc,
struct sctp_chunk *chunk,
sctp_cmd_seq_t *commands);
-static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
+static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
+ const struct sctp_association *asoc,
const struct sctp_chunk *chunk);
static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
@@ -301,6 +302,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
struct sctp_chunk *err_chunk;
struct sctp_packet *packet;
sctp_unrecognized_param_t *unk_param;
+ struct net *net;
int len;
/* 6.10 Bundling
@@ -318,7 +320,8 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
/* If the packet is an OOTB packet which is temporarily on the
* control endpoint, respond with an ABORT.
*/
- if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) {
+ net = sock_net(ep->base.sk);
+ if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
}
@@ -646,11 +649,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
int error = 0;
struct sctp_chunk *err_chk_p;
struct sock *sk;
+ struct net *net;
/* If the packet is an OOTB packet which is temporarily on the
* control endpoint, respond with an ABORT.
*/
- if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) {
+ net = sock_net(ep->base.sk);
+ if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
}
@@ -1171,7 +1176,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
/* Helper function to send out an abort for the restart
* condition.
*/
-static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
+static int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa,
struct sctp_chunk *init,
sctp_cmd_seq_t *commands)
{
@@ -1197,7 +1202,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
errhdr->length = htons(len);
/* Assign to the control socket. */
- ep = sctp_sk((sctp_get_ctl_sock()))->ep;
+ ep = sctp_sk(net->sctp.ctl_sock)->ep;
/* Association is NULL since this may be a restart attack and we
* want to send back the attacker's vtag.
@@ -1240,6 +1245,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
struct sctp_chunk *init,
sctp_cmd_seq_t *commands)
{
+ struct net *net = sock_net(new_asoc->base.sk);
struct sctp_transport *new_addr;
int ret = 1;
@@ -1258,7 +1264,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
transports) {
if (!list_has_sctp_addr(&asoc->peer.transport_addr_list,
&new_addr->ipaddr)) {
- sctp_sf_send_restart_abort(&new_addr->ipaddr, init,
+ sctp_sf_send_restart_abort(net, &new_addr->ipaddr, init,
commands);
ret = 0;
break;
@@ -1650,10 +1656,11 @@ sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep,
const sctp_subtype_t type,
void *arg, sctp_cmd_seq_t *commands)
{
+ struct net *net = sock_net(ep->base.sk);
/* Per the above section, we'll discard the chunk if we have an
* endpoint. If this is an OOTB INIT-ACK, treat it as such.
*/
- if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
+ if (ep == sctp_sk(net->sctp.ctl_sock)->ep)
return sctp_sf_ootb(ep, asoc, type, arg, commands);
else
return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
@@ -3163,8 +3170,10 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
struct sctp_packet *packet = NULL;
struct sctp_chunk *chunk = arg;
struct sctp_chunk *abort;
+ struct net *net;
- packet = sctp_ootb_pkt_new(asoc, chunk);
+ net = sock_net(ep->base.sk);
+ packet = sctp_ootb_pkt_new(net, asoc, chunk);
if (packet) {
/* Make an ABORT. The T bit will be set if the asoc
@@ -3425,8 +3434,10 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
struct sctp_packet *packet = NULL;
struct sctp_chunk *chunk = arg;
struct sctp_chunk *shut;
+ struct net *net;
- packet = sctp_ootb_pkt_new(asoc, chunk);
+ net = sock_net(ep->base.sk);
+ packet = sctp_ootb_pkt_new(net, asoc, chunk);
if (packet) {
/* Make an SHUTDOWN_COMPLETE.
@@ -4262,6 +4273,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
struct sctp_packet *packet = NULL;
struct sctp_chunk *chunk = arg;
struct sctp_chunk *abort = NULL;
+ struct net *net;
/* SCTP-AUTH, Section 6.3:
* It should be noted that if the receiver wants to tear
@@ -4282,6 +4294,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
if (!abort)
goto nomem;
+ net = sock_net(ep->base.sk);
if (asoc) {
/* Treat INIT-ACK as a special case during COOKIE-WAIT. */
if (chunk->chunk_hdr->type == SCTP_CID_INIT_ACK &&
@@ -4319,7 +4332,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
}
} else {
- packet = sctp_ootb_pkt_new(asoc, chunk);
+ packet = sctp_ootb_pkt_new(net, asoc, chunk);
if (!packet)
goto nomem_pkt;
@@ -5825,8 +5838,10 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
{
struct sctp_packet *packet;
struct sctp_chunk *abort;
+ struct net *net;
- packet = sctp_ootb_pkt_new(asoc, chunk);
+ net = sock_net(ep->base.sk);
+ packet = sctp_ootb_pkt_new(net, asoc, chunk);
if (packet) {
/* Make an ABORT.
@@ -5858,7 +5873,8 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
}
/* Allocate a packet for responding in the OOTB conditions. */
-static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
+static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
+ const struct sctp_association *asoc,
const struct sctp_chunk *chunk)
{
struct sctp_packet *packet;
@@ -5919,7 +5935,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc
* the source address.
*/
sctp_transport_route(transport, (union sctp_addr *)&chunk->dest,
- sctp_sk(sctp_get_ctl_sock()));
+ sctp_sk(net->sctp.ctl_sock));
packet = sctp_packet_init(&transport->packet, transport, sport, dport);
packet = sctp_packet_config(packet, vtag, 0);
@@ -5946,7 +5962,8 @@ static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
struct sctp_packet *packet;
if (err_chunk) {
- packet = sctp_ootb_pkt_new(asoc, chunk);
+ struct net *net = sock_net(ep->base.sk);
+ packet = sctp_ootb_pkt_new(net, asoc, chunk);
if (packet) {
struct sctp_signed_cookie *cookie;
--
1.7.5.4
The percpu sctp socket counter has nothing at all to do with the sctp
proc files, and having it in the wrong initialization is confusing,
and makes network namespace support a pain.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
net/sctp/protocol.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 6193d20..976d765 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -93,8 +93,6 @@ int sysctl_sctp_wmem[3];
/* Set up the proc fs entry for the SCTP protocol. */
static __init int sctp_proc_init(void)
{
- if (percpu_counter_init(&sctp_sockets_allocated, 0))
- goto out_nomem;
#ifdef CONFIG_PROC_FS
if (!proc_net_sctp) {
proc_net_sctp = proc_mkdir("sctp", init_net.proc_net);
@@ -125,12 +123,9 @@ out_snmp_proc_init:
remove_proc_entry("sctp", init_net.proc_net);
}
out_free_percpu:
- percpu_counter_destroy(&sctp_sockets_allocated);
#else
return 0;
#endif /* CONFIG_PROC_FS */
-
-out_nomem:
return -ENOMEM;
}
@@ -151,7 +146,6 @@ static void sctp_proc_exit(void)
remove_proc_entry("sctp", init_net.proc_net);
}
#endif
- percpu_counter_destroy(&sctp_sockets_allocated);
}
/* Private helper to extract ipv4 address and stash them in
@@ -1261,6 +1255,10 @@ SCTP_STATIC __init int sctp_init(void)
if (status)
goto err_init_mibs;
+ status = percpu_counter_init(&sctp_sockets_allocated, 0);
+ if (status)
+ goto err_percpu_counter_init;
+
/* Initialize proc fs directory. */
status = sctp_proc_init();
if (status)
@@ -1481,6 +1479,8 @@ err_ahash_alloc:
sctp_dbg_objcnt_exit();
sctp_proc_exit();
err_init_proc:
+ percpu_counter_destroy(&sctp_sockets_allocated);
+err_percpu_counter_init:
cleanup_sctp_mibs();
err_init_mibs:
kmem_cache_destroy(sctp_chunk_cachep);
@@ -1521,6 +1521,7 @@ SCTP_STATIC __exit void sctp_exit(void)
sizeof(struct sctp_bind_hashbucket)));
sctp_dbg_objcnt_exit();
+ percpu_counter_destroy(&sctp_sockets_allocated);
sctp_proc_exit();
cleanup_sctp_mibs();
--
1.7.5.4
- Convert all of the files under /proc/net/sctp to be per
network namespace.
- Don't print anything for /proc/net/sctp/snmp except in
the initial network namespaces as the snmp counters still
have to be converted to be per network namespace.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/netns/sctp.h | 5 +++
include/net/sctp/sctp.h | 16 +++++-----
net/sctp/proc.c | 59 +++++++++++++++++++++++------------
net/sctp/protocol.c | 77 +++++++++++++++++++--------------------------
4 files changed, 85 insertions(+), 72 deletions(-)
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
index 29e36b4..9c20a82 100644
--- a/include/net/netns/sctp.h
+++ b/include/net/netns/sctp.h
@@ -2,8 +2,13 @@
#define __NETNS_SCTP_H__
struct sock;
+struct proc_dir_entry;
struct netns_sctp {
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc_net_sctp;
+#endif
+
/* This is the global socket data structure used for responding to
* the Out-of-the-blue (OOTB) packets. A control sock will be created
* for this socket at the initialization time.
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 550a81b..ca716da 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -172,14 +172,14 @@ void sctp_backlog_migrate(struct sctp_association *assoc,
/*
* sctp/proc.c
*/
-int sctp_snmp_proc_init(void);
-void sctp_snmp_proc_exit(void);
-int sctp_eps_proc_init(void);
-void sctp_eps_proc_exit(void);
-int sctp_assocs_proc_init(void);
-void sctp_assocs_proc_exit(void);
-int sctp_remaddr_proc_init(void);
-void sctp_remaddr_proc_exit(void);
+int sctp_snmp_proc_init(struct net *net);
+void sctp_snmp_proc_exit(struct net *net);
+int sctp_eps_proc_init(struct net *net);
+void sctp_eps_proc_exit(struct net *net);
+int sctp_assocs_proc_init(struct net *net);
+void sctp_assocs_proc_exit(struct net *net);
+int sctp_remaddr_proc_init(struct net *net);
+void sctp_remaddr_proc_exit(struct net *net);
/*
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 1e2eee8..dc79a3a 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -80,8 +80,12 @@ static const struct snmp_mib sctp_snmp_list[] = {
/* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */
static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
{
+ struct net *net = seq->private;
int i;
+ if (!net_eq(net, &init_net))
+ return 0;
+
for (i = 0; sctp_snmp_list[i].name != NULL; i++)
seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
snmp_fold_field((void __percpu **)sctp_statistics,
@@ -93,7 +97,7 @@ static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
/* Initialize the seq file operations for 'snmp' object. */
static int sctp_snmp_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, sctp_snmp_seq_show, NULL);
+ return single_open_net(inode, file, sctp_snmp_seq_show);
}
static const struct file_operations sctp_snmp_seq_fops = {
@@ -105,11 +109,12 @@ static const struct file_operations sctp_snmp_seq_fops = {
};
/* Set up the proc fs entry for 'snmp' object. */
-int __init sctp_snmp_proc_init(void)
+int __net_init sctp_snmp_proc_init(struct net *net)
{
struct proc_dir_entry *p;
- p = proc_create("snmp", S_IRUGO, proc_net_sctp, &sctp_snmp_seq_fops);
+ p = proc_create("snmp", S_IRUGO, net->sctp.proc_net_sctp,
+ &sctp_snmp_seq_fops);
if (!p)
return -ENOMEM;
@@ -117,9 +122,9 @@ int __init sctp_snmp_proc_init(void)
}
/* Cleanup the proc fs entry for 'snmp' object. */
-void sctp_snmp_proc_exit(void)
+void sctp_snmp_proc_exit(struct net *net)
{
- remove_proc_entry("snmp", proc_net_sctp);
+ remove_proc_entry("snmp", net->sctp.proc_net_sctp);
}
/* Dump local addresses of an association/endpoint. */
@@ -197,6 +202,7 @@ static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
/* Display sctp endpoints (/proc/net/sctp/eps). */
static int sctp_eps_seq_show(struct seq_file *seq, void *v)
{
+ struct seq_net_private *priv = seq->private;
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
struct sctp_endpoint *ep;
@@ -213,6 +219,8 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
sctp_for_each_hentry(epb, node, &head->chain) {
ep = sctp_ep(epb);
sk = epb->sk;
+ if (!net_eq(sock_net(sk), priv->net))
+ continue;
seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
sctp_sk(sk)->type, sk->sk_state, hash,
epb->bind_addr.port,
@@ -238,7 +246,8 @@ static const struct seq_operations sctp_eps_ops = {
/* Initialize the seq file operations for 'eps' object. */
static int sctp_eps_seq_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &sctp_eps_ops);
+ return seq_open_net(inode, file, &sctp_eps_ops,
+ sizeof(struct seq_net_private));
}
static const struct file_operations sctp_eps_seq_fops = {
@@ -249,11 +258,12 @@ static const struct file_operations sctp_eps_seq_fops = {
};
/* Set up the proc fs entry for 'eps' object. */
-int __init sctp_eps_proc_init(void)
+int __net_init sctp_eps_proc_init(struct net *net)
{
struct proc_dir_entry *p;
- p = proc_create("eps", S_IRUGO, proc_net_sctp, &sctp_eps_seq_fops);
+ p = proc_create("eps", S_IRUGO, net->sctp.proc_net_sctp,
+ &sctp_eps_seq_fops);
if (!p)
return -ENOMEM;
@@ -261,9 +271,9 @@ int __init sctp_eps_proc_init(void)
}
/* Cleanup the proc fs entry for 'eps' object. */
-void sctp_eps_proc_exit(void)
+void sctp_eps_proc_exit(struct net *net)
{
- remove_proc_entry("eps", proc_net_sctp);
+ remove_proc_entry("eps", net->sctp.proc_net_sctp);
}
@@ -300,6 +310,7 @@ static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
/* Display sctp associations (/proc/net/sctp/assocs). */
static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
{
+ struct seq_net_private *priv = seq->private;
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
struct sctp_association *assoc;
@@ -316,6 +327,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
sctp_for_each_hentry(epb, node, &head->chain) {
assoc = sctp_assoc(epb);
sk = epb->sk;
+ if (!net_eq(sock_net(sk), priv->net))
+ continue;
seq_printf(seq,
"%8pK %8pK %-3d %-3d %-2d %-4d "
"%4d %8d %8d %7d %5lu %-5d %5d ",
@@ -354,7 +367,8 @@ static const struct seq_operations sctp_assoc_ops = {
/* Initialize the seq file operations for 'assocs' object. */
static int sctp_assocs_seq_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &sctp_assoc_ops);
+ return seq_open_net(inode, file, &sctp_assoc_ops,
+ sizeof(struct seq_net_private));
}
static const struct file_operations sctp_assocs_seq_fops = {
@@ -365,11 +379,11 @@ static const struct file_operations sctp_assocs_seq_fops = {
};
/* Set up the proc fs entry for 'assocs' object. */
-int __init sctp_assocs_proc_init(void)
+int __net_init sctp_assocs_proc_init(struct net *net)
{
struct proc_dir_entry *p;
- p = proc_create("assocs", S_IRUGO, proc_net_sctp,
+ p = proc_create("assocs", S_IRUGO, net->sctp.proc_net_sctp,
&sctp_assocs_seq_fops);
if (!p)
return -ENOMEM;
@@ -378,9 +392,9 @@ int __init sctp_assocs_proc_init(void)
}
/* Cleanup the proc fs entry for 'assocs' object. */
-void sctp_assocs_proc_exit(void)
+void sctp_assocs_proc_exit(struct net *net)
{
- remove_proc_entry("assocs", proc_net_sctp);
+ remove_proc_entry("assocs", net->sctp.proc_net_sctp);
}
static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos)
@@ -412,6 +426,7 @@ static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v)
static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
{
+ struct seq_net_private *priv = seq->private;
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
struct sctp_association *assoc;
@@ -426,6 +441,8 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
sctp_local_bh_disable();
read_lock(&head->lock);
sctp_for_each_hentry(epb, node, &head->chain) {
+ if (!net_eq(sock_net(epb->sk), priv->net))
+ continue;
assoc = sctp_assoc(epb);
list_for_each_entry(tsp, &assoc->peer.transport_addr_list,
transports) {
@@ -489,14 +506,15 @@ static const struct seq_operations sctp_remaddr_ops = {
};
/* Cleanup the proc fs entry for 'remaddr' object. */
-void sctp_remaddr_proc_exit(void)
+void sctp_remaddr_proc_exit(struct net *net)
{
- remove_proc_entry("remaddr", proc_net_sctp);
+ remove_proc_entry("remaddr", net->sctp.proc_net_sctp);
}
static int sctp_remaddr_seq_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &sctp_remaddr_ops);
+ return seq_open_net(inode, file, &sctp_remaddr_ops,
+ sizeof(struct seq_net_private));
}
static const struct file_operations sctp_remaddr_seq_fops = {
@@ -506,11 +524,12 @@ static const struct file_operations sctp_remaddr_seq_fops = {
.release = seq_release,
};
-int __init sctp_remaddr_proc_init(void)
+int __net_init sctp_remaddr_proc_init(struct net *net)
{
struct proc_dir_entry *p;
- p = proc_create("remaddr", S_IRUGO, proc_net_sctp, &sctp_remaddr_seq_fops);
+ p = proc_create("remaddr", S_IRUGO, net->sctp.proc_net_sctp,
+ &sctp_remaddr_seq_fops);
if (!p)
return -ENOMEM;
return 0;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 976d765..72b3aa7 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -71,10 +71,6 @@
struct sctp_globals sctp_globals __read_mostly;
DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly;
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry *proc_net_sctp;
-#endif
-
struct idr sctp_assocs_id;
DEFINE_SPINLOCK(sctp_assocs_id_lock);
@@ -91,60 +87,52 @@ int sysctl_sctp_rmem[3];
int sysctl_sctp_wmem[3];
/* Set up the proc fs entry for the SCTP protocol. */
-static __init int sctp_proc_init(void)
+static __net_init int sctp_proc_init(struct net *net)
{
#ifdef CONFIG_PROC_FS
- if (!proc_net_sctp) {
- proc_net_sctp = proc_mkdir("sctp", init_net.proc_net);
- if (!proc_net_sctp)
- goto out_free_percpu;
- }
-
- if (sctp_snmp_proc_init())
+ net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net);
+ if (!net->sctp.proc_net_sctp)
+ goto out_proc_net_sctp;
+ if (sctp_snmp_proc_init(net))
goto out_snmp_proc_init;
- if (sctp_eps_proc_init())
+ if (sctp_eps_proc_init(net))
goto out_eps_proc_init;
- if (sctp_assocs_proc_init())
+ if (sctp_assocs_proc_init(net))
goto out_assocs_proc_init;
- if (sctp_remaddr_proc_init())
+ if (sctp_remaddr_proc_init(net))
goto out_remaddr_proc_init;
return 0;
out_remaddr_proc_init:
- sctp_assocs_proc_exit();
+ sctp_assocs_proc_exit(net);
out_assocs_proc_init:
- sctp_eps_proc_exit();
+ sctp_eps_proc_exit(net);
out_eps_proc_init:
- sctp_snmp_proc_exit();
+ sctp_snmp_proc_exit(net);
out_snmp_proc_init:
- if (proc_net_sctp) {
- proc_net_sctp = NULL;
- remove_proc_entry("sctp", init_net.proc_net);
- }
-out_free_percpu:
-#else
- return 0;
-#endif /* CONFIG_PROC_FS */
+ remove_proc_entry("sctp", net->proc_net);
+ net->sctp.proc_net_sctp = NULL;
+out_proc_net_sctp:
return -ENOMEM;
+#endif /* CONFIG_PROC_FS */
+ return 0;
}
/* Clean up the proc fs entry for the SCTP protocol.
* Note: Do not make this __exit as it is used in the init error
* path.
*/
-static void sctp_proc_exit(void)
+static void sctp_proc_exit(struct net *net)
{
#ifdef CONFIG_PROC_FS
- sctp_snmp_proc_exit();
- sctp_eps_proc_exit();
- sctp_assocs_proc_exit();
- sctp_remaddr_proc_exit();
-
- if (proc_net_sctp) {
- proc_net_sctp = NULL;
- remove_proc_entry("sctp", init_net.proc_net);
- }
+ sctp_snmp_proc_exit(net);
+ sctp_eps_proc_exit(net);
+ sctp_assocs_proc_exit(net);
+ sctp_remaddr_proc_exit(net);
+
+ remove_proc_entry("sctp", net->proc_net);
+ net->sctp.proc_net_sctp = NULL;
#endif
}
@@ -1180,6 +1168,11 @@ static int sctp_net_init(struct net *net)
{
int status;
+ /* Initialize proc fs directory. */
+ status = sctp_proc_init(net);
+ if (status)
+ goto err_init_proc;
+
/* Initialize the control inode/socket for handling OOTB packets. */
if ((status = sctp_ctl_sock_init(net))) {
pr_err("Failed to initialize the SCTP control sock\n");
@@ -1202,6 +1195,8 @@ static int sctp_net_init(struct net *net)
return 0;
err_ctl_sock_init:
+ sctp_proc_exit(net);
+err_init_proc:
return status;
}
@@ -1213,6 +1208,8 @@ static void sctp_net_exit(struct net *net)
/* Free the control endpoint. */
inet_ctl_sock_destroy(net->sctp.ctl_sock);
+
+ sctp_proc_exit(net);
}
static struct pernet_operations sctp_net_ops = {
@@ -1259,11 +1256,6 @@ SCTP_STATIC __init int sctp_init(void)
if (status)
goto err_percpu_counter_init;
- /* Initialize proc fs directory. */
- status = sctp_proc_init();
- if (status)
- goto err_init_proc;
-
/* Initialize object count debugging. */
sctp_dbg_objcnt_init();
@@ -1477,8 +1469,6 @@ err_ehash_alloc:
sizeof(struct sctp_hashbucket)));
err_ahash_alloc:
sctp_dbg_objcnt_exit();
- sctp_proc_exit();
-err_init_proc:
percpu_counter_destroy(&sctp_sockets_allocated);
err_percpu_counter_init:
cleanup_sctp_mibs();
@@ -1522,7 +1512,6 @@ SCTP_STATIC __exit void sctp_exit(void)
sctp_dbg_objcnt_exit();
percpu_counter_destroy(&sctp_sockets_allocated);
- sctp_proc_exit();
cleanup_sctp_mibs();
rcu_barrier(); /* Wait for completion of call_rcu()'s */
--
1.7.5.4
- Fix the sctp_af operations to work in all namespaces
- Enable sctp socket creation in all network namespaces.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
net/sctp/ipv6.c | 12 ++++++------
net/sctp/protocol.c | 8 +++++---
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index bbf1534..a18cda6 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -582,7 +582,7 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
if (!(type & IPV6_ADDR_UNICAST))
return 0;
- return ipv6_chk_addr(&init_net, in6, NULL, 0);
+ return ipv6_chk_addr(sock_net(&sp->inet.sk), in6, NULL, 0);
}
/* This function checks if the address is a valid address to be used for
@@ -859,14 +859,14 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
struct net_device *dev;
if (type & IPV6_ADDR_LINKLOCAL) {
+ struct net *net;
if (!addr->v6.sin6_scope_id)
return 0;
+ net = sock_net(&opt->inet.sk);
rcu_read_lock();
- dev = dev_get_by_index_rcu(&init_net,
- addr->v6.sin6_scope_id);
+ dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id);
if (!dev ||
- !ipv6_chk_addr(&init_net, &addr->v6.sin6_addr,
- dev, 0)) {
+ !ipv6_chk_addr(net, &addr->v6.sin6_addr, dev, 0)) {
rcu_read_unlock();
return 0;
}
@@ -899,7 +899,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(sock_net(&opt->inet.sk),
addr->v6.sin6_scope_id);
rcu_read_unlock();
if (!dev)
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 72b3aa7..ab35691 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -367,7 +367,8 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
/* Should this be available for binding? */
static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
{
- int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr);
+ struct net *net = sock_net(&sp->inet.sk);
+ int ret = inet_addr_type(net, addr->v4.sin_addr.s_addr);
if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
@@ -454,7 +455,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(sock_net(sk), fl4);
if (!IS_ERR(rt))
dst = &rt->dst;
@@ -500,7 +501,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(sk), fl4);
if (!IS_ERR(rt)) {
dst = &rt->dst;
goto out_unlock;
@@ -1033,6 +1034,7 @@ static const struct net_protocol sctp_protocol = {
.handler = sctp_rcv,
.err_handler = sctp_v4_err,
.no_policy = 1,
+ .netns_ok = 1,
};
/* IPv4 address related functions. */
--
1.7.5.4
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/netns/sctp.h | 3 +
include/net/sctp/sctp.h | 9 +--
net/sctp/associola.c | 2 +-
net/sctp/chunk.c | 2 +-
net/sctp/endpointola.c | 2 +-
net/sctp/input.c | 22 +++---
net/sctp/ipv6.c | 4 +-
net/sctp/output.c | 2 +-
net/sctp/outqueue.c | 18 +++--
net/sctp/proc.c | 5 +-
net/sctp/protocol.c | 27 ++++----
net/sctp/sm_statefuns.c | 163 +++++++++++++++++++++++++++------------------
net/sctp/ulpqueue.c | 18 ++++--
13 files changed, 158 insertions(+), 119 deletions(-)
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
index 9c20a82..06ccddf 100644
--- a/include/net/netns/sctp.h
+++ b/include/net/netns/sctp.h
@@ -3,8 +3,11 @@
struct sock;
struct proc_dir_entry;
+struct sctp_mib;
struct netns_sctp {
+ DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
+
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_net_sctp;
#endif
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index ca716da..b0e6fe5 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -221,11 +221,10 @@ extern struct kmem_cache *sctp_bucket_cachep __read_mostly;
#define sctp_bh_unlock_sock(sk) bh_unlock_sock(sk)
/* SCTP SNMP MIB stats handlers */
-DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics);
-#define SCTP_INC_STATS(field) SNMP_INC_STATS(sctp_statistics, field)
-#define SCTP_INC_STATS_BH(field) SNMP_INC_STATS_BH(sctp_statistics, field)
-#define SCTP_INC_STATS_USER(field) SNMP_INC_STATS_USER(sctp_statistics, field)
-#define SCTP_DEC_STATS(field) SNMP_DEC_STATS(sctp_statistics, field)
+#define SCTP_INC_STATS(net, field) SNMP_INC_STATS((net)->sctp.sctp_statistics, field)
+#define SCTP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->sctp.sctp_statistics, field)
+#define SCTP_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->sctp.sctp_statistics, field)
+#define SCTP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->sctp.sctp_statistics, field)
#endif /* !TEST_FRAME */
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index ed4930b..8a1f27a 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1150,7 +1150,7 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
if (sctp_chunk_is_data(chunk))
asoc->peer.last_data_from = chunk->transport;
else
- SCTP_INC_STATS(SCTP_MIB_INCTRLCHUNKS);
+ SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_INCTRLCHUNKS);
if (chunk->transport)
chunk->transport->last_time_heard = jiffies;
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 6c85564..7c2df9c 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -257,7 +257,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
offset = 0;
if ((whole > 1) || (whole && over))
- SCTP_INC_STATS_USER(SCTP_MIB_FRAGUSRMSGS);
+ SCTP_INC_STATS_USER(sock_net(asoc->base.sk), SCTP_MIB_FRAGUSRMSGS);
/* Create chunks for all the full sized DATA chunks. */
for (i=0, len=first_len; i < whole; i++) {
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 6b76393..3edca80 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -478,7 +478,7 @@ normal:
if (asoc && sctp_chunk_is_data(chunk))
asoc->peer.last_data_from = chunk->transport;
else
- SCTP_INC_STATS(SCTP_MIB_INCTRLCHUNKS);
+ SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_INCTRLCHUNKS);
if (chunk->transport)
chunk->transport->last_time_heard = jiffies;
diff --git a/net/sctp/input.c b/net/sctp/input.c
index c9a0449..5308301 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -83,7 +83,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb);
/* Calculate the SCTP checksum of an SCTP packet. */
-static inline int sctp_rcv_checksum(struct sk_buff *skb)
+static inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb)
{
struct sctphdr *sh = sctp_hdr(skb);
__le32 cmp = sh->checksum;
@@ -99,7 +99,7 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb)
if (val != cmp) {
/* CRC failure, dump it. */
- SCTP_INC_STATS_BH(SCTP_MIB_CHECKSUMERRORS);
+ SCTP_INC_STATS_BH(net, SCTP_MIB_CHECKSUMERRORS);
return -1;
}
return 0;
@@ -137,7 +137,7 @@ int sctp_rcv(struct sk_buff *skb)
if (skb->pkt_type!=PACKET_HOST)
goto discard_it;
- SCTP_INC_STATS_BH(SCTP_MIB_INSCTPPACKS);
+ SCTP_INC_STATS_BH(net, SCTP_MIB_INSCTPPACKS);
if (skb_linearize(skb))
goto discard_it;
@@ -149,7 +149,7 @@ int sctp_rcv(struct sk_buff *skb)
if (skb->len < sizeof(struct sctphdr))
goto discard_it;
if (!sctp_checksum_disable && !skb_csum_unnecessary(skb) &&
- sctp_rcv_checksum(skb) < 0)
+ sctp_rcv_checksum(net, skb) < 0)
goto discard_it;
skb_pull(skb, sizeof(struct sctphdr));
@@ -220,7 +220,7 @@ int sctp_rcv(struct sk_buff *skb)
*/
if (!asoc) {
if (sctp_rcv_ootb(skb)) {
- SCTP_INC_STATS_BH(SCTP_MIB_OUTOFBLUES);
+ SCTP_INC_STATS_BH(net, SCTP_MIB_OUTOFBLUES);
goto discard_release;
}
}
@@ -276,9 +276,9 @@ int sctp_rcv(struct sk_buff *skb)
skb = NULL; /* sctp_chunk_free already freed the skb */
goto discard_release;
}
- SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG);
+ SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_BACKLOG);
} else {
- SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ);
+ SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_SOFTIRQ);
sctp_inq_push(&chunk->rcvr->inqueue, chunk);
}
@@ -293,7 +293,7 @@ int sctp_rcv(struct sk_buff *skb)
return 0;
discard_it:
- SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_DISCARDS);
+ SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_DISCARDS);
kfree_skb(skb);
return 0;
@@ -543,7 +543,7 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
* servers this needs to be solved differently.
*/
if (sock_owned_by_user(sk))
- NET_INC_STATS_BH(&init_net, LINUX_MIB_LOCKDROPPEDICMPS);
+ NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
*app = asoc;
*tpp = transport;
@@ -593,7 +593,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
struct net *net = dev_net(skb->dev);
if (skb->len < ihlen + 8) {
- ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
return;
}
@@ -607,7 +607,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
skb->network_header = saveip;
skb->transport_header = savesctp;
if (!sk) {
- ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
return;
}
/* Warning: The sock lock is held. Remember to call
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index a18cda6..ea14cb4 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -169,7 +169,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
skb->network_header = saveip;
skb->transport_header = savesctp;
if (!sk) {
- ICMP6_INC_STATS_BH(dev_net(skb->dev), idev, ICMP6_MIB_INERRORS);
+ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_INERRORS);
goto out;
}
@@ -243,7 +243,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
__func__, skb, skb->len,
&fl6.saddr, &fl6.daddr);
- SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
+ SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS);
if (!(transport->param_flags & SPP_PMTUD_ENABLE))
skb->local_df = 1;
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 838e18b..0c6359b 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -597,7 +597,7 @@ out:
return err;
no_route:
kfree_skb(nskb);
- IP_INC_STATS_BH(&init_net, IPSTATS_MIB_OUTNOROUTES);
+ IP_INC_STATS_BH(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES);
/* FIXME: Returning the 'err' will effect all the associations
* associated with a socket, although only one of the paths of the
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index e7aa177c..072bf6a 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -299,6 +299,7 @@ void sctp_outq_free(struct sctp_outq *q)
/* Put a new chunk in an sctp_outq. */
int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
{
+ struct net *net = sock_net(q->asoc->base.sk);
int error = 0;
SCTP_DEBUG_PRINTK("sctp_outq_tail(%p, %p[%s])\n",
@@ -337,15 +338,15 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
sctp_outq_tail_data(q, chunk);
if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
- SCTP_INC_STATS(SCTP_MIB_OUTUNORDERCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);
else
- SCTP_INC_STATS(SCTP_MIB_OUTORDERCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS);
q->empty = 0;
break;
}
} else {
list_add_tail(&chunk->list, &q->control_chunk_list);
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
}
if (error < 0)
@@ -478,11 +479,12 @@ void sctp_retransmit_mark(struct sctp_outq *q,
void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
sctp_retransmit_reason_t reason)
{
+ struct net *net = sock_net(q->asoc->base.sk);
int error = 0;
switch(reason) {
case SCTP_RTXR_T3_RTX:
- SCTP_INC_STATS(SCTP_MIB_T3_RETRANSMITS);
+ SCTP_INC_STATS(net, SCTP_MIB_T3_RETRANSMITS);
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX);
/* Update the retran path if the T3-rtx timer has expired for
* the current retran path.
@@ -493,15 +495,15 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
transport->asoc->unack_data;
break;
case SCTP_RTXR_FAST_RTX:
- SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
+ SCTP_INC_STATS(net, SCTP_MIB_FAST_RETRANSMITS);
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
q->fast_rtx = 1;
break;
case SCTP_RTXR_PMTUD:
- SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS);
+ SCTP_INC_STATS(net, SCTP_MIB_PMTUD_RETRANSMITS);
break;
case SCTP_RTXR_T1_RTX:
- SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS);
+ SCTP_INC_STATS(net, SCTP_MIB_T1_RETRANSMITS);
transport->asoc->init_retries++;
break;
default:
@@ -1914,6 +1916,6 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
if (ftsn_chunk) {
list_add_tail(&ftsn_chunk->list, &q->control_chunk_list);
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
}
}
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index dc79a3a..3e62ee5 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -83,12 +83,9 @@ static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
struct net *net = seq->private;
int i;
- if (!net_eq(net, &init_net))
- return 0;
-
for (i = 0; sctp_snmp_list[i].name != NULL; i++)
seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
- snmp_fold_field((void __percpu **)sctp_statistics,
+ snmp_fold_field((void __percpu **)net->sctp.sctp_statistics,
sctp_snmp_list[i].entry));
return 0;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index ab35691..69bdc72 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -69,7 +69,6 @@
/* Global data structures. */
struct sctp_globals sctp_globals __read_mostly;
-DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly;
struct idr sctp_assocs_id;
DEFINE_SPINLOCK(sctp_assocs_id_lock);
@@ -961,7 +960,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
- SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
+ SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS);
return ip_queue_xmit(skb, &transport->fl);
}
@@ -1102,16 +1101,16 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family)
return 1;
}
-static inline int init_sctp_mibs(void)
+static inline int init_sctp_mibs(struct net *net)
{
- return snmp_mib_init((void __percpu **)sctp_statistics,
+ return snmp_mib_init((void __percpu **)net->sctp.sctp_statistics,
sizeof(struct sctp_mib),
__alignof__(struct sctp_mib));
}
-static inline void cleanup_sctp_mibs(void)
+static inline void cleanup_sctp_mibs(struct net *net)
{
- snmp_mib_free((void __percpu **)sctp_statistics);
+ snmp_mib_free((void __percpu **)net->sctp.sctp_statistics);
}
static void sctp_v4_pf_init(void)
@@ -1170,6 +1169,11 @@ static int sctp_net_init(struct net *net)
{
int status;
+ /* Allocate and initialise sctp mibs. */
+ status = init_sctp_mibs(net);
+ if (status)
+ goto err_init_mibs;
+
/* Initialize proc fs directory. */
status = sctp_proc_init(net);
if (status)
@@ -1199,6 +1203,8 @@ static int sctp_net_init(struct net *net)
err_ctl_sock_init:
sctp_proc_exit(net);
err_init_proc:
+ cleanup_sctp_mibs(net);
+err_init_mibs:
return status;
}
@@ -1212,6 +1218,7 @@ static void sctp_net_exit(struct net *net)
inet_ctl_sock_destroy(net->sctp.ctl_sock);
sctp_proc_exit(net);
+ cleanup_sctp_mibs(net);
}
static struct pernet_operations sctp_net_ops = {
@@ -1249,11 +1256,6 @@ SCTP_STATIC __init int sctp_init(void)
if (!sctp_chunk_cachep)
goto err_chunk_cachep;
- /* Allocate and initialise sctp mibs. */
- status = init_sctp_mibs();
- if (status)
- goto err_init_mibs;
-
status = percpu_counter_init(&sctp_sockets_allocated, 0);
if (status)
goto err_percpu_counter_init;
@@ -1473,8 +1475,6 @@ err_ahash_alloc:
sctp_dbg_objcnt_exit();
percpu_counter_destroy(&sctp_sockets_allocated);
err_percpu_counter_init:
- cleanup_sctp_mibs();
-err_init_mibs:
kmem_cache_destroy(sctp_chunk_cachep);
err_chunk_cachep:
kmem_cache_destroy(sctp_bucket_cachep);
@@ -1514,7 +1514,6 @@ SCTP_STATIC __exit void sctp_exit(void)
sctp_dbg_objcnt_exit();
percpu_counter_destroy(&sctp_sockets_allocated);
- cleanup_sctp_mibs();
rcu_barrier(); /* Wait for completion of call_rcu()'s */
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index f2daf61..bee5e2c 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -213,6 +213,7 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
{
struct sctp_chunk *chunk = arg;
struct sctp_ulpevent *ev;
+ struct net *net;
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -260,8 +261,9 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
- SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ net = sock_net(asoc->base.sk);
+ SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
@@ -322,7 +324,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
*/
net = sock_net(ep->base.sk);
if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
- SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
}
@@ -369,7 +371,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
if (packet) {
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
SCTP_PACKET(packet));
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
return SCTP_DISPOSITION_CONSUME;
} else {
return SCTP_DISPOSITION_NOMEM;
@@ -540,7 +542,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
if (packet) {
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
SCTP_PACKET(packet));
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
error = SCTP_ERROR_INV_PARAM;
}
}
@@ -559,7 +561,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
+ SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_ABORTEDS);
return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED,
asoc, chunk->transport);
}
@@ -656,7 +658,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
*/
net = sock_net(ep->base.sk);
if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
- SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
}
@@ -809,8 +811,8 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_ESTABLISHED));
- SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
- SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS);
+ SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS);
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
if (new_asoc->autoclose)
@@ -868,6 +870,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
{
struct sctp_chunk *chunk = arg;
struct sctp_ulpevent *ev;
+ struct net *net;
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -897,8 +900,9 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_ESTABLISHED));
- SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
- SCTP_INC_STATS(SCTP_MIB_ACTIVEESTABS);
+ net = sock_net(ep->base.sk);
+ SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS);
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
if (asoc->autoclose)
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
@@ -972,13 +976,15 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
struct sctp_transport *transport = (struct sctp_transport *) arg;
if (asoc->overall_error_count >= asoc->max_retrans) {
+ struct net *net;
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ETIMEDOUT));
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_NO_ERROR));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ net = sock_net(ep->base.sk);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_DELETE_TCB;
}
@@ -1213,7 +1219,7 @@ static int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa,
goto out;
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, SCTP_PACKET(pkt));
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
/* Discard the rest of the inbound packet. */
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
@@ -1427,7 +1433,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
if (packet) {
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
SCTP_PACKET(packet));
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
retval = SCTP_DISPOSITION_CONSUME;
} else {
retval = SCTP_DISPOSITION_NOMEM;
@@ -1791,7 +1797,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_ESTABLISHED));
- SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(sock_net(new_asoc->base.sk), SCTP_MIB_CURRESTAB);
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
repl = sctp_make_cookie_ack(new_asoc, chunk);
@@ -1883,7 +1889,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_ESTABLISHED));
- SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_CURRESTAB);
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START,
SCTP_NULL());
@@ -2417,6 +2423,7 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
struct sctp_chunk *chunk = arg;
unsigned int len;
__be16 error = SCTP_ERROR_NO_ERROR;
+ struct net *net;
/* See if we have an error cause code in the chunk. */
len = ntohs(chunk->chunk_hdr->length);
@@ -2433,8 +2440,9 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET));
/* ASSOC_FAILED will DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ net = sock_net(ep->base.sk);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_ABORT;
}
@@ -2521,7 +2529,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
SCTP_DEBUG_PRINTK("ABORT received (INIT).\n");
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
+ SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_ABORTEDS);
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err));
@@ -2904,11 +2912,11 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
break;
case SCTP_IERROR_HIGH_TSN:
case SCTP_IERROR_BAD_STREAM:
- SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
+ SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
goto discard_noforce;
case SCTP_IERROR_DUP_TSN:
case SCTP_IERROR_IGNORE_TSN:
- SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
+ SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
goto discard_force;
case SCTP_IERROR_NO_DATA:
goto consume;
@@ -3197,7 +3205,7 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
SCTP_PACKET(packet));
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
sctp_sf_pdiscard(ep, asoc, type, arg, commands);
return SCTP_DISPOSITION_CONSUME;
@@ -3260,6 +3268,7 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
struct sctp_chunk *chunk = arg;
struct sctp_chunk *reply;
struct sctp_ulpevent *ev;
+ struct net *net;
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -3299,8 +3308,9 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
- SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ net = sock_net(asoc->base.sk);
+ SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
/* ...and remove all record of the association. */
@@ -3346,8 +3356,10 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
__u8 *ch_end;
int ootb_shut_ack = 0;
int ootb_cookie_ack = 0;
+ struct net *net;
- SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
+ net = sock_net(asoc->base.sk);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
ch = (sctp_chunkhdr_t *) chunk->chunk_hdr;
do {
@@ -3461,7 +3473,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
SCTP_PACKET(packet));
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
/* If the chunk length is invalid, we don't want to process
* the reset of the packet.
@@ -3508,7 +3520,7 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep,
* packet and the state function that handles OOTB SHUTDOWN_ACK is
* called with a NULL association.
*/
- SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
+ SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTOFBLUES);
return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands);
}
@@ -3699,6 +3711,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
*/
if (ADDIP_SERIAL_gte(rcvd_serial, sent_serial + 1) &&
!(asoc->addip_last_asconf)) {
+ struct net *net;
abort = sctp_make_abort(asoc, asconf_ack,
sizeof(sctp_errhdr_t));
if (abort) {
@@ -3716,12 +3729,14 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ net = sock_net(asoc->base.sk);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_ABORT;
}
if ((rcvd_serial == sent_serial) && asoc->addip_last_asconf) {
+ struct net *net;
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
@@ -3750,8 +3765,9 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ net = sock_net(asoc->base.sk);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_ABORT;
}
@@ -4222,7 +4238,7 @@ sctp_disposition_t sctp_sf_pdiscard(const struct sctp_endpoint *ep,
void *arg,
sctp_cmd_seq_t *commands)
{
- SCTP_INC_STATS(SCTP_MIB_IN_PKT_DISCARDS);
+ SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_PKT_DISCARDS);
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
return SCTP_DISPOSITION_CONSUME;
@@ -4315,7 +4331,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
}
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) {
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -4329,7 +4345,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
}
} else {
packet = sctp_ootb_pkt_new(net, asoc, chunk);
@@ -4347,10 +4363,10 @@ static sctp_disposition_t sctp_sf_abort_violation(
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
SCTP_PACKET(packet));
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
}
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
discard:
sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
@@ -4410,6 +4426,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
struct sctp_chunk *chunk = arg;
struct sctp_paramhdr *param = ext;
struct sctp_chunk *abort = NULL;
+ struct net *net;
if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
goto discard;
@@ -4419,15 +4436,16 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
if (!abort)
goto nomem;
+ net = sock_net(asoc->base.sk);
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
discard:
sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
@@ -4757,6 +4775,7 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
*/
struct sctp_chunk *abort = arg;
sctp_disposition_t retval;
+ struct net *net;
retval = SCTP_DISPOSITION_CONSUME;
@@ -4772,8 +4791,9 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_USER_ABORT));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ net = sock_net(asoc->base.sk);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return retval;
}
@@ -4824,13 +4844,15 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_shutdown(
void *arg,
sctp_cmd_seq_t *commands)
{
+ struct net *net = sock_net(asoc->base.sk);
+
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
- SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);
+ SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS);
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
@@ -4886,6 +4908,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
{
struct sctp_chunk *abort = arg;
sctp_disposition_t retval;
+ struct net *net = sock_net(asoc->base.sk);
/* Stop T1-init timer */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -4897,7 +4920,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
/* Even if we can't send the ABORT due to low memory delete the
* TCB. This is a departure from our typical NOMEM handling.
@@ -5318,8 +5341,9 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
sctp_cmd_seq_t *commands)
{
struct sctp_transport *transport = arg;
+ struct net *net = sock_net(asoc->base.sk);
- SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS);
+ SCTP_INC_STATS(net, SCTP_MIB_T3_RTX_EXPIREDS);
if (asoc->overall_error_count >= asoc->max_retrans) {
if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) {
@@ -5340,8 +5364,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_NO_ERROR));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_DELETE_TCB;
}
}
@@ -5403,7 +5427,8 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
void *arg,
sctp_cmd_seq_t *commands)
{
- SCTP_INC_STATS(SCTP_MIB_DELAY_SACK_EXPIREDS);
+ struct net *net = sock_net(asoc->base.sk);
+ SCTP_INC_STATS(net, SCTP_MIB_DELAY_SACK_EXPIREDS);
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE());
return SCTP_DISPOSITION_CONSUME;
}
@@ -5436,9 +5461,10 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
struct sctp_chunk *repl = NULL;
struct sctp_bind_addr *bp;
int attempts = asoc->init_err_counter + 1;
+ struct net *net = sock_net(asoc->base.sk);
SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
- SCTP_INC_STATS(SCTP_MIB_T1_INIT_EXPIREDS);
+ SCTP_INC_STATS(net, SCTP_MIB_T1_INIT_EXPIREDS);
if (attempts <= asoc->max_init_attempts) {
bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
@@ -5496,9 +5522,10 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
{
struct sctp_chunk *repl = NULL;
int attempts = asoc->init_err_counter + 1;
+ struct net *net = sock_net(asoc->base.sk);
SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
- SCTP_INC_STATS(SCTP_MIB_T1_COOKIE_EXPIREDS);
+ SCTP_INC_STATS(net, SCTP_MIB_T1_COOKIE_EXPIREDS);
if (attempts <= asoc->max_init_attempts) {
repl = sctp_make_cookie_echo(asoc, NULL);
@@ -5543,9 +5570,10 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
sctp_cmd_seq_t *commands)
{
struct sctp_chunk *reply = NULL;
+ struct net *net = sock_net(asoc->base.sk);
SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
- SCTP_INC_STATS(SCTP_MIB_T2_SHUTDOWN_EXPIREDS);
+ SCTP_INC_STATS(net, SCTP_MIB_T2_SHUTDOWN_EXPIREDS);
((struct sctp_association *)asoc)->shutdown_retries++;
@@ -5555,8 +5583,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
/* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_NO_ERROR));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_DELETE_TCB;
}
@@ -5613,8 +5641,9 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
{
struct sctp_chunk *chunk = asoc->addip_last_asconf;
struct sctp_transport *transport = chunk->transport;
+ struct net *net = sock_net(asoc->base.sk);
- SCTP_INC_STATS(SCTP_MIB_T4_RTO_EXPIREDS);
+ SCTP_INC_STATS(net, SCTP_MIB_T4_RTO_EXPIREDS);
/* ADDIP 4.1 B1) Increment the error counters and perform path failure
* detection on the appropriate destination address as defined in
@@ -5639,8 +5668,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
SCTP_ERROR(ETIMEDOUT));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_NO_ERROR));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_ABORT;
}
@@ -5682,9 +5711,10 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
sctp_cmd_seq_t *commands)
{
struct sctp_chunk *reply = NULL;
+ struct net *net = sock_net(asoc->base.sk);
SCTP_DEBUG_PRINTK("Timer T5 expired.\n");
- SCTP_INC_STATS(SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS);
+ SCTP_INC_STATS(net, SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS);
reply = sctp_make_abort(asoc, NULL, 0);
if (!reply)
@@ -5696,8 +5726,8 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_NO_ERROR));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_DELETE_TCB;
nomem:
@@ -5716,9 +5746,10 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire(
void *arg,
sctp_cmd_seq_t *commands)
{
+ struct net *net = sock_net(asoc->base.sk);
int disposition;
- SCTP_INC_STATS(SCTP_MIB_AUTOCLOSE_EXPIREDS);
+ SCTP_INC_STATS(net, SCTP_MIB_AUTOCLOSE_EXPIREDS);
/* From 9.2 Shutdown of an Association
* Upon receipt of the SHUTDOWN primitive from its upper
@@ -5976,7 +6007,7 @@ static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
sctp_packet_append_chunk(packet, err_chunk);
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
SCTP_PACKET(packet));
- SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
} else
sctp_chunk_free (err_chunk);
}
@@ -5996,6 +6027,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
__u32 tsn;
struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
struct sock *sk = asoc->base.sk;
+ struct net *net;
u16 ssn;
u16 sid;
u8 ordered = 0;
@@ -6112,6 +6144,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
* No User Data: This error cause is returned to the originator of a
* DATA chunk if a received DATA chunk has no user data.
*/
+ net = sock_net(sk);
if (unlikely(0 == datalen)) {
err = sctp_make_abort_no_data(asoc, chunk, tsn);
if (err) {
@@ -6126,8 +6159,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_NO_DATA));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_IERROR_NO_DATA;
}
@@ -6137,9 +6170,9 @@ static int sctp_eat_data(const struct sctp_association *asoc,
* if we renege and the chunk arrives again.
*/
if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
- SCTP_INC_STATS(SCTP_MIB_INUNORDERCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_INUNORDERCHUNKS);
else {
- SCTP_INC_STATS(SCTP_MIB_INORDERCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_INORDERCHUNKS);
ordered = 1;
}
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index f5a6a4f..360d869 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -326,7 +326,9 @@ static void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
* payload was fragmented on the way and ip had to reassemble them.
* We add the rest of skb's to the first skb's fraglist.
*/
-static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag)
+static struct sctp_ulpevent *sctp_make_reassembled_event(struct net *net,
+ struct sk_buff_head *queue, struct sk_buff *f_frag,
+ struct sk_buff *l_frag)
{
struct sk_buff *pos;
struct sk_buff *new = NULL;
@@ -394,7 +396,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu
}
event = sctp_skb2event(f_frag);
- SCTP_INC_STATS(SCTP_MIB_REASMUSRMSGS);
+ SCTP_INC_STATS(net, SCTP_MIB_REASMUSRMSGS);
return event;
}
@@ -493,7 +495,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul
cevent = sctp_skb2event(pd_first);
pd_point = sctp_sk(asoc->base.sk)->pd_point;
if (pd_point && pd_point <= pd_len) {
- retval = sctp_make_reassembled_event(&ulpq->reasm,
+ retval = sctp_make_reassembled_event(sock_net(asoc->base.sk),
+ &ulpq->reasm,
pd_first,
pd_last);
if (retval)
@@ -503,7 +506,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul
done:
return retval;
found:
- retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, pos);
+ retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
+ &ulpq->reasm, first_frag, pos);
if (retval)
retval->msg_flags |= MSG_EOR;
goto done;
@@ -563,7 +567,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq)
* further.
*/
done:
- retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag);
+ retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
+ &ulpq->reasm, first_frag, last_frag);
if (retval && is_last)
retval->msg_flags |= MSG_EOR;
@@ -655,7 +660,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq)
* further.
*/
done:
- retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag);
+ retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
+ &ulpq->reasm, first_frag, last_frag);
return retval;
}
--
1.7.5.4
On 08/06/2012 02:20 PM, Eric W. Biederman wrote:
> Jan Ariyasu <[email protected]> writes:
>
>> The following set of patches enable network-namespaces for the SCTP protocol.
>>
>> The multitude of global parameters are stored in a net_generic
>> structure, and the bulk of the patches enable the protocol to access
>> the parameters on a per-namespace basis. The first five patches
>> enable netns handling of the protocol, procfs and sysfs.
>
> I am going to do something to muddy the waters here, that I had hoped to
> avoid when I saw your patchset.
>
> A few weeks ago I wanted to play with sctp and also made a network
> namespace enabled version. I am not deeply attached to my changes,
> however when comparing the differences I realized that your code fails
> to make the lookup of associations per network namespace.
>
> Given that we only have source and destination port to lookup
> assoications by this almost guarantees one network namespace can
> accidentially use the association of another network namespace meerly
> by reusing the same ports.
>
Hi Eric
Associations are looked up by ports, but then verifyed by addresses.
Also, associations belong to sockets and simply validating the socket
namespace should be sufficient.
> The downside with my version is that it does not make all of the sctp
> tunables per network namespace the way yours does, but making all of
> the tunables per network namespace should be straight forward from
> my base.
>
> My patchset also misses some nice to haves like making the association
> id allocation per network namespace. It is not important for
> correctness of the code but it might allow an information leak between
> namespaces.
Hmm.. this one might be nice to have not from the perspective of leak,
but from resource limitation. Without this, once the id space is global
is can be exhausted faster.
-vlad
>
> So Jan I am going to send my patchset and hopefully you can rebase your
> changes to make all of the tunables per network namespace on top of
> mine.
>
> Since my patchset is half the size of your I think that is the most
> reasonable way to go.
>
> Eric
>
Vlad Yasevich <[email protected]> writes:
> Hi Eric
>
> Associations are looked up by ports, but then verifyed by addresses.
> Also, associations belong to sockets and simply validating the socket
> namespace should be sufficient.
True. Your set of patches isn't quite as likely to malfunction as it
looked at first glance. It requires address reuse which happens accross
namespaces but not too frequently.
As for validating the socket namespace I agree that is the fix and my
patchset winds up doing it.
>> The downside with my version is that it does not make all of the sctp
>> tunables per network namespace the way yours does, but making all of
>> the tunables per network namespace should be straight forward from
>> my base.
>>
>> My patchset also misses some nice to haves like making the association
>> id allocation per network namespace. It is not important for
>> correctness of the code but it might allow an information leak between
>> namespaces.
>
> Hmm.. this one might be nice to have not from the perspective of leak,
> but from resource limitation. Without this, once the id space is
> global is can be exhausted faster.
It takes a lot of associtations to exhaust the id space, but I have no
fundamental problems problems with the id allocation being per
namespace. I had actually overlooked the local association id when I
did my patches. After looking it became clear that making the
association id global was not necessary so I left it.
The sctp association id is a strange beast. My personal inclination is
that the sctp association id really ought to be per sctp socket, but I
have not looked enough at the sctp userspace API to see if that works in
practice. Shrug.
Mostly I am in favor of simple and correct.
Eric
On 08/06/2012 03:50 PM, Eric W. Biederman wrote:
> Vlad Yasevich <[email protected]> writes:
>
>
>> Hi Eric
>>
>> Associations are looked up by ports, but then verifyed by addresses.
>> Also, associations belong to sockets and simply validating the socket
>> namespace should be sufficient.
>
> True. Your set of patches isn't quite as likely to malfunction as it
> looked at first glance. It requires address reuse which happens accross
> namespaces but not too frequently.
Last time I looked at Jan's patches, I though she took care of the
address re-use issue. It isn't technically necessary to include
namespace into the hash mix, but I think it will make chains shorter
when namespaces are involved. Might be interesting to look.
>
> As for validating the socket namespace I agree that is the fix and my
> patchset winds up doing it.
Yes, I saw that.
>
>>> The downside with my version is that it does not make all of the sctp
>>> tunables per network namespace the way yours does, but making all of
>>> the tunables per network namespace should be straight forward from
>>> my base.
>>>
>>> My patchset also misses some nice to haves like making the association
>>> id allocation per network namespace. It is not important for
>>> correctness of the code but it might allow an information leak between
>>> namespaces.
>>
>> Hmm.. this one might be nice to have not from the perspective of leak,
>> but from resource limitation. Without this, once the id space is
>> global is can be exhausted faster.
>
> It takes a lot of associtations to exhaust the id space, but I have no
> fundamental problems problems with the id allocation being per
> namespace. I had actually overlooked the local association id when I
> did my patches. After looking it became clear that making the
> association id global was not necessary so I left it.
>
> The sctp association id is a strange beast. My personal inclination is
> that the sctp association id really ought to be per sctp socket, but I
> have not looked enough at the sctp userspace API to see if that works in
> practice. Shrug.
>
> Mostly I am in favor of simple and correct.
Technically association id must be unique within a namespace. Having
global id space may be simpler and correct enough as there would be no
duplication of ids between namespaces. The only thing of value the
per/namespace id space provides is that it restored the theoretical
maximum on sctp associations one can have.
However, this means teaching IDR about namespaces... :)
We can skip it for now.
-vlad
>
> Eric
>
From: [email protected] (Eric W. Biederman)
Date: Mon, 06 Aug 2012 12:50:46 -0700
> Vlad Yasevich <[email protected]> writes:
>
>
>> Hi Eric
>>
>> Associations are looked up by ports, but then verifyed by addresses.
>> Also, associations belong to sockets and simply validating the socket
>> namespace should be sufficient.
>
> True. Your set of patches isn't quite as likely to malfunction as it
> looked at first glance. It requires address reuse which happens accross
> namespaces but not too frequently.
>
> As for validating the socket namespace I agree that is the fix and my
> patchset winds up doing it.
FWIW I much prefer Eric's patch set, it was so significantly easier to
read and validate than Jan's.
On 08/06/2012 04:47 PM, David Miller wrote:
> From: [email protected] (Eric W. Biederman)
> Date: Mon, 06 Aug 2012 12:50:46 -0700
>
>> Vlad Yasevich <[email protected]> writes:
>>
>>
>>> Hi Eric
>>>
>>> Associations are looked up by ports, but then verifyed by addresses.
>>> Also, associations belong to sockets and simply validating the socket
>>> namespace should be sufficient.
>>
>> True. Your set of patches isn't quite as likely to malfunction as it
>> looked at first glance. It requires address reuse which happens accross
>> namespaces but not too frequently.
>>
>> As for validating the socket namespace I agree that is the fix and my
>> patchset winds up doing it.
>
> FWIW I much prefer Eric's patch set, it was so significantly easier to
> read and validate than Jan's.
>
Yes, but Eric's patch set is missing a very significant piece which is
per-net sctp tunables/globals. I think adding that piece in will
introduce some of the complexities of Jan's patch.
Also, I noticed that Eric went the route of placing sctp netns into
struct net, but Jan used a generic pointer. Which one should be used?
Is there some guidance?
-vlad
Vlad Yasevich <[email protected]> writes:
> On 08/06/2012 04:47 PM, David Miller wrote:
>> From: [email protected] (Eric W. Biederman)
>> Date: Mon, 06 Aug 2012 12:50:46 -0700
>>
>>> Vlad Yasevich <[email protected]> writes:
>>>
>>>
>>>> Hi Eric
>>>>
>>>> Associations are looked up by ports, but then verifyed by addresses.
>>>> Also, associations belong to sockets and simply validating the socket
>>>> namespace should be sufficient.
>>>
>>> True. Your set of patches isn't quite as likely to malfunction as it
>>> looked at first glance. It requires address reuse which happens accross
>>> namespaces but not too frequently.
>>>
>>> As for validating the socket namespace I agree that is the fix and my
>>> patchset winds up doing it.
>>
>> FWIW I much prefer Eric's patch set, it was so significantly easier to
>> read and validate than Jan's.
>>
>
> Yes, but Eric's patch set is missing a very significant piece which is per-net
> sctp tunables/globals. I think adding that piece in will introduce some of the
> complexities of Jan's patch.
And Jan's patchset is missing the per net snmp counters, as well
as the per net checks when looking in the hash tables. Things that look
like fairly fundamental correctness issues.
No offense but I think Jan's patchset has minor but significant
structural flaws and correctness issues that would require the patchset
to be respun, after review even if my patches did not exist.
The poor movement of variables from their global context into the per
net context is one of those problems.
The fact that after Jan's patchset all of the tunables despite being
made per net remain in struct sctp_globals and sit their unused is a
recipe for confusion.
So I think the simplest path forward would be to merge my patches, and
then merge Jan's tunable work after she has had a chance to rebase it.
> Also, I noticed that Eric went the route of placing sctp netns into struct net,
> but Jan used a generic pointer. Which one should be used? Is there some
> guidance?
Placing things directly in struct net is more efficient. Using net
generic is more convenient for development as using net generic does not
require a kernel recompile.
For minor things and especially where it does not have an impact on
performance net generic is the way to go.
It looked to me that sctp was fundamental enough and had enough
important data structures on the hot path that placing the variables
in struct net directly seemed sensible.
Eric
Since I am motivated to get things done, and since there has been much
grumbling about my patches not implementing tunables, I have added
tunable support on top of my last patchset.
I have performed basic testing on the these patches and nothing
appears amis.
The sm statemachine is a major tease as it has all of these association
and endpoint pointers in the common set of function parameters that turn
out to be NULL at the most inconvinient times. So I added to the common
parameter list a struct net pointer, that is never NULL.
include/net/netns/sctp.h | 96 +++++++-
include/net/sctp/sctp.h | 16 +-
include/net/sctp/sm.h | 8 +-
include/net/sctp/structs.h | 126 +---------
net/sctp/associola.c | 18 +-
net/sctp/auth.c | 20 ++-
net/sctp/bind_addr.c | 6 +-
net/sctp/endpointola.c | 13 +-
net/sctp/input.c | 6 +-
net/sctp/primitive.c | 4 +-
net/sctp/protocol.c | 137 +++++-----
net/sctp/sm_make_chunk.c | 61 +++--
net/sctp/sm_sideeffect.c | 26 ++-
net/sctp/sm_statefuns.c | 631 ++++++++++++++++++++++++--------------------
net/sctp/sm_statetable.c | 17 +-
net/sctp/socket.c | 92 ++++---
net/sctp/sysctl.c | 200 ++++++++------
net/sctp/transport.c | 23 +-
18 files changed, 817 insertions(+), 683 deletions(-)
Eric W. Biederman (7):
sctp: Add infrastructure for per net sysctls
sctp: Push struct net down to sctp_chunk_event_lookup
sctp: Push struct net down into sctp_transport_init
sctp: Push struct net down into sctp_in_scope
sctp: Push struct net down into all of the state machine functions
sctp: Push struct net down into sctp_verify_ext_param
sctp: Making sysctl tunables per net
Eric
Start with an empty sctp_net_table that will be populated as the various
tunable sysctls are made per net.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/netns/sctp.h | 6 +++++-
include/net/sctp/sctp.h | 4 ++++
net/sctp/protocol.c | 7 +++++++
net/sctp/sysctl.c | 21 +++++++++++++++++++++
4 files changed, 37 insertions(+), 1 deletions(-)
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
index 06ccddf..9576b60 100644
--- a/include/net/netns/sctp.h
+++ b/include/net/netns/sctp.h
@@ -4,6 +4,7 @@
struct sock;
struct proc_dir_entry;
struct sctp_mib;
+struct ctl_table_header;
struct netns_sctp {
DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
@@ -11,7 +12,9 @@ struct netns_sctp {
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_net_sctp;
#endif
-
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header *sysctl_header;
+#endif
/* This is the global socket data structure used for responding to
* the Out-of-the-blue (OOTB) packets. A control sock will be created
* for this socket at the initialization time.
@@ -32,6 +35,7 @@ struct netns_sctp {
/* Lock that protects the local_addr_list writers */
spinlock_t local_addr_lock;
+
};
#endif /* __NETNS_SCTP_H__ */
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index b0e6fe5..15037e7 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -375,9 +375,13 @@ static inline void sctp_dbg_objcnt_exit(void) { return; }
#if defined CONFIG_SYSCTL
void sctp_sysctl_register(void);
void sctp_sysctl_unregister(void);
+int sctp_sysctl_net_register(struct net *net);
+void sctp_sysctl_net_unregister(struct net *net);
#else
static inline void sctp_sysctl_register(void) { return; }
static inline void sctp_sysctl_unregister(void) { return; }
+static inline int sctp_sysctl_net_register(struct net *net) { return 0; }
+static inline void sctp_sysctl_net_unregister(struct net *net) { return; }
#endif
/* Size of Supported Address Parameter for 'x' address types. */
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 69bdc72..de25d9c 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1169,6 +1169,10 @@ static int sctp_net_init(struct net *net)
{
int status;
+ status = sctp_sysctl_net_register(net);
+ if (status)
+ goto err_sysctl_register;
+
/* Allocate and initialise sctp mibs. */
status = init_sctp_mibs(net);
if (status)
@@ -1205,6 +1209,8 @@ err_ctl_sock_init:
err_init_proc:
cleanup_sctp_mibs(net);
err_init_mibs:
+ sctp_sysctl_net_unregister(net);
+err_sysctl_register:
return status;
}
@@ -1219,6 +1225,7 @@ static void sctp_net_exit(struct net *net)
sctp_proc_exit(net);
cleanup_sctp_mibs(net);
+ sctp_sysctl_net_unregister(net);
}
static struct pernet_operations sctp_net_ops = {
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 2b2bfe9..7528d59 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -284,6 +284,27 @@ static ctl_table sctp_table[] = {
{ /* sentinel */ }
};
+static ctl_table sctp_net_table[] = {
+ { /* sentinel */ }
+};
+
+int sctp_sysctl_net_register(struct net *net)
+{
+ struct ctl_table *table;
+
+ table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table);
+ return 0;
+}
+
+void sctp_sysctl_net_unregister(struct net *net)
+{
+ unregister_net_sysctl_table(net->sctp.sysctl_header);
+}
+
static struct ctl_table_header * sctp_sysctl_header;
/* Sysctl registration. */
--
1.7.5.4
This trickles up through sctp_sm_lookup_event up to sctp_do_sm
and up further into sctp_primitiv_NAME before the code reaches
places where struct net can be reliably found.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/sctp/sctp.h | 12 ++++++------
include/net/sctp/sm.h | 5 +++--
net/sctp/associola.c | 5 +++--
net/sctp/endpointola.c | 4 +++-
net/sctp/input.c | 4 +++-
net/sctp/primitive.c | 4 ++--
net/sctp/sm_sideeffect.c | 24 ++++++++++++++++--------
net/sctp/sm_statetable.c | 11 +++++++----
net/sctp/socket.c | 27 +++++++++++++++++----------
9 files changed, 60 insertions(+), 36 deletions(-)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 15037e7..ef4ca25 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -139,12 +139,12 @@ extern int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *);
/*
* sctp/primitive.c
*/
-int sctp_primitive_ASSOCIATE(struct sctp_association *, void *arg);
-int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg);
-int sctp_primitive_ABORT(struct sctp_association *, void *arg);
-int sctp_primitive_SEND(struct sctp_association *, void *arg);
-int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg);
-int sctp_primitive_ASCONF(struct sctp_association *, void *arg);
+int sctp_primitive_ASSOCIATE(struct net *, struct sctp_association *, void *arg);
+int sctp_primitive_SHUTDOWN(struct net *, struct sctp_association *, void *arg);
+int sctp_primitive_ABORT(struct net *, struct sctp_association *, void *arg);
+int sctp_primitive_SEND(struct net *, struct sctp_association *, void *arg);
+int sctp_primitive_REQUESTHEARTBEAT(struct net *, struct sctp_association *, void *arg);
+int sctp_primitive_ASCONF(struct net *, struct sctp_association *, void *arg);
/*
* sctp/input.c
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 9148632..bcef130 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -178,7 +178,8 @@ sctp_state_fn_t sctp_sf_autoclose_timer_expire;
/* Prototypes for utility support functions. */
__u8 sctp_get_chunk_type(struct sctp_chunk *chunk);
-const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t,
+const sctp_sm_table_entry_t *sctp_sm_lookup_event(struct net *,
+ sctp_event_t,
sctp_state_t,
sctp_subtype_t);
int sctp_chunk_iif(const struct sctp_chunk *);
@@ -268,7 +269,7 @@ void sctp_chunk_assign_ssn(struct sctp_chunk *);
/* Prototypes for statetable processing. */
-int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
+int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype,
sctp_state_t state,
struct sctp_endpoint *,
struct sctp_association *asoc,
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 8a1f27a..6bcbeca 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1118,6 +1118,7 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
struct sctp_association *asoc =
container_of(work, struct sctp_association,
base.inqueue.immediate);
+ struct net *net = sock_net(asoc->base.sk);
struct sctp_endpoint *ep;
struct sctp_chunk *chunk;
struct sctp_inq *inqueue;
@@ -1150,13 +1151,13 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
if (sctp_chunk_is_data(chunk))
asoc->peer.last_data_from = chunk->transport;
else
- SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_INCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_INCTRLCHUNKS);
if (chunk->transport)
chunk->transport->last_time_heard = jiffies;
/* Run through the state machine. */
- error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype,
+ error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype,
state, ep, asoc, chunk, GFP_ATOMIC);
/* Check to see if the association is freed in response to
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 3edca80..8315792 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -413,6 +413,7 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work)
base.inqueue.immediate);
struct sctp_association *asoc;
struct sock *sk;
+ struct net *net;
struct sctp_transport *transport;
struct sctp_chunk *chunk;
struct sctp_inq *inqueue;
@@ -427,6 +428,7 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work)
asoc = NULL;
inqueue = &ep->base.inqueue;
sk = ep->base.sk;
+ net = sock_net(sk);
while (NULL != (chunk = sctp_inq_pop(inqueue))) {
subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
@@ -483,7 +485,7 @@ normal:
if (chunk->transport)
chunk->transport->last_time_heard = jiffies;
- error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, state,
+ error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype, state,
ep, asoc, chunk, GFP_ATOMIC);
if (error && chunk)
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 5308301..a2ceb70 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -466,11 +466,13 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
}
} else {
+ struct net *net = sock_net(sk);
+
if (timer_pending(&t->proto_unreach_timer) &&
del_timer(&t->proto_unreach_timer))
sctp_association_put(asoc);
- sctp_do_sm(SCTP_EVENT_T_OTHER,
+ sctp_do_sm(net, SCTP_EVENT_T_OTHER,
SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
asoc->state, asoc->ep, asoc, t,
GFP_ATOMIC);
diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c
index 534c7ea..794bb14 100644
--- a/net/sctp/primitive.c
+++ b/net/sctp/primitive.c
@@ -57,7 +57,7 @@
#define DECLARE_PRIMITIVE(name) \
/* This is called in the code as sctp_primitive_ ## name. */ \
-int sctp_primitive_ ## name(struct sctp_association *asoc, \
+int sctp_primitive_ ## name(struct net *net, struct sctp_association *asoc, \
void *arg) { \
int error = 0; \
sctp_event_t event_type; sctp_subtype_t subtype; \
@@ -69,7 +69,7 @@ int sctp_primitive_ ## name(struct sctp_association *asoc, \
state = asoc ? asoc->state : SCTP_STATE_CLOSED; \
ep = asoc ? asoc->ep : NULL; \
\
- error = sctp_do_sm(event_type, subtype, state, ep, asoc, \
+ error = sctp_do_sm(net, event_type, subtype, state, ep, asoc, \
arg, GFP_KERNEL); \
return error; \
}
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index fe99628..02c4c1c 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -251,6 +251,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
int error;
struct sctp_transport *transport = (struct sctp_transport *) peer;
struct sctp_association *asoc = transport->asoc;
+ struct net *net = sock_net(asoc->base.sk);
/* Check whether a task is in the sock. */
@@ -271,7 +272,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
goto out_unlock;
/* Run through the state machine. */
- error = sctp_do_sm(SCTP_EVENT_T_TIMEOUT,
+ error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT,
SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_T3_RTX),
asoc->state,
asoc->ep, asoc,
@@ -291,6 +292,7 @@ out_unlock:
static void sctp_generate_timeout_event(struct sctp_association *asoc,
sctp_event_timeout_t timeout_type)
{
+ struct net *net = sock_net(asoc->base.sk);
int error = 0;
sctp_bh_lock_sock(asoc->base.sk);
@@ -312,7 +314,7 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc,
goto out_unlock;
/* Run through the state machine. */
- error = sctp_do_sm(SCTP_EVENT_T_TIMEOUT,
+ error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT,
SCTP_ST_TIMEOUT(timeout_type),
asoc->state, asoc->ep, asoc,
(void *)timeout_type, GFP_ATOMIC);
@@ -371,6 +373,7 @@ void sctp_generate_heartbeat_event(unsigned long data)
int error = 0;
struct sctp_transport *transport = (struct sctp_transport *) data;
struct sctp_association *asoc = transport->asoc;
+ struct net *net = sock_net(asoc->base.sk);
sctp_bh_lock_sock(asoc->base.sk);
if (sock_owned_by_user(asoc->base.sk)) {
@@ -388,7 +391,7 @@ void sctp_generate_heartbeat_event(unsigned long data)
if (transport->dead)
goto out_unlock;
- error = sctp_do_sm(SCTP_EVENT_T_TIMEOUT,
+ error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT,
SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_HEARTBEAT),
asoc->state, asoc->ep, asoc,
transport, GFP_ATOMIC);
@@ -408,6 +411,7 @@ void sctp_generate_proto_unreach_event(unsigned long data)
{
struct sctp_transport *transport = (struct sctp_transport *) data;
struct sctp_association *asoc = transport->asoc;
+ struct net *net = sock_net(asoc->base.sk);
sctp_bh_lock_sock(asoc->base.sk);
if (sock_owned_by_user(asoc->base.sk)) {
@@ -426,7 +430,7 @@ void sctp_generate_proto_unreach_event(unsigned long data)
if (asoc->base.dead)
goto out_unlock;
- sctp_do_sm(SCTP_EVENT_T_OTHER,
+ sctp_do_sm(net, SCTP_EVENT_T_OTHER,
SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC);
@@ -753,8 +757,10 @@ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds,
int err = 0;
if (sctp_outq_sack(&asoc->outqueue, sackh)) {
+ struct net *net = sock_net(asoc->base.sk);
+
/* There are no more TSNs awaiting SACK. */
- err = sctp_do_sm(SCTP_EVENT_T_OTHER,
+ err = sctp_do_sm(net, SCTP_EVENT_T_OTHER,
SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN),
asoc->state, asoc->ep, asoc, NULL,
GFP_ATOMIC);
@@ -1042,6 +1048,8 @@ static int sctp_cmd_send_msg(struct sctp_association *asoc,
*/
static void sctp_cmd_send_asconf(struct sctp_association *asoc)
{
+ struct net *net = sock_net(asoc->base.sk);
+
/* Send the next asconf chunk from the addip chunk
* queue.
*/
@@ -1053,7 +1061,7 @@ static void sctp_cmd_send_asconf(struct sctp_association *asoc)
/* Hold the chunk until an ASCONF_ACK is received. */
sctp_chunk_hold(asconf);
- if (sctp_primitive_ASCONF(asoc, asconf))
+ if (sctp_primitive_ASCONF(net, asoc, asconf))
sctp_chunk_free(asconf);
else
asoc->addip_last_asconf = asconf;
@@ -1089,7 +1097,7 @@ static void sctp_cmd_send_asconf(struct sctp_association *asoc)
* If you want to understand all of lksctp, this is a
* good place to start.
*/
-int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
+int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype,
sctp_state_t state,
struct sctp_endpoint *ep,
struct sctp_association *asoc,
@@ -1110,7 +1118,7 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
/* Look up the state function, run it, and then process the
* side effects. These three steps are the heart of lksctp.
*/
- state_fn = sctp_sm_lookup_event(event_type, state, subtype);
+ state_fn = sctp_sm_lookup_event(net, event_type, state, subtype);
sctp_init_cmd_seq(&commands);
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 7c211a7..4a029d7 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -59,7 +59,8 @@ other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES];
static const sctp_sm_table_entry_t
timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES];
-static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
+static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(struct net *net,
+ sctp_cid_t cid,
sctp_state_t state);
@@ -82,13 +83,14 @@ static const sctp_sm_table_entry_t bug = {
rtn; \
})
-const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
+const sctp_sm_table_entry_t *sctp_sm_lookup_event(struct net *net,
+ sctp_event_t event_type,
sctp_state_t state,
sctp_subtype_t event_subtype)
{
switch (event_type) {
case SCTP_EVENT_T_CHUNK:
- return sctp_chunk_event_lookup(event_subtype.chunk, state);
+ return sctp_chunk_event_lookup(net, event_subtype.chunk, state);
case SCTP_EVENT_T_TIMEOUT:
return DO_LOOKUP(SCTP_EVENT_TIMEOUT_MAX, timeout,
timeout_event_table);
@@ -906,7 +908,8 @@ static const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][S
TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE,
};
-static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
+static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(struct net *net,
+ sctp_cid_t cid,
sctp_state_t state)
{
if (state > SCTP_STATE_MAX)
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 5b6dd0e..a6a4226 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -427,6 +427,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
static int sctp_send_asconf(struct sctp_association *asoc,
struct sctp_chunk *chunk)
{
+ struct net *net = sock_net(asoc->base.sk);
int retval = 0;
/* If there is an outstanding ASCONF chunk, queue it for later
@@ -439,7 +440,7 @@ static int sctp_send_asconf(struct sctp_association *asoc,
/* Hold the chunk until an ASCONF_ACK is received. */
sctp_chunk_hold(chunk);
- retval = sctp_primitive_ASCONF(asoc, chunk);
+ retval = sctp_primitive_ASCONF(net, asoc, chunk);
if (retval)
sctp_chunk_free(chunk);
else
@@ -1050,6 +1051,7 @@ static int __sctp_connect(struct sock* sk,
int addrs_size,
sctp_assoc_t *assoc_id)
{
+ struct net *net = sock_net(sk);
struct sctp_sock *sp;
struct sctp_endpoint *ep;
struct sctp_association *asoc = NULL;
@@ -1200,7 +1202,7 @@ static int __sctp_connect(struct sock* sk,
goto out_free;
}
- err = sctp_primitive_ASSOCIATE(asoc, NULL);
+ err = sctp_primitive_ASSOCIATE(net, asoc, NULL);
if (err < 0) {
goto out_free;
}
@@ -1458,6 +1460,7 @@ SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len,
*/
SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
{
+ struct net *net = sock_net(sk);
struct sctp_endpoint *ep;
struct sctp_association *asoc;
struct list_head *pos, *temp;
@@ -1499,9 +1502,9 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
chunk = sctp_make_abort_user(asoc, NULL, 0);
if (chunk)
- sctp_primitive_ABORT(asoc, chunk);
+ sctp_primitive_ABORT(net, asoc, chunk);
} else
- sctp_primitive_SHUTDOWN(asoc, NULL);
+ sctp_primitive_SHUTDOWN(net, asoc, NULL);
}
/* On a TCP-style socket, block for at most linger_time if set. */
@@ -1569,6 +1572,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *, sctp_cmsgs_t *);
SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
struct msghdr *msg, size_t msg_len)
{
+ struct net *net = sock_net(sk);
struct sctp_sock *sp;
struct sctp_endpoint *ep;
struct sctp_association *new_asoc=NULL, *asoc=NULL;
@@ -1714,7 +1718,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
if (sinfo_flags & SCTP_EOF) {
SCTP_DEBUG_PRINTK("Shutting down association: %p\n",
asoc);
- sctp_primitive_SHUTDOWN(asoc, NULL);
+ sctp_primitive_SHUTDOWN(net, asoc, NULL);
err = 0;
goto out_unlock;
}
@@ -1727,7 +1731,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
}
SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc);
- sctp_primitive_ABORT(asoc, chunk);
+ sctp_primitive_ABORT(net, asoc, chunk);
err = 0;
goto out_unlock;
}
@@ -1900,7 +1904,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
/* Auto-connect, if we aren't connected already. */
if (sctp_state(asoc, CLOSED)) {
- err = sctp_primitive_ASSOCIATE(asoc, NULL);
+ err = sctp_primitive_ASSOCIATE(net, asoc, NULL);
if (err < 0)
goto out_free;
SCTP_DEBUG_PRINTK("We associated primitively.\n");
@@ -1928,7 +1932,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
* works that way today. Keep it that way or this
* breaks.
*/
- err = sctp_primitive_SEND(asoc, datamsg);
+ err = sctp_primitive_SEND(net, asoc, datamsg);
/* Did the lower layer accept the chunk? */
if (err)
sctp_datamsg_free(datamsg);
@@ -2320,7 +2324,9 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
int error;
if (params->spp_flags & SPP_HB_DEMAND && trans) {
- error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans);
+ struct net *net = sock_net(trans->asoc->base.sk);
+
+ error = sctp_primitive_REQUESTHEARTBEAT(net, trans->asoc, trans);
if (error)
return error;
}
@@ -4011,6 +4017,7 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk)
*/
SCTP_STATIC void sctp_shutdown(struct sock *sk, int how)
{
+ struct net *net = sock_net(sk);
struct sctp_endpoint *ep;
struct sctp_association *asoc;
@@ -4022,7 +4029,7 @@ SCTP_STATIC void sctp_shutdown(struct sock *sk, int how)
if (!list_empty(&ep->asocs)) {
asoc = list_entry(ep->asocs.next,
struct sctp_association, asocs);
- sctp_primitive_SHUTDOWN(asoc, NULL);
+ sctp_primitive_SHUTDOWN(net, asoc, NULL);
}
}
}
--
1.7.5.4
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/sctp/structs.h | 2 +-
net/sctp/associola.c | 3 ++-
net/sctp/sm_statefuns.c | 2 +-
net/sctp/transport.c | 8 +++++---
4 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 6bdfcab..88d2179 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1066,7 +1066,7 @@ struct sctp_transport {
__u64 hb_nonce;
};
-struct sctp_transport *sctp_transport_new(const union sctp_addr *,
+struct sctp_transport *sctp_transport_new(struct net *, const union sctp_addr *,
gfp_t);
void sctp_transport_set_owner(struct sctp_transport *,
struct sctp_association *);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 6bcbeca..93a4513 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -641,6 +641,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
const gfp_t gfp,
const int peer_state)
{
+ struct net *net = sock_net(asoc->base.sk);
struct sctp_transport *peer;
struct sctp_sock *sp;
unsigned short port;
@@ -674,7 +675,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
return peer;
}
- peer = sctp_transport_new(addr, gfp);
+ peer = sctp_transport_new(net, addr, gfp);
if (!peer)
return NULL;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index bee5e2c..ff2530c 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -5958,7 +5958,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
}
/* Make a transport for the bucket, Eliza... */
- transport = sctp_transport_new(sctp_source(chunk), GFP_ATOMIC);
+ transport = sctp_transport_new(net, sctp_source(chunk), GFP_ATOMIC);
if (!transport)
goto nomem;
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index c97472b..aada963 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -59,7 +59,8 @@
/* 1st Level Abstractions. */
/* Initialize a new transport from provided memory. */
-static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
+static struct sctp_transport *sctp_transport_init(struct net *net,
+ struct sctp_transport *peer,
const union sctp_addr *addr,
gfp_t gfp)
{
@@ -109,7 +110,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
}
/* Allocate and initialize a new transport. */
-struct sctp_transport *sctp_transport_new(const union sctp_addr *addr,
+struct sctp_transport *sctp_transport_new(struct net *net,
+ const union sctp_addr *addr,
gfp_t gfp)
{
struct sctp_transport *transport;
@@ -118,7 +120,7 @@ struct sctp_transport *sctp_transport_new(const union sctp_addr *addr,
if (!transport)
goto fail;
- if (!sctp_transport_init(transport, addr, gfp))
+ if (!sctp_transport_init(net, transport, addr, gfp))
goto fail_init;
transport->malloced = 1;
--
1.7.5.4
struct net will be needed shortly when the tunables are made per network
namespace.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/sctp/structs.h | 2 +-
net/sctp/bind_addr.c | 4 ++--
net/sctp/protocol.c | 2 +-
net/sctp/sm_make_chunk.c | 3 ++-
4 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 88d2179..b0882f3 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1248,7 +1248,7 @@ 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(struct net *net, const union sctp_addr *addr, const sctp_scope_t scope);
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);
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index a85ce4b..23389ba 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -457,7 +457,7 @@ static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
if (sctp_is_any(NULL, addr)) {
error = sctp_copy_local_addr_list(net, dest, scope, gfp, flags);
- } else if (sctp_in_scope(addr, scope)) {
+ } else if (sctp_in_scope(net, addr, scope)) {
/* 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,7 +494,7 @@ 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(struct net *net, const union sctp_addr *addr, sctp_scope_t scope)
{
sctp_scope_t addr_scope = sctp_scope(addr);
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index de25d9c..85f87c3 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -210,7 +210,7 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
if (!addr->valid)
continue;
- if (sctp_in_scope(&addr->a, scope)) {
+ if (sctp_in_scope(net, &addr->a, scope)) {
/* 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.
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 479a70e..fb12835 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -2466,6 +2466,7 @@ static int sctp_process_param(struct sctp_association *asoc,
const union sctp_addr *peer_addr,
gfp_t gfp)
{
+ struct net *net = sock_net(asoc->base.sk);
union sctp_addr addr;
int i;
__u16 sat;
@@ -2494,7 +2495,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(net, &addr, scope))
if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED))
return 0;
break;
--
1.7.5.4
There are a handle of state machine functions primarily those dealing
with processing INIT packets where there is neither a valid endpoint nor
a valid assoication from which to derive a struct net. Therefore add
struct net * to the parameter list of sctp_state_fn_t and update all of
the state machine functions.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/sctp/sm.h | 3 +-
net/sctp/sm_sideeffect.c | 2 +-
net/sctp/sm_statefuns.c | 619 +++++++++++++++++++++++++---------------------
3 files changed, 341 insertions(+), 283 deletions(-)
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index bcef130..b5887e1 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -77,7 +77,8 @@ typedef struct {
int action;
} sctp_sm_command_t;
-typedef sctp_disposition_t (sctp_state_fn_t) (const struct sctp_endpoint *,
+typedef sctp_disposition_t (sctp_state_fn_t) (struct net *,
+ const struct sctp_endpoint *,
const struct sctp_association *,
const sctp_subtype_t type,
void *arg,
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 02c4c1c..bcfebb9 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1123,7 +1123,7 @@ int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype,
sctp_init_cmd_seq(&commands);
DEBUG_PRE;
- status = (*state_fn->fn)(ep, asoc, subtype, event_arg, &commands);
+ status = (*state_fn->fn)(net, ep, asoc, subtype, event_arg, &commands);
DEBUG_POST;
error = sctp_side_effects(event_type, subtype, state,
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index ff2530c..3e5ca61 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -66,7 +66,8 @@
#include <net/sctp/sm.h>
#include <net/sctp/structs.h>
-static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
+static struct sctp_packet *sctp_abort_pkt_new(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
struct sctp_chunk *chunk,
const void *payload,
@@ -77,34 +78,40 @@ static int sctp_eat_data(const struct sctp_association *asoc,
static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
const struct sctp_association *asoc,
const struct sctp_chunk *chunk);
-static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
+static void sctp_send_stale_cookie_err(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const struct sctp_chunk *chunk,
sctp_cmd_seq_t *commands,
struct sctp_chunk *err_chunk);
-static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_do_5_2_6_stale(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands);
-static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_shut_8_4_5(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands);
-static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_tabort_8_4_8(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands);
static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
-static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
+static sctp_disposition_t sctp_stop_t1_and_abort(struct net *net,
+ sctp_cmd_seq_t *commands,
__be16 error, int sk_err,
const struct sctp_association *asoc,
struct sctp_transport *transport);
static sctp_disposition_t sctp_sf_abort_violation(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
void *arg,
@@ -113,6 +120,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
const size_t paylen);
static sctp_disposition_t sctp_sf_violation_chunklen(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -120,6 +128,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
sctp_cmd_seq_t *commands);
static sctp_disposition_t sctp_sf_violation_paramlen(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -127,6 +136,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
sctp_cmd_seq_t *commands);
static sctp_disposition_t sctp_sf_violation_ctsn(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -134,18 +144,21 @@ static sctp_disposition_t sctp_sf_violation_ctsn(
sctp_cmd_seq_t *commands);
static sctp_disposition_t sctp_sf_violation_chunk(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands);
-static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep,
+static sctp_ierror_t sctp_sf_authenticate(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
struct sctp_chunk *chunk);
-static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
+static sctp_disposition_t __sctp_sf_do_9_1_abort(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -205,7 +218,8 @@ sctp_chunk_length_valid(struct sctp_chunk *chunk,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_4_C(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -213,10 +227,9 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
{
struct sctp_chunk *chunk = arg;
struct sctp_ulpevent *ev;
- struct net *net;
if (!sctp_vtag_verify_either(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* RFC 2960 6.10 Bundling
*
@@ -224,11 +237,11 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
* SHUTDOWN COMPLETE with any other chunks.
*/
if (!chunk->singleton)
- return sctp_sf_violation_chunk(ep, asoc, type, arg, commands);
+ return sctp_sf_violation_chunk(net, ep, asoc, type, arg, commands);
/* Make sure that the SHUTDOWN_COMPLETE chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* RFC 2960 10.2 SCTP-to-ULP
@@ -261,7 +274,6 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
- net = sock_net(asoc->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS);
SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
@@ -292,7 +304,8 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_5_1B_init(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -304,7 +317,6 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
struct sctp_chunk *err_chunk;
struct sctp_packet *packet;
sctp_unrecognized_param_t *unk_param;
- struct net *net;
int len;
/* 6.10 Bundling
@@ -317,22 +329,21 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
* with an INIT chunk that is bundled with other chunks.
*/
if (!chunk->singleton)
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* If the packet is an OOTB packet which is temporarily on the
* control endpoint, respond with an ABORT.
*/
- net = sock_net(ep->base.sk);
if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
- return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands);
}
/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
* Tag.
*/
if (chunk->sctp_hdr->vtag != 0)
- return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands);
/* Make sure that the INIT chunk has a valid length.
* Normally, this would cause an ABORT with a Protocol Violation
@@ -340,7 +351,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
* just discard the packet.
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t)))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* If the INIT is coming toward a closing socket, we'll send back
* and ABORT. Essentially, this catches the race of INIT being
@@ -349,7 +360,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
* can treat this OOTB
*/
if (sctp_sstate(ep->base.sk, CLOSING))
- return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands);
/* Verify the INIT chunk before processing it. */
err_chunk = NULL;
@@ -360,7 +371,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
* Send an ABORT, with causes if there is any.
*/
if (err_chunk) {
- packet = sctp_abort_pkt_new(ep, asoc, arg,
+ packet = sctp_abort_pkt_new(net, ep, asoc, arg,
(__u8 *)(err_chunk->chunk_hdr) +
sizeof(sctp_chunkhdr_t),
ntohs(err_chunk->chunk_hdr->length) -
@@ -377,7 +388,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
return SCTP_DISPOSITION_NOMEM;
}
} else {
- return sctp_sf_tabort_8_4_8(ep, asoc, type, arg,
+ return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg,
commands);
}
}
@@ -489,7 +500,8 @@ nomem:
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -501,18 +513,18 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
struct sctp_packet *packet;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
*/
if (!chunk->singleton)
- return sctp_sf_violation_chunk(ep, asoc, type, arg, commands);
+ return sctp_sf_violation_chunk(net, ep, asoc, type, arg, commands);
/* Make sure that the INIT-ACK chunk has a valid length */
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* Grab the INIT header. */
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
@@ -531,7 +543,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
* the association.
*/
if (err_chunk) {
- packet = sctp_abort_pkt_new(ep, asoc, arg,
+ packet = sctp_abort_pkt_new(net, ep, asoc, arg,
(__u8 *)(err_chunk->chunk_hdr) +
sizeof(sctp_chunkhdr_t),
ntohs(err_chunk->chunk_hdr->length) -
@@ -542,7 +554,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
if (packet) {
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
SCTP_PACKET(packet));
- SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
error = SCTP_ERROR_INV_PARAM;
}
}
@@ -559,10 +571,10 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
* was malformed.
*/
if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
- SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_ABORTEDS);
- return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED,
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
+ return sctp_stop_t1_and_abort(net, commands, error, ECONNREFUSED,
asoc, chunk->transport);
}
@@ -638,7 +650,8 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type, void *arg,
sctp_cmd_seq_t *commands)
@@ -651,15 +664,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
int error = 0;
struct sctp_chunk *err_chk_p;
struct sock *sk;
- struct net *net;
/* If the packet is an OOTB packet which is temporarily on the
* control endpoint, respond with an ABORT.
*/
- net = sock_net(ep->base.sk);
if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
- return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands);
}
/* Make sure that the COOKIE_ECHO chunk has a valid length.
@@ -668,7 +679,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
* in sctp_unpack_cookie().
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* If the endpoint is not listening or if the number of associations
* on the TCP-style socket exceed the max backlog, respond with an
@@ -677,7 +688,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
sk = ep->base.sk;
if (!sctp_sstate(sk, LISTENING) ||
(sctp_style(sk, TCP) && sk_acceptq_is_full(sk)))
- return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands);
/* "Decode" the chunk. We have no optional parameters so we
* are in good shape.
@@ -710,13 +721,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
goto nomem;
case -SCTP_IERROR_STALE_COOKIE:
- sctp_send_stale_cookie_err(ep, asoc, chunk, commands,
+ sctp_send_stale_cookie_err(net, ep, asoc, chunk, commands,
err_chk_p);
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
case -SCTP_IERROR_BAD_SIG:
default:
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
}
@@ -763,14 +774,14 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t));
auth.transport = chunk->transport;
- ret = sctp_sf_authenticate(ep, new_asoc, type, &auth);
+ ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth);
/* We can now safely free the auth_chunk clone */
kfree_skb(chunk->auth_chunk);
if (ret != SCTP_IERROR_NO_ERROR) {
sctp_association_free(new_asoc);
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
}
@@ -863,23 +874,23 @@ nomem:
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_5_1E_ca(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type, void *arg,
sctp_cmd_seq_t *commands)
{
struct sctp_chunk *chunk = arg;
struct sctp_ulpevent *ev;
- struct net *net;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Verify that the chunk length for the COOKIE-ACK is OK.
* If we don't do this, any bundled chunks may be junked.
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* Reset init error count upon receipt of COOKIE-ACK,
@@ -900,7 +911,6 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_ESTABLISHED));
- net = sock_net(ep->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS);
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
@@ -967,7 +977,8 @@ static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep,
}
/* Generate a HEARTBEAT packet on the given transport. */
-sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_sendbeat_8_3(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -976,13 +987,11 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
struct sctp_transport *transport = (struct sctp_transport *) arg;
if (asoc->overall_error_count >= asoc->max_retrans) {
- struct net *net;
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
SCTP_ERROR(ETIMEDOUT));
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_NO_ERROR));
- net = sock_net(ep->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_DELETE_TCB;
@@ -1039,7 +1048,8 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_beat_8_3(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -1050,11 +1060,11 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep,
size_t paylen = 0;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the HEARTBEAT chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_heartbeat_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* 8.3 The receiver of the HEARTBEAT should immediately
@@ -1106,7 +1116,8 @@ nomem:
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_backbeat_8_3(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -1119,12 +1130,12 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
unsigned long max_interval;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the HEARTBEAT-ACK chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t) +
sizeof(sctp_sender_hb_info_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
@@ -1213,7 +1224,7 @@ static int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa,
/* Association is NULL since this may be a restart attack and we
* want to send back the attacker's vtag.
*/
- pkt = sctp_abort_pkt_new(ep, NULL, init, errhdr, len);
+ pkt = sctp_abort_pkt_new(net, ep, NULL, init, errhdr, len);
if (!pkt)
goto out;
@@ -1370,6 +1381,7 @@ static char sctp_tietags_compare(struct sctp_association *new_asoc,
* chunk handling.
*/
static sctp_disposition_t sctp_sf_do_unexpected_init(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -1394,20 +1406,20 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
* with an INIT chunk that is bundled with other chunks.
*/
if (!chunk->singleton)
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
* Tag.
*/
if (chunk->sctp_hdr->vtag != 0)
- return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands);
/* Make sure that the INIT chunk has a valid length.
* In this case, we generate a protocol violation since we have
* an association established.
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* Grab the INIT header. */
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
@@ -1424,7 +1436,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
* Send an ABORT, with causes if there is any.
*/
if (err_chunk) {
- packet = sctp_abort_pkt_new(ep, asoc, arg,
+ packet = sctp_abort_pkt_new(net, ep, asoc, arg,
(__u8 *)(err_chunk->chunk_hdr) +
sizeof(sctp_chunkhdr_t),
ntohs(err_chunk->chunk_hdr->length) -
@@ -1433,14 +1445,14 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
if (packet) {
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
SCTP_PACKET(packet));
- SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
retval = SCTP_DISPOSITION_CONSUME;
} else {
retval = SCTP_DISPOSITION_NOMEM;
}
goto cleanup;
} else {
- return sctp_sf_tabort_8_4_8(ep, asoc, type, arg,
+ return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg,
commands);
}
}
@@ -1582,7 +1594,8 @@ cleanup:
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_5_2_1_siminit(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_5_2_1_siminit(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -1591,7 +1604,7 @@ sctp_disposition_t sctp_sf_do_5_2_1_siminit(const struct sctp_endpoint *ep,
/* Call helper to do the real work for both simulataneous and
* duplicate INIT chunk handling.
*/
- return sctp_sf_do_unexpected_init(ep, asoc, type, arg, commands);
+ return sctp_sf_do_unexpected_init(net, ep, asoc, type, arg, commands);
}
/*
@@ -1635,7 +1648,8 @@ sctp_disposition_t sctp_sf_do_5_2_1_siminit(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_5_2_2_dupinit(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_5_2_2_dupinit(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -1644,7 +1658,7 @@ sctp_disposition_t sctp_sf_do_5_2_2_dupinit(const struct sctp_endpoint *ep,
/* Call helper to do the real work for both simulataneous and
* duplicate INIT chunk handling.
*/
- return sctp_sf_do_unexpected_init(ep, asoc, type, arg, commands);
+ return sctp_sf_do_unexpected_init(net, ep, asoc, type, arg, commands);
}
@@ -1657,19 +1671,19 @@ sctp_disposition_t sctp_sf_do_5_2_2_dupinit(const struct sctp_endpoint *ep,
* An unexpected INIT ACK usually indicates the processing of an old or
* duplicated INIT chunk.
*/
-sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_5_2_3_initack(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg, sctp_cmd_seq_t *commands)
{
- struct net *net = sock_net(ep->base.sk);
/* Per the above section, we'll discard the chunk if we have an
* endpoint. If this is an OOTB INIT-ACK, treat it as such.
*/
if (ep == sctp_sk(net->sctp.ctl_sock)->ep)
- return sctp_sf_ootb(ep, asoc, type, arg, commands);
+ return sctp_sf_ootb(net, ep, asoc, type, arg, commands);
else
- return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
+ return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
}
/* Unexpected COOKIE-ECHO handler for peer restart (Table 2, action 'A')
@@ -1677,7 +1691,8 @@ sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep,
* Section 5.2.4
* A) In this case, the peer may have restarted.
*/
-static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
struct sctp_chunk *chunk,
sctp_cmd_seq_t *commands,
@@ -1713,7 +1728,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
* its peer.
*/
if (sctp_state(asoc, SHUTDOWN_ACK_SENT)) {
- disposition = sctp_sf_do_9_2_reshutack(ep, asoc,
+ disposition = sctp_sf_do_9_2_reshutack(net, ep, asoc,
SCTP_ST_CHUNK(chunk->chunk_hdr->type),
chunk, commands);
if (SCTP_DISPOSITION_NOMEM == disposition)
@@ -1776,7 +1791,8 @@ nomem:
* after responding to the local endpoint's INIT
*/
/* This case represents an initialization collision. */
-static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_do_dupcook_b(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
struct sctp_chunk *chunk,
sctp_cmd_seq_t *commands,
@@ -1797,7 +1813,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_ESTABLISHED));
- SCTP_INC_STATS(sock_net(new_asoc->base.sk), SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
repl = sctp_make_cookie_ack(new_asoc, chunk);
@@ -1846,7 +1862,8 @@ nomem:
* but a new tag of its own.
*/
/* This case represents an initialization collision. */
-static sctp_disposition_t sctp_sf_do_dupcook_c(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_do_dupcook_c(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
struct sctp_chunk *chunk,
sctp_cmd_seq_t *commands,
@@ -1867,7 +1884,8 @@ static sctp_disposition_t sctp_sf_do_dupcook_c(const struct sctp_endpoint *ep,
* enter the ESTABLISHED state, if it has not already done so.
*/
/* This case represents an initialization collision. */
-static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_do_dupcook_d(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
struct sctp_chunk *chunk,
sctp_cmd_seq_t *commands,
@@ -1889,7 +1907,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_ESTABLISHED));
- SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_CURRESTAB);
+ SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START,
SCTP_NULL());
@@ -1961,7 +1979,8 @@ nomem:
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_5_2_4_dupcook(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -1980,7 +1999,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
* done later.
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* "Decode" the chunk. We have no optional parameters so we
@@ -2014,12 +2033,12 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
goto nomem;
case -SCTP_IERROR_STALE_COOKIE:
- sctp_send_stale_cookie_err(ep, asoc, chunk, commands,
+ sctp_send_stale_cookie_err(net, ep, asoc, chunk, commands,
err_chk_p);
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
case -SCTP_IERROR_BAD_SIG:
default:
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
}
@@ -2030,27 +2049,27 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
switch (action) {
case 'A': /* Association restart. */
- retval = sctp_sf_do_dupcook_a(ep, asoc, chunk, commands,
+ retval = sctp_sf_do_dupcook_a(net, ep, asoc, chunk, commands,
new_asoc);
break;
case 'B': /* Collision case B. */
- retval = sctp_sf_do_dupcook_b(ep, asoc, chunk, commands,
+ retval = sctp_sf_do_dupcook_b(net, ep, asoc, chunk, commands,
new_asoc);
break;
case 'C': /* Collision case C. */
- retval = sctp_sf_do_dupcook_c(ep, asoc, chunk, commands,
+ retval = sctp_sf_do_dupcook_c(net, ep, asoc, chunk, commands,
new_asoc);
break;
case 'D': /* Collision case D. */
- retval = sctp_sf_do_dupcook_d(ep, asoc, chunk, commands,
+ retval = sctp_sf_do_dupcook_d(net, ep, asoc, chunk, commands,
new_asoc);
break;
default: /* Discard packet for all others. */
- retval = sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ retval = sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
break;
}
@@ -2076,6 +2095,7 @@ nomem:
* See sctp_sf_do_9_1_abort().
*/
sctp_disposition_t sctp_sf_shutdown_pending_abort(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -2085,7 +2105,7 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort(
struct sctp_chunk *chunk = arg;
if (!sctp_vtag_verify_either(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the ABORT chunk has a valid length.
* Since this is an ABORT chunk, we have to discard it
@@ -2098,7 +2118,7 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort(
* packet.
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* ADD-IP: Special case for ABORT chunks
* F4) One special consideration is that ABORT Chunks arriving
@@ -2107,9 +2127,9 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort(
*/
if (SCTP_ADDR_DEL ==
sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
- return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
+ return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
- return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands);
+ return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands);
}
/*
@@ -2117,7 +2137,8 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort(
*
* See sctp_sf_do_9_1_abort().
*/
-sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_shutdown_sent_abort(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2126,7 +2147,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep,
struct sctp_chunk *chunk = arg;
if (!sctp_vtag_verify_either(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the ABORT chunk has a valid length.
* Since this is an ABORT chunk, we have to discard it
@@ -2139,7 +2160,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep,
* packet.
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* ADD-IP: Special case for ABORT chunks
* F4) One special consideration is that ABORT Chunks arriving
@@ -2148,7 +2169,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep,
*/
if (SCTP_ADDR_DEL ==
sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
- return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
+ return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
/* Stop the T2-shutdown timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -2158,7 +2179,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
- return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands);
+ return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands);
}
/*
@@ -2167,6 +2188,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep,
* See sctp_sf_do_9_1_abort().
*/
sctp_disposition_t sctp_sf_shutdown_ack_sent_abort(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -2176,7 +2198,7 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_abort(
/* The same T2 timer, so we should be able to use
* common function with the SHUTDOWN-SENT state.
*/
- return sctp_sf_shutdown_sent_abort(ep, asoc, type, arg, commands);
+ return sctp_sf_shutdown_sent_abort(net, ep, asoc, type, arg, commands);
}
/*
@@ -2193,7 +2215,8 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_abort(
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_cookie_echoed_err(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2203,13 +2226,13 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
sctp_errhdr_t *err;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the ERROR chunk has a valid length.
* The parameter walking depends on this as well.
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* Process the error here */
@@ -2219,7 +2242,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
*/
sctp_walk_errors(err, chunk->chunk_hdr) {
if (SCTP_ERROR_STALE_COOKIE == err->cause)
- return sctp_sf_do_5_2_6_stale(ep, asoc, type,
+ return sctp_sf_do_5_2_6_stale(net, ep, asoc, type,
arg, commands);
}
@@ -2228,7 +2251,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
* we are discarding the packet, there should be no adverse
* affects.
*/
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
/*
@@ -2256,7 +2279,8 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_do_5_2_6_stale(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2378,7 +2402,8 @@ nomem:
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_9_1_abort(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2387,7 +2412,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
struct sctp_chunk *chunk = arg;
if (!sctp_vtag_verify_either(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the ABORT chunk has a valid length.
* Since this is an ABORT chunk, we have to discard it
@@ -2400,7 +2425,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
* packet.
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* ADD-IP: Special case for ABORT chunks
* F4) One special consideration is that ABORT Chunks arriving
@@ -2409,12 +2434,13 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
*/
if (SCTP_ADDR_DEL ==
sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
- return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
+ return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
- return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands);
+ return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands);
}
-static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
+static sctp_disposition_t __sctp_sf_do_9_1_abort(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2423,7 +2449,6 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
struct sctp_chunk *chunk = arg;
unsigned int len;
__be16 error = SCTP_ERROR_NO_ERROR;
- struct net *net;
/* See if we have an error cause code in the chunk. */
len = ntohs(chunk->chunk_hdr->length);
@@ -2432,7 +2457,7 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
sctp_errhdr_t *err;
sctp_walk_errors(err, chunk->chunk_hdr);
if ((void *)err != (void *)chunk->chunk_end)
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
}
@@ -2440,7 +2465,6 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET));
/* ASSOC_FAILED will DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error));
- net = sock_net(ep->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
@@ -2452,7 +2476,8 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
*
* See sctp_sf_do_9_1_abort() above.
*/
-sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_cookie_wait_abort(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2463,7 +2488,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
__be16 error = SCTP_ERROR_NO_ERROR;
if (!sctp_vtag_verify_either(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the ABORT chunk has a valid length.
* Since this is an ABORT chunk, we have to discard it
@@ -2476,27 +2501,28 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
* packet.
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* See if we have an error cause code in the chunk. */
len = ntohs(chunk->chunk_hdr->length);
if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
- return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, asoc,
+ return sctp_stop_t1_and_abort(net, commands, error, ECONNREFUSED, asoc,
chunk->transport);
}
/*
* Process an incoming ICMP as an ABORT. (COOKIE-WAIT state)
*/
-sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
- return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR,
+ return sctp_stop_t1_and_abort(net, commands, SCTP_ERROR_NO_ERROR,
ENOPROTOOPT, asoc,
(struct sctp_transport *)arg);
}
@@ -2504,7 +2530,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep
/*
* Process an ABORT. (COOKIE-ECHOED state)
*/
-sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_cookie_echoed_abort(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2513,7 +2540,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
/* There is a single T1 timer, so we should be able to use
* common function with the COOKIE-WAIT state.
*/
- return sctp_sf_cookie_wait_abort(ep, asoc, type, arg, commands);
+ return sctp_sf_cookie_wait_abort(net, ep, asoc, type, arg, commands);
}
/*
@@ -2521,7 +2548,8 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
*
* This is common code called by several sctp_sf_*_abort() functions above.
*/
-static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
+static sctp_disposition_t sctp_stop_t1_and_abort(struct net *net,
+ sctp_cmd_seq_t *commands,
__be16 error, int sk_err,
const struct sctp_association *asoc,
struct sctp_transport *transport)
@@ -2529,7 +2557,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
SCTP_DEBUG_PRINTK("ABORT received (INIT).\n");
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
- SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_ABORTEDS);
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err));
@@ -2572,7 +2600,8 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_9_2_shutdown(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2585,12 +2614,12 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
__u32 ctsn;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the SHUTDOWN chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk,
sizeof(struct sctp_shutdown_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* Convert the elaborate header. */
@@ -2610,7 +2639,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
* sender with an ABORT.
*/
if (!TSN_lt(ctsn, asoc->next_tsn))
- return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands);
+ return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands);
/* API 5.3.1.5 SCTP_SHUTDOWN_EVENT
* When a peer sends a SHUTDOWN, SCTP delivers this notification to
@@ -2634,7 +2663,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
disposition = SCTP_DISPOSITION_CONSUME;
if (sctp_outq_is_empty(&asoc->outqueue)) {
- disposition = sctp_sf_do_9_2_shutdown_ack(ep, asoc, type,
+ disposition = sctp_sf_do_9_2_shutdown_ack(net, ep, asoc, type,
arg, commands);
}
@@ -2660,7 +2689,8 @@ out:
* The Cumulative TSN Ack of the received SHUTDOWN chunk
* MUST be processed.
*/
-sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2671,12 +2701,12 @@ sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep,
__u32 ctsn;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the SHUTDOWN chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk,
sizeof(struct sctp_shutdown_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
sdh = (sctp_shutdownhdr_t *)chunk->skb->data;
@@ -2693,7 +2723,7 @@ sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep,
* sender with an ABORT.
*/
if (!TSN_lt(ctsn, asoc->next_tsn))
- return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands);
+ return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands);
/* verify, by checking the Cumulative TSN Ack field of the
* chunk, that all its outstanding DATA chunks have been
@@ -2712,7 +2742,8 @@ sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep,
* that belong to this association, it should discard the INIT chunk and
* retransmit the SHUTDOWN ACK chunk.
*/
-sctp_disposition_t sctp_sf_do_9_2_reshutack(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_9_2_reshutack(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2723,7 +2754,7 @@ sctp_disposition_t sctp_sf_do_9_2_reshutack(const struct sctp_endpoint *ep,
/* Make sure that the chunk has a valid length */
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* Since we are not going to really process this INIT, there
@@ -2775,7 +2806,8 @@ nomem:
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_ecn_cwr(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2786,10 +2818,10 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep,
u32 lowest_tsn;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_ecne_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
cwr = (sctp_cwrhdr_t *) chunk->skb->data;
@@ -2830,7 +2862,8 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_ecne(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_ecne(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2840,10 +2873,10 @@ sctp_disposition_t sctp_sf_do_ecne(const struct sctp_endpoint *ep,
struct sctp_chunk *chunk = arg;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_ecne_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
ecne = (sctp_ecnehdr_t *) chunk->skb->data;
@@ -2886,7 +2919,8 @@ sctp_disposition_t sctp_sf_do_ecne(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_eat_data_6_2(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -2899,11 +2933,11 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(chunk, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
SCTP_NULL());
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_data_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
error = sctp_eat_data(asoc, chunk, commands );
@@ -2912,16 +2946,16 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
break;
case SCTP_IERROR_HIGH_TSN:
case SCTP_IERROR_BAD_STREAM:
- SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
+ SCTP_INC_STATS(net, SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
goto discard_noforce;
case SCTP_IERROR_DUP_TSN:
case SCTP_IERROR_IGNORE_TSN:
- SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
+ SCTP_INC_STATS(net, SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
goto discard_force;
case SCTP_IERROR_NO_DATA:
goto consume;
case SCTP_IERROR_PROTO_VIOLATION:
- return sctp_sf_abort_violation(ep, asoc, chunk, commands,
+ return sctp_sf_abort_violation(net, ep, asoc, chunk, commands,
(u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t));
default:
BUG();
@@ -3007,7 +3041,8 @@ consume:
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_eat_data_fast_4_4(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -3019,11 +3054,11 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(chunk, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
SCTP_NULL());
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_data_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
error = sctp_eat_data(asoc, chunk, commands );
@@ -3037,7 +3072,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
case SCTP_IERROR_NO_DATA:
goto consume;
case SCTP_IERROR_PROTO_VIOLATION:
- return sctp_sf_abort_violation(ep, asoc, chunk, commands,
+ return sctp_sf_abort_violation(net, ep, asoc, chunk, commands,
(u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t));
default:
BUG();
@@ -3097,7 +3132,8 @@ consume:
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_eat_sack_6_2(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -3108,18 +3144,18 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep,
__u32 ctsn;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the SACK chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_sack_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* Pull the SACK chunk from the data buffer */
sackh = sctp_sm_pull_sack(chunk);
/* Was this a bogus SACK? */
if (!sackh)
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
chunk->subh.sack_hdr = sackh;
ctsn = ntohl(sackh->cum_tsn_ack);
@@ -3140,7 +3176,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep,
* sender with an ABORT.
*/
if (!TSN_lt(ctsn, asoc->next_tsn))
- return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands);
+ return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands);
/* Return this SACK for further processing. */
sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh));
@@ -3169,7 +3205,8 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_tabort_8_4_8(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -3178,9 +3215,7 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
struct sctp_packet *packet = NULL;
struct sctp_chunk *chunk = arg;
struct sctp_chunk *abort;
- struct net *net;
- net = sock_net(ep->base.sk);
packet = sctp_ootb_pkt_new(net, asoc, chunk);
if (packet) {
@@ -3207,7 +3242,7 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
- sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
return SCTP_DISPOSITION_CONSUME;
}
@@ -3222,7 +3257,8 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_operr_notify(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -3232,15 +3268,15 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
sctp_errhdr_t *err;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the ERROR chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
sctp_walk_errors(err, chunk->chunk_hdr);
if ((void *)err != (void *)chunk->chunk_end)
- return sctp_sf_violation_paramlen(ep, asoc, type, arg,
+ return sctp_sf_violation_paramlen(net, ep, asoc, type, arg,
(void *)err, commands);
sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
@@ -3259,7 +3295,8 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
*
* The return value is the disposition.
*/
-sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_9_2_final(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -3268,14 +3305,13 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
struct sctp_chunk *chunk = arg;
struct sctp_chunk *reply;
struct sctp_ulpevent *ev;
- struct net *net;
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the SHUTDOWN_ACK chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* 10.2 H) SHUTDOWN COMPLETE notification
*
@@ -3308,7 +3344,6 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
- net = sock_net(asoc->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS);
SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
@@ -3343,7 +3378,8 @@ nomem:
* receiver of the OOTB packet shall discard the OOTB packet and take
* no further action.
*/
-sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_ootb(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -3356,16 +3392,14 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
__u8 *ch_end;
int ootb_shut_ack = 0;
int ootb_cookie_ack = 0;
- struct net *net;
- net = sock_net(asoc->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
ch = (sctp_chunkhdr_t *) chunk->chunk_hdr;
do {
/* Report violation if the chunk is less then minimal */
if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* Now that we know we at least have a chunk header,
@@ -3380,7 +3414,7 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
* sending an ABORT of its own.
*/
if (SCTP_CID_ABORT == ch->type)
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR
* or a COOKIE ACK the SCTP Packet should be silently
@@ -3402,18 +3436,18 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
/* Report violation if chunk len overflows */
ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
if (ch_end > skb_tail_pointer(skb))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
ch = (sctp_chunkhdr_t *) ch_end;
} while (ch_end < skb_tail_pointer(skb));
if (ootb_shut_ack)
- return sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands);
+ return sctp_sf_shut_8_4_5(net, ep, asoc, type, arg, commands);
else if (ootb_cookie_ack)
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
else
- return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands);
}
/*
@@ -3437,7 +3471,8 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_shut_8_4_5(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -3446,9 +3481,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
struct sctp_packet *packet = NULL;
struct sctp_chunk *chunk = arg;
struct sctp_chunk *shut;
- struct net *net;
- net = sock_net(ep->base.sk);
packet = sctp_ootb_pkt_new(net, asoc, chunk);
if (packet) {
@@ -3479,13 +3512,13 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
* the reset of the packet.
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* We need to discard the rest of the packet to prevent
* potential bomming attacks from additional bundled chunks.
* This is documented in SCTP Threats ID.
*/
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
return SCTP_DISPOSITION_NOMEM;
@@ -3502,7 +3535,8 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
* chunks. --piggy ]
*
*/
-sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_8_5_1_E_sa(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -3512,7 +3546,7 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep,
/* Make sure that the SHUTDOWN_ACK chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
/* Although we do have an association in this case, it corresponds
@@ -3520,13 +3554,14 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep,
* packet and the state function that handles OOTB SHUTDOWN_ACK is
* called with a NULL association.
*/
- SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTOFBLUES);
+ SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
- return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands);
+ return sctp_sf_shut_8_4_5(net, ep, NULL, type, arg, commands);
}
/* ADDIP Section 4.2 Upon reception of an ASCONF Chunk. */
-sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_asconf(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type, void *arg,
sctp_cmd_seq_t *commands)
@@ -3542,7 +3577,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(chunk, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
SCTP_NULL());
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
/* ADD-IP: Section 4.1.1
@@ -3552,11 +3587,11 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
* described in [I-D.ietf-tsvwg-sctp-auth].
*/
if (!sctp_addip_noauth && !chunk->auth)
- return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
+ return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
/* Make sure that the ASCONF ADDIP chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_addip_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
hdr = (sctp_addiphdr_t *)chunk->skb->data;
@@ -3565,7 +3600,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
addr_param = (union sctp_addr_param *)hdr->params;
length = ntohs(addr_param->p.length);
if (length < sizeof(sctp_paramhdr_t))
- return sctp_sf_violation_paramlen(ep, asoc, type, arg,
+ return sctp_sf_violation_paramlen(net, ep, asoc, type, arg,
(void *)addr_param, commands);
/* Verify the ASCONF chunk before processing it. */
@@ -3573,7 +3608,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
(sctp_paramhdr_t *)((void *)addr_param + length),
(void *)chunk->chunk_end,
&err_param))
- return sctp_sf_violation_paramlen(ep, asoc, type, arg,
+ return sctp_sf_violation_paramlen(net, ep, asoc, type, arg,
(void *)err_param, commands);
/* ADDIP 5.2 E1) Compare the value of the serial number to the value
@@ -3653,7 +3688,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
* When building TLV parameters for the ASCONF Chunk that will add or
* delete IP addresses the D0 to D13 rules should be applied:
*/
-sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_asconf_ack(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type, void *arg,
sctp_cmd_seq_t *commands)
@@ -3668,7 +3704,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(asconf_ack, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
SCTP_NULL());
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
/* ADD-IP, Section 4.1.2:
@@ -3678,11 +3714,11 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
* described in [I-D.ietf-tsvwg-sctp-auth].
*/
if (!sctp_addip_noauth && !asconf_ack->auth)
- return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
+ return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
/* Make sure that the ADDIP chunk has a valid length. */
if (!sctp_chunk_length_valid(asconf_ack, sizeof(sctp_addip_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
addip_hdr = (sctp_addiphdr_t *)asconf_ack->skb->data;
@@ -3693,7 +3729,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
(sctp_paramhdr_t *)addip_hdr->params,
(void *)asconf_ack->chunk_end,
&err_param))
- return sctp_sf_violation_paramlen(ep, asoc, type, arg,
+ return sctp_sf_violation_paramlen(net, ep, asoc, type, arg,
(void *)err_param, commands);
if (last_asconf) {
@@ -3711,7 +3747,6 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
*/
if (ADDIP_SERIAL_gte(rcvd_serial, sent_serial + 1) &&
!(asoc->addip_last_asconf)) {
- struct net *net;
abort = sctp_make_abort(asoc, asconf_ack,
sizeof(sctp_errhdr_t));
if (abort) {
@@ -3729,14 +3764,12 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
- net = sock_net(asoc->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_ABORT;
}
if ((rcvd_serial == sent_serial) && asoc->addip_last_asconf) {
- struct net *net;
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
@@ -3765,7 +3798,6 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
- net = sock_net(asoc->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
return SCTP_DISPOSITION_ABORT;
@@ -3788,7 +3820,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_eat_fwd_tsn(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -3803,12 +3836,12 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(chunk, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
SCTP_NULL());
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
/* Make sure that the FORWARD_TSN chunk has valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_fwdtsn_chunk)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data;
@@ -3855,6 +3888,7 @@ discard_noforce:
}
sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -3870,12 +3904,12 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
if (!sctp_vtag_verify(chunk, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
SCTP_NULL());
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
/* Make sure that the FORWARD_TSN chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_fwdtsn_chunk)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data;
@@ -3942,7 +3976,8 @@ gen_shutdown:
*
* The return value is the disposition of the chunk.
*/
-static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep,
+static sctp_ierror_t sctp_sf_authenticate(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
struct sctp_chunk *chunk)
@@ -4015,7 +4050,8 @@ nomem:
return SCTP_IERROR_NOMEM;
}
-sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_eat_auth(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -4028,21 +4064,21 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
/* Make sure that the peer has AUTH capable */
if (!asoc->peer.auth_capable)
- return sctp_sf_unk_chunk(ep, asoc, type, arg, commands);
+ return sctp_sf_unk_chunk(net, ep, asoc, type, arg, commands);
if (!sctp_vtag_verify(chunk, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
SCTP_NULL());
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
/* Make sure that the AUTH chunk has valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_auth_chunk)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
- error = sctp_sf_authenticate(ep, asoc, type, chunk);
+ error = sctp_sf_authenticate(net, ep, asoc, type, chunk);
switch (error) {
case SCTP_IERROR_AUTH_BAD_HMAC:
/* Generate the ERROR chunk and discard the rest
@@ -4059,10 +4095,10 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
/* Fall Through */
case SCTP_IERROR_AUTH_BAD_KEYID:
case SCTP_IERROR_BAD_SIG:
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
case SCTP_IERROR_PROTO_VIOLATION:
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
case SCTP_IERROR_NOMEM:
@@ -4111,7 +4147,8 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_unk_chunk(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -4124,20 +4161,20 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
SCTP_DEBUG_PRINTK("Processing the unknown chunk id %d.\n", type.chunk);
if (!sctp_vtag_verify(unk_chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the chunk has a valid length.
* Since we don't know the chunk type, we use a general
* chunkhdr structure to make a comparison.
*/
if (!sctp_chunk_length_valid(unk_chunk, sizeof(sctp_chunkhdr_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
switch (type.chunk & SCTP_CID_ACTION_MASK) {
case SCTP_CID_ACTION_DISCARD:
/* Discard the packet. */
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
break;
case SCTP_CID_ACTION_DISCARD_ERR:
/* Generate an ERROR chunk as response. */
@@ -4152,7 +4189,7 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
}
/* Discard the packet. */
- sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
return SCTP_DISPOSITION_CONSUME;
break;
case SCTP_CID_ACTION_SKIP:
@@ -4194,7 +4231,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_discard_chunk(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_discard_chunk(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -4207,7 +4245,7 @@ sctp_disposition_t sctp_sf_discard_chunk(const struct sctp_endpoint *ep,
* chunkhdr structure to make a comparison.
*/
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
SCTP_DEBUG_PRINTK("Chunk %d is discarded\n", type.chunk);
@@ -4232,13 +4270,14 @@ sctp_disposition_t sctp_sf_discard_chunk(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_pdiscard(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_pdiscard(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
- SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_PKT_DISCARDS);
+ SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_DISCARDS);
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
return SCTP_DISPOSITION_CONSUME;
@@ -4259,7 +4298,8 @@ sctp_disposition_t sctp_sf_pdiscard(const struct sctp_endpoint *ep,
* We simply tag the chunk as a violation. The state machine will log
* the violation and continue.
*/
-sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_violation(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -4269,7 +4309,7 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
/* Make sure that the chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
return SCTP_DISPOSITION_VIOLATION;
@@ -4279,6 +4319,7 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
* Common function to handle a protocol violation.
*/
static sctp_disposition_t sctp_sf_abort_violation(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
void *arg,
@@ -4289,7 +4330,6 @@ static sctp_disposition_t sctp_sf_abort_violation(
struct sctp_packet *packet = NULL;
struct sctp_chunk *chunk = arg;
struct sctp_chunk *abort = NULL;
- struct net *net;
/* SCTP-AUTH, Section 6.3:
* It should be noted that if the receiver wants to tear
@@ -4310,7 +4350,6 @@ static sctp_disposition_t sctp_sf_abort_violation(
if (!abort)
goto nomem;
- net = sock_net(ep->base.sk);
if (asoc) {
/* Treat INIT-ACK as a special case during COOKIE-WAIT. */
if (chunk->chunk_hdr->type == SCTP_CID_INIT_ACK &&
@@ -4369,7 +4408,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
discard:
- sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
+ sctp_sf_pdiscard(net, ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
return SCTP_DISPOSITION_ABORT;
nomem_pkt:
@@ -4398,6 +4437,7 @@ nomem:
* Generate an ABORT chunk and terminate the association.
*/
static sctp_disposition_t sctp_sf_violation_chunklen(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -4406,7 +4446,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
{
static const char err_str[]="The following chunk had invalid length:";
- return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
+ return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str,
sizeof(err_str));
}
@@ -4417,6 +4457,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
* the length is considered as invalid.
*/
static sctp_disposition_t sctp_sf_violation_paramlen(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -4426,7 +4467,6 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
struct sctp_chunk *chunk = arg;
struct sctp_paramhdr *param = ext;
struct sctp_chunk *abort = NULL;
- struct net *net;
if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
goto discard;
@@ -4436,7 +4476,6 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
if (!abort)
goto nomem;
- net = sock_net(asoc->base.sk);
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
@@ -4448,7 +4487,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
discard:
- sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
+ sctp_sf_pdiscard(net, ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
return SCTP_DISPOSITION_ABORT;
nomem:
return SCTP_DISPOSITION_NOMEM;
@@ -4461,6 +4500,7 @@ nomem:
* error code.
*/
static sctp_disposition_t sctp_sf_violation_ctsn(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -4469,7 +4509,7 @@ static sctp_disposition_t sctp_sf_violation_ctsn(
{
static const char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:";
- return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
+ return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str,
sizeof(err_str));
}
@@ -4480,6 +4520,7 @@ static sctp_disposition_t sctp_sf_violation_ctsn(
* on the path and we may not want to continue this communication.
*/
static sctp_disposition_t sctp_sf_violation_chunk(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -4489,9 +4530,9 @@ static sctp_disposition_t sctp_sf_violation_chunk(
static const char err_str[]="The following chunk violates protocol:";
if (!asoc)
- return sctp_sf_violation(ep, asoc, type, arg, commands);
+ return sctp_sf_violation(net, ep, asoc, type, arg, commands);
- return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
+ return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str,
sizeof(err_str));
}
/***************************************************************************
@@ -4554,7 +4595,8 @@ static sctp_disposition_t sctp_sf_violation_chunk(
*
* The return value is a disposition.
*/
-sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_prm_asoc(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -4665,7 +4707,8 @@ nomem:
*
* The return value is the disposition.
*/
-sctp_disposition_t sctp_sf_do_prm_send(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_prm_send(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -4704,6 +4747,7 @@ sctp_disposition_t sctp_sf_do_prm_send(const struct sctp_endpoint *ep,
* The return value is the disposition.
*/
sctp_disposition_t sctp_sf_do_9_2_prm_shutdown(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -4725,7 +4769,7 @@ sctp_disposition_t sctp_sf_do_9_2_prm_shutdown(
disposition = SCTP_DISPOSITION_CONSUME;
if (sctp_outq_is_empty(&asoc->outqueue)) {
- disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type,
+ disposition = sctp_sf_do_9_2_start_shutdown(net, ep, asoc, type,
arg, commands);
}
return disposition;
@@ -4759,6 +4803,7 @@ sctp_disposition_t sctp_sf_do_9_2_prm_shutdown(
* The return value is the disposition.
*/
sctp_disposition_t sctp_sf_do_9_1_prm_abort(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -4775,7 +4820,6 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
*/
struct sctp_chunk *abort = arg;
sctp_disposition_t retval;
- struct net *net;
retval = SCTP_DISPOSITION_CONSUME;
@@ -4791,7 +4835,6 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_PERR(SCTP_ERROR_USER_ABORT));
- net = sock_net(asoc->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
@@ -4799,7 +4842,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
}
/* We tried an illegal operation on an association which is closed. */
-sctp_disposition_t sctp_sf_error_closed(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_error_closed(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -4812,7 +4856,8 @@ sctp_disposition_t sctp_sf_error_closed(const struct sctp_endpoint *ep,
/* We tried an illegal operation on an association which is shutting
* down.
*/
-sctp_disposition_t sctp_sf_error_shutdown(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_error_shutdown(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -4838,14 +4883,13 @@ sctp_disposition_t sctp_sf_error_shutdown(const struct sctp_endpoint *ep,
* (timers)
*/
sctp_disposition_t sctp_sf_cookie_wait_prm_shutdown(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
- struct net *net = sock_net(asoc->base.sk);
-
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
@@ -4874,6 +4918,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_shutdown(
* (timers)
*/
sctp_disposition_t sctp_sf_cookie_echoed_prm_shutdown(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -4882,7 +4927,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_shutdown(
/* There is a single T1 timer, so we should be able to use
* common function with the COOKIE-WAIT state.
*/
- return sctp_sf_cookie_wait_prm_shutdown(ep, asoc, type, arg, commands);
+ return sctp_sf_cookie_wait_prm_shutdown(net, ep, asoc, type, arg, commands);
}
/*
@@ -4900,6 +4945,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_shutdown(
* (timers)
*/
sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -4908,7 +4954,6 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
{
struct sctp_chunk *abort = arg;
sctp_disposition_t retval;
- struct net *net = sock_net(asoc->base.sk);
/* Stop T1-init timer */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -4950,6 +4995,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
* (timers)
*/
sctp_disposition_t sctp_sf_cookie_echoed_prm_abort(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -4959,7 +5005,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_abort(
/* There is a single T1 timer, so we should be able to use
* common function with the COOKIE-WAIT state.
*/
- return sctp_sf_cookie_wait_prm_abort(ep, asoc, type, arg, commands);
+ return sctp_sf_cookie_wait_prm_abort(net, ep, asoc, type, arg, commands);
}
/*
@@ -4975,6 +5021,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_abort(
* (timers)
*/
sctp_disposition_t sctp_sf_shutdown_pending_prm_abort(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -4985,7 +5032,7 @@ sctp_disposition_t sctp_sf_shutdown_pending_prm_abort(
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
- return sctp_sf_do_9_1_prm_abort(ep, asoc, type, arg, commands);
+ return sctp_sf_do_9_1_prm_abort(net, ep, asoc, type, arg, commands);
}
/*
@@ -5001,6 +5048,7 @@ sctp_disposition_t sctp_sf_shutdown_pending_prm_abort(
* (timers)
*/
sctp_disposition_t sctp_sf_shutdown_sent_prm_abort(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -5015,7 +5063,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_prm_abort(
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
- return sctp_sf_do_9_1_prm_abort(ep, asoc, type, arg, commands);
+ return sctp_sf_do_9_1_prm_abort(net, ep, asoc, type, arg, commands);
}
/*
@@ -5031,6 +5079,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_prm_abort(
* (timers)
*/
sctp_disposition_t sctp_sf_shutdown_ack_sent_prm_abort(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -5040,7 +5089,7 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_prm_abort(
/* The same T2 timer, so we should be able to use
* common function with the SHUTDOWN-SENT state.
*/
- return sctp_sf_shutdown_sent_prm_abort(ep, asoc, type, arg, commands);
+ return sctp_sf_shutdown_sent_prm_abort(net, ep, asoc, type, arg, commands);
}
/*
@@ -5066,6 +5115,7 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_prm_abort(
* association on which a heartbeat should be issued.
*/
sctp_disposition_t sctp_sf_do_prm_requestheartbeat(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -5097,7 +5147,8 @@ sctp_disposition_t sctp_sf_do_prm_requestheartbeat(
* When an endpoint has an ASCONF signaled change to be sent to the
* remote endpoint it should do A1 to A9
*/
-sctp_disposition_t sctp_sf_do_prm_asconf(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_prm_asconf(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -5118,6 +5169,7 @@ sctp_disposition_t sctp_sf_do_prm_asconf(const struct sctp_endpoint *ep,
* The return value is the disposition of the primitive.
*/
sctp_disposition_t sctp_sf_ignore_primitive(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -5139,6 +5191,7 @@ sctp_disposition_t sctp_sf_ignore_primitive(
* retransmit, the stack will immediately send up this notification.
*/
sctp_disposition_t sctp_sf_do_no_pending_tsn(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -5170,6 +5223,7 @@ sctp_disposition_t sctp_sf_do_no_pending_tsn(
* The return value is the disposition.
*/
sctp_disposition_t sctp_sf_do_9_2_start_shutdown(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -5239,6 +5293,7 @@ nomem:
* The return value is the disposition.
*/
sctp_disposition_t sctp_sf_do_9_2_shutdown_ack(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -5257,11 +5312,11 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown_ack(
*/
if (chunk) {
if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Make sure that the SHUTDOWN chunk has a valid length. */
if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_shutdown_chunk_t)))
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
}
@@ -5309,7 +5364,8 @@ nomem:
*
* The return value is the disposition of the event.
*/
-sctp_disposition_t sctp_sf_ignore_other(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_ignore_other(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -5334,14 +5390,14 @@ sctp_disposition_t sctp_sf_ignore_other(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_6_3_3_rtx(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
struct sctp_transport *transport = arg;
- struct net *net = sock_net(asoc->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_T3_RTX_EXPIREDS);
@@ -5421,13 +5477,13 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
* allow. However, an SCTP transmitter MUST NOT be more aggressive than
* the following algorithms allow.
*/
-sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_do_6_2_sack(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
- struct net *net = sock_net(asoc->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_DELAY_SACK_EXPIREDS);
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE());
return SCTP_DISPOSITION_CONSUME;
@@ -5452,7 +5508,8 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
* (timers, events)
*
*/
-sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_t1_init_timer_expire(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -5461,7 +5518,6 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
struct sctp_chunk *repl = NULL;
struct sctp_bind_addr *bp;
int attempts = asoc->init_err_counter + 1;
- struct net *net = sock_net(asoc->base.sk);
SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
SCTP_INC_STATS(net, SCTP_MIB_T1_INIT_EXPIREDS);
@@ -5514,7 +5570,8 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
* (timers, events)
*
*/
-sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_t1_cookie_timer_expire(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -5522,7 +5579,6 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
{
struct sctp_chunk *repl = NULL;
int attempts = asoc->init_err_counter + 1;
- struct net *net = sock_net(asoc->base.sk);
SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
SCTP_INC_STATS(net, SCTP_MIB_T1_COOKIE_EXPIREDS);
@@ -5563,14 +5619,14 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
* the T2-Shutdown timer, giving its peer ample opportunity to transmit
* all of its queued DATA chunks that have not yet been sent.
*/
-sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_t2_timer_expire(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
struct sctp_chunk *reply = NULL;
- struct net *net = sock_net(asoc->base.sk);
SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
SCTP_INC_STATS(net, SCTP_MIB_T2_SHUTDOWN_EXPIREDS);
@@ -5633,6 +5689,7 @@ nomem:
* If the T4 RTO timer expires the endpoint should do B1 to B5
*/
sctp_disposition_t sctp_sf_t4_timer_expire(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
@@ -5641,7 +5698,6 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
{
struct sctp_chunk *chunk = asoc->addip_last_asconf;
struct sctp_transport *transport = chunk->transport;
- struct net *net = sock_net(asoc->base.sk);
SCTP_INC_STATS(net, SCTP_MIB_T4_RTO_EXPIREDS);
@@ -5704,14 +5760,14 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
* At the expiration of this timer the sender SHOULD abort the association
* by sending an ABORT chunk.
*/
-sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_t5_timer_expire(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
struct sctp_chunk *reply = NULL;
- struct net *net = sock_net(asoc->base.sk);
SCTP_DEBUG_PRINTK("Timer T5 expired.\n");
SCTP_INC_STATS(net, SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS);
@@ -5740,13 +5796,13 @@ nomem:
* the user. So this routine looks same as sctp_sf_do_9_2_prm_shutdown().
*/
sctp_disposition_t sctp_sf_autoclose_timer_expire(
+ struct net *net,
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
- struct net *net = sock_net(asoc->base.sk);
int disposition;
SCTP_INC_STATS(net, SCTP_MIB_AUTOCLOSE_EXPIREDS);
@@ -5764,7 +5820,7 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire(
disposition = SCTP_DISPOSITION_CONSUME;
if (sctp_outq_is_empty(&asoc->outqueue)) {
- disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type,
+ disposition = sctp_sf_do_9_2_start_shutdown(net, ep, asoc, type,
arg, commands);
}
return disposition;
@@ -5782,7 +5838,8 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire(
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_not_impl(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_not_impl(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -5799,7 +5856,8 @@ sctp_disposition_t sctp_sf_not_impl(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_bug(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_bug(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -5819,7 +5877,8 @@ sctp_disposition_t sctp_sf_bug(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_timer_ignore(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_timer_ignore(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -5861,7 +5920,8 @@ static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk)
/* Create an ABORT packet to be sent as a response, with the specified
* error causes.
*/
-static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
+static struct sctp_packet *sctp_abort_pkt_new(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
struct sctp_chunk *chunk,
const void *payload,
@@ -5869,9 +5929,7 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
{
struct sctp_packet *packet;
struct sctp_chunk *abort;
- struct net *net;
- net = sock_net(ep->base.sk);
packet = sctp_ootb_pkt_new(net, asoc, chunk);
if (packet) {
@@ -5984,7 +6042,8 @@ void sctp_ootb_pkt_free(struct sctp_packet *packet)
}
/* Send a stale cookie error when a invalid COOKIE ECHO chunk is found */
-static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
+static void sctp_send_stale_cookie_err(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const struct sctp_chunk *chunk,
sctp_cmd_seq_t *commands,
@@ -5993,7 +6052,6 @@ static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
struct sctp_packet *packet;
if (err_chunk) {
- struct net *net = sock_net(ep->base.sk);
packet = sctp_ootb_pkt_new(net, asoc, chunk);
if (packet) {
struct sctp_signed_cookie *cookie;
@@ -6027,7 +6085,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
__u32 tsn;
struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
struct sock *sk = asoc->base.sk;
- struct net *net;
+ struct net *net = sock_net(sk);
u16 ssn;
u16 sid;
u8 ordered = 0;
@@ -6144,7 +6202,6 @@ static int sctp_eat_data(const struct sctp_association *asoc,
* No User Data: This error cause is returned to the originator of a
* DATA chunk if a received DATA chunk has no user data.
*/
- net = sock_net(sk);
if (unlikely(0 == datalen)) {
err = sctp_make_abort_no_data(asoc, chunk, tsn);
if (err) {
--
1.7.5.4
Add struct net as a parameter to sctp_verify_param so it can be passed
to sctp_verify_ext_param where struct net will be needed when the sctp
tunables become per net tunables.
Add struct net as a parameter to sctp_verify_init so struct net can be
passed to sctp_verify_param.
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/sctp/structs.h | 6 +++---
net/sctp/sm_make_chunk.c | 11 ++++++-----
net/sctp/sm_statefuns.c | 6 +++---
3 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index b0882f3..18052b4 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1410,9 +1410,9 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
int sctp_has_association(struct net *net, const union sctp_addr *laddr,
const union sctp_addr *paddr);
-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_verify_init(struct net *net, 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);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index fb12835..a4b096f 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1940,7 +1940,7 @@ static int sctp_process_hn_param(const struct sctp_association *asoc,
return 0;
}
-static int sctp_verify_ext_param(union sctp_params param)
+static int sctp_verify_ext_param(struct net *net, union sctp_params param)
{
__u16 num_ext = ntohs(param.p->length) - sizeof(sctp_paramhdr_t);
int have_auth = 0;
@@ -2081,7 +2081,8 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,
* SCTP_IERROR_ERROR - stop processing, trigger an ERROR
* SCTP_IERROR_NO_ERROR - continue with the chunk
*/
-static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc,
+static sctp_ierror_t sctp_verify_param(struct net *net,
+ const struct sctp_association *asoc,
union sctp_params param,
sctp_cid_t cid,
struct sctp_chunk *chunk,
@@ -2110,7 +2111,7 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc,
break;
case SCTP_PARAM_SUPPORTED_EXT:
- if (!sctp_verify_ext_param(param))
+ if (!sctp_verify_ext_param(net, param))
return SCTP_IERROR_ABORT;
break;
@@ -2198,7 +2199,7 @@ fallthrough:
}
/* Verify the INIT packet before we process it. */
-int sctp_verify_init(const struct sctp_association *asoc,
+int sctp_verify_init(struct net *net, const struct sctp_association *asoc,
sctp_cid_t cid,
sctp_init_chunk_t *peer_init,
struct sctp_chunk *chunk,
@@ -2245,7 +2246,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
/* Verify all the variable length parameters */
sctp_walk_params(param, peer_init, init_hdr.params) {
- result = sctp_verify_param(asoc, param, cid, chunk, errp);
+ result = sctp_verify_param(net, asoc, param, cid, chunk, errp);
switch (result) {
case SCTP_IERROR_ABORT:
case SCTP_IERROR_NOMEM:
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 3e5ca61..3722af2 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -364,7 +364,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(struct net *net,
/* Verify the INIT chunk before processing it. */
err_chunk = NULL;
- if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,
+ if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type,
(sctp_init_chunk_t *)chunk->chunk_hdr, chunk,
&err_chunk)) {
/* This chunk contains fatal error. It is to be discarded.
@@ -531,7 +531,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net,
/* Verify the INIT chunk before processing it. */
err_chunk = NULL;
- if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,
+ if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type,
(sctp_init_chunk_t *)chunk->chunk_hdr, chunk,
&err_chunk)) {
@@ -1429,7 +1429,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
/* Verify the INIT chunk before processing it. */
err_chunk = NULL;
- if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,
+ if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type,
(sctp_init_chunk_t *)chunk->chunk_hdr, chunk,
&err_chunk)) {
/* This chunk contains fatal error. It is to be discarded.
--
1.7.5.4
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
include/net/netns/sctp.h | 90 +++++++++++++++++++++
include/net/sctp/structs.h | 116 ---------------------------
net/sctp/associola.c | 10 ++-
net/sctp/auth.c | 20 ++++-
net/sctp/bind_addr.c | 2 +-
net/sctp/endpointola.c | 9 +-
net/sctp/input.c | 2 +-
net/sctp/protocol.c | 128 +++++++++++++++---------------
net/sctp/sm_make_chunk.c | 47 ++++++-----
net/sctp/sm_statefuns.c | 4 +-
net/sctp/sm_statetable.c | 6 +-
net/sctp/socket.c | 65 +++++++++------
net/sctp/sysctl.c | 185 ++++++++++++++++++++++---------------------
net/sctp/transport.c | 15 ++--
14 files changed, 355 insertions(+), 344 deletions(-)
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
index 9576b60..f15a5df 100644
--- a/include/net/netns/sctp.h
+++ b/include/net/netns/sctp.h
@@ -36,6 +36,96 @@ struct netns_sctp {
/* Lock that protects the local_addr_list writers */
spinlock_t local_addr_lock;
+ /* RFC2960 Section 14. Suggested SCTP Protocol Parameter Values
+ *
+ * The following protocol parameters are RECOMMENDED:
+ *
+ * RTO.Initial - 3 seconds
+ * RTO.Min - 1 second
+ * RTO.Max - 60 seconds
+ * RTO.Alpha - 1/8 (3 when converted to right shifts.)
+ * RTO.Beta - 1/4 (2 when converted to right shifts.)
+ */
+ unsigned int rto_initial;
+ unsigned int rto_min;
+ unsigned int rto_max;
+
+ /* Note: rto_alpha and rto_beta are really defined as inverse
+ * powers of two to facilitate integer operations.
+ */
+ int rto_alpha;
+ int rto_beta;
+
+ /* Max.Burst - 4 */
+ int max_burst;
+
+ /* Whether Cookie Preservative is enabled(1) or not(0) */
+ int cookie_preserve_enable;
+
+ /* Valid.Cookie.Life - 60 seconds */
+ unsigned int valid_cookie_life;
+
+ /* Delayed SACK timeout 200ms default*/
+ unsigned int sack_timeout;
+
+ /* HB.interval - 30 seconds */
+ unsigned int hb_interval;
+
+ /* Association.Max.Retrans - 10 attempts
+ * Path.Max.Retrans - 5 attempts (per destination address)
+ * Max.Init.Retransmits - 8 attempts
+ */
+ int max_retrans_association;
+ int max_retrans_path;
+ int max_retrans_init;
+ /* Potentially-Failed.Max.Retrans sysctl value
+ * taken from:
+ * http://tools.ietf.org/html/draft-nishida-tsvwg-sctp-failover-05
+ */
+ int pf_retrans;
+
+ /*
+ * Policy for preforming sctp/socket accounting
+ * 0 - do socket level accounting, all assocs share sk_sndbuf
+ * 1 - do sctp accounting, each asoc may use sk_sndbuf bytes
+ */
+ int sndbuf_policy;
+
+ /*
+ * Policy for preforming sctp/socket accounting
+ * 0 - do socket level accounting, all assocs share sk_rcvbuf
+ * 1 - do sctp accounting, each asoc may use sk_rcvbuf bytes
+ */
+ int rcvbuf_policy;
+
+ int default_auto_asconf;
+
+ /* Flag to indicate if addip is enabled. */
+ int addip_enable;
+ int addip_noauth;
+
+ /* Flag to indicate if PR-SCTP is enabled. */
+ int prsctp_enable;
+
+ /* Flag to idicate if SCTP-AUTH is enabled */
+ int auth_enable;
+
+ /*
+ * Policy to control SCTP IPv4 address scoping
+ * 0 - Disable IPv4 address scoping
+ * 1 - Enable IPv4 address scoping
+ * 2 - Selectively allow only IPv4 private addresses
+ * 3 - Selectively allow only IPv4 link local address
+ */
+ int scope_policy;
+
+ /* Threshold for rwnd update SACKS. Receive buffer shifted this many
+ * bits is an indicator of when to send and window update SACK.
+ */
+ int rwnd_upd_shift;
+
+ /* Threshold for autoclose timeout, in seconds. */
+ unsigned long max_autoclose;
};
#endif /* __NETNS_SCTP_H__ */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 18052b4..0fef00f 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -119,69 +119,6 @@ struct sctp_hashbucket {
/* The SCTP globals structure. */
extern struct sctp_globals {
- /* RFC2960 Section 14. Suggested SCTP Protocol Parameter Values
- *
- * The following protocol parameters are RECOMMENDED:
- *
- * RTO.Initial - 3 seconds
- * RTO.Min - 1 second
- * RTO.Max - 60 seconds
- * RTO.Alpha - 1/8 (3 when converted to right shifts.)
- * RTO.Beta - 1/4 (2 when converted to right shifts.)
- */
- unsigned int rto_initial;
- unsigned int rto_min;
- unsigned int rto_max;
-
- /* Note: rto_alpha and rto_beta are really defined as inverse
- * powers of two to facilitate integer operations.
- */
- int rto_alpha;
- int rto_beta;
-
- /* Max.Burst - 4 */
- int max_burst;
-
- /* Whether Cookie Preservative is enabled(1) or not(0) */
- int cookie_preserve_enable;
-
- /* Valid.Cookie.Life - 60 seconds */
- unsigned int valid_cookie_life;
-
- /* Delayed SACK timeout 200ms default*/
- unsigned int sack_timeout;
-
- /* HB.interval - 30 seconds */
- unsigned int hb_interval;
-
- /* Association.Max.Retrans - 10 attempts
- * Path.Max.Retrans - 5 attempts (per destination address)
- * Max.Init.Retransmits - 8 attempts
- */
- int max_retrans_association;
- int max_retrans_path;
- int max_retrans_init;
-
- /* Potentially-Failed.Max.Retrans sysctl value
- * taken from:
- * http://tools.ietf.org/html/draft-nishida-tsvwg-sctp-failover-05
- */
- int pf_retrans;
-
- /*
- * Policy for preforming sctp/socket accounting
- * 0 - do socket level accounting, all assocs share sk_sndbuf
- * 1 - do sctp accounting, each asoc may use sk_sndbuf bytes
- */
- int sndbuf_policy;
-
- /*
- * Policy for preforming sctp/socket accounting
- * 0 - do socket level accounting, all assocs share sk_rcvbuf
- * 1 - do sctp accounting, each asoc may use sk_rcvbuf bytes
- */
- int rcvbuf_policy;
-
/* The following variables are implementation specific. */
/* Default initialization values to be applied to new associations. */
@@ -205,56 +142,11 @@ extern struct sctp_globals {
int port_hashsize;
struct sctp_bind_hashbucket *port_hashtable;
- int default_auto_asconf;
-
- /* Flag to indicate if addip is enabled. */
- int addip_enable;
- int addip_noauth_enable;
-
- /* Flag to indicate if PR-SCTP is enabled. */
- int prsctp_enable;
-
- /* Flag to idicate if SCTP-AUTH is enabled */
- int auth_enable;
-
- /*
- * Policy to control SCTP IPv4 address scoping
- * 0 - Disable IPv4 address scoping
- * 1 - Enable IPv4 address scoping
- * 2 - Selectively allow only IPv4 private addresses
- * 3 - Selectively allow only IPv4 link local address
- */
- int ipv4_scope_policy;
-
/* Flag to indicate whether computing and verifying checksum
* is disabled. */
bool checksum_disable;
-
- /* Threshold for rwnd update SACKS. Receive buffer shifted this many
- * bits is an indicator of when to send and window update SACK.
- */
- int rwnd_update_shift;
-
- /* Threshold for autoclose timeout, in seconds. */
- unsigned long max_autoclose;
} sctp_globals;
-#define sctp_rto_initial (sctp_globals.rto_initial)
-#define sctp_rto_min (sctp_globals.rto_min)
-#define sctp_rto_max (sctp_globals.rto_max)
-#define sctp_rto_alpha (sctp_globals.rto_alpha)
-#define sctp_rto_beta (sctp_globals.rto_beta)
-#define sctp_max_burst (sctp_globals.max_burst)
-#define sctp_valid_cookie_life (sctp_globals.valid_cookie_life)
-#define sctp_cookie_preserve_enable (sctp_globals.cookie_preserve_enable)
-#define sctp_max_retrans_association (sctp_globals.max_retrans_association)
-#define sctp_sndbuf_policy (sctp_globals.sndbuf_policy)
-#define sctp_rcvbuf_policy (sctp_globals.rcvbuf_policy)
-#define sctp_max_retrans_path (sctp_globals.max_retrans_path)
-#define sctp_pf_retrans (sctp_globals.pf_retrans)
-#define sctp_max_retrans_init (sctp_globals.max_retrans_init)
-#define sctp_sack_timeout (sctp_globals.sack_timeout)
-#define sctp_hb_interval (sctp_globals.hb_interval)
#define sctp_max_instreams (sctp_globals.max_instreams)
#define sctp_max_outstreams (sctp_globals.max_outstreams)
#define sctp_address_families (sctp_globals.address_families)
@@ -264,15 +156,7 @@ extern struct sctp_globals {
#define sctp_assoc_hashtable (sctp_globals.assoc_hashtable)
#define sctp_port_hashsize (sctp_globals.port_hashsize)
#define sctp_port_hashtable (sctp_globals.port_hashtable)
-#define sctp_default_auto_asconf (sctp_globals.default_auto_asconf)
-#define sctp_scope_policy (sctp_globals.ipv4_scope_policy)
-#define sctp_addip_enable (sctp_globals.addip_enable)
-#define sctp_addip_noauth (sctp_globals.addip_noauth_enable)
-#define sctp_prsctp_enable (sctp_globals.prsctp_enable)
-#define sctp_auth_enable (sctp_globals.auth_enable)
#define sctp_checksum_disable (sctp_globals.checksum_disable)
-#define sctp_rwnd_upd_shift (sctp_globals.rwnd_update_shift)
-#define sctp_max_autoclose (sctp_globals.max_autoclose)
/* SCTP Socket type: UDP or TCP style. */
typedef enum {
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 93a4513..b1ef3bc 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -82,6 +82,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
sctp_scope_t scope,
gfp_t gfp)
{
+ struct net *net = sock_net(sk);
struct sctp_sock *sp;
int i;
sctp_paramhdr_t *p;
@@ -124,7 +125,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
* socket values.
*/
asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt;
- asoc->pf_retrans = sctp_pf_retrans;
+ asoc->pf_retrans = net->sctp.pf_retrans;
asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial);
asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max);
@@ -175,7 +176,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
- min_t(unsigned long, sp->autoclose, sctp_max_autoclose) * HZ;
+ min_t(unsigned long, sp->autoclose, net->sctp.max_autoclose) * HZ;
/* Initializes the timers */
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
@@ -281,7 +282,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
* and will revert old behavior.
*/
asoc->peer.asconf_capable = 0;
- if (sctp_addip_noauth)
+ if (net->sctp.addip_noauth)
asoc->peer.asconf_capable = 1;
asoc->asconf_addr_del_pending = NULL;
asoc->src_out_of_asoc_ok = 0;
@@ -1418,6 +1419,7 @@ void sctp_assoc_sync_pmtu(struct sock *sk, struct sctp_association *asoc)
/* Should we send a SACK to update our peer? */
static inline int sctp_peer_needs_update(struct sctp_association *asoc)
{
+ struct net *net = sock_net(asoc->base.sk);
switch (asoc->state) {
case SCTP_STATE_ESTABLISHED:
case SCTP_STATE_SHUTDOWN_PENDING:
@@ -1425,7 +1427,7 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc)
case SCTP_STATE_SHUTDOWN_SENT:
if ((asoc->rwnd > asoc->a_rwnd) &&
((asoc->rwnd - asoc->a_rwnd) >= max_t(__u32,
- (asoc->base.sk->sk_rcvbuf >> sctp_rwnd_upd_shift),
+ (asoc->base.sk->sk_rcvbuf >> net->sctp.rwnd_upd_shift),
asoc->pathmtu)))
return 1;
break;
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index bf81204..aaa6c12 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -392,13 +392,14 @@ nomem:
*/
int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp)
{
+ struct net *net = sock_net(asoc->base.sk);
struct sctp_auth_bytes *secret;
struct sctp_shared_key *ep_key;
/* If we don't support AUTH, or peer is not capable
* we don't need to do anything.
*/
- if (!sctp_auth_enable || !asoc->peer.auth_capable)
+ if (!net->sctp.auth_enable || !asoc->peer.auth_capable)
return 0;
/* If the key_id is non-zero and we couldn't find an
@@ -445,11 +446,12 @@ struct sctp_shared_key *sctp_auth_get_shkey(
*/
int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp)
{
+ struct net *net = sock_net(ep->base.sk);
struct crypto_hash *tfm = NULL;
__u16 id;
/* if the transforms are already allocted, we are done */
- if (!sctp_auth_enable) {
+ if (!net->sctp.auth_enable) {
ep->auth_hmacs = NULL;
return 0;
}
@@ -674,7 +676,12 @@ static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param)
/* Check if peer requested that this chunk is authenticated */
int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc)
{
- if (!sctp_auth_enable || !asoc || !asoc->peer.auth_capable)
+ struct net *net;
+ if (!asoc)
+ return 0;
+
+ net = sock_net(asoc->base.sk);
+ if (!net->sctp.auth_enable || !asoc->peer.auth_capable)
return 0;
return __sctp_auth_cid(chunk, asoc->peer.peer_chunks);
@@ -683,7 +690,12 @@ int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc)
/* Check if we requested that peer authenticate this chunk. */
int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc)
{
- if (!sctp_auth_enable || !asoc)
+ struct net *net;
+ if (!asoc)
+ return 0;
+
+ net = sock_net(asoc->base.sk);
+ if (!net->sctp.auth_enable);
return 0;
return __sctp_auth_cid(chunk,
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 23389ba..d886b3b 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -512,7 +512,7 @@ int sctp_in_scope(struct net *net, const union sctp_addr *addr, sctp_scope_t sco
* Address scoping can be selectively controlled via sysctl
* option
*/
- switch (sctp_scope_policy) {
+ switch (net->sctp.scope_policy) {
case SCTP_SCOPE_POLICY_DISABLE:
return 1;
case SCTP_SCOPE_POLICY_ENABLE:
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 8315792..1859e2b 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -65,6 +65,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
struct sock *sk,
gfp_t gfp)
{
+ struct net *net = sock_net(sk);
struct sctp_hmac_algo_param *auth_hmacs = NULL;
struct sctp_chunks_param *auth_chunks = NULL;
struct sctp_shared_key *null_key;
@@ -74,7 +75,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
if (!ep->digest)
return NULL;
- if (sctp_auth_enable) {
+ if (net->sctp.auth_enable) {
/* Allocate space for HMACS and CHUNKS authentication
* variables. There are arrays that we encode directly
* into parameters to make the rest of the operations easier.
@@ -106,7 +107,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
/* If the Add-IP functionality is enabled, we must
* authenticate, ASCONF and ASCONF-ACK chunks
*/
- if (sctp_addip_enable) {
+ if (net->sctp.addip_enable) {
auth_chunks->chunks[0] = SCTP_CID_ASCONF;
auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK;
auth_chunks->param_hdr.length =
@@ -140,14 +141,14 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
INIT_LIST_HEAD(&ep->asocs);
/* Use SCTP specific send buffer space queues. */
- ep->sndbuf_policy = sctp_sndbuf_policy;
+ ep->sndbuf_policy = net->sctp.sndbuf_policy;
sk->sk_data_ready = sctp_data_ready;
sk->sk_write_space = sctp_write_space;
sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
/* Get the receive buffer policy for this endpoint */
- ep->rcvbuf_policy = sctp_rcvbuf_policy;
+ ep->rcvbuf_policy = net->sctp.rcvbuf_policy;
/* Initialize the secret key used with cookie. */
get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE);
diff --git a/net/sctp/input.c b/net/sctp/input.c
index a2ceb70..25dfe73 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -1094,7 +1094,7 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
break;
case SCTP_CID_ASCONF:
- if (have_auth || sctp_addip_noauth)
+ if (have_auth || net->sctp.addip_noauth)
asoc = __sctp_rcv_asconf_lookup(
net, ch, laddr,
sctp_hdr(skb)->source,
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 85f87c3..657d263 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1169,6 +1169,70 @@ static int sctp_net_init(struct net *net)
{
int status;
+ /*
+ * 14. Suggested SCTP Protocol Parameter Values
+ */
+ /* The following protocol parameters are RECOMMENDED: */
+ /* RTO.Initial - 3 seconds */
+ net->sctp.rto_initial = SCTP_RTO_INITIAL;
+ /* RTO.Min - 1 second */
+ net->sctp.rto_min = SCTP_RTO_MIN;
+ /* RTO.Max - 60 seconds */
+ net->sctp.rto_max = SCTP_RTO_MAX;
+ /* RTO.Alpha - 1/8 */
+ net->sctp.rto_alpha = SCTP_RTO_ALPHA;
+ /* RTO.Beta - 1/4 */
+ net->sctp.rto_beta = SCTP_RTO_BETA;
+
+ /* Valid.Cookie.Life - 60 seconds */
+ net->sctp.valid_cookie_life = SCTP_DEFAULT_COOKIE_LIFE;
+
+ /* Whether Cookie Preservative is enabled(1) or not(0) */
+ net->sctp.cookie_preserve_enable = 1;
+
+ /* Max.Burst - 4 */
+ net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST;
+
+ /* Association.Max.Retrans - 10 attempts
+ * Path.Max.Retrans - 5 attempts (per destination address)
+ * Max.Init.Retransmits - 8 attempts
+ */
+ net->sctp.max_retrans_association = 10;
+ net->sctp.max_retrans_path = 5;
+ net->sctp.max_retrans_init = 8;
+
+ /* Sendbuffer growth - do per-socket accounting */
+ net->sctp.sndbuf_policy = 0;
+
+ /* Rcvbuffer growth - do per-socket accounting */
+ net->sctp.rcvbuf_policy = 0;
+
+ /* HB.interval - 30 seconds */
+ net->sctp.hb_interval = SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
+
+ /* delayed SACK timeout */
+ net->sctp.sack_timeout = SCTP_DEFAULT_TIMEOUT_SACK;
+
+ /* Disable ADDIP by default. */
+ net->sctp.addip_enable = 0;
+ net->sctp.addip_noauth = 0;
+ net->sctp.default_auto_asconf = 0;
+
+ /* Enable PR-SCTP by default. */
+ net->sctp.prsctp_enable = 1;
+
+ /* Disable AUTH by default. */
+ net->sctp.auth_enable = 0;
+
+ /* Set SCOPE policy to enabled */
+ net->sctp.scope_policy = SCTP_SCOPE_POLICY_ENABLE;
+
+ /* Set the default rwnd update threshold */
+ net->sctp.rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT;
+
+ /* Initialize maximum autoclose timeout. */
+ net->sctp.max_autoclose = INT_MAX / HZ;
+
status = sctp_sysctl_net_register(net);
if (status)
goto err_sysctl_register;
@@ -1270,59 +1334,12 @@ SCTP_STATIC __init int sctp_init(void)
/* Initialize object count debugging. */
sctp_dbg_objcnt_init();
- /*
- * 14. Suggested SCTP Protocol Parameter Values
- */
- /* The following protocol parameters are RECOMMENDED: */
- /* RTO.Initial - 3 seconds */
- sctp_rto_initial = SCTP_RTO_INITIAL;
- /* RTO.Min - 1 second */
- sctp_rto_min = SCTP_RTO_MIN;
- /* RTO.Max - 60 seconds */
- sctp_rto_max = SCTP_RTO_MAX;
- /* RTO.Alpha - 1/8 */
- sctp_rto_alpha = SCTP_RTO_ALPHA;
- /* RTO.Beta - 1/4 */
- sctp_rto_beta = SCTP_RTO_BETA;
-
- /* Valid.Cookie.Life - 60 seconds */
- sctp_valid_cookie_life = SCTP_DEFAULT_COOKIE_LIFE;
-
- /* Whether Cookie Preservative is enabled(1) or not(0) */
- sctp_cookie_preserve_enable = 1;
-
- /* Max.Burst - 4 */
- sctp_max_burst = SCTP_DEFAULT_MAX_BURST;
-
- /* Association.Max.Retrans - 10 attempts
- * Path.Max.Retrans - 5 attempts (per destination address)
- * Max.Init.Retransmits - 8 attempts
- */
- sctp_max_retrans_association = 10;
- sctp_max_retrans_path = 5;
- sctp_max_retrans_init = 8;
-
- /* Sendbuffer growth - do per-socket accounting */
- sctp_sndbuf_policy = 0;
-
- /* Rcvbuffer growth - do per-socket accounting */
- sctp_rcvbuf_policy = 0;
-
- /* HB.interval - 30 seconds */
- sctp_hb_interval = SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
-
- /* delayed SACK timeout */
- sctp_sack_timeout = SCTP_DEFAULT_TIMEOUT_SACK;
-
/* Implementation specific variables. */
/* Initialize default stream count setup information. */
sctp_max_instreams = SCTP_DEFAULT_INSTREAMS;
sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS;
- /* Initialize maximum autoclose timeout. */
- sctp_max_autoclose = INT_MAX / HZ;
-
/* Initialize handle used for association ids. */
idr_init(&sctp_assocs_id);
@@ -1409,23 +1426,6 @@ SCTP_STATIC __init int sctp_init(void)
pr_info("Hash tables configured (established %d bind %d)\n",
sctp_assoc_hashsize, sctp_port_hashsize);
- /* Disable ADDIP by default. */
- sctp_addip_enable = 0;
- sctp_addip_noauth = 0;
- sctp_default_auto_asconf = 0;
-
- /* Enable PR-SCTP by default. */
- sctp_prsctp_enable = 1;
-
- /* Disable AUTH by default. */
- sctp_auth_enable = 0;
-
- /* Set SCOPE policy to enabled */
- sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE;
-
- /* Set the default rwnd update threshold */
- sctp_rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT;
-
sctp_sysctl_register();
INIT_LIST_HEAD(&sctp_address_families);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index a4b096f..fbe1636 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -198,6 +198,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
const struct sctp_bind_addr *bp,
gfp_t gfp, int vparam_len)
{
+ struct net *net = sock_net(asoc->base.sk);
sctp_inithdr_t init;
union sctp_params addrs;
size_t chunksize;
@@ -237,7 +238,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
chunksize += WORD_ROUND(SCTP_SAT_LEN(num_types));
chunksize += sizeof(ecap_param);
- if (sctp_prsctp_enable)
+ if (net->sctp.prsctp_enable)
chunksize += sizeof(prsctp_param);
/* ADDIP: Section 4.2.7:
@@ -245,7 +246,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
* the ASCONF,the ASCONF-ACK, and the AUTH chunks in its INIT and
* INIT-ACK parameters.
*/
- if (sctp_addip_enable) {
+ if (net->sctp.addip_enable) {
extensions[num_ext] = SCTP_CID_ASCONF;
extensions[num_ext+1] = SCTP_CID_ASCONF_ACK;
num_ext += 2;
@@ -257,7 +258,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
chunksize += vparam_len;
/* Account for AUTH related parameters */
- if (sctp_auth_enable) {
+ if (net->sctp.auth_enable) {
/* Add random parameter length*/
chunksize += sizeof(asoc->c.auth_random);
@@ -331,7 +332,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
sctp_addto_param(retval, num_ext, extensions);
}
- if (sctp_prsctp_enable)
+ if (net->sctp.prsctp_enable)
sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
if (sp->adaptation_ind) {
@@ -342,7 +343,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
}
/* Add SCTP-AUTH chunks to the parameter list */
- if (sctp_auth_enable) {
+ if (net->sctp.auth_enable) {
sctp_addto_chunk(retval, sizeof(asoc->c.auth_random),
asoc->c.auth_random);
if (auth_hmacs)
@@ -1964,10 +1965,10 @@ static int sctp_verify_ext_param(struct net *net, union sctp_params param)
* only if ADD-IP is turned on and we are not backward-compatible
* mode.
*/
- if (sctp_addip_noauth)
+ if (net->sctp.addip_noauth)
return 1;
- if (sctp_addip_enable && !have_auth && have_asconf)
+ if (net->sctp.addip_enable && !have_auth && have_asconf)
return 0;
return 1;
@@ -1976,13 +1977,14 @@ static int sctp_verify_ext_param(struct net *net, union sctp_params param)
static void sctp_process_ext_param(struct sctp_association *asoc,
union sctp_params param)
{
+ struct net *net = sock_net(asoc->base.sk);
__u16 num_ext = ntohs(param.p->length) - sizeof(sctp_paramhdr_t);
int i;
for (i = 0; i < num_ext; i++) {
switch (param.ext->chunks[i]) {
case SCTP_CID_FWD_TSN:
- if (sctp_prsctp_enable &&
+ if (net->sctp.prsctp_enable &&
!asoc->peer.prsctp_capable)
asoc->peer.prsctp_capable = 1;
break;
@@ -1990,12 +1992,12 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
/* if the peer reports AUTH, assume that he
* supports AUTH.
*/
- if (sctp_auth_enable)
+ if (net->sctp.auth_enable)
asoc->peer.auth_capable = 1;
break;
case SCTP_CID_ASCONF:
case SCTP_CID_ASCONF_ACK:
- if (sctp_addip_enable)
+ if (net->sctp.addip_enable)
asoc->peer.asconf_capable = 1;
break;
default:
@@ -2116,7 +2118,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net,
break;
case SCTP_PARAM_SET_PRIMARY:
- if (sctp_addip_enable)
+ if (net->sctp.addip_enable)
break;
goto fallthrough;
@@ -2127,12 +2129,12 @@ static sctp_ierror_t sctp_verify_param(struct net *net,
break;
case SCTP_PARAM_FWD_TSN_SUPPORT:
- if (sctp_prsctp_enable)
+ if (net->sctp.prsctp_enable)
break;
goto fallthrough;
case SCTP_PARAM_RANDOM:
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
goto fallthrough;
/* SCTP-AUTH: Secion 6.1
@@ -2149,7 +2151,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net,
break;
case SCTP_PARAM_CHUNKS:
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
goto fallthrough;
/* SCTP-AUTH: Section 3.2
@@ -2165,7 +2167,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net,
break;
case SCTP_PARAM_HMAC_ALGO:
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
goto fallthrough;
hmacs = (struct sctp_hmac_algo_param *)param.p;
@@ -2271,6 +2273,7 @@ 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)
{
+ struct net *net = sock_net(asoc->base.sk);
union sctp_params param;
struct sctp_transport *transport;
struct list_head *pos, *temp;
@@ -2327,7 +2330,7 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk,
* also give us an option to silently ignore the packet, which
* is what we'll do here.
*/
- if (!sctp_addip_noauth &&
+ if (!net->sctp.addip_noauth &&
(asoc->peer.asconf_capable && !asoc->peer.auth_capable)) {
asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP |
SCTP_PARAM_DEL_IP |
@@ -2502,7 +2505,7 @@ do_addr_param:
break;
case SCTP_PARAM_COOKIE_PRESERVATIVE:
- if (!sctp_cookie_preserve_enable)
+ if (!net->sctp.cookie_preserve_enable)
break;
stale = ntohl(param.life->lifespan_increment);
@@ -2582,7 +2585,7 @@ do_addr_param:
break;
case SCTP_PARAM_SET_PRIMARY:
- if (!sctp_addip_enable)
+ if (!net->sctp.addip_enable)
goto fall_through;
addr_param = param.v + sizeof(sctp_addip_param_t);
@@ -2609,7 +2612,7 @@ do_addr_param:
break;
case SCTP_PARAM_FWD_TSN_SUPPORT:
- if (sctp_prsctp_enable) {
+ if (net->sctp.prsctp_enable) {
asoc->peer.prsctp_capable = 1;
break;
}
@@ -2617,7 +2620,7 @@ do_addr_param:
goto fall_through;
case SCTP_PARAM_RANDOM:
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
goto fall_through;
/* Save peer's random parameter */
@@ -2630,7 +2633,7 @@ do_addr_param:
break;
case SCTP_PARAM_HMAC_ALGO:
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
goto fall_through;
/* Save peer's HMAC list */
@@ -2646,7 +2649,7 @@ do_addr_param:
break;
case SCTP_PARAM_CHUNKS:
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
goto fall_through;
asoc->peer.peer_chunks = kmemdup(param.p,
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 3722af2..ace721d 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3586,7 +3586,7 @@ sctp_disposition_t sctp_sf_do_asconf(struct net *net,
* is received unauthenticated it MUST be silently discarded as
* described in [I-D.ietf-tsvwg-sctp-auth].
*/
- if (!sctp_addip_noauth && !chunk->auth)
+ if (!net->sctp.addip_noauth && !chunk->auth)
return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
/* Make sure that the ASCONF ADDIP chunk has a valid length. */
@@ -3713,7 +3713,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(struct net *net,
* is received unauthenticated it MUST be silently discarded as
* described in [I-D.ietf-tsvwg-sctp-auth].
*/
- if (!sctp_addip_noauth && !asconf_ack->auth)
+ if (!net->sctp.addip_noauth && !asconf_ack->auth)
return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
/* Make sure that the ADDIP chunk has a valid length. */
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 4a029d7..84d98d8 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -918,12 +918,12 @@ static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(struct net *net,
if (cid <= SCTP_CID_BASE_MAX)
return &chunk_event_table[cid][state];
- if (sctp_prsctp_enable) {
+ if (net->sctp.prsctp_enable) {
if (cid == SCTP_CID_FWD_TSN)
return &prsctp_chunk_event_table[0][state];
}
- if (sctp_addip_enable) {
+ if (net->sctp.addip_enable) {
if (cid == SCTP_CID_ASCONF)
return &addip_chunk_event_table[0][state];
@@ -931,7 +931,7 @@ static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(struct net *net,
return &addip_chunk_event_table[1][state];
}
- if (sctp_auth_enable) {
+ if (net->sctp.auth_enable) {
if (cid == SCTP_CID_AUTH)
return &auth_chunk_event_table[0][state];
}
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index a6a4226..d37d24f 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -516,6 +516,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
struct sockaddr *addrs,
int addrcnt)
{
+ struct net *net = sock_net(sk);
struct sctp_sock *sp;
struct sctp_endpoint *ep;
struct sctp_association *asoc;
@@ -530,7 +531,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
int i;
int retval = 0;
- if (!sctp_addip_enable)
+ if (!net->sctp.addip_enable)
return retval;
sp = sctp_sk(sk);
@@ -718,6 +719,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
struct sockaddr *addrs,
int addrcnt)
{
+ struct net *net = sock_net(sk);
struct sctp_sock *sp;
struct sctp_endpoint *ep;
struct sctp_association *asoc;
@@ -733,7 +735,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
int stored = 0;
chunk = NULL;
- if (!sctp_addip_enable)
+ if (!net->sctp.addip_enable)
return retval;
sp = sctp_sk(sk);
@@ -3039,6 +3041,7 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optval,
unsigned int optlen)
{
+ struct net *net = sock_net(sk);
struct sctp_sock *sp;
struct sctp_association *asoc = NULL;
struct sctp_setpeerprim prim;
@@ -3048,7 +3051,7 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
sp = sctp_sk(sk);
- if (!sctp_addip_enable)
+ if (!net->sctp.addip_enable)
return -EPERM;
if (optlen != sizeof(struct sctp_setpeerprim))
@@ -3285,9 +3288,10 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk,
char __user *optval,
unsigned int optlen)
{
+ struct net *net = sock_net(sk);
struct sctp_authchunk val;
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
return -EACCES;
if (optlen != sizeof(struct sctp_authchunk))
@@ -3317,11 +3321,12 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk,
char __user *optval,
unsigned int optlen)
{
+ struct net *net = sock_net(sk);
struct sctp_hmacalgo *hmacs;
u32 idents;
int err;
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
return -EACCES;
if (optlen < sizeof(struct sctp_hmacalgo))
@@ -3354,11 +3359,12 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
char __user *optval,
unsigned int optlen)
{
+ struct net *net = sock_net(sk);
struct sctp_authkey *authkey;
struct sctp_association *asoc;
int ret;
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
return -EACCES;
if (optlen <= sizeof(struct sctp_authkey))
@@ -3395,10 +3401,11 @@ static int sctp_setsockopt_active_key(struct sock *sk,
char __user *optval,
unsigned int optlen)
{
+ struct net *net = sock_net(sk);
struct sctp_authkeyid val;
struct sctp_association *asoc;
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
return -EACCES;
if (optlen != sizeof(struct sctp_authkeyid))
@@ -3423,10 +3430,11 @@ static int sctp_setsockopt_del_key(struct sock *sk,
char __user *optval,
unsigned int optlen)
{
+ struct net *net = sock_net(sk);
struct sctp_authkeyid val;
struct sctp_association *asoc;
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
return -EACCES;
if (optlen != sizeof(struct sctp_authkeyid))
@@ -3849,6 +3857,7 @@ out:
*/
SCTP_STATIC int sctp_init_sock(struct sock *sk)
{
+ struct net *net = sock_net(sk);
struct sctp_endpoint *ep;
struct sctp_sock *sp;
@@ -3878,7 +3887,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
sp->default_timetolive = 0;
sp->default_rcv_context = 0;
- sp->max_burst = sctp_max_burst;
+ sp->max_burst = net->sctp.max_burst;
/* Initialize default setup parameters. These parameters
* can be modified with the SCTP_INITMSG socket option or
@@ -3886,24 +3895,24 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
*/
sp->initmsg.sinit_num_ostreams = sctp_max_outstreams;
sp->initmsg.sinit_max_instreams = sctp_max_instreams;
- sp->initmsg.sinit_max_attempts = sctp_max_retrans_init;
- sp->initmsg.sinit_max_init_timeo = sctp_rto_max;
+ sp->initmsg.sinit_max_attempts = net->sctp.max_retrans_init;
+ sp->initmsg.sinit_max_init_timeo = net->sctp.rto_max;
/* Initialize default RTO related parameters. These parameters can
* be modified for with the SCTP_RTOINFO socket option.
*/
- sp->rtoinfo.srto_initial = sctp_rto_initial;
- sp->rtoinfo.srto_max = sctp_rto_max;
- sp->rtoinfo.srto_min = sctp_rto_min;
+ sp->rtoinfo.srto_initial = net->sctp.rto_initial;
+ sp->rtoinfo.srto_max = net->sctp.rto_max;
+ sp->rtoinfo.srto_min = net->sctp.rto_min;
/* Initialize default association related parameters. These parameters
* can be modified with the SCTP_ASSOCINFO socket option.
*/
- sp->assocparams.sasoc_asocmaxrxt = sctp_max_retrans_association;
+ sp->assocparams.sasoc_asocmaxrxt = net->sctp.max_retrans_association;
sp->assocparams.sasoc_number_peer_destinations = 0;
sp->assocparams.sasoc_peer_rwnd = 0;
sp->assocparams.sasoc_local_rwnd = 0;
- sp->assocparams.sasoc_cookie_life = sctp_valid_cookie_life;
+ sp->assocparams.sasoc_cookie_life = net->sctp.valid_cookie_life;
/* Initialize default event subscriptions. By default, all the
* options are off.
@@ -3913,10 +3922,10 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
/* Default Peer Address Parameters. These defaults can
* be modified via SCTP_PEER_ADDR_PARAMS
*/
- sp->hbinterval = sctp_hb_interval;
- sp->pathmaxrxt = sctp_max_retrans_path;
+ sp->hbinterval = net->sctp.hb_interval;
+ sp->pathmaxrxt = net->sctp.max_retrans_path;
sp->pathmtu = 0; // allow default discovery
- sp->sackdelay = sctp_sack_timeout;
+ sp->sackdelay = net->sctp.sack_timeout;
sp->sackfreq = 2;
sp->param_flags = SPP_HB_ENABLE |
SPP_PMTUD_ENABLE |
@@ -3967,10 +3976,10 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
local_bh_disable();
percpu_counter_inc(&sctp_sockets_allocated);
- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
- if (sctp_default_auto_asconf) {
+ sock_prot_inuse_add(net, sk->sk_prot, 1);
+ if (net->sctp.default_auto_asconf) {
list_add_tail(&sp->auto_asconf_list,
- &sock_net(sk)->sctp.auto_asconf_splist);
+ &net->sctp.auto_asconf_splist);
sp->do_auto_asconf = 1;
} else
sp->do_auto_asconf = 0;
@@ -5307,12 +5316,13 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len,
static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
char __user *optval, int __user *optlen)
{
+ struct net *net = sock_net(sk);
struct sctp_hmacalgo __user *p = (void __user *)optval;
struct sctp_hmac_algo_param *hmacs;
__u16 data_len = 0;
u32 num_idents;
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
return -EACCES;
hmacs = sctp_sk(sk)->ep->auth_hmacs_list;
@@ -5336,10 +5346,11 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
static int sctp_getsockopt_active_key(struct sock *sk, int len,
char __user *optval, int __user *optlen)
{
+ struct net *net = sock_net(sk);
struct sctp_authkeyid val;
struct sctp_association *asoc;
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
return -EACCES;
if (len < sizeof(struct sctp_authkeyid))
@@ -5368,6 +5379,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
char __user *optval, int __user *optlen)
{
+ struct net *net = sock_net(sk);
struct sctp_authchunks __user *p = (void __user *)optval;
struct sctp_authchunks val;
struct sctp_association *asoc;
@@ -5375,7 +5387,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
u32 num_chunks = 0;
char __user *to;
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
return -EACCES;
if (len < sizeof(struct sctp_authchunks))
@@ -5411,6 +5423,7 @@ num:
static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
char __user *optval, int __user *optlen)
{
+ struct net *net = sock_net(sk);
struct sctp_authchunks __user *p = (void __user *)optval;
struct sctp_authchunks val;
struct sctp_association *asoc;
@@ -5418,7 +5431,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
u32 num_chunks = 0;
char __user *to;
- if (!sctp_auth_enable)
+ if (!net->sctp.auth_enable)
return -EACCES;
if (len < sizeof(struct sctp_authchunks))
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 7528d59..22568f4 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -64,8 +64,34 @@ extern int sysctl_sctp_wmem[3];
static ctl_table sctp_table[] = {
{
+ .procname = "sctp_mem",
+ .data = &sysctl_sctp_mem,
+ .maxlen = sizeof(sysctl_sctp_mem),
+ .mode = 0644,
+ .proc_handler = proc_doulongvec_minmax
+ },
+ {
+ .procname = "sctp_rmem",
+ .data = &sysctl_sctp_rmem,
+ .maxlen = sizeof(sysctl_sctp_rmem),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
+ .procname = "sctp_wmem",
+ .data = &sysctl_sctp_wmem,
+ .maxlen = sizeof(sysctl_sctp_wmem),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+
+ { /* sentinel */ }
+};
+
+static ctl_table sctp_net_table[] = {
+ {
.procname = "rto_initial",
- .data = &sctp_rto_initial,
+ .data = &init_net.sctp.rto_initial,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
@@ -74,7 +100,7 @@ static ctl_table sctp_table[] = {
},
{
.procname = "rto_min",
- .data = &sctp_rto_min,
+ .data = &init_net.sctp.rto_min,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
@@ -83,7 +109,7 @@ static ctl_table sctp_table[] = {
},
{
.procname = "rto_max",
- .data = &sctp_rto_max,
+ .data = &init_net.sctp.rto_max,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
@@ -91,17 +117,22 @@ static ctl_table sctp_table[] = {
.extra2 = &timer_max
},
{
- .procname = "valid_cookie_life",
- .data = &sctp_valid_cookie_life,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = proc_dointvec_minmax,
- .extra1 = &one,
- .extra2 = &timer_max
+ .procname = "rto_alpha_exp_divisor",
+ .data = &init_net.sctp.rto_alpha,
+ .maxlen = sizeof(int),
+ .mode = 0444,
+ .proc_handler = proc_dointvec,
+ },
+ {
+ .procname = "rto_beta_exp_divisor",
+ .data = &init_net.sctp.rto_beta,
+ .maxlen = sizeof(int),
+ .mode = 0444,
+ .proc_handler = proc_dointvec,
},
{
.procname = "max_burst",
- .data = &sctp_max_burst,
+ .data = &init_net.sctp.max_burst,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
@@ -109,31 +140,42 @@ static ctl_table sctp_table[] = {
.extra2 = &int_max
},
{
- .procname = "association_max_retrans",
- .data = &sctp_max_retrans_association,
+ .procname = "cookie_preserve_enable",
+ .data = &init_net.sctp.cookie_preserve_enable,
.maxlen = sizeof(int),
.mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
+ .procname = "valid_cookie_life",
+ .data = &init_net.sctp.valid_cookie_life,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
.proc_handler = proc_dointvec_minmax,
- .extra1 = &one,
- .extra2 = &int_max
+ .extra1 = &one,
+ .extra2 = &timer_max
},
{
- .procname = "sndbuf_policy",
- .data = &sctp_sndbuf_policy,
+ .procname = "sack_timeout",
+ .data = &init_net.sctp.sack_timeout,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &sack_timer_min,
+ .extra2 = &sack_timer_max,
},
{
- .procname = "rcvbuf_policy",
- .data = &sctp_rcvbuf_policy,
- .maxlen = sizeof(int),
+ .procname = "hb_interval",
+ .data = &init_net.sctp.hb_interval,
+ .maxlen = sizeof(unsigned int),
.mode = 0644,
- .proc_handler = proc_dointvec,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &one,
+ .extra2 = &timer_max
},
{
- .procname = "path_max_retrans",
- .data = &sctp_max_retrans_path,
+ .procname = "association_max_retrans",
+ .data = &init_net.sctp.max_retrans_association,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
@@ -141,17 +183,17 @@ static ctl_table sctp_table[] = {
.extra2 = &int_max
},
{
- .procname = "pf_retrans",
- .data = &sctp_pf_retrans,
+ .procname = "path_max_retrans",
+ .data = &init_net.sctp.max_retrans_path,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
- .extra1 = &zero,
+ .extra1 = &one,
.extra2 = &int_max
},
{
.procname = "max_init_retransmits",
- .data = &sctp_max_retrans_init,
+ .data = &init_net.sctp.max_retrans_init,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
@@ -159,103 +201,66 @@ static ctl_table sctp_table[] = {
.extra2 = &int_max
},
{
- .procname = "hb_interval",
- .data = &sctp_hb_interval,
- .maxlen = sizeof(unsigned int),
+ .procname = "pf_retrans",
+ .data = &init_net.sctp.pf_retrans,
+ .maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
- .extra1 = &one,
- .extra2 = &timer_max
+ .extra1 = &zero,
+ .extra2 = &int_max
},
{
- .procname = "cookie_preserve_enable",
- .data = &sctp_cookie_preserve_enable,
+ .procname = "sndbuf_policy",
+ .data = &init_net.sctp.sndbuf_policy,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
- .procname = "rto_alpha_exp_divisor",
- .data = &sctp_rto_alpha,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = proc_dointvec,
- },
- {
- .procname = "rto_beta_exp_divisor",
- .data = &sctp_rto_beta,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = proc_dointvec,
- },
- {
- .procname = "addip_enable",
- .data = &sctp_addip_enable,
+ .procname = "rcvbuf_policy",
+ .data = &init_net.sctp.rcvbuf_policy,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "default_auto_asconf",
- .data = &sctp_default_auto_asconf,
+ .data = &init_net.sctp.default_auto_asconf,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
- .procname = "prsctp_enable",
- .data = &sctp_prsctp_enable,
+ .procname = "addip_enable",
+ .data = &init_net.sctp.addip_enable,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
- .procname = "sack_timeout",
- .data = &sctp_sack_timeout,
+ .procname = "addip_noauth_enable",
+ .data = &init_net.sctp.addip_noauth,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec_minmax,
- .extra1 = &sack_timer_min,
- .extra2 = &sack_timer_max,
- },
- {
- .procname = "sctp_mem",
- .data = &sysctl_sctp_mem,
- .maxlen = sizeof(sysctl_sctp_mem),
- .mode = 0644,
- .proc_handler = proc_doulongvec_minmax
- },
- {
- .procname = "sctp_rmem",
- .data = &sysctl_sctp_rmem,
- .maxlen = sizeof(sysctl_sctp_rmem),
- .mode = 0644,
.proc_handler = proc_dointvec,
},
{
- .procname = "sctp_wmem",
- .data = &sysctl_sctp_wmem,
- .maxlen = sizeof(sysctl_sctp_wmem),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- {
- .procname = "auth_enable",
- .data = &sctp_auth_enable,
+ .procname = "prsctp_enable",
+ .data = &init_net.sctp.prsctp_enable,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
- .procname = "addip_noauth_enable",
- .data = &sctp_addip_noauth,
+ .procname = "auth_enable",
+ .data = &init_net.sctp.auth_enable,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "addr_scope_policy",
- .data = &sctp_scope_policy,
+ .data = &init_net.sctp.scope_policy,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
@@ -264,7 +269,7 @@ static ctl_table sctp_table[] = {
},
{
.procname = "rwnd_update_shift",
- .data = &sctp_rwnd_upd_shift,
+ .data = &init_net.sctp.rwnd_upd_shift,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
@@ -273,7 +278,7 @@ static ctl_table sctp_table[] = {
},
{
.procname = "max_autoclose",
- .data = &sctp_max_autoclose,
+ .data = &init_net.sctp.max_autoclose,
.maxlen = sizeof(unsigned long),
.mode = 0644,
.proc_handler = &proc_doulongvec_minmax,
@@ -281,21 +286,21 @@ static ctl_table sctp_table[] = {
.extra2 = &max_autoclose_max,
},
- { /* sentinel */ }
-};
-
-static ctl_table sctp_net_table[] = {
{ /* sentinel */ }
};
int sctp_sysctl_net_register(struct net *net)
{
struct ctl_table *table;
+ int i;
table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
if (!table)
return -ENOMEM;
+ for (i = 0; table[i].data; i++)
+ table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp;
+
net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table);
return 0;
}
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index aada963..953c21e 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -77,7 +77,7 @@ static struct sctp_transport *sctp_transport_init(struct net *net,
* given destination transport address, set RTO to the protocol
* parameter 'RTO.Initial'.
*/
- peer->rto = msecs_to_jiffies(sctp_rto_initial);
+ peer->rto = msecs_to_jiffies(net->sctp.rto_initial);
peer->last_time_heard = jiffies;
peer->last_time_ecne_reduced = jiffies;
@@ -87,8 +87,8 @@ static struct sctp_transport *sctp_transport_init(struct net *net,
SPP_SACKDELAY_ENABLE;
/* Initialize the default path max_retrans. */
- peer->pathmaxrxt = sctp_max_retrans_path;
- peer->pf_retrans = sctp_pf_retrans;
+ peer->pathmaxrxt = net->sctp.max_retrans_path;
+ peer->pf_retrans = net->sctp.pf_retrans;
INIT_LIST_HEAD(&peer->transmitted);
INIT_LIST_HEAD(&peer->send_ready);
@@ -318,6 +318,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
SCTP_ASSERT(tp->rto_pending, "rto_pending not set", return);
if (tp->rttvar || tp->srtt) {
+ struct net *net = sock_net(tp->asoc->base.sk);
/* 6.3.1 C3) When a new RTT measurement R' is made, set
* RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'|
* SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R'
@@ -329,10 +330,10 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
* For example, assuming the default value of RTO.Alpha of
* 1/8, rto_alpha would be expressed as 3.
*/
- tp->rttvar = tp->rttvar - (tp->rttvar >> sctp_rto_beta)
- + ((abs(tp->srtt - rtt)) >> sctp_rto_beta);
- tp->srtt = tp->srtt - (tp->srtt >> sctp_rto_alpha)
- + (rtt >> sctp_rto_alpha);
+ tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta)
+ + ((abs(tp->srtt - rtt)) >> net->sctp.rto_beta);
+ tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha)
+ + (rtt >> net->sctp.rto_alpha);
} else {
/* 6.3.1 C2) When the first RTT measurement R is made, set
* SRTT <- R, RTTVAR <- R/2.
--
1.7.5.4
From: [email protected] (Eric W. Biederman)
Date: Tue, 07 Aug 2012 10:17:02 -0700
> Since I am motivated to get things done, and since there has been much
> grumbling about my patches not implementing tunables, I have added
> tunable support on top of my last patchset.
>
> I have performed basic testing on the these patches and nothing
> appears amis.
>
> The sm statemachine is a major tease as it has all of these association
> and endpoint pointers in the common set of function parameters that turn
> out to be NULL at the most inconvinient times. So I added to the common
> parameter list a struct net pointer, that is never NULL.
I like Eric's patch set and I'd like to apply it to net-next.
Vlad?
On 08/09/2012 02:20 AM, David Miller wrote:
> From: [email protected] (Eric W. Biederman)
> Date: Tue, 07 Aug 2012 10:17:02 -0700
>
>> Since I am motivated to get things done, and since there has been much
>> grumbling about my patches not implementing tunables, I have added
>> tunable support on top of my last patchset.
>>
>> I have performed basic testing on the these patches and nothing
>> appears amis.
>>
>> The sm statemachine is a major tease as it has all of these association
>> and endpoint pointers in the common set of function parameters that turn
>> out to be NULL at the most inconvinient times. So I added to the common
>> parameter list a struct net pointer, that is never NULL.
>
> I like Eric's patch set and I'd like to apply it to net-next.
>
> Vlad?
>
I like these patches much more as well, but not done reviewing yet.
I'll try to finish the review tonight
-vlad
Come on Vlad, please review this stuff some time this century. If you
want inclusion to be dependent upon your review, then the onus is on
you to review it in a timely manner. And you are not doing so here.
I'm not letting Eric's patches rot in patchwork for more than a week,
this is completely unacceptable.
On 08/14/2012 05:14 PM, David Miller wrote:
>
> Come on Vlad, please review this stuff some time this century. If you
> want inclusion to be dependent upon your review, then the onus is on
> you to review it in a timely manner. And you are not doing so here.
>
> I'm not letting Eric's patches rot in patchwork for more than a week,
> this is completely unacceptable.
>
I swear I sent an ACK 2 days ago, but I now see it sitting in my draft
folder. My bad. I'll go now and dust off the ACK...
-vlad
On 08/06/2012 02:39 PM, Eric W. Biederman wrote:
>
> - Add struct net into the port hash table hash calculation
> - Add struct net inot the struct sctp_bind_bucket so there
> is a memory of which network namespace a port is allocated in.
> No need for a ref count because sctp_bind_bucket only exists
> when there are sockets in the hash table and sockets can not
> change their network namspace, and sockets already ref count
> their network namespace.
> - Add struct net into the key comparison when we are testing
> to see if we have found the port hash table entry we are
> looking for.
>
> With these changes lookups in the port hash table becomes
> safe to use in multiple network namespaces.
>
> Signed-off-by: "Eric W. Biederman" <[email protected]>
Acked-by: Vlad Yasevich <[email protected]>
> ---
> include/net/sctp/sctp.h | 4 ++--
> include/net/sctp/structs.h | 1 +
> net/sctp/socket.c | 22 +++++++++++++---------
> 3 files changed, 16 insertions(+), 11 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index ff49964..7c05040 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -632,9 +632,9 @@ static inline int sctp_sanity_check(void)
>
> /* Warning: The following hash functions assume a power of two 'size'. */
> /* This is the hash function for the SCTP port hash table. */
> -static inline int sctp_phashfn(__u16 lport)
> +static inline int sctp_phashfn(struct net *net, __u16 lport)
> {
> - return lport & (sctp_port_hashsize - 1);
> + return (net_hash_mix(net) + lport) & (sctp_port_hashsize - 1);
> }
>
> /* This is the hash function for the endpoint hash table. */
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index fc5e600..c089bb1 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -102,6 +102,7 @@ struct sctp_bind_bucket {
> unsigned short fastreuse;
> struct hlist_node node;
> struct hlist_head owner;
> + struct net *net;
> };
>
> struct sctp_bind_hashbucket {
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 5e25981..4316b0f 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -5769,7 +5769,7 @@ static void sctp_unhash(struct sock *sk)
> * a fastreuse flag (FIXME: NPI ipg).
> */
> static struct sctp_bind_bucket *sctp_bucket_create(
> - struct sctp_bind_hashbucket *head, unsigned short snum);
> + struct sctp_bind_hashbucket *head, struct net *, unsigned short snum);
>
> static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
> {
> @@ -5799,11 +5799,12 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
> rover = low;
> if (inet_is_reserved_local_port(rover))
> continue;
> - index = sctp_phashfn(rover);
> + index = sctp_phashfn(sock_net(sk), rover);
> head = &sctp_port_hashtable[index];
> sctp_spin_lock(&head->lock);
> sctp_for_each_hentry(pp, node, &head->chain)
> - if (pp->port == rover)
> + if ((pp->port == rover) &&
> + net_eq(sock_net(sk), pp->net))
> goto next;
> break;
> next:
> @@ -5827,10 +5828,10 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
> * to the port number (snum) - we detect that with the
> * port iterator, pp being NULL.
> */
> - head = &sctp_port_hashtable[sctp_phashfn(snum)];
> + head = &sctp_port_hashtable[sctp_phashfn(sock_net(sk), snum)];
> sctp_spin_lock(&head->lock);
> sctp_for_each_hentry(pp, node, &head->chain) {
> - if (pp->port == snum)
> + if ((pp->port == snum) && net_eq(pp->net, sock_net(sk)))
> goto pp_found;
> }
> }
> @@ -5881,7 +5882,7 @@ pp_found:
> pp_not_found:
> /* If there was a hash table miss, create a new port. */
> ret = 1;
> - if (!pp && !(pp = sctp_bucket_create(head, snum)))
> + if (!pp && !(pp = sctp_bucket_create(head, sock_net(sk), snum)))
> goto fail_unlock;
>
> /* In either case (hit or miss), make sure fastreuse is 1 only
> @@ -6113,7 +6114,7 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
> ********************************************************************/
>
> static struct sctp_bind_bucket *sctp_bucket_create(
> - struct sctp_bind_hashbucket *head, unsigned short snum)
> + struct sctp_bind_hashbucket *head, struct net *net, unsigned short snum)
> {
> struct sctp_bind_bucket *pp;
>
> @@ -6123,6 +6124,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
> pp->port = snum;
> pp->fastreuse = 0;
> INIT_HLIST_HEAD(&pp->owner);
> + pp->net = net;
> hlist_add_head(&pp->node, &head->chain);
> }
> return pp;
> @@ -6142,7 +6144,8 @@ static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
> static inline void __sctp_put_port(struct sock *sk)
> {
> struct sctp_bind_hashbucket *head =
> - &sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->inet_num)];
> + &sctp_port_hashtable[sctp_phashfn(sock_net(sk),
> + inet_sk(sk)->inet_num)];
> struct sctp_bind_bucket *pp;
>
> sctp_spin_lock(&head->lock);
> @@ -6809,7 +6812,8 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
> newsp->hmac = NULL;
>
> /* Hook this new socket in to the bind_hash list. */
> - head = &sctp_port_hashtable[sctp_phashfn(inet_sk(oldsk)->inet_num)];
> + head = &sctp_port_hashtable[sctp_phashfn(sock_net(oldsk),
> + inet_sk(oldsk)->inet_num)];
> sctp_local_bh_disable();
> sctp_spin_lock(&head->lock);
> pp = sctp_sk(oldsk)->bind_hash;
>
On 08/06/2012 02:40 PM, Eric W. Biederman wrote:
>
> - Use struct net in the hash calculation
> - Use sock_net(endpoint.base.sk) in the endpoint lookups.
> - On receive calculate the network namespace from skb->dev.
>
> Signed-off-by: "Eric W. Biederman" <[email protected]>
Acked-by: Vlad Yasevich <[email protected]>
> ---
> include/net/sctp/sctp.h | 4 ++--
> include/net/sctp/structs.h | 2 +-
> net/sctp/endpointola.c | 4 +++-
> net/sctp/input.c | 19 ++++++++++++-------
> 4 files changed, 18 insertions(+), 11 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 7c05040..87b119f 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -638,9 +638,9 @@ static inline int sctp_phashfn(struct net *net, __u16 lport)
> }
>
> /* This is the hash function for the endpoint hash table. */
> -static inline int sctp_ep_hashfn(__u16 lport)
> +static inline int sctp_ep_hashfn(struct net *net, __u16 lport)
> {
> - return lport & (sctp_ep_hashsize - 1);
> + return (net_hash_mix(net) + lport) & (sctp_ep_hashsize - 1);
> }
>
> /* This is the hash function for the association hash table. */
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index c089bb1..9f9de55 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -1426,7 +1426,7 @@ struct sctp_association *sctp_endpoint_lookup_assoc(
> int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
> const union sctp_addr *);
> struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
> - const union sctp_addr *);
> + struct net *, const union sctp_addr *);
> int sctp_has_association(const union sctp_addr *laddr,
> const union sctp_addr *paddr);
>
> diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
> index 68a385d..50c87b4 100644
> --- a/net/sctp/endpointola.c
> +++ b/net/sctp/endpointola.c
> @@ -302,11 +302,13 @@ void sctp_endpoint_put(struct sctp_endpoint *ep)
>
> /* Is this the endpoint we are looking for? */
> struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
> + struct net *net,
> const union sctp_addr *laddr)
> {
> struct sctp_endpoint *retval = NULL;
>
> - if (htons(ep->base.bind_addr.port) == laddr->v4.sin_port) {
> + if ((htons(ep->base.bind_addr.port) == laddr->v4.sin_port) &&
> + net_eq(sock_net(ep->base.sk), net)) {
> if (sctp_bind_addr_match(&ep->base.bind_addr, laddr,
> sctp_sk(ep->base.sk)))
> retval = ep;
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index e64d521..c0ca893 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -70,7 +70,8 @@ static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
> const union sctp_addr *laddr,
> const union sctp_addr *paddr,
> struct sctp_transport **transportp);
> -static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
> +static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
> + const union sctp_addr *laddr);
> static struct sctp_association *__sctp_lookup_association(
> const union sctp_addr *local,
> const union sctp_addr *peer,
> @@ -129,6 +130,7 @@ int sctp_rcv(struct sk_buff *skb)
> union sctp_addr dest;
> int family;
> struct sctp_af *af;
> + struct net *net = dev_net(skb->dev);
>
> if (skb->pkt_type!=PACKET_HOST)
> goto discard_it;
> @@ -181,7 +183,7 @@ int sctp_rcv(struct sk_buff *skb)
> asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
>
> if (!asoc)
> - ep = __sctp_rcv_lookup_endpoint(&dest);
> + ep = __sctp_rcv_lookup_endpoint(net, &dest);
>
> /* Retrieve the common input handling substructure. */
> rcvr = asoc ? &asoc->base : &ep->base;
> @@ -723,12 +725,13 @@ discard:
> /* Insert endpoint into the hash table. */
> static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
> {
> + struct net *net = sock_net(ep->base.sk);
> struct sctp_ep_common *epb;
> struct sctp_hashbucket *head;
>
> epb = &ep->base;
>
> - epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
> + epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port);
> head = &sctp_ep_hashtable[epb->hashent];
>
> sctp_write_lock(&head->lock);
> @@ -747,12 +750,13 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep)
> /* Remove endpoint from the hash table. */
> static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
> {
> + struct net *net = sock_net(ep->base.sk);
> struct sctp_hashbucket *head;
> struct sctp_ep_common *epb;
>
> epb = &ep->base;
>
> - epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
> + epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port);
>
> head = &sctp_ep_hashtable[epb->hashent];
>
> @@ -770,7 +774,8 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
> }
>
> /* Look up an endpoint. */
> -static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
> +static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
> + const union sctp_addr *laddr)
> {
> struct sctp_hashbucket *head;
> struct sctp_ep_common *epb;
> @@ -778,12 +783,12 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
> struct hlist_node *node;
> int hash;
>
> - hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port));
> + hash = sctp_ep_hashfn(net, ntohs(laddr->v4.sin_port));
> head = &sctp_ep_hashtable[hash];
> read_lock(&head->lock);
> sctp_for_each_hentry(epb, node, &head->chain) {
> ep = sctp_ep(epb);
> - if (sctp_endpoint_is_match(ep, laddr))
> + if (sctp_endpoint_is_match(ep, net, laddr))
> goto hit;
> }
>
>
On 08/06/2012 02:41 PM, Eric W. Biederman wrote:
>
> - Use struct net in the hash calculation
> - Use sock_net(association.base.sk) in the association lookups.
> - On receive calculate the network namespace from skb->dev.
> - Pass struct net from receive down to the functions that actually
> do the association lookup.
>
> Signed-off-by: "Eric W. Biederman" <[email protected]>
Acked-by: Vlad Yasevich <[email protected]>
> ---
> include/net/sctp/sctp.h | 6 ++--
> include/net/sctp/structs.h | 3 +-
> net/sctp/associola.c | 4 ++-
> net/sctp/endpointola.c | 6 +++-
> net/sctp/input.c | 64 +++++++++++++++++++++++++++----------------
> net/sctp/ipv6.c | 3 +-
> 6 files changed, 54 insertions(+), 32 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 87b119f..640915a 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -156,7 +156,7 @@ void sctp_hash_established(struct sctp_association *);
> void sctp_unhash_established(struct sctp_association *);
> void sctp_hash_endpoint(struct sctp_endpoint *);
> void sctp_unhash_endpoint(struct sctp_endpoint *);
> -struct sock *sctp_err_lookup(int family, struct sk_buff *,
> +struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
> struct sctphdr *, struct sctp_association **,
> struct sctp_transport **);
> void sctp_err_finish(struct sock *, struct sctp_association *);
> @@ -644,9 +644,9 @@ static inline int sctp_ep_hashfn(struct net *net, __u16 lport)
> }
>
> /* This is the hash function for the association hash table. */
> -static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport)
> +static inline int sctp_assoc_hashfn(struct net *net, __u16 lport, __u16 rport)
> {
> - int h = (lport << 16) + rport;
> + int h = (lport << 16) + rport + net_hash_mix(net);
> h ^= h>>8;
> return h & (sctp_assoc_hashsize - 1);
> }
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 9f9de55..c0563d1 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -1427,7 +1427,7 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
> const union sctp_addr *);
> struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
> struct net *, const union sctp_addr *);
> -int sctp_has_association(const union sctp_addr *laddr,
> +int sctp_has_association(struct net *net, const union sctp_addr *laddr,
> const union sctp_addr *paddr);
>
> int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t,
> @@ -2014,6 +2014,7 @@ void sctp_assoc_control_transport(struct sctp_association *,
> sctp_transport_cmd_t, sctp_sn_error_t);
> struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *, __u32);
> struct sctp_transport *sctp_assoc_is_match(struct sctp_association *,
> + struct net *,
> const union sctp_addr *,
> const union sctp_addr *);
> void sctp_assoc_migrate(struct sctp_association *, struct sock *);
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index ebaef3e..a3601f3 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -1089,13 +1089,15 @@ out:
>
> /* Is this the association we are looking for? */
> struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc,
> + struct net *net,
> const union sctp_addr *laddr,
> const union sctp_addr *paddr)
> {
> struct sctp_transport *transport;
>
> if ((htons(asoc->base.bind_addr.port) == laddr->v4.sin_port) &&
> - (htons(asoc->peer.port) == paddr->v4.sin_port)) {
> + (htons(asoc->peer.port) == paddr->v4.sin_port) &&
> + net_eq(sock_net(asoc->base.sk), net)) {
> transport = sctp_assoc_lookup_paddr(asoc, paddr);
> if (!transport)
> goto out;
> diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
> index 50c87b4..6b76393 100644
> --- a/net/sctp/endpointola.c
> +++ b/net/sctp/endpointola.c
> @@ -345,7 +345,8 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
>
> rport = ntohs(paddr->v4.sin_port);
>
> - hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport);
> + hash = sctp_assoc_hashfn(sock_net(ep->base.sk), ep->base.bind_addr.port,
> + rport);
> head = &sctp_assoc_hashtable[hash];
> read_lock(&head->lock);
> sctp_for_each_hentry(epb, node, &head->chain) {
> @@ -388,13 +389,14 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
> {
> struct sctp_sockaddr_entry *addr;
> struct sctp_bind_addr *bp;
> + struct net *net = sock_net(ep->base.sk);
>
> bp = &ep->base.bind_addr;
> /* This function is called with the socket lock held,
> * so the address_list can not change.
> */
> list_for_each_entry(addr, &bp->address_list, list) {
> - if (sctp_has_association(&addr->a, paddr))
> + if (sctp_has_association(net, &addr->a, paddr))
> return 1;
> }
>
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index c0ca893..a7e9a85 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -66,13 +66,15 @@
>
> /* Forward declarations for internal helpers. */
> static int sctp_rcv_ootb(struct sk_buff *);
> -static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
> +static struct sctp_association *__sctp_rcv_lookup(struct net *net,
> + struct sk_buff *skb,
> const union sctp_addr *laddr,
> const union sctp_addr *paddr,
> struct sctp_transport **transportp);
> static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
> const union sctp_addr *laddr);
> static struct sctp_association *__sctp_lookup_association(
> + struct net *net,
> const union sctp_addr *local,
> const union sctp_addr *peer,
> struct sctp_transport **pt);
> @@ -180,7 +182,7 @@ int sctp_rcv(struct sk_buff *skb)
> !af->addr_valid(&dest, NULL, skb))
> goto discard_it;
>
> - asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
> + asoc = __sctp_rcv_lookup(net, skb, &src, &dest, &transport);
>
> if (!asoc)
> ep = __sctp_rcv_lookup_endpoint(net, &dest);
> @@ -476,7 +478,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
> }
>
> /* Common lookup code for icmp/icmpv6 error handler. */
> -struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
> +struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
> struct sctphdr *sctphdr,
> struct sctp_association **app,
> struct sctp_transport **tpp)
> @@ -505,7 +507,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
> /* Look for an association that matches the incoming ICMP error
> * packet.
> */
> - asoc = __sctp_lookup_association(&saddr, &daddr, &transport);
> + asoc = __sctp_lookup_association(net, &saddr, &daddr, &transport);
> if (!asoc)
> return NULL;
>
> @@ -588,6 +590,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
> struct inet_sock *inet;
> sk_buff_data_t saveip, savesctp;
> int err;
> + struct net *net = dev_net(skb->dev);
>
> if (skb->len < ihlen + 8) {
> ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
> @@ -599,7 +602,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
> savesctp = skb->transport_header;
> skb_reset_network_header(skb);
> skb_set_transport_header(skb, ihlen);
> - sk = sctp_err_lookup(AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
> + sk = sctp_err_lookup(net, AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
> /* Put back, the original values. */
> skb->network_header = saveip;
> skb->transport_header = savesctp;
> @@ -803,13 +806,15 @@ hit:
> /* Insert association into the hash table. */
> static void __sctp_hash_established(struct sctp_association *asoc)
> {
> + struct net *net = sock_net(asoc->base.sk);
> struct sctp_ep_common *epb;
> struct sctp_hashbucket *head;
>
> epb = &asoc->base;
>
> /* Calculate which chain this entry will belong to. */
> - epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port, asoc->peer.port);
> + epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port,
> + asoc->peer.port);
>
> head = &sctp_assoc_hashtable[epb->hashent];
>
> @@ -832,12 +837,13 @@ void sctp_hash_established(struct sctp_association *asoc)
> /* Remove association from the hash table. */
> static void __sctp_unhash_established(struct sctp_association *asoc)
> {
> + struct net *net = sock_net(asoc->base.sk);
> struct sctp_hashbucket *head;
> struct sctp_ep_common *epb;
>
> epb = &asoc->base;
>
> - epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port,
> + epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port,
> asoc->peer.port);
>
> head = &sctp_assoc_hashtable[epb->hashent];
> @@ -860,6 +866,7 @@ void sctp_unhash_established(struct sctp_association *asoc)
>
> /* Look up an association. */
> static struct sctp_association *__sctp_lookup_association(
> + struct net *net,
> const union sctp_addr *local,
> const union sctp_addr *peer,
> struct sctp_transport **pt)
> @@ -874,12 +881,13 @@ static struct sctp_association *__sctp_lookup_association(
> /* Optimize here for direct hit, only listening connections can
> * have wildcards anyways.
> */
> - hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port));
> + hash = sctp_assoc_hashfn(net, ntohs(local->v4.sin_port),
> + ntohs(peer->v4.sin_port));
> head = &sctp_assoc_hashtable[hash];
> read_lock(&head->lock);
> sctp_for_each_hentry(epb, node, &head->chain) {
> asoc = sctp_assoc(epb);
> - transport = sctp_assoc_is_match(asoc, local, peer);
> + transport = sctp_assoc_is_match(asoc, net, local, peer);
> if (transport)
> goto hit;
> }
> @@ -897,27 +905,29 @@ hit:
>
> /* Look up an association. BH-safe. */
> SCTP_STATIC
> -struct sctp_association *sctp_lookup_association(const union sctp_addr *laddr,
> +struct sctp_association *sctp_lookup_association(struct net *net,
> + const union sctp_addr *laddr,
> const union sctp_addr *paddr,
> struct sctp_transport **transportp)
> {
> struct sctp_association *asoc;
>
> sctp_local_bh_disable();
> - asoc = __sctp_lookup_association(laddr, paddr, transportp);
> + asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
> sctp_local_bh_enable();
>
> return asoc;
> }
>
> /* Is there an association matching the given local and peer addresses? */
> -int sctp_has_association(const union sctp_addr *laddr,
> +int sctp_has_association(struct net *net,
> + const union sctp_addr *laddr,
> const union sctp_addr *paddr)
> {
> struct sctp_association *asoc;
> struct sctp_transport *transport;
>
> - if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) {
> + if ((asoc = sctp_lookup_association(net, laddr, paddr, &transport))) {
> sctp_association_put(asoc);
> return 1;
> }
> @@ -943,7 +953,8 @@ int sctp_has_association(const union sctp_addr *laddr,
> * in certain circumstances.
> *
> */
> -static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
> +static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
> + struct sk_buff *skb,
> const union sctp_addr *laddr, struct sctp_transport **transportp)
> {
> struct sctp_association *asoc;
> @@ -983,7 +994,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
>
> af->from_addr_param(paddr, params.addr, sh->source, 0);
>
> - asoc = __sctp_lookup_association(laddr, paddr, &transport);
> + asoc = __sctp_lookup_association(net, laddr, paddr, &transport);
> if (asoc)
> return asoc;
> }
> @@ -1006,6 +1017,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
> * subsequent ASCONF Chunks. If found, proceed to rule D4.
> */
> static struct sctp_association *__sctp_rcv_asconf_lookup(
> + struct net *net,
> sctp_chunkhdr_t *ch,
> const union sctp_addr *laddr,
> __be16 peer_port,
> @@ -1025,7 +1037,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
>
> af->from_addr_param(&paddr, param, peer_port, 0);
>
> - return __sctp_lookup_association(laddr, &paddr, transportp);
> + return __sctp_lookup_association(net, laddr, &paddr, transportp);
> }
>
>
> @@ -1038,7 +1050,8 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
> * This means that any chunks that can help us identify the association need
> * to be looked at to find this association.
> */
> -static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
> +static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
> + struct sk_buff *skb,
> const union sctp_addr *laddr,
> struct sctp_transport **transportp)
> {
> @@ -1080,7 +1093,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
>
> case SCTP_CID_ASCONF:
> if (have_auth || sctp_addip_noauth)
> - asoc = __sctp_rcv_asconf_lookup(ch, laddr,
> + asoc = __sctp_rcv_asconf_lookup(
> + net, ch, laddr,
> sctp_hdr(skb)->source,
> transportp);
> default:
> @@ -1103,7 +1117,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
> * include looking inside of INIT/INIT-ACK chunks or after the AUTH
> * chunks.
> */
> -static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
> +static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
> + struct sk_buff *skb,
> const union sctp_addr *laddr,
> struct sctp_transport **transportp)
> {
> @@ -1123,11 +1138,11 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
> switch (ch->type) {
> case SCTP_CID_INIT:
> case SCTP_CID_INIT_ACK:
> - return __sctp_rcv_init_lookup(skb, laddr, transportp);
> + return __sctp_rcv_init_lookup(net, skb, laddr, transportp);
> break;
>
> default:
> - return __sctp_rcv_walk_lookup(skb, laddr, transportp);
> + return __sctp_rcv_walk_lookup(net, skb, laddr, transportp);
> break;
> }
>
> @@ -1136,21 +1151,22 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
> }
>
> /* Lookup an association for an inbound skb. */
> -static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
> +static struct sctp_association *__sctp_rcv_lookup(struct net *net,
> + struct sk_buff *skb,
> const union sctp_addr *paddr,
> const union sctp_addr *laddr,
> struct sctp_transport **transportp)
> {
> struct sctp_association *asoc;
>
> - asoc = __sctp_lookup_association(laddr, paddr, transportp);
> + asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
>
> /* Further lookup for INIT/INIT-ACK packets.
> * SCTP Implementors Guide, 2.18 Handling of address
> * parameters within the INIT or INIT-ACK.
> */
> if (!asoc)
> - asoc = __sctp_rcv_lookup_harder(skb, laddr, transportp);
> + asoc = __sctp_rcv_lookup_harder(net, skb, laddr, transportp);
>
> return asoc;
> }
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index ed7139e..2165a7e 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -154,6 +154,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
> struct ipv6_pinfo *np;
> sk_buff_data_t saveip, savesctp;
> int err;
> + struct net *net = dev_net(skb->dev);
>
> idev = in6_dev_get(skb->dev);
>
> @@ -162,7 +163,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
> savesctp = skb->transport_header;
> skb_reset_network_header(skb);
> skb_set_transport_header(skb, offset);
> - sk = sctp_err_lookup(AF_INET6, skb, sctp_hdr(skb), &asoc, &transport);
> + sk = sctp_err_lookup(net, AF_INET6, skb, sctp_hdr(skb), &asoc, &transport);
> /* Put back, the original pointers. */
> skb->network_header = saveip;
> skb->transport_header = savesctp;
>
On 08/06/2012 02:42 PM, Eric W. Biederman wrote:
>
> - Move the address lists into struct net
> - Add per network namespace initialization and cleanup
> - Pass around struct net so it is everywhere I need it.
> - Rename all of the global variable references into references
> to the variables moved into struct net
>
> Signed-off-by: "Eric W. Biederman" <[email protected]>
Acked-by: Vlad Yasevich <[email protected]>
> ---
> include/net/net_namespace.h | 4 +
> include/net/netns/sctp.h | 21 +++++++
> include/net/sctp/sctp.h | 4 +-
> include/net/sctp/structs.h | 22 +-------
> net/sctp/associola.c | 3 +-
> net/sctp/bind_addr.c | 14 ++--
> net/sctp/ipv6.c | 17 +++---
> net/sctp/protocol.c | 141 +++++++++++++++++++++++++------------------
> net/sctp/socket.c | 7 +-
> 9 files changed, 131 insertions(+), 102 deletions(-)
> create mode 100644 include/net/netns/sctp.h
>
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> index ae1cd6c..8ab5250 100644
> --- a/include/net/net_namespace.h
> +++ b/include/net/net_namespace.h
> @@ -15,6 +15,7 @@
> #include <net/netns/packet.h>
> #include <net/netns/ipv4.h>
> #include <net/netns/ipv6.h>
> +#include <net/netns/sctp.h>
> #include <net/netns/dccp.h>
> #include <net/netns/x_tables.h>
> #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> @@ -80,6 +81,9 @@ struct net {
> #if IS_ENABLED(CONFIG_IPV6)
> struct netns_ipv6 ipv6;
> #endif
> +#if defined(CONFIG_IP_SCTP) || defined(CONFIG_IP_SCTP_MODULE)
> + struct netns_sctp sctp;
> +#endif
> #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
> struct netns_dccp dccp;
> #endif
> diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
> new file mode 100644
> index 0000000..cbd684e
> --- /dev/null
> +++ b/include/net/netns/sctp.h
> @@ -0,0 +1,21 @@
> +#ifndef __NETNS_SCTP_H__
> +#define __NETNS_SCTP_H__
> +
> +struct netns_sctp {
> + /* This is the global local address list.
> + * We actively maintain this complete list of addresses on
> + * the system by catching address add/delete events.
> + *
> + * It is a list of sctp_sockaddr_entry.
> + */
> + struct list_head local_addr_list;
> + struct list_head addr_waitq;
> + struct timer_list addr_wq_timer;
> + struct list_head auto_asconf_splist;
> + spinlock_t addr_wq_lock;
> +
> + /* Lock that protects the local_addr_list writers */
> + spinlock_t local_addr_lock;
> +};
> +
> +#endif /* __NETNS_SCTP_H__ */
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 640915a..00c9205 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -115,12 +115,12 @@
> * sctp/protocol.c
> */
> extern struct sock *sctp_get_ctl_sock(void);
> -extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
> +extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
> sctp_scope_t, gfp_t gfp,
> int flags);
> 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
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index c0563d1..6bdfcab 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -205,21 +205,7 @@ extern struct sctp_globals {
> int port_hashsize;
> struct sctp_bind_hashbucket *port_hashtable;
>
> - /* This is the global local address list.
> - * We actively maintain this complete list of addresses on
> - * the system by catching address add/delete events.
> - *
> - * It is a list of sctp_sockaddr_entry.
> - */
> - struct list_head local_addr_list;
> int default_auto_asconf;
> - struct list_head addr_waitq;
> - struct timer_list addr_wq_timer;
> - struct list_head auto_asconf_splist;
> - spinlock_t addr_wq_lock;
> -
> - /* Lock that protects the local_addr_list writers */
> - spinlock_t addr_list_lock;
>
> /* Flag to indicate if addip is enabled. */
> int addip_enable;
> @@ -278,12 +264,6 @@ extern struct sctp_globals {
> #define sctp_assoc_hashtable (sctp_globals.assoc_hashtable)
> #define sctp_port_hashsize (sctp_globals.port_hashsize)
> #define sctp_port_hashtable (sctp_globals.port_hashtable)
> -#define sctp_local_addr_list (sctp_globals.local_addr_list)
> -#define sctp_local_addr_lock (sctp_globals.addr_list_lock)
> -#define sctp_auto_asconf_splist (sctp_globals.auto_asconf_splist)
> -#define sctp_addr_waitq (sctp_globals.addr_waitq)
> -#define sctp_addr_wq_timer (sctp_globals.addr_wq_timer)
> -#define sctp_addr_wq_lock (sctp_globals.addr_wq_lock)
> #define sctp_default_auto_asconf (sctp_globals.default_auto_asconf)
> #define sctp_scope_policy (sctp_globals.ipv4_scope_policy)
> #define sctp_addip_enable (sctp_globals.addip_enable)
> @@ -1241,7 +1221,7 @@ struct sctp_bind_addr {
>
> 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,
> +int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
> const struct sctp_bind_addr *src,
> sctp_scope_t scope, gfp_t gfp,
> int flags);
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index a3601f3..ed4930b 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -1544,7 +1544,8 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
> if (asoc->peer.ipv6_address)
> flags |= SCTP_ADDR6_PEERSUPP;
>
> - return sctp_bind_addr_copy(&asoc->base.bind_addr,
> + return sctp_bind_addr_copy(sock_net(asoc->base.sk),
> + &asoc->base.bind_addr,
> &asoc->ep->base.bind_addr,
> scope, gfp, flags);
> }
> diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
> index 4ece451..a85ce4b 100644
> --- a/net/sctp/bind_addr.c
> +++ b/net/sctp/bind_addr.c
> @@ -52,8 +52,8 @@
> #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,
> +static int sctp_copy_one_addr(struct net *, struct sctp_bind_addr *,
> + union sctp_addr *, sctp_scope_t scope, gfp_t gfp,
> int flags);
> static void sctp_bind_addr_clean(struct sctp_bind_addr *);
>
> @@ -62,7 +62,7 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *);
> /* Copy 'src' to 'dest' taking 'scope' into account. Omit addresses
> * in 'src' which have a broader scope than 'scope'.
> */
> -int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
> +int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
> const struct sctp_bind_addr *src,
> sctp_scope_t scope, gfp_t gfp,
> int flags)
> @@ -75,7 +75,7 @@ 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,
> + error = sctp_copy_one_addr(net, dest, &addr->a, scope,
> gfp, flags);
> if (error < 0)
> goto out;
> @@ -87,7 +87,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(net, dest, &addr->a,
> SCTP_SCOPE_LINK, gfp,
> flags);
> if (error < 0)
> @@ -448,7 +448,7 @@ 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,
> +static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
> union sctp_addr *addr,
> sctp_scope_t scope, gfp_t gfp,
> int flags)
> @@ -456,7 +456,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
> int error = 0;
>
> if (sctp_is_any(NULL, addr)) {
> - error = sctp_copy_local_addr_list(dest, scope, gfp, flags);
> + error = sctp_copy_local_addr_list(net, dest, scope, gfp, flags);
> } else if (sctp_in_scope(addr, scope)) {
> /* Now that the address is in scope, check to see if
> * the address type is supported by local sock as
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index 2165a7e..bbf1534 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -99,6 +99,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
> struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
> struct sctp_sockaddr_entry *addr = NULL;
> struct sctp_sockaddr_entry *temp;
> + struct net *net = dev_net(ifa->idev->dev);
> int found = 0;
>
> switch (ev) {
> @@ -110,27 +111,27 @@ 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->sctp.local_addr_lock);
> + list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
> + sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
> + spin_unlock_bh(&net->sctp.local_addr_lock);
> }
> break;
> case NETDEV_DOWN:
> - spin_lock_bh(&sctp_local_addr_lock);
> + spin_lock_bh(&net->sctp.local_addr_lock);
> list_for_each_entry_safe(addr, temp,
> - &sctp_local_addr_list, list) {
> + &net->sctp.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->sctp.local_addr_lock);
> if (found)
> kfree_rcu(addr, rcu);
> break;
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 1f89c4e..291e682 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -201,29 +201,29 @@ 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;
>
> 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->sctp.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;
>
> - list_for_each_safe(pos, temp, &sctp_local_addr_list) {
> + list_for_each_safe(pos, temp, &net->sctp.local_addr_list) {
> addr = list_entry(pos, struct sctp_sockaddr_entry, list);
> list_del(pos);
> kfree(addr);
> @@ -231,14 +231,14 @@ 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)
> +int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
> + sctp_scope_t scope, gfp_t gfp, int copy_flags)
> {
> struct sctp_sockaddr_entry *addr;
> int error = 0;
>
> rcu_read_lock();
> - list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
> + list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
> if (!addr->valid)
> continue;
> if (sctp_in_scope(&addr->a, scope)) {
> @@ -627,14 +627,15 @@ static void sctp_v4_ecn_capable(struct sock *sk)
>
> void sctp_addr_wq_timeout_handler(unsigned long arg)
> {
> + struct net *net = (struct net *)arg;
> struct sctp_sockaddr_entry *addrw, *temp;
> struct sctp_sock *sp;
>
> - spin_lock_bh(&sctp_addr_wq_lock);
> + spin_lock_bh(&net->sctp.addr_wq_lock);
>
> - list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
> + list_for_each_entry_safe(addrw, temp, &net->sctp.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,
> + " for cmd %d at entry %p\n", &net->sctp.addr_waitq, &addrw->a, addrw->state,
> addrw);
>
> #if IS_ENABLED(CONFIG_IPV6)
> @@ -648,7 +649,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;
>
> @@ -656,12 +657,12 @@ 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->sctp.addr_wq_timer, timeo_val);
> break;
> }
> }
> #endif
> - list_for_each_entry(sp, &sctp_auto_asconf_splist, auto_asconf_list) {
> + list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) {
> struct sock *sk;
>
> sk = sctp_opt2sk(sp);
> @@ -679,31 +680,32 @@ free_next:
> list_del(&addrw->list);
> kfree(addrw);
> }
> - spin_unlock_bh(&sctp_addr_wq_lock);
> + spin_unlock_bh(&net->sctp.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;
>
> - 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->sctp.addr_wq_lock);
> + del_timer(&net->sctp.addr_wq_timer);
> + list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
> list_del(&addrw->list);
> kfree(addrw);
> }
> - spin_unlock_bh(&sctp_addr_wq_lock);
> + spin_unlock_bh(&net->sctp.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;
>
> - list_for_each_entry(addrw, &sctp_addr_waitq, list) {
> + list_for_each_entry(addrw, &net->sctp.addr_waitq, list) {
> if (addrw->a.sa.sa_family != addr->a.sa.sa_family)
> continue;
> if (addrw->a.sa.sa_family == AF_INET) {
> @@ -719,7 +721,7 @@ 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;
> @@ -730,9 +732,9 @@ 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->sctp.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 ",
> @@ -741,27 +743,27 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
> list_del(&addrw->list);
> kfree(addrw);
> }
> - spin_unlock_bh(&sctp_addr_wq_lock);
> + spin_unlock_bh(&net->sctp.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->sctp.addr_wq_lock);
> return;
> }
> addrw->state = cmd;
> - list_add_tail(&addrw->list, &sctp_addr_waitq);
> + list_add_tail(&addrw->list, &net->sctp.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->sctp.addr_waitq);
>
> - if (!timer_pending(&sctp_addr_wq_timer)) {
> + if (!timer_pending(&net->sctp.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->sctp.addr_wq_timer, timeo_val);
> }
> - spin_unlock_bh(&sctp_addr_wq_lock);
> + spin_unlock_bh(&net->sctp.addr_wq_lock);
> }
>
> /* Event handler for inet address addition/deletion events.
> @@ -776,11 +778,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
> struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
> struct sctp_sockaddr_entry *addr = NULL;
> struct sctp_sockaddr_entry *temp;
> + struct net *net = dev_net(ifa->ifa_dev->dev);
> int found = 0;
>
> - if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net))
> - return NOTIFY_DONE;
> -
> switch (ev) {
> case NETDEV_UP:
> addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
> @@ -789,27 +789,27 @@ 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->sctp.local_addr_lock);
> + list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
> + sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
> + spin_unlock_bh(&net->sctp.local_addr_lock);
> }
> break;
> case NETDEV_DOWN:
> - spin_lock_bh(&sctp_local_addr_lock);
> + spin_lock_bh(&net->sctp.local_addr_lock);
> list_for_each_entry_safe(addr, temp,
> - &sctp_local_addr_list, list) {
> + &net->sctp.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->sctp.local_addr_lock);
> if (found)
> kfree_rcu(addr, rcu);
> break;
> @@ -1194,6 +1194,36 @@ static void sctp_v4_del_protocol(void)
> unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
> }
>
> +static int sctp_net_init(struct net *net)
> +{
> + /* Initialize the local address list. */
> + INIT_LIST_HEAD(&net->sctp.local_addr_list);
> + spin_lock_init(&net->sctp.local_addr_lock);
> + sctp_get_local_addr_list(net);
> +
> + /* Initialize the address event list */
> + INIT_LIST_HEAD(&net->sctp.addr_waitq);
> + INIT_LIST_HEAD(&net->sctp.auto_asconf_splist);
> + spin_lock_init(&net->sctp.addr_wq_lock);
> + net->sctp.addr_wq_timer.expires = 0;
> + setup_timer(&net->sctp.addr_wq_timer, sctp_addr_wq_timeout_handler,
> + (unsigned long)net);
> +
> + return 0;
> +}
> +
> +static void sctp_net_exit(struct net *net)
> +{
> + /* Free the local address list */
> + sctp_free_addr_wq(net);
> + sctp_free_local_addr_list(net);
> +}
> +
> +static struct pernet_operations sctp_net_ops = {
> + .init = sctp_net_init,
> + .exit = sctp_net_exit,
> +};
> +
> /* Initialize the universe into something sensible. */
> SCTP_STATIC __init int sctp_init(void)
> {
> @@ -1399,18 +1429,6 @@ 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);
> -
> status = sctp_v4_protosw_init();
>
> if (status)
> @@ -1426,6 +1444,10 @@ SCTP_STATIC __init int sctp_init(void)
> goto err_ctl_sock_init;
> }
>
> + status = register_pernet_subsys(&sctp_net_ops);
> + if (status)
> + goto err_register_pernet_subsys;
> +
> status = sctp_v4_add_protocol();
> if (status)
> goto err_add_protocol;
> @@ -1441,13 +1463,14 @@ out:
> err_v6_add_protocol:
> sctp_v4_del_protocol();
> err_add_protocol:
> + unregister_pernet_subsys(&sctp_net_ops);
> +err_register_pernet_subsys:
> inet_ctl_sock_destroy(sctp_ctl_sock);
> err_ctl_sock_init:
> sctp_v6_protosw_exit();
> err_v6_protosw_init:
> sctp_v4_protosw_exit();
> err_protosw_init:
> - sctp_free_local_addr_list();
> sctp_v4_pf_exit();
> sctp_v6_pf_exit();
> sctp_sysctl_unregister();
> @@ -1482,18 +1505,16 @@ 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 the control endpoint. */
> inet_ctl_sock_destroy(sctp_ctl_sock);
>
> + unregister_pernet_subsys(&sctp_net_ops);
> +
> /* 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/socket.c b/net/sctp/socket.c
> index 4316b0f..5b6dd0e 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3471,7 +3471,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
> sp->do_auto_asconf = 0;
> } else if (val && !sp->do_auto_asconf) {
> list_add_tail(&sp->auto_asconf_list,
> - &sctp_auto_asconf_splist);
> + &sock_net(sk)->sctp.auto_asconf_splist);
> sp->do_auto_asconf = 1;
> }
> return 0;
> @@ -3964,7 +3964,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
> sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
> if (sctp_default_auto_asconf) {
> list_add_tail(&sp->auto_asconf_list,
> - &sctp_auto_asconf_splist);
> + &sock_net(sk)->sctp.auto_asconf_splist);
> sp->do_auto_asconf = 1;
> } else
> sp->do_auto_asconf = 0;
> @@ -4653,9 +4653,10 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
> union sctp_addr temp;
> int cnt = 0;
> int addrlen;
> + struct net *net = sock_net(sk);
>
> rcu_read_lock();
> - list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
> + list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
> if (!addr->valid)
> continue;
>
>
On 08/06/2012 02:43 PM, Eric W. Biederman wrote:
>
> - Kill sctp_get_ctl_sock, it is useless now.
> - Pass struct net where needed so net->sctp.ctl_sock is accessible.
>
> Signed-off-by: "Eric W. Biederman" <[email protected]>
Acked-by: Vlad Yasevich <[email protected]>
> ---
> include/net/netns/sctp.h | 8 +++++++
> include/net/sctp/sctp.h | 1 -
> net/sctp/input.c | 4 +-
> net/sctp/protocol.c | 47 ++++++++++++++++++---------------------------
> net/sctp/sm_statefuns.c | 45 ++++++++++++++++++++++++++++++-------------
> 5 files changed, 60 insertions(+), 45 deletions(-)
>
> diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
> index cbd684e..29e36b4 100644
> --- a/include/net/netns/sctp.h
> +++ b/include/net/netns/sctp.h
> @@ -1,7 +1,15 @@
> #ifndef __NETNS_SCTP_H__
> #define __NETNS_SCTP_H__
>
> +struct sock;
> +
> struct netns_sctp {
> + /* This is the global socket data structure used for responding to
> + * the Out-of-the-blue (OOTB) packets. A control sock will be created
> + * for this socket at the initialization time.
> + */
> + struct sock *ctl_sock;
> +
> /* This is the global local address list.
> * We actively maintain this complete list of addresses on
> * the system by catching address add/delete events.
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 00c9205..550a81b 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -114,7 +114,6 @@
> /*
> * sctp/protocol.c
> */
> -extern struct sock *sctp_get_ctl_sock(void);
> extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
> sctp_scope_t, gfp_t gfp,
> int flags);
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index a7e9a85..c9a0449 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -204,7 +204,7 @@ int sctp_rcv(struct sk_buff *skb)
> sctp_endpoint_put(ep);
> ep = NULL;
> }
> - sk = sctp_get_ctl_sock();
> + sk = net->sctp.ctl_sock;
> ep = sctp_sk(sk)->ep;
> sctp_endpoint_hold(ep);
> rcvr = &ep->base;
> @@ -795,7 +795,7 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
> goto hit;
> }
>
> - ep = sctp_sk((sctp_get_ctl_sock()))->ep;
> + ep = sctp_sk(net->sctp.ctl_sock)->ep;
>
> hit:
> sctp_endpoint_hold(ep);
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 291e682..6193d20 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -78,12 +78,6 @@ struct proc_dir_entry *proc_net_sctp;
> struct idr sctp_assocs_id;
> DEFINE_SPINLOCK(sctp_assocs_id_lock);
>
> -/* This is the global socket data structure used for responding to
> - * the Out-of-the-blue (OOTB) packets. A control sock will be created
> - * for this socket at the initialization time.
> - */
> -static struct sock *sctp_ctl_sock;
> -
> static struct sctp_pf *sctp_pf_inet6_specific;
> static struct sctp_pf *sctp_pf_inet_specific;
> static struct sctp_af *sctp_af_v4_specific;
> @@ -96,12 +90,6 @@ long sysctl_sctp_mem[3];
> int sysctl_sctp_rmem[3];
> int sysctl_sctp_wmem[3];
>
> -/* Return the address of the control sock. */
> -struct sock *sctp_get_ctl_sock(void)
> -{
> - return sctp_ctl_sock;
> -}
> -
> /* Set up the proc fs entry for the SCTP protocol. */
> static __init int sctp_proc_init(void)
> {
> @@ -822,7 +810,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
> * Initialize the control inode/socket with a control endpoint data
> * structure. This endpoint is reserved exclusively for the OOTB processing.
> */
> -static int sctp_ctl_sock_init(void)
> +static int sctp_ctl_sock_init(struct net *net)
> {
> int err;
> sa_family_t family = PF_INET;
> @@ -830,14 +818,14 @@ static int sctp_ctl_sock_init(void)
> if (sctp_get_pf_specific(PF_INET6))
> family = PF_INET6;
>
> - err = inet_ctl_sock_create(&sctp_ctl_sock, family,
> - SOCK_SEQPACKET, IPPROTO_SCTP, &init_net);
> + err = inet_ctl_sock_create(&net->sctp.ctl_sock, family,
> + SOCK_SEQPACKET, IPPROTO_SCTP, net);
>
> /* If IPv6 socket could not be created, try the IPv4 socket */
> if (err < 0 && family == PF_INET6)
> - err = inet_ctl_sock_create(&sctp_ctl_sock, AF_INET,
> + err = inet_ctl_sock_create(&net->sctp.ctl_sock, AF_INET,
> SOCK_SEQPACKET, IPPROTO_SCTP,
> - &init_net);
> + net);
>
> if (err < 0) {
> pr_err("Failed to create the SCTP control socket\n");
> @@ -1196,6 +1184,14 @@ static void sctp_v4_del_protocol(void)
>
> static int sctp_net_init(struct net *net)
> {
> + int status;
> +
> + /* Initialize the control inode/socket for handling OOTB packets. */
> + if ((status = sctp_ctl_sock_init(net))) {
> + pr_err("Failed to initialize the SCTP control sock\n");
> + goto err_ctl_sock_init;
> + }
> +
> /* Initialize the local address list. */
> INIT_LIST_HEAD(&net->sctp.local_addr_list);
> spin_lock_init(&net->sctp.local_addr_lock);
> @@ -1210,6 +1206,9 @@ static int sctp_net_init(struct net *net)
> (unsigned long)net);
>
> return 0;
> +
> +err_ctl_sock_init:
> + return status;
> }
>
> static void sctp_net_exit(struct net *net)
> @@ -1217,6 +1216,9 @@ static void sctp_net_exit(struct net *net)
> /* Free the local address list */
> sctp_free_addr_wq(net);
> sctp_free_local_addr_list(net);
> +
> + /* Free the control endpoint. */
> + inet_ctl_sock_destroy(net->sctp.ctl_sock);
> }
>
> static struct pernet_operations sctp_net_ops = {
> @@ -1438,12 +1440,6 @@ SCTP_STATIC __init int sctp_init(void)
> if (status)
> goto err_v6_protosw_init;
>
> - /* Initialize the control inode/socket for handling OOTB packets. */
> - if ((status = sctp_ctl_sock_init())) {
> - pr_err("Failed to initialize the SCTP control sock\n");
> - goto err_ctl_sock_init;
> - }
> -
> status = register_pernet_subsys(&sctp_net_ops);
> if (status)
> goto err_register_pernet_subsys;
> @@ -1465,8 +1461,6 @@ err_v6_add_protocol:
> err_add_protocol:
> unregister_pernet_subsys(&sctp_net_ops);
> err_register_pernet_subsys:
> - inet_ctl_sock_destroy(sctp_ctl_sock);
> -err_ctl_sock_init:
> sctp_v6_protosw_exit();
> err_v6_protosw_init:
> sctp_v4_protosw_exit();
> @@ -1506,9 +1500,6 @@ SCTP_STATIC __exit void sctp_exit(void)
> sctp_v6_del_protocol();
> sctp_v4_del_protocol();
>
> - /* Free the control endpoint. */
> - inet_ctl_sock_destroy(sctp_ctl_sock);
> -
> unregister_pernet_subsys(&sctp_net_ops);
>
> /* Free protosw registrations */
> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> index 9fca103..f2daf61 100644
> --- a/net/sctp/sm_statefuns.c
> +++ b/net/sctp/sm_statefuns.c
> @@ -74,7 +74,8 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
> static int sctp_eat_data(const struct sctp_association *asoc,
> struct sctp_chunk *chunk,
> sctp_cmd_seq_t *commands);
> -static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
> +static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
> + const struct sctp_association *asoc,
> const struct sctp_chunk *chunk);
> static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
> const struct sctp_association *asoc,
> @@ -301,6 +302,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
> struct sctp_chunk *err_chunk;
> struct sctp_packet *packet;
> sctp_unrecognized_param_t *unk_param;
> + struct net *net;
> int len;
>
> /* 6.10 Bundling
> @@ -318,7 +320,8 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
> /* If the packet is an OOTB packet which is temporarily on the
> * control endpoint, respond with an ABORT.
> */
> - if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) {
> + net = sock_net(ep->base.sk);
> + if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
> SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
> return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
> }
> @@ -646,11 +649,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
> int error = 0;
> struct sctp_chunk *err_chk_p;
> struct sock *sk;
> + struct net *net;
>
> /* If the packet is an OOTB packet which is temporarily on the
> * control endpoint, respond with an ABORT.
> */
> - if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) {
> + net = sock_net(ep->base.sk);
> + if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
> SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
> return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
> }
> @@ -1171,7 +1176,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
> /* Helper function to send out an abort for the restart
> * condition.
> */
> -static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
> +static int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa,
> struct sctp_chunk *init,
> sctp_cmd_seq_t *commands)
> {
> @@ -1197,7 +1202,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
> errhdr->length = htons(len);
>
> /* Assign to the control socket. */
> - ep = sctp_sk((sctp_get_ctl_sock()))->ep;
> + ep = sctp_sk(net->sctp.ctl_sock)->ep;
>
> /* Association is NULL since this may be a restart attack and we
> * want to send back the attacker's vtag.
> @@ -1240,6 +1245,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
> struct sctp_chunk *init,
> sctp_cmd_seq_t *commands)
> {
> + struct net *net = sock_net(new_asoc->base.sk);
> struct sctp_transport *new_addr;
> int ret = 1;
>
> @@ -1258,7 +1264,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
> transports) {
> if (!list_has_sctp_addr(&asoc->peer.transport_addr_list,
> &new_addr->ipaddr)) {
> - sctp_sf_send_restart_abort(&new_addr->ipaddr, init,
> + sctp_sf_send_restart_abort(net, &new_addr->ipaddr, init,
> commands);
> ret = 0;
> break;
> @@ -1650,10 +1656,11 @@ sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep,
> const sctp_subtype_t type,
> void *arg, sctp_cmd_seq_t *commands)
> {
> + struct net *net = sock_net(ep->base.sk);
> /* Per the above section, we'll discard the chunk if we have an
> * endpoint. If this is an OOTB INIT-ACK, treat it as such.
> */
> - if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
> + if (ep == sctp_sk(net->sctp.ctl_sock)->ep)
> return sctp_sf_ootb(ep, asoc, type, arg, commands);
> else
> return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
> @@ -3163,8 +3170,10 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
> struct sctp_packet *packet = NULL;
> struct sctp_chunk *chunk = arg;
> struct sctp_chunk *abort;
> + struct net *net;
>
> - packet = sctp_ootb_pkt_new(asoc, chunk);
> + net = sock_net(ep->base.sk);
> + packet = sctp_ootb_pkt_new(net, asoc, chunk);
>
> if (packet) {
> /* Make an ABORT. The T bit will be set if the asoc
> @@ -3425,8 +3434,10 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
> struct sctp_packet *packet = NULL;
> struct sctp_chunk *chunk = arg;
> struct sctp_chunk *shut;
> + struct net *net;
>
> - packet = sctp_ootb_pkt_new(asoc, chunk);
> + net = sock_net(ep->base.sk);
> + packet = sctp_ootb_pkt_new(net, asoc, chunk);
>
> if (packet) {
> /* Make an SHUTDOWN_COMPLETE.
> @@ -4262,6 +4273,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
> struct sctp_packet *packet = NULL;
> struct sctp_chunk *chunk = arg;
> struct sctp_chunk *abort = NULL;
> + struct net *net;
>
> /* SCTP-AUTH, Section 6.3:
> * It should be noted that if the receiver wants to tear
> @@ -4282,6 +4294,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
> if (!abort)
> goto nomem;
>
> + net = sock_net(ep->base.sk);
> if (asoc) {
> /* Treat INIT-ACK as a special case during COOKIE-WAIT. */
> if (chunk->chunk_hdr->type == SCTP_CID_INIT_ACK &&
> @@ -4319,7 +4332,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
> SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> }
> } else {
> - packet = sctp_ootb_pkt_new(asoc, chunk);
> + packet = sctp_ootb_pkt_new(net, asoc, chunk);
>
> if (!packet)
> goto nomem_pkt;
> @@ -5825,8 +5838,10 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
> {
> struct sctp_packet *packet;
> struct sctp_chunk *abort;
> + struct net *net;
>
> - packet = sctp_ootb_pkt_new(asoc, chunk);
> + net = sock_net(ep->base.sk);
> + packet = sctp_ootb_pkt_new(net, asoc, chunk);
>
> if (packet) {
> /* Make an ABORT.
> @@ -5858,7 +5873,8 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
> }
>
> /* Allocate a packet for responding in the OOTB conditions. */
> -static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
> +static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
> + const struct sctp_association *asoc,
> const struct sctp_chunk *chunk)
> {
> struct sctp_packet *packet;
> @@ -5919,7 +5935,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc
> * the source address.
> */
> sctp_transport_route(transport, (union sctp_addr *)&chunk->dest,
> - sctp_sk(sctp_get_ctl_sock()));
> + sctp_sk(net->sctp.ctl_sock));
>
> packet = sctp_packet_init(&transport->packet, transport, sport, dport);
> packet = sctp_packet_config(packet, vtag, 0);
> @@ -5946,7 +5962,8 @@ static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
> struct sctp_packet *packet;
>
> if (err_chunk) {
> - packet = sctp_ootb_pkt_new(asoc, chunk);
> + struct net *net = sock_net(ep->base.sk);
> + packet = sctp_ootb_pkt_new(net, asoc, chunk);
> if (packet) {
> struct sctp_signed_cookie *cookie;
>
>
On 08/06/2012 02:44 PM, Eric W. Biederman wrote:
>
> The percpu sctp socket counter has nothing at all to do with the sctp
> proc files, and having it in the wrong initialization is confusing,
> and makes network namespace support a pain.
>
> Signed-off-by: "Eric W. Biederman" <[email protected]>
Acked-by: Vlad Yasevich <[email protected]>
> ---
> net/sctp/protocol.c | 13 +++++++------
> 1 files changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 6193d20..976d765 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -93,8 +93,6 @@ int sysctl_sctp_wmem[3];
> /* Set up the proc fs entry for the SCTP protocol. */
> static __init int sctp_proc_init(void)
> {
> - if (percpu_counter_init(&sctp_sockets_allocated, 0))
> - goto out_nomem;
> #ifdef CONFIG_PROC_FS
> if (!proc_net_sctp) {
> proc_net_sctp = proc_mkdir("sctp", init_net.proc_net);
> @@ -125,12 +123,9 @@ out_snmp_proc_init:
> remove_proc_entry("sctp", init_net.proc_net);
> }
> out_free_percpu:
> - percpu_counter_destroy(&sctp_sockets_allocated);
> #else
> return 0;
> #endif /* CONFIG_PROC_FS */
> -
> -out_nomem:
> return -ENOMEM;
> }
>
> @@ -151,7 +146,6 @@ static void sctp_proc_exit(void)
> remove_proc_entry("sctp", init_net.proc_net);
> }
> #endif
> - percpu_counter_destroy(&sctp_sockets_allocated);
> }
>
> /* Private helper to extract ipv4 address and stash them in
> @@ -1261,6 +1255,10 @@ SCTP_STATIC __init int sctp_init(void)
> if (status)
> goto err_init_mibs;
>
> + status = percpu_counter_init(&sctp_sockets_allocated, 0);
> + if (status)
> + goto err_percpu_counter_init;
> +
> /* Initialize proc fs directory. */
> status = sctp_proc_init();
> if (status)
> @@ -1481,6 +1479,8 @@ err_ahash_alloc:
> sctp_dbg_objcnt_exit();
> sctp_proc_exit();
> err_init_proc:
> + percpu_counter_destroy(&sctp_sockets_allocated);
> +err_percpu_counter_init:
> cleanup_sctp_mibs();
> err_init_mibs:
> kmem_cache_destroy(sctp_chunk_cachep);
> @@ -1521,6 +1521,7 @@ SCTP_STATIC __exit void sctp_exit(void)
> sizeof(struct sctp_bind_hashbucket)));
>
> sctp_dbg_objcnt_exit();
> + percpu_counter_destroy(&sctp_sockets_allocated);
> sctp_proc_exit();
> cleanup_sctp_mibs();
>
>
On 08/06/2012 02:45 PM, Eric W. Biederman wrote:
>
> - Convert all of the files under /proc/net/sctp to be per
> network namespace.
>
> - Don't print anything for /proc/net/sctp/snmp except in
> the initial network namespaces as the snmp counters still
> have to be converted to be per network namespace.
>
> Signed-off-by: "Eric W. Biederman" <[email protected]>
Acked-by: Vlad Yasevich <[email protected]>
> ---
> include/net/netns/sctp.h | 5 +++
> include/net/sctp/sctp.h | 16 +++++-----
> net/sctp/proc.c | 59 +++++++++++++++++++++++------------
> net/sctp/protocol.c | 77 +++++++++++++++++++--------------------------
> 4 files changed, 85 insertions(+), 72 deletions(-)
>
> diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
> index 29e36b4..9c20a82 100644
> --- a/include/net/netns/sctp.h
> +++ b/include/net/netns/sctp.h
> @@ -2,8 +2,13 @@
> #define __NETNS_SCTP_H__
>
> struct sock;
> +struct proc_dir_entry;
>
> struct netns_sctp {
> +#ifdef CONFIG_PROC_FS
> + struct proc_dir_entry *proc_net_sctp;
> +#endif
> +
> /* This is the global socket data structure used for responding to
> * the Out-of-the-blue (OOTB) packets. A control sock will be created
> * for this socket at the initialization time.
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 550a81b..ca716da 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -172,14 +172,14 @@ void sctp_backlog_migrate(struct sctp_association *assoc,
> /*
> * sctp/proc.c
> */
> -int sctp_snmp_proc_init(void);
> -void sctp_snmp_proc_exit(void);
> -int sctp_eps_proc_init(void);
> -void sctp_eps_proc_exit(void);
> -int sctp_assocs_proc_init(void);
> -void sctp_assocs_proc_exit(void);
> -int sctp_remaddr_proc_init(void);
> -void sctp_remaddr_proc_exit(void);
> +int sctp_snmp_proc_init(struct net *net);
> +void sctp_snmp_proc_exit(struct net *net);
> +int sctp_eps_proc_init(struct net *net);
> +void sctp_eps_proc_exit(struct net *net);
> +int sctp_assocs_proc_init(struct net *net);
> +void sctp_assocs_proc_exit(struct net *net);
> +int sctp_remaddr_proc_init(struct net *net);
> +void sctp_remaddr_proc_exit(struct net *net);
>
>
> /*
> diff --git a/net/sctp/proc.c b/net/sctp/proc.c
> index 1e2eee8..dc79a3a 100644
> --- a/net/sctp/proc.c
> +++ b/net/sctp/proc.c
> @@ -80,8 +80,12 @@ static const struct snmp_mib sctp_snmp_list[] = {
> /* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */
> static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
> {
> + struct net *net = seq->private;
> int i;
>
> + if (!net_eq(net, &init_net))
> + return 0;
> +
> for (i = 0; sctp_snmp_list[i].name != NULL; i++)
> seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
> snmp_fold_field((void __percpu **)sctp_statistics,
> @@ -93,7 +97,7 @@ static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
> /* Initialize the seq file operations for 'snmp' object. */
> static int sctp_snmp_seq_open(struct inode *inode, struct file *file)
> {
> - return single_open(file, sctp_snmp_seq_show, NULL);
> + return single_open_net(inode, file, sctp_snmp_seq_show);
> }
>
> static const struct file_operations sctp_snmp_seq_fops = {
> @@ -105,11 +109,12 @@ static const struct file_operations sctp_snmp_seq_fops = {
> };
>
> /* Set up the proc fs entry for 'snmp' object. */
> -int __init sctp_snmp_proc_init(void)
> +int __net_init sctp_snmp_proc_init(struct net *net)
> {
> struct proc_dir_entry *p;
>
> - p = proc_create("snmp", S_IRUGO, proc_net_sctp, &sctp_snmp_seq_fops);
> + p = proc_create("snmp", S_IRUGO, net->sctp.proc_net_sctp,
> + &sctp_snmp_seq_fops);
> if (!p)
> return -ENOMEM;
>
> @@ -117,9 +122,9 @@ int __init sctp_snmp_proc_init(void)
> }
>
> /* Cleanup the proc fs entry for 'snmp' object. */
> -void sctp_snmp_proc_exit(void)
> +void sctp_snmp_proc_exit(struct net *net)
> {
> - remove_proc_entry("snmp", proc_net_sctp);
> + remove_proc_entry("snmp", net->sctp.proc_net_sctp);
> }
>
> /* Dump local addresses of an association/endpoint. */
> @@ -197,6 +202,7 @@ static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
> /* Display sctp endpoints (/proc/net/sctp/eps). */
> static int sctp_eps_seq_show(struct seq_file *seq, void *v)
> {
> + struct seq_net_private *priv = seq->private;
> struct sctp_hashbucket *head;
> struct sctp_ep_common *epb;
> struct sctp_endpoint *ep;
> @@ -213,6 +219,8 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
> sctp_for_each_hentry(epb, node, &head->chain) {
> ep = sctp_ep(epb);
> sk = epb->sk;
> + if (!net_eq(sock_net(sk), priv->net))
> + continue;
> seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
> sctp_sk(sk)->type, sk->sk_state, hash,
> epb->bind_addr.port,
> @@ -238,7 +246,8 @@ static const struct seq_operations sctp_eps_ops = {
> /* Initialize the seq file operations for 'eps' object. */
> static int sctp_eps_seq_open(struct inode *inode, struct file *file)
> {
> - return seq_open(file, &sctp_eps_ops);
> + return seq_open_net(inode, file, &sctp_eps_ops,
> + sizeof(struct seq_net_private));
> }
>
> static const struct file_operations sctp_eps_seq_fops = {
> @@ -249,11 +258,12 @@ static const struct file_operations sctp_eps_seq_fops = {
> };
>
> /* Set up the proc fs entry for 'eps' object. */
> -int __init sctp_eps_proc_init(void)
> +int __net_init sctp_eps_proc_init(struct net *net)
> {
> struct proc_dir_entry *p;
>
> - p = proc_create("eps", S_IRUGO, proc_net_sctp, &sctp_eps_seq_fops);
> + p = proc_create("eps", S_IRUGO, net->sctp.proc_net_sctp,
> + &sctp_eps_seq_fops);
> if (!p)
> return -ENOMEM;
>
> @@ -261,9 +271,9 @@ int __init sctp_eps_proc_init(void)
> }
>
> /* Cleanup the proc fs entry for 'eps' object. */
> -void sctp_eps_proc_exit(void)
> +void sctp_eps_proc_exit(struct net *net)
> {
> - remove_proc_entry("eps", proc_net_sctp);
> + remove_proc_entry("eps", net->sctp.proc_net_sctp);
> }
>
>
> @@ -300,6 +310,7 @@ static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
> /* Display sctp associations (/proc/net/sctp/assocs). */
> static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
> {
> + struct seq_net_private *priv = seq->private;
> struct sctp_hashbucket *head;
> struct sctp_ep_common *epb;
> struct sctp_association *assoc;
> @@ -316,6 +327,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
> sctp_for_each_hentry(epb, node, &head->chain) {
> assoc = sctp_assoc(epb);
> sk = epb->sk;
> + if (!net_eq(sock_net(sk), priv->net))
> + continue;
> seq_printf(seq,
> "%8pK %8pK %-3d %-3d %-2d %-4d "
> "%4d %8d %8d %7d %5lu %-5d %5d ",
> @@ -354,7 +367,8 @@ static const struct seq_operations sctp_assoc_ops = {
> /* Initialize the seq file operations for 'assocs' object. */
> static int sctp_assocs_seq_open(struct inode *inode, struct file *file)
> {
> - return seq_open(file, &sctp_assoc_ops);
> + return seq_open_net(inode, file, &sctp_assoc_ops,
> + sizeof(struct seq_net_private));
> }
>
> static const struct file_operations sctp_assocs_seq_fops = {
> @@ -365,11 +379,11 @@ static const struct file_operations sctp_assocs_seq_fops = {
> };
>
> /* Set up the proc fs entry for 'assocs' object. */
> -int __init sctp_assocs_proc_init(void)
> +int __net_init sctp_assocs_proc_init(struct net *net)
> {
> struct proc_dir_entry *p;
>
> - p = proc_create("assocs", S_IRUGO, proc_net_sctp,
> + p = proc_create("assocs", S_IRUGO, net->sctp.proc_net_sctp,
> &sctp_assocs_seq_fops);
> if (!p)
> return -ENOMEM;
> @@ -378,9 +392,9 @@ int __init sctp_assocs_proc_init(void)
> }
>
> /* Cleanup the proc fs entry for 'assocs' object. */
> -void sctp_assocs_proc_exit(void)
> +void sctp_assocs_proc_exit(struct net *net)
> {
> - remove_proc_entry("assocs", proc_net_sctp);
> + remove_proc_entry("assocs", net->sctp.proc_net_sctp);
> }
>
> static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos)
> @@ -412,6 +426,7 @@ static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v)
>
> static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
> {
> + struct seq_net_private *priv = seq->private;
> struct sctp_hashbucket *head;
> struct sctp_ep_common *epb;
> struct sctp_association *assoc;
> @@ -426,6 +441,8 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
> sctp_local_bh_disable();
> read_lock(&head->lock);
> sctp_for_each_hentry(epb, node, &head->chain) {
> + if (!net_eq(sock_net(epb->sk), priv->net))
> + continue;
> assoc = sctp_assoc(epb);
> list_for_each_entry(tsp, &assoc->peer.transport_addr_list,
> transports) {
> @@ -489,14 +506,15 @@ static const struct seq_operations sctp_remaddr_ops = {
> };
>
> /* Cleanup the proc fs entry for 'remaddr' object. */
> -void sctp_remaddr_proc_exit(void)
> +void sctp_remaddr_proc_exit(struct net *net)
> {
> - remove_proc_entry("remaddr", proc_net_sctp);
> + remove_proc_entry("remaddr", net->sctp.proc_net_sctp);
> }
>
> static int sctp_remaddr_seq_open(struct inode *inode, struct file *file)
> {
> - return seq_open(file, &sctp_remaddr_ops);
> + return seq_open_net(inode, file, &sctp_remaddr_ops,
> + sizeof(struct seq_net_private));
> }
>
> static const struct file_operations sctp_remaddr_seq_fops = {
> @@ -506,11 +524,12 @@ static const struct file_operations sctp_remaddr_seq_fops = {
> .release = seq_release,
> };
>
> -int __init sctp_remaddr_proc_init(void)
> +int __net_init sctp_remaddr_proc_init(struct net *net)
> {
> struct proc_dir_entry *p;
>
> - p = proc_create("remaddr", S_IRUGO, proc_net_sctp, &sctp_remaddr_seq_fops);
> + p = proc_create("remaddr", S_IRUGO, net->sctp.proc_net_sctp,
> + &sctp_remaddr_seq_fops);
> if (!p)
> return -ENOMEM;
> return 0;
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 976d765..72b3aa7 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -71,10 +71,6 @@
> struct sctp_globals sctp_globals __read_mostly;
> DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly;
>
> -#ifdef CONFIG_PROC_FS
> -struct proc_dir_entry *proc_net_sctp;
> -#endif
> -
> struct idr sctp_assocs_id;
> DEFINE_SPINLOCK(sctp_assocs_id_lock);
>
> @@ -91,60 +87,52 @@ int sysctl_sctp_rmem[3];
> int sysctl_sctp_wmem[3];
>
> /* Set up the proc fs entry for the SCTP protocol. */
> -static __init int sctp_proc_init(void)
> +static __net_init int sctp_proc_init(struct net *net)
> {
> #ifdef CONFIG_PROC_FS
> - if (!proc_net_sctp) {
> - proc_net_sctp = proc_mkdir("sctp", init_net.proc_net);
> - if (!proc_net_sctp)
> - goto out_free_percpu;
> - }
> -
> - if (sctp_snmp_proc_init())
> + net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net);
> + if (!net->sctp.proc_net_sctp)
> + goto out_proc_net_sctp;
> + if (sctp_snmp_proc_init(net))
> goto out_snmp_proc_init;
> - if (sctp_eps_proc_init())
> + if (sctp_eps_proc_init(net))
> goto out_eps_proc_init;
> - if (sctp_assocs_proc_init())
> + if (sctp_assocs_proc_init(net))
> goto out_assocs_proc_init;
> - if (sctp_remaddr_proc_init())
> + if (sctp_remaddr_proc_init(net))
> goto out_remaddr_proc_init;
>
> return 0;
>
> out_remaddr_proc_init:
> - sctp_assocs_proc_exit();
> + sctp_assocs_proc_exit(net);
> out_assocs_proc_init:
> - sctp_eps_proc_exit();
> + sctp_eps_proc_exit(net);
> out_eps_proc_init:
> - sctp_snmp_proc_exit();
> + sctp_snmp_proc_exit(net);
> out_snmp_proc_init:
> - if (proc_net_sctp) {
> - proc_net_sctp = NULL;
> - remove_proc_entry("sctp", init_net.proc_net);
> - }
> -out_free_percpu:
> -#else
> - return 0;
> -#endif /* CONFIG_PROC_FS */
> + remove_proc_entry("sctp", net->proc_net);
> + net->sctp.proc_net_sctp = NULL;
> +out_proc_net_sctp:
> return -ENOMEM;
> +#endif /* CONFIG_PROC_FS */
> + return 0;
> }
>
> /* Clean up the proc fs entry for the SCTP protocol.
> * Note: Do not make this __exit as it is used in the init error
> * path.
> */
> -static void sctp_proc_exit(void)
> +static void sctp_proc_exit(struct net *net)
> {
> #ifdef CONFIG_PROC_FS
> - sctp_snmp_proc_exit();
> - sctp_eps_proc_exit();
> - sctp_assocs_proc_exit();
> - sctp_remaddr_proc_exit();
> -
> - if (proc_net_sctp) {
> - proc_net_sctp = NULL;
> - remove_proc_entry("sctp", init_net.proc_net);
> - }
> + sctp_snmp_proc_exit(net);
> + sctp_eps_proc_exit(net);
> + sctp_assocs_proc_exit(net);
> + sctp_remaddr_proc_exit(net);
> +
> + remove_proc_entry("sctp", net->proc_net);
> + net->sctp.proc_net_sctp = NULL;
> #endif
> }
>
> @@ -1180,6 +1168,11 @@ static int sctp_net_init(struct net *net)
> {
> int status;
>
> + /* Initialize proc fs directory. */
> + status = sctp_proc_init(net);
> + if (status)
> + goto err_init_proc;
> +
> /* Initialize the control inode/socket for handling OOTB packets. */
> if ((status = sctp_ctl_sock_init(net))) {
> pr_err("Failed to initialize the SCTP control sock\n");
> @@ -1202,6 +1195,8 @@ static int sctp_net_init(struct net *net)
> return 0;
>
> err_ctl_sock_init:
> + sctp_proc_exit(net);
> +err_init_proc:
> return status;
> }
>
> @@ -1213,6 +1208,8 @@ static void sctp_net_exit(struct net *net)
>
> /* Free the control endpoint. */
> inet_ctl_sock_destroy(net->sctp.ctl_sock);
> +
> + sctp_proc_exit(net);
> }
>
> static struct pernet_operations sctp_net_ops = {
> @@ -1259,11 +1256,6 @@ SCTP_STATIC __init int sctp_init(void)
> if (status)
> goto err_percpu_counter_init;
>
> - /* Initialize proc fs directory. */
> - status = sctp_proc_init();
> - if (status)
> - goto err_init_proc;
> -
> /* Initialize object count debugging. */
> sctp_dbg_objcnt_init();
>
> @@ -1477,8 +1469,6 @@ err_ehash_alloc:
> sizeof(struct sctp_hashbucket)));
> err_ahash_alloc:
> sctp_dbg_objcnt_exit();
> - sctp_proc_exit();
> -err_init_proc:
> percpu_counter_destroy(&sctp_sockets_allocated);
> err_percpu_counter_init:
> cleanup_sctp_mibs();
> @@ -1522,7 +1512,6 @@ SCTP_STATIC __exit void sctp_exit(void)
>
> sctp_dbg_objcnt_exit();
> percpu_counter_destroy(&sctp_sockets_allocated);
> - sctp_proc_exit();
> cleanup_sctp_mibs();
>
> rcu_barrier(); /* Wait for completion of call_rcu()'s */
>
On 08/06/2012 02:46 PM, Eric W. Biederman wrote:
>
> - Fix the sctp_af operations to work in all namespaces
> - Enable sctp socket creation in all network namespaces.
>
> Signed-off-by: "Eric W. Biederman" <[email protected]>
Acked-by: Vlad Yasevich <[email protected]>
> ---
> net/sctp/ipv6.c | 12 ++++++------
> net/sctp/protocol.c | 8 +++++---
> 2 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index bbf1534..a18cda6 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -582,7 +582,7 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
> if (!(type & IPV6_ADDR_UNICAST))
> return 0;
>
> - return ipv6_chk_addr(&init_net, in6, NULL, 0);
> + return ipv6_chk_addr(sock_net(&sp->inet.sk), in6, NULL, 0);
> }
>
> /* This function checks if the address is a valid address to be used for
> @@ -859,14 +859,14 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
> struct net_device *dev;
>
> if (type & IPV6_ADDR_LINKLOCAL) {
> + struct net *net;
> if (!addr->v6.sin6_scope_id)
> return 0;
> + net = sock_net(&opt->inet.sk);
> rcu_read_lock();
> - dev = dev_get_by_index_rcu(&init_net,
> - addr->v6.sin6_scope_id);
> + dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id);
> if (!dev ||
> - !ipv6_chk_addr(&init_net, &addr->v6.sin6_addr,
> - dev, 0)) {
> + !ipv6_chk_addr(net, &addr->v6.sin6_addr, dev, 0)) {
> rcu_read_unlock();
> return 0;
> }
> @@ -899,7 +899,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(sock_net(&opt->inet.sk),
> addr->v6.sin6_scope_id);
> rcu_read_unlock();
> if (!dev)
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 72b3aa7..ab35691 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -367,7 +367,8 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
> /* Should this be available for binding? */
> static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
> {
> - int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr);
> + struct net *net = sock_net(&sp->inet.sk);
> + int ret = inet_addr_type(net, addr->v4.sin_addr.s_addr);
>
>
> if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
> @@ -454,7 +455,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(sock_net(sk), fl4);
> if (!IS_ERR(rt))
> dst = &rt->dst;
>
> @@ -500,7 +501,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(sk), fl4);
> if (!IS_ERR(rt)) {
> dst = &rt->dst;
> goto out_unlock;
> @@ -1033,6 +1034,7 @@ static const struct net_protocol sctp_protocol = {
> .handler = sctp_rcv,
> .err_handler = sctp_v4_err,
> .no_policy = 1,
> + .netns_ok = 1,
> };
>
> /* IPv4 address related functions. */
>
On 08/06/2012 02:47 PM, Eric W. Biederman wrote:
>
> Signed-off-by: "Eric W. Biederman" <[email protected]>
Acked-by: Vlad Yasevich <[email protected]>
> ---
> include/net/netns/sctp.h | 3 +
> include/net/sctp/sctp.h | 9 +--
> net/sctp/associola.c | 2 +-
> net/sctp/chunk.c | 2 +-
> net/sctp/endpointola.c | 2 +-
> net/sctp/input.c | 22 +++---
> net/sctp/ipv6.c | 4 +-
> net/sctp/output.c | 2 +-
> net/sctp/outqueue.c | 18 +++--
> net/sctp/proc.c | 5 +-
> net/sctp/protocol.c | 27 ++++----
> net/sctp/sm_statefuns.c | 163 +++++++++++++++++++++++++++------------------
> net/sctp/ulpqueue.c | 18 ++++--
> 13 files changed, 158 insertions(+), 119 deletions(-)
>
> diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
> index 9c20a82..06ccddf 100644
> --- a/include/net/netns/sctp.h
> +++ b/include/net/netns/sctp.h
> @@ -3,8 +3,11 @@
>
> struct sock;
> struct proc_dir_entry;
> +struct sctp_mib;
>
> struct netns_sctp {
> + DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
> +
> #ifdef CONFIG_PROC_FS
> struct proc_dir_entry *proc_net_sctp;
> #endif
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index ca716da..b0e6fe5 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -221,11 +221,10 @@ extern struct kmem_cache *sctp_bucket_cachep __read_mostly;
> #define sctp_bh_unlock_sock(sk) bh_unlock_sock(sk)
>
> /* SCTP SNMP MIB stats handlers */
> -DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics);
> -#define SCTP_INC_STATS(field) SNMP_INC_STATS(sctp_statistics, field)
> -#define SCTP_INC_STATS_BH(field) SNMP_INC_STATS_BH(sctp_statistics, field)
> -#define SCTP_INC_STATS_USER(field) SNMP_INC_STATS_USER(sctp_statistics, field)
> -#define SCTP_DEC_STATS(field) SNMP_DEC_STATS(sctp_statistics, field)
> +#define SCTP_INC_STATS(net, field) SNMP_INC_STATS((net)->sctp.sctp_statistics, field)
> +#define SCTP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->sctp.sctp_statistics, field)
> +#define SCTP_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->sctp.sctp_statistics, field)
> +#define SCTP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->sctp.sctp_statistics, field)
>
> #endif /* !TEST_FRAME */
>
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index ed4930b..8a1f27a 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -1150,7 +1150,7 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
> if (sctp_chunk_is_data(chunk))
> asoc->peer.last_data_from = chunk->transport;
> else
> - SCTP_INC_STATS(SCTP_MIB_INCTRLCHUNKS);
> + SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_INCTRLCHUNKS);
>
> if (chunk->transport)
> chunk->transport->last_time_heard = jiffies;
> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
> index 6c85564..7c2df9c 100644
> --- a/net/sctp/chunk.c
> +++ b/net/sctp/chunk.c
> @@ -257,7 +257,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> offset = 0;
>
> if ((whole > 1) || (whole && over))
> - SCTP_INC_STATS_USER(SCTP_MIB_FRAGUSRMSGS);
> + SCTP_INC_STATS_USER(sock_net(asoc->base.sk), SCTP_MIB_FRAGUSRMSGS);
>
> /* Create chunks for all the full sized DATA chunks. */
> for (i=0, len=first_len; i < whole; i++) {
> diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
> index 6b76393..3edca80 100644
> --- a/net/sctp/endpointola.c
> +++ b/net/sctp/endpointola.c
> @@ -478,7 +478,7 @@ normal:
> if (asoc && sctp_chunk_is_data(chunk))
> asoc->peer.last_data_from = chunk->transport;
> else
> - SCTP_INC_STATS(SCTP_MIB_INCTRLCHUNKS);
> + SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_INCTRLCHUNKS);
>
> if (chunk->transport)
> chunk->transport->last_time_heard = jiffies;
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index c9a0449..5308301 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -83,7 +83,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb);
>
>
> /* Calculate the SCTP checksum of an SCTP packet. */
> -static inline int sctp_rcv_checksum(struct sk_buff *skb)
> +static inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb)
> {
> struct sctphdr *sh = sctp_hdr(skb);
> __le32 cmp = sh->checksum;
> @@ -99,7 +99,7 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb)
>
> if (val != cmp) {
> /* CRC failure, dump it. */
> - SCTP_INC_STATS_BH(SCTP_MIB_CHECKSUMERRORS);
> + SCTP_INC_STATS_BH(net, SCTP_MIB_CHECKSUMERRORS);
> return -1;
> }
> return 0;
> @@ -137,7 +137,7 @@ int sctp_rcv(struct sk_buff *skb)
> if (skb->pkt_type!=PACKET_HOST)
> goto discard_it;
>
> - SCTP_INC_STATS_BH(SCTP_MIB_INSCTPPACKS);
> + SCTP_INC_STATS_BH(net, SCTP_MIB_INSCTPPACKS);
>
> if (skb_linearize(skb))
> goto discard_it;
> @@ -149,7 +149,7 @@ int sctp_rcv(struct sk_buff *skb)
> if (skb->len < sizeof(struct sctphdr))
> goto discard_it;
> if (!sctp_checksum_disable && !skb_csum_unnecessary(skb) &&
> - sctp_rcv_checksum(skb) < 0)
> + sctp_rcv_checksum(net, skb) < 0)
> goto discard_it;
>
> skb_pull(skb, sizeof(struct sctphdr));
> @@ -220,7 +220,7 @@ int sctp_rcv(struct sk_buff *skb)
> */
> if (!asoc) {
> if (sctp_rcv_ootb(skb)) {
> - SCTP_INC_STATS_BH(SCTP_MIB_OUTOFBLUES);
> + SCTP_INC_STATS_BH(net, SCTP_MIB_OUTOFBLUES);
> goto discard_release;
> }
> }
> @@ -276,9 +276,9 @@ int sctp_rcv(struct sk_buff *skb)
> skb = NULL; /* sctp_chunk_free already freed the skb */
> goto discard_release;
> }
> - SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG);
> + SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_BACKLOG);
> } else {
> - SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ);
> + SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_SOFTIRQ);
> sctp_inq_push(&chunk->rcvr->inqueue, chunk);
> }
>
> @@ -293,7 +293,7 @@ int sctp_rcv(struct sk_buff *skb)
> return 0;
>
> discard_it:
> - SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_DISCARDS);
> + SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_DISCARDS);
> kfree_skb(skb);
> return 0;
>
> @@ -543,7 +543,7 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
> * servers this needs to be solved differently.
> */
> if (sock_owned_by_user(sk))
> - NET_INC_STATS_BH(&init_net, LINUX_MIB_LOCKDROPPEDICMPS);
> + NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
>
> *app = asoc;
> *tpp = transport;
> @@ -593,7 +593,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
> struct net *net = dev_net(skb->dev);
>
> if (skb->len < ihlen + 8) {
> - ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
> + ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
> return;
> }
>
> @@ -607,7 +607,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
> skb->network_header = saveip;
> skb->transport_header = savesctp;
> if (!sk) {
> - ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
> + ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
> return;
> }
> /* Warning: The sock lock is held. Remember to call
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index a18cda6..ea14cb4 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -169,7 +169,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
> skb->network_header = saveip;
> skb->transport_header = savesctp;
> if (!sk) {
> - ICMP6_INC_STATS_BH(dev_net(skb->dev), idev, ICMP6_MIB_INERRORS);
> + ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_INERRORS);
> goto out;
> }
>
> @@ -243,7 +243,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
> __func__, skb, skb->len,
> &fl6.saddr, &fl6.daddr);
>
> - SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
> + SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS);
>
> if (!(transport->param_flags & SPP_PMTUD_ENABLE))
> skb->local_df = 1;
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 838e18b..0c6359b 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -597,7 +597,7 @@ out:
> return err;
> no_route:
> kfree_skb(nskb);
> - IP_INC_STATS_BH(&init_net, IPSTATS_MIB_OUTNOROUTES);
> + IP_INC_STATS_BH(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES);
>
> /* FIXME: Returning the 'err' will effect all the associations
> * associated with a socket, although only one of the paths of the
> diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
> index e7aa177c..072bf6a 100644
> --- a/net/sctp/outqueue.c
> +++ b/net/sctp/outqueue.c
> @@ -299,6 +299,7 @@ void sctp_outq_free(struct sctp_outq *q)
> /* Put a new chunk in an sctp_outq. */
> int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
> {
> + struct net *net = sock_net(q->asoc->base.sk);
> int error = 0;
>
> SCTP_DEBUG_PRINTK("sctp_outq_tail(%p, %p[%s])\n",
> @@ -337,15 +338,15 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
>
> sctp_outq_tail_data(q, chunk);
> if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
> - SCTP_INC_STATS(SCTP_MIB_OUTUNORDERCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);
> else
> - SCTP_INC_STATS(SCTP_MIB_OUTORDERCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS);
> q->empty = 0;
> break;
> }
> } else {
> list_add_tail(&chunk->list, &q->control_chunk_list);
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
> }
>
> if (error < 0)
> @@ -478,11 +479,12 @@ void sctp_retransmit_mark(struct sctp_outq *q,
> void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
> sctp_retransmit_reason_t reason)
> {
> + struct net *net = sock_net(q->asoc->base.sk);
> int error = 0;
>
> switch(reason) {
> case SCTP_RTXR_T3_RTX:
> - SCTP_INC_STATS(SCTP_MIB_T3_RETRANSMITS);
> + SCTP_INC_STATS(net, SCTP_MIB_T3_RETRANSMITS);
> sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX);
> /* Update the retran path if the T3-rtx timer has expired for
> * the current retran path.
> @@ -493,15 +495,15 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
> transport->asoc->unack_data;
> break;
> case SCTP_RTXR_FAST_RTX:
> - SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
> + SCTP_INC_STATS(net, SCTP_MIB_FAST_RETRANSMITS);
> sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
> q->fast_rtx = 1;
> break;
> case SCTP_RTXR_PMTUD:
> - SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS);
> + SCTP_INC_STATS(net, SCTP_MIB_PMTUD_RETRANSMITS);
> break;
> case SCTP_RTXR_T1_RTX:
> - SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS);
> + SCTP_INC_STATS(net, SCTP_MIB_T1_RETRANSMITS);
> transport->asoc->init_retries++;
> break;
> default:
> @@ -1914,6 +1916,6 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
>
> if (ftsn_chunk) {
> list_add_tail(&ftsn_chunk->list, &q->control_chunk_list);
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
> }
> }
> diff --git a/net/sctp/proc.c b/net/sctp/proc.c
> index dc79a3a..3e62ee5 100644
> --- a/net/sctp/proc.c
> +++ b/net/sctp/proc.c
> @@ -83,12 +83,9 @@ static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
> struct net *net = seq->private;
> int i;
>
> - if (!net_eq(net, &init_net))
> - return 0;
> -
> for (i = 0; sctp_snmp_list[i].name != NULL; i++)
> seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
> - snmp_fold_field((void __percpu **)sctp_statistics,
> + snmp_fold_field((void __percpu **)net->sctp.sctp_statistics,
> sctp_snmp_list[i].entry));
>
> return 0;
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index ab35691..69bdc72 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -69,7 +69,6 @@
>
> /* Global data structures. */
> struct sctp_globals sctp_globals __read_mostly;
> -DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly;
>
> struct idr sctp_assocs_id;
> DEFINE_SPINLOCK(sctp_assocs_id_lock);
> @@ -961,7 +960,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
> inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
> IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
>
> - SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
> + SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS);
> return ip_queue_xmit(skb, &transport->fl);
> }
>
> @@ -1102,16 +1101,16 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family)
> return 1;
> }
>
> -static inline int init_sctp_mibs(void)
> +static inline int init_sctp_mibs(struct net *net)
> {
> - return snmp_mib_init((void __percpu **)sctp_statistics,
> + return snmp_mib_init((void __percpu **)net->sctp.sctp_statistics,
> sizeof(struct sctp_mib),
> __alignof__(struct sctp_mib));
> }
>
> -static inline void cleanup_sctp_mibs(void)
> +static inline void cleanup_sctp_mibs(struct net *net)
> {
> - snmp_mib_free((void __percpu **)sctp_statistics);
> + snmp_mib_free((void __percpu **)net->sctp.sctp_statistics);
> }
>
> static void sctp_v4_pf_init(void)
> @@ -1170,6 +1169,11 @@ static int sctp_net_init(struct net *net)
> {
> int status;
>
> + /* Allocate and initialise sctp mibs. */
> + status = init_sctp_mibs(net);
> + if (status)
> + goto err_init_mibs;
> +
> /* Initialize proc fs directory. */
> status = sctp_proc_init(net);
> if (status)
> @@ -1199,6 +1203,8 @@ static int sctp_net_init(struct net *net)
> err_ctl_sock_init:
> sctp_proc_exit(net);
> err_init_proc:
> + cleanup_sctp_mibs(net);
> +err_init_mibs:
> return status;
> }
>
> @@ -1212,6 +1218,7 @@ static void sctp_net_exit(struct net *net)
> inet_ctl_sock_destroy(net->sctp.ctl_sock);
>
> sctp_proc_exit(net);
> + cleanup_sctp_mibs(net);
> }
>
> static struct pernet_operations sctp_net_ops = {
> @@ -1249,11 +1256,6 @@ SCTP_STATIC __init int sctp_init(void)
> if (!sctp_chunk_cachep)
> goto err_chunk_cachep;
>
> - /* Allocate and initialise sctp mibs. */
> - status = init_sctp_mibs();
> - if (status)
> - goto err_init_mibs;
> -
> status = percpu_counter_init(&sctp_sockets_allocated, 0);
> if (status)
> goto err_percpu_counter_init;
> @@ -1473,8 +1475,6 @@ err_ahash_alloc:
> sctp_dbg_objcnt_exit();
> percpu_counter_destroy(&sctp_sockets_allocated);
> err_percpu_counter_init:
> - cleanup_sctp_mibs();
> -err_init_mibs:
> kmem_cache_destroy(sctp_chunk_cachep);
> err_chunk_cachep:
> kmem_cache_destroy(sctp_bucket_cachep);
> @@ -1514,7 +1514,6 @@ SCTP_STATIC __exit void sctp_exit(void)
>
> sctp_dbg_objcnt_exit();
> percpu_counter_destroy(&sctp_sockets_allocated);
> - cleanup_sctp_mibs();
>
> rcu_barrier(); /* Wait for completion of call_rcu()'s */
>
> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> index f2daf61..bee5e2c 100644
> --- a/net/sctp/sm_statefuns.c
> +++ b/net/sctp/sm_statefuns.c
> @@ -213,6 +213,7 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
> {
> struct sctp_chunk *chunk = arg;
> struct sctp_ulpevent *ev;
> + struct net *net;
>
> if (!sctp_vtag_verify_either(chunk, asoc))
> return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
> @@ -260,8 +261,9 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
> sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
> SCTP_STATE(SCTP_STATE_CLOSED));
>
> - SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + net = sock_net(asoc->base.sk);
> + SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>
> sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
>
> @@ -322,7 +324,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
> */
> net = sock_net(ep->base.sk);
> if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
> - SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
> return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
> }
>
> @@ -369,7 +371,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
> if (packet) {
> sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
> SCTP_PACKET(packet));
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
> return SCTP_DISPOSITION_CONSUME;
> } else {
> return SCTP_DISPOSITION_NOMEM;
> @@ -540,7 +542,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
> if (packet) {
> sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
> SCTP_PACKET(packet));
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
> error = SCTP_ERROR_INV_PARAM;
> }
> }
> @@ -559,7 +561,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
> if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
> return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
>
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> + SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_ABORTEDS);
> return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED,
> asoc, chunk->transport);
> }
> @@ -656,7 +658,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
> */
> net = sock_net(ep->base.sk);
> if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
> - SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
> return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
> }
>
> @@ -809,8 +811,8 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
> sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
> sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
> SCTP_STATE(SCTP_STATE_ESTABLISHED));
> - SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
> - SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS);
> + SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
> + SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS);
> sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
>
> if (new_asoc->autoclose)
> @@ -868,6 +870,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
> {
> struct sctp_chunk *chunk = arg;
> struct sctp_ulpevent *ev;
> + struct net *net;
>
> if (!sctp_vtag_verify(chunk, asoc))
> return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
> @@ -897,8 +900,9 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
> SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
> sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
> SCTP_STATE(SCTP_STATE_ESTABLISHED));
> - SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
> - SCTP_INC_STATS(SCTP_MIB_ACTIVEESTABS);
> + net = sock_net(ep->base.sk);
> + SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
> + SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS);
> sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
> if (asoc->autoclose)
> sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
> @@ -972,13 +976,15 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
> struct sctp_transport *transport = (struct sctp_transport *) arg;
>
> if (asoc->overall_error_count >= asoc->max_retrans) {
> + struct net *net;
> sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
> SCTP_ERROR(ETIMEDOUT));
> /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
> SCTP_PERR(SCTP_ERROR_NO_ERROR));
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + net = sock_net(ep->base.sk);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
> return SCTP_DISPOSITION_DELETE_TCB;
> }
>
> @@ -1213,7 +1219,7 @@ static int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa,
> goto out;
> sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, SCTP_PACKET(pkt));
>
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>
> /* Discard the rest of the inbound packet. */
> sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
> @@ -1427,7 +1433,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
> if (packet) {
> sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
> SCTP_PACKET(packet));
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
> retval = SCTP_DISPOSITION_CONSUME;
> } else {
> retval = SCTP_DISPOSITION_NOMEM;
> @@ -1791,7 +1797,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
> sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
> sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
> SCTP_STATE(SCTP_STATE_ESTABLISHED));
> - SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
> + SCTP_INC_STATS(sock_net(new_asoc->base.sk), SCTP_MIB_CURRESTAB);
> sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
>
> repl = sctp_make_cookie_ack(new_asoc, chunk);
> @@ -1883,7 +1889,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
> SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
> sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
> SCTP_STATE(SCTP_STATE_ESTABLISHED));
> - SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
> + SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_CURRESTAB);
> sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START,
> SCTP_NULL());
>
> @@ -2417,6 +2423,7 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
> struct sctp_chunk *chunk = arg;
> unsigned int len;
> __be16 error = SCTP_ERROR_NO_ERROR;
> + struct net *net;
>
> /* See if we have an error cause code in the chunk. */
> len = ntohs(chunk->chunk_hdr->length);
> @@ -2433,8 +2440,9 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
> sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET));
> /* ASSOC_FAILED will DELETE_TCB. */
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error));
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + net = sock_net(ep->base.sk);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>
> return SCTP_DISPOSITION_ABORT;
> }
> @@ -2521,7 +2529,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
> SCTP_DEBUG_PRINTK("ABORT received (INIT).\n");
> sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
> SCTP_STATE(SCTP_STATE_CLOSED));
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> + SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_ABORTEDS);
> sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
> SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
> sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err));
> @@ -2904,11 +2912,11 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
> break;
> case SCTP_IERROR_HIGH_TSN:
> case SCTP_IERROR_BAD_STREAM:
> - SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
> + SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
> goto discard_noforce;
> case SCTP_IERROR_DUP_TSN:
> case SCTP_IERROR_IGNORE_TSN:
> - SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
> + SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
> goto discard_force;
> case SCTP_IERROR_NO_DATA:
> goto consume;
> @@ -3197,7 +3205,7 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
> sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
> SCTP_PACKET(packet));
>
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>
> sctp_sf_pdiscard(ep, asoc, type, arg, commands);
> return SCTP_DISPOSITION_CONSUME;
> @@ -3260,6 +3268,7 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
> struct sctp_chunk *chunk = arg;
> struct sctp_chunk *reply;
> struct sctp_ulpevent *ev;
> + struct net *net;
>
> if (!sctp_vtag_verify(chunk, asoc))
> return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
> @@ -3299,8 +3308,9 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
>
> sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
> SCTP_STATE(SCTP_STATE_CLOSED));
> - SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + net = sock_net(asoc->base.sk);
> + SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
> sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
>
> /* ...and remove all record of the association. */
> @@ -3346,8 +3356,10 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
> __u8 *ch_end;
> int ootb_shut_ack = 0;
> int ootb_cookie_ack = 0;
> + struct net *net;
>
> - SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
> + net = sock_net(asoc->base.sk);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
>
> ch = (sctp_chunkhdr_t *) chunk->chunk_hdr;
> do {
> @@ -3461,7 +3473,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
> sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
> SCTP_PACKET(packet));
>
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>
> /* If the chunk length is invalid, we don't want to process
> * the reset of the packet.
> @@ -3508,7 +3520,7 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep,
> * packet and the state function that handles OOTB SHUTDOWN_ACK is
> * called with a NULL association.
> */
> - SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
> + SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTOFBLUES);
>
> return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands);
> }
> @@ -3699,6 +3711,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
> */
> if (ADDIP_SERIAL_gte(rcvd_serial, sent_serial + 1) &&
> !(asoc->addip_last_asconf)) {
> + struct net *net;
> abort = sctp_make_abort(asoc, asconf_ack,
> sizeof(sctp_errhdr_t));
> if (abort) {
> @@ -3716,12 +3729,14 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
> SCTP_ERROR(ECONNABORTED));
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
> SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + net = sock_net(asoc->base.sk);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
> return SCTP_DISPOSITION_ABORT;
> }
>
> if ((rcvd_serial == sent_serial) && asoc->addip_last_asconf) {
> + struct net *net;
> sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
> SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
>
> @@ -3750,8 +3765,9 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
> SCTP_ERROR(ECONNABORTED));
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
> SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + net = sock_net(asoc->base.sk);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
> return SCTP_DISPOSITION_ABORT;
> }
>
> @@ -4222,7 +4238,7 @@ sctp_disposition_t sctp_sf_pdiscard(const struct sctp_endpoint *ep,
> void *arg,
> sctp_cmd_seq_t *commands)
> {
> - SCTP_INC_STATS(SCTP_MIB_IN_PKT_DISCARDS);
> + SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_PKT_DISCARDS);
> sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
>
> return SCTP_DISPOSITION_CONSUME;
> @@ -4315,7 +4331,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
> }
>
> sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>
> if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) {
> sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
> @@ -4329,7 +4345,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
> SCTP_ERROR(ECONNABORTED));
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
> SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
> }
> } else {
> packet = sctp_ootb_pkt_new(net, asoc, chunk);
> @@ -4347,10 +4363,10 @@ static sctp_disposition_t sctp_sf_abort_violation(
> sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
> SCTP_PACKET(packet));
>
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
> }
>
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
>
> discard:
> sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
> @@ -4410,6 +4426,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
> struct sctp_chunk *chunk = arg;
> struct sctp_paramhdr *param = ext;
> struct sctp_chunk *abort = NULL;
> + struct net *net;
>
> if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
> goto discard;
> @@ -4419,15 +4436,16 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
> if (!abort)
> goto nomem;
>
> + net = sock_net(asoc->base.sk);
> sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>
> sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
> SCTP_ERROR(ECONNABORTED));
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
> SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
>
> discard:
> sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
> @@ -4757,6 +4775,7 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
> */
> struct sctp_chunk *abort = arg;
> sctp_disposition_t retval;
> + struct net *net;
>
> retval = SCTP_DISPOSITION_CONSUME;
>
> @@ -4772,8 +4791,9 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
> SCTP_PERR(SCTP_ERROR_USER_ABORT));
>
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + net = sock_net(asoc->base.sk);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>
> return retval;
> }
> @@ -4824,13 +4844,15 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_shutdown(
> void *arg,
> sctp_cmd_seq_t *commands)
> {
> + struct net *net = sock_net(asoc->base.sk);
> +
> sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
> SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
>
> sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
> SCTP_STATE(SCTP_STATE_CLOSED));
>
> - SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);
> + SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS);
>
> sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
>
> @@ -4886,6 +4908,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
> {
> struct sctp_chunk *abort = arg;
> sctp_disposition_t retval;
> + struct net *net = sock_net(asoc->base.sk);
>
> /* Stop T1-init timer */
> sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
> @@ -4897,7 +4920,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
> sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
> SCTP_STATE(SCTP_STATE_CLOSED));
>
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
>
> /* Even if we can't send the ABORT due to low memory delete the
> * TCB. This is a departure from our typical NOMEM handling.
> @@ -5318,8 +5341,9 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
> sctp_cmd_seq_t *commands)
> {
> struct sctp_transport *transport = arg;
> + struct net *net = sock_net(asoc->base.sk);
>
> - SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS);
> + SCTP_INC_STATS(net, SCTP_MIB_T3_RTX_EXPIREDS);
>
> if (asoc->overall_error_count >= asoc->max_retrans) {
> if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) {
> @@ -5340,8 +5364,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
> /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
> SCTP_PERR(SCTP_ERROR_NO_ERROR));
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
> return SCTP_DISPOSITION_DELETE_TCB;
> }
> }
> @@ -5403,7 +5427,8 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
> void *arg,
> sctp_cmd_seq_t *commands)
> {
> - SCTP_INC_STATS(SCTP_MIB_DELAY_SACK_EXPIREDS);
> + struct net *net = sock_net(asoc->base.sk);
> + SCTP_INC_STATS(net, SCTP_MIB_DELAY_SACK_EXPIREDS);
> sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE());
> return SCTP_DISPOSITION_CONSUME;
> }
> @@ -5436,9 +5461,10 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
> struct sctp_chunk *repl = NULL;
> struct sctp_bind_addr *bp;
> int attempts = asoc->init_err_counter + 1;
> + struct net *net = sock_net(asoc->base.sk);
>
> SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
> - SCTP_INC_STATS(SCTP_MIB_T1_INIT_EXPIREDS);
> + SCTP_INC_STATS(net, SCTP_MIB_T1_INIT_EXPIREDS);
>
> if (attempts <= asoc->max_init_attempts) {
> bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
> @@ -5496,9 +5522,10 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
> {
> struct sctp_chunk *repl = NULL;
> int attempts = asoc->init_err_counter + 1;
> + struct net *net = sock_net(asoc->base.sk);
>
> SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
> - SCTP_INC_STATS(SCTP_MIB_T1_COOKIE_EXPIREDS);
> + SCTP_INC_STATS(net, SCTP_MIB_T1_COOKIE_EXPIREDS);
>
> if (attempts <= asoc->max_init_attempts) {
> repl = sctp_make_cookie_echo(asoc, NULL);
> @@ -5543,9 +5570,10 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
> sctp_cmd_seq_t *commands)
> {
> struct sctp_chunk *reply = NULL;
> + struct net *net = sock_net(asoc->base.sk);
>
> SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
> - SCTP_INC_STATS(SCTP_MIB_T2_SHUTDOWN_EXPIREDS);
> + SCTP_INC_STATS(net, SCTP_MIB_T2_SHUTDOWN_EXPIREDS);
>
> ((struct sctp_association *)asoc)->shutdown_retries++;
>
> @@ -5555,8 +5583,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
> /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
> SCTP_PERR(SCTP_ERROR_NO_ERROR));
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
> return SCTP_DISPOSITION_DELETE_TCB;
> }
>
> @@ -5613,8 +5641,9 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
> {
> struct sctp_chunk *chunk = asoc->addip_last_asconf;
> struct sctp_transport *transport = chunk->transport;
> + struct net *net = sock_net(asoc->base.sk);
>
> - SCTP_INC_STATS(SCTP_MIB_T4_RTO_EXPIREDS);
> + SCTP_INC_STATS(net, SCTP_MIB_T4_RTO_EXPIREDS);
>
> /* ADDIP 4.1 B1) Increment the error counters and perform path failure
> * detection on the appropriate destination address as defined in
> @@ -5639,8 +5668,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
> SCTP_ERROR(ETIMEDOUT));
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
> SCTP_PERR(SCTP_ERROR_NO_ERROR));
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
> return SCTP_DISPOSITION_ABORT;
> }
>
> @@ -5682,9 +5711,10 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
> sctp_cmd_seq_t *commands)
> {
> struct sctp_chunk *reply = NULL;
> + struct net *net = sock_net(asoc->base.sk);
>
> SCTP_DEBUG_PRINTK("Timer T5 expired.\n");
> - SCTP_INC_STATS(SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS);
> + SCTP_INC_STATS(net, SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS);
>
> reply = sctp_make_abort(asoc, NULL, 0);
> if (!reply)
> @@ -5696,8 +5726,8 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
> SCTP_PERR(SCTP_ERROR_NO_ERROR));
>
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>
> return SCTP_DISPOSITION_DELETE_TCB;
> nomem:
> @@ -5716,9 +5746,10 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire(
> void *arg,
> sctp_cmd_seq_t *commands)
> {
> + struct net *net = sock_net(asoc->base.sk);
> int disposition;
>
> - SCTP_INC_STATS(SCTP_MIB_AUTOCLOSE_EXPIREDS);
> + SCTP_INC_STATS(net, SCTP_MIB_AUTOCLOSE_EXPIREDS);
>
> /* From 9.2 Shutdown of an Association
> * Upon receipt of the SHUTDOWN primitive from its upper
> @@ -5976,7 +6007,7 @@ static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
> sctp_packet_append_chunk(packet, err_chunk);
> sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
> SCTP_PACKET(packet));
> - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
> } else
> sctp_chunk_free (err_chunk);
> }
> @@ -5996,6 +6027,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
> __u32 tsn;
> struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
> struct sock *sk = asoc->base.sk;
> + struct net *net;
> u16 ssn;
> u16 sid;
> u8 ordered = 0;
> @@ -6112,6 +6144,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
> * No User Data: This error cause is returned to the originator of a
> * DATA chunk if a received DATA chunk has no user data.
> */
> + net = sock_net(sk);
> if (unlikely(0 == datalen)) {
> err = sctp_make_abort_no_data(asoc, chunk, tsn);
> if (err) {
> @@ -6126,8 +6159,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
> SCTP_ERROR(ECONNABORTED));
> sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
> SCTP_PERR(SCTP_ERROR_NO_DATA));
> - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
> return SCTP_IERROR_NO_DATA;
> }
>
> @@ -6137,9 +6170,9 @@ static int sctp_eat_data(const struct sctp_association *asoc,
> * if we renege and the chunk arrives again.
> */
> if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
> - SCTP_INC_STATS(SCTP_MIB_INUNORDERCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_INUNORDERCHUNKS);
> else {
> - SCTP_INC_STATS(SCTP_MIB_INORDERCHUNKS);
> + SCTP_INC_STATS(net, SCTP_MIB_INORDERCHUNKS);
> ordered = 1;
> }
>
> diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
> index f5a6a4f..360d869 100644
> --- a/net/sctp/ulpqueue.c
> +++ b/net/sctp/ulpqueue.c
> @@ -326,7 +326,9 @@ static void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
> * payload was fragmented on the way and ip had to reassemble them.
> * We add the rest of skb's to the first skb's fraglist.
> */
> -static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag)
> +static struct sctp_ulpevent *sctp_make_reassembled_event(struct net *net,
> + struct sk_buff_head *queue, struct sk_buff *f_frag,
> + struct sk_buff *l_frag)
> {
> struct sk_buff *pos;
> struct sk_buff *new = NULL;
> @@ -394,7 +396,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu
> }
>
> event = sctp_skb2event(f_frag);
> - SCTP_INC_STATS(SCTP_MIB_REASMUSRMSGS);
> + SCTP_INC_STATS(net, SCTP_MIB_REASMUSRMSGS);
>
> return event;
> }
> @@ -493,7 +495,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul
> cevent = sctp_skb2event(pd_first);
> pd_point = sctp_sk(asoc->base.sk)->pd_point;
> if (pd_point && pd_point <= pd_len) {
> - retval = sctp_make_reassembled_event(&ulpq->reasm,
> + retval = sctp_make_reassembled_event(sock_net(asoc->base.sk),
> + &ulpq->reasm,
> pd_first,
> pd_last);
> if (retval)
> @@ -503,7 +506,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul
> done:
> return retval;
> found:
> - retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, pos);
> + retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
> + &ulpq->reasm, first_frag, pos);
> if (retval)
> retval->msg_flags |= MSG_EOR;
> goto done;
> @@ -563,7 +567,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq)
> * further.
> */
> done:
> - retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag);
> + retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
> + &ulpq->reasm, first_frag, last_frag);
> if (retval && is_last)
> retval->msg_flags |= MSG_EOR;
>
> @@ -655,7 +660,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq)
> * further.
> */
> done:
> - retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag);
> + retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
> + &ulpq->reasm, first_frag, last_frag);
> return retval;
> }
>
>
On 08/07/2012 01:23 PM, Eric W. Biederman wrote:
>
> Start with an empty sctp_net_table that will be populated as the various
> tunable sysctls are made per net.
>
> Signed-off-by: "Eric W. Biederman" <[email protected]>
Acked-by: Vlad Yasevich <[email protected]>
> ---
> include/net/netns/sctp.h | 6 +++++-
> include/net/sctp/sctp.h | 4 ++++
> net/sctp/protocol.c | 7 +++++++
> net/sctp/sysctl.c | 21 +++++++++++++++++++++
> 4 files changed, 37 insertions(+), 1 deletions(-)
>
> diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
> index 06ccddf..9576b60 100644
> --- a/include/net/netns/sctp.h
> +++ b/include/net/netns/sctp.h
> @@ -4,6 +4,7 @@
> struct sock;
> struct proc_dir_entry;
> struct sctp_mib;
> +struct ctl_table_header;
>
> struct netns_sctp {
> DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
> @@ -11,7 +12,9 @@ struct netns_sctp {
> #ifdef CONFIG_PROC_FS
> struct proc_dir_entry *proc_net_sctp;
> #endif
> -
> +#ifdef CONFIG_SYSCTL
> + struct ctl_table_header *sysctl_header;
> +#endif
> /* This is the global socket data structure used for responding to
> * the Out-of-the-blue (OOTB) packets. A control sock will be created
> * for this socket at the initialization time.
> @@ -32,6 +35,7 @@ struct netns_sctp {
>
> /* Lock that protects the local_addr_list writers */
> spinlock_t local_addr_lock;
> +
> };
>
> #endif /* __NETNS_SCTP_H__ */
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index b0e6fe5..15037e7 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -375,9 +375,13 @@ static inline void sctp_dbg_objcnt_exit(void) { return; }
> #if defined CONFIG_SYSCTL
> void sctp_sysctl_register(void);
> void sctp_sysctl_unregister(void);
> +int sctp_sysctl_net_register(struct net *net);
> +void sctp_sysctl_net_unregister(struct net *net);
> #else
> static inline void sctp_sysctl_register(void) { return; }
> static inline void sctp_sysctl_unregister(void) { return; }
> +static inline int sctp_sysctl_net_register(struct net *net) { return 0; }
> +static inline void sctp_sysctl_net_unregister(struct net *net) { return; }
> #endif
>
> /* Size of Supported Address Parameter for 'x' address types. */
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 69bdc72..de25d9c 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -1169,6 +1169,10 @@ static int sctp_net_init(struct net *net)
> {
> int status;
>
> + status = sctp_sysctl_net_register(net);
> + if (status)
> + goto err_sysctl_register;
> +
> /* Allocate and initialise sctp mibs. */
> status = init_sctp_mibs(net);
> if (status)
> @@ -1205,6 +1209,8 @@ err_ctl_sock_init:
> err_init_proc:
> cleanup_sctp_mibs(net);
> err_init_mibs:
> + sctp_sysctl_net_unregister(net);
> +err_sysctl_register:
> return status;
> }
>
> @@ -1219,6 +1225,7 @@ static void sctp_net_exit(struct net *net)
>
> sctp_proc_exit(net);
> cleanup_sctp_mibs(net);
> + sctp_sysctl_net_unregister(net);
> }
>
> static struct pernet_operations sctp_net_ops = {
> diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
> index 2b2bfe9..7528d59 100644
> --- a/net/sctp/sysctl.c
> +++ b/net/sctp/sysctl.c
> @@ -284,6 +284,27 @@ static ctl_table sctp_table[] = {
> { /* sentinel */ }
> };
>
> +static ctl_table sctp_net_table[] = {
> + { /* sentinel */ }
> +};
> +
> +int sctp_sysctl_net_register(struct net *net)
> +{
> + struct ctl_table *table;
> +
> + table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
> + if (!table)
> + return -ENOMEM;
> +
> + net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table);
> + return 0;
> +}
> +
> +void sctp_sysctl_net_unregister(struct net *net)
> +{
> + unregister_net_sysctl_table(net->sctp.sysctl_header);
> +}
> +
> static struct ctl_table_header * sctp_sysctl_header;
>
> /* Sysctl registration. */
>
On 08/07/2012 01:17 PM, Eric W. Biederman wrote:
>
> Since I am motivated to get things done, and since there has been much
> grumbling about my patches not implementing tunables, I have added
> tunable support on top of my last patchset.
>
> I have performed basic testing on the these patches and nothing
> appears amis.
>
> The sm statemachine is a major tease as it has all of these association
> and endpoint pointers in the common set of function parameters that turn
> out to be NULL at the most inconvinient times. So I added to the common
> parameter list a struct net pointer, that is never NULL.
>
> include/net/netns/sctp.h | 96 +++++++-
> include/net/sctp/sctp.h | 16 +-
> include/net/sctp/sm.h | 8 +-
> include/net/sctp/structs.h | 126 +---------
> net/sctp/associola.c | 18 +-
> net/sctp/auth.c | 20 ++-
> net/sctp/bind_addr.c | 6 +-
> net/sctp/endpointola.c | 13 +-
> net/sctp/input.c | 6 +-
> net/sctp/primitive.c | 4 +-
> net/sctp/protocol.c | 137 +++++-----
> net/sctp/sm_make_chunk.c | 61 +++--
> net/sctp/sm_sideeffect.c | 26 ++-
> net/sctp/sm_statefuns.c | 631 ++++++++++++++++++++++++--------------------
> net/sctp/sm_statetable.c | 17 +-
> net/sctp/socket.c | 92 ++++---
> net/sctp/sysctl.c | 200 ++++++++------
> net/sctp/transport.c | 23 +-
> 18 files changed, 817 insertions(+), 683 deletions(-)
>
> Eric W. Biederman (7):
> sctp: Add infrastructure for per net sysctls
> sctp: Push struct net down to sctp_chunk_event_lookup
> sctp: Push struct net down into sctp_transport_init
> sctp: Push struct net down into sctp_in_scope
> sctp: Push struct net down into all of the state machine functions
> sctp: Push struct net down into sctp_verify_ext_param
> sctp: Making sysctl tunables per net
>
> Eric
>
>
Acked-by: Vlad Yasevich <[email protected]>
To this entire follow-on series. This is much better.
On 08/04/2012 05:30 PM, Jan Ariyasu wrote:
> The following set of patches enable network-namespaces for the SCTP protocol.
>
> The multitude of global parameters are stored in a net_generic
> structure, and the bulk of the patches enable the protocol to access
> the parameters on a per-namespace basis. The first five patches
> enable netns handling of the protocol, procfs and sysfs.
>
> Signed-off-by: Jan Ariyasu <[email protected]>
> ---
>
NACK. Sorry Jan, but Eric's patches are much cleaner and do everything
that's needed.
-vlad
From: [email protected] (Eric W. Biederman)
Date: Tue, 07 Aug 2012 10:17:02 -0700
>
> Since I am motivated to get things done, and since there has been much
> grumbling about my patches not implementing tunables, I have added
> tunable support on top of my last patchset.
>
> I have performed basic testing on the these patches and nothing
> appears amis.
>
> The sm statemachine is a major tease as it has all of these association
> and endpoint pointers in the common set of function parameters that turn
> out to be NULL at the most inconvinient times. So I added to the common
> parameter list a struct net pointer, that is never NULL.
Now that I have the ACKs from Vlad, I'm applying all of your work,
thanks Eric.