case DCCPO_CHANGE_L:
/* fall through */
case DCCPO_CHANGE_R:
+ if (pkt_type == DCCP_PKT_DATA)
+ break;
if (len < 2)
goto out_invalid_option;
rc = dccp_feat_change_recv(sk, opt, *value, value + 1,
case DCCPO_CONFIRM_L:
/* fall through */
case DCCPO_CONFIRM_R:
- if (len < 2)
+ if (pkt_type == DCCP_PKT_DATA)
+ break;
+ if (len < 2) /* FIXME this disallows empty confirm */
goto out_invalid_option;
if (dccp_feat_confirm_recv(sk, opt, *value,
value + 1, len - 1))
return 0;
}
+/* The length of all options needs to be a multiple of 4 (5.8) */
+static void dccp_insert_option_padding(struct sk_buff *skb)
+{
+ int padding = DCCP_SKB_CB(skb)->dccpd_opt_len % 4;
+
+ if (padding != 0) {
+ padding = 4 - padding;
+ memset(skb_push(skb, padding), 0, padding);
+ DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
+ }
+}
+
int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
dccp_insert_option_timestamp_echo(dp, NULL, skb))
return -1;
- /* XXX: insert other options when appropriate */
+ dccp_insert_option_padding(skb);
+ return 0;
+}
- if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) {
- /* The length of all options has to be a multiple of 4 */
- int padding = DCCP_SKB_CB(skb)->dccpd_opt_len % 4;
+int dccp_insert_options_rsk(struct dccp_request_sock *dreq, struct sk_buff *skb)
+{
+ DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
- if (padding != 0) {
- padding = 4 - padding;
- memset(skb_push(skb, padding), 0, padding);
- DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
- }
- }
+ if (dreq->dreq_timestamp_echo != 0 &&
+ dccp_insert_option_timestamp_echo(NULL, dreq, skb))
+ return -1;
+ dccp_insert_option_padding(skb);
return 0;
}