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 u_int plen; 1363 char *ib = indent_pr(indent, 0); 1364 /* XXX: check header length */ 1365 const struct forces_ilv *ilv = (struct forces_ilv *)pptr; 1366 1367 /* 1368 * print_metatlv() has ensured that len (what remains in the 1369 * ILV) >= ILV_HDRL. 1370 */ 1371 rlen = EXTRACT_32BITS(&ilv->length) - ILV_HDRL; 1372 TCHECK(*ilv); 1373 printf("%sMetaID 0x%x length %d\n", ib, EXTRACT_32BITS(&ilv->type), 1374 EXTRACT_32BITS(&ilv->length)); 1375 if (vflag >= 3) { 1376 hex_print_with_offset("\t\t[", ILV_DATA(ilv), rlen, 0); 1377 printf(" ]\n"); 1378 } 1379 return 0; 1380 1381 trunc: 1382 fputs("[|forces]", stdout); 1383 return -1; 1384 } 1385 1386 static int 1387 print_metatlv(register const u_char * pptr, register u_int len, 1388 u_int16_t op_msk _U_, int indent) 1389 { 1390 u_int dlen; 1391 char *ib = indent_pr(indent, 0); 1392 u_int rlen; 1393 const struct forces_ilv *ilv = (struct forces_ilv *)pptr; 1394 int invilv; 1395 1396 /* 1397 * redirect_print() has ensured that len (what remains in the 1398 * TLV) >= TLV_HDRL. 1399 */ 1400 dlen = len - TLV_HDRL; 1401 rlen = dlen; 1402 printf("\n%s METADATA length %d \n", ib, rlen); 1403 while (rlen != 0) { 1404 TCHECK(*ilv); 1405 invilv = ilv_valid(ilv, rlen); 1406 if (invilv) { 1407 break; 1408 } 1409 1410 /* 1411 * At this point, ilv_valid() has ensured that the ILV 1412 * length is large enough but not too large (it doesn't 1413 * go past the end of the containing TLV). 1414 */ 1415 print_metailv((u_char *) ilv, rlen, 0, indent + 1); 1416 ilv = GO_NXT_ILV(ilv, rlen); 1417 } 1418 1419 return 0; 1420 1421 trunc: 1422 fputs("[|forces]", stdout); 1423 return -1; 1424 } 1425 1426 1427 static int 1428 print_reddata(register const u_char * pptr, register u_int len, 1429 u_int16_t op_msk _U_, int indent _U_) 1430 { 1431 u_int dlen; 1432 char *ib = indent_pr(indent, 0); 1433 u_int rlen; 1434 1435 dlen = len - TLV_HDRL; 1436 rlen = dlen; 1437 printf("\n%s Redirect Data length %d \n", ib, rlen); 1438 1439 if (vflag >= 3) { 1440 printf("\t\t["); 1441 hex_print_with_offset("\n\t\t", pptr, rlen, 0); 1442 printf("\n\t\t]"); 1443 } 1444 1445 return 0; 1446 } 1447 1448 static int 1449 redirect_print(register const u_char * pptr, register u_int len, 1450 u_int16_t op_msk _U_, int indent) 1451 { 1452 const struct forces_tlv *tlv = (struct forces_tlv *)pptr; 1453 u_int dlen; 1454 u_int rlen; 1455 int invtlv; 1456 1457 /* 1458 * forces_type_print() has ensured that len (the TLV length) 1459 * >= TLV_HDRL. 1460 */ 1461 dlen = len - TLV_HDRL; 1462 if (dlen <= RD_MIN) { 1463 printf("\n\t\ttruncated Redirect TLV: %d bytes missing! ", 1464 RD_MIN - dlen); 1465 return -1; 1466 } 1467 1468 rlen = dlen; 1469 indent += 1; 1470 while (rlen != 0) { 1471 TCHECK(*tlv); 1472 invtlv = tlv_valid(tlv, rlen); 1473 if (invtlv) { 1474 printf("Bad Redirect data\n"); 1475 break; 1476 } 1477 1478 /* 1479 * At this point, tlv_valid() has ensured that the TLV 1480 * length is large enough but not too large (it doesn't 1481 * go past the end of the containing TLV). 1482 */ 1483 if (EXTRACT_16BITS(&tlv->type) == F_TLV_METD) { 1484 print_metatlv((u_char *) TLV_DATA(tlv), 1485 EXTRACT_16BITS(&tlv->length), 0, indent); 1486 } else if ((EXTRACT_16BITS(&tlv->type) == F_TLV_REDD)) { 1487 print_reddata((u_char *) TLV_DATA(tlv), 1488 EXTRACT_16BITS(&tlv->length), 0, indent); 1489 } else { 1490 printf("Unknown REDIRECT TLV 0x%x len %d\n", 1491 EXTRACT_16BITS(&tlv->type), 1492 EXTRACT_16BITS(&tlv->length)); 1493 } 1494 1495 tlv = GO_NXT_TLV(tlv, rlen); 1496 } 1497 1498 if (rlen) { 1499 printf 1500 ("\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %d Bytes ", 1501 EXTRACT_16BITS(&tlv->type), 1502 rlen - EXTRACT_16BITS(&tlv->length)); 1503 return -1; 1504 } 1505 1506 return 0; 1507 1508 trunc: 1509 fputs("[|forces]", stdout); 1510 return -1; 1511 } 1512 1513 #define OP_OFF 8 1514 #define OP_MIN 12 1515 1516 static int 1517 lfbselect_print(register const u_char * pptr, register u_int len, 1518 u_int16_t op_msk, int indent) 1519 { 1520 const struct forces_lfbsh *lfbs; 1521 const struct forces_tlv *otlv; 1522 char *ib = indent_pr(indent, 0); 1523 u_int dlen; 1524 u_int rlen; 1525 int invtlv; 1526 1527 /* 1528 * forces_type_print() has ensured that len (the TLV length) 1529 * >= TLV_HDRL. 1530 */ 1531 dlen = len - TLV_HDRL; 1532 if (dlen <= OP_MIN) { /* id, instance, oper tlv header .. */ 1533 printf("\n\t\ttruncated lfb selector: %d bytes missing! ", 1534 OP_MIN - dlen); 1535 return -1; 1536 } 1537 1538 /* 1539 * At this point, we know that dlen > OP_MIN; OP_OFF < OP_MIN, so 1540 * we also know that it's > OP_OFF. 1541 */ 1542 rlen = dlen - OP_OFF; 1543 1544 lfbs = (const struct forces_lfbsh *)pptr; 1545 TCHECK(*lfbs); 1546 if (vflag >= 3) { 1547 printf("\n%s%s(Classid %x) instance %x\n", 1548 ib, tok2str(ForCES_LFBs, NULL, EXTRACT_32BITS(&lfbs->class)), 1549 EXTRACT_32BITS(&lfbs->class), 1550 EXTRACT_32BITS(&lfbs->instance)); 1551 } 1552 1553 otlv = (struct forces_tlv *)(lfbs + 1); 1554 1555 indent += 1; 1556 while (rlen != 0) { 1557 TCHECK(*otlv); 1558 invtlv = tlv_valid(otlv, rlen); 1559 if (invtlv) 1560 break; 1561 1562 /* 1563 * At this point, tlv_valid() has ensured that the TLV 1564 * length is large enough but not too large (it doesn't 1565 * go past the end of the containing TLV). 1566 */ 1567 if (op_valid(EXTRACT_16BITS(&otlv->type), op_msk)) { 1568 otlv_print(otlv, 0, indent); 1569 } else { 1570 if (vflag < 3) 1571 printf("\n"); 1572 printf 1573 ("\t\tINValid oper-TLV type 0x%x length %d for this ForCES message\n", 1574 EXTRACT_16BITS(&otlv->type), EXTRACT_16BITS(&otlv->length)); 1575 invoptlv_print((u_char *)otlv, rlen, 0, indent); 1576 } 1577 otlv = GO_NXT_TLV(otlv, rlen); 1578 } 1579 1580 if (rlen) { 1581 printf 1582 ("\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %d Bytes ", 1583 EXTRACT_16BITS(&otlv->type), rlen - EXTRACT_16BITS(&otlv->length)); 1584 return -1; 1585 } 1586 1587 return 0; 1588 1589 trunc: 1590 fputs("[|forces]", stdout); 1591 return -1; 1592 } 1593 1594 static int 1595 forces_type_print(register const u_char * pptr, const struct forcesh *fhdr _U_, 1596 register u_int mlen, const struct tom_h *tops) 1597 { 1598 const struct forces_tlv *tltlv; 1599 u_int rlen; 1600 int invtlv; 1601 int rc = 0; 1602 int ttlv = 0; 1603 1604 /* 1605 * forces_print() has already checked that mlen >= ForCES_HDRL 1606 * by calling ForCES_HLN_VALID(). 1607 */ 1608 rlen = mlen - ForCES_HDRL; 1609 1610 if (rlen > TLV_HLN) { 1611 if (tops->flags & ZERO_TTLV) { 1612 printf("<0x%x>Illegal Top level TLV!\n", tops->flags); 1613 return -1; 1614 } 1615 } else { 1616 if (tops->flags & ZERO_MORE_TTLV) 1617 return 0; 1618 if (tops->flags & ONE_MORE_TTLV) { 1619 printf("\tTop level TLV Data missing!\n"); 1620 return -1; 1621 } 1622 } 1623 1624 if (tops->flags & ZERO_TTLV) { 1625 return 0; 1626 } 1627 1628 ttlv = tops->flags >> 4; 1629 tltlv = GET_TOP_TLV(pptr); 1630 1631 /*XXX: 15 top level tlvs will probably be fine 1632 You are nuts if you send more ;-> */ 1633 while (rlen != 0) { 1634 TCHECK(*tltlv); 1635 invtlv = tlv_valid(tltlv, rlen); 1636 if (invtlv) 1637 break; 1638 1639 /* 1640 * At this point, tlv_valid() has ensured that the TLV 1641 * length is large enough but not too large (it doesn't 1642 * go past the end of the packet). 1643 */ 1644 if (!ttlv_valid(EXTRACT_16BITS(&tltlv->type))) { 1645 printf("\n\tInvalid ForCES Top TLV type=0x%x", 1646 EXTRACT_16BITS(&tltlv->type)); 1647 return -1; 1648 } 1649 1650 if (vflag >= 3) 1651 printf("\t%s, length %d (data length %d Bytes)", 1652 tok2str(ForCES_TLV, NULL, EXTRACT_16BITS(&tltlv->type)), 1653 EXTRACT_16BITS(&tltlv->length), 1654 EXTRACT_16BITS(&tltlv->length) - TLV_HDRL); 1655 1656 rc = tops->print((u_char *) TLV_DATA(tltlv), 1657 EXTRACT_16BITS(&tltlv->length), tops->op_msk, 9); 1658 if (rc < 0) { 1659 return -1; 1660 } 1661 tltlv = GO_NXT_TLV(tltlv, rlen); 1662 ttlv--; 1663 if (ttlv <= 0) 1664 break; 1665 } 1666 /* 1667 * XXX - if ttlv != 0, does that mean that the packet was too 1668 * short, and didn't have *enough* TLVs in it? 1669 */ 1670 if (rlen) { 1671 printf("\tMess TopTLV header: min %u, total %d advertised %d ", 1672 TLV_HDRL, rlen, EXTRACT_16BITS(&tltlv->length)); 1673 return -1; 1674 } 1675 1676 return 0; 1677 1678 trunc: 1679 fputs("[|forces]", stdout); 1680 return -1; 1681 } 1682 1683 void 1684 forces_print(register const u_char * pptr, register u_int len) 1685 { 1686 const struct forcesh *fhdr; 1687 u_int mlen; 1688 u_int32_t flg_raw; 1689 const struct tom_h *tops; 1690 int rc = 0; 1691 1692 fhdr = (const struct forcesh *)pptr; 1693 TCHECK(*fhdr); 1694 if (!tom_valid(fhdr->fm_tom)) { 1695 printf("Invalid ForCES message type %d\n", fhdr->fm_tom); 1696 goto error; 1697 } 1698 1699 mlen = ForCES_BLN(fhdr); 1700 1701 tops = get_forces_tom(fhdr->fm_tom); 1702 if (tops->v == TOM_RSVD) { 1703 printf("\n\tUnknown ForCES message type=0x%x", fhdr->fm_tom); 1704 goto error; 1705 } 1706 1707 printf("\n\tForCES %s ", tops->s); 1708 if (!ForCES_HLN_VALID(mlen, len)) { 1709 printf 1710 ("Illegal ForCES pkt len - min %u, total recvd %d, advertised %d ", 1711 ForCES_HDRL, len, ForCES_BLN(fhdr)); 1712 goto error; 1713 } 1714 1715 TCHECK2(*(pptr + 20), 4); 1716 flg_raw = EXTRACT_32BITS(pptr + 20); 1717 if (vflag >= 1) { 1718 printf("\n\tForCES Version %d len %uB flags 0x%08x ", 1719 ForCES_V(fhdr), mlen, flg_raw); 1720 printf("\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%" PRIx64, 1721 ForCES_SID(fhdr), ForCES_node(ForCES_SID(fhdr)), 1722 ForCES_DID(fhdr), ForCES_node(ForCES_DID(fhdr)), 1723 EXTRACT_64BITS(fhdr->fm_cor)); 1724 1725 } 1726 if (vflag >= 2) { 1727 printf 1728 ("\n\tForCES flags:\n\t %s(0x%x), prio=%d, %s(0x%x),\n\t %s(0x%x), %s(0x%x)\n", 1729 ForCES_ACKp(ForCES_ACK(fhdr)), ForCES_ACK(fhdr), 1730 ForCES_PRI(fhdr), 1731 ForCES_EMp(ForCES_EM(fhdr)), ForCES_EM(fhdr), 1732 ForCES_ATp(ForCES_AT(fhdr)), ForCES_AT(fhdr), 1733 ForCES_TPp(ForCES_TP(fhdr)), ForCES_TP(fhdr)); 1734 printf 1735 ("\t Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n", 1736 ForCES_RS1(fhdr), ForCES_RS2(fhdr)); 1737 } 1738 rc = forces_type_print(pptr, fhdr, mlen, tops); 1739 if (rc < 0) { 1740 error: 1741 hex_print_with_offset("\n\t[", pptr, len, 0); 1742 printf("\n\t]"); 1743 return; 1744 } 1745 1746 if (vflag >= 4) { 1747 printf("\n\t Raw ForCES message\n\t ["); 1748 hex_print_with_offset("\n\t ", pptr, len, 0); 1749 printf("\n\t ]"); 1750 } 1751 printf("\n"); 1752 return; 1753 1754 trunc: 1755 fputs("[|forces]", stdout); 1756 } 1757