diff options
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 56 |
1 files changed, 34 insertions, 22 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e96b15a66aba..f73e9d38d5ba 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2658,20 +2658,23 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2658 | } | 2658 | } |
2659 | 2659 | ||
2660 | if (params->spp_flags & SPP_IPV6_FLOWLABEL) { | 2660 | if (params->spp_flags & SPP_IPV6_FLOWLABEL) { |
2661 | if (trans && trans->ipaddr.sa.sa_family == AF_INET6) { | 2661 | if (trans) { |
2662 | trans->flowlabel = params->spp_ipv6_flowlabel & | 2662 | if (trans->ipaddr.sa.sa_family == AF_INET6) { |
2663 | SCTP_FLOWLABEL_VAL_MASK; | ||
2664 | trans->flowlabel |= SCTP_FLOWLABEL_SET_MASK; | ||
2665 | } else if (asoc) { | ||
2666 | list_for_each_entry(trans, | ||
2667 | &asoc->peer.transport_addr_list, | ||
2668 | transports) { | ||
2669 | if (trans->ipaddr.sa.sa_family != AF_INET6) | ||
2670 | continue; | ||
2671 | trans->flowlabel = params->spp_ipv6_flowlabel & | 2663 | trans->flowlabel = params->spp_ipv6_flowlabel & |
2672 | SCTP_FLOWLABEL_VAL_MASK; | 2664 | SCTP_FLOWLABEL_VAL_MASK; |
2673 | trans->flowlabel |= SCTP_FLOWLABEL_SET_MASK; | 2665 | trans->flowlabel |= SCTP_FLOWLABEL_SET_MASK; |
2674 | } | 2666 | } |
2667 | } else if (asoc) { | ||
2668 | struct sctp_transport *t; | ||
2669 | |||
2670 | list_for_each_entry(t, &asoc->peer.transport_addr_list, | ||
2671 | transports) { | ||
2672 | if (t->ipaddr.sa.sa_family != AF_INET6) | ||
2673 | continue; | ||
2674 | t->flowlabel = params->spp_ipv6_flowlabel & | ||
2675 | SCTP_FLOWLABEL_VAL_MASK; | ||
2676 | t->flowlabel |= SCTP_FLOWLABEL_SET_MASK; | ||
2677 | } | ||
2675 | asoc->flowlabel = params->spp_ipv6_flowlabel & | 2678 | asoc->flowlabel = params->spp_ipv6_flowlabel & |
2676 | SCTP_FLOWLABEL_VAL_MASK; | 2679 | SCTP_FLOWLABEL_VAL_MASK; |
2677 | asoc->flowlabel |= SCTP_FLOWLABEL_SET_MASK; | 2680 | asoc->flowlabel |= SCTP_FLOWLABEL_SET_MASK; |
@@ -2687,12 +2690,13 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2687 | trans->dscp = params->spp_dscp & SCTP_DSCP_VAL_MASK; | 2690 | trans->dscp = params->spp_dscp & SCTP_DSCP_VAL_MASK; |
2688 | trans->dscp |= SCTP_DSCP_SET_MASK; | 2691 | trans->dscp |= SCTP_DSCP_SET_MASK; |
2689 | } else if (asoc) { | 2692 | } else if (asoc) { |
2690 | list_for_each_entry(trans, | 2693 | struct sctp_transport *t; |
2691 | &asoc->peer.transport_addr_list, | 2694 | |
2695 | list_for_each_entry(t, &asoc->peer.transport_addr_list, | ||
2692 | transports) { | 2696 | transports) { |
2693 | trans->dscp = params->spp_dscp & | 2697 | t->dscp = params->spp_dscp & |
2694 | SCTP_DSCP_VAL_MASK; | 2698 | SCTP_DSCP_VAL_MASK; |
2695 | trans->dscp |= SCTP_DSCP_SET_MASK; | 2699 | t->dscp |= SCTP_DSCP_SET_MASK; |
2696 | } | 2700 | } |
2697 | asoc->dscp = params->spp_dscp & SCTP_DSCP_VAL_MASK; | 2701 | asoc->dscp = params->spp_dscp & SCTP_DSCP_VAL_MASK; |
2698 | asoc->dscp |= SCTP_DSCP_SET_MASK; | 2702 | asoc->dscp |= SCTP_DSCP_SET_MASK; |
@@ -5005,9 +5009,14 @@ struct sctp_transport *sctp_transport_get_next(struct net *net, | |||
5005 | break; | 5009 | break; |
5006 | } | 5010 | } |
5007 | 5011 | ||
5012 | if (!sctp_transport_hold(t)) | ||
5013 | continue; | ||
5014 | |||
5008 | if (net_eq(sock_net(t->asoc->base.sk), net) && | 5015 | if (net_eq(sock_net(t->asoc->base.sk), net) && |
5009 | t->asoc->peer.primary_path == t) | 5016 | t->asoc->peer.primary_path == t) |
5010 | break; | 5017 | break; |
5018 | |||
5019 | sctp_transport_put(t); | ||
5011 | } | 5020 | } |
5012 | 5021 | ||
5013 | return t; | 5022 | return t; |
@@ -5017,13 +5026,18 @@ struct sctp_transport *sctp_transport_get_idx(struct net *net, | |||
5017 | struct rhashtable_iter *iter, | 5026 | struct rhashtable_iter *iter, |
5018 | int pos) | 5027 | int pos) |
5019 | { | 5028 | { |
5020 | void *obj = SEQ_START_TOKEN; | 5029 | struct sctp_transport *t; |
5021 | 5030 | ||
5022 | while (pos && (obj = sctp_transport_get_next(net, iter)) && | 5031 | if (!pos) |
5023 | !IS_ERR(obj)) | 5032 | return SEQ_START_TOKEN; |
5024 | pos--; | ||
5025 | 5033 | ||
5026 | return obj; | 5034 | while ((t = sctp_transport_get_next(net, iter)) && !IS_ERR(t)) { |
5035 | if (!--pos) | ||
5036 | break; | ||
5037 | sctp_transport_put(t); | ||
5038 | } | ||
5039 | |||
5040 | return t; | ||
5027 | } | 5041 | } |
5028 | 5042 | ||
5029 | int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), | 5043 | int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), |
@@ -5082,8 +5096,6 @@ again: | |||
5082 | 5096 | ||
5083 | tsp = sctp_transport_get_idx(net, &hti, *pos + 1); | 5097 | tsp = sctp_transport_get_idx(net, &hti, *pos + 1); |
5084 | for (; !IS_ERR_OR_NULL(tsp); tsp = sctp_transport_get_next(net, &hti)) { | 5098 | for (; !IS_ERR_OR_NULL(tsp); tsp = sctp_transport_get_next(net, &hti)) { |
5085 | if (!sctp_transport_hold(tsp)) | ||
5086 | continue; | ||
5087 | ret = cb(tsp, p); | 5099 | ret = cb(tsp, p); |
5088 | if (ret) | 5100 | if (ret) |
5089 | break; | 5101 | break; |