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 30 /* 31 * Per draft-ietf-forces-protocol-22 32 */ 33 #define ForCES_VERS 1 34 #define ForCES_HDRL 24 35 #define ForCES_ALNL 4U 36 #define TLV_HDRL 4 37 #define ILV_HDRL 8 38 39 #define TOM_RSVD 0x0 40 #define TOM_ASSNSETUP 0x1 41 #define TOM_ASSNTEARD 0x2 42 #define TOM_CONFIG 0x3 43 #define TOM_QUERY 0x4 44 #define TOM_EVENTNOT 0x5 45 #define TOM_PKTREDIR 0x6 46 #define TOM_HEARTBT 0x0F 47 #define TOM_ASSNSETREP 0x11 48 #define TOM_CONFIGREP 0x13 49 #define TOM_QUERYREP 0x14 50 51 /* 52 * tom_h Flags: resv1(8b):maxtlvs(4b):resv2(2b):mintlv(2b) 53 */ 54 #define ZERO_TTLV 0x01 55 #define ZERO_MORE_TTLV 0x02 56 #define ONE_MORE_TTLV 0x04 57 #define ZERO_TLV 0x00 58 #define ONE_TLV 0x10 59 #define TWO_TLV 0x20 60 #define MAX_TLV 0xF0 61 62 #define TTLV_T1 (ONE_MORE_TTLV|ONE_TLV) 63 #define TTLV_T2 (ONE_MORE_TTLV|MAX_TLV) 64 65 struct tom_h { 66 u_int32_t v; 67 u_int16_t flags; 68 u_int16_t op_msk; 69 const char *s; 70 int (*print) (register const u_char * pptr, register u_int len, 71 u_int16_t op_msk, int indent); 72 }; 73 74 enum { 75 TOM_RSV_I, 76 TOM_ASS_I, 77 TOM_AST_I, 78 TOM_CFG_I, 79 TOM_QRY_I, 80 TOM_EVN_I, 81 TOM_RED_I, 82 TOM_HBT_I, 83 TOM_ASR_I, 84 TOM_CNR_I, 85 TOM_QRR_I, 86 _TOM_RSV_MAX 87 }; 88 #define TOM_MAX_IND (_TOM_RSV_MAX - 1) 89 90 static inline int tom_valid(u_int8_t tom) 91 { 92 if (tom > 0) { 93 if (tom >= 0x7 && tom <= 0xe) 94 return 0; 95 if (tom == 0x10) 96 return 0; 97 if (tom > 0x14) 98 return 0; 99 return 1; 100 } else 101 return 0; 102 } 103 104 static inline const char *ForCES_node(u_int32_t node) 105 { 106 if (node <= 0x3FFFFFFF) 107 return "FE"; 108 if (node >= 0x40000000 && node <= 0x7FFFFFFF) 109 return "CE"; 110 if (node >= 0xC0000000 && node <= 0xFFFFFFEF) 111 return "AllMulticast"; 112 if (node == 0xFFFFFFFD) 113 return "AllCEsBroadcast"; 114 if (node == 0xFFFFFFFE) 115 return "AllFEsBroadcast"; 116 if (node == 0xFFFFFFFF) 117 return "AllBroadcast"; 118 119 return "ForCESreserved"; 120 121 } 122 123 static inline const char *ForCES_ACKp(u_int32_t flg) 124 { 125 if (flg == 0x0) 126 return "NoACK"; 127 if (flg == 0x1) 128 return "SuccessACK"; 129 if (flg == 0x2) 130 return "FailureACK"; 131 if (flg == 0x3) 132 return "AlwaysACK"; 133 return "ACKUnknown"; 134 } 135 136 static inline const char *ForCES_EMp(u_int32_t flg) 137 { 138 if (flg == 0x0) 139 return "EMReserved"; 140 if (flg == 0x1) 141 return "execute-all-or-none"; 142 if (flg == 0x2) 143 return "execute-until-failure"; 144 if (flg == 0x3) 145 return "continue-execute-on-failure"; 146 return "EMUnknown"; 147 } 148 149 static inline const char *ForCES_ATp(u_int32_t flg) 150 { 151 if (flg == 0x0) 152 return "Standalone"; 153 if (flg == 0x1) 154 return "2PCtransaction"; 155 return "ATUnknown"; 156 } 157 158 static inline const char *ForCES_TPp(u_int32_t flg) 159 { 160 if (flg == 0x0) 161 return "StartofTransaction"; 162 if (flg == 0x1) 163 return "MiddleofTransaction"; 164 if (flg == 0x2) 165 return "EndofTransaction"; 166 if (flg == 0x3) 167 return "abort"; 168 return "TPUnknown"; 169 } 170 171 /* 172 * Structure of forces header, naked of TLVs. 173 */ 174 struct forcesh { 175 u_int8_t fm_vrsvd; /* version and reserved */ 176 #define ForCES_V(forcesh) ((forcesh)->fm_vrsvd >> 4) 177 u_int8_t fm_tom; /* type of message */ 178 u_int16_t fm_len; /* total length * 4 bytes */ 179 #define ForCES_BLN(forcesh) ((u_int32_t)(EXTRACT_16BITS(&(forcesh)->fm_len) << 2)) 180 u_int32_t fm_sid; /* Source ID */ 181 #define ForCES_SID(forcesh) EXTRACT_32BITS(&(forcesh)->fm_sid) 182 u_int32_t fm_did; /* Destination ID */ 183 #define ForCES_DID(forcesh) EXTRACT_32BITS(&(forcesh)->fm_did) 184 u_int8_t fm_cor[8]; /* correlator */ 185 u_int32_t fm_flags; /* flags */ 186 #define ForCES_ACK(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0xC0000000) >> 30) 187 #define ForCES_PRI(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x38000000) >> 27) 188 #define ForCES_RS1(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x07000000) >> 24) 189 #define ForCES_EM(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00C00000) >> 22) 190 #define ForCES_AT(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00200000) >> 21) 191 #define ForCES_TP(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00180000) >> 19) 192 #define ForCES_RS2(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x0007FFFF) >> 0) 193 }; 194 195 #define ForCES_HLN_VALID(fhl,tlen) ((tlen) >= ForCES_HDRL && \ 196 (fhl) >= ForCES_HDRL && \ 197 (fhl) == (tlen)) 198 199 #define F_LFB_RSVD 0x0 200 #define F_LFB_FEO 0x1 201 #define F_LFB_FEPO 0x2 202 static const struct tok ForCES_LFBs[] = { 203 {F_LFB_RSVD, "Invalid TLV"}, 204 {F_LFB_FEO, "FEObj LFB"}, 205 {F_LFB_FEPO, "FEProtoObj LFB"}, 206 {0, NULL} 207 }; 208 209 enum { 210 F_OP_RSV, 211 F_OP_SET, 212 F_OP_SETPROP, 213 F_OP_SETRESP, 214 F_OP_SETPRESP, 215 F_OP_DEL, 216 F_OP_DELRESP, 217 F_OP_GET, 218 F_OP_GETPROP, 219 F_OP_GETRESP, 220 F_OP_GETPRESP, 221 F_OP_REPORT, 222 F_OP_COMMIT, 223 F_OP_RCOMMIT, 224 F_OP_RTRCOMP, 225 _F_OP_MAX 226 }; 227 228 #define F_OP_MAX (_F_OP_MAX - 1) 229 enum { 230 B_OP_SET = 1 << (F_OP_SET - 1), 231 B_OP_SETPROP = 1 << (F_OP_SETPROP - 1), 232 B_OP_SETRESP = 1 << (F_OP_SETRESP - 1), 233 B_OP_SETPRESP = 1 << (F_OP_SETPRESP - 1), 234 B_OP_DEL = 1 << (F_OP_DEL - 1), 235 B_OP_DELRESP = 1 << (F_OP_DELRESP - 1), 236 B_OP_GET = 1 << (F_OP_GET - 1), 237 B_OP_GETPROP = 1 << (F_OP_GETPROP - 1), 238 B_OP_GETRESP = 1 << (F_OP_GETRESP - 1), 239 B_OP_GETPRESP = 1 << (F_OP_GETPRESP - 1), 240 B_OP_REPORT = 1 << (F_OP_REPORT - 1), 241 B_OP_COMMIT = 1 << (F_OP_COMMIT - 1), 242 B_OP_RCOMMIT = 1 << (F_OP_RCOMMIT - 1), 243 B_OP_RTRCOMP = 1 << (F_OP_RTRCOMP - 1), 244 }; 245 246 struct optlv_h { 247 u_int16_t flags; 248 u_int16_t op_msk; 249 const char *s; 250 int (*print) (register const u_char * pptr, register u_int len, 251 u_int16_t op_msk, int indent); 252 }; 253 254 static int genoptlv_print(register const u_char * pptr, register u_int len, 255 u_int16_t op_msk, int indent); 256 static int recpdoptlv_print(register const u_char * pptr, register u_int len, 257 u_int16_t op_msk, int indent); 258 static int invoptlv_print(register const u_char * pptr, register u_int len, 259 u_int16_t op_msk, int indent); 260 261 #define OP_MIN_SIZ 8 262 struct pathdata_h { 263 u_int16_t pflags; 264 u_int16_t pIDcnt; 265 }; 266 267 #define B_FULLD 0x1 268 #define B_SPARD 0x2 269 #define B_RESTV 0x4 270 #define B_KEYIN 0x8 271 #define B_APPND 0x10 272 #define B_TRNG 0x20 273 274 static const struct optlv_h OPTLV_msg[F_OP_MAX + 1] = { 275 /* F_OP_RSV */ {ZERO_TTLV, 0, "Invalid OPTLV", invoptlv_print}, 276 /* F_OP_SET */ {TTLV_T2, B_FULLD | B_SPARD, " Set", recpdoptlv_print}, 277 /* F_OP_SETPROP */ 278 {TTLV_T2, B_FULLD | B_SPARD, " SetProp", recpdoptlv_print}, 279 /* F_OP_SETRESP */ {TTLV_T2, B_RESTV, " SetResp", recpdoptlv_print}, 280 /* F_OP_SETPRESP */ {TTLV_T2, B_RESTV, " SetPropResp", recpdoptlv_print}, 281 /* F_OP_DEL */ {ZERO_TTLV, 0, " Del", recpdoptlv_print}, 282 /* F_OP_DELRESP */ {TTLV_T2, B_RESTV, " DelResp", recpdoptlv_print}, 283 /* F_OP_GET */ {ZERO_TTLV, 0, " Get", recpdoptlv_print}, 284 /* F_OP_GETPROP */ {ZERO_TTLV, 0, " GetProp", recpdoptlv_print}, 285 /* F_OP_GETRESP */ 286 {TTLV_T2, B_FULLD | B_SPARD | B_RESTV, " GetResp", recpdoptlv_print}, 287 /* F_OP_GETPRESP */ 288 {TTLV_T2, B_FULLD | B_RESTV, " GetPropResp", recpdoptlv_print}, 289 /* F_OP_REPORT */ 290 {TTLV_T2, B_FULLD | B_SPARD, " Report", recpdoptlv_print}, 291 /* F_OP_COMMIT */ {ZERO_TTLV, 0, " Commit", NULL}, 292 /* F_OP_RCOMMIT */ {TTLV_T1, B_RESTV, " RCommit", genoptlv_print}, 293 /* F_OP_RTRCOMP */ {ZERO_TTLV, 0, " RTRCOMP", NULL}, 294 }; 295 296 static inline const struct optlv_h *get_forces_optlv_h(u_int16_t opt) 297 { 298 if (opt > F_OP_MAX || opt <= F_OP_RSV) 299 return &OPTLV_msg[F_OP_RSV]; 300 301 return &OPTLV_msg[opt]; 302 } 303 304 #define IND_SIZE 256 305 #define IND_CHR ' ' 306 #define IND_PREF '\n' 307 #define IND_SUF 0x0 308 char ind_buf[IND_SIZE]; 309 310 static inline char *indent_pr(int indent, int nlpref) 311 { 312 int i = 0; 313 char *r = ind_buf; 314 315 if (indent > (IND_SIZE - 1)) 316 indent = IND_SIZE - 1; 317 318 if (nlpref) { 319 r[i] = IND_PREF; 320 i++; 321 indent--; 322 } 323 324 while (--indent >= 0) 325 r[i++] = IND_CHR; 326 327 r[i] = IND_SUF; 328 return r; 329 } 330 331 static inline int op_valid(u_int16_t op, u_int16_t mask) 332 { 333 int opb = 1 << (op - 1); 334 335 if (op == 0) 336 return 0; 337 if (opb & mask) 338 return 1; 339 /* I guess we should allow vendor operations? */ 340 if (op >= 0x8000) 341 return 1; 342 return 0; 343 } 344 345 #define F_TLV_RSVD 0x0000 346 #define F_TLV_REDR 0x0001 347 #define F_TLV_ASRS 0x0010 348 #define F_TLV_ASRT 0x0011 349 #define F_TLV_LFBS 0x1000 350 #define F_TLV_PDAT 0x0110 351 #define F_TLV_KEYI 0x0111 352 #define F_TLV_FULD 0x0112 353 #define F_TLV_SPAD 0x0113 354 #define F_TLV_REST 0x0114 355 #define F_TLV_METD 0x0115 356 #define F_TLV_REDD 0x0116 357 #define F_TLV_TRNG 0x0117 358 359 360 #define F_TLV_VNST 0x8000 361 362 static const struct tok ForCES_TLV[] = { 363 {F_TLV_RSVD, "Invalid TLV"}, 364 {F_TLV_REDR, "REDIRECT TLV"}, 365 {F_TLV_ASRS, "ASResult TLV"}, 366 {F_TLV_ASRT, "ASTreason TLV"}, 367 {F_TLV_LFBS, "LFBselect TLV"}, 368 {F_TLV_PDAT, "PATH-DATA TLV"}, 369 {F_TLV_KEYI, "KEYINFO TLV"}, 370 {F_TLV_FULD, "FULLDATA TLV"}, 371 {F_TLV_SPAD, "SPARSEDATA TLV"}, 372 {F_TLV_REST, "RESULT TLV"}, 373 {F_TLV_METD, "METADATA TLV"}, 374 {F_TLV_REDD, "REDIRECTDATA TLV"}, 375 {0, NULL} 376 }; 377 378 #define TLV_HLN 4 379 static inline int ttlv_valid(u_int16_t ttlv) 380 { 381 if (ttlv > 0) { 382 if (ttlv == 1 || ttlv == 0x1000) 383 return 1; 384 if (ttlv >= 0x10 && ttlv <= 0x11) 385 return 1; 386 if (ttlv >= 0x110 && ttlv <= 0x116) 387 return 1; 388 if (ttlv >= 0x8000) 389 return 0; /* XXX: */ 390 } 391 392 return 0; 393 } 394 395 struct forces_ilv { 396 u_int32_t type; 397 u_int32_t length; 398 }; 399 400 struct forces_tlv { 401 u_int16_t type; 402 u_int16_t length; 403 }; 404 405 #define F_ALN_LEN(len) ( ((len)+ForCES_ALNL-1) & ~(ForCES_ALNL-1) ) 406 #define GET_TOP_TLV(fhdr) ((struct forces_tlv *)((fhdr) + sizeof (struct forcesh))) 407 #define TLV_SET_LEN(len) (F_ALN_LEN(TLV_HDRL) + (len)) 408 #define TLV_ALN_LEN(len) F_ALN_LEN(TLV_SET_LEN(len)) 409 #define TLV_RDAT_LEN(tlv) ((int)(EXTRACT_16BITS(&(tlv)->length) - TLV_SET_LEN(0)) 410 #define TLV_DATA(tlvp) ((void*)(((char*)(tlvp)) + TLV_SET_LEN(0))) 411 #define GO_NXT_TLV(tlv,rlen) ((rlen) -= F_ALN_LEN(EXTRACT_16BITS(&(tlv)->length)), \ 412 (struct forces_tlv*)(((char*)(tlv)) \ 413 + F_ALN_LEN(EXTRACT_16BITS(&(tlv)->length)))) 414 #define ILV_SET_LEN(len) (F_ALN_LEN(ILV_HDRL) + (len)) 415 #define ILV_ALN_LEN(len) F_ALN_LEN(ILV_SET_LEN(len)) 416 #define ILV_RDAT_LEN(ilv) ((int)(EXTRACT_32BITS(&(ilv)->length)) - ILV_SET_LEN(0)) 417 #define ILV_DATA(ilvp) ((void*)(((char*)(ilvp)) + ILV_SET_LEN(0))) 418 #define GO_NXT_ILV(ilv,rlen) ((rlen) -= F_ALN_LEN(EXTRACT_32BITS(&(ilv)->length)), \ 419 (struct forces_ilv *)(((char*)(ilv)) \ 420 + F_ALN_LEN(EXTRACT_32BITS(&(ilv)->length)))) 421 #define INVALID_RLEN -1 422 #define INVALID_STLN -2 423 #define INVALID_LTLN -3 424 #define INVALID_ALEN -4 425 426 static const struct tok ForCES_TLV_err[] = { 427 {INVALID_RLEN, "Invalid total length"}, 428 {INVALID_STLN, "xLV too short"}, 429 {INVALID_LTLN, "xLV too long"}, 430 {INVALID_ALEN, "data padding missing"}, 431 {0, NULL} 432 }; 433 434 static inline int tlv_valid(const struct forces_tlv *tlv, u_int rlen) 435 { 436 if (rlen < TLV_HDRL) 437 return INVALID_RLEN; 438 if (EXTRACT_16BITS(&tlv->length) < TLV_HDRL) 439 return INVALID_STLN; 440 if (EXTRACT_16BITS(&tlv->length) > rlen) 441 return INVALID_LTLN; 442 if (rlen < F_ALN_LEN(EXTRACT_16BITS(&tlv->length))) 443 return INVALID_ALEN; 444 445 return 0; 446 } 447 448 static inline int ilv_valid(const struct forces_ilv *ilv, u_int rlen) 449 { 450 if (rlen < ILV_HDRL) 451 return INVALID_RLEN; 452 if (EXTRACT_32BITS(&ilv->length) < ILV_HDRL) 453 return INVALID_STLN; 454 if (EXTRACT_32BITS(&ilv->length) > rlen) 455 return INVALID_LTLN; 456 if (rlen < F_ALN_LEN(EXTRACT_32BITS(&ilv->length))) 457 return INVALID_ALEN; 458 459 return 0; 460 } 461 462 static int lfbselect_print(register const u_char * pptr, register u_int len, 463 u_int16_t op_msk, int indent); 464 static int redirect_print(register const u_char * pptr, register u_int len, 465 u_int16_t op_msk, int indent); 466 static int asrtlv_print(register const u_char * pptr, register u_int len, 467 u_int16_t op_msk, int indent); 468 static int asttlv_print(register const u_char * pptr, register u_int len, 469 u_int16_t op_msk, int indent); 470 471 struct forces_lfbsh { 472 u_int32_t class; 473 u_int32_t instance; 474 }; 475 476 #define ASSNS_OPS (B_OP_REPORT) 477 #define CFG_OPS (B_OP_SET|B_OP_SETPROP|B_OP_DEL|B_OP_COMMIT|B_OP_RTRCOMP) 478 #define CFG_ROPS (B_OP_SETRESP|B_OP_SETPRESP|B_OP_DELRESP|B_OP_RCOMMIT) 479 #define CFG_QY (B_OP_GET|B_OP_GETPROP) 480 #define CFG_QYR (B_OP_GETRESP|B_OP_GETPRESP) 481 #define CFG_EVN (B_OP_REPORT) 482 483 static const struct tom_h ForCES_msg[TOM_MAX_IND + 1] = { 484 /* TOM_RSV_I */ {TOM_RSVD, ZERO_TTLV, 0, "Invalid message", NULL}, 485 /* TOM_ASS_I */ {TOM_ASSNSETUP, ZERO_MORE_TTLV | TWO_TLV, ASSNS_OPS, 486 "Association Setup", lfbselect_print}, 487 /* TOM_AST_I */ 488 {TOM_ASSNTEARD, TTLV_T1, 0, "Association TearDown", asttlv_print}, 489 /* TOM_CFG_I */ {TOM_CONFIG, TTLV_T2, CFG_OPS, "Config", lfbselect_print}, 490 /* TOM_QRY_I */ {TOM_QUERY, TTLV_T2, CFG_QY, "Query", lfbselect_print}, 491 /* TOM_EVN_I */ {TOM_EVENTNOT, TTLV_T1, CFG_EVN, "Event Notification", 492 lfbselect_print}, 493 /* TOM_RED_I */ 494 {TOM_PKTREDIR, TTLV_T2, 0, "Packet Redirect", redirect_print}, 495 /* TOM_HBT_I */ {TOM_HEARTBT, ZERO_TTLV, 0, "HeartBeat", NULL}, 496 /* TOM_ASR_I */ 497 {TOM_ASSNSETREP, TTLV_T1, 0, "Association Response", asrtlv_print}, 498 /* TOM_CNR_I */ {TOM_CONFIGREP, TTLV_T2, CFG_ROPS, "Config Response", 499 lfbselect_print}, 500 /* TOM_QRR_I */ 501 {TOM_QUERYREP, TTLV_T2, CFG_QYR, "Query Response", lfbselect_print}, 502 }; 503 504 static inline const struct tom_h *get_forces_tom(u_int8_t tom) 505 { 506 int i; 507 for (i = TOM_RSV_I; i <= TOM_MAX_IND; i++) { 508 const struct tom_h *th = &ForCES_msg[i]; 509 if (th->v == tom) 510 return th; 511 } 512 return &ForCES_msg[TOM_RSV_I]; 513 } 514 515 struct pdata_ops { 516 u_int32_t v; 517 u_int16_t flags; 518 u_int16_t op_msk; 519 const char *s; 520 int (*print) (register const u_char * pptr, register u_int len, 521 u_int16_t op_msk, int indent); 522 }; 523 524 enum { 525 PD_RSV_I, 526 PD_SEL_I, 527 PD_FDT_I, 528 PD_SDT_I, 529 PD_RES_I, 530 PD_PDT_I, 531 _PD_RSV_MAX 532 }; 533 #define PD_MAX_IND (_TOM_RSV_MAX - 1) 534 535 static inline int pd_valid(u_int16_t pd) 536 { 537 if (pd >= F_TLV_PDAT && pd <= F_TLV_REST) 538 return 1; 539 return 0; 540 } 541 542 static inline void chk_op_type(u_int16_t type, u_int16_t msk, u_int16_t omsk) 543 { 544 if (type != F_TLV_PDAT) { 545 if (msk & B_KEYIN) { 546 if (type != F_TLV_KEYI) { 547 printf 548 ("Based on flags expected KEYINFO TLV!\n"); 549 } 550 } else { 551 if (!(msk & omsk)) { 552 printf 553 ("Illegal DATA encoding for type 0x%x programmed %x got %x \n", 554 type, omsk, msk); 555 } 556 } 557 } 558 559 } 560 561 #define F_SELKEY 1 562 #define F_SELTABRANGE 2 563 #define F_TABAPPEND 4 564 565 struct res_val { 566 u_int8_t result; 567 u_int8_t resv1; 568 u_int16_t resv2; 569 }; 570 571 static int prestlv_print(register const u_char * pptr, register u_int len, 572 u_int16_t op_msk, int indent); 573 static int pkeyitlv_print(register const u_char * pptr, register u_int len, 574 u_int16_t op_msk, int indent); 575 static int fdatatlv_print(register const u_char * pptr, register u_int len, 576 u_int16_t op_msk, int indent); 577 static int sdatatlv_print(register const u_char * pptr, register u_int len, 578 u_int16_t op_msk, int indent); 579 580 static const struct pdata_ops ForCES_pdata[PD_MAX_IND + 1] = { 581 /* PD_RSV_I */ {0, 0, 0, "Invalid message", NULL}, 582 /* PD_SEL_I */ {F_TLV_KEYI, 0, 0, "KEYINFO TLV", pkeyitlv_print}, 583 /* PD_FDT_I */ {F_TLV_FULD, 0, B_FULLD, "FULLDATA TLV", fdatatlv_print}, 584 /* PD_SDT_I */ {F_TLV_SPAD, 0, B_SPARD, "SPARSEDATA TLV", sdatatlv_print}, 585 /* PD_RES_I */ {F_TLV_REST, 0, B_RESTV, "RESULT TLV", prestlv_print}, 586 /* PD_PDT_I */ 587 {F_TLV_PDAT, 0, 0, "Inner PATH-DATA TLV", recpdoptlv_print}, 588 }; 589 590 static inline const struct pdata_ops *get_forces_pd(u_int16_t pd) 591 { 592 int i; 593 for (i = PD_RSV_I + 1; i <= PD_MAX_IND; i++) { 594 const struct pdata_ops *pdo = &ForCES_pdata[i]; 595 if (pdo->v == pd) 596 return pdo; 597 } 598 return &ForCES_pdata[TOM_RSV_I]; 599 } 600 601 enum { 602 E_SUCCESS, 603 E_INVALID_HEADER, 604 E_LENGTH_MISMATCH, 605 E_VERSION_MISMATCH, 606 E_INVALID_DESTINATION_PID, 607 E_LFB_UNKNOWN, 608 E_LFB_NOT_FOUND, 609 E_LFB_INSTANCE_ID_NOT_FOUND, 610 E_INVALID_PATH, 611 E_COMPONENT_DOES_NOT_EXIST, 612 E_EXISTS, 613 E_NOT_FOUND, 614 E_READ_ONLY, 615 E_INVALID_ARRAY_CREATION, 616 E_VALUE_OUT_OF_RANGE, 617 E_CONTENTS_TOO_LONG, 618 E_INVALID_PARAMETERS, 619 E_INVALID_MESSAGE_TYPE, 620 E_INVALID_FLAGS, 621 E_INVALID_TLV, 622 E_EVENT_ERROR, 623 E_NOT_SUPPORTED, 624 E_MEMORY_ERROR, 625 E_INTERNAL_ERROR, 626 /* 0x18-0xFE are reserved .. */ 627 E_UNSPECIFIED_ERROR = 0XFF 628 }; 629 630 static const struct tok ForCES_errs[] = { 631 {E_SUCCESS, "SUCCESS"}, 632 {E_INVALID_HEADER, "INVALID HEADER"}, 633 {E_LENGTH_MISMATCH, "LENGTH MISMATCH"}, 634 {E_VERSION_MISMATCH, "VERSION MISMATCH"}, 635 {E_INVALID_DESTINATION_PID, "INVALID DESTINATION PID"}, 636 {E_LFB_UNKNOWN, "LFB UNKNOWN"}, 637 {E_LFB_NOT_FOUND, "LFB NOT FOUND"}, 638 {E_LFB_INSTANCE_ID_NOT_FOUND, "LFB INSTANCE ID NOT FOUND"}, 639 {E_INVALID_PATH, "INVALID PATH"}, 640 {E_COMPONENT_DOES_NOT_EXIST, "COMPONENT DOES NOT EXIST"}, 641 {E_EXISTS, "EXISTS ALREADY"}, 642 {E_NOT_FOUND, "NOT FOUND"}, 643 {E_READ_ONLY, "READ ONLY"}, 644 {E_INVALID_ARRAY_CREATION, "INVALID ARRAY CREATION"}, 645 {E_VALUE_OUT_OF_RANGE, "VALUE OUT OF RANGE"}, 646 {E_CONTENTS_TOO_LONG, "CONTENTS TOO LONG"}, 647 {E_INVALID_PARAMETERS, "INVALID PARAMETERS"}, 648 {E_INVALID_MESSAGE_TYPE, "INVALID MESSAGE TYPE"}, 649 {E_INVALID_FLAGS, "INVALID FLAGS"}, 650 {E_INVALID_TLV, "INVALID TLV"}, 651 {E_EVENT_ERROR, "EVENT ERROR"}, 652 {E_NOT_SUPPORTED, "NOT SUPPORTED"}, 653 {E_MEMORY_ERROR, "MEMORY ERROR"}, 654 {E_INTERNAL_ERROR, "INTERNAL ERROR"}, 655 {E_UNSPECIFIED_ERROR, "UNSPECIFIED ERROR"}, 656 {0, NULL} 657 }; 658 659 #define RESLEN 4 660 661 static int 662 prestlv_print(register const u_char * pptr, register u_int len, 663 u_int16_t op_msk _U_, int indent) 664 { 665 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 666 register const u_char *tdp = (u_char *) TLV_DATA(tlv); 667 struct res_val *r = (struct res_val *)tdp; 668 u_int dlen; 669 670 /* 671 * pdatacnt_print() has ensured that len (the TLV length) 672 * >= TLV_HDRL. 673 */ 674 dlen = len - TLV_HDRL; 675 if (dlen != RESLEN) { 676 printf("illegal RESULT-TLV: %d bytes!\n", dlen); 677 return -1; 678 } 679 680 TCHECK(*r); 681 if (r->result >= 0x18 && r->result <= 0xFE) { 682 printf("illegal reserved result code: 0x%x!\n", r->result); 683 return -1; 684 } 685 686 if (vflag >= 3) { 687 char *ib = indent_pr(indent, 0); 688 printf("%s Result: %s (code 0x%x)\n", ib, 689 tok2str(ForCES_errs, NULL, r->result), r->result); 690 } 691 return 0; 692 693 trunc: 694 fputs("[|forces]", stdout); 695 return -1; 696 } 697 698 static int 699 fdatatlv_print(register const u_char * pptr, register u_int len, 700 u_int16_t op_msk _U_, int indent) 701 { 702 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 703 u_int rlen; 704 register const u_char *tdp = (u_char *) TLV_DATA(tlv); 705 u_int16_t type; 706 707 /* 708 * pdatacnt_print() or pkeyitlv_print() has ensured that len 709 * (the TLV length) >= TLV_HDRL. 710 */ 711 rlen = len - TLV_HDRL; 712 TCHECK(*tlv); 713 type = EXTRACT_16BITS(&tlv->type); 714 if (type != F_TLV_FULD) { 715 printf("Error: expecting FULLDATA!\n"); 716 return -1; 717 } 718 719 if (vflag >= 3) { 720 char *ib = indent_pr(indent + 2, 1); 721 printf("%s[", &ib[1]); 722 hex_print_with_offset(ib, tdp, rlen, 0); 723 printf("\n%s]\n", &ib[1]); 724 } 725 return 0; 726 727 trunc: 728 fputs("[|forces]", stdout); 729 return -1; 730 } 731 732 static int 733 sdatailv_print(register const u_char * pptr, register u_int len, 734 u_int16_t op_msk _U_, int indent) 735 { 736 u_int rlen; 737 const struct forces_ilv *ilv = (struct forces_ilv *)pptr; 738 int invilv; 739 740 if (len < ILV_HDRL) { 741 printf("Error: BAD SPARSEDATA-TLV!\n"); 742 return -1; 743 } 744 rlen = len; 745 indent += 1; 746 while (rlen != 0) { 747 #if 0 748 printf("Jamal - outstanding length <%d>\n", rlen); 749 #endif 750 char *ib = indent_pr(indent, 1); 751 register const u_char *tdp = (u_char *) ILV_DATA(ilv); 752 TCHECK(*ilv); 753 invilv = ilv_valid(ilv, rlen); 754 if (invilv) { 755 printf("%s[", &ib[1]); 756 hex_print_with_offset(ib, tdp, rlen, 0); 757 printf("\n%s]\n", &ib[1]); 758 return -1; 759 } 760 if (vflag >= 3) { 761 int ilvl = EXTRACT_32BITS(&ilv->length); 762 printf("\n%s ILV: type %x length %d\n", &ib[1], 763 EXTRACT_32BITS(&ilv->type), ilvl); 764 hex_print_with_offset("\t\t[", tdp, ilvl-ILV_HDRL, 0); 765 } 766 767 ilv = GO_NXT_ILV(ilv, rlen); 768 } 769 770 return 0; 771 772 trunc: 773 fputs("[|forces]", stdout); 774 return -1; 775 } 776 777 static int 778 sdatatlv_print(register const u_char * pptr, register u_int len, 779 u_int16_t op_msk, int indent) 780 { 781 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 782 u_int rlen; 783 register const u_char *tdp = (u_char *) TLV_DATA(tlv); 784 u_int16_t type; 785 786 /* 787 * pdatacnt_print() has ensured that len (the TLV length) 788 * >= TLV_HDRL. 789 */ 790 rlen = len - TLV_HDRL; 791 TCHECK(*tlv); 792 type = EXTRACT_16BITS(&tlv->type); 793 if (type != F_TLV_SPAD) { 794 printf("Error: expecting SPARSEDATA!\n"); 795 return -1; 796 } 797 798 return sdatailv_print(tdp, rlen, op_msk, indent); 799 800 trunc: 801 fputs("[|forces]", stdout); 802 return -1; 803 } 804 805 static int 806 pkeyitlv_print(register const u_char * pptr, register u_int len, 807 u_int16_t op_msk, int indent) 808 { 809 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 810 register const u_char *tdp = (u_char *) TLV_DATA(tlv); 811 register const u_char *dp = tdp + 4; 812 const struct forces_tlv *kdtlv = (struct forces_tlv *)dp; 813 u_int32_t id; 814 char *ib = indent_pr(indent, 0); 815 u_int16_t type, tll; 816 int invtlv; 817 818 TCHECK(*tdp); 819 id = EXTRACT_32BITS(tdp); 820 printf("%sKeyinfo: Key 0x%x\n", ib, id); 821 TCHECK(*kdtlv); 822 type = EXTRACT_16BITS(&kdtlv->type); 823 invtlv = tlv_valid(kdtlv, len); 824 825 if (invtlv) { 826 printf("%s TLV type 0x%x len %d\n", 827 tok2str(ForCES_TLV_err, NULL, invtlv), type, 828 EXTRACT_16BITS(&kdtlv->length)); 829 return -1; 830 } 831 /* 832 * At this point, tlv_valid() has ensured that the TLV 833 * length is large enough but not too large (it doesn't 834 * go past the end of the containing TLV). 835 */ 836 tll = EXTRACT_16BITS(&kdtlv->length); 837 dp = (u_char *) TLV_DATA(kdtlv); 838 return fdatatlv_print(dp, tll, op_msk, indent); 839 840 trunc: 841 fputs("[|forces]", stdout); 842 return -1; 843 } 844 845 #define PTH_DESC_SIZE 12 846 847 static int 848 pdatacnt_print(register const u_char * pptr, register u_int len, 849 u_int16_t IDcnt, u_int16_t op_msk, int indent) 850 { 851 u_int i; 852 u_int32_t id; 853 char *ib = indent_pr(indent, 0); 854 855 if ((op_msk & B_APPND) && vflag >= 3) { 856 printf("%sTABLE APPEND\n", ib); 857 } 858 for (i = 0; i < IDcnt; i++) { 859 TCHECK2(*pptr, 4); 860 if (len < 4) 861 goto trunc; 862 id = EXTRACT_32BITS(pptr); 863 if (vflag >= 3) 864 printf("%sID#%02u: %d\n", ib, i + 1, id); 865 len -= 4; 866 pptr += 4; 867 } 868 869 if ((op_msk & B_TRNG) || (op_msk & B_KEYIN)) { 870 if (op_msk & B_TRNG) { 871 u_int32_t starti, endi; 872 873 if (len < PTH_DESC_SIZE) { 874 printf("pathlength %d with key/range too short %d\n", 875 len, PTH_DESC_SIZE); 876 return -1; 877 } 878 879 pptr += sizeof(struct forces_tlv); 880 len -= sizeof(struct forces_tlv); 881 882 starti = EXTRACT_32BITS(pptr); 883 pptr += 4; 884 len -= 4; 885 886 endi = EXTRACT_32BITS(pptr); 887 pptr += 4; 888 len -= 4; 889 890 if (vflag >= 3) 891 printf("%sTable range: [%d,%d]\n", ib, starti, endi); 892 } 893 894 if (op_msk & B_KEYIN) { 895 struct forces_tlv *keytlv; 896 u_int16_t tll; 897 898 if (len < PTH_DESC_SIZE) { 899 printf("pathlength %d with key/range too short %d\n", 900 len, PTH_DESC_SIZE); 901 return -1; 902 } 903 904 /* skip keyid */ 905 pptr += 4; 906 len -= 4; 907 keytlv = (struct forces_tlv *)pptr; 908 /* skip header */ 909 pptr += sizeof(struct forces_tlv); 910 len -= sizeof(struct forces_tlv); 911 /* skip key content */ 912 tll = EXTRACT_16BITS(&keytlv->length); 913 if (tll < TLV_HDRL) { 914 printf("key content length %u < %u\n", 915 tll, TLV_HDRL); 916 return -1; 917 } 918 tll -= TLV_HDRL; 919 if (len < tll) { 920 printf("key content too short\n"); 921 return -1; 922 } 923 pptr += tll; 924 len -= tll; 925 } 926 927 } 928 929 if (len) { 930 const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; 931 u_int16_t type; 932 u_int16_t tll; 933 int pad = 0; 934 u_int aln; 935 int invtlv; 936 937 TCHECK(*pdtlv); 938 type = EXTRACT_16BITS(&pdtlv->type); 939 invtlv = tlv_valid(pdtlv, len); 940 if (invtlv) { 941 printf 942 ("%s Outstanding bytes %d for TLV type 0x%x TLV len %d\n", 943 tok2str(ForCES_TLV_err, NULL, invtlv), len, type, 944 EXTRACT_16BITS(&pdtlv->length)); 945 goto pd_err; 946 } 947 /* 948 * At this point, tlv_valid() has ensured that the TLV 949 * length is large enough but not too large (it doesn't 950 * go past the end of the containing TLV). 951 */ 952 tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; 953 aln = F_ALN_LEN(EXTRACT_16BITS(&pdtlv->length)); 954 if (aln > EXTRACT_16BITS(&pdtlv->length)) { 955 if (aln > len) { 956 printf 957 ("Invalid padded pathdata TLV type 0x%x len %d missing %d pad bytes\n", 958 type, EXTRACT_16BITS(&pdtlv->length), aln - len); 959 } else { 960 pad = aln - EXTRACT_16BITS(&pdtlv->length); 961 } 962 } 963 if (pd_valid(type)) { 964 const struct pdata_ops *ops = get_forces_pd(type); 965 966 if (vflag >= 3 && ops->v != F_TLV_PDAT) { 967 if (pad) 968 printf 969 ("%s %s (Length %d DataLen %d pad %d Bytes)\n", 970 ib, ops->s, EXTRACT_16BITS(&pdtlv->length), 971 tll, pad); 972 else 973 printf 974 ("%s %s (Length %d DataLen %d Bytes)\n", 975 ib, ops->s, EXTRACT_16BITS(&pdtlv->length), 976 tll); 977 } 978 979 chk_op_type(type, op_msk, ops->op_msk); 980 981 if (ops->print((const u_char *)pdtlv, 982 tll + pad + TLV_HDRL, op_msk, 983 indent + 2) == -1) 984 return -1; 985 len -= (TLV_HDRL + pad + tll); 986 } else { 987 printf("Invalid path data content type 0x%x len %d\n", 988 type, EXTRACT_16BITS(&pdtlv->length)); 989 pd_err: 990 if (EXTRACT_16BITS(&pdtlv->length)) { 991 hex_print_with_offset("Bad Data val\n\t [", 992 pptr, len, 0); 993 printf("]\n"); 994 995 return -1; 996 } 997 } 998 } 999 return len; 1000 1001 trunc: 1002 fputs("[|forces]", stdout); 1003 return -1; 1004 } 1005 1006 static int 1007 pdata_print(register const u_char * pptr, register u_int len, 1008 u_int16_t op_msk, int indent) 1009 { 1010 const struct pathdata_h *pdh = (struct pathdata_h *)pptr; 1011 char *ib = indent_pr(indent, 0); 1012 u_int minsize = 0; 1013 int more_pd = 0; 1014 u_int16_t idcnt = 0; 1015 1016 TCHECK(*pdh); 1017 if (len < sizeof(struct pathdata_h)) 1018 goto trunc; 1019 if (vflag >= 3) { 1020 printf("\n%sPathdata: Flags 0x%x ID count %d\n", 1021 ib, EXTRACT_16BITS(&pdh->pflags), EXTRACT_16BITS(&pdh->pIDcnt)); 1022 } 1023 1024 if (EXTRACT_16BITS(&pdh->pflags) & F_SELKEY) { 1025 op_msk |= B_KEYIN; 1026 } 1027 1028 /* Table GET Range operation */ 1029 if (EXTRACT_16BITS(&pdh->pflags) & F_SELTABRANGE) { 1030 op_msk |= B_TRNG; 1031 } 1032 /* Table SET append operation */ 1033 if (EXTRACT_16BITS(&pdh->pflags) & F_TABAPPEND) { 1034 op_msk |= B_APPND; 1035 } 1036 1037 pptr += sizeof(struct pathdata_h); 1038 len -= sizeof(struct pathdata_h); 1039 idcnt = EXTRACT_16BITS(&pdh->pIDcnt); 1040 minsize = idcnt * 4; 1041 if (len < minsize) { 1042 printf("\t\t\ttruncated IDs expected %uB got %uB\n", minsize, 1043 len); 1044 hex_print_with_offset("\t\t\tID Data[", pptr, len, 0); 1045 printf("]\n"); 1046 return -1; 1047 } 1048 1049 if ((op_msk & B_TRNG) && (op_msk & B_KEYIN)) { 1050 printf("\t\t\tIllegal to have both Table ranges and keys\n"); 1051 return -1; 1052 } 1053 1054 more_pd = pdatacnt_print(pptr, len, idcnt, op_msk, indent); 1055 if (more_pd > 0) { 1056 int consumed = len - more_pd; 1057 pptr += consumed; 1058 len = more_pd; 1059 /* XXX: Argh, recurse some more */ 1060 return recpdoptlv_print(pptr, len, op_msk, indent+1); 1061 } else 1062 return 0; 1063 1064 trunc: 1065 fputs("[|forces]", stdout); 1066 return -1; 1067 } 1068 1069 static int 1070 genoptlv_print(register const u_char * pptr, register u_int len, 1071 u_int16_t op_msk, int indent) 1072 { 1073 const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; 1074 u_int16_t type; 1075 int tll; 1076 int invtlv; 1077 char *ib = indent_pr(indent, 0); 1078 1079 TCHECK(*pdtlv); 1080 type = EXTRACT_16BITS(&pdtlv->type); 1081 tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; 1082 invtlv = tlv_valid(pdtlv, len); 1083 printf("genoptlvprint - %s TLV type 0x%x len %d\n", 1084 tok2str(ForCES_TLV, NULL, type), type, EXTRACT_16BITS(&pdtlv->length)); 1085 if (!invtlv) { 1086 /* 1087 * At this point, tlv_valid() has ensured that the TLV 1088 * length is large enough but not too large (it doesn't 1089 * go past the end of the containing TLV). 1090 */ 1091 register const u_char *dp = (u_char *) TLV_DATA(pdtlv); 1092 if (!ttlv_valid(type)) { 1093 printf("%s TLV type 0x%x len %d\n", 1094 tok2str(ForCES_TLV_err, NULL, invtlv), type, 1095 EXTRACT_16BITS(&pdtlv->length)); 1096 return -1; 1097 } 1098 if (vflag >= 3) 1099 printf("%s%s, length %d (data length %d Bytes)", 1100 ib, tok2str(ForCES_TLV, NULL, type), 1101 EXTRACT_16BITS(&pdtlv->length), tll); 1102 1103 return pdata_print(dp, tll, op_msk, indent + 1); 1104 } else { 1105 printf("\t\t\tInvalid ForCES TLV type=%x", type); 1106 return -1; 1107 } 1108 1109 trunc: 1110 fputs("[|forces]", stdout); 1111 return -1; 1112 } 1113 1114 static int 1115 recpdoptlv_print(register const u_char * pptr, register u_int len, 1116 u_int16_t op_msk, int indent) 1117 { 1118 const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; 1119 int tll; 1120 int invtlv; 1121 u_int16_t type; 1122 register const u_char *dp; 1123 char *ib; 1124 1125 while (len != 0) { 1126 TCHECK(*pdtlv); 1127 invtlv = tlv_valid(pdtlv, len); 1128 if (invtlv) { 1129 break; 1130 } 1131 1132 /* 1133 * At this point, tlv_valid() has ensured that the TLV 1134 * length is large enough but not too large (it doesn't 1135 * go past the end of the containing TLV). 1136 */ 1137 ib = indent_pr(indent, 0); 1138 type = EXTRACT_16BITS(&pdtlv->type); 1139 dp = (u_char *) TLV_DATA(pdtlv); 1140 tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; 1141 1142 if (vflag >= 3) 1143 printf 1144 ("%s%s, length %d (data encapsulated %d Bytes)", 1145 ib, tok2str(ForCES_TLV, NULL, type), 1146 EXTRACT_16BITS(&pdtlv->length), 1147 EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL); 1148 1149 if (pdata_print(dp, tll, op_msk, indent + 1) == -1) 1150 return -1; 1151 pdtlv = GO_NXT_TLV(pdtlv, len); 1152 } 1153 1154 if (len) { 1155 printf 1156 ("\n\t\tMessy PATHDATA TLV header, type (0x%x)\n\t\texcess of %d Bytes ", 1157 EXTRACT_16BITS(&pdtlv->type), len - EXTRACT_16BITS(&pdtlv->length)); 1158 return -1; 1159 } 1160 1161 return 0; 1162 1163 trunc: 1164 fputs("[|forces]", stdout); 1165 return -1; 1166 } 1167 1168 static int 1169 invoptlv_print(register const u_char * pptr, register u_int len, 1170 u_int16_t op_msk _U_, int indent) 1171 { 1172 char *ib = indent_pr(indent, 1); 1173 1174 if (vflag >= 3) { 1175 printf("%sData[", &ib[1]); 1176 hex_print_with_offset(ib, pptr, len, 0); 1177 printf("%s]\n", ib); 1178 } 1179 return -1; 1180 } 1181 1182 static int 1183 otlv_print(const struct forces_tlv *otlv, u_int16_t op_msk _U_, int indent) 1184 { 1185 int rc = 0; 1186 register const u_char *dp = (u_char *) TLV_DATA(otlv); 1187 u_int16_t type; 1188 int tll; 1189 char *ib = indent_pr(indent, 0); 1190 const struct optlv_h *ops; 1191 1192 /* 1193 * lfbselect_print() has ensured that EXTRACT_16BITS(&otlv->length) 1194 * >= TLV_HDRL. 1195 */ 1196 TCHECK(*otlv); 1197 type = EXTRACT_16BITS(&otlv->type); 1198 tll = EXTRACT_16BITS(&otlv->length) - TLV_HDRL; 1199 ops = get_forces_optlv_h(type); 1200 if (vflag >= 3) { 1201 printf("%sOper TLV %s(0x%x) length %d\n", ib, ops->s, type, 1202 EXTRACT_16BITS(&otlv->length)); 1203 } 1204 /* empty TLVs like COMMIT and TRCOMMIT are empty, we stop here .. */ 1205 if (!ops->flags & ZERO_TTLV) { 1206 if (tll != 0) /* instead of "if (tll)" - for readability .. */ 1207 printf("%s: Illegal - MUST be empty\n", ops->s); 1208 return rc; 1209 } 1210 /* rest of ops must at least have 12B {pathinfo} */ 1211 if (tll < OP_MIN_SIZ) { 1212 printf("\t\tOper TLV %s(0x%x) length %d\n", ops->s, type, 1213 EXTRACT_16BITS(&otlv->length)); 1214 printf("\t\tTruncated data size %d minimum required %d\n", tll, 1215 OP_MIN_SIZ); 1216 return invoptlv_print(dp, tll, ops->op_msk, indent); 1217 1218 } 1219 1220 rc = ops->print(dp, tll, ops->op_msk, indent + 1); 1221 return rc; 1222 1223 trunc: 1224 fputs("[|forces]", stdout); 1225 return -1; 1226 } 1227 1228 #define ASTDLN 4 1229 #define ASTMCD 255 1230 static int 1231 asttlv_print(register const u_char * pptr, register u_int len, 1232 u_int16_t op_msk _U_, int indent) 1233 { 1234 u_int32_t rescode; 1235 u_int dlen; 1236 char *ib = indent_pr(indent, 0); 1237 1238 /* 1239 * forces_type_print() has ensured that len (the TLV length) 1240 * >= TLV_HDRL. 1241 */ 1242 dlen = len - TLV_HDRL; 1243 if (dlen != ASTDLN) { 1244 printf("illegal ASTresult-TLV: %d bytes!\n", dlen); 1245 return -1; 1246 } 1247 TCHECK2(*pptr, 4); 1248 rescode = EXTRACT_32BITS(pptr); 1249 if (rescode > ASTMCD) { 1250 printf("illegal ASTresult result code: %d!\n", rescode); 1251 return -1; 1252 } 1253 1254 if (vflag >= 3) { 1255 printf("Teardown reason:\n%s", ib); 1256 switch (rescode) { 1257 case 0: 1258 printf("Normal Teardown"); 1259 break; 1260 case 1: 1261 printf("Loss of Heartbeats"); 1262 break; 1263 case 2: 1264 printf("Out of bandwidth"); 1265 break; 1266 case 3: 1267 printf("Out of Memory"); 1268 break; 1269 case 4: 1270 printf("Application Crash"); 1271 break; 1272 default: 1273 printf("Unknown Teardown reason"); 1274 break; 1275 } 1276 printf("(%x)\n%s", rescode, ib); 1277 } 1278 return 0; 1279 1280 trunc: 1281 fputs("[|forces]", stdout); 1282 return -1; 1283 } 1284 1285 #define ASRDLN 4 1286 #define ASRMCD 3 1287 static int 1288 asrtlv_print(register const u_char * pptr, register u_int len, 1289 u_int16_t op_msk _U_, int indent) 1290 { 1291 u_int32_t rescode; 1292 u_int dlen; 1293 char *ib = indent_pr(indent, 0); 1294 1295 /* 1296 * forces_type_print() has ensured that len (the TLV length) 1297 * >= TLV_HDRL. 1298 */ 1299 dlen = len - TLV_HDRL; 1300 if (dlen != ASRDLN) { /* id, instance, oper tlv */ 1301 printf("illegal ASRresult-TLV: %d bytes!\n", dlen); 1302 return -1; 1303 } 1304 TCHECK2(*pptr, 4); 1305 rescode = EXTRACT_32BITS(pptr); 1306 1307 if (rescode > ASRMCD) { 1308 printf("illegal ASRresult result code: %d!\n", rescode); 1309 return -1; 1310 } 1311 1312 if (vflag >= 3) { 1313 printf("\n%s", ib); 1314 switch (rescode) { 1315 case 0: 1316 printf("Success "); 1317 break; 1318 case 1: 1319 printf("FE ID invalid "); 1320 break; 1321 case 2: 1322 printf("permission denied "); 1323 break; 1324 default: 1325 printf("Unknown "); 1326 break; 1327 } 1328 printf("(%x)\n%s", rescode, ib); 1329 } 1330 return 0; 1331 1332 trunc: 1333 fputs("[|forces]", stdout); 1334 return -1; 1335 } 1336 1337 #if 0 1338 /* 1339 * XXX - not used. 1340 */ 1341 static int 1342 gentltlv_print(register const u_char * pptr _U_, register u_int len, 1343 u_int16_t op_msk _U_, int indent _U_) 1344 { 1345 u_int dlen = len - TLV_HDRL; 1346 1347 if (dlen < 4) { /* at least 32 bits must exist */ 1348 printf("truncated TLV: %d bytes missing! ", 4 - dlen); 1349 return -1; 1350 } 1351 return 0; 1352 } 1353 #endif 1354 1355 #define RD_MIN 8 1356 1357 static int 1358 print_metailv(register const u_char * pptr, register u_int len, 1359 u_int16_t op_msk _U_, int indent) 1360 { 1361 u_int rlen; 1362 char *ib = indent_pr(indent, 0); 1363 /* XXX: check header length */ 1364 const struct forces_ilv *ilv = (struct forces_ilv *)pptr; 1365 1366 /* 1367 * print_metatlv() has ensured that len (what remains in the 1368 * ILV) >= ILV_HDRL. 1369 */ 1370 rlen = EXTRACT_32BITS(&ilv->length) - ILV_HDRL; 1371 TCHECK(*ilv); 1372 printf("%sMetaID 0x%x length %d\n", ib, EXTRACT_32BITS(&ilv->type), 1373 EXTRACT_32BITS(&ilv->length)); 1374 if (vflag >= 3) { 1375 hex_print_with_offset("\t\t[", ILV_DATA(ilv), rlen, 0); 1376 printf(" ]\n"); 1377 } 1378 return 0; 1379 1380 trunc: 1381 fputs("[|forces]", stdout); 1382 return -1; 1383 } 1384 1385 static int 1386 print_metatlv(register const u_char * pptr, register u_int len, 1387 u_int16_t op_msk _U_, int indent) 1388 { 1389 u_int dlen; 1390 char *ib = indent_pr(indent, 0); 1391 u_int rlen; 1392 const struct forces_ilv *ilv = (struct forces_ilv *)pptr; 1393 int invilv; 1394 1395 /* 1396 * redirect_print() has ensured that len (what remains in the 1397 * TLV) >= TLV_HDRL. 1398 */ 1399 dlen = len - TLV_HDRL; 1400 rlen = dlen; 1401 printf("\n%s METADATA length %d \n", ib, rlen); 1402 while (rlen != 0) { 1403 TCHECK(*ilv); 1404 invilv = ilv_valid(ilv, rlen); 1405 if (invilv) { 1406 break; 1407 } 1408 1409 /* 1410 * At this point, ilv_valid() has ensured that the ILV 1411 * length is large enough but not too large (it doesn't 1412 * go past the end of the containing TLV). 1413 */ 1414 print_metailv((u_char *) ilv, rlen, 0, indent + 1); 1415 ilv = GO_NXT_ILV(ilv, rlen); 1416 } 1417 1418 return 0; 1419 1420 trunc: 1421 fputs("[|forces]", stdout); 1422 return -1; 1423 } 1424 1425 1426 static int 1427 print_reddata(register const u_char * pptr, register u_int len, 1428 u_int16_t op_msk _U_, int indent _U_) 1429 { 1430 u_int dlen; 1431 char *ib = indent_pr(indent, 0); 1432 u_int rlen; 1433 1434 dlen = len - TLV_HDRL; 1435 rlen = dlen; 1436 printf("\n%s Redirect Data length %d \n", ib, rlen); 1437 1438 if (vflag >= 3) { 1439 printf("\t\t["); 1440 hex_print_with_offset("\n\t\t", pptr, rlen, 0); 1441 printf("\n\t\t]"); 1442 } 1443 1444 return 0; 1445 } 1446 1447 static int 1448 redirect_print(register const u_char * pptr, register u_int len, 1449 u_int16_t op_msk _U_, int indent) 1450 { 1451 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 1452 u_int dlen; 1453 u_int rlen; 1454 int invtlv; 1455 1456 /* 1457 * forces_type_print() has ensured that len (the TLV length) 1458 * >= TLV_HDRL. 1459 */ 1460 dlen = len - TLV_HDRL; 1461 if (dlen <= RD_MIN) { 1462 printf("\n\t\ttruncated Redirect TLV: %d bytes missing! ", 1463 RD_MIN - dlen); 1464 return -1; 1465 } 1466 1467 rlen = dlen; 1468 indent += 1; 1469 while (rlen != 0) { 1470 TCHECK(*tlv); 1471 invtlv = tlv_valid(tlv, rlen); 1472 if (invtlv) { 1473 printf("Bad Redirect data\n"); 1474 break; 1475 } 1476 1477 /* 1478 * At this point, tlv_valid() has ensured that the TLV 1479 * length is large enough but not too large (it doesn't 1480 * go past the end of the containing TLV). 1481 */ 1482 if (EXTRACT_16BITS(&tlv->type) == F_TLV_METD) { 1483 print_metatlv((u_char *) TLV_DATA(tlv), 1484 EXTRACT_16BITS(&tlv->length), 0, indent); 1485 } else if ((EXTRACT_16BITS(&tlv->type) == F_TLV_REDD)) { 1486 print_reddata((u_char *) TLV_DATA(tlv), 1487 EXTRACT_16BITS(&tlv->length), 0, indent); 1488 } else { 1489 printf("Unknown REDIRECT TLV 0x%x len %d\n", 1490 EXTRACT_16BITS(&tlv->type), 1491 EXTRACT_16BITS(&tlv->length)); 1492 } 1493 1494 tlv = GO_NXT_TLV(tlv, rlen); 1495 } 1496 1497 if (rlen) { 1498 printf 1499 ("\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %d Bytes ", 1500 EXTRACT_16BITS(&tlv->type), 1501 rlen - EXTRACT_16BITS(&tlv->length)); 1502 return -1; 1503 } 1504 1505 return 0; 1506 1507 trunc: 1508 fputs("[|forces]", stdout); 1509 return -1; 1510 } 1511 1512 #define OP_OFF 8 1513 #define OP_MIN 12 1514 1515 static int 1516 lfbselect_print(register const u_char * pptr, register u_int len, 1517 u_int16_t op_msk, int indent) 1518 { 1519 const struct forces_lfbsh *lfbs; 1520 const struct forces_tlv *otlv; 1521 char *ib = indent_pr(indent, 0); 1522 u_int dlen; 1523 u_int rlen; 1524 int invtlv; 1525 1526 /* 1527 * forces_type_print() has ensured that len (the TLV length) 1528 * >= TLV_HDRL. 1529 */ 1530 dlen = len - TLV_HDRL; 1531 if (dlen <= OP_MIN) { /* id, instance, oper tlv header .. */ 1532 printf("\n\t\ttruncated lfb selector: %d bytes missing! ", 1533 OP_MIN - dlen); 1534 return -1; 1535 } 1536 1537 /* 1538 * At this point, we know that dlen > OP_MIN; OP_OFF < OP_MIN, so 1539 * we also know that it's > OP_OFF. 1540 */ 1541 rlen = dlen - OP_OFF; 1542 1543 lfbs = (const struct forces_lfbsh *)pptr; 1544 TCHECK(*lfbs); 1545 if (vflag >= 3) { 1546 printf("\n%s%s(Classid %x) instance %x\n", 1547 ib, tok2str(ForCES_LFBs, NULL, EXTRACT_32BITS(&lfbs->class)), 1548 EXTRACT_32BITS(&lfbs->class), 1549 EXTRACT_32BITS(&lfbs->instance)); 1550 } 1551 1552 otlv = (struct forces_tlv *)(lfbs + 1); 1553 1554 indent += 1; 1555 while (rlen != 0) { 1556 TCHECK(*otlv); 1557 invtlv = tlv_valid(otlv, rlen); 1558 if (invtlv) 1559 break; 1560 1561 /* 1562 * At this point, tlv_valid() has ensured that the TLV 1563 * length is large enough but not too large (it doesn't 1564 * go past the end of the containing TLV). 1565 */ 1566 if (op_valid(EXTRACT_16BITS(&otlv->type), op_msk)) { 1567 otlv_print(otlv, 0, indent); 1568 } else { 1569 if (vflag < 3) 1570 printf("\n"); 1571 printf 1572 ("\t\tINValid oper-TLV type 0x%x length %d for this ForCES message\n", 1573 EXTRACT_16BITS(&otlv->type), EXTRACT_16BITS(&otlv->length)); 1574 invoptlv_print((u_char *)otlv, rlen, 0, indent); 1575 } 1576 otlv = GO_NXT_TLV(otlv, rlen); 1577 } 1578 1579 if (rlen) { 1580 printf 1581 ("\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %d Bytes ", 1582 EXTRACT_16BITS(&otlv->type), rlen - EXTRACT_16BITS(&otlv->length)); 1583 return -1; 1584 } 1585 1586 return 0; 1587 1588 trunc: 1589 fputs("[|forces]", stdout); 1590 return -1; 1591 } 1592 1593 static int 1594 forces_type_print(register const u_char * pptr, const struct forcesh *fhdr _U_, 1595 register u_int mlen, const struct tom_h *tops) 1596 { 1597 const struct forces_tlv *tltlv; 1598 u_int rlen; 1599 int invtlv; 1600 int rc = 0; 1601 int ttlv = 0; 1602 1603 /* 1604 * forces_print() has already checked that mlen >= ForCES_HDRL 1605 * by calling ForCES_HLN_VALID(). 1606 */ 1607 rlen = mlen - ForCES_HDRL; 1608 1609 if (rlen > TLV_HLN) { 1610 if (tops->flags & ZERO_TTLV) { 1611 printf("<0x%x>Illegal Top level TLV!\n", tops->flags); 1612 return -1; 1613 } 1614 } else { 1615 if (tops->flags & ZERO_MORE_TTLV) 1616 return 0; 1617 if (tops->flags & ONE_MORE_TTLV) { 1618 printf("\tTop level TLV Data missing!\n"); 1619 return -1; 1620 } 1621 } 1622 1623 if (tops->flags & ZERO_TTLV) { 1624 return 0; 1625 } 1626 1627 ttlv = tops->flags >> 4; 1628 tltlv = GET_TOP_TLV(pptr); 1629 1630 /*XXX: 15 top level tlvs will probably be fine 1631 You are nuts if you send more ;-> */ 1632 while (rlen != 0) { 1633 TCHECK(*tltlv); 1634 invtlv = tlv_valid(tltlv, rlen); 1635 if (invtlv) 1636 break; 1637 1638 /* 1639 * At this point, tlv_valid() has ensured that the TLV 1640 * length is large enough but not too large (it doesn't 1641 * go past the end of the packet). 1642 */ 1643 if (!ttlv_valid(EXTRACT_16BITS(&tltlv->type))) { 1644 printf("\n\tInvalid ForCES Top TLV type=0x%x", 1645 EXTRACT_16BITS(&tltlv->type)); 1646 return -1; 1647 } 1648 1649 if (vflag >= 3) 1650 printf("\t%s, length %d (data length %d Bytes)", 1651 tok2str(ForCES_TLV, NULL, EXTRACT_16BITS(&tltlv->type)), 1652 EXTRACT_16BITS(&tltlv->length), 1653 EXTRACT_16BITS(&tltlv->length) - TLV_HDRL); 1654 1655 rc = tops->print((u_char *) TLV_DATA(tltlv), 1656 EXTRACT_16BITS(&tltlv->length), tops->op_msk, 9); 1657 if (rc < 0) { 1658 return -1; 1659 } 1660 tltlv = GO_NXT_TLV(tltlv, rlen); 1661 ttlv--; 1662 if (ttlv <= 0) 1663 break; 1664 } 1665 /* 1666 * XXX - if ttlv != 0, does that mean that the packet was too 1667 * short, and didn't have *enough* TLVs in it? 1668 */ 1669 if (rlen) { 1670 printf("\tMess TopTLV header: min %u, total %d advertised %d ", 1671 TLV_HDRL, rlen, EXTRACT_16BITS(&tltlv->length)); 1672 return -1; 1673 } 1674 1675 return 0; 1676 1677 trunc: 1678 fputs("[|forces]", stdout); 1679 return -1; 1680 } 1681 1682 void 1683 forces_print(register const u_char * pptr, register u_int len) 1684 { 1685 const struct forcesh *fhdr; 1686 u_int mlen; 1687 u_int32_t flg_raw; 1688 const struct tom_h *tops; 1689 int rc = 0; 1690 1691 fhdr = (const struct forcesh *)pptr; 1692 TCHECK(*fhdr); 1693 if (!tom_valid(fhdr->fm_tom)) { 1694 printf("Invalid ForCES message type %d\n", fhdr->fm_tom); 1695 goto error; 1696 } 1697 1698 mlen = ForCES_BLN(fhdr); 1699 1700 tops = get_forces_tom(fhdr->fm_tom); 1701 if (tops->v == TOM_RSVD) { 1702 printf("\n\tUnknown ForCES message type=0x%x", fhdr->fm_tom); 1703 goto error; 1704 } 1705 1706 printf("\n\tForCES %s ", tops->s); 1707 if (!ForCES_HLN_VALID(mlen, len)) { 1708 printf 1709 ("Illegal ForCES pkt len - min %u, total recvd %d, advertised %d ", 1710 ForCES_HDRL, len, ForCES_BLN(fhdr)); 1711 goto error; 1712 } 1713 1714 TCHECK2(*(pptr + 20), 4); 1715 flg_raw = EXTRACT_32BITS(pptr + 20); 1716 if (vflag >= 1) { 1717 printf("\n\tForCES Version %d len %uB flags 0x%08x ", 1718 ForCES_V(fhdr), mlen, flg_raw); 1719 printf("\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%" PRIx64, 1720 ForCES_SID(fhdr), ForCES_node(ForCES_SID(fhdr)), 1721 ForCES_DID(fhdr), ForCES_node(ForCES_DID(fhdr)), 1722 EXTRACT_64BITS(fhdr->fm_cor)); 1723 1724 } 1725 if (vflag >= 2) { 1726 printf 1727 ("\n\tForCES flags:\n\t %s(0x%x), prio=%d, %s(0x%x),\n\t %s(0x%x), %s(0x%x)\n", 1728 ForCES_ACKp(ForCES_ACK(fhdr)), ForCES_ACK(fhdr), 1729 ForCES_PRI(fhdr), 1730 ForCES_EMp(ForCES_EM(fhdr)), ForCES_EM(fhdr), 1731 ForCES_ATp(ForCES_AT(fhdr)), ForCES_AT(fhdr), 1732 ForCES_TPp(ForCES_TP(fhdr)), ForCES_TP(fhdr)); 1733 printf 1734 ("\t Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n", 1735 ForCES_RS1(fhdr), ForCES_RS2(fhdr)); 1736 } 1737 rc = forces_type_print(pptr, fhdr, mlen, tops); 1738 if (rc < 0) { 1739 error: 1740 hex_print_with_offset("\n\t[", pptr, len, 0); 1741 printf("\n\t]"); 1742 return; 1743 } 1744 1745 if (vflag >= 4) { 1746 printf("\n\t Raw ForCES message\n\t ["); 1747 hex_print_with_offset("\n\t ", pptr, len, 0); 1748 printf("\n\t ]"); 1749 } 1750 printf("\n"); 1751 return; 1752 1753 trunc: 1754 fputs("[|forces]", stdout); 1755 } 1756