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