]> The Tcpdump Group git mirrors - tcpdump/blob - print-forces.c
Use EXTRACT_16BITS() and EXTRACT_32BITS() to fetch integral values.
[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 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_int16_t dlen = len - TLV_HDRL;
41
42 if (dlen != RESLEN) {
43 printf("illegal RESULT-TLV: %d bytes! \n", dlen);
44 return -1;
45 }
46
47 if (r->result >= 0x18 && r->result <= 0xFE) {
48 printf("illegal reserved result code: 0x%x! \n", r->result);
49 return -1;
50 }
51
52 if (vflag >= 3) {
53 char *ib = indent_pr(indent, 0);
54 printf("%s Result: %s (code 0x%x)\n", ib,
55 tok2str(ForCES_errs, NULL, r->result), r->result);
56 }
57 return 0;
58 }
59
60 int
61 fdatatlv_print(register const u_char * pptr, register u_int len,
62 u_int16_t op_msk _U_, int indent)
63 {
64 struct forces_tlv *tlv = (struct forces_tlv *)pptr;
65 u_int tll = len - TLV_HDRL;
66 register const u_char *tdp = (u_char *) TLV_DATA(tlv);
67 u_int16_t type = EXTRACT_16BITS(&tlv->type);
68 if (type != F_TLV_FULD) {
69 printf("Error: expecting FULLDATA!\n");
70 return -1;
71 }
72
73 if (vflag >= 3) {
74 char *ib = indent_pr(indent + 2, 1);
75 printf("%s[", &ib[1]);
76 hex_print_with_offset(ib, tdp, tll, 0);
77 printf("\n%s]\n", &ib[1]);
78 }
79 return 0;
80 }
81
82 int
83 sdatailv_print(register const u_char * pptr, register u_int len,
84 u_int16_t op_msk _U_, int indent)
85 {
86 u_int tll = len - ILV_HDRL;
87 struct forces_ilv *ilv = (struct forces_ilv *)pptr;
88 int invilv;
89
90 indent += 1;
91 while (1) {
92 invilv = ilv_valid(ilv, tll);
93 if (invilv) {
94 printf("Error: BAD ILV!\n");
95 return -1;
96 }
97 if (vflag >= 3) {
98 register const u_char *tdp = (u_char *) ILV_DATA(ilv);
99 char *ib = indent_pr(indent, 1);
100 printf("\n%s SPARSEDATA: type %x length %d\n", &ib[1],
101 EXTRACT_32BITS(&ilv->type),
102 EXTRACT_32BITS(&ilv->length));
103 printf("%s[", &ib[1]);
104 hex_print_with_offset(ib, tdp, tll, 0);
105 printf("\n%s]\n", &ib[1]);
106 }
107
108 ilv = GO_NXT_ILV(ilv, tll);
109 }
110
111 return 0;
112 }
113
114 int
115 sdatatlv_print(register const u_char * pptr, register u_int len,
116 u_int16_t op_msk, int indent)
117 {
118 struct forces_tlv *tlv = (struct forces_tlv *)pptr;
119 u_int tll = len - TLV_HDRL;
120 register const u_char *tdp = (u_char *) TLV_DATA(tlv);
121 u_int16_t type = EXTRACT_16BITS(&tlv->type);
122 if (type != F_TLV_SPAD) {
123 printf("Error: expecting SPARSEDATA!\n");
124 return -1;
125 }
126
127 return sdatailv_print(tdp, tll, op_msk, indent);
128 }
129
130 int
131 pkeyitlv_print(register const u_char * pptr, register u_int len,
132 u_int16_t op_msk, int indent)
133 {
134 struct forces_tlv *tlv = (struct forces_tlv *)pptr;
135 register const u_char *tdp = (u_char *) TLV_DATA(tlv);
136 register const u_char *dp = tdp + 4;
137 struct forces_tlv *kdtlv = (struct forces_tlv *)dp;
138 u_int32_t id = EXTRACT_32BITS(tdp);
139 char *ib = indent_pr(indent, 0);
140 u_int16_t type, tll;
141 int invtlv;
142
143 printf("%sKeyinfo: Key 0x%x\n", ib, id);
144 type = EXTRACT_16BITS(&kdtlv->type);
145 invtlv = tlv_valid(kdtlv, len);
146
147 if (invtlv) {
148 printf("%s TLV type 0x%x len %d\n",
149 tok2str(ForCES_TLV_err, NULL, invtlv), type,
150 EXTRACT_16BITS(&kdtlv->length));
151 return -1;
152 }
153 tll = EXTRACT_16BITS(&kdtlv->length);
154 dp = (u_char *) TLV_DATA(kdtlv);
155 return fdatatlv_print(dp, tll, op_msk, indent);
156 }
157
158 int
159 pdatacnt_print(register const u_char * pptr, register u_int len,
160 u_int32_t IDcnt, u_int16_t op_msk, int indent)
161 {
162 u_int i;
163 int rc;
164 u_int32_t id;
165 char *ib = indent_pr(indent, 0);
166
167 for (i = 0; i < IDcnt; i++) {
168 id = EXTRACT_32BITS(pptr);
169 if (vflag >= 3)
170 printf("%s ID#%02u: %d\n", ib, i + 1, id);
171 len -= 4;
172 pptr += 4;
173 }
174 if (len) {
175 struct forces_tlv *pdtlv = (struct forces_tlv *)pptr;
176 u_int16_t type = EXTRACT_16BITS(&pdtlv->type);
177 u_int16_t tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL;
178 int pad = 0;
179 u_int aln = F_ALN_LEN(EXTRACT_16BITS(&pdtlv->length));
180
181 int invtlv = tlv_valid(pdtlv, len);
182
183 if (invtlv) {
184 printf
185 ("%s Outstanding bytes %d for TLV type 0x%x TLV len %d\n",
186 tok2str(ForCES_TLV_err, NULL, invtlv), len, type,
187 EXTRACT_16BITS(&pdtlv->length));
188 goto pd_err;
189 }
190 if (aln > EXTRACT_16BITS(&pdtlv->length)) {
191 if (aln > len) {
192 printf
193 ("Invalid padded pathdata TLV type 0x%x len %d missing %d pad bytes\n",
194 type, EXTRACT_16BITS(&pdtlv->length), aln - len);
195 } else {
196 pad = aln - EXTRACT_16BITS(&pdtlv->length);
197 }
198 }
199 if (pd_valid(type)) {
200 struct pdata_ops *ops = get_forces_pd(type);
201
202 if (vflag >= 3 && ops->v != F_TLV_PDAT) {
203 if (pad)
204 printf
205 ("%s %s (Length %d DataLen %d pad %d Bytes)\n",
206 ib, ops->s, EXTRACT_16BITS(&pdtlv->length),
207 tll, pad);
208 else
209 printf
210 ("%s %s (Length %d DataLen %d Bytes)\n",
211 ib, ops->s, EXTRACT_16BITS(&pdtlv->length),
212 tll);
213 }
214
215 chk_op_type(type, op_msk, ops->op_msk);
216
217 rc = ops->print((const u_char *)pdtlv,
218 tll + pad + TLV_HDRL, op_msk,
219 indent + 2);
220 } else {
221 printf("Invalid path data content type 0x%x len %d\n",
222 type, EXTRACT_16BITS(&pdtlv->length));
223 pd_err:
224 if (EXTRACT_16BITS(&pdtlv->length)) {
225 hex_print_with_offset("Bad Data val\n\t [",
226 pptr, len, 0);
227 printf("]\n");
228
229 return -1;
230 }
231 }
232 }
233 return 0;
234 }
235
236 int
237 pdata_print(register const u_char * pptr, register u_int len,
238 u_int16_t op_msk, int indent)
239 {
240 struct pathdata_h *pdh = (struct pathdata_h *)pptr;
241 char *ib = indent_pr(indent, 0);
242 u_int minsize = 0;
243 if (vflag >= 3) {
244 printf("\n%sPathdata: Flags 0x%x ID count %d\n",
245 ib, EXTRACT_16BITS(&pdh->pflags), EXTRACT_16BITS(&pdh->pIDcnt));
246 }
247
248 if (EXTRACT_16BITS(&pdh->pflags) & F_SELKEY) {
249 op_msk |= B_KEYIN;
250 }
251 pptr += sizeof(struct pathdata_h);
252 len -= sizeof(struct pathdata_h);
253 minsize = EXTRACT_16BITS(&pdh->pIDcnt) * 4;
254 if (len < minsize) {
255 printf("\t\t\ttruncated IDs expected %uB got %uB\n", minsize,
256 len);
257 hex_print_with_offset("\t\t\tID Data[", pptr, len, 0);
258 printf("]\n");
259 return -1;
260 }
261 return pdatacnt_print(pptr, len, EXTRACT_16BITS(&pdh->pIDcnt), op_msk, indent);
262 }
263
264 int
265 genoptlv_print(register const u_char * pptr, register u_int len,
266 u_int16_t op_msk, int indent)
267 {
268 struct forces_tlv *pdtlv = (struct forces_tlv *)pptr;
269 u_int16_t type = EXTRACT_16BITS(&pdtlv->type);
270 int tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL;
271 int invtlv = tlv_valid(pdtlv, len);
272 char *ib = indent_pr(indent, 0);
273
274 printf("genoptlvprint - %s TLV type 0x%x len %d\n",
275 tok2str(ForCES_TLV, NULL, type), type, EXTRACT_16BITS(&pdtlv->length));
276 if (!invtlv) {
277 register const u_char *dp = (u_char *) TLV_DATA(pdtlv);
278 if (!ttlv_valid(type)) {
279 printf("%s TLV type 0x%x len %d\n",
280 tok2str(ForCES_TLV_err, NULL, invtlv), type,
281 EXTRACT_16BITS(&pdtlv->length));
282 return -1;
283 }
284 if (vflag >= 3)
285 printf("%s%s, length %d (data length %d Bytes)",
286 ib, tok2str(ForCES_TLV, NULL, type),
287 EXTRACT_16BITS(&pdtlv->length), tll);
288
289 return pdata_print(dp, tll, op_msk, indent + 1);
290 } else {
291 printf("\t\t\tInvalid ForCES TLV type=%x", type);
292 return -1;
293 }
294 }
295
296 int
297 recpdoptlv_print(register const u_char * pptr, register u_int len,
298 u_int16_t op_msk, int indent)
299 {
300 struct forces_tlv *pdtlv = (struct forces_tlv *)pptr;
301 int tll = len;
302 int rc = 0;
303 int invtlv;
304 u_int16_t type;
305 register const u_char *dp;
306 char *ib;
307
308 while (1) {
309 invtlv = tlv_valid(pdtlv, len);
310 if (invtlv) {
311 break;
312 }
313 ib = indent_pr(indent, 0);
314 type = EXTRACT_16BITS(&pdtlv->type);
315 dp = (u_char *) TLV_DATA(pdtlv);
316 tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL;
317
318 if (vflag >= 3)
319 printf
320 ("%s%s, length %d (data encapsulated %d Bytes)",
321 ib, tok2str(ForCES_TLV, NULL, type),
322 EXTRACT_16BITS(&pdtlv->length),
323 EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL);
324
325 rc = pdata_print(dp, tll, op_msk, indent + 1);
326 pdtlv = GO_NXT_TLV(pdtlv, len);
327 }
328
329 if (len) {
330 printf
331 ("\n\t\tMessy PATHDATA TLV header, type (0x%x) \n\t\texcess of %d Bytes ",
332 EXTRACT_16BITS(&pdtlv->type), tll - EXTRACT_16BITS(&pdtlv->length));
333 return -1;
334 }
335
336 return 0;
337 }
338
339 int
340 invoptlv_print(register const u_char * pptr, register u_int len,
341 u_int16_t op_msk _U_, int indent)
342 {
343 char *ib = indent_pr(indent, 1);
344 if (vflag >= 3) {
345 printf("%sData[", &ib[1]);
346 hex_print_with_offset(ib, pptr, len, 0);
347 printf("%s]\n", ib);
348 }
349 return -1;
350 }
351
352 int otlv_print(struct forces_tlv *otlv, u_int16_t op_msk _U_, int indent)
353 {
354 int rc = 0;
355 register const u_char *dp = (u_char *) TLV_DATA(otlv);
356 u_int16_t type = EXTRACT_16BITS(&otlv->type);
357 int tll = EXTRACT_16BITS(&otlv->length) - TLV_HDRL;
358 char *ib = indent_pr(indent, 0);
359 struct optlv_h *ops;
360
361 ops = get_forces_optlv_h(type);
362 if (vflag >= 3) {
363 printf("%sOper TLV %s(0x%x) length %d\n", ib, ops->s, type,
364 EXTRACT_16BITS(&otlv->length));
365 }
366 /* empty TLVs like COMMIT and TRCOMMIT are empty, we stop here .. */
367 if (!ops->flags & ZERO_TTLV) {
368 if (tll != 0) /* instead of "if (tll)" - for readability .. */
369 printf("%s: Illegal - MUST be empty\n", ops->s);
370 return rc;
371 }
372 /* rest of ops must at least have 12B {pathinfo} */
373 if (tll < OP_MIN_SIZ) {
374 printf("\t\tOper TLV %s(0x%x) length %d\n", ops->s, type,
375 EXTRACT_16BITS(&otlv->length));
376 printf("\t\tTruncated data size %d minimum required %d\n", tll,
377 OP_MIN_SIZ);
378 return invoptlv_print(dp, tll, ops->op_msk, indent);
379
380 }
381
382 rc = ops->print(dp, tll, ops->op_msk, indent + 1);
383 return rc;
384 }
385
386 #define ASTDLN 4
387 #define ASTMCD 255
388 int
389 asttlv_print(register const u_char * pptr, register u_int len,
390 u_int16_t op_msk _U_, int indent)
391 {
392
393 u_int32_t rescode;
394 u_int16_t dlen = len - TLV_HDRL;
395 char *ib = indent_pr(indent, 0);
396 if (dlen != ASTDLN) {
397 printf("illegal ASTresult-TLV: %d bytes! \n", dlen);
398 return -1;
399 }
400 rescode = EXTRACT_32BITS(pptr);
401 if (rescode > ASTMCD) {
402 printf("illegal ASTresult result code: %d! \n", rescode);
403 return -1;
404 }
405
406 if (vflag >= 3) {
407 printf("Teardown reason: \n%s", ib);
408 switch (rescode) {
409 case 0:
410 printf("Normal Teardown");
411 break;
412 case 1:
413 printf("Loss of Heartbeats");
414 break;
415 case 2:
416 printf("Out of bandwidth");
417 break;
418 case 3:
419 printf("Out of Memory");
420 break;
421 case 4:
422 printf("Application Crash");
423 break;
424 default:
425 printf("Unknown Teardown reason");
426 break;
427 }
428 printf("(%x) \n%s", rescode, ib);
429 }
430 return 0;
431 }
432
433 #define ASRDLN 4
434 #define ASRMCD 3
435 int
436 asrtlv_print(register const u_char * pptr, register u_int len,
437 u_int16_t op_msk _U_, int indent)
438 {
439
440 u_int32_t rescode;
441 u_int16_t dlen = len - TLV_HDRL;
442 char *ib = indent_pr(indent, 0);
443
444 if (dlen != ASRDLN) { /* id, instance, oper tlv */
445 printf("illegal ASRresult-TLV: %d bytes! \n", dlen);
446 return -1;
447 }
448 rescode = EXTRACT_32BITS(pptr);
449
450 if (rescode > ASRMCD) {
451 printf("illegal ASRresult result code: %d! \n", rescode);
452 return -1;
453 }
454
455 if (vflag >= 3) {
456 printf("\n%s", ib);
457 switch (rescode) {
458 case 0:
459 printf("Success ");
460 break;
461 case 1:
462 printf("FE ID invalid ");
463 break;
464 case 2:
465 printf("permission denied ");
466 break;
467 default:
468 printf("Unknown ");
469 break;
470 }
471 printf("(%x) \n%s", rescode, ib);
472 }
473 return 0;
474 }
475
476 int
477 gentltlv_print(register const u_char * pptr _U_, register u_int len,
478 u_int16_t op_msk _U_, int indent _U_)
479 {
480 u_int16_t dlen = len - TLV_HDRL;
481 if (dlen < 4) { /* at least 32 bits must exist */
482 printf("truncated TLV: %d bytes missing! ", 4 - dlen);
483 return -1;
484 }
485 return 0;
486 }
487
488 #define RD_MIN 8
489 int
490 print_metailv(register const u_char * pptr, register u_int len,
491 u_int16_t op_msk _U_, int indent)
492 {
493 u_int16_t dlen = len - ILV_HDRL;
494 int tll = dlen;
495 char *ib = indent_pr(indent, 0);
496 /* XXX: check header length */
497 struct forces_ilv *ilv = (struct forces_ilv *)pptr;
498 printf("\n%sMetaID 0x%x length %d\n", ib, EXTRACT_32BITS(&ilv->type),
499 EXTRACT_32BITS(&ilv->length));
500 hex_print_with_offset("\n\t\t\t\t[", ILV_DATA(ilv), tll, 0);
501 return 0;
502 }
503
504 int
505 print_metatlv(register const u_char * pptr, register u_int len,
506 u_int16_t op_msk _U_, int indent)
507 {
508 u_int16_t dlen = len - TLV_HDRL;
509 char *ib = indent_pr(indent, 0);
510 u_int tll = dlen;
511 struct forces_ilv *ilv = (struct forces_ilv *)pptr;
512 int invilv;
513
514 printf("\n%s METADATA \n", ib);
515 while (1) {
516 invilv = ilv_valid(ilv, tll);
517 if (invilv)
518 break;
519 print_metailv((u_char *) ilv, tll, 0, indent + 1);
520
521 ilv = GO_NXT_ILV(ilv, tll);
522 }
523
524 return 0;
525 }
526
527 /*
528 */
529 int
530 print_reddata(register const u_char * pptr, register u_int len,
531 u_int16_t op_msk _U_, int indent _U_)
532 {
533 u_int16_t dlen = len - TLV_HDRL;
534 u_int tll = dlen;
535 int invtlv;
536 struct forces_tlv *tlv = (struct forces_tlv *)pptr;
537
538 printf("\n\t\t Redirect DATA\n");
539 if (dlen <= RD_MIN) {
540 printf("\n\t\ttruncated Redirect data: %d bytes missing! ",
541 RD_MIN - dlen);
542 return -1;
543 }
544
545 invtlv = tlv_valid(tlv, tll);
546
547 if (invtlv) {
548 printf("Redir data type 0x%x len %d\n", EXTRACT_16BITS(&tlv->type),
549 EXTRACT_16BITS(&tlv->length));
550 return -1;
551 }
552
553 tll -= TLV_HDRL;
554 hex_print_with_offset("\n\t\t\t[", TLV_DATA(tlv), tll, 0);
555 return 0;
556 }
557
558 int
559 redirect_print(register const u_char * pptr, register u_int len,
560 u_int16_t op_msk _U_, int indent)
561 {
562 struct forces_tlv *tlv = (struct forces_tlv *)pptr;
563 u_int16_t dlen = len - TLV_HDRL;
564 u_int tll = dlen;
565 int invtlv;
566
567 if (dlen <= RD_MIN) {
568 printf("\n\t\ttruncated Redirect TLV: %d bytes missing! ",
569 RD_MIN - dlen);
570 return -1;
571 }
572
573 indent += 1;
574 while (1) {
575 invtlv = tlv_valid(tlv, tll);
576 if (invtlv)
577 break;
578 if (EXTRACT_16BITS(&tlv->type) == F_TLV_METD) {
579 print_metatlv((u_char *) TLV_DATA(tlv), tll, 0, indent);
580 } else if ((EXTRACT_16BITS(&tlv->type) == F_TLV_REDD)) {
581 print_reddata((u_char *) TLV_DATA(tlv), tll, 0, indent);
582 } else {
583 printf("Unknown REDIRECT TLV 0x%x len %d\n",
584 EXTRACT_16BITS(&tlv->type), EXTRACT_16BITS(&tlv->length));
585 }
586
587 tlv = GO_NXT_TLV(tlv, tll);
588 }
589
590 if (tll) {
591 printf
592 ("\n\t\tMessy Redirect TLV header, type (0x%x) \n\t\texcess of %d Bytes ",
593 EXTRACT_16BITS(&tlv->type), tll - EXTRACT_16BITS(&tlv->length));
594 return -1;
595 }
596
597 return 0;
598 }
599
600 #define OP_OFF 8
601 #define OP_MIN 12
602
603 int
604 lfbselect_print(register const u_char * pptr, register u_int len,
605 u_int16_t op_msk, int indent)
606 {
607 const struct forces_lfbsh *lfbs;
608 struct forces_tlv *otlv;
609 char *ib = indent_pr(indent, 0);
610 u_int16_t dlen = len - TLV_HDRL;
611 u_int tll = dlen - OP_OFF;
612 int invtlv;
613
614 if (dlen <= OP_MIN) { /* id, instance, oper tlv header .. */
615 printf("\n\t\ttruncated lfb selector: %d bytes missing! ",
616 OP_MIN - dlen);
617 return -1;
618 }
619
620 lfbs = (const struct forces_lfbsh *)pptr;
621 if (vflag >= 3) {
622 printf("\n%s%s(Classid %x) instance %x\n",
623 ib, tok2str(ForCES_LFBs, NULL, EXTRACT_32BITS(&lfbs->class)),
624 EXTRACT_32BITS(&lfbs->class),
625 EXTRACT_32BITS(&lfbs->instance));
626 }
627
628 otlv = (struct forces_tlv *)(lfbs + 1);
629
630 indent += 1;
631 while (1) {
632 invtlv = tlv_valid(otlv, tll);
633 if (invtlv)
634 break;
635 if (op_valid(EXTRACT_16BITS(&otlv->type), op_msk)) {
636 otlv_print(otlv, 0, indent);
637 } else {
638 if (vflag < 3)
639 printf("\n");
640 printf
641 ("\t\tINValid oper-TLV type 0x%x length %d for this ForCES message\n",
642 EXTRACT_16BITS(&otlv->type), EXTRACT_16BITS(&otlv->length));
643 invoptlv_print((u_char *)otlv, tll, 0, indent);
644 }
645 otlv = GO_NXT_TLV(otlv, tll);
646 }
647
648 if (tll) {
649 printf
650 ("\n\t\tMessy oper TLV header, type (0x%x) \n\t\texcess of %d Bytes ",
651 EXTRACT_16BITS(&otlv->type), tll - EXTRACT_16BITS(&otlv->length));
652 return -1;
653 }
654
655 return 0;
656 }
657
658 int
659 forces_type_print(register const u_char * pptr, const struct forcesh *fhdr _U_,
660 register u_int mlen, struct tom_h *tops)
661 {
662 struct forces_tlv *tltlv;
663 u_int tll;
664 int invtlv;
665 int rc = 0;
666 int ttlv = 0;
667
668 tll = mlen - sizeof(struct forcesh);
669
670 if (tll > TLV_HLN) {
671 if (tops->flags & ZERO_TTLV) {
672 printf("<0x%x>Illegal Top level TLV!\n", tops->flags);
673 return -1;
674 }
675 } else {
676 if (tops->flags & ZERO_MORE_TTLV)
677 return 0;
678 if (tops->flags & ONE_MORE_TTLV) {
679 printf("\tTop level TLV Data missing!\n");
680 return -1;
681 }
682 }
683
684 if (tops->flags & ZERO_TTLV) {
685 return 0;
686 }
687
688 ttlv = tops->flags >> 4;
689 tltlv = GET_TOP_TLV(pptr);
690
691 /*XXX: 15 top level tlvs will probably be fine
692 You are nuts if you send more ;-> */
693 while (1) {
694 invtlv = tlv_valid(tltlv, tll);
695 if (invtlv)
696 break;
697 if (!ttlv_valid(EXTRACT_16BITS(&tltlv->type))) {
698 printf("\n\tInvalid ForCES Top TLV type=0x%x",
699 EXTRACT_16BITS(&tltlv->type));
700 return -1;
701 }
702
703 if (vflag >= 3)
704 printf("\t%s, length %d (data length %d Bytes)",
705 tok2str(ForCES_TLV, NULL, EXTRACT_16BITS(&tltlv->type)),
706 EXTRACT_16BITS(&tltlv->length), EXTRACT_16BITS(&tltlv->length) - 4);
707
708 rc = tops->print((u_char *) TLV_DATA(tltlv),
709 EXTRACT_16BITS(&tltlv->length), tops->op_msk, 9);
710 if (rc < 0) {
711 return -1;
712 }
713 tltlv = GO_NXT_TLV(tltlv, tll);
714 ttlv--;
715 if (ttlv <= 0)
716 break;
717 }
718 if (tll) {
719 printf("\tMess TopTLV header: min %lu, total %d advertised %d ",
720 (unsigned long)sizeof(struct forces_tlv),
721 tll, EXTRACT_16BITS(&tltlv->length));
722 return -1;
723 }
724
725 return 0;
726 }
727
728 void forces_print(register const u_char * pptr, register u_int len)
729 {
730 const struct forcesh *fhdr;
731 u_int16_t mlen;
732 u_int32_t flg_raw;
733 struct tom_h *tops;
734 int rc = 0;
735
736 fhdr = (const struct forcesh *)pptr;
737 if (!tom_valid(fhdr->fm_tom)) {
738 printf("Invalid ForCES message type %d\n", fhdr->fm_tom);
739 goto error;
740 }
741
742 mlen = ForCES_BLN(fhdr);
743
744 tops = get_forces_tom(fhdr->fm_tom);
745 if (tops->v == TOM_RSVD) {
746 printf("\n\tUnknown ForCES message type=0x%x", fhdr->fm_tom);
747 goto error;
748 }
749
750 printf("\n\tForCES %s ", tops->s);
751 if (!ForCES_HLN_VALID(mlen, len)) {
752 printf
753 ("Illegal ForCES pkt len - min %lu, total recvd %d, advertised %d ",
754 (unsigned long)sizeof(struct forcesh), len, ForCES_BLN(fhdr));
755 goto error;
756 }
757
758 flg_raw = EXTRACT_32BITS(pptr + 20);
759 if (vflag >= 1) {
760 printf("\n\tForCES Version %d len %uB flags 0x%08x ",
761 ForCES_V(fhdr), mlen, flg_raw);
762 printf("\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%"
763 PRIu64, ForCES_SID(fhdr), ForCES_node(ForCES_SID(fhdr)),
764 ForCES_DID(fhdr), ForCES_node(ForCES_DID(fhdr)),
765 EXTRACT_64BITS(fhdr->fm_cor));
766
767 }
768 if (vflag >= 2) {
769 printf
770 ("\n\tForCES flags:\n\t %s(0x%x), prio=%d, %s(0x%x),\n\t %s(0x%x), %s(0x%x)\n",
771 ForCES_ACKp(ForCES_ACK(fhdr)), ForCES_ACK(fhdr),
772 ForCES_PRI(fhdr),
773 ForCES_EMp(ForCES_EM(fhdr)), ForCES_EM(fhdr),
774 ForCES_ATp(ForCES_AT(fhdr)), ForCES_AT(fhdr),
775 ForCES_TPp(ForCES_TP(fhdr)), ForCES_TP(fhdr));
776 printf
777 ("\t Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n",
778 ForCES_RS1(fhdr), ForCES_RS2(fhdr));
779 }
780 rc = forces_type_print(pptr, fhdr, mlen, tops);
781 if (rc < 0) {
782 error:
783 hex_print_with_offset("\n\t[", pptr, len, 0);
784 printf("\n\t]");
785 return;
786 }
787
788 if (vflag >= 4) {
789 printf("\n\t Raw ForCES message \n\t [");
790 hex_print_with_offset("\n\t ", pptr, len, 0);
791 printf("\n\t ]");
792 }
793 printf("\n");
794 }