Fix various typos and spelling errors.
[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  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
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 #include <epan/packet.h>
32 #include <epan/dissectors/packet-http.h>
33
34 #define TCP_PORT_DAAP 3689
35
36 /* DAAP tags */
37 /* Some information taken from http://tapjam.net/daap/ */
38 /* and http://www.deleet.de/projekte/daap/?ContentCodes */
39 /* Container tags */
40 #define daap_mcon       0x6d636f6e
41 #define daap_msrv       0x6d737276
42 #define daap_mccr       0x6d636372
43 #define daap_mdcl       0x6d64636c
44 #define daap_mlog       0x6d6c6f67
45 #define daap_mupd       0x6d757064
46 #define daap_avdb       0x61766462
47 #define daap_mlcl       0x6d6c636c
48 #define daap_mlit       0x6d6c6974
49 #define daap_mbcl       0x6d62636c
50 #define daap_adbs       0x61646273
51 #define daap_aply       0x61706c79
52 #define daap_apso       0x6170736f
53 #define daap_mudl       0x6d75646c
54 #define daap_abro       0x6162726f
55 #define daap_abar       0x61626172
56 #define daap_arsv       0x61727376
57 #define daap_abal       0x6162616c
58 #define daap_abcp       0x61626370
59 #define daap_abgn       0x6162676e
60 #define daap_prsv       0x70727376
61 #define daap_arif       0x61726966
62 #define daap_mctc       0x6d637463
63 /* String tags */
64 #define daap_minm       0x6d696e6d
65 #define daap_msts       0x6d737473
66 #define daap_mcnm       0x6d636e6d
67 #define daap_mcna       0x6d636e61
68 #define daap_asal       0x6173616c
69 #define daap_asar       0x61736172
70 #define daap_ascm       0x6173636d
71 #define daap_asfm       0x6173666d
72 #define daap_aseq       0x61736571
73 #define daap_asgn       0x6173676e
74 #define daap_asdt       0x61736474
75 #define daap_asul       0x6173756c
76 #define daap_ascp       0x61736370
77 #define daap_asct       0x61736374
78 #define daap_ascn       0x6173636e
79 #define daap_aslc       0x61736c63
80 #define daap_asky       0x61736b79
81 #define daap_aeSN       0x6165534e
82 #define daap_aeNN       0x61654e4e
83 #define daap_aeEN       0x6165454e
84 #define daap_assn       0x6173736e
85 #define daap_assa       0x61737361
86 #define daap_assl       0x6173736c
87 #define daap_assc       0x61737363
88 #define daap_asss       0x61737373
89 #define daap_asaa       0x61736161
90 #define daap_aspu       0x61737075
91 #define daap_aeCR       0x61654352
92 /* uint64 tags */
93 #define daap_mper       0x6d706572
94 #define daap_aeGU       0x61654755
95 #define daap_aeGR       0x61654752
96 #define daap_asai       0x61736169
97 #define daap_asls       0x61736c73
98 /* uint32 tags */
99 #define daap_mstt       0x6d737474
100 #define daap_musr       0x6d757372
101 #define daap_miid       0x6d696964
102 #define daap_mcti       0x6d637469
103 #define daap_mpco       0x6d70636f
104 #define daap_mimc       0x6d696d63
105 #define daap_mrco       0x6d72636f
106 #define daap_mtco       0x6d74636f
107 #define daap_mstm       0x6d73746d
108 #define daap_msdc       0x6d736463
109 #define daap_mlid       0x6d6c6964
110 #define daap_msur       0x6d737572
111 #define daap_asda       0x61736461
112 #define daap_asdm       0x6173646d
113 #define daap_assr       0x61737372
114 #define daap_assz       0x6173737a
115 #define daap_asst       0x61737374
116 #define daap_assp       0x61737370
117 #define daap_astm       0x6173746d
118 #define daap_aeNV       0x61654e56
119 #define daap_ascd       0x61736364
120 #define daap_ascs       0x61736373
121 #define daap_aeSV       0x61655356
122 #define daap_aePI       0x61655049
123 #define daap_aeCI       0x61654349
124 #define daap_aeGI       0x61654749
125 #define daap_aeAI       0x61654149
126 #define daap_aeSI       0x61655349
127 #define daap_aeES       0x61654553
128 #define daap_aeSU       0x61655355
129 #define daap_asbo       0x6173626f
130 #define daap_aeGH       0x61654748
131 #define daap_aeGD       0x61654744
132 #define daap_aeGE       0x61654745
133 #define daap_meds       0x6d656473
134 /*TODO:
135 #define daap_msto               0x6d7374OO utcoffset
136 */
137 /* uint16 tags */
138 #define daap_mcty       0x6d637479
139 #define daap_asbt       0x61736274
140 #define daap_asbr       0x61736272
141 #define daap_asdc       0x61736463
142 #define daap_asdn       0x6173646e
143 #define daap_astc       0x61737463
144 #define daap_astn       0x6173746e
145 #define daap_asyr       0x61737972
146 #define daap_ased       0x61736564
147 /* byte  tags */
148 #define daap_mikd       0x6d696b64
149 #define daap_msau       0x6d736175
150 #define daap_msty       0x6d737479
151 #define daap_asrv       0x61737276 /* XXX: may be uint16 in newer iTunes versions! */
152 #define daap_asur       0x61737572
153 #define daap_asdk       0x6173646b
154 #define daap_muty       0x6d757479
155 #define daap_msas       0x6d736173
156 #define daap_aeHV       0x61654856
157 #define daap_aeHD       0x61654844
158 #define daap_aePC       0x61655043
159 #define daap_aePP       0x61655050
160 #define daap_aeMK       0x61654d4b
161 #define daap_aeSG       0x61655347
162 #define daap_apsm       0x6170736d
163 #define daap_aprm       0x6170726d
164 #define daap_asgp       0x61736770
165 #define daap_aePS       0x61655053
166 #define daap_asbk       0x6173626b
167 /* boolean  tags */
168 #define daap_mslr       0x6d736c72
169 #define daap_msal       0x6d73616c
170 #define daap_msup       0x6d737570
171 #define daap_mspi       0x6d737069
172 #define daap_msex       0x6d736578
173 #define daap_msbr       0x6d736272
174 #define daap_msqy       0x6d737179
175 #define daap_msix       0x6d736978
176 #define daap_msrs       0x6d737273
177 #define daap_asco       0x6173636f
178 #define daap_asdb       0x61736462
179 #define daap_abpl       0x6162706c
180 #define daap_aeSP       0x61655350
181 #define daap_ashp       0x61736870
182 /* version (32-bit)*/
183 #define daap_mpro       0x6d70726f
184 #define daap_apro       0x6170726f
185 /* date/time */
186 /* TODO:
187 #define daap_mstc 0xMMSSTTCC utctime
188 #define daap_asdr ("daap.songdatereleased")
189 #define daap_asdp ("daap.songdatepurchased")
190 */
191
192 /*XXX: Sorted by value definition since it appears that the "value" is just */
193 /*     the ascii representation of the last 4 letters of the definition.    */
194 /*     (Sorted so a binary search can be done when using value_string_ext)  */
195 static const value_string vals_tag_code[] = {
196    { daap_abal, "browse album listing" },
197    { daap_abar, "browse artist listing" },
198    { daap_abcp, "browse composer listing" },
199    { daap_abgn, "browse genre listing" },
200    { daap_abpl, "base playlist" },
201    { daap_abro, "database browse" },
202    { daap_adbs, "database songs" },
203    { daap_aeAI, "com.apple.itunes.itms-artistid" },
204    { daap_aeCI, "com.apple.itunes.itms-composerid" },
205    { daap_aeCR, "com.apple.itunes.content-rating" },
206    { daap_aeEN, "com.apple.itunes.episode-num-str" },
207    { daap_aeES, "com.apple.itunes.episode-sort" },
208    { daap_aeGD, "com.apple.itunes.gapless-enc-dr" },
209    { daap_aeGE, "com.apple.itunes.gapless-enc-del" },
210    { daap_aeGH, "com.apple.itunes.gapless-heur" },
211    { daap_aeGI, "com.apple.itunes.itms-genreid" },
212    { daap_aeGR, "com.apple.itunes.gapless-resy" },
213    { daap_aeGU, "com.apple.itunes.gapless-dur" },
214    { daap_aeHD, "com.apple.itunes.is-hd-video" },
215    { daap_aeHV, "com.apple.itunes.has-video" },
216    { daap_aeMK, "com.apple.itunes.mediakind" },
217    { daap_aeNN, "com.apple.itunes.network-name" },
218    { daap_aeNV, "com.apple.itunes.norm-volume" },
219    { daap_aePC, "com.apple.itunes.is-podcast" },
220    { daap_aePI, "com.apple.itunes.itms-playlistid" },
221    { daap_aePP, "com.apple.itunes.is-podcast-playlist" },
222    { daap_aePS, "com.apple.itunes.special-playlist" },
223    { daap_aeSG, "com.apple.itunes.saved-genius" },
224    { daap_aeSI, "com.apple.itunes.itms-songid" },
225    { daap_aeSN, "com.apple.itunes.series-name" },
226    { daap_aeSP, "com.apple.itunes.smart-playlist" },
227    { daap_aeSU, "com.apple.itunes.season-num" },
228    { daap_aeSV, "com.apple.itunes.music-sharing-version" },
229    { daap_aply, "database playlists" },
230    { daap_aprm, "playlist repeat mode" },
231    { daap_apro, "protocol (application?) version (apro)" },
232    { daap_apsm, "playlist shuffle mode" },
233    { daap_apso, "playlist songs" },
234    { daap_arif, "resolveinfo" },
235    { daap_arsv, "resolve" },
236    { daap_asaa, "song album artist" },
237    { daap_asai, "song album id"},
238    { daap_asal, "song album" },
239    { daap_asar, "song artist" },
240    { daap_asbk, "song bookmarkable" },
241    { daap_asbo, "song bookmark" },
242    { daap_asbr, "song bitrate" },
243    { daap_asbt, "song beats-per-minute" },
244    { daap_ascd, "song codec type" },
245    { daap_ascm, "song comment" },
246    { daap_ascn, "song content description" },
247    { daap_asco, "song compilation" },
248    { daap_ascp, "song composer" },
249    { daap_ascs, "song codec subtype" },
250    { daap_asct, "song category" },
251    { daap_asda, "song date added" },
252    { daap_asdb, "song disabled" },
253    { daap_asdc, "song disccount" },
254    { daap_asdk, "song data kind" },
255    { daap_asdm, "song date modified" },
256    { daap_asdn, "song discnumber" },
257    { daap_asdt, "song description" },
258    { daap_ased, "song extra data" },
259    { daap_aseq, "song eq preset" },
260    { daap_asfm, "song format" },
261    { daap_asgn, "song genre" },
262    { daap_asgp, "song gapless" },
263    { daap_ashp, "song has been played" },
264    { daap_asky, "song keywords" },
265    { daap_aslc, "song long content description" },
266    { daap_asls, "song long size"},
267    { daap_aspu, "song podcast url" },
268    { daap_asrv, "song relative volume" },
269    { daap_assa, "sort artist" },
270    { daap_assc, "sort composer" },
271    { daap_assn, "sort name" },
272    { daap_assp, "song stop time (milliseconds)" },
273    { daap_assr, "song sample rate" },
274    { daap_asss, "sort seriesname" },
275    { daap_asst, "song start time (milliseconds)" },
276    { daap_assz, "song size" },
277    { daap_astc, "song track count" },
278    { daap_astm, "song time (milliseconds)" },
279    { daap_astn, "song track number" },
280    { daap_asul, "song data url" },
281    { daap_asur, "song user rating" },
282    { daap_asyr, "song year" },
283    { daap_avdb, "server databases" },
284    { daap_mbcl, "bag (mbcl)" },
285    { daap_mccr, "content codes response" },
286    { daap_mcna, "content codes name" },
287    { daap_mcnm, "content codes number" },
288    { daap_mcon, "container (mcon)" },
289    { daap_mctc, "container count" },
290    { daap_mcti, "container item id (mcti)" },
291    { daap_mcty, "content codes type" },
292    { daap_mdcl, "dictionary (mdcl)" },
293    { daap_meds, "edit commands supported" },
294    { daap_miid, "item id (miid)" },
295    { daap_mikd, "item kind (mikd)" },
296    { daap_mimc, "item count (mimc)" },
297    { daap_minm, "item name (minm)" },
298    { daap_mlcl, "listing (mlcl)" },
299    { daap_mlid, "session id" },
300    { daap_mlit, "listing item (mlit)" },
301    { daap_mlog, "login response" },
302    { daap_mpco, "parent container id (mpco)" },
303    { daap_mper, "persistent id (mper)" },
304    { daap_mpro, "protocol version (mpro)" },
305    { daap_mrco, "returned count (mrco)" },
306    { daap_msal, "supports auto-logout (msal)" },
307    { daap_msas, "authentication schemes" },
308    { daap_msau, "authentication method (msau)" },
309    { daap_msbr, "supports browse" },
310    { daap_msdc, "databases count" },
311    { daap_msex, "supports extensions (msex)" },
312    { daap_msix, "supports index" },
313    { daap_mslr, "login required (mslr)" },
314    { daap_mspi, "supports persistent ids (mspi)" },
315    { daap_msqy, "supports query" },
316    { daap_msrs, "supports resolve" },
317    { daap_msrv, "server info response (msrv)" },
318    { daap_mstm, "timeout interval" },
319    { daap_msts, "status string (msts)" },
320    { daap_mstt, "status (mstt)" },
321    { daap_msup, "supports update (msup)" },
322    { daap_msur, "server revision" },
323    { daap_mtco, "specified total count (mtco)" },
324    { daap_mudl, "deleted id listing" },
325    { daap_mupd, "update response" },
326    { daap_musr, "server revision" },
327    { daap_muty, "update type" },
328    { daap_prsv, "resolve" },
329    { 0,         NULL}
330 };
331 static value_string_ext vals_tag_code_ext = VALUE_STRING_EXT_INIT(vals_tag_code);
332
333 /* Initialize the protocol and registered fields */
334 static int proto_daap = -1;
335 static int hf_daap_name = -1;
336 static int hf_daap_size = -1;
337
338 /* Initialize the subtree pointers */
339 static gint ett_daap = -1;
340 static gint ett_daap_sub = -1;
341
342 /* Forward declarations */
343 static void dissect_daap_one_tag(proto_tree *tree, tvbuff_t *tvb);
344
345 static void
346 dissect_daap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
347 {
348    proto_item *ti;
349    proto_tree *daap_tree;
350    gboolean is_request = (pinfo->destport == TCP_PORT_DAAP);
351
352    col_set_str(pinfo->cinfo, COL_PROTOCOL, "DAAP");
353
354    /*
355     * XXX - what if the body is gzipped?  This isn't the only protocol
356     * running atop HTTP that might have a problem with that....
357     */
358    if (check_col(pinfo->cinfo, COL_INFO)) {
359       if (is_request) {
360          col_set_str(pinfo->cinfo, COL_INFO, "DAAP Request");
361       } else {
362          /* This is done in two functions on purpose. If the tvb_get_xxx()
363           * functions fail, at least something will be in the info column
364           */
365          col_set_str(pinfo->cinfo, COL_INFO, "DAAP Response");
366          col_append_fstr(pinfo->cinfo, COL_INFO, " [first tag: %s, size: %d]",
367                          tvb_format_text(tvb, 0, 4),
368                          tvb_get_ntohl(tvb, 4));
369       }
370    }
371
372    if (tree) {
373       ti = proto_tree_add_item(tree, proto_daap, tvb, 0, -1, FALSE);
374       daap_tree = proto_item_add_subtree(ti, ett_daap);
375       dissect_daap_one_tag(daap_tree, tvb);
376    }
377 }
378
379 static void
380 dissect_daap_one_tag(proto_tree *tree, tvbuff_t *tvb)
381 {
382    gint        offset = 0;
383    gint        reported_length;
384    guint32     tagname;
385    guint32     tagsize;
386    gint        len;
387    proto_item *ti;
388    proto_item *ti2;
389    proto_tree *new_tree;
390    tvbuff_t   *new_tvb;
391
392    reported_length = tvb_reported_length(tvb);
393
394    while ((offset >= 0) &&  (offset < reported_length)) {
395       tagname = tvb_get_ntohl(tvb, offset);
396       tagsize = tvb_get_ntohl(tvb, offset+4);
397       ti = proto_tree_add_text(tree, tvb, offset, 8,
398                                "Tag: %-40s %3u byte%c",
399                                val_to_str_ext(tagname, &vals_tag_code_ext, "Unknown tag (0x%0x)"),
400                                tagsize,
401                                plurality(tagsize, ' ', 's'));
402
403       ti2 = proto_tree_add_item(tree, hf_daap_name, tvb, offset, 4, FALSE);
404       PROTO_ITEM_SET_HIDDEN(ti2);
405       ti2 = proto_tree_add_item(tree, hf_daap_size, tvb, offset+4, 4, FALSE);
406       PROTO_ITEM_SET_HIDDEN(ti2);
407
408       offset += 8;
409
410       len = reported_length - offset; /* should be >= 0 since no exception above */ 
411       DISSECTOR_ASSERT(len >= 0);
412       if (tagsize <= (unsigned)len) {
413          len = tagsize;
414       }
415       proto_item_set_len(ti, 8+len);              /* *Now* it's Ok to set the length.              */
416                                                   /*  (Done here so that the proto_tree_add_text   */
417                                                   /*   above will show tag and tagsize even if     */
418                                                   /*   tagsize is very large).                     */
419       switch (tagname) {
420       case daap_mcon:
421       case daap_msrv:
422       case daap_mccr:
423       case daap_mdcl:
424       case daap_mlog:
425       case daap_mupd:
426       case daap_avdb:
427       case daap_mlcl:
428       case daap_mlit:
429       case daap_mbcl:
430       case daap_adbs:
431       case daap_aply:
432       case daap_apso:
433       case daap_mudl:
434       case daap_abro:
435       case daap_abar:
436       case daap_arsv:
437       case daap_abal:
438       case daap_abcp:
439       case daap_abgn:
440       case daap_prsv:
441       case daap_arif:
442          /* Container tags */
443          new_tree = proto_item_add_subtree(ti, ett_daap_sub);
444          new_tvb  = tvb_new_subset(tvb, offset, len, len);    /* Use a new tvb so bounds checking        */
445                                                               /*  works Ok when dissecting container.    */
446                                                               /* Note: len is within tvb; checked above. */
447                                                               /* len (see above) is used so that we'll   */
448                                                               /* at least try to dissect what we have    */
449                                                               /* before throwing an exception.           */
450          dissect_daap_one_tag(new_tree, new_tvb);
451          break;
452       case daap_minm:
453       case daap_msts:
454       case daap_mcnm:
455       case daap_mcna:
456       case daap_asal:
457       case daap_asar:
458       case daap_ascm:
459       case daap_asfm:
460       case daap_aseq:
461       case daap_asgn:
462       case daap_asdt:
463       case daap_asul:
464       case daap_ascp:
465       case daap_asct:
466       case daap_ascn:
467       case daap_aslc:
468       case daap_asky:
469       case daap_aeSN:
470       case daap_aeNN:
471       case daap_aeEN:
472       case daap_assn:
473       case daap_assa:
474       case daap_assl:
475       case daap_assc:
476       case daap_asss:
477       case daap_asaa:
478       case daap_aspu:
479       case daap_aeCR:
480          /* Tags contain strings */
481          proto_item_append_text(ti, "; Data: %s",
482                                 tvb_format_text(tvb, offset, tagsize));
483          break;
484       case daap_mper:
485       case daap_aeGR:
486       case daap_aeGU:
487       case daap_asai:
488       case daap_asls:
489          /* Tags conain uint64 */
490          proto_item_append_text(ti, "; Persistent Id: %" G_GINT64_MODIFIER "u",
491                                 tvb_get_ntoh64(tvb, offset));
492          break;
493       case daap_mstt:
494          proto_item_append_text(ti, "; Status: %d",
495                                 tvb_get_ntohl(tvb, offset));
496          break;
497       case daap_musr:
498       case daap_msur:
499          proto_item_append_text(ti, "; Revision: %d",
500                                 tvb_get_ntohl(tvb, offset));
501          break;
502       case daap_miid:
503       case daap_mcti:
504       case daap_mpco:
505       case daap_mlid:
506          proto_item_append_text(ti, "; Id: %d",
507                                 tvb_get_ntohl(tvb, offset));
508          break;
509       case daap_mrco:
510       case daap_mtco:
511       case daap_mimc:
512       case daap_msdc:
513       case daap_mctc:
514          proto_item_append_text(ti, "; Count: %d",
515                                 tvb_get_ntohl(tvb, offset));
516          break;
517       case daap_mstm:
518          proto_item_append_text(ti, "; Timeout: %d seconds",
519                                 tvb_get_ntohl(tvb, offset));
520          break;
521       case daap_asda:
522       case daap_asdm:
523       case daap_assr:
524       case daap_assz:
525       case daap_asst:
526       case daap_assp:
527       case daap_astm:
528       case daap_aeNV:
529       case daap_ascd:
530       case daap_ascs:
531       case daap_aeSV:
532       case daap_aePI:
533       case daap_aeCI:
534       case daap_aeGI:
535       case daap_aeAI:
536       case daap_aeSI:
537       case daap_aeES:
538       case daap_asbo:
539       case daap_aeGH:
540       case daap_aeGD:
541       case daap_aeGE:
542       case daap_meds:
543          /* Tags conain uint32 */
544          proto_item_append_text(ti, "; Data: %d",
545                                 tvb_get_ntohl(tvb, offset));
546          break;
547
548       case daap_mcty:
549       case daap_asbt:
550       case daap_asbr:
551       case daap_asdc:
552       case daap_asdn:
553       case daap_astc:
554       case daap_astn:
555       case daap_asyr:
556       case daap_ased:
557          /* Tags conain uint16 */
558          proto_item_append_text(ti, "; Data: %d",
559                                 tvb_get_ntohs(tvb, offset));
560          break;
561
562       case daap_mikd:
563       case daap_msau:
564       case daap_msty:
565       case daap_asrv:
566       case daap_asur:
567       case daap_asdk:
568       case daap_muty:
569       case daap_msas:
570       case daap_aeHV:
571       case daap_aeHD:
572       case daap_aePC:
573       case daap_aePP:
574       case daap_aeMK:
575       case daap_aeSG:
576       case daap_apsm:
577       case daap_aprm:
578       case daap_asgp:
579       case daap_aePS:
580          /* Tags conain uint8 */
581          proto_item_append_text(ti, "; Data: %d",
582                                 tvb_get_guint8(tvb, offset));
583
584          break;
585
586       case daap_mslr:
587       case daap_msal:
588       case daap_msup:
589       case daap_mspi:
590       case daap_msex:
591       case daap_msbr:
592       case daap_msqy:
593       case daap_msix:
594       case daap_msrs:
595       case daap_asco:
596       case daap_asdb:
597       case daap_abpl:
598       case daap_aeSP:
599       case daap_asbk:
600          /* Tags ARE boolean. Data is (uint8), but it seems
601           * the value is always zero. So, if the tag is present
602           * the "bool" is true.
603           */
604          proto_item_append_text(ti, "; Data: True");
605          break;
606
607       case daap_mpro:
608       case daap_apro:
609          /* Tags conain version (uint32) */
610          proto_item_append_text(ti, "; Version: %d.%d.%d.%d",
611                                 tvb_get_guint8(tvb, offset),
612                                 tvb_get_guint8(tvb, offset+1),
613                                 tvb_get_guint8(tvb, offset+2),
614                                 tvb_get_guint8(tvb, offset+3));
615          break;
616
617       default:
618          break;
619       }
620       if ((signed)tagsize < 0)   /* we'll consider a tagsize >= 0x80000000 invalid */
621           break;
622       offset += tagsize;
623    }
624    if ((offset < 0) || ((reported_length - offset) != 0)) {
625        THROW(ReportedBoundsError);
626    }
627    return;
628 }
629
630
631 /* Register the protocol with Wireshark */
632 void
633 proto_register_daap(void)
634 {
635
636    static hf_register_info hf[] = {
637       { &hf_daap_name,
638         { "Name", "daap.name", FT_STRING, BASE_NONE, NULL, 0x0,
639           "Tag Name", HFILL}
640       },
641       { &hf_daap_size,
642         { "Size", "daap.size", FT_UINT32, BASE_DEC, NULL, 0x0,
643           "Tag Size", HFILL }
644       }
645    };
646
647    static gint *ett[] = {
648       &ett_daap,
649       &ett_daap_sub,
650    };
651
652    proto_daap = proto_register_protocol("Digital Audio Access Protocol",
653                                         "DAAP", "daap");
654
655    proto_register_field_array(proto_daap, hf, array_length(hf));
656    proto_register_subtree_array(ett, array_length(ett));
657 }
658
659 void
660 proto_reg_handoff_daap(void)
661 {
662    dissector_handle_t daap_handle;
663
664    daap_handle = create_dissector_handle(dissect_daap, proto_daap);
665    http_dissector_add(TCP_PORT_DAAP, daap_handle);
666 }