]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-forces.c
CI: Add warning exemptions for Sun C (suncc-5.14) on Solaris 10
[tcpdump] / print-forces.c
index 26e83d3167c7037fffb768db1ddf603ce9078d9d..197d6c65354704f984b728fb93143ed05d05448d 100644 (file)
  *
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+/* \summary: Forwarding and Control Element Separation (ForCES) Protocol printer */
+
+/* specification: RFC 5810 */
 
-#include <tcpdump-stdinc.h>
+#include <config.h>
 
-#include <stdio.h>
-#include <stdlib.h>
+#include "netdissect-stdinc.h"
 
-#include "interface.h"
+#define ND_LONGJMP_FROM_TCHECK
+#include "netdissect.h"
 #include "extract.h"
 
-#include "forces.h"
+
+#define        ForCES_VERS     1
+#define        ForCES_HDRL     24
+#define        ForCES_ALNL     4U
+#define TLV_HDRL       4
+#define ILV_HDRL       8
+
+#define TOM_RSVD       0x0
+#define TOM_ASSNSETUP  0x1
+#define TOM_ASSNTEARD  0x2
+#define TOM_CONFIG     0x3
+#define TOM_QUERY      0x4
+#define TOM_EVENTNOT   0x5
+#define TOM_PKTREDIR   0x6
+#define TOM_HEARTBT    0x0F
+#define TOM_ASSNSETREP 0x11
+#define TOM_CONFIGREP  0x13
+#define TOM_QUERYREP   0x14
+
+/*
+ * tom_h Flags: resv1(8b):maxtlvs(4b):resv2(2b):mintlv(2b)
+*/
+#define ZERO_TTLV      0x01
+#define ZERO_MORE_TTLV 0x02
+#define ONE_MORE_TTLV  0x04
+#define ZERO_TLV       0x00
+#define ONE_TLV                0x10
+#define TWO_TLV                0x20
+#define MAX_TLV                0xF0
+
+#define TTLV_T1                (ONE_MORE_TTLV|ONE_TLV)
+#define TTLV_T2                (ONE_MORE_TTLV|MAX_TLV)
+
+struct tom_h {
+       uint32_t v;
+       uint16_t flags;
+       uint16_t op_msk;
+       const char *s;
+       int (*print) (netdissect_options *ndo, const u_char * pptr, u_int len,
+                     uint16_t op_msk, int indent);
+};
+
+enum {
+       TOM_RSV_I,
+       TOM_ASS_I,
+       TOM_AST_I,
+       TOM_CFG_I,
+       TOM_QRY_I,
+       TOM_EVN_I,
+       TOM_RED_I,
+       TOM_HBT_I,
+       TOM_ASR_I,
+       TOM_CNR_I,
+       TOM_QRR_I,
+       _TOM_RSV_MAX
+};
+#define TOM_MAX_IND (_TOM_RSV_MAX - 1)
+
+static int
+tom_valid(uint8_t tom)
+{
+       if (tom > 0) {
+               if (tom >= 0x7 && tom <= 0xe)
+                       return 0;
+               if (tom == 0x10)
+                       return 0;
+               if (tom > 0x14)
+                       return 0;
+               return 1;
+       } else
+               return 0;
+}
+
+static const char *
+ForCES_node(uint32_t node)
+{
+       if (node <= 0x3FFFFFFF)
+               return "FE";
+       if (node >= 0x40000000 && node <= 0x7FFFFFFF)
+               return "CE";
+       if (node >= 0xC0000000 && node <= 0xFFFFFFEF)
+               return "AllMulticast";
+       if (node == 0xFFFFFFFD)
+               return "AllCEsBroadcast";
+       if (node == 0xFFFFFFFE)
+               return "AllFEsBroadcast";
+       if (node == 0xFFFFFFFF)
+               return "AllBroadcast";
+
+       return "ForCESreserved";
+
+}
+
+static const struct tok ForCES_ACKs[] = {
+       {0x0, "NoACK"},
+       {0x1, "SuccessACK"},
+       {0x2, "FailureACK"},
+       {0x3, "AlwaysACK"},
+       {0, NULL}
+};
+
+static const struct tok ForCES_EMs[] = {
+       {0x0, "EMReserved"},
+       {0x1, "execute-all-or-none"},
+       {0x2, "execute-until-failure"},
+       {0x3, "continue-execute-on-failure"},
+       {0, NULL}
+};
+
+static const struct tok ForCES_ATs[] = {
+       {0x0, "Standalone"},
+       {0x1, "2PCtransaction"},
+       {0, NULL}
+};
+
+static const struct tok ForCES_TPs[] = {
+       {0x0, "StartofTransaction"},
+       {0x1, "MiddleofTransaction"},
+       {0x2, "EndofTransaction"},
+       {0x3, "abort"},
+       {0, NULL}
+};
+
+/*
+ * Structure of forces header, naked of TLVs.
+ */
+struct forcesh {
+       nd_uint8_t fm_vrsvd;    /* version and reserved */
+#define ForCES_V(forcesh)      (GET_U_1((forcesh)->fm_vrsvd) >> 4)
+       nd_uint8_t fm_tom;      /* type of message */
+       nd_uint16_t fm_len;     /* total length * 4 bytes */
+#define ForCES_BLN(forcesh)    ((uint32_t)(GET_BE_U_2((forcesh)->fm_len) << 2))
+       nd_uint32_t fm_sid;     /* Source ID */
+#define ForCES_SID(forcesh)    GET_BE_U_4((forcesh)->fm_sid)
+       nd_uint32_t fm_did;     /* Destination ID */
+#define ForCES_DID(forcesh)    GET_BE_U_4((forcesh)->fm_did)
+       nd_uint8_t fm_cor[8];   /* correlator */
+       nd_uint32_t fm_flags;   /* flags */
+#define ForCES_ACK(forcesh)    ((GET_BE_U_4((forcesh)->fm_flags)&0xC0000000) >> 30)
+#define ForCES_PRI(forcesh)    ((GET_BE_U_4((forcesh)->fm_flags)&0x38000000) >> 27)
+#define ForCES_RS1(forcesh)    ((GET_BE_U_4((forcesh)->fm_flags)&0x07000000) >> 24)
+#define ForCES_EM(forcesh)     ((GET_BE_U_4((forcesh)->fm_flags)&0x00C00000) >> 22)
+#define ForCES_AT(forcesh)     ((GET_BE_U_4((forcesh)->fm_flags)&0x00200000) >> 21)
+#define ForCES_TP(forcesh)     ((GET_BE_U_4((forcesh)->fm_flags)&0x00180000) >> 19)
+#define ForCES_RS2(forcesh)    ((GET_BE_U_4((forcesh)->fm_flags)&0x0007FFFF) >> 0)
+};
+
+#define ForCES_HLN_VALID(fhl,tlen) ((tlen) >= ForCES_HDRL && \
+                                  (fhl) >= ForCES_HDRL && \
+                                  (fhl) == (tlen))
+
+#define F_LFB_RSVD 0x0
+#define F_LFB_FEO 0x1
+#define F_LFB_FEPO 0x2
+static const struct tok ForCES_LFBs[] = {
+       {F_LFB_RSVD, "Invalid TLV"},
+       {F_LFB_FEO, "FEObj LFB"},
+       {F_LFB_FEPO, "FEProtoObj LFB"},
+       {0, NULL}
+};
+
+/* this is defined in RFC5810 section A.2 */
+/*   https://www.iana.org/assignments/forces/forces.xhtml#oper-tlv-types */
+enum {
+       F_OP_RSV        = 0,
+       F_OP_SET        = 1,
+       F_OP_SETPROP    = 2,
+       F_OP_SETRESP    = 3,
+       F_OP_SETPRESP   = 4,
+       F_OP_DEL        = 5,
+       F_OP_DELRESP    = 6,
+       F_OP_GET        = 7,
+       F_OP_GETPROP    = 8,
+       F_OP_GETRESP    = 9,
+       F_OP_GETPRESP   = 10,
+       F_OP_REPORT     = 11,
+       F_OP_COMMIT     = 12,
+       F_OP_RCOMMIT    = 13,
+       F_OP_RTRCOMP    = 14,
+       _F_OP_MAX
+};
+#define F_OP_MAX       (_F_OP_MAX - 1)
+
+enum {
+       B_OP_SET = 1 << (F_OP_SET - 1),
+       B_OP_SETPROP = 1 << (F_OP_SETPROP - 1),
+       B_OP_SETRESP = 1 << (F_OP_SETRESP - 1),
+       B_OP_SETPRESP = 1 << (F_OP_SETPRESP - 1),
+       B_OP_DEL = 1 << (F_OP_DEL - 1),
+       B_OP_DELRESP = 1 << (F_OP_DELRESP - 1),
+       B_OP_GET = 1 << (F_OP_GET - 1),
+       B_OP_GETPROP = 1 << (F_OP_GETPROP - 1),
+       B_OP_GETRESP = 1 << (F_OP_GETRESP - 1),
+       B_OP_GETPRESP = 1 << (F_OP_GETPRESP - 1),
+       B_OP_REPORT = 1 << (F_OP_REPORT - 1),
+       B_OP_COMMIT = 1 << (F_OP_COMMIT - 1),
+       B_OP_RCOMMIT = 1 << (F_OP_RCOMMIT - 1),
+       B_OP_RTRCOMP = 1 << (F_OP_RTRCOMP - 1)
+};
+
+struct optlv_h {
+       uint16_t flags;
+       uint16_t op_msk;
+       const char *s;
+       int (*print) (netdissect_options *ndo, const u_char * pptr, u_int len,
+                     uint16_t op_msk, int indent);
+};
+
+static int genoptlv_print(netdissect_options *, const u_char * pptr, u_int len,
+                        uint16_t op_msk, int indent);
+static int recpdoptlv_print(netdissect_options *, const u_char * pptr, u_int len,
+                           uint16_t op_msk, int indent);
+static int invoptlv_print(netdissect_options *, const u_char * pptr, u_int len,
+                         uint16_t op_msk, int indent);
+
+#define OP_MIN_SIZ 8
+struct pathdata_h {
+       nd_uint16_t pflags;
+       nd_uint16_t pIDcnt;
+};
+
+#define        B_FULLD         0x1
+#define        B_SPARD         0x2
+#define B_RESTV                0x4
+#define B_KEYIN                0x8
+#define B_APPND                0x10
+#define B_TRNG         0x20
+
+static const struct optlv_h OPTLV_msg[F_OP_MAX + 1] = {
+       /* F_OP_RSV */ {ZERO_TTLV, 0, "Invalid OPTLV", invoptlv_print},
+       /* F_OP_SET */ {TTLV_T2, B_FULLD | B_SPARD, " Set", recpdoptlv_print},
+       /* F_OP_SETPROP */
+           {TTLV_T2, B_FULLD | B_SPARD, " SetProp", recpdoptlv_print},
+       /* F_OP_SETRESP */ {TTLV_T2, B_RESTV, " SetResp", recpdoptlv_print},
+       /* F_OP_SETPRESP */ {TTLV_T2, B_RESTV, " SetPropResp", recpdoptlv_print},
+       /* F_OP_DEL */ {ZERO_TTLV, 0, " Del", recpdoptlv_print},
+       /* F_OP_DELRESP */ {TTLV_T2, B_RESTV, " DelResp", recpdoptlv_print},
+       /* F_OP_GET */ {ZERO_TTLV, 0, " Get", recpdoptlv_print},
+       /* F_OP_GETPROP */ {ZERO_TTLV, 0, " GetProp", recpdoptlv_print},
+       /* F_OP_GETRESP */
+           {TTLV_T2, B_FULLD | B_SPARD | B_RESTV, " GetResp", recpdoptlv_print},
+       /* F_OP_GETPRESP */
+           {TTLV_T2, B_FULLD | B_RESTV, " GetPropResp", recpdoptlv_print},
+       /* F_OP_REPORT */
+           {TTLV_T2, B_FULLD | B_SPARD, " Report", recpdoptlv_print},
+       /* F_OP_COMMIT */ {ZERO_TTLV, 0, " Commit", NULL},
+       /* F_OP_RCOMMIT */ {TTLV_T1, B_RESTV, " RCommit", genoptlv_print},
+       /* F_OP_RTRCOMP */ {ZERO_TTLV, 0, " RTRCOMP", NULL},
+};
+
+static const struct optlv_h *
+get_forces_optlv_h(uint16_t opt)
+{
+       if (opt > F_OP_MAX || opt == F_OP_RSV)
+               return &OPTLV_msg[F_OP_RSV];
+
+       return &OPTLV_msg[opt];
+}
+
+#define IND_SIZE 256
+#define IND_CHR ' '
+#define IND_PREF '\n'
+#define IND_SUF 0x0
+static char ind_buf[IND_SIZE];
+
+static char *
+indent_pr(int indent, int nlpref)
+{
+       int i = 0;
+       char *r = ind_buf;
+
+       if (indent > (IND_SIZE - 1))
+               indent = IND_SIZE - 1;
+
+       if (nlpref) {
+               r[i] = IND_PREF;
+               i++;
+               indent--;
+       }
+
+       while (--indent >= 0)
+               r[i++] = IND_CHR;
+
+       r[i] = IND_SUF;
+       return r;
+}
+
+static int
+op_valid(uint16_t op, uint16_t mask)
+{
+       if (op == 0)
+               return 0;
+       if (op <= F_OP_MAX)
+               return (1 << (op - 1)) & mask; /* works only for 0x0001 through 0x0010 */
+       /* I guess we should allow vendor operations? */
+       if (op >= 0x8000)
+               return 1;
+       return 0;
+}
+
+#define F_TLV_RSVD     0x0000
+#define F_TLV_REDR     0x0001
+#define F_TLV_ASRS     0x0010
+#define F_TLV_ASRT     0x0011
+#define F_TLV_LFBS     0x1000
+#define F_TLV_PDAT     0x0110
+#define F_TLV_KEYI     0x0111
+#define F_TLV_FULD     0x0112
+#define F_TLV_SPAD     0x0113
+#define F_TLV_REST     0x0114
+#define F_TLV_METD     0x0115
+#define F_TLV_REDD     0x0116
+#define F_TLV_TRNG     0x0117
+
+
+#define F_TLV_VNST     0x8000
+
+static const struct tok ForCES_TLV[] = {
+       {F_TLV_RSVD, "Invalid TLV"},
+       {F_TLV_REDR, "REDIRECT TLV"},
+       {F_TLV_ASRS, "ASResult TLV"},
+       {F_TLV_ASRT, "ASTreason TLV"},
+       {F_TLV_LFBS, "LFBselect TLV"},
+       {F_TLV_PDAT, "PATH-DATA TLV"},
+       {F_TLV_KEYI, "KEYINFO TLV"},
+       {F_TLV_FULD, "FULLDATA TLV"},
+       {F_TLV_SPAD, "SPARSEDATA TLV"},
+       {F_TLV_REST, "RESULT TLV"},
+       {F_TLV_METD, "METADATA TLV"},
+       {F_TLV_REDD, "REDIRECTDATA TLV"},
+       {0, NULL}
+};
+
+#define TLV_HLN        4
+static int
+ttlv_valid(uint16_t ttlv)
+{
+       if (ttlv > 0) {
+               if (ttlv == 1 || ttlv == 0x1000)
+                       return 1;
+               if (ttlv >= 0x10 && ttlv <= 0x11)
+                       return 1;
+               if (ttlv >= 0x110 && ttlv <= 0x116)
+                       return 1;
+               if (ttlv >= 0x8000)
+                       return 0;       /* XXX: */
+       }
+
+       return 0;
+}
+
+struct forces_ilv {
+       nd_uint32_t type;
+       nd_uint32_t length;
+};
+
+struct forces_tlv {
+       nd_uint16_t type;
+       nd_uint16_t length;
+};
+
+#define F_ALN_LEN(len) roundup2(len, ForCES_ALNL)
+#define        GET_TOP_TLV(fhdr) ((const struct forces_tlv *)((fhdr) + sizeof (struct forcesh)))
+#define TLV_SET_LEN(len)  (F_ALN_LEN(TLV_HDRL) + (len))
+#define TLV_DATA(tlvp)   ((const void*)(((const char*)(tlvp)) + TLV_SET_LEN(0)))
+#define GO_NXT_TLV(tlv,rlen) ((rlen) -= F_ALN_LEN(GET_BE_U_2((tlv)->length)), \
+                             (const struct forces_tlv*)(((const char*)(tlv)) \
+                                     + F_ALN_LEN(GET_BE_U_2((tlv)->length))))
+#define ILV_SET_LEN(len)  (F_ALN_LEN(ILV_HDRL) + (len))
+#define ILV_DATA(ilvp)   ((const void*)(((const char*)(ilvp)) + ILV_SET_LEN(0)))
+#define GO_NXT_ILV(ilv,rlen) ((rlen) -= F_ALN_LEN(GET_BE_U_4((ilv)->length)), \
+                             (const struct forces_ilv *)(((const char*)(ilv)) \
+                                     + F_ALN_LEN(GET_BE_U_4((ilv)->length))))
+#define INVALID_RLEN 1
+#define INVALID_STLN 2
+#define INVALID_LTLN 3
+#define INVALID_ALEN 4
+
+static const struct tok ForCES_TLV_err[] = {
+       {INVALID_RLEN, "Invalid total length"},
+       {INVALID_STLN, "xLV too short"},
+       {INVALID_LTLN, "xLV too long"},
+       {INVALID_ALEN, "data padding missing"},
+       {0, NULL}
+};
+
+static u_int
+tlv_valid(u_int tlvl, u_int rlen)
+{
+       if (rlen < TLV_HDRL)
+               return INVALID_RLEN;
+       if (tlvl < TLV_HDRL)
+               return INVALID_STLN;
+       if (tlvl > rlen)
+               return INVALID_LTLN;
+       if (rlen < F_ALN_LEN(tlvl))
+               return INVALID_ALEN;
+
+       return 0;
+}
+
+static int
+ilv_valid(netdissect_options *ndo, const struct forces_ilv *ilv, u_int rlen)
+{
+       if (rlen < ILV_HDRL)
+               return INVALID_RLEN;
+       if (GET_BE_U_4(ilv->length) < ILV_HDRL)
+               return INVALID_STLN;
+       if (GET_BE_U_4(ilv->length) > rlen)
+               return INVALID_LTLN;
+       if (rlen < F_ALN_LEN(GET_BE_U_4(ilv->length)))
+               return INVALID_ALEN;
+
+       return 0;
+}
+
+static int lfbselect_print(netdissect_options *, const u_char * pptr, u_int len,
+                          uint16_t op_msk, int indent);
+static int redirect_print(netdissect_options *, const u_char * pptr, u_int len,
+                         uint16_t op_msk, int indent);
+static int asrtlv_print(netdissect_options *, const u_char * pptr, u_int len,
+                       uint16_t op_msk, int indent);
+static int asttlv_print(netdissect_options *, const u_char * pptr, u_int len,
+                       uint16_t op_msk, int indent);
+
+struct forces_lfbsh {
+       nd_uint32_t class;
+       nd_uint32_t instance;
+};
+
+#define ASSNS_OPS (B_OP_REPORT)
+#define CFG_OPS        (B_OP_SET|B_OP_SETPROP|B_OP_DEL|B_OP_COMMIT|B_OP_RTRCOMP)
+#define CFG_ROPS (B_OP_SETRESP|B_OP_SETPRESP|B_OP_DELRESP|B_OP_RCOMMIT)
+#define CFG_QY (B_OP_GET|B_OP_GETPROP)
+#define CFG_QYR (B_OP_GETRESP|B_OP_GETPRESP)
+#define CFG_EVN (B_OP_REPORT)
+
+static const struct tom_h ForCES_msg[TOM_MAX_IND + 1] = {
+       /* TOM_RSV_I */ {TOM_RSVD, ZERO_TTLV, 0, "Invalid message", NULL},
+       /* TOM_ASS_I */ {TOM_ASSNSETUP, ZERO_MORE_TTLV | TWO_TLV, ASSNS_OPS,
+                      "Association Setup", lfbselect_print},
+       /* TOM_AST_I */
+           {TOM_ASSNTEARD, TTLV_T1, 0, "Association TearDown", asttlv_print},
+       /* TOM_CFG_I */ {TOM_CONFIG, TTLV_T2, CFG_OPS, "Config", lfbselect_print},
+       /* TOM_QRY_I */ {TOM_QUERY, TTLV_T2, CFG_QY, "Query", lfbselect_print},
+       /* TOM_EVN_I */ {TOM_EVENTNOT, TTLV_T1, CFG_EVN, "Event Notification",
+                      lfbselect_print},
+       /* TOM_RED_I */
+           {TOM_PKTREDIR, TTLV_T2, 0, "Packet Redirect", redirect_print},
+       /* TOM_HBT_I */ {TOM_HEARTBT, ZERO_TTLV, 0, "HeartBeat", NULL},
+       /* TOM_ASR_I */
+           {TOM_ASSNSETREP, TTLV_T1, 0, "Association Response", asrtlv_print},
+       /* TOM_CNR_I */ {TOM_CONFIGREP, TTLV_T2, CFG_ROPS, "Config Response",
+                      lfbselect_print},
+       /* TOM_QRR_I */
+           {TOM_QUERYREP, TTLV_T2, CFG_QYR, "Query Response", lfbselect_print},
+};
+
+static const struct tom_h *
+get_forces_tom(uint8_t tom)
+{
+       int i;
+       for (i = TOM_RSV_I; i <= TOM_MAX_IND; i++) {
+               const struct tom_h *th = &ForCES_msg[i];
+               if (th->v == tom)
+                       return th;
+       }
+       return &ForCES_msg[TOM_RSV_I];
+}
+
+struct pdata_ops {
+       uint32_t v;
+       uint16_t flags;
+       uint16_t op_msk;
+       const char *s;
+       int (*print) (netdissect_options *, const u_char * pptr, u_int len,
+                     uint16_t op_msk, int indent);
+};
+
+enum {
+       PD_RSV_I,
+       PD_SEL_I,
+       PD_FDT_I,
+       PD_SDT_I,
+       PD_RES_I,
+       PD_PDT_I,
+       _PD_RSV_MAX
+};
+#define PD_MAX_IND (_TOM_RSV_MAX - 1)
+
+static int
+pd_valid(uint16_t pd)
+{
+       if (pd >= F_TLV_PDAT && pd <= F_TLV_REST)
+               return 1;
+       return 0;
+}
+
+static void
+chk_op_type(netdissect_options *ndo,
+            uint16_t type, uint16_t msk, uint16_t omsk)
+{
+       if (type != F_TLV_PDAT) {
+               if (msk & B_KEYIN) {
+                       if (type != F_TLV_KEYI) {
+                               ND_PRINT("Based on flags expected KEYINFO TLV!\n");
+                       }
+               } else {
+                       if (!(msk & omsk)) {
+                               ND_PRINT("Illegal DATA encoding for type 0x%x programmed %x got %x\n",
+                                         type, omsk, msk);
+                       }
+               }
+       }
+
+}
+
+#define F_SELKEY 1
+#define F_SELTABRANGE 2
+#define F_TABAPPEND 4
+
+struct res_val {
+       nd_uint8_t result;
+       nd_uint8_t resv1;
+       nd_uint16_t resv2;
+};
+
+static int prestlv_print(netdissect_options *, const u_char * pptr, u_int len,
+                        uint16_t op_msk, int indent);
+static int pkeyitlv_print(netdissect_options *, const u_char * pptr, u_int len,
+                         uint16_t op_msk, int indent);
+static int fdatatlv_print(netdissect_options *, const u_char * pptr, u_int len,
+                         uint16_t op_msk, int indent);
+static int sdatatlv_print(netdissect_options *, const u_char * pptr, u_int len,
+                         uint16_t op_msk, int indent);
+
+static const struct pdata_ops ForCES_pdata[PD_MAX_IND + 1] = {
+       /* PD_RSV_I */ {0, 0, 0, "Invalid message", NULL},
+       /* PD_SEL_I */ {F_TLV_KEYI, 0, 0, "KEYINFO TLV", pkeyitlv_print},
+       /* PD_FDT_I */ {F_TLV_FULD, 0, B_FULLD, "FULLDATA TLV", fdatatlv_print},
+       /* PD_SDT_I */ {F_TLV_SPAD, 0, B_SPARD, "SPARSEDATA TLV", sdatatlv_print},
+       /* PD_RES_I */ {F_TLV_REST, 0, B_RESTV, "RESULT TLV", prestlv_print},
+       /* PD_PDT_I */
+           {F_TLV_PDAT, 0, 0, "Inner PATH-DATA TLV", recpdoptlv_print},
+};
+
+static const struct pdata_ops *
+get_forces_pd(uint16_t pd)
+{
+       int i;
+       for (i = PD_RSV_I + 1; i <= PD_MAX_IND; i++) {
+               const struct pdata_ops *pdo = &ForCES_pdata[i];
+               if (pdo->v == pd)
+                       return pdo;
+       }
+       return &ForCES_pdata[TOM_RSV_I];
+}
+
+enum {
+       E_SUCCESS,
+       E_INVALID_HEADER,
+       E_LENGTH_MISMATCH,
+       E_VERSION_MISMATCH,
+       E_INVALID_DESTINATION_PID,
+       E_LFB_UNKNOWN,
+       E_LFB_NOT_FOUND,
+       E_LFB_INSTANCE_ID_NOT_FOUND,
+       E_INVALID_PATH,
+       E_COMPONENT_DOES_NOT_EXIST,
+       E_EXISTS,
+       E_NOT_FOUND,
+       E_READ_ONLY,
+       E_INVALID_ARRAY_CREATION,
+       E_VALUE_OUT_OF_RANGE,
+       E_CONTENTS_TOO_LONG,
+       E_INVALID_PARAMETERS,
+       E_INVALID_MESSAGE_TYPE,
+       E_INVALID_FLAGS,
+       E_INVALID_TLV,
+       E_EVENT_ERROR,
+       E_NOT_SUPPORTED,
+       E_MEMORY_ERROR,
+       E_INTERNAL_ERROR,
+       /* 0x18-0xFE are reserved .. */
+       E_UNSPECIFIED_ERROR = 0XFF
+};
+
+static const struct tok ForCES_errs[] = {
+       {E_SUCCESS, "SUCCESS"},
+       {E_INVALID_HEADER, "INVALID HEADER"},
+       {E_LENGTH_MISMATCH, "LENGTH MISMATCH"},
+       {E_VERSION_MISMATCH, "VERSION MISMATCH"},
+       {E_INVALID_DESTINATION_PID, "INVALID DESTINATION PID"},
+       {E_LFB_UNKNOWN, "LFB UNKNOWN"},
+       {E_LFB_NOT_FOUND, "LFB NOT FOUND"},
+       {E_LFB_INSTANCE_ID_NOT_FOUND, "LFB INSTANCE ID NOT FOUND"},
+       {E_INVALID_PATH, "INVALID PATH"},
+       {E_COMPONENT_DOES_NOT_EXIST, "COMPONENT DOES NOT EXIST"},
+       {E_EXISTS, "EXISTS ALREADY"},
+       {E_NOT_FOUND, "NOT FOUND"},
+       {E_READ_ONLY, "READ ONLY"},
+       {E_INVALID_ARRAY_CREATION, "INVALID ARRAY CREATION"},
+       {E_VALUE_OUT_OF_RANGE, "VALUE OUT OF RANGE"},
+       {E_CONTENTS_TOO_LONG, "CONTENTS TOO LONG"},
+       {E_INVALID_PARAMETERS, "INVALID PARAMETERS"},
+       {E_INVALID_MESSAGE_TYPE, "INVALID MESSAGE TYPE"},
+       {E_INVALID_FLAGS, "INVALID FLAGS"},
+       {E_INVALID_TLV, "INVALID TLV"},
+       {E_EVENT_ERROR, "EVENT ERROR"},
+       {E_NOT_SUPPORTED, "NOT SUPPORTED"},
+       {E_MEMORY_ERROR, "MEMORY ERROR"},
+       {E_INTERNAL_ERROR, "INTERNAL ERROR"},
+       {E_UNSPECIFIED_ERROR, "UNSPECIFIED ERROR"},
+       {0, NULL}
+};
+
+static const struct tok tdr_str[] = {
+       { 0, "Normal Teardown" },
+       { 1, "Loss of Heartbeats" },
+       { 2, "Out of bandwidth" },
+       { 3, "Out of Memory" },
+       { 4, "Application Crash" },
+       { 0, NULL }
+};
 
 #define RESLEN 4
 
