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".
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * Copied from README.developer
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 * - split services into a subtree
36 * - split platform into a subtree
50 #include <epan/packet.h>
51 #include <epan/ipproto.h>
53 /* Forward declaration we need below */
54 void proto_reg_handoff_tivoconnect(void);
56 /* Initialize the protocol and registered fields */
57 static int proto_tivoconnect = -1;
58 static int hf_tivoconnect_flavor = -1;
59 static int hf_tivoconnect_method = -1;
60 static int hf_tivoconnect_platform = -1;
61 static int hf_tivoconnect_machine = -1;
62 static int hf_tivoconnect_identity = -1;
63 static int hf_tivoconnect_services = -1;
64 static int hf_tivoconnect_version = -1;
66 /* Initialize the subtree pointers */
67 static gint ett_tivoconnect = -1;
69 /* Code to actually dissect the packets */
71 dissect_tivoconnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
73 /* parsing variables */
74 gchar * string = NULL;
77 gchar * proto_name = NULL;
78 gchar * packet_identity = NULL;
79 gchar * packet_machine = NULL;
81 /* validate that we have a tivoconnect packet */
82 if ( tvb_strncaseeql(tvb, 0, "tivoconnect", 11) != 0) {
86 length = tvb_length(tvb);
87 string = (gchar*)tvb_get_ephemeral_string(tvb, 0, length);
89 /* Make entries in Protocol column and Info column on summary display */
90 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TiVoConnect");
92 /* make a distinction between UDP and TCP packets */
93 proto_name = pinfo->ipproto == IP_PROTO_TCP ?
94 "Discovery Connection" :
97 col_set_str(pinfo->cinfo, COL_INFO, proto_name);
100 /* Set up structures needed to add the protocol subtree and manage it */
101 proto_item *ti = NULL;
102 proto_tree *tivoconnect_tree = NULL;
104 /* parsing variables */
106 gchar * field = NULL;
108 /* create display subtree for the protocol */
109 ti = proto_tree_add_item(tree, proto_tivoconnect, tvb, 0, -1, FALSE);
111 tivoconnect_tree = proto_item_add_subtree(ti, ett_tivoconnect);
113 /* process the packet */
114 for ( field = strtok(string,"\n");
116 offset+=length, field = strtok(NULL,"\n") ) {
117 gchar * value = NULL;
120 length = (int)strlen(field) + 1;
122 if ( !(value=strchr(field, '=')) ) {
123 /* bad packet: missing the field separator */
127 fieldlen=(int)strlen(field)+1;
129 if ( g_ascii_strcasecmp(field,"tivoconnect") == 0 ) {
130 proto_tree_add_item(tivoconnect_tree,
131 hf_tivoconnect_flavor, tvb, offset+fieldlen,
132 length-fieldlen-1, FALSE);
134 else if ( g_ascii_strcasecmp(field,"method") == 0 ) {
135 proto_tree_add_item(tivoconnect_tree,
136 hf_tivoconnect_method, tvb, offset+fieldlen,
137 length-fieldlen-1, FALSE);
139 else if ( g_ascii_strcasecmp(field,"platform") == 0 ) {
140 proto_tree_add_item(tivoconnect_tree,
141 hf_tivoconnect_platform, tvb, offset+fieldlen,
142 length-fieldlen-1, FALSE);
144 else if ( g_ascii_strcasecmp(field,"machine") == 0 ) {
145 proto_tree_add_item(tivoconnect_tree,
146 hf_tivoconnect_machine, tvb, offset+fieldlen,
147 length-fieldlen-1, FALSE);
148 packet_machine = value;
150 else if ( g_ascii_strcasecmp(field,"identity") == 0 ) {
151 proto_tree_add_item(tivoconnect_tree,
152 hf_tivoconnect_identity, tvb, offset+fieldlen,
153 length-fieldlen-1, FALSE);
154 packet_identity = value;
156 else if ( g_ascii_strcasecmp(field,"services") == 0 ) {
157 proto_tree_add_item(tivoconnect_tree,
158 hf_tivoconnect_services, tvb, offset+fieldlen,
159 length-fieldlen-1, FALSE);
161 else if ( g_ascii_strcasecmp(field,"swversion") == 0 ) {
162 proto_tree_add_item(tivoconnect_tree,
163 hf_tivoconnect_version, tvb, offset+fieldlen,
164 length-fieldlen-1, FALSE);
171 /* Adjust "Info" column and top of tree into more useful info */
172 if (packet_machine) {
173 proto_item_append_text(ti, ", %s", packet_machine);
174 if (check_col(pinfo->cinfo, COL_INFO))
175 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
176 proto_name, packet_machine);
178 if (packet_identity) {
179 proto_item_append_text(ti,
180 packet_machine ? " (%s)" : ", ID:%s",
182 if (packet_machine) {
183 if (check_col(pinfo->cinfo, COL_INFO))
184 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s (%s)",
185 proto_name, packet_machine, packet_identity);
188 if (check_col(pinfo->cinfo, COL_INFO))
189 col_add_fstr(pinfo->cinfo, COL_INFO, "%s ID:%s",
190 proto_name, packet_identity);
196 /* If this protocol has a sub-dissector call it here, see section 1.8 */
198 return tvb_length(tvb);
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_handle;
263 tivoconnect_handle = new_create_dissector_handle(dissect_tivoconnect, proto_tivoconnect);
264 dissector_add("udp.port", 2190, tivoconnect_handle);
265 dissector_add("tcp.port", 2190, tivoconnect_handle);