]> The Tcpdump Group git mirrors - tcpdump/blob - print-forces.c
Add support for getting table ranges Fixup get by key formatting while at it
[tcpdump] / print-forces.c
1 /*
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.
12 *
13 * Copyright (c) 2009 Mojatatu Networks, Inc
14 *
15 */
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <tcpdump-stdinc.h>
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include "interface.h"
27 #include "extract.h"
28
29 #include "forces.h"
30
31 #define RESLEN 4
32
33 int
34 prestlv_print(register const u_char * pptr, register u_int len,
35 u_int16_t op_msk _U_, int indent)
36 {
37 const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
38 register const u_char *tdp = (u_char *) TLV_DATA(tlv);
39 struct res_val *r = (struct res_val *)tdp;
40 u_int dlen;
41
42 /*
43 * pdatacnt_print() has ensured that len (the TLV length)
44 * >= TLV_HDRL.
45 */
46 dlen = len - TLV_HDRL;
47 if (dlen != RESLEN) {
48 printf("illegal RESULT-TLV: %d bytes!\n", dlen);
49 return -1;
50 }
51
52 TCHECK(*r);
53 if (r->result >= 0x18 && r->result <= 0xFE) {
54 printf("illegal reserved result code: 0x%x!\n", r->result);
55 return -1;
56 }
57
58 if (vflag >= 3) {
59 char *ib = indent_pr(indent, 0);
60 printf("%s Result: %s (code 0x%x)\n", ib,
61 tok2str(ForCES_errs, NULL, r->result), r->result);
62 }
63 return 0;
64
65 trunc:
66 fputs("[|forces]", stdout);
67 return -1;
68 }
69
70 int
71 fdatatlv_print(register const u_char * pptr, register u_int len,
72 u_int16_t op_msk _U_, int indent)
73 {
74 const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
75 u_int rlen;
76 register const u_char *tdp = (u_char *) TLV_DATA(tlv);
77 u_int16_t type;
78
79 /*
80 * pdatacnt_print() or pkeyitlv_print() has ensured that len
81 * (the TLV length) >= TLV_HDRL.
82 */
83 rlen = len - TLV_HDRL;
84 TCHECK(*tlv);
85 type = EXTRACT_16BITS(&tlv->type);
86 if (type != F_TLV_FULD) {
87 printf("Error: expecting FULLDATA!\n");
88 return -1;
89 }
90
91 if (vflag >= 3) {
92 char *ib = indent_pr(indent + 2, 1);
93 printf("%s[", &ib[1]);
94 hex_print_with_offset(ib, tdp, rlen, 0);
95 printf("\n%s]\n", &ib[1]);
96 }
97 return 0;
98
99 trunc:
100 fputs("[|forces]", stdout);
101 return -1;
102 }
103
104 int
105 sdatailv_print(register const u_char * pptr, register u_int len,
106 u_int16_t op_msk _U_, int indent)
107 {
108 u_int rlen;
109 const struct forces_ilv *ilv = (struct forces_ilv *)pptr;
110 int invilv;
111
112 if (len < ILV_HDRL) {
113 printf("Error: BAD SPARSEDATA-TLV!\n");
114 return -1;
115 }
116 rlen = len;
117 indent += 1;
118 while (rlen != 0) {
119 //printf("Jamal - outstanding length <%d>\n", rlen);
120 char *ib = indent_pr(indent, 1);
121 register const u_char *tdp = (u_char *) ILV_DATA(ilv);
122 TCHECK(*ilv);
123 invilv = ilv_valid(ilv, rlen);
124 if (invilv) {
125 printf("%s[", &ib[1]);
126 hex_print_with_offset(ib, tdp, rlen, 0);
127 printf("\n%s]\n", &ib[1]);
128 return -1;
129 }
130 if (vflag >= 3) {
131 int ilvl = EXTRACT_32BITS(&ilv->length);
132 printf("\n%s ILV: type %x length %d\n", &ib[1],
133 EXTRACT_32BITS(&ilv->type), ilvl);
134 hex_print_with_offset("\t\t[", tdp, ilvl-ILV_HDRL, 0);
135 }
136
137 ilv = GO_NXT_ILV(ilv, rlen);
138 }
139
140 return 0;
141
142 trunc:
143 fputs("[|forces]", stdout);
144 return -1;
145 }
146
147 int
148 sdatatlv_print(register const u_char * pptr, register u_int len,
149 u_int16_t op_msk, int indent)
150 {
151 const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
152 u_int rlen;
153 register const u_char *tdp = (u_char *) TLV_DATA(tlv);
154 u_int16_t type;
155
156 /*
157 * pdatacnt_print() has ensured that len (the TLV length)
158 * >= TLV_HDRL.
159 */
160 rlen = len - TLV_HDRL;
161 TCHECK(*tlv);
162 type = EXTRACT_16BITS(&tlv->type);
163 if (type != F_TLV_SPAD) {
164 printf("Error: expecting SPARSEDATA!\n");
165 return -1;
166 }
167
168 return sdatailv_print(tdp, rlen, op_msk, indent);
169
170 trunc:
171 fputs("[|forces]", stdout);
172 return -1;
173 }
174
175 int
176 pkeyitlv_print(register const u_char * pptr, register u_int len,
177 u_int16_t op_msk, int indent)
178 {
179 const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
180 register const u_char *tdp = (u_char *) TLV_DATA(tlv);
181 register const u_char *dp = tdp + 4;
182 const struct forces_tlv *kdtlv = (struct forces_tlv *)dp;
183 u_int32_t id;
184 char *ib = indent_pr(indent, 0);
185 u_int16_t type, tll;
186 int invtlv;
187
188 TCHECK(*tdp);
189 id = EXTRACT_32BITS(tdp);
190 printf("%sKeyinfo: Key 0x%x\n", ib, id);
191 TCHECK(*kdtlv);
192 type = EXTRACT_16BITS(&kdtlv->type);
193 invtlv = tlv_valid(kdtlv, len);
194
195 if (invtlv) {
196 printf("%s TLV type 0x%x len %d\n",
197 tok2str(ForCES_TLV_err, NULL, invtlv), type,
198 EXTRACT_16BITS(&kdtlv->length));
199 return -1;
200 }
201 /*
202 * At this point, tlv_valid() has ensured that the TLV
203 * length is large enough but not too large (it doesn't
204 * go past the end of the containing TLV).
205 */
206 tll = EXTRACT_16BITS(&kdtlv->length);
207 dp = (u_char *) TLV_DATA(kdtlv);
208 return fdatatlv_print(dp, tll, op_msk, indent);
209
210 trunc:
211 fputs("[|forces]", stdout);
212 return -1;
213 }
214
215 #define PTH_DESC_SIZE 12
216
217 int
218 pdatacnt_print(register const u_char * pptr, register u_int len,
219 u_int16_t IDcnt, u_int16_t op_msk, int indent)
220 {
221 u_int i;
222 u_int32_t id;
223 char *ib = indent_pr(indent, 0);
224
225 for (i = 0; i < IDcnt; i++) {
226 TCHECK2(*pptr, 4);
227 if (len < 4)
228 goto trunc;
229 id = EXTRACT_32BITS(pptr);
230 if (vflag >= 3)
231 printf("%sID#%02u: %d\n", ib, i + 1, id);
232 len -= 4;
233 pptr += 4;
234 }
235
236 if ((op_msk & B_TRNG) || (op_msk & B_KEYIN)) {
237 if (len < PTH_DESC_SIZE) {
238 printf("pathlength %d with key/range too short %d\n",
239 len, PTH_DESC_SIZE);
240 return -1;
241 }
242
243 if (op_msk & B_TRNG) {
244 u_int32_t starti, endi;
245 pptr += sizeof(struct forces_tlv);
246 len -= sizeof(struct forces_tlv);
247
248 starti = EXTRACT_32BITS(pptr);
249 pptr += 4;
250 len -= 4;
251
252 endi = EXTRACT_32BITS(pptr);
253 pptr += 4;
254 len -= 4;
255
256 if (vflag >= 3)
257 printf("%sTable range: [%d,%d]\n", ib, starti, endi);
258 }
259
260 if (op_msk & B_KEYIN) {
261 struct forces_tlv *keytlv;
262 u_int16_t tll;
263 u_int32_t keyid = EXTRACT_32BITS(pptr);
264 /* skip keyid */
265 pptr += 4;
266 len -= 4;
267 keytlv = (struct forces_tlv *)pptr;
268 /* skip header */
269 pptr += sizeof(struct forces_tlv);
270 len -= sizeof(struct forces_tlv);
271 /* skip key content */
272 tll = EXTRACT_16BITS(&keytlv->length) - TLV_HDRL;
273 pptr += tll;
274 len -= tll;
275 if (len < 0) {
276 printf("Key content too short\n");
277 return -1;
278 }
279 }
280
281 }
282
283 if (len) {
284 const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr;
285 u_int16_t type;
286 u_int16_t tll;
287 int pad = 0;
288 u_int aln;
289 int invtlv;
290
291 TCHECK(*pdtlv);
292 type = EXTRACT_16BITS(&pdtlv->type);
293 invtlv = tlv_valid(pdtlv, len);
294 if (invtlv) {
295 printf
296 ("%s Outstanding bytes %d for TLV type 0x%x TLV len %d\n",
297 tok2str(ForCES_TLV_err, NULL, invtlv), len, type,
298 EXTRACT_16BITS(&pdtlv->length));
299 goto pd_err;
300 }
301 /*
302 * At this point, tlv_valid() has ensured that the TLV
303 * length is large enough but not too large (it doesn't
304 * go past the end of the containing TLV).
305 */
306 tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL;
307 aln = F_ALN_LEN(EXTRACT_16BITS(&pdtlv->length));
308 if (aln > EXTRACT_16BITS(&pdtlv->length)) {
309 if (aln > len) {
310 printf
311 ("Invalid padded pathdata TLV type 0x%x len %d missing %d pad bytes\n",
312 type, EXTRACT_16BITS(&pdtlv->length), aln - len);
313 } else {
314 pad = aln - EXTRACT_16BITS(&pdtlv->length);
315 }
316 }
317 if (pd_valid(type)) {
318 const struct pdata_ops *ops = get_forces_pd(type);
319
320 if (vflag >= 3 && ops->v != F_TLV_PDAT) {
321 if (pad)
322 printf
323 ("%s %s (Length %d DataLen %d pad %d Bytes)\n",
324 ib, ops->s, EXTRACT_16BITS(&pdtlv->length),
325 tll, pad);
326 else
327 printf
328 ("%s %s (Length %d DataLen %d Bytes)\n",
329 ib, ops->s, EXTRACT_16BITS(&pdtlv->length),
330 tll);
331 }
332
333 chk_op_type(type, op_msk, ops->op_msk);
334
335 if (ops->print((const u_char *)pdtlv,
336 tll + pad + TLV_HDRL, op_msk,
337 indent + 2) == -1)
338 return -1;
339 len -= (TLV_HDRL + pad + tll);
340 } else {
341 printf("Invalid path data content type 0x%x len %d\n",
342 type, EXTRACT_16BITS(&pdtlv->length));
343 pd_err:
344 if (EXTRACT_16BITS(&pdtlv->length)) {
345 hex_print_with_offset("Bad Data val\n\t [",
346 pptr, len, 0);
347 printf("]\n");
348
349 return -1;
350 }
351 }
352 }
353 return len;
354
355 trunc:
356 fputs("[|forces]", stdout);
357 return -1;
358 }
359
360 int
361 pdata_print(register const u_char * pptr, register u_int len,
362 u_int16_t op_msk, int indent)
363 {
364 const struct pathdata_h *pdh = (struct pathdata_h *)pptr;
365 char *ib = indent_pr(indent, 0);
366 u_int minsize = 0;
367 int more_pd = 0;
368 u_int16_t idcnt = 0;
369
370 TCHECK(*pdh);
371 if (len < sizeof(struct pathdata_h))
372 goto trunc;
373 if (vflag >= 3) {
374 printf("\n%sPathdata: Flags 0x%x ID count %d\n",
375 ib, EXTRACT_16BITS(&pdh->pflags), EXTRACT_16BITS(&pdh->pIDcnt));
376 }
377
378 if (EXTRACT_16BITS(&pdh->pflags) & F_SELKEY) {
379 op_msk |= B_KEYIN;
380 }
381
382 /* Table GET Range operation */
383 if (EXTRACT_16BITS(&pdh->pflags) & F_SELTABRANGE) {
384 op_msk |= B_TRNG;
385 }
386
387 pptr += sizeof(struct pathdata_h);
388 len -= sizeof(struct pathdata_h);
389 idcnt = EXTRACT_16BITS(&pdh->pIDcnt);
390 minsize = idcnt * 4;
391 if (len < minsize) {
392 printf("\t\t\ttruncated IDs expected %uB got %uB\n", minsize,
393 len);
394 hex_print_with_offset("\t\t\tID Data[", pptr, len, 0);
395 printf("]\n");
396 return -1;
397 }
398
399 if ((op_msk & B_TRNG) && (op_msk & B_KEYIN)) {
400 printf("\t\t\tIllegal to have both Table ranges and keys\n");
401 return -1;
402 }
403
404 more_pd = pdatacnt_print(pptr, len, idcnt, op_msk, indent);
405 if (more_pd > 0) {
406 int consumed = len - more_pd;
407 pptr += consumed;
408 len = more_pd;
409 /* XXX: Argh, recurse some more */
410 return recpdoptlv_print(pptr, len, op_msk, indent+1);
411 } else
412 return 0;
413
414 trunc:
415 fputs("[|forces]", stdout);
416 return -1;
417 }
418
419 int
420 genoptlv_print(register const u_char * pptr, register u_int len,
421 u_int16_t op_msk, int indent)
422 {
423 const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr;
424 u_int16_t type;
425 int tll;
426 int invtlv;
427 char *ib = indent_pr(indent, 0);
428
429 TCHECK(*pdtlv);
430 type = EXTRACT_16BITS(&pdtlv->type);
431 tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL;
432 invtlv = tlv_valid(pdtlv, len);
433 printf("genoptlvprint - %s TLV type 0x%x len %d\n",
434 tok2str(ForCES_TLV, NULL, type), type, EXTRACT_16BITS(&pdtlv->length));
435 if (!invtlv) {
436 /*
437 * At this point, tlv_valid() has ensured that the TLV
438 * length is large enough but not too large (it doesn't
439 * go past the end of the containing TLV).
440 */
441 register const u_char *dp = (u_char *) TLV_DATA(pdtlv);
442 if (!ttlv_valid(type)) {
443 printf("%s TLV type 0x%x len %d\n",
444 tok2str(ForCES_TLV_err, NULL, invtlv), type,
445 EXTRACT_16BITS(&pdtlv->length));
446 return -1;
447 }
448 if (vflag >= 3)
449 printf("%s%s, length %d (data length %d Bytes)",
450 ib, tok2str(ForCES_TLV, NULL, type),
451 EXTRACT_16BITS(&pdtlv->length), tll);
452
453 return pdata_print(dp, tll, op_msk, indent + 1);
454 } else {
455 printf("\t\t\tInvalid ForCES TLV type=%x", type);
456 return -1;
457 }
458
459 trunc:
460 fputs("[|forces]", stdout);
461 return -1;
462 }
463
464 int
465 recpdoptlv_print(register const u_char * pptr, register u_int len,
466 u_int16_t op_msk, int indent)
467 {
468 const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr;
469 int tll;
470 int invtlv;
471 u_int16_t type;
472 register const u_char *dp;
473 char *ib;
474
475 while (len != 0) {
476 TCHECK(*pdtlv);
477 invtlv = tlv_valid(pdtlv, len);
478 if (invtlv) {
479 break;
480 }
481
482 /*
483 * At this point, tlv_valid() has ensured that the TLV
484 * length is large enough but not too large (it doesn't
485 * go past the end of the containing TLV).
486 */
487 ib = indent_pr(indent, 0);
488 type = EXTRACT_16BITS(&pdtlv->type);
489 dp = (u_char *) TLV_DATA(pdtlv);
490 tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL;
491
492 if (vflag >= 3)
493 printf
494 ("%s%s, length %d (data encapsulated %d Bytes)",
495 ib, tok2str(ForCES_TLV, NULL, type),
496 EXTRACT_16BITS(&pdtlv->length),
497 EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL);
498
499 if (pdata_print(dp, tll, op_msk, indent + 1) == -1)
500 return -1;
501 pdtlv = GO_NXT_TLV(pdtlv, len);
502 }
503
504 if (len) {
505 printf
506 ("\n\t\tMessy PATHDATA TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
507 EXTRACT_16BITS(&pdtlv->type), len - EXTRACT_16BITS(&pdtlv->length));
508 return -1;
509 }
510
511 return 0;
512
513 trunc:
514 fputs("[|forces]", stdout);
515 return -1;
516 }
517
518 int
519 invoptlv_print(register const u_char * pptr, register u_int len,
520 u_int16_t op_msk _U_, int indent)
521 {
522 char *ib = indent_pr(indent, 1);
523
524 if (vflag >= 3) {
525 printf("%sData[", &ib[1]);
526 hex_print_with_offset(ib, pptr, len, 0);
527 printf("%s]\n", ib);
528 }
529 return -1;
530 }
531
532 int otlv_print(const struct forces_tlv *otlv, u_int16_t op_msk _U_, int indent)
533 {
534 int rc = 0;
535 register const u_char *dp = (u_char *) TLV_DATA(otlv);
536 u_int16_t type;
537 int tll;
538 char *ib = indent_pr(indent, 0);
539 const struct optlv_h *ops;
540
541 /*
542 * lfbselect_print() has ensured that EXTRACT_16BITS(&otlv->length)
543 * >= TLV_HDRL.
544 */
545 TCHECK(*otlv);
546 type = EXTRACT_16BITS(&otlv->type);
547 tll = EXTRACT_16BITS(&otlv->length) - TLV_HDRL;
548 ops = get_forces_optlv_h(type);
549 if (vflag >= 3) {
550 printf("%sOper TLV %s(0x%x) length %d\n", ib, ops->s, type,
551 EXTRACT_16BITS(&otlv->length));
552 }
553 /* empty TLVs like COMMIT and TRCOMMIT are empty, we stop here .. */
554 if (!ops->flags & ZERO_TTLV) {
555 if (tll != 0) /* instead of "if (tll)" - for readability .. */
556 printf("%s: Illegal - MUST be empty\n", ops->s);
557 return rc;
558 }
559 /* rest of ops must at least have 12B {pathinfo} */
560 if (tll < OP_MIN_SIZ) {
561 printf("\t\tOper TLV %s(0x%x) length %d\n", ops->s, type,
562 EXTRACT_16BITS(&otlv->length));
563 printf("\t\tTruncated data size %d minimum required %d\n", tll,
564 OP_MIN_SIZ);
565 return invoptlv_print(dp, tll, ops->op_msk, indent);
566
567 }
568
569 rc = ops->print(dp, tll, ops->op_msk, indent + 1);
570 return rc;
571
572 trunc:
573 fputs("[|forces]", stdout);
574 return -1;
575 }
576
577 #define ASTDLN 4
578 #define ASTMCD 255
579 int
580 asttlv_print(register const u_char * pptr, register u_int len,
581 u_int16_t op_msk _U_, int indent)
582 {
583 u_int32_t rescode;
584 u_int dlen;
585 char *ib = indent_pr(indent, 0);
586
587 /*
588 * forces_type_print() has ensured that len (the TLV length)
589 * >= TLV_HDRL.
590 */
591 dlen = len - TLV_HDRL;
592 if (dlen != ASTDLN) {
593 printf("illegal ASTresult-TLV: %d bytes!\n", dlen);
594 return -1;
595 }
596 TCHECK2(*pptr, 4);
597 rescode = EXTRACT_32BITS(pptr);
598 if (rescode > ASTMCD) {
599 printf("illegal ASTresult result code: %d!\n", rescode);
600 return -1;
601 }
602
603 if (vflag >= 3) {
604 printf("Teardown reason:\n%s", ib);
605 switch (rescode) {
606 case 0:
607 printf("Normal Teardown");
608 break;
609 case 1:
610 printf("Loss of Heartbeats");
611 break;
612 case 2:
613 printf("Out of bandwidth");
614 break;
615 case 3:
616 printf("Out of Memory");
617 break;
618 case 4:
619 printf("Application Crash");
620 break;
621 default:
622 printf("Unknown Teardown reason");
623 break;
624 }
625 printf("(%x)\n%s", rescode, ib);
626 }
627 return 0;
628
629 trunc:
630 fputs("[|forces]", stdout);
631 return -1;
632 }
633
634 #define ASRDLN 4
635 #define ASRMCD 3
636 int
637 asrtlv_print(register const u_char * pptr, register u_int len,
638 u_int16_t op_msk _U_, int indent)
639 {
640 u_int32_t rescode;
641 u_int dlen;
642 char *ib = indent_pr(indent, 0);
643
644 /*
645 * forces_type_print() has ensured that len (the TLV length)
646 * >= TLV_HDRL.
647 */
648 dlen = len - TLV_HDRL;
649 if (dlen != ASRDLN) { /* id, instance, oper tlv */
650 printf("illegal ASRresult-TLV: %d bytes!\n", dlen);
651 return -1;
652 }
653 TCHECK2(*pptr, 4);
654 rescode = EXTRACT_32BITS(pptr);
655
656 if (rescode > ASRMCD) {
657 printf("illegal ASRresult result code: %d!\n", rescode);
658 return -1;
659 }
660
661 if (vflag >= 3) {
662 printf("\n%s", ib);
663 switch (rescode) {
664 case 0:
665 printf("Success ");
666 break;
667 case 1:
668 printf("FE ID invalid ");
669 break;
670 case 2:
671 printf("permission denied ");
672 break;
673 default:
674 printf("Unknown ");
675 break;
676 }
677 printf("(%x)\n%s", rescode, ib);
678 }
679 return 0;
680
681 trunc:
682 fputs("[|forces]", stdout);
683 return -1;
684 }
685
686 /*
687 * XXX - not used.
688 */
689 int
690 gentltlv_print(register const u_char * pptr _U_, register u_int len,
691 u_int16_t op_msk _U_, int indent _U_)
692 {
693 u_int dlen = len - TLV_HDRL;
694
695 if (dlen < 4) { /* at least 32 bits must exist */
696 printf("truncated TLV: %d bytes missing! ", 4 - dlen);
697 return -1;
698 }
699 return 0;
700 }
701
702 #define RD_MIN 8
703
704 int
705 print_metailv(register const u_char * pptr, register u_int len,
706 u_int16_t op_msk _U_, int indent)
707 {
708 u_int rlen;
709 u_int plen;
710 char *ib = indent_pr(indent, 0);
711 /* XXX: check header length */
712 const struct forces_ilv *ilv = (struct forces_ilv *)pptr;
713
714 /*
715 * print_metatlv() has ensured that len (what remains in the
716 * ILV) >= ILV_HDRL.
717 */
718 rlen = EXTRACT_32BITS(&ilv->length) - ILV_HDRL;
719 TCHECK(*ilv);
720 printf("%sMetaID 0x%x length %d\n", ib, EXTRACT_32BITS(&ilv->type),
721 EXTRACT_32BITS(&ilv->length));
722 if (vflag >= 3) {
723 hex_print_with_offset("\t\t[", ILV_DATA(ilv), rlen, 0);
724 printf(" ]\n");
725 }
726 return 0;
727
728 trunc:
729 fputs("[|forces]", stdout);
730 return -1;
731 }
732
733 int
734 print_metatlv(register const u_char * pptr, register u_int len,
735 u_int16_t op_msk _U_, int indent)
736 {
737 u_int dlen;
738 char *ib = indent_pr(indent, 0);
739 u_int rlen;
740 const struct forces_ilv *ilv = (struct forces_ilv *)pptr;
741 int invilv;
742
743 /*
744 * redirect_print() has ensured that len (what remains in the
745 * TLV) >= TLV_HDRL.
746 */
747 dlen = len - TLV_HDRL;
748 rlen = dlen;
749 printf("\n%s METADATA length %d \n", ib, rlen);
750 while (rlen != 0) {
751 TCHECK(*ilv);
752 invilv = ilv_valid(ilv, rlen);
753 if (invilv) {
754 break;
755 }
756
757 /*
758 * At this point, ilv_valid() has ensured that the ILV
759 * length is large enough but not too large (it doesn't
760 * go past the end of the containing TLV).
761 */
762 print_metailv((u_char *) ilv, rlen, 0, indent + 1);
763 ilv = GO_NXT_ILV(ilv, rlen);
764 }
765
766 return 0;
767
768 trunc:
769 fputs("[|forces]", stdout);
770 return -1;
771 }
772
773
774 int
775 print_reddata(register const u_char * pptr, register u_int len,
776 u_int16_t op_msk _U_, int indent _U_)
777 {
778 u_int dlen;
779 char *ib = indent_pr(indent, 0);
780 u_int rlen;
781 const struct forces_ilv *ilv = (struct forces_ilv *)pptr;
782 int invilv;
783
784 dlen = len - TLV_HDRL;
785 rlen = dlen;
786 printf("\n%s Redirect Data length %d \n", ib, rlen);
787
788 if (vflag >= 3) {
789 printf("\t\t[");
790 hex_print_with_offset("\n\t\t", pptr, rlen, 0);
791 printf("\n\t\t]");
792 }
793
794 return 0;
795 }
796
797 int
798 redirect_print(register const u_char * pptr, register u_int len,
799 u_int16_t op_msk _U_, int indent)
800 {
801 const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
802 u_int dlen;
803 u_int rlen;
804 int invtlv;
805
806 /*
807 * forces_type_print() has ensured that len (the TLV length)
808 * >= TLV_HDRL.
809 */
810 dlen = len - TLV_HDRL;
811 if (dlen <= RD_MIN) {
812 printf("\n\t\ttruncated Redirect TLV: %d bytes missing! ",
813 RD_MIN - dlen);
814 return -1;
815 }
816
817 rlen = dlen;
818 indent += 1;
819 while (rlen != 0) {
820 TCHECK(*tlv);
821 invtlv = tlv_valid(tlv, rlen);
822 if (invtlv) {
823 printf("Bad Redirect data\n");
824 break;
825 }
826
827 /*
828 * At this point, tlv_valid() has ensured that the TLV
829 * length is large enough but not too large (it doesn't
830 * go past the end of the containing TLV).
831 */
832 if (EXTRACT_16BITS(&tlv->type) == F_TLV_METD) {
833 print_metatlv((u_char *) TLV_DATA(tlv),
834 EXTRACT_16BITS(&tlv->length), 0, indent);
835 } else if ((EXTRACT_16BITS(&tlv->type) == F_TLV_REDD)) {
836 print_reddata((u_char *) TLV_DATA(tlv),
837 EXTRACT_16BITS(&tlv->length), 0, indent);
838 } else {
839 printf("Unknown REDIRECT TLV 0x%x len %d\n",
840 EXTRACT_16BITS(&tlv->type),
841 EXTRACT_16BITS(&tlv->length));
842 }
843
844 tlv = GO_NXT_TLV(tlv, rlen);
845 }
846
847 if (rlen) {
848 printf
849 ("\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
850 EXTRACT_16BITS(&tlv->type),
851 rlen - EXTRACT_16BITS(&tlv->length));
852 return -1;
853 }
854
855 return 0;
856
857 trunc:
858 fputs("[|forces]", stdout);
859 return -1;
860 }
861
862 #define OP_OFF 8
863 #define OP_MIN 12
864
865 int
866 lfbselect_print(register const u_char * pptr, register u_int len,
867 u_int16_t op_msk, int indent)
868 {
869 const struct forces_lfbsh *lfbs;
870 const struct forces_tlv *otlv;
871 char *ib = indent_pr(indent, 0);
872 u_int dlen;
873 u_int rlen;
874 int invtlv;
875
876 /*
877 * forces_type_print() has ensured that len (the TLV length)
878 * >= TLV_HDRL.
879 */
880 dlen = len - TLV_HDRL;
881 if (dlen <= OP_MIN) { /* id, instance, oper tlv header .. */
882 printf("\n\t\ttruncated lfb selector: %d bytes missing! ",
883 OP_MIN - dlen);
884 return -1;
885 }
886
887 /*
888 * At this point, we know that dlen > OP_MIN; OP_OFF < OP_MIN, so
889 * we also know that it's > OP_OFF.
890 */
891 rlen = dlen - OP_OFF;
892
893 lfbs = (const struct forces_lfbsh *)pptr;
894 TCHECK(*lfbs);
895 if (vflag >= 3) {
896 printf("\n%s%s(Classid %x) instance %x\n",
897 ib, tok2str(ForCES_LFBs, NULL, EXTRACT_32BITS(&lfbs->class)),
898 EXTRACT_32BITS(&lfbs->class),
899 EXTRACT_32BITS(&lfbs->instance));
900 }
901
902 otlv = (struct forces_tlv *)(lfbs + 1);
903
904 indent += 1;
905 while (rlen != 0) {
906 TCHECK(*otlv);
907 invtlv = tlv_valid(otlv, rlen);
908 if (invtlv)
909 break;
910
911 /*
912 * At this point, tlv_valid() has ensured that the TLV
913 * length is large enough but not too large (it doesn't
914 * go past the end of the containing TLV).
915 */
916 if (op_valid(EXTRACT_16BITS(&otlv->type), op_msk)) {
917 otlv_print(otlv, 0, indent);
918 } else {
919 if (vflag < 3)
920 printf("\n");
921 printf
922 ("\t\tINValid oper-TLV type 0x%x length %d for this ForCES message\n",
923 EXTRACT_16BITS(&otlv->type), EXTRACT_16BITS(&otlv->length));
924 invoptlv_print((u_char *)otlv, rlen, 0, indent);
925 }
926 otlv = GO_NXT_TLV(otlv, rlen);
927 }
928
929 if (rlen) {
930 printf
931 ("\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
932 EXTRACT_16BITS(&otlv->type), rlen - EXTRACT_16BITS(&otlv->length));
933 return -1;
934 }
935
936 return 0;
937
938 trunc:
939 fputs("[|forces]", stdout);
940 return -1;
941 }
942
943 int
944 forces_type_print(register const u_char * pptr, const struct forcesh *fhdr _U_,
945 register u_int mlen, const struct tom_h *tops)
946 {
947 const struct forces_tlv *tltlv;
948 u_int rlen;
949 int invtlv;
950 int rc = 0;
951 int ttlv = 0;
952
953 /*
954 * forces_print() has already checked that mlen >= ForCES_HDRL
955 * by calling ForCES_HLN_VALID().
956 */
957 rlen = mlen - ForCES_HDRL;
958
959 if (rlen > TLV_HLN) {
960 if (tops->flags & ZERO_TTLV) {
961 printf("<0x%x>Illegal Top level TLV!\n", tops->flags);
962 return -1;
963 }
964 } else {
965 if (tops->flags & ZERO_MORE_TTLV)
966 return 0;
967 if (tops->flags & ONE_MORE_TTLV) {
968 printf("\tTop level TLV Data missing!\n");
969 return -1;
970 }
971 }
972
973 if (tops->flags & ZERO_TTLV) {
974 return 0;
975 }
976
977 ttlv = tops->flags >> 4;
978 tltlv = GET_TOP_TLV(pptr);
979
980 /*XXX: 15 top level tlvs will probably be fine
981 You are nuts if you send more ;-> */
982 while (rlen != 0) {
983 TCHECK(*tltlv);
984 invtlv = tlv_valid(tltlv, rlen);
985 if (invtlv)
986 break;
987
988 /*
989 * At this point, tlv_valid() has ensured that the TLV
990 * length is large enough but not too large (it doesn't
991 * go past the end of the packet).
992 */
993 if (!ttlv_valid(EXTRACT_16BITS(&tltlv->type))) {
994 printf("\n\tInvalid ForCES Top TLV type=0x%x",
995 EXTRACT_16BITS(&tltlv->type));
996 return -1;
997 }
998
999 if (vflag >= 3)
1000 printf("\t%s, length %d (data length %d Bytes)",
1001 tok2str(ForCES_TLV, NULL, EXTRACT_16BITS(&tltlv->type)),
1002 EXTRACT_16BITS(&tltlv->length),
1003 EXTRACT_16BITS(&tltlv->length) - TLV_HDRL);
1004
1005 rc = tops->print((u_char *) TLV_DATA(tltlv),
1006 EXTRACT_16BITS(&tltlv->length), tops->op_msk, 9);
1007 if (rc < 0) {
1008 return -1;
1009 }
1010 tltlv = GO_NXT_TLV(tltlv, rlen);
1011 ttlv--;
1012 if (ttlv <= 0)
1013 break;
1014 }
1015 /*
1016 * XXX - if ttlv != 0, does that mean that the packet was too
1017 * short, and didn't have *enough* TLVs in it?
1018 */
1019 if (rlen) {
1020 printf("\tMess TopTLV header: min %u, total %d advertised %d ",
1021 TLV_HDRL, rlen, EXTRACT_16BITS(&tltlv->length));
1022 return -1;
1023 }
1024
1025 return 0;
1026
1027 trunc:
1028 fputs("[|forces]", stdout);
1029 return -1;
1030 }
1031
1032 void forces_print(register const u_char * pptr, register u_int len)
1033 {
1034 const struct forcesh *fhdr;
1035 u_int mlen;
1036 u_int32_t flg_raw;
1037 const struct tom_h *tops;
1038 int rc = 0;
1039
1040 fhdr = (const struct forcesh *)pptr;
1041 TCHECK(*fhdr);
1042 if (!tom_valid(fhdr->fm_tom)) {
1043 printf("Invalid ForCES message type %d\n", fhdr->fm_tom);
1044 goto error;
1045 }
1046
1047 mlen = ForCES_BLN(fhdr);
1048
1049 tops = get_forces_tom(fhdr->fm_tom);
1050 if (tops->v == TOM_RSVD) {
1051 printf("\n\tUnknown ForCES message type=0x%x", fhdr->fm_tom);
1052 goto error;
1053 }
1054
1055 printf("\n\tForCES %s ", tops->s);
1056 if (!ForCES_HLN_VALID(mlen, len)) {
1057 printf
1058 ("Illegal ForCES pkt len - min %u, total recvd %d, advertised %d ",
1059 ForCES_HDRL, len, ForCES_BLN(fhdr));
1060 goto error;
1061 }
1062
1063 TCHECK2(*(pptr + 20), 4);
1064 flg_raw = EXTRACT_32BITS(pptr + 20);
1065 if (vflag >= 1) {
1066 printf("\n\tForCES Version %d len %uB flags 0x%08x ",
1067 ForCES_V(fhdr), mlen, flg_raw);
1068 printf("\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%" PRIx64,
1069 ForCES_SID(fhdr), ForCES_node(ForCES_SID(fhdr)),
1070 ForCES_DID(fhdr), ForCES_node(ForCES_DID(fhdr)),
1071 EXTRACT_64BITS(fhdr->fm_cor));
1072
1073 }
1074 if (vflag >= 2) {
1075 printf
1076 ("\n\tForCES flags:\n\t %s(0x%x), prio=%d, %s(0x%x),\n\t %s(0x%x), %s(0x%x)\n",
1077 ForCES_ACKp(ForCES_ACK(fhdr)), ForCES_ACK(fhdr),
1078 ForCES_PRI(fhdr),
1079 ForCES_EMp(ForCES_EM(fhdr)), ForCES_EM(fhdr),
1080 ForCES_ATp(ForCES_AT(fhdr)), ForCES_AT(fhdr),
1081 ForCES_TPp(ForCES_TP(fhdr)), ForCES_TP(fhdr));
1082 printf
1083 ("\t Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n",
1084 ForCES_RS1(fhdr), ForCES_RS2(fhdr));
1085 }
1086 rc = forces_type_print(pptr, fhdr, mlen, tops);
1087 if (rc < 0) {
1088 error:
1089 hex_print_with_offset("\n\t[", pptr, len, 0);
1090 printf("\n\t]");
1091 return;
1092 }
1093
1094 if (vflag >= 4) {
1095 printf("\n\t Raw ForCES message\n\t [");
1096 hex_print_with_offset("\n\t ", pptr, len, 0);
1097 printf("\n\t ]");
1098 }
1099 printf("\n");
1100 return;
1101
1102 trunc:
1103 fputs("[|forces]", stdout);
1104 }