/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 | | */ |