/* packet-daap.c * Routines for Digital Audio Access Protocol dissection * Copyright 2004, Kelly Byrd * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include #include #include #include #include "packet-http.h" #define TCP_PORT_DAAP 3689 /* DAAP tags */ /* Some information taken from http://tapjam.net/daap/ */ /* and http://www.deleet.de/projekte/daap/?ContentCodes */ /* DACP tags */ /* Information from http://dacp.jsharkey.org/ */ /* and http://code.google.com/p/tunesremote-plus/ */ /* Container tags */ #define daap_mcon 0x6d636f6e #define daap_msrv 0x6d737276 #define daap_mccr 0x6d636372 #define daap_mdcl 0x6d64636c #define daap_mlog 0x6d6c6f67 #define daap_mupd 0x6d757064 #define daap_avdb 0x61766462 #define daap_mlcl 0x6d6c636c #define daap_mlit 0x6d6c6974 #define daap_mbcl 0x6d62636c #define daap_adbs 0x61646273 #define daap_aply 0x61706c79 #define daap_apso 0x6170736f #define daap_mudl 0x6d75646c #define daap_abro 0x6162726f #define daap_abar 0x61626172 #define daap_arsv 0x61727376 #define daap_abal 0x6162616c #define daap_abcp 0x61626370 #define daap_abgn 0x6162676e #define daap_prsv 0x70727376 #define daap_arif 0x61726966 #define daap_mctc 0x6d637463 #define dacp_casp 0x63617370 #define dacp_cmst 0x636d7374 #define dacp_cmgt 0x636d6774 /* String tags */ #define daap_minm 0x6d696e6d #define daap_msts 0x6d737473 #define daap_mcnm 0x6d636e6d #define daap_mcna 0x6d636e61 #define daap_asal 0x6173616c #define daap_asar 0x61736172 #define daap_ascm 0x6173636d #define daap_asfm 0x6173666d #define daap_aseq 0x61736571 #define daap_asgn 0x6173676e #define daap_asdt 0x61736474 #define daap_asul 0x6173756c #define daap_ascp 0x61736370 #define daap_asct 0x61736374 #define daap_ascn 0x6173636e #define daap_aslc 0x61736c63 #define daap_asky 0x61736b79 #define daap_aeSN 0x6165534e #define daap_aeNN 0x61654e4e #define daap_aeEN 0x6165454e #define daap_assn 0x6173736e #define daap_assa 0x61737361 #define daap_assl 0x6173736c #define daap_assc 0x61737363 #define daap_asss 0x61737373 #define daap_asaa 0x61736161 #define daap_aspu 0x61737075 #define daap_aeCR 0x61654352 #define dacp_cana 0x63616e61 #define dacp_cang 0x63616e67 #define dacp_canl 0x63616e6c #define dacp_cann 0x63616e6e /* uint64 tags */ #define daap_mper 0x6d706572 #define daap_aeGU 0x61654755 #define daap_aeGR 0x61654752 #define daap_asai 0x61736169 #define daap_asls 0x61736c73 /* uint32 tags */ #define daap_mstt 0x6d737474 #define daap_musr 0x6d757372 #define daap_miid 0x6d696964 #define daap_mcti 0x6d637469 #define daap_mpco 0x6d70636f #define daap_mimc 0x6d696d63 #define daap_mrco 0x6d72636f #define daap_mtco 0x6d74636f #define daap_mstm 0x6d73746d #define daap_msdc 0x6d736463 #define daap_mlid 0x6d6c6964 #define daap_msur 0x6d737572 #define daap_asda 0x61736461 #define daap_asdm 0x6173646d #define daap_assr 0x61737372 #define daap_assz 0x6173737a #define daap_asst 0x61737374 #define daap_assp 0x61737370 #define daap_astm 0x6173746d #define daap_aeNV 0x61654e56 #define daap_ascd 0x61736364 #define daap_ascs 0x61736373 #define daap_aeSV 0x61655356 #define daap_aePI 0x61655049 #define daap_aeCI 0x61654349 #define daap_aeGI 0x61654749 #define daap_aeAI 0x61654149 #define daap_aeSI 0x61655349 #define daap_aeES 0x61654553 #define daap_aeSU 0x61655355 #define daap_asbo 0x6173626f #define daap_aeGH 0x61654748 #define daap_aeGD 0x61654744 #define daap_aeGE 0x61654745 #define daap_meds 0x6d656473 #define dacp_cmsr 0x636d7372 #define dacp_cant 0x63616e74 #define dacp_cast 0x63617374 #define dacp_cmvo 0x636d766f /*TODO: #define daap_msto 0x6d7374OO utcoffset */ /* uint16 tags */ #define daap_mcty 0x6d637479 #define daap_asbt 0x61736274 #define daap_asbr 0x61736272 #define daap_asdc 0x61736463 #define daap_asdn 0x6173646e #define daap_astc 0x61737463 #define daap_astn 0x6173746e #define daap_asyr 0x61737972 #define daap_ased 0x61736564 /* byte tags */ #define daap_mikd 0x6d696b64 #define daap_msau 0x6d736175 #define daap_msty 0x6d737479 #define daap_asrv 0x61737276 /* XXX: may be uint16 in newer iTunes versions! */ #define daap_asur 0x61737572 #define daap_asdk 0x6173646b #define daap_muty 0x6d757479 #define daap_msas 0x6d736173 #define daap_aeHV 0x61654856 #define daap_aeHD 0x61654844 #define daap_aePC 0x61655043 #define daap_aePP 0x61655050 #define daap_aeMK 0x61654d4b #define daap_aeSG 0x61655347 #define daap_apsm 0x6170736d #define daap_aprm 0x6170726d #define daap_asgp 0x61736770 #define daap_aePS 0x61655053 #define daap_asbk 0x6173626b #define dacp_cafs 0x63616673 #define dacp_caps 0x63617073 #define dacp_carp 0x63617270 #define dacp_cash 0x63617368 #define dacp_cavs 0x63617673 /* boolean tags */ #define daap_mslr 0x6d736c72 #define daap_msal 0x6d73616c #define daap_msup 0x6d737570 #define daap_mspi 0x6d737069 #define daap_msex 0x6d736578 #define daap_msbr 0x6d736272 #define daap_msqy 0x6d737179 #define daap_msix 0x6d736978 #define daap_msrs 0x6d737273 #define daap_asco 0x6173636f #define daap_asdb 0x61736462 #define daap_abpl 0x6162706c #define daap_aeSP 0x61655350 #define daap_ashp 0x61736870 /* version (32-bit)*/ #define daap_mpro 0x6d70726f #define daap_apro 0x6170726f /* now playing */ #define dacp_canp 0x63616e70 #define daap_png 0x89504e47 /* date/time */ /* TODO: #define daap_mstc 0xMMSSTTCC utctime #define daap_asdr ("daap.songdatereleased") #define daap_asdp ("daap.songdatepurchased") */ void proto_register_daap(void); void proto_reg_handoff_daap(void); static dissector_handle_t daap_handle; static dissector_handle_t png_handle; /*XXX: Sorted by value definition since it appears that the "value" is just */ /* the ascii representation of the last 4 letters of the definition. */ /* (Sorted so a binary search can be done when using value_string_ext) */ static const value_string vals_tag_code[] = { { daap_abal, "browse album listing" }, { daap_abar, "browse artist listing" }, { daap_abcp, "browse composer listing" }, { daap_abgn, "browse genre listing" }, { daap_abpl, "base playlist" }, { daap_abro, "database browse" }, { daap_adbs, "database songs" }, { daap_aeAI, "com.apple.itunes.itms-artistid" }, { daap_aeCI, "com.apple.itunes.itms-composerid" }, { daap_aeCR, "com.apple.itunes.content-rating" }, { daap_aeEN, "com.apple.itunes.episode-num-str" }, { daap_aeES, "com.apple.itunes.episode-sort" }, { daap_aeGD, "com.apple.itunes.gapless-enc-dr" }, { daap_aeGE, "com.apple.itunes.gapless-enc-del" }, { daap_aeGH, "com.apple.itunes.gapless-heur" }, { daap_aeGI, "com.apple.itunes.itms-genreid" }, { daap_aeGR, "com.apple.itunes.gapless-resy" }, { daap_aeGU, "com.apple.itunes.gapless-dur" }, { daap_aeHD, "com.apple.itunes.is-hd-video" }, { daap_aeHV, "com.apple.itunes.has-video" }, { daap_aeMK, "com.apple.itunes.mediakind" }, { daap_aeNN, "com.apple.itunes.network-name" }, { daap_aeNV, "com.apple.itunes.norm-volume" }, { daap_aePC, "com.apple.itunes.is-podcast" }, { daap_aePI, "com.apple.itunes.itms-playlistid" }, { daap_aePP, "com.apple.itunes.is-podcast-playlist" }, { daap_aePS, "com.apple.itunes.special-playlist" }, { daap_aeSG, "com.apple.itunes.saved-genius" }, { daap_aeSI, "com.apple.itunes.itms-songid" }, { daap_aeSN, "com.apple.itunes.series-name" }, { daap_aeSP, "com.apple.itunes.smart-playlist" }, { daap_aeSU, "com.apple.itunes.season-num" }, { daap_aeSV, "com.apple.itunes.music-sharing-version" }, { daap_aply, "database playlists" }, { daap_aprm, "playlist repeat mode" }, { daap_apro, "protocol (application?) version (apro)" }, { daap_apsm, "playlist shuffle mode" }, { daap_apso, "playlist songs" }, { daap_arif, "resolveinfo" }, { daap_arsv, "resolve" }, { daap_asaa, "song album artist" }, { daap_asai, "song album id"}, { daap_asal, "song album" }, { daap_asar, "song artist" }, { daap_asbk, "song bookmarkable" }, { daap_asbo, "song bookmark" }, { daap_asbr, "song bitrate" }, { daap_asbt, "song beats-per-minute" }, { daap_ascd, "song codec type" }, { daap_ascm, "song comment" }, { daap_ascn, "song content description" }, { daap_asco, "song compilation" }, { daap_ascp, "song composer" }, { daap_ascs, "song codec subtype" }, { daap_asct, "song category" }, { daap_asda, "song date added" }, { daap_asdb, "song disabled" }, { daap_asdc, "song disccount" }, { daap_asdk, "song data kind" }, { daap_asdm, "song date modified" }, { daap_asdn, "song discnumber" }, { daap_asdt, "song description" }, { daap_ased, "song extra data" }, { daap_aseq, "song eq preset" }, { daap_asfm, "song format" }, { daap_asgn, "song genre" }, { daap_asgp, "song gapless" }, { daap_ashp, "song has been played" }, { daap_asky, "song keywords" }, { daap_aslc, "song long content description" }, { daap_asls, "song long size"}, { daap_aspu, "song podcast url" }, { daap_asrv, "song relative volume" }, { daap_assa, "sort artist" }, { daap_assc, "sort composer" }, { daap_assn, "sort name" }, { daap_assp, "song stop time (milliseconds)" }, { daap_assr, "song sample rate" }, { daap_asss, "sort seriesname" }, { daap_asst, "song start time (milliseconds)" }, { daap_assz, "song size" }, { daap_astc, "song track count" }, { daap_astm, "song time (milliseconds)" }, { daap_astn, "song track number" }, { daap_asul, "song data url" }, { daap_asur, "song user rating" }, { daap_asyr, "song year" }, { daap_avdb, "server databases" }, { dacp_cafs, "fullscreen" }, { dacp_cana, "song artist" }, { dacp_cang, "song genre" }, { dacp_canl, "song album" }, { dacp_cann, "song name" }, { dacp_canp, "now playing" }, { dacp_cant, "song time remaining (milliseconds)" }, { dacp_caps, "play status" }, { dacp_carp, "repeat" }, { dacp_cash, "shuffle" }, { dacp_casp, "speakers container" }, { dacp_cast, "song time total (milliseconds)" }, { dacp_cavs, "visualizer" }, { dacp_cmgt, "container (cmgt)" }, { dacp_cmsr, "status revision" }, { dacp_cmst, "control container" }, { dacp_cmvo, "volume" }, { daap_mbcl, "bag (mbcl)" }, { daap_mccr, "content codes response" }, { daap_mcna, "content codes name" }, { daap_mcnm, "content codes number" }, { daap_mcon, "container (mcon)" }, { daap_mctc, "container count" }, { daap_mcti, "container item id (mcti)" }, { daap_mcty, "content codes type" }, { daap_mdcl, "dictionary (mdcl)" }, { daap_meds, "edit commands supported" }, { daap_miid, "item id (miid)" }, { daap_mikd, "item kind (mikd)" }, { daap_mimc, "item count (mimc)" }, { daap_minm, "item name (minm)" }, { daap_mlcl, "listing (mlcl)" }, { daap_mlid, "session id" }, { daap_mlit, "listing item (mlit)" }, { daap_mlog, "login response" }, { daap_mpco, "parent container id (mpco)" }, { daap_mper, "persistent id (mper)" }, { daap_mpro, "protocol version (mpro)" }, { daap_mrco, "returned count (mrco)" }, { daap_msal, "supports auto-logout (msal)" }, { daap_msas, "authentication schemes" }, { daap_msau, "authentication method (msau)" }, { daap_msbr, "supports browse" }, { daap_msdc, "databases count" }, { daap_msex, "supports extensions (msex)" }, { daap_msix, "supports index" }, { daap_mslr, "login required (mslr)" }, { daap_mspi, "supports persistent ids (mspi)" }, { daap_msqy, "supports query" }, { daap_msrs, "supports resolve" }, { daap_msrv, "server info response (msrv)" }, { daap_mstm, "timeout interval" }, { daap_msts, "status string (msts)" }, { daap_mstt, "status (mstt)" }, { daap_msup, "supports update (msup)" }, { daap_msur, "server revision" }, { daap_mtco, "specified total count (mtco)" }, { daap_mudl, "deleted id listing" }, { daap_mupd, "update response" }, { daap_musr, "server revision" }, { daap_muty, "update type" }, { daap_prsv, "resolve" }, { 0, NULL} }; static value_string_ext vals_tag_code_ext = VALUE_STRING_EXT_INIT(vals_tag_code); /* Initialize the protocol and registered fields */ static int proto_daap; static int hf_daap_name; static int hf_daap_size; static int hf_daap_data_string; static int hf_daap_persistent_id; static int hf_daap_status; static int hf_daap_rev; static int hf_daap_id; static int hf_daap_cnt; static int hf_daap_timeout; static int hf_daap_data; static int hf_daap_playlist_id; static int hf_daap_track_id; /* Initialize the subtree pointers */ static int ett_daap; static int ett_daap_sub; static expert_field ei_daap_max_recursion_depth_reached; /* Forward declarations */ static void dissect_daap_one_tag(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb); static int dissect_daap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { proto_item *ti; proto_tree *daap_tree; unsigned first_tag; first_tag = tvb_get_ntohl(tvb, 0); col_set_str(pinfo->cinfo, COL_PROTOCOL, "DAAP"); /* * This catches album art coming back from iTunes. * XXX - will those have a media type of image/png * rather than application/x-dmap-tagged? If so, * this is no longer necessary. */ if (first_tag == daap_png) { call_dissector(png_handle, tvb, pinfo, tree); return tvb_captured_length(tvb); } /* This is done in two functions on purpose. If the tvb_get_xxx() * functions fail, at least something will be in the info column */ col_set_str(pinfo->cinfo, COL_INFO, "DAAP Response"); col_append_fstr(pinfo->cinfo, COL_INFO, " [first tag: %s, size: %d]", tvb_format_text(pinfo->pool, tvb, 0, 4), tvb_get_ntohl(tvb, 4)); ti = proto_tree_add_item(tree, proto_daap, tvb, 0, -1, ENC_NA); daap_tree = proto_item_add_subtree(ti, ett_daap); dissect_daap_one_tag(daap_tree, pinfo, tvb); return tvb_captured_length(tvb); } #define DAAP_MAX_RECURSION_DEPTH 100 static void // NOLINTNEXTLINE(misc-no-recursion) dissect_daap_one_tag(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb) { unsigned offset = 0; uint32_t tagname, tagsize; proto_item *tag_ti; proto_tree *tag_tree; tvbuff_t *new_tvb; unsigned recursion_depth = p_get_proto_depth(pinfo, proto_daap); if (++recursion_depth >= DAAP_MAX_RECURSION_DEPTH) { proto_tree_add_expert(tree, pinfo, &ei_daap_max_recursion_depth_reached, tvb, 0, 0); return; } p_set_proto_depth(pinfo, proto_daap, recursion_depth); while (offset < tvb_reported_length(tvb)) { tagname = tvb_get_ntohl(tvb, offset); tagsize = tvb_get_ntohl(tvb, offset+4); tag_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_daap_sub, &tag_ti, "Tag: "); proto_tree_add_item_ret_uint(tag_tree, hf_daap_name, tvb, offset, 4, ENC_ASCII|ENC_NA, &tagname); offset += 4; proto_tree_add_item_ret_uint(tag_tree, hf_daap_size, tvb, offset, 4, ENC_BIG_ENDIAN, &tagsize); offset += 4; proto_item_append_text(tag_ti, "%s, %u byte%c", val_to_str_ext(tagname, &vals_tag_code_ext, "Unknown tag (0x%0x)"), tagsize, plurality(tagsize, ' ', 's')); proto_item_set_len(tag_ti, 8+tagsize); if (tagsize > INT_MAX) break; switch (tagname) { case daap_mcon: case daap_msrv: case daap_mccr: case daap_mdcl: case daap_mlog: case daap_mupd: case daap_avdb: case daap_mlcl: case daap_mlit: case daap_mbcl: case daap_adbs: case daap_aply: case daap_apso: case daap_mudl: case daap_abro: case daap_abar: case daap_arsv: case daap_abal: case daap_abcp: case daap_abgn: case daap_prsv: case daap_arif: case dacp_casp: case dacp_cmgt: case dacp_cmst: /* Container tags */ new_tvb = tvb_new_subset_length(tvb, offset, (int)tagsize); dissect_daap_one_tag(tag_tree, pinfo, new_tvb); break; case daap_minm: case daap_msts: case daap_mcnm: case daap_mcna: case daap_asal: case daap_asar: case daap_ascm: case daap_asfm: case daap_aseq: case daap_asgn: case daap_asdt: case daap_asul: case daap_ascp: case daap_asct: case daap_ascn: case daap_aslc: case daap_asky: case daap_aeSN: case daap_aeNN: case daap_aeEN: case daap_assn: case daap_assa: case daap_assl: case daap_assc: case daap_asss: case daap_asaa: case daap_aspu: case daap_aeCR: case dacp_cana: case dacp_cang: case dacp_canl: case dacp_cann: /* Tags contain strings XXX - verify that they're really 7bit ASCII */ proto_tree_add_item(tag_tree, hf_daap_data_string, tvb, offset, tagsize, ENC_ASCII); break; case daap_mper: case daap_aeGR: case daap_aeGU: case daap_asai: case daap_asls: proto_tree_add_item(tag_tree, hf_daap_persistent_id, tvb, offset, tagsize, ENC_BIG_ENDIAN); break; case daap_mstt: proto_tree_add_item(tag_tree, hf_daap_status, tvb, offset, tagsize, ENC_BIG_ENDIAN); break; case daap_musr: case daap_msur: proto_tree_add_item(tag_tree, hf_daap_rev, tvb, offset, tagsize, ENC_BIG_ENDIAN); break; case daap_miid: case daap_mcti: case daap_mpco: case daap_mlid: proto_tree_add_item(tag_tree, hf_daap_id, tvb, offset, tagsize, ENC_BIG_ENDIAN); break; case daap_mrco: case daap_mtco: case daap_mimc: case daap_msdc: case daap_mctc: proto_tree_add_item(tag_tree, hf_daap_cnt, tvb, offset, tagsize, ENC_BIG_ENDIAN); break; case daap_mstm: proto_tree_add_item(tag_tree, hf_daap_timeout, tvb, offset, tagsize, ENC_BIG_ENDIAN); break; case daap_asda: case daap_asdm: case daap_assr: case daap_assz: case daap_asst: case daap_assp: case daap_astm: case daap_aeNV: case daap_ascd: case daap_ascs: case daap_aeSV: case daap_aePI: case daap_aeCI: case daap_aeGI: case daap_aeAI: case daap_aeSI: case daap_aeES: case daap_asbo: case daap_aeGH: case daap_aeGD: case daap_aeGE: case dacp_cant: case dacp_cast: case dacp_cmsr: case dacp_cmvo: case daap_meds: /* Tags contain uint32 XXX - check tagsize here and below */ proto_tree_add_item(tag_tree, hf_daap_data, tvb, offset, tagsize, ENC_BIG_ENDIAN); break; case daap_mcty: case daap_asbt: case daap_asbr: case daap_asdc: case daap_asdn: case daap_astc: case daap_astn: case daap_asyr: case daap_ased: /* Tags contain uint16 */ proto_tree_add_item(tag_tree, hf_daap_data, tvb, offset, tagsize, ENC_BIG_ENDIAN); break; case daap_mikd: case daap_msau: case daap_msty: case daap_asrv: case daap_asur: case daap_asdk: case daap_muty: case daap_msas: case daap_aeHV: case daap_aeHD: case daap_aePC: case daap_aePP: case daap_aeMK: case daap_aeSG: case daap_apsm: case daap_aprm: case daap_asgp: case daap_aePS: case dacp_cafs: case dacp_caps: case dacp_carp: case dacp_cash: case dacp_cavs: /* Tags contain uint8 */ proto_tree_add_item(tag_tree, hf_daap_data, tvb, offset, tagsize, ENC_BIG_ENDIAN); break; case daap_mslr: case daap_msal: case daap_msup: case daap_mspi: case daap_msex: case daap_msbr: case daap_msqy: case daap_msix: case daap_msrs: case daap_asco: case daap_asdb: case daap_abpl: case daap_aeSP: case daap_asbk: /* Tags ARE boolean. Data is (uint8), but it seems * the value is always zero. So, if the tag is present * the "bool" is true. */ proto_item_append_text(tag_ti, "; Data: True"); break; case daap_mpro: case daap_apro: /* Tags contain version (uint32) */ proto_item_append_text(tag_ti, "; Version: %d.%d.%d.%d", tvb_get_uint8(tvb, offset), tvb_get_uint8(tvb, offset+1), tvb_get_uint8(tvb, offset+2), tvb_get_uint8(tvb, offset+3)); break; case dacp_canp: /* now playing */ /* bytes 4-7 contain uint32 playlist id */ /* bytes 12-15 contain uint32 track id */ proto_tree_add_item(tag_tree, hf_daap_playlist_id, tvb, offset+4, 4, ENC_BIG_ENDIAN); proto_tree_add_item(tag_tree, hf_daap_track_id, tvb, offset+12, 4, ENC_BIG_ENDIAN); break; default: break; } offset += tagsize; } } /* Register the protocol with Wireshark */ void proto_register_daap(void) { static hf_register_info hf[] = { { &hf_daap_name, { "Tag name", "daap.name", FT_UINT32, BASE_HEX|BASE_EXT_STRING, &vals_tag_code_ext, 0, NULL, HFILL } }, { &hf_daap_size, { "Tag size", "daap.size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_daap_data_string, { "Data string", "daap.data_string", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_daap_persistent_id, { "Persistent Id", "daap.persistent_id", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_daap_status, { "Status", "daap.status", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_daap_rev, { "Revision", "daap.revision", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_daap_id, { "Id", "daap.id", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_daap_cnt, { "Count", "daap.count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_daap_timeout, { "Timeout (seconds)", "daap.timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, /* this will hold data for the tags that contain 32, 16 or 8 bits of payload */ { &hf_daap_data, { "Data", "daap.data", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_daap_playlist_id, { "Playlist Id", "daap.playlist_id", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_daap_track_id, { "Track Id", "daap.track_id", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } } }; static int *ett[] = { &ett_daap, &ett_daap_sub, }; expert_module_t *expert_daap; static ei_register_info ei[] = { { &ei_daap_max_recursion_depth_reached, { "daap.max_recursion_depth_reached", PI_PROTOCOL, PI_WARN, "Maximum allowed recursion depth reached - stop decoding", EXPFILL }} }; proto_daap = proto_register_protocol("Digital Audio Access Protocol", "DAAP", "daap"); expert_daap = expert_register_protocol(proto_daap); expert_register_field_array(expert_daap, ei, array_length(ei)); proto_register_field_array(proto_daap, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); daap_handle = register_dissector("daap", dissect_daap, proto_daap); } void proto_reg_handoff_daap(void) { http_tcp_port_add(TCP_PORT_DAAP); dissector_add_string("media_type", "application/x-dmap-tagged", daap_handle); png_handle = find_dissector_add_dependency("png", proto_daap); } /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * * Local Variables: * c-basic-offset: 3 * tab-width: 8 * indent-tabs-mode: nil * End: * * ex: set shiftwidth=3 tabstop=8 expandtab: * :indentSize=3:tabSize=8:noTabs=true: */