static inline u_int tlv_valid(const struct forces_tlv *tlv, u_int rlen) { if (rlen < TLV_HDRL) return INVALID_RLEN; if (EXTRACT_16BITS(&tlv->length) < TLV_HDRL) return INVALID_STLN; if (EXTRACT_16BITS(&tlv->length) > rlen) return INVALID_LTLN; if (rlen < F_ALN_LEN(EXTRACT_16BITS(&tlv->length))) return INVALID_ALEN; return 0; }
static inline int ilv_valid(const struct forces_ilv *ilv, u_int rlen) { if (rlen < ILV_HDRL) return INVALID_RLEN; if (EXTRACT_32BITS(&ilv->length) < ILV_HDRL) return INVALID_STLN; if (EXTRACT_32BITS(&ilv->length) > rlen) return INVALID_LTLN; if (rlen < F_ALN_LEN(EXTRACT_32BITS(&ilv->length))) return INVALID_ALEN; return 0; }
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; }