/src/wireshark/epan/dissectors/packet-lacp.c
Line | Count | Source |
1 | | /* packet-lacp.c |
2 | | * Routines for Link Aggregation Control Protocol dissection. |
3 | | * IEEE Std 802.1AX-2014 Section 6.4.2.3 |
4 | | * Split from IEEE Std 802.3-2005 and named IEEE 802.3ad before that |
5 | | * |
6 | | * Copyright 2002 Steve Housley <steve_housley@3com.com> |
7 | | * |
8 | | * Wireshark - Network traffic analyzer |
9 | | * By Gerald Combs <gerald@wireshark.org> |
10 | | * Copyright 1998 Gerald Combs |
11 | | * |
12 | | * SPDX-License-Identifier: GPL-2.0-or-later |
13 | | */ |
14 | | |
15 | | #include "config.h" |
16 | | |
17 | | #include <epan/etypes.h> |
18 | | #include <epan/packet.h> |
19 | | #include <epan/to_str.h> |
20 | | #include <epan/expert.h> |
21 | | #include <epan/tfs.h> |
22 | | #include <wsutil/array.h> |
23 | | #include "packet-slowprotocols.h" |
24 | | |
25 | | /* General declarations */ |
26 | | void proto_register_lacp(void); |
27 | | void proto_reg_handoff_lacp(void); |
28 | | |
29 | | static dissector_handle_t lacp_handle; |
30 | | |
31 | 115 | #define VLACP_MAGIC_LACP 0x01010114 |
32 | 115 | #define VLACP_MAGIC_MARKER 0x02010114 |
33 | | |
34 | | /* TLV Types */ |
35 | 610 | #define LACPDU_TYPE_TERMINATOR 0x00 |
36 | 115 | #define LACPDU_TYPE_ACTOR_INFORMATION 0x01 |
37 | 115 | #define LACPDU_TYPE_PARTNER_INFORMATION 0x02 |
38 | 115 | #define LACPDU_TYPE_COLLECTOR_INFORMATION 0x03 |
39 | | |
40 | | static const value_string lacp_type_vals[] = { |
41 | | { LACPDU_TYPE_TERMINATOR, "Terminator" }, |
42 | | { LACPDU_TYPE_ACTOR_INFORMATION, "Actor Information" }, |
43 | | { LACPDU_TYPE_PARTNER_INFORMATION, "Partner Information" }, |
44 | | { LACPDU_TYPE_COLLECTOR_INFORMATION, "Collector Information" }, |
45 | | { 0, NULL } |
46 | | }; |
47 | | |
48 | | /* Actor and Partner Flag bits */ |
49 | 28 | #define LACPDU_FLAGS_ACTIVITY 0x01 |
50 | 28 | #define LACPDU_FLAGS_TIMEOUT 0x02 |
51 | 28 | #define LACPDU_FLAGS_AGGREGATION 0x04 |
52 | 28 | #define LACPDU_FLAGS_SYNC 0x08 |
53 | 28 | #define LACPDU_FLAGS_COLLECTING 0x10 |
54 | 28 | #define LACPDU_FLAGS_DISTRIB 0x20 |
55 | 28 | #define LACPDU_FLAGS_DEFAULTED 0x40 |
56 | 28 | #define LACPDU_FLAGS_EXPIRED 0x80 |
57 | | |
58 | | /* Initialise the protocol and registered fields */ |
59 | | static int proto_lacp; |
60 | | |
61 | | static int hf_lacp_vlacp_subtype; |
62 | | static int hf_lacp_version; |
63 | | static int hf_lacp_tlv_type; |
64 | | static int hf_lacp_tlv_length; |
65 | | |
66 | | static int hf_lacp_actor_sysid_priority; |
67 | | static int hf_lacp_actor_sysid; |
68 | | static int hf_lacp_actor_key; |
69 | | static int hf_lacp_actor_port_priority; |
70 | | static int hf_lacp_actor_port; |
71 | | static int hf_lacp_actor_state; |
72 | | static int hf_lacp_actor_state_str; |
73 | | static int hf_lacp_flags_a_activity; |
74 | | static int hf_lacp_flags_a_timeout; |
75 | | static int hf_lacp_flags_a_aggregation; |
76 | | static int hf_lacp_flags_a_sync; |
77 | | static int hf_lacp_flags_a_collecting; |
78 | | static int hf_lacp_flags_a_distrib; |
79 | | static int hf_lacp_flags_a_defaulted; |
80 | | static int hf_lacp_flags_a_expired; |
81 | | static int hf_lacp_actor_reserved; |
82 | | |
83 | | static int hf_lacp_partner_sysid_priority; |
84 | | static int hf_lacp_partner_sysid; |
85 | | static int hf_lacp_partner_key; |
86 | | static int hf_lacp_partner_port_priority; |
87 | | static int hf_lacp_partner_port; |
88 | | static int hf_lacp_partner_state; |
89 | | static int hf_lacp_partner_state_str; |
90 | | static int hf_lacp_flags_p_activity; |
91 | | static int hf_lacp_flags_p_timeout; |
92 | | static int hf_lacp_flags_p_aggregation; |
93 | | static int hf_lacp_flags_p_sync; |
94 | | static int hf_lacp_flags_p_collecting; |
95 | | static int hf_lacp_flags_p_distrib; |
96 | | static int hf_lacp_flags_p_defaulted; |
97 | | static int hf_lacp_flags_p_expired; |
98 | | static int hf_lacp_partner_reserved; |
99 | | |
100 | | static int hf_lacp_coll_max_delay; |
101 | | static int hf_lacp_coll_reserved; |
102 | | |
103 | | static int hf_lacp_pad; |
104 | | |
105 | | static int hf_lacp_vendor; |
106 | | |
107 | | static int hf_lacp_vendor_hp_length; |
108 | | static int hf_lacp_vendor_hp_irf_domain; |
109 | | static int hf_lacp_vendor_hp_irf_mac; |
110 | | static int hf_lacp_vendor_hp_irf_switch; |
111 | | static int hf_lacp_vendor_hp_irf_port; |
112 | | static int hf_lacp_vendor_hp_unknown; |
113 | | |
114 | | |
115 | | /* Initialise the subtree pointers */ |
116 | | static int ett_lacp; |
117 | | static int ett_lacp_a_flags; |
118 | | static int ett_lacp_p_flags; |
119 | | |
120 | | /* Expert Items */ |
121 | | static expert_field ei_lacp_wrong_tlv_type; |
122 | | static expert_field ei_lacp_wrong_tlv_length; |
123 | | |
124 | | static const true_false_string tfs_active_passive = { "Active", "Passive" }; |
125 | | static const true_false_string tfs_short_long_timeout = { "Short Timeout", "Long Timeout" }; |
126 | | static const true_false_string tfs_aggregatable_individual = { "Aggregatable", "Individual" }; |
127 | | static const true_false_string tfs_in_sync_out_sync = { "In Sync", "Out of Sync" }; |
128 | | |
129 | | static const char * lacp_state_flags_to_str(wmem_allocator_t *scope, uint32_t value) |
130 | 202 | { |
131 | 202 | wmem_strbuf_t *buf = wmem_strbuf_new(scope, ""); |
132 | 202 | const unsigned int flags_count = 8; |
133 | 202 | static const char first_letters[] = "EFDCSGSA"; |
134 | 202 | unsigned int i; |
135 | | |
136 | 1.81k | for (i = 0; i < flags_count; i++) { |
137 | 1.61k | if (((value >> (flags_count - 1 - i)) & 1)) { |
138 | 714 | wmem_strbuf_append_c(buf, first_letters[i]); |
139 | 902 | } else { |
140 | 902 | wmem_strbuf_append_c(buf, '*'); |
141 | 902 | } |
142 | 1.61k | } |
143 | | |
144 | 202 | return wmem_strbuf_finalize(buf); |
145 | 202 | } |
146 | | |
147 | | /* |
148 | | * Name: dissect_lacp |
149 | | * |
150 | | * Description: |
151 | | * This function is used to dissect the Link Aggregation Control Protocol |
152 | | * defined in IEEE 802.1AX |
153 | | * |
154 | | * Input Arguments: |
155 | | * tvb: buffer associated with the rcv packet (see tvbuff.h). |
156 | | * pinfo: structure associated with the rcv packet (see packet_info.h). |
157 | | * tree: the protocol tree associated with the rcv packet (see proto.h). |
158 | | * |
159 | | * Return Values: None |
160 | | * |
161 | | * Notes: |
162 | | */ |
163 | | static int |
164 | | dissect_lacp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
165 | 115 | { |
166 | 115 | int offset = 0, length_remaining; |
167 | 115 | unsigned tlv_type, tlv_length; |
168 | 115 | unsigned version, port, key; |
169 | 115 | const char *sysidstr, *flagstr; |
170 | 115 | uint32_t protodetect; |
171 | 115 | uint8_t is_vlacp; |
172 | | |
173 | 115 | proto_tree *lacp_tree; |
174 | 115 | proto_item *lacp_item, *tlv_type_item, *tlv_length_item; |
175 | 115 | proto_item *ti; |
176 | | |
177 | 115 | static int * const actor_flags[] = { |
178 | 115 | &hf_lacp_flags_a_activity, |
179 | 115 | &hf_lacp_flags_a_timeout, |
180 | 115 | &hf_lacp_flags_a_aggregation, |
181 | 115 | &hf_lacp_flags_a_sync, |
182 | 115 | &hf_lacp_flags_a_collecting, |
183 | 115 | &hf_lacp_flags_a_distrib, |
184 | 115 | &hf_lacp_flags_a_defaulted, |
185 | 115 | &hf_lacp_flags_a_expired, |
186 | 115 | NULL |
187 | 115 | }; |
188 | 115 | static int * const partner_flags[] = { |
189 | 115 | &hf_lacp_flags_p_activity, |
190 | 115 | &hf_lacp_flags_p_timeout, |
191 | 115 | &hf_lacp_flags_p_aggregation, |
192 | 115 | &hf_lacp_flags_p_sync, |
193 | 115 | &hf_lacp_flags_p_collecting, |
194 | 115 | &hf_lacp_flags_p_distrib, |
195 | 115 | &hf_lacp_flags_p_defaulted, |
196 | 115 | &hf_lacp_flags_p_expired, |
197 | 115 | NULL |
198 | 115 | }; |
199 | | |
200 | 115 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "LACP"); |
201 | 115 | col_set_str(pinfo->cinfo, COL_INFO, "Link Aggregation Control Protocol"); |
202 | | |
203 | | /* FIXME |
204 | | * Validate that the destination MAC address is one of the following |
205 | | * (IEEE 802.1AX-2014 6.2.11.2): |
206 | | * 01-80-C2-00-00-00: Nearest Customer Bridge group address |
207 | | * 01-80-C2-00-00-02: IEEE 802.3 Slow_Protocols_Mulitcast group address |
208 | | * 01-80-C2-00-00-03: Nearest non-TPMR Bridge group address |
209 | | */ |
210 | | |
211 | 115 | protodetect = tvb_get_ntohl(tvb, 0); |
212 | 115 | if ((protodetect == VLACP_MAGIC_LACP) || (protodetect == VLACP_MAGIC_MARKER)) { |
213 | 0 | is_vlacp = 1; |
214 | | /* Add vLACP Heading */ |
215 | 0 | lacp_item = proto_tree_add_protocol_format(tree, proto_lacp, tvb, |
216 | 0 | 0, -1, "Virtual Link Aggregation Control Protocol"); |
217 | 115 | } else { |
218 | 115 | is_vlacp = 0; |
219 | | /* Add LACP Heading - Note: 1 byte for slowprotocol has been consumed already */ |
220 | 115 | lacp_item = proto_tree_add_protocol_format(tree, proto_lacp, tvb, |
221 | 115 | 0, -1, "Link Aggregation Control Protocol"); |
222 | 115 | } |
223 | 115 | lacp_tree = proto_item_add_subtree(lacp_item, ett_lacp); |
224 | | |
225 | 115 | if (is_vlacp == 1) { |
226 | 0 | proto_tree_add_item(lacp_tree, hf_lacp_vlacp_subtype, tvb, offset, 1, ENC_NA); |
227 | 0 | offset += 1; |
228 | 0 | } |
229 | | |
230 | | /* Version Number */ |
231 | | |
232 | 115 | proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_version, tvb, offset, 1, ENC_NA, &version); |
233 | 115 | offset += 1; |
234 | | |
235 | 115 | col_add_fstr(pinfo->cinfo, COL_INFO, "v%d", version); |
236 | | |
237 | | /* Actor */ |
238 | | |
239 | 115 | tlv_type_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type); |
240 | 115 | offset += 1; |
241 | | |
242 | 115 | tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length); |
243 | 115 | offset += 1; |
244 | | |
245 | 115 | if (tlv_type != LACPDU_TYPE_ACTOR_INFORMATION) { |
246 | 113 | expert_add_info(pinfo, tlv_type_item, &ei_lacp_wrong_tlv_type); |
247 | 113 | } |
248 | 115 | if (tlv_length != 20) { |
249 | 115 | expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length); |
250 | 115 | } |
251 | | |
252 | 115 | proto_tree_add_item(lacp_tree, hf_lacp_actor_sysid_priority, tvb, offset, 2, ENC_BIG_ENDIAN); |
253 | 115 | offset += 2; |
254 | | |
255 | 115 | proto_tree_add_item(lacp_tree, hf_lacp_actor_sysid, tvb, offset, 6, ENC_NA); |
256 | 115 | sysidstr = tvb_ether_to_str(pinfo->pool, tvb, offset); |
257 | 115 | offset += 6; |
258 | | |
259 | 115 | proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_actor_key, tvb, offset, 2, ENC_BIG_ENDIAN, &key); |
260 | 115 | offset += 2; |
261 | | |
262 | 115 | proto_tree_add_item(lacp_tree, hf_lacp_actor_port_priority, tvb, offset, 2, ENC_BIG_ENDIAN); |
263 | 115 | offset += 2; |
264 | | |
265 | 115 | proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_actor_port, tvb, offset, 2, ENC_BIG_ENDIAN, &port); |
266 | 115 | offset += 2; |
267 | | |
268 | 115 | proto_tree_add_bitmask_with_flags(lacp_tree, tvb, offset, hf_lacp_actor_state, |
269 | 115 | ett_lacp_a_flags, actor_flags, ENC_NA, BMT_NO_INT|BMT_NO_TFS|BMT_NO_FALSE); |
270 | 115 | flagstr = lacp_state_flags_to_str(pinfo->pool, tvb_get_uint8(tvb, offset)); |
271 | 115 | ti = proto_tree_add_string(lacp_tree, hf_lacp_actor_state_str, tvb, offset, 1, flagstr); |
272 | 115 | proto_item_set_generated(ti); |
273 | 115 | offset += 1; |
274 | | |
275 | 115 | proto_tree_add_item(lacp_tree, hf_lacp_actor_reserved, tvb, offset, 3, ENC_NA); |
276 | 115 | offset += 3; |
277 | | |
278 | 115 | col_append_fstr(pinfo->cinfo, COL_INFO, " ACTOR %s P: %d K: %d %s", sysidstr, port, key, flagstr); |
279 | | |
280 | | /* Partner */ |
281 | | |
282 | 115 | tlv_type_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type); |
283 | 115 | offset += 1; |
284 | | |
285 | 115 | tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length); |
286 | 115 | offset += 1; |
287 | | |
288 | 115 | if (tlv_type != LACPDU_TYPE_PARTNER_INFORMATION) { |
289 | 103 | expert_add_info(pinfo, tlv_type_item, &ei_lacp_wrong_tlv_type); |
290 | 103 | } |
291 | 115 | if (tlv_length != 20) { |
292 | 104 | expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length); |
293 | 104 | } |
294 | | |
295 | 115 | proto_tree_add_item(lacp_tree, hf_lacp_partner_sysid_priority, tvb, offset, 2, ENC_BIG_ENDIAN); |
296 | 115 | offset += 2; |
297 | | |
298 | 115 | proto_tree_add_item(lacp_tree, hf_lacp_partner_sysid, tvb, offset, 6, ENC_NA); |
299 | 115 | sysidstr = tvb_ether_to_str(pinfo->pool, tvb, offset); |
300 | 115 | offset += 6; |
301 | | |
302 | 115 | proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_partner_key, tvb, offset, 2, ENC_BIG_ENDIAN, &key); |
303 | 115 | offset += 2; |
304 | | |
305 | 115 | proto_tree_add_item(lacp_tree, hf_lacp_partner_port_priority, tvb, offset, 2, ENC_BIG_ENDIAN); |
306 | 115 | offset += 2; |
307 | | |
308 | 115 | proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_partner_port, tvb, offset, 2, ENC_BIG_ENDIAN, &port); |
309 | 115 | offset += 2; |
310 | | |
311 | 115 | proto_tree_add_bitmask_with_flags(lacp_tree, tvb, offset, hf_lacp_partner_state, ett_lacp_p_flags, partner_flags, ENC_NA, BMT_NO_INT|BMT_NO_TFS|BMT_NO_FALSE); |
312 | 115 | flagstr = lacp_state_flags_to_str(pinfo->pool, tvb_get_uint8(tvb, offset)); |
313 | 115 | ti = proto_tree_add_string(lacp_tree, hf_lacp_partner_state_str, tvb, offset, 1, flagstr); |
314 | 115 | proto_item_set_generated(ti); |
315 | 115 | offset += 1; |
316 | | |
317 | 115 | proto_tree_add_item(lacp_tree, hf_lacp_partner_reserved, tvb, offset, 3, ENC_NA); |
318 | 115 | offset += 3; |
319 | | |
320 | 115 | col_append_fstr(pinfo->cinfo, COL_INFO, " PARTNER %s P: %d K: %d %s", sysidstr, port, key, flagstr); |
321 | | |
322 | | /* Collector */ |
323 | | |
324 | 115 | tlv_type_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type); |
325 | 115 | offset += 1; |
326 | | |
327 | 115 | tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length); |
328 | 115 | offset += 1; |
329 | | |
330 | 115 | if (tlv_type != LACPDU_TYPE_COLLECTOR_INFORMATION) { |
331 | 75 | expert_add_info(pinfo, tlv_type_item, &ei_lacp_wrong_tlv_type); |
332 | 75 | } |
333 | 115 | if (tlv_length != 16) { |
334 | 91 | expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length); |
335 | 91 | } |
336 | | |
337 | 115 | proto_tree_add_item(lacp_tree, hf_lacp_coll_max_delay, tvb, offset, 2, ENC_BIG_ENDIAN); |
338 | 115 | offset += 2; |
339 | | |
340 | 115 | proto_tree_add_item(lacp_tree, hf_lacp_coll_reserved, tvb, offset, 12, ENC_NA); |
341 | 115 | offset += 12; |
342 | | |
343 | | /* col_append_fstr(pinfo->cinfo, COL_INFO, " COLLECTOR"); */ |
344 | | |
345 | | /* Other TLVs (LACP version 2) */ |
346 | | |
347 | 115 | proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type); |
348 | 115 | offset += 1; |
349 | | |
350 | 115 | tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length); |
351 | 115 | offset += 1; |
352 | | |
353 | 305 | while (tlv_type != LACPDU_TYPE_TERMINATOR && tlv_length >= 2) { |
354 | 190 | offset += (tlv_length - 2); |
355 | 190 | proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type); |
356 | 190 | offset += 1; |
357 | | |
358 | 190 | tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length); |
359 | 190 | offset += 1; |
360 | 190 | } |
361 | | |
362 | | /* Terminator - already handled */ |
363 | | |
364 | 115 | if (tlv_length != 0) { |
365 | 24 | expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length); |
366 | 24 | } |
367 | | |
368 | | /* Pad */ |
369 | | |
370 | 115 | if (offset < (128 - 1 - 18)) { /* LACPv1 fixed size - Eth */ |
371 | 37 | proto_tree_add_item(lacp_tree, hf_lacp_pad, tvb, offset, (128 - 1 - 18)-offset, ENC_NA); |
372 | 37 | offset += ((128 - 1 - 18)-offset); |
373 | 37 | } |
374 | | |
375 | | /* HP specific stuff (in violation of standard) */ |
376 | | |
377 | 115 | length_remaining = tvb_reported_length_remaining(tvb, offset); |
378 | 115 | if (length_remaining) { |
379 | | |
380 | | /* HP LACP MAD IRF, first bytes is always 0x64 and second bytes is the rest of length */ |
381 | 33 | if (length_remaining > 2 && (tvb_get_uint8(tvb, offset) == 0x64) && ((length_remaining -2) == tvb_get_uint8(tvb, offset+1)) ) |
382 | 0 | { |
383 | 0 | proto_tree_add_item(lacp_tree, hf_lacp_vendor, tvb, offset, length_remaining, ENC_NA); |
384 | 0 | proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 1, ENC_NA); |
385 | 0 | offset += 1; |
386 | |
|
387 | 0 | proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_length, tvb, offset, 1, ENC_NA); |
388 | 0 | offset += 1; |
389 | |
|
390 | 0 | proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 2, ENC_NA); |
391 | 0 | offset += 2; |
392 | |
|
393 | 0 | proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_domain, tvb, offset, 2, ENC_BIG_ENDIAN); |
394 | 0 | offset += 2; |
395 | |
|
396 | 0 | proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_mac, tvb, offset, 6, ENC_NA); |
397 | 0 | offset += 6; |
398 | |
|
399 | 0 | proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 8, ENC_NA); |
400 | 0 | offset += 8; |
401 | |
|
402 | 0 | proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_switch, tvb, offset, 2, ENC_BIG_ENDIAN); |
403 | 0 | offset += 2; |
404 | |
|
405 | 0 | proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_port, tvb, offset, 2, ENC_BIG_ENDIAN); |
406 | 0 | offset += 2; |
407 | |
|
408 | 0 | proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 2, ENC_NA); |
409 | 33 | } else { |
410 | | /* Not the HP specific extras. Don't claim the remaining data. It may actually be an ethernet trailer. */ |
411 | 33 | set_actual_length(tvb, tvb_captured_length(tvb) - length_remaining); |
412 | 33 | proto_item_set_len(lacp_item, tvb_captured_length(tvb)); |
413 | 33 | } |
414 | 33 | } |
415 | 115 | return tvb_captured_length(tvb); |
416 | 115 | } |
417 | | |
418 | | /* Register the protocol with Wireshark */ |
419 | | void |
420 | | proto_register_lacp(void) |
421 | 14 | { |
422 | | /* Setup list of header fields */ |
423 | | |
424 | 14 | static hf_register_info hf[] = { |
425 | 14 | { &hf_lacp_vlacp_subtype, |
426 | 14 | { "vLACP subtype", "lacp.vlacp_subtype", |
427 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, |
428 | 14 | "Avaya vlacp unused lacp subtype byte", HFILL }}, |
429 | | |
430 | 14 | { &hf_lacp_version, |
431 | 14 | { "LACP Version", "lacp.version", |
432 | 14 | FT_UINT8, BASE_HEX, NULL, 0x0, |
433 | 14 | NULL, HFILL }}, |
434 | | |
435 | 14 | { &hf_lacp_tlv_type, |
436 | 14 | { "TLV Type", "lacp.tlv_type", |
437 | 14 | FT_UINT8, BASE_HEX, VALS(lacp_type_vals), 0x0, |
438 | 14 | NULL, HFILL }}, |
439 | | |
440 | 14 | { &hf_lacp_tlv_length, |
441 | 14 | { "TLV Length", "lacp.tlv_length", |
442 | 14 | FT_UINT8, BASE_HEX, NULL, 0x0, |
443 | 14 | NULL, HFILL }}, |
444 | | |
445 | 14 | { &hf_lacp_actor_sysid_priority, |
446 | 14 | { "Actor System Priority", "lacp.actor.sys_priority", |
447 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
448 | 14 | NULL, HFILL }}, |
449 | | |
450 | 14 | { &hf_lacp_actor_sysid, |
451 | 14 | { "Actor System ID", "lacp.actor.sysid", |
452 | 14 | FT_ETHER, BASE_NONE, NULL, 0x0, |
453 | 14 | NULL, HFILL }}, |
454 | | |
455 | 14 | { &hf_lacp_actor_key, |
456 | 14 | { "Actor Key", "lacp.actor.key", |
457 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
458 | 14 | NULL, HFILL }}, |
459 | | |
460 | 14 | { &hf_lacp_actor_port_priority, |
461 | 14 | { "Actor Port Priority", "lacp.actor.port_priority", |
462 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
463 | 14 | NULL, HFILL }}, |
464 | | |
465 | 14 | { &hf_lacp_actor_port, |
466 | 14 | { "Actor Port", "lacp.actor.port", |
467 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
468 | 14 | NULL, HFILL }}, |
469 | | |
470 | 14 | { &hf_lacp_actor_state, |
471 | 14 | { "Actor State", "lacp.actor.state", |
472 | 14 | FT_UINT8, BASE_HEX, NULL, 0x0, |
473 | 14 | NULL, HFILL }}, |
474 | | |
475 | 14 | { &hf_lacp_actor_state_str, |
476 | 14 | { "Actor State Flags", "lacp.actor.state_str", |
477 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
478 | 14 | NULL, HFILL }}, |
479 | | |
480 | 14 | { &hf_lacp_flags_a_activity, |
481 | 14 | { "LACP Activity", "lacp.actor.state.activity", |
482 | 14 | FT_BOOLEAN, 8, TFS(&tfs_active_passive), LACPDU_FLAGS_ACTIVITY, |
483 | 14 | NULL, HFILL }}, |
484 | | |
485 | 14 | { &hf_lacp_flags_a_timeout, |
486 | 14 | { "LACP Timeout", "lacp.actor.state.timeout", |
487 | 14 | FT_BOOLEAN, 8, TFS(&tfs_short_long_timeout), LACPDU_FLAGS_TIMEOUT, |
488 | 14 | NULL, HFILL }}, |
489 | | |
490 | 14 | { &hf_lacp_flags_a_aggregation, |
491 | 14 | { "Aggregation", "lacp.actor.state.aggregation", |
492 | 14 | FT_BOOLEAN, 8, TFS(&tfs_aggregatable_individual), LACPDU_FLAGS_AGGREGATION, |
493 | 14 | NULL, HFILL }}, |
494 | | |
495 | 14 | { &hf_lacp_flags_a_sync, |
496 | 14 | { "Synchronization", "lacp.actor.state.synchronization", |
497 | 14 | FT_BOOLEAN, 8, TFS(&tfs_in_sync_out_sync), LACPDU_FLAGS_SYNC, |
498 | 14 | NULL, HFILL }}, |
499 | | |
500 | 14 | { &hf_lacp_flags_a_collecting, |
501 | 14 | { "Collecting", "lacp.actor.state.collecting", |
502 | 14 | FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), LACPDU_FLAGS_COLLECTING, |
503 | 14 | NULL, HFILL }}, |
504 | | |
505 | 14 | { &hf_lacp_flags_a_distrib, |
506 | 14 | { "Distributing", "lacp.actor.state.distributing", |
507 | 14 | FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), LACPDU_FLAGS_DISTRIB, |
508 | 14 | NULL, HFILL }}, |
509 | | |
510 | 14 | { &hf_lacp_flags_a_defaulted, |
511 | 14 | { "Defaulted", "lacp.actor.state.defaulted", |
512 | 14 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_DEFAULTED, |
513 | 14 | "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }}, |
514 | | |
515 | 14 | { &hf_lacp_flags_a_expired, |
516 | 14 | { "Expired", "lacp.actor.state.expired", |
517 | 14 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_EXPIRED, |
518 | 14 | NULL, HFILL }}, |
519 | | |
520 | 14 | { &hf_lacp_actor_reserved, |
521 | 14 | { "Reserved", "lacp.actor.reserved", |
522 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
523 | 14 | NULL, HFILL }}, |
524 | | |
525 | 14 | { &hf_lacp_partner_sysid_priority, |
526 | 14 | { "Partner System Priority", "lacp.partner.sys_priority", |
527 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
528 | 14 | NULL, HFILL }}, |
529 | | |
530 | 14 | { &hf_lacp_partner_sysid, |
531 | 14 | { "Partner System", "lacp.partner.sysid", |
532 | 14 | FT_ETHER, BASE_NONE, NULL, 0x0, |
533 | 14 | NULL, HFILL }}, |
534 | | |
535 | 14 | { &hf_lacp_partner_key, |
536 | 14 | { "Partner Key", "lacp.partner.key", |
537 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
538 | 14 | NULL, HFILL }}, |
539 | | |
540 | 14 | { &hf_lacp_partner_port_priority, |
541 | 14 | { "Partner Port Priority", "lacp.partner.port_priority", |
542 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
543 | 14 | NULL, HFILL }}, |
544 | | |
545 | 14 | { &hf_lacp_partner_port, |
546 | 14 | { "Partner Port", "lacp.partner.port", |
547 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
548 | 14 | "The port number associated with this link assigned to the port by the Partner (via Management or Admin)", HFILL }}, |
549 | | |
550 | 14 | { &hf_lacp_partner_state, |
551 | 14 | { "Partner State", "lacp.partner.state", |
552 | 14 | FT_UINT8, BASE_HEX, NULL, 0x0, |
553 | 14 | NULL, HFILL }}, |
554 | | |
555 | 14 | { &hf_lacp_partner_state_str, |
556 | 14 | { "Partner State Flags", "lacp.partner.state_str", |
557 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
558 | 14 | NULL, HFILL }}, |
559 | | |
560 | 14 | { &hf_lacp_flags_p_activity, |
561 | 14 | { "LACP Activity", "lacp.partner.state.activity", |
562 | 14 | FT_BOOLEAN, 8, TFS(&tfs_active_passive), LACPDU_FLAGS_ACTIVITY, |
563 | 14 | NULL, HFILL }}, |
564 | | |
565 | 14 | { &hf_lacp_flags_p_timeout, |
566 | 14 | { "LACP Timeout", "lacp.partner.state.timeout", |
567 | 14 | FT_BOOLEAN, 8, TFS(&tfs_short_long_timeout), LACPDU_FLAGS_TIMEOUT, |
568 | 14 | NULL, HFILL }}, |
569 | | |
570 | 14 | { &hf_lacp_flags_p_aggregation, |
571 | 14 | { "Aggregation", "lacp.partner.state.aggregation", |
572 | 14 | FT_BOOLEAN, 8, TFS(&tfs_aggregatable_individual), LACPDU_FLAGS_AGGREGATION, |
573 | 14 | NULL, HFILL }}, |
574 | | |
575 | 14 | { &hf_lacp_flags_p_sync, |
576 | 14 | { "Synchronization", "lacp.partner.state.synchronization", |
577 | 14 | FT_BOOLEAN, 8, TFS(&tfs_in_sync_out_sync), LACPDU_FLAGS_SYNC, |
578 | 14 | NULL, HFILL }}, |
579 | | |
580 | 14 | { &hf_lacp_flags_p_collecting, |
581 | 14 | { "Collecting", "lacp.partner.state.collecting", |
582 | 14 | FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), LACPDU_FLAGS_COLLECTING, |
583 | 14 | NULL, HFILL }}, |
584 | | |
585 | 14 | { &hf_lacp_flags_p_distrib, |
586 | 14 | { "Distributing", "lacp.partner.state.distributing", |
587 | 14 | FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), LACPDU_FLAGS_DISTRIB, |
588 | 14 | NULL, HFILL }}, |
589 | | |
590 | 14 | { &hf_lacp_flags_p_defaulted, |
591 | 14 | { "Defaulted", "lacp.partner.state.defaulted", |
592 | 14 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_DEFAULTED, |
593 | 14 | "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }}, |
594 | | |
595 | 14 | { &hf_lacp_flags_p_expired, |
596 | 14 | { "Expired", "lacp.partner.state.expired", |
597 | 14 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_EXPIRED, |
598 | 14 | NULL, HFILL }}, |
599 | | |
600 | 14 | { &hf_lacp_partner_reserved, |
601 | 14 | { "Reserved", "lacp.partner.reserved", |
602 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
603 | 14 | NULL, HFILL }}, |
604 | | |
605 | 14 | { &hf_lacp_coll_max_delay, |
606 | 14 | { "Collector Max Delay", "lacp.collector.max_delay", |
607 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
608 | 14 | "The max delay of the station sending the LACPDU (in tens of usecs)", HFILL }}, |
609 | | |
610 | 14 | { &hf_lacp_coll_reserved, |
611 | 14 | { "Reserved", "lacp.coll_reserved", |
612 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
613 | 14 | NULL, HFILL }}, |
614 | | |
615 | 14 | { &hf_lacp_pad, |
616 | 14 | { "Pad", "lacp.pad", |
617 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
618 | 14 | NULL, HFILL }}, |
619 | | |
620 | 14 | { &hf_lacp_vendor, |
621 | 14 | { "Unknown vendor", "lacp.vendor", |
622 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
623 | 14 | "Some extra bytes (Vendor Specific ?)", HFILL }}, |
624 | | |
625 | | /* HP IRF MAD LACP */ |
626 | 14 | { &hf_lacp_vendor_hp_length, |
627 | 14 | { "Length", "lacp.vendor.hp.length", |
628 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, |
629 | 14 | "The length of HP TLV", HFILL }}, |
630 | 14 | { &hf_lacp_vendor_hp_irf_domain, |
631 | 14 | { "IRF Domain", "lacp.vendor.hp.irf_domain", |
632 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
633 | 14 | NULL, HFILL }}, |
634 | 14 | { &hf_lacp_vendor_hp_irf_mac, |
635 | 14 | { "IRF MAC", "lacp.vendor.hp.irf_mac", |
636 | 14 | FT_ETHER, BASE_NONE, NULL, 0x0, |
637 | 14 | NULL, HFILL }}, |
638 | 14 | { &hf_lacp_vendor_hp_irf_switch, |
639 | 14 | { "IRF Switch", "lacp.vendor.hp.irf_switch", |
640 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
641 | 14 | "Number of switch on the IRF stack", HFILL }}, |
642 | 14 | { &hf_lacp_vendor_hp_irf_port, |
643 | 14 | { "IRF Port", "lacp.vendor.hp.irf_port", |
644 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
645 | 14 | "Stack ID where the LACP is attached", HFILL }}, |
646 | 14 | { &hf_lacp_vendor_hp_unknown, |
647 | 14 | { "Unknown", "lacp.vendor.hp.unknown", |
648 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
649 | 14 | NULL, HFILL }}, |
650 | 14 | }; |
651 | | |
652 | | /* Setup protocol subtree array */ |
653 | | |
654 | 14 | static int *ett[] = { |
655 | 14 | &ett_lacp, |
656 | 14 | &ett_lacp_a_flags, |
657 | 14 | &ett_lacp_p_flags, |
658 | 14 | }; |
659 | | |
660 | 14 | static ei_register_info ei[] = { |
661 | 14 | { &ei_lacp_wrong_tlv_type, { "lacp.wrong_tlv_type", PI_MALFORMED, PI_ERROR, "TLV is not expected type", EXPFILL }}, |
662 | 14 | { &ei_lacp_wrong_tlv_length, { "lacp.wrong_tlv_length", PI_MALFORMED, PI_ERROR, "TLV is not expected length", EXPFILL }}, |
663 | 14 | }; |
664 | | |
665 | 14 | expert_module_t* expert_lacp; |
666 | | |
667 | | |
668 | | /* Register the protocol name and description */ |
669 | | |
670 | 14 | proto_lacp = proto_register_protocol("Link Aggregation Control Protocol", "LACP", "lacp"); |
671 | | |
672 | | /* Required function calls to register the header fields and subtrees used */ |
673 | | |
674 | 14 | proto_register_field_array(proto_lacp, hf, array_length(hf)); |
675 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
676 | 14 | expert_lacp = expert_register_protocol(proto_lacp); |
677 | 14 | expert_register_field_array(expert_lacp, ei, array_length(ei)); |
678 | | |
679 | 14 | lacp_handle = register_dissector("lacp", dissect_lacp, proto_lacp); |
680 | 14 | } |
681 | | |
682 | | void |
683 | | proto_reg_handoff_lacp(void) |
684 | 14 | { |
685 | 14 | dissector_add_uint("slow.subtype", LACP_SUBTYPE, lacp_handle); |
686 | 14 | dissector_add_uint("ethertype", ETHERTYPE_VLACP, lacp_handle); |
687 | 14 | } |
688 | | |
689 | | /* |
690 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
691 | | * |
692 | | * Local variables: |
693 | | * c-basic-offset: 4 |
694 | | * tab-width: 8 |
695 | | * indent-tabs-mode: nil |
696 | | * End: |
697 | | * |
698 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
699 | | * :indentSize=4:tabSize=8:noTabs=true: |
700 | | */ |