diff options
Diffstat (limited to 'net/dccp/input.c')
-rw-r--r-- | net/dccp/input.c | 164 |
1 files changed, 73 insertions, 91 deletions
diff --git a/net/dccp/input.c b/net/dccp/input.c index 779d0ed9ae94..df0e6714aa11 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c | |||
@@ -159,13 +159,15 @@ static void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb) | |||
159 | dccp_time_wait(sk, DCCP_TIME_WAIT, 0); | 159 | dccp_time_wait(sk, DCCP_TIME_WAIT, 0); |
160 | } | 160 | } |
161 | 161 | ||
162 | static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) | 162 | static void dccp_handle_ackvec_processing(struct sock *sk, struct sk_buff *skb) |
163 | { | 163 | { |
164 | struct dccp_sock *dp = dccp_sk(sk); | 164 | struct dccp_ackvec *av = dccp_sk(sk)->dccps_hc_rx_ackvec; |
165 | 165 | ||
166 | if (dccp_msk(sk)->dccpms_send_ack_vector) | 166 | if (av == NULL) |
167 | dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk, | 167 | return; |
168 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 168 | if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) |
169 | dccp_ackvec_clear_state(av, DCCP_SKB_CB(skb)->dccpd_ack_seq); | ||
170 | dccp_ackvec_input(av, skb); | ||
169 | } | 171 | } |
170 | 172 | ||
171 | static void dccp_deliver_input_to_ccids(struct sock *sk, struct sk_buff *skb) | 173 | static void dccp_deliver_input_to_ccids(struct sock *sk, struct sk_buff *skb) |
@@ -364,22 +366,13 @@ discard: | |||
364 | int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, | 366 | int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, |
365 | const struct dccp_hdr *dh, const unsigned len) | 367 | const struct dccp_hdr *dh, const unsigned len) |
366 | { | 368 | { |
367 | struct dccp_sock *dp = dccp_sk(sk); | ||
368 | |||
369 | if (dccp_check_seqno(sk, skb)) | 369 | if (dccp_check_seqno(sk, skb)) |
370 | goto discard; | 370 | goto discard; |
371 | 371 | ||
372 | if (dccp_parse_options(sk, NULL, skb)) | 372 | if (dccp_parse_options(sk, NULL, skb)) |
373 | return 1; | 373 | return 1; |
374 | 374 | ||
375 | if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) | 375 | dccp_handle_ackvec_processing(sk, skb); |
376 | dccp_event_ack_recv(sk, skb); | ||
377 | |||
378 | if (dccp_msk(sk)->dccpms_send_ack_vector && | ||
379 | dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, | ||
380 | DCCP_SKB_CB(skb)->dccpd_seq, | ||
381 | DCCP_ACKVEC_STATE_RECEIVED)) | ||
382 | goto discard; | ||
383 | dccp_deliver_input_to_ccids(sk, skb); | 376 | dccp_deliver_input_to_ccids(sk, skb); |
384 | 377 | ||
385 | return __dccp_rcv_established(sk, skb, dh, len); | 378 | return __dccp_rcv_established(sk, skb, dh, len); |
@@ -421,40 +414,33 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, | |||
421 | goto out_invalid_packet; | 414 | goto out_invalid_packet; |
422 | } | 415 | } |
423 | 416 | ||
417 | /* | ||
418 | * If option processing (Step 8) failed, return 1 here so that | ||
419 | * dccp_v4_do_rcv() sends a Reset. The Reset code depends on | ||
420 | * the option type and is set in dccp_parse_options(). | ||
421 | */ | ||
424 | if (dccp_parse_options(sk, NULL, skb)) | 422 | if (dccp_parse_options(sk, NULL, skb)) |
425 | goto out_invalid_packet; | 423 | return 1; |
426 | 424 | ||
427 | /* Obtain usec RTT sample from SYN exchange (used by CCID 3) */ | 425 | /* Obtain usec RTT sample from SYN exchange (used by CCID 3) */ |
428 | if (likely(dp->dccps_options_received.dccpor_timestamp_echo)) | 426 | if (likely(dp->dccps_options_received.dccpor_timestamp_echo)) |
429 | dp->dccps_syn_rtt = dccp_sample_rtt(sk, 10 * (tstamp - | 427 | dp->dccps_syn_rtt = dccp_sample_rtt(sk, 10 * (tstamp - |
430 | dp->dccps_options_received.dccpor_timestamp_echo)); | 428 | dp->dccps_options_received.dccpor_timestamp_echo)); |
431 | 429 | ||
432 | if (dccp_msk(sk)->dccpms_send_ack_vector && | ||
433 | dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, | ||
434 | DCCP_SKB_CB(skb)->dccpd_seq, | ||
435 | DCCP_ACKVEC_STATE_RECEIVED)) | ||
436 | goto out_invalid_packet; /* FIXME: change error code */ | ||
437 | |||
438 | /* Stop the REQUEST timer */ | 430 | /* Stop the REQUEST timer */ |
439 | inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); | 431 | inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); |
440 | WARN_ON(sk->sk_send_head == NULL); | 432 | WARN_ON(sk->sk_send_head == NULL); |
441 | kfree_skb(sk->sk_send_head); | 433 | kfree_skb(sk->sk_send_head); |
442 | sk->sk_send_head = NULL; | 434 | sk->sk_send_head = NULL; |
443 | 435 | ||
444 | dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq; | ||
445 | dccp_update_gsr(sk, dp->dccps_isr); | ||
446 | /* | 436 | /* |
447 | * SWL and AWL are initially adjusted so that they are not less than | 437 | * Set ISR, GSR from packet. ISS was set in dccp_v{4,6}_connect |
448 | * the initial Sequence Numbers received and sent, respectively: | 438 | * and GSS in dccp_transmit_skb(). Setting AWL/AWH and SWL/SWH |
449 | * SWL := max(GSR + 1 - floor(W/4), ISR), | 439 | * is done as part of activating the feature values below, since |
450 | * AWL := max(GSS - W' + 1, ISS). | 440 | * these settings depend on the local/remote Sequence Window |
451 | * These adjustments MUST be applied only at the beginning of the | 441 | * features, which were undefined or not confirmed until now. |
452 | * connection. | ||
453 | * | ||
454 | * AWL was adjusted in dccp_v4_connect -acme | ||
455 | */ | 442 | */ |
456 | dccp_set_seqno(&dp->dccps_swl, | 443 | dp->dccps_gsr = dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq; |
457 | max48(dp->dccps_swl, dp->dccps_isr)); | ||
458 | 444 | ||
459 | dccp_sync_mss(sk, icsk->icsk_pmtu_cookie); | 445 | dccp_sync_mss(sk, icsk->icsk_pmtu_cookie); |
460 | 446 | ||
@@ -475,6 +461,15 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, | |||
475 | */ | 461 | */ |
476 | dccp_set_state(sk, DCCP_PARTOPEN); | 462 | dccp_set_state(sk, DCCP_PARTOPEN); |
477 | 463 | ||
464 | /* | ||
465 | * If feature negotiation was successful, activate features now; | ||
466 | * an activation failure means that this host could not activate | ||
467 | * one ore more features (e.g. insufficient memory), which would | ||
468 | * leave at least one feature in an undefined state. | ||
469 | */ | ||
470 | if (dccp_feat_activate_values(sk, &dp->dccps_featneg)) | ||
471 | goto unable_to_proceed; | ||
472 | |||
478 | /* Make sure socket is routed, for correct metrics. */ | 473 | /* Make sure socket is routed, for correct metrics. */ |
479 | icsk->icsk_af_ops->rebuild_header(sk); | 474 | icsk->icsk_af_ops->rebuild_header(sk); |
480 | 475 | ||
@@ -509,6 +504,16 @@ out_invalid_packet: | |||
509 | /* dccp_v4_do_rcv will send a reset */ | 504 | /* dccp_v4_do_rcv will send a reset */ |
510 | DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; | 505 | DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; |
511 | return 1; | 506 | return 1; |
507 | |||
508 | unable_to_proceed: | ||
509 | DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_ABORTED; | ||
510 | /* | ||
511 | * We mark this socket as no longer usable, so that the loop in | ||
512 | * dccp_sendmsg() terminates and the application gets notified. | ||
513 | */ | ||
514 | dccp_set_state(sk, DCCP_CLOSED); | ||
515 | sk->sk_err = ECOMM; | ||
516 | return 1; | ||
512 | } | 517 | } |
513 | 518 | ||
514 | static int dccp_rcv_respond_partopen_state_process(struct sock *sk, | 519 | static int dccp_rcv_respond_partopen_state_process(struct sock *sk, |
@@ -590,8 +595,6 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
590 | if (inet_csk(sk)->icsk_af_ops->conn_request(sk, | 595 | if (inet_csk(sk)->icsk_af_ops->conn_request(sk, |
591 | skb) < 0) | 596 | skb) < 0) |
592 | return 1; | 597 | return 1; |
593 | |||
594 | /* FIXME: do congestion control initialization */ | ||
595 | goto discard; | 598 | goto discard; |
596 | } | 599 | } |
597 | if (dh->dccph_type == DCCP_PKT_RESET) | 600 | if (dh->dccph_type == DCCP_PKT_RESET) |
@@ -600,30 +603,36 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
600 | /* Caller (dccp_v4_do_rcv) will send Reset */ | 603 | /* Caller (dccp_v4_do_rcv) will send Reset */ |
601 | dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; | 604 | dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; |
602 | return 1; | 605 | return 1; |
606 | } else if (sk->sk_state == DCCP_CLOSED) { | ||
607 | dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; | ||
608 | return 1; | ||
603 | } | 609 | } |
604 | 610 | ||
605 | if (sk->sk_state != DCCP_REQUESTING) { | 611 | /* Step 6: Check sequence numbers (omitted in LISTEN/REQUEST state) */ |
606 | if (dccp_check_seqno(sk, skb)) | 612 | if (sk->sk_state != DCCP_REQUESTING && dccp_check_seqno(sk, skb)) |
607 | goto discard; | 613 | goto discard; |
608 | |||
609 | /* | ||
610 | * Step 8: Process options and mark acknowledgeable | ||
611 | */ | ||
612 | if (dccp_parse_options(sk, NULL, skb)) | ||
613 | return 1; | ||
614 | |||
615 | if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) | ||
616 | dccp_event_ack_recv(sk, skb); | ||
617 | |||
618 | if (dccp_msk(sk)->dccpms_send_ack_vector && | ||
619 | dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, | ||
620 | DCCP_SKB_CB(skb)->dccpd_seq, | ||
621 | DCCP_ACKVEC_STATE_RECEIVED)) | ||
622 | goto discard; | ||
623 | 614 | ||
624 | dccp_deliver_input_to_ccids(sk, skb); | 615 | /* |
616 | * Step 7: Check for unexpected packet types | ||
617 | * If (S.is_server and P.type == Response) | ||
618 | * or (S.is_client and P.type == Request) | ||
619 | * or (S.state == RESPOND and P.type == Data), | ||
620 | * Send Sync packet acknowledging P.seqno | ||
621 | * Drop packet and return | ||
622 | */ | ||
623 | if ((dp->dccps_role != DCCP_ROLE_CLIENT && | ||
624 | dh->dccph_type == DCCP_PKT_RESPONSE) || | ||
625 | (dp->dccps_role == DCCP_ROLE_CLIENT && | ||
626 | dh->dccph_type == DCCP_PKT_REQUEST) || | ||
627 | (sk->sk_state == DCCP_RESPOND && dh->dccph_type == DCCP_PKT_DATA)) { | ||
628 | dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC); | ||
629 | goto discard; | ||
625 | } | 630 | } |
626 | 631 | ||
632 | /* Step 8: Process options */ | ||
633 | if (dccp_parse_options(sk, NULL, skb)) | ||
634 | return 1; | ||
635 | |||
627 | /* | 636 | /* |
628 | * Step 9: Process Reset | 637 | * Step 9: Process Reset |
629 | * If P.type == Reset, | 638 | * If P.type == Reset, |
@@ -631,44 +640,22 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
631 | * S.state := TIMEWAIT | 640 | * S.state := TIMEWAIT |
632 | * Set TIMEWAIT timer | 641 | * Set TIMEWAIT timer |
633 | * Drop packet and return | 642 | * Drop packet and return |
634 | */ | 643 | */ |
635 | if (dh->dccph_type == DCCP_PKT_RESET) { | 644 | if (dh->dccph_type == DCCP_PKT_RESET) { |
636 | dccp_rcv_reset(sk, skb); | 645 | dccp_rcv_reset(sk, skb); |
637 | return 0; | 646 | return 0; |
638 | /* | 647 | } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { /* Step 13 */ |
639 | * Step 7: Check for unexpected packet types | ||
640 | * If (S.is_server and P.type == Response) | ||
641 | * or (S.is_client and P.type == Request) | ||
642 | * or (S.state == RESPOND and P.type == Data), | ||
643 | * Send Sync packet acknowledging P.seqno | ||
644 | * Drop packet and return | ||
645 | */ | ||
646 | } else if ((dp->dccps_role != DCCP_ROLE_CLIENT && | ||
647 | dh->dccph_type == DCCP_PKT_RESPONSE) || | ||
648 | (dp->dccps_role == DCCP_ROLE_CLIENT && | ||
649 | dh->dccph_type == DCCP_PKT_REQUEST) || | ||
650 | (sk->sk_state == DCCP_RESPOND && | ||
651 | dh->dccph_type == DCCP_PKT_DATA)) { | ||
652 | dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC); | ||
653 | goto discard; | ||
654 | } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { | ||
655 | if (dccp_rcv_closereq(sk, skb)) | 648 | if (dccp_rcv_closereq(sk, skb)) |
656 | return 0; | 649 | return 0; |
657 | goto discard; | 650 | goto discard; |
658 | } else if (dh->dccph_type == DCCP_PKT_CLOSE) { | 651 | } else if (dh->dccph_type == DCCP_PKT_CLOSE) { /* Step 14 */ |
659 | if (dccp_rcv_close(sk, skb)) | 652 | if (dccp_rcv_close(sk, skb)) |
660 | return 0; | 653 | return 0; |
661 | goto discard; | 654 | goto discard; |
662 | } | 655 | } |
663 | 656 | ||
664 | switch (sk->sk_state) { | 657 | switch (sk->sk_state) { |
665 | case DCCP_CLOSED: | ||
666 | dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; | ||
667 | return 1; | ||
668 | |||
669 | case DCCP_REQUESTING: | 658 | case DCCP_REQUESTING: |
670 | /* FIXME: do congestion control initialization */ | ||
671 | |||
672 | queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len); | 659 | queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len); |
673 | if (queued >= 0) | 660 | if (queued >= 0) |
674 | return queued; | 661 | return queued; |
@@ -676,8 +663,12 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
676 | __kfree_skb(skb); | 663 | __kfree_skb(skb); |
677 | return 0; | 664 | return 0; |
678 | 665 | ||
679 | case DCCP_RESPOND: | ||
680 | case DCCP_PARTOPEN: | 666 | case DCCP_PARTOPEN: |
667 | /* Step 8: if using Ack Vectors, mark packet acknowledgeable */ | ||
668 | dccp_handle_ackvec_processing(sk, skb); | ||
669 | dccp_deliver_input_to_ccids(sk, skb); | ||
670 | /* fall through */ | ||
671 | case DCCP_RESPOND: | ||
681 | queued = dccp_rcv_respond_partopen_state_process(sk, skb, | 672 | queued = dccp_rcv_respond_partopen_state_process(sk, skb, |
682 | dh, len); | 673 | dh, len); |
683 | break; | 674 | break; |
@@ -716,16 +707,7 @@ u32 dccp_sample_rtt(struct sock *sk, long delta) | |||
716 | /* dccpor_elapsed_time is either zeroed out or set and > 0 */ | 707 | /* dccpor_elapsed_time is either zeroed out or set and > 0 */ |
717 | delta -= dccp_sk(sk)->dccps_options_received.dccpor_elapsed_time * 10; | 708 | delta -= dccp_sk(sk)->dccps_options_received.dccpor_elapsed_time * 10; |
718 | 709 | ||
719 | if (unlikely(delta <= 0)) { | 710 | return dccp_sane_rtt(delta); |
720 | DCCP_WARN("unusable RTT sample %ld, using min\n", delta); | ||
721 | return DCCP_SANE_RTT_MIN; | ||
722 | } | ||
723 | if (unlikely(delta > DCCP_SANE_RTT_MAX)) { | ||
724 | DCCP_WARN("RTT sample %ld too large, using max\n", delta); | ||
725 | return DCCP_SANE_RTT_MAX; | ||
726 | } | ||
727 | |||
728 | return delta; | ||
729 | } | 711 | } |
730 | 712 | ||
731 | EXPORT_SYMBOL_GPL(dccp_sample_rtt); | 713 | EXPORT_SYMBOL_GPL(dccp_sample_rtt); |