2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that: (1) source code
4 * distributions retain the above copyright notice and this paragraph
5 * in its entirety, and (2) distributions including binary code include
6 * the above copyright notice and this paragraph in its entirety in
7 * the documentation or other materials provided with the distribution.
8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11 * FOR A PARTICULAR PURPOSE.
13 * Copyright (c) 2009 Mojatatu Networks, Inc
21 #include <tcpdump-stdinc.h>
23 #include "interface.h"
26 static const char tstr
[] = "[|forces]";
29 * RFC5810: Forwarding and Control Element Separation (ForCES) Protocol
32 #define ForCES_HDRL 24
33 #define ForCES_ALNL 4U
38 #define TOM_ASSNSETUP 0x1
39 #define TOM_ASSNTEARD 0x2
40 #define TOM_CONFIG 0x3
42 #define TOM_EVENTNOT 0x5
43 #define TOM_PKTREDIR 0x6
44 #define TOM_HEARTBT 0x0F
45 #define TOM_ASSNSETREP 0x11
46 #define TOM_CONFIGREP 0x13
47 #define TOM_QUERYREP 0x14
50 * tom_h Flags: resv1(8b):maxtlvs(4b):resv2(2b):mintlv(2b)
52 #define ZERO_TTLV 0x01
53 #define ZERO_MORE_TTLV 0x02
54 #define ONE_MORE_TTLV 0x04
60 #define TTLV_T1 (ONE_MORE_TTLV|ONE_TLV)
61 #define TTLV_T2 (ONE_MORE_TTLV|MAX_TLV)
68 int (*print
) (netdissect_options
*ndo
, register const u_char
* pptr
, register u_int len
,
69 uint16_t op_msk
, int indent
);
86 #define TOM_MAX_IND (_TOM_RSV_MAX - 1)
88 static inline int tom_valid(uint8_t tom
)
91 if (tom
>= 0x7 && tom
<= 0xe)
102 static inline const char *ForCES_node(uint32_t node
)
104 if (node
<= 0x3FFFFFFF)
106 if (node
>= 0x40000000 && node
<= 0x7FFFFFFF)
108 if (node
>= 0xC0000000 && node
<= 0xFFFFFFEF)
109 return "AllMulticast";
110 if (node
== 0xFFFFFFFD)
111 return "AllCEsBroadcast";
112 if (node
== 0xFFFFFFFE)
113 return "AllFEsBroadcast";
114 if (node
== 0xFFFFFFFF)
115 return "AllBroadcast";
117 return "ForCESreserved";
121 static const struct tok ForCES_ACKs
[] = {
129 static const struct tok ForCES_EMs
[] = {
131 {0x1, "execute-all-or-none"},
132 {0x2, "execute-until-failure"},
133 {0x3, "continue-execute-on-failure"},
137 static const struct tok ForCES_ATs
[] = {
139 {0x1, "2PCtransaction"},
143 static const struct tok ForCES_TPs
[] = {
144 {0x0, "StartofTransaction"},
145 {0x1, "MiddleofTransaction"},
146 {0x2, "EndofTransaction"},
152 * Structure of forces header, naked of TLVs.
155 uint8_t fm_vrsvd
; /* version and reserved */
156 #define ForCES_V(forcesh) ((forcesh)->fm_vrsvd >> 4)
157 uint8_t fm_tom
; /* type of message */
158 uint16_t fm_len
; /* total length * 4 bytes */
159 #define ForCES_BLN(forcesh) ((uint32_t)(EXTRACT_16BITS(&(forcesh)->fm_len) << 2))
160 uint32_t fm_sid
; /* Source ID */
161 #define ForCES_SID(forcesh) EXTRACT_32BITS(&(forcesh)->fm_sid)
162 uint32_t fm_did
; /* Destination ID */
163 #define ForCES_DID(forcesh) EXTRACT_32BITS(&(forcesh)->fm_did)
164 uint8_t fm_cor
[8]; /* correlator */
165 uint32_t fm_flags
; /* flags */
166 #define ForCES_ACK(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0xC0000000) >> 30)
167 #define ForCES_PRI(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x38000000) >> 27)
168 #define ForCES_RS1(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x07000000) >> 24)
169 #define ForCES_EM(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00C00000) >> 22)
170 #define ForCES_AT(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00200000) >> 21)
171 #define ForCES_TP(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00180000) >> 19)
172 #define ForCES_RS2(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x0007FFFF) >> 0)
175 #define ForCES_HLN_VALID(fhl,tlen) ((tlen) >= ForCES_HDRL && \
176 (fhl) >= ForCES_HDRL && \
179 #define F_LFB_RSVD 0x0
180 #define F_LFB_FEO 0x1
181 #define F_LFB_FEPO 0x2
182 static const struct tok ForCES_LFBs
[] = {
183 {F_LFB_RSVD
, "Invalid TLV"},
184 {F_LFB_FEO
, "FEObj LFB"},
185 {F_LFB_FEPO
, "FEProtoObj LFB"},
189 /* this is defined in RFC5810 section A.2 */
190 /* http://www.iana.org/assignments/forces/forces.xhtml#oper-tlv-types */
209 #define F_OP_MAX (_F_OP_MAX - 1)
212 B_OP_SET
= 1 << (F_OP_SET
- 1),
213 B_OP_SETPROP
= 1 << (F_OP_SETPROP
- 1),
214 B_OP_SETRESP
= 1 << (F_OP_SETRESP
- 1),
215 B_OP_SETPRESP
= 1 << (F_OP_SETPRESP
- 1),
216 B_OP_DEL
= 1 << (F_OP_DEL
- 1),
217 B_OP_DELRESP
= 1 << (F_OP_DELRESP
- 1),
218 B_OP_GET
= 1 << (F_OP_GET
- 1),
219 B_OP_GETPROP
= 1 << (F_OP_GETPROP
- 1),
220 B_OP_GETRESP
= 1 << (F_OP_GETRESP
- 1),
221 B_OP_GETPRESP
= 1 << (F_OP_GETPRESP
- 1),
222 B_OP_REPORT
= 1 << (F_OP_REPORT
- 1),
223 B_OP_COMMIT
= 1 << (F_OP_COMMIT
- 1),
224 B_OP_RCOMMIT
= 1 << (F_OP_RCOMMIT
- 1),
225 B_OP_RTRCOMP
= 1 << (F_OP_RTRCOMP
- 1),
232 int (*print
) (netdissect_options
*ndo
, register const u_char
* pptr
, register u_int len
,
233 uint16_t op_msk
, int indent
);
236 static int genoptlv_print(netdissect_options
*, register const u_char
* pptr
, register u_int len
,
237 uint16_t op_msk
, int indent
);
238 static int recpdoptlv_print(netdissect_options
*, register const u_char
* pptr
, register u_int len
,
239 uint16_t op_msk
, int indent
);
240 static int invoptlv_print(netdissect_options
*, register const u_char
* pptr
, register u_int len
,
241 uint16_t op_msk
, int indent
);
256 static const struct optlv_h OPTLV_msg
[F_OP_MAX
+ 1] = {
257 /* F_OP_RSV */ {ZERO_TTLV
, 0, "Invalid OPTLV", invoptlv_print
},
258 /* F_OP_SET */ {TTLV_T2
, B_FULLD
| B_SPARD
, " Set", recpdoptlv_print
},
260 {TTLV_T2
, B_FULLD
| B_SPARD
, " SetProp", recpdoptlv_print
},
261 /* F_OP_SETRESP */ {TTLV_T2
, B_RESTV
, " SetResp", recpdoptlv_print
},
262 /* F_OP_SETPRESP */ {TTLV_T2
, B_RESTV
, " SetPropResp", recpdoptlv_print
},
263 /* F_OP_DEL */ {ZERO_TTLV
, 0, " Del", recpdoptlv_print
},
264 /* F_OP_DELRESP */ {TTLV_T2
, B_RESTV
, " DelResp", recpdoptlv_print
},
265 /* F_OP_GET */ {ZERO_TTLV
, 0, " Get", recpdoptlv_print
},
266 /* F_OP_GETPROP */ {ZERO_TTLV
, 0, " GetProp", recpdoptlv_print
},
268 {TTLV_T2
, B_FULLD
| B_SPARD
| B_RESTV
, " GetResp", recpdoptlv_print
},
270 {TTLV_T2
, B_FULLD
| B_RESTV
, " GetPropResp", recpdoptlv_print
},
272 {TTLV_T2
, B_FULLD
| B_SPARD
, " Report", recpdoptlv_print
},
273 /* F_OP_COMMIT */ {ZERO_TTLV
, 0, " Commit", NULL
},
274 /* F_OP_RCOMMIT */ {TTLV_T1
, B_RESTV
, " RCommit", genoptlv_print
},
275 /* F_OP_RTRCOMP */ {ZERO_TTLV
, 0, " RTRCOMP", NULL
},
278 static inline const struct optlv_h
*get_forces_optlv_h(uint16_t opt
)
280 if (opt
> F_OP_MAX
|| opt
<= F_OP_RSV
)
281 return &OPTLV_msg
[F_OP_RSV
];
283 return &OPTLV_msg
[opt
];
288 #define IND_PREF '\n'
290 char ind_buf
[IND_SIZE
];
292 static inline char *indent_pr(int indent
, int nlpref
)
297 if (indent
> (IND_SIZE
- 1))
298 indent
= IND_SIZE
- 1;
306 while (--indent
>= 0)
313 static inline int op_valid(uint16_t op
, uint16_t mask
)
315 int opb
= 1 << (op
- 1);
321 /* I guess we should allow vendor operations? */
327 #define F_TLV_RSVD 0x0000
328 #define F_TLV_REDR 0x0001
329 #define F_TLV_ASRS 0x0010
330 #define F_TLV_ASRT 0x0011
331 #define F_TLV_LFBS 0x1000
332 #define F_TLV_PDAT 0x0110
333 #define F_TLV_KEYI 0x0111
334 #define F_TLV_FULD 0x0112
335 #define F_TLV_SPAD 0x0113
336 #define F_TLV_REST 0x0114
337 #define F_TLV_METD 0x0115
338 #define F_TLV_REDD 0x0116
339 #define F_TLV_TRNG 0x0117
342 #define F_TLV_VNST 0x8000
344 static const struct tok ForCES_TLV
[] = {
345 {F_TLV_RSVD
, "Invalid TLV"},
346 {F_TLV_REDR
, "REDIRECT TLV"},
347 {F_TLV_ASRS
, "ASResult TLV"},
348 {F_TLV_ASRT
, "ASTreason TLV"},
349 {F_TLV_LFBS
, "LFBselect TLV"},
350 {F_TLV_PDAT
, "PATH-DATA TLV"},
351 {F_TLV_KEYI
, "KEYINFO TLV"},
352 {F_TLV_FULD
, "FULLDATA TLV"},
353 {F_TLV_SPAD
, "SPARSEDATA TLV"},
354 {F_TLV_REST
, "RESULT TLV"},
355 {F_TLV_METD
, "METADATA TLV"},
356 {F_TLV_REDD
, "REDIRECTDATA TLV"},
361 static inline int ttlv_valid(uint16_t ttlv
)
364 if (ttlv
== 1 || ttlv
== 0x1000)
366 if (ttlv
>= 0x10 && ttlv
<= 0x11)
368 if (ttlv
>= 0x110 && ttlv
<= 0x116)
387 #define F_ALN_LEN(len) ( ((len)+ForCES_ALNL-1) & ~(ForCES_ALNL-1) )
388 #define GET_TOP_TLV(fhdr) ((const struct forces_tlv *)((fhdr) + sizeof (struct forcesh)))
389 #define TLV_SET_LEN(len) (F_ALN_LEN(TLV_HDRL) + (len))
390 #define TLV_ALN_LEN(len) F_ALN_LEN(TLV_SET_LEN(len))
391 #define TLV_RDAT_LEN(tlv) ((int)(EXTRACT_16BITS(&(tlv)->length) - TLV_SET_LEN(0))
392 #define TLV_DATA(tlvp) ((const void*)(((const char*)(tlvp)) + TLV_SET_LEN(0)))
393 #define GO_NXT_TLV(tlv,rlen) ((rlen) -= F_ALN_LEN(EXTRACT_16BITS(&(tlv)->length)), \
394 (const struct forces_tlv*)(((const char*)(tlv)) \
395 + F_ALN_LEN(EXTRACT_16BITS(&(tlv)->length))))
396 #define ILV_SET_LEN(len) (F_ALN_LEN(ILV_HDRL) + (len))
397 #define ILV_ALN_LEN(len) F_ALN_LEN(ILV_SET_LEN(len))
398 #define ILV_RDAT_LEN(ilv) ((int)(EXTRACT_32BITS(&(ilv)->length)) - ILV_SET_LEN(0))
399 #define ILV_DATA(ilvp) ((const void*)(((const char*)(ilvp)) + ILV_SET_LEN(0)))
400 #define GO_NXT_ILV(ilv,rlen) ((rlen) -= F_ALN_LEN(EXTRACT_32BITS(&(ilv)->length)), \
401 (const struct forces_ilv *)(((const char*)(ilv)) \
402 + F_ALN_LEN(EXTRACT_32BITS(&(ilv)->length))))
403 #define INVALID_RLEN 1
404 #define INVALID_STLN 2
405 #define INVALID_LTLN 3
406 #define INVALID_ALEN 4
408 static const struct tok ForCES_TLV_err
[] = {
409 {INVALID_RLEN
, "Invalid total length"},
410 {INVALID_STLN
, "xLV too short"},
411 {INVALID_LTLN
, "xLV too long"},
412 {INVALID_ALEN
, "data padding missing"},
416 static inline u_int
tlv_valid(const struct forces_tlv
*tlv
, u_int rlen
)
420 if (EXTRACT_16BITS(&tlv
->length
) < TLV_HDRL
)
422 if (EXTRACT_16BITS(&tlv
->length
) > rlen
)
424 if (rlen
< F_ALN_LEN(EXTRACT_16BITS(&tlv
->length
)))
430 static inline int ilv_valid(const struct forces_ilv
*ilv
, u_int rlen
)
434 if (EXTRACT_32BITS(&ilv
->length
) < ILV_HDRL
)
436 if (EXTRACT_32BITS(&ilv
->length
) > rlen
)
438 if (rlen
< F_ALN_LEN(EXTRACT_32BITS(&ilv
->length
)))
444 static int lfbselect_print(netdissect_options
*, register const u_char
* pptr
, register u_int len
,
445 uint16_t op_msk
, int indent
);
446 static int redirect_print(netdissect_options
*, register const u_char
* pptr
, register u_int len
,
447 uint16_t op_msk
, int indent
);
448 static int asrtlv_print(netdissect_options
*, register const u_char
* pptr
, register u_int len
,
449 uint16_t op_msk
, int indent
);
450 static int asttlv_print(netdissect_options
*, register const u_char
* pptr
, register u_int len
,
451 uint16_t op_msk
, int indent
);
453 struct forces_lfbsh
{
458 #define ASSNS_OPS (B_OP_REPORT)
459 #define CFG_OPS (B_OP_SET|B_OP_SETPROP|B_OP_DEL|B_OP_COMMIT|B_OP_RTRCOMP)
460 #define CFG_ROPS (B_OP_SETRESP|B_OP_SETPRESP|B_OP_DELRESP|B_OP_RCOMMIT)
461 #define CFG_QY (B_OP_GET|B_OP_GETPROP)
462 #define CFG_QYR (B_OP_GETRESP|B_OP_GETPRESP)
463 #define CFG_EVN (B_OP_REPORT)
465 static const struct tom_h ForCES_msg
[TOM_MAX_IND
+ 1] = {
466 /* TOM_RSV_I */ {TOM_RSVD
, ZERO_TTLV
, 0, "Invalid message", NULL
},
467 /* TOM_ASS_I */ {TOM_ASSNSETUP
, ZERO_MORE_TTLV
| TWO_TLV
, ASSNS_OPS
,
468 "Association Setup", lfbselect_print
},
470 {TOM_ASSNTEARD
, TTLV_T1
, 0, "Association TearDown", asttlv_print
},
471 /* TOM_CFG_I */ {TOM_CONFIG
, TTLV_T2
, CFG_OPS
, "Config", lfbselect_print
},
472 /* TOM_QRY_I */ {TOM_QUERY
, TTLV_T2
, CFG_QY
, "Query", lfbselect_print
},
473 /* TOM_EVN_I */ {TOM_EVENTNOT
, TTLV_T1
, CFG_EVN
, "Event Notification",
476 {TOM_PKTREDIR
, TTLV_T2
, 0, "Packet Redirect", redirect_print
},
477 /* TOM_HBT_I */ {TOM_HEARTBT
, ZERO_TTLV
, 0, "HeartBeat", NULL
},
479 {TOM_ASSNSETREP
, TTLV_T1
, 0, "Association Response", asrtlv_print
},
480 /* TOM_CNR_I */ {TOM_CONFIGREP
, TTLV_T2
, CFG_ROPS
, "Config Response",
483 {TOM_QUERYREP
, TTLV_T2
, CFG_QYR
, "Query Response", lfbselect_print
},
486 static inline const struct tom_h
*get_forces_tom(uint8_t tom
)
489 for (i
= TOM_RSV_I
; i
<= TOM_MAX_IND
; i
++) {
490 const struct tom_h
*th
= &ForCES_msg
[i
];
494 return &ForCES_msg
[TOM_RSV_I
];
502 int (*print
) (netdissect_options
*, register const u_char
* pptr
, register u_int len
,
503 uint16_t op_msk
, int indent
);
515 #define PD_MAX_IND (_TOM_RSV_MAX - 1)
517 static inline int pd_valid(uint16_t pd
)
519 if (pd
>= F_TLV_PDAT
&& pd
<= F_TLV_REST
)
525 chk_op_type(netdissect_options
*ndo
,
526 uint16_t type
, uint16_t msk
, uint16_t omsk
)
528 if (type
!= F_TLV_PDAT
) {
530 if (type
!= F_TLV_KEYI
) {
531 ND_PRINT((ndo
, "Based on flags expected KEYINFO TLV!\n"));
535 ND_PRINT((ndo
, "Illegal DATA encoding for type 0x%x programmed %x got %x \n",
544 #define F_SELTABRANGE 2
545 #define F_TABAPPEND 4
553 static int prestlv_print(netdissect_options
*, register const u_char
* pptr
, register u_int len
,
554 uint16_t op_msk
, int indent
);
555 static int pkeyitlv_print(netdissect_options
*, register const u_char
* pptr
, register u_int len
,
556 uint16_t op_msk
, int indent
);
557 static int fdatatlv_print(netdissect_options
*, register const u_char
* pptr
, register u_int len
,
558 uint16_t op_msk
, int indent
);
559 static int sdatatlv_print(netdissect_options
*, register const u_char
* pptr
, register u_int len
,
560 uint16_t op_msk
, int indent
);
562 static const struct pdata_ops ForCES_pdata
[PD_MAX_IND
+ 1] = {
563 /* PD_RSV_I */ {0, 0, 0, "Invalid message", NULL
},
564 /* PD_SEL_I */ {F_TLV_KEYI
, 0, 0, "KEYINFO TLV", pkeyitlv_print
},
565 /* PD_FDT_I */ {F_TLV_FULD
, 0, B_FULLD
, "FULLDATA TLV", fdatatlv_print
},
566 /* PD_SDT_I */ {F_TLV_SPAD
, 0, B_SPARD
, "SPARSEDATA TLV", sdatatlv_print
},
567 /* PD_RES_I */ {F_TLV_REST
, 0, B_RESTV
, "RESULT TLV", prestlv_print
},
569 {F_TLV_PDAT
, 0, 0, "Inner PATH-DATA TLV", recpdoptlv_print
},
572 static inline const struct pdata_ops
*get_forces_pd(uint16_t pd
)
575 for (i
= PD_RSV_I
+ 1; i
<= PD_MAX_IND
; i
++) {
576 const struct pdata_ops
*pdo
= &ForCES_pdata
[i
];
580 return &ForCES_pdata
[TOM_RSV_I
];
588 E_INVALID_DESTINATION_PID
,
591 E_LFB_INSTANCE_ID_NOT_FOUND
,
593 E_COMPONENT_DOES_NOT_EXIST
,
597 E_INVALID_ARRAY_CREATION
,
598 E_VALUE_OUT_OF_RANGE
,
600 E_INVALID_PARAMETERS
,
601 E_INVALID_MESSAGE_TYPE
,
608 /* 0x18-0xFE are reserved .. */
609 E_UNSPECIFIED_ERROR
= 0XFF
612 static const struct tok ForCES_errs
[] = {
613 {E_SUCCESS
, "SUCCESS"},
614 {E_INVALID_HEADER
, "INVALID HEADER"},
615 {E_LENGTH_MISMATCH
, "LENGTH MISMATCH"},
616 {E_VERSION_MISMATCH
, "VERSION MISMATCH"},
617 {E_INVALID_DESTINATION_PID
, "INVALID DESTINATION PID"},
618 {E_LFB_UNKNOWN
, "LFB UNKNOWN"},
619 {E_LFB_NOT_FOUND
, "LFB NOT FOUND"},
620 {E_LFB_INSTANCE_ID_NOT_FOUND
, "LFB INSTANCE ID NOT FOUND"},
621 {E_INVALID_PATH
, "INVALID PATH"},
622 {E_COMPONENT_DOES_NOT_EXIST
, "COMPONENT DOES NOT EXIST"},
623 {E_EXISTS
, "EXISTS ALREADY"},
624 {E_NOT_FOUND
, "NOT FOUND"},
625 {E_READ_ONLY
, "READ ONLY"},
626 {E_INVALID_ARRAY_CREATION
, "INVALID ARRAY CREATION"},
627 {E_VALUE_OUT_OF_RANGE
, "VALUE OUT OF RANGE"},
628 {E_CONTENTS_TOO_LONG
, "CONTENTS TOO LONG"},
629 {E_INVALID_PARAMETERS
, "INVALID PARAMETERS"},
630 {E_INVALID_MESSAGE_TYPE
, "INVALID MESSAGE TYPE"},
631 {E_INVALID_FLAGS
, "INVALID FLAGS"},
632 {E_INVALID_TLV
, "INVALID TLV"},
633 {E_EVENT_ERROR
, "EVENT ERROR"},
634 {E_NOT_SUPPORTED
, "NOT SUPPORTED"},
635 {E_MEMORY_ERROR
, "MEMORY ERROR"},
636 {E_INTERNAL_ERROR
, "INTERNAL ERROR"},
637 {E_UNSPECIFIED_ERROR
, "UNSPECIFIED ERROR"},
644 prestlv_print(netdissect_options
*ndo
,
645 register const u_char
* pptr
, register u_int len
,
646 uint16_t op_msk _U_
, int indent
)
648 const struct forces_tlv
*tlv
= (const struct forces_tlv
*)pptr
;
649 register const u_char
*tdp
= (const u_char
*) TLV_DATA(tlv
);
650 const struct res_val
*r
= (const struct res_val
*)tdp
;
654 * pdatacnt_print() has ensured that len (the TLV length)
657 dlen
= len
- TLV_HDRL
;
658 if (dlen
!= RESLEN
) {
659 ND_PRINT((ndo
, "illegal RESULT-TLV: %d bytes!\n", dlen
));
664 if (r
->result
>= 0x18 && r
->result
<= 0xFE) {
665 ND_PRINT((ndo
, "illegal reserved result code: 0x%x!\n", r
->result
));
669 if (ndo
->ndo_vflag
>= 3) {
670 char *ib
= indent_pr(indent
, 0);
671 ND_PRINT((ndo
, "%s Result: %s (code 0x%x)\n", ib
,
672 tok2str(ForCES_errs
, NULL
, r
->result
), r
->result
));
677 ND_PRINT((ndo
, "%s", tstr
));
682 fdatatlv_print(netdissect_options
*ndo
,
683 register const u_char
* pptr
, register u_int len
,
684 uint16_t op_msk _U_
, int indent
)
686 const struct forces_tlv
*tlv
= (const struct forces_tlv
*)pptr
;
688 register const u_char
*tdp
= (const u_char
*) TLV_DATA(tlv
);
692 * pdatacnt_print() or pkeyitlv_print() has ensured that len
693 * (the TLV length) >= TLV_HDRL.
695 rlen
= len
- TLV_HDRL
;
697 type
= EXTRACT_16BITS(&tlv
->type
);
698 if (type
!= F_TLV_FULD
) {
699 ND_PRINT((ndo
, "Error: expecting FULLDATA!\n"));
703 if (ndo
->ndo_vflag
>= 3) {
704 char *ib
= indent_pr(indent
+ 2, 1);
705 ND_PRINT((ndo
, "%s[", &ib
[1]));
706 hex_print_with_offset(ndo
, ib
, tdp
, rlen
, 0);
707 ND_PRINT((ndo
, "\n%s]\n", &ib
[1]));
712 ND_PRINT((ndo
, "%s", tstr
));
717 sdatailv_print(netdissect_options
*ndo
,
718 register const u_char
* pptr
, register u_int len
,
719 uint16_t op_msk _U_
, int indent
)
722 const struct forces_ilv
*ilv
= (const struct forces_ilv
*)pptr
;
725 if (len
< ILV_HDRL
) {
726 ND_PRINT((ndo
, "Error: BAD SPARSEDATA-TLV!\n"));
733 ND_PRINT((ndo
, "Jamal - outstanding length <%d>\n", rlen
));
735 char *ib
= indent_pr(indent
, 1);
736 register const u_char
*tdp
= (const u_char
*) ILV_DATA(ilv
);
738 invilv
= ilv_valid(ilv
, rlen
);
740 ND_PRINT((ndo
, "%s[", &ib
[1]));
741 hex_print_with_offset(ndo
, ib
, tdp
, rlen
, 0);
742 ND_PRINT((ndo
, "\n%s]\n", &ib
[1]));
745 if (ndo
->ndo_vflag
>= 3) {
746 int ilvl
= EXTRACT_32BITS(&ilv
->length
);
747 ND_PRINT((ndo
, "\n%s ILV: type %x length %d\n", &ib
[1],
748 EXTRACT_32BITS(&ilv
->type
), ilvl
));
749 hex_print_with_offset(ndo
, "\t\t[", tdp
, ilvl
-ILV_HDRL
, 0);
752 ilv
= GO_NXT_ILV(ilv
, rlen
);
758 ND_PRINT((ndo
, "%s", tstr
));
763 sdatatlv_print(netdissect_options
*ndo
,
764 register const u_char
* pptr
, register u_int len
,
765 uint16_t op_msk
, int indent
)
767 const struct forces_tlv
*tlv
= (const struct forces_tlv
*)pptr
;
769 register const u_char
*tdp
= (const u_char
*) TLV_DATA(tlv
);
773 * pdatacnt_print() has ensured that len (the TLV length)
776 rlen
= len
- TLV_HDRL
;
778 type
= EXTRACT_16BITS(&tlv
->type
);
779 if (type
!= F_TLV_SPAD
) {
780 ND_PRINT((ndo
, "Error: expecting SPARSEDATA!\n"));
784 return sdatailv_print(ndo
, tdp
, rlen
, op_msk
, indent
);
787 ND_PRINT((ndo
, "%s", tstr
));
792 pkeyitlv_print(netdissect_options
*ndo
,
793 register const u_char
* pptr
, register u_int len
,
794 uint16_t op_msk
, int indent
)
796 const struct forces_tlv
*tlv
= (const struct forces_tlv
*)pptr
;
797 register const u_char
*tdp
= (const u_char
*) TLV_DATA(tlv
);
798 register const u_char
*dp
= tdp
+ 4;
799 const struct forces_tlv
*kdtlv
= (const struct forces_tlv
*)dp
;
801 char *ib
= indent_pr(indent
, 0);
806 id
= EXTRACT_32BITS(tdp
);
807 ND_PRINT((ndo
, "%sKeyinfo: Key 0x%x\n", ib
, id
));
809 type
= EXTRACT_16BITS(&kdtlv
->type
);
810 invtlv
= tlv_valid(kdtlv
, len
);
813 ND_PRINT((ndo
, "%s TLV type 0x%x len %d\n",
814 tok2str(ForCES_TLV_err
, NULL
, invtlv
), type
,
815 EXTRACT_16BITS(&kdtlv
->length
)));
819 * At this point, tlv_valid() has ensured that the TLV
820 * length is large enough but not too large (it doesn't
821 * go past the end of the containing TLV).
823 tll
= EXTRACT_16BITS(&kdtlv
->length
);
824 dp
= (const u_char
*) TLV_DATA(kdtlv
);
825 return fdatatlv_print(ndo
, dp
, tll
, op_msk
, indent
);
828 ND_PRINT((ndo
, "%s", tstr
));
832 #define PTH_DESC_SIZE 12
835 pdatacnt_print(netdissect_options
*ndo
,
836 register const u_char
* pptr
, register u_int len
,
837 uint16_t IDcnt
, uint16_t op_msk
, int indent
)
841 char *ib
= indent_pr(indent
, 0);
843 if ((op_msk
& B_APPND
) && ndo
->ndo_vflag
>= 3) {
844 ND_PRINT((ndo
, "%sTABLE APPEND\n", ib
));
846 for (i
= 0; i
< IDcnt
; i
++) {
847 ND_TCHECK2(*pptr
, 4);
850 id
= EXTRACT_32BITS(pptr
);
851 if (ndo
->ndo_vflag
>= 3)
852 ND_PRINT((ndo
, "%sID#%02u: %d\n", ib
, i
+ 1, id
));
857 if ((op_msk
& B_TRNG
) || (op_msk
& B_KEYIN
)) {
858 if (op_msk
& B_TRNG
) {
859 uint32_t starti
, endi
;
861 if (len
< PTH_DESC_SIZE
) {
862 ND_PRINT((ndo
, "pathlength %d with key/range too short %d\n",
863 len
, PTH_DESC_SIZE
));
867 pptr
+= sizeof(struct forces_tlv
);
868 len
-= sizeof(struct forces_tlv
);
870 starti
= EXTRACT_32BITS(pptr
);
874 endi
= EXTRACT_32BITS(pptr
);
878 if (ndo
->ndo_vflag
>= 3)
879 ND_PRINT((ndo
, "%sTable range: [%d,%d]\n", ib
, starti
, endi
));
882 if (op_msk
& B_KEYIN
) {
883 const struct forces_tlv
*keytlv
;
886 if (len
< PTH_DESC_SIZE
) {
887 ND_PRINT((ndo
, "pathlength %d with key/range too short %d\n",
888 len
, PTH_DESC_SIZE
));
895 keytlv
= (const struct forces_tlv
*)pptr
;
897 pptr
+= sizeof(struct forces_tlv
);
898 len
-= sizeof(struct forces_tlv
);
899 /* skip key content */
900 tll
= EXTRACT_16BITS(&keytlv
->length
);
901 if (tll
< TLV_HDRL
) {
902 ND_PRINT((ndo
, "key content length %u < %u\n",
908 ND_PRINT((ndo
, "key content too short\n"));
918 const struct forces_tlv
*pdtlv
= (const struct forces_tlv
*)pptr
;
926 type
= EXTRACT_16BITS(&pdtlv
->type
);
927 invtlv
= tlv_valid(pdtlv
, len
);
929 ND_PRINT((ndo
, "%s Outstanding bytes %d for TLV type 0x%x TLV len %d\n",
930 tok2str(ForCES_TLV_err
, NULL
, invtlv
), len
, type
,
931 EXTRACT_16BITS(&pdtlv
->length
)));
935 * At this point, tlv_valid() has ensured that the TLV
936 * length is large enough but not too large (it doesn't
937 * go past the end of the containing TLV).
939 tll
= EXTRACT_16BITS(&pdtlv
->length
) - TLV_HDRL
;
940 aln
= F_ALN_LEN(EXTRACT_16BITS(&pdtlv
->length
));
941 if (aln
> EXTRACT_16BITS(&pdtlv
->length
)) {
944 "Invalid padded pathdata TLV type 0x%x len %d missing %d pad bytes\n",
945 type
, EXTRACT_16BITS(&pdtlv
->length
), aln
- len
));
947 pad
= aln
- EXTRACT_16BITS(&pdtlv
->length
);
950 if (pd_valid(type
)) {
951 const struct pdata_ops
*ops
= get_forces_pd(type
);
953 if (ndo
->ndo_vflag
>= 3 && ops
->v
!= F_TLV_PDAT
) {
955 ND_PRINT((ndo
, "%s %s (Length %d DataLen %d pad %d Bytes)\n",
956 ib
, ops
->s
, EXTRACT_16BITS(&pdtlv
->length
), tll
, pad
));
958 ND_PRINT((ndo
, "%s %s (Length %d DataLen %d Bytes)\n",
959 ib
, ops
->s
, EXTRACT_16BITS(&pdtlv
->length
), tll
));
962 chk_op_type(ndo
, type
, op_msk
, ops
->op_msk
);
964 if (ops
->print(ndo
, (const u_char
*)pdtlv
,
965 tll
+ pad
+ TLV_HDRL
, op_msk
,
968 len
-= (TLV_HDRL
+ pad
+ tll
);
970 ND_PRINT((ndo
, "Invalid path data content type 0x%x len %d\n",
971 type
, EXTRACT_16BITS(&pdtlv
->length
)));
973 if (EXTRACT_16BITS(&pdtlv
->length
)) {
974 hex_print_with_offset(ndo
, "Bad Data val\n\t [",
976 ND_PRINT((ndo
, "]\n"));
985 ND_PRINT((ndo
, "%s", tstr
));
990 pdata_print(netdissect_options
*ndo
,
991 register const u_char
* pptr
, register u_int len
,
992 uint16_t op_msk
, int indent
)
994 const struct pathdata_h
*pdh
= (const struct pathdata_h
*)pptr
;
995 char *ib
= indent_pr(indent
, 0);
1001 if (len
< sizeof(struct pathdata_h
))
1003 if (ndo
->ndo_vflag
>= 3) {
1004 ND_PRINT((ndo
, "\n%sPathdata: Flags 0x%x ID count %d\n",
1005 ib
, EXTRACT_16BITS(&pdh
->pflags
), EXTRACT_16BITS(&pdh
->pIDcnt
)));
1008 if (EXTRACT_16BITS(&pdh
->pflags
) & F_SELKEY
) {
1012 /* Table GET Range operation */
1013 if (EXTRACT_16BITS(&pdh
->pflags
) & F_SELTABRANGE
) {
1016 /* Table SET append operation */
1017 if (EXTRACT_16BITS(&pdh
->pflags
) & F_TABAPPEND
) {
1021 pptr
+= sizeof(struct pathdata_h
);
1022 len
-= sizeof(struct pathdata_h
);
1023 idcnt
= EXTRACT_16BITS(&pdh
->pIDcnt
);
1024 minsize
= idcnt
* 4;
1025 if (len
< minsize
) {
1026 ND_PRINT((ndo
, "\t\t\ttruncated IDs expected %uB got %uB\n", minsize
,
1028 hex_print_with_offset(ndo
, "\t\t\tID Data[", pptr
, len
, 0);
1029 ND_PRINT((ndo
, "]\n"));
1033 if ((op_msk
& B_TRNG
) && (op_msk
& B_KEYIN
)) {
1034 ND_PRINT((ndo
, "\t\t\tIllegal to have both Table ranges and keys\n"));
1038 more_pd
= pdatacnt_print(ndo
, pptr
, len
, idcnt
, op_msk
, indent
);
1040 int consumed
= len
- more_pd
;
1043 /* XXX: Argh, recurse some more */
1044 return recpdoptlv_print(ndo
, pptr
, len
, op_msk
, indent
+1);
1049 ND_PRINT((ndo
, "%s", tstr
));
1054 genoptlv_print(netdissect_options
*ndo
,
1055 register const u_char
* pptr
, register u_int len
,
1056 uint16_t op_msk
, int indent
)
1058 const struct forces_tlv
*pdtlv
= (const struct forces_tlv
*)pptr
;
1062 char *ib
= indent_pr(indent
, 0);
1065 type
= EXTRACT_16BITS(&pdtlv
->type
);
1066 tll
= EXTRACT_16BITS(&pdtlv
->length
) - TLV_HDRL
;
1067 invtlv
= tlv_valid(pdtlv
, len
);
1068 ND_PRINT((ndo
, "genoptlvprint - %s TLV type 0x%x len %d\n",
1069 tok2str(ForCES_TLV
, NULL
, type
), type
, EXTRACT_16BITS(&pdtlv
->length
)));
1072 * At this point, tlv_valid() has ensured that the TLV
1073 * length is large enough but not too large (it doesn't
1074 * go past the end of the containing TLV).
1076 register const u_char
*dp
= (const u_char
*) TLV_DATA(pdtlv
);
1077 if (!ttlv_valid(type
)) {
1078 ND_PRINT((ndo
, "%s TLV type 0x%x len %d\n",
1079 tok2str(ForCES_TLV_err
, NULL
, invtlv
), type
,
1080 EXTRACT_16BITS(&pdtlv
->length
)));
1083 if (ndo
->ndo_vflag
>= 3)
1084 ND_PRINT((ndo
, "%s%s, length %d (data length %d Bytes)",
1085 ib
, tok2str(ForCES_TLV
, NULL
, type
),
1086 EXTRACT_16BITS(&pdtlv
->length
), tll
));
1088 return pdata_print(ndo
, dp
, tll
, op_msk
, indent
+ 1);
1090 ND_PRINT((ndo
, "\t\t\tInvalid ForCES TLV type=%x", type
));
1095 ND_PRINT((ndo
, "%s", tstr
));
1100 recpdoptlv_print(netdissect_options
*ndo
,
1101 register const u_char
* pptr
, register u_int len
,
1102 uint16_t op_msk
, int indent
)
1104 const struct forces_tlv
*pdtlv
= (const struct forces_tlv
*)pptr
;
1108 register const u_char
*dp
;
1113 invtlv
= tlv_valid(pdtlv
, len
);
1119 * At this point, tlv_valid() has ensured that the TLV
1120 * length is large enough but not too large (it doesn't
1121 * go past the end of the containing TLV).
1123 ib
= indent_pr(indent
, 0);
1124 type
= EXTRACT_16BITS(&pdtlv
->type
);
1125 dp
= (const u_char
*) TLV_DATA(pdtlv
);
1126 tll
= EXTRACT_16BITS(&pdtlv
->length
) - TLV_HDRL
;
1128 if (ndo
->ndo_vflag
>= 3)
1129 ND_PRINT((ndo
, "%s%s, length %d (data encapsulated %d Bytes)",
1130 ib
, tok2str(ForCES_TLV
, NULL
, type
),
1131 EXTRACT_16BITS(&pdtlv
->length
),
1132 EXTRACT_16BITS(&pdtlv
->length
) - TLV_HDRL
));
1134 if (pdata_print(ndo
, dp
, tll
, op_msk
, indent
+ 1) == -1)
1136 pdtlv
= GO_NXT_TLV(pdtlv
, len
);
1141 "\n\t\tMessy PATHDATA TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
1142 EXTRACT_16BITS(&pdtlv
->type
), len
- EXTRACT_16BITS(&pdtlv
->length
)));
1149 ND_PRINT((ndo
, "%s", tstr
));
1154 invoptlv_print(netdissect_options
*ndo
,
1155 register const u_char
* pptr
, register u_int len
,
1156 uint16_t op_msk _U_
, int indent
)
1158 char *ib
= indent_pr(indent
, 1);
1160 if (ndo
->ndo_vflag
>= 3) {
1161 ND_PRINT((ndo
, "%sData[", &ib
[1]));
1162 hex_print_with_offset(ndo
, ib
, pptr
, len
, 0);
1163 ND_PRINT((ndo
, "%s]\n", ib
));
1169 otlv_print(netdissect_options
*ndo
,
1170 const struct forces_tlv
*otlv
, uint16_t op_msk _U_
, int indent
)
1173 register const u_char
*dp
= (const u_char
*) TLV_DATA(otlv
);
1176 char *ib
= indent_pr(indent
, 0);
1177 const struct optlv_h
*ops
;
1180 * lfbselect_print() has ensured that EXTRACT_16BITS(&otlv->length)
1184 type
= EXTRACT_16BITS(&otlv
->type
);
1185 tll
= EXTRACT_16BITS(&otlv
->length
) - TLV_HDRL
;
1186 ops
= get_forces_optlv_h(type
);
1187 if (ndo
->ndo_vflag
>= 3) {
1188 ND_PRINT((ndo
, "%sOper TLV %s(0x%x) length %d\n", ib
, ops
->s
, type
,
1189 EXTRACT_16BITS(&otlv
->length
)));
1191 /* rest of ops must at least have 12B {pathinfo} */
1192 if (tll
< OP_MIN_SIZ
) {
1193 ND_PRINT((ndo
, "\t\tOper TLV %s(0x%x) length %d\n", ops
->s
, type
,
1194 EXTRACT_16BITS(&otlv
->length
)));
1195 ND_PRINT((ndo
, "\t\tTruncated data size %d minimum required %d\n", tll
,
1197 return invoptlv_print(ndo
, dp
, tll
, ops
->op_msk
, indent
);
1201 /* XXX - do anything with ops->flags? */
1203 rc
= ops
->print(ndo
, dp
, tll
, ops
->op_msk
, indent
+ 1);
1208 ND_PRINT((ndo
, "%s", tstr
));
1215 asttlv_print(netdissect_options
*ndo
,
1216 register const u_char
* pptr
, register u_int len
,
1217 uint16_t op_msk _U_
, int indent
)
1221 char *ib
= indent_pr(indent
, 0);
1224 * forces_type_print() has ensured that len (the TLV length)
1227 dlen
= len
- TLV_HDRL
;
1228 if (dlen
!= ASTDLN
) {
1229 ND_PRINT((ndo
, "illegal ASTresult-TLV: %d bytes!\n", dlen
));
1232 ND_TCHECK2(*pptr
, 4);
1233 rescode
= EXTRACT_32BITS(pptr
);
1234 if (rescode
> ASTMCD
) {
1235 ND_PRINT((ndo
, "illegal ASTresult result code: %d!\n", rescode
));
1239 if (ndo
->ndo_vflag
>= 3) {
1240 ND_PRINT((ndo
, "Teardown reason:\n%s", ib
));
1243 ND_PRINT((ndo
, "Normal Teardown"));
1246 ND_PRINT((ndo
, "Loss of Heartbeats"));
1249 ND_PRINT((ndo
, "Out of bandwidth"));
1252 ND_PRINT((ndo
, "Out of Memory"));
1255 ND_PRINT((ndo
, "Application Crash"));
1258 ND_PRINT((ndo
, "Unknown Teardown reason"));
1261 ND_PRINT((ndo
, "(%x)\n%s", rescode
, ib
));
1266 ND_PRINT((ndo
, "%s", tstr
));
1273 asrtlv_print(netdissect_options
*ndo
,
1274 register const u_char
* pptr
, register u_int len
,
1275 uint16_t op_msk _U_
, int indent
)
1279 char *ib
= indent_pr(indent
, 0);
1282 * forces_type_print() has ensured that len (the TLV length)
1285 dlen
= len
- TLV_HDRL
;
1286 if (dlen
!= ASRDLN
) { /* id, instance, oper tlv */
1287 ND_PRINT((ndo
, "illegal ASRresult-TLV: %d bytes!\n", dlen
));
1290 ND_TCHECK2(*pptr
, 4);
1291 rescode
= EXTRACT_32BITS(pptr
);
1293 if (rescode
> ASRMCD
) {
1294 ND_PRINT((ndo
, "illegal ASRresult result code: %d!\n", rescode
));
1298 if (ndo
->ndo_vflag
>= 3) {
1299 ND_PRINT((ndo
, "\n%s", ib
));
1302 ND_PRINT((ndo
, "Success "));
1305 ND_PRINT((ndo
, "FE ID invalid "));
1308 ND_PRINT((ndo
, "permission denied "));
1311 ND_PRINT((ndo
, "Unknown "));
1314 ND_PRINT((ndo
, "(%x)\n%s", rescode
, ib
));
1319 ND_PRINT((ndo
, "%s", tstr
));
1328 gentltlv_print(netdissect_options
*ndo
,
1329 register const u_char
* pptr _U_
, register u_int len
,
1330 uint16_t op_msk _U_
, int indent _U_
)
1332 u_int dlen
= len
- TLV_HDRL
;
1334 if (dlen
< 4) { /* at least 32 bits must exist */
1335 ND_PRINT((ndo
, "truncated TLV: %d bytes missing! ", 4 - dlen
));
1345 print_metailv(netdissect_options
*ndo
,
1346 register const u_char
* pptr
, uint16_t op_msk _U_
, int indent
)
1349 char *ib
= indent_pr(indent
, 0);
1350 /* XXX: check header length */
1351 const struct forces_ilv
*ilv
= (const struct forces_ilv
*)pptr
;
1354 * print_metatlv() has ensured that len (what remains in the
1357 rlen
= EXTRACT_32BITS(&ilv
->length
) - ILV_HDRL
;
1359 ND_PRINT((ndo
, "%sMetaID 0x%x length %d\n", ib
, EXTRACT_32BITS(&ilv
->type
),
1360 EXTRACT_32BITS(&ilv
->length
)));
1361 if (ndo
->ndo_vflag
>= 3) {
1362 hex_print_with_offset(ndo
, "\t\t[", ILV_DATA(ilv
), rlen
, 0);
1363 ND_PRINT((ndo
, " ]\n"));
1368 ND_PRINT((ndo
, "%s", tstr
));
1373 print_metatlv(netdissect_options
*ndo
,
1374 register const u_char
* pptr
, register u_int len
,
1375 uint16_t op_msk _U_
, int indent
)
1378 char *ib
= indent_pr(indent
, 0);
1380 const struct forces_ilv
*ilv
= (const struct forces_ilv
*)pptr
;
1384 * redirect_print() has ensured that len (what remains in the
1387 dlen
= len
- TLV_HDRL
;
1389 ND_PRINT((ndo
, "\n%s METADATA length %d \n", ib
, rlen
));
1392 invilv
= ilv_valid(ilv
, rlen
);
1398 * At this point, ilv_valid() has ensured that the ILV
1399 * length is large enough but not too large (it doesn't
1400 * go past the end of the containing TLV).
1402 print_metailv(ndo
, (const u_char
*) ilv
, 0, indent
+ 1);
1403 ilv
= GO_NXT_ILV(ilv
, rlen
);
1409 ND_PRINT((ndo
, "%s", tstr
));
1415 print_reddata(netdissect_options
*ndo
,
1416 register const u_char
* pptr
, register u_int len
,
1417 uint16_t op_msk _U_
, int indent _U_
)
1420 char *ib
= indent_pr(indent
, 0);
1423 dlen
= len
- TLV_HDRL
;
1425 ND_PRINT((ndo
, "\n%s Redirect Data length %d \n", ib
, rlen
));
1427 if (ndo
->ndo_vflag
>= 3) {
1428 ND_PRINT((ndo
, "\t\t["));
1429 hex_print_with_offset(ndo
, "\n\t\t", pptr
, rlen
, 0);
1430 ND_PRINT((ndo
, "\n\t\t]"));
1437 redirect_print(netdissect_options
*ndo
,
1438 register const u_char
* pptr
, register u_int len
,
1439 uint16_t op_msk _U_
, int indent
)
1441 const struct forces_tlv
*tlv
= (const struct forces_tlv
*)pptr
;
1447 * forces_type_print() has ensured that len (the TLV length)
1450 dlen
= len
- TLV_HDRL
;
1451 if (dlen
<= RD_MIN
) {
1452 ND_PRINT((ndo
, "\n\t\ttruncated Redirect TLV: %d bytes missing! ",
1461 invtlv
= tlv_valid(tlv
, rlen
);
1463 ND_PRINT((ndo
, "Bad Redirect data\n"));
1468 * At this point, tlv_valid() has ensured that the TLV
1469 * length is large enough but not too large (it doesn't
1470 * go past the end of the containing TLV).
1472 if (EXTRACT_16BITS(&tlv
->type
) == F_TLV_METD
) {
1473 print_metatlv(ndo
, (const u_char
*) TLV_DATA(tlv
),
1474 EXTRACT_16BITS(&tlv
->length
), 0, indent
);
1475 } else if ((EXTRACT_16BITS(&tlv
->type
) == F_TLV_REDD
)) {
1476 print_reddata(ndo
, (const u_char
*) TLV_DATA(tlv
),
1477 EXTRACT_16BITS(&tlv
->length
), 0, indent
);
1479 ND_PRINT((ndo
, "Unknown REDIRECT TLV 0x%x len %d\n",
1480 EXTRACT_16BITS(&tlv
->type
),
1481 EXTRACT_16BITS(&tlv
->length
)));
1484 tlv
= GO_NXT_TLV(tlv
, rlen
);
1489 "\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
1490 EXTRACT_16BITS(&tlv
->type
),
1491 rlen
- EXTRACT_16BITS(&tlv
->length
)));
1498 ND_PRINT((ndo
, "%s", tstr
));
1506 lfbselect_print(netdissect_options
*ndo
,
1507 register const u_char
* pptr
, register u_int len
,
1508 uint16_t op_msk
, int indent
)
1510 const struct forces_lfbsh
*lfbs
;
1511 const struct forces_tlv
*otlv
;
1512 char *ib
= indent_pr(indent
, 0);
1518 * forces_type_print() has ensured that len (the TLV length)
1521 dlen
= len
- TLV_HDRL
;
1522 if (dlen
<= OP_MIN
) { /* id, instance, oper tlv header .. */
1523 ND_PRINT((ndo
, "\n\t\ttruncated lfb selector: %d bytes missing! ",
1529 * At this point, we know that dlen > OP_MIN; OP_OFF < OP_MIN, so
1530 * we also know that it's > OP_OFF.
1532 rlen
= dlen
- OP_OFF
;
1534 lfbs
= (const struct forces_lfbsh
*)pptr
;
1536 if (ndo
->ndo_vflag
>= 3) {
1537 ND_PRINT((ndo
, "\n%s%s(Classid %x) instance %x\n",
1538 ib
, tok2str(ForCES_LFBs
, NULL
, EXTRACT_32BITS(&lfbs
->class)),
1539 EXTRACT_32BITS(&lfbs
->class),
1540 EXTRACT_32BITS(&lfbs
->instance
)));
1543 otlv
= (const struct forces_tlv
*)(lfbs
+ 1);
1548 invtlv
= tlv_valid(otlv
, rlen
);
1553 * At this point, tlv_valid() has ensured that the TLV
1554 * length is large enough but not too large (it doesn't
1555 * go past the end of the containing TLV).
1557 if (op_valid(EXTRACT_16BITS(&otlv
->type
), op_msk
)) {
1558 otlv_print(ndo
, otlv
, 0, indent
);
1560 if (ndo
->ndo_vflag
< 3)
1561 ND_PRINT((ndo
, "\n"));
1563 "\t\tINValid oper-TLV type 0x%x length %d for this ForCES message\n",
1564 EXTRACT_16BITS(&otlv
->type
), EXTRACT_16BITS(&otlv
->length
)));
1565 invoptlv_print(ndo
, (const u_char
*)otlv
, rlen
, 0, indent
);
1567 otlv
= GO_NXT_TLV(otlv
, rlen
);
1572 "\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
1573 EXTRACT_16BITS(&otlv
->type
), rlen
- EXTRACT_16BITS(&otlv
->length
)));
1580 ND_PRINT((ndo
, "%s", tstr
));
1585 forces_type_print(netdissect_options
*ndo
,
1586 register const u_char
* pptr
, const struct forcesh
*fhdr _U_
,
1587 register u_int mlen
, const struct tom_h
*tops
)
1589 const struct forces_tlv
*tltlv
;
1596 * forces_print() has already checked that mlen >= ForCES_HDRL
1597 * by calling ForCES_HLN_VALID().
1599 rlen
= mlen
- ForCES_HDRL
;
1601 if (rlen
> TLV_HLN
) {
1602 if (tops
->flags
& ZERO_TTLV
) {
1603 ND_PRINT((ndo
, "<0x%x>Illegal Top level TLV!\n", tops
->flags
));
1607 if (tops
->flags
& ZERO_MORE_TTLV
)
1609 if (tops
->flags
& ONE_MORE_TTLV
) {
1610 ND_PRINT((ndo
, "\tTop level TLV Data missing!\n"));
1615 if (tops
->flags
& ZERO_TTLV
) {
1619 ttlv
= tops
->flags
>> 4;
1620 tltlv
= GET_TOP_TLV(pptr
);
1622 /*XXX: 15 top level tlvs will probably be fine
1623 You are nuts if you send more ;-> */
1626 invtlv
= tlv_valid(tltlv
, rlen
);
1631 * At this point, tlv_valid() has ensured that the TLV
1632 * length is large enough but not too large (it doesn't
1633 * go past the end of the packet).
1635 if (!ttlv_valid(EXTRACT_16BITS(&tltlv
->type
))) {
1636 ND_PRINT((ndo
, "\n\tInvalid ForCES Top TLV type=0x%x",
1637 EXTRACT_16BITS(&tltlv
->type
)));
1641 if (ndo
->ndo_vflag
>= 3)
1642 ND_PRINT((ndo
, "\t%s, length %d (data length %d Bytes)",
1643 tok2str(ForCES_TLV
, NULL
, EXTRACT_16BITS(&tltlv
->type
)),
1644 EXTRACT_16BITS(&tltlv
->length
),
1645 EXTRACT_16BITS(&tltlv
->length
) - TLV_HDRL
));
1647 rc
= tops
->print(ndo
, (const u_char
*) TLV_DATA(tltlv
),
1648 EXTRACT_16BITS(&tltlv
->length
), tops
->op_msk
, 9);
1652 tltlv
= GO_NXT_TLV(tltlv
, rlen
);
1658 * XXX - if ttlv != 0, does that mean that the packet was too
1659 * short, and didn't have *enough* TLVs in it?
1662 ND_PRINT((ndo
, "\tMess TopTLV header: min %u, total %d advertised %d ",
1663 TLV_HDRL
, rlen
, EXTRACT_16BITS(&tltlv
->length
)));
1670 ND_PRINT((ndo
, "%s", tstr
));
1675 forces_print(netdissect_options
*ndo
,
1676 register const u_char
* pptr
, register u_int len
)
1678 const struct forcesh
*fhdr
;
1681 const struct tom_h
*tops
;
1684 fhdr
= (const struct forcesh
*)pptr
;
1686 if (!tom_valid(fhdr
->fm_tom
)) {
1687 ND_PRINT((ndo
, "Invalid ForCES message type %d\n", fhdr
->fm_tom
));
1691 mlen
= ForCES_BLN(fhdr
);
1693 tops
= get_forces_tom(fhdr
->fm_tom
);
1694 if (tops
->v
== TOM_RSVD
) {
1695 ND_PRINT((ndo
, "\n\tUnknown ForCES message type=0x%x", fhdr
->fm_tom
));
1699 ND_PRINT((ndo
, "\n\tForCES %s ", tops
->s
));
1700 if (!ForCES_HLN_VALID(mlen
, len
)) {
1702 "Illegal ForCES pkt len - min %u, total recvd %d, advertised %d ",
1703 ForCES_HDRL
, len
, ForCES_BLN(fhdr
)));
1707 ND_TCHECK2(*(pptr
+ 20), 4);
1708 flg_raw
= EXTRACT_32BITS(pptr
+ 20);
1709 if (ndo
->ndo_vflag
>= 1) {
1710 ND_PRINT((ndo
, "\n\tForCES Version %d len %uB flags 0x%08x ",
1711 ForCES_V(fhdr
), mlen
, flg_raw
));
1713 "\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%" PRIx64
,
1714 ForCES_SID(fhdr
), ForCES_node(ForCES_SID(fhdr
)),
1715 ForCES_DID(fhdr
), ForCES_node(ForCES_DID(fhdr
)),
1716 EXTRACT_64BITS(fhdr
->fm_cor
)));
1719 if (ndo
->ndo_vflag
>= 2) {
1721 "\n\tForCES flags:\n\t %s(0x%x), prio=%d, %s(0x%x),\n\t %s(0x%x), %s(0x%x)\n",
1722 tok2str(ForCES_ACKs
, "ACKUnknown", ForCES_ACK(fhdr
)),
1725 tok2str(ForCES_EMs
, "EMUnknown", ForCES_EM(fhdr
)),
1727 tok2str(ForCES_ATs
, "ATUnknown", ForCES_AT(fhdr
)),
1729 tok2str(ForCES_TPs
, "TPUnknown", ForCES_TP(fhdr
)),
1732 "\t Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n",
1733 ForCES_RS1(fhdr
), ForCES_RS2(fhdr
)));
1735 rc
= forces_type_print(ndo
, pptr
, fhdr
, mlen
, tops
);
1738 hex_print_with_offset(ndo
, "\n\t[", pptr
, len
, 0);
1739 ND_PRINT((ndo
, "\n\t]"));
1743 if (ndo
->ndo_vflag
>= 4) {
1744 ND_PRINT((ndo
, "\n\t Raw ForCES message\n\t ["));
1745 hex_print_with_offset(ndo
, "\n\t ", pptr
, len
, 0);
1746 ND_PRINT((ndo
, "\n\t ]"));
1748 ND_PRINT((ndo
, "\n"));
1752 ND_PRINT((ndo
, "%s", tstr
));
1756 * c-style: whitesmith