1 /* 2 * net/dccp/feat.c 3 * 4 * An implementation of the DCCP protocol 5 * Andrea Bittau <a.bittau@cs.ucl.ac.uk> 6 * 7 * ASSUMPTIONS 8 * ----------- 9 * o All currently known SP features have 1-byte quantities. If in the future 10 * extensions of RFCs 4340..42 define features with item lengths larger than 11 * one byte, a feature-specific extension of the code will be required. 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License 15 * as published by the Free Software Foundation; either version 16 * 2 of the License, or (at your option) any later version. 17 */ 18 19 #include <linux/module.h> 20 21 #include "ccid.h" 22 #include "feat.h" 23 24 #define DCCP_FEAT_SP_NOAGREE (-123) 25 26 static const struct { 27 u8 feat_num; /* DCCPF_xxx */ 28 enum dccp_feat_type rxtx; /* RX or TX */ 29 enum dccp_feat_type reconciliation; /* SP or NN */ 30 u8 default_value; /* as in 6.4 */ 31 /* 32 * Lookup table for location and type of features (from RFC 4340/4342) 33 * +--------------------------+----+-----+----+----+---------+-----------+ 34 * | Feature | Location | Reconc. | Initial | Section | 35 * | | RX | TX | SP | NN | Value | Reference | 36 * +--------------------------+----+-----+----+----+---------+-----------+ 37 * | DCCPF_CCID | | X | X | | 2 | 10 | 38 * | DCCPF_SHORT_SEQNOS | | X | X | | 0 | 7.6.1 | 39 * | DCCPF_SEQUENCE_WINDOW | | X | | X | 100 | 7.5.2 | 40 * | DCCPF_ECN_INCAPABLE | X | | X | | 0 | 12.1 | 41 * | DCCPF_ACK_RATIO | | X | | X | 2 | 11.3 | 42 * | DCCPF_SEND_ACK_VECTOR | X | | X | | 0 | 11.5 | 43 * | DCCPF_SEND_NDP_COUNT | | X | X | | 0 | 7.7.2 | 44 * | DCCPF_MIN_CSUM_COVER | X | | X | | 0 | 9.2.1 | 45 * | DCCPF_DATA_CHECKSUM | X | | X | | 0 | 9.3.1 | 46 * | DCCPF_SEND_LEV_RATE | X | | X | | 0 | 4342/8.4 | 47 * +--------------------------+----+-----+----+----+---------+-----------+ 48 */ 49 } dccp_feat_table[] = { 50 { DCCPF_CCID, FEAT_AT_TX, FEAT_SP, 2 }, 51 { DCCPF_SHORT_SEQNOS, FEAT_AT_TX, FEAT_SP, 0 }, 52 { DCCPF_SEQUENCE_WINDOW, FEAT_AT_TX, FEAT_NN, 100 }, 53 { DCCPF_ECN_INCAPABLE, FEAT_AT_RX, FEAT_SP, 0 }, 54 { DCCPF_ACK_RATIO, FEAT_AT_TX, FEAT_NN, 2 }, 55 { DCCPF_SEND_ACK_VECTOR, FEAT_AT_RX, FEAT_SP, 0 }, 56 { DCCPF_SEND_NDP_COUNT, FEAT_AT_TX, FEAT_SP, 0 }, 57 { DCCPF_MIN_CSUM_COVER, FEAT_AT_RX, FEAT_SP, 0 }, 58 { DCCPF_DATA_CHECKSUM, FEAT_AT_RX, FEAT_SP, 0 }, 59 { DCCPF_SEND_LEV_RATE, FEAT_AT_RX, FEAT_SP, 0 }, 60 }; 61 #define DCCP_FEAT_SUPPORTED_MAX ARRAY_SIZE(dccp_feat_table) 62 63 /** 64 * dccp_feat_index - Hash function to map feature number into array position 65 * Returns consecutive array index or -1 if the feature is not understood. 66 */ 67 static int dccp_feat_index(u8 feat_num) 68 { 69 /* The first 9 entries are occupied by the types from RFC 4340, 6.4 */ 70 if (feat_num > DCCPF_RESERVED && feat_num <= DCCPF_DATA_CHECKSUM) 71 return feat_num - 1; 72 73 /* 74 * Other features: add cases for new feature types here after adding 75 * them to the above table. 76 */ 77 switch (feat_num) { 78 case DCCPF_SEND_LEV_RATE: 79 return DCCP_FEAT_SUPPORTED_MAX - 1; 80 } 81 return -1; 82 } 83 84 static u8 dccp_feat_type(u8 feat_num) 85 { 86 int idx = dccp_feat_index(feat_num); 87 88 if (idx < 0) 89 return FEAT_UNKNOWN; 90 return dccp_feat_table[idx].reconciliation; 91 } 92 93 /* copy constructor, fval must not already contain allocated memory */ 94 static int dccp_feat_clone_sp_val(dccp_feat_val *fval, u8 const *val, u8 len) 95 { 96 fval->sp.len = len; 97 if (fval->sp.len > 0) { 98 fval->sp.vec = kmemdup(val, len, gfp_any()); 99 if (fval->sp.vec == NULL) { 100 fval->sp.len = 0; 101 return -ENOBUFS; 102 } 103 } 104 return 0; 105 } 106 107 static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val) 108 { 109 if (unlikely(val == NULL)) 110 return; 111 if (dccp_feat_type(feat_num) == FEAT_SP) 112 kfree(val->sp.vec); 113 memset(val, 0, sizeof(*val)); 114 } 115 116 static struct dccp_feat_entry * 117 dccp_feat_clone_entry(struct dccp_feat_entry const *original) 118 { 119 struct dccp_feat_entry *new; 120 u8 type = dccp_feat_type(original->feat_num); 121 122 if (type == FEAT_UNKNOWN) 123 return NULL; 124 125 new = kmemdup(original, sizeof(struct dccp_feat_entry), gfp_any()); 126 if (new == NULL) 127 return NULL; 128 129 if (type == FEAT_SP && dccp_feat_clone_sp_val(&new->val, 130 original->val.sp.vec, 131 original->val.sp.len)) { 132 kfree(new); 133 return NULL; 134 } 135 return new; 136 } 137 138 static void dccp_feat_entry_destructor(struct dccp_feat_entry *entry) 139 { 140 if (entry != NULL) { 141 dccp_feat_val_destructor(entry->feat_num, &entry->val); 142 kfree(entry); 143 } 144 } 145 146 /* 147 * List management functions 148 * 149 * Feature negotiation lists rely on and maintain the following invariants: 150 * - each feat_num in the list is known, i.e. we know its type and default value 151 * - each feat_num/is_local combination is unique (old entries are overwritten) 152 * - SP values are always freshly allocated 153 * - list is sorted in increasing order of feature number (faster lookup) 154 */ 155 156 static inline void dccp_feat_list_pop(struct dccp_feat_entry *entry) 157 { 158 list_del(&entry->node); 159 dccp_feat_entry_destructor(entry); 160 } 161 162 void dccp_feat_list_purge(struct list_head *fn_list) 163 { 164 struct dccp_feat_entry *entry, *next; 165 166 list_for_each_entry_safe(entry, next, fn_list, node) 167 dccp_feat_entry_destructor(entry); 168 INIT_LIST_HEAD(fn_list); 169 } 170 EXPORT_SYMBOL_GPL(dccp_feat_list_purge); 171 172 /* generate @to as full clone of @from - @to must not contain any nodes */ 173 int dccp_feat_clone_list(struct list_head const *from, struct list_head *to) 174 { 175 struct dccp_feat_entry *entry, *new; 176 177 INIT_LIST_HEAD(to); 178 list_for_each_entry(entry, from, node) { 179 new = dccp_feat_clone_entry(entry); 180 if (new == NULL) 181 goto cloning_failed; 182 list_add_tail(&new->node, to); 183 } 184 return 0; 185 186 cloning_failed: 187 dccp_feat_list_purge(to); 188 return -ENOMEM; 189 } 190 191 int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature, 192 u8 *val, u8 len, gfp_t gfp) 193 { 194 struct dccp_opt_pend *opt; 195 196 dccp_feat_debug(type, feature, *val); 197 198 if (len > 3) { 199 DCCP_WARN("invalid length %d\n", len); 200 return -EINVAL; 201 } 202 /* XXX add further sanity checks */ 203 204 /* check if that feature is already being negotiated */ 205 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { 206 /* ok we found a negotiation for this option already */ 207 if (opt->dccpop_feat == feature && opt->dccpop_type == type) { 208 dccp_pr_debug("Replacing old\n"); 209 /* replace */ 210 BUG_ON(opt->dccpop_val == NULL); 211 kfree(opt->dccpop_val); 212 opt->dccpop_val = val; 213 opt->dccpop_len = len; 214 opt->dccpop_conf = 0; 215 return 0; 216 } 217 } 218 219 /* negotiation for a new feature */ 220 opt = kmalloc(sizeof(*opt), gfp); 221 if (opt == NULL) 222 return -ENOMEM; 223 224 opt->dccpop_type = type; 225 opt->dccpop_feat = feature; 226 opt->dccpop_len = len; 227 opt->dccpop_val = val; 228 opt->dccpop_conf = 0; 229 opt->dccpop_sc = NULL; 230 231 BUG_ON(opt->dccpop_val == NULL); 232 233 list_add_tail(&opt->dccpop_node, &dmsk->dccpms_pending); 234 return 0; 235 } 236 237 EXPORT_SYMBOL_GPL(dccp_feat_change); 238 239 static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr) 240 { 241 struct dccp_sock *dp = dccp_sk(sk); 242 struct dccp_minisock *dmsk = dccp_msk(sk); 243 /* figure out if we are changing our CCID or the peer's */ 244 const int rx = type == DCCPO_CHANGE_R; 245 const u8 ccid_nr = rx ? dmsk->dccpms_rx_ccid : dmsk->dccpms_tx_ccid; 246 struct ccid *new_ccid; 247 248 /* Check if nothing is being changed. */ 249 if (ccid_nr == new_ccid_nr) 250 return 0; 251 252 new_ccid = ccid_new(new_ccid_nr, sk, rx, GFP_ATOMIC); 253 if (new_ccid == NULL) 254 return -ENOMEM; 255 256 if (rx) { 257 ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); 258 dp->dccps_hc_rx_ccid = new_ccid; 259 dmsk->dccpms_rx_ccid = new_ccid_nr; 260 } else { 261 ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); 262 dp->dccps_hc_tx_ccid = new_ccid; 263 dmsk->dccpms_tx_ccid = new_ccid_nr; 264 } 265 266 return 0; 267 } 268 269 static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val) 270 { 271 dccp_feat_debug(type, feat, val); 272 273 switch (feat) { 274 case DCCPF_CCID: 275 return dccp_feat_update_ccid(sk, type, val); 276 default: 277 dccp_pr_debug("UNIMPLEMENTED: %s(%d, ...)\n", 278 dccp_feat_typename(type), feat); 279 break; 280 } 281 return 0; 282 } 283 284 static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, 285 u8 *rpref, u8 rlen) 286 { 287 struct dccp_sock *dp = dccp_sk(sk); 288 u8 *spref, slen, *res = NULL; 289 int i, j, rc, agree = 1; 290 291 BUG_ON(rpref == NULL); 292 293 /* check if we are the black sheep */ 294 if (dp->dccps_role == DCCP_ROLE_CLIENT) { 295 spref = rpref; 296 slen = rlen; 297 rpref = opt->dccpop_val; 298 rlen = opt->dccpop_len; 299 } else { 300 spref = opt->dccpop_val; 301 slen = opt->dccpop_len; 302 } 303 /* 304 * Now we have server preference list in spref and client preference in 305 * rpref 306 */ 307 BUG_ON(spref == NULL); 308 BUG_ON(rpref == NULL); 309 310 /* FIXME sanity check vals */ 311 312 /* Are values in any order? XXX Lame "algorithm" here */ 313 for (i = 0; i < slen; i++) { 314 for (j = 0; j < rlen; j++) { 315 if (spref[i] == rpref[j]) { 316 res = &spref[i]; 317 break; 318 } 319 } 320 if (res) 321 break; 322 } 323 324 /* we didn't agree on anything */ 325 if (res == NULL) { 326 /* confirm previous value */ 327 switch (opt->dccpop_feat) { 328 case DCCPF_CCID: 329 /* XXX did i get this right? =P */ 330 if (opt->dccpop_type == DCCPO_CHANGE_L) 331 res = &dccp_msk(sk)->dccpms_tx_ccid; 332 else 333 res = &dccp_msk(sk)->dccpms_rx_ccid; 334 break; 335 336 default: 337 DCCP_BUG("Fell through, feat=%d", opt->dccpop_feat); 338 /* XXX implement res */ 339 return -EFAULT; 340 } 341 342 dccp_pr_debug("Don't agree... reconfirming %d\n", *res); 343 agree = 0; /* this is used for mandatory options... */ 344 } 345 346 /* need to put result and our preference list */ 347 rlen = 1 + opt->dccpop_len; 348 rpref = kmalloc(rlen, GFP_ATOMIC); 349 if (rpref == NULL) 350 return -ENOMEM; 351 352 *rpref = *res; 353 memcpy(&rpref[1], opt->dccpop_val, opt->dccpop_len); 354 355 /* put it in the "confirm queue" */ 356 if (opt->dccpop_sc == NULL) { 357 opt->dccpop_sc = kmalloc(sizeof(*opt->dccpop_sc), GFP_ATOMIC); 358 if (opt->dccpop_sc == NULL) { 359 kfree(rpref); 360 return -ENOMEM; 361 } 362 } else { 363 /* recycle the confirm slot */ 364 BUG_ON(opt->dccpop_sc->dccpoc_val == NULL); 365 kfree(opt->dccpop_sc->dccpoc_val); 366 dccp_pr_debug("recycling confirm slot\n"); 367 } 368 memset(opt->dccpop_sc, 0, sizeof(*opt->dccpop_sc)); 369 370 opt->dccpop_sc->dccpoc_val = rpref; 371 opt->dccpop_sc->dccpoc_len = rlen; 372 373 /* update the option on our side [we are about to send the confirm] */ 374 rc = dccp_feat_update(sk, opt->dccpop_type, opt->dccpop_feat, *res); 375 if (rc) { 376 kfree(opt->dccpop_sc->dccpoc_val); 377 kfree(opt->dccpop_sc); 378 opt->dccpop_sc = NULL; 379 return rc; 380 } 381 382 dccp_pr_debug("Will confirm %d\n", *rpref); 383 384 /* say we want to change to X but we just got a confirm X, suppress our 385 * change 386 */ 387 if (!opt->dccpop_conf) { 388 if (*opt->dccpop_val == *res) 389 opt->dccpop_conf = 1; 390 dccp_pr_debug("won't ask for change of same feature\n"); 391 } 392 393 return agree ? 0 : DCCP_FEAT_SP_NOAGREE; /* used for mandatory opts */ 394 } 395 396 static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) 397 { 398 struct dccp_minisock *dmsk = dccp_msk(sk); 399 struct dccp_opt_pend *opt; 400 int rc = 1; 401 u8 t; 402 403 /* 404 * We received a CHANGE. We gotta match it against our own preference 405 * list. If we got a CHANGE_R it means it's a change for us, so we need 406 * to compare our CHANGE_L list. 407 */ 408 if (type == DCCPO_CHANGE_L) 409 t = DCCPO_CHANGE_R; 410 else 411 t = DCCPO_CHANGE_L; 412 413 /* find our preference list for this feature */ 414 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { 415 if (opt->dccpop_type != t || opt->dccpop_feat != feature) 416 continue; 417 418 /* find the winner from the two preference lists */ 419 rc = dccp_feat_reconcile(sk, opt, val, len); 420 break; 421 } 422 423 /* We didn't deal with the change. This can happen if we have no 424 * preference list for the feature. In fact, it just shouldn't 425 * happen---if we understand a feature, we should have a preference list 426 * with at least the default value. 427 */ 428 BUG_ON(rc == 1); 429 430 return rc; 431 } 432 433 static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) 434 { 435 struct dccp_opt_pend *opt; 436 struct dccp_minisock *dmsk = dccp_msk(sk); 437 u8 *copy; 438 int rc; 439 440 /* NN features must be Change L (sec. 6.3.2) */ 441 if (type != DCCPO_CHANGE_L) { 442 dccp_pr_debug("received %s for NN feature %d\n", 443 dccp_feat_typename(type), feature); 444 return -EFAULT; 445 } 446 447 /* XXX sanity check opt val */ 448 449 /* copy option so we can confirm it */ 450 opt = kzalloc(sizeof(*opt), GFP_ATOMIC); 451 if (opt == NULL) 452 return -ENOMEM; 453 454 copy = kmemdup(val, len, GFP_ATOMIC); 455 if (copy == NULL) { 456 kfree(opt); 457 return -ENOMEM; 458 } 459 460 opt->dccpop_type = DCCPO_CONFIRM_R; /* NN can only confirm R */ 461 opt->dccpop_feat = feature; 462 opt->dccpop_val = copy; 463 opt->dccpop_len = len; 464 465 /* change feature */ 466 rc = dccp_feat_update(sk, type, feature, *val); 467 if (rc) { 468 kfree(opt->dccpop_val); 469 kfree(opt); 470 return rc; 471 } 472 473 dccp_feat_debug(type, feature, *copy); 474 475 list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf); 476 477 return 0; 478 } 479 480 static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk, 481 u8 type, u8 feature) 482 { 483 /* XXX check if other confirms for that are queued and recycle slot */ 484 struct dccp_opt_pend *opt = kzalloc(sizeof(*opt), GFP_ATOMIC); 485 486 if (opt == NULL) { 487 /* XXX what do we do? Ignoring should be fine. It's a change 488 * after all =P 489 */ 490 return; 491 } 492 493 switch (type) { 494 case DCCPO_CHANGE_L: 495 opt->dccpop_type = DCCPO_CONFIRM_R; 496 break; 497 case DCCPO_CHANGE_R: 498 opt->dccpop_type = DCCPO_CONFIRM_L; 499 break; 500 default: 501 DCCP_WARN("invalid type %d\n", type); 502 kfree(opt); 503 return; 504 } 505 opt->dccpop_feat = feature; 506 opt->dccpop_val = NULL; 507 opt->dccpop_len = 0; 508 509 /* change feature */ 510 dccp_pr_debug("Empty %s(%d)\n", dccp_feat_typename(type), feature); 511 512 list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf); 513 } 514 515 static void dccp_feat_flush_confirm(struct sock *sk) 516 { 517 struct dccp_minisock *dmsk = dccp_msk(sk); 518 /* Check if there is anything to confirm in the first place */ 519 int yes = !list_empty(&dmsk->dccpms_conf); 520 521 if (!yes) { 522 struct dccp_opt_pend *opt; 523 524 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { 525 if (opt->dccpop_conf) { 526 yes = 1; 527 break; 528 } 529 } 530 } 531 532 if (!yes) 533 return; 534 535 /* OK there is something to confirm... */ 536 /* XXX check if packet is in flight? Send delayed ack?? */ 537 if (sk->sk_state == DCCP_OPEN) 538 dccp_send_ack(sk); 539 } 540 541 int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) 542 { 543 int rc; 544 545 dccp_feat_debug(type, feature, *val); 546 547 /* figure out if it's SP or NN feature */ 548 switch (feature) { 549 /* deal with SP features */ 550 case DCCPF_CCID: 551 rc = dccp_feat_sp(sk, type, feature, val, len); 552 break; 553 554 /* deal with NN features */ 555 case DCCPF_ACK_RATIO: 556 rc = dccp_feat_nn(sk, type, feature, val, len); 557 break; 558 559 /* XXX implement other features */ 560 default: 561 dccp_pr_debug("UNIMPLEMENTED: not handling %s(%d, ...)\n", 562 dccp_feat_typename(type), feature); 563 rc = -EFAULT; 564 break; 565 } 566 567 /* check if there were problems changing features */ 568 if (rc) { 569 /* If we don't agree on SP, we sent a confirm for old value. 570 * However we propagate rc to caller in case option was 571 * mandatory 572 */ 573 if (rc != DCCP_FEAT_SP_NOAGREE) 574 dccp_feat_empty_confirm(dccp_msk(sk), type, feature); 575 } 576 577 /* generate the confirm [if required] */ 578 dccp_feat_flush_confirm(sk); 579 580 return rc; 581 } 582 583 EXPORT_SYMBOL_GPL(dccp_feat_change_recv); 584 585 int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, 586 u8 *val, u8 len) 587 { 588 u8 t; 589 struct dccp_opt_pend *opt; 590 struct dccp_minisock *dmsk = dccp_msk(sk); 591 int found = 0; 592 int all_confirmed = 1; 593 594 dccp_feat_debug(type, feature, *val); 595 596 /* locate our change request */ 597 switch (type) { 598 case DCCPO_CONFIRM_L: t = DCCPO_CHANGE_R; break; 599 case DCCPO_CONFIRM_R: t = DCCPO_CHANGE_L; break; 600 default: DCCP_WARN("invalid type %d\n", type); 601 return 1; 602 603 } 604 /* XXX sanity check feature value */ 605 606 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { 607 if (!opt->dccpop_conf && opt->dccpop_type == t && 608 opt->dccpop_feat == feature) { 609 found = 1; 610 dccp_pr_debug("feature %d found\n", opt->dccpop_feat); 611 612 /* XXX do sanity check */ 613 614 opt->dccpop_conf = 1; 615 616 /* We got a confirmation---change the option */ 617 dccp_feat_update(sk, opt->dccpop_type, 618 opt->dccpop_feat, *val); 619 620 /* XXX check the return value of dccp_feat_update */ 621 break; 622 } 623 624 if (!opt->dccpop_conf) 625 all_confirmed = 0; 626 } 627 628 /* fix re-transmit timer */ 629 /* XXX gotta make sure that no option negotiation occurs during 630 * connection shutdown. Consider that the CLOSEREQ is sent and timer is 631 * on. if all options are confirmed it might kill timer which should 632 * remain alive until close is received. 633 */ 634 if (all_confirmed) { 635 dccp_pr_debug("clear feat negotiation timer %p\n", sk); 636 inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); 637 } 638 639 if (!found) 640 dccp_pr_debug("%s(%d, ...) never requested\n", 641 dccp_feat_typename(type), feature); 642 return 0; 643 } 644 645 EXPORT_SYMBOL_GPL(dccp_feat_confirm_recv); 646 647 void dccp_feat_clean(struct dccp_minisock *dmsk) 648 { 649 struct dccp_opt_pend *opt, *next; 650 651 list_for_each_entry_safe(opt, next, &dmsk->dccpms_pending, 652 dccpop_node) { 653 BUG_ON(opt->dccpop_val == NULL); 654 kfree(opt->dccpop_val); 655 656 if (opt->dccpop_sc != NULL) { 657 BUG_ON(opt->dccpop_sc->dccpoc_val == NULL); 658 kfree(opt->dccpop_sc->dccpoc_val); 659 kfree(opt->dccpop_sc); 660 } 661 662 kfree(opt); 663 } 664 INIT_LIST_HEAD(&dmsk->dccpms_pending); 665 666 list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) { 667 BUG_ON(opt == NULL); 668 if (opt->dccpop_val != NULL) 669 kfree(opt->dccpop_val); 670 kfree(opt); 671 } 672 INIT_LIST_HEAD(&dmsk->dccpms_conf); 673 } 674 675 EXPORT_SYMBOL_GPL(dccp_feat_clean); 676 677 /* this is to be called only when a listening sock creates its child. It is 678 * assumed by the function---the confirm is not duplicated, but rather it is 679 * "passed on". 680 */ 681 int dccp_feat_clone(struct sock *oldsk, struct sock *newsk) 682 { 683 struct dccp_minisock *olddmsk = dccp_msk(oldsk); 684 struct dccp_minisock *newdmsk = dccp_msk(newsk); 685 struct dccp_opt_pend *opt; 686 int rc = 0; 687 688 INIT_LIST_HEAD(&newdmsk->dccpms_pending); 689 INIT_LIST_HEAD(&newdmsk->dccpms_conf); 690 691 list_for_each_entry(opt, &olddmsk->dccpms_pending, dccpop_node) { 692 struct dccp_opt_pend *newopt; 693 /* copy the value of the option */ 694 u8 *val = kmemdup(opt->dccpop_val, opt->dccpop_len, GFP_ATOMIC); 695 696 if (val == NULL) 697 goto out_clean; 698 699 newopt = kmemdup(opt, sizeof(*newopt), GFP_ATOMIC); 700 if (newopt == NULL) { 701 kfree(val); 702 goto out_clean; 703 } 704 705 /* insert the option */ 706 newopt->dccpop_val = val; 707 list_add_tail(&newopt->dccpop_node, &newdmsk->dccpms_pending); 708 709 /* XXX what happens with backlogs and multiple connections at 710 * once... 711 */ 712 /* the master socket no longer needs to worry about confirms */ 713 opt->dccpop_sc = NULL; /* it's not a memleak---new socket has it */ 714 715 /* reset state for a new socket */ 716 opt->dccpop_conf = 0; 717 } 718 719 /* XXX not doing anything about the conf queue */ 720 721 out: 722 return rc; 723 724 out_clean: 725 dccp_feat_clean(newdmsk); 726 rc = -ENOMEM; 727 goto out; 728 } 729 730 EXPORT_SYMBOL_GPL(dccp_feat_clone); 731 732 static int __dccp_feat_init(struct dccp_minisock *dmsk, u8 type, u8 feat, 733 u8 *val, u8 len) 734 { 735 int rc = -ENOMEM; 736 u8 *copy = kmemdup(val, len, GFP_KERNEL); 737 738 if (copy != NULL) { 739 rc = dccp_feat_change(dmsk, type, feat, copy, len, GFP_KERNEL); 740 if (rc) 741 kfree(copy); 742 } 743 return rc; 744 } 745 746 int dccp_feat_init(struct dccp_minisock *dmsk) 747 { 748 int rc; 749 750 INIT_LIST_HEAD(&dmsk->dccpms_pending); 751 INIT_LIST_HEAD(&dmsk->dccpms_conf); 752 753 /* CCID L */ 754 rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_L, DCCPF_CCID, 755 &dmsk->dccpms_tx_ccid, 1); 756 if (rc) 757 goto out; 758 759 /* CCID R */ 760 rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_R, DCCPF_CCID, 761 &dmsk->dccpms_rx_ccid, 1); 762 if (rc) 763 goto out; 764 765 /* Ack ratio */ 766 rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_L, DCCPF_ACK_RATIO, 767 &dmsk->dccpms_ack_ratio, 1); 768 out: 769 return rc; 770 } 771 772 EXPORT_SYMBOL_GPL(dccp_feat_init); 773 774 #ifdef CONFIG_IP_DCCP_DEBUG 775 const char *dccp_feat_typename(const u8 type) 776 { 777 switch(type) { 778 case DCCPO_CHANGE_L: return("ChangeL"); 779 case DCCPO_CONFIRM_L: return("ConfirmL"); 780 case DCCPO_CHANGE_R: return("ChangeR"); 781 case DCCPO_CONFIRM_R: return("ConfirmR"); 782 /* the following case must not appear in feature negotation */ 783 default: dccp_pr_debug("unknown type %d [BUG!]\n", type); 784 } 785 return NULL; 786 } 787 788 EXPORT_SYMBOL_GPL(dccp_feat_typename); 789 790 const char *dccp_feat_name(const u8 feat) 791 { 792 static const char *feature_names[] = { 793 [DCCPF_RESERVED] = "Reserved", 794 [DCCPF_CCID] = "CCID", 795 [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos", 796 [DCCPF_SEQUENCE_WINDOW] = "Sequence Window", 797 [DCCPF_ECN_INCAPABLE] = "ECN Incapable", 798 [DCCPF_ACK_RATIO] = "Ack Ratio", 799 [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector", 800 [DCCPF_SEND_NDP_COUNT] = "Send NDP Count", 801 [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage", 802 [DCCPF_DATA_CHECKSUM] = "Send Data Checksum", 803 }; 804 if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC) 805 return feature_names[DCCPF_RESERVED]; 806 807 if (feat == DCCPF_SEND_LEV_RATE) 808 return "Send Loss Event Rate"; 809 if (feat >= DCCPF_MIN_CCID_SPECIFIC) 810 return "CCID-specific"; 811 812 return feature_names[feat]; 813 } 814 815 EXPORT_SYMBOL_GPL(dccp_feat_name); 816 #endif /* CONFIG_IP_DCCP_DEBUG */ 817