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 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 10 * 2 of the License, or (at your option) any later version. 11 */ 12 13 #include <linux/module.h> 14 15 #include "ccid.h" 16 #include "feat.h" 17 18 #define DCCP_FEAT_SP_NOAGREE (-123) 19 20 int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature, 21 u8 *val, u8 len, gfp_t gfp) 22 { 23 struct dccp_opt_pend *opt; 24 25 dccp_feat_debug(type, feature, *val); 26 27 if (!dccp_feat_is_valid_type(type)) { 28 DCCP_WARN("option type %d invalid in negotiation\n", type); 29 return 1; 30 } 31 if (!dccp_feat_is_valid_length(type, feature, len)) { 32 DCCP_WARN("invalid length %d\n", len); 33 return 1; 34 } 35 /* XXX add further sanity checks */ 36 37 /* check if that feature is already being negotiated */ 38 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { 39 /* ok we found a negotiation for this option already */ 40 if (opt->dccpop_feat == feature && opt->dccpop_type == type) { 41 dccp_pr_debug("Replacing old\n"); 42 /* replace */ 43 BUG_ON(opt->dccpop_val == NULL); 44 kfree(opt->dccpop_val); 45 opt->dccpop_val = val; 46 opt->dccpop_len = len; 47 opt->dccpop_conf = 0; 48 return 0; 49 } 50 } 51 52 /* negotiation for a new feature */ 53 opt = kmalloc(sizeof(*opt), gfp); 54 if (opt == NULL) 55 return -ENOMEM; 56 57 opt->dccpop_type = type; 58 opt->dccpop_feat = feature; 59 opt->dccpop_len = len; 60 opt->dccpop_val = val; 61 opt->dccpop_conf = 0; 62 opt->dccpop_sc = NULL; 63 64 BUG_ON(opt->dccpop_val == NULL); 65 66 list_add_tail(&opt->dccpop_node, &dmsk->dccpms_pending); 67 return 0; 68 } 69 70 EXPORT_SYMBOL_GPL(dccp_feat_change); 71 72 static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr) 73 { 74 struct dccp_sock *dp = dccp_sk(sk); 75 struct dccp_minisock *dmsk = dccp_msk(sk); 76 /* figure out if we are changing our CCID or the peer's */ 77 const int rx = type == DCCPO_CHANGE_R; 78 const u8 ccid_nr = rx ? dmsk->dccpms_rx_ccid : dmsk->dccpms_tx_ccid; 79 struct ccid *new_ccid; 80 81 /* Check if nothing is being changed. */ 82 if (ccid_nr == new_ccid_nr) 83 return 0; 84 85 new_ccid = ccid_new(new_ccid_nr, sk, rx, GFP_ATOMIC); 86 if (new_ccid == NULL) 87 return -ENOMEM; 88 89 if (rx) { 90 ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); 91 dp->dccps_hc_rx_ccid = new_ccid; 92 dmsk->dccpms_rx_ccid = new_ccid_nr; 93 } else { 94 ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); 95 dp->dccps_hc_tx_ccid = new_ccid; 96 dmsk->dccpms_tx_ccid = new_ccid_nr; 97 } 98 99 return 0; 100 } 101 102 /* XXX taking only u8 vals */ 103 static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val) 104 { 105 dccp_feat_debug(type, feat, val); 106 107 switch (feat) { 108 case DCCPF_CCID: 109 return dccp_feat_update_ccid(sk, type, val); 110 default: 111 dccp_pr_debug("UNIMPLEMENTED: %s(%d, ...)\n", 112 dccp_feat_typename(type), feat); 113 break; 114 } 115 return 0; 116 } 117 118 static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, 119 u8 *rpref, u8 rlen) 120 { 121 struct dccp_sock *dp = dccp_sk(sk); 122 u8 *spref, slen, *res = NULL; 123 int i, j, rc, agree = 1; 124 125 BUG_ON(rpref == NULL); 126 127 /* check if we are the black sheep */ 128 if (dp->dccps_role == DCCP_ROLE_CLIENT) { 129 spref = rpref; 130 slen = rlen; 131 rpref = opt->dccpop_val; 132 rlen = opt->dccpop_len; 133 } else { 134 spref = opt->dccpop_val; 135 slen = opt->dccpop_len; 136 } 137 /* 138 * Now we have server preference list in spref and client preference in 139 * rpref 140 */ 141 BUG_ON(spref == NULL); 142 BUG_ON(rpref == NULL); 143 144 /* FIXME sanity check vals */ 145 146 /* Are values in any order? XXX Lame "algorithm" here */ 147 /* XXX assume values are 1 byte */ 148 for (i = 0; i < slen; i++) { 149 for (j = 0; j < rlen; j++) { 150 if (spref[i] == rpref[j]) { 151 res = &spref[i]; 152 break; 153 } 154 } 155 if (res) 156 break; 157 } 158 159 /* we didn't agree on anything */ 160 if (res == NULL) { 161 /* confirm previous value */ 162 switch (opt->dccpop_feat) { 163 case DCCPF_CCID: 164 /* XXX did i get this right? =P */ 165 if (opt->dccpop_type == DCCPO_CHANGE_L) 166 res = &dccp_msk(sk)->dccpms_tx_ccid; 167 else 168 res = &dccp_msk(sk)->dccpms_rx_ccid; 169 break; 170 171 default: 172 DCCP_BUG("Fell through, feat=%d", opt->dccpop_feat); 173 /* XXX implement res */ 174 return -EFAULT; 175 } 176 177 dccp_pr_debug("Don't agree... reconfirming %d\n", *res); 178 agree = 0; /* this is used for mandatory options... */ 179 } 180 181 /* need to put result and our preference list */ 182 /* XXX assume 1 byte vals */ 183 rlen = 1 + opt->dccpop_len; 184 rpref = kmalloc(rlen, GFP_ATOMIC); 185 if (rpref == NULL) 186 return -ENOMEM; 187 188 *rpref = *res; 189 memcpy(&rpref[1], opt->dccpop_val, opt->dccpop_len); 190 191 /* put it in the "confirm queue" */ 192 if (opt->dccpop_sc == NULL) { 193 opt->dccpop_sc = kmalloc(sizeof(*opt->dccpop_sc), GFP_ATOMIC); 194 if (opt->dccpop_sc == NULL) { 195 kfree(rpref); 196 return -ENOMEM; 197 } 198 } else { 199 /* recycle the confirm slot */ 200 BUG_ON(opt->dccpop_sc->dccpoc_val == NULL); 201 kfree(opt->dccpop_sc->dccpoc_val); 202 dccp_pr_debug("recycling confirm slot\n"); 203 } 204 memset(opt->dccpop_sc, 0, sizeof(*opt->dccpop_sc)); 205 206 opt->dccpop_sc->dccpoc_val = rpref; 207 opt->dccpop_sc->dccpoc_len = rlen; 208 209 /* update the option on our side [we are about to send the confirm] */ 210 rc = dccp_feat_update(sk, opt->dccpop_type, opt->dccpop_feat, *res); 211 if (rc) { 212 kfree(opt->dccpop_sc->dccpoc_val); 213 kfree(opt->dccpop_sc); 214 opt->dccpop_sc = NULL; 215 return rc; 216 } 217 218 dccp_pr_debug("Will confirm %d\n", *rpref); 219 220 /* say we want to change to X but we just got a confirm X, suppress our 221 * change 222 */ 223 if (!opt->dccpop_conf) { 224 if (*opt->dccpop_val == *res) 225 opt->dccpop_conf = 1; 226 dccp_pr_debug("won't ask for change of same feature\n"); 227 } 228 229 return agree ? 0 : DCCP_FEAT_SP_NOAGREE; /* used for mandatory opts */ 230 } 231 232 static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) 233 { 234 struct dccp_minisock *dmsk = dccp_msk(sk); 235 struct dccp_opt_pend *opt; 236 int rc = 1; 237 u8 t; 238 239 /* 240 * We received a CHANGE. We gotta match it against our own preference 241 * list. If we got a CHANGE_R it means it's a change for us, so we need 242 * to compare our CHANGE_L list. 243 */ 244 if (type == DCCPO_CHANGE_L) 245 t = DCCPO_CHANGE_R; 246 else 247 t = DCCPO_CHANGE_L; 248 249 /* find our preference list for this feature */ 250 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { 251 if (opt->dccpop_type != t || opt->dccpop_feat != feature) 252 continue; 253 254 /* find the winner from the two preference lists */ 255 rc = dccp_feat_reconcile(sk, opt, val, len); 256 break; 257 } 258 259 /* We didn't deal with the change. This can happen if we have no 260 * preference list for the feature. In fact, it just shouldn't 261 * happen---if we understand a feature, we should have a preference list 262 * with at least the default value. 263 */ 264 BUG_ON(rc == 1); 265 266 return rc; 267 } 268 269 static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) 270 { 271 struct dccp_opt_pend *opt; 272 struct dccp_minisock *dmsk = dccp_msk(sk); 273 u8 *copy; 274 int rc; 275 276 /* NN features must be Change L (sec. 6.3.2) */ 277 if (type != DCCPO_CHANGE_L) { 278 dccp_pr_debug("received %s for NN feature %d\n", 279 dccp_feat_typename(type), feature); 280 return -EFAULT; 281 } 282 283 /* XXX sanity check opt val */ 284 285 /* copy option so we can confirm it */ 286 opt = kzalloc(sizeof(*opt), GFP_ATOMIC); 287 if (opt == NULL) 288 return -ENOMEM; 289 290 copy = kmemdup(val, len, GFP_ATOMIC); 291 if (copy == NULL) { 292 kfree(opt); 293 return -ENOMEM; 294 } 295 296 opt->dccpop_type = DCCPO_CONFIRM_R; /* NN can only confirm R */ 297 opt->dccpop_feat = feature; 298 opt->dccpop_val = copy; 299 opt->dccpop_len = len; 300 301 /* change feature */ 302 rc = dccp_feat_update(sk, type, feature, *val); 303 if (rc) { 304 kfree(opt->dccpop_val); 305 kfree(opt); 306 return rc; 307 } 308 309 dccp_feat_debug(type, feature, *copy); 310 311 list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf); 312 313 return 0; 314 } 315 316 static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk, 317 u8 type, u8 feature) 318 { 319 /* XXX check if other confirms for that are queued and recycle slot */ 320 struct dccp_opt_pend *opt = kzalloc(sizeof(*opt), GFP_ATOMIC); 321 322 if (opt == NULL) { 323 /* XXX what do we do? Ignoring should be fine. It's a change 324 * after all =P 325 */ 326 return; 327 } 328 329 switch (type) { 330 case DCCPO_CHANGE_L: opt->dccpop_type = DCCPO_CONFIRM_R; break; 331 case DCCPO_CHANGE_R: opt->dccpop_type = DCCPO_CONFIRM_L; break; 332 default: DCCP_WARN("invalid type %d\n", type); return; 333 334 } 335 opt->dccpop_feat = feature; 336 opt->dccpop_val = NULL; 337 opt->dccpop_len = 0; 338 339 /* change feature */ 340 dccp_pr_debug("Empty %s(%d)\n", dccp_feat_typename(type), feature); 341 342 list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf); 343 } 344 345 static void dccp_feat_flush_confirm(struct sock *sk) 346 { 347 struct dccp_minisock *dmsk = dccp_msk(sk); 348 /* Check if there is anything to confirm in the first place */ 349 int yes = !list_empty(&dmsk->dccpms_conf); 350 351 if (!yes) { 352 struct dccp_opt_pend *opt; 353 354 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { 355 if (opt->dccpop_conf) { 356 yes = 1; 357 break; 358 } 359 } 360 } 361 362 if (!yes) 363 return; 364 365 /* OK there is something to confirm... */ 366 /* XXX check if packet is in flight? Send delayed ack?? */ 367 if (sk->sk_state == DCCP_OPEN) 368 dccp_send_ack(sk); 369 } 370 371 int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) 372 { 373 int rc; 374 375 dccp_feat_debug(type, feature, *val); 376 377 /* figure out if it's SP or NN feature */ 378 switch (feature) { 379 /* deal with SP features */ 380 case DCCPF_CCID: 381 rc = dccp_feat_sp(sk, type, feature, val, len); 382 break; 383 384 /* deal with NN features */ 385 case DCCPF_ACK_RATIO: 386 rc = dccp_feat_nn(sk, type, feature, val, len); 387 break; 388 389 /* XXX implement other features */ 390 default: 391 dccp_pr_debug("UNIMPLEMENTED: not handling %s(%d, ...)\n", 392 dccp_feat_typename(type), feature); 393 rc = -EFAULT; 394 break; 395 } 396 397 /* check if there were problems changing features */ 398 if (rc) { 399 /* If we don't agree on SP, we sent a confirm for old value. 400 * However we propagate rc to caller in case option was 401 * mandatory 402 */ 403 if (rc != DCCP_FEAT_SP_NOAGREE) 404 dccp_feat_empty_confirm(dccp_msk(sk), type, feature); 405 } 406 407 /* generate the confirm [if required] */ 408 dccp_feat_flush_confirm(sk); 409 410 return rc; 411 } 412 413 EXPORT_SYMBOL_GPL(dccp_feat_change_recv); 414 415 int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, 416 u8 *val, u8 len) 417 { 418 u8 t; 419 struct dccp_opt_pend *opt; 420 struct dccp_minisock *dmsk = dccp_msk(sk); 421 int found = 0; 422 int all_confirmed = 1; 423 424 dccp_feat_debug(type, feature, *val); 425 426 /* locate our change request */ 427 switch (type) { 428 case DCCPO_CONFIRM_L: t = DCCPO_CHANGE_R; break; 429 case DCCPO_CONFIRM_R: t = DCCPO_CHANGE_L; break; 430 default: DCCP_WARN("invalid type %d\n", type); 431 return 1; 432 433 } 434 /* XXX sanity check feature value */ 435 436 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { 437 if (!opt->dccpop_conf && opt->dccpop_type == t && 438 opt->dccpop_feat == feature) { 439 found = 1; 440 dccp_pr_debug("feature %d found\n", opt->dccpop_feat); 441 442 /* XXX do sanity check */ 443 444 opt->dccpop_conf = 1; 445 446 /* We got a confirmation---change the option */ 447 dccp_feat_update(sk, opt->dccpop_type, 448 opt->dccpop_feat, *val); 449 450 /* XXX check the return value of dccp_feat_update */ 451 break; 452 } 453 454 if (!opt->dccpop_conf) 455 all_confirmed = 0; 456 } 457 458 /* fix re-transmit timer */ 459 /* XXX gotta make sure that no option negotiation occurs during 460 * connection shutdown. Consider that the CLOSEREQ is sent and timer is 461 * on. if all options are confirmed it might kill timer which should 462 * remain alive until close is received. 463 */ 464 if (all_confirmed) { 465 dccp_pr_debug("clear feat negotiation timer %p\n", sk); 466 inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); 467 } 468 469 if (!found) 470 dccp_pr_debug("%s(%d, ...) never requested\n", 471 dccp_feat_typename(type), feature); 472 return 0; 473 } 474 475 EXPORT_SYMBOL_GPL(dccp_feat_confirm_recv); 476 477 void dccp_feat_clean(struct dccp_minisock *dmsk) 478 { 479 struct dccp_opt_pend *opt, *next; 480 481 list_for_each_entry_safe(opt, next, &dmsk->dccpms_pending, 482 dccpop_node) { 483 BUG_ON(opt->dccpop_val == NULL); 484 kfree(opt->dccpop_val); 485 486 if (opt->dccpop_sc != NULL) { 487 BUG_ON(opt->dccpop_sc->dccpoc_val == NULL); 488 kfree(opt->dccpop_sc->dccpoc_val); 489 kfree(opt->dccpop_sc); 490 } 491 492 kfree(opt); 493 } 494 INIT_LIST_HEAD(&dmsk->dccpms_pending); 495 496 list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) { 497 BUG_ON(opt == NULL); 498 if (opt->dccpop_val != NULL) 499 kfree(opt->dccpop_val); 500 kfree(opt); 501 } 502 INIT_LIST_HEAD(&dmsk->dccpms_conf); 503 } 504 505 EXPORT_SYMBOL_GPL(dccp_feat_clean); 506 507 /* this is to be called only when a listening sock creates its child. It is 508 * assumed by the function---the confirm is not duplicated, but rather it is 509 * "passed on". 510 */ 511 int dccp_feat_clone(struct sock *oldsk, struct sock *newsk) 512 { 513 struct dccp_minisock *olddmsk = dccp_msk(oldsk); 514 struct dccp_minisock *newdmsk = dccp_msk(newsk); 515 struct dccp_opt_pend *opt; 516 int rc = 0; 517 518 INIT_LIST_HEAD(&newdmsk->dccpms_pending); 519 INIT_LIST_HEAD(&newdmsk->dccpms_conf); 520 521 list_for_each_entry(opt, &olddmsk->dccpms_pending, dccpop_node) { 522 struct dccp_opt_pend *newopt; 523 /* copy the value of the option */ 524 u8 *val = kmemdup(opt->dccpop_val, opt->dccpop_len, GFP_ATOMIC); 525 526 if (val == NULL) 527 goto out_clean; 528 529 newopt = kmemdup(opt, sizeof(*newopt), GFP_ATOMIC); 530 if (newopt == NULL) { 531 kfree(val); 532 goto out_clean; 533 } 534 535 /* insert the option */ 536 newopt->dccpop_val = val; 537 list_add_tail(&newopt->dccpop_node, &newdmsk->dccpms_pending); 538 539 /* XXX what happens with backlogs and multiple connections at 540 * once... 541 */ 542 /* the master socket no longer needs to worry about confirms */ 543 opt->dccpop_sc = NULL; /* it's not a memleak---new socket has it */ 544 545 /* reset state for a new socket */ 546 opt->dccpop_conf = 0; 547 } 548 549 /* XXX not doing anything about the conf queue */ 550 551 out: 552 return rc; 553 554 out_clean: 555 dccp_feat_clean(newdmsk); 556 rc = -ENOMEM; 557 goto out; 558 } 559 560 EXPORT_SYMBOL_GPL(dccp_feat_clone); 561 562 static int __dccp_feat_init(struct dccp_minisock *dmsk, u8 type, u8 feat, 563 u8 *val, u8 len) 564 { 565 int rc = -ENOMEM; 566 u8 *copy = kmemdup(val, len, GFP_KERNEL); 567 568 if (copy != NULL) { 569 rc = dccp_feat_change(dmsk, type, feat, copy, len, GFP_KERNEL); 570 if (rc) 571 kfree(copy); 572 } 573 return rc; 574 } 575 576 int dccp_feat_init(struct dccp_minisock *dmsk) 577 { 578 int rc; 579 580 INIT_LIST_HEAD(&dmsk->dccpms_pending); 581 INIT_LIST_HEAD(&dmsk->dccpms_conf); 582 583 /* CCID L */ 584 rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_L, DCCPF_CCID, 585 &dmsk->dccpms_tx_ccid, 1); 586 if (rc) 587 goto out; 588 589 /* CCID R */ 590 rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_R, DCCPF_CCID, 591 &dmsk->dccpms_rx_ccid, 1); 592 if (rc) 593 goto out; 594 595 /* Ack ratio */ 596 rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_L, DCCPF_ACK_RATIO, 597 &dmsk->dccpms_ack_ratio, 1); 598 out: 599 return rc; 600 } 601 602 EXPORT_SYMBOL_GPL(dccp_feat_init); 603 604 #ifdef CONFIG_IP_DCCP_DEBUG 605 const char *dccp_feat_typename(const u8 type) 606 { 607 switch(type) { 608 case DCCPO_CHANGE_L: return("ChangeL"); 609 case DCCPO_CONFIRM_L: return("ConfirmL"); 610 case DCCPO_CHANGE_R: return("ChangeR"); 611 case DCCPO_CONFIRM_R: return("ConfirmR"); 612 /* the following case must not appear in feature negotation */ 613 default: dccp_pr_debug("unknown type %d [BUG!]\n", type); 614 } 615 return NULL; 616 } 617 618 EXPORT_SYMBOL_GPL(dccp_feat_typename); 619 620 const char *dccp_feat_name(const u8 feat) 621 { 622 static const char *feature_names[] = { 623 [DCCPF_RESERVED] = "Reserved", 624 [DCCPF_CCID] = "CCID", 625 [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos", 626 [DCCPF_SEQUENCE_WINDOW] = "Sequence Window", 627 [DCCPF_ECN_INCAPABLE] = "ECN Incapable", 628 [DCCPF_ACK_RATIO] = "Ack Ratio", 629 [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector", 630 [DCCPF_SEND_NDP_COUNT] = "Send NDP Count", 631 [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage", 632 [DCCPF_DATA_CHECKSUM] = "Send Data Checksum", 633 }; 634 if (feat >= DCCPF_MIN_CCID_SPECIFIC) 635 return "CCID-specific"; 636 637 if (dccp_feat_is_reserved(feat)) 638 return feature_names[DCCPF_RESERVED]; 639 640 return feature_names[feat]; 641 } 642 643 EXPORT_SYMBOL_GPL(dccp_feat_name); 644 #endif /* CONFIG_IP_DCCP_DEBUG */ 645