aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/input.c')
-rw-r--r--net/sctp/input.c71
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
118struct 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 */
303int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) 315int 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 */
347void sctp_icmp_proto_unreachable(struct sock *sk, 353void 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. */
362struct sock *sctp_err_lookup(int family, struct sk_buff *skb, 367struct 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. */
435void sctp_err_finish(struct sock *sk, struct sctp_endpoint *ep, 424void 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
540out_unlock: 525out_unlock:
541 sctp_err_finish(sk, ep, asoc); 526 sctp_err_finish(sk, asoc);
542} 527}
543 528
544/* 529/*