1 /* packet-tivoconnect.c
2 * Routines for TiVoConnect Discovery Protocol dissection
3 * Copyright 2006, Kees Cook <kees@outflux.net>
4 * IANA UDP/TCP port: 2190 (tivoconnect)
5 * Protocol Spec: http://tivo.com/developer/i/TiVoConnectDiscovery.pdf
7 * IANA's full name is "TiVoConnect Beacon", where as TiVo's own
8 * documentation calls this protocol "TiVoConnect Discovery Protocol".
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * Copied from README.developer
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 * - split services into a subtree
34 * - split platform into a subtree
44 #include <epan/packet.h>
46 /* Forward declaration we need below */
47 void proto_reg_handoff_tivoconnect(void);
48 void proto_register_tivoconnect(void);
50 /* Initialize the protocol and registered fields */
51 static int proto_tivoconnect = -1;
52 static int hf_tivoconnect_flavor = -1;
53 static int hf_tivoconnect_method = -1;
54 static int hf_tivoconnect_platform = -1;
55 static int hf_tivoconnect_machine = -1;
56 static int hf_tivoconnect_identity = -1;
57 static int hf_tivoconnect_services = -1;
58 static int hf_tivoconnect_version = -1;
60 /* Initialize the subtree pointers */
61 static gint ett_tivoconnect = -1;
63 /* Code to actually dissect the packets */
65 dissect_tivoconnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_tcp)
67 /* parsing variables */
68 gchar * string = NULL;
71 const gchar * proto_name = NULL;
72 gchar * packet_identity = NULL;
73 gchar * packet_machine = NULL;
75 /* validate that we have a tivoconnect packet */
76 if ( tvb_strncaseeql(tvb, 0, "tivoconnect", 11) != 0) {
80 length = tvb_length(tvb);
81 string = (gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, 0, length, ENC_ASCII);
83 /* Make entries in Protocol column and Info column on summary display */
84 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TiVoConnect");
86 /* make a distinction between UDP and TCP packets */
87 proto_name = is_tcp ? "Discovery Connection" : "Discovery Beacon";
89 col_set_str(pinfo->cinfo, COL_INFO, proto_name);
92 /* Set up structures needed to add the protocol subtree and manage it */
93 proto_item *ti = NULL;
94 proto_tree *tivoconnect_tree = NULL;
96 /* parsing variables */
100 /* create display subtree for the protocol */
101 ti = proto_tree_add_item(tree, proto_tivoconnect, tvb, 0, -1, ENC_NA);
103 tivoconnect_tree = proto_item_add_subtree(ti, ett_tivoconnect);
105 /* process the packet */
106 for ( field = strtok(string,"\n");
108 offset+=length, field = strtok(NULL,"\n") ) {
109 gchar * value = NULL;
112 length = (int)strlen(field) + 1;
114 if ( !(value=strchr(field, '=')) ) {
115 /* bad packet: missing the field separator */
119 fieldlen=(int)strlen(field)+1;
121 if ( g_ascii_strcasecmp(field,"tivoconnect") == 0 ) {
122 proto_tree_add_item(tivoconnect_tree,
123 hf_tivoconnect_flavor, tvb, offset+fieldlen,
124 length-fieldlen-1, ENC_ASCII|ENC_NA);
126 else if ( g_ascii_strcasecmp(field,"method") == 0 ) {
127 proto_tree_add_item(tivoconnect_tree,
128 hf_tivoconnect_method, tvb, offset+fieldlen,
129 length-fieldlen-1, ENC_ASCII|ENC_NA);
131 else if ( g_ascii_strcasecmp(field,"platform") == 0 ) {
132 proto_tree_add_item(tivoconnect_tree,
133 hf_tivoconnect_platform, tvb, offset+fieldlen,
134 length-fieldlen-1, ENC_ASCII|ENC_NA);
136 else if ( g_ascii_strcasecmp(field,"machine") == 0 ) {
137 proto_tree_add_item(tivoconnect_tree,
138 hf_tivoconnect_machine, tvb, offset+fieldlen,
139 length-fieldlen-1, ENC_ASCII|ENC_NA);
140 packet_machine = value;
142 else if ( g_ascii_strcasecmp(field,"identity") == 0 ) {
143 proto_tree_add_item(tivoconnect_tree,
144 hf_tivoconnect_identity, tvb, offset+fieldlen,
145 length-fieldlen-1, ENC_ASCII|ENC_NA);
146 packet_identity = value;
148 else if ( g_ascii_strcasecmp(field,"services") == 0 ) {
149 proto_tree_add_item(tivoconnect_tree,
150 hf_tivoconnect_services, tvb, offset+fieldlen,
151 length-fieldlen-1, ENC_ASCII|ENC_NA);
153 else if ( g_ascii_strcasecmp(field,"swversion") == 0 ) {
154 proto_tree_add_item(tivoconnect_tree,
155 hf_tivoconnect_version, tvb, offset+fieldlen,
156 length-fieldlen-1, ENC_ASCII|ENC_NA);
163 /* Adjust "Info" column and top of tree into more useful info */
164 if (packet_machine) {
165 proto_item_append_text(ti, ", %s", packet_machine);
166 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
167 proto_name, packet_machine);
169 if (packet_identity) {
170 proto_item_append_text(ti,
171 packet_machine ? " (%s)" : ", ID:%s",
173 if (packet_machine) {
174 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s (%s)",
175 proto_name, packet_machine, packet_identity);
178 col_add_fstr(pinfo->cinfo, COL_INFO, "%s ID:%s",
179 proto_name, packet_identity);
185 /* If this protocol has a sub-dissector call it here, see section 1.8 */
187 return tvb_length(tvb);
191 dissect_tivoconnect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
193 return dissect_tivoconnect(tvb, pinfo, tree, TRUE);
197 dissect_tivoconnect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
199 return dissect_tivoconnect(tvb, pinfo, tree, FALSE);
202 /* Register the protocol with Wireshark */
204 /* this format is require because a script is used to build the C function
205 that calls all the protocol registration.
209 proto_register_tivoconnect(void)
211 /* Setup list of header fields See Section 1.6.1 for details*/
212 static hf_register_info hf[] = {
213 { &hf_tivoconnect_flavor,
214 { "Flavor", "tivoconnect.flavor",
215 FT_STRINGZ, BASE_NONE, NULL, 0,
216 "Protocol Flavor supported by the originator", HFILL }},
217 { &hf_tivoconnect_method,
218 { "Method", "tivoconnect.method",
219 FT_STRINGZ, BASE_NONE, NULL, 0,
220 "Packet was delivered via UDP(broadcast) or TCP(connected)", HFILL }},
221 { &hf_tivoconnect_platform,
222 { "Platform", "tivoconnect.platform",
223 FT_STRINGZ, BASE_NONE, NULL, 0,
224 "System platform, either tcd(TiVo) or pc(Computer)", HFILL }},
225 { &hf_tivoconnect_machine,
226 { "Machine", "tivoconnect.machine",
227 FT_STRINGZ, BASE_NONE, NULL, 0,
228 "Human-readable system name", HFILL }},
229 { &hf_tivoconnect_identity,
230 { "Identity", "tivoconnect.identity",
231 FT_STRINGZ, BASE_NONE, NULL, 0,
232 "Unique serial number for the system", HFILL }},
233 { &hf_tivoconnect_services,
234 { "Services", "tivoconnect.services",
235 FT_STRINGZ, BASE_NONE, NULL, 0,
236 "List of available services on the system", HFILL }},
237 { &hf_tivoconnect_version,
238 { "Version", "tivoconnect.version",
239 FT_STRINGZ, BASE_NONE, NULL, 0,
240 "System software version", HFILL }},
243 /* Setup protocol subtree array */
244 static gint *ett[] = {
248 /* Register the protocol name and description */
249 proto_tivoconnect = proto_register_protocol("TiVoConnect Discovery Protocol",
250 "TiVoConnect", "tivoconnect");
252 /* Required function calls to register the header fields and subtrees used */
253 proto_register_field_array(proto_tivoconnect, hf, array_length(hf));
254 proto_register_subtree_array(ett, array_length(ett));
259 proto_reg_handoff_tivoconnect(void)
261 dissector_handle_t tivoconnect_tcp_handle, tivoconnect_udp_handle;
263 tivoconnect_tcp_handle = new_create_dissector_handle(dissect_tivoconnect_tcp, proto_tivoconnect);
264 tivoconnect_udp_handle = new_create_dissector_handle(dissect_tivoconnect_udp, proto_tivoconnect);
265 dissector_add_uint("udp.port", 2190, tivoconnect_udp_handle);
266 dissector_add_uint("tcp.port", 2190, tivoconnect_tcp_handle);