diff options
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r-- | net/dccp/options.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c index b11d7b7167f0..791e07853a79 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -430,6 +430,7 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | |||
430 | { | 430 | { |
431 | struct dccp_sock *dp = dccp_sk(sk); | 431 | struct dccp_sock *dp = dccp_sk(sk); |
432 | struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; | 432 | struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; |
433 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | ||
433 | const u16 buflen = dccp_ackvec_buflen(av); | 434 | const u16 buflen = dccp_ackvec_buflen(av); |
434 | /* Figure out how many options do we need to represent the ackvec */ | 435 | /* Figure out how many options do we need to represent the ackvec */ |
435 | const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN); | 436 | const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN); |
@@ -438,10 +439,25 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | |||
438 | const unsigned char *tail, *from; | 439 | const unsigned char *tail, *from; |
439 | unsigned char *to; | 440 | unsigned char *to; |
440 | 441 | ||
441 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) | 442 | if (dcb->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { |
443 | DCCP_WARN("Lacking space for %u bytes on %s packet\n", len, | ||
444 | dccp_packet_name(dcb->dccpd_type)); | ||
442 | return -1; | 445 | return -1; |
443 | 446 | } | |
444 | DCCP_SKB_CB(skb)->dccpd_opt_len += len; | 447 | /* |
448 | * Since Ack Vectors are variable-length, we can not always predict | ||
449 | * their size. To catch exception cases where the space is running out | ||
450 | * on the skb, a separate Sync is scheduled to carry the Ack Vector. | ||
451 | */ | ||
452 | if (len > DCCPAV_MIN_OPTLEN && | ||
453 | len + dcb->dccpd_opt_len + skb->len > dp->dccps_mss_cache) { | ||
454 | DCCP_WARN("No space left for Ack Vector (%u) on skb (%u+%u), " | ||
455 | "MPS=%u ==> reduce payload size?\n", len, skb->len, | ||
456 | dcb->dccpd_opt_len, dp->dccps_mss_cache); | ||
457 | dp->dccps_sync_scheduled = 1; | ||
458 | return 0; | ||
459 | } | ||
460 | dcb->dccpd_opt_len += len; | ||
445 | 461 | ||
446 | to = skb_push(skb, len); | 462 | to = skb_push(skb, len); |
447 | len = buflen; | 463 | len = buflen; |
@@ -482,7 +498,7 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | |||
482 | /* | 498 | /* |
483 | * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340. | 499 | * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340. |
484 | */ | 500 | */ |
485 | if (dccp_ackvec_update_records(av, DCCP_SKB_CB(skb)->dccpd_seq, nonce)) | 501 | if (dccp_ackvec_update_records(av, dcb->dccpd_seq, nonce)) |
486 | return -ENOBUFS; | 502 | return -ENOBUFS; |
487 | return 0; | 503 | return 0; |
488 | } | 504 | } |