-int
-prestlv_print(register const u_char * pptr, register u_int len,
-             u_int16_t op_msk _U_, int indent)
+static int
+prestlv_print(netdissect_options *ndo,
+              const u_char * pptr, u_int len,
+              uint16_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;
+       const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
+       const u_char *tdp = TLV_DATA(tlv);
+       const struct res_val *r = (const struct res_val *)tdp;
        u_int dlen;
+       uint8_t result;
 
        /*
         * pdatacnt_print() has ensured that len (the TLV length)
@@ -45,207 +670,265 @@ prestlv_print(register const u_char * pptr, register u_int len,
         */
        dlen = len - TLV_HDRL;
        if (dlen != RESLEN) {
-               printf("illegal RESULT-TLV: %d bytes!\n", dlen);
-               return -1;
+               ND_PRINT("illegal RESULT-TLV: %u bytes!\n", dlen);
+               goto invalid;
        }
 
-       TCHECK(*r);
-       if (r->result >= 0x18 && r->result <= 0xFE) {
-               printf("illegal reserved result code: 0x%x!\n", r->result);
-               return -1;
+       ND_TCHECK_SIZE(r);
+       result = GET_U_1(r->result);
+       if (result >= 0x18 && result <= 0xFE) {
+               ND_PRINT("illegal reserved result code: 0x%x!\n", result);
+               goto invalid;
        }
 
-       if (vflag >= 3) {
+       if (ndo->ndo_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);
+               ND_PRINT("%s  Result: %s (code 0x%x)\n", ib,
+                      tok2str(ForCES_errs, NULL, result), result);
        }
        return 0;
 
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
        return -1;
 }
 
-int
-fdatatlv_print(register const u_char * pptr, register u_int len,
-              u_int16_t op_msk _U_, int indent)
+static int
+fdatatlv_print(netdissect_options *ndo,
+               const u_char * pptr, u_int len,
+               uint16_t op_msk _U_, int indent)
 {
-       const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
+       const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
        u_int rlen;
-       register const u_char *tdp = (u_char *) TLV_DATA(tlv);
-       u_int16_t type;
+       const u_char *tdp = TLV_DATA(tlv);
+       uint16_t type;
 
        /*
         * pdatacnt_print() or pkeyitlv_print() has ensured that len
         * (the TLV length) >= TLV_HDRL.
         */
        rlen = len - TLV_HDRL;
-       TCHECK(*tlv);
-       type = EXTRACT_16BITS(&tlv->type);
+       ND_TCHECK_SIZE(tlv);
+       type = GET_BE_U_2(tlv->type);
        if (type != F_TLV_FULD) {
-               printf("Error: expecting FULLDATA!\n");
-               return -1;
+               ND_PRINT("Error: expecting FULLDATA!\n");
+               goto invalid;
        }
 
-       if (vflag >= 3) {
+       if (ndo->ndo_vflag >= 3) {
                char *ib = indent_pr(indent + 2, 1);
-               printf("%s[", &ib[1]);
-               hex_print_with_offset(ib, tdp, rlen, 0);
-               printf("\n%s]\n", &ib[1]);
+               ND_PRINT("%s[", ib + 1);
+               hex_print(ndo, ib, tdp, rlen);
+               ND_PRINT("\n%s]", ib + 1);
        }
        return 0;
 
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
        return -1;
 }
 
-int
-sdatailv_print(register const u_char * pptr, register u_int len,
-              u_int16_t op_msk _U_, int indent)
+static int
+sdatailv_print(netdissect_options *ndo,
+               const u_char * pptr, u_int len,
+               uint16_t op_msk _U_, int indent)
 {
        u_int rlen;
-       const struct forces_ilv *ilv = (struct forces_ilv *)pptr;
+       const struct forces_ilv *ilv = (const struct forces_ilv *)pptr;
        int invilv;
 
        if (len < ILV_HDRL) {
-               printf("Error: BAD SPARSEDATA-TLV!\n");
-               return -1;
+               ND_PRINT("Error: BAD SPARSEDATA-TLV!\n");
+               goto invalid;
        }
-       rlen = len - ILV_HDRL;
+       rlen = len;
        indent += 1;
        while (rlen != 0) {
-               TCHECK(*ilv);
-               invilv = ilv_valid(ilv, rlen);
+               char *ib = indent_pr(indent, 1);
+               const u_char *tdp = ILV_DATA(ilv);
+               invilv = ilv_valid(ndo, ilv, rlen);
                if (invilv) {
-                       printf("Error: BAD ILV!\n");
-                       return -1;
+                       ND_PRINT("Error: %s, rlen %u\n",
+                                tok2str(ForCES_TLV_err, NULL, invilv), rlen);
+                       goto invalid;
                }
-               if (vflag >= 3) {
-                       register const u_char *tdp = (u_char *) ILV_DATA(ilv);
-                       char *ib = indent_pr(indent, 1);
-                       printf("\n%s SPARSEDATA: type %x length %d\n", &ib[1],
-                              EXTRACT_32BITS(&ilv->type),
-                              EXTRACT_32BITS(&ilv->length));
-                       printf("%s[", &ib[1]);
-                       hex_print_with_offset(ib, tdp, rlen, 0);
-                       printf("\n%s]\n", &ib[1]);
+               if (ndo->ndo_vflag >= 3) {
+                       u_int ilvl = GET_BE_U_4(ilv->length);
+                       ND_PRINT("\n%s ILV: type %x length %u\n", ib + 1,
+                                 GET_BE_U_4(ilv->type), ilvl);
+                       hex_print(ndo, "\t\t[", tdp, ilvl-ILV_HDRL);
                }
 
                ilv = GO_NXT_ILV(ilv, rlen);
        }
 
        return 0;
-
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
        return -1;
 }
 
-int
-sdatatlv_print(register const u_char * pptr, register u_int len,
-              u_int16_t op_msk, int indent)
+static int
+sdatatlv_print(netdissect_options *ndo,
+               const u_char * pptr, u_int len,
+               uint16_t op_msk, int indent)
 {
-       const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
+       const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
        u_int rlen;
-       register const u_char *tdp = (u_char *) TLV_DATA(tlv);
-       u_int16_t type;
+       const u_char *tdp = TLV_DATA(tlv);
+       uint16_t type;
 
        /*
         * pdatacnt_print() has ensured that len (the TLV length)
         * >= TLV_HDRL.
         */
        rlen = len - TLV_HDRL;
-       TCHECK(*tlv);
-       type = EXTRACT_16BITS(&tlv->type);
+       ND_TCHECK_SIZE(tlv);
+       type = GET_BE_U_2(tlv->type);
        if (type != F_TLV_SPAD) {
-               printf("Error: expecting SPARSEDATA!\n");
-               return -1;
+               ND_PRINT("Error: expecting SPARSEDATA!\n");
+               goto invalid;
        }
 
-       return sdatailv_print(tdp, rlen, op_msk, indent);
+       return sdatailv_print(ndo, tdp, rlen, op_msk, indent);
 
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
        return -1;
 }
 
-int
-pkeyitlv_print(register const u_char * pptr, register u_int len,
-              u_int16_t op_msk, int indent)
+static int
+pkeyitlv_print(netdissect_options *ndo,
+               const u_char * pptr, u_int len,
+               uint16_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;
+       const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
+       const u_char *tdp = TLV_DATA(tlv);
+       const u_char *dp = tdp + 4;
+       const struct forces_tlv *kdtlv = (const struct forces_tlv *)dp;
+       uint32_t id;
        char *ib = indent_pr(indent, 0);
-       u_int16_t type, tll;
-       int invtlv;
+       uint16_t type, tll;
+       u_int invtlv;
 
-       TCHECK(*tdp);
-       id = EXTRACT_32BITS(tdp);
-       printf("%sKeyinfo: Key 0x%x\n", ib, id);
-       TCHECK(*kdtlv);
-       type = EXTRACT_16BITS(&kdtlv->type);
-       invtlv = tlv_valid(kdtlv, len);
+       id = GET_BE_U_4(tdp);
+       ND_PRINT("%sKeyinfo: Key 0x%x\n", ib, id);
+       type = GET_BE_U_2(kdtlv->type);
+       tll = GET_BE_U_2(kdtlv->length);
+       invtlv = tlv_valid(tll, len);
 
        if (invtlv) {
-               printf("%s TLV type 0x%x len %d\n",
+               ND_PRINT("%s TLV type 0x%x len %u\n",
                       tok2str(ForCES_TLV_err, NULL, invtlv), type,
-                      EXTRACT_16BITS(&kdtlv->length));
-               return -1;
+                      tll);
+               goto invalid;
        }
        /*
         * 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(dp, tll, op_msk, indent);
-
-trunc:
-       fputs("[|forces]", stdout);
+       tll = GET_BE_U_2(kdtlv->length);
+       dp = TLV_DATA(kdtlv);
+       return fdatatlv_print(ndo, dp, tll, op_msk, indent);
+invalid:
        return -1;
 }
 
-int
-pdatacnt_print(register const u_char * pptr, register u_int len,
-              u_int32_t IDcnt, u_int16_t op_msk, int indent)
+#define PTH_DESC_SIZE 12
+
+static int
+pdatacnt_print(netdissect_options *ndo,
+               const u_char * pptr, u_int len,
+               uint16_t IDcnt, uint16_t op_msk, int indent)
 {
        u_int i;
-       int rc;
-       u_int32_t id;
+       uint32_t id;
        char *ib = indent_pr(indent, 0);
 
+       if ((op_msk & B_APPND) && ndo->ndo_vflag >= 3) {
+               ND_PRINT("%sTABLE APPEND\n", ib);
+       }
        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);
+               ND_ICHECK_U(len, <, 4);
+               id = GET_BE_U_4(pptr);
+               if (ndo->ndo_vflag >= 3)
+                       ND_PRINT("%sID#%02u: %u\n", ib, i + 1, id);
                len -= 4;
                pptr += 4;
        }
+
+       if ((op_msk & B_TRNG) || (op_msk & B_KEYIN)) {
+               if (op_msk & B_TRNG) {
+                       uint32_t starti, endi;
+
+                       if (len < PTH_DESC_SIZE) {
+                               ND_PRINT("pathlength %u with key/range too short %u\n",
+                                      len, PTH_DESC_SIZE);
+                               goto invalid;
+                       }
+
+                       pptr += sizeof(struct forces_tlv);
+                       len -= sizeof(struct forces_tlv);
+
+                       starti = GET_BE_U_4(pptr);
+                       pptr += 4;
+                       len -= 4;
+
+                       endi = GET_BE_U_4(pptr);
+                       pptr += 4;
+                       len -= 4;
+
+                       if (ndo->ndo_vflag >= 3)
+                               ND_PRINT("%sTable range: [%u,%u]\n", ib, starti, endi);
+               }
+
+               if (op_msk & B_KEYIN) {
+                       const struct forces_tlv *keytlv;
+                       uint16_t tll;
+
+                       if (len < PTH_DESC_SIZE) {
+                               ND_PRINT("pathlength %u with key/range too short %u\n",
+                                      len, PTH_DESC_SIZE);
+                               goto invalid;
+                       }
+
+                       /* skip keyid */
+                       pptr += 4;
+                       len -= 4;
+                       keytlv = (const struct forces_tlv *)pptr;
+                       /* skip header */
+                       pptr += sizeof(struct forces_tlv);
+                       len -= sizeof(struct forces_tlv);
+                       /* skip key content */
+                       tll = GET_BE_U_2(keytlv->length);
+                       if (tll < TLV_HDRL) {
+                               ND_PRINT("key content length %u < %u\n",
+                                       tll, TLV_HDRL);
+                               goto invalid;
+                       }
+                       tll -= TLV_HDRL;
+                       if (len < tll) {
+                               ND_PRINT("key content too short\n");
+                               goto invalid;
+                       }
+                       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;
+               const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr;
+               uint16_t type;
+               uint16_t tlvl, tll;
+               u_int pad = 0;
                u_int aln;
-               int invtlv;
+               u_int invtlv;
 
-               TCHECK(*pdtlv);
-               type = EXTRACT_16BITS(&pdtlv->type);
-               invtlv = tlv_valid(pdtlv, len);
+               type = GET_BE_U_2(pdtlv->type);
+               tlvl = GET_BE_U_2(pdtlv->length);
+               invtlv = tlv_valid(tlvl, 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));
+                       ND_PRINT("%s Outstanding bytes %u for TLV type 0x%x TLV len %u\n",
+                                 tok2str(ForCES_TLV_err, NULL, invtlv), len, type,
+                                 tlvl);
                        goto pd_err;
                }
                /*
@@ -253,154 +936,174 @@ pdatacnt_print(register const u_char * pptr, register u_int len,
                 * 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)) {
+               tll = tlvl - TLV_HDRL;
+               aln = F_ALN_LEN(tlvl);
+               if (aln > tlvl) {
                        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);
+                               ND_PRINT("Invalid padded pathdata TLV type 0x%x len %u missing %u pad bytes\n",
+                                         type, tlvl, aln - len);
                        } else {
-                               pad = aln - EXTRACT_16BITS(&pdtlv->length);
+                               pad = aln - tlvl;
                        }
                }
                if (pd_valid(type)) {
                        const struct pdata_ops *ops = get_forces_pd(type);
 
-                       if (vflag >= 3 && ops->v != F_TLV_PDAT) {
+                       if (ndo->ndo_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);
+                                       ND_PRINT("%s  %s (Length %u DataLen %u pad %u Bytes)\n",
+                                                 ib, ops->s, tlvl, tll, pad);
                                else
-                                       printf
-                                           ("%s  %s (Length %d DataLen %d Bytes)\n",
-                                            ib, ops->s, EXTRACT_16BITS(&pdtlv->length),
-                                            tll);
+                                       ND_PRINT("%s  %s (Length %u DataLen %u Bytes)\n",
+                                                 ib, ops->s, tlvl, tll);
                        }
 
-                       chk_op_type(type, op_msk, ops->op_msk);
+                       chk_op_type(ndo, type, op_msk, ops->op_msk);
 
-                       rc = ops->print((const u_char *)pdtlv,
-                                       tll + pad + TLV_HDRL, op_msk,
-                                       indent + 2);
+                       ND_ICHECK_U(ops->print(ndo, (const u_char *)pdtlv,
+                                   tll + pad + TLV_HDRL, op_msk, indent + 2),
+                                   ==, -1);
+                       len -= (TLV_HDRL + pad + tll);
                } else {
-                       printf("Invalid path data content type 0x%x len %d\n",
-                              type, EXTRACT_16BITS(&pdtlv->length));
+                       ND_PRINT("Invalid path data content type 0x%x len %u\n",
+                              type, tlvl);
 pd_err:
-                       if (EXTRACT_16BITS(&pdtlv->length)) {
-                               hex_print_with_offset("Bad Data val\n\t  [",
-                                                     pptr, len, 0);
-                               printf("]\n");
+                       if (tlvl) {
+                                hex_print(ndo, "Bad Data val\n\t  [",
+                                         pptr, len);
+                               ND_PRINT("]\n");
 
-                               return -1;
+                               goto invalid;
                        }
                }
        }
-       return 0;
+       return len;
 
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
        return -1;
 }
 
-int
-pdata_print(register const u_char * pptr, register u_int len,
-           u_int16_t op_msk, int indent)
+static int
+pdata_print(netdissect_options *ndo,
+            const u_char * pptr, u_int len,
+            uint16_t op_msk, int indent)
 {
-       const struct pathdata_h *pdh = (struct pathdata_h *)pptr;
+       const struct pathdata_h *pdh = (const struct pathdata_h *)pptr;
        char *ib = indent_pr(indent, 0);
        u_int minsize = 0;
-
-       TCHECK(*pdh);
-       if (len < sizeof(struct pathdata_h))
-               goto trunc;
-       if (vflag >= 3) {
-               printf("\n%sPathdata: Flags 0x%x ID count %d\n",
-                      ib, EXTRACT_16BITS(&pdh->pflags), EXTRACT_16BITS(&pdh->pIDcnt));
+       int more_pd = 0;
+       uint16_t idcnt = 0;
+
+       ND_TCHECK_SIZE(pdh);
+       ND_ICHECK_ZU(len, <, sizeof(struct pathdata_h));
+       if (ndo->ndo_vflag >= 3) {
+               ND_PRINT("\n%sPathdata: Flags 0x%x ID count %u\n",
+                      ib, GET_BE_U_2(pdh->pflags),
+                      GET_BE_U_2(pdh->pIDcnt));
        }
 
-       if (EXTRACT_16BITS(&pdh->pflags) & F_SELKEY) {
+       if (GET_BE_U_2(pdh->pflags) & F_SELKEY) {
                op_msk |= B_KEYIN;
        }
+
+       /* Table GET Range operation */
+       if (GET_BE_U_2(pdh->pflags) & F_SELTABRANGE) {
+               op_msk |= B_TRNG;
+       }
+       /* Table SET append operation */
+       if (GET_BE_U_2(pdh->pflags) & F_TABAPPEND) {
+               op_msk |= B_APPND;
+       }
+
        pptr += sizeof(struct pathdata_h);
        len -= sizeof(struct pathdata_h);
-       minsize = EXTRACT_16BITS(&pdh->pIDcnt) * 4;
+       idcnt = GET_BE_U_2(pdh->pIDcnt);
+       minsize = idcnt * 4;
        if (len < minsize) {
-               printf("\t\t\ttruncated IDs expected %uB got %uB\n", minsize,
+               ND_PRINT("\t\t\ttruncated IDs expected %uB got %uB\n", minsize,
                       len);
-               hex_print_with_offset("\t\t\tID Data[", pptr, len, 0);
-               printf("]\n");
-               return -1;
+               hex_print(ndo, "\t\t\tID Data[", pptr, len);
+               ND_PRINT("]\n");
+               goto invalid;
        }
-       return pdatacnt_print(pptr, len, EXTRACT_16BITS(&pdh->pIDcnt), op_msk, indent);
 
-trunc:
-       fputs("[|forces]", stdout);
+       if ((op_msk & B_TRNG) && (op_msk & B_KEYIN)) {
+               ND_PRINT("\t\t\tIllegal to have both Table ranges and keys\n");
+               goto invalid;
+       }
+
+       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 more_pd;
+
+invalid:
        return -1;
 }
 
-int
-genoptlv_print(register const u_char * pptr, register u_int len,
-              u_int16_t op_msk, int indent)
+static int
+genoptlv_print(netdissect_options *ndo,
+               const u_char * pptr, u_int len,
+               uint16_t op_msk, int indent)
 {
-       const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr;
-       u_int16_t type;
-       int tll;
-       int invtlv;
+       const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr;
+       uint16_t type;
+       u_int tlvl;
+       u_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);
+       type = GET_BE_U_2(pdtlv->type);
+       tlvl = GET_BE_U_2(pdtlv->length);
+       invtlv = tlv_valid(tlvl, len);
+       ND_PRINT("genoptlvprint - %s TLV type 0x%x len %u\n",
+              tok2str(ForCES_TLV, NULL, type), type, tlvl);
+       if (invtlv) {
+               ND_PRINT("\t\t\tInvalid ForCES TLV type=%x", type);
+               goto invalid;
+       }
+       /*
+        * 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).
+        */
+       const u_char *dp = TLV_DATA(pdtlv);
 
-               return pdata_print(dp, tll, op_msk, indent + 1);
-       } else {
-               printf("\t\t\tInvalid ForCES TLV type=%x", type);
-               return -1;
+       if (!ttlv_valid(type)) {
+               ND_PRINT("%s TLV type 0x%x len %u\n",
+                      tok2str(ForCES_TLV_err, NULL, invtlv), type,
+                      tlvl);
+               goto invalid;
        }
+       if (ndo->ndo_vflag >= 3)
+               ND_PRINT("%s%s, length %u (data length %u Bytes)",
+                      ib, tok2str(ForCES_TLV, NULL, type),
+                      tlvl, tlvl - TLV_HDRL);
 
-trunc:
-       fputs("[|forces]", stdout);
+       return pdata_print(ndo, dp, tlvl - TLV_HDRL, op_msk, indent + 1);
+invalid:
        return -1;
 }
 
-int
-recpdoptlv_print(register const u_char * pptr, register u_int len,
-                u_int16_t op_msk, int indent)
+static int
+recpdoptlv_print(netdissect_options *ndo,
+                 const u_char * pptr, u_int len,
+                 uint16_t op_msk, int indent)
 {
-       const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr;
-       int tll;
-       int rc = 0;
-       int invtlv;
-       u_int16_t type;
-       register const u_char *dp;
-       char *ib;
+       const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr;
 
        while (len != 0) {
-               TCHECK(*pdtlv);
-               invtlv = tlv_valid(pdtlv, len);
+               uint16_t type, tlvl;
+               u_int invtlv;
+               char *ib;
+               const u_char *dp;
+
+               tlvl = GET_BE_U_2(pdtlv->length);
+               invtlv = tlv_valid(tlvl, len);
                if (invtlv) {
                        break;
                }
@@ -411,101 +1114,94 @@ recpdoptlv_print(register const u_char * pptr, register u_int len,
                 * go past the end of the containing TLV).
                 */
                ib = indent_pr(indent, 0);
-               type = EXTRACT_16BITS(&pdtlv->type);
-               dp = (u_char *) TLV_DATA(pdtlv);
-               tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL;
-
-               if (vflag >= 3)
-                       printf
-                           ("%s%s, length %d (data encapsulated %d Bytes)",
-                            ib, tok2str(ForCES_TLV, NULL, type),
-                            EXTRACT_16BITS(&pdtlv->length),
-                            EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL);
-
-               rc = pdata_print(dp, tll, op_msk, indent + 1);
+               type = GET_BE_U_2(pdtlv->type);
+               dp = TLV_DATA(pdtlv);
+
+               if (ndo->ndo_vflag >= 3)
+                       ND_PRINT("%s%s, length %u (data encapsulated %u Bytes)",
+                                 ib, tok2str(ForCES_TLV, NULL, type),
+                                 tlvl,
+                                 tlvl - TLV_HDRL);
+
+               ND_ICHECK_U(pdata_print(ndo, dp, tlvl - TLV_HDRL, op_msk, indent + 1),
+                           ==, -1);
                pdtlv = GO_NXT_TLV(pdtlv, len);
        }
 
        if (len) {
-               printf
-                   ("\n\t\tMessy PATHDATA TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
-                    EXTRACT_16BITS(&pdtlv->type), len - EXTRACT_16BITS(&pdtlv->length));
-               return -1;
+               ND_PRINT("\n\t\tMessy PATHDATA TLV header, type (0x%x)\n\t\texcess of %u Bytes ",
+                         GET_BE_U_2(pdtlv->type),
+                         len - GET_BE_U_2(pdtlv->length));
+               goto invalid;
        }
 
        return 0;
-
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
        return -1;
 }
 
-int
-invoptlv_print(register const u_char * pptr, register u_int len,
-              u_int16_t op_msk _U_, int indent)
+static int
+invoptlv_print(netdissect_options *ndo,
+               const u_char * pptr, u_int len,
+               uint16_t op_msk _U_, int indent)
 {
        char *ib = indent_pr(indent, 1);
 
-       if (vflag >= 3) {
-               printf("%sData[", &ib[1]);
-               hex_print_with_offset(ib, pptr, len, 0);
-               printf("%s]\n", ib);
+       if (ndo->ndo_vflag >= 3) {
+               ND_PRINT("%sData[", ib + 1);
+               hex_print(ndo, ib, pptr, len);
+               ND_PRINT("%s]\n", ib);
        }
        return -1;
 }
 
-int otlv_print(const struct forces_tlv *otlv, u_int16_t op_msk _U_, int indent)
+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);
-       u_int16_t type;
-       int tll;
+       const u_char *dp = TLV_DATA(otlv);
+       uint16_t type;
+       u_int tll;
        char *ib = indent_pr(indent, 0);
        const struct optlv_h *ops;
 
        /*
-        * lfbselect_print() has ensured that EXTRACT_16BITS(&otlv->length)
+        * lfbselect_print() has ensured that GET_BE_U_2(otlv->length)
         * >= TLV_HDRL.
         */
-       TCHECK(*otlv);
-       type = EXTRACT_16BITS(&otlv->type);
-       tll = EXTRACT_16BITS(&otlv->length) - TLV_HDRL;
+       type = GET_BE_U_2(otlv->type);
+       tll = GET_BE_U_2(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;
+       if (ndo->ndo_vflag >= 3) {
+               ND_PRINT("%sOper TLV %s(0x%x) length %u\n", ib, ops->s, type,
+                      GET_BE_U_2(otlv->length));
        }
        /* 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,
+               ND_PRINT("\t\tOper TLV %s(0x%x) length %u\n", ops->s, type,
+                      GET_BE_U_2(otlv->length));
+               ND_PRINT("\t\tTruncated data size %u minimum required %u\n", tll,
                       OP_MIN_SIZ);
-               return invoptlv_print(dp, tll, ops->op_msk, indent);
+               return invoptlv_print(ndo, dp, tll, ops->op_msk, indent);
 
        }
 
-       rc = ops->print(dp, tll, ops->op_msk, indent + 1);
+       /* XXX - do anything with ops->flags? */
+        if(ops->print) {
+                rc = ops->print(ndo, dp, tll, ops->op_msk, indent + 1);
+        }
        return rc;
-
-trunc:
-       fputs("[|forces]", stdout);
-       return -1;
 }
 
 #define ASTDLN 4
 #define ASTMCD 255
-int
-asttlv_print(register const u_char * pptr, register u_int len,
-            u_int16_t op_msk _U_, int indent)
+static int
+asttlv_print(netdissect_options *ndo,
+             const u_char * pptr, u_int len,
+             uint16_t op_msk _U_, int indent)
 {
-       u_int32_t rescode;
+       uint32_t rescode;
        u_int dlen;
        char *ib = indent_pr(indent, 0);
 
@@ -515,54 +1211,33 @@ asttlv_print(register const u_char * pptr, register u_int len,
         */
        dlen = len - TLV_HDRL;
        if (dlen != ASTDLN) {
-               printf("illegal ASTresult-TLV: %d bytes!\n", dlen);
-               return -1;
+               ND_PRINT("illegal ASTresult-TLV: %u bytes!\n", dlen);
+               goto invalid;
        }
-       TCHECK2(*pptr, 4);
-       rescode = EXTRACT_32BITS(pptr);
+       rescode = GET_BE_U_4(pptr);
        if (rescode > ASTMCD) {
-               printf("illegal ASTresult result code: %d!\n", rescode);
-               return -1;
+               ND_PRINT("illegal ASTresult result code: %u!\n", rescode);
+               goto invalid;
        }
 
-       if (vflag >= 3) {
-               printf("Teardown reason:\n%s", ib);
-               switch (rescode) {
-               case 0:
-                       printf("Normal Teardown");
-                       break;
-               case 1:
-                       printf("Loss of Heartbeats");
-                       break;
-               case 2:
-                       printf("Out of bandwidth");
-                       break;
-               case 3:
-                       printf("Out of Memory");
-                       break;
-               case 4:
-                       printf("Application Crash");
-                       break;
-               default:
-                       printf("Unknown Teardown reason");
-                       break;
-               }
-               printf("(%x)\n%s", rescode, ib);
+       if (ndo->ndo_vflag >= 3) {
+               ND_PRINT("Teardown reason:\n%s%s", ib,
+                        tok2str(tdr_str, "unknown (%u)", rescode));
+               ND_PRINT("(%x)\n%s", rescode, ib);
        }
        return 0;
-
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
        return -1;
 }
 
 #define ASRDLN 4
 #define ASRMCD 3
-int
-asrtlv_print(register const u_char * pptr, register u_int len,
-            u_int16_t op_msk _U_, int indent)
+static int
+asrtlv_print(netdissect_options *ndo,
+             const u_char * pptr, u_int len,
+             uint16_t op_msk _U_, int indent)
 {
-       u_int32_t rescode;
+       uint32_t rescode;
        u_int dlen;
        char *ib = indent_pr(indent, 0);
 
@@ -572,94 +1247,92 @@ asrtlv_print(register const u_char * pptr, register u_int len,
         */
        dlen = len - TLV_HDRL;
        if (dlen != ASRDLN) {   /* id, instance, oper tlv */
-               printf("illegal ASRresult-TLV: %d bytes!\n", dlen);
-               return -1;
+               ND_PRINT("illegal ASRresult-TLV: %u bytes!\n", dlen);
+               goto invalid;
        }
-       TCHECK2(*pptr, 4);
-       rescode = EXTRACT_32BITS(pptr);
+       rescode = GET_BE_U_4(pptr);
 
        if (rescode > ASRMCD) {
-               printf("illegal ASRresult result code: %d!\n", rescode);
-               return -1;
+               ND_PRINT("illegal ASRresult result code: %u!\n", rescode);
+               goto invalid;
        }
 
-       if (vflag >= 3) {
-               printf("\n%s", ib);
+       if (ndo->ndo_vflag >= 3) {
+               ND_PRINT("\n%s", ib);
                switch (rescode) {
                case 0:
-                       printf("Success ");
+                       ND_PRINT("Success ");
                        break;
                case 1:
-                       printf("FE ID invalid ");
+                       ND_PRINT("FE ID invalid ");
                        break;
                case 2:
-                       printf("permission denied ");
+                       ND_PRINT("permission denied ");
                        break;
                default:
-                       printf("Unknown ");
+                       ND_PRINT("Unknown ");
                        break;
                }
-               printf("(%x)\n%s", rescode, ib);
+               ND_PRINT("(%x)\n%s", rescode, ib);
        }
        return 0;
-
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
        return -1;
 }
 
+#if 0
 /*
  * XXX - not used.
  */
-int
-gentltlv_print(register const u_char * pptr _U_, register u_int len,
-              u_int16_t op_msk _U_, int indent _U_)
+static int
+gentltlv_print(netdissect_options *ndo,
+               const u_char * pptr _U_, u_int len,
+               uint16_t op_msk _U_, int indent _U_)
 {
        u_int dlen = len - TLV_HDRL;
 
        if (dlen < 4) {         /* at least 32 bits must exist */
-               printf("truncated TLV: %d bytes missing! ", 4 - dlen);
+               ND_PRINT("truncated TLV: %u bytes missing! ", 4 - dlen);
                return -1;
        }
        return 0;
 }
+#endif
 
 #define RD_MIN 8
-int
-print_metailv(register const u_char * pptr, register u_int len,
-             u_int16_t op_msk _U_, int indent)
+
+static int
+print_metailv(netdissect_options *ndo,
+              const struct forces_ilv * ilv, uint16_t op_msk _U_,
+              const int indent)
 {
-       u_int dlen;
        u_int rlen;
        char *ib = indent_pr(indent, 0);
        /* XXX: check header length */
-       const struct forces_ilv *ilv = (struct forces_ilv *)pptr;
 
        /*
         * print_metatlv() has ensured that len (what remains in the
         * ILV) >= ILV_HDRL.
         */
-       dlen = len - ILV_HDRL;
-       rlen = dlen;
-       TCHECK(*ilv);
-       printf("\n%sMetaID 0x%x length %d\n", ib, EXTRACT_32BITS(&ilv->type),
-              EXTRACT_32BITS(&ilv->length));
-       hex_print_with_offset("\n\t\t\t\t[", ILV_DATA(ilv), rlen, 0);
+       rlen = GET_BE_U_4(ilv->length) - ILV_HDRL;
+       ND_PRINT("%sMetaID 0x%x length %u\n", ib, GET_BE_U_4(ilv->type),
+                 GET_BE_U_4(ilv->length));
+       if (ndo->ndo_vflag >= 3) {
+               hex_print(ndo, "\t\t[", ILV_DATA(ilv), rlen);
+               ND_PRINT(" ]\n");
+       }
        return 0;
-
-trunc:
-       fputs("[|forces]", stdout);
-       return -1;
 }
 
-int
-print_metatlv(register const u_char * pptr, register u_int len,
-             u_int16_t op_msk _U_, int indent)
+static int
+print_metatlv(netdissect_options *ndo,
+              const u_char * pptr, u_int len,
+              uint16_t op_msk _U_, int indent)
 {
        u_int dlen;
        char *ib = indent_pr(indent, 0);
        u_int rlen;
-       const struct forces_ilv *ilv = (struct forces_ilv *)pptr;
+       const struct forces_ilv *ilv = (const struct forces_ilv *)pptr;
        int invilv;
 
        /*
@@ -668,85 +1341,57 @@ print_metatlv(register const u_char * pptr, register u_int len,
         */
        dlen = len - TLV_HDRL;
        rlen = dlen;
-       printf("\n%s METADATA\n", ib);
+       ND_PRINT("\n%s METADATA length %u\n", ib, rlen);
        while (rlen != 0) {
-               TCHECK(*ilv);
-               invilv = ilv_valid(ilv, rlen);
-               if (invilv)
+               invilv = ilv_valid(ndo, ilv, rlen);
+               if (invilv) {
                        break;
+               }
 
                /*
                 * At this point, ilv_valid() has ensured that the ILV
                 * length is large enough but not too large (it doesn't
                 * go past the end of the containing TLV).
                 */
-               print_metailv((u_char *) ilv, rlen, 0, indent + 1);
-
+               print_metailv(ndo, ilv, 0, indent + 1);
                ilv = GO_NXT_ILV(ilv, rlen);
        }
 
        return 0;
-
-trunc:
-       fputs("[|forces]", stdout);
-       return -1;
 }
 
-/*
-*/
-int
-print_reddata(register const u_char * pptr, register u_int len,
-             u_int16_t op_msk _U_, int indent _U_)
+
+static int
+print_reddata(netdissect_options *ndo,
+              const u_char * pptr, u_int len,
+              uint16_t op_msk _U_, int indent)
 {
        u_int dlen;
+       char *ib = indent_pr(indent, 0);
        u_int rlen;
-       int invtlv;
-       const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
 
-       /*
-        * redirect_print() has ensured that len (what remains in the
-        * TLV) >= TLV_HDRL.
-        */
        dlen = len - TLV_HDRL;
-       printf("\n\t\t Redirect DATA\n");
-       if (dlen <= RD_MIN) {
-               printf("\n\t\ttruncated Redirect data: %d bytes missing! ",
-                      RD_MIN - dlen);
-               return -1;
-       }
-
        rlen = dlen;
-       TCHECK(*tlv);
-       invtlv = tlv_valid(tlv, rlen);
+       ND_PRINT("\n%s Redirect Data length %u\n", ib, rlen);
 
-       if (invtlv) {
-               printf("Redir data type 0x%x len %d\n", EXTRACT_16BITS(&tlv->type),
-                      EXTRACT_16BITS(&tlv->length));
-               return -1;
+       if (ndo->ndo_vflag >= 3) {
+               ND_PRINT("\t\t[");
+               hex_print(ndo, "\n\t\t", pptr, rlen);
+               ND_PRINT("\n\t\t]");
        }
 
-       /*
-        * 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).
-        */
-       rlen -= TLV_HDRL;
-       hex_print_with_offset("\n\t\t\t[", TLV_DATA(tlv), rlen, 0);
        return 0;
-
-trunc:
-       fputs("[|forces]", stdout);
-       return -1;
 }
 
-int
-redirect_print(register const u_char * pptr, register u_int len,
-              u_int16_t op_msk _U_, int indent)
+static int
+redirect_print(netdissect_options *ndo,
+               const u_char * pptr, u_int len,
+               uint16_t op_msk _U_, int indent)
 {
-       const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
+       const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
        u_int dlen;
        u_int rlen;
-       int invtlv;
+       u_int invtlv;
 
        /*
         * forces_type_print() has ensured that len (the TLV length)
@@ -754,63 +1399,72 @@ redirect_print(register const u_char * pptr, register u_int len,
         */
        dlen = len - TLV_HDRL;
        if (dlen <= RD_MIN) {
-               printf("\n\t\ttruncated Redirect TLV: %d bytes missing! ",
+               ND_PRINT("\n\t\ttruncated Redirect TLV: %u bytes missing! ",
                       RD_MIN - dlen);
-               return -1;
+               goto invalid;
        }
 
        rlen = dlen;
        indent += 1;
        while (rlen != 0) {
-               TCHECK(*tlv);
-               invtlv = tlv_valid(tlv, rlen);
-               if (invtlv)
+               uint16_t type, tlvl;
+
+               type = GET_BE_U_2(tlv->type);
+               tlvl = GET_BE_U_2(tlv->length);
+               invtlv = tlv_valid(tlvl, rlen);
+               if (invtlv) {
+                       ND_PRINT("Bad Redirect data\n");
                        break;
+               }
 
                /*
                 * 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).
                 */
-               if (EXTRACT_16BITS(&tlv->type) == F_TLV_METD) {
-                       print_metatlv((u_char *) TLV_DATA(tlv), rlen, 0, indent);
-               } else if ((EXTRACT_16BITS(&tlv->type) == F_TLV_REDD)) {
-                       print_reddata((u_char *) TLV_DATA(tlv), rlen, 0, indent);
+               if (type == F_TLV_METD) {
+                       print_metatlv(ndo, TLV_DATA(tlv),
+                                     tlvl, 0,
+                                     indent);
+               } else if (type == F_TLV_REDD) {
+                       print_reddata(ndo, TLV_DATA(tlv),
+                                     tlvl, 0,
+                                     indent);
                } else {
-                       printf("Unknown REDIRECT TLV 0x%x len %d\n",
-                              EXTRACT_16BITS(&tlv->type), EXTRACT_16BITS(&tlv->length));
+                       ND_PRINT("Unknown REDIRECT TLV 0x%x len %u\n",
+                              type,
+                              tlvl);
                }
 
                tlv = GO_NXT_TLV(tlv, rlen);
        }
 
        if (rlen) {
-               printf
-                   ("\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
-                    EXTRACT_16BITS(&tlv->type), rlen - EXTRACT_16BITS(&tlv->length));
-               return -1;
+               ND_PRINT("\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %u Bytes ",
+                         GET_BE_U_2(tlv->type),
+                         rlen - GET_BE_U_2(tlv->length));
+               goto invalid;
        }
 
        return 0;
-
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
        return -1;
 }
 
 #define OP_OFF 8
 #define OP_MIN 12
 
-int
-lfbselect_print(register const u_char * pptr, register u_int len,
-               u_int16_t op_msk, int indent)
+static int
+lfbselect_print(netdissect_options *ndo,
+                const u_char * pptr, u_int len,
+                uint16_t op_msk, int indent)
 {
        const struct forces_lfbsh *lfbs;
        const struct forces_tlv *otlv;
        char *ib = indent_pr(indent, 0);
        u_int dlen;
        u_int rlen;
-       int invtlv;
+       u_int invtlv;
 
        /*
         * forces_type_print() has ensured that len (the TLV length)
@@ -818,9 +1472,9 @@ lfbselect_print(register const u_char * pptr, register u_int len,
         */
        dlen = len - TLV_HDRL;
        if (dlen <= OP_MIN) {   /* id, instance, oper tlv header .. */
-               printf("\n\t\ttruncated lfb selector: %d bytes missing! ",
+               ND_PRINT("\n\t\tundersized lfb selector: %u bytes missing! ",
                       OP_MIN - dlen);
-               return -1;
+               goto invalid;
        }
 
        /*
@@ -830,20 +1484,24 @@ lfbselect_print(register const u_char * pptr, register u_int len,
        rlen = dlen - OP_OFF;
 
        lfbs = (const struct forces_lfbsh *)pptr;
-       TCHECK(*lfbs);
-       if (vflag >= 3) {
-               printf("\n%s%s(Classid %x) instance %x\n",
-                      ib, tok2str(ForCES_LFBs, NULL, EXTRACT_32BITS(&lfbs->class)),
-                      EXTRACT_32BITS(&lfbs->class),
-                      EXTRACT_32BITS(&lfbs->instance));
+       ND_TCHECK_SIZE(lfbs);
+       if (ndo->ndo_vflag >= 3) {
+               ND_PRINT("\n%s%s(Classid %x) instance %x\n",
+                      ib,
+                      tok2str(ForCES_LFBs, NULL, GET_BE_U_4(lfbs->class)),
+                      GET_BE_U_4(lfbs->class),
+                      GET_BE_U_4(lfbs->instance));
        }
 
-       otlv = (struct forces_tlv *)(lfbs + 1);
+       otlv = (const struct forces_tlv *)(lfbs + 1);
 
        indent += 1;
        while (rlen != 0) {
-               TCHECK(*otlv);
-               invtlv = tlv_valid(otlv, rlen);
+               uint16_t type, tlvl;
+
+               type = GET_BE_U_2(otlv->type);
+               tlvl = GET_BE_U_2(otlv->length);
+               invtlv = tlv_valid(tlvl, rlen);
                if (invtlv)
                        break;
 
@@ -852,42 +1510,41 @@ lfbselect_print(register const u_char * pptr, register u_int len,
                 * length is large enough but not too large (it doesn't
                 * go past the end of the containing TLV).
                 */
-               if (op_valid(EXTRACT_16BITS(&otlv->type), op_msk)) {
-                       otlv_print(otlv, 0, indent);
+               if (op_valid(type, op_msk)) {
+                       otlv_print(ndo, otlv, 0, indent);
                } else {
-                       if (vflag < 3)
-                               printf("\n");
-                       printf
-                           ("\t\tINValid oper-TLV type 0x%x length %d for this ForCES message\n",
-                            EXTRACT_16BITS(&otlv->type), EXTRACT_16BITS(&otlv->length));
-                       invoptlv_print((u_char *)otlv, rlen, 0, indent);
+                       if (ndo->ndo_vflag < 3)
+                               ND_PRINT("\n");
+                       ND_PRINT("\t\tINValid oper-TLV type 0x%x length %u for this ForCES message\n",
+                                 type, tlvl);
+                       invoptlv_print(ndo, (const u_char *)otlv, rlen, 0, indent);
                }
                otlv = GO_NXT_TLV(otlv, rlen);
        }
 
        if (rlen) {
-               printf
-                   ("\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
-                    EXTRACT_16BITS(&otlv->type), rlen - EXTRACT_16BITS(&otlv->length));
-               return -1;
+               ND_PRINT("\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %u Bytes ",
+                         GET_BE_U_2(otlv->type),
+                         rlen - GET_BE_U_2(otlv->length));
+               goto invalid;
        }
 
        return 0;
 
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
        return -1;
 }
 
-int
-forces_type_print(register const u_char * pptr, const struct forcesh *fhdr _U_,
-                 register u_int mlen, const struct tom_h *tops)
+static int
+forces_type_print(netdissect_options *ndo,
+                  const u_char * pptr, const struct forcesh *fhdr _U_,
+                  u_int mlen, const struct tom_h *tops)
 {
        const struct forces_tlv *tltlv;
        u_int rlen;
-       int invtlv;
+       u_int invtlv;
        int rc = 0;
-       int ttlv = 0;
+       u_int ttlv = 0;
 
        /*
         * forces_print() has already checked that mlen >= ForCES_HDRL
@@ -897,15 +1554,15 @@ forces_type_print(register const u_char * pptr, const struct forcesh *fhdr _U_,
 
        if (rlen > TLV_HLN) {
                if (tops->flags & ZERO_TTLV) {
-                       printf("<0x%x>Illegal Top level TLV!\n", tops->flags);
-                       return -1;
+                       ND_PRINT("<0x%x>Illegal Top level TLV!\n", tops->flags);
+                       goto invalid;
                }
        } else {
                if (tops->flags & ZERO_MORE_TTLV)
                        return 0;
                if (tops->flags & ONE_MORE_TTLV) {
-                       printf("\tTop level TLV Data missing!\n");
-                       return -1;
+                       ND_PRINT("\tTop level TLV Data missing!\n");
+                       goto invalid;
                }
        }
 
@@ -919,8 +1576,11 @@ forces_type_print(register const u_char * pptr, const struct forcesh *fhdr _U_,
        /*XXX: 15 top level tlvs will probably be fine
           You are nuts if you send more ;-> */
        while (rlen != 0) {
-               TCHECK(*tltlv);
-               invtlv = tlv_valid(tltlv, rlen);
+               uint16_t type, tlvl;
+
+               type = GET_BE_U_2(tltlv->type);
+               tlvl = GET_BE_U_2(tltlv->length);
+               invtlv = tlv_valid(tlvl, rlen);
                if (invtlv)
                        break;
 
@@ -929,23 +1589,22 @@ forces_type_print(register const u_char * pptr, const struct forcesh *fhdr _U_,
                 * length is large enough but not too large (it doesn't
                 * go past the end of the packet).
                 */
-               if (!ttlv_valid(EXTRACT_16BITS(&tltlv->type))) {
-                       printf("\n\tInvalid ForCES Top TLV type=0x%x",
-                              EXTRACT_16BITS(&tltlv->type));
-                       return -1;
+               if (!ttlv_valid(type)) {
+                       ND_PRINT("\n\tInvalid ForCES Top TLV type=0x%x",
+                              type);
+                       goto invalid;
                }
 
-               if (vflag >= 3)
-                       printf("\t%s, length %d (data length %d Bytes)",
-                              tok2str(ForCES_TLV, NULL, EXTRACT_16BITS(&tltlv->type)),
-                              EXTRACT_16BITS(&tltlv->length),
-                              EXTRACT_16BITS(&tltlv->length) - TLV_HDRL);
+               if (ndo->ndo_vflag >= 3)
+                       ND_PRINT("\t%s, length %u (data length %u Bytes)",
+                              tok2str(ForCES_TLV, NULL, type),
+                              tlvl,
+                              tlvl - TLV_HDRL);
 
-               rc = tops->print((u_char *) TLV_DATA(tltlv),
-                                EXTRACT_16BITS(&tltlv->length), tops->op_msk, 9);
-               if (rc < 0) {
-                       return -1;
-               }
+               rc = tops->print(ndo, TLV_DATA(tltlv),
+                                tlvl,
+                                tops->op_msk, 9);
+               ND_ICHECK_U(rc, <, 0);
                tltlv = GO_NXT_TLV(tltlv, rlen);
                ttlv--;
                if (ttlv <= 0)
@@ -956,88 +1615,84 @@ forces_type_print(register const u_char * pptr, const struct forcesh *fhdr _U_,
         * short, and didn't have *enough* TLVs in it?
         */
        if (rlen) {
-               printf("\tMess TopTLV header: min %u, total %d advertised %d ",
-                      TLV_HDRL, rlen, EXTRACT_16BITS(&tltlv->length));
-               return -1;
+               ND_PRINT("\tMess TopTLV header: min %u, total %u advertised %u ",
+                      TLV_HDRL, rlen, GET_BE_U_2(tltlv->length));
+               goto invalid;
        }
 
        return 0;
-
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
        return -1;
 }
 
-void forces_print(register const u_char * pptr, register u_int len)
+void
+forces_print(netdissect_options *ndo,
+             const u_char * pptr, u_int len)
 {
        const struct forcesh *fhdr;
        u_int mlen;
-       u_int32_t flg_raw;
+       uint32_t flg_raw;
+       uint8_t tom;
        const struct tom_h *tops;
        int rc = 0;
 
+       ndo->ndo_protocol = "forces";
        fhdr = (const struct forcesh *)pptr;
-       TCHECK(*fhdr);
-       if (!tom_valid(fhdr->fm_tom)) {
-               printf("Invalid ForCES message type %d\n", fhdr->fm_tom);
-               goto error;
+       ND_TCHECK_SIZE(fhdr);
+       tom = GET_U_1(fhdr->fm_tom);
+       if (!tom_valid(tom)) {
+               ND_PRINT("Invalid ForCES message type %u\n", tom);
+               goto invalid;
        }
 
        mlen = ForCES_BLN(fhdr);
 
-       tops = get_forces_tom(fhdr->fm_tom);
+       tops = get_forces_tom(tom);
        if (tops->v == TOM_RSVD) {
-               printf("\n\tUnknown ForCES message type=0x%x", fhdr->fm_tom);
-               goto error;
+               ND_PRINT("\n\tUnknown ForCES message type=0x%x", tom);
+               goto invalid;
        }
 
-       printf("\n\tForCES %s ", tops->s);
+       ND_PRINT("\n\tForCES %s ", tops->s);
        if (!ForCES_HLN_VALID(mlen, len)) {
-               printf
-                   ("Illegal ForCES pkt len - min %u, total recvd %d, advertised %d ",
-                    ForCES_HDRL, len, ForCES_BLN(fhdr));
-               goto error;
+               ND_PRINT("Illegal ForCES pkt len - min %u, total recvd %u, advertised %u ",
+                         ForCES_HDRL, len, ForCES_BLN(fhdr));
+               goto invalid;
        }
 
-       TCHECK2(*(pptr + 20), 4);
-       flg_raw = EXTRACT_32BITS(pptr + 20);
-       if (vflag >= 1) {
-               printf("\n\tForCES Version %d len %uB flags 0x%08x ",
+       flg_raw = GET_BE_U_4(pptr + 20);
+       if (ndo->ndo_vflag >= 1) {
+               ND_PRINT("\n\tForCES Version %u len %uB flags 0x%08x ",
                       ForCES_V(fhdr), mlen, flg_raw);
-               printf("\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%" PRIu64,
+               ND_PRINT("\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%" PRIx64,
                       ForCES_SID(fhdr), ForCES_node(ForCES_SID(fhdr)),
                       ForCES_DID(fhdr), ForCES_node(ForCES_DID(fhdr)),
-                      EXTRACT_64BITS(fhdr->fm_cor));
+                      GET_BE_U_8(fhdr->fm_cor));
 
        }
-       if (vflag >= 2) {
-               printf
-                   ("\n\tForCES flags:\n\t  %s(0x%x), prio=%d, %s(0x%x),\n\t  %s(0x%x), %s(0x%x)\n",
-                    ForCES_ACKp(ForCES_ACK(fhdr)), ForCES_ACK(fhdr),
+       if (ndo->ndo_vflag >= 2) {
+               ND_PRINT("\n\tForCES flags:\n\t  %s(0x%x), prio=%u, %s(0x%x),\n\t  %s(0x%x), %s(0x%x)\n",
+                    tok2str(ForCES_ACKs, "ACKUnknown", ForCES_ACK(fhdr)),
+                    ForCES_ACK(fhdr),
                     ForCES_PRI(fhdr),
-                    ForCES_EMp(ForCES_EM(fhdr)), ForCES_EM(fhdr),
-                    ForCES_ATp(ForCES_AT(fhdr)), ForCES_AT(fhdr),
-                    ForCES_TPp(ForCES_TP(fhdr)), ForCES_TP(fhdr));
-               printf
-                   ("\t  Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n",
+                    tok2str(ForCES_EMs, "EMUnknown", ForCES_EM(fhdr)),
+                    ForCES_EM(fhdr),
+                    tok2str(ForCES_ATs, "ATUnknown", ForCES_AT(fhdr)),
+                    ForCES_AT(fhdr),
+                    tok2str(ForCES_TPs, "TPUnknown", ForCES_TP(fhdr)),
+                    ForCES_TP(fhdr));
+               ND_PRINT("\t  Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n",
                     ForCES_RS1(fhdr), ForCES_RS2(fhdr));
        }
-       rc = forces_type_print(pptr, fhdr, mlen, tops);
-       if (rc < 0) {
-error:
-               hex_print_with_offset("\n\t[", pptr, len, 0);
-               printf("\n\t]");
-               return;
-       }
+       rc = forces_type_print(ndo, pptr, fhdr, mlen, tops);
+       ND_ICHECK_U(rc, <, 0);
 
-       if (vflag >= 4) {
-               printf("\n\t  Raw ForCES message\n\t [");
-               hex_print_with_offset("\n\t ", pptr, len, 0);
-               printf("\n\t ]");
+       if (ndo->ndo_vflag >= 4) {
+               ND_PRINT("\n\t  Raw ForCES message\n\t [");
+               hex_print(ndo, "\n\t ", pptr, len);
+               ND_PRINT("\n\t ]");
        }
-       printf("\n");
        return;
-
-trunc:
-       fputs("[|forces]", stdout);
+invalid:
+       nd_print_invalid(ndo);
 }