Make a separate local_addr_list for each netns, and use that list to when creating associations. Signed-off-by: Jan Ariyasu <jan.ariyasu@xxxxxx> --- include/net/sctp/sctp.h | 8 ++- include/net/sctp/structs.h | 28 ++++---- net/sctp/associola.c | 6 +- net/sctp/bind_addr.c | 25 ++++--- net/sctp/ipv6.c | 47 ++++++++------ net/sctp/output.c | 4 +- net/sctp/protocol.c | 154 ++++++++++++++++++++++++-------------------- net/sctp/sm_make_chunk.c | 8 ++- net/sctp/sm_sideeffect.c | 3 +- net/sctp/sm_statefuns.c | 16 +++-- net/sctp/socket.c | 59 ++++++++++------- net/sctp/transport.c | 15 +++-- 12 files changed, 216 insertions(+), 157 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 97ba550..bda317a 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -121,10 +121,11 @@ extern int sctp_net_id; */ extern int sctp_copy_local_addr_list(struct sctp_bind_addr *, sctp_scope_t, gfp_t gfp, - int flags); + int flags, struct net *); extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); extern int sctp_register_pf(struct sctp_pf *, sa_family_t); -extern void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *, int); +extern void sctp_addr_wq_mgmt(struct net *, + struct sctp_sockaddr_entry *, int); /* * sctp/socket.c @@ -139,7 +140,8 @@ void sctp_sock_rfree(struct sk_buff *skb); void sctp_copy_sock(struct sock *newsk, struct sock *sk, struct sctp_association *asoc); extern struct percpu_counter sctp_sockets_allocated; -extern int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *); +extern int sctp_asconf_mgmt(struct net *, struct sctp_sock *, + struct sctp_sockaddr_entry *); /* * sctp/primitive.c diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index bc65718..2034d53 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -718,7 +718,8 @@ struct sctp_af { int optname, char __user *optval, int __user *optlen); - void (*get_dst) (struct sctp_transport *t, + void (*get_dst) (struct net *net, + struct sctp_transport *t, union sctp_addr *saddr, struct flowi *fl, struct sock *sk); @@ -751,7 +752,7 @@ struct sctp_af { sctp_scope_t (*scope) (union sctp_addr *); void (*inaddr_any) (union sctp_addr *, __be16); int (*is_any) (const union sctp_addr *); - int (*available) (union sctp_addr *, + int (*available) (struct net *, union sctp_addr *, struct sctp_sock *); int (*skb_iif) (const struct sk_buff *sk); int (*is_ce) (const struct sk_buff *sk); @@ -775,8 +776,10 @@ struct sctp_pf { int (*cmp_addr) (const union sctp_addr *, const union sctp_addr *, struct sctp_sock *); - int (*bind_verify) (struct sctp_sock *, union sctp_addr *); - int (*send_verify) (struct sctp_sock *, union sctp_addr *); + int (*bind_verify) (struct net *, struct sctp_sock *, + union sctp_addr *); + int (*send_verify) (struct net *, struct sctp_sock *, + union sctp_addr *); int (*supported_addrs)(const struct sctp_sock *, __be16 *); struct sock *(*create_accept_sk) (struct sock *sk, struct sctp_association *asoc); @@ -1220,9 +1223,10 @@ struct sctp_transport *sctp_transport_new(const union sctp_addr *, gfp_t); void sctp_transport_set_owner(struct sctp_transport *, struct sctp_association *); -void sctp_transport_route(struct sctp_transport *, union sctp_addr *, - struct sctp_sock *); -void sctp_transport_pmtu(struct sctp_transport *, struct sock *sk); +void sctp_transport_route(struct net *, struct sctp_transport *, + union sctp_addr *, struct sctp_sock *); +void sctp_transport_pmtu(struct net *, struct sctp_transport *, + struct sock *sk); void sctp_transport_free(struct sctp_transport *); void sctp_transport_reset_timers(struct sctp_transport *); void sctp_transport_hold(struct sctp_transport *); @@ -1373,6 +1377,7 @@ void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port); void sctp_bind_addr_free(struct sctp_bind_addr *); int sctp_bind_addr_copy(struct sctp_bind_addr *dest, const struct sctp_bind_addr *src, + struct net *net, sctp_scope_t scope, gfp_t gfp, int flags); int sctp_bind_addr_dup(struct sctp_bind_addr *dest, @@ -1398,7 +1403,8 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len, __u16 port, gfp_t gfp); sctp_scope_t sctp_scope(const union sctp_addr *); -int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope); +int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope, + struct net *net); int sctp_is_any(struct sock *sk, const union sctp_addr *addr); int sctp_addr_is_valid(const union sctp_addr *addr); int sctp_is_ep_boundall(struct sock *sk); @@ -1564,8 +1570,8 @@ int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t, sctp_init_chunk_t *peer_init, struct sctp_chunk *chunk, struct sctp_chunk **err_chunk); int sctp_process_init(struct sctp_association *, struct sctp_chunk *chunk, - const union sctp_addr *peer, - sctp_init_chunk_t *init, gfp_t gfp); + const union sctp_addr *peer, sctp_init_chunk_t *init, + struct net *net, gfp_t gfp); __u32 sctp_generate_tag(const struct sctp_endpoint *); __u32 sctp_generate_tsn(const struct sctp_endpoint *); @@ -2160,7 +2166,7 @@ void sctp_assoc_set_primary(struct sctp_association *, void sctp_assoc_del_nonprimary_peers(struct sctp_association *, struct sctp_transport *); int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *, - sctp_scope_t, gfp_t); + struct net *, sctp_scope_t, gfp_t); int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *, struct sctp_cookie*, gfp_t gfp); diff --git a/net/sctp/associola.c b/net/sctp/associola.c index ebaef3e..001f44b 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -644,6 +644,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, struct sctp_transport *peer; struct sctp_sock *sp; unsigned short port; + struct net *net = sock_net(asoc->base.sk); sp = sctp_sk(asoc->base.sk); @@ -702,7 +703,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, */ peer->param_flags = asoc->param_flags; - sctp_transport_route(peer, NULL, sp); + sctp_transport_route(net, peer, NULL, sp); /* Initialize the pmtu of the transport. */ if (peer->param_flags & SPP_PMTUD_DISABLE) { @@ -1529,6 +1530,7 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) * local endpoint and the remote peer. */ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, + struct net *net, sctp_scope_t scope, gfp_t gfp) { int flags; @@ -1543,7 +1545,7 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, flags |= SCTP_ADDR6_PEERSUPP; return sctp_bind_addr_copy(&asoc->base.bind_addr, - &asoc->ep->base.bind_addr, + &asoc->ep->base.bind_addr, net, scope, gfp, flags); } diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 4ece451..2b18722 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -52,9 +52,10 @@ #include <net/sctp/sm.h> /* Forward declarations for internal helpers. */ -static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *, - sctp_scope_t scope, gfp_t gfp, - int flags); +static int sctp_copy_one_addr(struct sctp_bind_addr *, + union sctp_addr *, struct net *, + sctp_scope_t scope, + gfp_t gfp, int flags); static void sctp_bind_addr_clean(struct sctp_bind_addr *); /* First Level Abstractions. */ @@ -64,6 +65,7 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *); */ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, const struct sctp_bind_addr *src, + struct net *net, sctp_scope_t scope, gfp_t gfp, int flags) { @@ -75,8 +77,8 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, /* Extract the addresses which are relevant for this scope. */ list_for_each_entry(addr, &src->address_list, list) { - error = sctp_copy_one_addr(dest, &addr->a, scope, - gfp, flags); + error = sctp_copy_one_addr(dest, &addr->a, net, + scope, gfp, flags); if (error < 0) goto out; } @@ -87,7 +89,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, */ if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) { list_for_each_entry(addr, &src->address_list, list) { - error = sctp_copy_one_addr(dest, &addr->a, + error = sctp_copy_one_addr(dest, &addr->a, net, SCTP_SCOPE_LINK, gfp, flags); if (error < 0) @@ -450,14 +452,15 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, /* Copy out addresses from the global local address list. */ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, union sctp_addr *addr, + struct net *net, sctp_scope_t scope, gfp_t gfp, int flags) { int error = 0; if (sctp_is_any(NULL, addr)) { - error = sctp_copy_local_addr_list(dest, scope, gfp, flags); - } else if (sctp_in_scope(addr, scope)) { + error = sctp_copy_local_addr_list(dest, scope, gfp, flags, net); + } else if (sctp_in_scope(addr, scope, net)) { /* Now that the address is in scope, check to see if * the address type is supported by local sock as * well as the remote peer. @@ -494,9 +497,11 @@ int sctp_is_any(struct sock *sk, const union sctp_addr *addr) } /* Is 'addr' valid for 'scope'? */ -int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope) +int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope, + struct net *net) { sctp_scope_t addr_scope = sctp_scope(addr); + struct sctp_net_params *net_params = sctp_get_params(net); /* The unusable SCTP addresses will not be considered with * any defined scopes. @@ -512,7 +517,7 @@ int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope) * Address scoping can be selectively controlled via sysctl * option */ - switch (sctp_scope_policy) { + switch (net_params->ipv4_scope_policy) { case SCTP_SCOPE_POLICY_DISABLE: return 1; case SCTP_SCOPE_POLICY_ENABLE: diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index ed7139e..67cae63 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -88,7 +88,7 @@ static int sctp_v6_cmp_addr(const union sctp_addr *addr1, const union sctp_addr *addr2); /* Event handler for inet6 address addition/deletion events. - * The sctp_local_addr_list needs to be protocted by a spin lock since + * The local_addr_list needs to be protocted by a spin lock since * multiple notifiers (say IPv4 and IPv6) may be running at the same * time and thus corrupt the list. * The reader side is protected with RCU. @@ -100,6 +100,8 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, struct sctp_sockaddr_entry *addr = NULL; struct sctp_sockaddr_entry *temp; int found = 0; + struct net *net = dev_net(ifa->idev->dev); + struct sctp_net_params *net_params = sctp_get_params(net); switch (ev) { case NETDEV_UP: @@ -110,27 +112,28 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, addr->a.v6.sin6_addr = ifa->addr; addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; addr->valid = 1; - spin_lock_bh(&sctp_local_addr_lock); - list_add_tail_rcu(&addr->list, &sctp_local_addr_list); - sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW); - spin_unlock_bh(&sctp_local_addr_lock); + spin_lock_bh(&net_params->addr_list_lock); + list_add_tail_rcu(&addr->list, + &net_params->local_addr_list); + sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW); + spin_unlock_bh(&net_params->addr_list_lock); } break; case NETDEV_DOWN: - spin_lock_bh(&sctp_local_addr_lock); + spin_lock_bh(&net_params->addr_list_lock); list_for_each_entry_safe(addr, temp, - &sctp_local_addr_list, list) { + &net_params->local_addr_list, list) { if (addr->a.sa.sa_family == AF_INET6 && ipv6_addr_equal(&addr->a.v6.sin6_addr, &ifa->addr)) { - sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL); + sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL); found = 1; addr->valid = 0; list_del_rcu(&addr->list); break; } } - spin_unlock_bh(&sctp_local_addr_lock); + spin_unlock_bh(&net_params->addr_list_lock); if (found) kfree_rcu(addr, rcu); break; @@ -252,8 +255,9 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) /* Returns the dst cache entry for the given source and destination ip * addresses. */ -static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, - struct flowi *fl, struct sock *sk) +static void sctp_v6_get_dst(struct net *net, struct sctp_transport *t, + union sctp_addr *saddr, struct flowi *fl, + struct sock *sk) { struct sctp_association *asoc = t->asoc; struct dst_entry *dst = NULL; @@ -561,7 +565,8 @@ static int sctp_v6_is_any(const union sctp_addr *addr) } /* Should this be available for binding? */ -static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp) +static int sctp_v6_available(struct net *net, union sctp_addr *addr, + struct sctp_sock *sp) { int type; const struct in6_addr *in6 = (const struct in6_addr *)&addr->v6.sin6_addr; @@ -575,12 +580,12 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp) if (sp && ipv6_only_sock(sctp_opt2sk(sp))) return 0; sctp_v6_map_v4(addr); - return sctp_get_af_specific(AF_INET)->available(addr, sp); + return sctp_get_af_specific(AF_INET)->available(net, addr, sp); } if (!(type & IPV6_ADDR_UNICAST)) return 0; - return ipv6_chk_addr(&init_net, in6, NULL, 0); + return ipv6_chk_addr(net, in6, NULL, 0); } /* This function checks if the address is a valid address to be used for @@ -845,7 +850,8 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, /* Verify that the provided sockaddr looks bindable. Common verification, * has already been taken care of. */ -static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) +static int sctp_inet6_bind_verify(struct net *net, struct sctp_sock *opt, + union sctp_addr *addr) { struct sctp_af *af; @@ -860,10 +866,10 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) if (!addr->v6.sin6_scope_id) return 0; rcu_read_lock(); - dev = dev_get_by_index_rcu(&init_net, + dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id); if (!dev || - !ipv6_chk_addr(&init_net, &addr->v6.sin6_addr, + !ipv6_chk_addr(net, &addr->v6.sin6_addr, dev, 0)) { rcu_read_unlock(); return 0; @@ -876,13 +882,14 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) af = opt->pf->af; } - return af->available(addr, opt); + return af->available(net, addr, opt); } /* Verify that the provided sockaddr looks sendable. Common verification, * has already been taken care of. */ -static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr) +static int sctp_inet6_send_verify(struct net *net, struct sctp_sock *opt, + union sctp_addr *addr) { struct sctp_af *af = NULL; @@ -897,7 +904,7 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr) if (!addr->v6.sin6_scope_id) return 0; rcu_read_lock(); - dev = dev_get_by_index_rcu(&init_net, + dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id); rcu_read_unlock(); if (!dev) diff --git a/net/sctp/output.c b/net/sctp/output.c index 838e18b..f9c5ffa 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -377,6 +377,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) struct sk_buff *nskb; struct sctp_chunk *chunk, *tmp; struct sock *sk; + struct net *net; int err = 0; int padding; /* How much padding do we need? */ __u8 has_data = 0; @@ -393,6 +394,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) /* Set up convenience variables... */ chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list); sk = chunk->skb->sk; + net = sock_net(sk); /* Allocate the new skb. */ nskb = alloc_skb(packet->size + LL_MAX_HEADER, GFP_ATOMIC); @@ -408,7 +410,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) skb_set_owner_w(nskb, sk); if (!sctp_transport_dst_check(tp)) { - sctp_transport_route(tp, NULL, sctp_sk(sk)); + sctp_transport_route(net, tp, NULL, sctp_sk(sk)); if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) { sctp_assoc_sync_pmtu(sk, asoc); } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 28dbef2..dce07d6 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -196,29 +196,32 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, /* Extract our IP addresses from the system and stash them in the * protocol structure. */ -static void sctp_get_local_addr_list(void) +static void sctp_get_local_addr_list(struct net *net) { struct net_device *dev; struct list_head *pos; struct sctp_af *af; + struct sctp_net_params *net_params = sctp_get_params(net); rcu_read_lock(); - for_each_netdev_rcu(&init_net, dev) { + for_each_netdev_rcu(net, dev) { __list_for_each(pos, &sctp_address_families) { af = list_entry(pos, struct sctp_af, list); - af->copy_addrlist(&sctp_local_addr_list, dev); + af->copy_addrlist(&net_params->local_addr_list, dev); } } rcu_read_unlock(); } /* Free the existing local addresses. */ -static void sctp_free_local_addr_list(void) +static void sctp_free_local_addr_list(struct net *net) { struct sctp_sockaddr_entry *addr; struct list_head *pos, *temp; + struct sctp_net_params *net_params = + sctp_get_params(net); - list_for_each_safe(pos, temp, &sctp_local_addr_list) { + list_for_each_safe(pos, temp, &net_params->local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); list_del(pos); kfree(addr); @@ -227,16 +230,17 @@ static void sctp_free_local_addr_list(void) /* Copy the local addresses which are valid for 'scope' into 'bp'. */ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, - gfp_t gfp, int copy_flags) + gfp_t gfp, int copy_flags, struct net *net) { struct sctp_sockaddr_entry *addr; int error = 0; + struct sctp_net_params *net_params = sctp_get_params(net); rcu_read_lock(); - list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) { + list_for_each_entry_rcu(addr, &net_params->local_addr_list, list) { if (!addr->valid) continue; - if (sctp_in_scope(&addr->a, scope)) { + if (sctp_in_scope(&addr->a, scope, net)) { /* Now that the address is in scope, check to see if * the address type is really supported by the local * sock as well as the remote peer. @@ -389,11 +393,15 @@ static int sctp_v4_addr_valid(union sctp_addr *addr, return 1; } -/* Should this be available for binding? */ -static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp) +/* Should this be available for binding? + * Note that we could derive struct net *net from the sctp_sock *sp, + * but the IPv6 version of this code doesn't have the same information + * in the last argument. + */ +static int sctp_v4_available(struct net *net, union sctp_addr *addr, + struct sctp_sock *sp) { - int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr); - + int ret = inet_addr_type(net, addr->v4.sin_addr.s_addr); if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) && ret != RTN_LOCAL && @@ -450,8 +458,9 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr) * addresses. If an association is passed, trys to get a dst entry with a * source address that matches an address in the bind address list. */ -static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, - struct flowi *fl, struct sock *sk) +static void sctp_v4_get_dst(struct net *net, struct sctp_transport *t, + union sctp_addr *saddr, struct flowi *fl, + struct sock *sk) { struct sctp_association *asoc = t->asoc; struct rtable *rt; @@ -479,7 +488,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", __func__, &fl4->daddr, &fl4->saddr); - rt = ip_route_output_key(&init_net, fl4); + rt = ip_route_output_key(net, fl4); if (!IS_ERR(rt)) dst = &rt->dst; @@ -525,7 +534,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, (AF_INET == laddr->a.sa.sa_family)) { fl4->saddr = laddr->a.v4.sin_addr.s_addr; fl4->fl4_sport = laddr->a.v4.sin_port; - rt = ip_route_output_key(&init_net, fl4); + rt = ip_route_output_key(sock_net(asoc->base.sk), fl4); if (!IS_ERR(rt)) { dst = &rt->dst; goto out_unlock; @@ -624,13 +633,15 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) { struct sctp_sockaddr_entry *addrw, *temp; struct sctp_sock *sp; + struct net *net = (struct net *)arg; + struct sctp_net_params *net_params = sctp_get_params(net); - spin_lock_bh(&sctp_addr_wq_lock); + spin_lock_bh(&net_params->addr_wq_lock); - list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) { + list_for_each_entry_safe(addrw, temp, &net_params->addr_waitq, list) { SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ", - " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state, - addrw); + " for cmd %d at entry %p\n", &net_params->addr_waitq, + &addrw->a, addrw->state, addrw); #if IS_ENABLED(CONFIG_IPV6) /* Now we send an ASCONF for each association */ @@ -643,7 +654,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) goto free_next; in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr; - if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 && + if (ipv6_chk_addr(net, in6, NULL, 0) == 0 && addrw->state == SCTP_ADDR_NEW) { unsigned long timeo_val; @@ -651,7 +662,8 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) SCTP_ADDRESS_TICK_DELAY); timeo_val = jiffies; timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); - mod_timer(&sctp_addr_wq_timer, timeo_val); + mod_timer(&net_params->addr_wq_timer, + timeo_val); break; } } @@ -664,7 +676,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) if (!sctp_is_ep_boundall(sk)) continue; sctp_bh_lock_sock(sk); - if (sctp_asconf_mgmt(sp, addrw) < 0) + if (sctp_asconf_mgmt(net, sp, addrw) < 0) SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: sctp_asconf_mgmt failed\n"); sctp_bh_unlock_sock(sk); } @@ -674,31 +686,35 @@ free_next: list_del(&addrw->list); kfree(addrw); } - spin_unlock_bh(&sctp_addr_wq_lock); + spin_unlock_bh(&net_params->addr_wq_lock); } -static void sctp_free_addr_wq(void) +static void sctp_free_addr_wq(struct net *net) { struct sctp_sockaddr_entry *addrw; struct sctp_sockaddr_entry *temp; + struct sctp_net_params *net_params = sctp_get_params(net); - spin_lock_bh(&sctp_addr_wq_lock); - del_timer(&sctp_addr_wq_timer); - list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) { + spin_lock_bh(&net_params->addr_wq_lock); + del_timer(&net_params->addr_wq_timer); + list_for_each_entry_safe(addrw, temp, &net_params->addr_waitq, list) { list_del(&addrw->list); kfree(addrw); } - spin_unlock_bh(&sctp_addr_wq_lock); + spin_unlock_bh(&net_params->addr_wq_lock); } /* lookup the entry for the same address in the addr_waitq * sctp_addr_wq MUST be locked */ -static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entry *addr) +static struct sctp_sockaddr_entry *sctp_addr_wq_lookup( + struct net *net, + struct sctp_sockaddr_entry *addr) { struct sctp_sockaddr_entry *addrw; + struct sctp_net_params *net_params = sctp_get_params(net); - list_for_each_entry(addrw, &sctp_addr_waitq, list) { + list_for_each_entry(addrw, &net_params->addr_waitq, list) { if (addrw->a.sa.sa_family != addr->a.sa.sa_family) continue; if (addrw->a.sa.sa_family == AF_INET) { @@ -714,10 +730,12 @@ static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entr return NULL; } -void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd) +void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, + int cmd) { struct sctp_sockaddr_entry *addrw; unsigned long timeo_val; + struct sctp_net_params *net_params = sctp_get_params(net); /* first, we check if an opposite message already exist in the queue. * If we found such message, it is removed. @@ -725,38 +743,38 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd) * new address after a couple of addition and deletion of that address */ - spin_lock_bh(&sctp_addr_wq_lock); + spin_lock_bh(&net_params->addr_wq_lock); /* Offsets existing events in addr_wq */ - addrw = sctp_addr_wq_lookup(addr); + addrw = sctp_addr_wq_lookup(net, addr); if (addrw) { if (addrw->state != cmd) { SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ", " in wq %p\n", addrw->state, &addrw->a, - &sctp_addr_waitq); + &net_params->addr_waitq); list_del(&addrw->list); kfree(addrw); } - spin_unlock_bh(&sctp_addr_wq_lock); + spin_unlock_bh(&net_params->addr_wq_lock); return; } /* OK, we have to add the new address to the wait queue */ addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); if (addrw == NULL) { - spin_unlock_bh(&sctp_addr_wq_lock); + spin_unlock_bh(&net_params->addr_wq_lock); return; } addrw->state = cmd; - list_add_tail(&addrw->list, &sctp_addr_waitq); + list_add_tail(&addrw->list, &net_params->addr_waitq); SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ", - " in wq %p\n", addrw->state, &addrw->a, &sctp_addr_waitq); + " in wq %p\n", addrw->state, &addrw->a, &net_params->addr_waitq); - if (!timer_pending(&sctp_addr_wq_timer)) { + if (!timer_pending(&net_params->addr_wq_timer)) { timeo_val = jiffies; timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); - mod_timer(&sctp_addr_wq_timer, timeo_val); + mod_timer(&net_params->addr_wq_timer, timeo_val); } - spin_unlock_bh(&sctp_addr_wq_lock); + spin_unlock_bh(&net_params->addr_wq_lock); } /* Event handler for inet address addition/deletion events. @@ -772,9 +790,8 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, struct sctp_sockaddr_entry *addr = NULL; struct sctp_sockaddr_entry *temp; int found = 0; - - if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net)) - return NOTIFY_DONE; + struct net *net = dev_net(ifa->ifa_dev->dev); + struct sctp_net_params *net_params = sctp_get_params(net); switch (ev) { case NETDEV_UP: @@ -784,27 +801,28 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, addr->a.v4.sin_port = 0; addr->a.v4.sin_addr.s_addr = ifa->ifa_local; addr->valid = 1; - spin_lock_bh(&sctp_local_addr_lock); - list_add_tail_rcu(&addr->list, &sctp_local_addr_list); - sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW); - spin_unlock_bh(&sctp_local_addr_lock); + spin_lock_bh(&net_params->addr_list_lock); + list_add_tail_rcu(&addr->list, + &net_params->local_addr_list); + sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW); + spin_unlock_bh(&net_params->addr_list_lock); } break; case NETDEV_DOWN: - spin_lock_bh(&sctp_local_addr_lock); + spin_lock_bh(&net_params->addr_list_lock); list_for_each_entry_safe(addr, temp, - &sctp_local_addr_list, list) { + &net_params->local_addr_list, list) { if (addr->a.sa.sa_family == AF_INET && addr->a.v4.sin_addr.s_addr == ifa->ifa_local) { - sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL); + sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL); found = 1; addr->valid = 0; list_del_rcu(&addr->list); break; } } - spin_unlock_bh(&sctp_local_addr_lock); + spin_unlock_bh(&net_params->addr_list_lock); if (found) kfree_rcu(addr, rcu); break; @@ -955,15 +973,17 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1, /* Verify that provided sockaddr looks bindable. Common verification has * already been taken care of. */ -static int sctp_inet_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) +static int sctp_inet_bind_verify(struct net *net, struct sctp_sock *opt, + union sctp_addr *addr) { - return sctp_v4_available(addr, opt); + return sctp_v4_available(net, addr, opt); } /* Verify that sockaddr looks sendable. Common verification has already * been taken care of. */ -static int sctp_inet_send_verify(struct sctp_sock *opt, union sctp_addr *addr) +static int sctp_inet_send_verify(struct net *net, struct sctp_sock *opt, + union sctp_addr *addr) { return 1; } @@ -1562,6 +1582,8 @@ static int __net_init sctp_net_init(struct net *net) if (err) goto err_param_init; + sctp_get_local_addr_list(net); + goto out; err_param_init: sctp_proc_exit(net); err_proc_init: @@ -1572,7 +1594,12 @@ out: static void __net_exit sctp_net_exit(struct net *net) { + sctp_free_addr_wq(net); + /* Free the control sock */ sctp_ctl_sock_destroy(net); + /* Free the local address list. */ + sctp_free_local_addr_list(net); + /* Clean up procfs */ sctp_proc_exit(net); } @@ -1623,17 +1650,7 @@ SCTP_STATIC __init int sctp_init(void) sctp_v4_pf_init(); sctp_v6_pf_init(); - /* Initialize the local address list. */ - INIT_LIST_HEAD(&sctp_local_addr_list); - spin_lock_init(&sctp_local_addr_lock); - sctp_get_local_addr_list(); - /* Initialize the address event list */ - INIT_LIST_HEAD(&sctp_addr_waitq); - INIT_LIST_HEAD(&sctp_auto_asconf_splist); - spin_lock_init(&sctp_addr_wq_lock); - sctp_addr_wq_timer.expires = 0; - setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0); /* Register SCTP protocol */ status = sctp_v4_protosw_init(); @@ -1689,7 +1706,6 @@ err_add_protocol: err_v6_protosw_init: sctp_v4_protosw_exit(); err_protosw_init: - sctp_free_local_addr_list(); sctp_v6_pf_exit(); sctp_v4_pf_exit(); sctp_hashtable_globals_free(); @@ -1710,15 +1726,11 @@ SCTP_STATIC __exit void sctp_exit(void) /* Unregister with inet6/inet layers. */ sctp_v6_del_protocol(); sctp_v4_del_protocol(); - sctp_free_addr_wq(); /* Free protosw registrations */ sctp_v6_protosw_exit(); sctp_v4_protosw_exit(); - /* Free the local address list. */ - sctp_free_local_addr_list(); - /* Unregister with socket layer. */ sctp_v6_pf_exit(); sctp_v4_pf_exit(); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 479a70e..af02b44 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -79,6 +79,7 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, static int sctp_process_param(struct sctp_association *asoc, union sctp_params param, const union sctp_addr *peer_addr, + struct net *net, gfp_t gfp); static void *sctp_addto_param(struct sctp_chunk *chunk, int len, const void *data); @@ -2268,7 +2269,7 @@ int sctp_verify_init(const struct sctp_association *asoc, */ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, const union sctp_addr *peer_addr, - sctp_init_chunk_t *peer_init, gfp_t gfp) + sctp_init_chunk_t *peer_init, struct net *net, gfp_t gfp) { union sctp_params param; struct sctp_transport *transport; @@ -2305,7 +2306,7 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, src_match = 1; } - if (!sctp_process_param(asoc, param, peer_addr, gfp)) + if (!sctp_process_param(asoc, param, peer_addr, net, gfp)) goto clean_up; } @@ -2464,6 +2465,7 @@ nomem: static int sctp_process_param(struct sctp_association *asoc, union sctp_params param, const union sctp_addr *peer_addr, + struct net *net, gfp_t gfp) { union sctp_addr addr; @@ -2494,7 +2496,7 @@ do_addr_param: af = sctp_get_af_specific(param_type2af(param.p->type)); af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0); scope = sctp_scope(peer_addr); - if (sctp_in_scope(&addr, scope)) + if (sctp_in_scope(&addr, scope, net)) if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED)) return 0; break; diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index fe99628..8fe4a25 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -615,7 +615,8 @@ static int sctp_cmd_process_init(sctp_cmd_seq_t *commands, * fail during INIT processing (due to malloc problems), * just return the error and stop processing the stack. */ - if (!sctp_process_init(asoc, chunk, sctp_source(chunk), peer_init, gfp)) + if (!sctp_process_init(asoc, chunk, sctp_source(chunk), peer_init, + &init_net, gfp)) error = -ENOMEM; else error = 0; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 91dcdd6..85a46ac 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -388,6 +388,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, goto nomem; if (sctp_assoc_set_bind_addr_from_ep(new_asoc, + &init_net, sctp_scope(sctp_source(chunk)), GFP_ATOMIC) < 0) goto nomem_init; @@ -395,7 +396,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, /* The call, sctp_process_init(), can fail on memory allocation. */ if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), (sctp_init_chunk_t *)chunk->chunk_hdr, - GFP_ATOMIC)) + &init_net, GFP_ATOMIC)) goto nomem_init; /* B) "Z" shall respond immediately with an INIT ACK chunk. */ @@ -726,7 +727,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, if (!sctp_process_init(new_asoc, chunk, &chunk->subh.cookie_hdr->c.peer_addr, - peer_init, GFP_ATOMIC)) + peer_init, &init_net, GFP_ATOMIC)) goto nomem_init; /* SCTP-AUTH: Now that we've populate required fields in @@ -1444,7 +1445,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( if (!new_asoc) goto nomem; - if (sctp_assoc_set_bind_addr_from_ep(new_asoc, + if (sctp_assoc_set_bind_addr_from_ep(new_asoc, &init_net, sctp_scope(sctp_source(chunk)), GFP_ATOMIC) < 0) goto nomem; @@ -1454,7 +1455,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( */ if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), (sctp_init_chunk_t *)chunk->chunk_hdr, - GFP_ATOMIC)) + &init_net, GFP_ATOMIC)) goto nomem; /* Make sure no new addresses are being added during the @@ -1682,7 +1683,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, - GFP_ATOMIC)) + &init_net, GFP_ATOMIC)) goto nomem; /* Make sure no new addresses are being added during the @@ -1777,7 +1778,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep, */ peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, - GFP_ATOMIC)) + &init_net, GFP_ATOMIC)) goto nomem; /* Update the content of current association. */ @@ -5918,7 +5919,8 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc /* Cache a route for the transport with the chunk's destination as * the source address. */ - sctp_transport_route(transport, (union sctp_addr *)&chunk->dest, + sctp_transport_route(&init_net, transport, + (union sctp_addr *)&chunk->dest, sctp_sk(*sctp_get_ctl_sock(&init_net))); packet = sctp_packet_init(&transport->packet, transport, sport, dport); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5e25981..790e597 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -101,8 +101,10 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt, union sctp_addr *addr, int len); static int sctp_bindx_add(struct sock *, struct sockaddr *, int); static int sctp_bindx_rem(struct sock *, struct sockaddr *, int); -static int sctp_send_asconf_add_ip(struct sock *, struct sockaddr *, int); -static int sctp_send_asconf_del_ip(struct sock *, struct sockaddr *, int); +static int sctp_send_asconf_add_ip(struct net*, struct sock *, + struct sockaddr *, int); +static int sctp_send_asconf_del_ip(struct net*, struct sock *, + struct sockaddr *, int); static int sctp_send_asconf(struct sctp_association *asoc, struct sctp_chunk *chunk); static int sctp_do_bind(struct sock *, union sctp_addr *, int); @@ -197,7 +199,7 @@ static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr, if (!af->addr_valid(addr, sctp_sk(sk), NULL)) return -EINVAL; - if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr))) + if (!sctp_sk(sk)->pf->send_verify(sock_net(sk), sctp_sk(sk), (addr))) return -EINVAL; return 0; @@ -360,7 +362,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) len); /* PF specific bind() address verification. */ - if (!sp->pf->bind_verify(sp, addr)) + if (!sp->pf->bind_verify(sock_net(sk), sp, addr)) return -EADDRNOTAVAIL; /* We must either be unbound, or bind to the same port. @@ -511,7 +513,8 @@ err_bindx_add: * * Only sctp_setsockopt_bindx() is supposed to call this function. */ -static int sctp_send_asconf_add_ip(struct sock *sk, +static int sctp_send_asconf_add_ip(struct net *net, + struct sock *sk, struct sockaddr *addrs, int addrcnt) { @@ -608,7 +611,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk, trans->ssthresh = asoc->peer.i.a_rwnd; trans->rto = asoc->rto_initial; trans->rtt = trans->srtt = trans->rttvar = 0; - sctp_transport_route(trans, NULL, + sctp_transport_route(net, trans, NULL, sctp_sk(asoc->base.sk)); } } @@ -713,7 +716,8 @@ err_bindx_rem: * * Only sctp_setsockopt_bindx() is supposed to call this function. */ -static int sctp_send_asconf_del_ip(struct sock *sk, +static int sctp_send_asconf_del_ip(struct net *net, + struct sock *sk, struct sockaddr *addrs, int addrcnt) { @@ -847,7 +851,7 @@ skip_mkasconf: list_for_each_entry(transport, &asoc->peer.transport_addr_list, transports) { dst_release(transport->dst); - sctp_transport_route(transport, NULL, + sctp_transport_route(net, transport, NULL, sctp_sk(asoc->base.sk)); } @@ -861,7 +865,8 @@ out: } /* set addr events to assocs in the endpoint. ep and addr_wq must be locked */ -int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw) +int sctp_asconf_mgmt(struct net *net, struct sctp_sock *sp, + struct sctp_sockaddr_entry *addrw) { struct sock *sk = sctp_opt2sk(sp); union sctp_addr *addr; @@ -877,9 +882,11 @@ int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw) return -EINVAL; if (addrw->state == SCTP_ADDR_NEW) - return sctp_send_asconf_add_ip(sk, (struct sockaddr *)addr, 1); + return sctp_send_asconf_add_ip(net, sk, + (struct sockaddr *)addr, 1); else - return sctp_send_asconf_del_ip(sk, (struct sockaddr *)addr, 1); + return sctp_send_asconf_del_ip(net, sk, + (struct sockaddr *)addr, 1); } /* Helper for tunneling sctp_bindx() requests through sctp_setsockopt() @@ -969,6 +976,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr *sa_addr; void *addr_buf; struct sctp_af *af; + struct net *net = sock_net(sk); SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p" " addrs_size %d opt %d\n", sk, addrs, addrs_size, op); @@ -1019,14 +1027,14 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, err = sctp_bindx_add(sk, kaddrs, addrcnt); if (err) goto out; - err = sctp_send_asconf_add_ip(sk, kaddrs, addrcnt); + err = sctp_send_asconf_add_ip(net, sk, kaddrs, addrcnt); break; case SCTP_BINDX_REM_ADDR: err = sctp_bindx_rem(sk, kaddrs, addrcnt); if (err) goto out; - err = sctp_send_asconf_del_ip(sk, kaddrs, addrcnt); + err = sctp_send_asconf_del_ip(net, sk, kaddrs, addrcnt); break; default: @@ -1170,8 +1178,9 @@ static int __sctp_connect(struct sock* sk, goto out_free; } - err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, - GFP_KERNEL); + err = sctp_assoc_set_bind_addr_from_ep(asoc, + sock_net(sk), + scope, GFP_KERNEL); if (err < 0) { goto out_free; } @@ -1797,7 +1806,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, goto out_unlock; } asoc = new_asoc; - err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL); + err = sctp_assoc_set_bind_addr_from_ep(asoc, sock_net(sk), + scope, GFP_KERNEL); if (err < 0) { err = -ENOMEM; goto out_free; @@ -2309,7 +2319,8 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, * SPP_SACKDELAY_ENABLE, setting both will have undefined * results. */ -static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, +static int sctp_apply_peer_addr_params(struct net *net, + struct sctp_paddrparams *params, struct sctp_transport *trans, struct sctp_association *asoc, struct sctp_sock *sp, @@ -2389,7 +2400,8 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, trans->param_flags = (trans->param_flags & ~SPP_PMTUD) | pmtud_change; if (update) { - sctp_transport_pmtu(trans, sctp_opt2sk(sp)); + sctp_transport_pmtu(net, trans, + sctp_opt2sk(sp)); sctp_assoc_sync_pmtu(sctp_opt2sk(sp), asoc); } } else if (asoc) { @@ -2457,6 +2469,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, struct sctp_transport *trans = NULL; struct sctp_association *asoc = NULL; struct sctp_sock *sp = sctp_sk(sk); + struct net *net = sock_net(sk); int error; int hb_change, pmtud_change, sackdelay_change; @@ -2504,7 +2517,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, return -EINVAL; /* Process parameters. */ - error = sctp_apply_peer_addr_params(¶ms, trans, asoc, sp, + error = sctp_apply_peer_addr_params(net, ¶ms, trans, asoc, sp, hb_change, pmtud_change, sackdelay_change); @@ -2517,8 +2530,8 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, if (!trans && asoc) { list_for_each_entry(trans, &asoc->peer.transport_addr_list, transports) { - sctp_apply_peer_addr_params(¶ms, trans, asoc, sp, - hb_change, pmtud_change, + sctp_apply_peer_addr_params(net, ¶ms, trans, asoc, + sp, hb_change, pmtud_change, sackdelay_change); } } @@ -4653,9 +4666,11 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, union sctp_addr temp; int cnt = 0; int addrlen; + struct sctp_net_params *net_params = + sctp_get_params(sock_net(sk)); rcu_read_lock(); - list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) { + list_for_each_entry_rcu(addr, &net_params->local_addr_list, list) { if (!addr->valid) continue; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index c97472b..856ba86 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -214,12 +214,14 @@ void sctp_transport_set_owner(struct sctp_transport *transport, } /* Initialize the pmtu of a transport. */ -void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) +void sctp_transport_pmtu(struct net *net, struct sctp_transport *transport, + struct sock *sk) { /* If we don't have a fresh route, look one up */ if (!transport->dst || transport->dst->obsolete) { dst_release(transport->dst); - transport->af_specific->get_dst(transport, &transport->saddr, + transport->af_specific->get_dst(net, transport, + &transport->saddr, &transport->fl, sk); } @@ -247,27 +249,28 @@ void sctp_transport_update_pmtu(struct sock *sk, struct sctp_transport *t, u32 p dst = sctp_transport_dst_check(t); if (!dst) - t->af_specific->get_dst(t, &t->saddr, &t->fl, sk); + t->af_specific->get_dst(sock_net(sk), t, &t->saddr, &t->fl, sk); if (dst) { dst->ops->update_pmtu(dst, sk, NULL, pmtu); dst = sctp_transport_dst_check(t); if (!dst) - t->af_specific->get_dst(t, &t->saddr, &t->fl, sk); + t->af_specific->get_dst(sock_net(sk), t, &t->saddr, + &t->fl, sk); } } /* Caches the dst entry and source address for a transport's destination * address. */ -void sctp_transport_route(struct sctp_transport *transport, +void sctp_transport_route(struct net *net, struct sctp_transport *transport, union sctp_addr *saddr, struct sctp_sock *opt) { struct sctp_association *asoc = transport->asoc; struct sctp_af *af = transport->af_specific; - af->get_dst(transport, saddr, &transport->fl, sctp_opt2sk(opt)); + af->get_dst(net, transport, saddr, &transport->fl, sctp_opt2sk(opt)); if (saddr) memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-sctp" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html