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