From: Arnaldo Carvalho de Melo Date: Tue, 21 Mar 2006 06:32:06 +0000 (-0800) Subject: [DCCP] options: Make dccp_insert_options & friends yell on error X-Git-Tag: v2.6.17-rc1~1175^2~66 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2d0817d11eaec57435feb61493331a763f732a2b;p=profile%2Fivi%2Fkernel-x86-ivi.git [DCCP] options: Make dccp_insert_options & friends yell on error And not the silly LIMIT_NETDEBUG and silently return without inserting the option requested. Also drop some old debugging messages associated to option insertion. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index 5c76e81..b5981e5 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -81,15 +81,16 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) return -1; - avr = dccp_ackvec_record_new(); - if (avr == NULL) - return -1; - dccp_timestamp(sk, &now); elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10; - if (elapsed_time != 0) - dccp_insert_option_elapsed_time(sk, skb, elapsed_time); + if (elapsed_time != 0 && + dccp_insert_option_elapsed_time(sk, skb, elapsed_time)) + return -1; + + avr = dccp_ackvec_record_new(); + if (avr == NULL) + return -1; DCCP_SKB_CB(skb)->dccpd_opt_len += len; @@ -310,7 +311,6 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, av->dccpav_buf_ackno = ackno; dccp_timestamp(sk, &av->dccpav_time); out: - dccp_pr_debug(""); return 0; out_duplicate: diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 3dec50d..f7eb6c6 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -41,9 +41,9 @@ struct ccid_operations { unsigned char option, unsigned char len, u16 idx, unsigned char* value); - void (*ccid_hc_rx_insert_options)(struct sock *sk, + int (*ccid_hc_rx_insert_options)(struct sock *sk, struct sk_buff *skb); - void (*ccid_hc_tx_insert_options)(struct sock *sk, + int (*ccid_hc_tx_insert_options)(struct sock *sk, struct sk_buff *skb); void (*ccid_hc_tx_packet_recv)(struct sock *sk, struct sk_buff *skb); @@ -146,18 +146,20 @@ static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk, return rc; } -static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk, - struct sk_buff *skb) +static inline int ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk, + struct sk_buff *skb) { if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL) - ccid->ccid_ops->ccid_hc_tx_insert_options(sk, skb); + return ccid->ccid_ops->ccid_hc_tx_insert_options(sk, skb); + return 0; } -static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, - struct sk_buff *skb) +static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, + struct sk_buff *skb) { if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL) - ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb); + return ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb); + return 0; } static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk, diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index ff426a9..b4a51d0 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -574,16 +574,15 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) } } -static void ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb) +static int ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb) { const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); BUG_ON(hctx == NULL); - if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) - return; - - DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count; + if (sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN) + DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count; + return 0; } static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, @@ -774,7 +773,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) dccp_send_ack(sk); } -static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) +static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) { const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); __be32 x_recv, pinv; @@ -782,23 +781,27 @@ static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) BUG_ON(hcrx == NULL); if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) - return; + return 0; DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter; if (dccp_packet_without_ack(skb)) - return; - - if (hcrx->ccid3hcrx_elapsed_time != 0) - dccp_insert_option_elapsed_time(sk, skb, - hcrx->ccid3hcrx_elapsed_time); - dccp_insert_option_timestamp(sk, skb); + return 0; + x_recv = htonl(hcrx->ccid3hcrx_x_recv); pinv = htonl(hcrx->ccid3hcrx_pinv); - dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE, - &pinv, sizeof(pinv)); - dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE, - &x_recv, sizeof(x_recv)); + + if ((hcrx->ccid3hcrx_elapsed_time != 0 && + dccp_insert_option_elapsed_time(sk, skb, + hcrx->ccid3hcrx_elapsed_time)) || + dccp_insert_option_timestamp(sk, skb) || + dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE, + &pinv, sizeof(pinv)) || + dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE, + &x_recv, sizeof(x_recv))) + return -1; + + return 0; } /* calculate first loss interval diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 7f5be08..34e70fb 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -326,13 +326,13 @@ static inline int dccp_ack_pending(const struct sock *sk) inet_csk_ack_scheduled(sk); } -extern void dccp_insert_options(struct sock *sk, struct sk_buff *skb); -extern void dccp_insert_option_elapsed_time(struct sock *sk, +extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb); +extern int dccp_insert_option_elapsed_time(struct sock *sk, struct sk_buff *skb, u32 elapsed_time); -extern void dccp_insert_option_timestamp(struct sock *sk, +extern int dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb); -extern void dccp_insert_option(struct sock *sk, struct sk_buff *skb, +extern int dccp_insert_option(struct sock *sk, struct sk_buff *skb, unsigned char option, const void *value, unsigned char len); diff --git a/net/dccp/options.c b/net/dccp/options.c index 0161a18..da16760 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -283,17 +283,14 @@ static inline int dccp_ndp_len(const int ndp) return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3; } -void dccp_insert_option(struct sock *sk, struct sk_buff *skb, +int dccp_insert_option(struct sock *sk, struct sk_buff *skb, const unsigned char option, const void *value, const unsigned char len) { unsigned char *to; - if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN) { - LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " - "%d option!\n", option); - return; - } + if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN) + return -1; DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2; @@ -302,11 +299,12 @@ void dccp_insert_option(struct sock *sk, struct sk_buff *skb, *to++ = len + 2; memcpy(to, value, len); + return 0; } EXPORT_SYMBOL_GPL(dccp_insert_option); -static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb) +static int dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); int ndp = dp->dccps_ndp_count; @@ -322,7 +320,7 @@ static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb) const int len = ndp_len + 2; if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) - return; + return -1; DCCP_SKB_CB(skb)->dccpd_opt_len += len; @@ -331,6 +329,8 @@ static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb) *ptr++ = len; dccp_encode_value_var(ndp, ptr, ndp_len); } + + return 0; } static inline int dccp_elapsed_time_len(const u32 elapsed_time) @@ -338,27 +338,18 @@ static inline int dccp_elapsed_time_len(const u32 elapsed_time) return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4; } -void dccp_insert_option_elapsed_time(struct sock *sk, - struct sk_buff *skb, - u32 elapsed_time) +int dccp_insert_option_elapsed_time(struct sock *sk, struct sk_buff *skb, + u32 elapsed_time) { -#ifdef CONFIG_IP_DCCP_DEBUG - struct dccp_sock *dp = dccp_sk(sk); - const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT TX opt: " : "server TX opt: "; -#endif const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time); const int len = 2 + elapsed_time_len; unsigned char *to; if (elapsed_time_len == 0) - return; + return 0; - if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { - LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to " - "insert elapsed time!\n"); - return; - } + if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) + return -1; DCCP_SKB_CB(skb)->dccpd_opt_len += len; @@ -374,10 +365,7 @@ void dccp_insert_option_elapsed_time(struct sock *sk, memcpy(to, &var32, 4); } - dccp_pr_debug("%sELAPSED_TIME=%u, len=%d, seqno=%llu\n", - debug_prefix, elapsed_time, - len, - (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq); + return 0; } EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time); @@ -398,7 +386,7 @@ void dccp_timestamp(const struct sock *sk, struct timeval *tv) EXPORT_SYMBOL_GPL(dccp_timestamp); -void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) +int dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) { struct timeval tv; __be32 now; @@ -408,19 +396,15 @@ void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) /* yes this will overflow but that is the point as we want a * 10 usec 32 bit timer which mean it wraps every 11.9 hours */ - dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now)); + return dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now)); } EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp); -static void dccp_insert_option_timestamp_echo(struct sock *sk, - struct sk_buff *skb) +static int dccp_insert_option_timestamp_echo(struct sock *sk, + struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); -#ifdef CONFIG_IP_DCCP_DEBUG - const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT TX opt: " : "server TX opt: "; -#endif struct timeval now; __be32 tstamp_echo; u32 elapsed_time; @@ -432,11 +416,8 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, elapsed_time_len = dccp_elapsed_time_len(elapsed_time); len = 6 + elapsed_time_len; - if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { - LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " - "timestamp echo!\n"); - return; - } + if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) + return -1; DCCP_SKB_CB(skb)->dccpd_opt_len += len; @@ -456,14 +437,10 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, memcpy(to, &var32, 4); } - dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, seqno=%llu\n", - debug_prefix, dp->dccps_timestamp_echo, - len, - (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq); - dp->dccps_timestamp_echo = 0; dp->dccps_timestamp_time.tv_sec = 0; dp->dccps_timestamp_time.tv_usec = 0; + return 0; } static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, @@ -491,7 +468,7 @@ static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, return 0; } -static void dccp_insert_feat(struct sock *sk, struct sk_buff *skb) +static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); struct dccp_opt_pend *opt, *next; @@ -551,44 +528,48 @@ static void dccp_insert_feat(struct sock *sk, struct sk_buff *skb) inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, inet_csk(sk)->icsk_rto, DCCP_RTO_MAX); } + + return 0; } -void dccp_insert_options(struct sock *sk, struct sk_buff *skb) +int dccp_insert_options(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); DCCP_SKB_CB(skb)->dccpd_opt_len = 0; - if (dp->dccps_options.dccpo_send_ndp_count) - dccp_insert_option_ndp(sk, skb); + if (dp->dccps_options.dccpo_send_ndp_count && + dccp_insert_option_ndp(sk, skb)) + return -1; if (!dccp_packet_without_ack(skb)) { if (dp->dccps_options.dccpo_send_ack_vector && - dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) - dccp_insert_option_ackvec(sk, skb); - if (dp->dccps_timestamp_echo != 0) - dccp_insert_option_timestamp_echo(sk, skb); + dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) && + dccp_insert_option_ackvec(sk, skb)) + return -1; + + if (dp->dccps_timestamp_echo != 0 && + dccp_insert_option_timestamp_echo(sk, skb)) + return -1; } if (dp->dccps_hc_rx_insert_options) { - ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb); + if (ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb)) + return -1; dp->dccps_hc_rx_insert_options = 0; } if (dp->dccps_hc_tx_insert_options) { - ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb); + if (ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb)) + return -1; dp->dccps_hc_tx_insert_options = 0; } /* Feature negotiation */ - switch(DCCP_SKB_CB(skb)->dccpd_type) { - /* Data packets can't do feat negotiation */ - case DCCP_PKT_DATA: - case DCCP_PKT_DATAACK: - break; - default: - dccp_insert_feat(sk, skb); - break; - } + /* Data packets can't do feat negotiation */ + if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA && + DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK && + dccp_insert_options_feat(sk, skb)) + return -1; /* XXX: insert other options when appropriate */ @@ -602,4 +583,6 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb) DCCP_SKB_CB(skb)->dccpd_opt_len += padding; } } + + return 0; } diff --git a/net/dccp/output.c b/net/dccp/output.c index 2975e3d..7409e4a 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -83,7 +83,11 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) } dcb->dccpd_seq = dp->dccps_gss; - dccp_insert_options(sk, skb); + + if (dccp_insert_options(sk, skb)) { + kfree_skb(skb); + return -EPROTO; + } skb->h.raw = skb_push(skb, dccp_header_size); dh = dccp_hdr(skb); @@ -296,7 +300,11 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, dreq = dccp_rsk(req); DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss; - dccp_insert_options(sk, skb); + + if (dccp_insert_options(sk, skb)) { + kfree_skb(skb); + return NULL; + } skb->h.raw = skb_push(skb, dccp_header_size); @@ -344,7 +352,11 @@ static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst, DCCP_SKB_CB(skb)->dccpd_reset_code = code; DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESET; DCCP_SKB_CB(skb)->dccpd_seq = dp->dccps_gss; - dccp_insert_options(sk, skb); + + if (dccp_insert_options(sk, skb)) { + kfree_skb(skb); + return NULL; + } skb->h.raw = skb_push(skb, dccp_header_size);