/* packet-daap.c * Routines for Digital Audio Access Protocol dissection * Copyright 2004, Kelly Byrd * * $Id$ * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #define TCP_PORT_DAAP 3689 /* DAAP tags */ /* 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_abal 0x6162616c #define daap_abcp 0x61626370 #define daap_abgn 0x6162676e #define daap_prsv 0x70727376 #define daap_arif 0x61726966 /* 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 /* uint64 tags */ #define daap_mper 0x6d706572 /* 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 /* 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 /* byte tags */ #define daap_mikd 0x6d696b64 #define daap_msau 0x6d736175 #define daap_msty 0x6d737479 #define daap_asrv 0x61737276 #define daap_asur 0x61737572 #define daap_asdk 0x6173646b /* 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 /* version (32-bit)*/ #define daap_mpro 0x6d70726f #define daap_apro 0x6170726f /* Initialize the protocol and registered fields */ static int proto_daap = -1; static int hf_daap_name = -1; static int hf_daap_size = -1; /* Initialize the subtree pointers */ static gint ett_daap = -1; static gint ett_daap_sub = -1; /* Forward declarations */ static int dissect_daap_one_tag(proto_tree *tree, tvbuff_t *tvb, int offset, int length); static void dissect_daap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *daap_tree; int offset = 0; gboolean is_request = (pinfo->destport == TCP_PORT_DAAP); if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "DAAP"); /* * XXX - what if the body is gzipped? This isn't the only protocol * running atop HTTP that might have a problem with that.... */ if (check_col(pinfo->cinfo, COL_INFO)) { if (is_request) { col_set_str(pinfo->cinfo, COL_INFO, "DAAP Request"); } else { /* 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, " [tag: %s, size: %d]", tvb_format_text(tvb, offset, 4), tvb_get_ntohl(tvb, offset+4)); } } if (tree) { ti = proto_tree_add_item(tree, proto_daap, tvb, 0, -1, FALSE); daap_tree = proto_item_add_subtree(ti, ett_daap); dissect_daap_one_tag(daap_tree, tvb, offset, 0); } } static int dissect_daap_one_tag(proto_tree *tree, tvbuff_t *tvb, int offset, int length) { unsigned int tagname; int tagsize; int new_offset; proto_item *ti = NULL; proto_item *ti2 = NULL; proto_tree *new_tree = NULL; do { if (!tvb_offset_exists(tvb, offset)) break; tagname = tvb_get_ntohl(tvb, offset); tagsize = tvb_get_ntohl(tvb, offset+4); tvb_ensure_bytes_exist(tvb, offset, tagsize+8); ti = proto_tree_add_text(tree, tvb, offset, tagsize+8, "Tag: %c%c%c%c, Size: %d", tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3), tagsize); ti2 = proto_tree_add_item(tree, hf_daap_name, tvb, offset, 4, FALSE); PROTO_ITEM_SET_HIDDEN(ti2); ti2 = proto_tree_add_item(tree, hf_daap_size, tvb, offset+4, 4, FALSE); PROTO_ITEM_SET_HIDDEN(ti2); offset += 8; length -= 8; 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_abal: case daap_abcp: case daap_abgn: case daap_prsv: case daap_arif: /* Container tags */ new_tree = proto_item_add_subtree(ti, ett_daap_sub); new_offset = dissect_daap_one_tag(new_tree, tvb, offset, tagsize); 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: /* Tags contain strings */ proto_item_append_text(ti, ", Data: %s", tvb_format_text(tvb, offset, tagsize)); break; case daap_mper: /* Tags conain uint64 */ proto_item_append_text(ti, ", Persistent Id: %" G_GINT64_MODIFIER "u", tvb_get_ntoh64(tvb, offset)); break; case daap_mstt: proto_item_append_text(ti, ", Status: %d", tvb_get_ntohl(tvb, offset)); break; case daap_musr: case daap_msur: proto_item_append_text(ti, ", Revision: %d", tvb_get_ntohl(tvb, offset)); break; case daap_miid: case daap_mcti: case daap_mpco: case daap_mlid: proto_item_append_text(ti, ", Id: %d", tvb_get_ntohl(tvb, offset)); break; case daap_mrco: case daap_mtco: case daap_mimc: case daap_msdc: proto_item_append_text(ti, ", Count: %d", tvb_get_ntohl(tvb, offset)); break; case daap_mstm: proto_item_append_text(ti, ", Timeout: %d seconds", tvb_get_ntohl(tvb, offset)); 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: /* Tags conain uint32 */ proto_item_append_text(ti, ", Data: %d", tvb_get_ntohl(tvb, offset)); 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: /* Tags conain uint16 */ proto_item_append_text(ti, ", Data: %d", tvb_get_ntohs(tvb, offset)); break; case daap_mikd: case daap_msau: case daap_msty: case daap_asrv: case daap_asur: case daap_asdk: /* Tags conain uint8 */ proto_item_append_text(ti, ", Data: %d", tvb_get_guint8(tvb, offset)); 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: /* 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(ti, ", Data: True"); break; case daap_mpro: case daap_apro: /* Tags conain version (uint32) */ proto_item_append_text(ti, ", Version: %d.%d.%d.%d", tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3)); break; default: break; } offset += tagsize; length -= tagsize; } while (length > 0); return offset; } /* Register the protocol with Wireshark */ void proto_register_daap(void) { static hf_register_info hf[] = { { &hf_daap_name, { "Name", "daap.name", FT_STRING, BASE_NONE, NULL, 0x0, "Tag Name", HFILL} }, { &hf_daap_size, { "Size", "daap.size", FT_UINT32, BASE_DEC, NULL, 0x0, "Tag Size", HFILL } } }; static gint *ett[] = { &ett_daap, &ett_daap_sub, }; proto_daap = proto_register_protocol("Digital Audio Access Protocol", "DAAP", "daap"); proto_register_field_array(proto_daap, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } /* If this dissector uses sub-dissector registration add a registration routine. This format is required because a script is used to find these routines and create the code that calls these routines. */ void proto_reg_handoff_daap(void) { dissector_handle_t daap_handle; daap_handle = create_dissector_handle(dissect_daap, proto_daap); http_dissector_add(TCP_PORT_DAAP, daap_handle); }