Revert "Fixup: tvb_* -> tvb_captured"
[metze/wireshark/wip.git] / epan / dissectors / packet-tivoconnect.c
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
6  *
7  * IANA's full name is "TiVoConnect Beacon", where as TiVo's own
8  * documentation calls this protocol "TiVoConnect Discovery Protocol".
9  *
10  * Wireshark - Network traffic analyzer
11  * By Gerald Combs <gerald@wireshark.org>
12  * Copyright 1998 Gerald Combs
13  *
14  * Copied from README.developer
15  *
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.
20  *
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.
25  *
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.
29  */
30
31 /*
32  * TODO
33  * - split services into a subtree
34  * - split platform into a subtree
35  *
36  */
37
38 #include "config.h"
39
40 #include <string.h>
41
42 #include <glib.h>
43
44 #include <epan/packet.h>
45
46 /* Forward declaration we need below */
47 void proto_reg_handoff_tivoconnect(void);
48 void proto_register_tivoconnect(void);
49
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;
59
60 /* Initialize the subtree pointers */
61 static gint ett_tivoconnect = -1;
62
63 /* Code to actually dissect the packets */
64 static int
65 dissect_tivoconnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_tcp)
66 {
67     /* parsing variables */
68     gchar * string = NULL;
69     gint length = -1;
70     /* value strings */
71     const gchar * proto_name = NULL;
72     gchar * packet_identity = NULL;
73     gchar * packet_machine = NULL;
74
75     /* validate that we have a tivoconnect packet */
76     if ( tvb_strncaseeql(tvb, 0, "tivoconnect", 11) != 0) {
77         return 0;
78     }
79
80     length = tvb_length(tvb);
81     string = (gchar*)tvb_get_string_enc(wmem_packet_scope(), tvb, 0, length, ENC_ASCII);
82
83     /* Make entries in Protocol column and Info column on summary display */
84     col_set_str(pinfo->cinfo, COL_PROTOCOL, "TiVoConnect");
85
86     /* make a distinction between UDP and TCP packets */
87     proto_name = is_tcp ? "Discovery Connection" : "Discovery Beacon";
88
89     col_set_str(pinfo->cinfo, COL_INFO, proto_name);
90
91     if (tree) {
92         /* Set up structures needed to add the protocol subtree and manage it */
93         proto_item *ti = NULL;
94         proto_tree *tivoconnect_tree = NULL;
95
96         /* parsing variables */
97         guint offset = 0;
98         gchar * field = NULL;
99
100         /* create display subtree for the protocol */
101         ti = proto_tree_add_item(tree, proto_tivoconnect, tvb, 0, -1, ENC_NA);
102
103         tivoconnect_tree = proto_item_add_subtree(ti, ett_tivoconnect);
104
105         /* process the packet */
106         for ( field = strtok(string,"\n");
107               field;
108               offset+=length, field = strtok(NULL,"\n") ) {
109             gchar * value = NULL;
110             gint fieldlen;
111
112             length = (int)strlen(field) + 1;
113
114             if ( !(value=strchr(field, '=')) ) {
115                 /* bad packet: missing the field separator */
116                 continue;
117             }
118             *value++='\0';
119             fieldlen=(int)strlen(field)+1;
120
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);
125             }
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);
130             }
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);
135             }
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;
141             }
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;
147             }
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);
152             }
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);
157             }
158             else {
159                 /* unknown field! */
160             }
161         }
162
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);
168         }
169         if (packet_identity) {
170             proto_item_append_text(ti,
171                         packet_machine ? " (%s)" : ", ID:%s",
172                         packet_identity);
173             if (packet_machine) {
174                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s (%s)",
175                                  proto_name, packet_machine, packet_identity);
176             }
177             else {
178                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s ID:%s",
179                                  proto_name, packet_identity);
180             }
181         }
182
183     }
184
185     /* If this protocol has a sub-dissector call it here, see section 1.8 */
186
187     return tvb_length(tvb);
188 }
189
190 static int
191 dissect_tivoconnect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
192 {
193     return dissect_tivoconnect(tvb, pinfo, tree, TRUE);
194 }
195
196 static int
197 dissect_tivoconnect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
198 {
199     return dissect_tivoconnect(tvb, pinfo, tree, FALSE);
200 }
201
202 /* Register the protocol with Wireshark */
203
204 /* this format is require because a script is used to build the C function
205    that calls all the protocol registration.
206 */
207
208 void
209 proto_register_tivoconnect(void)
210 {
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 }},
241     };
242
243     /* Setup protocol subtree array */
244     static gint *ett[] = {
245         &ett_tivoconnect,
246     };
247
248     /* Register the protocol name and description */
249     proto_tivoconnect = proto_register_protocol("TiVoConnect Discovery Protocol",
250         "TiVoConnect", "tivoconnect");
251
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));
255 }
256
257
258 void
259 proto_reg_handoff_tivoconnect(void)
260 {
261     dissector_handle_t tivoconnect_tcp_handle, tivoconnect_udp_handle;
262
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);
267 }