^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * net/dccp/options.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * An implementation of the DCCP protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/dccp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "ackvec.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "ccid.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "dccp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "feat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) u64 dccp_decode_value_var(const u8 *bf, const u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) u64 value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (len >= DCCP_OPTVAL_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) value += ((u64)*bf++) << 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (len > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) value += ((u64)*bf++) << 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (len > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) value += ((u64)*bf++) << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (len > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) value += ((u64)*bf++) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (len > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) value += ((u64)*bf++) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) value += *bf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * dccp_parse_options - Parse DCCP options present in @skb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * @sk: client|server|listening dccp socket (when @dreq != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * @dreq: request socket to use during connection setup, or NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * @skb: frame to parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct dccp_sock *dp = dccp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) const struct dccp_hdr *dh = dccp_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) unsigned char *opt_ptr = options;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) const unsigned char *opt_end = (unsigned char *)dh +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) (dh->dccph_doff * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct dccp_options_received *opt_recv = &dp->dccps_options_received;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned char opt, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned char *value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 elapsed_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) __be32 opt_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int mandatory = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) memset(opt_recv, 0, sizeof(*opt_recv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) opt = len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) while (opt_ptr != opt_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) opt = *opt_ptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) value = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Check if this isn't a single byte option */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (opt > DCCPO_MAX_RESERVED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (opt_ptr == opt_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) goto out_nonsensical_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) len = *opt_ptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (len < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) goto out_nonsensical_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * Remove the type and len fields, leaving
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * just the value size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) len -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) value = opt_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) opt_ptr += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (opt_ptr > opt_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) goto out_nonsensical_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * CCID-specific options are ignored during connection setup, as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * negotiation may still be in progress (see RFC 4340, 10.3).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * The same applies to Ack Vectors, as these depend on the CCID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (dreq != NULL && (opt >= DCCPO_MIN_RX_CCID_SPECIFIC ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) goto ignore_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) switch (opt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) case DCCPO_PADDING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) case DCCPO_MANDATORY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (mandatory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) goto out_invalid_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (pkt_type != DCCP_PKT_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) mandatory = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) case DCCPO_NDP_COUNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (len > 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) goto out_invalid_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) opt_recv->dccpor_ndp = dccp_decode_value_var(value, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) dccp_pr_debug("%s opt: NDP count=%llu\n", dccp_role(sk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) (unsigned long long)opt_recv->dccpor_ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) goto out_invalid_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) rc = dccp_feat_parse_options(sk, dreq, mandatory, opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) *value, value + 1, len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) goto out_featneg_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) case DCCPO_TIMESTAMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (len != 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) goto out_invalid_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * RFC 4340 13.1: "The precise time corresponding to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * Timestamp Value zero is not specified". We use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * zero to indicate absence of a meaningful timestamp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) opt_val = get_unaligned((__be32 *)value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (unlikely(opt_val == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) DCCP_WARN("Timestamp with zero value\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (dreq != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) dreq->dreq_timestamp_echo = ntohl(opt_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) dreq->dreq_timestamp_time = dccp_timestamp();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) opt_recv->dccpor_timestamp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) dp->dccps_timestamp_echo = ntohl(opt_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) dp->dccps_timestamp_time = dccp_timestamp();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) dccp_pr_debug("%s rx opt: TIMESTAMP=%u, ackno=%llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) dccp_role(sk), ntohl(opt_val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) (unsigned long long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) DCCP_SKB_CB(skb)->dccpd_ack_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* schedule an Ack in case this sender is quiescent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) inet_csk_schedule_ack(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) case DCCPO_TIMESTAMP_ECHO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (len != 4 && len != 6 && len != 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) goto out_invalid_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) opt_val = get_unaligned((__be32 *)value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) opt_recv->dccpor_timestamp_echo = ntohl(opt_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) "ackno=%llu", dccp_role(sk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) opt_recv->dccpor_timestamp_echo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) len + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) (unsigned long long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) DCCP_SKB_CB(skb)->dccpd_ack_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) value += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (len == 4) { /* no elapsed time included */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dccp_pr_debug_cat("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (len == 6) { /* 2-byte elapsed time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) __be16 opt_val2 = get_unaligned((__be16 *)value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) elapsed_time = ntohs(opt_val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) } else { /* 4-byte elapsed time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) opt_val = get_unaligned((__be32 *)value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) elapsed_time = ntohl(opt_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dccp_pr_debug_cat(", ELAPSED_TIME=%u\n", elapsed_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* Give precedence to the biggest ELAPSED_TIME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (elapsed_time > opt_recv->dccpor_elapsed_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) opt_recv->dccpor_elapsed_time = elapsed_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) case DCCPO_ELAPSED_TIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (dccp_packet_without_ack(skb)) /* RFC 4340, 13.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (len == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) __be16 opt_val2 = get_unaligned((__be16 *)value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) elapsed_time = ntohs(opt_val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) } else if (len == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) opt_val = get_unaligned((__be32 *)value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) elapsed_time = ntohl(opt_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) goto out_invalid_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (elapsed_time > opt_recv->dccpor_elapsed_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) opt_recv->dccpor_elapsed_time = elapsed_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) dccp_role(sk), elapsed_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) case DCCPO_MIN_RX_CCID_SPECIFIC ... DCCPO_MAX_RX_CCID_SPECIFIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) pkt_type, opt, value, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) goto out_invalid_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case DCCPO_ACK_VECTOR_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) case DCCPO_ACK_VECTOR_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (dccp_packet_without_ack(skb)) /* RFC 4340, 11.4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * Ack vectors are processed by the TX CCID if it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * interested. The RX CCID need not parse Ack Vectors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * since it is only interested in clearing old state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) pkt_type, opt, value, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) goto out_invalid_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) DCCP_CRIT("DCCP(%p): option %d(len=%d) not "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) "implemented, ignoring", sk, opt, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ignore_option:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (opt != DCCPO_MANDATORY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) mandatory = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* mandatory was the last byte in option list -> reset connection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (mandatory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) goto out_invalid_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) out_nonsensical_length:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* RFC 4340, 5.8: ignore option and all remaining option space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) out_invalid_option:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) DCCP_INC_STATS(DCCP_MIB_INVALIDOPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) rc = DCCP_RESET_CODE_OPTION_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) out_featneg_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) DCCP_WARN("DCCP(%p): Option %d (len=%d) error=%u\n", sk, opt, len, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) DCCP_SKB_CB(skb)->dccpd_reset_code = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) DCCP_SKB_CB(skb)->dccpd_reset_data[0] = opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) DCCP_SKB_CB(skb)->dccpd_reset_data[1] = len > 0 ? value[0] : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) DCCP_SKB_CB(skb)->dccpd_reset_data[2] = len > 1 ? value[1] : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) EXPORT_SYMBOL_GPL(dccp_parse_options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) void dccp_encode_value_var(const u64 value, u8 *to, const u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (len >= DCCP_OPTVAL_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) *to++ = (value & 0xFF0000000000ull) >> 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (len > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) *to++ = (value & 0xFF00000000ull) >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (len > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) *to++ = (value & 0xFF000000) >> 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (len > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) *to++ = (value & 0xFF0000) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (len > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) *to++ = (value & 0xFF00) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) *to++ = (value & 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static inline u8 dccp_ndp_len(const u64 ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (likely(ndp <= 0xFF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return likely(ndp <= USHRT_MAX) ? 2 : (ndp <= UINT_MAX ? 4 : 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int dccp_insert_option(struct sk_buff *skb, const unsigned char option,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) const void *value, const unsigned char len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) unsigned char *to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) to = skb_push(skb, len + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) *to++ = option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) *to++ = len + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) memcpy(to, value, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) EXPORT_SYMBOL_GPL(dccp_insert_option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct dccp_sock *dp = dccp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) u64 ndp = dp->dccps_ndp_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (dccp_non_data_packet(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) ++dp->dccps_ndp_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) dp->dccps_ndp_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (ndp > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) unsigned char *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) const int ndp_len = dccp_ndp_len(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) const int len = ndp_len + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) DCCP_SKB_CB(skb)->dccpd_opt_len += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ptr = skb_push(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) *ptr++ = DCCPO_NDP_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) *ptr++ = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) dccp_encode_value_var(ndp, ptr, ndp_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) static inline int dccp_elapsed_time_len(const u32 elapsed_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static int dccp_insert_option_timestamp(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) __be32 now = htonl(dccp_timestamp());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* yes this will overflow but that is the point as we want a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * 10 usec 32 bit timer which mean it wraps every 11.9 hours */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return dccp_insert_option(skb, DCCPO_TIMESTAMP, &now, sizeof(now));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static int dccp_insert_option_timestamp_echo(struct dccp_sock *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct dccp_request_sock *dreq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) __be32 tstamp_echo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) unsigned char *to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) u32 elapsed_time, elapsed_time_len, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (dreq != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) elapsed_time = dccp_timestamp() - dreq->dreq_timestamp_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) tstamp_echo = htonl(dreq->dreq_timestamp_echo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) dreq->dreq_timestamp_echo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) elapsed_time = dccp_timestamp() - dp->dccps_timestamp_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) tstamp_echo = htonl(dp->dccps_timestamp_echo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) dp->dccps_timestamp_echo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) len = 6 + elapsed_time_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) DCCP_SKB_CB(skb)->dccpd_opt_len += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) to = skb_push(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) *to++ = DCCPO_TIMESTAMP_ECHO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) *to++ = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) memcpy(to, &tstamp_echo, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) to += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (elapsed_time_len == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) const __be16 var16 = htons((u16)elapsed_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) memcpy(to, &var16, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) } else if (elapsed_time_len == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) const __be32 var32 = htonl(elapsed_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) memcpy(to, &var32, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct dccp_sock *dp = dccp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) const u16 buflen = dccp_ackvec_buflen(av);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* Figure out how many options do we need to represent the ackvec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) u16 len = buflen + 2 * nr_opts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) u8 i, nonce = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) const unsigned char *tail, *from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) unsigned char *to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (dcb->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) DCCP_WARN("Lacking space for %u bytes on %s packet\n", len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) dccp_packet_name(dcb->dccpd_type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * Since Ack Vectors are variable-length, we can not always predict
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * their size. To catch exception cases where the space is running out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * on the skb, a separate Sync is scheduled to carry the Ack Vector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (len > DCCPAV_MIN_OPTLEN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) len + dcb->dccpd_opt_len + skb->len > dp->dccps_mss_cache) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) DCCP_WARN("No space left for Ack Vector (%u) on skb (%u+%u), "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) "MPS=%u ==> reduce payload size?\n", len, skb->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) dcb->dccpd_opt_len, dp->dccps_mss_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) dp->dccps_sync_scheduled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) dcb->dccpd_opt_len += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) to = skb_push(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) len = buflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) from = av->av_buf + av->av_buf_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) tail = av->av_buf + DCCPAV_MAX_ACKVEC_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) for (i = 0; i < nr_opts; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) int copylen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (len > DCCP_SINGLE_OPT_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) copylen = DCCP_SINGLE_OPT_MAXLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * RFC 4340, 12.2: Encode the Nonce Echo for this Ack Vector via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * its type; ack_nonce is the sum of all individual buf_nonce's.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) nonce ^= av->av_buf_nonce[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) *to++ = DCCPO_ACK_VECTOR_0 + av->av_buf_nonce[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) *to++ = copylen + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /* Check if buf_head wraps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (from + copylen > tail) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) const u16 tailsize = tail - from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) memcpy(to, from, tailsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) to += tailsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) len -= tailsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) copylen -= tailsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) from = av->av_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) memcpy(to, from, copylen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) from += copylen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) to += copylen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) len -= copylen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (dccp_ackvec_update_records(av, dcb->dccpd_seq, nonce))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * dccp_insert_option_mandatory - Mandatory option (5.8.2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * @skb: frame into which to insert option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * Note that since we are using skb_push, this function needs to be called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * _after_ inserting the option it is supposed to influence (stack order).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int dccp_insert_option_mandatory(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (DCCP_SKB_CB(skb)->dccpd_opt_len >= DCCP_MAX_OPT_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) DCCP_SKB_CB(skb)->dccpd_opt_len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) *(u8 *)skb_push(skb, 1) = DCCPO_MANDATORY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * dccp_insert_fn_opt - Insert single Feature-Negotiation option into @skb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * @skb: frame to insert feature negotiation option into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * @type: %DCCPO_CHANGE_L, %DCCPO_CHANGE_R, %DCCPO_CONFIRM_L, %DCCPO_CONFIRM_R
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * @feat: one out of %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * @val: NN value or SP array (preferred element first) to copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * @len: true length of @val in bytes (excluding first element repetition)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * @repeat_first: whether to copy the first element of @val twice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * The last argument is used to construct Confirm options, where the preferred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * value and the preference list appear separately (RFC 4340, 6.3.1). Preference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * lists are kept such that the preferred entry is always first, so we only need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * to copy twice, and avoid the overhead of cloning into a bigger array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) u8 *val, u8 len, bool repeat_first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) u8 tot_len, *to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /* take the `Feature' field and possible repetition into account */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (len > (DCCP_SINGLE_OPT_MAXLEN - 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) DCCP_WARN("length %u for feature %u too large\n", len, feat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (unlikely(val == NULL || len == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) len = repeat_first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) tot_len = 3 + repeat_first + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (DCCP_SKB_CB(skb)->dccpd_opt_len + tot_len > DCCP_MAX_OPT_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) DCCP_WARN("packet too small for feature %d option!\n", feat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) DCCP_SKB_CB(skb)->dccpd_opt_len += tot_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) to = skb_push(skb, tot_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) *to++ = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) *to++ = tot_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) *to++ = feat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (repeat_first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) *to++ = *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) memcpy(to, val, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* The length of all options needs to be a multiple of 4 (5.8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static void dccp_insert_option_padding(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int padding = DCCP_SKB_CB(skb)->dccpd_opt_len % 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (padding != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) padding = 4 - padding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) memset(skb_push(skb, padding), 0, padding);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct dccp_sock *dp = dccp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (dp->dccps_send_ndp_count && dccp_insert_option_ndp(sk, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /* Feature Negotiation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (dccp_feat_insert_opts(dp, NULL, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_REQUEST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * Obtain RTT sample from Request/Response exchange.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * This is currently used for TFRC initialisation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (dccp_insert_option_timestamp(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) } else if (dccp_ackvec_pending(sk) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) dccp_insert_option_ackvec(sk, skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (dp->dccps_hc_rx_insert_options) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) dp->dccps_hc_rx_insert_options = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (dp->dccps_timestamp_echo != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) dccp_insert_option_timestamp_echo(dp, NULL, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) dccp_insert_option_padding(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) int dccp_insert_options_rsk(struct dccp_request_sock *dreq, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (dccp_feat_insert_opts(NULL, dreq, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /* Obtain RTT sample from Response/Ack exchange (used by TFRC). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (dccp_insert_option_timestamp(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (dreq->dreq_timestamp_echo != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) dccp_insert_option_timestamp_echo(NULL, dreq, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) dccp_insert_option_padding(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }