14 #include <linux/dccp.h>
15 #include <linux/module.h>
16 #include <linux/types.h>
17 #include <asm/unaligned.h>
18 #include <linux/kernel.h>
31 value += ((
u64)*bf++) << 40;
33 value += ((
u64)*bf++) << 32;
35 value += ((
u64)*bf++) << 24;
37 value += ((
u64)*bf++) << 16;
39 value += ((
u64)*bf++) << 8;
57 unsigned char *
options = (
unsigned char *)dh + dccp_hdr_len(skb);
58 unsigned char *opt_ptr =
options;
59 const unsigned char *opt_end = (
unsigned char *)dh +
69 memset(opt_recv, 0,
sizeof(*opt_recv));
72 while (opt_ptr != opt_end) {
79 if (opt_ptr == opt_end)
80 goto out_nonsensical_length;
84 goto out_nonsensical_length;
93 if (opt_ptr > opt_end)
94 goto out_nonsensical_length;
111 goto out_invalid_option;
117 goto out_invalid_option;
127 goto out_invalid_option;
131 goto out_featneg_failed;
135 goto out_invalid_option;
143 DCCP_WARN(
"Timestamp with zero value\n");
160 inet_csk_schedule_ack(sk);
163 if (len != 4 && len != 6 && len != 8)
164 goto out_invalid_option;
185 elapsed_time =
ntohs(opt_val2);
188 elapsed_time =
ntohl(opt_val);
198 if (dccp_packet_without_ack(skb))
203 elapsed_time =
ntohs(opt_val2);
204 }
else if (len == 4) {
206 elapsed_time =
ntohl(opt_val);
208 goto out_invalid_option;
219 pkt_type, opt,
value, len))
220 goto out_invalid_option;
224 if (dccp_packet_without_ack(skb))
234 pkt_type, opt,
value, len))
235 goto out_invalid_option;
238 DCCP_CRIT(
"DCCP(%p): option %d(len=%d) not "
239 "implemented, ignoring", sk, opt, len);
249 goto out_invalid_option;
251 out_nonsensical_length:
259 DCCP_WARN(
"DCCP(%p): Option %d (len=%d) error=%u\n", sk, opt, len, rc);
272 *to++ = (value & 0xFF0000000000ull) >> 40;
274 *to++ = (value & 0xFF00000000ull) >> 32;
276 *to++ = (value & 0xFF000000) >> 24;
278 *to++ = (value & 0xFF0000) >> 16;
280 *to++ = (value & 0xFF00) >> 8;
282 *to++ = (value & 0xFF);
285 static inline u8 dccp_ndp_len(
const u64 ndp)
293 const void *
value,
const unsigned char len)
317 if (dccp_non_data_packet(skb))
324 const int ndp_len = dccp_ndp_len(ndp);
325 const int len = ndp_len + 2;
341 static inline int dccp_elapsed_time_len(
const u32 elapsed_time)
343 return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
349 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
350 const int len = 2 + elapsed_time_len;
353 if (elapsed_time_len == 0)
365 if (elapsed_time_len == 2) {
378 static int dccp_insert_option_timestamp(
struct sk_buff *skb)
387 static int dccp_insert_option_timestamp_echo(
struct dccp_sock *dp,
393 u32 elapsed_time, elapsed_time_len, len;
405 elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
406 len = 6 + elapsed_time_len;
417 memcpy(to, &tstamp_echo, 4);
420 if (elapsed_time_len == 2) {
423 }
else if (elapsed_time_len == 4) {
431 static int dccp_insert_option_ackvec(
struct sock *sk,
struct sk_buff *skb)
439 u16 len = buflen + 2 * nr_opts;
445 DCCP_WARN(
"Lacking space for %u bytes on %s packet\n", len,
456 DCCP_WARN(
"No space left for Ack Vector (%u) on skb (%u+%u), "
457 "MPS=%u ==> reduce payload size?\n", len, skb->
len,
469 for (i = 0; i < nr_opts; ++
i) {
485 if (from + copylen > tail) {
486 const u16 tailsize = tail -
from;
488 memcpy(to, from, tailsize);
495 memcpy(to, from, copylen);
537 u8 *
val,
u8 len,
bool repeat_first)
543 DCCP_WARN(
"length %u for feature %u too large\n", len, feat);
548 len = repeat_first =
false;
549 tot_len = 3 + repeat_first + len;
552 DCCP_WARN(
"packet too small for feature %d option!\n", feat);
570 static void dccp_insert_option_padding(
struct sk_buff *skb)
601 if (dccp_insert_option_timestamp(skb))
604 }
else if (dccp_ackvec_pending(sk) &&
605 dccp_insert_option_ackvec(sk, skb)) {
617 dccp_insert_option_timestamp_echo(dp,
NULL, skb))
620 dccp_insert_option_padding(skb);
632 if (dccp_insert_option_timestamp(skb))
636 dccp_insert_option_timestamp_echo(
NULL, dreq, skb))
639 dccp_insert_option_padding(skb);