diff options
Diffstat (limited to 'net/sctp/input.c')
| -rw-r--r-- | net/sctp/input.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c index b719a77d66b4..fffc880a646d 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
| @@ -178,6 +178,37 @@ int sctp_rcv(struct sk_buff *skb) | |||
| 178 | 178 | ||
| 179 | asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); | 179 | asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); |
| 180 | 180 | ||
| 181 | if (!asoc) | ||
| 182 | ep = __sctp_rcv_lookup_endpoint(&dest); | ||
| 183 | |||
| 184 | /* Retrieve the common input handling substructure. */ | ||
| 185 | rcvr = asoc ? &asoc->base : &ep->base; | ||
| 186 | sk = rcvr->sk; | ||
| 187 | |||
| 188 | /* | ||
| 189 | * If a frame arrives on an interface and the receiving socket is | ||
| 190 | * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB | ||
| 191 | */ | ||
| 192 | if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) | ||
| 193 | { | ||
| 194 | sock_put(sk); | ||
| 195 | if (asoc) { | ||
| 196 | sctp_association_put(asoc); | ||
| 197 | asoc = NULL; | ||
| 198 | } else { | ||
| 199 | sctp_endpoint_put(ep); | ||
| 200 | ep = NULL; | ||
| 201 | } | ||
| 202 | sk = sctp_get_ctl_sock(); | ||
| 203 | ep = sctp_sk(sk)->ep; | ||
| 204 | sctp_endpoint_hold(ep); | ||
| 205 | sock_hold(sk); | ||
| 206 | rcvr = &ep->base; | ||
| 207 | } | ||
| 208 | |||
| 209 | if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) | ||
| 210 | goto discard_release; | ||
| 211 | |||
| 181 | /* | 212 | /* |
| 182 | * RFC 2960, 8.4 - Handle "Out of the blue" Packets. | 213 | * RFC 2960, 8.4 - Handle "Out of the blue" Packets. |
| 183 | * An SCTP packet is called an "out of the blue" (OOTB) | 214 | * An SCTP packet is called an "out of the blue" (OOTB) |
| @@ -187,22 +218,12 @@ int sctp_rcv(struct sk_buff *skb) | |||
| 187 | * packet belongs. | 218 | * packet belongs. |
| 188 | */ | 219 | */ |
| 189 | if (!asoc) { | 220 | if (!asoc) { |
| 190 | ep = __sctp_rcv_lookup_endpoint(&dest); | ||
| 191 | if (sctp_rcv_ootb(skb)) { | 221 | if (sctp_rcv_ootb(skb)) { |
| 192 | SCTP_INC_STATS_BH(SCTP_MIB_OUTOFBLUES); | 222 | SCTP_INC_STATS_BH(SCTP_MIB_OUTOFBLUES); |
| 193 | goto discard_release; | 223 | goto discard_release; |
| 194 | } | 224 | } |
| 195 | } | 225 | } |
| 196 | 226 | ||
| 197 | /* Retrieve the common input handling substructure. */ | ||
| 198 | rcvr = asoc ? &asoc->base : &ep->base; | ||
| 199 | sk = rcvr->sk; | ||
| 200 | |||
| 201 | if ((sk) && (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)) { | ||
| 202 | goto discard_release; | ||
| 203 | } | ||
| 204 | |||
| 205 | |||
| 206 | /* SCTP seems to always need a timestamp right now (FIXME) */ | 227 | /* SCTP seems to always need a timestamp right now (FIXME) */ |
| 207 | if (skb->stamp.tv_sec == 0) { | 228 | if (skb->stamp.tv_sec == 0) { |
| 208 | do_gettimeofday(&skb->stamp); | 229 | do_gettimeofday(&skb->stamp); |
| @@ -265,13 +286,11 @@ discard_it: | |||
| 265 | 286 | ||
| 266 | discard_release: | 287 | discard_release: |
| 267 | /* Release any structures we may be holding. */ | 288 | /* Release any structures we may be holding. */ |
| 268 | if (asoc) { | 289 | sock_put(sk); |
| 269 | sock_put(asoc->base.sk); | 290 | if (asoc) |
| 270 | sctp_association_put(asoc); | 291 | sctp_association_put(asoc); |
| 271 | } else { | 292 | else |
| 272 | sock_put(ep->base.sk); | ||
| 273 | sctp_endpoint_put(ep); | 293 | sctp_endpoint_put(ep); |
| 274 | } | ||
| 275 | 294 | ||
| 276 | goto discard_it; | 295 | goto discard_it; |
| 277 | } | 296 | } |
