2 * Routines for Cisco Wireless LAN Context Control Protocol dissection
4 * Copyright 2005, Joerg Mayer (see AUTHORS file)
5 * Copyright 2006, Stephen Fisher <stephentfisher@yahoo.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * The CISCOWL dissector was merged into this one.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 /* Version 0x00 was reverse engineered */
31 /* Version 0xC1 Protocol reference: US Patent Application 0050220054 */
33 /* More clues to version 0x00 of the protocol:
35 * Header (Eth V2 or SNAP)
38 * 0202: Unknown, Length 36 (14 + 20 + 2)
39 * 4001: Unknown, Length 48 (14 + 32 + 2)
40 * 4601: Unknown, Length 34 (14 + 18 + 2)
41 * 4081 on Eth V2: Name, Version Length 84 (14 + 48 + 20 + 2)
42 * 4081 on 802.3: Name Length 72 (14 + 56 + 2)
45 * Unknown1 (2 bytes) Unknown19 + Unknown2 may be a MAC address on type 0202
46 * Unknown2 (4 bytes) see Unknown19
50 * Device name (8 bytes)
54 * Version string (10 bytes)
69 #include <epan/packet.h>
70 #include <epan/prefs.h>
71 #include <epan/etypes.h>
73 #include "packet-llc.h"
75 static const value_string wlccp_sap_vs[] = {
76 { 0, "Context Management" },
77 { 2, "Radio Resource Management" },
81 static const value_string wlccp_subtype_vs[] = {
89 static const value_string wlccp_node_type_vs[] = {
91 { 1, "Access Point (AP)" },
92 { 2, "Subnet Context Manager (SCM)" },
93 { 4, "Local Context Manager (LCM)" },
94 { 8, "Campus Context Manager (CCM)" },
95 { 0x10, "Infrastructure (ICN)" },
99 static const value_string cisco_pid_vals[] = {
104 /* Bit fields in message type */
105 #define MT_SUBTYPE (0xC0)
106 #define MT_BASE_MSG_TYPE (0x3F)
108 /* Bit fields in flags */
109 #define F_RETRY (1<<15)
110 #define F_RESPONSE_REQUEST (1<<14)
111 #define F_TLV (1<<13)
112 #define F_INBOUND (1<<12)
113 #define F_OUTBOUND (1<<11)
114 #define F_HOPWISE_ROUTING (1<<10)
115 #define F_ROOT_CM (1<<9)
116 #define F_RELAY (1<<8)
119 #define WLCCP_UDP_PORT 2887
120 /* WLCCP also uses an LCC OUI type and an ethertype */
122 /* Forward declaration we need below */
123 void proto_reg_handoff_wlccp(void);
125 /* Initialize the protocol and registered fields */
126 static int proto_wlccp = -1;
128 static int hf_llc_wlccp_pid = -1;
130 static int hf_wlccp_version = -1;
132 static int hf_wlccp_dstmac = -1;
133 static int hf_wlccp_srcmac = -1;
134 static int hf_wlccp_hostname = -1;
136 static int hf_wlccp_sap = -1;
137 static int hf_wlccp_destination_node_type = -1;
138 static int hf_wlccp_length = -1;
139 static int hf_wlccp_type = -1;
140 static int hf_wlccp_subtype = -1;
141 static int hf_wlccp_base_message_type = -1;
142 static int hf_wlccp_hops = -1;
143 static int hf_wlccp_msg_id = -1;
144 static int hf_wlccp_flags = -1;
145 static int hf_wlccp_retry_flag = -1;
146 static int hf_wlccp_response_request_flag = -1;
147 static int hf_wlccp_tlv_flag = -1;
148 static int hf_wlccp_inbound_flag = -1;
149 static int hf_wlccp_outbound_flag = -1;
150 static int hf_wlccp_hopwise_routing_flag = -1;
151 static int hf_wlccp_root_cm_flag = -1;
152 static int hf_wlccp_relay_flag = -1;
153 static int hf_wlccp_mic_flag = -1;
154 static int hf_wlccp_originator_node_type = -1;
155 static int hf_wlccp_originator = -1;
156 static int hf_wlccp_responder_node_type = -1;
157 static int hf_wlccp_responder = -1;
158 static int hf_wlccp_relay_node_type = -1;
159 static int hf_wlccp_relay_node_id = -1;
160 static int hf_wlccp_priority = -1;
161 static int hf_wlccp_age = -1;
162 static int hf_wlccp_period = -1;
163 static int hf_wlccp_ipv4_address = -1;
166 /* Initialize the subtree pointers */
167 static gint ett_wlccp = -1;
168 static gint ett_wlccp_type = -1;
169 static gint ett_wlccp_flags = -1;
171 /* Code to actually dissect the packets */
173 dissect_wlccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
175 /* Set up structures needed to add the protocol subtree and manage it */
177 proto_tree *wlccp_tree, *wlccp_type_tree, *wlccp_flags_tree;
180 guint offset = 0, version;
182 /* Make entries in Protocol column and Info column on summary display */
183 if (check_col(pinfo->cinfo, COL_PROTOCOL))
184 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLCCP");
186 if (check_col(pinfo->cinfo, COL_INFO)) {
187 if(tvb_get_guint8(tvb, 0) == 0xC1) { /* Get the version number */
188 col_add_fstr(pinfo->cinfo, COL_INFO, "Message subtype: %s",
189 match_strval((tvb_get_guint8(tvb, 6)>>6) & 3,
192 col_add_str(pinfo->cinfo, COL_INFO, "WLCCP frame");
197 /* create display subtree for the protocol */
198 ti = proto_tree_add_item(tree, proto_wlccp, tvb, 0, -1, FALSE);
199 wlccp_tree = proto_item_add_subtree(ti, ett_wlccp);
201 proto_tree_add_item(wlccp_tree, hf_wlccp_version,
202 tvb, offset, 1, FALSE);
203 version = tvb_get_guint8(tvb, 0);
207 proto_tree_add_item(wlccp_tree, hf_wlccp_length,
210 proto_tree_add_item(wlccp_tree, hf_wlccp_type,
212 type = tvb_get_ntohs(tvb, 2);
214 proto_tree_add_item(wlccp_tree, hf_wlccp_dstmac,
217 proto_tree_add_item(wlccp_tree, hf_wlccp_srcmac,
221 proto_tree_add_item(wlccp_tree, hf_wlccp_ipv4_address,
224 proto_tree_add_item(wlccp_tree, hf_wlccp_hostname,
229 if(version == 0xC1) {
230 proto_tree_add_item(wlccp_tree, hf_wlccp_sap,
231 tvb, offset, 1, FALSE);
234 proto_tree_add_item(wlccp_tree, hf_wlccp_destination_node_type,
235 tvb, offset, 2, FALSE);
238 proto_tree_add_item(wlccp_tree, hf_wlccp_length,
239 tvb, offset, 2, FALSE);
242 ti = proto_tree_add_item(wlccp_tree, hf_wlccp_type,
243 tvb, offset, 1, FALSE);
244 wlccp_type_tree = proto_item_add_subtree(ti, ett_wlccp_type);
246 proto_tree_add_item(wlccp_type_tree, hf_wlccp_subtype,
247 tvb, offset, 1, FALSE);
248 proto_tree_add_item(wlccp_type_tree, hf_wlccp_base_message_type,
249 tvb, offset, 1, FALSE);
252 proto_tree_add_item(wlccp_tree, hf_wlccp_hops,
253 tvb, offset, 1, FALSE);
256 proto_tree_add_item(wlccp_tree, hf_wlccp_msg_id,
257 tvb, offset, 2, FALSE);
260 ti = proto_tree_add_item(wlccp_tree, hf_wlccp_flags,
261 tvb, offset, 2, FALSE);
262 flags = tvb_get_ntohs(tvb, offset);
263 wlccp_flags_tree = proto_item_add_subtree(ti, ett_wlccp_flags);
265 proto_tree_add_item(wlccp_flags_tree, hf_wlccp_retry_flag,
266 tvb, offset, 2, FALSE);
268 proto_tree_add_item(wlccp_flags_tree,
269 hf_wlccp_response_request_flag,
270 tvb, offset, 2, FALSE);
272 proto_tree_add_item(wlccp_flags_tree,
274 tvb, offset, 2, FALSE);
276 proto_tree_add_item(wlccp_flags_tree,
277 hf_wlccp_inbound_flag,
278 tvb, offset, 2, FALSE);
280 proto_tree_add_item(wlccp_flags_tree,
281 hf_wlccp_outbound_flag,
282 tvb, offset, 2, FALSE);
284 proto_tree_add_item(wlccp_flags_tree,
285 hf_wlccp_hopwise_routing_flag,
286 tvb, offset, 2, FALSE);
288 proto_tree_add_item(wlccp_flags_tree,
289 hf_wlccp_root_cm_flag,
290 tvb, offset, 2, FALSE);
292 proto_tree_add_item(wlccp_flags_tree,
294 tvb, offset, 2, FALSE);
295 relay_flag = (tvb_get_ntohs(tvb, offset)>>8) & 1;
297 proto_tree_add_item(wlccp_flags_tree,
299 tvb, offset, 2, FALSE);
302 proto_tree_add_item(wlccp_tree, hf_wlccp_originator_node_type,
303 tvb, offset, 2, FALSE);
306 proto_tree_add_item(wlccp_tree, hf_wlccp_originator,
307 tvb, offset, 6, FALSE);
310 proto_tree_add_item(wlccp_tree, hf_wlccp_responder_node_type,
311 tvb, offset, 2, FALSE);
314 proto_tree_add_item(wlccp_tree, hf_wlccp_responder,
315 tvb, offset, 6, FALSE);
318 offset += 6; /* Skip over MAC address of sender again */
321 proto_tree_add_item(wlccp_tree, hf_wlccp_relay_node_type,
322 tvb, offset, 2, FALSE);
325 proto_tree_add_item(wlccp_tree, hf_wlccp_relay_node_id,
326 tvb, offset, 6, FALSE);
330 if(flags == 0x2800) { /* We have extra information at the end of the frame */
331 proto_tree_add_item(wlccp_tree, hf_wlccp_priority,
334 proto_tree_add_item(wlccp_tree, hf_wlccp_age,
337 proto_tree_add_item(wlccp_tree, hf_wlccp_period,
340 proto_tree_add_item(wlccp_tree, hf_wlccp_ipv4_address,
349 /* Register the protocol with Wireshark */
351 proto_register_wlccp(void)
353 /* Setup list of header fields See Section 1.6.1 for details*/
354 static hf_register_info hf[] = {
356 { "Version", "wlccp.version",
357 FT_UINT8, BASE_HEX, NULL,
358 0x0, "Protocol ID/Version", HFILL }
362 { "Src MAC", "wlccp.srcmac",
363 FT_ETHER, BASE_NONE, NULL,
364 0x0, "Source MAC address", HFILL }
368 { "Dst MAC", "wlccp.dstmac",
369 FT_ETHER, BASE_NONE, NULL,
370 0x0, "Destination MAC address", HFILL }
373 { &hf_wlccp_hostname,
374 { "Hostname", "wlccp.hostname",
375 FT_STRING, BASE_NONE, NULL,
376 0x0, "Hostname of device", HFILL }
380 { "SAP", "wlccp.sap",
381 FT_UINT8, BASE_DEC, VALS(wlccp_sap_vs),
382 0x0, "Service Access Point ID", HFILL }
385 { &hf_wlccp_destination_node_type,
386 { "Destination node type", "wlccp.destination_node_type",
387 FT_UINT8, BASE_DEC, VALS(wlccp_node_type_vs),
388 0x0, "Node type of the hop destination", HFILL }
392 { "Length", "wlccp.length",
393 FT_UINT16, BASE_DEC, NULL,
394 0x0, "Length of WLCCP payload (bytes)", HFILL }
399 { "Message Type", "wlccp.type",
400 FT_UINT8, BASE_HEX, NULL,
401 0x0, "Message Type", HFILL }
405 { "Subtype", "wlccp.subtype",
406 FT_UINT8, BASE_DEC, VALS(wlccp_subtype_vs),
407 MT_SUBTYPE, "Message Subtype", HFILL }
410 { &hf_wlccp_base_message_type,
411 { "Base message type", "wlccp.base_message_type",
412 FT_UINT8, BASE_HEX_DEC, NULL,
413 MT_BASE_MSG_TYPE, "Base message type", HFILL }
418 { "Hops", "wlccp.hops",
419 FT_UINT8, BASE_DEC, NULL,
420 0x0, "Number of WLCCP hops", HFILL }
424 { "Message ID", "wlccp.msg_id",
425 FT_UINT16, BASE_DEC, NULL,
426 0x0, "Sequence number used to match request/reply pairs",
432 { "Flags", "wlccp.flags",
433 FT_UINT16, BASE_HEX, NULL,
434 0x0, "Flags", HFILL }
437 { &hf_wlccp_retry_flag,
438 { "Retry flag", "wlccp.retry_flag",
439 FT_UINT16, BASE_DEC, NULL,
440 F_RETRY, "Set on for retransmissions", HFILL }
443 { &hf_wlccp_response_request_flag,
444 { "Response request flag", "wlccp.response_request_flag",
445 FT_UINT16, BASE_DEC, NULL,
446 F_RESPONSE_REQUEST, "Set on to request a reply", HFILL }
449 { &hf_wlccp_tlv_flag,
450 { "TLV flag", "wlccp.tlv_flag",
451 FT_UINT16, BASE_DEC, NULL,
452 F_TLV, "Set to indicate that optional TLVs follow the fixed fields", HFILL }
455 { &hf_wlccp_inbound_flag,
456 { "Inbound flag", "wlccp.inbound_flag",
457 FT_UINT16, BASE_DEC, NULL,
458 F_INBOUND, "Message is inbound to the top of the topology tree", HFILL }
461 { &hf_wlccp_outbound_flag,
462 { "Outbound flag", "wlccp.outbound_flag",
463 FT_UINT16, BASE_DEC, NULL,
464 F_OUTBOUND, "Message is outbound from the top of the topology tree", HFILL }
467 { &hf_wlccp_hopwise_routing_flag,
468 { "Hopwise-routing flag", "wlccp.hopwise_routing_flag",
469 FT_UINT16, BASE_DEC, NULL,
470 F_HOPWISE_ROUTING, "On to force intermediate access points to process the message also", HFILL }
473 { &hf_wlccp_root_cm_flag,
474 { "Root context manager flag", "wlccp.root_cm_flag",
475 FT_UINT16, BASE_DEC, NULL,
476 F_ROOT_CM, "Set to on to send message to the root context manager of the topology tree", HFILL }
479 { &hf_wlccp_relay_flag,
480 { "Relay flag", "wlccp.relay_flag",
481 FT_UINT16, BASE_DEC, NULL,
482 F_RELAY, "Signifies that this header is immediately followed by a relay node field", HFILL }
485 { &hf_wlccp_mic_flag,
486 { "MIC flag", "wlccp.mic_flag",
487 FT_UINT16, BASE_DEC, NULL,
488 F_MIC, "On in a message that must be authenticated and has an authentication TLV", HFILL }
491 { &hf_wlccp_originator_node_type,
492 { "Originator node type", "wlccp.originator_node_type",
493 FT_UINT8, BASE_DEC, VALS(wlccp_node_type_vs),
494 0x0, "Originating device's node type", HFILL }
497 { &hf_wlccp_originator,
498 { "Originator", "wlccp.originator",
499 FT_ETHER, BASE_NONE, NULL,
500 0x0, "Originating device's MAC address", HFILL }
503 { &hf_wlccp_responder_node_type,
504 { "Responder node type", "wlccp.responder_node_type",
505 FT_UINT8, BASE_DEC, VALS(wlccp_node_type_vs),
506 0x0, "Responding device's node type", HFILL }
509 { &hf_wlccp_responder,
510 { "Responder", "wlccp.responder",
511 FT_ETHER, BASE_NONE, NULL,
512 0x0, "Responding device's MAC address", HFILL }
515 { &hf_wlccp_relay_node_type,
516 { "Relay node type", "wlccp.relay_node_type",
517 FT_UINT8, BASE_DEC, VALS(wlccp_node_type_vs),
518 0x0, "Type of node which relayed this message", HFILL }
521 { &hf_wlccp_relay_node_id,
522 { "Relay node ID", "wlccp.relay_node_id",
523 FT_ETHER, BASE_NONE, NULL,
524 0x0, "Node which relayed this message", HFILL }
527 { &hf_wlccp_priority,
528 { "WDS priority", "wlccp.priority",
529 FT_UINT8, BASE_DEC, NULL, 0,
530 "WDS priority of this access point", HFILL }
534 { "Age", "wlccp.age",
535 FT_UINT32, BASE_DEC, NULL, 0,
536 "Time since AP became a WDS master", HFILL }
540 { "Period", "wlccp.period",
541 FT_UINT8, BASE_DEC, NULL, 0,
542 "Interval between announcements (seconds)", HFILL }
545 { &hf_wlccp_ipv4_address,
546 { "IPv4 Address", "wlccp.ipv4_address",
547 FT_IPv4, BASE_NONE, NULL, 0,
548 "IPv4 address of this access point", HFILL }
553 /* Setup protocol subtree array */
554 static gint *ett[] = {
560 /* Register the protocol name and description */
561 proto_wlccp = proto_register_protocol("Cisco Wireless LAN Context Control Protocol", "WLCCP", "wlccp");
563 /* Required function calls to register the header fields and subtrees used */
564 proto_register_field_array(proto_wlccp, hf, array_length(hf));
565 proto_register_subtree_array(ett, array_length(ett));
572 proto_reg_handoff_wlccp(void)
574 static gboolean inited = FALSE;
578 dissector_handle_t wlccp_handle;
580 wlccp_handle = create_dissector_handle(dissect_wlccp,
583 dissector_add("ethertype", ETHERTYPE_WLCCP, wlccp_handle);
584 dissector_add("udp.port", WLCCP_UDP_PORT, wlccp_handle);
585 dissector_add("llc.wlccp_pid", 0x0000, wlccp_handle);
593 proto_register_wlccp_oui(void)
595 static hf_register_info hf[] = {
597 { "PID", "llc.wlccp_pid",
598 FT_UINT16, BASE_HEX, VALS(cisco_pid_vals),
603 llc_add_oui(OUI_CISCOWL, "llc.wlccp_pid", "Cisco WLCCP OUI PID", &hf);