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