options.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. /*
  2. * net/dccp/options.c
  3. *
  4. * An implementation of the DCCP protocol
  5. * Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
  6. * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
  7. * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version
  12. * 2 of the License, or (at your option) any later version.
  13. */
  14. #include <linux/dccp.h>
  15. #include <linux/module.h>
  16. #include <linux/types.h>
  17. #include <linux/kernel.h>
  18. #include <linux/skbuff.h>
  19. #include "ackvec.h"
  20. #include "ccid.h"
  21. #include "dccp.h"
  22. #include "feat.h"
  23. int dccp_feat_default_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW;
  24. int dccp_feat_default_rx_ccid = DCCPF_INITIAL_CCID;
  25. int dccp_feat_default_tx_ccid = DCCPF_INITIAL_CCID;
  26. int dccp_feat_default_ack_ratio = DCCPF_INITIAL_ACK_RATIO;
  27. int dccp_feat_default_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;
  28. int dccp_feat_default_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT;
  29. EXPORT_SYMBOL_GPL(dccp_feat_default_sequence_window);
  30. void dccp_minisock_init(struct dccp_minisock *dmsk)
  31. {
  32. dmsk->dccpms_sequence_window = dccp_feat_default_sequence_window;
  33. dmsk->dccpms_rx_ccid = dccp_feat_default_rx_ccid;
  34. dmsk->dccpms_tx_ccid = dccp_feat_default_tx_ccid;
  35. dmsk->dccpms_ack_ratio = dccp_feat_default_ack_ratio;
  36. dmsk->dccpms_send_ack_vector = dccp_feat_default_send_ack_vector;
  37. dmsk->dccpms_send_ndp_count = dccp_feat_default_send_ndp_count;
  38. }
  39. static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
  40. {
  41. u32 value = 0;
  42. if (len > 3)
  43. value += *bf++ << 24;
  44. if (len > 2)
  45. value += *bf++ << 16;
  46. if (len > 1)
  47. value += *bf++ << 8;
  48. if (len > 0)
  49. value += *bf;
  50. return value;
  51. }
  52. int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
  53. {
  54. struct dccp_sock *dp = dccp_sk(sk);
  55. #ifdef CONFIG_IP_DCCP_DEBUG
  56. const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
  57. "CLIENT rx opt: " : "server rx opt: ";
  58. #endif
  59. const struct dccp_hdr *dh = dccp_hdr(skb);
  60. const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type;
  61. unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
  62. unsigned char *opt_ptr = options;
  63. const unsigned char *opt_end = (unsigned char *)dh +
  64. (dh->dccph_doff * 4);
  65. struct dccp_options_received *opt_recv = &dp->dccps_options_received;
  66. unsigned char opt, len;
  67. unsigned char *value;
  68. u32 elapsed_time;
  69. int rc;
  70. int mandatory = 0;
  71. memset(opt_recv, 0, sizeof(*opt_recv));
  72. opt = len = 0;
  73. while (opt_ptr != opt_end) {
  74. opt = *opt_ptr++;
  75. len = 0;
  76. value = NULL;
  77. /* Check if this isn't a single byte option */
  78. if (opt > DCCPO_MAX_RESERVED) {
  79. if (opt_ptr == opt_end)
  80. goto out_invalid_option;
  81. len = *opt_ptr++;
  82. if (len < 3)
  83. goto out_invalid_option;
  84. /*
  85. * Remove the type and len fields, leaving
  86. * just the value size
  87. */
  88. len -= 2;
  89. value = opt_ptr;
  90. opt_ptr += len;
  91. if (opt_ptr > opt_end)
  92. goto out_invalid_option;
  93. }
  94. switch (opt) {
  95. case DCCPO_PADDING:
  96. break;
  97. case DCCPO_MANDATORY:
  98. if (mandatory)
  99. goto out_invalid_option;
  100. if (pkt_type != DCCP_PKT_DATA)
  101. mandatory = 1;
  102. break;
  103. case DCCPO_NDP_COUNT:
  104. if (len > 3)
  105. goto out_invalid_option;
  106. opt_recv->dccpor_ndp = dccp_decode_value_var(value, len);
  107. dccp_pr_debug("%sNDP count=%d\n", debug_prefix,
  108. opt_recv->dccpor_ndp);
  109. break;
  110. case DCCPO_CHANGE_L:
  111. /* fall through */
  112. case DCCPO_CHANGE_R:
  113. if (len < 2)
  114. goto out_invalid_option;
  115. rc = dccp_feat_change_recv(sk, opt, *value, value + 1,
  116. len - 1);
  117. /*
  118. * When there is a change error, change_recv is
  119. * responsible for dealing with it. i.e. reply with an
  120. * empty confirm.
  121. * If the change was mandatory, then we need to die.
  122. */
  123. if (rc && mandatory)
  124. goto out_invalid_option;
  125. break;
  126. case DCCPO_CONFIRM_L:
  127. /* fall through */
  128. case DCCPO_CONFIRM_R:
  129. if (len < 2)
  130. goto out_invalid_option;
  131. if (dccp_feat_confirm_recv(sk, opt, *value,
  132. value + 1, len - 1))
  133. goto out_invalid_option;
  134. break;
  135. case DCCPO_ACK_VECTOR_0:
  136. case DCCPO_ACK_VECTOR_1:
  137. if (pkt_type == DCCP_PKT_DATA)
  138. break;
  139. if (dccp_msk(sk)->dccpms_send_ack_vector &&
  140. dccp_ackvec_parse(sk, skb, opt, value, len))
  141. goto out_invalid_option;
  142. break;
  143. case DCCPO_TIMESTAMP:
  144. if (len != 4)
  145. goto out_invalid_option;
  146. opt_recv->dccpor_timestamp = ntohl(*(__be32 *)value);
  147. dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
  148. dccp_timestamp(sk, &dp->dccps_timestamp_time);
  149. dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n",
  150. debug_prefix, opt_recv->dccpor_timestamp,
  151. (unsigned long long)
  152. DCCP_SKB_CB(skb)->dccpd_ack_seq);
  153. break;
  154. case DCCPO_TIMESTAMP_ECHO:
  155. if (len != 4 && len != 6 && len != 8)
  156. goto out_invalid_option;
  157. opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value);
  158. dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, ",
  159. debug_prefix,
  160. opt_recv->dccpor_timestamp_echo,
  161. len + 2,
  162. (unsigned long long)
  163. DCCP_SKB_CB(skb)->dccpd_ack_seq);
  164. if (len == 4)
  165. break;
  166. if (len == 6)
  167. elapsed_time = ntohs(*(__be16 *)(value + 4));
  168. else
  169. elapsed_time = ntohl(*(__be32 *)(value + 4));
  170. /* Give precedence to the biggest ELAPSED_TIME */
  171. if (elapsed_time > opt_recv->dccpor_elapsed_time)
  172. opt_recv->dccpor_elapsed_time = elapsed_time;
  173. break;
  174. case DCCPO_ELAPSED_TIME:
  175. if (len != 2 && len != 4)
  176. goto out_invalid_option;
  177. if (pkt_type == DCCP_PKT_DATA)
  178. continue;
  179. if (len == 2)
  180. elapsed_time = ntohs(*(__be16 *)value);
  181. else
  182. elapsed_time = ntohl(*(__be32 *)value);
  183. if (elapsed_time > opt_recv->dccpor_elapsed_time)
  184. opt_recv->dccpor_elapsed_time = elapsed_time;
  185. dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix,
  186. elapsed_time);
  187. break;
  188. /*
  189. * From draft-ietf-dccp-spec-11.txt:
  190. *
  191. * Option numbers 128 through 191 are for
  192. * options sent from the HC-Sender to the
  193. * HC-Receiver; option numbers 192 through 255
  194. * are for options sent from the HC-Receiver to
  195. * the HC-Sender.
  196. */
  197. case 128 ... 191: {
  198. const u16 idx = value - options;
  199. if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk,
  200. opt, len, idx,
  201. value) != 0)
  202. goto out_invalid_option;
  203. }
  204. break;
  205. case 192 ... 255: {
  206. const u16 idx = value - options;
  207. if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
  208. opt, len, idx,
  209. value) != 0)
  210. goto out_invalid_option;
  211. }
  212. break;
  213. default:
  214. pr_info("DCCP(%p): option %d(len=%d) not "
  215. "implemented, ignoring\n",
  216. sk, opt, len);
  217. break;
  218. }
  219. if (opt != DCCPO_MANDATORY)
  220. mandatory = 0;
  221. }
  222. /* mandatory was the last byte in option list -> reset connection */
  223. if (mandatory)
  224. goto out_invalid_option;
  225. return 0;
  226. out_invalid_option:
  227. DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT);
  228. DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR;
  229. pr_info("DCCP(%p): invalid option %d, len=%d\n", sk, opt, len);
  230. return -1;
  231. }
  232. EXPORT_SYMBOL_GPL(dccp_parse_options);
  233. static void dccp_encode_value_var(const u32 value, unsigned char *to,
  234. const unsigned int len)
  235. {
  236. if (len > 3)
  237. *to++ = (value & 0xFF000000) >> 24;
  238. if (len > 2)
  239. *to++ = (value & 0xFF0000) >> 16;
  240. if (len > 1)
  241. *to++ = (value & 0xFF00) >> 8;
  242. if (len > 0)
  243. *to++ = (value & 0xFF);
  244. }
  245. static inline int dccp_ndp_len(const int ndp)
  246. {
  247. return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3;
  248. }
  249. int dccp_insert_option(struct sock *sk, struct sk_buff *skb,
  250. const unsigned char option,
  251. const void *value, const unsigned char len)
  252. {
  253. unsigned char *to;
  254. if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN)
  255. return -1;
  256. DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2;
  257. to = skb_push(skb, len + 2);
  258. *to++ = option;
  259. *to++ = len + 2;
  260. memcpy(to, value, len);
  261. return 0;
  262. }
  263. EXPORT_SYMBOL_GPL(dccp_insert_option);
  264. static int dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
  265. {
  266. struct dccp_sock *dp = dccp_sk(sk);
  267. int ndp = dp->dccps_ndp_count;
  268. if (dccp_non_data_packet(skb))
  269. ++dp->dccps_ndp_count;
  270. else
  271. dp->dccps_ndp_count = 0;
  272. if (ndp > 0) {
  273. unsigned char *ptr;
  274. const int ndp_len = dccp_ndp_len(ndp);
  275. const int len = ndp_len + 2;
  276. if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
  277. return -1;
  278. DCCP_SKB_CB(skb)->dccpd_opt_len += len;
  279. ptr = skb_push(skb, len);
  280. *ptr++ = DCCPO_NDP_COUNT;
  281. *ptr++ = len;
  282. dccp_encode_value_var(ndp, ptr, ndp_len);
  283. }
  284. return 0;
  285. }
  286. static inline int dccp_elapsed_time_len(const u32 elapsed_time)
  287. {
  288. return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
  289. }
  290. int dccp_insert_option_elapsed_time(struct sock *sk, struct sk_buff *skb,
  291. u32 elapsed_time)
  292. {
  293. const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
  294. const int len = 2 + elapsed_time_len;
  295. unsigned char *to;
  296. if (elapsed_time_len == 0)
  297. return 0;
  298. if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
  299. return -1;
  300. DCCP_SKB_CB(skb)->dccpd_opt_len += len;
  301. to = skb_push(skb, len);
  302. *to++ = DCCPO_ELAPSED_TIME;
  303. *to++ = len;
  304. if (elapsed_time_len == 2) {
  305. const __be16 var16 = htons((u16)elapsed_time);
  306. memcpy(to, &var16, 2);
  307. } else {
  308. const __be32 var32 = htonl(elapsed_time);
  309. memcpy(to, &var32, 4);
  310. }
  311. return 0;
  312. }
  313. EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
  314. void dccp_timestamp(const struct sock *sk, struct timeval *tv)
  315. {
  316. const struct dccp_sock *dp = dccp_sk(sk);
  317. do_gettimeofday(tv);
  318. tv->tv_sec -= dp->dccps_epoch.tv_sec;
  319. tv->tv_usec -= dp->dccps_epoch.tv_usec;
  320. while (tv->tv_usec < 0) {
  321. tv->tv_sec--;
  322. tv->tv_usec += USEC_PER_SEC;
  323. }
  324. }
  325. EXPORT_SYMBOL_GPL(dccp_timestamp);
  326. int dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
  327. {
  328. struct timeval tv;
  329. __be32 now;
  330. dccp_timestamp(sk, &tv);
  331. now = htonl(timeval_usecs(&tv) / 10);
  332. /* yes this will overflow but that is the point as we want a
  333. * 10 usec 32 bit timer which mean it wraps every 11.9 hours */
  334. return dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
  335. }
  336. EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp);
  337. static int dccp_insert_option_timestamp_echo(struct sock *sk,
  338. struct sk_buff *skb)
  339. {
  340. struct dccp_sock *dp = dccp_sk(sk);
  341. struct timeval now;
  342. __be32 tstamp_echo;
  343. u32 elapsed_time;
  344. int len, elapsed_time_len;
  345. unsigned char *to;
  346. dccp_timestamp(sk, &now);
  347. elapsed_time = timeval_delta(&now, &dp->dccps_timestamp_time) / 10;
  348. elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
  349. len = 6 + elapsed_time_len;
  350. if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
  351. return -1;
  352. DCCP_SKB_CB(skb)->dccpd_opt_len += len;
  353. to = skb_push(skb, len);
  354. *to++ = DCCPO_TIMESTAMP_ECHO;
  355. *to++ = len;
  356. tstamp_echo = htonl(dp->dccps_timestamp_echo);
  357. memcpy(to, &tstamp_echo, 4);
  358. to += 4;
  359. if (elapsed_time_len == 2) {
  360. const __be16 var16 = htons((u16)elapsed_time);
  361. memcpy(to, &var16, 2);
  362. } else if (elapsed_time_len == 4) {
  363. const __be32 var32 = htonl(elapsed_time);
  364. memcpy(to, &var32, 4);
  365. }
  366. dp->dccps_timestamp_echo = 0;
  367. dp->dccps_timestamp_time.tv_sec = 0;
  368. dp->dccps_timestamp_time.tv_usec = 0;
  369. return 0;
  370. }
  371. static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
  372. u8 *val, u8 len)
  373. {
  374. u8 *to;
  375. if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) {
  376. LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small"
  377. " to insert feature %d option!\n", feat);
  378. return -1;
  379. }
  380. DCCP_SKB_CB(skb)->dccpd_opt_len += len + 3;
  381. to = skb_push(skb, len + 3);
  382. *to++ = type;
  383. *to++ = len + 3;
  384. *to++ = feat;
  385. if (len)
  386. memcpy(to, val, len);
  387. dccp_pr_debug("option %d feat %d len %d\n", type, feat, len);
  388. return 0;
  389. }
  390. static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb)
  391. {
  392. struct dccp_sock *dp = dccp_sk(sk);
  393. struct dccp_minisock *dmsk = dccp_msk(sk);
  394. struct dccp_opt_pend *opt, *next;
  395. int change = 0;
  396. /* confirm any options [NN opts] */
  397. list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) {
  398. dccp_insert_feat_opt(skb, opt->dccpop_type,
  399. opt->dccpop_feat, opt->dccpop_val,
  400. opt->dccpop_len);
  401. /* fear empty confirms */
  402. if (opt->dccpop_val)
  403. kfree(opt->dccpop_val);
  404. kfree(opt);
  405. }
  406. INIT_LIST_HEAD(&dmsk->dccpms_conf);
  407. /* see which features we need to send */
  408. list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
  409. /* see if we need to send any confirm */
  410. if (opt->dccpop_sc) {
  411. dccp_insert_feat_opt(skb, opt->dccpop_type + 1,
  412. opt->dccpop_feat,
  413. opt->dccpop_sc->dccpoc_val,
  414. opt->dccpop_sc->dccpoc_len);
  415. BUG_ON(!opt->dccpop_sc->dccpoc_val);
  416. kfree(opt->dccpop_sc->dccpoc_val);
  417. kfree(opt->dccpop_sc);
  418. opt->dccpop_sc = NULL;
  419. }
  420. /* any option not confirmed, re-send it */
  421. if (!opt->dccpop_conf) {
  422. dccp_insert_feat_opt(skb, opt->dccpop_type,
  423. opt->dccpop_feat, opt->dccpop_val,
  424. opt->dccpop_len);
  425. change++;
  426. }
  427. }
  428. /* Retransmit timer.
  429. * If this is the master listening sock, we don't set a timer on it. It
  430. * should be fine because if the dude doesn't receive our RESPONSE
  431. * [which will contain the CHANGE] he will send another REQUEST which
  432. * will "retrnasmit" the change.
  433. */
  434. if (change && dp->dccps_role != DCCP_ROLE_LISTEN) {
  435. dccp_pr_debug("reset feat negotiation timer %p\n", sk);
  436. /* XXX don't reset the timer on re-transmissions. I.e. reset it
  437. * only when sending new stuff i guess. Currently the timer
  438. * never backs off because on re-transmission it just resets it!
  439. */
  440. inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
  441. inet_csk(sk)->icsk_rto, DCCP_RTO_MAX);
  442. }
  443. return 0;
  444. }
  445. int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
  446. {
  447. struct dccp_sock *dp = dccp_sk(sk);
  448. struct dccp_minisock *dmsk = dccp_msk(sk);
  449. DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
  450. if (dmsk->dccpms_send_ndp_count &&
  451. dccp_insert_option_ndp(sk, skb))
  452. return -1;
  453. if (!dccp_packet_without_ack(skb)) {
  454. if (dmsk->dccpms_send_ack_vector &&
  455. dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&
  456. dccp_insert_option_ackvec(sk, skb))
  457. return -1;
  458. if (dp->dccps_timestamp_echo != 0 &&
  459. dccp_insert_option_timestamp_echo(sk, skb))
  460. return -1;
  461. }
  462. if (dp->dccps_hc_rx_insert_options) {
  463. if (ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb))
  464. return -1;
  465. dp->dccps_hc_rx_insert_options = 0;
  466. }
  467. if (dp->dccps_hc_tx_insert_options) {
  468. if (ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb))
  469. return -1;
  470. dp->dccps_hc_tx_insert_options = 0;
  471. }
  472. /* Feature negotiation */
  473. /* Data packets can't do feat negotiation */
  474. if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA &&
  475. DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK &&
  476. dccp_insert_options_feat(sk, skb))
  477. return -1;
  478. /* XXX: insert other options when appropriate */
  479. if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) {
  480. /* The length of all options has to be a multiple of 4 */
  481. int padding = DCCP_SKB_CB(skb)->dccpd_opt_len % 4;
  482. if (padding != 0) {
  483. padding = 4 - padding;
  484. memset(skb_push(skb, padding), 0, padding);
  485. DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
  486. }
  487. }
  488. return 0;
  489. }