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