int otlv_print(const struct forces_tlv *otlv, u_int16_t op_msk _U_, int indent) { int rc = 0; register const u_char *dp = (u_char *) TLV_DATA(otlv); u_int16_t type; int tll; char *ib = indent_pr(indent, 0); const struct optlv_h *ops; /* * lfbselect_print() has ensured that EXTRACT_16BITS(&otlv->length) * >= TLV_HDRL. */ TCHECK(*otlv); type = EXTRACT_16BITS(&otlv->type); tll = EXTRACT_16BITS(&otlv->length) - TLV_HDRL; ops = get_forces_optlv_h(type); if (vflag >= 3) { printf("%sOper TLV %s(0x%x) length %d\n", ib, ops->s, type, EXTRACT_16BITS(&otlv->length)); } /* empty TLVs like COMMIT and TRCOMMIT are empty, we stop here .. */ if (!ops->flags & ZERO_TTLV) { if (tll != 0) /* instead of "if (tll)" - for readability .. */ printf("%s: Illegal - MUST be empty\n", ops->s); return rc; } /* rest of ops must at least have 12B {pathinfo} */ if (tll < OP_MIN_SIZ) { printf("\t\tOper TLV %s(0x%x) length %d\n", ops->s, type, EXTRACT_16BITS(&otlv->length)); printf("\t\tTruncated data size %d minimum required %d\n", tll, OP_MIN_SIZ); return invoptlv_print(dp, tll, ops->op_msk, indent); } rc = ops->print(dp, tll, ops->op_msk, indent + 1); return rc; trunc: fputs("[|forces]", stdout); return -1; }
int genoptlv_print(register const u_char * pptr, register u_int len, u_int16_t op_msk, int indent) { const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; u_int16_t type; int tll; int invtlv; char *ib = indent_pr(indent, 0); TCHECK(*pdtlv); type = EXTRACT_16BITS(&pdtlv->type); tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; invtlv = tlv_valid(pdtlv, len); printf("genoptlvprint - %s TLV type 0x%x len %d\n", tok2str(ForCES_TLV, NULL, type), type, EXTRACT_16BITS(&pdtlv->length)); if (!invtlv) { /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ register const u_char *dp = (u_char *) TLV_DATA(pdtlv); if (!ttlv_valid(type)) { printf("%s TLV type 0x%x len %d\n", tok2str(ForCES_TLV_err, NULL, invtlv), type, EXTRACT_16BITS(&pdtlv->length)); return -1; } if (vflag >= 3) printf("%s%s, length %d (data length %d Bytes)", ib, tok2str(ForCES_TLV, NULL, type), EXTRACT_16BITS(&pdtlv->length), tll); return pdata_print(dp, tll, op_msk, indent + 1); } else { printf("\t\t\tInvalid ForCES TLV type=%x", type); return -1; } trunc: fputs("[|forces]", stdout); return -1; }
static int otlv_print(netdissect_options *ndo, const struct forces_tlv *otlv, uint16_t op_msk _U_, int indent) { int rc = 0; register const u_char *dp = (u_char *) TLV_DATA(otlv); uint16_t type; int tll; char *ib = indent_pr(indent, 0); const struct optlv_h *ops; /* * lfbselect_print() has ensured that EXTRACT_16BITS(&otlv->length) * >= TLV_HDRL. */ ND_TCHECK(*otlv); type = EXTRACT_16BITS(&otlv->type); tll = EXTRACT_16BITS(&otlv->length) - TLV_HDRL; ops = get_forces_optlv_h(type); if (ndo->ndo_vflag >= 3) { ND_PRINT((ndo, "%sOper TLV %s(0x%x) length %d\n", ib, ops->s, type, EXTRACT_16BITS(&otlv->length))); } /* rest of ops must at least have 12B {pathinfo} */ if (tll < OP_MIN_SIZ) { ND_PRINT((ndo, "\t\tOper TLV %s(0x%x) length %d\n", ops->s, type, EXTRACT_16BITS(&otlv->length))); ND_PRINT((ndo, "\t\tTruncated data size %d minimum required %d\n", tll, OP_MIN_SIZ)); return invoptlv_print(ndo, dp, tll, ops->op_msk, indent); } /* XXX - do anything with ops->flags? */ if(ops->print) { rc = ops->print(ndo, dp, tll, ops->op_msk, indent + 1); } return rc; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; }
int sdatailv_print(register const u_char * pptr, register u_int len, u_int16_t op_msk _U_, int indent) { u_int rlen; const struct forces_ilv *ilv = (struct forces_ilv *)pptr; int invilv; if (len < ILV_HDRL) { printf("Error: BAD SPARSEDATA-TLV!\n"); return -1; } rlen = len; indent += 1; while (rlen != 0) { char *ib = indent_pr(indent, 1); register const u_char *tdp = (u_char *) ILV_DATA(ilv); TCHECK(*ilv); invilv = ilv_valid(ilv, rlen); if (invilv) { printf("%s[", &ib[1]); hex_print_with_offset(ib, tdp, rlen, 0); printf("\n%s]\n", &ib[1]); return -1; } if (vflag >= 3) { int ilvl = EXTRACT_32BITS(&ilv->length); printf("\n%s ILV: type %x length %d\n", &ib[1], EXTRACT_32BITS(&ilv->type), ilvl); hex_print_with_offset("\t\t[", tdp, ilvl-ILV_HDRL, 0); } ilv = GO_NXT_ILV(ilv, rlen); } return 0; trunc: fputs("[|forces]", stdout); return -1; }
static int pkeyitlv_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, u_int16_t op_msk, int indent) { const struct forces_tlv *tlv = (struct forces_tlv *)pptr; register const u_char *tdp = (u_char *) TLV_DATA(tlv); register const u_char *dp = tdp + 4; const struct forces_tlv *kdtlv = (struct forces_tlv *)dp; u_int32_t id; char *ib = indent_pr(indent, 0); u_int16_t type, tll; u_int invtlv; ND_TCHECK(*tdp); id = EXTRACT_32BITS(tdp); ND_PRINT((ndo, "%sKeyinfo: Key 0x%x\n", ib, id)); ND_TCHECK(*kdtlv); type = EXTRACT_16BITS(&kdtlv->type); invtlv = tlv_valid(kdtlv, len); if (invtlv) { ND_PRINT((ndo, "%s TLV type 0x%x len %d\n", tok2str(ForCES_TLV_err, NULL, invtlv), type, EXTRACT_16BITS(&kdtlv->length))); return -1; } /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ tll = EXTRACT_16BITS(&kdtlv->length); dp = (u_char *) TLV_DATA(kdtlv); return fdatatlv_print(ndo, dp, tll, op_msk, indent); trunc: ND_PRINT((ndo, "%s", tstr)); return -1; }
static int prestlv_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, u_int16_t op_msk _U_, int indent) { const struct forces_tlv *tlv = (struct forces_tlv *)pptr; register const u_char *tdp = (u_char *) TLV_DATA(tlv); struct res_val *r = (struct res_val *)tdp; u_int dlen; /* * pdatacnt_print() has ensured that len (the TLV length) * >= TLV_HDRL. */ dlen = len - TLV_HDRL; if (dlen != RESLEN) { ND_PRINT((ndo, "illegal RESULT-TLV: %d bytes!\n", dlen)); return -1; } ND_TCHECK(*r); if (r->result >= 0x18 && r->result <= 0xFE) { ND_PRINT((ndo, "illegal reserved result code: 0x%x!\n", r->result)); return -1; } if (ndo->ndo_vflag >= 3) { char *ib = indent_pr(indent, 0); ND_PRINT((ndo, "%s Result: %s (code 0x%x)\n", ib, tok2str(ForCES_errs, NULL, r->result), r->result)); } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; }
int prestlv_print(register const u_char * pptr, register u_int len, u_int16_t op_msk _U_, int indent) { const struct forces_tlv *tlv = (struct forces_tlv *)pptr; register const u_char *tdp = (u_char *) TLV_DATA(tlv); struct res_val *r = (struct res_val *)tdp; u_int dlen; /* * pdatacnt_print() has ensured that len (the TLV length) * >= TLV_HDRL. */ dlen = len - TLV_HDRL; if (dlen != RESLEN) { printf("illegal RESULT-TLV: %d bytes!\n", dlen); return -1; } TCHECK(*r); if (r->result >= 0x18 && r->result <= 0xFE) { printf("illegal reserved result code: 0x%x!\n", r->result); return -1; } if (vflag >= 3) { char *ib = indent_pr(indent, 0); printf("%s Result: %s (code 0x%x)\n", ib, tok2str(ForCES_errs, NULL, r->result), r->result); } return 0; trunc: fputs("[|forces]", stdout); return -1; }
static int pdata_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, u_int16_t op_msk, int indent) { const struct pathdata_h *pdh = (struct pathdata_h *)pptr; char *ib = indent_pr(indent, 0); u_int minsize = 0; int more_pd = 0; u_int16_t idcnt = 0; ND_TCHECK(*pdh); if (len < sizeof(struct pathdata_h)) goto trunc; if (ndo->ndo_vflag >= 3) { ND_PRINT((ndo, "\n%sPathdata: Flags 0x%x ID count %d\n", ib, EXTRACT_16BITS(&pdh->pflags), EXTRACT_16BITS(&pdh->pIDcnt))); } if (EXTRACT_16BITS(&pdh->pflags) & F_SELKEY) { op_msk |= B_KEYIN; } /* Table GET Range operation */ if (EXTRACT_16BITS(&pdh->pflags) & F_SELTABRANGE) { op_msk |= B_TRNG; } /* Table SET append operation */ if (EXTRACT_16BITS(&pdh->pflags) & F_TABAPPEND) { op_msk |= B_APPND; } pptr += sizeof(struct pathdata_h); len -= sizeof(struct pathdata_h); idcnt = EXTRACT_16BITS(&pdh->pIDcnt); minsize = idcnt * 4; if (len < minsize) { ND_PRINT((ndo, "\t\t\ttruncated IDs expected %uB got %uB\n", minsize, len)); hex_print_with_offset(ndo, "\t\t\tID Data[", pptr, len, 0); ND_PRINT((ndo, "]\n")); return -1; } if ((op_msk & B_TRNG) && (op_msk & B_KEYIN)) { ND_PRINT((ndo, "\t\t\tIllegal to have both Table ranges and keys\n")); return -1; } more_pd = pdatacnt_print(ndo, pptr, len, idcnt, op_msk, indent); if (more_pd > 0) { int consumed = len - more_pd; pptr += consumed; len = more_pd; /* XXX: Argh, recurse some more */ return recpdoptlv_print(ndo, pptr, len, op_msk, indent+1); } else return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; }
static int pdatacnt_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, u_int16_t IDcnt, u_int16_t op_msk, int indent) { u_int i; u_int32_t id; char *ib = indent_pr(indent, 0); if ((op_msk & B_APPND) && ndo->ndo_vflag >= 3) { ND_PRINT((ndo, "%sTABLE APPEND\n", ib)); } for (i = 0; i < IDcnt; i++) { ND_TCHECK2(*pptr, 4); if (len < 4) goto trunc; id = EXTRACT_32BITS(pptr); if (ndo->ndo_vflag >= 3) ND_PRINT((ndo, "%sID#%02u: %d\n", ib, i + 1, id)); len -= 4; pptr += 4; } if ((op_msk & B_TRNG) || (op_msk & B_KEYIN)) { if (op_msk & B_TRNG) { u_int32_t starti, endi; if (len < PTH_DESC_SIZE) { ND_PRINT((ndo, "pathlength %d with key/range too short %d\n", len, PTH_DESC_SIZE)); return -1; } pptr += sizeof(struct forces_tlv); len -= sizeof(struct forces_tlv); starti = EXTRACT_32BITS(pptr); pptr += 4; len -= 4; endi = EXTRACT_32BITS(pptr); pptr += 4; len -= 4; if (ndo->ndo_vflag >= 3) ND_PRINT((ndo, "%sTable range: [%d,%d]\n", ib, starti, endi)); } if (op_msk & B_KEYIN) { struct forces_tlv *keytlv; u_int16_t tll; if (len < PTH_DESC_SIZE) { ND_PRINT((ndo, "pathlength %d with key/range too short %d\n", len, PTH_DESC_SIZE)); return -1; } /* skip keyid */ pptr += 4; len -= 4; keytlv = (struct forces_tlv *)pptr; /* skip header */ pptr += sizeof(struct forces_tlv); len -= sizeof(struct forces_tlv); /* skip key content */ tll = EXTRACT_16BITS(&keytlv->length); if (tll < TLV_HDRL) { ND_PRINT((ndo, "key content length %u < %u\n", tll, TLV_HDRL)); return -1; } tll -= TLV_HDRL; if (len < tll) { ND_PRINT((ndo, "key content too short\n")); return -1; } pptr += tll; len -= tll; } } if (len) { const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; u_int16_t type; u_int16_t tll; int pad = 0; u_int aln; u_int invtlv; ND_TCHECK(*pdtlv); type = EXTRACT_16BITS(&pdtlv->type); invtlv = tlv_valid(pdtlv, len); if (invtlv) { ND_PRINT((ndo, "%s Outstanding bytes %d for TLV type 0x%x TLV len %d\n", tok2str(ForCES_TLV_err, NULL, invtlv), len, type, EXTRACT_16BITS(&pdtlv->length))); goto pd_err; } /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; aln = F_ALN_LEN(EXTRACT_16BITS(&pdtlv->length)); if (aln > EXTRACT_16BITS(&pdtlv->length)) { if (aln > len) { ND_PRINT((ndo, "Invalid padded pathdata TLV type 0x%x len %d missing %d pad bytes\n", type, EXTRACT_16BITS(&pdtlv->length), aln - len)); } else { pad = aln - EXTRACT_16BITS(&pdtlv->length); } } if (pd_valid(type)) { const struct pdata_ops *ops = get_forces_pd(type); if (ndo->ndo_vflag >= 3 && ops->v != F_TLV_PDAT) { if (pad) ND_PRINT((ndo, "%s %s (Length %d DataLen %d pad %d Bytes)\n", ib, ops->s, EXTRACT_16BITS(&pdtlv->length), tll, pad)); else ND_PRINT((ndo, "%s %s (Length %d DataLen %d Bytes)\n", ib, ops->s, EXTRACT_16BITS(&pdtlv->length), tll)); } chk_op_type(ndo, type, op_msk, ops->op_msk); if (ops->print(ndo, (const u_char *)pdtlv, tll + pad + TLV_HDRL, op_msk, indent + 2) == -1) return -1; len -= (TLV_HDRL + pad + tll); } else { ND_PRINT((ndo, "Invalid path data content type 0x%x len %d\n", type, EXTRACT_16BITS(&pdtlv->length))); pd_err: if (EXTRACT_16BITS(&pdtlv->length)) { hex_print_with_offset(ndo, "Bad Data val\n\t [", pptr, len, 0); ND_PRINT((ndo, "]\n")); return -1; } } } return len; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; }
int pdatacnt_print(register const u_char * pptr, register u_int len, u_int16_t IDcnt, u_int16_t op_msk, int indent) { u_int i; u_int32_t id; char *ib = indent_pr(indent, 0); for (i = 0; i < IDcnt; i++) { TCHECK2(*pptr, 4); if (len < 4) goto trunc; id = EXTRACT_32BITS(pptr); if (vflag >= 3) printf("%s ID#%02u: %d\n", ib, i + 1, id); len -= 4; pptr += 4; } if (len) { const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; u_int16_t type; u_int16_t tll; int pad = 0; u_int aln; int invtlv; TCHECK(*pdtlv); type = EXTRACT_16BITS(&pdtlv->type); invtlv = tlv_valid(pdtlv, len); if (invtlv) { printf ("%s Outstanding bytes %d for TLV type 0x%x TLV len %d\n", tok2str(ForCES_TLV_err, NULL, invtlv), len, type, EXTRACT_16BITS(&pdtlv->length)); goto pd_err; } /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; aln = F_ALN_LEN(EXTRACT_16BITS(&pdtlv->length)); if (aln > EXTRACT_16BITS(&pdtlv->length)) { if (aln > len) { printf ("Invalid padded pathdata TLV type 0x%x len %d missing %d pad bytes\n", type, EXTRACT_16BITS(&pdtlv->length), aln - len); } else { pad = aln - EXTRACT_16BITS(&pdtlv->length); } } if (pd_valid(type)) { const struct pdata_ops *ops = get_forces_pd(type); if (vflag >= 3 && ops->v != F_TLV_PDAT) { if (pad) printf ("%s %s (Length %d DataLen %d pad %d Bytes)\n", ib, ops->s, EXTRACT_16BITS(&pdtlv->length), tll, pad); else printf ("%s %s (Length %d DataLen %d Bytes)\n", ib, ops->s, EXTRACT_16BITS(&pdtlv->length), tll); } chk_op_type(type, op_msk, ops->op_msk); if (ops->print((const u_char *)pdtlv, tll + pad + TLV_HDRL, op_msk, indent + 2) == -1) return -1; len -= (TLV_HDRL + pad + tll); } else { printf("Invalid path data content type 0x%x len %d\n", type, EXTRACT_16BITS(&pdtlv->length)); pd_err: if (EXTRACT_16BITS(&pdtlv->length)) { hex_print_with_offset("Bad Data val\n\t [", pptr, len, 0); printf("]\n"); return -1; } } } return len; trunc: fputs("[|forces]", stdout); return -1; }