Coverage Report

Created: 2026-01-02 06:13

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