tcpdump  4.99.1
About: tcpdump is a tool for network monitoring and data acquisition.
  Fossies Dox: tcpdump-4.99.1.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

print-cfm.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1998-2006 The TCPDUMP project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that: (1) source code
6  * distributions retain the above copyright notice and this paragraph
7  * in its entirety, and (2) distributions including binary code include
8  * the above copyright notice and this paragraph in its entirety in
9  * the documentation or other materials provided with the distribution.
10  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13  * FOR A PARTICULAR PURPOSE.
14  *
15  * Original code by Hannes Gredler (hannes@gredler.at)
16  */
17 
18 /* \summary: IEEE 802.1ag Connectivity Fault Management (CFM) protocols printer */
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 #include "netdissect-stdinc.h"
25 
26 #include "netdissect.h"
27 #include "extract.h"
28 #include "addrtoname.h"
29 #include "oui.h"
30 #include "af.h"
31 
32 
38 };
39 
40 #define CFM_VERSION 0
41 #define CFM_EXTRACT_VERSION(x) ((x)&0x1f)
42 #define CFM_EXTRACT_MD_LEVEL(x) (((x)&0xe0)>>5)
43 
44 #define CFM_OPCODE_CCM 1
45 #define CFM_OPCODE_LBR 2
46 #define CFM_OPCODE_LBM 3
47 #define CFM_OPCODE_LTR 4
48 #define CFM_OPCODE_LTM 5
49 
50 static const struct tok cfm_opcode_values[] = {
51  { CFM_OPCODE_CCM, "Continuity Check Message"},
52  { CFM_OPCODE_LBR, "Loopback Reply"},
53  { CFM_OPCODE_LBM, "Loopback Message"},
54  { CFM_OPCODE_LTR, "Linktrace Reply"},
55  { CFM_OPCODE_LTM, "Linktrace Message"},
56  { 0, NULL}
57 };
58 
59 /*
60  * Message Formats.
61  */
62 struct cfm_ccm_t {
67 };
68 
69 /*
70  * Timer Bases for the CCM Interval field.
71  * Expressed in units of seconds.
72  */
73 static const float ccm_interval_base[8] = {0.0f, 0.003333f, 0.01f, 0.1f, 1.0f, 10.0f, 60.0f, 600.0f};
74 #define CCM_INTERVAL_MIN_MULTIPLIER 3.25
75 #define CCM_INTERVAL_MAX_MULTIPLIER 3.5
76 
77 #define CFM_CCM_RDI_FLAG 0x80
78 #define CFM_EXTRACT_CCM_INTERVAL(x) ((x)&0x07)
79 
80 #define CFM_CCM_MD_FORMAT_8021 0
81 #define CFM_CCM_MD_FORMAT_NONE 1
82 #define CFM_CCM_MD_FORMAT_DNS 2
83 #define CFM_CCM_MD_FORMAT_MAC 3
84 #define CFM_CCM_MD_FORMAT_CHAR 4
85 
86 static const struct tok cfm_md_nameformat_values[] = {
87  { CFM_CCM_MD_FORMAT_8021, "IEEE 802.1"},
88  { CFM_CCM_MD_FORMAT_NONE, "No MD Name present"},
89  { CFM_CCM_MD_FORMAT_DNS, "DNS string"},
90  { CFM_CCM_MD_FORMAT_MAC, "MAC + 16Bit Integer"},
91  { CFM_CCM_MD_FORMAT_CHAR, "Character string"},
92  { 0, NULL}
93 };
94 
95 #define CFM_CCM_MA_FORMAT_8021 0
96 #define CFM_CCM_MA_FORMAT_VID 1
97 #define CFM_CCM_MA_FORMAT_CHAR 2
98 #define CFM_CCM_MA_FORMAT_INT 3
99 #define CFM_CCM_MA_FORMAT_VPN 4
100 
101 static const struct tok cfm_ma_nameformat_values[] = {
102  { CFM_CCM_MA_FORMAT_8021, "IEEE 802.1"},
103  { CFM_CCM_MA_FORMAT_VID, "Primary VID"},
104  { CFM_CCM_MA_FORMAT_CHAR, "Character string"},
105  { CFM_CCM_MA_FORMAT_INT, "16Bit Integer"},
106  { CFM_CCM_MA_FORMAT_VPN, "RFC2685 VPN-ID"},
107  { 0, NULL}
108 };
109 
110 struct cfm_lbm_t {
112 };
113 
114 struct cfm_ltm_t {
119 };
120 
121 static const struct tok cfm_ltm_flag_values[] = {
122  { 0x80, "Use Forwarding-DB only"},
123  { 0, NULL}
124 };
125 
126 struct cfm_ltr_t {
130 };
131 
132 static const struct tok cfm_ltr_flag_values[] = {
133  { 0x80, "UseFDB Only"},
134  { 0x40, "FwdYes"},
135  { 0x20, "Terminal MEP"},
136  { 0, NULL}
137 };
138 
139 static const struct tok cfm_ltr_replay_action_values[] = {
140  { 1, "Exact Match"},
141  { 2, "Filtering DB"},
142  { 3, "MIP CCM DB"},
143  { 0, NULL}
144 };
145 
146 
147 #define CFM_TLV_END 0
148 #define CFM_TLV_SENDER_ID 1
149 #define CFM_TLV_PORT_STATUS 2
150 #define CFM_TLV_INTERFACE_STATUS 3
151 #define CFM_TLV_DATA 4
152 #define CFM_TLV_REPLY_INGRESS 5
153 #define CFM_TLV_REPLY_EGRESS 6
154 #define CFM_TLV_PRIVATE 31
155 
156 static const struct tok cfm_tlv_values[] = {
157  { CFM_TLV_END, "End"},
158  { CFM_TLV_SENDER_ID, "Sender ID"},
159  { CFM_TLV_PORT_STATUS, "Port status"},
160  { CFM_TLV_INTERFACE_STATUS, "Interface status"},
161  { CFM_TLV_DATA, "Data"},
162  { CFM_TLV_REPLY_INGRESS, "Reply Ingress"},
163  { CFM_TLV_REPLY_EGRESS, "Reply Egress"},
164  { CFM_TLV_PRIVATE, "Organization Specific"},
165  { 0, NULL}
166 };
167 
168 /*
169  * TLVs
170  */
171 
175 };
176 
177 /* FIXME define TLV formats */
178 
179 static const struct tok cfm_tlv_port_status_values[] = {
180  { 1, "Blocked"},
181  { 2, "Up"},
182  { 0, NULL}
183 };
184 
185 static const struct tok cfm_tlv_interface_status_values[] = {
186  { 1, "Up"},
187  { 2, "Down"},
188  { 3, "Testing"},
189  { 5, "Dormant"},
190  { 6, "not present"},
191  { 7, "lower Layer down"},
192  { 0, NULL}
193 };
194 
195 #define CFM_CHASSIS_ID_CHASSIS_COMPONENT 1
196 #define CFM_CHASSIS_ID_INTERFACE_ALIAS 2
197 #define CFM_CHASSIS_ID_PORT_COMPONENT 3
198 #define CFM_CHASSIS_ID_MAC_ADDRESS 4
199 #define CFM_CHASSIS_ID_NETWORK_ADDRESS 5
200 #define CFM_CHASSIS_ID_INTERFACE_NAME 6
201 #define CFM_CHASSIS_ID_LOCAL 7
202 
203 static const struct tok cfm_tlv_senderid_chassisid_values[] = {
204  { 0, "Reserved"},
205  { CFM_CHASSIS_ID_CHASSIS_COMPONENT, "Chassis component"},
206  { CFM_CHASSIS_ID_INTERFACE_ALIAS, "Interface alias"},
207  { CFM_CHASSIS_ID_PORT_COMPONENT, "Port component"},
208  { CFM_CHASSIS_ID_MAC_ADDRESS, "MAC address"},
209  { CFM_CHASSIS_ID_NETWORK_ADDRESS, "Network address"},
210  { CFM_CHASSIS_ID_INTERFACE_NAME, "Interface name"},
211  { CFM_CHASSIS_ID_LOCAL, "Locally assigned"},
212  { 0, NULL}
213 };
214 
215 
216 static int
218  const u_char *tptr, const u_int length)
219 {
220  u_int network_addr_type;
221  u_int hexdump = FALSE;
222 
223  /*
224  * Although AFIs are typically 2 octets wide,
225  * 802.1ab specifies that this field width
226  * is only one octet.
227  */
228  if (length < 1) {
229  ND_PRINT("\n\t Network Address Type (invalid, no data");
230  return hexdump;
231  }
232  /* The calling function must make any due ND_TCHECK calls. */
233  network_addr_type = GET_U_1(tptr);
234  ND_PRINT("\n\t Network Address Type %s (%u)",
235  tok2str(af_values, "Unknown", network_addr_type),
236  network_addr_type);
237 
238  /*
239  * Resolve the passed in Address.
240  */
241  switch(network_addr_type) {
242  case AFNUM_INET:
243  if (length != 1 + 4) {
244  ND_PRINT("(invalid IPv4 address length %u)", length - 1);
245  hexdump = TRUE;
246  break;
247  }
248  ND_PRINT(", %s", GET_IPADDR_STRING(tptr + 1));
249  break;
250 
251  case AFNUM_INET6:
252  if (length != 1 + 16) {
253  ND_PRINT("(invalid IPv6 address length %u)", length - 1);
254  hexdump = TRUE;
255  break;
256  }
257  ND_PRINT(", %s", GET_IP6ADDR_STRING(tptr + 1));
258  break;
259 
260  default:
261  hexdump = TRUE;
262  break;
263  }
264 
265  return hexdump;
266 }
267 
268 void
270  const u_char *pptr, u_int length)
271 {
272  const struct cfm_common_header_t *cfm_common_header;
274  const struct cfm_tlv_header_t *cfm_tlv_header;
275  const uint8_t *tptr, *tlv_ptr;
276  const uint8_t *namesp;
277  u_int names_data_remaining;
278  uint8_t md_nameformat, md_namelength;
279  const uint8_t *md_name;
280  uint8_t ma_nameformat, ma_namelength;
281  const uint8_t *ma_name;
282  u_int hexdump, tlen, cfm_tlv_len, cfm_tlv_type, ccm_interval;
283 
284 
285  union {
286  const struct cfm_ccm_t *cfm_ccm;
287  const struct cfm_lbm_t *cfm_lbm;
288  const struct cfm_ltm_t *cfm_ltm;
289  const struct cfm_ltr_t *cfm_ltr;
290  } msg_ptr;
291 
292  ndo->ndo_protocol = "cfm";
293  tptr=pptr;
294  cfm_common_header = (const struct cfm_common_header_t *)pptr;
295  if (length < sizeof(*cfm_common_header))
296  goto tooshort;
297  ND_TCHECK_SIZE(cfm_common_header);
298 
299  /*
300  * Sanity checking of the header.
301  */
302  mdlevel_version = GET_U_1(cfm_common_header->mdlevel_version);
304  ND_PRINT("CFMv%u not supported, length %u",
306  return;
307  }
308 
309  opcode = GET_U_1(cfm_common_header->opcode);
310  ND_PRINT("CFMv%u %s, MD Level %u, length %u",
312  tok2str(cfm_opcode_values, "unknown (%u)", opcode),
314  length);
315 
316  /*
317  * In non-verbose mode just print the opcode and md-level.
318  */
319  if (ndo->ndo_vflag < 1) {
320  return;
321  }
322 
323  flags = GET_U_1(cfm_common_header->flags);
324  first_tlv_offset = GET_U_1(cfm_common_header->first_tlv_offset);
325  ND_PRINT("\n\tFirst TLV offset %u", first_tlv_offset);
326 
327  tptr += sizeof(struct cfm_common_header_t);
328  tlen = length - sizeof(struct cfm_common_header_t);
329 
330  /*
331  * Sanity check the first TLV offset.
332  */
333  if (first_tlv_offset > tlen) {
334  ND_PRINT(" (too large, must be <= %u)", tlen);
335  return;
336  }
337 
338  switch (opcode) {
339  case CFM_OPCODE_CCM:
340  msg_ptr.cfm_ccm = (const struct cfm_ccm_t *)tptr;
341  if (first_tlv_offset < sizeof(*msg_ptr.cfm_ccm)) {
342  ND_PRINT(" (too small 1, must be >= %zu)",
343  sizeof(*msg_ptr.cfm_ccm));
344  return;
345  }
346  if (tlen < sizeof(*msg_ptr.cfm_ccm))
347  goto tooshort;
348  ND_TCHECK_SIZE(msg_ptr.cfm_ccm);
349 
350  ccm_interval = CFM_EXTRACT_CCM_INTERVAL(flags);
351  ND_PRINT(", Flags [CCM Interval %u%s]",
352  ccm_interval,
353  flags & CFM_CCM_RDI_FLAG ?
354  ", RDI" : "");
355 
356  /*
357  * Resolve the CCM interval field.
358  */
359  if (ccm_interval) {
360  ND_PRINT("\n\t CCM Interval %.3fs"
361  ", min CCM Lifetime %.3fs, max CCM Lifetime %.3fs",
362  ccm_interval_base[ccm_interval],
365  }
366 
367  ND_PRINT("\n\t Sequence Number 0x%08x, MA-End-Point-ID 0x%04x",
368  GET_BE_U_4(msg_ptr.cfm_ccm->sequence),
369  GET_BE_U_2(msg_ptr.cfm_ccm->ma_epi));
370 
371  namesp = msg_ptr.cfm_ccm->names;
372  names_data_remaining = sizeof(msg_ptr.cfm_ccm->names);
373 
374  /*
375  * Resolve the MD fields.
376  */
377  md_nameformat = GET_U_1(namesp);
378  namesp++;
379  names_data_remaining--; /* We know this is != 0 */
380  if (md_nameformat != CFM_CCM_MD_FORMAT_NONE) {
381  md_namelength = GET_U_1(namesp);
382  namesp++;
383  names_data_remaining--; /* We know this is !=0 */
384  ND_PRINT("\n\t MD Name Format %s (%u), MD Name length %u",
386  md_nameformat),
387  md_nameformat,
388  md_namelength);
389 
390  /*
391  * -3 for the MA short name format and length and one byte
392  * of MA short name.
393  */
394  if (md_namelength > names_data_remaining - 3) {
395  ND_PRINT(" (too large, must be <= %u)", names_data_remaining - 2);
396  return;
397  }
398 
399  md_name = namesp;
400  ND_PRINT("\n\t MD Name: ");
401  switch (md_nameformat) {
404  nd_printjnp(ndo, md_name, md_namelength);
405  break;
406 
408  if (md_namelength == MAC_ADDR_LEN) {
409  ND_PRINT("\n\t MAC %s", GET_ETHERADDR_STRING(md_name));
410  } else {
411  ND_PRINT("\n\t MAC (length invalid)");
412  }
413  break;
414 
415  /* FIXME add printers for those MD formats - hexdump for now */
417  default:
418  print_unknown_data(ndo, md_name, "\n\t ",
419  md_namelength);
420  }
421  namesp += md_namelength;
422  names_data_remaining -= md_namelength;
423  } else {
424  ND_PRINT("\n\t MD Name Format %s (%u)",
426  md_nameformat),
427  md_nameformat);
428  }
429 
430 
431  /*
432  * Resolve the MA fields.
433  */
434  ma_nameformat = GET_U_1(namesp);
435  namesp++;
436  names_data_remaining--; /* We know this is != 0 */
437  ma_namelength = GET_U_1(namesp);
438  namesp++;
439  names_data_remaining--; /* We know this is != 0 */
440  ND_PRINT("\n\t MA Name-Format %s (%u), MA name length %u",
442  ma_nameformat),
443  ma_nameformat,
444  ma_namelength);
445 
446  if (ma_namelength > names_data_remaining) {
447  ND_PRINT(" (too large, must be <= %u)", names_data_remaining);
448  return;
449  }
450 
451  ma_name = namesp;
452  ND_PRINT("\n\t MA Name: ");
453  switch (ma_nameformat) {
455  nd_printjnp(ndo, ma_name, ma_namelength);
456  break;
457 
458  /* FIXME add printers for those MA formats - hexdump for now */
463  default:
464  print_unknown_data(ndo, ma_name, "\n\t ", ma_namelength);
465  }
466  break;
467 
468  case CFM_OPCODE_LTM:
469  msg_ptr.cfm_ltm = (const struct cfm_ltm_t *)tptr;
470  if (first_tlv_offset < sizeof(*msg_ptr.cfm_ltm)) {
471  ND_PRINT(" (too small 4, must be >= %zu)",
472  sizeof(*msg_ptr.cfm_ltm));
473  return;
474  }
475  if (tlen < sizeof(*msg_ptr.cfm_ltm))
476  goto tooshort;
477  ND_TCHECK_SIZE(msg_ptr.cfm_ltm);
478 
479  ND_PRINT(", Flags [%s]",
480  bittok2str(cfm_ltm_flag_values, "none", flags));
481 
482  ND_PRINT("\n\t Transaction-ID 0x%08x, ttl %u",
483  GET_BE_U_4(msg_ptr.cfm_ltm->transaction_id),
484  GET_U_1(msg_ptr.cfm_ltm->ttl));
485 
486  ND_PRINT("\n\t Original-MAC %s, Target-MAC %s",
487  GET_ETHERADDR_STRING(msg_ptr.cfm_ltm->original_mac),
488  GET_ETHERADDR_STRING(msg_ptr.cfm_ltm->target_mac));
489  break;
490 
491  case CFM_OPCODE_LTR:
492  msg_ptr.cfm_ltr = (const struct cfm_ltr_t *)tptr;
493  if (first_tlv_offset < sizeof(*msg_ptr.cfm_ltr)) {
494  ND_PRINT(" (too small 5, must be >= %zu)",
495  sizeof(*msg_ptr.cfm_ltr));
496  return;
497  }
498  if (tlen < sizeof(*msg_ptr.cfm_ltr))
499  goto tooshort;
500  ND_TCHECK_SIZE(msg_ptr.cfm_ltr);
501 
502  ND_PRINT(", Flags [%s]",
503  bittok2str(cfm_ltr_flag_values, "none", flags));
504 
505  ND_PRINT("\n\t Transaction-ID 0x%08x, ttl %u",
506  GET_BE_U_4(msg_ptr.cfm_ltr->transaction_id),
507  GET_U_1(msg_ptr.cfm_ltr->ttl));
508 
509  ND_PRINT("\n\t Replay-Action %s (%u)",
511  "Unknown",
512  GET_U_1(msg_ptr.cfm_ltr->replay_action)),
513  GET_U_1(msg_ptr.cfm_ltr->replay_action));
514  break;
515 
516  /*
517  * No message decoder yet.
518  * Hexdump everything up until the start of the TLVs
519  */
520  case CFM_OPCODE_LBR:
521  case CFM_OPCODE_LBM:
522  default:
523  print_unknown_data(ndo, tptr, "\n\t ",
524  tlen - first_tlv_offset);
525  break;
526  }
527 
528  tptr += first_tlv_offset;
529  tlen -= first_tlv_offset;
530 
531  while (tlen > 0) {
532  cfm_tlv_header = (const struct cfm_tlv_header_t *)tptr;
533 
534  /* Enough to read the tlv type ? */
535  cfm_tlv_type = GET_U_1(cfm_tlv_header->type);
536 
537  ND_PRINT("\n\t%s TLV (0x%02x)",
538  tok2str(cfm_tlv_values, "Unknown", cfm_tlv_type),
539  cfm_tlv_type);
540 
541  if (cfm_tlv_type == CFM_TLV_END) {
542  /* Length is "Not present if the Type field is 0." */
543  return;
544  }
545 
546  /* do we have the full tlv header ? */
547  if (tlen < sizeof(struct cfm_tlv_header_t))
548  goto tooshort;
549  ND_TCHECK_LEN(tptr, sizeof(struct cfm_tlv_header_t));
550  cfm_tlv_len=GET_BE_U_2(cfm_tlv_header->length);
551 
552  ND_PRINT(", length %u", cfm_tlv_len);
553 
554  tptr += sizeof(struct cfm_tlv_header_t);
555  tlen -= sizeof(struct cfm_tlv_header_t);
556  tlv_ptr = tptr;
557 
558  /* do we have the full tlv ? */
559  if (tlen < cfm_tlv_len)
560  goto tooshort;
561  ND_TCHECK_LEN(tptr, cfm_tlv_len);
562  hexdump = FALSE;
563 
564  switch(cfm_tlv_type) {
565  case CFM_TLV_PORT_STATUS:
566  if (cfm_tlv_len < 1) {
567  ND_PRINT(" (too short, must be >= 1)");
568  return;
569  }
570  ND_PRINT(", Status: %s (%u)",
571  tok2str(cfm_tlv_port_status_values, "Unknown", GET_U_1(tptr)),
572  GET_U_1(tptr));
573  break;
574 
576  if (cfm_tlv_len < 1) {
577  ND_PRINT(" (too short, must be >= 1)");
578  return;
579  }
580  ND_PRINT(", Status: %s (%u)",
582  GET_U_1(tptr));
583  break;
584 
585  case CFM_TLV_PRIVATE:
586  if (cfm_tlv_len < 4) {
587  ND_PRINT(" (too short, must be >= 4)");
588  return;
589  }
590  ND_PRINT(", Vendor: %s (%u), Sub-Type %u",
591  tok2str(oui_values,"Unknown", GET_BE_U_3(tptr)),
592  GET_BE_U_3(tptr),
593  GET_U_1(tptr + 3));
594  hexdump = TRUE;
595  break;
596 
597  case CFM_TLV_SENDER_ID:
598  {
599  u_int chassis_id_type, chassis_id_length;
600  u_int mgmt_addr_length;
601 
602  if (cfm_tlv_len < 1) {
603  ND_PRINT(" (too short, must be >= 1)");
604  goto next_tlv;
605  }
606 
607  /*
608  * Get the Chassis ID length and check it.
609  * IEEE 802.1Q-2014 Section 21.5.3.1
610  */
611  chassis_id_length = GET_U_1(tptr);
612  tptr++;
613  tlen--;
614  cfm_tlv_len--;
615 
616  if (chassis_id_length) {
617  /*
618  * IEEE 802.1Q-2014 Section 21.5.3.2: Chassis ID Subtype, references
619  * IEEE 802.1AB-2005 Section 9.5.2.2, subsequently
620  * IEEE 802.1AB-2016 Section 8.5.2.2: chassis ID subtype
621  */
622  if (cfm_tlv_len < 1) {
623  ND_PRINT("\n\t (TLV too short)");
624  goto next_tlv;
625  }
626  chassis_id_type = GET_U_1(tptr);
627  cfm_tlv_len--;
628  ND_PRINT("\n\t Chassis-ID Type %s (%u), Chassis-ID length %u",
630  "Unknown",
631  chassis_id_type),
632  chassis_id_type,
633  chassis_id_length);
634 
635  if (cfm_tlv_len < chassis_id_length) {
636  ND_PRINT("\n\t (TLV too short)");
637  goto next_tlv;
638  }
639 
640  /* IEEE 802.1Q-2014 Section 21.5.3.3: Chassis ID */
641  switch (chassis_id_type) {
643  if (chassis_id_length != MAC_ADDR_LEN) {
644  ND_PRINT(" (invalid MAC address length)");
645  hexdump = TRUE;
646  break;
647  }
648  ND_PRINT("\n\t MAC %s", GET_ETHERADDR_STRING(tptr + 1));
649  break;
650 
652  hexdump |= cfm_network_addr_print(ndo, tptr + 1, chassis_id_length);
653  break;
654 
655  case CFM_CHASSIS_ID_INTERFACE_NAME: /* fall through */
660  nd_printjnp(ndo, tptr + 1, chassis_id_length);
661  break;
662 
663  default:
664  hexdump = TRUE;
665  break;
666  }
667  cfm_tlv_len -= chassis_id_length;
668 
669  tptr += 1 + chassis_id_length;
670  tlen -= 1 + chassis_id_length;
671  }
672 
673  /*
674  * Check if there is a Management Address.
675  * IEEE 802.1Q-2014 Section 21.5.3.4: Management Address Domain Length
676  * This and all subsequent fields are not present if the TLV length
677  * allows only the above fields.
678  */
679  if (cfm_tlv_len == 0) {
680  /* No, there isn't; we're done. */
681  break;
682  }
683 
684  /* Here mgmt_addr_length stands for the management domain length. */
685  mgmt_addr_length = GET_U_1(tptr);
686  tptr++;
687  tlen--;
688  cfm_tlv_len--;
689  ND_PRINT("\n\t Management Address Domain Length %u", mgmt_addr_length);
690  if (mgmt_addr_length) {
691  /* IEEE 802.1Q-2014 Section 21.5.3.5: Management Address Domain */
692  if (cfm_tlv_len < mgmt_addr_length) {
693  ND_PRINT("\n\t (TLV too short)");
694  goto next_tlv;
695  }
696  cfm_tlv_len -= mgmt_addr_length;
697  /*
698  * XXX - this is an OID; print it as such.
699  */
700  hex_print(ndo, "\n\t Management Address Domain: ", tptr, mgmt_addr_length);
701  tptr += mgmt_addr_length;
702  tlen -= mgmt_addr_length;
703 
704  /*
705  * IEEE 802.1Q-2014 Section 21.5.3.6: Management Address Length
706  * This field is present if Management Address Domain Length is not 0.
707  */
708  if (cfm_tlv_len < 1) {
709  ND_PRINT(" (Management Address Length is missing)");
710  hexdump = TRUE;
711  break;
712  }
713 
714  /* Here mgmt_addr_length stands for the management address length. */
715  mgmt_addr_length = GET_U_1(tptr);
716  tptr++;
717  tlen--;
718  cfm_tlv_len--;
719  ND_PRINT("\n\t Management Address Length %u", mgmt_addr_length);
720  if (mgmt_addr_length) {
721  /* IEEE 802.1Q-2014 Section 21.5.3.7: Management Address */
722  if (cfm_tlv_len < mgmt_addr_length) {
723  ND_PRINT("\n\t (TLV too short)");
724  return;
725  }
726  cfm_tlv_len -= mgmt_addr_length;
727  /*
728  * XXX - this is a TransportDomain; print it as such.
729  */
730  hex_print(ndo, "\n\t Management Address: ", tptr, mgmt_addr_length);
731  tptr += mgmt_addr_length;
732  tlen -= mgmt_addr_length;
733  }
734  }
735  break;
736  }
737 
738  /*
739  * FIXME those are the defined TLVs that lack a decoder
740  * you are welcome to contribute code ;-)
741  */
742 
743  case CFM_TLV_DATA:
746  default:
747  hexdump = TRUE;
748  break;
749  }
750  /* do we want to see an additional hexdump ? */
751  if (hexdump || ndo->ndo_vflag > 1)
752  print_unknown_data(ndo, tlv_ptr, "\n\t ", cfm_tlv_len);
753 
754 next_tlv:
755  tptr+=cfm_tlv_len;
756  tlen-=cfm_tlv_len;
757  }
758  return;
759 
760 tooshort:
761  ND_PRINT("\n\t\t packet is too short");
762  return;
763 
764 trunc:
765  nd_print_trunc(ndo);
766 }
#define GET_IPADDR_STRING(p)
Definition: addrtoname.h:120
#define GET_IP6ADDR_STRING(p)
Definition: addrtoname.h:121
#define GET_ETHERADDR_STRING(p)
Definition: addrtoname.h:117
const struct tok af_values[]
Definition: af.c:26
#define AFNUM_INET6
Definition: af.h:23
#define AFNUM_INET
Definition: af.h:22
#define GET_BE_U_4(p)
Definition: extract.h:877
#define GET_BE_U_3(p)
Definition: extract.h:876
#define GET_BE_U_2(p)
Definition: extract.h:875
#define GET_U_1(p)
Definition: extract.h:872
#define TRUE
#define FALSE
unsigned char nd_uint16_t[2]
Definition: netdissect.h:47
int print_unknown_data(netdissect_options *, const u_char *, const char *, u_int)
Definition: util-print.c:441
void nd_printjnp(netdissect_options *, const u_char *, u_int)
Definition: util-print.c:182
#define ND_TCHECK_LEN(p, l)
Definition: netdissect.h:368
const char * tok2str(const struct tok *, const char *, u_int)
Definition: util-print.c:485
#define ND_TCHECK_SIZE(p)
Definition: netdissect.h:372
unsigned char nd_mac_addr[6U]
Definition: netdissect.h:103
#define MAC_ADDR_LEN
Definition: netdissect.h:102
char * bittok2str(const struct tok *, const char *, u_int)
Definition: util-print.c:558
unsigned char nd_byte
Definition: netdissect.h:108
void hex_print(netdissect_options *, const char *ident, const u_char *cp, u_int)
Definition: print-ascii.c:212
void nd_print_trunc(netdissect_options *)
Definition: util-print.c:409
#define ND_PRINT(...)
Definition: netdissect.h:385
unsigned char nd_uint32_t[4]
Definition: netdissect.h:49
unsigned char nd_uint8_t[1]
Definition: netdissect.h:46
const struct tok oui_values[]
Definition: oui.c:26
#define CFM_CHASSIS_ID_INTERFACE_ALIAS
Definition: print-cfm.c:196
static const struct tok cfm_md_nameformat_values[]
Definition: print-cfm.c:86
#define CFM_TLV_REPLY_INGRESS
Definition: print-cfm.c:152
static const struct tok cfm_opcode_values[]
Definition: print-cfm.c:50
#define CFM_TLV_REPLY_EGRESS
Definition: print-cfm.c:153
#define CFM_OPCODE_LTM
Definition: print-cfm.c:48
#define CFM_CHASSIS_ID_MAC_ADDRESS
Definition: print-cfm.c:198
#define CFM_CCM_MA_FORMAT_VPN
Definition: print-cfm.c:99
#define CFM_CCM_MA_FORMAT_VID
Definition: print-cfm.c:96
static const struct tok cfm_ltr_replay_action_values[]
Definition: print-cfm.c:139
#define CFM_CCM_MA_FORMAT_INT
Definition: print-cfm.c:98
#define CFM_TLV_DATA
Definition: print-cfm.c:151
static const struct tok cfm_ltr_flag_values[]
Definition: print-cfm.c:132
#define CFM_EXTRACT_MD_LEVEL(x)
Definition: print-cfm.c:42
#define CFM_OPCODE_CCM
Definition: print-cfm.c:44
void cfm_print(netdissect_options *ndo, const u_char *pptr, u_int length)
Definition: print-cfm.c:269
#define CFM_CHASSIS_ID_PORT_COMPONENT
Definition: print-cfm.c:197
static int cfm_network_addr_print(netdissect_options *ndo, const u_char *tptr, const u_int length)
Definition: print-cfm.c:217
#define CFM_CCM_MD_FORMAT_DNS
Definition: print-cfm.c:82
static const struct tok cfm_tlv_values[]
Definition: print-cfm.c:156
#define CFM_CHASSIS_ID_NETWORK_ADDRESS
Definition: print-cfm.c:199
#define CFM_EXTRACT_VERSION(x)
Definition: print-cfm.c:41
#define CFM_CHASSIS_ID_LOCAL
Definition: print-cfm.c:201
#define CFM_OPCODE_LBR
Definition: print-cfm.c:45
#define CFM_OPCODE_LTR
Definition: print-cfm.c:47
#define CFM_CCM_MA_FORMAT_8021
Definition: print-cfm.c:95
#define CFM_TLV_END
Definition: print-cfm.c:147
#define CFM_OPCODE_LBM
Definition: print-cfm.c:46
static const struct tok cfm_ma_nameformat_values[]
Definition: print-cfm.c:101
static const struct tok cfm_tlv_senderid_chassisid_values[]
Definition: print-cfm.c:203
#define CFM_EXTRACT_CCM_INTERVAL(x)
Definition: print-cfm.c:78
#define CFM_CHASSIS_ID_INTERFACE_NAME
Definition: print-cfm.c:200
#define CCM_INTERVAL_MAX_MULTIPLIER
Definition: print-cfm.c:75
#define CFM_TLV_PORT_STATUS
Definition: print-cfm.c:149
#define CFM_TLV_PRIVATE
Definition: print-cfm.c:154
#define CFM_CCM_MD_FORMAT_NONE
Definition: print-cfm.c:81
#define CFM_CCM_MD_FORMAT_MAC
Definition: print-cfm.c:83
static const struct tok cfm_tlv_interface_status_values[]
Definition: print-cfm.c:185
#define CFM_CCM_MA_FORMAT_CHAR
Definition: print-cfm.c:97
#define CFM_TLV_INTERFACE_STATUS
Definition: print-cfm.c:150
static const struct tok cfm_ltm_flag_values[]
Definition: print-cfm.c:121
#define CCM_INTERVAL_MIN_MULTIPLIER
Definition: print-cfm.c:74
#define CFM_CCM_MD_FORMAT_8021
Definition: print-cfm.c:80
#define CFM_CCM_RDI_FLAG
Definition: print-cfm.c:77
#define CFM_CCM_MD_FORMAT_CHAR
Definition: print-cfm.c:84
static const struct tok cfm_tlv_port_status_values[]
Definition: print-cfm.c:179
#define CFM_VERSION
Definition: print-cfm.c:40
#define CFM_TLV_SENDER_ID
Definition: print-cfm.c:148
static const float ccm_interval_base[8]
Definition: print-cfm.c:73
#define CFM_CHASSIS_ID_CHASSIS_COMPONENT
Definition: print-cfm.c:195
static const struct tok opcode[]
Definition: print-lwres.c:180
nd_byte names[48]
Definition: print-cfm.c:65
nd_uint16_t ma_epi
Definition: print-cfm.c:64
nd_byte itu_t_y_1731[16]
Definition: print-cfm.c:66
nd_uint32_t sequence
Definition: print-cfm.c:63
nd_uint8_t flags
Definition: print-cfm.c:36
nd_uint8_t opcode
Definition: print-cfm.c:35
nd_uint8_t first_tlv_offset
Definition: print-cfm.c:37
nd_uint8_t mdlevel_version
Definition: print-cfm.c:34
nd_uint32_t transaction_id
Definition: print-cfm.c:111
nd_uint8_t ttl
Definition: print-cfm.c:116
nd_mac_addr target_mac
Definition: print-cfm.c:118
nd_mac_addr original_mac
Definition: print-cfm.c:117
nd_uint32_t transaction_id
Definition: print-cfm.c:115
nd_uint8_t ttl
Definition: print-cfm.c:128
nd_uint32_t transaction_id
Definition: print-cfm.c:127
nd_uint8_t replay_action
Definition: print-cfm.c:129
nd_uint16_t length
Definition: print-cfm.c:174
nd_uint8_t type
Definition: print-cfm.c:173
const char * ndo_protocol
Definition: netdissect.h:218