Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d0817d1 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by David S. Miller
Browse files

[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: default avatarArnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 110bae4e
Loading
Loading
Loading
Loading
+7 −7
Original line number Original line Diff line number Diff line
@@ -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)
	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
		return -1;
		return -1;


	avr = dccp_ackvec_record_new();
	if (avr == NULL)
		return -1;

	dccp_timestamp(sk, &now);
	dccp_timestamp(sk, &now);
	elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10;
	elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10;


	if (elapsed_time != 0)
	if (elapsed_time != 0 &&
		dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
	    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;
	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;
	av->dccpav_buf_ackno = ackno;
	dccp_timestamp(sk, &av->dccpav_time);
	dccp_timestamp(sk, &av->dccpav_time);
out:
out:
	dccp_pr_debug("");
	return 0;
	return 0;


out_duplicate:
out_duplicate:
+10 −8
Original line number Original line Diff line number Diff line
@@ -41,9 +41,9 @@ struct ccid_operations {
						    unsigned char option,
						    unsigned char option,
						    unsigned char len, u16 idx,
						    unsigned char len, u16 idx,
						    unsigned char* value);
						    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);
						     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);
						     struct sk_buff *skb);
	void		(*ccid_hc_tx_packet_recv)(struct sock *sk,
	void		(*ccid_hc_tx_packet_recv)(struct sock *sk,
						  struct sk_buff *skb);
						  struct sk_buff *skb);
@@ -146,18 +146,20 @@ static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
	return rc;
	return rc;
}
}


static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
static inline int ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
					    struct sk_buff *skb)
					    struct sk_buff *skb)
{
{
	if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL)
	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,
static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
					    struct sk_buff *skb)
					    struct sk_buff *skb)
{
{
	if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL)
	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,
static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
+20 −17
Original line number Original line Diff line number Diff line
@@ -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);
	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);


	BUG_ON(hctx == NULL);
	BUG_ON(hctx == NULL);


	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
	if (sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)
		return;

		DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
		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,
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);
	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);
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
	__be32 x_recv, pinv;
	__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);
	BUG_ON(hcrx == NULL);


	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
		return;
		return 0;


	DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter;
	DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter;


	if (dccp_packet_without_ack(skb))
	if (dccp_packet_without_ack(skb))
		return;
		return 0;


	if (hcrx->ccid3hcrx_elapsed_time != 0)
		dccp_insert_option_elapsed_time(sk, skb,
						hcrx->ccid3hcrx_elapsed_time);
	dccp_insert_option_timestamp(sk, skb);
	x_recv = htonl(hcrx->ccid3hcrx_x_recv);
	x_recv = htonl(hcrx->ccid3hcrx_x_recv);
	pinv   = htonl(hcrx->ccid3hcrx_pinv);
	pinv   = htonl(hcrx->ccid3hcrx_pinv);

	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,
	    dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,
			   &pinv, sizeof(pinv));
		    	       &pinv, sizeof(pinv)) ||
	    dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
	    dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
			   &x_recv, sizeof(x_recv));
		    	       &x_recv, sizeof(x_recv)))
		return -1;

	return 0;
}
}


/* calculate first loss interval
/* calculate first loss interval
+4 −4
Original line number Original line Diff line number Diff line
@@ -326,13 +326,13 @@ static inline int dccp_ack_pending(const struct sock *sk)
	       inet_csk_ack_scheduled(sk);
	       inet_csk_ack_scheduled(sk);
}
}


extern void dccp_insert_options(struct sock *sk, struct sk_buff *skb);
extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb);
extern void dccp_insert_option_elapsed_time(struct sock *sk,
extern int dccp_insert_option_elapsed_time(struct sock *sk,
					    struct sk_buff *skb,
					    struct sk_buff *skb,
					    u32 elapsed_time);
					    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);
					 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,
			       unsigned char option,
			       const void *value, unsigned char len);
			       const void *value, unsigned char len);


+46 −63
Original line number Original line Diff line number Diff line
@@ -283,17 +283,14 @@ static inline int dccp_ndp_len(const int ndp)
	return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3;
	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 unsigned char option,
			const void *value, const unsigned char len)
			const void *value, const unsigned char len)
{
{
	unsigned char *to;
	unsigned char *to;


	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN) {
	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN)
		LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert "
		return -1;
			       "%d option!\n", option);
		return;
	}


	DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2;
	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;
	*to++ = len + 2;


	memcpy(to, value, len);
	memcpy(to, value, len);
	return 0;
}
}


EXPORT_SYMBOL_GPL(dccp_insert_option);
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);
	struct dccp_sock *dp = dccp_sk(sk);
	int ndp = dp->dccps_ndp_count;
	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;
		const int len = ndp_len + 2;


		if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
		if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
			return;
			return -1;


		DCCP_SKB_CB(skb)->dccpd_opt_len += len;
		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;
		*ptr++ = len;
		dccp_encode_value_var(ndp, ptr, ndp_len);
		dccp_encode_value_var(ndp, ptr, ndp_len);
	}
	}

	return 0;
}
}


static inline int dccp_elapsed_time_len(const u32 elapsed_time)
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;
	return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
}
}


void dccp_insert_option_elapsed_time(struct sock *sk,
int dccp_insert_option_elapsed_time(struct sock *sk, struct sk_buff *skb,
				     struct sk_buff *skb,
				    u32 elapsed_time)
				    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 elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
	const int len = 2 + elapsed_time_len;
	const int len = 2 + elapsed_time_len;
	unsigned char *to;
	unsigned char *to;


	if (elapsed_time_len == 0)
	if (elapsed_time_len == 0)
		return;
		return 0;


	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
		LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to "
		return -1;
					 "insert elapsed time!\n");
		return;
	}


	DCCP_SKB_CB(skb)->dccpd_opt_len += len;
	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);
		memcpy(to, &var32, 4);
	}
	}


	dccp_pr_debug("%sELAPSED_TIME=%u, len=%d, seqno=%llu\n",
	return 0;
		      debug_prefix, elapsed_time,
		      len,
		      (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
}
}


EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
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);
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;
	struct timeval tv;
	__be32 now;
	__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
	/* 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 */
	 * 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);
EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp);


static void dccp_insert_option_timestamp_echo(struct sock *sk,
static int dccp_insert_option_timestamp_echo(struct sock *sk,
					     struct sk_buff *skb)
					     struct sk_buff *skb)
{
{
	struct dccp_sock *dp = dccp_sk(sk);
	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;
	struct timeval now;
	__be32 tstamp_echo;
	__be32 tstamp_echo;
	u32 elapsed_time;
	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);
	elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
	len = 6 + elapsed_time_len;
	len = 6 + elapsed_time_len;


	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
		LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert "
		return -1;
					 "timestamp echo!\n");
		return;
	}


	DCCP_SKB_CB(skb)->dccpd_opt_len += len;
	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);
		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_echo = 0;
	dp->dccps_timestamp_time.tv_sec = 0;
	dp->dccps_timestamp_time.tv_sec = 0;
	dp->dccps_timestamp_time.tv_usec = 0;
	dp->dccps_timestamp_time.tv_usec = 0;
	return 0;
}
}


static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
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;
	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_sock *dp = dccp_sk(sk);
	struct dccp_opt_pend *opt, *next;
	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_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
					  inet_csk(sk)->icsk_rto, DCCP_RTO_MAX);
					  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);
	struct dccp_sock *dp = dccp_sk(sk);


	DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
	DCCP_SKB_CB(skb)->dccpd_opt_len = 0;


	if (dp->dccps_options.dccpo_send_ndp_count)
	if (dp->dccps_options.dccpo_send_ndp_count &&
		dccp_insert_option_ndp(sk, skb);
	    dccp_insert_option_ndp(sk, skb))
		return -1;


	if (!dccp_packet_without_ack(skb)) {
	if (!dccp_packet_without_ack(skb)) {
		if (dp->dccps_options.dccpo_send_ack_vector &&
		if (dp->dccps_options.dccpo_send_ack_vector &&
		    dccp_ackvec_pending(dp->dccps_hc_rx_ackvec))
		    dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&
			dccp_insert_option_ackvec(sk, skb);
		    dccp_insert_option_ackvec(sk, skb))
		if (dp->dccps_timestamp_echo != 0)
			return -1;
			dccp_insert_option_timestamp_echo(sk, skb);

		if (dp->dccps_timestamp_echo != 0 &&
		    dccp_insert_option_timestamp_echo(sk, skb))
			return -1;
	}
	}


	if (dp->dccps_hc_rx_insert_options) {
	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;
		dp->dccps_hc_rx_insert_options = 0;
	}
	}
	if (dp->dccps_hc_tx_insert_options) {
	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;
		dp->dccps_hc_tx_insert_options = 0;
	}
	}


	/* Feature negotiation */
	/* Feature negotiation */
	switch(DCCP_SKB_CB(skb)->dccpd_type) {
	/* Data packets can't do feat negotiation */
	/* Data packets can't do feat negotiation */
	case DCCP_PKT_DATA:
	if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA &&
	case DCCP_PKT_DATAACK:
	    DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK &&
		break;
	    dccp_insert_options_feat(sk, skb))
	default:
		return -1;
		dccp_insert_feat(sk, skb);
		break;
	}


	/* XXX: insert other options when appropriate */
	/* 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;
			DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
		}
		}
	}
	}

	return 0;
}
}
Loading