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