diff options
Diffstat (limited to 'net/sctp/input.c')
-rw-r--r-- | net/sctp/input.c | 71 |
1 files changed, 28 insertions, 43 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c index 339f7acfdb64..742be9171b7d 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -115,6 +115,17 @@ static void sctp_rcv_set_owner_r(struct sk_buff *skb, struct sock *sk) | |||
115 | atomic_add(sizeof(struct sctp_chunk),&sk->sk_rmem_alloc); | 115 | atomic_add(sizeof(struct sctp_chunk),&sk->sk_rmem_alloc); |
116 | } | 116 | } |
117 | 117 | ||
118 | struct sctp_input_cb { | ||
119 | union { | ||
120 | struct inet_skb_parm h4; | ||
121 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) | ||
122 | struct inet6_skb_parm h6; | ||
123 | #endif | ||
124 | } header; | ||
125 | struct sctp_chunk *chunk; | ||
126 | }; | ||
127 | #define SCTP_INPUT_CB(__skb) ((struct sctp_input_cb *)&((__skb)->cb[0])) | ||
128 | |||
118 | /* | 129 | /* |
119 | * This is the routine which IP calls when receiving an SCTP packet. | 130 | * This is the routine which IP calls when receiving an SCTP packet. |
120 | */ | 131 | */ |
@@ -243,6 +254,7 @@ int sctp_rcv(struct sk_buff *skb) | |||
243 | ret = -ENOMEM; | 254 | ret = -ENOMEM; |
244 | goto discard_release; | 255 | goto discard_release; |
245 | } | 256 | } |
257 | SCTP_INPUT_CB(skb)->chunk = chunk; | ||
246 | 258 | ||
247 | sctp_rcv_set_owner_r(skb,sk); | 259 | sctp_rcv_set_owner_r(skb,sk); |
248 | 260 | ||
@@ -265,9 +277,9 @@ int sctp_rcv(struct sk_buff *skb) | |||
265 | sctp_bh_lock_sock(sk); | 277 | sctp_bh_lock_sock(sk); |
266 | 278 | ||
267 | if (sock_owned_by_user(sk)) | 279 | if (sock_owned_by_user(sk)) |
268 | sk_add_backlog(sk, (struct sk_buff *) chunk); | 280 | sk_add_backlog(sk, skb); |
269 | else | 281 | else |
270 | sctp_backlog_rcv(sk, (struct sk_buff *) chunk); | 282 | sctp_backlog_rcv(sk, skb); |
271 | 283 | ||
272 | /* Release the sock and any reference counts we took in the | 284 | /* Release the sock and any reference counts we took in the |
273 | * lookup calls. | 285 | * lookup calls. |
@@ -302,14 +314,8 @@ discard_release: | |||
302 | */ | 314 | */ |
303 | int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) | 315 | int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) |
304 | { | 316 | { |
305 | struct sctp_chunk *chunk; | 317 | struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; |
306 | struct sctp_inq *inqueue; | 318 | struct sctp_inq *inqueue = &chunk->rcvr->inqueue; |
307 | |||
308 | /* One day chunk will live inside the skb, but for | ||
309 | * now this works. | ||
310 | */ | ||
311 | chunk = (struct sctp_chunk *) skb; | ||
312 | inqueue = &chunk->rcvr->inqueue; | ||
313 | 319 | ||
314 | sctp_inq_push(inqueue, chunk); | 320 | sctp_inq_push(inqueue, chunk); |
315 | return 0; | 321 | return 0; |
@@ -345,7 +351,6 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, | |||
345 | * | 351 | * |
346 | */ | 352 | */ |
347 | void sctp_icmp_proto_unreachable(struct sock *sk, | 353 | void sctp_icmp_proto_unreachable(struct sock *sk, |
348 | struct sctp_endpoint *ep, | ||
349 | struct sctp_association *asoc, | 354 | struct sctp_association *asoc, |
350 | struct sctp_transport *t) | 355 | struct sctp_transport *t) |
351 | { | 356 | { |
@@ -361,7 +366,6 @@ void sctp_icmp_proto_unreachable(struct sock *sk, | |||
361 | /* Common lookup code for icmp/icmpv6 error handler. */ | 366 | /* Common lookup code for icmp/icmpv6 error handler. */ |
362 | struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | 367 | struct sock *sctp_err_lookup(int family, struct sk_buff *skb, |
363 | struct sctphdr *sctphdr, | 368 | struct sctphdr *sctphdr, |
364 | struct sctp_endpoint **epp, | ||
365 | struct sctp_association **app, | 369 | struct sctp_association **app, |
366 | struct sctp_transport **tpp) | 370 | struct sctp_transport **tpp) |
367 | { | 371 | { |
@@ -369,11 +373,10 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
369 | union sctp_addr daddr; | 373 | union sctp_addr daddr; |
370 | struct sctp_af *af; | 374 | struct sctp_af *af; |
371 | struct sock *sk = NULL; | 375 | struct sock *sk = NULL; |
372 | struct sctp_endpoint *ep = NULL; | ||
373 | struct sctp_association *asoc = NULL; | 376 | struct sctp_association *asoc = NULL; |
374 | struct sctp_transport *transport = NULL; | 377 | struct sctp_transport *transport = NULL; |
375 | 378 | ||
376 | *app = NULL; *epp = NULL; *tpp = NULL; | 379 | *app = NULL; *tpp = NULL; |
377 | 380 | ||
378 | af = sctp_get_af_specific(family); | 381 | af = sctp_get_af_specific(family); |
379 | if (unlikely(!af)) { | 382 | if (unlikely(!af)) { |
@@ -388,26 +391,15 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
388 | * packet. | 391 | * packet. |
389 | */ | 392 | */ |
390 | asoc = __sctp_lookup_association(&saddr, &daddr, &transport); | 393 | asoc = __sctp_lookup_association(&saddr, &daddr, &transport); |
391 | if (!asoc) { | 394 | if (!asoc) |
392 | /* If there is no matching association, see if it matches any | 395 | return NULL; |
393 | * endpoint. This may happen for an ICMP error generated in | ||
394 | * response to an INIT_ACK. | ||
395 | */ | ||
396 | ep = __sctp_rcv_lookup_endpoint(&daddr); | ||
397 | if (!ep) { | ||
398 | return NULL; | ||
399 | } | ||
400 | } | ||
401 | 396 | ||
402 | if (asoc) { | 397 | sk = asoc->base.sk; |
403 | sk = asoc->base.sk; | ||
404 | 398 | ||
405 | if (ntohl(sctphdr->vtag) != asoc->c.peer_vtag) { | 399 | if (ntohl(sctphdr->vtag) != asoc->c.peer_vtag) { |
406 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); | 400 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); |
407 | goto out; | 401 | goto out; |
408 | } | 402 | } |
409 | } else | ||
410 | sk = ep->base.sk; | ||
411 | 403 | ||
412 | sctp_bh_lock_sock(sk); | 404 | sctp_bh_lock_sock(sk); |
413 | 405 | ||
@@ -417,7 +409,6 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
417 | if (sock_owned_by_user(sk)) | 409 | if (sock_owned_by_user(sk)) |
418 | NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS); | 410 | NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS); |
419 | 411 | ||
420 | *epp = ep; | ||
421 | *app = asoc; | 412 | *app = asoc; |
422 | *tpp = transport; | 413 | *tpp = transport; |
423 | return sk; | 414 | return sk; |
@@ -426,21 +417,16 @@ out: | |||
426 | sock_put(sk); | 417 | sock_put(sk); |
427 | if (asoc) | 418 | if (asoc) |
428 | sctp_association_put(asoc); | 419 | sctp_association_put(asoc); |
429 | if (ep) | ||
430 | sctp_endpoint_put(ep); | ||
431 | return NULL; | 420 | return NULL; |
432 | } | 421 | } |
433 | 422 | ||
434 | /* Common cleanup code for icmp/icmpv6 error handler. */ | 423 | /* Common cleanup code for icmp/icmpv6 error handler. */ |
435 | void sctp_err_finish(struct sock *sk, struct sctp_endpoint *ep, | 424 | void sctp_err_finish(struct sock *sk, struct sctp_association *asoc) |
436 | struct sctp_association *asoc) | ||
437 | { | 425 | { |
438 | sctp_bh_unlock_sock(sk); | 426 | sctp_bh_unlock_sock(sk); |
439 | sock_put(sk); | 427 | sock_put(sk); |
440 | if (asoc) | 428 | if (asoc) |
441 | sctp_association_put(asoc); | 429 | sctp_association_put(asoc); |
442 | if (ep) | ||
443 | sctp_endpoint_put(ep); | ||
444 | } | 430 | } |
445 | 431 | ||
446 | /* | 432 | /* |
@@ -465,7 +451,6 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
465 | int type = skb->h.icmph->type; | 451 | int type = skb->h.icmph->type; |
466 | int code = skb->h.icmph->code; | 452 | int code = skb->h.icmph->code; |
467 | struct sock *sk; | 453 | struct sock *sk; |
468 | struct sctp_endpoint *ep; | ||
469 | struct sctp_association *asoc; | 454 | struct sctp_association *asoc; |
470 | struct sctp_transport *transport; | 455 | struct sctp_transport *transport; |
471 | struct inet_sock *inet; | 456 | struct inet_sock *inet; |
@@ -482,7 +467,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
482 | savesctp = skb->h.raw; | 467 | savesctp = skb->h.raw; |
483 | skb->nh.iph = iph; | 468 | skb->nh.iph = iph; |
484 | skb->h.raw = (char *)sh; | 469 | skb->h.raw = (char *)sh; |
485 | sk = sctp_err_lookup(AF_INET, skb, sh, &ep, &asoc, &transport); | 470 | sk = sctp_err_lookup(AF_INET, skb, sh, &asoc, &transport); |
486 | /* Put back, the original pointers. */ | 471 | /* Put back, the original pointers. */ |
487 | skb->nh.raw = saveip; | 472 | skb->nh.raw = saveip; |
488 | skb->h.raw = savesctp; | 473 | skb->h.raw = savesctp; |
@@ -509,7 +494,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
509 | } | 494 | } |
510 | else { | 495 | else { |
511 | if (ICMP_PROT_UNREACH == code) { | 496 | if (ICMP_PROT_UNREACH == code) { |
512 | sctp_icmp_proto_unreachable(sk, ep, asoc, | 497 | sctp_icmp_proto_unreachable(sk, asoc, |
513 | transport); | 498 | transport); |
514 | goto out_unlock; | 499 | goto out_unlock; |
515 | } | 500 | } |
@@ -538,7 +523,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
538 | } | 523 | } |
539 | 524 | ||
540 | out_unlock: | 525 | out_unlock: |
541 | sctp_err_finish(sk, ep, asoc); | 526 | sctp_err_finish(sk, asoc); |
542 | } | 527 | } |
543 | 528 | ||
544 | /* | 529 | /* |