xref: /dflybsd-src/contrib/tcpdump/print-forces.c (revision 59c07fbdf8168fa08c76c515186d561b5a92690c)
127bfbee1SPeter Avalos /*
227bfbee1SPeter Avalos  * Redistribution and use in source and binary forms, with or without
327bfbee1SPeter Avalos  * modification, are permitted provided that: (1) source code
427bfbee1SPeter Avalos  * distributions retain the above copyright notice and this paragraph
527bfbee1SPeter Avalos  * in its entirety, and (2) distributions including binary code include
627bfbee1SPeter Avalos  * the above copyright notice and this paragraph in its entirety in
727bfbee1SPeter Avalos  * the documentation or other materials provided with the distribution.
827bfbee1SPeter Avalos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
927bfbee1SPeter Avalos  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
1027bfbee1SPeter Avalos  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1127bfbee1SPeter Avalos  * FOR A PARTICULAR PURPOSE.
1227bfbee1SPeter Avalos  *
1327bfbee1SPeter Avalos  * Copyright (c) 2009 Mojatatu Networks, Inc
1427bfbee1SPeter Avalos  *
1527bfbee1SPeter Avalos  */
1627bfbee1SPeter Avalos 
17411677aeSAaron LI /* \summary: Forwarding and Control Element Separation (ForCES) Protocol printer */
18411677aeSAaron LI 
19411677aeSAaron LI /* specification: RFC 5810 */
20411677aeSAaron LI 
2127bfbee1SPeter Avalos #ifdef HAVE_CONFIG_H
22*ed775ee7SAntonio Huete Jimenez #include <config.h>
2327bfbee1SPeter Avalos #endif
2427bfbee1SPeter Avalos 
25*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
2627bfbee1SPeter Avalos 
27411677aeSAaron LI #include "netdissect.h"
2827bfbee1SPeter Avalos #include "extract.h"
2927bfbee1SPeter Avalos 
30411677aeSAaron LI 
31411677aeSAaron LI #define	ForCES_VERS	1
32411677aeSAaron LI #define	ForCES_HDRL	24
33411677aeSAaron LI #define	ForCES_ALNL	4U
34411677aeSAaron LI #define TLV_HDRL	4
35411677aeSAaron LI #define ILV_HDRL	8
36411677aeSAaron LI 
37411677aeSAaron LI #define TOM_RSVD 	0x0
38411677aeSAaron LI #define TOM_ASSNSETUP 	0x1
39411677aeSAaron LI #define TOM_ASSNTEARD 	0x2
40411677aeSAaron LI #define TOM_CONFIG 	0x3
41411677aeSAaron LI #define TOM_QUERY 	0x4
42411677aeSAaron LI #define TOM_EVENTNOT 	0x5
43411677aeSAaron LI #define TOM_PKTREDIR 	0x6
44411677aeSAaron LI #define TOM_HEARTBT 	0x0F
45411677aeSAaron LI #define TOM_ASSNSETREP 	0x11
46411677aeSAaron LI #define TOM_CONFIGREP 	0x13
47411677aeSAaron LI #define TOM_QUERYREP 	0x14
48411677aeSAaron LI 
49411677aeSAaron LI /*
50411677aeSAaron LI  * tom_h Flags: resv1(8b):maxtlvs(4b):resv2(2b):mintlv(2b)
51411677aeSAaron LI */
52411677aeSAaron LI #define ZERO_TTLV	0x01
53411677aeSAaron LI #define ZERO_MORE_TTLV	0x02
54411677aeSAaron LI #define ONE_MORE_TTLV	0x04
55411677aeSAaron LI #define ZERO_TLV	0x00
56411677aeSAaron LI #define ONE_TLV		0x10
57411677aeSAaron LI #define TWO_TLV		0x20
58411677aeSAaron LI #define MAX_TLV		0xF0
59411677aeSAaron LI 
60411677aeSAaron LI #define TTLV_T1		(ONE_MORE_TTLV|ONE_TLV)
61411677aeSAaron LI #define TTLV_T2		(ONE_MORE_TTLV|MAX_TLV)
62411677aeSAaron LI 
63411677aeSAaron LI struct tom_h {
64411677aeSAaron LI 	uint32_t v;
65411677aeSAaron LI 	uint16_t flags;
66411677aeSAaron LI 	uint16_t op_msk;
67411677aeSAaron LI 	const char *s;
68*ed775ee7SAntonio Huete Jimenez 	int (*print) (netdissect_options *ndo, const u_char * pptr, u_int len,
69411677aeSAaron LI 		      uint16_t op_msk, int indent);
70411677aeSAaron LI };
71411677aeSAaron LI 
72411677aeSAaron LI enum {
73411677aeSAaron LI 	TOM_RSV_I,
74411677aeSAaron LI 	TOM_ASS_I,
75411677aeSAaron LI 	TOM_AST_I,
76411677aeSAaron LI 	TOM_CFG_I,
77411677aeSAaron LI 	TOM_QRY_I,
78411677aeSAaron LI 	TOM_EVN_I,
79411677aeSAaron LI 	TOM_RED_I,
80411677aeSAaron LI 	TOM_HBT_I,
81411677aeSAaron LI 	TOM_ASR_I,
82411677aeSAaron LI 	TOM_CNR_I,
83411677aeSAaron LI 	TOM_QRR_I,
84411677aeSAaron LI 	_TOM_RSV_MAX
85411677aeSAaron LI };
86411677aeSAaron LI #define TOM_MAX_IND (_TOM_RSV_MAX - 1)
87411677aeSAaron LI 
88*ed775ee7SAntonio Huete Jimenez static int
tom_valid(uint8_t tom)89*ed775ee7SAntonio Huete Jimenez tom_valid(uint8_t tom)
90411677aeSAaron LI {
91411677aeSAaron LI 	if (tom > 0) {
92411677aeSAaron LI 		if (tom >= 0x7 && tom <= 0xe)
93411677aeSAaron LI 			return 0;
94411677aeSAaron LI 		if (tom == 0x10)
95411677aeSAaron LI 			return 0;
96411677aeSAaron LI 		if (tom > 0x14)
97411677aeSAaron LI 			return 0;
98411677aeSAaron LI 		return 1;
99411677aeSAaron LI 	} else
100411677aeSAaron LI 		return 0;
101411677aeSAaron LI }
102411677aeSAaron LI 
103*ed775ee7SAntonio Huete Jimenez static const char *
ForCES_node(uint32_t node)104*ed775ee7SAntonio Huete Jimenez ForCES_node(uint32_t node)
105411677aeSAaron LI {
106411677aeSAaron LI 	if (node <= 0x3FFFFFFF)
107411677aeSAaron LI 		return "FE";
108411677aeSAaron LI 	if (node >= 0x40000000 && node <= 0x7FFFFFFF)
109411677aeSAaron LI 		return "CE";
110411677aeSAaron LI 	if (node >= 0xC0000000 && node <= 0xFFFFFFEF)
111411677aeSAaron LI 		return "AllMulticast";
112411677aeSAaron LI 	if (node == 0xFFFFFFFD)
113411677aeSAaron LI 		return "AllCEsBroadcast";
114411677aeSAaron LI 	if (node == 0xFFFFFFFE)
115411677aeSAaron LI 		return "AllFEsBroadcast";
116411677aeSAaron LI 	if (node == 0xFFFFFFFF)
117411677aeSAaron LI 		return "AllBroadcast";
118411677aeSAaron LI 
119411677aeSAaron LI 	return "ForCESreserved";
120411677aeSAaron LI 
121411677aeSAaron LI }
122411677aeSAaron LI 
123411677aeSAaron LI static const struct tok ForCES_ACKs[] = {
124411677aeSAaron LI 	{0x0, "NoACK"},
125411677aeSAaron LI 	{0x1, "SuccessACK"},
126411677aeSAaron LI 	{0x2, "FailureACK"},
127411677aeSAaron LI 	{0x3, "AlwaysACK"},
128411677aeSAaron LI 	{0, NULL}
129411677aeSAaron LI };
130411677aeSAaron LI 
131411677aeSAaron LI static const struct tok ForCES_EMs[] = {
132411677aeSAaron LI 	{0x0, "EMReserved"},
133411677aeSAaron LI 	{0x1, "execute-all-or-none"},
134411677aeSAaron LI 	{0x2, "execute-until-failure"},
135411677aeSAaron LI 	{0x3, "continue-execute-on-failure"},
136411677aeSAaron LI 	{0, NULL}
137411677aeSAaron LI };
138411677aeSAaron LI 
139411677aeSAaron LI static const struct tok ForCES_ATs[] = {
140411677aeSAaron LI 	{0x0, "Standalone"},
141411677aeSAaron LI 	{0x1, "2PCtransaction"},
142411677aeSAaron LI 	{0, NULL}
143411677aeSAaron LI };
144411677aeSAaron LI 
145411677aeSAaron LI static const struct tok ForCES_TPs[] = {
146411677aeSAaron LI 	{0x0, "StartofTransaction"},
147411677aeSAaron LI 	{0x1, "MiddleofTransaction"},
148411677aeSAaron LI 	{0x2, "EndofTransaction"},
149411677aeSAaron LI 	{0x3, "abort"},
150411677aeSAaron LI 	{0, NULL}
151411677aeSAaron LI };
152411677aeSAaron LI 
153411677aeSAaron LI /*
154411677aeSAaron LI  * Structure of forces header, naked of TLVs.
155411677aeSAaron LI  */
156411677aeSAaron LI struct forcesh {
157411677aeSAaron LI 	nd_uint8_t fm_vrsvd;	/* version and reserved */
158*ed775ee7SAntonio Huete Jimenez #define ForCES_V(forcesh)	(GET_U_1((forcesh)->fm_vrsvd) >> 4)
159411677aeSAaron LI 	nd_uint8_t fm_tom;	/* type of message */
160411677aeSAaron LI 	nd_uint16_t fm_len;	/* total length * 4 bytes */
161*ed775ee7SAntonio Huete Jimenez #define ForCES_BLN(forcesh)	((uint32_t)(GET_BE_U_2((forcesh)->fm_len) << 2))
162411677aeSAaron LI 	nd_uint32_t fm_sid;	/* Source ID */
163*ed775ee7SAntonio Huete Jimenez #define ForCES_SID(forcesh)	GET_BE_U_4((forcesh)->fm_sid)
164411677aeSAaron LI 	nd_uint32_t fm_did;	/* Destination ID */
165*ed775ee7SAntonio Huete Jimenez #define ForCES_DID(forcesh)	GET_BE_U_4((forcesh)->fm_did)
166411677aeSAaron LI 	nd_uint8_t fm_cor[8];	/* correlator */
167411677aeSAaron LI 	nd_uint32_t fm_flags;	/* flags */
168*ed775ee7SAntonio Huete Jimenez #define ForCES_ACK(forcesh)	((GET_BE_U_4((forcesh)->fm_flags)&0xC0000000) >> 30)
169*ed775ee7SAntonio Huete Jimenez #define ForCES_PRI(forcesh)	((GET_BE_U_4((forcesh)->fm_flags)&0x38000000) >> 27)
170*ed775ee7SAntonio Huete Jimenez #define ForCES_RS1(forcesh)	((GET_BE_U_4((forcesh)->fm_flags)&0x07000000) >> 24)
171*ed775ee7SAntonio Huete Jimenez #define ForCES_EM(forcesh)	((GET_BE_U_4((forcesh)->fm_flags)&0x00C00000) >> 22)
172*ed775ee7SAntonio Huete Jimenez #define ForCES_AT(forcesh)	((GET_BE_U_4((forcesh)->fm_flags)&0x00200000) >> 21)
173*ed775ee7SAntonio Huete Jimenez #define ForCES_TP(forcesh)	((GET_BE_U_4((forcesh)->fm_flags)&0x00180000) >> 19)
174*ed775ee7SAntonio Huete Jimenez #define ForCES_RS2(forcesh)	((GET_BE_U_4((forcesh)->fm_flags)&0x0007FFFF) >> 0)
175411677aeSAaron LI };
176411677aeSAaron LI 
177411677aeSAaron LI #define ForCES_HLN_VALID(fhl,tlen) ((tlen) >= ForCES_HDRL && \
178411677aeSAaron LI 				   (fhl) >= ForCES_HDRL && \
179411677aeSAaron LI 				   (fhl) == (tlen))
180411677aeSAaron LI 
181411677aeSAaron LI #define F_LFB_RSVD 0x0
182411677aeSAaron LI #define F_LFB_FEO 0x1
183411677aeSAaron LI #define F_LFB_FEPO 0x2
184411677aeSAaron LI static const struct tok ForCES_LFBs[] = {
185411677aeSAaron LI 	{F_LFB_RSVD, "Invalid TLV"},
186411677aeSAaron LI 	{F_LFB_FEO, "FEObj LFB"},
187411677aeSAaron LI 	{F_LFB_FEPO, "FEProtoObj LFB"},
188411677aeSAaron LI 	{0, NULL}
189411677aeSAaron LI };
190411677aeSAaron LI 
191411677aeSAaron LI /* this is defined in RFC5810 section A.2 */
192*ed775ee7SAntonio Huete Jimenez /*   https://www.iana.org/assignments/forces/forces.xhtml#oper-tlv-types */
193411677aeSAaron LI enum {
194411677aeSAaron LI 	F_OP_RSV        = 0,
195411677aeSAaron LI 	F_OP_SET        = 1,
196411677aeSAaron LI 	F_OP_SETPROP    = 2,
197411677aeSAaron LI 	F_OP_SETRESP    = 3,
198411677aeSAaron LI 	F_OP_SETPRESP   = 4,
199411677aeSAaron LI 	F_OP_DEL        = 5,
200411677aeSAaron LI 	F_OP_DELRESP    = 6,
201411677aeSAaron LI 	F_OP_GET        = 7,
202411677aeSAaron LI 	F_OP_GETPROP    = 8,
203411677aeSAaron LI 	F_OP_GETRESP    = 9,
204411677aeSAaron LI 	F_OP_GETPRESP   = 10,
205411677aeSAaron LI 	F_OP_REPORT     = 11,
206411677aeSAaron LI 	F_OP_COMMIT     = 12,
207411677aeSAaron LI 	F_OP_RCOMMIT    = 13,
208411677aeSAaron LI 	F_OP_RTRCOMP    = 14,
209411677aeSAaron LI 	_F_OP_MAX
210411677aeSAaron LI };
211411677aeSAaron LI #define F_OP_MAX	(_F_OP_MAX - 1)
212411677aeSAaron LI 
213411677aeSAaron LI enum {
214411677aeSAaron LI 	B_OP_SET = 1 << (F_OP_SET - 1),
215411677aeSAaron LI 	B_OP_SETPROP = 1 << (F_OP_SETPROP - 1),
216411677aeSAaron LI 	B_OP_SETRESP = 1 << (F_OP_SETRESP - 1),
217411677aeSAaron LI 	B_OP_SETPRESP = 1 << (F_OP_SETPRESP - 1),
218411677aeSAaron LI 	B_OP_DEL = 1 << (F_OP_DEL - 1),
219411677aeSAaron LI 	B_OP_DELRESP = 1 << (F_OP_DELRESP - 1),
220411677aeSAaron LI 	B_OP_GET = 1 << (F_OP_GET - 1),
221411677aeSAaron LI 	B_OP_GETPROP = 1 << (F_OP_GETPROP - 1),
222411677aeSAaron LI 	B_OP_GETRESP = 1 << (F_OP_GETRESP - 1),
223411677aeSAaron LI 	B_OP_GETPRESP = 1 << (F_OP_GETPRESP - 1),
224411677aeSAaron LI 	B_OP_REPORT = 1 << (F_OP_REPORT - 1),
225411677aeSAaron LI 	B_OP_COMMIT = 1 << (F_OP_COMMIT - 1),
226411677aeSAaron LI 	B_OP_RCOMMIT = 1 << (F_OP_RCOMMIT - 1),
227411677aeSAaron LI 	B_OP_RTRCOMP = 1 << (F_OP_RTRCOMP - 1)
228411677aeSAaron LI };
229411677aeSAaron LI 
230411677aeSAaron LI struct optlv_h {
231411677aeSAaron LI 	uint16_t flags;
232411677aeSAaron LI 	uint16_t op_msk;
233411677aeSAaron LI 	const char *s;
234*ed775ee7SAntonio Huete Jimenez 	int (*print) (netdissect_options *ndo, const u_char * pptr, u_int len,
235411677aeSAaron LI 		      uint16_t op_msk, int indent);
236411677aeSAaron LI };
237411677aeSAaron LI 
238*ed775ee7SAntonio Huete Jimenez static int genoptlv_print(netdissect_options *, const u_char * pptr, u_int len,
239411677aeSAaron LI 			 uint16_t op_msk, int indent);
240*ed775ee7SAntonio Huete Jimenez static int recpdoptlv_print(netdissect_options *, const u_char * pptr, u_int len,
241411677aeSAaron LI 			    uint16_t op_msk, int indent);
242*ed775ee7SAntonio Huete Jimenez static int invoptlv_print(netdissect_options *, const u_char * pptr, u_int len,
243411677aeSAaron LI 			  uint16_t op_msk, int indent);
244411677aeSAaron LI 
245411677aeSAaron LI #define OP_MIN_SIZ 8
246411677aeSAaron LI struct pathdata_h {
247411677aeSAaron LI 	nd_uint16_t pflags;
248411677aeSAaron LI 	nd_uint16_t pIDcnt;
249411677aeSAaron LI };
250411677aeSAaron LI 
251411677aeSAaron LI #define	B_FULLD		0x1
252411677aeSAaron LI #define	B_SPARD 	0x2
253411677aeSAaron LI #define B_RESTV		0x4
254411677aeSAaron LI #define B_KEYIN		0x8
255411677aeSAaron LI #define B_APPND		0x10
256411677aeSAaron LI #define B_TRNG		0x20
257411677aeSAaron LI 
258411677aeSAaron LI static const struct optlv_h OPTLV_msg[F_OP_MAX + 1] = {
259411677aeSAaron LI 	/* F_OP_RSV */ {ZERO_TTLV, 0, "Invalid OPTLV", invoptlv_print},
260411677aeSAaron LI 	/* F_OP_SET */ {TTLV_T2, B_FULLD | B_SPARD, " Set", recpdoptlv_print},
261411677aeSAaron LI 	/* F_OP_SETPROP */
262411677aeSAaron LI 	    {TTLV_T2, B_FULLD | B_SPARD, " SetProp", recpdoptlv_print},
263411677aeSAaron LI 	/* F_OP_SETRESP */ {TTLV_T2, B_RESTV, " SetResp", recpdoptlv_print},
264411677aeSAaron LI 	/* F_OP_SETPRESP */ {TTLV_T2, B_RESTV, " SetPropResp", recpdoptlv_print},
265411677aeSAaron LI 	/* F_OP_DEL */ {ZERO_TTLV, 0, " Del", recpdoptlv_print},
266411677aeSAaron LI 	/* F_OP_DELRESP */ {TTLV_T2, B_RESTV, " DelResp", recpdoptlv_print},
267411677aeSAaron LI 	/* F_OP_GET */ {ZERO_TTLV, 0, " Get", recpdoptlv_print},
268411677aeSAaron LI 	/* F_OP_GETPROP */ {ZERO_TTLV, 0, " GetProp", recpdoptlv_print},
269411677aeSAaron LI 	/* F_OP_GETRESP */
270411677aeSAaron LI 	    {TTLV_T2, B_FULLD | B_SPARD | B_RESTV, " GetResp", recpdoptlv_print},
271411677aeSAaron LI 	/* F_OP_GETPRESP */
272411677aeSAaron LI 	    {TTLV_T2, B_FULLD | B_RESTV, " GetPropResp", recpdoptlv_print},
273411677aeSAaron LI 	/* F_OP_REPORT */
274411677aeSAaron LI 	    {TTLV_T2, B_FULLD | B_SPARD, " Report", recpdoptlv_print},
275411677aeSAaron LI 	/* F_OP_COMMIT */ {ZERO_TTLV, 0, " Commit", NULL},
276411677aeSAaron LI 	/* F_OP_RCOMMIT */ {TTLV_T1, B_RESTV, " RCommit", genoptlv_print},
277411677aeSAaron LI 	/* F_OP_RTRCOMP */ {ZERO_TTLV, 0, " RTRCOMP", NULL},
278411677aeSAaron LI };
279411677aeSAaron LI 
280*ed775ee7SAntonio Huete Jimenez static const struct optlv_h *
get_forces_optlv_h(uint16_t opt)281*ed775ee7SAntonio Huete Jimenez get_forces_optlv_h(uint16_t opt)
282411677aeSAaron LI {
283*ed775ee7SAntonio Huete Jimenez 	if (opt > F_OP_MAX || opt == F_OP_RSV)
284411677aeSAaron LI 		return &OPTLV_msg[F_OP_RSV];
285411677aeSAaron LI 
286411677aeSAaron LI 	return &OPTLV_msg[opt];
287411677aeSAaron LI }
288411677aeSAaron LI 
289411677aeSAaron LI #define IND_SIZE 256
290411677aeSAaron LI #define IND_CHR ' '
291411677aeSAaron LI #define IND_PREF '\n'
292411677aeSAaron LI #define IND_SUF 0x0
293411677aeSAaron LI static char ind_buf[IND_SIZE];
294411677aeSAaron LI 
295*ed775ee7SAntonio Huete Jimenez static char *
indent_pr(int indent,int nlpref)296*ed775ee7SAntonio Huete Jimenez indent_pr(int indent, int nlpref)
297411677aeSAaron LI {
298411677aeSAaron LI 	int i = 0;
299411677aeSAaron LI 	char *r = ind_buf;
300411677aeSAaron LI 
301411677aeSAaron LI 	if (indent > (IND_SIZE - 1))
302411677aeSAaron LI 		indent = IND_SIZE - 1;
303411677aeSAaron LI 
304411677aeSAaron LI 	if (nlpref) {
305411677aeSAaron LI 		r[i] = IND_PREF;
306411677aeSAaron LI 		i++;
307411677aeSAaron LI 		indent--;
308411677aeSAaron LI 	}
309411677aeSAaron LI 
310411677aeSAaron LI 	while (--indent >= 0)
311411677aeSAaron LI 		r[i++] = IND_CHR;
312411677aeSAaron LI 
313411677aeSAaron LI 	r[i] = IND_SUF;
314411677aeSAaron LI 	return r;
315411677aeSAaron LI }
316411677aeSAaron LI 
317*ed775ee7SAntonio Huete Jimenez static int
op_valid(uint16_t op,uint16_t mask)318*ed775ee7SAntonio Huete Jimenez op_valid(uint16_t op, uint16_t mask)
319411677aeSAaron LI {
320411677aeSAaron LI 	if (op == 0)
321411677aeSAaron LI 		return 0;
322*ed775ee7SAntonio Huete Jimenez 	if (op <= F_OP_MAX)
323*ed775ee7SAntonio Huete Jimenez 		return (1 << (op - 1)) & mask; /* works only for 0x0001 through 0x0010 */
324411677aeSAaron LI 	/* I guess we should allow vendor operations? */
325411677aeSAaron LI 	if (op >= 0x8000)
326411677aeSAaron LI 		return 1;
327411677aeSAaron LI 	return 0;
328411677aeSAaron LI }
329411677aeSAaron LI 
330411677aeSAaron LI #define F_TLV_RSVD	0x0000
331411677aeSAaron LI #define F_TLV_REDR	0x0001
332411677aeSAaron LI #define F_TLV_ASRS	0x0010
333411677aeSAaron LI #define F_TLV_ASRT	0x0011
334411677aeSAaron LI #define F_TLV_LFBS	0x1000
335411677aeSAaron LI #define F_TLV_PDAT	0x0110
336411677aeSAaron LI #define F_TLV_KEYI	0x0111
337411677aeSAaron LI #define F_TLV_FULD	0x0112
338411677aeSAaron LI #define F_TLV_SPAD	0x0113
339411677aeSAaron LI #define F_TLV_REST	0x0114
340411677aeSAaron LI #define F_TLV_METD	0x0115
341411677aeSAaron LI #define F_TLV_REDD	0x0116
342411677aeSAaron LI #define F_TLV_TRNG	0x0117
343411677aeSAaron LI 
344411677aeSAaron LI 
345411677aeSAaron LI #define F_TLV_VNST	0x8000
346411677aeSAaron LI 
347411677aeSAaron LI static const struct tok ForCES_TLV[] = {
348411677aeSAaron LI 	{F_TLV_RSVD, "Invalid TLV"},
349411677aeSAaron LI 	{F_TLV_REDR, "REDIRECT TLV"},
350411677aeSAaron LI 	{F_TLV_ASRS, "ASResult TLV"},
351411677aeSAaron LI 	{F_TLV_ASRT, "ASTreason TLV"},
352411677aeSAaron LI 	{F_TLV_LFBS, "LFBselect TLV"},
353411677aeSAaron LI 	{F_TLV_PDAT, "PATH-DATA TLV"},
354411677aeSAaron LI 	{F_TLV_KEYI, "KEYINFO TLV"},
355411677aeSAaron LI 	{F_TLV_FULD, "FULLDATA TLV"},
356411677aeSAaron LI 	{F_TLV_SPAD, "SPARSEDATA TLV"},
357411677aeSAaron LI 	{F_TLV_REST, "RESULT TLV"},
358411677aeSAaron LI 	{F_TLV_METD, "METADATA TLV"},
359411677aeSAaron LI 	{F_TLV_REDD, "REDIRECTDATA TLV"},
360411677aeSAaron LI 	{0, NULL}
361411677aeSAaron LI };
362411677aeSAaron LI 
363411677aeSAaron LI #define TLV_HLN	4
364*ed775ee7SAntonio Huete Jimenez static int
ttlv_valid(uint16_t ttlv)365*ed775ee7SAntonio Huete Jimenez ttlv_valid(uint16_t ttlv)
366411677aeSAaron LI {
367411677aeSAaron LI 	if (ttlv > 0) {
368411677aeSAaron LI 		if (ttlv == 1 || ttlv == 0x1000)
369411677aeSAaron LI 			return 1;
370411677aeSAaron LI 		if (ttlv >= 0x10 && ttlv <= 0x11)
371411677aeSAaron LI 			return 1;
372411677aeSAaron LI 		if (ttlv >= 0x110 && ttlv <= 0x116)
373411677aeSAaron LI 			return 1;
374411677aeSAaron LI 		if (ttlv >= 0x8000)
375411677aeSAaron LI 			return 0;	/* XXX: */
376411677aeSAaron LI 	}
377411677aeSAaron LI 
378411677aeSAaron LI 	return 0;
379411677aeSAaron LI }
380411677aeSAaron LI 
381411677aeSAaron LI struct forces_ilv {
382411677aeSAaron LI 	nd_uint32_t type;
383411677aeSAaron LI 	nd_uint32_t length;
384411677aeSAaron LI };
385411677aeSAaron LI 
386411677aeSAaron LI struct forces_tlv {
387411677aeSAaron LI 	nd_uint16_t type;
388411677aeSAaron LI 	nd_uint16_t length;
389411677aeSAaron LI };
390411677aeSAaron LI 
391*ed775ee7SAntonio Huete Jimenez #define F_ALN_LEN(len) roundup2(len, ForCES_ALNL)
392411677aeSAaron LI #define	GET_TOP_TLV(fhdr) ((const struct forces_tlv *)((fhdr) + sizeof (struct forcesh)))
393411677aeSAaron LI #define TLV_SET_LEN(len)  (F_ALN_LEN(TLV_HDRL) + (len))
394411677aeSAaron LI #define TLV_DATA(tlvp)   ((const void*)(((const char*)(tlvp)) + TLV_SET_LEN(0)))
395*ed775ee7SAntonio Huete Jimenez #define GO_NXT_TLV(tlv,rlen) ((rlen) -= F_ALN_LEN(GET_BE_U_2((tlv)->length)), \
396411677aeSAaron LI 		              (const struct forces_tlv*)(((const char*)(tlv)) \
397*ed775ee7SAntonio Huete Jimenez 				      + F_ALN_LEN(GET_BE_U_2((tlv)->length))))
398411677aeSAaron LI #define ILV_SET_LEN(len)  (F_ALN_LEN(ILV_HDRL) + (len))
399411677aeSAaron LI #define ILV_DATA(ilvp)   ((const void*)(((const char*)(ilvp)) + ILV_SET_LEN(0)))
400*ed775ee7SAntonio Huete Jimenez #define GO_NXT_ILV(ilv,rlen) ((rlen) -= F_ALN_LEN(GET_BE_U_4((ilv)->length)), \
401411677aeSAaron LI 		              (const struct forces_ilv *)(((const char*)(ilv)) \
402*ed775ee7SAntonio Huete Jimenez 				      + F_ALN_LEN(GET_BE_U_4((ilv)->length))))
403411677aeSAaron LI #define INVALID_RLEN 1
404411677aeSAaron LI #define INVALID_STLN 2
405411677aeSAaron LI #define INVALID_LTLN 3
406411677aeSAaron LI #define INVALID_ALEN 4
407411677aeSAaron LI 
408411677aeSAaron LI static const struct tok ForCES_TLV_err[] = {
409411677aeSAaron LI 	{INVALID_RLEN, "Invalid total length"},
410411677aeSAaron LI 	{INVALID_STLN, "xLV too short"},
411411677aeSAaron LI 	{INVALID_LTLN, "xLV too long"},
412411677aeSAaron LI 	{INVALID_ALEN, "data padding missing"},
413411677aeSAaron LI 	{0, NULL}
414411677aeSAaron LI };
415411677aeSAaron LI 
416*ed775ee7SAntonio Huete Jimenez static u_int
tlv_valid(u_int tlvl,u_int rlen)417*ed775ee7SAntonio Huete Jimenez tlv_valid(u_int tlvl, u_int rlen)
418411677aeSAaron LI {
419411677aeSAaron LI 	if (rlen < TLV_HDRL)
420411677aeSAaron LI 		return INVALID_RLEN;
421*ed775ee7SAntonio Huete Jimenez 	if (tlvl < TLV_HDRL)
422411677aeSAaron LI 		return INVALID_STLN;
423*ed775ee7SAntonio Huete Jimenez 	if (tlvl > rlen)
424411677aeSAaron LI 		return INVALID_LTLN;
425*ed775ee7SAntonio Huete Jimenez 	if (rlen < F_ALN_LEN(tlvl))
426411677aeSAaron LI 		return INVALID_ALEN;
427411677aeSAaron LI 
428411677aeSAaron LI 	return 0;
429411677aeSAaron LI }
430411677aeSAaron LI 
431*ed775ee7SAntonio Huete Jimenez static int
ilv_valid(netdissect_options * ndo,const struct forces_ilv * ilv,u_int rlen)432*ed775ee7SAntonio Huete Jimenez ilv_valid(netdissect_options *ndo, const struct forces_ilv *ilv, u_int rlen)
433411677aeSAaron LI {
434411677aeSAaron LI 	if (rlen < ILV_HDRL)
435411677aeSAaron LI 		return INVALID_RLEN;
436*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_4(ilv->length) < ILV_HDRL)
437411677aeSAaron LI 		return INVALID_STLN;
438*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_4(ilv->length) > rlen)
439411677aeSAaron LI 		return INVALID_LTLN;
440*ed775ee7SAntonio Huete Jimenez 	if (rlen < F_ALN_LEN(GET_BE_U_4(ilv->length)))
441411677aeSAaron LI 		return INVALID_ALEN;
442411677aeSAaron LI 
443411677aeSAaron LI 	return 0;
444411677aeSAaron LI }
445411677aeSAaron LI 
446*ed775ee7SAntonio Huete Jimenez static int lfbselect_print(netdissect_options *, const u_char * pptr, u_int len,
447411677aeSAaron LI 			   uint16_t op_msk, int indent);
448*ed775ee7SAntonio Huete Jimenez static int redirect_print(netdissect_options *, const u_char * pptr, u_int len,
449411677aeSAaron LI 			  uint16_t op_msk, int indent);
450*ed775ee7SAntonio Huete Jimenez static int asrtlv_print(netdissect_options *, const u_char * pptr, u_int len,
451411677aeSAaron LI 			uint16_t op_msk, int indent);
452*ed775ee7SAntonio Huete Jimenez static int asttlv_print(netdissect_options *, const u_char * pptr, u_int len,
453411677aeSAaron LI 			uint16_t op_msk, int indent);
454411677aeSAaron LI 
455411677aeSAaron LI struct forces_lfbsh {
456411677aeSAaron LI 	nd_uint32_t class;
457411677aeSAaron LI 	nd_uint32_t instance;
458411677aeSAaron LI };
459411677aeSAaron LI 
460411677aeSAaron LI #define ASSNS_OPS (B_OP_REPORT)
461411677aeSAaron LI #define CFG_OPS	(B_OP_SET|B_OP_SETPROP|B_OP_DEL|B_OP_COMMIT|B_OP_RTRCOMP)
462411677aeSAaron LI #define CFG_ROPS (B_OP_SETRESP|B_OP_SETPRESP|B_OP_DELRESP|B_OP_RCOMMIT)
463411677aeSAaron LI #define CFG_QY (B_OP_GET|B_OP_GETPROP)
464411677aeSAaron LI #define CFG_QYR (B_OP_GETRESP|B_OP_GETPRESP)
465411677aeSAaron LI #define CFG_EVN (B_OP_REPORT)
466411677aeSAaron LI 
467411677aeSAaron LI static const struct tom_h ForCES_msg[TOM_MAX_IND + 1] = {
468411677aeSAaron LI 	/* TOM_RSV_I */ {TOM_RSVD, ZERO_TTLV, 0, "Invalid message", NULL},
469411677aeSAaron LI 	/* TOM_ASS_I */ {TOM_ASSNSETUP, ZERO_MORE_TTLV | TWO_TLV, ASSNS_OPS,
470411677aeSAaron LI 		       "Association Setup", lfbselect_print},
471411677aeSAaron LI 	/* TOM_AST_I */
472411677aeSAaron LI 	    {TOM_ASSNTEARD, TTLV_T1, 0, "Association TearDown", asttlv_print},
473411677aeSAaron LI 	/* TOM_CFG_I */ {TOM_CONFIG, TTLV_T2, CFG_OPS, "Config", lfbselect_print},
474411677aeSAaron LI 	/* TOM_QRY_I */ {TOM_QUERY, TTLV_T2, CFG_QY, "Query", lfbselect_print},
475411677aeSAaron LI 	/* TOM_EVN_I */ {TOM_EVENTNOT, TTLV_T1, CFG_EVN, "Event Notification",
476411677aeSAaron LI 		       lfbselect_print},
477411677aeSAaron LI 	/* TOM_RED_I */
478411677aeSAaron LI 	    {TOM_PKTREDIR, TTLV_T2, 0, "Packet Redirect", redirect_print},
479411677aeSAaron LI 	/* TOM_HBT_I */ {TOM_HEARTBT, ZERO_TTLV, 0, "HeartBeat", NULL},
480411677aeSAaron LI 	/* TOM_ASR_I */
481411677aeSAaron LI 	    {TOM_ASSNSETREP, TTLV_T1, 0, "Association Response", asrtlv_print},
482411677aeSAaron LI 	/* TOM_CNR_I */ {TOM_CONFIGREP, TTLV_T2, CFG_ROPS, "Config Response",
483411677aeSAaron LI 		       lfbselect_print},
484411677aeSAaron LI 	/* TOM_QRR_I */
485411677aeSAaron LI 	    {TOM_QUERYREP, TTLV_T2, CFG_QYR, "Query Response", lfbselect_print},
486411677aeSAaron LI };
487411677aeSAaron LI 
488*ed775ee7SAntonio Huete Jimenez static const struct tom_h *
get_forces_tom(uint8_t tom)489*ed775ee7SAntonio Huete Jimenez get_forces_tom(uint8_t tom)
490411677aeSAaron LI {
491411677aeSAaron LI 	int i;
492411677aeSAaron LI 	for (i = TOM_RSV_I; i <= TOM_MAX_IND; i++) {
493411677aeSAaron LI 		const struct tom_h *th = &ForCES_msg[i];
494411677aeSAaron LI 		if (th->v == tom)
495411677aeSAaron LI 			return th;
496411677aeSAaron LI 	}
497411677aeSAaron LI 	return &ForCES_msg[TOM_RSV_I];
498411677aeSAaron LI }
499411677aeSAaron LI 
500411677aeSAaron LI struct pdata_ops {
501411677aeSAaron LI 	uint32_t v;
502411677aeSAaron LI 	uint16_t flags;
503411677aeSAaron LI 	uint16_t op_msk;
504411677aeSAaron LI 	const char *s;
505*ed775ee7SAntonio Huete Jimenez 	int (*print) (netdissect_options *, const u_char * pptr, u_int len,
506411677aeSAaron LI 		      uint16_t op_msk, int indent);
507411677aeSAaron LI };
508411677aeSAaron LI 
509411677aeSAaron LI enum {
510411677aeSAaron LI 	PD_RSV_I,
511411677aeSAaron LI 	PD_SEL_I,
512411677aeSAaron LI 	PD_FDT_I,
513411677aeSAaron LI 	PD_SDT_I,
514411677aeSAaron LI 	PD_RES_I,
515411677aeSAaron LI 	PD_PDT_I,
516411677aeSAaron LI 	_PD_RSV_MAX
517411677aeSAaron LI };
518411677aeSAaron LI #define PD_MAX_IND (_TOM_RSV_MAX - 1)
519411677aeSAaron LI 
520*ed775ee7SAntonio Huete Jimenez static int
pd_valid(uint16_t pd)521*ed775ee7SAntonio Huete Jimenez pd_valid(uint16_t pd)
522411677aeSAaron LI {
523411677aeSAaron LI 	if (pd >= F_TLV_PDAT && pd <= F_TLV_REST)
524411677aeSAaron LI 		return 1;
525411677aeSAaron LI 	return 0;
526411677aeSAaron LI }
527411677aeSAaron LI 
528*ed775ee7SAntonio Huete Jimenez static void
chk_op_type(netdissect_options * ndo,uint16_t type,uint16_t msk,uint16_t omsk)529411677aeSAaron LI chk_op_type(netdissect_options *ndo,
530411677aeSAaron LI             uint16_t type, uint16_t msk, uint16_t omsk)
531411677aeSAaron LI {
532411677aeSAaron LI 	if (type != F_TLV_PDAT) {
533411677aeSAaron LI 		if (msk & B_KEYIN) {
534411677aeSAaron LI 			if (type != F_TLV_KEYI) {
535*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("Based on flags expected KEYINFO TLV!\n");
536411677aeSAaron LI 			}
537411677aeSAaron LI 		} else {
538411677aeSAaron LI 			if (!(msk & omsk)) {
539*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("Illegal DATA encoding for type 0x%x programmed %x got %x\n",
540*ed775ee7SAntonio Huete Jimenez 				          type, omsk, msk);
541411677aeSAaron LI 			}
542411677aeSAaron LI 		}
543411677aeSAaron LI 	}
544411677aeSAaron LI 
545411677aeSAaron LI }
546411677aeSAaron LI 
547411677aeSAaron LI #define F_SELKEY 1
548411677aeSAaron LI #define F_SELTABRANGE 2
549411677aeSAaron LI #define F_TABAPPEND 4
550411677aeSAaron LI 
551411677aeSAaron LI struct res_val {
552411677aeSAaron LI 	nd_uint8_t result;
553411677aeSAaron LI 	nd_uint8_t resv1;
554411677aeSAaron LI 	nd_uint16_t resv2;
555411677aeSAaron LI };
556411677aeSAaron LI 
557*ed775ee7SAntonio Huete Jimenez static int prestlv_print(netdissect_options *, const u_char * pptr, u_int len,
558411677aeSAaron LI 			 uint16_t op_msk, int indent);
559*ed775ee7SAntonio Huete Jimenez static int pkeyitlv_print(netdissect_options *, const u_char * pptr, u_int len,
560411677aeSAaron LI 			  uint16_t op_msk, int indent);
561*ed775ee7SAntonio Huete Jimenez static int fdatatlv_print(netdissect_options *, const u_char * pptr, u_int len,
562411677aeSAaron LI 			  uint16_t op_msk, int indent);
563*ed775ee7SAntonio Huete Jimenez static int sdatatlv_print(netdissect_options *, const u_char * pptr, u_int len,
564411677aeSAaron LI 			  uint16_t op_msk, int indent);
565411677aeSAaron LI 
566411677aeSAaron LI static const struct pdata_ops ForCES_pdata[PD_MAX_IND + 1] = {
567411677aeSAaron LI 	/* PD_RSV_I */ {0, 0, 0, "Invalid message", NULL},
568411677aeSAaron LI 	/* PD_SEL_I */ {F_TLV_KEYI, 0, 0, "KEYINFO TLV", pkeyitlv_print},
569411677aeSAaron LI 	/* PD_FDT_I */ {F_TLV_FULD, 0, B_FULLD, "FULLDATA TLV", fdatatlv_print},
570411677aeSAaron LI 	/* PD_SDT_I */ {F_TLV_SPAD, 0, B_SPARD, "SPARSEDATA TLV", sdatatlv_print},
571411677aeSAaron LI 	/* PD_RES_I */ {F_TLV_REST, 0, B_RESTV, "RESULT TLV", prestlv_print},
572411677aeSAaron LI 	/* PD_PDT_I */
573411677aeSAaron LI 	    {F_TLV_PDAT, 0, 0, "Inner PATH-DATA TLV", recpdoptlv_print},
574411677aeSAaron LI };
575411677aeSAaron LI 
576*ed775ee7SAntonio Huete Jimenez static const struct pdata_ops *
get_forces_pd(uint16_t pd)577*ed775ee7SAntonio Huete Jimenez get_forces_pd(uint16_t pd)
578411677aeSAaron LI {
579411677aeSAaron LI 	int i;
580411677aeSAaron LI 	for (i = PD_RSV_I + 1; i <= PD_MAX_IND; i++) {
581411677aeSAaron LI 		const struct pdata_ops *pdo = &ForCES_pdata[i];
582411677aeSAaron LI 		if (pdo->v == pd)
583411677aeSAaron LI 			return pdo;
584411677aeSAaron LI 	}
585411677aeSAaron LI 	return &ForCES_pdata[TOM_RSV_I];
586411677aeSAaron LI }
587411677aeSAaron LI 
588411677aeSAaron LI enum {
589411677aeSAaron LI 	E_SUCCESS,
590411677aeSAaron LI 	E_INVALID_HEADER,
591411677aeSAaron LI 	E_LENGTH_MISMATCH,
592411677aeSAaron LI 	E_VERSION_MISMATCH,
593411677aeSAaron LI 	E_INVALID_DESTINATION_PID,
594411677aeSAaron LI 	E_LFB_UNKNOWN,
595411677aeSAaron LI 	E_LFB_NOT_FOUND,
596411677aeSAaron LI 	E_LFB_INSTANCE_ID_NOT_FOUND,
597411677aeSAaron LI 	E_INVALID_PATH,
598411677aeSAaron LI 	E_COMPONENT_DOES_NOT_EXIST,
599411677aeSAaron LI 	E_EXISTS,
600411677aeSAaron LI 	E_NOT_FOUND,
601411677aeSAaron LI 	E_READ_ONLY,
602411677aeSAaron LI 	E_INVALID_ARRAY_CREATION,
603411677aeSAaron LI 	E_VALUE_OUT_OF_RANGE,
604411677aeSAaron LI 	E_CONTENTS_TOO_LONG,
605411677aeSAaron LI 	E_INVALID_PARAMETERS,
606411677aeSAaron LI 	E_INVALID_MESSAGE_TYPE,
607411677aeSAaron LI 	E_INVALID_FLAGS,
608411677aeSAaron LI 	E_INVALID_TLV,
609411677aeSAaron LI 	E_EVENT_ERROR,
610411677aeSAaron LI 	E_NOT_SUPPORTED,
611411677aeSAaron LI 	E_MEMORY_ERROR,
612411677aeSAaron LI 	E_INTERNAL_ERROR,
613411677aeSAaron LI 	/* 0x18-0xFE are reserved .. */
614411677aeSAaron LI 	E_UNSPECIFIED_ERROR = 0XFF
615411677aeSAaron LI };
616411677aeSAaron LI 
617411677aeSAaron LI static const struct tok ForCES_errs[] = {
618411677aeSAaron LI 	{E_SUCCESS, "SUCCESS"},
619411677aeSAaron LI 	{E_INVALID_HEADER, "INVALID HEADER"},
620411677aeSAaron LI 	{E_LENGTH_MISMATCH, "LENGTH MISMATCH"},
621411677aeSAaron LI 	{E_VERSION_MISMATCH, "VERSION MISMATCH"},
622411677aeSAaron LI 	{E_INVALID_DESTINATION_PID, "INVALID DESTINATION PID"},
623411677aeSAaron LI 	{E_LFB_UNKNOWN, "LFB UNKNOWN"},
624411677aeSAaron LI 	{E_LFB_NOT_FOUND, "LFB NOT FOUND"},
625411677aeSAaron LI 	{E_LFB_INSTANCE_ID_NOT_FOUND, "LFB INSTANCE ID NOT FOUND"},
626411677aeSAaron LI 	{E_INVALID_PATH, "INVALID PATH"},
627411677aeSAaron LI 	{E_COMPONENT_DOES_NOT_EXIST, "COMPONENT DOES NOT EXIST"},
628411677aeSAaron LI 	{E_EXISTS, "EXISTS ALREADY"},
629411677aeSAaron LI 	{E_NOT_FOUND, "NOT FOUND"},
630411677aeSAaron LI 	{E_READ_ONLY, "READ ONLY"},
631411677aeSAaron LI 	{E_INVALID_ARRAY_CREATION, "INVALID ARRAY CREATION"},
632411677aeSAaron LI 	{E_VALUE_OUT_OF_RANGE, "VALUE OUT OF RANGE"},
633411677aeSAaron LI 	{E_CONTENTS_TOO_LONG, "CONTENTS TOO LONG"},
634411677aeSAaron LI 	{E_INVALID_PARAMETERS, "INVALID PARAMETERS"},
635411677aeSAaron LI 	{E_INVALID_MESSAGE_TYPE, "INVALID MESSAGE TYPE"},
636411677aeSAaron LI 	{E_INVALID_FLAGS, "INVALID FLAGS"},
637411677aeSAaron LI 	{E_INVALID_TLV, "INVALID TLV"},
638411677aeSAaron LI 	{E_EVENT_ERROR, "EVENT ERROR"},
639411677aeSAaron LI 	{E_NOT_SUPPORTED, "NOT SUPPORTED"},
640411677aeSAaron LI 	{E_MEMORY_ERROR, "MEMORY ERROR"},
641411677aeSAaron LI 	{E_INTERNAL_ERROR, "INTERNAL ERROR"},
642411677aeSAaron LI 	{E_UNSPECIFIED_ERROR, "UNSPECIFIED ERROR"},
643411677aeSAaron LI 	{0, NULL}
644411677aeSAaron LI };
64527bfbee1SPeter Avalos 
64627bfbee1SPeter Avalos #define RESLEN	4
64727bfbee1SPeter Avalos 
648411677aeSAaron LI static int
prestlv_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk _U_,int indent)649411677aeSAaron LI prestlv_print(netdissect_options *ndo,
650*ed775ee7SAntonio Huete Jimenez               const u_char * pptr, u_int len,
651411677aeSAaron LI               uint16_t op_msk _U_, int indent)
65227bfbee1SPeter Avalos {
653411677aeSAaron LI 	const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
654*ed775ee7SAntonio Huete Jimenez 	const u_char *tdp = (const u_char *) TLV_DATA(tlv);
655411677aeSAaron LI 	const struct res_val *r = (const struct res_val *)tdp;
65627bfbee1SPeter Avalos 	u_int dlen;
657*ed775ee7SAntonio Huete Jimenez 	uint8_t result;
65827bfbee1SPeter Avalos 
65927bfbee1SPeter Avalos 	/*
66027bfbee1SPeter Avalos 	 * pdatacnt_print() has ensured that len (the TLV length)
66127bfbee1SPeter Avalos 	 * >= TLV_HDRL.
66227bfbee1SPeter Avalos 	 */
66327bfbee1SPeter Avalos 	dlen = len - TLV_HDRL;
66427bfbee1SPeter Avalos 	if (dlen != RESLEN) {
665*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("illegal RESULT-TLV: %u bytes!\n", dlen);
66627bfbee1SPeter Avalos 		return -1;
66727bfbee1SPeter Avalos 	}
66827bfbee1SPeter Avalos 
669*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_SIZE(r);
670*ed775ee7SAntonio Huete Jimenez 	result = GET_U_1(r->result);
671*ed775ee7SAntonio Huete Jimenez 	if (result >= 0x18 && result <= 0xFE) {
672*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("illegal reserved result code: 0x%x!\n", result);
67327bfbee1SPeter Avalos 		return -1;
67427bfbee1SPeter Avalos 	}
67527bfbee1SPeter Avalos 
676411677aeSAaron LI 	if (ndo->ndo_vflag >= 3) {
67727bfbee1SPeter Avalos 		char *ib = indent_pr(indent, 0);
678*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%s  Result: %s (code 0x%x)\n", ib,
679*ed775ee7SAntonio Huete Jimenez 		       tok2str(ForCES_errs, NULL, result), result);
68027bfbee1SPeter Avalos 	}
68127bfbee1SPeter Avalos 	return 0;
68227bfbee1SPeter Avalos 
68327bfbee1SPeter Avalos trunc:
684*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
68527bfbee1SPeter Avalos 	return -1;
68627bfbee1SPeter Avalos }
68727bfbee1SPeter Avalos 
688411677aeSAaron LI static int
fdatatlv_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk _U_,int indent)689411677aeSAaron LI fdatatlv_print(netdissect_options *ndo,
690*ed775ee7SAntonio Huete Jimenez                const u_char * pptr, u_int len,
691411677aeSAaron LI                uint16_t op_msk _U_, int indent)
69227bfbee1SPeter Avalos {
693411677aeSAaron LI 	const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
69427bfbee1SPeter Avalos 	u_int rlen;
695*ed775ee7SAntonio Huete Jimenez 	const u_char *tdp = (const u_char *) TLV_DATA(tlv);
696411677aeSAaron LI 	uint16_t type;
69727bfbee1SPeter Avalos 
69827bfbee1SPeter Avalos 	/*
69927bfbee1SPeter Avalos 	 * pdatacnt_print() or pkeyitlv_print() has ensured that len
70027bfbee1SPeter Avalos 	 * (the TLV length) >= TLV_HDRL.
70127bfbee1SPeter Avalos 	 */
70227bfbee1SPeter Avalos 	rlen = len - TLV_HDRL;
703*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_SIZE(tlv);
704*ed775ee7SAntonio Huete Jimenez 	type = GET_BE_U_2(tlv->type);
70527bfbee1SPeter Avalos 	if (type != F_TLV_FULD) {
706*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("Error: expecting FULLDATA!\n");
70727bfbee1SPeter Avalos 		return -1;
70827bfbee1SPeter Avalos 	}
70927bfbee1SPeter Avalos 
710411677aeSAaron LI 	if (ndo->ndo_vflag >= 3) {
71127bfbee1SPeter Avalos 		char *ib = indent_pr(indent + 2, 1);
712*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%s[", ib + 1);
713*ed775ee7SAntonio Huete Jimenez 		hex_print(ndo, ib, tdp, rlen);
714*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n%s]", ib + 1);
71527bfbee1SPeter Avalos 	}
71627bfbee1SPeter Avalos 	return 0;
71727bfbee1SPeter Avalos 
71827bfbee1SPeter Avalos trunc:
719*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
72027bfbee1SPeter Avalos 	return -1;
72127bfbee1SPeter Avalos }
72227bfbee1SPeter Avalos 
723411677aeSAaron LI static int
sdatailv_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk _U_,int indent)724411677aeSAaron LI sdatailv_print(netdissect_options *ndo,
725*ed775ee7SAntonio Huete Jimenez                const u_char * pptr, u_int len,
726411677aeSAaron LI                uint16_t op_msk _U_, int indent)
72727bfbee1SPeter Avalos {
72827bfbee1SPeter Avalos 	u_int rlen;
729411677aeSAaron LI 	const struct forces_ilv *ilv = (const struct forces_ilv *)pptr;
73027bfbee1SPeter Avalos 	int invilv;
73127bfbee1SPeter Avalos 
73227bfbee1SPeter Avalos 	if (len < ILV_HDRL) {
733*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("Error: BAD SPARSEDATA-TLV!\n");
73427bfbee1SPeter Avalos 		return -1;
73527bfbee1SPeter Avalos 	}
7366263709fSPeter Avalos 	rlen = len;
73727bfbee1SPeter Avalos 	indent += 1;
73827bfbee1SPeter Avalos 	while (rlen != 0) {
739411677aeSAaron LI #if 0
740*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("Jamal - outstanding length <%u>\n", rlen);
741411677aeSAaron LI #endif
7426263709fSPeter Avalos 		char *ib = indent_pr(indent, 1);
743*ed775ee7SAntonio Huete Jimenez 		const u_char *tdp = (const u_char *) ILV_DATA(ilv);
744*ed775ee7SAntonio Huete Jimenez 		invilv = ilv_valid(ndo, ilv, rlen);
74527bfbee1SPeter Avalos 		if (invilv) {
746*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Error: %s, rlen %u\n",
747*ed775ee7SAntonio Huete Jimenez 			         tok2str(ForCES_TLV_err, NULL, invilv), rlen);
7486263709fSPeter Avalos 			return -1;
7496263709fSPeter Avalos 		}
750411677aeSAaron LI 		if (ndo->ndo_vflag >= 3) {
751*ed775ee7SAntonio Huete Jimenez 			u_int ilvl = GET_BE_U_4(ilv->length);
752*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n%s ILV: type %x length %u\n", ib + 1,
753*ed775ee7SAntonio Huete Jimenez 				  GET_BE_U_4(ilv->type), ilvl);
754*ed775ee7SAntonio Huete Jimenez 			hex_print(ndo, "\t\t[", tdp, ilvl-ILV_HDRL);
75527bfbee1SPeter Avalos 		}
75627bfbee1SPeter Avalos 
75727bfbee1SPeter Avalos 		ilv = GO_NXT_ILV(ilv, rlen);
75827bfbee1SPeter Avalos 	}
75927bfbee1SPeter Avalos 
76027bfbee1SPeter Avalos 	return 0;
76127bfbee1SPeter Avalos }
76227bfbee1SPeter Avalos 
763411677aeSAaron LI static int
sdatatlv_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk,int indent)764411677aeSAaron LI sdatatlv_print(netdissect_options *ndo,
765*ed775ee7SAntonio Huete Jimenez                const u_char * pptr, u_int len,
766411677aeSAaron LI                uint16_t op_msk, int indent)
76727bfbee1SPeter Avalos {
768411677aeSAaron LI 	const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
76927bfbee1SPeter Avalos 	u_int rlen;
770*ed775ee7SAntonio Huete Jimenez 	const u_char *tdp = (const u_char *) TLV_DATA(tlv);
771411677aeSAaron LI 	uint16_t type;
77227bfbee1SPeter Avalos 
77327bfbee1SPeter Avalos 	/*
77427bfbee1SPeter Avalos 	 * pdatacnt_print() has ensured that len (the TLV length)
77527bfbee1SPeter Avalos 	 * >= TLV_HDRL.
77627bfbee1SPeter Avalos 	 */
77727bfbee1SPeter Avalos 	rlen = len - TLV_HDRL;
778*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_SIZE(tlv);
779*ed775ee7SAntonio Huete Jimenez 	type = GET_BE_U_2(tlv->type);
78027bfbee1SPeter Avalos 	if (type != F_TLV_SPAD) {
781*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("Error: expecting SPARSEDATA!\n");
78227bfbee1SPeter Avalos 		return -1;
78327bfbee1SPeter Avalos 	}
78427bfbee1SPeter Avalos 
785411677aeSAaron LI 	return sdatailv_print(ndo, tdp, rlen, op_msk, indent);
78627bfbee1SPeter Avalos 
78727bfbee1SPeter Avalos trunc:
788*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
78927bfbee1SPeter Avalos 	return -1;
79027bfbee1SPeter Avalos }
79127bfbee1SPeter Avalos 
792411677aeSAaron LI static int
pkeyitlv_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk,int indent)793411677aeSAaron LI pkeyitlv_print(netdissect_options *ndo,
794*ed775ee7SAntonio Huete Jimenez                const u_char * pptr, u_int len,
795411677aeSAaron LI                uint16_t op_msk, int indent)
79627bfbee1SPeter Avalos {
797411677aeSAaron LI 	const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
798*ed775ee7SAntonio Huete Jimenez 	const u_char *tdp = (const u_char *) TLV_DATA(tlv);
799*ed775ee7SAntonio Huete Jimenez 	const u_char *dp = tdp + 4;
800411677aeSAaron LI 	const struct forces_tlv *kdtlv = (const struct forces_tlv *)dp;
801411677aeSAaron LI 	uint32_t id;
80227bfbee1SPeter Avalos 	char *ib = indent_pr(indent, 0);
803411677aeSAaron LI 	uint16_t type, tll;
804411677aeSAaron LI 	u_int invtlv;
80527bfbee1SPeter Avalos 
806*ed775ee7SAntonio Huete Jimenez 	id = GET_BE_U_4(tdp);
807*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%sKeyinfo: Key 0x%x\n", ib, id);
808*ed775ee7SAntonio Huete Jimenez 	type = GET_BE_U_2(kdtlv->type);
809*ed775ee7SAntonio Huete Jimenez 	tll = GET_BE_U_2(kdtlv->length);
810*ed775ee7SAntonio Huete Jimenez 	invtlv = tlv_valid(tll, len);
81127bfbee1SPeter Avalos 
81227bfbee1SPeter Avalos 	if (invtlv) {
813*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%s TLV type 0x%x len %u\n",
81427bfbee1SPeter Avalos 		       tok2str(ForCES_TLV_err, NULL, invtlv), type,
815*ed775ee7SAntonio Huete Jimenez 		       tll);
81627bfbee1SPeter Avalos 		return -1;
81727bfbee1SPeter Avalos 	}
81827bfbee1SPeter Avalos 	/*
81927bfbee1SPeter Avalos 	 * At this point, tlv_valid() has ensured that the TLV
82027bfbee1SPeter Avalos 	 * length is large enough but not too large (it doesn't
82127bfbee1SPeter Avalos 	 * go past the end of the containing TLV).
82227bfbee1SPeter Avalos 	 */
823*ed775ee7SAntonio Huete Jimenez 	tll = GET_BE_U_2(kdtlv->length);
824411677aeSAaron LI 	dp = (const u_char *) TLV_DATA(kdtlv);
825411677aeSAaron LI 	return fdatatlv_print(ndo, dp, tll, op_msk, indent);
82627bfbee1SPeter Avalos }
82727bfbee1SPeter Avalos 
828411677aeSAaron LI #define PTH_DESC_SIZE 12
829411677aeSAaron LI 
830411677aeSAaron LI static int
pdatacnt_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t IDcnt,uint16_t op_msk,int indent)831411677aeSAaron LI pdatacnt_print(netdissect_options *ndo,
832*ed775ee7SAntonio Huete Jimenez                const u_char * pptr, u_int len,
833411677aeSAaron LI                uint16_t IDcnt, uint16_t op_msk, int indent)
83427bfbee1SPeter Avalos {
83527bfbee1SPeter Avalos 	u_int i;
836411677aeSAaron LI 	uint32_t id;
83727bfbee1SPeter Avalos 	char *ib = indent_pr(indent, 0);
83827bfbee1SPeter Avalos 
839411677aeSAaron LI 	if ((op_msk & B_APPND) && ndo->ndo_vflag >= 3) {
840*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%sTABLE APPEND\n", ib);
841411677aeSAaron LI 	}
84227bfbee1SPeter Avalos 	for (i = 0; i < IDcnt; i++) {
843*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_4(pptr);
84427bfbee1SPeter Avalos 		if (len < 4)
84527bfbee1SPeter Avalos 			goto trunc;
846*ed775ee7SAntonio Huete Jimenez 		id = GET_BE_U_4(pptr);
847411677aeSAaron LI 		if (ndo->ndo_vflag >= 3)
848*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%sID#%02u: %u\n", ib, i + 1, id);
84927bfbee1SPeter Avalos 		len -= 4;
85027bfbee1SPeter Avalos 		pptr += 4;
85127bfbee1SPeter Avalos 	}
852411677aeSAaron LI 
853411677aeSAaron LI 	if ((op_msk & B_TRNG) || (op_msk & B_KEYIN)) {
854411677aeSAaron LI 		if (op_msk & B_TRNG) {
855411677aeSAaron LI 			uint32_t starti, endi;
856411677aeSAaron LI 
857411677aeSAaron LI 			if (len < PTH_DESC_SIZE) {
858*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("pathlength %u with key/range too short %u\n",
859*ed775ee7SAntonio Huete Jimenez 				       len, PTH_DESC_SIZE);
860411677aeSAaron LI 				return -1;
861411677aeSAaron LI 			}
862411677aeSAaron LI 
863411677aeSAaron LI 			pptr += sizeof(struct forces_tlv);
864411677aeSAaron LI 			len -= sizeof(struct forces_tlv);
865411677aeSAaron LI 
866*ed775ee7SAntonio Huete Jimenez 			starti = GET_BE_U_4(pptr);
867411677aeSAaron LI 			pptr += 4;
868411677aeSAaron LI 			len -= 4;
869411677aeSAaron LI 
870*ed775ee7SAntonio Huete Jimenez 			endi = GET_BE_U_4(pptr);
871411677aeSAaron LI 			pptr += 4;
872411677aeSAaron LI 			len -= 4;
873411677aeSAaron LI 
874411677aeSAaron LI 			if (ndo->ndo_vflag >= 3)
875*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("%sTable range: [%u,%u]\n", ib, starti, endi);
876411677aeSAaron LI 		}
877411677aeSAaron LI 
878411677aeSAaron LI 		if (op_msk & B_KEYIN) {
879411677aeSAaron LI 			const struct forces_tlv *keytlv;
880411677aeSAaron LI 			uint16_t tll;
881411677aeSAaron LI 
882411677aeSAaron LI 			if (len < PTH_DESC_SIZE) {
883*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("pathlength %u with key/range too short %u\n",
884*ed775ee7SAntonio Huete Jimenez 				       len, PTH_DESC_SIZE);
885411677aeSAaron LI 				return -1;
886411677aeSAaron LI 			}
887411677aeSAaron LI 
888411677aeSAaron LI 			/* skip keyid */
889411677aeSAaron LI 			pptr += 4;
890411677aeSAaron LI 			len -= 4;
891411677aeSAaron LI 			keytlv = (const struct forces_tlv *)pptr;
892411677aeSAaron LI 			/* skip header */
893411677aeSAaron LI 			pptr += sizeof(struct forces_tlv);
894411677aeSAaron LI 			len -= sizeof(struct forces_tlv);
895411677aeSAaron LI 			/* skip key content */
896*ed775ee7SAntonio Huete Jimenez 			tll = GET_BE_U_2(keytlv->length);
897411677aeSAaron LI 			if (tll < TLV_HDRL) {
898*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("key content length %u < %u\n",
899*ed775ee7SAntonio Huete Jimenez 					tll, TLV_HDRL);
900411677aeSAaron LI 				return -1;
901411677aeSAaron LI 			}
902411677aeSAaron LI 			tll -= TLV_HDRL;
903411677aeSAaron LI 			if (len < tll) {
904*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("key content too short\n");
905411677aeSAaron LI 				return -1;
906411677aeSAaron LI 			}
907411677aeSAaron LI 			pptr += tll;
908411677aeSAaron LI 			len -= tll;
909411677aeSAaron LI 		}
910411677aeSAaron LI 
911411677aeSAaron LI 	}
912411677aeSAaron LI 
91327bfbee1SPeter Avalos 	if (len) {
914411677aeSAaron LI 		const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr;
915411677aeSAaron LI 		uint16_t type;
916*ed775ee7SAntonio Huete Jimenez 		uint16_t tlvl, tll;
917*ed775ee7SAntonio Huete Jimenez 		u_int pad = 0;
91827bfbee1SPeter Avalos 		u_int aln;
919411677aeSAaron LI 		u_int invtlv;
92027bfbee1SPeter Avalos 
921*ed775ee7SAntonio Huete Jimenez 		type = GET_BE_U_2(pdtlv->type);
922*ed775ee7SAntonio Huete Jimenez 		tlvl = GET_BE_U_2(pdtlv->length);
923*ed775ee7SAntonio Huete Jimenez 		invtlv = tlv_valid(tlvl, len);
92427bfbee1SPeter Avalos 		if (invtlv) {
925*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s Outstanding bytes %u for TLV type 0x%x TLV len %u\n",
92627bfbee1SPeter Avalos 			          tok2str(ForCES_TLV_err, NULL, invtlv), len, type,
927*ed775ee7SAntonio Huete Jimenez 			          tlvl);
92827bfbee1SPeter Avalos 			goto pd_err;
92927bfbee1SPeter Avalos 		}
93027bfbee1SPeter Avalos 		/*
93127bfbee1SPeter Avalos 		 * At this point, tlv_valid() has ensured that the TLV
93227bfbee1SPeter Avalos 		 * length is large enough but not too large (it doesn't
93327bfbee1SPeter Avalos 		 * go past the end of the containing TLV).
93427bfbee1SPeter Avalos 		 */
935*ed775ee7SAntonio Huete Jimenez 		tll = tlvl - TLV_HDRL;
936*ed775ee7SAntonio Huete Jimenez 		aln = F_ALN_LEN(tlvl);
937*ed775ee7SAntonio Huete Jimenez 		if (aln > tlvl) {
93827bfbee1SPeter Avalos 			if (aln > len) {
939*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("Invalid padded pathdata TLV type 0x%x len %u missing %u pad bytes\n",
940*ed775ee7SAntonio Huete Jimenez 				          type, tlvl, aln - len);
94127bfbee1SPeter Avalos 			} else {
942*ed775ee7SAntonio Huete Jimenez 				pad = aln - tlvl;
94327bfbee1SPeter Avalos 			}
94427bfbee1SPeter Avalos 		}
94527bfbee1SPeter Avalos 		if (pd_valid(type)) {
94627bfbee1SPeter Avalos 			const struct pdata_ops *ops = get_forces_pd(type);
94727bfbee1SPeter Avalos 
948411677aeSAaron LI 			if (ndo->ndo_vflag >= 3 && ops->v != F_TLV_PDAT) {
94927bfbee1SPeter Avalos 				if (pad)
950*ed775ee7SAntonio Huete Jimenez 					ND_PRINT("%s  %s (Length %u DataLen %u pad %u Bytes)\n",
951*ed775ee7SAntonio Huete Jimenez 					          ib, ops->s, tlvl, tll, pad);
95227bfbee1SPeter Avalos 				else
953*ed775ee7SAntonio Huete Jimenez 					ND_PRINT("%s  %s (Length %u DataLen %u Bytes)\n",
954*ed775ee7SAntonio Huete Jimenez 					          ib, ops->s, tlvl, tll);
95527bfbee1SPeter Avalos 			}
95627bfbee1SPeter Avalos 
957411677aeSAaron LI 			chk_op_type(ndo, type, op_msk, ops->op_msk);
95827bfbee1SPeter Avalos 
959411677aeSAaron LI 			if (ops->print(ndo, (const u_char *)pdtlv,
96027bfbee1SPeter Avalos 					tll + pad + TLV_HDRL, op_msk,
9616263709fSPeter Avalos 					indent + 2) == -1)
9626263709fSPeter Avalos 				return -1;
96327bfbee1SPeter Avalos 			len -= (TLV_HDRL + pad + tll);
96427bfbee1SPeter Avalos 		} else {
965*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Invalid path data content type 0x%x len %u\n",
966*ed775ee7SAntonio Huete Jimenez 			       type, tlvl);
96727bfbee1SPeter Avalos pd_err:
968*ed775ee7SAntonio Huete Jimenez 			if (tlvl) {
969*ed775ee7SAntonio Huete Jimenez                                 hex_print(ndo, "Bad Data val\n\t  [",
970*ed775ee7SAntonio Huete Jimenez 					  pptr, len);
971*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("]\n");
97227bfbee1SPeter Avalos 
97327bfbee1SPeter Avalos 				return -1;
97427bfbee1SPeter Avalos 			}
97527bfbee1SPeter Avalos 		}
97627bfbee1SPeter Avalos 	}
97727bfbee1SPeter Avalos 	return len;
97827bfbee1SPeter Avalos 
97927bfbee1SPeter Avalos trunc:
980*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
98127bfbee1SPeter Avalos 	return -1;
98227bfbee1SPeter Avalos }
98327bfbee1SPeter Avalos 
984411677aeSAaron LI static int
pdata_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk,int indent)985411677aeSAaron LI pdata_print(netdissect_options *ndo,
986*ed775ee7SAntonio Huete Jimenez             const u_char * pptr, u_int len,
987411677aeSAaron LI             uint16_t op_msk, int indent)
98827bfbee1SPeter Avalos {
989411677aeSAaron LI 	const struct pathdata_h *pdh = (const struct pathdata_h *)pptr;
99027bfbee1SPeter Avalos 	char *ib = indent_pr(indent, 0);
99127bfbee1SPeter Avalos 	u_int minsize = 0;
99227bfbee1SPeter Avalos 	int more_pd = 0;
993411677aeSAaron LI 	uint16_t idcnt = 0;
99427bfbee1SPeter Avalos 
995*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_SIZE(pdh);
99627bfbee1SPeter Avalos 	if (len < sizeof(struct pathdata_h))
99727bfbee1SPeter Avalos 		goto trunc;
998411677aeSAaron LI 	if (ndo->ndo_vflag >= 3) {
999*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n%sPathdata: Flags 0x%x ID count %u\n",
1000*ed775ee7SAntonio Huete Jimenez 		       ib, GET_BE_U_2(pdh->pflags),
1001*ed775ee7SAntonio Huete Jimenez 		       GET_BE_U_2(pdh->pIDcnt));
100227bfbee1SPeter Avalos 	}
100327bfbee1SPeter Avalos 
1004*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_2(pdh->pflags) & F_SELKEY) {
100527bfbee1SPeter Avalos 		op_msk |= B_KEYIN;
100627bfbee1SPeter Avalos 	}
1007411677aeSAaron LI 
1008411677aeSAaron LI 	/* Table GET Range operation */
1009*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_2(pdh->pflags) & F_SELTABRANGE) {
1010411677aeSAaron LI 		op_msk |= B_TRNG;
1011411677aeSAaron LI 	}
1012411677aeSAaron LI 	/* Table SET append operation */
1013*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_2(pdh->pflags) & F_TABAPPEND) {
1014411677aeSAaron LI 		op_msk |= B_APPND;
1015411677aeSAaron LI 	}
1016411677aeSAaron LI 
101727bfbee1SPeter Avalos 	pptr += sizeof(struct pathdata_h);
101827bfbee1SPeter Avalos 	len -= sizeof(struct pathdata_h);
1019*ed775ee7SAntonio Huete Jimenez 	idcnt = GET_BE_U_2(pdh->pIDcnt);
102027bfbee1SPeter Avalos 	minsize = idcnt * 4;
102127bfbee1SPeter Avalos 	if (len < minsize) {
1022*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\t\t\ttruncated IDs expected %uB got %uB\n", minsize,
1023*ed775ee7SAntonio Huete Jimenez 		       len);
1024*ed775ee7SAntonio Huete Jimenez 		hex_print(ndo, "\t\t\tID Data[", pptr, len);
1025*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("]\n");
102627bfbee1SPeter Avalos 		return -1;
102727bfbee1SPeter Avalos 	}
1028411677aeSAaron LI 
1029411677aeSAaron LI 	if ((op_msk & B_TRNG) && (op_msk & B_KEYIN)) {
1030*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\t\t\tIllegal to have both Table ranges and keys\n");
1031411677aeSAaron LI 		return -1;
1032411677aeSAaron LI 	}
1033411677aeSAaron LI 
1034411677aeSAaron LI 	more_pd = pdatacnt_print(ndo, pptr, len, idcnt, op_msk, indent);
103527bfbee1SPeter Avalos 	if (more_pd > 0) {
103627bfbee1SPeter Avalos 		int consumed = len - more_pd;
103727bfbee1SPeter Avalos 		pptr += consumed;
103827bfbee1SPeter Avalos 		len = more_pd;
103927bfbee1SPeter Avalos 		/* XXX: Argh, recurse some more */
1040411677aeSAaron LI 		return recpdoptlv_print(ndo, pptr, len, op_msk, indent+1);
104127bfbee1SPeter Avalos 	} else
104227bfbee1SPeter Avalos 		return 0;
104327bfbee1SPeter Avalos 
104427bfbee1SPeter Avalos trunc:
1045*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
104627bfbee1SPeter Avalos 	return -1;
104727bfbee1SPeter Avalos }
104827bfbee1SPeter Avalos 
1049411677aeSAaron LI static int
genoptlv_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk,int indent)1050411677aeSAaron LI genoptlv_print(netdissect_options *ndo,
1051*ed775ee7SAntonio Huete Jimenez                const u_char * pptr, u_int len,
1052411677aeSAaron LI                uint16_t op_msk, int indent)
105327bfbee1SPeter Avalos {
1054411677aeSAaron LI 	const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr;
1055411677aeSAaron LI 	uint16_t type;
1056*ed775ee7SAntonio Huete Jimenez 	u_int tlvl;
1057411677aeSAaron LI 	u_int invtlv;
105827bfbee1SPeter Avalos 	char *ib = indent_pr(indent, 0);
105927bfbee1SPeter Avalos 
1060*ed775ee7SAntonio Huete Jimenez 	type = GET_BE_U_2(pdtlv->type);
1061*ed775ee7SAntonio Huete Jimenez 	tlvl = GET_BE_U_2(pdtlv->length);
1062*ed775ee7SAntonio Huete Jimenez 	invtlv = tlv_valid(tlvl, len);
1063*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("genoptlvprint - %s TLV type 0x%x len %u\n",
1064*ed775ee7SAntonio Huete Jimenez 	       tok2str(ForCES_TLV, NULL, type), type, tlvl);
106527bfbee1SPeter Avalos 	if (!invtlv) {
106627bfbee1SPeter Avalos 		/*
106727bfbee1SPeter Avalos 		 * At this point, tlv_valid() has ensured that the TLV
106827bfbee1SPeter Avalos 		 * length is large enough but not too large (it doesn't
106927bfbee1SPeter Avalos 		 * go past the end of the containing TLV).
107027bfbee1SPeter Avalos 		 */
1071*ed775ee7SAntonio Huete Jimenez 		const u_char *dp = (const u_char *) TLV_DATA(pdtlv);
1072*ed775ee7SAntonio Huete Jimenez 
107327bfbee1SPeter Avalos 		if (!ttlv_valid(type)) {
1074*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s TLV type 0x%x len %u\n",
107527bfbee1SPeter Avalos 			       tok2str(ForCES_TLV_err, NULL, invtlv), type,
1076*ed775ee7SAntonio Huete Jimenez 			       tlvl);
107727bfbee1SPeter Avalos 			return -1;
107827bfbee1SPeter Avalos 		}
1079411677aeSAaron LI 		if (ndo->ndo_vflag >= 3)
1080*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s%s, length %u (data length %u Bytes)",
108127bfbee1SPeter Avalos 			       ib, tok2str(ForCES_TLV, NULL, type),
1082*ed775ee7SAntonio Huete Jimenez 			       tlvl, tlvl - TLV_HDRL);
108327bfbee1SPeter Avalos 
1084*ed775ee7SAntonio Huete Jimenez 		return pdata_print(ndo, dp, tlvl - TLV_HDRL, op_msk, indent + 1);
108527bfbee1SPeter Avalos 	} else {
1086*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\t\t\tInvalid ForCES TLV type=%x", type);
108727bfbee1SPeter Avalos 		return -1;
108827bfbee1SPeter Avalos 	}
108927bfbee1SPeter Avalos }
109027bfbee1SPeter Avalos 
1091411677aeSAaron LI static int
recpdoptlv_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk,int indent)1092411677aeSAaron LI recpdoptlv_print(netdissect_options *ndo,
1093*ed775ee7SAntonio Huete Jimenez                  const u_char * pptr, u_int len,
1094411677aeSAaron LI                  uint16_t op_msk, int indent)
109527bfbee1SPeter Avalos {
1096411677aeSAaron LI 	const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr;
109727bfbee1SPeter Avalos 
109827bfbee1SPeter Avalos 	while (len != 0) {
1099*ed775ee7SAntonio Huete Jimenez 		uint16_t type, tlvl;
1100*ed775ee7SAntonio Huete Jimenez 		u_int invtlv;
1101*ed775ee7SAntonio Huete Jimenez 		char *ib;
1102*ed775ee7SAntonio Huete Jimenez 		const u_char *dp;
1103*ed775ee7SAntonio Huete Jimenez 
1104*ed775ee7SAntonio Huete Jimenez 		tlvl = GET_BE_U_2(pdtlv->length);
1105*ed775ee7SAntonio Huete Jimenez 		invtlv = tlv_valid(tlvl, len);
110627bfbee1SPeter Avalos 		if (invtlv) {
110727bfbee1SPeter Avalos 			break;
110827bfbee1SPeter Avalos 		}
110927bfbee1SPeter Avalos 
111027bfbee1SPeter Avalos 		/*
111127bfbee1SPeter Avalos 		 * At this point, tlv_valid() has ensured that the TLV
111227bfbee1SPeter Avalos 		 * length is large enough but not too large (it doesn't
111327bfbee1SPeter Avalos 		 * go past the end of the containing TLV).
111427bfbee1SPeter Avalos 		 */
111527bfbee1SPeter Avalos 		ib = indent_pr(indent, 0);
1116*ed775ee7SAntonio Huete Jimenez 		type = GET_BE_U_2(pdtlv->type);
1117411677aeSAaron LI 		dp = (const u_char *) TLV_DATA(pdtlv);
111827bfbee1SPeter Avalos 
1119411677aeSAaron LI 		if (ndo->ndo_vflag >= 3)
1120*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s%s, length %u (data encapsulated %u Bytes)",
112127bfbee1SPeter Avalos 			          ib, tok2str(ForCES_TLV, NULL, type),
1122*ed775ee7SAntonio Huete Jimenez 			          tlvl,
1123*ed775ee7SAntonio Huete Jimenez 			          tlvl - TLV_HDRL);
112427bfbee1SPeter Avalos 
1125*ed775ee7SAntonio Huete Jimenez 		if (pdata_print(ndo, dp, tlvl - TLV_HDRL, op_msk, indent + 1) == -1)
11266263709fSPeter Avalos 			return -1;
112727bfbee1SPeter Avalos 		pdtlv = GO_NXT_TLV(pdtlv, len);
112827bfbee1SPeter Avalos 	}
112927bfbee1SPeter Avalos 
113027bfbee1SPeter Avalos 	if (len) {
1131*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t\tMessy PATHDATA TLV header, type (0x%x)\n\t\texcess of %u Bytes ",
1132*ed775ee7SAntonio Huete Jimenez 		          GET_BE_U_2(pdtlv->type),
1133*ed775ee7SAntonio Huete Jimenez 		          len - GET_BE_U_2(pdtlv->length));
113427bfbee1SPeter Avalos 		return -1;
113527bfbee1SPeter Avalos 	}
113627bfbee1SPeter Avalos 
113727bfbee1SPeter Avalos 	return 0;
113827bfbee1SPeter Avalos }
113927bfbee1SPeter Avalos 
1140411677aeSAaron LI static int
invoptlv_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk _U_,int indent)1141411677aeSAaron LI invoptlv_print(netdissect_options *ndo,
1142*ed775ee7SAntonio Huete Jimenez                const u_char * pptr, u_int len,
1143411677aeSAaron LI                uint16_t op_msk _U_, int indent)
114427bfbee1SPeter Avalos {
114527bfbee1SPeter Avalos 	char *ib = indent_pr(indent, 1);
114627bfbee1SPeter Avalos 
1147411677aeSAaron LI 	if (ndo->ndo_vflag >= 3) {
1148*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%sData[", ib + 1);
1149*ed775ee7SAntonio Huete Jimenez 		hex_print(ndo, ib, pptr, len);
1150*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%s]\n", ib);
115127bfbee1SPeter Avalos 	}
115227bfbee1SPeter Avalos 	return -1;
115327bfbee1SPeter Avalos }
115427bfbee1SPeter Avalos 
1155411677aeSAaron LI static int
otlv_print(netdissect_options * ndo,const struct forces_tlv * otlv,uint16_t op_msk _U_,int indent)1156411677aeSAaron LI otlv_print(netdissect_options *ndo,
1157411677aeSAaron LI            const struct forces_tlv *otlv, uint16_t op_msk _U_, int indent)
115827bfbee1SPeter Avalos {
115927bfbee1SPeter Avalos 	int rc = 0;
1160*ed775ee7SAntonio Huete Jimenez 	const u_char *dp = (const u_char *) TLV_DATA(otlv);
1161411677aeSAaron LI 	uint16_t type;
1162*ed775ee7SAntonio Huete Jimenez 	u_int tll;
116327bfbee1SPeter Avalos 	char *ib = indent_pr(indent, 0);
116427bfbee1SPeter Avalos 	const struct optlv_h *ops;
116527bfbee1SPeter Avalos 
116627bfbee1SPeter Avalos 	/*
1167*ed775ee7SAntonio Huete Jimenez 	 * lfbselect_print() has ensured that GET_BE_U_2(otlv->length)
116827bfbee1SPeter Avalos 	 * >= TLV_HDRL.
116927bfbee1SPeter Avalos 	 */
1170*ed775ee7SAntonio Huete Jimenez 	type = GET_BE_U_2(otlv->type);
1171*ed775ee7SAntonio Huete Jimenez 	tll = GET_BE_U_2(otlv->length) - TLV_HDRL;
117227bfbee1SPeter Avalos 	ops = get_forces_optlv_h(type);
1173411677aeSAaron LI 	if (ndo->ndo_vflag >= 3) {
1174*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%sOper TLV %s(0x%x) length %u\n", ib, ops->s, type,
1175*ed775ee7SAntonio Huete Jimenez 		       GET_BE_U_2(otlv->length));
117627bfbee1SPeter Avalos 	}
117727bfbee1SPeter Avalos 	/* rest of ops must at least have 12B {pathinfo} */
117827bfbee1SPeter Avalos 	if (tll < OP_MIN_SIZ) {
1179*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\t\tOper TLV %s(0x%x) length %u\n", ops->s, type,
1180*ed775ee7SAntonio Huete Jimenez 		       GET_BE_U_2(otlv->length));
1181*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\t\tTruncated data size %u minimum required %u\n", tll,
1182*ed775ee7SAntonio Huete Jimenez 		       OP_MIN_SIZ);
1183411677aeSAaron LI 		return invoptlv_print(ndo, dp, tll, ops->op_msk, indent);
118427bfbee1SPeter Avalos 
118527bfbee1SPeter Avalos 	}
118627bfbee1SPeter Avalos 
1187411677aeSAaron LI 	/* XXX - do anything with ops->flags? */
1188411677aeSAaron LI         if(ops->print) {
1189411677aeSAaron LI                 rc = ops->print(ndo, dp, tll, ops->op_msk, indent + 1);
1190411677aeSAaron LI         }
119127bfbee1SPeter Avalos 	return rc;
119227bfbee1SPeter Avalos }
119327bfbee1SPeter Avalos 
119427bfbee1SPeter Avalos #define ASTDLN	4
119527bfbee1SPeter Avalos #define ASTMCD	255
1196411677aeSAaron LI static int
asttlv_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk _U_,int indent)1197411677aeSAaron LI asttlv_print(netdissect_options *ndo,
1198*ed775ee7SAntonio Huete Jimenez              const u_char * pptr, u_int len,
1199411677aeSAaron LI              uint16_t op_msk _U_, int indent)
120027bfbee1SPeter Avalos {
1201411677aeSAaron LI 	uint32_t rescode;
120227bfbee1SPeter Avalos 	u_int dlen;
120327bfbee1SPeter Avalos 	char *ib = indent_pr(indent, 0);
120427bfbee1SPeter Avalos 
120527bfbee1SPeter Avalos 	/*
120627bfbee1SPeter Avalos 	 * forces_type_print() has ensured that len (the TLV length)
120727bfbee1SPeter Avalos 	 * >= TLV_HDRL.
120827bfbee1SPeter Avalos 	 */
120927bfbee1SPeter Avalos 	dlen = len - TLV_HDRL;
121027bfbee1SPeter Avalos 	if (dlen != ASTDLN) {
1211*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("illegal ASTresult-TLV: %u bytes!\n", dlen);
121227bfbee1SPeter Avalos 		return -1;
121327bfbee1SPeter Avalos 	}
1214*ed775ee7SAntonio Huete Jimenez 	rescode = GET_BE_U_4(pptr);
121527bfbee1SPeter Avalos 	if (rescode > ASTMCD) {
1216*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("illegal ASTresult result code: %u!\n", rescode);
121727bfbee1SPeter Avalos 		return -1;
121827bfbee1SPeter Avalos 	}
121927bfbee1SPeter Avalos 
1220411677aeSAaron LI 	if (ndo->ndo_vflag >= 3) {
1221*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("Teardown reason:\n%s", ib);
122227bfbee1SPeter Avalos 		switch (rescode) {
122327bfbee1SPeter Avalos 		case 0:
1224*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Normal Teardown");
122527bfbee1SPeter Avalos 			break;
122627bfbee1SPeter Avalos 		case 1:
1227*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Loss of Heartbeats");
122827bfbee1SPeter Avalos 			break;
122927bfbee1SPeter Avalos 		case 2:
1230*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Out of bandwidth");
123127bfbee1SPeter Avalos 			break;
123227bfbee1SPeter Avalos 		case 3:
1233*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Out of Memory");
123427bfbee1SPeter Avalos 			break;
123527bfbee1SPeter Avalos 		case 4:
1236*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Application Crash");
123727bfbee1SPeter Avalos 			break;
123827bfbee1SPeter Avalos 		default:
1239*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Unknown Teardown reason");
124027bfbee1SPeter Avalos 			break;
124127bfbee1SPeter Avalos 		}
1242*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(%x)\n%s", rescode, ib);
124327bfbee1SPeter Avalos 	}
124427bfbee1SPeter Avalos 	return 0;
124527bfbee1SPeter Avalos }
124627bfbee1SPeter Avalos 
124727bfbee1SPeter Avalos #define ASRDLN	4
124827bfbee1SPeter Avalos #define ASRMCD	3
1249411677aeSAaron LI static int
asrtlv_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk _U_,int indent)1250411677aeSAaron LI asrtlv_print(netdissect_options *ndo,
1251*ed775ee7SAntonio Huete Jimenez              const u_char * pptr, u_int len,
1252411677aeSAaron LI              uint16_t op_msk _U_, int indent)
125327bfbee1SPeter Avalos {
1254411677aeSAaron LI 	uint32_t rescode;
125527bfbee1SPeter Avalos 	u_int dlen;
125627bfbee1SPeter Avalos 	char *ib = indent_pr(indent, 0);
125727bfbee1SPeter Avalos 
125827bfbee1SPeter Avalos 	/*
125927bfbee1SPeter Avalos 	 * forces_type_print() has ensured that len (the TLV length)
126027bfbee1SPeter Avalos 	 * >= TLV_HDRL.
126127bfbee1SPeter Avalos 	 */
126227bfbee1SPeter Avalos 	dlen = len - TLV_HDRL;
126327bfbee1SPeter Avalos 	if (dlen != ASRDLN) {	/* id, instance, oper tlv */
1264*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("illegal ASRresult-TLV: %u bytes!\n", dlen);
126527bfbee1SPeter Avalos 		return -1;
126627bfbee1SPeter Avalos 	}
1267*ed775ee7SAntonio Huete Jimenez 	rescode = GET_BE_U_4(pptr);
126827bfbee1SPeter Avalos 
126927bfbee1SPeter Avalos 	if (rescode > ASRMCD) {
1270*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("illegal ASRresult result code: %u!\n", rescode);
127127bfbee1SPeter Avalos 		return -1;
127227bfbee1SPeter Avalos 	}
127327bfbee1SPeter Avalos 
1274411677aeSAaron LI 	if (ndo->ndo_vflag >= 3) {
1275*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n%s", ib);
127627bfbee1SPeter Avalos 		switch (rescode) {
127727bfbee1SPeter Avalos 		case 0:
1278*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Success ");
127927bfbee1SPeter Avalos 			break;
128027bfbee1SPeter Avalos 		case 1:
1281*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("FE ID invalid ");
128227bfbee1SPeter Avalos 			break;
128327bfbee1SPeter Avalos 		case 2:
1284*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("permission denied ");
128527bfbee1SPeter Avalos 			break;
128627bfbee1SPeter Avalos 		default:
1287*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Unknown ");
128827bfbee1SPeter Avalos 			break;
128927bfbee1SPeter Avalos 		}
1290*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(%x)\n%s", rescode, ib);
129127bfbee1SPeter Avalos 	}
129227bfbee1SPeter Avalos 	return 0;
129327bfbee1SPeter Avalos }
129427bfbee1SPeter Avalos 
1295411677aeSAaron LI #if 0
129627bfbee1SPeter Avalos /*
129727bfbee1SPeter Avalos  * XXX - not used.
129827bfbee1SPeter Avalos  */
1299411677aeSAaron LI static int
1300411677aeSAaron LI gentltlv_print(netdissect_options *ndo,
1301*ed775ee7SAntonio Huete Jimenez                const u_char * pptr _U_, u_int len,
1302411677aeSAaron LI                uint16_t op_msk _U_, int indent _U_)
130327bfbee1SPeter Avalos {
130427bfbee1SPeter Avalos 	u_int dlen = len - TLV_HDRL;
130527bfbee1SPeter Avalos 
130627bfbee1SPeter Avalos 	if (dlen < 4) {		/* at least 32 bits must exist */
1307*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("truncated TLV: %u bytes missing! ", 4 - dlen);
130827bfbee1SPeter Avalos 		return -1;
130927bfbee1SPeter Avalos 	}
131027bfbee1SPeter Avalos 	return 0;
131127bfbee1SPeter Avalos }
1312411677aeSAaron LI #endif
131327bfbee1SPeter Avalos 
131427bfbee1SPeter Avalos #define RD_MIN 8
1315411677aeSAaron LI 
1316411677aeSAaron LI static int
print_metailv(netdissect_options * ndo,const u_char * pptr,uint16_t op_msk _U_,int indent)1317411677aeSAaron LI print_metailv(netdissect_options *ndo,
1318*ed775ee7SAntonio Huete Jimenez               const u_char * pptr, uint16_t op_msk _U_, int indent)
131927bfbee1SPeter Avalos {
132027bfbee1SPeter Avalos 	u_int rlen;
132127bfbee1SPeter Avalos 	char *ib = indent_pr(indent, 0);
132227bfbee1SPeter Avalos 	/* XXX: check header length */
1323411677aeSAaron LI 	const struct forces_ilv *ilv = (const struct forces_ilv *)pptr;
132427bfbee1SPeter Avalos 
132527bfbee1SPeter Avalos 	/*
132627bfbee1SPeter Avalos 	 * print_metatlv() has ensured that len (what remains in the
132727bfbee1SPeter Avalos 	 * ILV) >= ILV_HDRL.
132827bfbee1SPeter Avalos 	 */
1329*ed775ee7SAntonio Huete Jimenez 	rlen = GET_BE_U_4(ilv->length) - ILV_HDRL;
1330*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%sMetaID 0x%x length %u\n", ib, GET_BE_U_4(ilv->type),
1331*ed775ee7SAntonio Huete Jimenez 		  GET_BE_U_4(ilv->length));
1332411677aeSAaron LI 	if (ndo->ndo_vflag >= 3) {
1333*ed775ee7SAntonio Huete Jimenez 		hex_print(ndo, "\t\t[", ILV_DATA(ilv), rlen);
1334*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" ]\n");
1335411677aeSAaron LI 	}
133627bfbee1SPeter Avalos 	return 0;
133727bfbee1SPeter Avalos }
133827bfbee1SPeter Avalos 
1339411677aeSAaron LI static int
print_metatlv(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk _U_,int indent)1340411677aeSAaron LI print_metatlv(netdissect_options *ndo,
1341*ed775ee7SAntonio Huete Jimenez               const u_char * pptr, u_int len,
1342411677aeSAaron LI               uint16_t op_msk _U_, int indent)
134327bfbee1SPeter Avalos {
134427bfbee1SPeter Avalos 	u_int dlen;
134527bfbee1SPeter Avalos 	char *ib = indent_pr(indent, 0);
134627bfbee1SPeter Avalos 	u_int rlen;
1347411677aeSAaron LI 	const struct forces_ilv *ilv = (const struct forces_ilv *)pptr;
134827bfbee1SPeter Avalos 	int invilv;
134927bfbee1SPeter Avalos 
135027bfbee1SPeter Avalos 	/*
135127bfbee1SPeter Avalos 	 * redirect_print() has ensured that len (what remains in the
135227bfbee1SPeter Avalos 	 * TLV) >= TLV_HDRL.
135327bfbee1SPeter Avalos 	 */
135427bfbee1SPeter Avalos 	dlen = len - TLV_HDRL;
135527bfbee1SPeter Avalos 	rlen = dlen;
1356*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n%s METADATA length %u\n", ib, rlen);
135727bfbee1SPeter Avalos 	while (rlen != 0) {
1358*ed775ee7SAntonio Huete Jimenez 		invilv = ilv_valid(ndo, ilv, rlen);
1359411677aeSAaron LI 		if (invilv) {
136027bfbee1SPeter Avalos 			break;
1361411677aeSAaron LI 		}
136227bfbee1SPeter Avalos 
136327bfbee1SPeter Avalos 		/*
136427bfbee1SPeter Avalos 		 * At this point, ilv_valid() has ensured that the ILV
136527bfbee1SPeter Avalos 		 * length is large enough but not too large (it doesn't
136627bfbee1SPeter Avalos 		 * go past the end of the containing TLV).
136727bfbee1SPeter Avalos 		 */
1368411677aeSAaron LI 		print_metailv(ndo, (const u_char *) ilv, 0, indent + 1);
136927bfbee1SPeter Avalos 		ilv = GO_NXT_ILV(ilv, rlen);
137027bfbee1SPeter Avalos 	}
137127bfbee1SPeter Avalos 
137227bfbee1SPeter Avalos 	return 0;
137327bfbee1SPeter Avalos }
137427bfbee1SPeter Avalos 
1375411677aeSAaron LI 
1376411677aeSAaron LI static int
print_reddata(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk _U_,int indent)1377411677aeSAaron LI print_reddata(netdissect_options *ndo,
1378*ed775ee7SAntonio Huete Jimenez               const u_char * pptr, u_int len,
1379411677aeSAaron LI               uint16_t op_msk _U_, int indent)
138027bfbee1SPeter Avalos {
138127bfbee1SPeter Avalos 	u_int dlen;
1382411677aeSAaron LI 	char *ib = indent_pr(indent, 0);
138327bfbee1SPeter Avalos 	u_int rlen;
138427bfbee1SPeter Avalos 
138527bfbee1SPeter Avalos 	dlen = len - TLV_HDRL;
138627bfbee1SPeter Avalos 	rlen = dlen;
1387*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n%s Redirect Data length %u\n", ib, rlen);
138827bfbee1SPeter Avalos 
1389411677aeSAaron LI 	if (ndo->ndo_vflag >= 3) {
1390*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\t\t[");
1391*ed775ee7SAntonio Huete Jimenez 		hex_print(ndo, "\n\t\t", pptr, rlen);
1392*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t\t]");
139327bfbee1SPeter Avalos 	}
139427bfbee1SPeter Avalos 
139527bfbee1SPeter Avalos 	return 0;
139627bfbee1SPeter Avalos }
139727bfbee1SPeter Avalos 
1398411677aeSAaron LI static int
redirect_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk _U_,int indent)1399411677aeSAaron LI redirect_print(netdissect_options *ndo,
1400*ed775ee7SAntonio Huete Jimenez                const u_char * pptr, u_int len,
1401411677aeSAaron LI                uint16_t op_msk _U_, int indent)
140227bfbee1SPeter Avalos {
1403411677aeSAaron LI 	const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
140427bfbee1SPeter Avalos 	u_int dlen;
140527bfbee1SPeter Avalos 	u_int rlen;
1406411677aeSAaron LI 	u_int invtlv;
140727bfbee1SPeter Avalos 
140827bfbee1SPeter Avalos 	/*
140927bfbee1SPeter Avalos 	 * forces_type_print() has ensured that len (the TLV length)
141027bfbee1SPeter Avalos 	 * >= TLV_HDRL.
141127bfbee1SPeter Avalos 	 */
141227bfbee1SPeter Avalos 	dlen = len - TLV_HDRL;
141327bfbee1SPeter Avalos 	if (dlen <= RD_MIN) {
1414*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t\ttruncated Redirect TLV: %u bytes missing! ",
1415*ed775ee7SAntonio Huete Jimenez 		       RD_MIN - dlen);
141627bfbee1SPeter Avalos 		return -1;
141727bfbee1SPeter Avalos 	}
141827bfbee1SPeter Avalos 
141927bfbee1SPeter Avalos 	rlen = dlen;
142027bfbee1SPeter Avalos 	indent += 1;
142127bfbee1SPeter Avalos 	while (rlen != 0) {
1422*ed775ee7SAntonio Huete Jimenez 		uint16_t type, tlvl;
1423*ed775ee7SAntonio Huete Jimenez 
1424*ed775ee7SAntonio Huete Jimenez 		type = GET_BE_U_2(tlv->type);
1425*ed775ee7SAntonio Huete Jimenez 		tlvl = GET_BE_U_2(tlv->length);
1426*ed775ee7SAntonio Huete Jimenez 		invtlv = tlv_valid(tlvl, rlen);
1427411677aeSAaron LI 		if (invtlv) {
1428*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Bad Redirect data\n");
142927bfbee1SPeter Avalos 			break;
1430411677aeSAaron LI 		}
143127bfbee1SPeter Avalos 
143227bfbee1SPeter Avalos 		/*
143327bfbee1SPeter Avalos 		 * At this point, tlv_valid() has ensured that the TLV
143427bfbee1SPeter Avalos 		 * length is large enough but not too large (it doesn't
143527bfbee1SPeter Avalos 		 * go past the end of the containing TLV).
143627bfbee1SPeter Avalos 		 */
1437*ed775ee7SAntonio Huete Jimenez 		if (type == F_TLV_METD) {
1438411677aeSAaron LI 			print_metatlv(ndo, (const u_char *) TLV_DATA(tlv),
1439*ed775ee7SAntonio Huete Jimenez 				      tlvl, 0,
1440*ed775ee7SAntonio Huete Jimenez 				      indent);
1441*ed775ee7SAntonio Huete Jimenez 		} else if (type == F_TLV_REDD) {
1442411677aeSAaron LI 			print_reddata(ndo, (const u_char *) TLV_DATA(tlv),
1443*ed775ee7SAntonio Huete Jimenez 				      tlvl, 0,
1444*ed775ee7SAntonio Huete Jimenez 				      indent);
144527bfbee1SPeter Avalos 		} else {
1446*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Unknown REDIRECT TLV 0x%x len %u\n",
1447*ed775ee7SAntonio Huete Jimenez 			       type,
1448*ed775ee7SAntonio Huete Jimenez 			       tlvl);
144927bfbee1SPeter Avalos 		}
145027bfbee1SPeter Avalos 
145127bfbee1SPeter Avalos 		tlv = GO_NXT_TLV(tlv, rlen);
145227bfbee1SPeter Avalos 	}
145327bfbee1SPeter Avalos 
145427bfbee1SPeter Avalos 	if (rlen) {
1455*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %u Bytes ",
1456*ed775ee7SAntonio Huete Jimenez 		          GET_BE_U_2(tlv->type),
1457*ed775ee7SAntonio Huete Jimenez 		          rlen - GET_BE_U_2(tlv->length));
145827bfbee1SPeter Avalos 		return -1;
145927bfbee1SPeter Avalos 	}
146027bfbee1SPeter Avalos 
146127bfbee1SPeter Avalos 	return 0;
146227bfbee1SPeter Avalos }
146327bfbee1SPeter Avalos 
146427bfbee1SPeter Avalos #define OP_OFF 8
146527bfbee1SPeter Avalos #define OP_MIN 12
146627bfbee1SPeter Avalos 
1467411677aeSAaron LI static int
lfbselect_print(netdissect_options * ndo,const u_char * pptr,u_int len,uint16_t op_msk,int indent)1468411677aeSAaron LI lfbselect_print(netdissect_options *ndo,
1469*ed775ee7SAntonio Huete Jimenez                 const u_char * pptr, u_int len,
1470411677aeSAaron LI                 uint16_t op_msk, int indent)
147127bfbee1SPeter Avalos {
147227bfbee1SPeter Avalos 	const struct forces_lfbsh *lfbs;
147327bfbee1SPeter Avalos 	const struct forces_tlv *otlv;
147427bfbee1SPeter Avalos 	char *ib = indent_pr(indent, 0);
147527bfbee1SPeter Avalos 	u_int dlen;
147627bfbee1SPeter Avalos 	u_int rlen;
1477411677aeSAaron LI 	u_int invtlv;
147827bfbee1SPeter Avalos 
147927bfbee1SPeter Avalos 	/*
148027bfbee1SPeter Avalos 	 * forces_type_print() has ensured that len (the TLV length)
148127bfbee1SPeter Avalos 	 * >= TLV_HDRL.
148227bfbee1SPeter Avalos 	 */
148327bfbee1SPeter Avalos 	dlen = len - TLV_HDRL;
148427bfbee1SPeter Avalos 	if (dlen <= OP_MIN) {	/* id, instance, oper tlv header .. */
1485*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t\ttruncated lfb selector: %u bytes missing! ",
1486*ed775ee7SAntonio Huete Jimenez 		       OP_MIN - dlen);
148727bfbee1SPeter Avalos 		return -1;
148827bfbee1SPeter Avalos 	}
148927bfbee1SPeter Avalos 
149027bfbee1SPeter Avalos 	/*
149127bfbee1SPeter Avalos 	 * At this point, we know that dlen > OP_MIN; OP_OFF < OP_MIN, so
149227bfbee1SPeter Avalos 	 * we also know that it's > OP_OFF.
149327bfbee1SPeter Avalos 	 */
149427bfbee1SPeter Avalos 	rlen = dlen - OP_OFF;
149527bfbee1SPeter Avalos 
149627bfbee1SPeter Avalos 	lfbs = (const struct forces_lfbsh *)pptr;
1497*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_SIZE(lfbs);
1498411677aeSAaron LI 	if (ndo->ndo_vflag >= 3) {
1499*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n%s%s(Classid %x) instance %x\n",
1500*ed775ee7SAntonio Huete Jimenez 		       ib,
1501*ed775ee7SAntonio Huete Jimenez 		       tok2str(ForCES_LFBs, NULL, GET_BE_U_4(lfbs->class)),
1502*ed775ee7SAntonio Huete Jimenez 		       GET_BE_U_4(lfbs->class),
1503*ed775ee7SAntonio Huete Jimenez 		       GET_BE_U_4(lfbs->instance));
150427bfbee1SPeter Avalos 	}
150527bfbee1SPeter Avalos 
1506411677aeSAaron LI 	otlv = (const struct forces_tlv *)(lfbs + 1);
150727bfbee1SPeter Avalos 
150827bfbee1SPeter Avalos 	indent += 1;
150927bfbee1SPeter Avalos 	while (rlen != 0) {
1510*ed775ee7SAntonio Huete Jimenez 		uint16_t type, tlvl;
1511*ed775ee7SAntonio Huete Jimenez 
1512*ed775ee7SAntonio Huete Jimenez 		type = GET_BE_U_2(otlv->type);
1513*ed775ee7SAntonio Huete Jimenez 		tlvl = GET_BE_U_2(otlv->length);
1514*ed775ee7SAntonio Huete Jimenez 		invtlv = tlv_valid(tlvl, rlen);
151527bfbee1SPeter Avalos 		if (invtlv)
151627bfbee1SPeter Avalos 			break;
151727bfbee1SPeter Avalos 
151827bfbee1SPeter Avalos 		/*
151927bfbee1SPeter Avalos 		 * At this point, tlv_valid() has ensured that the TLV
152027bfbee1SPeter Avalos 		 * length is large enough but not too large (it doesn't
152127bfbee1SPeter Avalos 		 * go past the end of the containing TLV).
152227bfbee1SPeter Avalos 		 */
1523*ed775ee7SAntonio Huete Jimenez 		if (op_valid(type, op_msk)) {
1524411677aeSAaron LI 			otlv_print(ndo, otlv, 0, indent);
152527bfbee1SPeter Avalos 		} else {
1526411677aeSAaron LI 			if (ndo->ndo_vflag < 3)
1527*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n");
1528*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\t\tINValid oper-TLV type 0x%x length %u for this ForCES message\n",
1529*ed775ee7SAntonio Huete Jimenez 			          type, tlvl);
1530411677aeSAaron LI 			invoptlv_print(ndo, (const u_char *)otlv, rlen, 0, indent);
153127bfbee1SPeter Avalos 		}
153227bfbee1SPeter Avalos 		otlv = GO_NXT_TLV(otlv, rlen);
153327bfbee1SPeter Avalos 	}
153427bfbee1SPeter Avalos 
153527bfbee1SPeter Avalos 	if (rlen) {
1536*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %u Bytes ",
1537*ed775ee7SAntonio Huete Jimenez 		          GET_BE_U_2(otlv->type),
1538*ed775ee7SAntonio Huete Jimenez 		          rlen - GET_BE_U_2(otlv->length));
153927bfbee1SPeter Avalos 		return -1;
154027bfbee1SPeter Avalos 	}
154127bfbee1SPeter Avalos 
154227bfbee1SPeter Avalos 	return 0;
154327bfbee1SPeter Avalos 
154427bfbee1SPeter Avalos trunc:
1545*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
154627bfbee1SPeter Avalos 	return -1;
154727bfbee1SPeter Avalos }
154827bfbee1SPeter Avalos 
1549411677aeSAaron LI 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)1550411677aeSAaron LI forces_type_print(netdissect_options *ndo,
1551*ed775ee7SAntonio Huete Jimenez                   const u_char * pptr, const struct forcesh *fhdr _U_,
1552*ed775ee7SAntonio Huete Jimenez                   u_int mlen, const struct tom_h *tops)
155327bfbee1SPeter Avalos {
155427bfbee1SPeter Avalos 	const struct forces_tlv *tltlv;
155527bfbee1SPeter Avalos 	u_int rlen;
1556411677aeSAaron LI 	u_int invtlv;
155727bfbee1SPeter Avalos 	int rc = 0;
1558*ed775ee7SAntonio Huete Jimenez 	u_int ttlv = 0;
155927bfbee1SPeter Avalos 
156027bfbee1SPeter Avalos 	/*
156127bfbee1SPeter Avalos 	 * forces_print() has already checked that mlen >= ForCES_HDRL
156227bfbee1SPeter Avalos 	 * by calling ForCES_HLN_VALID().
156327bfbee1SPeter Avalos 	 */
156427bfbee1SPeter Avalos 	rlen = mlen - ForCES_HDRL;
156527bfbee1SPeter Avalos 
156627bfbee1SPeter Avalos 	if (rlen > TLV_HLN) {
156727bfbee1SPeter Avalos 		if (tops->flags & ZERO_TTLV) {
1568*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("<0x%x>Illegal Top level TLV!\n", tops->flags);
156927bfbee1SPeter Avalos 			return -1;
157027bfbee1SPeter Avalos 		}
157127bfbee1SPeter Avalos 	} else {
157227bfbee1SPeter Avalos 		if (tops->flags & ZERO_MORE_TTLV)
157327bfbee1SPeter Avalos 			return 0;
157427bfbee1SPeter Avalos 		if (tops->flags & ONE_MORE_TTLV) {
1575*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\tTop level TLV Data missing!\n");
157627bfbee1SPeter Avalos 			return -1;
157727bfbee1SPeter Avalos 		}
157827bfbee1SPeter Avalos 	}
157927bfbee1SPeter Avalos 
158027bfbee1SPeter Avalos 	if (tops->flags & ZERO_TTLV) {
158127bfbee1SPeter Avalos 		return 0;
158227bfbee1SPeter Avalos 	}
158327bfbee1SPeter Avalos 
158427bfbee1SPeter Avalos 	ttlv = tops->flags >> 4;
158527bfbee1SPeter Avalos 	tltlv = GET_TOP_TLV(pptr);
158627bfbee1SPeter Avalos 
158727bfbee1SPeter Avalos 	/*XXX: 15 top level tlvs will probably be fine
158827bfbee1SPeter Avalos 	   You are nuts if you send more ;-> */
158927bfbee1SPeter Avalos 	while (rlen != 0) {
1590*ed775ee7SAntonio Huete Jimenez 		uint16_t type, tlvl;
1591*ed775ee7SAntonio Huete Jimenez 
1592*ed775ee7SAntonio Huete Jimenez 		type = GET_BE_U_2(tltlv->type);
1593*ed775ee7SAntonio Huete Jimenez 		tlvl = GET_BE_U_2(tltlv->length);
1594*ed775ee7SAntonio Huete Jimenez 		invtlv = tlv_valid(tlvl, rlen);
159527bfbee1SPeter Avalos 		if (invtlv)
159627bfbee1SPeter Avalos 			break;
159727bfbee1SPeter Avalos 
159827bfbee1SPeter Avalos 		/*
159927bfbee1SPeter Avalos 		 * At this point, tlv_valid() has ensured that the TLV
160027bfbee1SPeter Avalos 		 * length is large enough but not too large (it doesn't
160127bfbee1SPeter Avalos 		 * go past the end of the packet).
160227bfbee1SPeter Avalos 		 */
1603*ed775ee7SAntonio Huete Jimenez 		if (!ttlv_valid(type)) {
1604*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\tInvalid ForCES Top TLV type=0x%x",
1605*ed775ee7SAntonio Huete Jimenez 			       type);
160627bfbee1SPeter Avalos 			return -1;
160727bfbee1SPeter Avalos 		}
160827bfbee1SPeter Avalos 
1609411677aeSAaron LI 		if (ndo->ndo_vflag >= 3)
1610*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\t%s, length %u (data length %u Bytes)",
1611*ed775ee7SAntonio Huete Jimenez 			       tok2str(ForCES_TLV, NULL, type),
1612*ed775ee7SAntonio Huete Jimenez 			       tlvl,
1613*ed775ee7SAntonio Huete Jimenez 			       tlvl - TLV_HDRL);
161427bfbee1SPeter Avalos 
1615411677aeSAaron LI 		rc = tops->print(ndo, (const u_char *) TLV_DATA(tltlv),
1616*ed775ee7SAntonio Huete Jimenez 				 tlvl,
1617*ed775ee7SAntonio Huete Jimenez 				 tops->op_msk, 9);
161827bfbee1SPeter Avalos 		if (rc < 0) {
161927bfbee1SPeter Avalos 			return -1;
162027bfbee1SPeter Avalos 		}
162127bfbee1SPeter Avalos 		tltlv = GO_NXT_TLV(tltlv, rlen);
162227bfbee1SPeter Avalos 		ttlv--;
162327bfbee1SPeter Avalos 		if (ttlv <= 0)
162427bfbee1SPeter Avalos 			break;
162527bfbee1SPeter Avalos 	}
162627bfbee1SPeter Avalos 	/*
162727bfbee1SPeter Avalos 	 * XXX - if ttlv != 0, does that mean that the packet was too
162827bfbee1SPeter Avalos 	 * short, and didn't have *enough* TLVs in it?
162927bfbee1SPeter Avalos 	 */
163027bfbee1SPeter Avalos 	if (rlen) {
1631*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\tMess TopTLV header: min %u, total %u advertised %u ",
1632*ed775ee7SAntonio Huete Jimenez 		       TLV_HDRL, rlen, GET_BE_U_2(tltlv->length));
163327bfbee1SPeter Avalos 		return -1;
163427bfbee1SPeter Avalos 	}
163527bfbee1SPeter Avalos 
163627bfbee1SPeter Avalos 	return 0;
163727bfbee1SPeter Avalos }
163827bfbee1SPeter Avalos 
1639411677aeSAaron LI void
forces_print(netdissect_options * ndo,const u_char * pptr,u_int len)1640411677aeSAaron LI forces_print(netdissect_options *ndo,
1641*ed775ee7SAntonio Huete Jimenez              const u_char * pptr, u_int len)
164227bfbee1SPeter Avalos {
164327bfbee1SPeter Avalos 	const struct forcesh *fhdr;
164427bfbee1SPeter Avalos 	u_int mlen;
1645411677aeSAaron LI 	uint32_t flg_raw;
1646*ed775ee7SAntonio Huete Jimenez 	uint8_t tom;
164727bfbee1SPeter Avalos 	const struct tom_h *tops;
164827bfbee1SPeter Avalos 	int rc = 0;
164927bfbee1SPeter Avalos 
1650*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "forces";
165127bfbee1SPeter Avalos 	fhdr = (const struct forcesh *)pptr;
1652*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_SIZE(fhdr);
1653*ed775ee7SAntonio Huete Jimenez 	tom = GET_U_1(fhdr->fm_tom);
1654*ed775ee7SAntonio Huete Jimenez 	if (!tom_valid(tom)) {
1655*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("Invalid ForCES message type %u\n", tom);
165627bfbee1SPeter Avalos 		goto error;
165727bfbee1SPeter Avalos 	}
165827bfbee1SPeter Avalos 
165927bfbee1SPeter Avalos 	mlen = ForCES_BLN(fhdr);
166027bfbee1SPeter Avalos 
1661*ed775ee7SAntonio Huete Jimenez 	tops = get_forces_tom(tom);
166227bfbee1SPeter Avalos 	if (tops->v == TOM_RSVD) {
1663*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\tUnknown ForCES message type=0x%x", tom);
166427bfbee1SPeter Avalos 		goto error;
166527bfbee1SPeter Avalos 	}
166627bfbee1SPeter Avalos 
1667*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\tForCES %s ", tops->s);
166827bfbee1SPeter Avalos 	if (!ForCES_HLN_VALID(mlen, len)) {
1669*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("Illegal ForCES pkt len - min %u, total recvd %u, advertised %u ",
1670*ed775ee7SAntonio Huete Jimenez 		          ForCES_HDRL, len, ForCES_BLN(fhdr));
167127bfbee1SPeter Avalos 		goto error;
167227bfbee1SPeter Avalos 	}
167327bfbee1SPeter Avalos 
1674*ed775ee7SAntonio Huete Jimenez 	flg_raw = GET_BE_U_4(pptr + 20);
1675411677aeSAaron LI 	if (ndo->ndo_vflag >= 1) {
1676*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\tForCES Version %u len %uB flags 0x%08x ",
1677*ed775ee7SAntonio Huete Jimenez 		       ForCES_V(fhdr), mlen, flg_raw);
1678*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%" PRIx64,
167927bfbee1SPeter Avalos 		       ForCES_SID(fhdr), ForCES_node(ForCES_SID(fhdr)),
168027bfbee1SPeter Avalos 		       ForCES_DID(fhdr), ForCES_node(ForCES_DID(fhdr)),
1681*ed775ee7SAntonio Huete Jimenez 		       GET_BE_U_8(fhdr->fm_cor));
168227bfbee1SPeter Avalos 
168327bfbee1SPeter Avalos 	}
1684411677aeSAaron LI 	if (ndo->ndo_vflag >= 2) {
1685*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\tForCES flags:\n\t  %s(0x%x), prio=%u, %s(0x%x),\n\t  %s(0x%x), %s(0x%x)\n",
1686411677aeSAaron LI 		     tok2str(ForCES_ACKs, "ACKUnknown", ForCES_ACK(fhdr)),
1687411677aeSAaron LI 		     ForCES_ACK(fhdr),
168827bfbee1SPeter Avalos 		     ForCES_PRI(fhdr),
1689411677aeSAaron LI 		     tok2str(ForCES_EMs, "EMUnknown", ForCES_EM(fhdr)),
1690411677aeSAaron LI 		     ForCES_EM(fhdr),
1691411677aeSAaron LI 		     tok2str(ForCES_ATs, "ATUnknown", ForCES_AT(fhdr)),
1692411677aeSAaron LI 		     ForCES_AT(fhdr),
1693411677aeSAaron LI 		     tok2str(ForCES_TPs, "TPUnknown", ForCES_TP(fhdr)),
1694*ed775ee7SAntonio Huete Jimenez 		     ForCES_TP(fhdr));
1695*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\t  Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n",
1696*ed775ee7SAntonio Huete Jimenez 		     ForCES_RS1(fhdr), ForCES_RS2(fhdr));
169727bfbee1SPeter Avalos 	}
1698411677aeSAaron LI 	rc = forces_type_print(ndo, pptr, fhdr, mlen, tops);
169927bfbee1SPeter Avalos 	if (rc < 0) {
170027bfbee1SPeter Avalos error:
1701*ed775ee7SAntonio Huete Jimenez 		hex_print(ndo, "\n\t[", pptr, len);
1702*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t]");
170327bfbee1SPeter Avalos 		return;
170427bfbee1SPeter Avalos 	}
170527bfbee1SPeter Avalos 
1706411677aeSAaron LI 	if (ndo->ndo_vflag >= 4) {
1707*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t  Raw ForCES message\n\t [");
1708*ed775ee7SAntonio Huete Jimenez 		hex_print(ndo, "\n\t ", pptr, len);
1709*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t ]");
171027bfbee1SPeter Avalos 	}
171127bfbee1SPeter Avalos 	return;
171227bfbee1SPeter Avalos 
171327bfbee1SPeter Avalos trunc:
1714*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
171527bfbee1SPeter Avalos }
1716