diff options
| author | Eric W. Biederman <ebiederm@xmission.com> | 2012-08-06 04:42:04 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-08-15 02:12:17 -0400 |
| commit | 4db67e808640e3934d82ce61ee8e2e89fd877ba8 (patch) | |
| tree | ff02e330187c41970c75f6d8a6275e1cc25165f0 /net/sctp | |
| parent | 4110cc255ddec59c79fba4d71cdd948d0a382140 (diff) | |
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>
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp')
| -rw-r--r-- | net/sctp/associola.c | 3 | ||||
| -rw-r--r-- | net/sctp/bind_addr.c | 14 | ||||
| -rw-r--r-- | net/sctp/ipv6.c | 17 | ||||
| -rw-r--r-- | net/sctp/protocol.c | 143 | ||||
| -rw-r--r-- | net/sctp/socket.c | 7 |
5 files changed, 104 insertions, 80 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index a3601f35ac15..ed4930b31341 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, | |||
| 1544 | if (asoc->peer.ipv6_address) | 1544 | if (asoc->peer.ipv6_address) |
| 1545 | flags |= SCTP_ADDR6_PEERSUPP; | 1545 | flags |= SCTP_ADDR6_PEERSUPP; |
| 1546 | 1546 | ||
| 1547 | return sctp_bind_addr_copy(&asoc->base.bind_addr, | 1547 | return sctp_bind_addr_copy(sock_net(asoc->base.sk), |
| 1548 | &asoc->base.bind_addr, | ||
| 1548 | &asoc->ep->base.bind_addr, | 1549 | &asoc->ep->base.bind_addr, |
| 1549 | scope, gfp, flags); | 1550 | scope, gfp, flags); |
| 1550 | } | 1551 | } |
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 4ece451c8d27..a85ce4b3e574 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
| @@ -52,8 +52,8 @@ | |||
| 52 | #include <net/sctp/sm.h> | 52 | #include <net/sctp/sm.h> |
| 53 | 53 | ||
| 54 | /* Forward declarations for internal helpers. */ | 54 | /* Forward declarations for internal helpers. */ |
| 55 | static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *, | 55 | static int sctp_copy_one_addr(struct net *, struct sctp_bind_addr *, |
| 56 | sctp_scope_t scope, gfp_t gfp, | 56 | union sctp_addr *, sctp_scope_t scope, gfp_t gfp, |
| 57 | int flags); | 57 | int flags); |
| 58 | static void sctp_bind_addr_clean(struct sctp_bind_addr *); | 58 | static void sctp_bind_addr_clean(struct sctp_bind_addr *); |
| 59 | 59 | ||
| @@ -62,7 +62,7 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *); | |||
| 62 | /* Copy 'src' to 'dest' taking 'scope' into account. Omit addresses | 62 | /* Copy 'src' to 'dest' taking 'scope' into account. Omit addresses |
| 63 | * in 'src' which have a broader scope than 'scope'. | 63 | * in 'src' which have a broader scope than 'scope'. |
| 64 | */ | 64 | */ |
| 65 | int sctp_bind_addr_copy(struct sctp_bind_addr *dest, | 65 | int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest, |
| 66 | const struct sctp_bind_addr *src, | 66 | const struct sctp_bind_addr *src, |
| 67 | sctp_scope_t scope, gfp_t gfp, | 67 | sctp_scope_t scope, gfp_t gfp, |
| 68 | int flags) | 68 | int flags) |
| @@ -75,7 +75,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, | |||
| 75 | 75 | ||
| 76 | /* Extract the addresses which are relevant for this scope. */ | 76 | /* Extract the addresses which are relevant for this scope. */ |
| 77 | list_for_each_entry(addr, &src->address_list, list) { | 77 | list_for_each_entry(addr, &src->address_list, list) { |
| 78 | error = sctp_copy_one_addr(dest, &addr->a, scope, | 78 | error = sctp_copy_one_addr(net, dest, &addr->a, scope, |
| 79 | gfp, flags); | 79 | gfp, flags); |
| 80 | if (error < 0) | 80 | if (error < 0) |
| 81 | goto out; | 81 | goto out; |
| @@ -87,7 +87,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, | |||
| 87 | */ | 87 | */ |
| 88 | if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) { | 88 | if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) { |
| 89 | list_for_each_entry(addr, &src->address_list, list) { | 89 | list_for_each_entry(addr, &src->address_list, list) { |
| 90 | error = sctp_copy_one_addr(dest, &addr->a, | 90 | error = sctp_copy_one_addr(net, dest, &addr->a, |
| 91 | SCTP_SCOPE_LINK, gfp, | 91 | SCTP_SCOPE_LINK, gfp, |
| 92 | flags); | 92 | flags); |
| 93 | if (error < 0) | 93 | if (error < 0) |
| @@ -448,7 +448,7 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, | |||
| 448 | } | 448 | } |
| 449 | 449 | ||
| 450 | /* Copy out addresses from the global local address list. */ | 450 | /* Copy out addresses from the global local address list. */ |
| 451 | static int sctp_copy_one_addr(struct sctp_bind_addr *dest, | 451 | static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest, |
| 452 | union sctp_addr *addr, | 452 | union sctp_addr *addr, |
| 453 | sctp_scope_t scope, gfp_t gfp, | 453 | sctp_scope_t scope, gfp_t gfp, |
| 454 | int flags) | 454 | int flags) |
| @@ -456,7 +456,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, | |||
| 456 | int error = 0; | 456 | int error = 0; |
| 457 | 457 | ||
| 458 | if (sctp_is_any(NULL, addr)) { | 458 | if (sctp_is_any(NULL, addr)) { |
| 459 | error = sctp_copy_local_addr_list(dest, scope, gfp, flags); | 459 | error = sctp_copy_local_addr_list(net, dest, scope, gfp, flags); |
| 460 | } else if (sctp_in_scope(addr, scope)) { | 460 | } else if (sctp_in_scope(addr, scope)) { |
| 461 | /* Now that the address is in scope, check to see if | 461 | /* Now that the address is in scope, check to see if |
| 462 | * the address type is supported by local sock as | 462 | * the address type is supported by local sock as |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 2165a7ed25f1..bbf15341eb2b 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, | |||
| 99 | struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; | 99 | struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; |
| 100 | struct sctp_sockaddr_entry *addr = NULL; | 100 | struct sctp_sockaddr_entry *addr = NULL; |
| 101 | struct sctp_sockaddr_entry *temp; | 101 | struct sctp_sockaddr_entry *temp; |
| 102 | struct net *net = dev_net(ifa->idev->dev); | ||
| 102 | int found = 0; | 103 | int found = 0; |
| 103 | 104 | ||
| 104 | switch (ev) { | 105 | switch (ev) { |
| @@ -110,27 +111,27 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, | |||
| 110 | addr->a.v6.sin6_addr = ifa->addr; | 111 | addr->a.v6.sin6_addr = ifa->addr; |
| 111 | addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; | 112 | addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; |
| 112 | addr->valid = 1; | 113 | addr->valid = 1; |
| 113 | spin_lock_bh(&sctp_local_addr_lock); | 114 | spin_lock_bh(&net->sctp.local_addr_lock); |
| 114 | list_add_tail_rcu(&addr->list, &sctp_local_addr_list); | 115 | list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list); |
| 115 | sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW); | 116 | sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW); |
| 116 | spin_unlock_bh(&sctp_local_addr_lock); | 117 | spin_unlock_bh(&net->sctp.local_addr_lock); |
| 117 | } | 118 | } |
| 118 | break; | 119 | break; |
| 119 | case NETDEV_DOWN: | 120 | case NETDEV_DOWN: |
| 120 | spin_lock_bh(&sctp_local_addr_lock); | 121 | spin_lock_bh(&net->sctp.local_addr_lock); |
| 121 | list_for_each_entry_safe(addr, temp, | 122 | list_for_each_entry_safe(addr, temp, |
| 122 | &sctp_local_addr_list, list) { | 123 | &net->sctp.local_addr_list, list) { |
| 123 | if (addr->a.sa.sa_family == AF_INET6 && | 124 | if (addr->a.sa.sa_family == AF_INET6 && |
| 124 | ipv6_addr_equal(&addr->a.v6.sin6_addr, | 125 | ipv6_addr_equal(&addr->a.v6.sin6_addr, |
| 125 | &ifa->addr)) { | 126 | &ifa->addr)) { |
| 126 | sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL); | 127 | sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL); |
| 127 | found = 1; | 128 | found = 1; |
| 128 | addr->valid = 0; | 129 | addr->valid = 0; |
| 129 | list_del_rcu(&addr->list); | 130 | list_del_rcu(&addr->list); |
| 130 | break; | 131 | break; |
| 131 | } | 132 | } |
| 132 | } | 133 | } |
| 133 | spin_unlock_bh(&sctp_local_addr_lock); | 134 | spin_unlock_bh(&net->sctp.local_addr_lock); |
| 134 | if (found) | 135 | if (found) |
| 135 | kfree_rcu(addr, rcu); | 136 | kfree_rcu(addr, rcu); |
| 136 | break; | 137 | break; |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 1f89c4e69645..7025d96bae5f 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, | |||
| 201 | /* Extract our IP addresses from the system and stash them in the | 201 | /* Extract our IP addresses from the system and stash them in the |
| 202 | * protocol structure. | 202 | * protocol structure. |
| 203 | */ | 203 | */ |
| 204 | static void sctp_get_local_addr_list(void) | 204 | static void sctp_get_local_addr_list(struct net *net) |
| 205 | { | 205 | { |
| 206 | struct net_device *dev; | 206 | struct net_device *dev; |
| 207 | struct list_head *pos; | 207 | struct list_head *pos; |
| 208 | struct sctp_af *af; | 208 | struct sctp_af *af; |
| 209 | 209 | ||
| 210 | rcu_read_lock(); | 210 | rcu_read_lock(); |
| 211 | for_each_netdev_rcu(&init_net, dev) { | 211 | for_each_netdev_rcu(net, dev) { |
| 212 | __list_for_each(pos, &sctp_address_families) { | 212 | __list_for_each(pos, &sctp_address_families) { |
| 213 | af = list_entry(pos, struct sctp_af, list); | 213 | af = list_entry(pos, struct sctp_af, list); |
| 214 | af->copy_addrlist(&sctp_local_addr_list, dev); | 214 | af->copy_addrlist(&net->sctp.local_addr_list, dev); |
| 215 | } | 215 | } |
| 216 | } | 216 | } |
| 217 | rcu_read_unlock(); | 217 | rcu_read_unlock(); |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | /* Free the existing local addresses. */ | 220 | /* Free the existing local addresses. */ |
| 221 | static void sctp_free_local_addr_list(void) | 221 | static void sctp_free_local_addr_list(struct net *net) |
| 222 | { | 222 | { |
| 223 | struct sctp_sockaddr_entry *addr; | 223 | struct sctp_sockaddr_entry *addr; |
| 224 | struct list_head *pos, *temp; | 224 | struct list_head *pos, *temp; |
| 225 | 225 | ||
| 226 | list_for_each_safe(pos, temp, &sctp_local_addr_list) { | 226 | list_for_each_safe(pos, temp, &net->sctp.local_addr_list) { |
| 227 | addr = list_entry(pos, struct sctp_sockaddr_entry, list); | 227 | addr = list_entry(pos, struct sctp_sockaddr_entry, list); |
| 228 | list_del(pos); | 228 | list_del(pos); |
| 229 | kfree(addr); | 229 | kfree(addr); |
| @@ -231,14 +231,14 @@ static void sctp_free_local_addr_list(void) | |||
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | /* Copy the local addresses which are valid for 'scope' into 'bp'. */ | 233 | /* Copy the local addresses which are valid for 'scope' into 'bp'. */ |
| 234 | int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, | 234 | int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp, |
| 235 | gfp_t gfp, int copy_flags) | 235 | sctp_scope_t scope, gfp_t gfp, int copy_flags) |
| 236 | { | 236 | { |
| 237 | struct sctp_sockaddr_entry *addr; | 237 | struct sctp_sockaddr_entry *addr; |
| 238 | int error = 0; | 238 | int error = 0; |
| 239 | 239 | ||
| 240 | rcu_read_lock(); | 240 | rcu_read_lock(); |
| 241 | list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) { | 241 | list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) { |
| 242 | if (!addr->valid) | 242 | if (!addr->valid) |
| 243 | continue; | 243 | continue; |
| 244 | if (sctp_in_scope(&addr->a, scope)) { | 244 | if (sctp_in_scope(&addr->a, scope)) { |
| @@ -627,14 +627,15 @@ static void sctp_v4_ecn_capable(struct sock *sk) | |||
| 627 | 627 | ||
| 628 | void sctp_addr_wq_timeout_handler(unsigned long arg) | 628 | void sctp_addr_wq_timeout_handler(unsigned long arg) |
| 629 | { | 629 | { |
| 630 | struct net *net = (struct net *)arg; | ||
| 630 | struct sctp_sockaddr_entry *addrw, *temp; | 631 | struct sctp_sockaddr_entry *addrw, *temp; |
| 631 | struct sctp_sock *sp; | 632 | struct sctp_sock *sp; |
| 632 | 633 | ||
| 633 | spin_lock_bh(&sctp_addr_wq_lock); | 634 | spin_lock_bh(&net->sctp.addr_wq_lock); |
| 634 | 635 | ||
| 635 | list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) { | 636 | list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { |
| 636 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ", | 637 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ", |
| 637 | " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state, | 638 | " for cmd %d at entry %p\n", &net->sctp.addr_waitq, &addrw->a, addrw->state, |
| 638 | addrw); | 639 | addrw); |
| 639 | 640 | ||
| 640 | #if IS_ENABLED(CONFIG_IPV6) | 641 | #if IS_ENABLED(CONFIG_IPV6) |
| @@ -648,7 +649,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) | |||
| 648 | goto free_next; | 649 | goto free_next; |
| 649 | 650 | ||
| 650 | in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr; | 651 | in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr; |
| 651 | if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 && | 652 | if (ipv6_chk_addr(net, in6, NULL, 0) == 0 && |
| 652 | addrw->state == SCTP_ADDR_NEW) { | 653 | addrw->state == SCTP_ADDR_NEW) { |
| 653 | unsigned long timeo_val; | 654 | unsigned long timeo_val; |
| 654 | 655 | ||
| @@ -656,12 +657,12 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) | |||
| 656 | SCTP_ADDRESS_TICK_DELAY); | 657 | SCTP_ADDRESS_TICK_DELAY); |
| 657 | timeo_val = jiffies; | 658 | timeo_val = jiffies; |
| 658 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); | 659 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); |
| 659 | mod_timer(&sctp_addr_wq_timer, timeo_val); | 660 | mod_timer(&net->sctp.addr_wq_timer, timeo_val); |
| 660 | break; | 661 | break; |
| 661 | } | 662 | } |
| 662 | } | 663 | } |
| 663 | #endif | 664 | #endif |
| 664 | list_for_each_entry(sp, &sctp_auto_asconf_splist, auto_asconf_list) { | 665 | list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) { |
| 665 | struct sock *sk; | 666 | struct sock *sk; |
| 666 | 667 | ||
| 667 | sk = sctp_opt2sk(sp); | 668 | sk = sctp_opt2sk(sp); |
| @@ -679,31 +680,32 @@ free_next: | |||
| 679 | list_del(&addrw->list); | 680 | list_del(&addrw->list); |
| 680 | kfree(addrw); | 681 | kfree(addrw); |
| 681 | } | 682 | } |
| 682 | spin_unlock_bh(&sctp_addr_wq_lock); | 683 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
| 683 | } | 684 | } |
| 684 | 685 | ||
| 685 | static void sctp_free_addr_wq(void) | 686 | static void sctp_free_addr_wq(struct net *net) |
| 686 | { | 687 | { |
| 687 | struct sctp_sockaddr_entry *addrw; | 688 | struct sctp_sockaddr_entry *addrw; |
| 688 | struct sctp_sockaddr_entry *temp; | 689 | struct sctp_sockaddr_entry *temp; |
| 689 | 690 | ||
| 690 | spin_lock_bh(&sctp_addr_wq_lock); | 691 | spin_lock_bh(&net->sctp.addr_wq_lock); |
| 691 | del_timer(&sctp_addr_wq_timer); | 692 | del_timer(&net->sctp.addr_wq_timer); |
| 692 | list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) { | 693 | list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { |
| 693 | list_del(&addrw->list); | 694 | list_del(&addrw->list); |
| 694 | kfree(addrw); | 695 | kfree(addrw); |
| 695 | } | 696 | } |
| 696 | spin_unlock_bh(&sctp_addr_wq_lock); | 697 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
| 697 | } | 698 | } |
| 698 | 699 | ||
| 699 | /* lookup the entry for the same address in the addr_waitq | 700 | /* lookup the entry for the same address in the addr_waitq |
| 700 | * sctp_addr_wq MUST be locked | 701 | * sctp_addr_wq MUST be locked |
| 701 | */ | 702 | */ |
| 702 | static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entry *addr) | 703 | static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct net *net, |
| 704 | struct sctp_sockaddr_entry *addr) | ||
| 703 | { | 705 | { |
| 704 | struct sctp_sockaddr_entry *addrw; | 706 | struct sctp_sockaddr_entry *addrw; |
| 705 | 707 | ||
| 706 | list_for_each_entry(addrw, &sctp_addr_waitq, list) { | 708 | list_for_each_entry(addrw, &net->sctp.addr_waitq, list) { |
| 707 | if (addrw->a.sa.sa_family != addr->a.sa.sa_family) | 709 | if (addrw->a.sa.sa_family != addr->a.sa.sa_family) |
| 708 | continue; | 710 | continue; |
| 709 | if (addrw->a.sa.sa_family == AF_INET) { | 711 | 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 | |||
| 719 | return NULL; | 721 | return NULL; |
| 720 | } | 722 | } |
| 721 | 723 | ||
| 722 | void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd) | 724 | void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cmd) |
| 723 | { | 725 | { |
| 724 | struct sctp_sockaddr_entry *addrw; | 726 | struct sctp_sockaddr_entry *addrw; |
| 725 | unsigned long timeo_val; | 727 | unsigned long timeo_val; |
| @@ -730,38 +732,38 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd) | |||
| 730 | * new address after a couple of addition and deletion of that address | 732 | * new address after a couple of addition and deletion of that address |
| 731 | */ | 733 | */ |
| 732 | 734 | ||
| 733 | spin_lock_bh(&sctp_addr_wq_lock); | 735 | spin_lock_bh(&net->sctp.addr_wq_lock); |
| 734 | /* Offsets existing events in addr_wq */ | 736 | /* Offsets existing events in addr_wq */ |
| 735 | addrw = sctp_addr_wq_lookup(addr); | 737 | addrw = sctp_addr_wq_lookup(net, addr); |
| 736 | if (addrw) { | 738 | if (addrw) { |
| 737 | if (addrw->state != cmd) { | 739 | if (addrw->state != cmd) { |
| 738 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ", | 740 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ", |
| 739 | " in wq %p\n", addrw->state, &addrw->a, | 741 | " in wq %p\n", addrw->state, &addrw->a, |
| 740 | &sctp_addr_waitq); | 742 | &net->sctp.addr_waitq); |
| 741 | list_del(&addrw->list); | 743 | list_del(&addrw->list); |
| 742 | kfree(addrw); | 744 | kfree(addrw); |
| 743 | } | 745 | } |
| 744 | spin_unlock_bh(&sctp_addr_wq_lock); | 746 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
| 745 | return; | 747 | return; |
| 746 | } | 748 | } |
| 747 | 749 | ||
| 748 | /* OK, we have to add the new address to the wait queue */ | 750 | /* OK, we have to add the new address to the wait queue */ |
| 749 | addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); | 751 | addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); |
| 750 | if (addrw == NULL) { | 752 | if (addrw == NULL) { |
| 751 | spin_unlock_bh(&sctp_addr_wq_lock); | 753 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
| 752 | return; | 754 | return; |
| 753 | } | 755 | } |
| 754 | addrw->state = cmd; | 756 | addrw->state = cmd; |
| 755 | list_add_tail(&addrw->list, &sctp_addr_waitq); | 757 | list_add_tail(&addrw->list, &net->sctp.addr_waitq); |
| 756 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ", | 758 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ", |
| 757 | " in wq %p\n", addrw->state, &addrw->a, &sctp_addr_waitq); | 759 | " in wq %p\n", addrw->state, &addrw->a, &net->sctp.addr_waitq); |
| 758 | 760 | ||
| 759 | if (!timer_pending(&sctp_addr_wq_timer)) { | 761 | if (!timer_pending(&net->sctp.addr_wq_timer)) { |
| 760 | timeo_val = jiffies; | 762 | timeo_val = jiffies; |
| 761 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); | 763 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); |
| 762 | mod_timer(&sctp_addr_wq_timer, timeo_val); | 764 | mod_timer(&net->sctp.addr_wq_timer, timeo_val); |
| 763 | } | 765 | } |
| 764 | spin_unlock_bh(&sctp_addr_wq_lock); | 766 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
| 765 | } | 767 | } |
| 766 | 768 | ||
| 767 | /* Event handler for inet address addition/deletion events. | 769 | /* Event handler for inet address addition/deletion events. |
| @@ -776,11 +778,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, | |||
| 776 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; | 778 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; |
| 777 | struct sctp_sockaddr_entry *addr = NULL; | 779 | struct sctp_sockaddr_entry *addr = NULL; |
| 778 | struct sctp_sockaddr_entry *temp; | 780 | struct sctp_sockaddr_entry *temp; |
| 781 | struct net *net = dev_net(ifa->ifa_dev->dev); | ||
| 779 | int found = 0; | 782 | int found = 0; |
| 780 | 783 | ||
| 781 | if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net)) | ||
| 782 | return NOTIFY_DONE; | ||
| 783 | |||
| 784 | switch (ev) { | 784 | switch (ev) { |
| 785 | case NETDEV_UP: | 785 | case NETDEV_UP: |
| 786 | addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); | 786 | 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, | |||
| 789 | addr->a.v4.sin_port = 0; | 789 | addr->a.v4.sin_port = 0; |
| 790 | addr->a.v4.sin_addr.s_addr = ifa->ifa_local; | 790 | addr->a.v4.sin_addr.s_addr = ifa->ifa_local; |
| 791 | addr->valid = 1; | 791 | addr->valid = 1; |
| 792 | spin_lock_bh(&sctp_local_addr_lock); | 792 | spin_lock_bh(&net->sctp.local_addr_lock); |
| 793 | list_add_tail_rcu(&addr->list, &sctp_local_addr_list); | 793 | list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list); |
| 794 | sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW); | 794 | sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW); |
| 795 | spin_unlock_bh(&sctp_local_addr_lock); | 795 | spin_unlock_bh(&net->sctp.local_addr_lock); |
| 796 | } | 796 | } |
| 797 | break; | 797 | break; |
| 798 | case NETDEV_DOWN: | 798 | case NETDEV_DOWN: |
| 799 | spin_lock_bh(&sctp_local_addr_lock); | 799 | spin_lock_bh(&net->sctp.local_addr_lock); |
| 800 | list_for_each_entry_safe(addr, temp, | 800 | list_for_each_entry_safe(addr, temp, |
| 801 | &sctp_local_addr_list, list) { | 801 | &net->sctp.local_addr_list, list) { |
| 802 | if (addr->a.sa.sa_family == AF_INET && | 802 | if (addr->a.sa.sa_family == AF_INET && |
| 803 | addr->a.v4.sin_addr.s_addr == | 803 | addr->a.v4.sin_addr.s_addr == |
| 804 | ifa->ifa_local) { | 804 | ifa->ifa_local) { |
| 805 | sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL); | 805 | sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL); |
| 806 | found = 1; | 806 | found = 1; |
| 807 | addr->valid = 0; | 807 | addr->valid = 0; |
| 808 | list_del_rcu(&addr->list); | 808 | list_del_rcu(&addr->list); |
| 809 | break; | 809 | break; |
| 810 | } | 810 | } |
| 811 | } | 811 | } |
| 812 | spin_unlock_bh(&sctp_local_addr_lock); | 812 | spin_unlock_bh(&net->sctp.local_addr_lock); |
| 813 | if (found) | 813 | if (found) |
| 814 | kfree_rcu(addr, rcu); | 814 | kfree_rcu(addr, rcu); |
| 815 | break; | 815 | break; |
| @@ -1194,6 +1194,36 @@ static void sctp_v4_del_protocol(void) | |||
| 1194 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | 1194 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); |
| 1195 | } | 1195 | } |
| 1196 | 1196 | ||
| 1197 | static int sctp_net_init(struct net *net) | ||
| 1198 | { | ||
| 1199 | /* Initialize the local address list. */ | ||
| 1200 | INIT_LIST_HEAD(&net->sctp.local_addr_list); | ||
| 1201 | spin_lock_init(&net->sctp.local_addr_lock); | ||
| 1202 | sctp_get_local_addr_list(net); | ||
| 1203 | |||
| 1204 | /* Initialize the address event list */ | ||
| 1205 | INIT_LIST_HEAD(&net->sctp.addr_waitq); | ||
| 1206 | INIT_LIST_HEAD(&net->sctp.auto_asconf_splist); | ||
| 1207 | spin_lock_init(&net->sctp.addr_wq_lock); | ||
| 1208 | net->sctp.addr_wq_timer.expires = 0; | ||
| 1209 | setup_timer(&net->sctp.addr_wq_timer, sctp_addr_wq_timeout_handler, | ||
| 1210 | (unsigned long)net); | ||
| 1211 | |||
| 1212 | return 0; | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | static void sctp_net_exit(struct net *net) | ||
| 1216 | { | ||
| 1217 | /* Free the local address list */ | ||
| 1218 | sctp_free_addr_wq(net); | ||
| 1219 | sctp_free_local_addr_list(net); | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | static struct pernet_operations sctp_net_ops = { | ||
| 1223 | .init = sctp_net_init, | ||
| 1224 | .exit = sctp_net_exit, | ||
| 1225 | }; | ||
| 1226 | |||
| 1197 | /* Initialize the universe into something sensible. */ | 1227 | /* Initialize the universe into something sensible. */ |
| 1198 | SCTP_STATIC __init int sctp_init(void) | 1228 | SCTP_STATIC __init int sctp_init(void) |
| 1199 | { | 1229 | { |
| @@ -1399,18 +1429,6 @@ SCTP_STATIC __init int sctp_init(void) | |||
| 1399 | sctp_v4_pf_init(); | 1429 | sctp_v4_pf_init(); |
| 1400 | sctp_v6_pf_init(); | 1430 | sctp_v6_pf_init(); |
| 1401 | 1431 | ||
| 1402 | /* Initialize the local address list. */ | ||
| 1403 | INIT_LIST_HEAD(&sctp_local_addr_list); | ||
| 1404 | spin_lock_init(&sctp_local_addr_lock); | ||
| 1405 | sctp_get_local_addr_list(); | ||
| 1406 | |||
| 1407 | /* Initialize the address event list */ | ||
| 1408 | INIT_LIST_HEAD(&sctp_addr_waitq); | ||
| 1409 | INIT_LIST_HEAD(&sctp_auto_asconf_splist); | ||
| 1410 | spin_lock_init(&sctp_addr_wq_lock); | ||
| 1411 | sctp_addr_wq_timer.expires = 0; | ||
| 1412 | setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0); | ||
| 1413 | |||
| 1414 | status = sctp_v4_protosw_init(); | 1432 | status = sctp_v4_protosw_init(); |
| 1415 | 1433 | ||
| 1416 | if (status) | 1434 | if (status) |
| @@ -1426,6 +1444,10 @@ SCTP_STATIC __init int sctp_init(void) | |||
| 1426 | goto err_ctl_sock_init; | 1444 | goto err_ctl_sock_init; |
| 1427 | } | 1445 | } |
| 1428 | 1446 | ||
| 1447 | status = register_pernet_subsys(&sctp_net_ops); | ||
| 1448 | if (status) | ||
| 1449 | goto err_register_pernet_subsys; | ||
| 1450 | |||
| 1429 | status = sctp_v4_add_protocol(); | 1451 | status = sctp_v4_add_protocol(); |
| 1430 | if (status) | 1452 | if (status) |
| 1431 | goto err_add_protocol; | 1453 | goto err_add_protocol; |
| @@ -1441,13 +1463,14 @@ out: | |||
| 1441 | err_v6_add_protocol: | 1463 | err_v6_add_protocol: |
| 1442 | sctp_v4_del_protocol(); | 1464 | sctp_v4_del_protocol(); |
| 1443 | err_add_protocol: | 1465 | err_add_protocol: |
| 1466 | unregister_pernet_subsys(&sctp_net_ops); | ||
| 1467 | err_register_pernet_subsys: | ||
| 1444 | inet_ctl_sock_destroy(sctp_ctl_sock); | 1468 | inet_ctl_sock_destroy(sctp_ctl_sock); |
| 1445 | err_ctl_sock_init: | 1469 | err_ctl_sock_init: |
| 1446 | sctp_v6_protosw_exit(); | 1470 | sctp_v6_protosw_exit(); |
| 1447 | err_v6_protosw_init: | 1471 | err_v6_protosw_init: |
| 1448 | sctp_v4_protosw_exit(); | 1472 | sctp_v4_protosw_exit(); |
| 1449 | err_protosw_init: | 1473 | err_protosw_init: |
| 1450 | sctp_free_local_addr_list(); | ||
| 1451 | sctp_v4_pf_exit(); | 1474 | sctp_v4_pf_exit(); |
| 1452 | sctp_v6_pf_exit(); | 1475 | sctp_v6_pf_exit(); |
| 1453 | sctp_sysctl_unregister(); | 1476 | sctp_sysctl_unregister(); |
| @@ -1482,18 +1505,16 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
| 1482 | /* Unregister with inet6/inet layers. */ | 1505 | /* Unregister with inet6/inet layers. */ |
| 1483 | sctp_v6_del_protocol(); | 1506 | sctp_v6_del_protocol(); |
| 1484 | sctp_v4_del_protocol(); | 1507 | sctp_v4_del_protocol(); |
| 1485 | sctp_free_addr_wq(); | ||
| 1486 | 1508 | ||
| 1487 | /* Free the control endpoint. */ | 1509 | /* Free the control endpoint. */ |
| 1488 | inet_ctl_sock_destroy(sctp_ctl_sock); | 1510 | inet_ctl_sock_destroy(sctp_ctl_sock); |
| 1489 | 1511 | ||
| 1512 | unregister_pernet_subsys(&sctp_net_ops); | ||
| 1513 | |||
| 1490 | /* Free protosw registrations */ | 1514 | /* Free protosw registrations */ |
| 1491 | sctp_v6_protosw_exit(); | 1515 | sctp_v6_protosw_exit(); |
| 1492 | sctp_v4_protosw_exit(); | 1516 | sctp_v4_protosw_exit(); |
| 1493 | 1517 | ||
| 1494 | /* Free the local address list. */ | ||
| 1495 | sctp_free_local_addr_list(); | ||
| 1496 | |||
| 1497 | /* Unregister with socket layer. */ | 1518 | /* Unregister with socket layer. */ |
| 1498 | sctp_v6_pf_exit(); | 1519 | sctp_v6_pf_exit(); |
| 1499 | sctp_v4_pf_exit(); | 1520 | sctp_v4_pf_exit(); |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 4316b0f988d4..5b6dd0e3d1f6 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, | |||
| 3471 | sp->do_auto_asconf = 0; | 3471 | sp->do_auto_asconf = 0; |
| 3472 | } else if (val && !sp->do_auto_asconf) { | 3472 | } else if (val && !sp->do_auto_asconf) { |
| 3473 | list_add_tail(&sp->auto_asconf_list, | 3473 | list_add_tail(&sp->auto_asconf_list, |
| 3474 | &sctp_auto_asconf_splist); | 3474 | &sock_net(sk)->sctp.auto_asconf_splist); |
| 3475 | sp->do_auto_asconf = 1; | 3475 | sp->do_auto_asconf = 1; |
| 3476 | } | 3476 | } |
| 3477 | return 0; | 3477 | return 0; |
| @@ -3964,7 +3964,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
| 3964 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | 3964 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
| 3965 | if (sctp_default_auto_asconf) { | 3965 | if (sctp_default_auto_asconf) { |
| 3966 | list_add_tail(&sp->auto_asconf_list, | 3966 | list_add_tail(&sp->auto_asconf_list, |
| 3967 | &sctp_auto_asconf_splist); | 3967 | &sock_net(sk)->sctp.auto_asconf_splist); |
| 3968 | sp->do_auto_asconf = 1; | 3968 | sp->do_auto_asconf = 1; |
| 3969 | } else | 3969 | } else |
| 3970 | sp->do_auto_asconf = 0; | 3970 | sp->do_auto_asconf = 0; |
| @@ -4653,9 +4653,10 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, | |||
| 4653 | union sctp_addr temp; | 4653 | union sctp_addr temp; |
| 4654 | int cnt = 0; | 4654 | int cnt = 0; |
| 4655 | int addrlen; | 4655 | int addrlen; |
| 4656 | struct net *net = sock_net(sk); | ||
| 4656 | 4657 | ||
| 4657 | rcu_read_lock(); | 4658 | rcu_read_lock(); |
| 4658 | list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) { | 4659 | list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) { |
| 4659 | if (!addr->valid) | 4660 | if (!addr->valid) |
| 4660 | continue; | 4661 | continue; |
| 4661 | 4662 | ||
