PageRenderTime 70ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/epan/dissectors/packet-sdp.c

https://github.com/labx-technologies-llc/wireshark
C | 2763 lines | 2060 code | 333 blank | 370 comment | 488 complexity | f4be8ff309ab793438220629debe7b5e MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /* packet-sdp.c
  2. * Routines for SDP packet disassembly (RFC 2327)
  3. *
  4. * Jason Lango <jal@netapp.com>
  5. * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu>
  6. *
  7. * $Id$
  8. *
  9. * Wireshark - Network traffic analyzer
  10. * By Gerald Combs <gerald@wireshark.org>
  11. * Copyright 1998 Gerald Combs
  12. *
  13. * This program is free software; you can redistribute it and/or
  14. * modify it under the terms of the GNU General Public License
  15. * as published by the Free Software Foundation; either version 2
  16. * of the License, or (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  26. * Ref http://www.ietf.org/rfc/rfc4566.txt?number=4566
  27. */
  28. #include "config.h"
  29. #ifdef HAVE_SYS_TYPES_H
  30. #include <sys/types.h>
  31. #endif
  32. #ifdef HAVE_SYS_SOCKET_H
  33. #include <sys/socket.h>
  34. #endif
  35. #ifdef HAVE_NETINET_IN_H
  36. # include <netinet/in.h>
  37. #endif
  38. #ifdef HAVE_ARPA_INET_H
  39. #include <arpa/inet.h>
  40. #endif
  41. #ifdef HAVE_WINSOCK2_H
  42. #include <winsock2.h> /* needed to define AF_ values on Windows */
  43. #endif
  44. #ifdef NEED_INET_V6DEFS_H
  45. # include "wsutil/inet_v6defs.h"
  46. #endif
  47. #include <glib.h>
  48. #include <epan/packet.h>
  49. #include <epan/strutil.h>
  50. #include <epan/emem.h>
  51. #include <epan/wmem/wmem.h>
  52. #include <epan/base64.h>
  53. #include <epan/asn1.h>
  54. #include <epan/prefs.h>
  55. #include <epan/expert.h>
  56. #include <epan/tap.h>
  57. #include <epan/rtp_pt.h>
  58. #include <epan/show_exception.h>
  59. #include "packet-sdp.h"
  60. #include "packet-rtp.h"
  61. #include "packet-rtcp.h"
  62. #include "packet-t38.h"
  63. #include "packet-msrp.h"
  64. #include "packet-sprt.h"
  65. #include "packet-per.h"
  66. #include "packet-h245.h"
  67. #include "packet-h264.h"
  68. #include "packet-mp4ves.h"
  69. static dissector_handle_t rtp_handle;
  70. static dissector_handle_t rtcp_handle;
  71. static dissector_handle_t t38_handle;
  72. static dissector_handle_t sprt_handle;
  73. static dissector_handle_t msrp_handle;
  74. static dissector_handle_t h264_handle;
  75. static dissector_handle_t mp4ves_handle;
  76. static int sdp_tap = -1;
  77. static int proto_sdp = -1;
  78. static int proto_sprt = -1;
  79. static const char* UNKNOWN_ENCODING = "Unknown";
  80. static emem_tree_t *sdp_transport_reqs = NULL;
  81. static emem_tree_t *sdp_transport_rsps = NULL;
  82. /* preference globals */
  83. static gboolean global_sdp_establish_conversation = TRUE;
  84. /* Top level fields */
  85. static int hf_protocol_version = -1;
  86. static int hf_owner = -1;
  87. static int hf_session_name = -1;
  88. static int hf_session_info = -1;
  89. static int hf_uri = -1;
  90. static int hf_email = -1;
  91. static int hf_phone = -1;
  92. static int hf_connection_info = -1;
  93. static int hf_bandwidth = -1;
  94. static int hf_timezone = -1;
  95. static int hf_encryption_key = -1;
  96. static int hf_session_attribute = -1;
  97. static int hf_media_attribute = -1;
  98. static int hf_time = -1;
  99. static int hf_repeat_time = -1;
  100. static int hf_media = -1;
  101. static int hf_media_title = -1;
  102. static int hf_unknown = -1;
  103. static int hf_invalid = -1;
  104. static int hf_ipbcp_version = -1;
  105. static int hf_ipbcp_type = -1;
  106. /* hf_owner subfields*/
  107. static int hf_owner_username = -1;
  108. static int hf_owner_sessionid = -1;
  109. static int hf_owner_version = -1;
  110. static int hf_owner_network_type = -1;
  111. static int hf_owner_address_type = -1;
  112. static int hf_owner_address = -1;
  113. /* hf_connection_info subfields */
  114. static int hf_connection_info_network_type = -1;
  115. static int hf_connection_info_address_type = -1;
  116. static int hf_connection_info_connection_address = -1;
  117. static int hf_connection_info_ttl = -1;
  118. static int hf_connection_info_num_addr = -1;
  119. /* hf_bandwidth subfields */
  120. static int hf_bandwidth_modifier = -1;
  121. static int hf_bandwidth_value = -1;
  122. /* hf_time subfields */
  123. static int hf_time_start = -1;
  124. static int hf_time_stop = -1;
  125. /* hf_repeat_time subfield */
  126. static int hf_repeat_time_interval = -1;
  127. static int hf_repeat_time_duration = -1;
  128. static int hf_repeat_time_offset = -1;
  129. /* hf_timezone subfields */
  130. static int hf_timezone_time = -1;
  131. static int hf_timezone_offset = -1;
  132. /* hf_encryption_key subfields */
  133. static int hf_encryption_key_type = -1;
  134. static int hf_encryption_key_data = -1;
  135. /* hf_session_attribute subfields */
  136. static int hf_session_attribute_field = -1;
  137. static int hf_session_attribute_value = -1;
  138. /* hf_media subfields */
  139. static int hf_media_media = -1;
  140. static int hf_media_port = -1;
  141. static int hf_media_portcount = -1;
  142. static int hf_media_proto = -1;
  143. static int hf_media_format = -1;
  144. /* hf_session_attribute subfields */
  145. static int hf_media_attribute_field = -1;
  146. static int hf_media_attribute_value = -1;
  147. static int hf_media_encoding_name = -1;
  148. static int hf_media_sample_rate = -1;
  149. static int hf_media_format_specific_parameter = -1;
  150. static int hf_sdp_fmtp_mpeg4_profile_level_id = -1;
  151. static int hf_sdp_fmtp_h263_profile = -1;
  152. static int hf_sdp_fmtp_h263_level = -1;
  153. static int hf_sdp_h264_packetization_mode = -1;
  154. static int hf_SDPh223LogicalChannelParameters = -1;
  155. /* hf_session_attribute hf_media_attribute subfields */
  156. static int hf_key_mgmt_att_value = -1;
  157. static int hf_key_mgmt_prtcl_id = -1;
  158. static int hf_key_mgmt_data = -1;
  159. static int hf_sdp_crypto_tag = -1;
  160. static int hf_sdp_crypto_crypto_suite = -1;
  161. static int hf_sdp_crypto_master_key = -1;
  162. static int hf_sdp_crypto_master_salt = -1;
  163. static int hf_sdp_crypto_lifetime = -1;
  164. static int hf_sdp_crypto_mki = -1;
  165. static int hf_sdp_crypto_mki_length = -1;
  166. /* trees */
  167. static int ett_sdp = -1;
  168. static int ett_sdp_owner = -1;
  169. static int ett_sdp_connection_info = -1;
  170. static int ett_sdp_bandwidth = -1;
  171. static int ett_sdp_time = -1;
  172. static int ett_sdp_repeat_time = -1;
  173. static int ett_sdp_timezone = -1;
  174. static int ett_sdp_encryption_key = -1;
  175. static int ett_sdp_session_attribute = -1;
  176. static int ett_sdp_media = -1;
  177. static int ett_sdp_media_attribute = -1;
  178. static int ett_sdp_fmtp = -1;
  179. static int ett_sdp_key_mgmt = -1;
  180. static int ett_sdp_crypto_key_parameters = -1;
  181. static expert_field ei_sdp_invalid_key_param = EI_INIT;
  182. static expert_field ei_sdp_invalid_line = EI_INIT;
  183. #define SDP_RTP_PROTO 0x00000001
  184. #define SDP_SRTP_PROTO 0x00000002
  185. #define SDP_T38_PROTO 0x00000004
  186. #define SDP_MSRP_PROTO 0x00000008
  187. #define SDP_SPRT_PROTO 0x00000010
  188. #define SDP_IPv4 0x80000000
  189. #define SDP_IPv6 0x40000000
  190. #define SDP_MSRP_IPv4 0x20000000
  191. #define SDP_VIDEO 0x10000000
  192. #define SDP_MAX_RTP_CHANNELS 4
  193. #define SDP_MAX_RTP_PAYLOAD_TYPES 20
  194. #define SDP_NO_OF_PT 128
  195. typedef struct {
  196. gint32 pt[SDP_MAX_RTP_PAYLOAD_TYPES];
  197. gint8 pt_count;
  198. GHashTable *rtp_dyn_payload;
  199. gboolean set_rtp;
  200. } transport_media_pt_t;
  201. typedef struct {
  202. enum sdp_exchange_type sdp_status;
  203. char *encoding_name[SDP_NO_OF_PT];
  204. int sample_rate[SDP_NO_OF_PT];
  205. int media_port[SDP_MAX_RTP_CHANNELS];
  206. address src_addr[SDP_MAX_RTP_CHANNELS];
  207. guint proto_bitmask[SDP_MAX_RTP_CHANNELS];
  208. transport_media_pt_t media[SDP_MAX_RTP_CHANNELS];
  209. gint8 media_count;
  210. /* SRTP related info XXX note currently we only handle one crypto line in the SDP
  211. * We should probably handle offer/answer and session updates etc(SIP) quite possibly the whole handling of
  212. * seting up the RTP conversations should be done by the signaling protocol(s) calling the SDP dissector
  213. * and the SDP dissector just provide the relevant data.
  214. */
  215. guint encryption_algorithm;
  216. guint auth_algorithm;
  217. guint mki_len; /* number of octets used for the MKI in the RTP payload */
  218. guint auth_tag_len; /* number of octets used for the Auth Tag in the RTP payload */
  219. } transport_info_t;
  220. /* Data that is retrieved from a packet, but does not need to be kept */
  221. typedef struct {
  222. char *connection_address;
  223. char *connection_type;
  224. char *media_type;
  225. char *media_port[SDP_MAX_RTP_CHANNELS];
  226. char *media_proto[SDP_MAX_RTP_CHANNELS];
  227. guint8 media_count;
  228. /* MSRP transport info (as set while parsing path attribute) */
  229. gboolean msrp_transport_address_set;
  230. guint32 msrp_ipaddr[4];
  231. guint16 msrp_port_number;
  232. } disposable_media_info_t;
  233. /* key-mgmt dissector
  234. * IANA registry:
  235. * http://www.iana.org/assignments/sdp-parameters
  236. */
  237. static dissector_table_t key_mgmt_dissector_table;
  238. /* Subdissector functions */
  239. static void
  240. dissect_sdp_owner(tvbuff_t *tvb, proto_item *ti) {
  241. proto_tree *sdp_owner_tree;
  242. gint offset, next_offset, tokenlen;
  243. offset = 0;
  244. sdp_owner_tree = proto_item_add_subtree(ti, ett_sdp_owner);
  245. /* Find the username */
  246. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  247. if (next_offset == -1)
  248. return;
  249. tokenlen = next_offset - offset;
  250. proto_tree_add_item(sdp_owner_tree, hf_owner_username, tvb, offset, tokenlen,
  251. ENC_ASCII|ENC_NA);
  252. offset = next_offset + 1;
  253. /* Find the session id */
  254. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  255. if (next_offset == -1)
  256. return;
  257. tokenlen = next_offset - offset;
  258. proto_tree_add_item(sdp_owner_tree, hf_owner_sessionid, tvb, offset,
  259. tokenlen, ENC_ASCII|ENC_NA);
  260. offset = next_offset + 1;
  261. /* Find the version */
  262. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  263. if (next_offset == -1)
  264. return;
  265. tokenlen = next_offset - offset;
  266. proto_tree_add_item(sdp_owner_tree, hf_owner_version, tvb, offset, tokenlen,
  267. ENC_ASCII|ENC_NA);
  268. offset = next_offset + 1;
  269. /* Find the network type */
  270. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  271. if (next_offset == -1)
  272. return;
  273. tokenlen = next_offset - offset;
  274. proto_tree_add_item(sdp_owner_tree, hf_owner_network_type, tvb, offset,
  275. tokenlen, ENC_ASCII|ENC_NA);
  276. offset = next_offset + 1;
  277. /* Find the address type */
  278. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  279. if (next_offset == -1)
  280. return;
  281. tokenlen = next_offset - offset;
  282. proto_tree_add_item(sdp_owner_tree, hf_owner_address_type, tvb, offset,
  283. tokenlen, ENC_ASCII|ENC_NA);
  284. offset = next_offset + 1;
  285. /* Find the address */
  286. proto_tree_add_item(sdp_owner_tree, hf_owner_address, tvb, offset, -1, ENC_ASCII|ENC_NA);
  287. }
  288. /*
  289. * XXX - this can leak memory if an exception is thrown after we've fetched
  290. * a string.
  291. */
  292. static void
  293. dissect_sdp_connection_info(tvbuff_t *tvb, proto_item* ti,
  294. disposable_media_info_t *media_info) {
  295. proto_tree *sdp_connection_info_tree;
  296. gint offset, next_offset, tokenlen;
  297. offset = 0;
  298. sdp_connection_info_tree = proto_item_add_subtree(ti,
  299. ett_sdp_connection_info);
  300. /* Find the network type */
  301. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  302. if (next_offset == -1)
  303. return;
  304. tokenlen = next_offset - offset;
  305. proto_tree_add_item(sdp_connection_info_tree,
  306. hf_connection_info_network_type, tvb, offset, tokenlen,
  307. ENC_ASCII|ENC_NA);
  308. offset = next_offset + 1;
  309. /* Find the address type */
  310. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  311. if (next_offset == -1)
  312. return;
  313. tokenlen = next_offset - offset;
  314. /* Save connection address type */
  315. media_info->connection_type = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
  316. proto_tree_add_item(sdp_connection_info_tree,
  317. hf_connection_info_address_type, tvb, offset, tokenlen,
  318. ENC_ASCII|ENC_NA);
  319. offset = next_offset + 1;
  320. /* Find the connection address */
  321. /* XXX - what if there's a <number of addresses> value? */
  322. next_offset = tvb_find_guint8(tvb, offset, -1, '/');
  323. if (next_offset == -1) {
  324. tokenlen = -1; /* end of tvbuff */
  325. /* Save connection address */
  326. media_info->connection_address =
  327. (char*)tvb_get_ephemeral_string(tvb, offset, tvb_length_remaining(tvb, offset));
  328. } else {
  329. tokenlen = next_offset - offset;
  330. /* Save connection address */
  331. media_info->connection_address = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
  332. }
  333. proto_tree_add_item(sdp_connection_info_tree,
  334. hf_connection_info_connection_address, tvb, offset,
  335. tokenlen, ENC_ASCII|ENC_NA);
  336. if (next_offset != -1) {
  337. offset = next_offset + 1;
  338. next_offset = tvb_find_guint8(tvb, offset, -1, '/');
  339. if (next_offset == -1) {
  340. tokenlen = -1; /* end of tvbuff */
  341. } else {
  342. tokenlen = next_offset - offset;
  343. }
  344. proto_tree_add_item(sdp_connection_info_tree,
  345. hf_connection_info_ttl, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  346. if (next_offset != -1) {
  347. offset = next_offset + 1;
  348. proto_tree_add_item(sdp_connection_info_tree,
  349. hf_connection_info_num_addr, tvb, offset, -1, ENC_ASCII|ENC_NA);
  350. }
  351. }
  352. }
  353. static void
  354. dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti) {
  355. proto_tree *sdp_bandwidth_tree;
  356. gint offset, next_offset, tokenlen;
  357. proto_item *item;
  358. gboolean unit_is_kbs = FALSE;
  359. gboolean unit_is_bps = FALSE;
  360. offset = 0;
  361. sdp_bandwidth_tree = proto_item_add_subtree(ti, ett_sdp_bandwidth);
  362. /* find the modifier */
  363. next_offset = tvb_find_guint8(tvb, offset, -1, ':');
  364. if (next_offset == -1)
  365. return;
  366. tokenlen = next_offset - offset;
  367. item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_modifier, tvb, offset,
  368. tokenlen, ENC_ASCII|ENC_NA);
  369. if (tvb_strneql(tvb, offset, "CT", 2) == 0) {
  370. proto_item_append_text(item, " [Conference Total(total bandwidth of all RTP sessions)]");
  371. unit_is_kbs = TRUE;
  372. } else if (tvb_strneql(tvb, offset, "AS", 2) == 0) {
  373. proto_item_append_text(item, " [Application Specific (RTP session bandwidth)]");
  374. unit_is_kbs = TRUE;
  375. } else if (tvb_strneql(tvb, offset, "TIAS", 4) == 0) {
  376. proto_item_append_text(item, " [Transport Independent Application Specific maximum]");
  377. unit_is_bps = TRUE;
  378. }
  379. offset = next_offset + 1;
  380. item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_value, tvb, offset, -1,
  381. ENC_ASCII|ENC_NA);
  382. if (unit_is_kbs == TRUE)
  383. proto_item_append_text(item, " kb/s");
  384. if (unit_is_bps == TRUE)
  385. proto_item_append_text(item, " b/s");
  386. }
  387. static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti) {
  388. proto_tree *sdp_time_tree;
  389. gint offset, next_offset, tokenlen;
  390. offset = 0;
  391. sdp_time_tree = proto_item_add_subtree(ti, ett_sdp_time);
  392. /* get start time */
  393. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  394. if (next_offset == -1)
  395. return;
  396. tokenlen = next_offset - offset;
  397. proto_tree_add_item(sdp_time_tree, hf_time_start, tvb, offset, tokenlen,
  398. ENC_ASCII|ENC_NA);
  399. /* get stop time */
  400. offset = next_offset + 1;
  401. proto_tree_add_item(sdp_time_tree, hf_time_stop, tvb, offset, -1, ENC_ASCII|ENC_NA);
  402. }
  403. static void dissect_sdp_repeat_time(tvbuff_t *tvb, proto_item* ti) {
  404. proto_tree *sdp_repeat_time_tree;
  405. gint offset, next_offset, tokenlen;
  406. offset = 0;
  407. sdp_repeat_time_tree = proto_item_add_subtree(ti, ett_sdp_time);
  408. /* get interval */
  409. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  410. if (next_offset == -1)
  411. return;
  412. tokenlen = next_offset - offset;
  413. proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_interval, tvb,
  414. offset, tokenlen, ENC_ASCII|ENC_NA);
  415. /* get duration */
  416. offset = next_offset + 1;
  417. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  418. if (next_offset == -1)
  419. return;
  420. tokenlen = next_offset - offset;
  421. proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_duration, tvb,
  422. offset, tokenlen, ENC_ASCII|ENC_NA);
  423. /* get offsets */
  424. do{
  425. offset = next_offset +1;
  426. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  427. if (next_offset != -1) {
  428. tokenlen = next_offset - offset;
  429. } else {
  430. tokenlen = -1; /* end of tvbuff */
  431. }
  432. proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_offset,
  433. tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  434. } while (next_offset != -1);
  435. }
  436. static void
  437. dissect_sdp_timezone(tvbuff_t *tvb, proto_item* ti) {
  438. proto_tree* sdp_timezone_tree;
  439. gint offset, next_offset, tokenlen;
  440. offset = 0;
  441. sdp_timezone_tree = proto_item_add_subtree(ti, ett_sdp_timezone);
  442. do{
  443. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  444. if (next_offset == -1)
  445. break;
  446. tokenlen = next_offset - offset;
  447. proto_tree_add_item(sdp_timezone_tree, hf_timezone_time, tvb, offset,
  448. tokenlen, ENC_ASCII|ENC_NA);
  449. offset = next_offset + 1;
  450. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  451. if (next_offset != -1) {
  452. tokenlen = next_offset - offset;
  453. } else {
  454. tokenlen = -1; /* end of tvbuff */
  455. }
  456. proto_tree_add_item(sdp_timezone_tree, hf_timezone_offset, tvb, offset,
  457. tokenlen, ENC_ASCII|ENC_NA);
  458. offset = next_offset + 1;
  459. } while (next_offset != -1);
  460. }
  461. static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti) {
  462. proto_tree *sdp_encryption_key_tree;
  463. gint offset, next_offset, tokenlen;
  464. offset = 0;
  465. sdp_encryption_key_tree = proto_item_add_subtree(ti, ett_sdp_encryption_key);
  466. next_offset = tvb_find_guint8(tvb, offset, -1, ':');
  467. if (next_offset == -1)
  468. return;
  469. tokenlen = next_offset - offset;
  470. proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_type,
  471. tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  472. offset = next_offset + 1;
  473. proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_data,
  474. tvb, offset, -1, ENC_ASCII|ENC_NA);
  475. }
  476. static void dissect_key_mgmt(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) {
  477. gchar *data_p = NULL;
  478. gchar *prtcl_id = NULL;
  479. gint len;
  480. tvbuff_t *keymgmt_tvb;
  481. gboolean found_match = FALSE;
  482. proto_tree *key_tree;
  483. gint next_offset;
  484. gint offset = 0;
  485. gint tokenlen;
  486. key_tree = proto_item_add_subtree(ti, ett_sdp_key_mgmt);
  487. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  488. if (next_offset == -1)
  489. return;
  490. tokenlen = next_offset - offset;
  491. prtcl_id = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  492. proto_tree_add_item(key_tree, hf_key_mgmt_prtcl_id, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  493. offset = next_offset + 1;
  494. len = tvb_length_remaining(tvb, offset);
  495. if (len < 0)
  496. return;
  497. data_p = tvb_get_ephemeral_string(tvb, offset, len);
  498. keymgmt_tvb = base64_to_tvb(tvb, data_p);
  499. add_new_data_source(pinfo, keymgmt_tvb, "Key Management Data");
  500. if ((prtcl_id != NULL) && (key_mgmt_dissector_table != NULL)) {
  501. found_match = dissector_try_string(key_mgmt_dissector_table,
  502. prtcl_id,
  503. keymgmt_tvb, pinfo,
  504. key_tree);
  505. }
  506. if (found_match) {
  507. proto_item *ti2 = proto_tree_add_item(key_tree, hf_key_mgmt_data,
  508. keymgmt_tvb, 0, -1, ENC_NA);
  509. PROTO_ITEM_SET_HIDDEN(ti2);
  510. } else {
  511. proto_tree_add_item(key_tree, hf_key_mgmt_data,
  512. keymgmt_tvb, 0, -1, ENC_NA);
  513. }
  514. }
  515. static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) {
  516. proto_tree *sdp_session_attribute_tree;
  517. gint offset, next_offset, tokenlen;
  518. guint8 *field_name;
  519. offset = 0;
  520. sdp_session_attribute_tree = proto_item_add_subtree(ti,
  521. ett_sdp_session_attribute);
  522. next_offset = tvb_find_guint8(tvb, offset, -1, ':');
  523. if (next_offset == -1)
  524. return;
  525. tokenlen = next_offset - offset;
  526. proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_field,
  527. tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  528. field_name = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  529. offset = next_offset + 1;
  530. if (strcmp((char*)field_name, "ipbcp") == 0) {
  531. offset = tvb_pbrk_guint8(tvb, offset, -1,"0123456789", NULL);
  532. if (offset == -1)
  533. return;
  534. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  535. if (next_offset == -1)
  536. return;
  537. tokenlen = next_offset - offset;
  538. proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_version, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  539. offset = tvb_pbrk_guint8(tvb, offset, -1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ", NULL);
  540. if (offset == -1)
  541. return;
  542. tokenlen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
  543. if (tokenlen == -1)
  544. return;
  545. proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_type, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  546. } else if (strcmp((char*)field_name, "key-mgmt") == 0) {
  547. tvbuff_t *key_tvb;
  548. proto_item *key_ti;
  549. key_tvb = tvb_new_subset_remaining(tvb, offset);
  550. key_ti = proto_tree_add_item(sdp_session_attribute_tree, hf_key_mgmt_att_value, key_tvb, 0, -1, ENC_ASCII|ENC_NA);
  551. dissect_key_mgmt(key_tvb, pinfo, key_ti);
  552. } else {
  553. proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_value,
  554. tvb, offset, -1, ENC_ASCII|ENC_NA);
  555. }
  556. }
  557. /* Dissect media description */
  558. static void
  559. dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
  560. transport_info_t *transport_info, disposable_media_info_t *media_info) {
  561. proto_tree *sdp_media_tree;
  562. gint offset, next_offset, tokenlen, idx;
  563. guint8 *media_format;
  564. offset = 0;
  565. /* Create tree for media session */
  566. sdp_media_tree = proto_item_add_subtree(ti, ett_sdp_media);
  567. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  568. if (next_offset == -1)
  569. return;
  570. tokenlen = next_offset - offset;
  571. /* Type of media session */
  572. proto_tree_add_item(sdp_media_tree, hf_media_media, tvb, offset, tokenlen,
  573. ENC_ASCII|ENC_NA);
  574. media_info->media_type = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
  575. offset = next_offset + 1;
  576. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  577. if (next_offset == -1)
  578. return;
  579. tokenlen = next_offset - offset;
  580. next_offset = tvb_find_guint8(tvb, offset, tokenlen, '/');
  581. if (next_offset != -1) {
  582. tokenlen = next_offset - offset;
  583. /* Save port info */
  584. media_info->media_port[media_info->media_count] = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
  585. proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
  586. atoi((char*)tvb_get_ephemeral_string(tvb, offset, tokenlen)));
  587. offset = next_offset + 1;
  588. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  589. if (next_offset == -1)
  590. return;
  591. tokenlen = next_offset - offset;
  592. proto_tree_add_item(sdp_media_tree, hf_media_portcount, tvb, offset,
  593. tokenlen, ENC_ASCII|ENC_NA);
  594. offset = next_offset + 1;
  595. } else {
  596. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  597. if (next_offset == -1)
  598. return;
  599. tokenlen = next_offset - offset;
  600. /* Save port info */
  601. media_info->media_port[media_info->media_count] = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
  602. /* XXX Remember Port */
  603. proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
  604. atoi((char*)tvb_get_ephemeral_string(tvb, offset, tokenlen)));
  605. offset = next_offset + 1;
  606. }
  607. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  608. if ( next_offset == -1)
  609. return;
  610. tokenlen = next_offset - offset;
  611. /* Save port protocol */
  612. media_info->media_proto[media_info->media_count] = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
  613. /* XXX Remember Protocol */
  614. proto_tree_add_item(sdp_media_tree, hf_media_proto, tvb, offset, tokenlen,
  615. ENC_ASCII|ENC_NA);
  616. do {
  617. offset = next_offset + 1;
  618. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  619. if (next_offset == -1) {
  620. tokenlen = tvb_length_remaining(tvb, offset); /* End of tvbuff */
  621. if (tokenlen == 0)
  622. break; /* Nothing more left */
  623. } else {
  624. tokenlen = next_offset - offset;
  625. }
  626. if (!strcmp(media_info->media_proto[media_info->media_count], "RTP/AVP")) {
  627. media_format = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  628. proto_tree_add_string(sdp_media_tree, hf_media_format, tvb, offset,
  629. tokenlen, val_to_str_ext((guint32)strtoul((char*)media_format, NULL, 10), &rtp_payload_type_vals_ext, "%u"));
  630. idx = transport_info->media[transport_info->media_count].pt_count;
  631. transport_info->media[transport_info->media_count].pt[idx] = (gint32)strtol((char*)media_format, NULL, 10);
  632. if (idx < (SDP_MAX_RTP_PAYLOAD_TYPES-1))
  633. transport_info->media[transport_info->media_count].pt_count++;
  634. } else {
  635. proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, offset,
  636. tokenlen, ENC_ASCII|ENC_NA);
  637. }
  638. } while (next_offset != -1);
  639. /* XXX Dissect traffic to "Port" as "Protocol"
  640. * Remember this Port/Protocol pair so we can tear it down again later
  641. * Actually, it's harder than that:
  642. * We need to find out the address of the other side first and it
  643. * looks like that info can be found in SIP headers only.
  644. */
  645. }
  646. static tvbuff_t *
  647. ascii_bytes_to_tvb(tvbuff_t *tvb, packet_info *pinfo, gint len, gchar *msg)
  648. {
  649. guint8 *buf = (guint8 *)wmem_alloc(pinfo->pool, 10240);
  650. /* arbitrary maximum length */
  651. if (len < 20480) {
  652. int i;
  653. tvbuff_t *bytes_tvb;
  654. /* first, skip to where the encoded pdu starts, this is
  655. the first hex digit after the '=' char.
  656. */
  657. while (1) {
  658. if ((*msg == 0) || (*msg == '\n')) {
  659. return NULL;
  660. }
  661. if (*msg == '=') {
  662. msg++;
  663. break;
  664. }
  665. msg++;
  666. }
  667. while (1) {
  668. if ((*msg == 0) || (*msg == '\n')) {
  669. return NULL;
  670. }
  671. if ( ((*msg >= '0') && (*msg <= '9'))
  672. || ((*msg >= 'a') && (*msg <= 'f'))
  673. || ((*msg >= 'A') && (*msg <= 'F'))) {
  674. break;
  675. }
  676. msg++;
  677. }
  678. i = 0;
  679. while (((*msg >= '0') && (*msg <= '9'))
  680. || ((*msg >= 'a') && (*msg <= 'f'))
  681. || ((*msg >= 'A') && (*msg <= 'F'))) {
  682. int val;
  683. if ((*msg >= '0') && (*msg <= '9')) {
  684. val = (*msg)-'0';
  685. } else if ((*msg >= 'a') && (*msg <= 'f')) {
  686. val = (*msg)-'a'+10;
  687. } else if ((*msg >= 'A') && (*msg <= 'F')) {
  688. val = (*msg)-'A'+10;
  689. } else {
  690. return NULL;
  691. }
  692. val <<= 4;
  693. msg++;
  694. if ((*msg >= '0') && (*msg <= '9')) {
  695. val |= (*msg)-'0';
  696. } else if ((*msg >= 'a') && (*msg <= 'f')) {
  697. val |= (*msg)-'a'+10;
  698. } else if ((*msg >= 'A') && (*msg <= 'F')) {
  699. val |= (*msg)-'A'+10;
  700. } else {
  701. return NULL;
  702. }
  703. msg++;
  704. buf[i] = (guint8)val;
  705. i++;
  706. }
  707. if (i == 0) {
  708. return NULL;
  709. }
  710. bytes_tvb = tvb_new_child_real_data(tvb, buf, i, i);
  711. add_new_data_source(pinfo, bytes_tvb, "ASCII bytes to tvb");
  712. return bytes_tvb;
  713. }
  714. return NULL;
  715. }
  716. /* Annex X Profiles and levels definition */
  717. static const value_string h263_profile_vals[] =
  718. {
  719. { 0, "Baseline Profile" },
  720. { 1, "H.320 Coding Efficiency Version 2 Backward-Compatibility Profile" },
  721. { 2, "Version 1 Backward-Compatibility Profile" },
  722. { 3, "Version 2 Interactive and Streaming Wireless Profile" },
  723. { 4, "Version 3 Interactive and Streaming Wireless Profile" },
  724. { 5, "Conversational High Compression Profile" },
  725. { 6, "Conversational Internet Profile" },
  726. { 7, "Conversational Interlace Profile" },
  727. { 8, "High Latency Profile" },
  728. { 0, NULL },
  729. };
  730. /* RFC 4629 The level are described in table X.2 of H.263 annex X */
  731. static const value_string h263_level_vals[] =
  732. {
  733. { 10, "QCIF (176 x 144), 1 x 64Kb/s" },
  734. { 20, "CIF (352 x 288), 2 x 64Kb/s" },
  735. { 30, "CIF (352 x 288), 6 x 64Kb/s" },
  736. { 40, "CIF (352 x 288), 32 x 64Kb/s" },
  737. { 45, "QCIF (176 x144) support of CPFMT, 2 x 64Kb/s" },
  738. { 50, "CIF (352 x 288) support of CPFMT, 64 x 64Kb/s" },
  739. { 60, "CPFMT: 720 x 288 support of CPFMT, 128 x 64Kb/s" },
  740. { 70, "CPFMT: 720 x 576 support of CPFMT, 256 x 64Kb/s" },
  741. { 0, NULL },
  742. };
  743. static const value_string h264_packetization_mode_vals[] =
  744. {
  745. { 0, "Single NAL mode" },
  746. { 1, "Non-interleaved mode" },
  747. { 2, "Interleaved mode" },
  748. { 0, NULL },
  749. };
  750. /*
  751. * TODO: Make this a more generic routine to dissect fmtp parameters depending on media types
  752. */
  753. static void
  754. decode_sdp_fmtp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, gint tokenlen, char *mime_type) {
  755. gint next_offset;
  756. gint end_offset;
  757. guint8 *field_name;
  758. gchar *format_specific_parameter;
  759. proto_item *item;
  760. tvbuff_t * volatile data_tvb;
  761. end_offset = offset + tokenlen;
  762. #if 0
  763. proto_tree_add_text(tree, tvb, offset, tokenlen, "Debug; Analysed string: '%s'",
  764. tvb_get_ephemeral_string(tvb, offset, tokenlen));
  765. #endif
  766. /* Look for an '=' within this value - this may indicate that there is a
  767. profile-level-id parameter to find if the MPEG4 media type is in use */
  768. next_offset = tvb_find_guint8(tvb, offset, -1, '=');
  769. if (next_offset == -1)
  770. {
  771. /* Give up (and avoid exception) if '=' not found */
  772. return;
  773. }
  774. /* Find the name of the parameter */
  775. tokenlen = next_offset - offset;
  776. field_name = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  777. #if 0
  778. proto_tree_add_text(tree, tvb, offset, tokenlen, "Debug; MIMEtype '%s'Parameter name: '%s'", mime_type, field_name); */
  779. #endif
  780. offset = next_offset;
  781. /* Dissect the MPEG4 profile-level-id parameter if present */
  782. if ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "MP4V-ES") == 0)) {
  783. if (strcmp((char*)field_name, "profile-level-id") == 0) {
  784. offset++;
  785. tokenlen = end_offset - offset;
  786. format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  787. item = proto_tree_add_uint(tree, hf_sdp_fmtp_mpeg4_profile_level_id, tvb, offset, tokenlen,
  788. (guint32)strtol((char*)format_specific_parameter, NULL, 10));
  789. PROTO_ITEM_SET_GENERATED(item);
  790. } else if (strcmp((char*)field_name, "config") == 0) {
  791. /* String including "=" */
  792. tokenlen = end_offset - offset;
  793. format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  794. /* ascii_bytes_to_tvb requires the "=" to be in the buffer */
  795. data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
  796. if (mp4ves_handle && data_tvb) {
  797. dissect_mp4ves_config(data_tvb, pinfo, tree);
  798. }
  799. }
  800. }
  801. /* Dissect the H263-2000 profile parameter if present */
  802. if (((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-2000") == 0)) ||
  803. ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-1998") == 0))) {
  804. if (strcmp((char*)field_name, "profile") == 0) {
  805. offset++;
  806. tokenlen = end_offset - offset;
  807. format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  808. item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_profile, tvb, offset, tokenlen,
  809. (guint32)strtol((char*)format_specific_parameter, NULL, 10));
  810. PROTO_ITEM_SET_GENERATED(item);
  811. } else if (strcmp((char*)field_name, "level") == 0) {
  812. offset++;
  813. tokenlen = end_offset - offset;
  814. format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  815. item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_level, tvb, offset, tokenlen,
  816. (guint32)strtol((char*)format_specific_parameter, NULL, 10));
  817. PROTO_ITEM_SET_GENERATED(item);
  818. }
  819. }
  820. /* Dissect the H264 profile-level-id parameter
  821. * RFC 3984:
  822. * A base16 [6] (hexadecimal) representation of
  823. * the following three bytes in the sequence
  824. * parameter set NAL unit specified in [1]: 1)
  825. * profile_idc, 2) a byte herein referred to as
  826. * profile-iop, composed of the values of
  827. * constraint_set0_flag, constraint_set1_flag,
  828. * constraint_set2_flag, and reserved_zero_5bits
  829. * in bit-significance order, starting from the
  830. * most significant bit, and 3) level_idc.
  831. */
  832. if ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H264") == 0)) {
  833. if (strcmp(field_name, "profile-level-id") == 0) {
  834. int length = 0;
  835. /* Length includes "=" as it's required by ascii_bytes_to_tvb()*/
  836. tokenlen = end_offset - offset;
  837. format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  838. data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
  839. if (!data_tvb) {
  840. proto_tree_add_text(tree, tvb, offset, tokenlen, "Could not convert '%s' to 3 bytes", format_specific_parameter);
  841. return;
  842. }
  843. length = tvb_length(data_tvb);
  844. if (length == 3) {
  845. if (h264_handle && data_tvb) {
  846. dissect_h264_profile(data_tvb, pinfo, tree);
  847. }
  848. } else {
  849. item = proto_tree_add_text(tree, tvb, offset, tokenlen, "Incorrectly coded, must be three bytes");
  850. PROTO_ITEM_SET_GENERATED(item);
  851. }
  852. } else if (strcmp(field_name, "packetization-mode") == 0) {
  853. offset++;
  854. tokenlen = end_offset - offset;
  855. format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  856. item = proto_tree_add_uint(tree, hf_sdp_h264_packetization_mode, tvb, offset, tokenlen,
  857. (guint32)strtol((char*)format_specific_parameter, NULL, 10));
  858. PROTO_ITEM_SET_GENERATED(item);
  859. } else if (strcmp(field_name, "sprop-parameter-sets") == 0) {
  860. /* The value of the parameter is the
  861. base64 [6] representation of the initial
  862. parameter set NAL units as specified in
  863. sections 7.3.2.1 and 7.3.2.2 of [1]. The
  864. parameter sets are conveyed in decoding order,
  865. and no framing of the parameter set NAL units
  866. takes place. A comma is used to separate any
  867. pair of parameter sets in the list.
  868. */
  869. gchar *data_p = NULL;
  870. gint comma_offset;
  871. /* Move past '=' */
  872. offset++;
  873. comma_offset = tvb_find_guint8(tvb, offset, -1, ',');
  874. if (comma_offset != -1) {
  875. tokenlen = comma_offset - offset;
  876. } else {
  877. tokenlen = end_offset - offset;
  878. }
  879. data_p = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  880. proto_tree_add_text(tree, tvb, offset, tokenlen, "NAL unit 1 string: %s", data_p);
  881. /* proto_tree_add_text(tree, tvb, offset, tokenlen, "String %s", data_p); */
  882. data_tvb = base64_to_tvb(tvb, data_p);
  883. add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets");
  884. if (h264_handle && data_tvb) {
  885. TRY {
  886. dissect_h264_nal_unit(data_tvb, pinfo, tree);
  887. }
  888. CATCH_NONFATAL_ERRORS {
  889. show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
  890. }
  891. ENDTRY;
  892. if (comma_offset != -1) {
  893. /* Second NAL unit */
  894. offset = comma_offset +1;
  895. tokenlen = end_offset - offset;
  896. data_p = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  897. proto_tree_add_text(tree, tvb, offset, tokenlen, "NAL unit 2 string: %s", data_p);
  898. data_tvb = base64_to_tvb(tvb, data_p);
  899. add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets 2");
  900. dissect_h264_nal_unit(data_tvb, pinfo, tree);
  901. }
  902. }
  903. }
  904. }
  905. }
  906. typedef struct {
  907. const char *name;
  908. } sdp_names_t;
  909. #define SDP_RTPMAP 1
  910. #define SDP_FMTP 2
  911. #define SDP_PATH 3
  912. #define SDP_H248_ITEM 4
  913. #define SDP_CRYPTO 5
  914. #define SDP_SPRTMAP 6
  915. static const sdp_names_t sdp_media_attribute_names[] = {
  916. { "Unknown-name"}, /* 0 Pad so that the real headers start at index 1 */
  917. { "rtpmap"}, /* 1 */
  918. { "fmtp"}, /* 2 */
  919. { "path"}, /* 3 */
  920. { "h248item"}, /* 4 */
  921. { "crypto"}, /* 5 */
  922. { "sprt"}, /* 6 */
  923. };
  924. static gint find_sdp_media_attribute_names(tvbuff_t *tvb, int offset, guint len)
  925. {
  926. guint i;
  927. for (i = 1; i < array_length(sdp_media_attribute_names); i++) {
  928. if ((len == strlen(sdp_media_attribute_names[i].name)) &&
  929. (tvb_strncaseeql(tvb, offset, sdp_media_attribute_names[i].name, len) == 0))
  930. return i;
  931. }
  932. return -1;
  933. }
  934. static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item * ti, int length,
  935. transport_info_t *transport_info, disposable_media_info_t *media_info) {
  936. proto_tree *sdp_media_attribute_tree, *parameter_item;
  937. proto_item *fmtp_item, *media_format_item, *parameter_tree;
  938. proto_tree *fmtp_tree;
  939. gint offset, next_offset, tokenlen, n, colon_offset;
  940. /*??guint8 *field_name;*/
  941. guint8 *payload_type;
  942. guint8 *attribute_value;
  943. gint *key;
  944. guint8 pt;
  945. gint sdp_media_attrbute_code;
  946. const char *msrp_res = "msrp://";
  947. const char *h324ext_h223lcparm = "h324ext/h223lcparm";
  948. gboolean has_more_pars = TRUE;
  949. tvbuff_t *h245_tvb;
  950. guint8 master_key_length = 0, master_salt_length = 0;
  951. encoding_name_and_rate_t *encoding_name_and_rate;
  952. offset = 0;
  953. /* Create attribute tree */
  954. sdp_media_attribute_tree = proto_item_add_subtree(ti,
  955. ett_sdp_media_attribute);
  956. /* Find end of field */
  957. colon_offset = tvb_find_guint8(tvb, offset, -1, ':');
  958. if (colon_offset == -1)
  959. return;
  960. /* Attribute field name is token before ':' */
  961. tokenlen = colon_offset - offset;
  962. proto_tree_add_item(sdp_media_attribute_tree,
  963. hf_media_attribute_field,
  964. tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  965. /*??field_name = tvb_get_ephemeral_string(tvb, offset, tokenlen);*/
  966. sdp_media_attrbute_code = find_sdp_media_attribute_names(tvb, offset, tokenlen);
  967. /* Skip colon */
  968. offset = colon_offset + 1;
  969. /* skip leading wsp */
  970. offset = tvb_skip_wsp(tvb, offset, tvb_length_remaining(tvb, offset));
  971. /* Value is the remainder of the line */
  972. attribute_value = tvb_get_ephemeral_string(tvb, offset, tvb_length_remaining(tvb, offset));
  973. /*********************************************/
  974. /* Special parsing for some field name types */
  975. switch (sdp_media_attrbute_code) {
  976. case SDP_RTPMAP:
  977. /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
  978. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  979. if (next_offset == -1)
  980. return;
  981. tokenlen = next_offset - offset;
  982. proto_tree_add_item(sdp_media_attribute_tree, hf_media_format, tvb,
  983. offset, tokenlen, ENC_ASCII|ENC_NA);
  984. payload_type = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  985. offset = next_offset + 1;
  986. next_offset = tvb_find_guint8(tvb, offset, -1, '/');
  987. if (next_offset == -1) {
  988. return;
  989. }
  990. tokenlen = next_offset - offset;
  991. proto_tree_add_item(sdp_media_attribute_tree, hf_media_encoding_name, tvb,
  992. offset, tokenlen, ENC_ASCII|ENC_NA);
  993. pt = atoi((char*)payload_type);
  994. if (pt >= SDP_NO_OF_PT) {
  995. return; /* Invalid */
  996. }
  997. key = se_new(gint);
  998. *key = (gint)strtol((char*)payload_type, NULL, 10);
  999. transport_info->encoding_name[pt] = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
  1000. next_offset = next_offset + 1;
  1001. offset = next_offset;
  1002. while (length-1 >= next_offset) {
  1003. if (!g_ascii_isdigit(tvb_get_guint8(tvb, next_offset)))
  1004. break;
  1005. next_offset++;
  1006. }
  1007. tokenlen = next_offset - offset;
  1008. proto_tree_add_item(sdp_media_attribute_tree, hf_media_sample_rate, tvb,
  1009. offset, tokenlen, ENC_ASCII|ENC_NA);
  1010. transport_info->sample_rate[pt] = atoi(tvb_get_ephemeral_string(tvb, offset, tokenlen));
  1011. /* As per RFC2327 it is possible to have multiple Media Descriptions ("m=").
  1012. For example:
  1013. a=rtpmap:101 G726-32/8000
  1014. m=audio 49170 RTP/AVP 0 97
  1015. a=rtpmap:97 telephone-event/8000
  1016. m=audio 49172 RTP/AVP 97 101
  1017. a=rtpmap:97 G726-24/8000
  1018. The Media attributes ("a="s) after the "m=" only apply for that "m=".
  1019. If there is an "a=" before the first "m=", that attribute applies for
  1020. all the session (all the "m="s).
  1021. */
  1022. /* so, if this "a=" appear before any "m=", we add it to all the dynamic
  1023. * hash tables
  1024. */
  1025. if (transport_info->media_count < 0) {
  1026. for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
  1027. encoding_name_and_rate = se_new(encoding_name_and_rate_t);
  1028. encoding_name_and_rate->encoding_name = se_strdup(transport_info->encoding_name[pt]);
  1029. encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
  1030. if (n == 0) {
  1031. g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
  1032. key, encoding_name_and_rate);
  1033. } else { /* we create a new key and encoding_name to assign to the other hash tables */
  1034. gint *key2;
  1035. key2 = se_new(gint);
  1036. *key2 = (gint)strtol((char*)payload_type, NULL, 10);
  1037. g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
  1038. key2, encoding_name_and_rate);
  1039. }
  1040. }
  1041. return;
  1042. /* if the "a=" is after an "m=", only apply to this "m=" */
  1043. } else
  1044. /* in case there is an overflow in SDP_MAX_RTP_CHANNELS, we keep always the last "m=" */
  1045. encoding_name_and_rate = se_new(encoding_name_and_rate_t);
  1046. encoding_name_and_rate->encoding_name = se_strdup(transport_info->encoding_name[pt]);
  1047. encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
  1048. g_hash_table_insert(transport_info->media[ transport_info->media_count ].rtp_dyn_payload,
  1049. key, encoding_name_and_rate);
  1050. break;
  1051. case SDP_FMTP:
  1052. if (sdp_media_attribute_tree) {
  1053. guint8 media_format;
  1054. /* Reading the Format parameter(fmtp) */
  1055. /* Skip leading space, if any */
  1056. offset = tvb_skip_wsp(tvb, offset, tvb_length_remaining(tvb, offset));
  1057. /* Media format extends to the next space */
  1058. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  1059. if (next_offset == -1)
  1060. return;
  1061. tokenlen = next_offset - offset;
  1062. media_format_item = proto_tree_add_item(sdp_media_attribute_tree,
  1063. hf_media_format, tvb, offset,
  1064. tokenlen, ENC_ASCII|ENC_NA);
  1065. media_format = atoi((char*)tvb_get_ephemeral_string(tvb, offset, tokenlen));
  1066. if (media_format >= SDP_NO_OF_PT) {
  1067. return; /* Invalid */
  1068. }
  1069. /* Append encoding name to format if known */
  1070. proto_item_append_text(media_format_item, " [%s]",
  1071. transport_info->encoding_name[media_format]);
  1072. #if 0 /* XXX: ?? */
  1073. payload_type = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  1074. #endif
  1075. /* Move offset past the payload type */
  1076. offset = next_offset + 1;
  1077. while (has_more_pars == TRUE) {
  1078. next_offset = tvb_find_guint8(tvb, offset, -1, ';');
  1079. offset = tvb_skip_wsp(tvb, offset, tvb_length_remaining(tvb, offset));
  1080. if (next_offset == -1) {
  1081. has_more_pars = FALSE;
  1082. next_offset= tvb_length(tvb);
  1083. }
  1084. /* There are at least 2 - add the first parameter */
  1085. tokenlen = next_offset - offset;
  1086. fmtp_item = proto_tree_add_item(sdp_media_attribute_tree,
  1087. hf_media_format_specific_parameter, tvb,
  1088. offset, tokenlen, ENC_ASCII|ENC_NA);
  1089. fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp);
  1090. decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen,
  1091. transport_info->encoding_name[media_format]);
  1092. /* Move offset past "; " and onto firts char */
  1093. offset = next_offset + 1;
  1094. }
  1095. }
  1096. break;
  1097. case SDP_PATH:
  1098. /* msrp attributes that contain address needed for conversation */
  1099. /* RFC 4975
  1100. * path = path-label ":" path-list
  1101. * path-label = "path"
  1102. * path-list= MSRP-URI *(SP MSRP-URI)
  1103. * MSRP-URI = msrp-scheme "://" authority
  1104. * ["/" session-id] ";" transport *( ";" URI-parameter)
  1105. * ; authority as defined in RFC3986
  1106. *
  1107. * msrp-scheme = "msrp" / "msrps"
  1108. * RFC 3986
  1109. * The authority component is preceded by a double slash ("//") and is terminated by
  1110. * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by
  1111. * the end of the URI.
  1112. */
  1113. /* Check for "msrp://" */
  1114. if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0) {
  1115. int address_offset, port_offset, port_end_offset;
  1116. /* Address starts here */
  1117. address_offset = offset + (int)strlen(msrp_res);
  1118. /* Port is after next ':' */
  1119. port_offset = tvb_find_guint8(tvb, address_offset, -1, ':');
  1120. /* Check if port is present if not skipp */
  1121. if (port_offset!= -1) {
  1122. /* Port ends with '/' */
  1123. port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/');
  1124. if (port_end_offset == -1) {
  1125. /* No "/" look for the ";" */
  1126. port_end_offset = tvb_find_guint8(tvb, port_offset, -1, ';');;
  1127. }
  1128. /* Attempt to convert address */
  1129. if (inet_pton(AF_INET,
  1130. (char*)tvb_get_ephemeral_string(tvb, address_offset, port_offset-address_offset),
  1131. &media_info->msrp_ipaddr) > 0) {
  1132. /* Get port number */
  1133. media_info->msrp_port_number = atoi((char*)tvb_get_ephemeral_string(tvb, port_offset + 1, port_end_offset - port_offset - 1));
  1134. /* Set flag so this info can be used */
  1135. media_info->msrp_transport_address_set = TRUE;
  1136. }
  1137. }
  1138. }
  1139. break;
  1140. case SDP_H248_ITEM:
  1141. /* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/
  1142. if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0) {
  1143. /* A.5.1.3 H.223 Logical channel parameters
  1144. * This property indicates the H.245
  1145. * H223LogicalChannelsParameters structure encoded by applying the PER specified in
  1146. * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined
  1147. * in ITU-T Rec. H.248.15 is used.
  1148. */
  1149. gint len;
  1150. asn1_ctx_t actx;
  1151. len = (gint)strlen(attribute_value);
  1152. h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, len, attribute_value);
  1153. /* arbitrary maximum length */
  1154. /* should go through a handle, however, the two h245 entry
  1155. points are different, one is over tpkt and the other is raw
  1156. */
  1157. if (h245_tvb) {
  1158. asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
  1159. dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx,
  1160. sdp_media_attribute_tree,
  1161. hf_SDPh223LogicalChannelParameters);
  1162. }
  1163. }
  1164. break;
  1165. case SDP_CRYPTO:
  1166. /* http://tools.ietf.org/html/rfc4568
  1167. * 9.1. Generic "Crypto" Attribute Grammar
  1168. *
  1169. * The ABNF grammar for the crypto attribute is defined below:
  1170. *
  1171. * "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params
  1172. * *(1*WSP session-param)
  1173. *
  1174. * tag = 1*9DIGIT
  1175. * crypto-suite = 1*(ALPHA / DIGIT / "_")
  1176. *
  1177. * key-params = key-param *(";" key-param)
  1178. * key-param = key-method ":" key-info
  1179. * key-method = "inline" / key-method-ext
  1180. * key-method-ext = 1*(ALPHA / DIGIT / "_")
  1181. * key-info = 1*(%x21-3A / %x3C-7E) ; visible (printing) chars
  1182. * ; except semi-colon
  1183. * session-param = 1*(VCHAR) ; visible (printing) characters
  1184. *
  1185. * where WSP, ALPHA, DIGIT, and VCHAR are defined in [RFC4234].
  1186. *
  1187. */
  1188. /* We are at the first colon */
  1189. /* tag */
  1190. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  1191. if(next_offset==-1){
  1192. /* XXX Add expert item? */
  1193. return;
  1194. }
  1195. tokenlen = next_offset - offset;
  1196. proto_tree_add_uint(sdp_media_attribute_tree, hf_sdp_crypto_tag, tvb, offset, tokenlen,
  1197. atoi((char*)tvb_get_ephemeral_string(tvb, offset, tokenlen)));
  1198. offset = next_offset + 1;
  1199. /* crypto-suite */
  1200. next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
  1201. if(next_offset==-1){
  1202. /* XXX Add expert item? */
  1203. return;
  1204. }
  1205. tokenlen = next_offset - offset;
  1206. parameter_item = proto_tree_add_item(sdp_media_attribute_tree, hf_sdp_crypto_crypto_suite,
  1207. tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  1208. if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_80", tokenlen) == 0) {
  1209. /* XXX This may only work in simple cases */
  1210. if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
  1211. transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
  1212. transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
  1213. /* number of octets used for the Auth Tag in the RTP payload */
  1214. transport_info->auth_tag_len = 10;
  1215. }
  1216. master_key_length = 16; /* 128 bits = 16 octets */
  1217. master_salt_length = 14; /* 112 bits = 14 octets */
  1218. } else if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_32", tokenlen) == 0) {
  1219. /* XXX This may only work in simple cases */
  1220. if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
  1221. transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
  1222. transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
  1223. /* number of octets used for the Auth Tag in the RTP payload */
  1224. transport_info->auth_tag_len = 4;
  1225. }
  1226. master_key_length = 16; /* 128 bits = 16 octets */
  1227. master_salt_length = 14; /* 112 bits = 14 octets */
  1228. } else if (tvb_strncaseeql(tvb, offset, "F8_128_HMAC_SHA1_80", tokenlen) == 0) {
  1229. if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
  1230. /* XXX This may only work in simple cases */
  1231. transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_F8;
  1232. transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
  1233. /* number of octets used for the Auth Tag in the RTP payload */
  1234. transport_info->auth_tag_len = 10;
  1235. }
  1236. master_key_length = 16; /* 128 bits = 16 octets */
  1237. master_salt_length = 14; /* 112 bits = 14 octets */
  1238. }
  1239. offset = next_offset + 1;
  1240. /* key-params */
  1241. while (has_more_pars == TRUE) {
  1242. int param_end_offset;
  1243. tvbuff_t *key_salt_tvb;
  1244. gchar *data_p = NULL;
  1245. param_end_offset = tvb_find_guint8(tvb, offset, -1, ';');
  1246. if (param_end_offset == -1) {
  1247. has_more_pars = FALSE;
  1248. param_end_offset = tvb_length(tvb);
  1249. }
  1250. /* key-method or key-method-ext */
  1251. next_offset = tvb_find_guint8(tvb, offset, -1, ':');
  1252. if (next_offset == -1) {
  1253. expert_add_info(pinfo, parameter_item, &ei_sdp_invalid_key_param);
  1254. break;
  1255. }
  1256. if (tvb_strncaseeql(tvb, offset, "inline", next_offset-offset) == 0) {
  1257. parameter_item = proto_tree_add_text(sdp_media_attribute_tree,
  1258. tvb, offset, param_end_offset-offset, "Key parameters");
  1259. parameter_tree = proto_item_add_subtree(parameter_item, ett_sdp_crypto_key_parameters);
  1260. /* XXX only for SRTP? */
  1261. /* srtp-key-info = key-salt ["|" lifetime] ["|" mki] */
  1262. offset = next_offset +1;
  1263. next_offset = tvb_find_guint8(tvb, offset, -1, '|');
  1264. if (next_offset == -1) {
  1265. tokenlen = param_end_offset - offset;
  1266. } else {
  1267. tokenlen = next_offset - offset;
  1268. }
  1269. data_p = tvb_get_ephemeral_string(tvb, offset, tokenlen);
  1270. key_salt_tvb = base64_to_tvb(tvb, data_p);
  1271. add_new_data_source(pinfo, key_salt_tvb, "Key_Salt_tvb");
  1272. if (master_key_length != 0) {
  1273. proto_tree_add_text(parameter_tree, tvb, offset, tokenlen, "Key and Salt");
  1274. proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_key,
  1275. key_salt_tvb, 0, master_key_length, ENC_ASCII|ENC_NA);
  1276. proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_salt,
  1277. key_salt_tvb, master_key_length, master_salt_length, ENC_ASCII|ENC_NA);
  1278. } else {
  1279. proto_tree_add_text(parameter_tree, key_salt_tvb, 0, -1, "Key and Salt");
  1280. }
  1281. /* ["|" lifetime] ["|" mki] are optional */
  1282. if (next_offset != -1) {
  1283. offset = next_offset + 1;
  1284. next_offset = tvb_find_guint8(tvb, offset, -1, '|');
  1285. if(next_offset == -1){
  1286. if(next_offset < param_end_offset){
  1287. next_offset = param_end_offset;
  1288. }
  1289. }
  1290. if (next_offset != -1) {
  1291. /*lifetime = ["2^"] 1*(DIGIT) ; see section 6.1 for "2^" */
  1292. tokenlen = next_offset - offset;
  1293. proto_tree_add_item(parameter_tree, hf_sdp_crypto_lifetime,
  1294. tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  1295. offset = next_offset + 1;
  1296. }
  1297. /* mki = mki-value ":" mki-length
  1298. *
  1299. * mki-value = 1*DIGIT
  1300. */
  1301. if(offset>param_end_offset){
  1302. next_offset = -1;
  1303. }else{
  1304. next_offset = tvb_find_guint8(tvb, offset, -1, ':');
  1305. }
  1306. if (next_offset != -1) {
  1307. tokenlen = next_offset - offset;
  1308. proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  1309. offset = next_offset + 1;
  1310. /* mki-length = 1*3DIGIT ; range 1..128. */
  1311. next_offset = param_end_offset;
  1312. tokenlen = next_offset - offset;
  1313. /* This will not work if more than one parameter */
  1314. /* number of octets used for the MKI in the RTP payload */
  1315. transport_info->mki_len = atoi((char*)tvb_get_ephemeral_string(tvb, offset, tokenlen));
  1316. proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki_length,
  1317. tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
  1318. }
  1319. }
  1320. offset = param_end_offset;
  1321. } else {
  1322. break;
  1323. }
  1324. }
  1325. break;
  1326. default:
  1327. /* No special treatment for values of this attribute type, just add as one item. */
  1328. proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
  1329. tvb, offset, -1, ENC_ASCII|ENC_NA);
  1330. break;
  1331. }
  1332. }
  1333. static void
  1334. call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, int length,
  1335. transport_info_t *transport_info, disposable_media_info_t *media_info) {
  1336. if (hf == hf_owner) {
  1337. dissect_sdp_owner(tvb, ti);
  1338. } else if (hf == hf_connection_info) {
  1339. dissect_sdp_connection_info(tvb, ti, media_info);
  1340. } else if (hf == hf_bandwidth) {
  1341. dissect_sdp_bandwidth(tvb, ti);
  1342. } else if (hf == hf_time) {
  1343. dissect_sdp_time(tvb, ti);
  1344. } else if (hf == hf_repeat_time) {
  1345. dissect_sdp_repeat_time(tvb, ti);
  1346. } else if (hf == hf_timezone) {
  1347. dissect_sdp_timezone(tvb, ti);
  1348. } else if (hf == hf_encryption_key) {
  1349. dissect_sdp_encryption_key(tvb, ti);
  1350. } else if (hf == hf_session_attribute) {
  1351. dissect_sdp_session_attribute(tvb, pinfo, ti);
  1352. } else if (hf == hf_media) {
  1353. dissect_sdp_media(tvb, ti, transport_info, media_info);
  1354. } else if (hf == hf_media_attribute) {
  1355. dissect_sdp_media_attribute(tvb, pinfo, ti, length, transport_info, media_info);
  1356. }
  1357. }
  1358. static void
  1359. convert_disposable_media(transport_info_t* transport_info, disposable_media_info_t* media_info,
  1360. gint start_transport_info_count)
  1361. {
  1362. gint8 n, i, transport_index;
  1363. guint proto_bitmask;
  1364. for (n = 0; (n < media_info->media_count) && (n+start_transport_info_count < SDP_MAX_RTP_CHANNELS); n++)
  1365. {
  1366. transport_index = n+start_transport_info_count;
  1367. if (media_info->media_port[n] != NULL) {
  1368. transport_info->media_port[transport_index] = (int)strtol(media_info->media_port[n], NULL, 10);
  1369. }
  1370. if (media_info->media_proto[n] != NULL) {
  1371. /* Check if media protocol is RTP
  1372. * and stream decoding is enabled in preferences
  1373. */
  1374. if (global_sdp_establish_conversation) {
  1375. proto_bitmask = 0;
  1376. /* Check if media protocol is RTP */
  1377. if (!strcmp(media_info->media_proto[n],"RTP/AVP")) {
  1378. transport_info->proto_bitmask[transport_index] |= SDP_RTP_PROTO;
  1379. proto_bitmask |= SDP_RTP_PROTO;
  1380. }
  1381. /* Check if media protocol is SRTP */
  1382. else if (!strcmp(media_info->media_proto[n],"RTP/SAVP")) {
  1383. transport_info->proto_bitmask[transport_index] |= SDP_SRTP_PROTO;
  1384. proto_bitmask |= SDP_SRTP_PROTO;
  1385. }
  1386. /* Check if media protocol is T38 */
  1387. else if ((!strcmp(media_info->media_proto[n],"UDPTL")) ||
  1388. (!strcmp(media_info->media_proto[n],"udptl"))) {
  1389. transport_info->proto_bitmask[transport_index] |= SDP_T38_PROTO;
  1390. proto_bitmask |= SDP_T38_PROTO;
  1391. }
  1392. /* Check if media protocol is MSRP/TCP */
  1393. else if (!strcmp(media_info->media_proto[n],"msrp/tcp")) {
  1394. transport_info->proto_bitmask[transport_index] |= SDP_MSRP_PROTO;
  1395. proto_bitmask |= SDP_MSRP_PROTO;
  1396. }
  1397. /* Check if media protocol is SPRT */
  1398. else if ((!strcmp(media_info->media_proto[n],"UDPSPRT")) ||
  1399. (!strcmp(media_info->media_proto[n],"udpsprt"))) {
  1400. transport_info->proto_bitmask[transport_index] |= SDP_SPRT_PROTO;
  1401. proto_bitmask |= SDP_SPRT_PROTO;
  1402. }
  1403. if (transport_info->media_port[transport_index] == 0) {
  1404. /* This will disable any ports that share the media */
  1405. for (i = 0; i < transport_index; i++) {
  1406. if (proto_bitmask & transport_info->proto_bitmask[i]) {
  1407. transport_info->media_port[i] = 0;
  1408. }
  1409. }
  1410. }
  1411. }
  1412. }
  1413. if ((media_info->connection_address != NULL) &&
  1414. (media_info->connection_type != NULL)) {
  1415. if (strcmp(media_info->connection_type, "IP4") == 0) {
  1416. transport_info->src_addr[transport_index].data = se_alloc(4);
  1417. if (inet_pton(AF_INET, media_info->connection_address, (void*)transport_info->src_addr[transport_index].data) > 0) {
  1418. /* connection_address could be converted to a valid ipv4 address*/
  1419. transport_info->proto_bitmask[transport_index] |= SDP_IPv4;
  1420. transport_info->src_addr[transport_index].type = AT_IPv4;
  1421. transport_info->src_addr[transport_index].len = 4;
  1422. }
  1423. } else if (strcmp(media_info->connection_type, "IP6") == 0) {
  1424. transport_info->src_addr[transport_index].data = se_alloc(16);
  1425. if (inet_pton(AF_INET6, media_info->connection_address, (void*)transport_info->src_addr[transport_index].data) > 0) {
  1426. /* connection_address could be converted to a valid ipv6 address*/
  1427. transport_info->proto_bitmask[transport_index] |= SDP_IPv6;
  1428. transport_info->src_addr[transport_index].type = AT_IPv6;
  1429. transport_info->src_addr[transport_index].len = 16;
  1430. }
  1431. }
  1432. }
  1433. /* MSRP uses addresses discovered in attribute
  1434. rather than connection information of media session line */
  1435. if ((transport_info->proto_bitmask[transport_index] & SDP_MSRP_PROTO) &&
  1436. (transport_info->proto_bitmask[transport_index] & SDP_MSRP_IPv4) &&
  1437. msrp_handle) {
  1438. transport_info->src_addr[transport_index].type = AT_IPv4;
  1439. transport_info->src_addr[transport_index].len = 4;
  1440. transport_info->src_addr[transport_index].data = se_memdup(media_info->msrp_ipaddr, 4);
  1441. transport_info->media_port[transport_index] = media_info->msrp_port_number;
  1442. }
  1443. if ((media_info->media_type != NULL) && (strcmp(media_info->media_type, "video") == 0)) {
  1444. transport_info->proto_bitmask[transport_index] |= SDP_VIDEO;
  1445. }
  1446. }
  1447. }
  1448. void
  1449. setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type exchange_type, int request_frame)
  1450. {
  1451. gint offset = 0, next_offset, n;
  1452. int linelen;
  1453. gboolean in_media_description = FALSE;
  1454. guchar type, delim;
  1455. const int tokenoffset = 2;
  1456. int hf = -1;
  1457. gint start_transport_info_count = 0;
  1458. transport_info_t* transport_info = NULL;
  1459. disposable_media_info_t media_info;
  1460. struct srtp_info *srtp_info = NULL;
  1461. /* Only do this once during first pass */
  1462. if (pinfo->fd->flags.visited)
  1463. return;
  1464. memset(&media_info, 0, sizeof(media_info));
  1465. if (request_frame != 0)
  1466. transport_info = (transport_info_t*)se_tree_lookup32( sdp_transport_reqs, request_frame );
  1467. if (transport_info == NULL) {
  1468. transport_info = se_new0(transport_info_t);
  1469. transport_info->media_count = -1;
  1470. for (n = 0; n < SDP_NO_OF_PT; n++) {
  1471. transport_info->encoding_name[n] = (char*)UNKNOWN_ENCODING;
  1472. }
  1473. for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
  1474. transport_info->media[n].rtp_dyn_payload =
  1475. g_hash_table_new(g_int_hash, g_int_equal);
  1476. transport_info->media[n].set_rtp = FALSE;
  1477. }
  1478. if (request_frame != 0)
  1479. se_tree_insert32(sdp_transport_reqs, request_frame, (void *)transport_info);
  1480. }
  1481. if (exchange_type != SDP_EXCHANGE_OFFER)
  1482. se_tree_insert32(sdp_transport_rsps, pinfo->fd->num, (void *)transport_info);
  1483. /* Offer has already been answered or rejected and hash tables freed, so
  1484. * don't try to add to it
  1485. * XXX - Need to support "modified offers" */
  1486. if ((transport_info->sdp_status == SDP_EXCHANGE_ANSWER_REJECT) ||
  1487. (transport_info->sdp_status == SDP_EXCHANGE_ANSWER_ACCEPT))
  1488. return;
  1489. if (transport_info->media_count > 0)
  1490. start_transport_info_count = transport_info->media_count;
  1491. /*
  1492. * Show the SDP message a line at a time.
  1493. */
  1494. while (tvb_reported_length_remaining(tvb, offset) > 0) {
  1495. /*
  1496. * Find the end of the line.
  1497. */
  1498. linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
  1499. /*
  1500. * Line must contain at least e.g. "v=".
  1501. */
  1502. if (linelen < 2)
  1503. break;
  1504. type = tvb_get_guint8(tvb, offset);
  1505. delim = tvb_get_guint8(tvb, offset + 1);
  1506. if (delim != '=') {
  1507. offset = next_offset;
  1508. continue;
  1509. }
  1510. /*
  1511. * Attributes. Only care about ones that affect the transport. Ignore others.
  1512. */
  1513. switch (type) {
  1514. case 'c':
  1515. hf = hf_connection_info;
  1516. break;
  1517. case 'm':
  1518. hf = hf_media;
  1519. /* Increase the count of media channels, but don't walk off the end of the arrays. */
  1520. if (((transport_info->media_count < 0) && (in_media_description == FALSE)) || (transport_info->media_count < (SDP_MAX_RTP_CHANNELS-1)))
  1521. transport_info->media_count++;
  1522. if (in_media_description && (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1)))
  1523. media_info.media_count++;
  1524. in_media_description = TRUE;
  1525. break;
  1526. case 'a':
  1527. if (in_media_description) {
  1528. hf = hf_media_attribute;
  1529. } else {
  1530. hf = hf_session_attribute;
  1531. }
  1532. break;
  1533. default:
  1534. hf = hf_unknown;
  1535. break;
  1536. }
  1537. if (hf != hf_unknown)
  1538. {
  1539. call_sdp_subdissector(tvb_new_subset(tvb, offset + tokenoffset,
  1540. linelen - tokenoffset,
  1541. linelen - tokenoffset),
  1542. pinfo,
  1543. hf, NULL, linelen-tokenoffset, transport_info, &media_info);
  1544. }
  1545. offset = next_offset;
  1546. }
  1547. if (in_media_description) {
  1548. /* Increase the count of media channels, but don't walk off the end of the arrays. */
  1549. if (transport_info->media_count < (SDP_MAX_RTP_CHANNELS-1))
  1550. transport_info->media_count++;
  1551. if (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
  1552. media_info.media_count++;
  1553. }
  1554. /* Take all of the collected strings and convert them into something permanent
  1555. * for the life of the capture
  1556. */
  1557. convert_disposable_media(transport_info, &media_info, start_transport_info_count);
  1558. /* We have a successful negotiation, apply data to their respective protocols */
  1559. if ((exchange_type == SDP_EXCHANGE_ANSWER_ACCEPT) &&
  1560. (transport_info->sdp_status == SDP_EXCHANGE_OFFER)) {
  1561. for (n = 0; n <= transport_info->media_count; n++) {
  1562. guint32 current_rtp_port = 0;
  1563. /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
  1564. if ((transport_info->media_port[n] != 0) &&
  1565. (transport_info->proto_bitmask[n] & (SDP_RTP_PROTO|SDP_SRTP_PROTO)) &&
  1566. (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6))) {
  1567. if (rtp_handle) {
  1568. if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
  1569. srtp_info = se_new0(struct srtp_info);
  1570. if (transport_info->encryption_algorithm != SRTP_ENC_ALG_NOT_SET) {
  1571. srtp_info->encryption_algorithm = transport_info->encryption_algorithm;
  1572. srtp_info->auth_algorithm = transport_info->auth_algorithm;
  1573. srtp_info->mki_len = transport_info->mki_len;
  1574. srtp_info->auth_tag_len = transport_info->auth_tag_len;
  1575. }
  1576. srtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
  1577. (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
  1578. transport_info->media[n].rtp_dyn_payload, srtp_info);
  1579. } else {
  1580. rtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
  1581. (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
  1582. transport_info->media[n].rtp_dyn_payload);
  1583. }
  1584. transport_info->media[n].set_rtp = TRUE;
  1585. /* SPRT might use the same port... */
  1586. current_rtp_port = transport_info->media_port[n];
  1587. }
  1588. if (rtcp_handle) {
  1589. if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
  1590. srtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num, srtp_info);
  1591. } else {
  1592. rtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num);
  1593. }
  1594. }
  1595. }
  1596. /* add SPRT conversation */
  1597. if ((transport_info->proto_bitmask[n] & SDP_SPRT_PROTO) &&
  1598. (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6)) &&
  1599. (sprt_handle)) {
  1600. if (transport_info->media_port[n] == 0 && current_rtp_port) {
  1601. sprt_add_address(pinfo, &transport_info->src_addr[n], current_rtp_port,
  1602. 0, "SDP", pinfo->fd->num); /* will use same port as RTP */
  1603. } else {
  1604. sprt_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
  1605. }
  1606. }
  1607. /* Add t38 conversation, if available and only if no rtp */
  1608. if ((transport_info->media_port[n] != 0) &&
  1609. !transport_info->media[n].set_rtp &&
  1610. (transport_info->proto_bitmask[n] & SDP_T38_PROTO) &&
  1611. (transport_info->proto_bitmask[n] & SDP_IPv4) &&
  1612. t38_handle) {
  1613. t38_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
  1614. }
  1615. /* Add MSRP conversation. Uses addresses discovered in attribute
  1616. rather than connection information of media session line
  1617. (already handled in media conversion) */
  1618. if ((transport_info->proto_bitmask[n] & SDP_MSRP_PROTO) &&
  1619. (transport_info->proto_bitmask[n] & SDP_MSRP_IPv4) &&
  1620. msrp_handle) {
  1621. msrp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], "SDP", pinfo->fd->num);
  1622. }
  1623. /* Free the hash table if we did't assigned it to a conv use it */
  1624. if (!transport_info->media[n].set_rtp)
  1625. {
  1626. rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
  1627. transport_info->media[n].rtp_dyn_payload = NULL;
  1628. }
  1629. }
  1630. /* Free the remaining hash tables not used */
  1631. if (transport_info->media_count == -1)
  1632. {
  1633. for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++)
  1634. {
  1635. if (!transport_info->media[n].set_rtp)
  1636. {
  1637. rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
  1638. transport_info->media[n].rtp_dyn_payload = NULL;
  1639. }
  1640. }
  1641. }
  1642. else
  1643. {
  1644. for (n = transport_info->media_count; n < SDP_MAX_RTP_CHANNELS; n++)
  1645. {
  1646. if (!transport_info->media[n].set_rtp)
  1647. {
  1648. rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
  1649. transport_info->media[n].rtp_dyn_payload = NULL;
  1650. }
  1651. }
  1652. }
  1653. transport_info->sdp_status = SDP_EXCHANGE_ANSWER_ACCEPT;
  1654. } else if ((exchange_type == SDP_EXCHANGE_ANSWER_REJECT) &&
  1655. (transport_info->sdp_status != SDP_EXCHANGE_ANSWER_REJECT)){
  1656. /* Free the hash tables, since they won't be put to use */
  1657. for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++)
  1658. {
  1659. if (!transport_info->media[n].set_rtp)
  1660. {
  1661. rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
  1662. transport_info->media[n].rtp_dyn_payload = NULL;
  1663. }
  1664. }
  1665. transport_info->sdp_status = SDP_EXCHANGE_ANSWER_REJECT;
  1666. }
  1667. }
  1668. void setup_sdp_transport_resend(int current_frame, int request_frame)
  1669. {
  1670. transport_info_t* transport_info = NULL;
  1671. if (request_frame != 0) {
  1672. transport_info = (transport_info_t*)se_tree_lookup32( sdp_transport_reqs, request_frame );
  1673. if (transport_info != NULL) {
  1674. se_tree_insert32(sdp_transport_reqs, current_frame, (void *)transport_info);
  1675. }
  1676. }
  1677. }
  1678. static void
  1679. dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  1680. {
  1681. proto_tree *sdp_tree;
  1682. proto_item *ti, *sub_ti;
  1683. gint offset = 0, next_offset, n, i;
  1684. int linelen;
  1685. gboolean in_media_description;
  1686. guchar type, delim;
  1687. int datalen, tokenoffset, hf = -1;
  1688. char *string;
  1689. transport_info_t local_transport_info;
  1690. transport_info_t* transport_info = NULL;
  1691. disposable_media_info_t media_info;
  1692. sdp_packet_info *sdp_pi;
  1693. struct srtp_info *srtp_info = NULL;
  1694. /* Initialise packet info for passing to tap */
  1695. sdp_pi = ep_new(sdp_packet_info);
  1696. sdp_pi->summary_str[0] = '\0';
  1697. if (!pinfo->fd->flags.visited) {
  1698. transport_info = (transport_info_t*)se_tree_lookup32( sdp_transport_reqs, pinfo->fd->num );
  1699. if (transport_info == NULL) {
  1700. /* Can't find it in the requests, make sure it's not a response */
  1701. transport_info = (transport_info_t*)se_tree_lookup32( sdp_transport_rsps, pinfo->fd->num );
  1702. }
  1703. }
  1704. if (transport_info == NULL) {
  1705. transport_info = &local_transport_info;
  1706. }
  1707. /* Initialize local transport info */
  1708. memset(&local_transport_info, 0, sizeof(local_transport_info));
  1709. local_transport_info.media_count = -1;
  1710. for (n = 0; n < SDP_NO_OF_PT; n++) {
  1711. local_transport_info.encoding_name[n] = (char*)UNKNOWN_ENCODING;
  1712. }
  1713. for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
  1714. local_transport_info.media[n].rtp_dyn_payload =
  1715. g_hash_table_new(g_int_hash, g_int_equal);
  1716. local_transport_info.media[n].set_rtp = FALSE;
  1717. }
  1718. memset(&media_info, 0, sizeof(media_info));
  1719. /*
  1720. * As RFC 2327 says, "SDP is purely a format for session
  1721. * description - it does not incorporate a transport protocol,
  1722. * and is intended to use different transport protocols as
  1723. * appropriate including the Session Announcement Protocol,
  1724. * Session Initiation Protocol, Real-Time Streaming Protocol,
  1725. * electronic mail using the MIME extensions, and the
  1726. * Hypertext Transport Protocol."
  1727. *
  1728. * We therefore don't set the protocol or info columns;
  1729. * instead, we append to them, so that we don't erase
  1730. * what the protocol inside which the SDP stuff resides
  1731. * put there.
  1732. */
  1733. col_append_str(pinfo->cinfo, COL_PROTOCOL, "/SDP");
  1734. /* XXX: Needs description.
  1735. * Putting with session description in info col is redundant when it's in the
  1736. * protocol col in my opinion, commenting it out for now 2012-10-09. Remove if no one complains.
  1737. * If some one want it consider " ,with SDP"
  1738. */
  1739. /*col_append_str(pinfo->cinfo, COL_INFO, ", with session description");*/
  1740. ti = proto_tree_add_item(tree, proto_sdp, tvb, offset, -1, ENC_NA);
  1741. sdp_tree = proto_item_add_subtree(ti, ett_sdp);
  1742. /*
  1743. * Show the SDP message a line at a time.
  1744. */
  1745. in_media_description = FALSE;
  1746. while (tvb_reported_length_remaining(tvb, offset) > 0) {
  1747. /*
  1748. * Find the end of the line.
  1749. */
  1750. linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
  1751. /*
  1752. * Line must contain at least e.g. "v=".
  1753. */
  1754. if (linelen < 2)
  1755. break;
  1756. type = tvb_get_guint8(tvb, offset);
  1757. delim = tvb_get_guint8(tvb, offset + 1);
  1758. if (delim != '=') {
  1759. proto_item *ti2 = proto_tree_add_item(sdp_tree, hf_invalid, tvb, offset, linelen, ENC_ASCII|ENC_NA);
  1760. expert_add_info(pinfo, ti2, &ei_sdp_invalid_line);
  1761. offset = next_offset;
  1762. continue;
  1763. }
  1764. /*
  1765. * Attributes.
  1766. */
  1767. switch (type) {
  1768. case 'v':
  1769. hf = hf_protocol_version;
  1770. break;
  1771. case 'o':
  1772. hf = hf_owner;
  1773. break;
  1774. case 's':
  1775. hf = hf_session_name;
  1776. break;
  1777. case 'i':
  1778. if (in_media_description) {
  1779. hf = hf_media_title;
  1780. } else {
  1781. hf = hf_session_info;
  1782. }
  1783. break;
  1784. case 'u':
  1785. hf = hf_uri;
  1786. break;
  1787. case 'e':
  1788. hf = hf_email;
  1789. break;
  1790. case 'p':
  1791. hf = hf_phone;
  1792. break;
  1793. case 'c':
  1794. hf = hf_connection_info;
  1795. break;
  1796. case 'b':
  1797. hf = hf_bandwidth;
  1798. break;
  1799. case 't':
  1800. hf = hf_time;
  1801. break;
  1802. case 'r':
  1803. hf = hf_repeat_time;
  1804. break;
  1805. case 'm':
  1806. hf = hf_media;
  1807. /* Increase the count of media channels, but don't walk off the end of the arrays. */
  1808. if (local_transport_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
  1809. local_transport_info.media_count++;
  1810. if (in_media_description && (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1)))
  1811. media_info.media_count++;
  1812. in_media_description = TRUE;
  1813. break;
  1814. case 'k':
  1815. hf = hf_encryption_key;
  1816. break;
  1817. case 'a':
  1818. if (in_media_description) {
  1819. hf = hf_media_attribute;
  1820. } else {
  1821. hf = hf_session_attribute;
  1822. }
  1823. break;
  1824. case 'z':
  1825. hf = hf_timezone;
  1826. break;
  1827. default:
  1828. hf = hf_unknown;
  1829. break;
  1830. }
  1831. tokenoffset = 2;
  1832. if (hf == hf_unknown)
  1833. tokenoffset = 0;
  1834. string = (char*)tvb_get_ephemeral_string(tvb, offset + tokenoffset,
  1835. linelen - tokenoffset);
  1836. sub_ti = proto_tree_add_string(sdp_tree, hf, tvb, offset, linelen,
  1837. string);
  1838. call_sdp_subdissector(tvb_new_subset(tvb, offset + tokenoffset,
  1839. linelen - tokenoffset,
  1840. linelen - tokenoffset),
  1841. pinfo,
  1842. hf, sub_ti, linelen-tokenoffset,
  1843. &local_transport_info, &media_info);
  1844. offset = next_offset;
  1845. }
  1846. if (in_media_description) {
  1847. /* Increase the count of media channels, but don't walk off the end of the arrays. */
  1848. if (local_transport_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
  1849. local_transport_info.media_count++;
  1850. if (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
  1851. media_info.media_count++;
  1852. }
  1853. /* Take all of the collected strings and convert them into something permanent
  1854. * for the life of the capture
  1855. */
  1856. if (transport_info == &local_transport_info)
  1857. convert_disposable_media(transport_info, &media_info, 0);
  1858. for (n = 0; n < local_transport_info.media_count; n++)
  1859. {
  1860. /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
  1861. /* XXX - This is a placeholder for higher layer protocols that haven't implemented the proper
  1862. * OFFER/ANSWER functionality using setup_sdp_transport(). Once all of the higher layers
  1863. * use setup_sdp_transport(), this should be removed
  1864. */
  1865. guint32 current_rtp_port = 0;
  1866. if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
  1867. (transport_info->media_port[n] != 0) &&
  1868. (transport_info->proto_bitmask[n] & (SDP_RTP_PROTO|SDP_SRTP_PROTO)) &&
  1869. (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6))) {
  1870. if (rtp_handle) {
  1871. if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
  1872. srtp_info = se_new0(struct srtp_info);
  1873. if (transport_info->encryption_algorithm != SRTP_ENC_ALG_NOT_SET) {
  1874. srtp_info->encryption_algorithm = transport_info->encryption_algorithm;
  1875. srtp_info->auth_algorithm = transport_info->auth_algorithm;
  1876. srtp_info->mki_len = transport_info->mki_len;
  1877. srtp_info->auth_tag_len = transport_info->auth_tag_len;
  1878. }
  1879. srtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
  1880. (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
  1881. transport_info->media[n].rtp_dyn_payload, srtp_info);
  1882. } else {
  1883. rtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
  1884. (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
  1885. transport_info->media[n].rtp_dyn_payload);
  1886. }
  1887. transport_info->media[n].set_rtp = TRUE;
  1888. /* SPRT might use the same port... */
  1889. current_rtp_port = transport_info->media_port[n];
  1890. }
  1891. if (rtcp_handle) {
  1892. if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
  1893. srtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num, srtp_info);
  1894. } else {
  1895. rtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num);
  1896. }
  1897. }
  1898. }
  1899. /* add SPRT conversation */
  1900. /* XXX - more placeholder functionality */
  1901. if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
  1902. (transport_info->proto_bitmask[n] & SDP_SPRT_PROTO) &&
  1903. (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6)) &&
  1904. (sprt_handle)) {
  1905. if (transport_info->media_port[n] == 0 && current_rtp_port) {
  1906. sprt_add_address(pinfo, &transport_info->src_addr[n], current_rtp_port,
  1907. 0, "SDP", pinfo->fd->num); /* will use same port as RTP */
  1908. } else {
  1909. sprt_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
  1910. }
  1911. }
  1912. /* Add t38 conversation, if available and only if no rtp */
  1913. /* XXX - more placeholder functionality */
  1914. if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
  1915. (transport_info->media_port[n] != 0) &&
  1916. !transport_info->media[n].set_rtp &&
  1917. (transport_info->proto_bitmask[n] & SDP_T38_PROTO) &&
  1918. (transport_info->proto_bitmask[n] & SDP_IPv4) &&
  1919. t38_handle) {
  1920. t38_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
  1921. }
  1922. /* Add MSRP conversation. Uses addresses discovered in attribute
  1923. rather than connection information of media session line */
  1924. /* XXX - more placeholder functionality */
  1925. if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
  1926. (transport_info->proto_bitmask[n] & SDP_MSRP_PROTO) &&
  1927. (transport_info->proto_bitmask[n] & SDP_MSRP_IPv4) &&
  1928. msrp_handle) {
  1929. msrp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], "SDP", pinfo->fd->num);
  1930. }
  1931. if (local_transport_info.media_port[n] != 0) {
  1932. /* Create the RTP summary str for the Voip Call analysis.
  1933. * XXX - Currently this is based only on the current packet
  1934. */
  1935. for (i = 0; i < local_transport_info.media[n].pt_count; i++)
  1936. {
  1937. /* if the payload type is dynamic (96 to 127), check the hash table to add the desc in the SDP summary */
  1938. if ((local_transport_info.media[n].pt[i] >= 96) && (local_transport_info.media[n].pt[i] <= 127)) {
  1939. encoding_name_and_rate_t *encoding_name_and_rate_pt =
  1940. (encoding_name_and_rate_t *)g_hash_table_lookup(
  1941. local_transport_info.media[n].rtp_dyn_payload,
  1942. &local_transport_info.media[n].pt[i]);
  1943. if (encoding_name_and_rate_pt) {
  1944. if (strlen(sdp_pi->summary_str))
  1945. g_strlcat(sdp_pi->summary_str, " ", 50);
  1946. g_strlcat(sdp_pi->summary_str, encoding_name_and_rate_pt->encoding_name, 50);
  1947. } else {
  1948. char num_pt[10];
  1949. g_snprintf(num_pt, 10, "%u", local_transport_info.media[n].pt[i]);
  1950. if (strlen(sdp_pi->summary_str))
  1951. g_strlcat(sdp_pi->summary_str, " ", 50);
  1952. g_strlcat(sdp_pi->summary_str, num_pt, 50);
  1953. }
  1954. } else {
  1955. if (strlen(sdp_pi->summary_str))
  1956. g_strlcat(sdp_pi->summary_str, " ", 50);
  1957. g_strlcat(sdp_pi->summary_str,
  1958. val_to_str_ext(local_transport_info.media[n].pt[i], &rtp_payload_type_short_vals_ext, "%u"),
  1959. 50);
  1960. }
  1961. }
  1962. }
  1963. /* Free the hash table if we did't assigned it to a conv use it */
  1964. /* XXX - more placeholder functionality */
  1965. if ((transport_info == &local_transport_info) &&
  1966. !transport_info->media[n].set_rtp)
  1967. {
  1968. rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
  1969. transport_info->media[n].rtp_dyn_payload = NULL;
  1970. }
  1971. /* Create the T38 summary str for the Voip Call analysis
  1972. * XXX - Currently this is based only on the current packet
  1973. */
  1974. if ((local_transport_info.media_port[n] != 0) &&
  1975. (local_transport_info.proto_bitmask[n] & SDP_T38_PROTO)) {
  1976. if (strlen(sdp_pi->summary_str))
  1977. g_strlcat(sdp_pi->summary_str, " ", 50);
  1978. g_strlcat(sdp_pi->summary_str, "t38", 50);
  1979. }
  1980. }
  1981. /* Free the remainded hash tables not used */
  1982. /* XXX - more placeholder functionality */
  1983. if (transport_info == &local_transport_info) {
  1984. for (n = transport_info->media_count; n < SDP_MAX_RTP_CHANNELS; n++)
  1985. {
  1986. if (!transport_info->media[n].set_rtp)
  1987. {
  1988. rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
  1989. transport_info->media[n].rtp_dyn_payload = NULL;
  1990. }
  1991. }
  1992. }
  1993. datalen = tvb_length_remaining(tvb, offset);
  1994. if (datalen > 0) {
  1995. proto_tree_add_text(sdp_tree, tvb, offset, datalen, "Data (%d bytes)", datalen);
  1996. }
  1997. /* Report this packet to the tap */
  1998. tap_queue_packet(sdp_tap, pinfo, sdp_pi);
  1999. }
  2000. static void
  2001. sdp_init(void)
  2002. {
  2003. /* se_...() allocations are automatically cleared when a new capture starts,
  2004. so we should be safe to create the tree without any previous checks */
  2005. sdp_transport_reqs = se_tree_create_non_persistent(
  2006. EMEM_TREE_TYPE_RED_BLACK, "sdp_transport_reqs");
  2007. sdp_transport_rsps = se_tree_create_non_persistent(
  2008. EMEM_TREE_TYPE_RED_BLACK, "sdp_transport_rsps");
  2009. }
  2010. void
  2011. proto_register_sdp(void)
  2012. {
  2013. static hf_register_info hf[] = {
  2014. { &hf_protocol_version,
  2015. { "Session Description Protocol Version (v)", "sdp.version",
  2016. FT_STRING, BASE_NONE, NULL, 0x0,
  2017. NULL, HFILL }
  2018. },
  2019. { &hf_owner,
  2020. { "Owner/Creator, Session Id (o)",
  2021. "sdp.owner", FT_STRING, BASE_NONE, NULL,
  2022. 0x0, NULL, HFILL}
  2023. },
  2024. { &hf_session_name,
  2025. { "Session Name (s)", "sdp.session_name",
  2026. FT_STRING, BASE_NONE, NULL, 0x0,
  2027. NULL, HFILL }
  2028. },
  2029. { &hf_session_info,
  2030. { "Session Information (i)", "sdp.session_info",
  2031. FT_STRING, BASE_NONE, NULL, 0x0,
  2032. NULL, HFILL }
  2033. },
  2034. { &hf_uri,
  2035. { "URI of Description (u)", "sdp.uri",
  2036. FT_STRING, BASE_NONE, NULL, 0x0,
  2037. NULL, HFILL }
  2038. },
  2039. { &hf_email,
  2040. { "E-mail Address (e)", "sdp.email",
  2041. FT_STRING, BASE_NONE, NULL, 0x0,
  2042. "E-mail Address", HFILL }
  2043. },
  2044. { &hf_phone,
  2045. { "Phone Number (p)", "sdp.phone",
  2046. FT_STRING, BASE_NONE, NULL, 0x0,
  2047. NULL, HFILL }
  2048. },
  2049. { &hf_connection_info,
  2050. { "Connection Information (c)", "sdp.connection_info",
  2051. FT_STRING, BASE_NONE, NULL, 0x0,
  2052. NULL, HFILL }
  2053. },
  2054. { &hf_bandwidth,
  2055. { "Bandwidth Information (b)", "sdp.bandwidth",
  2056. FT_STRING, BASE_NONE, NULL, 0x0,
  2057. NULL, HFILL }
  2058. },
  2059. { &hf_timezone,
  2060. { "Time Zone Adjustments (z)", "sdp.timezone",
  2061. FT_STRING, BASE_NONE, NULL, 0x0,
  2062. NULL, HFILL }
  2063. },
  2064. { &hf_encryption_key,
  2065. { "Encryption Key (k)", "sdp.encryption_key",
  2066. FT_STRING, BASE_NONE, NULL, 0x0,
  2067. NULL, HFILL }
  2068. },
  2069. { &hf_session_attribute,
  2070. { "Session Attribute (a)", "sdp.session_attr",
  2071. FT_STRING, BASE_NONE, NULL, 0x0,
  2072. NULL, HFILL }
  2073. },
  2074. { &hf_media_attribute,
  2075. { "Media Attribute (a)", "sdp.media_attr",
  2076. FT_STRING, BASE_NONE, NULL, 0x0,
  2077. NULL, HFILL }
  2078. },
  2079. { &hf_time,
  2080. { "Time Description, active time (t)",
  2081. "sdp.time", FT_STRING, BASE_NONE, NULL,
  2082. 0x0, NULL, HFILL }
  2083. },
  2084. { &hf_repeat_time,
  2085. { "Repeat Time (r)", "sdp.repeat_time",
  2086. FT_STRING, BASE_NONE, NULL, 0x0,
  2087. NULL, HFILL }
  2088. },
  2089. { &hf_media,
  2090. { "Media Description, name and address (m)",
  2091. "sdp.media", FT_STRING, BASE_NONE, NULL,
  2092. 0x0, NULL, HFILL }
  2093. },
  2094. { &hf_media_title,
  2095. { "Media Title (i)", "sdp.media_title",
  2096. FT_STRING, BASE_NONE, NULL, 0x0,
  2097. "Media Title", HFILL }
  2098. },
  2099. { &hf_unknown,
  2100. { "Unknown", "sdp.unknown",
  2101. FT_STRING, BASE_NONE, NULL, 0x0,
  2102. NULL, HFILL }
  2103. },
  2104. { &hf_invalid,
  2105. { "Invalid line", "sdp.invalid",
  2106. FT_STRING, BASE_NONE, NULL, 0x0,
  2107. NULL, HFILL }
  2108. },
  2109. { &hf_owner_username,
  2110. { "Owner Username", "sdp.owner.username",
  2111. FT_STRING, BASE_NONE, NULL, 0x0,
  2112. NULL, HFILL }
  2113. },
  2114. { &hf_owner_sessionid,
  2115. { "Session ID", "sdp.owner.sessionid",
  2116. FT_STRING, BASE_NONE, NULL, 0x0,
  2117. NULL, HFILL }
  2118. },
  2119. { &hf_owner_version,
  2120. { "Session Version", "sdp.owner.version",
  2121. FT_STRING, BASE_NONE, NULL, 0x0,
  2122. NULL, HFILL }
  2123. },
  2124. { &hf_owner_network_type,
  2125. { "Owner Network Type", "sdp.owner.network_type",
  2126. FT_STRING, BASE_NONE, NULL, 0x0,
  2127. NULL, HFILL }
  2128. },
  2129. { &hf_owner_address_type,
  2130. { "Owner Address Type", "sdp.owner.address_type",
  2131. FT_STRING, BASE_NONE, NULL, 0x0,
  2132. NULL, HFILL }
  2133. },
  2134. { &hf_owner_address,
  2135. { "Owner Address", "sdp.owner.address",
  2136. FT_STRING, BASE_NONE, NULL, 0x0,
  2137. NULL, HFILL }
  2138. },
  2139. { &hf_connection_info_network_type,
  2140. { "Connection Network Type", "sdp.connection_info.network_type",
  2141. FT_STRING, BASE_NONE, NULL, 0x0,
  2142. NULL, HFILL }
  2143. },
  2144. { &hf_connection_info_address_type,
  2145. { "Connection Address Type", "sdp.connection_info.address_type",
  2146. FT_STRING, BASE_NONE, NULL, 0x0,
  2147. NULL, HFILL }
  2148. },
  2149. { &hf_connection_info_connection_address,
  2150. { "Connection Address", "sdp.connection_info.address",
  2151. FT_STRING, BASE_NONE, NULL, 0x0,
  2152. NULL, HFILL }
  2153. },
  2154. { &hf_connection_info_ttl,
  2155. { "Connection TTL", "sdp.connection_info.ttl",
  2156. FT_STRING, BASE_NONE, NULL, 0x0,
  2157. NULL, HFILL }
  2158. },
  2159. { &hf_connection_info_num_addr,
  2160. { "Connection Number of Addresses", "sdp.connection_info.num_addr",
  2161. FT_STRING, BASE_NONE, NULL, 0x0,
  2162. NULL, HFILL }
  2163. },
  2164. { &hf_bandwidth_modifier,
  2165. { "Bandwidth Modifier", "sdp.bandwidth.modifier",
  2166. FT_STRING, BASE_NONE, NULL, 0x0,
  2167. NULL, HFILL }
  2168. },
  2169. { &hf_bandwidth_value,
  2170. { "Bandwidth Value", "sdp.bandwidth.value",
  2171. FT_STRING, BASE_NONE, NULL, 0x0,
  2172. "Bandwidth Value (in kbits/s)", HFILL }
  2173. },
  2174. { &hf_time_start,
  2175. { "Session Start Time", "sdp.time.start",
  2176. FT_STRING, BASE_NONE, NULL, 0x0,
  2177. NULL, HFILL }
  2178. },
  2179. { &hf_time_stop,
  2180. { "Session Stop Time", "sdp.time.stop",
  2181. FT_STRING, BASE_NONE, NULL, 0x0,
  2182. NULL, HFILL }
  2183. },
  2184. { &hf_repeat_time_interval,
  2185. { "Repeat Interval", "sdp.repeat_time.interval",
  2186. FT_STRING, BASE_NONE, NULL, 0x0,
  2187. NULL, HFILL }
  2188. },
  2189. { &hf_repeat_time_duration,
  2190. { "Repeat Duration", "sdp.repeat_time.duration",
  2191. FT_STRING, BASE_NONE, NULL, 0x0,
  2192. NULL, HFILL }
  2193. },
  2194. { &hf_repeat_time_offset,
  2195. { "Repeat Offset", "sdp.repeat_time.offset",
  2196. FT_STRING, BASE_NONE, NULL, 0x0,
  2197. NULL, HFILL }
  2198. },
  2199. { &hf_timezone_time,
  2200. { "Timezone Time", "sdp.timezone.time",
  2201. FT_STRING, BASE_NONE, NULL, 0x0,
  2202. NULL, HFILL }
  2203. },
  2204. { &hf_timezone_offset,
  2205. { "Timezone Offset", "sdp.timezone.offset",
  2206. FT_STRING, BASE_NONE, NULL, 0x0,
  2207. NULL, HFILL }
  2208. },
  2209. { &hf_encryption_key_type,
  2210. { "Key Type", "sdp.encryption_key.type",
  2211. FT_STRING, BASE_NONE, NULL, 0x0,
  2212. NULL, HFILL }
  2213. },
  2214. { &hf_encryption_key_data,
  2215. { "Key Data", "sdp.encryption_key.data",
  2216. FT_STRING, BASE_NONE, NULL, 0x0,
  2217. NULL, HFILL }
  2218. },
  2219. { &hf_session_attribute_field,
  2220. { "Session Attribute Fieldname", "sdp.session_attr.field",
  2221. FT_STRING, BASE_NONE, NULL, 0x0,
  2222. NULL, HFILL }
  2223. },
  2224. { &hf_session_attribute_value,
  2225. { "Session Attribute Value", "sdp.session_attr.value",
  2226. FT_STRING, BASE_NONE, NULL, 0x0,
  2227. NULL, HFILL }
  2228. },
  2229. { &hf_media_media,
  2230. { "Media Type", "sdp.media.media",
  2231. FT_STRING, BASE_NONE, NULL, 0x0,
  2232. NULL, HFILL }
  2233. },
  2234. { &hf_media_port,
  2235. { "Media Port", "sdp.media.port",
  2236. FT_UINT16, BASE_DEC, NULL, 0x0,
  2237. NULL, HFILL }
  2238. },
  2239. { &hf_media_portcount,
  2240. { "Media Port Count", "sdp.media.portcount",
  2241. FT_STRING, BASE_NONE, NULL, 0x0,
  2242. NULL, HFILL }
  2243. },
  2244. { &hf_media_proto,
  2245. { "Media Protocol", "sdp.media.proto",
  2246. FT_STRING, BASE_NONE, NULL, 0x0,
  2247. NULL, HFILL }
  2248. },
  2249. { &hf_media_format,
  2250. { "Media Format", "sdp.media.format",
  2251. FT_STRING, BASE_NONE, NULL, 0x0,
  2252. NULL, HFILL }
  2253. },
  2254. { &hf_media_attribute_field,
  2255. { "Media Attribute Fieldname", "sdp.media_attribute.field",
  2256. FT_STRING, BASE_NONE, NULL, 0x0,
  2257. NULL, HFILL }
  2258. },
  2259. { &hf_media_attribute_value,
  2260. { "Media Attribute Value", "sdp.media_attribute.value",
  2261. FT_STRING, BASE_NONE, NULL, 0x0,
  2262. NULL, HFILL }
  2263. },
  2264. { &hf_media_encoding_name,
  2265. { "MIME Type", "sdp.mime.type",
  2266. FT_STRING, BASE_NONE, NULL, 0x0,
  2267. "SDP MIME Type", HFILL }
  2268. },
  2269. { &hf_media_sample_rate,
  2270. { "Sample Rate", "sdp.sample_rate",
  2271. FT_STRING, BASE_NONE, NULL, 0x0,
  2272. NULL, HFILL }
  2273. },
  2274. { &hf_media_format_specific_parameter,
  2275. { "Media format specific parameters", "sdp.fmtp.parameter",
  2276. FT_STRING, BASE_NONE, NULL, 0x0,
  2277. "Format specific parameter(fmtp)", HFILL }
  2278. },
  2279. { &hf_ipbcp_version,
  2280. { "IPBCP Protocol Version", "sdp.ipbcp.version",
  2281. FT_STRING, BASE_NONE, NULL, 0x0,
  2282. NULL, HFILL }
  2283. },
  2284. { &hf_ipbcp_type,
  2285. { "IPBCP Command Type", "sdp.ipbcp.command",
  2286. FT_STRING, BASE_NONE, NULL, 0x0,
  2287. NULL, HFILL }
  2288. },
  2289. {&hf_sdp_fmtp_mpeg4_profile_level_id,
  2290. { "Level Code", "sdp.fmtp.profile_level_id",
  2291. FT_UINT32, BASE_DEC, VALS(mp4ves_level_indication_vals), 0x0,
  2292. NULL, HFILL }
  2293. },
  2294. { &hf_sdp_fmtp_h263_profile,
  2295. { "Profile", "sdp.fmtp.h263profile",
  2296. FT_UINT32, BASE_DEC, VALS(h263_profile_vals), 0x0,
  2297. NULL, HFILL }
  2298. },
  2299. { &hf_sdp_fmtp_h263_level,
  2300. { "Level", "sdp.fmtp.h263level",
  2301. FT_UINT32, BASE_DEC, VALS(h263_level_vals), 0x0,
  2302. NULL, HFILL }
  2303. },
  2304. { &hf_sdp_h264_packetization_mode,
  2305. { "Packetization mode", "sdp.fmtp.h264_packetization_mode",
  2306. FT_UINT32, BASE_DEC, VALS(h264_packetization_mode_vals), 0x0,
  2307. NULL, HFILL }
  2308. },
  2309. { &hf_SDPh223LogicalChannelParameters,
  2310. { "h223LogicalChannelParameters", "sdp.h223LogicalChannelParameters",
  2311. FT_NONE, BASE_NONE, NULL, 0,
  2312. NULL, HFILL }
  2313. },
  2314. { &hf_key_mgmt_att_value,
  2315. { "Key Management", "sdp.key_mgmt",
  2316. FT_STRING, BASE_NONE, NULL, 0x0,
  2317. NULL, HFILL }
  2318. },
  2319. { &hf_key_mgmt_prtcl_id,
  2320. { "Key Management Protocol (kmpid)", "sdp.key_mgmt.kmpid",
  2321. FT_STRING, BASE_NONE, NULL, 0x0,
  2322. NULL, HFILL }
  2323. },
  2324. { &hf_key_mgmt_data,
  2325. { "Key Management Data", "sdp.key_mgmt.data",
  2326. FT_BYTES, BASE_NONE, NULL, 0x0,
  2327. NULL, HFILL }
  2328. },
  2329. { &hf_sdp_crypto_tag,
  2330. { "tag", "sdp.crypto.tag",
  2331. FT_UINT32, BASE_DEC, NULL, 0x0,
  2332. NULL, HFILL }
  2333. },
  2334. { &hf_sdp_crypto_crypto_suite,
  2335. { "Crypto suite", "sdp.crypto.crypto_suite",
  2336. FT_STRING, BASE_NONE, NULL, 0x0,
  2337. NULL, HFILL }
  2338. },
  2339. { &hf_sdp_crypto_master_key,
  2340. { "Master Key", "sdp.crypto.master_key",
  2341. FT_BYTES, BASE_NONE, NULL, 0x0,
  2342. NULL, HFILL }
  2343. },
  2344. { &hf_sdp_crypto_master_salt,
  2345. { "Master salt", "sdp.crypto.master_salt",
  2346. FT_BYTES, BASE_NONE, NULL, 0x0,
  2347. NULL, HFILL }
  2348. },
  2349. { &hf_sdp_crypto_lifetime,
  2350. { "Lifetime", "sdp.crypto.lifetime",
  2351. FT_STRING, BASE_NONE, NULL, 0x0,
  2352. NULL, HFILL }
  2353. },
  2354. { &hf_sdp_crypto_mki,
  2355. { "mki-value", "sdp.crypto.mki-valu",
  2356. FT_STRING, BASE_NONE, NULL, 0x0,
  2357. NULL, HFILL }
  2358. },
  2359. { &hf_sdp_crypto_mki_length,
  2360. { "mki_length", "sdp.crypto.mki_length",
  2361. FT_STRING, BASE_NONE, NULL, 0x0,
  2362. NULL, HFILL }
  2363. },
  2364. };
  2365. static gint *ett[] = {
  2366. &ett_sdp,
  2367. &ett_sdp_owner,
  2368. &ett_sdp_connection_info,
  2369. &ett_sdp_bandwidth,
  2370. &ett_sdp_time,
  2371. &ett_sdp_repeat_time,
  2372. &ett_sdp_timezone,
  2373. &ett_sdp_encryption_key,
  2374. &ett_sdp_session_attribute,
  2375. &ett_sdp_media,
  2376. &ett_sdp_media_attribute,
  2377. &ett_sdp_fmtp,
  2378. &ett_sdp_key_mgmt,
  2379. &ett_sdp_crypto_key_parameters,
  2380. };
  2381. static ei_register_info ei[] = {
  2382. { &ei_sdp_invalid_key_param, { "sdp.invalid_key_param", PI_MALFORMED, PI_NOTE, "Invalid key-param (no ':' delimiter)", EXPFILL }},
  2383. { &ei_sdp_invalid_line, { "sdp.invalid_line", PI_MALFORMED, PI_NOTE, "Invalid SDP line (no '=' delimiter)", EXPFILL }},
  2384. };
  2385. module_t *sdp_module;
  2386. expert_module_t* expert_sdp;
  2387. proto_sdp = proto_register_protocol("Session Description Protocol",
  2388. "SDP", "sdp");
  2389. proto_register_field_array(proto_sdp, hf, array_length(hf));
  2390. proto_register_subtree_array(ett, array_length(ett));
  2391. expert_sdp = expert_register_protocol(proto_sdp);
  2392. expert_register_field_array(expert_sdp, ei, array_length(ei));
  2393. key_mgmt_dissector_table = register_dissector_table("key_mgmt",
  2394. "Key Management", FT_STRING, BASE_NONE);
  2395. /*
  2396. * Preferences registration
  2397. */
  2398. sdp_module = prefs_register_protocol(proto_sdp, NULL);
  2399. prefs_register_bool_preference(sdp_module, "establish_conversation",
  2400. "Establish Media Conversation",
  2401. "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based "
  2402. "upon port numbers found in SDP payload",
  2403. &global_sdp_establish_conversation);
  2404. register_init_routine(sdp_init);
  2405. /*
  2406. * Register the dissector by name, so other dissectors can
  2407. * grab it by name rather than just referring to it directly.
  2408. */
  2409. register_dissector("sdp", dissect_sdp, proto_sdp);
  2410. /* Register for tapping */
  2411. sdp_tap = register_tap("sdp");
  2412. }
  2413. void
  2414. proto_reg_handoff_sdp(void)
  2415. {
  2416. dissector_handle_t sdp_handle;
  2417. rtp_handle = find_dissector("rtp");
  2418. rtcp_handle = find_dissector("rtcp");
  2419. msrp_handle = find_dissector("msrp");
  2420. t38_handle = find_dissector("t38");
  2421. sprt_handle = find_dissector("sprt");
  2422. h264_handle = find_dissector("h264");
  2423. mp4ves_handle = find_dissector("mp4ves");
  2424. proto_sprt = dissector_handle_get_protocol_index(find_dissector("sprt"));
  2425. sdp_handle = find_dissector("sdp");
  2426. dissector_add_string("media_type", "application/sdp", sdp_handle);
  2427. dissector_add_uint("bctp.tpi", 0x20, sdp_handle);
  2428. }