1 /* 2 * Redistribution and use in source and binary forms, with or without 3 * modification, are permitted provided that: (1) source code 4 * distributions retain the above copyright notice and this paragraph 5 * in its entirety, and (2) distributions including binary code include 6 * the above copyright notice and this paragraph in its entirety in 7 * the documentation or other materials provided with the distribution. 8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 11 * FOR A PARTICULAR PURPOSE. 12 * 13 * Copyright (c) 2009 Mojatatu Networks, Inc 14 * 15 */ 16 17 #ifdef HAVE_CONFIG_H 18 #include "config.h" 19 #endif 20 21 #include <tcpdump-stdinc.h> 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 26 #include "interface.h" 27 #include "extract.h" 28 29 #include "forces.h" 30 31 #define RESLEN 4 32 33 int 34 prestlv_print(register const u_char * pptr, register u_int len, 35 u_int16_t op_msk _U_, int indent) 36 { 37 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 38 register const u_char *tdp = (u_char *) TLV_DATA(tlv); 39 struct res_val *r = (struct res_val *)tdp; 40 u_int dlen; 41 42 /* 43 * pdatacnt_print() has ensured that len (the TLV length) 44 * >= TLV_HDRL. 45 */ 46 dlen = len - TLV_HDRL; 47 if (dlen != RESLEN) { 48 printf("illegal RESULT-TLV: %d bytes!\n", dlen); 49 return -1; 50 } 51 52 TCHECK(*r); 53 if (r->result >= 0x18 && r->result <= 0xFE) { 54 printf("illegal reserved result code: 0x%x!\n", r->result); 55 return -1; 56 } 57 58 if (vflag >= 3) { 59 char *ib = indent_pr(indent, 0); 60 printf("%s Result: %s (code 0x%x)\n", ib, 61 tok2str(ForCES_errs, NULL, r->result), r->result); 62 } 63 return 0; 64 65 trunc: 66 fputs("[|forces]", stdout); 67 return -1; 68 } 69 70 int 71 fdatatlv_print(register const u_char * pptr, register u_int len, 72 u_int16_t op_msk _U_, int indent) 73 { 74 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 75 u_int rlen; 76 register const u_char *tdp = (u_char *) TLV_DATA(tlv); 77 u_int16_t type; 78 79 /* 80 * pdatacnt_print() or pkeyitlv_print() has ensured that len 81 * (the TLV length) >= TLV_HDRL. 82 */ 83 rlen = len - TLV_HDRL; 84 TCHECK(*tlv); 85 type = EXTRACT_16BITS(&tlv->type); 86 if (type != F_TLV_FULD) { 87 printf("Error: expecting FULLDATA!\n"); 88 return -1; 89 } 90 91 if (vflag >= 3) { 92 char *ib = indent_pr(indent + 2, 1); 93 printf("%s[", &ib[1]); 94 hex_print_with_offset(ib, tdp, rlen, 0); 95 printf("\n%s]\n", &ib[1]); 96 } 97 return 0; 98 99 trunc: 100 fputs("[|forces]", stdout); 101 return -1; 102 } 103 104 int 105 sdatailv_print(register const u_char * pptr, register u_int len, 106 u_int16_t op_msk _U_, int indent) 107 { 108 u_int rlen; 109 const struct forces_ilv *ilv = (struct forces_ilv *)pptr; 110 int invilv; 111 112 if (len < ILV_HDRL) { 113 printf("Error: BAD SPARSEDATA-TLV!\n"); 114 return -1; 115 } 116 rlen = len; 117 indent += 1; 118 while (rlen != 0) { 119 char *ib = indent_pr(indent, 1); 120 register const u_char *tdp = (u_char *) ILV_DATA(ilv); 121 TCHECK(*ilv); 122 invilv = ilv_valid(ilv, rlen); 123 if (invilv) { 124 printf("%s[", &ib[1]); 125 hex_print_with_offset(ib, tdp, rlen, 0); 126 printf("\n%s]\n", &ib[1]); 127 return -1; 128 } 129 if (vflag >= 3) { 130 int ilvl = EXTRACT_32BITS(&ilv->length); 131 printf("\n%s ILV: type %x length %d\n", &ib[1], 132 EXTRACT_32BITS(&ilv->type), ilvl); 133 hex_print_with_offset("\t\t[", tdp, ilvl-ILV_HDRL, 0); 134 } 135 136 ilv = GO_NXT_ILV(ilv, rlen); 137 } 138 139 return 0; 140 141 trunc: 142 fputs("[|forces]", stdout); 143 return -1; 144 } 145 146 int 147 sdatatlv_print(register const u_char * pptr, register u_int len, 148 u_int16_t op_msk, int indent) 149 { 150 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 151 u_int rlen; 152 register const u_char *tdp = (u_char *) TLV_DATA(tlv); 153 u_int16_t type; 154 155 /* 156 * pdatacnt_print() has ensured that len (the TLV length) 157 * >= TLV_HDRL. 158 */ 159 rlen = len - TLV_HDRL; 160 TCHECK(*tlv); 161 type = EXTRACT_16BITS(&tlv->type); 162 if (type != F_TLV_SPAD) { 163 printf("Error: expecting SPARSEDATA!\n"); 164 return -1; 165 } 166 167 return sdatailv_print(tdp, rlen, op_msk, indent); 168 169 trunc: 170 fputs("[|forces]", stdout); 171 return -1; 172 } 173 174 int 175 pkeyitlv_print(register const u_char * pptr, register u_int len, 176 u_int16_t op_msk, int indent) 177 { 178 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 179 register const u_char *tdp = (u_char *) TLV_DATA(tlv); 180 register const u_char *dp = tdp + 4; 181 const struct forces_tlv *kdtlv = (struct forces_tlv *)dp; 182 u_int32_t id; 183 char *ib = indent_pr(indent, 0); 184 u_int16_t type, tll; 185 int invtlv; 186 187 TCHECK(*tdp); 188 id = EXTRACT_32BITS(tdp); 189 printf("%sKeyinfo: Key 0x%x\n", ib, id); 190 TCHECK(*kdtlv); 191 type = EXTRACT_16BITS(&kdtlv->type); 192 invtlv = tlv_valid(kdtlv, len); 193 194 if (invtlv) { 195 printf("%s TLV type 0x%x len %d\n", 196 tok2str(ForCES_TLV_err, NULL, invtlv), type, 197 EXTRACT_16BITS(&kdtlv->length)); 198 return -1; 199 } 200 /* 201 * At this point, tlv_valid() has ensured that the TLV 202 * length is large enough but not too large (it doesn't 203 * go past the end of the containing TLV). 204 */ 205 tll = EXTRACT_16BITS(&kdtlv->length); 206 dp = (u_char *) TLV_DATA(kdtlv); 207 return fdatatlv_print(dp, tll, op_msk, indent); 208 209 trunc: 210 fputs("[|forces]", stdout); 211 return -1; 212 } 213 214 int 215 pdatacnt_print(register const u_char * pptr, register u_int len, 216 u_int16_t IDcnt, u_int16_t op_msk, int indent) 217 { 218 u_int i; 219 u_int32_t id; 220 char *ib = indent_pr(indent, 0); 221 222 for (i = 0; i < IDcnt; i++) { 223 TCHECK2(*pptr, 4); 224 if (len < 4) 225 goto trunc; 226 id = EXTRACT_32BITS(pptr); 227 if (vflag >= 3) 228 printf("%s ID#%02u: %d\n", ib, i + 1, id); 229 len -= 4; 230 pptr += 4; 231 } 232 if (len) { 233 const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; 234 u_int16_t type; 235 u_int16_t tll; 236 int pad = 0; 237 u_int aln; 238 int invtlv; 239 240 TCHECK(*pdtlv); 241 type = EXTRACT_16BITS(&pdtlv->type); 242 invtlv = tlv_valid(pdtlv, len); 243 if (invtlv) { 244 printf 245 ("%s Outstanding bytes %d for TLV type 0x%x TLV len %d\n", 246 tok2str(ForCES_TLV_err, NULL, invtlv), len, type, 247 EXTRACT_16BITS(&pdtlv->length)); 248 goto pd_err; 249 } 250 /* 251 * At this point, tlv_valid() has ensured that the TLV 252 * length is large enough but not too large (it doesn't 253 * go past the end of the containing TLV). 254 */ 255 tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; 256 aln = F_ALN_LEN(EXTRACT_16BITS(&pdtlv->length)); 257 if (aln > EXTRACT_16BITS(&pdtlv->length)) { 258 if (aln > len) { 259 printf 260 ("Invalid padded pathdata TLV type 0x%x len %d missing %d pad bytes\n", 261 type, EXTRACT_16BITS(&pdtlv->length), aln - len); 262 } else { 263 pad = aln - EXTRACT_16BITS(&pdtlv->length); 264 } 265 } 266 if (pd_valid(type)) { 267 const struct pdata_ops *ops = get_forces_pd(type); 268 269 if (vflag >= 3 && ops->v != F_TLV_PDAT) { 270 if (pad) 271 printf 272 ("%s %s (Length %d DataLen %d pad %d Bytes)\n", 273 ib, ops->s, EXTRACT_16BITS(&pdtlv->length), 274 tll, pad); 275 else 276 printf 277 ("%s %s (Length %d DataLen %d Bytes)\n", 278 ib, ops->s, EXTRACT_16BITS(&pdtlv->length), 279 tll); 280 } 281 282 chk_op_type(type, op_msk, ops->op_msk); 283 284 if (ops->print((const u_char *)pdtlv, 285 tll + pad + TLV_HDRL, op_msk, 286 indent + 2) == -1) 287 return -1; 288 len -= (TLV_HDRL + pad + tll); 289 } else { 290 printf("Invalid path data content type 0x%x len %d\n", 291 type, EXTRACT_16BITS(&pdtlv->length)); 292 pd_err: 293 if (EXTRACT_16BITS(&pdtlv->length)) { 294 hex_print_with_offset("Bad Data val\n\t [", 295 pptr, len, 0); 296 printf("]\n"); 297 298 return -1; 299 } 300 } 301 } 302 return len; 303 304 trunc: 305 fputs("[|forces]", stdout); 306 return -1; 307 } 308 309 int 310 pdata_print(register const u_char * pptr, register u_int len, 311 u_int16_t op_msk, int indent) 312 { 313 const struct pathdata_h *pdh = (struct pathdata_h *)pptr; 314 char *ib = indent_pr(indent, 0); 315 u_int minsize = 0; 316 int more_pd = 0; 317 u_int16_t idcnt = 0; 318 319 TCHECK(*pdh); 320 if (len < sizeof(struct pathdata_h)) 321 goto trunc; 322 if (vflag >= 3) { 323 printf("\n%sPathdata: Flags 0x%x ID count %d\n", 324 ib, EXTRACT_16BITS(&pdh->pflags), EXTRACT_16BITS(&pdh->pIDcnt)); 325 } 326 327 if (EXTRACT_16BITS(&pdh->pflags) & F_SELKEY) { 328 op_msk |= B_KEYIN; 329 } 330 pptr += sizeof(struct pathdata_h); 331 len -= sizeof(struct pathdata_h); 332 idcnt = EXTRACT_16BITS(&pdh->pIDcnt); 333 minsize = idcnt * 4; 334 if (len < minsize) { 335 printf("\t\t\ttruncated IDs expected %uB got %uB\n", minsize, 336 len); 337 hex_print_with_offset("\t\t\tID Data[", pptr, len, 0); 338 printf("]\n"); 339 return -1; 340 } 341 more_pd = pdatacnt_print(pptr, len, idcnt, op_msk, indent); 342 if (more_pd > 0) { 343 int consumed = len - more_pd; 344 pptr += consumed; 345 len = more_pd; 346 /* XXX: Argh, recurse some more */ 347 return recpdoptlv_print(pptr, len, op_msk, indent+1); 348 } else 349 return 0; 350 351 trunc: 352 fputs("[|forces]", stdout); 353 return -1; 354 } 355 356 int 357 genoptlv_print(register const u_char * pptr, register u_int len, 358 u_int16_t op_msk, int indent) 359 { 360 const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; 361 u_int16_t type; 362 int tll; 363 int invtlv; 364 char *ib = indent_pr(indent, 0); 365 366 TCHECK(*pdtlv); 367 type = EXTRACT_16BITS(&pdtlv->type); 368 tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; 369 invtlv = tlv_valid(pdtlv, len); 370 printf("genoptlvprint - %s TLV type 0x%x len %d\n", 371 tok2str(ForCES_TLV, NULL, type), type, EXTRACT_16BITS(&pdtlv->length)); 372 if (!invtlv) { 373 /* 374 * At this point, tlv_valid() has ensured that the TLV 375 * length is large enough but not too large (it doesn't 376 * go past the end of the containing TLV). 377 */ 378 register const u_char *dp = (u_char *) TLV_DATA(pdtlv); 379 if (!ttlv_valid(type)) { 380 printf("%s TLV type 0x%x len %d\n", 381 tok2str(ForCES_TLV_err, NULL, invtlv), type, 382 EXTRACT_16BITS(&pdtlv->length)); 383 return -1; 384 } 385 if (vflag >= 3) 386 printf("%s%s, length %d (data length %d Bytes)", 387 ib, tok2str(ForCES_TLV, NULL, type), 388 EXTRACT_16BITS(&pdtlv->length), tll); 389 390 return pdata_print(dp, tll, op_msk, indent + 1); 391 } else { 392 printf("\t\t\tInvalid ForCES TLV type=%x", type); 393 return -1; 394 } 395 396 trunc: 397 fputs("[|forces]", stdout); 398 return -1; 399 } 400 401 int 402 recpdoptlv_print(register const u_char * pptr, register u_int len, 403 u_int16_t op_msk, int indent) 404 { 405 const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; 406 int tll; 407 int invtlv; 408 u_int16_t type; 409 register const u_char *dp; 410 char *ib; 411 412 while (len != 0) { 413 TCHECK(*pdtlv); 414 invtlv = tlv_valid(pdtlv, len); 415 if (invtlv) { 416 break; 417 } 418 419 /* 420 * At this point, tlv_valid() has ensured that the TLV 421 * length is large enough but not too large (it doesn't 422 * go past the end of the containing TLV). 423 */ 424 ib = indent_pr(indent, 0); 425 type = EXTRACT_16BITS(&pdtlv->type); 426 dp = (u_char *) TLV_DATA(pdtlv); 427 tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; 428 429 if (vflag >= 3) 430 printf 431 ("%s%s, length %d (data encapsulated %d Bytes)", 432 ib, tok2str(ForCES_TLV, NULL, type), 433 EXTRACT_16BITS(&pdtlv->length), 434 EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL); 435 436 if (pdata_print(dp, tll, op_msk, indent + 1) == -1) 437 return -1; 438 pdtlv = GO_NXT_TLV(pdtlv, len); 439 } 440 441 if (len) { 442 printf 443 ("\n\t\tMessy PATHDATA TLV header, type (0x%x)\n\t\texcess of %d Bytes ", 444 EXTRACT_16BITS(&pdtlv->type), len - EXTRACT_16BITS(&pdtlv->length)); 445 return -1; 446 } 447 448 return 0; 449 450 trunc: 451 fputs("[|forces]", stdout); 452 return -1; 453 } 454 455 int 456 invoptlv_print(register const u_char * pptr, register u_int len, 457 u_int16_t op_msk _U_, int indent) 458 { 459 char *ib = indent_pr(indent, 1); 460 461 if (vflag >= 3) { 462 printf("%sData[", &ib[1]); 463 hex_print_with_offset(ib, pptr, len, 0); 464 printf("%s]\n", ib); 465 } 466 return -1; 467 } 468 469 int otlv_print(const struct forces_tlv *otlv, u_int16_t op_msk _U_, int indent) 470 { 471 int rc = 0; 472 register const u_char *dp = (u_char *) TLV_DATA(otlv); 473 u_int16_t type; 474 int tll; 475 char *ib = indent_pr(indent, 0); 476 const struct optlv_h *ops; 477 478 /* 479 * lfbselect_print() has ensured that EXTRACT_16BITS(&otlv->length) 480 * >= TLV_HDRL. 481 */ 482 TCHECK(*otlv); 483 type = EXTRACT_16BITS(&otlv->type); 484 tll = EXTRACT_16BITS(&otlv->length) - TLV_HDRL; 485 ops = get_forces_optlv_h(type); 486 if (vflag >= 3) { 487 printf("%sOper TLV %s(0x%x) length %d\n", ib, ops->s, type, 488 EXTRACT_16BITS(&otlv->length)); 489 } 490 /* empty TLVs like COMMIT and TRCOMMIT are empty, we stop here .. */ 491 if (!ops->flags & ZERO_TTLV) { 492 if (tll != 0) /* instead of "if (tll)" - for readability .. */ 493 printf("%s: Illegal - MUST be empty\n", ops->s); 494 return rc; 495 } 496 /* rest of ops must at least have 12B {pathinfo} */ 497 if (tll < OP_MIN_SIZ) { 498 printf("\t\tOper TLV %s(0x%x) length %d\n", ops->s, type, 499 EXTRACT_16BITS(&otlv->length)); 500 printf("\t\tTruncated data size %d minimum required %d\n", tll, 501 OP_MIN_SIZ); 502 return invoptlv_print(dp, tll, ops->op_msk, indent); 503 504 } 505 506 rc = ops->print(dp, tll, ops->op_msk, indent + 1); 507 return rc; 508 509 trunc: 510 fputs("[|forces]", stdout); 511 return -1; 512 } 513 514 #define ASTDLN 4 515 #define ASTMCD 255 516 int 517 asttlv_print(register const u_char * pptr, register u_int len, 518 u_int16_t op_msk _U_, int indent) 519 { 520 u_int32_t rescode; 521 u_int dlen; 522 char *ib = indent_pr(indent, 0); 523 524 /* 525 * forces_type_print() has ensured that len (the TLV length) 526 * >= TLV_HDRL. 527 */ 528 dlen = len - TLV_HDRL; 529 if (dlen != ASTDLN) { 530 printf("illegal ASTresult-TLV: %d bytes!\n", dlen); 531 return -1; 532 } 533 TCHECK2(*pptr, 4); 534 rescode = EXTRACT_32BITS(pptr); 535 if (rescode > ASTMCD) { 536 printf("illegal ASTresult result code: %d!\n", rescode); 537 return -1; 538 } 539 540 if (vflag >= 3) { 541 printf("Teardown reason:\n%s", ib); 542 switch (rescode) { 543 case 0: 544 printf("Normal Teardown"); 545 break; 546 case 1: 547 printf("Loss of Heartbeats"); 548 break; 549 case 2: 550 printf("Out of bandwidth"); 551 break; 552 case 3: 553 printf("Out of Memory"); 554 break; 555 case 4: 556 printf("Application Crash"); 557 break; 558 default: 559 printf("Unknown Teardown reason"); 560 break; 561 } 562 printf("(%x)\n%s", rescode, ib); 563 } 564 return 0; 565 566 trunc: 567 fputs("[|forces]", stdout); 568 return -1; 569 } 570 571 #define ASRDLN 4 572 #define ASRMCD 3 573 int 574 asrtlv_print(register const u_char * pptr, register u_int len, 575 u_int16_t op_msk _U_, int indent) 576 { 577 u_int32_t rescode; 578 u_int dlen; 579 char *ib = indent_pr(indent, 0); 580 581 /* 582 * forces_type_print() has ensured that len (the TLV length) 583 * >= TLV_HDRL. 584 */ 585 dlen = len - TLV_HDRL; 586 if (dlen != ASRDLN) { /* id, instance, oper tlv */ 587 printf("illegal ASRresult-TLV: %d bytes!\n", dlen); 588 return -1; 589 } 590 TCHECK2(*pptr, 4); 591 rescode = EXTRACT_32BITS(pptr); 592 593 if (rescode > ASRMCD) { 594 printf("illegal ASRresult result code: %d!\n", rescode); 595 return -1; 596 } 597 598 if (vflag >= 3) { 599 printf("\n%s", ib); 600 switch (rescode) { 601 case 0: 602 printf("Success "); 603 break; 604 case 1: 605 printf("FE ID invalid "); 606 break; 607 case 2: 608 printf("permission denied "); 609 break; 610 default: 611 printf("Unknown "); 612 break; 613 } 614 printf("(%x)\n%s", rescode, ib); 615 } 616 return 0; 617 618 trunc: 619 fputs("[|forces]", stdout); 620 return -1; 621 } 622 623 /* 624 * XXX - not used. 625 */ 626 int 627 gentltlv_print(register const u_char * pptr _U_, register u_int len, 628 u_int16_t op_msk _U_, int indent _U_) 629 { 630 u_int dlen = len - TLV_HDRL; 631 632 if (dlen < 4) { /* at least 32 bits must exist */ 633 printf("truncated TLV: %d bytes missing! ", 4 - dlen); 634 return -1; 635 } 636 return 0; 637 } 638 639 #define RD_MIN 8 640 int 641 print_metailv(register const u_char * pptr, register u_int len, 642 u_int16_t op_msk _U_, int indent) 643 { 644 u_int dlen; 645 u_int rlen; 646 char *ib = indent_pr(indent, 0); 647 /* XXX: check header length */ 648 const struct forces_ilv *ilv = (struct forces_ilv *)pptr; 649 650 /* 651 * print_metatlv() has ensured that len (what remains in the 652 * ILV) >= ILV_HDRL. 653 */ 654 dlen = len - ILV_HDRL; 655 rlen = dlen; 656 TCHECK(*ilv); 657 printf("\n%sMetaID 0x%x length %d\n", ib, EXTRACT_32BITS(&ilv->type), 658 EXTRACT_32BITS(&ilv->length)); 659 hex_print_with_offset("\n\t\t\t\t[", ILV_DATA(ilv), rlen, 0); 660 return 0; 661 662 trunc: 663 fputs("[|forces]", stdout); 664 return -1; 665 } 666 667 int 668 print_metatlv(register const u_char * pptr, register u_int len, 669 u_int16_t op_msk _U_, int indent) 670 { 671 u_int dlen; 672 char *ib = indent_pr(indent, 0); 673 u_int rlen; 674 const struct forces_ilv *ilv = (struct forces_ilv *)pptr; 675 int invilv; 676 677 /* 678 * redirect_print() has ensured that len (what remains in the 679 * TLV) >= TLV_HDRL. 680 */ 681 dlen = len - TLV_HDRL; 682 rlen = dlen; 683 printf("\n%s METADATA\n", ib); 684 while (rlen != 0) { 685 TCHECK(*ilv); 686 invilv = ilv_valid(ilv, rlen); 687 if (invilv) 688 break; 689 690 /* 691 * At this point, ilv_valid() has ensured that the ILV 692 * length is large enough but not too large (it doesn't 693 * go past the end of the containing TLV). 694 */ 695 print_metailv((u_char *) ilv, rlen, 0, indent + 1); 696 697 ilv = GO_NXT_ILV(ilv, rlen); 698 } 699 700 return 0; 701 702 trunc: 703 fputs("[|forces]", stdout); 704 return -1; 705 } 706 707 /* 708 */ 709 int 710 print_reddata(register const u_char * pptr, register u_int len, 711 u_int16_t op_msk _U_, int indent _U_) 712 { 713 u_int dlen; 714 u_int rlen; 715 int invtlv; 716 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 717 718 /* 719 * redirect_print() has ensured that len (what remains in the 720 * TLV) >= TLV_HDRL. 721 */ 722 dlen = len - TLV_HDRL; 723 printf("\n\t\t Redirect DATA\n"); 724 if (dlen <= RD_MIN) { 725 printf("\n\t\ttruncated Redirect data: %d bytes missing! ", 726 RD_MIN - dlen); 727 return -1; 728 } 729 730 rlen = dlen; 731 TCHECK(*tlv); 732 invtlv = tlv_valid(tlv, rlen); 733 734 if (invtlv) { 735 printf("Redir data type 0x%x len %d\n", EXTRACT_16BITS(&tlv->type), 736 EXTRACT_16BITS(&tlv->length)); 737 return -1; 738 } 739 740 /* 741 * At this point, tlv_valid() has ensured that the TLV 742 * length is large enough but not too large (it doesn't 743 * go past the end of the containing TLV). 744 */ 745 rlen -= TLV_HDRL; 746 hex_print_with_offset("\n\t\t\t[", TLV_DATA(tlv), rlen, 0); 747 return 0; 748 749 trunc: 750 fputs("[|forces]", stdout); 751 return -1; 752 } 753 754 int 755 redirect_print(register const u_char * pptr, register u_int len, 756 u_int16_t op_msk _U_, int indent) 757 { 758 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 759 u_int dlen; 760 u_int rlen; 761 int invtlv; 762 763 /* 764 * forces_type_print() has ensured that len (the TLV length) 765 * >= TLV_HDRL. 766 */ 767 dlen = len - TLV_HDRL; 768 if (dlen <= RD_MIN) { 769 printf("\n\t\ttruncated Redirect TLV: %d bytes missing! ", 770 RD_MIN - dlen); 771 return -1; 772 } 773 774 rlen = dlen; 775 indent += 1; 776 while (rlen != 0) { 777 TCHECK(*tlv); 778 invtlv = tlv_valid(tlv, rlen); 779 if (invtlv) 780 break; 781 782 /* 783 * At this point, tlv_valid() has ensured that the TLV 784 * length is large enough but not too large (it doesn't 785 * go past the end of the containing TLV). 786 */ 787 if (EXTRACT_16BITS(&tlv->type) == F_TLV_METD) { 788 print_metatlv((u_char *) TLV_DATA(tlv), rlen, 0, indent); 789 } else if ((EXTRACT_16BITS(&tlv->type) == F_TLV_REDD)) { 790 print_reddata((u_char *) TLV_DATA(tlv), rlen, 0, indent); 791 } else { 792 printf("Unknown REDIRECT TLV 0x%x len %d\n", 793 EXTRACT_16BITS(&tlv->type), EXTRACT_16BITS(&tlv->length)); 794 } 795 796 tlv = GO_NXT_TLV(tlv, rlen); 797 } 798 799 if (rlen) { 800 printf 801 ("\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %d Bytes ", 802 EXTRACT_16BITS(&tlv->type), rlen - EXTRACT_16BITS(&tlv->length)); 803 return -1; 804 } 805 806 return 0; 807 808 trunc: 809 fputs("[|forces]", stdout); 810 return -1; 811 } 812 813 #define OP_OFF 8 814 #define OP_MIN 12 815 816 int 817 lfbselect_print(register const u_char * pptr, register u_int len, 818 u_int16_t op_msk, int indent) 819 { 820 const struct forces_lfbsh *lfbs; 821 const struct forces_tlv *otlv; 822 char *ib = indent_pr(indent, 0); 823 u_int dlen; 824 u_int rlen; 825 int invtlv; 826 827 /* 828 * forces_type_print() has ensured that len (the TLV length) 829 * >= TLV_HDRL. 830 */ 831 dlen = len - TLV_HDRL; 832 if (dlen <= OP_MIN) { /* id, instance, oper tlv header .. */ 833 printf("\n\t\ttruncated lfb selector: %d bytes missing! ", 834 OP_MIN - dlen); 835 return -1; 836 } 837 838 /* 839 * At this point, we know that dlen > OP_MIN; OP_OFF < OP_MIN, so 840 * we also know that it's > OP_OFF. 841 */ 842 rlen = dlen - OP_OFF; 843 844 lfbs = (const struct forces_lfbsh *)pptr; 845 TCHECK(*lfbs); 846 if (vflag >= 3) { 847 printf("\n%s%s(Classid %x) instance %x\n", 848 ib, tok2str(ForCES_LFBs, NULL, EXTRACT_32BITS(&lfbs->class)), 849 EXTRACT_32BITS(&lfbs->class), 850 EXTRACT_32BITS(&lfbs->instance)); 851 } 852 853 otlv = (struct forces_tlv *)(lfbs + 1); 854 855 indent += 1; 856 while (rlen != 0) { 857 TCHECK(*otlv); 858 invtlv = tlv_valid(otlv, rlen); 859 if (invtlv) 860 break; 861 862 /* 863 * At this point, tlv_valid() has ensured that the TLV 864 * length is large enough but not too large (it doesn't 865 * go past the end of the containing TLV). 866 */ 867 if (op_valid(EXTRACT_16BITS(&otlv->type), op_msk)) { 868 otlv_print(otlv, 0, indent); 869 } else { 870 if (vflag < 3) 871 printf("\n"); 872 printf 873 ("\t\tINValid oper-TLV type 0x%x length %d for this ForCES message\n", 874 EXTRACT_16BITS(&otlv->type), EXTRACT_16BITS(&otlv->length)); 875 invoptlv_print((u_char *)otlv, rlen, 0, indent); 876 } 877 otlv = GO_NXT_TLV(otlv, rlen); 878 } 879 880 if (rlen) { 881 printf 882 ("\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %d Bytes ", 883 EXTRACT_16BITS(&otlv->type), rlen - EXTRACT_16BITS(&otlv->length)); 884 return -1; 885 } 886 887 return 0; 888 889 trunc: 890 fputs("[|forces]", stdout); 891 return -1; 892 } 893 894 int 895 forces_type_print(register const u_char * pptr, const struct forcesh *fhdr _U_, 896 register u_int mlen, const struct tom_h *tops) 897 { 898 const struct forces_tlv *tltlv; 899 u_int rlen; 900 int invtlv; 901 int rc = 0; 902 int ttlv = 0; 903 904 /* 905 * forces_print() has already checked that mlen >= ForCES_HDRL 906 * by calling ForCES_HLN_VALID(). 907 */ 908 rlen = mlen - ForCES_HDRL; 909 910 if (rlen > TLV_HLN) { 911 if (tops->flags & ZERO_TTLV) { 912 printf("<0x%x>Illegal Top level TLV!\n", tops->flags); 913 return -1; 914 } 915 } else { 916 if (tops->flags & ZERO_MORE_TTLV) 917 return 0; 918 if (tops->flags & ONE_MORE_TTLV) { 919 printf("\tTop level TLV Data missing!\n"); 920 return -1; 921 } 922 } 923 924 if (tops->flags & ZERO_TTLV) { 925 return 0; 926 } 927 928 ttlv = tops->flags >> 4; 929 tltlv = GET_TOP_TLV(pptr); 930 931 /*XXX: 15 top level tlvs will probably be fine 932 You are nuts if you send more ;-> */ 933 while (rlen != 0) { 934 TCHECK(*tltlv); 935 invtlv = tlv_valid(tltlv, rlen); 936 if (invtlv) 937 break; 938 939 /* 940 * At this point, tlv_valid() has ensured that the TLV 941 * length is large enough but not too large (it doesn't 942 * go past the end of the packet). 943 */ 944 if (!ttlv_valid(EXTRACT_16BITS(&tltlv->type))) { 945 printf("\n\tInvalid ForCES Top TLV type=0x%x", 946 EXTRACT_16BITS(&tltlv->type)); 947 return -1; 948 } 949 950 if (vflag >= 3) 951 printf("\t%s, length %d (data length %d Bytes)", 952 tok2str(ForCES_TLV, NULL, EXTRACT_16BITS(&tltlv->type)), 953 EXTRACT_16BITS(&tltlv->length), 954 EXTRACT_16BITS(&tltlv->length) - TLV_HDRL); 955 956 rc = tops->print((u_char *) TLV_DATA(tltlv), 957 EXTRACT_16BITS(&tltlv->length), tops->op_msk, 9); 958 if (rc < 0) { 959 return -1; 960 } 961 tltlv = GO_NXT_TLV(tltlv, rlen); 962 ttlv--; 963 if (ttlv <= 0) 964 break; 965 } 966 /* 967 * XXX - if ttlv != 0, does that mean that the packet was too 968 * short, and didn't have *enough* TLVs in it? 969 */ 970 if (rlen) { 971 printf("\tMess TopTLV header: min %u, total %d advertised %d ", 972 TLV_HDRL, rlen, EXTRACT_16BITS(&tltlv->length)); 973 return -1; 974 } 975 976 return 0; 977 978 trunc: 979 fputs("[|forces]", stdout); 980 return -1; 981 } 982 983 void forces_print(register const u_char * pptr, register u_int len) 984 { 985 const struct forcesh *fhdr; 986 u_int mlen; 987 u_int32_t flg_raw; 988 const struct tom_h *tops; 989 int rc = 0; 990 991 fhdr = (const struct forcesh *)pptr; 992 TCHECK(*fhdr); 993 if (!tom_valid(fhdr->fm_tom)) { 994 printf("Invalid ForCES message type %d\n", fhdr->fm_tom); 995 goto error; 996 } 997 998 mlen = ForCES_BLN(fhdr); 999 1000 tops = get_forces_tom(fhdr->fm_tom); 1001 if (tops->v == TOM_RSVD) { 1002 printf("\n\tUnknown ForCES message type=0x%x", fhdr->fm_tom); 1003 goto error; 1004 } 1005 1006 printf("\n\tForCES %s ", tops->s); 1007 if (!ForCES_HLN_VALID(mlen, len)) { 1008 printf 1009 ("Illegal ForCES pkt len - min %u, total recvd %d, advertised %d ", 1010 ForCES_HDRL, len, ForCES_BLN(fhdr)); 1011 goto error; 1012 } 1013 1014 TCHECK2(*(pptr + 20), 4); 1015 flg_raw = EXTRACT_32BITS(pptr + 20); 1016 if (vflag >= 1) { 1017 printf("\n\tForCES Version %d len %uB flags 0x%08x ", 1018 ForCES_V(fhdr), mlen, flg_raw); 1019 printf("\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%" PRIx64, 1020 ForCES_SID(fhdr), ForCES_node(ForCES_SID(fhdr)), 1021 ForCES_DID(fhdr), ForCES_node(ForCES_DID(fhdr)), 1022 EXTRACT_64BITS(fhdr->fm_cor)); 1023 1024 } 1025 if (vflag >= 2) { 1026 printf 1027 ("\n\tForCES flags:\n\t %s(0x%x), prio=%d, %s(0x%x),\n\t %s(0x%x), %s(0x%x)\n", 1028 ForCES_ACKp(ForCES_ACK(fhdr)), ForCES_ACK(fhdr), 1029 ForCES_PRI(fhdr), 1030 ForCES_EMp(ForCES_EM(fhdr)), ForCES_EM(fhdr), 1031 ForCES_ATp(ForCES_AT(fhdr)), ForCES_AT(fhdr), 1032 ForCES_TPp(ForCES_TP(fhdr)), ForCES_TP(fhdr)); 1033 printf 1034 ("\t Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n", 1035 ForCES_RS1(fhdr), ForCES_RS2(fhdr)); 1036 } 1037 rc = forces_type_print(pptr, fhdr, mlen, tops); 1038 if (rc < 0) { 1039 error: 1040 hex_print_with_offset("\n\t[", pptr, len, 0); 1041 printf("\n\t]"); 1042 return; 1043 } 1044 1045 if (vflag >= 4) { 1046 printf("\n\t Raw ForCES message\n\t ["); 1047 hex_print_with_offset("\n\t ", pptr, len, 0); 1048 printf("\n\t ]"); 1049 } 1050 printf("\n"); 1051 return; 1052 1053 trunc: 1054 fputs("[|forces]", stdout); 1055 } 1056