Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.29-rc7 1241 lines 38 kB view raw
1/* 2 * net/dccp/feat.c 3 * 4 * Feature negotiation for the DCCP protocol (RFC 4340, section 6) 5 * 6 * Copyright (c) 2008 Gerrit Renker <gerrit@erg.abdn.ac.uk> 7 * Rewrote from scratch, some bits from earlier code by 8 * Copyright (c) 2005 Andrea Bittau <a.bittau@cs.ucl.ac.uk> 9 * 10 * 11 * ASSUMPTIONS 12 * ----------- 13 * o Feature negotiation is coordinated with connection setup (as in TCP), wild 14 * changes of parameters of an established connection are not supported. 15 * o All currently known SP features have 1-byte quantities. If in the future 16 * extensions of RFCs 4340..42 define features with item lengths larger than 17 * one byte, a feature-specific extension of the code will be required. 18 * 19 * This program is free software; you can redistribute it and/or 20 * modify it under the terms of the GNU General Public License 21 * as published by the Free Software Foundation; either version 22 * 2 of the License, or (at your option) any later version. 23 */ 24#include <linux/module.h> 25#include "ccid.h" 26#include "feat.h" 27 28/* 29 * Feature activation handlers. 30 * 31 * These all use an u64 argument, to provide enough room for NN/SP features. At 32 * this stage the negotiated values have been checked to be within their range. 33 */ 34static int dccp_hdlr_ccid(struct sock *sk, u64 ccid, bool rx) 35{ 36 struct dccp_sock *dp = dccp_sk(sk); 37 struct ccid *new_ccid = ccid_new(ccid, sk, rx); 38 39 if (new_ccid == NULL) 40 return -ENOMEM; 41 42 if (rx) { 43 ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); 44 dp->dccps_hc_rx_ccid = new_ccid; 45 } else { 46 ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); 47 dp->dccps_hc_tx_ccid = new_ccid; 48 } 49 return 0; 50} 51 52static int dccp_hdlr_seq_win(struct sock *sk, u64 seq_win, bool rx) 53{ 54 if (!rx) 55 dccp_msk(sk)->dccpms_sequence_window = seq_win; 56 return 0; 57} 58 59static int dccp_hdlr_ack_ratio(struct sock *sk, u64 ratio, bool rx) 60{ 61 if (rx) 62 dccp_sk(sk)->dccps_r_ack_ratio = ratio; 63 else 64 dccp_sk(sk)->dccps_l_ack_ratio = ratio; 65 return 0; 66} 67 68static int dccp_hdlr_ackvec(struct sock *sk, u64 enable, bool rx) 69{ 70 struct dccp_sock *dp = dccp_sk(sk); 71 72 if (rx) { 73 if (enable && dp->dccps_hc_rx_ackvec == NULL) { 74 dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(gfp_any()); 75 if (dp->dccps_hc_rx_ackvec == NULL) 76 return -ENOMEM; 77 } else if (!enable) { 78 dccp_ackvec_free(dp->dccps_hc_rx_ackvec); 79 dp->dccps_hc_rx_ackvec = NULL; 80 } 81 } 82 return 0; 83} 84 85static int dccp_hdlr_ndp(struct sock *sk, u64 enable, bool rx) 86{ 87 if (!rx) 88 dccp_sk(sk)->dccps_send_ndp_count = (enable > 0); 89 return 0; 90} 91 92/* 93 * Minimum Checksum Coverage is located at the RX side (9.2.1). This means that 94 * `rx' holds when the sending peer informs about his partial coverage via a 95 * ChangeR() option. In the other case, we are the sender and the receiver 96 * announces its coverage via ChangeL() options. The policy here is to honour 97 * such communication by enabling the corresponding partial coverage - but only 98 * if it has not been set manually before; the warning here means that all 99 * packets will be dropped. 100 */ 101static int dccp_hdlr_min_cscov(struct sock *sk, u64 cscov, bool rx) 102{ 103 struct dccp_sock *dp = dccp_sk(sk); 104 105 if (rx) 106 dp->dccps_pcrlen = cscov; 107 else { 108 if (dp->dccps_pcslen == 0) 109 dp->dccps_pcslen = cscov; 110 else if (cscov > dp->dccps_pcslen) 111 DCCP_WARN("CsCov %u too small, peer requires >= %u\n", 112 dp->dccps_pcslen, (u8)cscov); 113 } 114 return 0; 115} 116 117static const struct { 118 u8 feat_num; /* DCCPF_xxx */ 119 enum dccp_feat_type rxtx; /* RX or TX */ 120 enum dccp_feat_type reconciliation; /* SP or NN */ 121 u8 default_value; /* as in 6.4 */ 122 int (*activation_hdlr)(struct sock *sk, u64 val, bool rx); 123/* 124 * Lookup table for location and type of features (from RFC 4340/4342) 125 * +--------------------------+----+-----+----+----+---------+-----------+ 126 * | Feature | Location | Reconc. | Initial | Section | 127 * | | RX | TX | SP | NN | Value | Reference | 128 * +--------------------------+----+-----+----+----+---------+-----------+ 129 * | DCCPF_CCID | | X | X | | 2 | 10 | 130 * | DCCPF_SHORT_SEQNOS | | X | X | | 0 | 7.6.1 | 131 * | DCCPF_SEQUENCE_WINDOW | | X | | X | 100 | 7.5.2 | 132 * | DCCPF_ECN_INCAPABLE | X | | X | | 0 | 12.1 | 133 * | DCCPF_ACK_RATIO | | X | | X | 2 | 11.3 | 134 * | DCCPF_SEND_ACK_VECTOR | X | | X | | 0 | 11.5 | 135 * | DCCPF_SEND_NDP_COUNT | | X | X | | 0 | 7.7.2 | 136 * | DCCPF_MIN_CSUM_COVER | X | | X | | 0 | 9.2.1 | 137 * | DCCPF_DATA_CHECKSUM | X | | X | | 0 | 9.3.1 | 138 * | DCCPF_SEND_LEV_RATE | X | | X | | 0 | 4342/8.4 | 139 * +--------------------------+----+-----+----+----+---------+-----------+ 140 */ 141} dccp_feat_table[] = { 142 { DCCPF_CCID, FEAT_AT_TX, FEAT_SP, 2, dccp_hdlr_ccid }, 143 { DCCPF_SHORT_SEQNOS, FEAT_AT_TX, FEAT_SP, 0, NULL }, 144 { DCCPF_SEQUENCE_WINDOW, FEAT_AT_TX, FEAT_NN, 100, dccp_hdlr_seq_win }, 145 { DCCPF_ECN_INCAPABLE, FEAT_AT_RX, FEAT_SP, 0, NULL }, 146 { DCCPF_ACK_RATIO, FEAT_AT_TX, FEAT_NN, 2, dccp_hdlr_ack_ratio}, 147 { DCCPF_SEND_ACK_VECTOR, FEAT_AT_RX, FEAT_SP, 0, dccp_hdlr_ackvec }, 148 { DCCPF_SEND_NDP_COUNT, FEAT_AT_TX, FEAT_SP, 0, dccp_hdlr_ndp }, 149 { DCCPF_MIN_CSUM_COVER, FEAT_AT_RX, FEAT_SP, 0, dccp_hdlr_min_cscov}, 150 { DCCPF_DATA_CHECKSUM, FEAT_AT_RX, FEAT_SP, 0, NULL }, 151 { DCCPF_SEND_LEV_RATE, FEAT_AT_RX, FEAT_SP, 0, NULL }, 152}; 153#define DCCP_FEAT_SUPPORTED_MAX ARRAY_SIZE(dccp_feat_table) 154 155/** 156 * dccp_feat_index - Hash function to map feature number into array position 157 * Returns consecutive array index or -1 if the feature is not understood. 158 */ 159static int dccp_feat_index(u8 feat_num) 160{ 161 /* The first 9 entries are occupied by the types from RFC 4340, 6.4 */ 162 if (feat_num > DCCPF_RESERVED && feat_num <= DCCPF_DATA_CHECKSUM) 163 return feat_num - 1; 164 165 /* 166 * Other features: add cases for new feature types here after adding 167 * them to the above table. 168 */ 169 switch (feat_num) { 170 case DCCPF_SEND_LEV_RATE: 171 return DCCP_FEAT_SUPPORTED_MAX - 1; 172 } 173 return -1; 174} 175 176static u8 dccp_feat_type(u8 feat_num) 177{ 178 int idx = dccp_feat_index(feat_num); 179 180 if (idx < 0) 181 return FEAT_UNKNOWN; 182 return dccp_feat_table[idx].reconciliation; 183} 184 185static int dccp_feat_default_value(u8 feat_num) 186{ 187 int idx = dccp_feat_index(feat_num); 188 /* 189 * There are no default values for unknown features, so encountering a 190 * negative index here indicates a serious problem somewhere else. 191 */ 192 DCCP_BUG_ON(idx < 0); 193 194 return idx < 0 ? 0 : dccp_feat_table[idx].default_value; 195} 196 197static int __dccp_feat_activate(struct sock *sk, const int idx, 198 const bool is_local, dccp_feat_val const *fval) 199{ 200 bool rx; 201 u64 val; 202 203 if (idx < 0 || idx >= DCCP_FEAT_SUPPORTED_MAX) 204 return -1; 205 if (dccp_feat_table[idx].activation_hdlr == NULL) 206 return 0; 207 208 if (fval == NULL) { 209 val = dccp_feat_table[idx].default_value; 210 } else if (dccp_feat_table[idx].reconciliation == FEAT_SP) { 211 if (fval->sp.vec == NULL) { 212 /* 213 * This can happen when an empty Confirm is sent 214 * for an SP (i.e. known) feature. In this case 215 * we would be using the default anyway. 216 */ 217 DCCP_CRIT("Feature #%d undefined: using default", idx); 218 val = dccp_feat_table[idx].default_value; 219 } else { 220 val = fval->sp.vec[0]; 221 } 222 } else { 223 val = fval->nn; 224 } 225 226 /* Location is RX if this is a local-RX or remote-TX feature */ 227 rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX)); 228 229 return dccp_feat_table[idx].activation_hdlr(sk, val, rx); 230} 231 232/* Test for "Req'd" feature (RFC 4340, 6.4) */ 233static inline int dccp_feat_must_be_understood(u8 feat_num) 234{ 235 return feat_num == DCCPF_CCID || feat_num == DCCPF_SHORT_SEQNOS || 236 feat_num == DCCPF_SEQUENCE_WINDOW; 237} 238 239/* copy constructor, fval must not already contain allocated memory */ 240static int dccp_feat_clone_sp_val(dccp_feat_val *fval, u8 const *val, u8 len) 241{ 242 fval->sp.len = len; 243 if (fval->sp.len > 0) { 244 fval->sp.vec = kmemdup(val, len, gfp_any()); 245 if (fval->sp.vec == NULL) { 246 fval->sp.len = 0; 247 return -ENOBUFS; 248 } 249 } 250 return 0; 251} 252 253static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val) 254{ 255 if (unlikely(val == NULL)) 256 return; 257 if (dccp_feat_type(feat_num) == FEAT_SP) 258 kfree(val->sp.vec); 259 memset(val, 0, sizeof(*val)); 260} 261 262static struct dccp_feat_entry * 263 dccp_feat_clone_entry(struct dccp_feat_entry const *original) 264{ 265 struct dccp_feat_entry *new; 266 u8 type = dccp_feat_type(original->feat_num); 267 268 if (type == FEAT_UNKNOWN) 269 return NULL; 270 271 new = kmemdup(original, sizeof(struct dccp_feat_entry), gfp_any()); 272 if (new == NULL) 273 return NULL; 274 275 if (type == FEAT_SP && dccp_feat_clone_sp_val(&new->val, 276 original->val.sp.vec, 277 original->val.sp.len)) { 278 kfree(new); 279 return NULL; 280 } 281 return new; 282} 283 284static void dccp_feat_entry_destructor(struct dccp_feat_entry *entry) 285{ 286 if (entry != NULL) { 287 dccp_feat_val_destructor(entry->feat_num, &entry->val); 288 kfree(entry); 289 } 290} 291 292/* 293 * List management functions 294 * 295 * Feature negotiation lists rely on and maintain the following invariants: 296 * - each feat_num in the list is known, i.e. we know its type and default value 297 * - each feat_num/is_local combination is unique (old entries are overwritten) 298 * - SP values are always freshly allocated 299 * - list is sorted in increasing order of feature number (faster lookup) 300 */ 301static struct dccp_feat_entry *dccp_feat_list_lookup(struct list_head *fn_list, 302 u8 feat_num, bool is_local) 303{ 304 struct dccp_feat_entry *entry; 305 306 list_for_each_entry(entry, fn_list, node) { 307 if (entry->feat_num == feat_num && entry->is_local == is_local) 308 return entry; 309 else if (entry->feat_num > feat_num) 310 break; 311 } 312 return NULL; 313} 314 315/** 316 * dccp_feat_entry_new - Central list update routine (called by all others) 317 * @head: list to add to 318 * @feat: feature number 319 * @local: whether the local (1) or remote feature with number @feat is meant 320 * This is the only constructor and serves to ensure the above invariants. 321 */ 322static struct dccp_feat_entry * 323 dccp_feat_entry_new(struct list_head *head, u8 feat, bool local) 324{ 325 struct dccp_feat_entry *entry; 326 327 list_for_each_entry(entry, head, node) 328 if (entry->feat_num == feat && entry->is_local == local) { 329 dccp_feat_val_destructor(entry->feat_num, &entry->val); 330 return entry; 331 } else if (entry->feat_num > feat) { 332 head = &entry->node; 333 break; 334 } 335 336 entry = kmalloc(sizeof(*entry), gfp_any()); 337 if (entry != NULL) { 338 entry->feat_num = feat; 339 entry->is_local = local; 340 list_add_tail(&entry->node, head); 341 } 342 return entry; 343} 344 345/** 346 * dccp_feat_push_change - Add/overwrite a Change option in the list 347 * @fn_list: feature-negotiation list to update 348 * @feat: one of %dccp_feature_numbers 349 * @local: whether local (1) or remote (0) @feat_num is meant 350 * @needs_mandatory: whether to use Mandatory feature negotiation options 351 * @fval: pointer to NN/SP value to be inserted (will be copied) 352 */ 353static int dccp_feat_push_change(struct list_head *fn_list, u8 feat, u8 local, 354 u8 mandatory, dccp_feat_val *fval) 355{ 356 struct dccp_feat_entry *new = dccp_feat_entry_new(fn_list, feat, local); 357 358 if (new == NULL) 359 return -ENOMEM; 360 361 new->feat_num = feat; 362 new->is_local = local; 363 new->state = FEAT_INITIALISING; 364 new->needs_confirm = 0; 365 new->empty_confirm = 0; 366 new->val = *fval; 367 new->needs_mandatory = mandatory; 368 369 return 0; 370} 371 372/** 373 * dccp_feat_push_confirm - Add a Confirm entry to the FN list 374 * @fn_list: feature-negotiation list to add to 375 * @feat: one of %dccp_feature_numbers 376 * @local: whether local (1) or remote (0) @feat_num is being confirmed 377 * @fval: pointer to NN/SP value to be inserted or NULL 378 * Returns 0 on success, a Reset code for further processing otherwise. 379 */ 380static int dccp_feat_push_confirm(struct list_head *fn_list, u8 feat, u8 local, 381 dccp_feat_val *fval) 382{ 383 struct dccp_feat_entry *new = dccp_feat_entry_new(fn_list, feat, local); 384 385 if (new == NULL) 386 return DCCP_RESET_CODE_TOO_BUSY; 387 388 new->feat_num = feat; 389 new->is_local = local; 390 new->state = FEAT_STABLE; /* transition in 6.6.2 */ 391 new->needs_confirm = 1; 392 new->empty_confirm = (fval == NULL); 393 new->val.nn = 0; /* zeroes the whole structure */ 394 if (!new->empty_confirm) 395 new->val = *fval; 396 new->needs_mandatory = 0; 397 398 return 0; 399} 400 401static int dccp_push_empty_confirm(struct list_head *fn_list, u8 feat, u8 local) 402{ 403 return dccp_feat_push_confirm(fn_list, feat, local, NULL); 404} 405 406static inline void dccp_feat_list_pop(struct dccp_feat_entry *entry) 407{ 408 list_del(&entry->node); 409 dccp_feat_entry_destructor(entry); 410} 411 412void dccp_feat_list_purge(struct list_head *fn_list) 413{ 414 struct dccp_feat_entry *entry, *next; 415 416 list_for_each_entry_safe(entry, next, fn_list, node) 417 dccp_feat_entry_destructor(entry); 418 INIT_LIST_HEAD(fn_list); 419} 420EXPORT_SYMBOL_GPL(dccp_feat_list_purge); 421 422/* generate @to as full clone of @from - @to must not contain any nodes */ 423int dccp_feat_clone_list(struct list_head const *from, struct list_head *to) 424{ 425 struct dccp_feat_entry *entry, *new; 426 427 INIT_LIST_HEAD(to); 428 list_for_each_entry(entry, from, node) { 429 new = dccp_feat_clone_entry(entry); 430 if (new == NULL) 431 goto cloning_failed; 432 list_add_tail(&new->node, to); 433 } 434 return 0; 435 436cloning_failed: 437 dccp_feat_list_purge(to); 438 return -ENOMEM; 439} 440 441/** 442 * dccp_feat_valid_nn_length - Enforce length constraints on NN options 443 * Length is between 0 and %DCCP_OPTVAL_MAXLEN. Used for outgoing packets only, 444 * incoming options are accepted as long as their values are valid. 445 */ 446static u8 dccp_feat_valid_nn_length(u8 feat_num) 447{ 448 if (feat_num == DCCPF_ACK_RATIO) /* RFC 4340, 11.3 and 6.6.8 */ 449 return 2; 450 if (feat_num == DCCPF_SEQUENCE_WINDOW) /* RFC 4340, 7.5.2 and 6.5 */ 451 return 6; 452 return 0; 453} 454 455static u8 dccp_feat_is_valid_nn_val(u8 feat_num, u64 val) 456{ 457 switch (feat_num) { 458 case DCCPF_ACK_RATIO: 459 return val <= DCCPF_ACK_RATIO_MAX; 460 case DCCPF_SEQUENCE_WINDOW: 461 return val >= DCCPF_SEQ_WMIN && val <= DCCPF_SEQ_WMAX; 462 } 463 return 0; /* feature unknown - so we can't tell */ 464} 465 466/* check that SP values are within the ranges defined in RFC 4340 */ 467static u8 dccp_feat_is_valid_sp_val(u8 feat_num, u8 val) 468{ 469 switch (feat_num) { 470 case DCCPF_CCID: 471 return val == DCCPC_CCID2 || val == DCCPC_CCID3; 472 /* Type-check Boolean feature values: */ 473 case DCCPF_SHORT_SEQNOS: 474 case DCCPF_ECN_INCAPABLE: 475 case DCCPF_SEND_ACK_VECTOR: 476 case DCCPF_SEND_NDP_COUNT: 477 case DCCPF_DATA_CHECKSUM: 478 case DCCPF_SEND_LEV_RATE: 479 return val < 2; 480 case DCCPF_MIN_CSUM_COVER: 481 return val < 16; 482 } 483 return 0; /* feature unknown */ 484} 485 486static u8 dccp_feat_sp_list_ok(u8 feat_num, u8 const *sp_list, u8 sp_len) 487{ 488 if (sp_list == NULL || sp_len < 1) 489 return 0; 490 while (sp_len--) 491 if (!dccp_feat_is_valid_sp_val(feat_num, *sp_list++)) 492 return 0; 493 return 1; 494} 495 496/** 497 * dccp_feat_insert_opts - Generate FN options from current list state 498 * @skb: next sk_buff to be sent to the peer 499 * @dp: for client during handshake and general negotiation 500 * @dreq: used by the server only (all Changes/Confirms in LISTEN/RESPOND) 501 */ 502int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq, 503 struct sk_buff *skb) 504{ 505 struct list_head *fn = dreq ? &dreq->dreq_featneg : &dp->dccps_featneg; 506 struct dccp_feat_entry *pos, *next; 507 u8 opt, type, len, *ptr, nn_in_nbo[DCCP_OPTVAL_MAXLEN]; 508 bool rpt; 509 510 /* put entries into @skb in the order they appear in the list */ 511 list_for_each_entry_safe_reverse(pos, next, fn, node) { 512 opt = dccp_feat_genopt(pos); 513 type = dccp_feat_type(pos->feat_num); 514 rpt = false; 515 516 if (pos->empty_confirm) { 517 len = 0; 518 ptr = NULL; 519 } else { 520 if (type == FEAT_SP) { 521 len = pos->val.sp.len; 522 ptr = pos->val.sp.vec; 523 rpt = pos->needs_confirm; 524 } else if (type == FEAT_NN) { 525 len = dccp_feat_valid_nn_length(pos->feat_num); 526 ptr = nn_in_nbo; 527 dccp_encode_value_var(pos->val.nn, ptr, len); 528 } else { 529 DCCP_BUG("unknown feature %u", pos->feat_num); 530 return -1; 531 } 532 } 533 534 if (dccp_insert_fn_opt(skb, opt, pos->feat_num, ptr, len, rpt)) 535 return -1; 536 if (pos->needs_mandatory && dccp_insert_option_mandatory(skb)) 537 return -1; 538 /* 539 * Enter CHANGING after transmitting the Change option (6.6.2). 540 */ 541 if (pos->state == FEAT_INITIALISING) 542 pos->state = FEAT_CHANGING; 543 } 544 return 0; 545} 546 547/** 548 * __feat_register_nn - Register new NN value on socket 549 * @fn: feature-negotiation list to register with 550 * @feat: an NN feature from %dccp_feature_numbers 551 * @mandatory: use Mandatory option if 1 552 * @nn_val: value to register (restricted to 4 bytes) 553 * Note that NN features are local by definition (RFC 4340, 6.3.2). 554 */ 555static int __feat_register_nn(struct list_head *fn, u8 feat, 556 u8 mandatory, u64 nn_val) 557{ 558 dccp_feat_val fval = { .nn = nn_val }; 559 560 if (dccp_feat_type(feat) != FEAT_NN || 561 !dccp_feat_is_valid_nn_val(feat, nn_val)) 562 return -EINVAL; 563 564 /* Don't bother with default values, they will be activated anyway. */ 565 if (nn_val - (u64)dccp_feat_default_value(feat) == 0) 566 return 0; 567 568 return dccp_feat_push_change(fn, feat, 1, mandatory, &fval); 569} 570 571/** 572 * __feat_register_sp - Register new SP value/list on socket 573 * @fn: feature-negotiation list to register with 574 * @feat: an SP feature from %dccp_feature_numbers 575 * @is_local: whether the local (1) or the remote (0) @feat is meant 576 * @mandatory: use Mandatory option if 1 577 * @sp_val: SP value followed by optional preference list 578 * @sp_len: length of @sp_val in bytes 579 */ 580static int __feat_register_sp(struct list_head *fn, u8 feat, u8 is_local, 581 u8 mandatory, u8 const *sp_val, u8 sp_len) 582{ 583 dccp_feat_val fval; 584 585 if (dccp_feat_type(feat) != FEAT_SP || 586 !dccp_feat_sp_list_ok(feat, sp_val, sp_len)) 587 return -EINVAL; 588 589 /* Avoid negotiating alien CCIDs by only advertising supported ones */ 590 if (feat == DCCPF_CCID && !ccid_support_check(sp_val, sp_len)) 591 return -EOPNOTSUPP; 592 593 if (dccp_feat_clone_sp_val(&fval, sp_val, sp_len)) 594 return -ENOMEM; 595 596 return dccp_feat_push_change(fn, feat, is_local, mandatory, &fval); 597} 598 599/** 600 * dccp_feat_register_sp - Register requests to change SP feature values 601 * @sk: client or listening socket 602 * @feat: one of %dccp_feature_numbers 603 * @is_local: whether the local (1) or remote (0) @feat is meant 604 * @list: array of preferred values, in descending order of preference 605 * @len: length of @list in bytes 606 */ 607int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local, 608 u8 const *list, u8 len) 609{ /* any changes must be registered before establishing the connection */ 610 if (sk->sk_state != DCCP_CLOSED) 611 return -EISCONN; 612 if (dccp_feat_type(feat) != FEAT_SP) 613 return -EINVAL; 614 return __feat_register_sp(&dccp_sk(sk)->dccps_featneg, feat, is_local, 615 0, list, len); 616} 617 618/* Analogous to dccp_feat_register_sp(), but for non-negotiable values */ 619int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val) 620{ 621 /* any changes must be registered before establishing the connection */ 622 if (sk->sk_state != DCCP_CLOSED) 623 return -EISCONN; 624 if (dccp_feat_type(feat) != FEAT_NN) 625 return -EINVAL; 626 return __feat_register_nn(&dccp_sk(sk)->dccps_featneg, feat, 0, val); 627} 628 629/* 630 * Tracking features whose value depend on the choice of CCID 631 * 632 * This is designed with an extension in mind so that a list walk could be done 633 * before activating any features. However, the existing framework was found to 634 * work satisfactorily up until now, the automatic verification is left open. 635 * When adding new CCIDs, add a corresponding dependency table here. 636 */ 637static const struct ccid_dependency *dccp_feat_ccid_deps(u8 ccid, bool is_local) 638{ 639 static const struct ccid_dependency ccid2_dependencies[2][2] = { 640 /* 641 * CCID2 mandates Ack Vectors (RFC 4341, 4.): as CCID is a TX 642 * feature and Send Ack Vector is an RX feature, `is_local' 643 * needs to be reversed. 644 */ 645 { /* Dependencies of the receiver-side (remote) CCID2 */ 646 { 647 .dependent_feat = DCCPF_SEND_ACK_VECTOR, 648 .is_local = true, 649 .is_mandatory = true, 650 .val = 1 651 }, 652 { 0, 0, 0, 0 } 653 }, 654 { /* Dependencies of the sender-side (local) CCID2 */ 655 { 656 .dependent_feat = DCCPF_SEND_ACK_VECTOR, 657 .is_local = false, 658 .is_mandatory = true, 659 .val = 1 660 }, 661 { 0, 0, 0, 0 } 662 } 663 }; 664 static const struct ccid_dependency ccid3_dependencies[2][5] = { 665 { /* 666 * Dependencies of the receiver-side CCID3 667 */ 668 { /* locally disable Ack Vectors */ 669 .dependent_feat = DCCPF_SEND_ACK_VECTOR, 670 .is_local = true, 671 .is_mandatory = false, 672 .val = 0 673 }, 674 { /* see below why Send Loss Event Rate is on */ 675 .dependent_feat = DCCPF_SEND_LEV_RATE, 676 .is_local = true, 677 .is_mandatory = true, 678 .val = 1 679 }, 680 { /* NDP Count is needed as per RFC 4342, 6.1.1 */ 681 .dependent_feat = DCCPF_SEND_NDP_COUNT, 682 .is_local = false, 683 .is_mandatory = true, 684 .val = 1 685 }, 686 { 0, 0, 0, 0 }, 687 }, 688 { /* 689 * CCID3 at the TX side: we request that the HC-receiver 690 * will not send Ack Vectors (they will be ignored, so 691 * Mandatory is not set); we enable Send Loss Event Rate 692 * (Mandatory since the implementation does not support 693 * the Loss Intervals option of RFC 4342, 8.6). 694 * The last two options are for peer's information only. 695 */ 696 { 697 .dependent_feat = DCCPF_SEND_ACK_VECTOR, 698 .is_local = false, 699 .is_mandatory = false, 700 .val = 0 701 }, 702 { 703 .dependent_feat = DCCPF_SEND_LEV_RATE, 704 .is_local = false, 705 .is_mandatory = true, 706 .val = 1 707 }, 708 { /* this CCID does not support Ack Ratio */ 709 .dependent_feat = DCCPF_ACK_RATIO, 710 .is_local = true, 711 .is_mandatory = false, 712 .val = 0 713 }, 714 { /* tell receiver we are sending NDP counts */ 715 .dependent_feat = DCCPF_SEND_NDP_COUNT, 716 .is_local = true, 717 .is_mandatory = false, 718 .val = 1 719 }, 720 { 0, 0, 0, 0 } 721 } 722 }; 723 switch (ccid) { 724 case DCCPC_CCID2: 725 return ccid2_dependencies[is_local]; 726 case DCCPC_CCID3: 727 return ccid3_dependencies[is_local]; 728 default: 729 return NULL; 730 } 731} 732 733/** 734 * dccp_feat_propagate_ccid - Resolve dependencies of features on choice of CCID 735 * @fn: feature-negotiation list to update 736 * @id: CCID number to track 737 * @is_local: whether TX CCID (1) or RX CCID (0) is meant 738 * This function needs to be called after registering all other features. 739 */ 740static int dccp_feat_propagate_ccid(struct list_head *fn, u8 id, bool is_local) 741{ 742 const struct ccid_dependency *table = dccp_feat_ccid_deps(id, is_local); 743 int i, rc = (table == NULL); 744 745 for (i = 0; rc == 0 && table[i].dependent_feat != DCCPF_RESERVED; i++) 746 if (dccp_feat_type(table[i].dependent_feat) == FEAT_SP) 747 rc = __feat_register_sp(fn, table[i].dependent_feat, 748 table[i].is_local, 749 table[i].is_mandatory, 750 &table[i].val, 1); 751 else 752 rc = __feat_register_nn(fn, table[i].dependent_feat, 753 table[i].is_mandatory, 754 table[i].val); 755 return rc; 756} 757 758/** 759 * dccp_feat_finalise_settings - Finalise settings before starting negotiation 760 * @dp: client or listening socket (settings will be inherited) 761 * This is called after all registrations (socket initialisation, sysctls, and 762 * sockopt calls), and before sending the first packet containing Change options 763 * (ie. client-Request or server-Response), to ensure internal consistency. 764 */ 765int dccp_feat_finalise_settings(struct dccp_sock *dp) 766{ 767 struct list_head *fn = &dp->dccps_featneg; 768 struct dccp_feat_entry *entry; 769 int i = 2, ccids[2] = { -1, -1 }; 770 771 /* 772 * Propagating CCIDs: 773 * 1) not useful to propagate CCID settings if this host advertises more 774 * than one CCID: the choice of CCID may still change - if this is 775 * the client, or if this is the server and the client sends 776 * singleton CCID values. 777 * 2) since is that propagate_ccid changes the list, we defer changing 778 * the sorted list until after the traversal. 779 */ 780 list_for_each_entry(entry, fn, node) 781 if (entry->feat_num == DCCPF_CCID && entry->val.sp.len == 1) 782 ccids[entry->is_local] = entry->val.sp.vec[0]; 783 while (i--) 784 if (ccids[i] > 0 && dccp_feat_propagate_ccid(fn, ccids[i], i)) 785 return -1; 786 return 0; 787} 788 789/** 790 * dccp_feat_server_ccid_dependencies - Resolve CCID-dependent features 791 * It is the server which resolves the dependencies once the CCID has been 792 * fully negotiated. If no CCID has been negotiated, it uses the default CCID. 793 */ 794int dccp_feat_server_ccid_dependencies(struct dccp_request_sock *dreq) 795{ 796 struct list_head *fn = &dreq->dreq_featneg; 797 struct dccp_feat_entry *entry; 798 u8 is_local, ccid; 799 800 for (is_local = 0; is_local <= 1; is_local++) { 801 entry = dccp_feat_list_lookup(fn, DCCPF_CCID, is_local); 802 803 if (entry != NULL && !entry->empty_confirm) 804 ccid = entry->val.sp.vec[0]; 805 else 806 ccid = dccp_feat_default_value(DCCPF_CCID); 807 808 if (dccp_feat_propagate_ccid(fn, ccid, is_local)) 809 return -1; 810 } 811 return 0; 812} 813 814/* Select the first entry in @servlist that also occurs in @clilist (6.3.1) */ 815static int dccp_feat_preflist_match(u8 *servlist, u8 slen, u8 *clilist, u8 clen) 816{ 817 u8 c, s; 818 819 for (s = 0; s < slen; s++) 820 for (c = 0; c < clen; c++) 821 if (servlist[s] == clilist[c]) 822 return servlist[s]; 823 return -1; 824} 825 826/** 827 * dccp_feat_prefer - Move preferred entry to the start of array 828 * Reorder the @array_len elements in @array so that @preferred_value comes 829 * first. Returns >0 to indicate that @preferred_value does occur in @array. 830 */ 831static u8 dccp_feat_prefer(u8 preferred_value, u8 *array, u8 array_len) 832{ 833 u8 i, does_occur = 0; 834 835 if (array != NULL) { 836 for (i = 0; i < array_len; i++) 837 if (array[i] == preferred_value) { 838 array[i] = array[0]; 839 does_occur++; 840 } 841 if (does_occur) 842 array[0] = preferred_value; 843 } 844 return does_occur; 845} 846 847/** 848 * dccp_feat_reconcile - Reconcile SP preference lists 849 * @fval: SP list to reconcile into 850 * @arr: received SP preference list 851 * @len: length of @arr in bytes 852 * @is_server: whether this side is the server (and @fv is the server's list) 853 * @reorder: whether to reorder the list in @fv after reconciling with @arr 854 * When successful, > 0 is returned and the reconciled list is in @fval. 855 * A value of 0 means that negotiation failed (no shared entry). 856 */ 857static int dccp_feat_reconcile(dccp_feat_val *fv, u8 *arr, u8 len, 858 bool is_server, bool reorder) 859{ 860 int rc; 861 862 if (!fv->sp.vec || !arr) { 863 DCCP_CRIT("NULL feature value or array"); 864 return 0; 865 } 866 867 if (is_server) 868 rc = dccp_feat_preflist_match(fv->sp.vec, fv->sp.len, arr, len); 869 else 870 rc = dccp_feat_preflist_match(arr, len, fv->sp.vec, fv->sp.len); 871 872 if (!reorder) 873 return rc; 874 if (rc < 0) 875 return 0; 876 877 /* 878 * Reorder list: used for activating features and in dccp_insert_fn_opt. 879 */ 880 return dccp_feat_prefer(rc, fv->sp.vec, fv->sp.len); 881} 882 883/** 884 * dccp_feat_change_recv - Process incoming ChangeL/R options 885 * @fn: feature-negotiation list to update 886 * @is_mandatory: whether the Change was preceded by a Mandatory option 887 * @opt: %DCCPO_CHANGE_L or %DCCPO_CHANGE_R 888 * @feat: one of %dccp_feature_numbers 889 * @val: NN value or SP value/preference list 890 * @len: length of @val in bytes 891 * @server: whether this node is the server (1) or the client (0) 892 */ 893static u8 dccp_feat_change_recv(struct list_head *fn, u8 is_mandatory, u8 opt, 894 u8 feat, u8 *val, u8 len, const bool server) 895{ 896 u8 defval, type = dccp_feat_type(feat); 897 const bool local = (opt == DCCPO_CHANGE_R); 898 struct dccp_feat_entry *entry; 899 dccp_feat_val fval; 900 901 if (len == 0 || type == FEAT_UNKNOWN) /* 6.1 and 6.6.8 */ 902 goto unknown_feature_or_value; 903 904 /* 905 * Negotiation of NN features: Change R is invalid, so there is no 906 * simultaneous negotiation; hence we do not look up in the list. 907 */ 908 if (type == FEAT_NN) { 909 if (local || len > sizeof(fval.nn)) 910 goto unknown_feature_or_value; 911 912 /* 6.3.2: "The feature remote MUST accept any valid value..." */ 913 fval.nn = dccp_decode_value_var(val, len); 914 if (!dccp_feat_is_valid_nn_val(feat, fval.nn)) 915 goto unknown_feature_or_value; 916 917 return dccp_feat_push_confirm(fn, feat, local, &fval); 918 } 919 920 /* 921 * Unidirectional/simultaneous negotiation of SP features (6.3.1) 922 */ 923 entry = dccp_feat_list_lookup(fn, feat, local); 924 if (entry == NULL) { 925 /* 926 * No particular preferences have been registered. We deal with 927 * this situation by assuming that all valid values are equally 928 * acceptable, and apply the following checks: 929 * - if the peer's list is a singleton, we accept a valid value; 930 * - if we are the server, we first try to see if the peer (the 931 * client) advertises the default value. If yes, we use it, 932 * otherwise we accept the preferred value; 933 * - else if we are the client, we use the first list element. 934 */ 935 if (dccp_feat_clone_sp_val(&fval, val, 1)) 936 return DCCP_RESET_CODE_TOO_BUSY; 937 938 if (len > 1 && server) { 939 defval = dccp_feat_default_value(feat); 940 if (dccp_feat_preflist_match(&defval, 1, val, len) > -1) 941 fval.sp.vec[0] = defval; 942 } else if (!dccp_feat_is_valid_sp_val(feat, fval.sp.vec[0])) { 943 kfree(fval.sp.vec); 944 goto unknown_feature_or_value; 945 } 946 947 /* Treat unsupported CCIDs like invalid values */ 948 if (feat == DCCPF_CCID && !ccid_support_check(fval.sp.vec, 1)) { 949 kfree(fval.sp.vec); 950 goto not_valid_or_not_known; 951 } 952 953 return dccp_feat_push_confirm(fn, feat, local, &fval); 954 955 } else if (entry->state == FEAT_UNSTABLE) { /* 6.6.2 */ 956 return 0; 957 } 958 959 if (dccp_feat_reconcile(&entry->val, val, len, server, true)) { 960 entry->empty_confirm = 0; 961 } else if (is_mandatory) { 962 return DCCP_RESET_CODE_MANDATORY_ERROR; 963 } else if (entry->state == FEAT_INITIALISING) { 964 /* 965 * Failed simultaneous negotiation (server only): try to `save' 966 * the connection by checking whether entry contains the default 967 * value for @feat. If yes, send an empty Confirm to signal that 968 * the received Change was not understood - which implies using 969 * the default value. 970 * If this also fails, we use Reset as the last resort. 971 */ 972 WARN_ON(!server); 973 defval = dccp_feat_default_value(feat); 974 if (!dccp_feat_reconcile(&entry->val, &defval, 1, server, true)) 975 return DCCP_RESET_CODE_OPTION_ERROR; 976 entry->empty_confirm = 1; 977 } 978 entry->needs_confirm = 1; 979 entry->needs_mandatory = 0; 980 entry->state = FEAT_STABLE; 981 return 0; 982 983unknown_feature_or_value: 984 if (!is_mandatory) 985 return dccp_push_empty_confirm(fn, feat, local); 986 987not_valid_or_not_known: 988 return is_mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR 989 : DCCP_RESET_CODE_OPTION_ERROR; 990} 991 992/** 993 * dccp_feat_confirm_recv - Process received Confirm options 994 * @fn: feature-negotiation list to update 995 * @is_mandatory: whether @opt was preceded by a Mandatory option 996 * @opt: %DCCPO_CONFIRM_L or %DCCPO_CONFIRM_R 997 * @feat: one of %dccp_feature_numbers 998 * @val: NN value or SP value/preference list 999 * @len: length of @val in bytes 1000 * @server: whether this node is server (1) or client (0) 1001 */ 1002static u8 dccp_feat_confirm_recv(struct list_head *fn, u8 is_mandatory, u8 opt, 1003 u8 feat, u8 *val, u8 len, const bool server) 1004{ 1005 u8 *plist, plen, type = dccp_feat_type(feat); 1006 const bool local = (opt == DCCPO_CONFIRM_R); 1007 struct dccp_feat_entry *entry = dccp_feat_list_lookup(fn, feat, local); 1008 1009 if (entry == NULL) { /* nothing queued: ignore or handle error */ 1010 if (is_mandatory && type == FEAT_UNKNOWN) 1011 return DCCP_RESET_CODE_MANDATORY_ERROR; 1012 1013 if (!local && type == FEAT_NN) /* 6.3.2 */ 1014 goto confirmation_failed; 1015 return 0; 1016 } 1017 1018 if (entry->state != FEAT_CHANGING) /* 6.6.2 */ 1019 return 0; 1020 1021 if (len == 0) { 1022 if (dccp_feat_must_be_understood(feat)) /* 6.6.7 */ 1023 goto confirmation_failed; 1024 /* 1025 * Empty Confirm during connection setup: this means reverting 1026 * to the `old' value, which in this case is the default. Since 1027 * we handle default values automatically when no other values 1028 * have been set, we revert to the old value by removing this 1029 * entry from the list. 1030 */ 1031 dccp_feat_list_pop(entry); 1032 return 0; 1033 } 1034 1035 if (type == FEAT_NN) { 1036 if (len > sizeof(entry->val.nn)) 1037 goto confirmation_failed; 1038 1039 if (entry->val.nn == dccp_decode_value_var(val, len)) 1040 goto confirmation_succeeded; 1041 1042 DCCP_WARN("Bogus Confirm for non-existing value\n"); 1043 goto confirmation_failed; 1044 } 1045 1046 /* 1047 * Parsing SP Confirms: the first element of @val is the preferred 1048 * SP value which the peer confirms, the remainder depends on @len. 1049 * Note that only the confirmed value need to be a valid SP value. 1050 */ 1051 if (!dccp_feat_is_valid_sp_val(feat, *val)) 1052 goto confirmation_failed; 1053 1054 if (len == 1) { /* peer didn't supply a preference list */ 1055 plist = val; 1056 plen = len; 1057 } else { /* preferred value + preference list */ 1058 plist = val + 1; 1059 plen = len - 1; 1060 } 1061 1062 /* Check whether the peer got the reconciliation right (6.6.8) */ 1063 if (dccp_feat_reconcile(&entry->val, plist, plen, server, 0) != *val) { 1064 DCCP_WARN("Confirm selected the wrong value %u\n", *val); 1065 return DCCP_RESET_CODE_OPTION_ERROR; 1066 } 1067 entry->val.sp.vec[0] = *val; 1068 1069confirmation_succeeded: 1070 entry->state = FEAT_STABLE; 1071 return 0; 1072 1073confirmation_failed: 1074 DCCP_WARN("Confirmation failed\n"); 1075 return is_mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR 1076 : DCCP_RESET_CODE_OPTION_ERROR; 1077} 1078 1079/** 1080 * dccp_feat_parse_options - Process Feature-Negotiation Options 1081 * @sk: for general use and used by the client during connection setup 1082 * @dreq: used by the server during connection setup 1083 * @mandatory: whether @opt was preceded by a Mandatory option 1084 * @opt: %DCCPO_CHANGE_L | %DCCPO_CHANGE_R | %DCCPO_CONFIRM_L | %DCCPO_CONFIRM_R 1085 * @feat: one of %dccp_feature_numbers 1086 * @val: value contents of @opt 1087 * @len: length of @val in bytes 1088 * Returns 0 on success, a Reset code for ending the connection otherwise. 1089 */ 1090int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq, 1091 u8 mandatory, u8 opt, u8 feat, u8 *val, u8 len) 1092{ 1093 struct dccp_sock *dp = dccp_sk(sk); 1094 struct list_head *fn = dreq ? &dreq->dreq_featneg : &dp->dccps_featneg; 1095 bool server = false; 1096 1097 switch (sk->sk_state) { 1098 /* 1099 * Negotiation during connection setup 1100 */ 1101 case DCCP_LISTEN: 1102 server = true; /* fall through */ 1103 case DCCP_REQUESTING: 1104 switch (opt) { 1105 case DCCPO_CHANGE_L: 1106 case DCCPO_CHANGE_R: 1107 return dccp_feat_change_recv(fn, mandatory, opt, feat, 1108 val, len, server); 1109 case DCCPO_CONFIRM_R: 1110 case DCCPO_CONFIRM_L: 1111 return dccp_feat_confirm_recv(fn, mandatory, opt, feat, 1112 val, len, server); 1113 } 1114 } 1115 return 0; /* ignore FN options in all other states */ 1116} 1117 1118int dccp_feat_init(struct sock *sk) 1119{ 1120 struct dccp_sock *dp = dccp_sk(sk); 1121 struct dccp_minisock *dmsk = dccp_msk(sk); 1122 int rc; 1123 1124 INIT_LIST_HEAD(&dmsk->dccpms_pending); /* XXX no longer used */ 1125 INIT_LIST_HEAD(&dmsk->dccpms_conf); /* XXX no longer used */ 1126 1127 /* Ack ratio */ 1128 rc = __feat_register_nn(&dp->dccps_featneg, DCCPF_ACK_RATIO, 0, 1129 dp->dccps_l_ack_ratio); 1130 return rc; 1131} 1132 1133EXPORT_SYMBOL_GPL(dccp_feat_init); 1134 1135int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) 1136{ 1137 struct dccp_sock *dp = dccp_sk(sk); 1138 struct dccp_feat_entry *cur, *next; 1139 int idx; 1140 dccp_feat_val *fvals[DCCP_FEAT_SUPPORTED_MAX][2] = { 1141 [0 ... DCCP_FEAT_SUPPORTED_MAX-1] = { NULL, NULL } 1142 }; 1143 1144 list_for_each_entry(cur, fn_list, node) { 1145 /* 1146 * An empty Confirm means that either an unknown feature type 1147 * or an invalid value was present. In the first case there is 1148 * nothing to activate, in the other the default value is used. 1149 */ 1150 if (cur->empty_confirm) 1151 continue; 1152 1153 idx = dccp_feat_index(cur->feat_num); 1154 if (idx < 0) { 1155 DCCP_BUG("Unknown feature %u", cur->feat_num); 1156 goto activation_failed; 1157 } 1158 if (cur->state != FEAT_STABLE) { 1159 DCCP_CRIT("Negotiation of %s %u failed in state %u", 1160 cur->is_local ? "local" : "remote", 1161 cur->feat_num, cur->state); 1162 goto activation_failed; 1163 } 1164 fvals[idx][cur->is_local] = &cur->val; 1165 } 1166 1167 /* 1168 * Activate in decreasing order of index, so that the CCIDs are always 1169 * activated as the last feature. This avoids the case where a CCID 1170 * relies on the initialisation of one or more features that it depends 1171 * on (e.g. Send NDP Count, Send Ack Vector, and Ack Ratio features). 1172 */ 1173 for (idx = DCCP_FEAT_SUPPORTED_MAX; --idx >= 0;) 1174 if (__dccp_feat_activate(sk, idx, 0, fvals[idx][0]) || 1175 __dccp_feat_activate(sk, idx, 1, fvals[idx][1])) { 1176 DCCP_CRIT("Could not activate %d", idx); 1177 goto activation_failed; 1178 } 1179 1180 /* Clean up Change options which have been confirmed already */ 1181 list_for_each_entry_safe(cur, next, fn_list, node) 1182 if (!cur->needs_confirm) 1183 dccp_feat_list_pop(cur); 1184 1185 dccp_pr_debug("Activation OK\n"); 1186 return 0; 1187 1188activation_failed: 1189 /* 1190 * We clean up everything that may have been allocated, since 1191 * it is difficult to track at which stage negotiation failed. 1192 * This is ok, since all allocation functions below are robust 1193 * against NULL arguments. 1194 */ 1195 ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); 1196 ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); 1197 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; 1198 dccp_ackvec_free(dp->dccps_hc_rx_ackvec); 1199 dp->dccps_hc_rx_ackvec = NULL; 1200 return -1; 1201} 1202 1203#ifdef CONFIG_IP_DCCP_DEBUG 1204const char *dccp_feat_typename(const u8 type) 1205{ 1206 switch(type) { 1207 case DCCPO_CHANGE_L: return("ChangeL"); 1208 case DCCPO_CONFIRM_L: return("ConfirmL"); 1209 case DCCPO_CHANGE_R: return("ChangeR"); 1210 case DCCPO_CONFIRM_R: return("ConfirmR"); 1211 /* the following case must not appear in feature negotation */ 1212 default: dccp_pr_debug("unknown type %d [BUG!]\n", type); 1213 } 1214 return NULL; 1215} 1216 1217const char *dccp_feat_name(const u8 feat) 1218{ 1219 static const char *feature_names[] = { 1220 [DCCPF_RESERVED] = "Reserved", 1221 [DCCPF_CCID] = "CCID", 1222 [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos", 1223 [DCCPF_SEQUENCE_WINDOW] = "Sequence Window", 1224 [DCCPF_ECN_INCAPABLE] = "ECN Incapable", 1225 [DCCPF_ACK_RATIO] = "Ack Ratio", 1226 [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector", 1227 [DCCPF_SEND_NDP_COUNT] = "Send NDP Count", 1228 [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage", 1229 [DCCPF_DATA_CHECKSUM] = "Send Data Checksum", 1230 }; 1231 if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC) 1232 return feature_names[DCCPF_RESERVED]; 1233 1234 if (feat == DCCPF_SEND_LEV_RATE) 1235 return "Send Loss Event Rate"; 1236 if (feat >= DCCPF_MIN_CCID_SPECIFIC) 1237 return "CCID-specific"; 1238 1239 return feature_names[feat]; 1240} 1241#endif /* CONFIG_IP_DCCP_DEBUG */