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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 * - split services into a subtree
36 * - split platform into a subtree
46 #include <epan/packet.h>
47 #include <epan/ipproto.h>
49 /* Forward declaration we need below */
50 void proto_reg_handoff_tivoconnect(void);
52 /* Initialize the protocol and registered fields */
53 static int proto_tivoconnect
= -1;
54 static int hf_tivoconnect_flavor
= -1;
55 static int hf_tivoconnect_method
= -1;
56 static int hf_tivoconnect_platform
= -1;
57 static int hf_tivoconnect_machine
= -1;
58 static int hf_tivoconnect_identity
= -1;
59 static int hf_tivoconnect_services
= -1;
60 static int hf_tivoconnect_version
= -1;
62 /* Initialize the subtree pointers */
63 static gint ett_tivoconnect
= -1;
65 /* Code to actually dissect the packets */
67 dissect_tivoconnect(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
69 /* parsing variables */
70 gchar
* string
= NULL
;
73 const gchar
* proto_name
= NULL
;
74 gchar
* packet_identity
= NULL
;
75 gchar
* packet_machine
= NULL
;
77 /* validate that we have a tivoconnect packet */
78 if ( tvb_strncaseeql(tvb
, 0, "tivoconnect", 11) != 0) {
82 length
= tvb_length(tvb
);
83 string
= (gchar
*)tvb_get_string(wmem_packet_scope(), tvb
, 0, length
);
85 /* Make entries in Protocol column and Info column on summary display */
86 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "TiVoConnect");
88 /* make a distinction between UDP and TCP packets */
89 proto_name
= pinfo
->ipproto
== IP_PROTO_TCP
?
90 "Discovery Connection" :
93 col_set_str(pinfo
->cinfo
, COL_INFO
, proto_name
);
96 /* Set up structures needed to add the protocol subtree and manage it */
97 proto_item
*ti
= NULL
;
98 proto_tree
*tivoconnect_tree
= NULL
;
100 /* parsing variables */
102 gchar
* field
= NULL
;
104 /* create display subtree for the protocol */
105 ti
= proto_tree_add_item(tree
, proto_tivoconnect
, tvb
, 0, -1, ENC_NA
);
107 tivoconnect_tree
= proto_item_add_subtree(ti
, ett_tivoconnect
);
109 /* process the packet */
110 for ( field
= strtok(string
,"\n");
112 offset
+=length
, field
= strtok(NULL
,"\n") ) {
113 gchar
* value
= NULL
;
116 length
= (int)strlen(field
) + 1;
118 if ( !(value
=strchr(field
, '=')) ) {
119 /* bad packet: missing the field separator */
123 fieldlen
=(int)strlen(field
)+1;
125 if ( g_ascii_strcasecmp(field
,"tivoconnect") == 0 ) {
126 proto_tree_add_item(tivoconnect_tree
,
127 hf_tivoconnect_flavor
, tvb
, offset
+fieldlen
,
128 length
-fieldlen
-1, ENC_ASCII
|ENC_NA
);
130 else if ( g_ascii_strcasecmp(field
,"method") == 0 ) {
131 proto_tree_add_item(tivoconnect_tree
,
132 hf_tivoconnect_method
, tvb
, offset
+fieldlen
,
133 length
-fieldlen
-1, ENC_ASCII
|ENC_NA
);
135 else if ( g_ascii_strcasecmp(field
,"platform") == 0 ) {
136 proto_tree_add_item(tivoconnect_tree
,
137 hf_tivoconnect_platform
, tvb
, offset
+fieldlen
,
138 length
-fieldlen
-1, ENC_ASCII
|ENC_NA
);
140 else if ( g_ascii_strcasecmp(field
,"machine") == 0 ) {
141 proto_tree_add_item(tivoconnect_tree
,
142 hf_tivoconnect_machine
, tvb
, offset
+fieldlen
,
143 length
-fieldlen
-1, ENC_ASCII
|ENC_NA
);
144 packet_machine
= value
;
146 else if ( g_ascii_strcasecmp(field
,"identity") == 0 ) {
147 proto_tree_add_item(tivoconnect_tree
,
148 hf_tivoconnect_identity
, tvb
, offset
+fieldlen
,
149 length
-fieldlen
-1, ENC_ASCII
|ENC_NA
);
150 packet_identity
= value
;
152 else if ( g_ascii_strcasecmp(field
,"services") == 0 ) {
153 proto_tree_add_item(tivoconnect_tree
,
154 hf_tivoconnect_services
, tvb
, offset
+fieldlen
,
155 length
-fieldlen
-1, ENC_ASCII
|ENC_NA
);
157 else if ( g_ascii_strcasecmp(field
,"swversion") == 0 ) {
158 proto_tree_add_item(tivoconnect_tree
,
159 hf_tivoconnect_version
, tvb
, offset
+fieldlen
,
160 length
-fieldlen
-1, ENC_ASCII
|ENC_NA
);
167 /* Adjust "Info" column and top of tree into more useful info */
168 if (packet_machine
) {
169 proto_item_append_text(ti
, ", %s", packet_machine
);
170 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s %s",
171 proto_name
, packet_machine
);
173 if (packet_identity
) {
174 proto_item_append_text(ti
,
175 packet_machine
? " (%s)" : ", ID:%s",
177 if (packet_machine
) {
178 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s %s (%s)",
179 proto_name
, packet_machine
, packet_identity
);
182 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s ID:%s",
183 proto_name
, packet_identity
);
189 /* If this protocol has a sub-dissector call it here, see section 1.8 */
191 return tvb_length(tvb
);
195 /* Register the protocol with Wireshark */
197 /* this format is require because a script is used to build the C function
198 that calls all the protocol registration.
202 proto_register_tivoconnect(void)
204 /* Setup list of header fields See Section 1.6.1 for details*/
205 static hf_register_info hf
[] = {
206 { &hf_tivoconnect_flavor
,
207 { "Flavor", "tivoconnect.flavor",
208 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
209 "Protocol Flavor supported by the originator", HFILL
}},
210 { &hf_tivoconnect_method
,
211 { "Method", "tivoconnect.method",
212 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
213 "Packet was delivered via UDP(broadcast) or TCP(connected)", HFILL
}},
214 { &hf_tivoconnect_platform
,
215 { "Platform", "tivoconnect.platform",
216 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
217 "System platform, either tcd(TiVo) or pc(Computer)", HFILL
}},
218 { &hf_tivoconnect_machine
,
219 { "Machine", "tivoconnect.machine",
220 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
221 "Human-readable system name", HFILL
}},
222 { &hf_tivoconnect_identity
,
223 { "Identity", "tivoconnect.identity",
224 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
225 "Unique serial number for the system", HFILL
}},
226 { &hf_tivoconnect_services
,
227 { "Services", "tivoconnect.services",
228 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
229 "List of available services on the system", HFILL
}},
230 { &hf_tivoconnect_version
,
231 { "Version", "tivoconnect.version",
232 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
233 "System software version", HFILL
}},
236 /* Setup protocol subtree array */
237 static gint
*ett
[] = {
241 /* Register the protocol name and description */
242 proto_tivoconnect
= proto_register_protocol("TiVoConnect Discovery Protocol",
243 "TiVoConnect", "tivoconnect");
245 /* Required function calls to register the header fields and subtrees used */
246 proto_register_field_array(proto_tivoconnect
, hf
, array_length(hf
));
247 proto_register_subtree_array(ett
, array_length(ett
));
252 proto_reg_handoff_tivoconnect(void)
254 dissector_handle_t tivoconnect_handle
;
256 tivoconnect_handle
= new_create_dissector_handle(dissect_tivoconnect
, proto_tivoconnect
);
257 dissector_add_uint("udp.port", 2190, tivoconnect_handle
);
258 dissector_add_uint("tcp.port", 2190, tivoconnect_handle
);