diff options
Diffstat (limited to 'net/sctp/socket.c')
| -rw-r--r-- | net/sctp/socket.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 2fc0a92caa78..9f1a908776de 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -972,6 +972,7 @@ static int __sctp_connect(struct sock* sk, | |||
| 972 | int walk_size = 0; | 972 | int walk_size = 0; |
| 973 | union sctp_addr *sa_addr; | 973 | union sctp_addr *sa_addr; |
| 974 | void *addr_buf; | 974 | void *addr_buf; |
| 975 | unsigned short port; | ||
| 975 | 976 | ||
| 976 | sp = sctp_sk(sk); | 977 | sp = sctp_sk(sk); |
| 977 | ep = sp->ep; | 978 | ep = sp->ep; |
| @@ -992,6 +993,7 @@ static int __sctp_connect(struct sock* sk, | |||
| 992 | while (walk_size < addrs_size) { | 993 | while (walk_size < addrs_size) { |
| 993 | sa_addr = (union sctp_addr *)addr_buf; | 994 | sa_addr = (union sctp_addr *)addr_buf; |
| 994 | af = sctp_get_af_specific(sa_addr->sa.sa_family); | 995 | af = sctp_get_af_specific(sa_addr->sa.sa_family); |
| 996 | port = ntohs(sa_addr->v4.sin_port); | ||
| 995 | 997 | ||
| 996 | /* If the address family is not supported or if this address | 998 | /* If the address family is not supported or if this address |
| 997 | * causes the address buffer to overflow return EINVAL. | 999 | * causes the address buffer to overflow return EINVAL. |
| @@ -1005,6 +1007,12 @@ static int __sctp_connect(struct sock* sk, | |||
| 1005 | if (err) | 1007 | if (err) |
| 1006 | goto out_free; | 1008 | goto out_free; |
| 1007 | 1009 | ||
| 1010 | /* Make sure the destination port is correctly set | ||
| 1011 | * in all addresses. | ||
| 1012 | */ | ||
| 1013 | if (asoc && asoc->peer.port && asoc->peer.port != port) | ||
| 1014 | goto out_free; | ||
| 1015 | |||
| 1008 | memcpy(&to, sa_addr, af->sockaddr_len); | 1016 | memcpy(&to, sa_addr, af->sockaddr_len); |
| 1009 | 1017 | ||
| 1010 | /* Check if there already is a matching association on the | 1018 | /* Check if there already is a matching association on the |
| @@ -5012,7 +5020,8 @@ pp_found: | |||
| 5012 | struct hlist_node *node; | 5020 | struct hlist_node *node; |
| 5013 | 5021 | ||
| 5014 | SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n"); | 5022 | SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n"); |
| 5015 | if (pp->fastreuse && sk->sk_reuse) | 5023 | if (pp->fastreuse && sk->sk_reuse && |
| 5024 | sk->sk_state != SCTP_SS_LISTENING) | ||
| 5016 | goto success; | 5025 | goto success; |
| 5017 | 5026 | ||
| 5018 | /* Run through the list of sockets bound to the port | 5027 | /* Run through the list of sockets bound to the port |
| @@ -5029,7 +5038,8 @@ pp_found: | |||
| 5029 | struct sctp_endpoint *ep2; | 5038 | struct sctp_endpoint *ep2; |
| 5030 | ep2 = sctp_sk(sk2)->ep; | 5039 | ep2 = sctp_sk(sk2)->ep; |
| 5031 | 5040 | ||
| 5032 | if (reuse && sk2->sk_reuse) | 5041 | if (reuse && sk2->sk_reuse && |
| 5042 | sk2->sk_state != SCTP_SS_LISTENING) | ||
| 5033 | continue; | 5043 | continue; |
| 5034 | 5044 | ||
| 5035 | if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, | 5045 | if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, |
| @@ -5050,9 +5060,13 @@ pp_not_found: | |||
| 5050 | * if sk->sk_reuse is too (that is, if the caller requested | 5060 | * if sk->sk_reuse is too (that is, if the caller requested |
| 5051 | * SO_REUSEADDR on this socket -sk-). | 5061 | * SO_REUSEADDR on this socket -sk-). |
| 5052 | */ | 5062 | */ |
| 5053 | if (hlist_empty(&pp->owner)) | 5063 | if (hlist_empty(&pp->owner)) { |
| 5054 | pp->fastreuse = sk->sk_reuse ? 1 : 0; | 5064 | if (sk->sk_reuse && sk->sk_state != SCTP_SS_LISTENING) |
| 5055 | else if (pp->fastreuse && !sk->sk_reuse) | 5065 | pp->fastreuse = 1; |
| 5066 | else | ||
| 5067 | pp->fastreuse = 0; | ||
| 5068 | } else if (pp->fastreuse && | ||
| 5069 | (!sk->sk_reuse || sk->sk_state == SCTP_SS_LISTENING)) | ||
| 5056 | pp->fastreuse = 0; | 5070 | pp->fastreuse = 0; |
| 5057 | 5071 | ||
| 5058 | /* We are set, so fill up all the data in the hash table | 5072 | /* We are set, so fill up all the data in the hash table |
| @@ -5060,8 +5074,8 @@ pp_not_found: | |||
| 5060 | * sockets FIXME: Blurry, NPI (ipg). | 5074 | * sockets FIXME: Blurry, NPI (ipg). |
| 5061 | */ | 5075 | */ |
| 5062 | success: | 5076 | success: |
| 5063 | inet_sk(sk)->num = snum; | ||
| 5064 | if (!sctp_sk(sk)->bind_hash) { | 5077 | if (!sctp_sk(sk)->bind_hash) { |
| 5078 | inet_sk(sk)->num = snum; | ||
| 5065 | sk_add_bind_node(sk, &pp->owner); | 5079 | sk_add_bind_node(sk, &pp->owner); |
| 5066 | sctp_sk(sk)->bind_hash = pp; | 5080 | sctp_sk(sk)->bind_hash = pp; |
| 5067 | } | 5081 | } |
| @@ -5134,12 +5148,16 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | |||
| 5134 | * This is not currently spelled out in the SCTP sockets | 5148 | * This is not currently spelled out in the SCTP sockets |
| 5135 | * extensions draft, but follows the practice as seen in TCP | 5149 | * extensions draft, but follows the practice as seen in TCP |
| 5136 | * sockets. | 5150 | * sockets. |
| 5151 | * | ||
| 5152 | * Additionally, turn off fastreuse flag since we are not listening | ||
| 5137 | */ | 5153 | */ |
| 5154 | sk->sk_state = SCTP_SS_LISTENING; | ||
| 5138 | if (!ep->base.bind_addr.port) { | 5155 | if (!ep->base.bind_addr.port) { |
| 5139 | if (sctp_autobind(sk)) | 5156 | if (sctp_autobind(sk)) |
| 5140 | return -EAGAIN; | 5157 | return -EAGAIN; |
| 5141 | } | 5158 | } else |
| 5142 | sk->sk_state = SCTP_SS_LISTENING; | 5159 | sctp_sk(sk)->bind_hash->fastreuse = 0; |
| 5160 | |||
| 5143 | sctp_hash_endpoint(ep); | 5161 | sctp_hash_endpoint(ep); |
| 5144 | return 0; | 5162 | return 0; |
| 5145 | } | 5163 | } |
| @@ -5177,11 +5195,13 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) | |||
| 5177 | * extensions draft, but follows the practice as seen in TCP | 5195 | * extensions draft, but follows the practice as seen in TCP |
| 5178 | * sockets. | 5196 | * sockets. |
| 5179 | */ | 5197 | */ |
| 5198 | sk->sk_state = SCTP_SS_LISTENING; | ||
| 5180 | if (!ep->base.bind_addr.port) { | 5199 | if (!ep->base.bind_addr.port) { |
| 5181 | if (sctp_autobind(sk)) | 5200 | if (sctp_autobind(sk)) |
| 5182 | return -EAGAIN; | 5201 | return -EAGAIN; |
| 5183 | } | 5202 | } else |
| 5184 | sk->sk_state = SCTP_SS_LISTENING; | 5203 | sctp_sk(sk)->bind_hash->fastreuse = 0; |
| 5204 | |||
| 5185 | sk->sk_max_ack_backlog = backlog; | 5205 | sk->sk_max_ack_backlog = backlog; |
| 5186 | sctp_hash_endpoint(ep); | 5206 | sctp_hash_endpoint(ep); |
| 5187 | return 0; | 5207 | return 0; |
