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