1214456Srpaulo/*
2214456Srpaulo * Copyright (c) 1982, 1986, 1993
3214456Srpaulo *	The Regents of the University of California.  All rights reserved.
4214456Srpaulo *
5214456Srpaulo * Redistribution and use in source and binary forms, with or without
6214456Srpaulo * modification, are permitted provided that the following conditions
7214456Srpaulo * are met:
8214456Srpaulo * 1. Redistributions of source code must retain the above copyright
9214456Srpaulo *    notice, this list of conditions and the following disclaimer.
10214456Srpaulo * 2. Redistributions in binary form must reproduce the above copyright
11214456Srpaulo *    notice, this list of conditions and the following disclaimer in the
12214456Srpaulo *    documentation and/or other materials provided with the distribution.
13214456Srpaulo * 3. All advertising materials mentioning features or use of this software
14214456Srpaulo *    must display the following acknowledgement:
15214456Srpaulo *	This product includes software developed by the University of
16214456Srpaulo *	California, Berkeley and its contributors.
17214456Srpaulo * 4. Neither the name of the University nor the names of its contributors
18214456Srpaulo *    may be used to endorse or promote products derived from this software
19214456Srpaulo *    without specific prior written permission.
20214456Srpaulo *
21214456Srpaulo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22214456Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23214456Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24214456Srpaulo * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25214456Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26214456Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27214456Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28214456Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29214456Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30214456Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31214456Srpaulo * SUCH DAMAGE.
32214456Srpaulo *
33214456Srpaulo * Copyright (c) 2009 Mojatatu Networks, Inc
34214456Srpaulo *
35214456Srpaulo */
36214456Srpaulo
37214456Srpaulo/*
38214456Srpaulo * Per draft-ietf-forces-protocol-22
39214456Srpaulo*/
40214456Srpaulo#define	ForCES_VERS	1
41214456Srpaulo#define	ForCES_HDRL	24
42214456Srpaulo#define	ForCES_ALNL	4U
43214456Srpaulo#define TLV_HDRL	4
44214456Srpaulo#define ILV_HDRL	8
45214456Srpaulo
46214456Srpaulo#define TOM_RSVD 	0x0
47214456Srpaulo#define TOM_ASSNSETUP 	0x1
48214456Srpaulo#define TOM_ASSNTEARD 	0x2
49214456Srpaulo#define TOM_CONFIG 	0x3
50214456Srpaulo#define TOM_QUERY 	0x4
51214456Srpaulo#define TOM_EVENTNOT 	0x5
52214456Srpaulo#define TOM_PKTREDIR 	0x6
53214456Srpaulo#define TOM_HEARTBT 	0x0F
54214456Srpaulo#define TOM_ASSNSETREP 	0x11
55214456Srpaulo#define TOM_CONFIGREP 	0x13
56214456Srpaulo#define TOM_QUERYREP 	0x14
57214456Srpaulo
58214456Srpaulo/*
59214456Srpaulo * tom_h Flags: resv1(8b):maxtlvs(4b):resv2(2b):mintlv(2b)
60214456Srpaulo*/
61214456Srpaulo#define ZERO_TTLV	0x01
62214456Srpaulo#define ZERO_MORE_TTLV	0x02
63214456Srpaulo#define ONE_MORE_TTLV	0x04
64214456Srpaulo#define ZERO_TLV	0x00
65214456Srpaulo#define ONE_TLV		0x10
66214456Srpaulo#define TWO_TLV		0x20
67214456Srpaulo#define MAX_TLV		0xF0
68214456Srpaulo
69214456Srpaulo#define TTLV_T1		(ONE_MORE_TTLV|ONE_TLV)
70214456Srpaulo#define TTLV_T2		(ONE_MORE_TTLV|MAX_TLV)
71214456Srpaulo
72214456Srpaulostruct tom_h {
73214456Srpaulo	u_int32_t v;
74214456Srpaulo	u_int16_t flags;
75214456Srpaulo	u_int16_t op_msk;
76214456Srpaulo	const char *s;
77214456Srpaulo	int (*print) (register const u_char * pptr, register u_int len,
78214456Srpaulo		      u_int16_t op_msk, int indent);
79214456Srpaulo};
80214456Srpaulo
81214456Srpauloenum {
82214456Srpaulo	TOM_RSV_I,
83214456Srpaulo	TOM_ASS_I,
84214456Srpaulo	TOM_AST_I,
85214456Srpaulo	TOM_CFG_I,
86214456Srpaulo	TOM_QRY_I,
87214456Srpaulo	TOM_EVN_I,
88214456Srpaulo	TOM_RED_I,
89214456Srpaulo	TOM_HBT_I,
90214456Srpaulo	TOM_ASR_I,
91214456Srpaulo	TOM_CNR_I,
92214456Srpaulo	TOM_QRR_I,
93214456Srpaulo	_TOM_RSV_MAX
94214456Srpaulo};
95214456Srpaulo#define TOM_MAX_IND (_TOM_RSV_MAX - 1)
96214456Srpaulo
97214456Srpauloint lfbselect_print(register const u_char * pptr, register u_int len,
98214456Srpaulo		    u_int16_t op_msk, int indent);
99214456Srpauloint redirect_print(register const u_char * pptr, register u_int len,
100214456Srpaulo		   u_int16_t op_msk, int indent);
101214456Srpauloint asrtlv_print(register const u_char * pptr, register u_int len,
102214456Srpaulo		 u_int16_t op_msk, int indent);
103214456Srpauloint asttlv_print(register const u_char * pptr, register u_int len,
104214456Srpaulo		 u_int16_t op_msk, int indent);
105214456Srpauloint gentltlv_print(register const u_char * pptr, register u_int len,
106214456Srpaulo		   u_int16_t op_msk, int indent);
107214456Srpauloint print_metailv(register const u_char * pptr, register u_int len,
108214456Srpaulo	      u_int16_t op_msk, int indent);
109214456Srpauloint print_metatlv(register const u_char * pptr, register u_int len,
110214456Srpaulo	      u_int16_t op_msk, int indent);
111214456Srpauloint print_reddata(register const u_char * pptr, register u_int len,
112214456Srpaulo	      u_int16_t op_msk, int indent);
113214456Srpaulo
114214456Srpaulostatic inline int tom_valid(u_int8_t tom)
115214456Srpaulo{
116214456Srpaulo	if (tom > 0) {
117214456Srpaulo		if (tom >= 0x7 && tom <= 0xe)
118214456Srpaulo			return 0;
119214456Srpaulo		if (tom == 0x10)
120214456Srpaulo			return 0;
121214456Srpaulo		if (tom > 0x14)
122214456Srpaulo			return 0;
123214456Srpaulo		return 1;
124214456Srpaulo	} else
125214456Srpaulo		return 0;
126214456Srpaulo}
127214456Srpaulo
128214456Srpaulostatic inline const char *ForCES_node(u_int32_t node)
129214456Srpaulo{
130214456Srpaulo	if (node <= 0x3FFFFFFF)
131214456Srpaulo		return "FE";
132214456Srpaulo	if (node >= 0x40000000 && node <= 0x7FFFFFFF)
133214456Srpaulo		return "CE";
134214456Srpaulo	if (node >= 0xC0000000 && node <= 0xFFFFFFEF)
135214456Srpaulo		return "AllMulticast";
136214456Srpaulo	if (node == 0xFFFFFFFD)
137214456Srpaulo		return "AllCEsBroadcast";
138214456Srpaulo	if (node == 0xFFFFFFFE)
139214456Srpaulo		return "AllFEsBroadcast";
140214456Srpaulo	if (node == 0xFFFFFFFF)
141214456Srpaulo		return "AllBroadcast";
142214456Srpaulo
143214456Srpaulo	return "ForCESreserved";
144214456Srpaulo
145214456Srpaulo}
146214456Srpaulo
147214456Srpaulostatic inline const char *ForCES_ACKp(u_int32_t flg)
148214456Srpaulo{
149214456Srpaulo	if (flg == 0x0)
150214456Srpaulo		return "NoACK";
151214456Srpaulo	if (flg == 0x1)
152214456Srpaulo		return "SuccessACK";
153214456Srpaulo	if (flg == 0x2)
154214456Srpaulo		return "FailureACK";
155214456Srpaulo	if (flg == 0x3)
156214456Srpaulo		return "AlwaysACK";
157214456Srpaulo	return "ACKUnknown";
158214456Srpaulo}
159214456Srpaulo
160214456Srpaulostatic inline const char *ForCES_EMp(u_int32_t flg)
161214456Srpaulo{
162214456Srpaulo	if (flg == 0x0)
163214456Srpaulo		return "EMReserved";
164214456Srpaulo	if (flg == 0x1)
165214456Srpaulo		return "execute-all-or-none";
166214456Srpaulo	if (flg == 0x2)
167214456Srpaulo		return "execute-until-failure";
168214456Srpaulo	if (flg == 0x3)
169214456Srpaulo		return "continue-execute-on-failure";
170214456Srpaulo	return "EMUnknown";
171214456Srpaulo}
172214456Srpaulo
173214456Srpaulostatic inline const char *ForCES_ATp(u_int32_t flg)
174214456Srpaulo{
175214456Srpaulo	if (flg == 0x0)
176214456Srpaulo		return "Standalone";
177214456Srpaulo	if (flg == 0x1)
178214456Srpaulo		return "2PCtransaction";
179214456Srpaulo	return "ATUnknown";
180214456Srpaulo}
181214456Srpaulo
182214456Srpaulostatic inline const char *ForCES_TPp(u_int32_t flg)
183214456Srpaulo{
184214456Srpaulo	if (flg == 0x0)
185214456Srpaulo		return "StartofTransaction";
186214456Srpaulo	if (flg == 0x1)
187214456Srpaulo		return "MiddleofTransaction";
188214456Srpaulo	if (flg == 0x2)
189214456Srpaulo		return "EndofTransaction";
190214456Srpaulo	if (flg == 0x3)
191214456Srpaulo		return "abort";
192214456Srpaulo	return "TPUnknown";
193214456Srpaulo}
194214456Srpaulo
195214456Srpaulo/*
196214456Srpaulo * Structure of forces header, naked of TLVs.
197214456Srpaulo */
198214456Srpaulostruct forcesh {
199214456Srpaulo	u_int8_t fm_vrsvd;	/* version and reserved */
200214456Srpaulo#define ForCES_V(forcesh)	((forcesh)->fm_vrsvd >> 4)
201214456Srpaulo	u_int8_t fm_tom;	/* type of message */
202214456Srpaulo	u_int16_t fm_len;	/* total length * 4 bytes */
203214456Srpaulo#define ForCES_BLN(forcesh)	((u_int32_t)(EXTRACT_16BITS(&(forcesh)->fm_len) << 2))
204214456Srpaulo	u_int32_t fm_sid;	/* Source ID */
205214456Srpaulo#define ForCES_SID(forcesh)	EXTRACT_32BITS(&(forcesh)->fm_sid)
206214456Srpaulo	u_int32_t fm_did;	/* Destination ID */
207214456Srpaulo#define ForCES_DID(forcesh)	EXTRACT_32BITS(&(forcesh)->fm_did)
208214456Srpaulo	u_int8_t fm_cor[8];	/* correlator */
209214456Srpaulo	u_int32_t fm_flags;	/* flags */
210214456Srpaulo#define ForCES_ACK(forcesh)	((EXTRACT_32BITS(&(forcesh)->fm_flags)&0xC0000000) >> 30)
211214456Srpaulo#define ForCES_PRI(forcesh)	((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x38000000) >> 27)
212214456Srpaulo#define ForCES_RS1(forcesh)	((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x07000000) >> 24)
213214456Srpaulo#define ForCES_EM(forcesh)	((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00C00000) >> 22)
214214456Srpaulo#define ForCES_AT(forcesh)	((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00200000) >> 21)
215214456Srpaulo#define ForCES_TP(forcesh)	((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00180000) >> 19)
216214456Srpaulo#define ForCES_RS2(forcesh)	((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x0007FFFF) >> 0)
217214456Srpaulo};
218214456Srpaulo
219214456Srpaulo#define ForCES_HLN_VALID(fhl,tlen) ((tlen) >= ForCES_HDRL && \
220214456Srpaulo				   (fhl) >= ForCES_HDRL && \
221214456Srpaulo				   (fhl) == (tlen))
222214456Srpaulo
223214456Srpaulo#define F_LFB_RSVD 0x0
224214456Srpaulo#define F_LFB_FEO 0x1
225214456Srpaulo#define F_LFB_FEPO 0x2
226214456Srpauloconst struct tok ForCES_LFBs[] = {
227214456Srpaulo	{F_LFB_RSVD, "Invalid TLV"},
228214456Srpaulo	{F_LFB_FEO, "FEObj LFB"},
229214456Srpaulo	{F_LFB_FEPO, "FEProtoObj LFB"},
230214456Srpaulo	{0, NULL}
231214456Srpaulo};
232214456Srpaulo
233214456Srpauloint forces_type_print(register const u_char * pptr, const struct forcesh *fhdr,
234214456Srpaulo		  register u_int mlen, const struct tom_h *tops);
235214456Srpaulo
236214456Srpauloenum {
237214456Srpaulo	F_OP_RSV,
238214456Srpaulo	F_OP_SET,
239214456Srpaulo	F_OP_SETPROP,
240214456Srpaulo	F_OP_SETRESP,
241214456Srpaulo	F_OP_SETPRESP,
242214456Srpaulo	F_OP_DEL,
243214456Srpaulo	F_OP_DELRESP,
244214456Srpaulo	F_OP_GET,
245214456Srpaulo	F_OP_GETPROP,
246214456Srpaulo	F_OP_GETRESP,
247214456Srpaulo	F_OP_GETPRESP,
248214456Srpaulo	F_OP_REPORT,
249214456Srpaulo	F_OP_COMMIT,
250214456Srpaulo	F_OP_RCOMMIT,
251214456Srpaulo	F_OP_RTRCOMP,
252214456Srpaulo	_F_OP_MAX
253214456Srpaulo};
254214456Srpaulo
255214456Srpaulo#define F_OP_MAX	(_F_OP_MAX - 1)
256214456Srpauloenum {
257214456Srpaulo	B_OP_SET = 1 << (F_OP_SET - 1),
258214456Srpaulo	B_OP_SETPROP = 1 << (F_OP_SETPROP - 1),
259214456Srpaulo	B_OP_SETRESP = 1 << (F_OP_SETRESP - 1),
260214456Srpaulo	B_OP_SETPRESP = 1 << (F_OP_SETPRESP - 1),
261214456Srpaulo	B_OP_DEL = 1 << (F_OP_DEL - 1),
262214456Srpaulo	B_OP_DELRESP = 1 << (F_OP_DELRESP - 1),
263214456Srpaulo	B_OP_GET = 1 << (F_OP_GET - 1),
264214456Srpaulo	B_OP_GETPROP = 1 << (F_OP_GETPROP - 1),
265214456Srpaulo	B_OP_GETRESP = 1 << (F_OP_GETRESP - 1),
266214456Srpaulo	B_OP_GETPRESP = 1 << (F_OP_GETPRESP - 1),
267214456Srpaulo	B_OP_REPORT = 1 << (F_OP_REPORT - 1),
268214456Srpaulo	B_OP_COMMIT = 1 << (F_OP_COMMIT - 1),
269214456Srpaulo	B_OP_RCOMMIT = 1 << (F_OP_RCOMMIT - 1),
270214456Srpaulo	B_OP_RTRCOMP = 1 << (F_OP_RTRCOMP - 1),
271214456Srpaulo};
272214456Srpaulo
273214456Srpaulostruct optlv_h {
274214456Srpaulo	u_int16_t flags;
275214456Srpaulo	u_int16_t op_msk;
276214456Srpaulo	const char *s;
277214456Srpaulo	int (*print) (register const u_char * pptr, register u_int len,
278214456Srpaulo		      u_int16_t op_msk, int indent);
279214456Srpaulo};
280214456Srpaulo
281214456Srpauloint genoptlv_print(register const u_char * pptr, register u_int len,
282214456Srpaulo		   u_int16_t op_msk, int indent);
283214456Srpauloint recpdoptlv_print(register const u_char * pptr, register u_int len,
284214456Srpaulo		     u_int16_t op_msk, int indent);
285214456Srpauloint invoptlv_print(register const u_char * pptr, register u_int len,
286214456Srpaulo		   u_int16_t op_msk, int indent);
287214456Srpaulo
288214456Srpaulo#define OP_MIN_SIZ 8
289214456Srpaulostruct pathdata_h {
290214456Srpaulo	u_int16_t pflags;
291214456Srpaulo	u_int16_t pIDcnt;
292214456Srpaulo};
293214456Srpaulo
294214456Srpaulo#define	B_FULLD		0x1
295214456Srpaulo#define	B_SPARD 	0x2
296214456Srpaulo#define B_RESTV		0x4
297214456Srpaulo#define B_KEYIN		0x8
298214456Srpaulo
299214456Srpaulostatic const struct optlv_h OPTLV_msg[F_OP_MAX + 1] = {
300214456Srpaulo	/* F_OP_RSV */ {ZERO_TTLV, 0, "Invalid OPTLV", invoptlv_print},
301214456Srpaulo	/* F_OP_SET */ {TTLV_T2, B_FULLD | B_SPARD, " Set", recpdoptlv_print},
302214456Srpaulo	/* F_OP_SETPROP */
303214456Srpaulo	    {TTLV_T2, B_FULLD | B_SPARD, " SetProp", recpdoptlv_print},
304214456Srpaulo	/* F_OP_SETRESP */ {TTLV_T2, B_RESTV, " SetResp", recpdoptlv_print},
305214456Srpaulo	/* F_OP_SETPRESP */ {TTLV_T2, B_RESTV, " SetPropResp", recpdoptlv_print},
306214456Srpaulo	/* F_OP_DEL */ {ZERO_TTLV, 0, " Del", recpdoptlv_print},
307214456Srpaulo	/* F_OP_DELRESP */ {TTLV_T2, B_RESTV, " DelResp", recpdoptlv_print},
308214456Srpaulo	/* F_OP_GET */ {ZERO_TTLV, 0, " Get", recpdoptlv_print},
309214456Srpaulo	/* F_OP_GETPROP */ {ZERO_TTLV, 0, " GetProp", recpdoptlv_print},
310214456Srpaulo	/* F_OP_GETRESP */
311241235Sdelphij	    {TTLV_T2, B_FULLD | B_SPARD | B_RESTV, " GetResp", recpdoptlv_print},
312214456Srpaulo	/* F_OP_GETPRESP */
313214456Srpaulo	    {TTLV_T2, B_FULLD | B_RESTV, " GetPropResp", recpdoptlv_print},
314214456Srpaulo	/* F_OP_REPORT */
315214456Srpaulo	    {TTLV_T2, B_FULLD | B_SPARD, " Report", recpdoptlv_print},
316214456Srpaulo	/* F_OP_COMMIT */ {ZERO_TTLV, 0, " Commit", NULL},
317214456Srpaulo	/* F_OP_RCOMMIT */ {TTLV_T1, B_RESTV, " RCommit", genoptlv_print},
318214456Srpaulo	/* F_OP_RTRCOMP */ {ZERO_TTLV, 0, " RTRCOMP", NULL},
319214456Srpaulo};
320214456Srpaulo
321214456Srpaulostatic inline const struct optlv_h *get_forces_optlv_h(u_int16_t opt)
322214456Srpaulo{
323214456Srpaulo	if (opt > F_OP_MAX || opt <= F_OP_RSV)
324214456Srpaulo		return &OPTLV_msg[F_OP_RSV];
325214456Srpaulo
326214456Srpaulo	return &OPTLV_msg[opt];
327214456Srpaulo}
328214456Srpaulo
329214456Srpaulo#define IND_SIZE 256
330214456Srpaulo#define IND_CHR ' '
331214456Srpaulo#define IND_PREF '\n'
332214456Srpaulo#define IND_SUF 0x0
333214456Srpaulochar ind_buf[IND_SIZE];
334214456Srpaulo
335214456Srpaulostatic inline char *indent_pr(int indent, int nlpref)
336214456Srpaulo{
337214456Srpaulo	int i = 0;
338214456Srpaulo	char *r = ind_buf;
339214456Srpaulo
340214456Srpaulo	if (indent > (IND_SIZE - 1))
341214456Srpaulo		indent = IND_SIZE - 1;
342214456Srpaulo
343214456Srpaulo	if (nlpref) {
344214456Srpaulo		r[i] = IND_PREF;
345214456Srpaulo		i++;
346214456Srpaulo		indent--;
347214456Srpaulo	}
348214456Srpaulo
349214456Srpaulo	while (--indent >= 0)
350214456Srpaulo		r[i++] = IND_CHR;
351214456Srpaulo
352214456Srpaulo	r[i] = IND_SUF;
353214456Srpaulo	return r;
354214456Srpaulo}
355214456Srpaulo
356214456Srpaulostatic inline int op_valid(u_int16_t op, u_int16_t mask)
357214456Srpaulo{
358214456Srpaulo	int opb = 1 << (op - 1);
359214456Srpaulo
360214456Srpaulo	if (op == 0)
361214456Srpaulo		return 0;
362214456Srpaulo	if (opb & mask)
363214456Srpaulo		return 1;
364214456Srpaulo	/* I guess we should allow vendor operations? */
365214456Srpaulo	if (op >= 0x8000)
366214456Srpaulo		return 1;
367214456Srpaulo	return 0;
368214456Srpaulo}
369214456Srpaulo
370214456Srpaulo#define F_TLV_RSVD	0x0000
371214456Srpaulo#define F_TLV_REDR	0x0001
372214456Srpaulo#define F_TLV_ASRS	0x0010
373214456Srpaulo#define F_TLV_ASRT	0x0011
374214456Srpaulo#define F_TLV_LFBS	0x1000
375214456Srpaulo#define F_TLV_PDAT	0x0110
376214456Srpaulo#define F_TLV_KEYI	0x0111
377214456Srpaulo#define F_TLV_FULD	0x0112
378214456Srpaulo#define F_TLV_SPAD	0x0113
379214456Srpaulo#define F_TLV_REST	0x0114
380214456Srpaulo#define F_TLV_METD	0x0115
381214456Srpaulo#define F_TLV_REDD	0x0116
382214456Srpaulo#define F_TLV_VNST	0x8000
383214456Srpaulo
384214456Srpaulostatic const struct tok ForCES_TLV[] = {
385214456Srpaulo	{F_TLV_RSVD, "Invalid TLV"},
386214456Srpaulo	{F_TLV_REDR, "REDIRECT TLV"},
387214456Srpaulo	{F_TLV_ASRS, "ASResult TLV"},
388214456Srpaulo	{F_TLV_ASRT, "ASTreason TLV"},
389214456Srpaulo	{F_TLV_LFBS, "LFBselect TLV"},
390214456Srpaulo	{F_TLV_PDAT, "PATH-DATA TLV"},
391214456Srpaulo	{F_TLV_KEYI, "KEYINFO TLV"},
392214456Srpaulo	{F_TLV_FULD, "FULLDATA TLV"},
393214456Srpaulo	{F_TLV_SPAD, "SPARSEDATA TLV"},
394214456Srpaulo	{F_TLV_REST, "RESULT TLV"},
395214456Srpaulo	{F_TLV_METD, "METADATA TLV"},
396214456Srpaulo	{F_TLV_REDD, "REDIRECTDATA TLV"},
397214456Srpaulo	{0, NULL}
398214456Srpaulo};
399214456Srpaulo
400214456Srpaulo#define TLV_HLN	4
401214456Srpaulostatic inline int ttlv_valid(u_int16_t ttlv)
402214456Srpaulo{
403214456Srpaulo	if (ttlv > 0) {
404214456Srpaulo		if (ttlv == 1 || ttlv == 0x1000)
405214456Srpaulo			return 1;
406214456Srpaulo		if (ttlv >= 0x10 && ttlv <= 0x11)
407214456Srpaulo			return 1;
408214456Srpaulo		if (ttlv >= 0x110 && ttlv <= 0x116)
409214456Srpaulo			return 1;
410214456Srpaulo		if (ttlv >= 0x8000)
411214456Srpaulo			return 0;	/* XXX: */
412214456Srpaulo	}
413214456Srpaulo
414214456Srpaulo	return 0;
415214456Srpaulo}
416214456Srpaulo
417214456Srpaulostruct forces_ilv {
418214456Srpaulo	u_int32_t type;
419214456Srpaulo	u_int32_t length;
420214456Srpaulo};
421214456Srpaulo
422214456Srpaulostruct forces_tlv {
423214456Srpaulo	u_int16_t type;
424214456Srpaulo	u_int16_t length;
425214456Srpaulo};
426214456Srpaulo
427214456Srpauloint otlv_print(const struct forces_tlv *otlv, u_int16_t op_msk, int indent);
428214456Srpaulo
429214456Srpaulo#define F_ALN_LEN(len) ( ((len)+ForCES_ALNL-1) & ~(ForCES_ALNL-1) )
430214456Srpaulo#define	GET_TOP_TLV(fhdr) ((struct forces_tlv *)((fhdr) + sizeof (struct forcesh)))
431214456Srpaulo#define TLV_SET_LEN(len)  (F_ALN_LEN(TLV_HDRL) + (len))
432214456Srpaulo#define TLV_ALN_LEN(len)  F_ALN_LEN(TLV_SET_LEN(len))
433214456Srpaulo#define TLV_RDAT_LEN(tlv) ((int)(EXTRACT_16BITS(&(tlv)->length) - TLV_SET_LEN(0))
434214456Srpaulo#define TLV_DATA(tlvp)   ((void*)(((char*)(tlvp)) + TLV_SET_LEN(0)))
435214456Srpaulo#define GO_NXT_TLV(tlv,rlen) ((rlen) -= F_ALN_LEN(EXTRACT_16BITS(&(tlv)->length)), \
436214456Srpaulo		              (struct forces_tlv*)(((char*)(tlv)) \
437214456Srpaulo				      + F_ALN_LEN(EXTRACT_16BITS(&(tlv)->length))))
438214456Srpaulo#define ILV_SET_LEN(len)  (F_ALN_LEN(ILV_HDRL) + (len))
439214456Srpaulo#define ILV_ALN_LEN(len)  F_ALN_LEN(ILV_SET_LEN(len))
440214456Srpaulo#define ILV_RDAT_LEN(ilv) ((int)(EXTRACT_32BITS(&(ilv)->length)) - ILV_SET_LEN(0))
441214456Srpaulo#define ILV_DATA(ilvp)   ((void*)(((char*)(ilvp)) + ILV_SET_LEN(0)))
442214456Srpaulo#define GO_NXT_ILV(ilv,rlen) ((rlen) -= F_ALN_LEN(EXTRACT_32BITS(&(ilv)->length)), \
443214456Srpaulo		              (struct forces_ilv *)(((char*)(ilv)) \
444214456Srpaulo				      + F_ALN_LEN(EXTRACT_32BITS(&(ilv)->length))))
445214456Srpaulo#define INVALID_RLEN -1
446214456Srpaulo#define INVALID_STLN -2
447214456Srpaulo#define INVALID_LTLN -3
448214456Srpaulo#define INVALID_ALEN -4
449214456Srpaulo
450214456Srpaulostatic const struct tok ForCES_TLV_err[] = {
451214456Srpaulo	{INVALID_RLEN, "Invalid total length"},
452214456Srpaulo	{INVALID_STLN, "xLV too short"},
453214456Srpaulo	{INVALID_LTLN, "xLV too long"},
454214456Srpaulo	{INVALID_ALEN, "data padding missing"},
455214456Srpaulo	{0, NULL}
456214456Srpaulo};
457214456Srpaulo
458214456Srpaulostatic inline int tlv_valid(const struct forces_tlv *tlv, u_int rlen)
459214456Srpaulo{
460214456Srpaulo	if (rlen < TLV_HDRL)
461214456Srpaulo		return INVALID_RLEN;
462214456Srpaulo	if (EXTRACT_16BITS(&tlv->length) < TLV_HDRL)
463214456Srpaulo		return INVALID_STLN;
464214456Srpaulo	if (EXTRACT_16BITS(&tlv->length) > rlen)
465214456Srpaulo		return INVALID_LTLN;
466214456Srpaulo	if (rlen < F_ALN_LEN(EXTRACT_16BITS(&tlv->length)))
467214456Srpaulo		return INVALID_ALEN;
468214456Srpaulo
469214456Srpaulo	return 0;
470214456Srpaulo}
471214456Srpaulo
472214456Srpaulostatic inline int ilv_valid(const struct forces_ilv *ilv, u_int rlen)
473214456Srpaulo{
474214456Srpaulo	if (rlen < ILV_HDRL)
475214456Srpaulo		return INVALID_RLEN;
476214456Srpaulo	if (EXTRACT_32BITS(&ilv->length) < ILV_HDRL)
477214456Srpaulo		return INVALID_STLN;
478214456Srpaulo	if (EXTRACT_32BITS(&ilv->length) > rlen)
479214456Srpaulo		return INVALID_LTLN;
480214456Srpaulo	if (rlen < F_ALN_LEN(EXTRACT_32BITS(&ilv->length)))
481214456Srpaulo		return INVALID_ALEN;
482214456Srpaulo
483214456Srpaulo	return 0;
484214456Srpaulo}
485214456Srpaulo
486214456Srpaulostruct forces_lfbsh {
487214456Srpaulo	u_int32_t class;
488214456Srpaulo	u_int32_t instance;
489214456Srpaulo};
490214456Srpaulo
491214456Srpaulo#define ASSNS_OPS (B_OP_REPORT)
492214456Srpaulo#define CFG_OPS	(B_OP_SET|B_OP_SETPROP|B_OP_DEL|B_OP_COMMIT|B_OP_RTRCOMP)
493214456Srpaulo#define CFG_ROPS (B_OP_SETRESP|B_OP_SETPRESP|B_OP_DELRESP|B_OP_RCOMMIT)
494214456Srpaulo#define CFG_QY (B_OP_GET|B_OP_GETPROP)
495214456Srpaulo#define CFG_QYR (B_OP_GETRESP|B_OP_GETPRESP)
496214456Srpaulo#define CFG_EVN (B_OP_REPORT)
497214456Srpaulo
498214456Srpaulostatic const struct tom_h ForCES_msg[TOM_MAX_IND + 1] = {
499214456Srpaulo	/* TOM_RSV_I */ {TOM_RSVD, ZERO_TTLV, 0, "Invalid message", NULL},
500214456Srpaulo	/* TOM_ASS_I */ {TOM_ASSNSETUP, ZERO_MORE_TTLV | TWO_TLV, ASSNS_OPS,
501214456Srpaulo		       "Association Setup", lfbselect_print},
502214456Srpaulo	/* TOM_AST_I */
503214456Srpaulo	    {TOM_ASSNTEARD, TTLV_T1, 0, "Association TearDown", asttlv_print},
504214456Srpaulo	/* TOM_CFG_I */ {TOM_CONFIG, TTLV_T2, CFG_OPS, "Config", lfbselect_print},
505214456Srpaulo	/* TOM_QRY_I */ {TOM_QUERY, TTLV_T2, CFG_QY, "Query", lfbselect_print},
506214456Srpaulo	/* TOM_EVN_I */ {TOM_EVENTNOT, TTLV_T1, CFG_EVN, "Event Notification",
507214456Srpaulo		       lfbselect_print},
508214456Srpaulo	/* TOM_RED_I */
509214456Srpaulo	    {TOM_PKTREDIR, TTLV_T2, 0, "Packet Redirect", redirect_print},
510214456Srpaulo	/* TOM_HBT_I */ {TOM_HEARTBT, ZERO_TTLV, 0, "HeartBeat", NULL},
511214456Srpaulo	/* TOM_ASR_I */
512214456Srpaulo	    {TOM_ASSNSETREP, TTLV_T1, 0, "Association Response", asrtlv_print},
513214456Srpaulo	/* TOM_CNR_I */ {TOM_CONFIGREP, TTLV_T2, CFG_ROPS, "Config Response",
514214456Srpaulo		       lfbselect_print},
515214456Srpaulo	/* TOM_QRR_I */
516214456Srpaulo	    {TOM_QUERYREP, TTLV_T2, CFG_QYR, "Query Response", lfbselect_print},
517214456Srpaulo};
518214456Srpaulo
519214456Srpaulostatic inline const struct tom_h *get_forces_tom(u_int8_t tom)
520214456Srpaulo{
521214456Srpaulo	int i;
522214456Srpaulo	for (i = TOM_RSV_I; i <= TOM_MAX_IND; i++) {
523214456Srpaulo		const struct tom_h *th = &ForCES_msg[i];
524214456Srpaulo		if (th->v == tom)
525214456Srpaulo			return th;
526214456Srpaulo	}
527214456Srpaulo	return &ForCES_msg[TOM_RSV_I];
528214456Srpaulo}
529214456Srpaulo
530214456Srpaulostruct pdata_ops {
531214456Srpaulo	u_int32_t v;
532214456Srpaulo	u_int16_t flags;
533214456Srpaulo	u_int16_t op_msk;
534214456Srpaulo	const char *s;
535214456Srpaulo	int (*print) (register const u_char * pptr, register u_int len,
536214456Srpaulo		      u_int16_t op_msk, int indent);
537214456Srpaulo};
538214456Srpaulo
539214456Srpauloenum {
540214456Srpaulo	PD_RSV_I,
541214456Srpaulo	PD_SEL_I,
542214456Srpaulo	PD_FDT_I,
543214456Srpaulo	PD_SDT_I,
544214456Srpaulo	PD_RES_I,
545214456Srpaulo	PD_PDT_I,
546214456Srpaulo	_PD_RSV_MAX
547214456Srpaulo};
548214456Srpaulo#define PD_MAX_IND (_TOM_RSV_MAX - 1)
549214456Srpaulo
550214456Srpaulostatic inline int pd_valid(u_int16_t pd)
551214456Srpaulo{
552214456Srpaulo	if (pd >= F_TLV_PDAT && pd <= F_TLV_REST)
553214456Srpaulo		return 1;
554214456Srpaulo	return 0;
555214456Srpaulo}
556214456Srpaulo
557214456Srpaulostatic inline void chk_op_type(u_int16_t type, u_int16_t msk, u_int16_t omsk)
558214456Srpaulo{
559214456Srpaulo	if (type != F_TLV_PDAT) {
560214456Srpaulo		if (msk & B_KEYIN) {
561214456Srpaulo			if (type != F_TLV_KEYI) {
562214456Srpaulo				printf
563214456Srpaulo				    ("Based on flags expected KEYINFO TLV!\n");
564214456Srpaulo			}
565214456Srpaulo		} else {
566214456Srpaulo			if (!(msk & omsk)) {
567214456Srpaulo				printf
568214456Srpaulo				    ("Illegal DATA encoding for type 0x%x programmed %x got %x \n",
569214456Srpaulo				     type, omsk, msk);
570214456Srpaulo			}
571214456Srpaulo		}
572214456Srpaulo	}
573214456Srpaulo
574214456Srpaulo}
575214456Srpaulo
576214456Srpauloint fdatatlv_print(register const u_char * pptr, register u_int len,
577214456Srpaulo		   u_int16_t op_msk, int indent);
578214456Srpauloint sdatailv_print(register const u_char * pptr, register u_int len,
579214456Srpaulo	       u_int16_t op_msk, int indent);
580214456Srpauloint sdatatlv_print(register const u_char * pptr, register u_int len,
581214456Srpaulo		   u_int16_t op_msk, int indent);
582214456Srpauloint pdatatlv_print(register const u_char * pptr, register u_int len,
583214456Srpaulo		   u_int16_t op_msk, int indent);
584214456Srpauloint pkeyitlv_print(register const u_char * pptr, register u_int len,
585214456Srpaulo		   u_int16_t op_msk, int indent);
586214456Srpaulo
587214456Srpauloint pdatacnt_print(register const u_char * pptr, register u_int len,
588235530Sdelphij	       u_int16_t IDcnt, u_int16_t op_msk, int indent);
589214456Srpauloint pdata_print(register const u_char * pptr, register u_int len,
590214456Srpaulo	    u_int16_t op_msk, int indent);
591214456Srpaulo
592214456Srpauloint prestlv_print(register const u_char * pptr, register u_int len,
593214456Srpaulo		  u_int16_t op_msk, int indent);
594214456Srpaulo#define F_SELKEY 1
595214456Srpaulo
596214456Srpaulostruct res_val {
597214456Srpaulo	u_int8_t result;
598214456Srpaulo	u_int8_t resv1;
599214456Srpaulo	u_int16_t resv2;
600214456Srpaulo};
601214456Srpaulo
602214456Srpaulostatic const struct pdata_ops ForCES_pdata[PD_MAX_IND + 1] = {
603214456Srpaulo	/* PD_RSV_I */ {0, 0, 0, "Invalid message", NULL},
604214456Srpaulo	/* PD_SEL_I */ {F_TLV_KEYI, 0, 0, "KEYINFO TLV", pkeyitlv_print},
605214456Srpaulo	/* PD_FDT_I */ {F_TLV_FULD, 0, B_FULLD, "FULLDATA TLV", fdatatlv_print},
606214456Srpaulo	/* PD_SDT_I */ {F_TLV_SPAD, 0, B_SPARD, "SPARSEDATA TLV", sdatatlv_print},
607214456Srpaulo	/* PD_RES_I */ {F_TLV_REST, 0, B_RESTV, "RESULT TLV", prestlv_print},
608214456Srpaulo	/* PD_PDT_I */
609214456Srpaulo	    {F_TLV_PDAT, 0, 0, "Inner PATH-DATA TLV", recpdoptlv_print},
610214456Srpaulo};
611214456Srpaulo
612214456Srpaulostatic inline const struct pdata_ops *get_forces_pd(u_int16_t pd)
613214456Srpaulo{
614214456Srpaulo	int i;
615214456Srpaulo	for (i = PD_RSV_I + 1; i <= PD_MAX_IND; i++) {
616214456Srpaulo		const struct pdata_ops *pdo = &ForCES_pdata[i];
617214456Srpaulo		if (pdo->v == pd)
618214456Srpaulo			return pdo;
619214456Srpaulo	}
620214456Srpaulo	return &ForCES_pdata[TOM_RSV_I];
621214456Srpaulo}
622214456Srpaulo
623214456Srpauloenum {
624214456Srpaulo	E_SUCCESS,
625214456Srpaulo	E_INVALID_HEADER,
626214456Srpaulo	E_LENGTH_MISMATCH,
627214456Srpaulo	E_VERSION_MISMATCH,
628214456Srpaulo	E_INVALID_DESTINATION_PID,
629214456Srpaulo	E_LFB_UNKNOWN,
630214456Srpaulo	E_LFB_NOT_FOUND,
631214456Srpaulo	E_LFB_INSTANCE_ID_NOT_FOUND,
632214456Srpaulo	E_INVALID_PATH,
633214456Srpaulo	E_COMPONENT_DOES_NOT_EXIST,
634214456Srpaulo	E_EXISTS,
635214456Srpaulo	E_NOT_FOUND,
636214456Srpaulo	E_READ_ONLY,
637214456Srpaulo	E_INVALID_ARRAY_CREATION,
638214456Srpaulo	E_VALUE_OUT_OF_RANGE,
639214456Srpaulo	E_CONTENTS_TOO_LONG,
640214456Srpaulo	E_INVALID_PARAMETERS,
641214456Srpaulo	E_INVALID_MESSAGE_TYPE,
642214456Srpaulo	E_INVALID_FLAGS,
643214456Srpaulo	E_INVALID_TLV,
644214456Srpaulo	E_EVENT_ERROR,
645214456Srpaulo	E_NOT_SUPPORTED,
646214456Srpaulo	E_MEMORY_ERROR,
647214456Srpaulo	E_INTERNAL_ERROR,
648214456Srpaulo	/* 0x18-0xFE are reserved .. */
649214456Srpaulo	E_UNSPECIFIED_ERROR = 0XFF
650214456Srpaulo};
651214456Srpaulo
652214456Srpauloconst struct tok ForCES_errs[] = {
653214456Srpaulo	{E_SUCCESS, "SUCCESS"},
654214456Srpaulo	{E_INVALID_HEADER, "INVALID HEADER"},
655214456Srpaulo	{E_LENGTH_MISMATCH, "LENGTH MISMATCH"},
656214456Srpaulo	{E_VERSION_MISMATCH, "VERSION MISMATCH"},
657214456Srpaulo	{E_INVALID_DESTINATION_PID, "INVALID DESTINATION PID"},
658214456Srpaulo	{E_LFB_UNKNOWN, "LFB UNKNOWN"},
659214456Srpaulo	{E_LFB_NOT_FOUND, "LFB NOT FOUND"},
660214456Srpaulo	{E_LFB_INSTANCE_ID_NOT_FOUND, "LFB INSTANCE ID NOT FOUND"},
661214456Srpaulo	{E_INVALID_PATH, "INVALID PATH"},
662214456Srpaulo	{E_COMPONENT_DOES_NOT_EXIST, "COMPONENT DOES NOT EXIST"},
663214456Srpaulo	{E_EXISTS, "EXISTS ALREADY"},
664214456Srpaulo	{E_NOT_FOUND, "NOT FOUND"},
665214456Srpaulo	{E_READ_ONLY, "READ ONLY"},
666214456Srpaulo	{E_INVALID_ARRAY_CREATION, "INVALID ARRAY CREATION"},
667214456Srpaulo	{E_VALUE_OUT_OF_RANGE, "VALUE OUT OF RANGE"},
668214456Srpaulo	{E_CONTENTS_TOO_LONG, "CONTENTS TOO LONG"},
669214456Srpaulo	{E_INVALID_PARAMETERS, "INVALID PARAMETERS"},
670214456Srpaulo	{E_INVALID_MESSAGE_TYPE, "INVALID MESSAGE TYPE"},
671214456Srpaulo	{E_INVALID_FLAGS, "INVALID FLAGS"},
672214456Srpaulo	{E_INVALID_TLV, "INVALID TLV"},
673214456Srpaulo	{E_EVENT_ERROR, "EVENT ERROR"},
674214456Srpaulo	{E_NOT_SUPPORTED, "NOT SUPPORTED"},
675214456Srpaulo	{E_MEMORY_ERROR, "MEMORY ERROR"},
676214456Srpaulo	{E_INTERNAL_ERROR, "INTERNAL ERROR"},
677214456Srpaulo	{E_UNSPECIFIED_ERROR, "UNSPECIFIED ERROR"},
678214456Srpaulo	{0, NULL}
679214456Srpaulo};
680