bugfix of crash_00001_20050124142515.cap: dissector packet-daap.c displayed [Dissecto...
[obnox/wireshark/wip.git] / epan / dissectors / packet-daap.c
1 /* packet-daap.c
2  * Routines for Digital Audio Access Protocol dissection
3  * Copyright 2004, Kelly Byrd <kbyrd@memcpy.com>
4  *
5  * $Id$
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <glib.h>
31
32 #include <epan/packet.h>
33 #include <epan/dissectors/packet-http.h>
34
35 #define TCP_PORT_DAAP 3689
36
37 /* DAAP tags */
38 /* Container tags */
39 #define daap_mcon       0x6d636f6e
40 #define daap_msrv       0x6d737276
41 #define daap_mccr       0x6d636372
42 #define daap_mdcl       0x6d64636c
43 #define daap_mlog       0x6d6c6f67
44 #define daap_mupd       0x6d757064
45 #define daap_avdb       0x61766462
46 #define daap_mlcl       0x6d6c636c
47 #define daap_mlit       0x6d6c6974
48 #define daap_mbcl       0x6d62636c
49 #define daap_adbs       0x61646273
50 #define daap_aply       0x61706c79
51 #define daap_apso       0x6170736f
52 #define daap_mudl       0x6d75646c
53 #define daap_abro       0x6162726f
54 #define daap_abal       0x6162616c
55 #define daap_abcp       0x61626370
56 #define daap_abgn       0x6162676e
57 #define daap_prsv       0x70727376
58 #define daap_arif       0x61726966
59 /* String tags */
60 #define daap_minm       0x6d696e6d
61 #define daap_msts       0x6d737473
62 #define daap_mcnm       0x6d636e6d
63 #define daap_mcna       0x6d636e61
64 #define daap_asal       0x6173616c
65 #define daap_asar       0x61736172
66 #define daap_ascm       0x6173636d
67 #define daap_asfm       0x6173666d
68 #define daap_aseq       0x61736571
69 #define daap_asgn       0x6173676e
70 #define daap_asdt       0x61736474
71 #define daap_asul       0x6173756c
72 /* uint64 tags */
73 #define daap_mper       0x6d706572
74 /* uint32 tags */
75 #define daap_mstt       0x6d737474
76 #define daap_musr       0x6d757372
77 #define daap_miid       0x6d696964
78 #define daap_mcti       0x6d637469
79 #define daap_mpco       0x6d70636f
80 #define daap_mimc       0x6d696d63
81 #define daap_mrco       0x6d72636f
82 #define daap_mtco       0x6d74636f
83 #define daap_mstm       0x6d73746d
84 #define daap_msdc       0x6d736463
85 #define daap_mlid       0x6d6c6964
86 #define daap_msur       0x6d737572
87 #define daap_asda       0x61736461
88 #define daap_asdm       0x6173646d
89 #define daap_assr       0x61737372
90 #define daap_assz       0x6173737a
91 #define daap_asst       0x61737374
92 #define daap_assp       0x61737370
93 #define daap_astm       0x6173746d
94 #define daap_aeNV       0x61654e56
95 /* uint16 tags */
96 #define daap_mcty       0x6d637479
97 #define daap_asbt       0x61736274
98 #define daap_asbr       0x61736272
99 #define daap_asdc       0x61736463
100 #define daap_asdn       0x6173646e
101 #define daap_astc       0x61737463
102 #define daap_astn       0x6173746e
103 #define daap_asyr       0x61737972
104 /* byte  tags */
105 #define daap_mikd       0x6d696b64
106 #define daap_msau       0x6d736175
107 #define daap_msty       0x6d737479
108 #define daap_asrv       0x61737276
109 #define daap_asur       0x61737572
110 #define daap_asdk       0x6173646b
111 /* boolean  tags */
112 #define daap_mslr       0x6d736c72
113 #define daap_msal       0x6d73616c
114 #define daap_msup       0x6d737570
115 #define daap_mspi       0x6d737069
116 #define daap_msex       0x6d736578
117 #define daap_msbr       0x6d736272
118 #define daap_msqy       0x6d737179
119 #define daap_msix       0x6d736978
120 #define daap_msrs       0x6d737273
121 #define daap_asco       0x6173636f
122 #define daap_asdb       0x61736462
123 #define daap_abpl       0x6162706c
124 #define daap_aeSP       0x61655350
125 /* version (32-bit)*/
126 #define daap_mpro       0x6d70726f
127 #define daap_apro       0x6170726f
128
129
130 /* Initialize the protocol and registered fields */
131 static int proto_daap = -1;
132 static int hf_daap_name = -1;
133 static int hf_daap_size = -1;
134
135 /* Initialize the subtree pointers */
136 static gint ett_daap = -1;
137 static gint ett_daap_sub = -1;
138
139 /* Forward declarations */
140 static int dissect_daap_one_tag(proto_tree *tree, tvbuff_t *tvb, int offset, int length);
141
142 static void
143 dissect_daap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
144 {
145    proto_item *ti;
146    proto_tree *daap_tree;
147    int offset = 0;
148    gboolean is_request = (pinfo->destport == TCP_PORT_DAAP);
149    
150    
151    if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
152       col_set_str(pinfo->cinfo, COL_PROTOCOL, "DAAP");
153    
154    
155    if (check_col(pinfo->cinfo, COL_INFO)) {
156       if (is_request) {
157          col_add_str(pinfo->cinfo, COL_INFO, "DAAP Request");
158       } else {
159          /* This is done in two functions on purpose. If the tvb_get_xxx()
160           * functions fail, at least something will be in the info column
161           */
162          col_add_str(pinfo->cinfo, COL_INFO, "DAAP Response");
163          col_append_fstr(pinfo->cinfo, COL_INFO, " [tag: %s, size: %d]",
164                  tvb_format_text(tvb, offset, 4), tvb_get_ntohl(tvb, offset+4));
165       }
166    }
167
168    
169    
170    if (tree) {
171       ti = proto_tree_add_item(tree, proto_daap, tvb, 0, -1, FALSE);
172       daap_tree = proto_item_add_subtree(ti, ett_daap);     
173       dissect_daap_one_tag(daap_tree, tvb, offset, 0);
174    }
175 }
176
177 static int
178 dissect_daap_one_tag(proto_tree *tree, tvbuff_t *tvb, int offset, int length)
179 {
180    unsigned int tagname;
181    int tagsize;
182    int new_offset;
183    proto_item *ti = NULL;
184    proto_item *ti2 = NULL;
185    proto_tree *new_tree = NULL;
186
187    do {
188       if (!tvb_offset_exists(tvb, offset)) 
189          break;
190
191       tagname = tvb_get_ntohl(tvb, offset);
192       tagsize = tvb_get_ntohl(tvb, offset+4);
193       tvb_ensure_bytes_exist(tvb, offset, tagsize+8);
194       ti = proto_tree_add_text(tree, tvb, offset, tagsize+8, 
195                                "Tag: %c%c%c%c, Size: %d", 
196                                tvb_get_guint8(tvb, offset),
197                                tvb_get_guint8(tvb, offset+1),
198                                tvb_get_guint8(tvb, offset+2),
199                                tvb_get_guint8(tvb, offset+3),
200                                tagsize);
201
202       ti2 = proto_tree_add_item(tree, hf_daap_name, tvb, offset, 4, FALSE);
203       PROTO_ITEM_SET_HIDDEN(ti2);
204       ti2 = proto_tree_add_item(tree, hf_daap_size, tvb, offset+4, 4, FALSE);
205       PROTO_ITEM_SET_HIDDEN(ti2);
206       offset += 8;
207       length -= 8;
208
209       switch (tagname) {
210       case daap_mcon:
211       case daap_msrv:
212       case daap_mccr:
213       case daap_mdcl:
214       case daap_mlog:
215       case daap_mupd:
216       case daap_avdb:
217       case daap_mlcl:
218       case daap_mlit:
219       case daap_mbcl:
220       case daap_adbs:
221       case daap_aply:
222       case daap_apso:
223       case daap_mudl:
224       case daap_abro:
225       case daap_abal:
226       case daap_abcp:
227       case daap_abgn:
228       case daap_prsv:
229       case daap_arif:
230          /* Container tags */
231          new_tree = proto_item_add_subtree(ti, ett_daap_sub);
232          new_offset = dissect_daap_one_tag(new_tree, tvb, offset, 
233                                            tagsize);
234          break;
235       case daap_minm:
236       case daap_msts:
237       case daap_mcnm:
238       case daap_mcna:
239       case daap_asal:
240       case daap_asar:
241       case daap_ascm:
242       case daap_asfm:
243       case daap_aseq:
244       case daap_asgn:
245       case daap_asdt:
246       case daap_asul:
247          /* Tags contain strings */
248          proto_item_append_text(ti, ", Data: %s",
249                                 tvb_format_text(tvb, offset, tagsize));
250          break;
251       case daap_mper:
252          /* Tags conain uint64 */
253          proto_item_append_text(ti, ", Persistent Id: %" PRIu64, 
254                                 tvb_get_ntoh64(tvb, offset));
255          break;
256       case daap_mstt:
257          proto_item_append_text(ti, ", Status: %d", 
258                                 tvb_get_ntohl(tvb, offset));
259          break;
260       case daap_musr:
261       case daap_msur:
262          proto_item_append_text(ti, ", Revision: %d", 
263                                 tvb_get_ntohl(tvb, offset));
264          break;
265       case daap_miid:
266       case daap_mcti:
267       case daap_mpco:
268       case daap_mlid:
269          proto_item_append_text(ti, ", Id: %d", 
270                                 tvb_get_ntohl(tvb, offset));
271          break;
272       case daap_mrco:
273       case daap_mtco:
274       case daap_mimc:
275       case daap_msdc:
276          proto_item_append_text(ti, ", Count: %d", 
277                                 tvb_get_ntohl(tvb, offset));
278          break;
279       case daap_mstm:
280          proto_item_append_text(ti, ", Timeout: %d seconds", 
281                                 tvb_get_ntohl(tvb, offset));
282          break;
283       case daap_asda:
284       case daap_asdm:
285       case daap_assr:
286       case daap_assz:
287       case daap_asst:
288       case daap_assp:
289       case daap_astm:
290       case daap_aeNV:
291          /* Tags conain uint32 */
292          proto_item_append_text(ti, ", Data: %d", 
293                                 tvb_get_ntohl(tvb, offset));
294          break;
295
296       case daap_mcty:
297       case daap_asbt:
298       case daap_asbr:
299       case daap_asdc:
300       case daap_asdn:
301       case daap_astc:
302       case daap_astn:
303       case daap_asyr:
304          /* Tags conain uint16 */
305          proto_item_append_text(ti, ", Data: %d", 
306                                 tvb_get_ntohs(tvb, offset));
307          break;
308
309       case daap_mikd:
310       case daap_msau:
311       case daap_msty:
312       case daap_asrv:
313       case daap_asur:
314       case daap_asdk:
315          /* Tags conain uint8 */
316          proto_item_append_text(ti, ", Data: %d", 
317                                 tvb_get_guint8(tvb, offset));
318
319          break;
320
321       case daap_mslr:
322       case daap_msal:
323       case daap_msup:
324       case daap_mspi:
325       case daap_msex:
326       case daap_msbr:
327       case daap_msqy:
328       case daap_msix:
329       case daap_msrs:
330       case daap_asco:
331       case daap_asdb:
332       case daap_abpl:
333       case daap_aeSP:
334          /* Tags ARE boolean. Data is (uint8), but it seems
335           * the value is always zero. So, if the tag is present
336           * the "bool" is true. 
337           */
338          proto_item_append_text(ti, ", Data: True");
339          break;
340
341       case daap_mpro:
342       case daap_apro:
343          /* Tags conain version (uint32) */
344          proto_item_append_text(ti, ", Version: %d.%d.%d.%d",
345                                 tvb_get_guint8(tvb, offset),
346                                 tvb_get_guint8(tvb, offset+1),
347                                 tvb_get_guint8(tvb, offset+2),
348                                 tvb_get_guint8(tvb, offset+3));
349          break;
350
351       default: 
352          break;
353       }
354       offset += tagsize;
355       length -= tagsize;
356    } while (length > 0);
357    return offset;
358 }
359
360
361 /* Register the protocol with Ethereal */
362 void
363 proto_register_daap(void)
364 {        
365    
366    static hf_register_info hf[] = {
367       { &hf_daap_name,
368         { "Name", "daap.name", FT_STRING, BASE_NONE, NULL, 0x0, 
369           "Tag Name", HFILL}
370       },
371       { &hf_daap_size,
372         { "Size", "daap.size", FT_UINT32, BASE_DEC, NULL, 0x0, 
373           "Tag Size", HFILL }
374       }
375    };
376
377    static gint *ett[] = {
378       &ett_daap,
379       &ett_daap_sub,
380    };
381
382    proto_daap = proto_register_protocol("Digital Audio Access Protocol",
383                                         "DAAP", "daap");
384
385    proto_register_field_array(proto_daap, hf, array_length(hf));
386    proto_register_subtree_array(ett, array_length(ett));
387 }
388
389
390 /* If this dissector uses sub-dissector registration add a registration routine.
391    This format is required because a script is used to find these routines and
392    create the code that calls these routines.
393 */
394 void
395 proto_reg_handoff_daap(void)
396 {
397     dissector_handle_t daap_handle;
398
399     daap_handle = create_dissector_handle(dissect_daap, proto_daap);
400     http_dissector_add(TCP_PORT_DAAP, daap_handle);
401 }