]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/tcpdump/print-forces.c
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / 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 }