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