checkAPIs.pl: support for new-style dissectors in check_hf_entries
[metze/wireshark/wip.git] / epan / dissectors / packet-msdp.c
1 /* packet-msdp.c
2  * Routines for Multicast Source Discovery Protocol (MSDP) dissection.
3  * RFC 3618
4  *
5  * Copyright 2001, Heikki Vatiainen <hessu@cs.tut.fi>
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * SPDX-License-Identifier: GPL-2.0-or-later
12  */
13
14 #include "config.h"
15
16 #include <epan/packet.h>
17 #include <epan/to_str.h>
18 #include <epan/expert.h>
19
20 void proto_register_msdp(void);
21 void proto_reg_handoff_msdp(void);
22
23 /* MSDP (Type-Length-Value) TLV types. The messages are a sequence of TLVs. */
24 enum { MSDP_SA     = 1,
25        MSDP_SA_REQ,
26        MSDP_SA_RSP,
27        MSDP_KEEP_ALIVE,
28        MSDP_NOTIFICATION,  /* draft 10, but not RFC 3618 */
29
30        /* These are only assigned in MSDP spec. Their use is specified
31         * elsewhere */
32        MSDP_TRACE_IN_PROGRESS,
33        MSDP_TRACE_REPLY
34 };
35
36 static const value_string msdp_types[] = {
37         { MSDP_SA,                "IPv4 Source-Active"           },
38         { MSDP_SA_REQ,            "IPv4 Source-Active Request"   },
39         { MSDP_SA_RSP,            "IPv4 Source-Active Response"  },
40         { MSDP_KEEP_ALIVE,        "KeepAlive"                    },
41         { MSDP_NOTIFICATION,      "Notification"                 },
42
43         { MSDP_TRACE_IN_PROGRESS, "MSDP traceroute in progress"  },
44         { MSDP_TRACE_REPLY,       "MSDP traceroute reply"        },
45         { 0, NULL },
46 };
47
48
49 /* Error codes */
50 enum { MESSAGE_HEADER_ERROR = 1,
51        SA_REQUEST_ERROR,
52        SA_MESSAGE_SA_RESPONSE_ERROR,
53        HOLD_TIMER_EXPIRED,
54        FSM_ERROR,
55        NOTIFICATION,
56        CEASE
57 };
58
59 static const value_string error_vals[] = {
60         { MESSAGE_HEADER_ERROR,         "Message Header Error"         },
61         { SA_REQUEST_ERROR,             "SA-Request Error"             },
62         { SA_MESSAGE_SA_RESPONSE_ERROR, "SA-Message/SA-Response Error" },
63         { HOLD_TIMER_EXPIRED,           "Hold Timer Expired"           },
64         { FSM_ERROR,                    "Finite State Machine Error"   },
65         { NOTIFICATION,                 "Notification"                 },
66         { CEASE,                        "Cease"                        },
67         { 0, NULL },
68 };
69
70
71 /* Message Header Error subcodes */
72 static const value_string hdr_error_vals[] = {
73         { 0, "Unspecific"         },
74         { 2, "Bad Message Length" },
75         { 3, "Bad Message Type"   },
76         { 0, NULL },
77 };
78
79 /* SA-Request Error subcodes (the O-bit is always clear) */
80 static const value_string sa_req_error_vals[] = {
81         { 0, "Unspecific"    },
82         { 1, "Invalid Group" },
83         { 0, NULL },
84 };
85
86 /* SA-Message/SA-Response Error subcodes */
87 static const value_string sa_msg_error_vals[] = {
88         { 0, "Unspecific"                             },
89         { 1, "Invalid Entry Count"                    },
90         { 2, "Invalid RP Address"                     },
91         { 3, "Invalid Group Address"                  },
92         { 4, "Invalid Source Address"                 },
93         { 5, "Invalid Sprefix Length"                 },
94         { 6, "Looping SA (Self is RP)"                },
95         { 7, "Unknown Encapsulation"                  },
96         { 8, "Administrative Scope Boundary Violated" },
97         { 0, NULL },
98 };
99
100 /* Finite State Machine Error subcodes (the O-bit is always clear) */
101 static const value_string fsm_error_vals[] = {
102         { 0, "Unspecific"                        },
103         { 1, "Unexpected Message Type FSM Error" },
104         { 0, NULL },
105 };
106
107 /*
108  * Hold Timer Expired subcodes (the O-bit is always clear):
109  * Notification subcodes (the O-bit is always clear):
110  * Cease subcodes (the O-bit is always clear):
111  *
112  * These have only "Unspecific" specified.
113  */
114 static const value_string sa_unspec_error_vals[] = {
115         { 0, "Unspecific" },
116         { 0, NULL },
117 };
118
119 #define MSDP_PORT  639
120
121 /* Initialize the protocol and registered fields */
122 static int proto_msdp = -1;
123 static int hf_msdp_type = -1;
124 static int hf_msdp_length = -1;
125
126 static int hf_msdp_sa_entry_count = -1;
127 static int hf_msdp_sa_rp_addr = -1;
128 static int hf_msdp_sa_reserved = -1;
129 static int hf_msdp_sa_sprefix_len = -1;
130 static int hf_msdp_sa_group_addr = -1;
131 static int hf_msdp_sa_src_addr = -1;
132
133 static int hf_msdp_sa_req_res = -1;
134 static int hf_msdp_sa_req_group = -1;
135
136 static int hf_msdp_not_o = -1;
137 static int hf_msdp_not_error = -1;
138 static int hf_msdp_not_error_sub = -1;
139
140 static int hf_msdp_not_group_address = -1;
141 static int hf_msdp_not_rp_address = -1;
142 static int hf_msdp_not_source_address = -1;
143 static int hf_msdp_not_res = -1;
144 static int hf_msdp_not_entry_count = -1;
145 static int hf_msdp_not_sprefix_len = -1;
146
147 static int hf_msdp_tlv_contents = -1;
148 static int hf_msdp_trailing_junk = -1;
149 static int hf_msdp_unknown_data = -1;
150
151 static gint ett_msdp = -1;
152 static gint ett_msdp_sa_entry = -1;
153 static gint ett_msdp_sa_enc_data = -1;
154 static gint ett_msdp_not_data = -1;
155
156 static expert_field ei_msdp_tlv_len_too_short = EI_INIT;
157 static expert_field ei_msdp_tlv_len_too_long = EI_INIT;
158
159 static dissector_handle_t ip_handle;
160
161
162 static void
163 dissect_msdp_sa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
164     int *offset, int length, proto_item *length_item);
165 static void
166 dissect_msdp_notification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
167     int *offset, guint16 tlv_len, proto_item *length_item);
168
169
170 static int
171 dissect_msdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
172 {
173         proto_item *ti;
174         proto_tree *msdp_tree;
175         proto_item *length_item;
176         int         offset;
177         guint32     type;
178         guint32     length;
179
180
181         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSDP");
182
183         col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(tvb_get_guint8(tvb, 0),
184                                                                      msdp_types,
185                                                                      "<Unknown MSDP TLV type>"));
186
187         ti = proto_tree_add_item(tree, proto_msdp, tvb, 0, -1, ENC_NA);
188         msdp_tree = proto_item_add_subtree(ti, ett_msdp);
189
190         offset = 0;
191         while (tvb_reported_length_remaining(tvb, offset) != 0) {
192                 proto_tree_add_item_ret_uint(msdp_tree, hf_msdp_type, tvb, offset, 1, ENC_BIG_ENDIAN, &type);
193                 length_item = proto_tree_add_item_ret_uint(msdp_tree, hf_msdp_length, tvb, offset + 1, 2, ENC_BIG_ENDIAN, &length);
194                 if (length < 3) {
195                         expert_add_info_format(pinfo, length_item,
196                             &ei_msdp_tlv_len_too_short,
197                             "TLV length < 3");
198                         break;
199                 }
200                 offset += 3;
201                 length -= 3;
202
203                 switch (type) {
204                 case MSDP_SA:
205                         dissect_msdp_sa(tvb, pinfo, msdp_tree, &offset,
206                                         length, length_item);
207                         break;
208                 case MSDP_SA_REQ:
209                         /*
210                          * This type is mentioned in the RFC but the format
211                          * isn't described.
212                          */
213                         if (length < 1) {
214                                 expert_add_info_format(pinfo, length_item,
215                                     &ei_msdp_tlv_len_too_short,
216                                     "TLV length for IPv4 Source-Active Request < 8");
217                                 break;
218                         }
219                         proto_tree_add_item(msdp_tree, hf_msdp_sa_req_res, tvb, offset, 1, ENC_BIG_ENDIAN);
220                         offset += 1;
221                         length -= 1;
222                         if (length < 4) {
223                                 expert_add_info_format(pinfo, length_item,
224                                     &ei_msdp_tlv_len_too_short,
225                                     "TLV length for IPv4 Source-Active Request < 8");
226                                 offset += length;
227                                 break;
228                         }
229                         proto_tree_add_item(msdp_tree, hf_msdp_sa_req_group, tvb, offset, 4, ENC_BIG_ENDIAN);
230                         offset += 4;
231                         length -= 4;
232                         if (length > 0) {
233                                 expert_add_info_format(pinfo, length_item,
234                                     &ei_msdp_tlv_len_too_long,
235                                     "TLV length for KeepAlive > 8");
236                                 proto_tree_add_item(tree, hf_msdp_trailing_junk, tvb, offset, length, ENC_NA);
237                                 offset += length;
238                         }
239                         break;
240                 case MSDP_SA_RSP:
241                         /*
242                          * This type is mentioned in the RFC but the format
243                          * isn't described.
244                          */
245                         dissect_msdp_sa(tvb, pinfo, msdp_tree, &offset,
246                                         length, length_item);
247                         break;
248                 case MSDP_KEEP_ALIVE:
249                         if (length > 0) {
250                                 expert_add_info_format(pinfo, length_item,
251                                     &ei_msdp_tlv_len_too_long,
252                                     "TLV length for KeepAlive > 3");
253                                 proto_tree_add_item(tree, hf_msdp_trailing_junk, tvb, offset, length, ENC_NA);
254                                 offset += length;
255                         }
256                         break;
257                 case MSDP_NOTIFICATION:
258                         /*
259                          * This was in draft 10, but is reserved in the
260                          * RFC.
261                          */
262                         dissect_msdp_notification(tvb, pinfo, msdp_tree, &offset, length, length_item);
263                         break;
264                 default:
265                         if (length > 0)
266                                 proto_tree_add_item(msdp_tree, hf_msdp_tlv_contents, tvb, offset, length, ENC_NA);
267                         offset += length;
268                         break;
269                 }
270         }
271
272         return tvb_captured_length(tvb);
273 }
274
275 /* Both Source-Active and Source-Active Response have the same format
276  * with one exception. Encapsulated multicast data is not allowed in
277  * SA Response.
278  */
279 static void dissect_msdp_sa(tvbuff_t *tvb, packet_info *pinfo,
280     proto_tree *tree, int *offset, int length, proto_item *length_item)
281 {
282         guint32 entries;
283
284         if (length < 1) {
285                 expert_add_info_format(pinfo, length_item,
286                     &ei_msdp_tlv_len_too_short,
287                     "TLV length for IPv4 Source-Active or Source-Active Response < 5");
288                 return;
289         }
290         proto_tree_add_item_ret_uint(tree, hf_msdp_sa_entry_count, tvb, *offset, 1, ENC_BIG_ENDIAN, &entries);
291         *offset += 1;
292         length -= 1;
293
294         if (length < 4) {
295                 expert_add_info_format(pinfo, length_item,
296                     &ei_msdp_tlv_len_too_short,
297                     "TLV length for IPv4 Source-Active or Source-Active Response < 5");
298                 *offset += length;
299                 return;
300         }
301         proto_tree_add_item(tree, hf_msdp_sa_rp_addr, tvb, *offset, 4, ENC_BIG_ENDIAN);
302         *offset += 4;
303         length -= 4;
304
305         /* Put each of the (S,G) entries in their own subtree.
306          * This is probably visually better.
307          */
308         while (entries-- > 0) {
309                 proto_tree *entry_tree;
310
311                 if (length < 12) {
312                         expert_add_info_format(pinfo, length_item,
313                             &ei_msdp_tlv_len_too_short,
314                             "TLV length for IPv4 Source-Active or Source-Active Response too short");
315                         *offset += length;
316                         return;
317                 }
318                 entry_tree = proto_tree_add_subtree_format(tree, tvb, *offset, 12, ett_msdp_sa_entry, NULL,
319                                          "(S,G) block: %s/%u -> %s",
320                                          tvb_ip_to_str(tvb, *offset + 8),
321                                          tvb_get_guint8(tvb, *offset + 3),
322                                          tvb_ip_to_str(tvb, *offset + 4));
323
324                 proto_tree_add_item(entry_tree, hf_msdp_sa_reserved, tvb, *offset, 3, ENC_BIG_ENDIAN);
325                 *offset += 3;
326                 length -= 3;
327                 proto_tree_add_item(entry_tree, hf_msdp_sa_sprefix_len, tvb, *offset, 1, ENC_BIG_ENDIAN);
328                 *offset += 1;
329                 length -= 1;
330                 proto_tree_add_item(entry_tree, hf_msdp_sa_group_addr, tvb, *offset, 4, ENC_BIG_ENDIAN);
331                 *offset += 4;
332                 length -= 4;
333                 proto_tree_add_item(entry_tree, hf_msdp_sa_src_addr, tvb, *offset, 4, ENC_BIG_ENDIAN);
334                 *offset += 4;
335                 length -= 4;
336         }
337
338         /*
339          * Check if an encapsulated multicast IPv4 packet follows
340          */
341         if (length > 0) {
342                 proto_tree *enc_tree;
343                 gint reported_length;
344                 tvbuff_t *next_tvb;
345
346                 enc_tree = proto_tree_add_subtree_format(tree, tvb, *offset, length,
347                                          ett_msdp_sa_enc_data, NULL, "Encapsulated IPv4 packet: %u bytes",
348                                          length);
349
350                 reported_length = tvb_reported_length_remaining(tvb, *offset);
351                 DISSECTOR_ASSERT(reported_length >= 0);
352                 if (reported_length > length)
353                         reported_length = length;
354
355                 next_tvb = tvb_new_subset_length(tvb, *offset, reported_length);
356                 /* Set the protocol and information columns read-only so
357                  * that they reflect the MSDP packet rather than the
358                  * encapsulated packet.
359                  */
360                 col_set_writable(pinfo->cinfo, COL_PROTOCOL, FALSE);
361                 col_set_writable(pinfo->cinfo, COL_INFO, FALSE);
362                 call_dissector(ip_handle, next_tvb, pinfo, enc_tree);
363         }
364         *offset += length;
365
366         return;
367 }
368
369 /* Note: updates *offset */
370 static void add_notification_data_ipv4addr(tvbuff_t *tvb, proto_tree *tree, int *offset, int hf_addr)
371 {
372         proto_tree_add_item(tree, hf_msdp_not_res, tvb, *offset, 3, ENC_BIG_ENDIAN);
373         *offset += 3;
374         proto_tree_add_item(tree, hf_addr, tvb, *offset, 4, ENC_BIG_ENDIAN);
375         *offset += 4;
376
377         return;
378 }
379
380 static void dissect_msdp_notification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, guint16 tlv_len, proto_item *length_item)
381 {
382         guint8              error, error_sub;
383         const value_string *vals;
384         gint reported_length;
385         tvbuff_t *next_tvb;
386
387         if (tlv_len < 1) {
388                 expert_add_info_format(pinfo, length_item,
389                     &ei_msdp_tlv_len_too_short,
390                     "TLV length for Notification < 4");
391                 return;
392         }
393         proto_tree_add_item(tree, hf_msdp_not_o, tvb, *offset, 1, ENC_BIG_ENDIAN);
394         proto_tree_add_item(tree, hf_msdp_not_error, tvb, *offset, 1, ENC_BIG_ENDIAN);
395         error = tvb_get_guint8(tvb, *offset);
396         error &= 0x7F;             /* Error is 7-bit field. O-bit is bit 8 */
397         *offset += 1;
398         tlv_len -= 1;
399
400         /* Depending on the Error Code, we collect the correct
401          * value_strings for the Error subcode
402          */
403         switch (error) {
404         case MESSAGE_HEADER_ERROR:
405                 vals = hdr_error_vals;
406                 break;
407         case SA_REQUEST_ERROR:
408                 vals = sa_req_error_vals;
409                 break;
410         case SA_MESSAGE_SA_RESPONSE_ERROR:
411                 vals = sa_msg_error_vals;
412                 break;
413         case FSM_ERROR:
414                 vals = fsm_error_vals;
415                 break;
416         case HOLD_TIMER_EXPIRED:
417         case NOTIFICATION:
418         case CEASE:
419                 vals = sa_unspec_error_vals;
420                 break;
421         default:
422                 vals = sa_unspec_error_vals;
423                 break;
424         }
425
426         if (tlv_len < 1) {
427                 expert_add_info_format(pinfo, length_item,
428                     &ei_msdp_tlv_len_too_short,
429                     "TLV length for Notification < 5");
430                 return;
431         }
432         error_sub = tvb_get_guint8(tvb, *offset);
433         proto_tree_add_uint_format_value(tree, hf_msdp_not_error_sub, tvb, *offset, 1,
434                                    error_sub, "%s (%u)",
435                                    val_to_str_const(error_sub, vals, "<Unknown Error subcode>"),
436                                    error_sub);
437         *offset += 1;
438         tlv_len -= 1;
439
440         /* Do switch again, this time to dissect the data portion
441          * correctly. Ugly.
442          */
443         switch (error) {
444         case SA_REQUEST_ERROR:
445                 if (tlv_len < 7) {
446                         expert_add_info_format(pinfo, length_item,
447                             &ei_msdp_tlv_len_too_short,
448                             "TLV length for Notification SA-Request Error < 12");
449                         *offset += tlv_len;
450                         return;
451                 }
452                 add_notification_data_ipv4addr(tvb, tree, offset, hf_msdp_not_group_address);
453                 tlv_len -= 7;
454                 break;
455         case SA_MESSAGE_SA_RESPONSE_ERROR:
456                 if (error_sub == 0) {
457                         break;
458                 } else if (error_sub == 1) {
459                         if (tlv_len < 1) {
460                                 expert_add_info_format(pinfo, length_item,
461                                     &ei_msdp_tlv_len_too_short,
462                                     "TLV length for Notification SA-Response Invalid Entry Count Error < 6");
463                                 return;
464                         }
465                         proto_tree_add_item(tree, hf_msdp_not_entry_count, tvb, *offset, 1, ENC_BIG_ENDIAN);
466                         *offset += 1;
467                         tlv_len -= 1;
468                         break;
469                 } else if (error_sub == 2) {
470                         if (tlv_len < 7) {
471                                 expert_add_info_format(pinfo, length_item,
472                                     &ei_msdp_tlv_len_too_short,
473                                     "TLV length for Notification SA-Response Invalid RP Address Error < 12");
474                                 *offset += tlv_len;
475                                 return;
476                         }
477                         add_notification_data_ipv4addr(tvb, tree, offset, hf_msdp_not_rp_address);
478                         tlv_len -= 7;
479                         break;
480                 } else if (error_sub == 3 || error_sub == 8) {
481                         if (tlv_len < 7) {
482                                 expert_add_info_format(pinfo, length_item,
483                                     &ei_msdp_tlv_len_too_short,
484                                     "TLV length for Notification SA-Response %s Error < 12",
485                                     (error_sub == 3) ? "Invalid Group Address"
486                                                      : "Administrative Scope Boundary Violated");
487                                 *offset += tlv_len;
488                                 return;
489                         }
490                         add_notification_data_ipv4addr(tvb, tree, offset, hf_msdp_not_group_address);
491                         tlv_len -= 7;
492                         break;
493                 } else if (error_sub == 4) {
494                         if (tlv_len < 7) {
495                                 expert_add_info_format(pinfo, length_item,
496                                     &ei_msdp_tlv_len_too_short,
497                                     "TLV length for Notification SA-Response Invalid Source Address Error < 12");
498                                 *offset += tlv_len;
499                                 return;
500                         }
501                         add_notification_data_ipv4addr(tvb, tree, offset, hf_msdp_not_source_address);
502                         tlv_len -= 7;
503                         break;
504                 } else if (error_sub == 5) {
505                         if (tlv_len < 1) {
506                                 expert_add_info_format(pinfo, length_item,
507                                     &ei_msdp_tlv_len_too_short,
508                                     "TLV length for Notification SA-Response Invalid Invalid Sprefix Length Error < 6");
509                                 return;
510                         }
511                         proto_tree_add_item(tree, hf_msdp_not_sprefix_len, tvb, *offset, 1, ENC_BIG_ENDIAN);
512                         *offset += 1;
513                         tlv_len -= 1;
514                         break;
515                 } else if (error_sub == 6) {
516                         if (tlv_len > 0) {
517                                 reported_length = tvb_reported_length_remaining(tvb, *offset);
518                                 DISSECTOR_ASSERT(reported_length >= 0);
519                                 if (reported_length > tlv_len)
520                                         reported_length = tlv_len;
521                                 next_tvb = tvb_new_subset_length(tvb, *offset, reported_length);
522                                 dissect_msdp(next_tvb, pinfo, tree, NULL);
523                         }
524                         *offset += tlv_len;
525                         tlv_len = 0;
526                 } else if (error_sub == 7) {
527                         if (tlv_len > 0) {
528                                 reported_length = tvb_reported_length_remaining(tvb, *offset);
529                                 DISSECTOR_ASSERT(reported_length >= 0);
530                                 if (reported_length > tlv_len)
531                                         reported_length = tlv_len;
532                                 next_tvb = tvb_new_subset_length(tvb, *offset, reported_length);
533                                 dissect_msdp(next_tvb, pinfo, tree, NULL);
534                         }
535                         *offset += tlv_len;
536                         tlv_len = 0;
537                         break;
538                 } else {
539                         if (tlv_len > 0)
540                                 proto_tree_add_item(tree, hf_msdp_unknown_data, tvb, *offset, tlv_len, ENC_NA);
541                         *offset += tlv_len;
542                         tlv_len = 0;
543                         break;
544                 }
545                 break;
546         case MESSAGE_HEADER_ERROR:
547         case NOTIFICATION:
548                 /* Data contains the message that had an error. Even a
549                  * broken Notification message causes a Notification
550                  * message with Error Code set to Notification to be
551                  * sent back.
552                  */
553                 if (tlv_len > 0) {
554                         reported_length = tvb_reported_length_remaining(tvb, *offset);
555                         DISSECTOR_ASSERT(reported_length >= 0);
556                         if (reported_length > tlv_len)
557                                 reported_length = tlv_len;
558                         next_tvb = tvb_new_subset_length(tvb, *offset, reported_length);
559                         dissect_msdp(next_tvb, pinfo, tree, NULL);
560                 }
561                 *offset += tlv_len;
562                 tlv_len = 0;
563                 break;
564         case FSM_ERROR:
565         case HOLD_TIMER_EXPIRED:
566         case CEASE:
567                 /* Do nothing. These contain no data */
568                 break;
569         default:
570                 if (tlv_len > 0)
571                         proto_tree_add_item(tree, hf_msdp_unknown_data, tvb, *offset, tlv_len, ENC_NA);
572                 *offset += tlv_len;
573                 tlv_len = 0;
574                 break;
575         }
576         if (tlv_len != 0) {
577                 expert_add_info_format(pinfo, length_item,
578                     &ei_msdp_tlv_len_too_long,
579                     "TLV length too long");
580                 proto_tree_add_item(tree, hf_msdp_trailing_junk, tvb, *offset, tlv_len, ENC_NA);
581                 *offset += tlv_len;
582         }
583
584         return;
585 }
586
587 void
588 proto_register_msdp(void)
589 {
590         static hf_register_info hf[] = {
591                 { &hf_msdp_type,
592                         { "Type",           "msdp.type",
593                         FT_UINT8, BASE_DEC, VALS(msdp_types), 0,
594                         "MSDP TLV type", HFILL }
595                 },
596                 { &hf_msdp_length,
597                         { "Length",           "msdp.length",
598                         FT_UINT16, BASE_DEC, NULL, 0,
599                         "MSDP TLV Length", HFILL }
600                 },
601                 { &hf_msdp_sa_entry_count,
602                         { "Entry Count",           "msdp.sa.entry_count",
603                         FT_UINT8, BASE_DEC, NULL, 0,
604                         "MSDP SA Entry Count", HFILL }
605                 },
606                 { &hf_msdp_sa_rp_addr,
607                         { "RP Address",           "msdp.sa.rp_addr",
608                         FT_IPv4, BASE_NONE, NULL, 0,
609                         "Active source's RP address", HFILL }
610                 },
611                 { &hf_msdp_sa_reserved,
612                         { "Reserved",           "msdp.sa.reserved",
613                         FT_UINT24, BASE_HEX, NULL, 0,
614                         "Transmitted as zeros and ignored by a receiver", HFILL }
615                 },
616                 { &hf_msdp_sa_sprefix_len,
617                         { "Sprefix len",           "msdp.sa.sprefix_len",
618                         FT_UINT8, BASE_DEC, NULL, 0,
619                         "The route prefix length associated with source address", HFILL }
620                 },
621                 { &hf_msdp_sa_group_addr,
622                         { "Group Address",           "msdp.sa.group_addr",
623                         FT_IPv4, BASE_NONE, NULL, 0,
624                         "The group address the active source has sent data to", HFILL }
625                 },
626                 { &hf_msdp_sa_src_addr,
627                         { "Source Address",           "msdp.sa.src_addr",
628                         FT_IPv4, BASE_NONE, NULL, 0,
629                         "The IP address of the active source", HFILL }
630                 },
631                 { &hf_msdp_sa_req_res,
632                         { "Reserved",           "msdp.sa_req.res",
633                         FT_UINT8, BASE_HEX, NULL, 0,
634                         "Transmitted as zeros and ignored by a receiver", HFILL }
635                 },
636                 { &hf_msdp_sa_req_group,
637                         { "Group Address",           "msdp.sa_req.group_addr",
638                         FT_IPv4, BASE_NONE, NULL, 0,
639                         "The group address the MSDP peer is requesting", HFILL }
640                 },
641                 { &hf_msdp_not_o,
642                         { "Open-bit",           "msdp.not.o",
643                         FT_UINT8, BASE_HEX, NULL, 0x80,
644                         "If clear, the connection will be closed", HFILL }
645                 },
646                 { &hf_msdp_not_error,
647                         { "Error Code",           "msdp.not.error",
648                         FT_UINT8, BASE_DEC, VALS(error_vals), 0x7F,
649                         "Indicates the type of Notification", HFILL }
650                 },
651                 { &hf_msdp_not_error_sub,
652                         { "Error subcode",           "msdp.not.error_sub",
653                         FT_UINT8, BASE_DEC, NULL, 0,
654                         NULL, HFILL }
655                 },
656                 { &hf_msdp_not_group_address,
657                         { "Group address",           "msdp.not.group_address",
658                         FT_IPv4, BASE_NONE, NULL, 0,
659                         "Group address in Notification messages", HFILL }
660                 },
661                 { &hf_msdp_not_rp_address,
662                         { "RP address",           "msdp.not.rp_address",
663                         FT_IPv4, BASE_NONE, NULL, 0,
664                         "RP address in Notification messages", HFILL }
665                 },
666                 { &hf_msdp_not_source_address,
667                         { "Source address",           "msdp.not.source_address",
668                         FT_IPv4, BASE_NONE, NULL, 0,
669                         "Source address in Notification messages", HFILL }
670                 },
671                 { &hf_msdp_not_res,
672                         { "Reserved",           "msdp.not.res",
673                         FT_UINT24, BASE_HEX, NULL, 0,
674                         "Reserved field in Notification messages", HFILL }
675                 },
676                 { &hf_msdp_not_entry_count,
677                         { "Entry Count",           "msdp.not.entry_count",
678                         FT_UINT24, BASE_HEX, NULL, 0,
679                         "Entry Count in Notification messages", HFILL }
680                 },
681                 { &hf_msdp_not_sprefix_len,
682                         { "Sprefix len",           "msdp.not.sprefix_len",
683                         FT_UINT8, BASE_DEC, NULL, 0,
684                         "Source prefix length in Notification messages", HFILL }
685                 },
686                 { &hf_msdp_tlv_contents,
687                         { "TLV contents",           "msdp.tlv_contents",
688                         FT_BYTES, BASE_NONE, NULL, 0,
689                         NULL, HFILL }
690                 },
691                 { &hf_msdp_trailing_junk,
692                         { "Trailing junk",           "msdp.trailing_junk",
693                         FT_BYTES, BASE_NONE, NULL, 0,
694                         NULL, HFILL }
695                 },
696                 { &hf_msdp_unknown_data,
697                         { "Unknown data",           "msdp.unknown_data",
698                         FT_BYTES, BASE_NONE, NULL, 0,
699                         NULL, HFILL }
700                 },
701         };
702
703         static gint *ett[] = {
704                 &ett_msdp,
705                 &ett_msdp_sa_entry,
706                 &ett_msdp_sa_enc_data,
707                 &ett_msdp_not_data,
708         };
709
710         static ei_register_info ei[] = {
711                 { &ei_msdp_tlv_len_too_long,
712                     { "msdp.tlv_len.too_long", PI_PROTOCOL, PI_WARN,
713                       "TLV length too long", EXPFILL }
714                 },
715                 { &ei_msdp_tlv_len_too_short,
716                     { "msdp.tlv_len.too_short", PI_MALFORMED, PI_ERROR,
717                       "TLV length too short", EXPFILL }
718                 },
719         };
720
721         expert_module_t *expert_msdp;
722
723         proto_msdp = proto_register_protocol("Multicast Source Discovery Protocol",
724             "MSDP", "msdp");
725
726         proto_register_field_array(proto_msdp, hf, array_length(hf));
727         proto_register_subtree_array(ett, array_length(ett));
728         expert_msdp = expert_register_protocol(proto_msdp);
729         expert_register_field_array(expert_msdp, ei, array_length(ei));
730 }
731
732 void
733 proto_reg_handoff_msdp(void)
734 {
735         dissector_handle_t msdp_handle;
736
737         msdp_handle = create_dissector_handle(dissect_msdp, proto_msdp);
738         dissector_add_uint_with_preference("tcp.port", MSDP_PORT, msdp_handle);
739
740         ip_handle = find_dissector_add_dependency("ip", proto_msdp);
741 }
742
743 /*
744  * Editor modelines
745  *
746  * Local Variables:
747  * c-basic-offset: 8
748  * tab-width: 8
749  * indent-tabs-mode: nil
750  * End:
751  *
752  * ex: set shiftwidth=8 tabstop=8 expandtab:
753  * :indentSize=8:tabSize=8:noTabs=true:
754  */