2 * Routines for the disassembly of the "Ubiquiti Discovery Protocol (UBDP)"
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include <epan/packet.h>
13 #include <epan/expert.h>
16 #define UB_TLV_LENGTH 1
19 #define UB_HW_IP_ADDR 2
20 #define UB_FIRMWARE_FULL 3
21 #define UB_HW_IP_ADDR_2 4
22 #define UB_HW_ADDR_2 5
25 #define UB_RND_CHALLENGE 8
26 #define UB_CHALLENGE 9
28 #define UB_HOSTNAME 11
31 #define UB_WLAN_MODE 14
33 #define UB_SYSTEM_ID 16
35 #define UB_HW_ADDR_3 19
38 #define UB_FIRMWARE 22
40 #define UB_LOCATING 24
41 #define UB_DHCP_CLIENT 25
42 #define UB_DHCP_CLIENT_BOUND 26
43 #define UB_PLATFORM_VERS 27
44 #define UB_SSHD_PORT 28
46 void proto_register_ubdp(void);
47 void proto_reg_handoff_ubdp(void);
49 static int proto_ubdp
;
51 static int hf_ubdp_version
;
52 static int hf_ubdp_command
;
53 static int hf_ubdp_size
;
54 static int hf_ubdp_type
;
55 static int hf_ubdp_len
;
56 static int hf_ubdp_mac
;
57 static int hf_ubdp_ip
;
58 static int hf_ubdp_firmware_full
;
59 static int hf_ubdp_username
;
60 static int hf_ubdp_salt
;
61 static int hf_ubdp_rnd_challenge
;
62 static int hf_ubdp_challenge
;
63 static int hf_ubdp_uptime
;
64 static int hf_ubdp_hostname
;
65 static int hf_ubdp_product
;
66 static int hf_ubdp_ssid
;
67 static int hf_ubdp_wlan_mode
;
68 static int hf_ubdp_webui
;
69 static int hf_ubdp_system_id
;
70 static int hf_ubdp_seq_num
;
71 static int hf_ubdp_model
;
72 static int hf_ubdp_firmware
;
73 static int hf_ubdp_default
;
74 static int hf_ubdp_locating
;
75 static int hf_ubdp_dhcp_client
;
76 static int hf_ubdp_dhcp_client_bound
;
77 static int hf_ubdp_platform_vers
;
78 static int hf_ubdp_sshd_port
;
79 static int hf_ubdp_generic
;
82 static int ett_ubdp_tlv
;
84 static expert_field ei_ubdp_bad_version
;
85 static expert_field ei_ubdp_unexpected_len
;
87 static dissector_handle_t ubdp_handle
;
89 /* Format Identifier */
90 static const value_string type_vals
[] = {
91 { UB_HW_ADDR
, "MAC Address" },
92 { UB_HW_IP_ADDR
, "MAC and IP Address" },
93 { UB_FIRMWARE_FULL
, "Firmware Detailed" },
94 { UB_HW_IP_ADDR_2
, "IP Address" },
95 { UB_HW_ADDR_2
, "MAC Address" },
96 { UB_USERNAME
, "Username" },
98 { UB_RND_CHALLENGE
, "Random Challenge" },
99 { UB_CHALLENGE
, "Challenge" },
100 { UB_UPTIME
, "Uptime" },
101 { UB_HOSTNAME
, "Hostname" },
102 { UB_PRODUCT
, "Product" },
103 { UB_ESSID
, "ESSID" },
104 { UB_WLAN_MODE
, "WLAN Mode" },
105 { UB_WEBUI
, "Web-UI" },
106 { UB_SYSTEM_ID
, "System ID" },
107 { UB_SEQ_NUM
, "Counter" },
108 { UB_HW_ADDR_3
, "MAC Address" },
109 { UB_TYPE
, "Model Type" },
110 { UB_MODEL
, "Model" },
111 { UB_FIRMWARE
, "Firmware" },
112 { UB_DEFAULT
, "Default" },
113 { UB_LOCATING
, "Locating" },
114 { UB_DHCP_CLIENT
, "DHCP-Client" },
115 { UB_DHCP_CLIENT_BOUND
, "DHCP-Client Bound" },
116 { UB_PLATFORM_VERS
, "Platform Version"},
117 { UB_SSHD_PORT
, "SSHD Port"},
121 static const string_string ubiquiti_vals
[] = {
122 {"UP4", "UP4: UniFi Phone-X"},
123 {"UP5", "UP5: UniFi Phone"},
124 {"UP5c", "UP5c: UniFi Phone"},
125 {"UP5t", "UP5t: UniFi Phone-Pro"},
126 {"UP5tc", "UP5tc: UniFi Phone-Pro"},
127 {"UP7", "UP7: UniFi Phone-Executive"},
128 {"UP7c", "UP7c: UniFi Phone-Executive"},
129 {"N2N", "N2N: NanoStation M2"},
130 {"p2N", "p2N: PicoStation M2"},
131 {"P6E", "P6E: mFi mPower Pro"},
132 {"US8P150", "US8P150: UniFi Switch 8 POE-150W"},
133 {"US16P150","US16P150: UniFi Switch 16 POE-150W"},
134 {"US24", "US24: UniFi Switch 24"},
135 {"US24P250","US24P250: UniFi Switch 24 POE-250W"},
136 {"US24P500","US24P500: UniFi Switch 24 POE-500W"},
137 {"US48", "US48: UniFi Switch 48"},
138 {"US48P500","US48P500: UniFi Switch 48 POE-500W"},
139 {"US48P750","US48P750: UniFi Switch 48 POE-750W"},
140 {"UGW3", "UGW3: UniFi Security Gateway"},
141 {"UGW4", "UGW4: UniFi Security Gateway-Pro"},
142 {"BZ2", "BZ2: UniFi AP"},
143 {"BZ2LR", "BZ2LR: UniFi AP-LR"},
144 {"U2O", "U2O: UniFi AP-Outdoor"},
145 {"U2HSR", "U2HSR: UniFi AP-Outdoor+"},
146 {"U2IW", "U2IW: UniFi AP-In Wall"},
147 {"U5O", "U5O: UniFi AP-Outdoor 5G"},
148 {"U7E", "U7E: UniFi AP-AC"},
149 {"U7Ev2", "U7Ev2: UniFi AP-AC v2"},
150 {"U7EDU", "U7EDU: UniFi AP-AC-EDU"},
151 {"U7HD", "U7HD: UniFi AP-AC-HD"},
152 {"U7LR", "U7LR: UniFi AP-AC-LR"},
153 {"U7LT", "U7LT: UniFi AP-AC-Lite"},
154 {"U7MSH", "U7MSH: UniFi AP-AC-Mesh"},
155 {"U7MP", "U7MP: UniFi AP-AC-Mesh-Pro"},
156 {"U7O", "U7O: UniFi AP-AC Outdoor"},
157 {"U7P", "U7P: UniFi AP-Pro"},
158 {"U7PG2", "U7PG2: UniFi AP-AC-Pro Gen2"},
164 dissect_ubdp(tvbuff_t
*ubdp_tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
166 proto_tree
*ubdp_tree
, *tlv_tree
;
167 proto_item
*ubdp_item
, *tlv_item
;
168 uint32_t ubdp_length
;
175 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "UBDP");
176 col_set_str(pinfo
->cinfo
, COL_INFO
, "UBDP");
178 ubdp_item
= proto_tree_add_item(tree
, proto_ubdp
, ubdp_tvb
, 0, -1, ENC_NA
);
179 ubdp_tree
= proto_item_add_subtree(ubdp_item
, ett_ubdp
);
181 proto_tree_add_item_ret_uint(ubdp_tree
, hf_ubdp_version
, ubdp_tvb
, offset
, 1, ENC_BIG_ENDIAN
, &version
);
182 proto_tree_add_item(ubdp_tree
, hf_ubdp_command
, ubdp_tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
183 proto_tree_add_item(ubdp_tree
, hf_ubdp_size
, ubdp_tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
);
187 if (version
!= 1 && version
!= 2){
188 expert_add_info(pinfo
, ubdp_item
, &ei_ubdp_bad_version
);
189 return tvb_captured_length(ubdp_tvb
);
191 while(tvb_reported_length_remaining(ubdp_tvb
, offset
) != 0){
192 tlv_tree
= proto_tree_add_subtree(ubdp_tree
, ubdp_tvb
, offset
+ UB_TLV_TYPE
, -1, ett_ubdp_tlv
, &tlv_item
, "");
193 proto_tree_add_item_ret_uint(tlv_tree
, hf_ubdp_type
, ubdp_tvb
, offset
+ UB_TLV_TYPE
, 1, ENC_BIG_ENDIAN
, &ubdp_type
);
194 proto_item_set_text(tlv_tree
, "%s", val_to_str_const(ubdp_type
, type_vals
, "Unknown type"));
195 proto_tree_add_item_ret_uint(tlv_tree
, hf_ubdp_len
, ubdp_tvb
, offset
+ UB_TLV_LENGTH
, 2, ENC_BIG_ENDIAN
, &ubdp_length
);
202 if(ubdp_length
== 6){
203 proto_tree_add_item(tlv_tree
, hf_ubdp_mac
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
205 expert_add_info(pinfo
, tlv_item
, &ei_ubdp_unexpected_len
);
206 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
210 case UB_HW_IP_ADDR_2
:
211 if(ubdp_length
== 10){ // UB_HW_IP_ADDR
212 proto_tree_add_item(tlv_tree
, hf_ubdp_mac
, ubdp_tvb
, offset
, 6, ENC_NA
);
213 proto_tree_add_item(tlv_tree
, hf_ubdp_ip
, ubdp_tvb
, offset
+ 6, 4, ENC_NA
);
214 }else if(ubdp_length
== 4){ // UB_HW_IP_ADDR_2
215 proto_tree_add_item(tlv_tree
, hf_ubdp_ip
, ubdp_tvb
, offset
, 4, ENC_NA
);
217 expert_add_info(pinfo
, tlv_item
, &ei_ubdp_unexpected_len
);
218 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
221 case UB_FIRMWARE_FULL
:
222 proto_tree_add_item(tlv_tree
, hf_ubdp_firmware_full
, ubdp_tvb
, offset
, ubdp_length
, ENC_ASCII
);
225 proto_tree_add_item(tlv_tree
, hf_ubdp_username
, ubdp_tvb
, offset
, ubdp_length
, ENC_ASCII
);
228 proto_tree_add_item(tlv_tree
, hf_ubdp_salt
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
230 case UB_RND_CHALLENGE
:
231 proto_tree_add_item(tlv_tree
, hf_ubdp_rnd_challenge
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
234 proto_tree_add_item(tlv_tree
, hf_ubdp_challenge
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
237 if(ubdp_length
== 4){
238 proto_tree_add_item(tlv_tree
, hf_ubdp_uptime
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
240 expert_add_info(pinfo
, tlv_item
, &ei_ubdp_unexpected_len
);
241 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
245 proto_tree_add_item(tlv_tree
, hf_ubdp_hostname
, ubdp_tvb
, offset
, ubdp_length
, ENC_UTF_8
);
248 uValue
= tvb_get_string_enc(pinfo
->pool
, ubdp_tvb
, offset
, ubdp_length
, ENC_ASCII
);
249 uModel
= try_str_to_str(uValue
, ubiquiti_vals
);
250 proto_tree_add_string(tlv_tree
, hf_ubdp_product
, ubdp_tvb
, offset
, ubdp_length
, uModel
? uModel
: uValue
);
253 proto_tree_add_item(tlv_tree
, hf_ubdp_ssid
, ubdp_tvb
, offset
, ubdp_length
, ENC_ASCII
);
256 if(ubdp_length
== 1){
257 proto_tree_add_item(tlv_tree
, hf_ubdp_wlan_mode
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
259 expert_add_info(pinfo
, tlv_item
, &ei_ubdp_unexpected_len
);
260 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
264 proto_tree_add_item(tlv_tree
, hf_ubdp_webui
, ubdp_tvb
, offset
, ubdp_length
, ENC_UTF_8
);
267 if(ubdp_length
== 2){
268 proto_tree_add_item(tlv_tree
, hf_ubdp_system_id
, ubdp_tvb
, offset
, ubdp_length
, ENC_BIG_ENDIAN
);
270 expert_add_info(pinfo
, tlv_item
, &ei_ubdp_unexpected_len
);
271 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
275 if(ubdp_length
== 4){
276 proto_tree_add_item(tlv_tree
, hf_ubdp_seq_num
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
278 expert_add_info(pinfo
, tlv_item
, &ei_ubdp_unexpected_len
);
279 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
283 uValue
= tvb_get_string_enc(pinfo
->pool
, ubdp_tvb
, offset
, ubdp_length
, ENC_ASCII
);
284 uModel
= try_str_to_str(uValue
, ubiquiti_vals
);
285 proto_tree_add_string(tlv_tree
, hf_ubdp_model
, ubdp_tvb
, offset
, ubdp_length
, uModel
? uModel
: uValue
);
288 uValue
= tvb_get_string_enc(pinfo
->pool
, ubdp_tvb
, offset
, ubdp_length
, ENC_ASCII
);
289 uModel
= try_str_to_str(uValue
, ubiquiti_vals
);
290 proto_tree_add_string(tlv_tree
, hf_ubdp_model
, ubdp_tvb
, offset
, ubdp_length
, uModel
? uModel
: uValue
);
293 proto_tree_add_item(tlv_tree
, hf_ubdp_firmware
, ubdp_tvb
, offset
, ubdp_length
, ENC_ASCII
);
296 if(ubdp_length
== 1 || ubdp_length
== 4){
297 proto_tree_add_item(tlv_tree
, hf_ubdp_default
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
299 expert_add_info(pinfo
, tlv_item
, &ei_ubdp_unexpected_len
);
300 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
304 if(ubdp_length
== 1 || ubdp_length
== 4){
305 proto_tree_add_item(tlv_tree
, hf_ubdp_locating
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
307 expert_add_info(pinfo
, tlv_item
, &ei_ubdp_unexpected_len
);
308 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
312 if(ubdp_length
== 1){
313 proto_tree_add_item(tlv_tree
, hf_ubdp_dhcp_client
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
315 expert_add_info(pinfo
, tlv_item
, &ei_ubdp_unexpected_len
);
316 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
319 case UB_DHCP_CLIENT_BOUND
:
320 if(ubdp_length
== 1){
321 proto_tree_add_item(tlv_tree
, hf_ubdp_dhcp_client_bound
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
323 expert_add_info(pinfo
, tlv_item
, &ei_ubdp_unexpected_len
);
324 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
327 case UB_PLATFORM_VERS
:
328 proto_tree_add_item(tlv_tree
, hf_ubdp_platform_vers
, ubdp_tvb
, offset
, ubdp_length
, ENC_ASCII
);
331 if(ubdp_length
== 2){
332 proto_tree_add_item(tlv_tree
, hf_ubdp_dhcp_client_bound
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
334 expert_add_info(pinfo
, tlv_item
, &ei_ubdp_unexpected_len
);
335 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
339 proto_tree_add_item(tlv_tree
, hf_ubdp_generic
, ubdp_tvb
, offset
, ubdp_length
, ENC_NA
);
342 proto_item_set_len(tlv_item
, ubdp_length
+ 3);
343 offset
+= ubdp_length
;
345 return tvb_captured_length(ubdp_tvb
);
349 proto_register_ubdp(void)
351 static hf_register_info hf
[] = {
352 { &hf_ubdp_version
, {"Version", "ubdp.version", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
353 { &hf_ubdp_command
, {"Command", "ubdp.command", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
354 { &hf_ubdp_size
, {"Data Bytes","ubdp.size",FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
355 { &hf_ubdp_type
, {"Type","ubdp.type",FT_UINT8
, BASE_DEC
, VALS(type_vals
), 0x0, NULL
, HFILL
}},
356 { &hf_ubdp_len
, {"Length","ubdp.len",FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
357 { &hf_ubdp_mac
, {"MAC","ubdp.mac",FT_ETHER
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
358 { &hf_ubdp_ip
, {"IP","ubdp.ip",FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
359 { &hf_ubdp_firmware_full
, {"Firmware Path","ubdp.firmware_full",FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
360 { &hf_ubdp_username
, {"Username", "ubdp.username", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
361 { &hf_ubdp_salt
, {"Salt", "ubdp.salt", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
362 { &hf_ubdp_rnd_challenge
, {"Random Challenge", "ubdp.rnd_challenge", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
363 { &hf_ubdp_challenge
, {"Challenge", "ubdp.challenge", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
364 { &hf_ubdp_uptime
, {"Uptime","ubdp.uptime",FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
365 { &hf_ubdp_hostname
, {"Hostname","ubdp.hostname",FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
366 { &hf_ubdp_product
, {"Product","ubdp.product",FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
367 { &hf_ubdp_ssid
, {"SSID","ubdp.ssid",FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
368 { &hf_ubdp_wlan_mode
, {"Wireless Mode","ubdp.wlan_mode",FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
369 { &hf_ubdp_webui
, {"Web-UI", "ubdp.web_ui", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
370 { &hf_ubdp_seq_num
, {"Counter","ubdp.seq_num",FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
371 { &hf_ubdp_model
, {"Model","ubdp.model",FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
372 { &hf_ubdp_system_id
, {"System ID","ubdp.system_id",FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
373 { &hf_ubdp_firmware
, {"Version","ubdp.firmware",FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
374 { &hf_ubdp_default
, {"Default", "ubdp.default", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
375 { &hf_ubdp_locating
, {"Locating", "ubdp.locating", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
376 { &hf_ubdp_dhcp_client
, {"DHCP-Client", "ubdp.dhcp_client", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
377 { &hf_ubdp_dhcp_client_bound
, {"DHCP-Client Bound", "ubdp.dhcp_client_bound", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
378 { &hf_ubdp_platform_vers
, {"Platform Version","ubdp.platform_vers",FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
379 { &hf_ubdp_sshd_port
, {"SSHD Port","ubdp.sshd_port", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
380 { &hf_ubdp_generic
, {"Unknown Field","ubdp.unk",FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}}
383 static int *ett
[] = {
388 static ei_register_info ei
[] = {
389 { &ei_ubdp_bad_version
, { "ubdp.bad-version-detected", PI_PROTOCOL
, PI_WARN
, "Bad Version Detected", EXPFILL
}},
390 { &ei_ubdp_unexpected_len
, { "ubdp.bad-field-length-detected", PI_PROTOCOL
, PI_WARN
, "Bad Length Field Detected", EXPFILL
}},
393 expert_module_t
* expert_ubdp
;
395 proto_ubdp
= proto_register_protocol("Ubiquiti Discovery Protocol", "UBDP", "ubdp");
397 proto_register_field_array(proto_ubdp
, hf
, array_length(hf
));
398 proto_register_subtree_array(ett
, array_length(ett
));
400 expert_ubdp
= expert_register_protocol(proto_ubdp
);
401 expert_register_field_array(expert_ubdp
, ei
, array_length(ei
));
403 ubdp_handle
= register_dissector("ubdp", dissect_ubdp
, proto_ubdp
);
407 proto_reg_handoff_ubdp(void)
409 dissector_add_for_decode_as_with_preference("udp.port", ubdp_handle
);
413 * Editor modelines - https://www.wireshark.org/tools/modelines.html
418 * indent-tabs-mode: nil
421 * vi: set shiftwidth=4 tabstop=8 expandtab:
422 * :indentSize=4:tabSize=8:noTabs=true: