1 /* packet-ubdp.c 2 * Routines for the disassembly of the "Ubiquiti Discovery Protocol (UBDP)" 3 * 4 * Wireshark - Network traffic analyzer 5 * By Gerald Combs <gerald@wireshark.org> 6 * Copyright 1998 Gerald Combs 7 * 8 * SPDX-License-Identifier: GPL-2.0-or-later 9 */ 10 11 #include "config.h" 12 #include <stdio.h> 13 #include <epan/packet.h> 14 #include <epan/expert.h> 15 16 #define UB_TLV_TYPE 0 17 #define UB_TLV_LENGTH 1 18 19 #define UB_HW_ADDR 1 20 #define UB_HW_IP_ADDR 2 21 #define UB_FIRMWARE_FULL 3 22 #define UB_USERNAME 6 23 #define UB_UPTIME 10 24 #define UB_HOSTNAME 11 25 #define UB_PRODUCT 12 26 #define UB_ESSID 13 27 #define UB_WLAN_MODE 14 28 #define UB_SYSTEM_ID 16 29 #define UB_SEQ_NUM 18 30 #define UB_HW_ADDR_2 19 31 #define UB_TYPE 20 32 #define UB_MODEL 21 33 #define UB_FIRMWARE 22 34 #define UB_PLATFORM_VERS 27 35 36 void proto_register_ubdp(void); 37 void proto_reg_handoff_ubdp(void); 38 39 static int proto_ubdp = -1; 40 41 static int hf_ubdp_version = -1; 42 static int hf_ubdp_command = -1; 43 static int hf_ubdp_size = -1; 44 static int hf_ubdp_type = -1; 45 static int hf_ubdp_len = -1; 46 static int hf_ubdp_mac = -1; 47 static int hf_ubdp_ip = -1; 48 static int hf_ubdp_firmware_full = -1; 49 static int hf_ubdp_username = -1; 50 static int hf_ubdp_uptime = -1; 51 static int hf_ubdp_hostname = -1; 52 static int hf_ubdp_product = -1; 53 static int hf_ubdp_ssid = -1; 54 static int hf_ubdp_wlan_mode = -1; 55 static int hf_ubdp_system_id = -1; 56 static int hf_ubdp_seq_num = -1; 57 static int hf_ubdp_model = -1; 58 static int hf_ubdp_firmware = -1; 59 static int hf_ubdp_platform_vers = -1; 60 static int hf_ubdp_generic = -1; 61 62 static gint ett_ubdp = -1; 63 static gint ett_ubdp_tlv = -1; 64 65 static expert_field ei_ubdp_bad_version = EI_INIT; 66 static expert_field ei_ubdp_unexpected_len = EI_INIT; 67 68 static dissector_handle_t ubdp_handle; 69 70 /* Format Identifier */ 71 static const value_string type_vals[] = { 72 { UB_HW_ADDR, "MAC Address" }, 73 { UB_HW_IP_ADDR, "MAC and IP Address" }, 74 { UB_FIRMWARE_FULL, "Firmware Detailed" }, 75 { UB_USERNAME, "Username" }, 76 { UB_UPTIME, "Uptime" }, 77 { UB_HOSTNAME, "Hostname" }, 78 { UB_PRODUCT, "Product" }, 79 { UB_ESSID, "ESSID" }, 80 { UB_WLAN_MODE, "WLAN Mode" }, 81 { UB_SYSTEM_ID, "System ID" }, 82 { UB_SEQ_NUM, "Counter" }, 83 { UB_HW_ADDR_2, "MAC Address" }, 84 { UB_TYPE, "Model Type" }, 85 { UB_MODEL, "Model" }, 86 { UB_FIRMWARE, "Firmware" }, 87 { UB_PLATFORM_VERS, "Platform Version"}, 88 { 0, NULL } 89 }; 90 91 static const string_string ubiquiti_vals[] = { 92 {"UP4", "UP4: UniFi Phone-X"}, 93 {"UP5", "UP5: UniFi Phone"}, 94 {"UP5c", "UP5c: UniFi Phone"}, 95 {"UP5t", "UP5t: UniFi Phone-Pro"}, 96 {"UP5tc", "UP5tc: UniFi Phone-Pro"}, 97 {"UP7", "UP7: UniFi Phone-Executive"}, 98 {"UP7c", "UP7c: UniFi Phone-Executive"}, 99 {"N2N", "N2N: NanoStation M2"}, 100 {"p2N", "p2N: PicoStation M2"}, 101 {"P6E", "P6E: mFi mPower Pro"}, 102 {"US8P150", "US8P150: UniFi Switch 8 POE-150W"}, 103 {"US16P150","US16P150: UniFi Switch 16 POE-150W"}, 104 {"US24", "US24: UniFi Switch 24"}, 105 {"US24P250","US24P250: UniFi Switch 24 POE-250W"}, 106 {"US24P500","US24P500: UniFi Switch 24 POE-500W"}, 107 {"US48", "US48: UniFi Switch 48"}, 108 {"US48P500","US48P500: UniFi Switch 48 POE-500W"}, 109 {"US48P750","US48P750: UniFi Switch 48 POE-750W"}, 110 {"UGW3", "UGW3: UniFi Security Gateway"}, 111 {"UGW4", "UGW4: UniFi Security Gateway-Pro"}, 112 {"BZ2", "BZ2: UniFi AP"}, 113 {"BZ2LR", "BZ2LR: UniFi AP-LR"}, 114 {"U2O", "U2O: UniFi AP-Outdoor"}, 115 {"U2HSR", "U2HSR: UniFi AP-Outdoor+"}, 116 {"U2IW", "U2IW: UniFi AP-In Wall"}, 117 {"U5O", "U5O: UniFi AP-Outdoor 5G"}, 118 {"U7E", "U7E: UniFi AP-AC"}, 119 {"U7Ev2", "U7Ev2: UniFi AP-AC v2"}, 120 {"U7EDU", "U7EDU: UniFi AP-AC-EDU"}, 121 {"U7HD", "U7HD: UniFi AP-AC-HD"}, 122 {"U7LR", "U7LR: UniFi AP-AC-LR"}, 123 {"U7LT", "U7LT: UniFi AP-AC-Lite"}, 124 {"U7MSH", "U7MSH: UniFi AP-AC-Mesh"}, 125 {"U7MP", "U7MP: UniFi AP-AC-Mesh-Pro"}, 126 {"U7O", "U7O: UniFi AP-AC Outdoor"}, 127 {"U7P", "U7P: UniFi AP-Pro"}, 128 {"U7PG2", "U7PG2: UniFi AP-AC-Pro Gen2"}, 129 {NULL, NULL} 130 }; 131 132 133 static int 134 dissect_ubdp(tvbuff_t *ubdp_tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) 135 { 136 proto_tree *ubdp_tree, *tlv_tree; 137 proto_item *ubdp_item, *tlv_item; 138 guint32 ubdp_length; 139 guint32 ubdp_type; 140 guint32 version; 141 gint offset = 0; 142 gchar *uValue; 143 const gchar *uModel; 144 145 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UBDP"); 146 col_clear(pinfo->cinfo, COL_INFO); 147 col_add_fstr(pinfo->cinfo, COL_INFO, "UBDP"); 148 149 ubdp_item = proto_tree_add_item(tree, proto_ubdp, ubdp_tvb, 0, -1, ENC_NA); 150 ubdp_tree = proto_item_add_subtree(ubdp_item, ett_ubdp); 151 152 proto_tree_add_item_ret_uint(ubdp_tree, hf_ubdp_version, ubdp_tvb, offset, 1, ENC_BIG_ENDIAN, &version); 153 proto_tree_add_item(ubdp_tree, hf_ubdp_command, ubdp_tvb, offset + 1, 1, ENC_BIG_ENDIAN); 154 proto_tree_add_item(ubdp_tree, hf_ubdp_size, ubdp_tvb, offset + 2, 2, ENC_BIG_ENDIAN); 155 156 offset+=4; 157 158 if (version != 1 && version != 2){ 159 expert_add_info(pinfo, ubdp_item, &ei_ubdp_bad_version); 160 return tvb_captured_length(ubdp_tvb); 161 } 162 while(tvb_reported_length_remaining(ubdp_tvb, offset) != 0){ 163 tlv_tree = proto_tree_add_subtree(ubdp_tree, ubdp_tvb, offset + UB_TLV_TYPE, -1, ett_ubdp_tlv, &tlv_item, ""); 164 proto_tree_add_item_ret_uint(tlv_tree, hf_ubdp_type, ubdp_tvb, offset + UB_TLV_TYPE, 1, ENC_BIG_ENDIAN, &ubdp_type); 165 proto_item_set_text(tlv_tree, "%s", val_to_str_const(ubdp_type, type_vals, "Unknown type")); 166 proto_tree_add_item_ret_uint(tlv_tree, hf_ubdp_len, ubdp_tvb, offset + UB_TLV_LENGTH, 2, ENC_BIG_ENDIAN, &ubdp_length); 167 offset += 3; 168 169 switch(ubdp_type){ 170 case UB_HW_ADDR: 171 case UB_HW_ADDR_2: 172 if(ubdp_length == 6){ 173 proto_tree_add_item(tlv_tree, hf_ubdp_mac, ubdp_tvb, offset, ubdp_length, ENC_NA); 174 }else{ 175 expert_add_info(pinfo, tlv_item, &ei_ubdp_unexpected_len); 176 proto_tree_add_item(tlv_tree, hf_ubdp_generic, ubdp_tvb, offset, ubdp_length, ENC_NA); 177 } 178 break; 179 case UB_HW_IP_ADDR: 180 if(ubdp_length == 10){ 181 proto_tree_add_item(tlv_tree, hf_ubdp_mac, ubdp_tvb, offset, 6, ENC_NA); 182 proto_tree_add_item(tlv_tree, hf_ubdp_ip, ubdp_tvb, offset + 6, 4, ENC_NA); 183 }else{ 184 expert_add_info(pinfo, tlv_item, &ei_ubdp_unexpected_len); 185 proto_tree_add_item(tlv_tree, hf_ubdp_generic, ubdp_tvb, offset, ubdp_length, ENC_NA); 186 } 187 break; 188 case UB_FIRMWARE_FULL: 189 proto_tree_add_item(tlv_tree, hf_ubdp_firmware_full, ubdp_tvb, offset, ubdp_length, ENC_ASCII|ENC_NA); 190 break; 191 case UB_USERNAME: 192 proto_tree_add_item(tlv_tree, hf_ubdp_username, ubdp_tvb, offset, ubdp_length, ENC_ASCII|ENC_NA); 193 break; 194 case UB_UPTIME: 195 if(ubdp_length == 4){ 196 proto_tree_add_item(tlv_tree, hf_ubdp_uptime, ubdp_tvb, offset, ubdp_length, ENC_NA); 197 }else{ 198 expert_add_info(pinfo, tlv_item, &ei_ubdp_unexpected_len); 199 proto_tree_add_item(tlv_tree, hf_ubdp_generic, ubdp_tvb, offset, ubdp_length, ENC_NA); 200 } 201 break; 202 case UB_HOSTNAME: 203 proto_tree_add_item(tlv_tree, hf_ubdp_hostname, ubdp_tvb, offset, ubdp_length, ENC_ASCII|ENC_NA); 204 break; 205 case UB_PRODUCT: 206 uValue = tvb_get_string_enc(pinfo->pool, ubdp_tvb, offset, ubdp_length, ENC_ASCII); 207 uModel = try_str_to_str(uValue, ubiquiti_vals); 208 proto_tree_add_string(tlv_tree, hf_ubdp_product, ubdp_tvb, offset, ubdp_length, uModel ? uModel : uValue); 209 break; 210 case UB_ESSID: 211 proto_tree_add_item(tlv_tree, hf_ubdp_ssid, ubdp_tvb, offset, ubdp_length, ENC_ASCII|ENC_NA); 212 break; 213 case UB_WLAN_MODE: 214 if(ubdp_length == 1){ 215 proto_tree_add_item(tlv_tree, hf_ubdp_wlan_mode, ubdp_tvb, offset, ubdp_length, ENC_NA); 216 }else{ 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); 219 } 220 break; 221 case UB_SYSTEM_ID: 222 if(ubdp_length == 2){ 223 proto_tree_add_item(tlv_tree, hf_ubdp_system_id, ubdp_tvb, offset, ubdp_length, ENC_BIG_ENDIAN); 224 }else{ 225 expert_add_info(pinfo, tlv_item, &ei_ubdp_unexpected_len); 226 proto_tree_add_item(tlv_tree, hf_ubdp_generic, ubdp_tvb, offset, ubdp_length, ENC_NA); 227 } 228 break; 229 case UB_SEQ_NUM: 230 if(ubdp_length == 4){ 231 proto_tree_add_item(tlv_tree, hf_ubdp_seq_num, ubdp_tvb, offset, ubdp_length, ENC_NA); 232 }else{ 233 expert_add_info(pinfo, tlv_item, &ei_ubdp_unexpected_len); 234 proto_tree_add_item(tlv_tree, hf_ubdp_generic, ubdp_tvb, offset, ubdp_length, ENC_NA); 235 } 236 break; 237 case UB_TYPE: 238 uValue = tvb_get_string_enc(pinfo->pool, ubdp_tvb, offset, ubdp_length, ENC_ASCII); 239 uModel = try_str_to_str(uValue, ubiquiti_vals); 240 proto_tree_add_string(tlv_tree, hf_ubdp_model, ubdp_tvb, offset, ubdp_length, uModel ? uModel : uValue); 241 break; 242 case UB_MODEL: 243 uValue = tvb_get_string_enc(pinfo->pool, ubdp_tvb, offset, ubdp_length, ENC_ASCII); 244 uModel = try_str_to_str(uValue, ubiquiti_vals); 245 proto_tree_add_string(tlv_tree, hf_ubdp_model, ubdp_tvb, offset, ubdp_length, uModel ? uModel : uValue); 246 break; 247 case UB_FIRMWARE: 248 proto_tree_add_item(tlv_tree, hf_ubdp_firmware, ubdp_tvb, offset, ubdp_length, ENC_ASCII|ENC_NA); 249 break; 250 case UB_PLATFORM_VERS: 251 proto_tree_add_item(tlv_tree, hf_ubdp_platform_vers, ubdp_tvb, offset, ubdp_length, ENC_ASCII|ENC_NA); 252 break; 253 default: 254 proto_tree_add_item(tlv_tree, hf_ubdp_generic, ubdp_tvb, offset, ubdp_length, ENC_NA); 255 break; 256 } 257 proto_item_set_len(tlv_item, ubdp_length + 3); 258 offset += ubdp_length; 259 } 260 return tvb_captured_length(ubdp_tvb); 261 } 262 263 void 264 proto_register_ubdp(void) 265 { 266 static hf_register_info hf[] = { 267 { &hf_ubdp_version, {"Version", "ubdp.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 268 { &hf_ubdp_command, {"Command", "ubdp.command", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 269 { &hf_ubdp_size, {"Data Bytes","ubdp.size",FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 270 { &hf_ubdp_type, {"Type","ubdp.type",FT_UINT8, BASE_DEC, VALS(type_vals), 0x0, NULL, HFILL }}, 271 { &hf_ubdp_len, {"Length","ubdp.len",FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 272 { &hf_ubdp_mac, {"MAC","ubdp.mac",FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, 273 { &hf_ubdp_ip, {"IP","ubdp.ip",FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, 274 { &hf_ubdp_firmware_full, {"Firmware Path","ubdp.firmware_full",FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }}, 275 { &hf_ubdp_username, {"Username", "ubdp.username", FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }}, 276 { &hf_ubdp_uptime, {"Uptime","ubdp.uptime",FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 277 { &hf_ubdp_hostname, {"Hostname","ubdp.hostname",FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }}, 278 { &hf_ubdp_product, {"Product","ubdp.product",FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }}, 279 { &hf_ubdp_ssid, {"SSID","ubdp.ssid",FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }}, 280 { &hf_ubdp_wlan_mode, {"Wireless Mode","ubdp.wlan_mode",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 281 { &hf_ubdp_seq_num, {"Counter","ubdp.seq_num",FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 282 { &hf_ubdp_model, {"Model","ubdp.model",FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }}, 283 { &hf_ubdp_system_id, {"System ID","ubdp.system_id",FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, 284 { &hf_ubdp_firmware, {"Version","ubdp.firmware",FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }}, 285 { &hf_ubdp_platform_vers, {"Platform Version","ubdp.platform_vers",FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }}, 286 { &hf_ubdp_generic, {"Unknown Field","ubdp.unk",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }} 287 }; 288 289 static gint *ett[] = { 290 &ett_ubdp, 291 &ett_ubdp_tlv 292 }; 293 294 static ei_register_info ei[] = { 295 { &ei_ubdp_bad_version, { "ubdp.bad-version-detected", PI_PROTOCOL, PI_WARN, "Bad Version Detected", EXPFILL }}, 296 { &ei_ubdp_unexpected_len, { "ubdp.bad-field-length-detected", PI_PROTOCOL, PI_WARN, "Bad Length Field Detected", EXPFILL }}, 297 }; 298 299 expert_module_t* expert_ubdp; 300 301 proto_ubdp = proto_register_protocol("Ubiquiti Discovery Protocol", "UBDP", "ubdp"); 302 303 proto_register_field_array(proto_ubdp, hf, array_length(hf)); 304 proto_register_subtree_array(ett, array_length(ett)); 305 306 expert_ubdp = expert_register_protocol(proto_ubdp); 307 expert_register_field_array(expert_ubdp, ei, array_length(ei)); 308 309 register_dissector("ubdp", dissect_ubdp, proto_ubdp); 310 ubdp_handle = create_dissector_handle(dissect_ubdp, proto_ubdp); 311 } 312 313 void 314 proto_reg_handoff_ubdp(void) 315 { 316 dissector_add_for_decode_as_with_preference("udp.port", ubdp_handle); 317 } 318 319 /* 320 * Editor modelines - https://www.wireshark.org/tools/modelines.html 321 * 322 * Local variables: 323 * c-basic-offset: 4 324 * tab-width: 8 325 * indent-tabs-mode: nil 326 * End: 327 * 328 * vi: set shiftwidth=4 tabstop=8 expandtab: 329 * :indentSize=4:tabSize=8:noTabs=true: 330 */ 331