lkml.org 
[lkml]   [2012]   [Aug]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH net-next 4/9] sctp: Make the address lists per network namespace

    - 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" <ebiederm@xmission.com>
    ---
    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


    \
     
     \ /
      Last update: 2012-08-07 03:41    [W:4.487 / U:0.208 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site