diff options
-rw-r--r-- | include/net/net_namespace.h | 4 | ||||
-rw-r--r-- | include/net/netns/sctp.h | 21 | ||||
-rw-r--r-- | include/net/sctp/sctp.h | 4 | ||||
-rw-r--r-- | include/net/sctp/structs.h | 22 | ||||
-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 |
9 files changed, 132 insertions, 103 deletions
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 97e441945c13..5ae57f1ab755 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <net/netns/packet.h> | 15 | #include <net/netns/packet.h> |
16 | #include <net/netns/ipv4.h> | 16 | #include <net/netns/ipv4.h> |
17 | #include <net/netns/ipv6.h> | 17 | #include <net/netns/ipv6.h> |
18 | #include <net/netns/sctp.h> | ||
18 | #include <net/netns/dccp.h> | 19 | #include <net/netns/dccp.h> |
19 | #include <net/netns/x_tables.h> | 20 | #include <net/netns/x_tables.h> |
20 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | 21 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) |
@@ -81,6 +82,9 @@ struct net { | |||
81 | #if IS_ENABLED(CONFIG_IPV6) | 82 | #if IS_ENABLED(CONFIG_IPV6) |
82 | struct netns_ipv6 ipv6; | 83 | struct netns_ipv6 ipv6; |
83 | #endif | 84 | #endif |
85 | #if defined(CONFIG_IP_SCTP) || defined(CONFIG_IP_SCTP_MODULE) | ||
86 | struct netns_sctp sctp; | ||
87 | #endif | ||
84 | #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) | 88 | #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) |
85 | struct netns_dccp dccp; | 89 | struct netns_dccp dccp; |
86 | #endif | 90 | #endif |
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h new file mode 100644 index 000000000000..cbd684e01cf7 --- /dev/null +++ b/include/net/netns/sctp.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef __NETNS_SCTP_H__ | ||
2 | #define __NETNS_SCTP_H__ | ||
3 | |||
4 | struct netns_sctp { | ||
5 | /* This is the global local address list. | ||
6 | * We actively maintain this complete list of addresses on | ||
7 | * the system by catching address add/delete events. | ||
8 | * | ||
9 | * It is a list of sctp_sockaddr_entry. | ||
10 | */ | ||
11 | struct list_head local_addr_list; | ||
12 | struct list_head addr_waitq; | ||
13 | struct timer_list addr_wq_timer; | ||
14 | struct list_head auto_asconf_splist; | ||
15 | spinlock_t addr_wq_lock; | ||
16 | |||
17 | /* Lock that protects the local_addr_list writers */ | ||
18 | spinlock_t local_addr_lock; | ||
19 | }; | ||
20 | |||
21 | #endif /* __NETNS_SCTP_H__ */ | ||
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 640915a0613d..00c920537d4a 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -115,12 +115,12 @@ | |||
115 | * sctp/protocol.c | 115 | * sctp/protocol.c |
116 | */ | 116 | */ |
117 | extern struct sock *sctp_get_ctl_sock(void); | 117 | extern struct sock *sctp_get_ctl_sock(void); |
118 | extern int sctp_copy_local_addr_list(struct sctp_bind_addr *, | 118 | extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *, |
119 | sctp_scope_t, gfp_t gfp, | 119 | sctp_scope_t, gfp_t gfp, |
120 | int flags); | 120 | int flags); |
121 | extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); | 121 | extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); |
122 | extern int sctp_register_pf(struct sctp_pf *, sa_family_t); | 122 | extern int sctp_register_pf(struct sctp_pf *, sa_family_t); |
123 | extern void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *, int); | 123 | extern void sctp_addr_wq_mgmt(struct net *, struct sctp_sockaddr_entry *, int); |
124 | 124 | ||
125 | /* | 125 | /* |
126 | * sctp/socket.c | 126 | * sctp/socket.c |
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index c0563d1dd7c7..6bdfcabe560e 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -205,21 +205,7 @@ extern struct sctp_globals { | |||
205 | int port_hashsize; | 205 | int port_hashsize; |
206 | struct sctp_bind_hashbucket *port_hashtable; | 206 | struct sctp_bind_hashbucket *port_hashtable; |
207 | 207 | ||
208 | /* This is the global local address list. | ||
209 | * We actively maintain this complete list of addresses on | ||
210 | * the system by catching address add/delete events. | ||
211 | * | ||
212 | * It is a list of sctp_sockaddr_entry. | ||
213 | */ | ||
214 | struct list_head local_addr_list; | ||
215 | int default_auto_asconf; | 208 | int default_auto_asconf; |
216 | struct list_head addr_waitq; | ||
217 | struct timer_list addr_wq_timer; | ||
218 | struct list_head auto_asconf_splist; | ||
219 | spinlock_t addr_wq_lock; | ||
220 | |||
221 | /* Lock that protects the local_addr_list writers */ | ||
222 | spinlock_t addr_list_lock; | ||
223 | 209 | ||
224 | /* Flag to indicate if addip is enabled. */ | 210 | /* Flag to indicate if addip is enabled. */ |
225 | int addip_enable; | 211 | int addip_enable; |
@@ -278,12 +264,6 @@ extern struct sctp_globals { | |||
278 | #define sctp_assoc_hashtable (sctp_globals.assoc_hashtable) | 264 | #define sctp_assoc_hashtable (sctp_globals.assoc_hashtable) |
279 | #define sctp_port_hashsize (sctp_globals.port_hashsize) | 265 | #define sctp_port_hashsize (sctp_globals.port_hashsize) |
280 | #define sctp_port_hashtable (sctp_globals.port_hashtable) | 266 | #define sctp_port_hashtable (sctp_globals.port_hashtable) |
281 | #define sctp_local_addr_list (sctp_globals.local_addr_list) | ||
282 | #define sctp_local_addr_lock (sctp_globals.addr_list_lock) | ||
283 | #define sctp_auto_asconf_splist (sctp_globals.auto_asconf_splist) | ||
284 | #define sctp_addr_waitq (sctp_globals.addr_waitq) | ||
285 | #define sctp_addr_wq_timer (sctp_globals.addr_wq_timer) | ||
286 | #define sctp_addr_wq_lock (sctp_globals.addr_wq_lock) | ||
287 | #define sctp_default_auto_asconf (sctp_globals.default_auto_asconf) | 267 | #define sctp_default_auto_asconf (sctp_globals.default_auto_asconf) |
288 | #define sctp_scope_policy (sctp_globals.ipv4_scope_policy) | 268 | #define sctp_scope_policy (sctp_globals.ipv4_scope_policy) |
289 | #define sctp_addip_enable (sctp_globals.addip_enable) | 269 | #define sctp_addip_enable (sctp_globals.addip_enable) |
@@ -1241,7 +1221,7 @@ struct sctp_bind_addr { | |||
1241 | 1221 | ||
1242 | void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port); | 1222 | void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port); |
1243 | void sctp_bind_addr_free(struct sctp_bind_addr *); | 1223 | void sctp_bind_addr_free(struct sctp_bind_addr *); |
1244 | int sctp_bind_addr_copy(struct sctp_bind_addr *dest, | 1224 | int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest, |
1245 | const struct sctp_bind_addr *src, | 1225 | const struct sctp_bind_addr *src, |
1246 | sctp_scope_t scope, gfp_t gfp, | 1226 | sctp_scope_t scope, gfp_t gfp, |
1247 | int flags); | 1227 | int flags); |
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 | ||