diff options
author | Michael Mann <mmann78@netscape.net> | 2016-10-09 20:01:45 -0400 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2016-10-11 20:34:04 +0000 |
commit | 7cef0cb93cc44ed02cd68caa79d3d97173b0edfe (patch) | |
tree | 0fe688ba6dcbd680c882e6f5c58621d8373d070d /epan/dissectors/packet-lsd.c | |
parent | 53c20dd179ca60a9cf7bdfffe0af8c1a9b5c1f8b (diff) |
Add Local Service Discovery (LSD) protocol
Bug: 12985
Change-Id: Iceacd3d122337091380d56bd7fa9875bf7cb4d47
Reviewed-on: https://code.wireshark.org/review/18134
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan/dissectors/packet-lsd.c')
-rw-r--r-- | epan/dissectors/packet-lsd.c | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/epan/dissectors/packet-lsd.c b/epan/dissectors/packet-lsd.c new file mode 100644 index 0000000000..f8a667b2f8 --- /dev/null +++ b/epan/dissectors/packet-lsd.c @@ -0,0 +1,207 @@ +/* packet-lsd.c + * Local Service Discovery packet dissector + * + * From http://bittorrent.org/beps/bep_0014.html + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include <epan/packet.h> +#include <epan/expert.h> +#include <wsutil/strtoi.h> + +void proto_register_lsd(void); +void proto_reg_handoff_lsd(void); + +#define LSD_MULTICAST_ADDRESS 0xEFC0988F /* 239.192.152.143 */ +#define LSD_PORT 6771 + +static int proto_lsd = -1; +static int hf_lsd_header = -1; +static int hf_lsd_host = -1; +static int hf_lsd_port = -1; +static int hf_lsd_infohash = -1; + +static gint ett_lsd = -1; + +static expert_field ei_lsd_field = EI_INIT; + +static gboolean +parse_string_field(proto_tree *tree, int hf, packet_info *pinfo, tvbuff_t *tvb, int offset, int* next_offset, int* linelen) +{ + guint8 *str; + header_field_info* hf_info = proto_registrar_get_nth(hf); + gchar **field_and_value; + proto_item* ti; + gchar *p; + + *linelen = tvb_find_line_end(tvb, offset, -1, next_offset, FALSE); + if (*linelen < 0) + return FALSE; + + str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, *linelen, ENC_ASCII); + if (g_ascii_strncasecmp(str, hf_info->name, strlen(hf_info->name)) == 0) + { + field_and_value = wmem_strsplit(wmem_packet_scope(), str, ":", 1); + p = field_and_value[1]; + while(g_ascii_isspace(*p)) + p++; + proto_tree_add_string(tree, hf, tvb, offset, *linelen, p); + } + else + { + ti = proto_tree_add_string_format(tree, hf, tvb, offset, *linelen, str, "%s", str); + expert_add_info_format(pinfo, ti, &ei_lsd_field, "%s field malformed", hf_info->name); + } + + return TRUE; +} + +static int +dissect_lsd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + proto_item *ti = NULL; + proto_tree *lsd_tree; + int offset = 0, next_offset = 0, linelen; + guint8 *str; + gchar **field_and_value; + guint16 port; + gboolean valid; + + linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); + if (linelen < 0) + return 0; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "LSD"); + col_clear(pinfo->cinfo, COL_INFO); + + /* Create display subtree for the protocol */ + ti = proto_tree_add_item(tree, proto_lsd, tvb, 0, -1, ENC_NA); + lsd_tree = proto_item_add_subtree(ti, ett_lsd); + + proto_tree_add_item(lsd_tree, hf_lsd_header, tvb, offset, linelen, ENC_ASCII|ENC_NA); + + offset = next_offset; + if (!parse_string_field(lsd_tree, hf_lsd_host, pinfo, tvb, offset, &next_offset, &linelen)) + return offset+linelen; + + offset = next_offset; + linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); + if (linelen < 0) + return offset+linelen; + str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, linelen, ENC_ASCII); + if (g_ascii_strncasecmp(str, "Port", strlen("Port")) == 0) + { + field_and_value = wmem_strsplit(wmem_packet_scope(), str, ":", 1); + valid = ws_strtou16(field_and_value[1], NULL, &port); + ti = proto_tree_add_uint(lsd_tree, hf_lsd_port, tvb, offset, linelen, port); + if (!valid) + { + expert_add_info_format(pinfo, ti, &ei_lsd_field, "Port value malformed"); + } + } + else + { + ti = proto_tree_add_uint(lsd_tree, hf_lsd_port, tvb, offset, 0, 0xFFFF); + expert_add_info_format(pinfo, ti, &ei_lsd_field, "Port field malformed"); + } + proto_item_set_len(ti, linelen); + + offset = next_offset; + if (!parse_string_field(lsd_tree, hf_lsd_infohash, pinfo, tvb, offset, &next_offset, &linelen)) + return offset+linelen; + + return tvb_captured_length(tvb); +} + +static gboolean +dissect_lsd_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + if (pinfo->dst.type != AT_IPv4) + return FALSE; + + if (g_ntohl((*((const guint32 *)pinfo->dst.data))) != LSD_MULTICAST_ADDRESS) + return FALSE; + + if (pinfo->destport != LSD_PORT) + return FALSE; + + return (dissect_lsd(tvb, pinfo, tree, data) != 0); +} + +void +proto_register_lsd(void) +{ + static hf_register_info hf[] = { + { &hf_lsd_header, + { "Header", "lsd.header", + FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } + }, + { &hf_lsd_host, + { "Host", "lsd.host", + FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } + }, + { &hf_lsd_port, + { "Port", "lsd.port", + FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } + }, + { &hf_lsd_infohash, + { "Infohash", "lsd.infohash", + FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } + }, + }; + + static gint *ett[] = { + &ett_lsd, + }; + + static ei_register_info ei[] = { + { &ei_lsd_field, { "lsd.malformed_field", PI_MALFORMED, PI_ERROR, "Malformed LDS field", EXPFILL }}, + }; + + expert_module_t* expert_lsd; + + proto_lsd = proto_register_protocol("Local Service Discovery", "LSD", "lsd"); + + proto_register_field_array(proto_lsd, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_lsd = expert_register_protocol(proto_lsd); + expert_register_field_array(expert_lsd, ei, array_length(ei)); +} + +void +proto_reg_handoff_lsd(void) +{ + heur_dissector_add( "udp", dissect_lsd_heur, "LSD over UDP", "lsd_udp", proto_lsd, HEURISTIC_ENABLE); +} + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local Variables: + * c-basic-offset: 2 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=2 tabstop=8 expandtab: + * :indentSize=2:tabSize=8:noTabs=true: + */ |