format_text_wmem -> format_text
[metze/wireshark/wip.git] / epan / dissectors / packet-rtsp.c
1 /* packet-rtsp.c
2  * Routines for RTSP packet disassembly (RFC 2326)
3  *
4  * Jason Lango <jal@netapp.com>
5  * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu>
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  *
25  * References:
26  * RTSP is defined in RFC 2326, http://www.ietf.org/rfc/rfc2326.txt?number=2326
27  * http://www.iana.org/assignments/rsvp-parameters
28  */
29
30 #include "config.h"
31
32 #include <stdio.h>      /* for sscanf() */
33
34 #include <glib.h>
35 #include <epan/packet.h>
36 #include <epan/req_resp_hdrs.h>
37 #include <epan/prefs.h>
38 #include <epan/conversation.h>
39 #include <epan/expert.h>
40 #include <epan/strutil.h>
41 #include <epan/tap-voip.h>
42 #include <epan/stats_tree.h>
43 #include <epan/addr_resolv.h>
44 #include <wsutil/str_util.h>
45 #include <wsutil/strtoi.h>
46
47 #include "packet-rdt.h"
48 #include "packet-rtp.h"
49 #include "packet-rtcp.h"
50 #include "packet-e164.h"
51 #include "packet-rtsp.h"
52
53 void proto_register_rtsp(void);
54
55 static int rtsp_tap = -1;
56 static rtsp_info_value_t *rtsp_stat_info;
57
58 /* http://www.iana.org/assignments/rtsp-parameters/rtsp-parameters.xml */
59
60 const value_string rtsp_status_code_vals[] = {
61     { 100, "Continue" },
62     { 199, "Informational - Others" },
63
64     { 200, "OK"},
65     { 201, "Created"},
66     { 250, "Low on Storage Space"},
67     { 299, "Success - Others"},
68
69     { 300, "Multiple Choices"},
70     { 301, "Moved Permanently"},
71     { 302, "Moved Temporarily"},
72     { 303, "See Other"},
73     { 305, "Use Proxy"},
74     { 399, "Redirection - Others"},
75
76     { 400, "Bad Request"},
77     { 401, "Unauthorized"},
78     { 402, "Payment Required"},
79     { 403, "Forbidden"},
80     { 404, "Not Found"},
81     { 405, "Method Not Allowed"},
82     { 406, "Not Acceptable"},
83     { 407, "Proxy Authentication Required"},
84     { 408, "Request Timeout"},
85     { 410, "Gone"},
86     { 411, "Length Required"},
87     { 412, "Precondition Failed"},
88     { 413, "Request Entity Too Large"},
89     { 414, "Request-URI Too Long"},
90     { 415, "Unsupported Media Type"},
91     { 451, "Invalid Parameter"},
92     { 452, "Illegal Conferenec Identifier"},
93     { 453, "Not Enough Bandwidth"},
94     { 454, "Session Not Found"},
95     { 455, "Method Not Valid In This State"},
96     { 456, "Header Field Not Valid"},
97     { 457, "Invalid Range"},
98     { 458, "Parameter Is Read-Only"},
99     { 459, "Aggregate Operation Not Allowed"},
100     { 460, "Only Aggregate Operation Allowed"},
101     { 461, "Unsupported Transport"},
102     { 462, "Destination Unreachable"},
103     { 499, "Client Error - Others"},
104
105     { 500, "Internal Server Error"},
106     { 501, "Not Implemented"},
107     { 502, "Bad Gateway"},
108     { 503, "Service Unavailable"},
109     { 504, "Gateway Timeout"},
110     { 505, "RTSP Version not supported"},
111     { 551, "Option Not Support"},
112     { 599, "Server Error - Others"},
113
114     { 0,    NULL}
115 };
116
117 static int proto_rtsp       = -1;
118
119 static gint ett_rtsp        = -1;
120 static gint ett_rtspframe   = -1;
121 static gint ett_rtsp_method     = -1;
122
123 static int hf_rtsp_request  = -1;
124 static int hf_rtsp_response = -1;
125 static int hf_rtsp_content_type = -1;
126 static int hf_rtsp_content_length   = -1;
127 static int hf_rtsp_method   = -1;
128 static int hf_rtsp_url      = -1;
129 static int hf_rtsp_status   = -1;
130 static int hf_rtsp_session  = -1;
131 static int hf_rtsp_transport    = -1;
132 static int hf_rtsp_rdtfeaturelevel  = -1;
133 static int hf_rtsp_X_Vig_Msisdn = -1;
134 static int hf_rtsp_magic = -1;
135 static int hf_rtsp_channel = -1;
136 static int hf_rtsp_length = -1;
137 static int hf_rtsp_data = -1;
138
139 static int voip_tap = -1;
140
141 static expert_field ei_rtsp_unknown_transport_type = EI_INIT;
142 static expert_field ei_rtsp_bad_server_port = EI_INIT;
143 static expert_field ei_rtsp_bad_client_port = EI_INIT;
144 static expert_field ei_rtsp_bad_interleaved_channel = EI_INIT;
145 static expert_field ei_rtsp_content_length_invalid = EI_INIT;
146 static expert_field ei_rtsp_rdtfeaturelevel_invalid = EI_INIT;
147 static expert_field ei_rtsp_bad_server_ip_address = EI_INIT;
148 static expert_field ei_rtsp_bad_client_ip_address = EI_INIT;
149
150 static dissector_handle_t rtsp_handle;
151 static dissector_handle_t rtp_handle;
152 static dissector_handle_t rtp_rfc4571_handle;
153 static dissector_handle_t rtcp_handle;
154 static dissector_handle_t rdt_handle;
155 static dissector_table_t media_type_dissector_table;
156 static heur_dissector_list_t heur_subdissector_list;
157
158 static const gchar *st_str_packets = "Total RTSP Packets";
159 static const gchar *st_str_requests = "RTSP Request Packets";
160 static const gchar *st_str_responses = "RTSP Response Packets";
161 static const gchar *st_str_resp_broken = "???: broken";
162 static const gchar *st_str_resp_100 = "1xx: Informational";
163 static const gchar *st_str_resp_200 = "2xx: Success";
164 static const gchar *st_str_resp_300 = "3xx: Redirection";
165 static const gchar *st_str_resp_400 = "4xx: Client Error";
166 static const gchar *st_str_resp_500 = "5xx: Server Error";
167 static const gchar *st_str_other = "Other RTSP Packets";
168
169 static int st_node_packets = -1;
170 static int st_node_requests = -1;
171 static int st_node_responses = -1;
172 static int st_node_resp_broken = -1;
173 static int st_node_resp_100 = -1;
174 static int st_node_resp_200 = -1;
175 static int st_node_resp_300 = -1;
176 static int st_node_resp_400 = -1;
177 static int st_node_resp_500 = -1;
178 static int st_node_other = -1;
179
180 static void
181 rtsp_stats_tree_init(stats_tree* st)
182 {
183     st_node_packets     = stats_tree_create_node(st, st_str_packets, 0, TRUE);
184     st_node_requests    = stats_tree_create_pivot(st, st_str_requests, st_node_packets);
185     st_node_responses   = stats_tree_create_node(st, st_str_responses, st_node_packets, TRUE);
186     st_node_resp_broken = stats_tree_create_node(st, st_str_resp_broken, st_node_responses, TRUE);
187     st_node_resp_100    = stats_tree_create_node(st, st_str_resp_100,    st_node_responses, TRUE);
188     st_node_resp_200    = stats_tree_create_node(st, st_str_resp_200,    st_node_responses, TRUE);
189     st_node_resp_300    = stats_tree_create_node(st, st_str_resp_300,    st_node_responses, TRUE);
190     st_node_resp_400    = stats_tree_create_node(st, st_str_resp_400,    st_node_responses, TRUE);
191     st_node_resp_500    = stats_tree_create_node(st, st_str_resp_500,    st_node_responses, TRUE);
192     st_node_other       = stats_tree_create_node(st, st_str_other, st_node_packets, FALSE);
193 }
194
195 /* RTSP/Packet Counter stats packet function */
196 static int
197 rtsp_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p)
198 {
199     const rtsp_info_value_t *v = (const rtsp_info_value_t *)p;
200     guint         i = v->response_code;
201     int           resp_grp;
202     const gchar  *resp_str;
203     static gchar  str[64];
204
205     tick_stat_node(st, st_str_packets, 0, FALSE);
206
207     if (i) {
208         tick_stat_node(st, st_str_responses, st_node_packets, FALSE);
209
210         if ( (i<100)||(i>=600) ) {
211             resp_grp = st_node_resp_broken;
212             resp_str = st_str_resp_broken;
213         } else if (i<200) {
214             resp_grp = st_node_resp_100;
215             resp_str = st_str_resp_100;
216         } else if (i<300) {
217             resp_grp = st_node_resp_200;
218             resp_str = st_str_resp_200;
219         } else if (i<400) {
220             resp_grp = st_node_resp_300;
221             resp_str = st_str_resp_300;
222         } else if (i<500) {
223             resp_grp = st_node_resp_400;
224             resp_str = st_str_resp_400;
225         } else {
226             resp_grp = st_node_resp_500;
227             resp_str = st_str_resp_500;
228         }
229
230         tick_stat_node(st, resp_str, st_node_responses, FALSE);
231
232         g_snprintf(str, sizeof(str),"%u %s",i,val_to_str(i,rtsp_status_code_vals, "Unknown (%d)"));
233         tick_stat_node(st, str, resp_grp, FALSE);
234     } else if (v->request_method) {
235         stats_tree_tick_pivot(st,st_node_requests,v->request_method);
236     } else {
237         tick_stat_node(st, st_str_other, st_node_packets, FALSE);
238     }
239
240     return 1;
241 }
242 void proto_reg_handoff_rtsp(void);
243
244 /*
245  * desegmentation of RTSP headers
246  * (when we are over TCP or another protocol providing the desegmentation API)
247  */
248 static gboolean rtsp_desegment_headers = TRUE;
249
250 /*
251  * desegmentation of RTSP bodies
252  * (when we are over TCP or another protocol providing the desegmentation API)
253  * TODO let the user filter on content-type the bodies he wants desegmented
254  */
255 static gboolean rtsp_desegment_body = TRUE;
256
257 /* http://www.iana.org/assignments/port-numbers lists two rtsp ports.
258  * In Addition RTSP uses display port over Wi-Fi Display: 7236.
259  */
260 #define RTSP_TCP_PORT_RANGE           "554,8554,7236"
261
262 /*
263  * Takes an array of bytes, assumed to contain a null-terminated
264  * string, as an argument, and returns the length of the string -
265  * i.e., the size of the array, minus 1 for the null terminator.
266  */
267 #define STRLEN_CONST(str)   (sizeof (str) - 1)
268
269 #define RTSP_FRAMEHDR   ('$')
270
271 typedef struct {
272     dissector_handle_t      dissector;
273 } rtsp_interleaved_t;
274
275 #define RTSP_MAX_INTERLEAVED        (256)
276
277 /*
278  * Careful about dynamically allocating memory in this structure (say
279  * for dynamically increasing the size of the 'interleaved' array) -
280  * the containing structure is garbage collected and contained
281  * pointers will not be freed.
282  */
283 typedef struct {
284     rtsp_interleaved_t      interleaved[RTSP_MAX_INTERLEAVED];
285 } rtsp_conversation_data_t;
286
287 static int
288 dissect_rtspinterleaved(tvbuff_t *tvb, int offset, packet_info *pinfo,
289     proto_tree *tree)
290 {
291     guint           length_remaining;
292     proto_item     *ti;
293     proto_tree     *rtspframe_tree = NULL;
294     int             orig_offset;
295     guint8          rf_chan;    /* interleaved channel id */
296     guint16         rf_len;     /* packet length */
297     tvbuff_t       *next_tvb;
298     conversation_t *conv;
299     rtsp_conversation_data_t *data;
300     dissector_handle_t        dissector;
301
302     /*
303      * This will throw an exception if we don't have any data left.
304      * That's what we want.  (See "tcp_dissect_pdus()", which is
305      * similar.)
306      */
307     length_remaining = tvb_ensure_captured_length_remaining(tvb, offset);
308
309     /*
310      * Can we do reassembly?
311      */
312     if (rtsp_desegment_headers && pinfo->can_desegment) {
313         /*
314          * Yes - would an RTSP multiplexed header starting at
315          * this offset be split across segment boundaries?
316          */
317         if (length_remaining < 4) {
318             /*
319              * Yes.  Tell the TCP dissector where the data for
320              * this message starts in the data it handed us and
321              * that we need "some more data."  Don't tell it
322              * exactly how many bytes we need because if/when we
323              * ask for even more (after the header) that will
324              * break reassembly.
325              */
326             pinfo->desegment_offset = offset;
327             pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
328             return -1;
329         }
330     }
331
332     /*
333      * Get the "$", channel, and length from the header.
334      */
335     orig_offset = offset;
336     rf_chan = tvb_get_guint8(tvb, offset+1);
337     rf_len = tvb_get_ntohs(tvb, offset+2);
338
339     /*
340      * Can we do reassembly?
341      */
342     if (rtsp_desegment_body && pinfo->can_desegment) {
343         /*
344          * Yes - is the header + encapsulated packet split
345          * across segment boundaries?
346          */
347         if (length_remaining < 4U + rf_len) {
348             /*
349              * Yes.  Tell the TCP dissector where the data
350              * for this message starts in the data it handed
351              * us, and how many more bytes we need, and return.
352              */
353             pinfo->desegment_offset = offset;
354             pinfo->desegment_len = 4U + rf_len - length_remaining;
355             return -1;
356         }
357     }
358
359     col_add_fstr(pinfo->cinfo, COL_INFO,
360             "Interleaved channel 0x%02x, %u bytes",
361             rf_chan, rf_len);
362
363     ti = proto_tree_add_protocol_format(tree, proto_rtsp, tvb,
364         offset, 4,
365         "RTSP Interleaved Frame, Channel: 0x%02x, %u bytes",
366         rf_chan, rf_len);
367     rtspframe_tree = proto_item_add_subtree(ti, ett_rtspframe);
368
369     proto_tree_add_item(rtspframe_tree, hf_rtsp_magic, tvb, offset, 1, ENC_BIG_ENDIAN);
370
371     offset += 1;
372
373     proto_tree_add_item(rtspframe_tree, hf_rtsp_channel, tvb, offset, 1, ENC_BIG_ENDIAN);
374
375     offset += 1;
376
377     proto_tree_add_item(rtspframe_tree, hf_rtsp_length, tvb, offset, 2, ENC_BIG_ENDIAN);
378     offset += 2;
379
380     /*
381      * We set the actual length of the tvbuff for the interleaved
382      * stuff to the minimum of what's left in the tvbuff and the
383      * length in the header.
384      *
385      * XXX - what if there's nothing left in the tvbuff?
386      * We'd want a BoundsError exception to be thrown, so
387      * that a Short Frame would be reported.
388      */
389     if (length_remaining > rf_len)
390         length_remaining = rf_len;
391     next_tvb = tvb_new_subset_length_caplen(tvb, offset, length_remaining, rf_len);
392
393     conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
394         pinfo->srcport, pinfo->destport, 0);
395
396     if (conv &&
397         (data = (rtsp_conversation_data_t *)conversation_get_proto_data(conv, proto_rtsp)) &&
398         /* Add the following condition if it is not always true.
399         rf_chan < RTSP_MAX_INTERLEAVED &&
400         */
401         (dissector = data->interleaved[rf_chan].dissector)) {
402         call_dissector(dissector, next_tvb, pinfo, tree);
403     } else {
404         gboolean dissected = FALSE;
405         heur_dtbl_entry_t *hdtbl_entry = NULL;
406
407         dissected = dissector_try_heuristic(heur_subdissector_list,
408                             next_tvb, pinfo, tree, &hdtbl_entry, NULL);
409
410         if (!dissected) {
411             proto_tree_add_item(rtspframe_tree, hf_rtsp_data, tvb, offset, rf_len, ENC_NA);
412         }
413     }
414
415     offset += rf_len;
416
417     return offset - orig_offset;
418 }
419
420 static void process_rtsp_request(tvbuff_t *tvb, int offset, const guchar *data,
421                                  size_t linelen, size_t next_line_offset,
422                                  proto_tree *tree);
423
424 static void process_rtsp_reply(tvbuff_t *tvb, int offset, const guchar *data,
425                                size_t linelen, size_t next_line_offset,
426                                proto_tree *tree);
427
428 typedef enum {
429     RTSP_REQUEST,
430     RTSP_REPLY,
431     RTSP_NOT_FIRST_LINE
432 } rtsp_type_t;
433
434 static const char *rtsp_methods[] = {
435     "DESCRIBE",
436     "ANNOUNCE",
437     "GET_PARAMETER",
438     "OPTIONS",
439     "PAUSE",
440     "PLAY",
441     "RECORD",
442     "REDIRECT",
443     "SETUP",
444     "SET_PARAMETER",
445     "TEARDOWN"
446 };
447
448 #define RTSP_NMETHODS   array_length(rtsp_methods)
449
450 static gboolean
451 is_rtsp_request_or_reply(const guchar *line, size_t linelen, rtsp_type_t *type)
452 {
453     guint         ii;
454     const guchar *token, *next_token;
455     int           tokenlen;
456     gchar         response_chars[4];
457
458     /* Is this an RTSP reply? */
459     if (linelen >= 5 && g_ascii_strncasecmp("RTSP/", line, 5) == 0) {
460         /*
461          * Yes.
462          */
463         *type = RTSP_REPLY;
464         /* The first token is the version. */
465         tokenlen = get_token_len(line, line+5, &token);
466         if (tokenlen != 0) {
467             /* The next token is the status code. */
468             tokenlen = get_token_len(token, line+linelen, &next_token);
469             if (tokenlen >= 3) {
470                 memcpy(response_chars, token, 3);
471                 response_chars[3] = '\0';
472                 ws_strtou32(response_chars, NULL, &rtsp_stat_info->response_code);
473             }
474         }
475         return TRUE;
476     }
477
478     /*
479      * Is this an RTSP request?
480      * Check whether the line begins with one of the RTSP request
481      * methods.
482      */
483     for (ii = 0; ii < RTSP_NMETHODS; ii++) {
484         size_t len = strlen(rtsp_methods[ii]);
485         if (linelen >= len &&
486             g_ascii_strncasecmp(rtsp_methods[ii], line, len) == 0 &&
487             (len == linelen || g_ascii_isspace(line[len])))
488         {
489             *type = RTSP_REQUEST;
490             rtsp_stat_info->request_method =
491                wmem_strndup(wmem_packet_scope(), rtsp_methods[ii], len+1);
492             return TRUE;
493         }
494     }
495
496     /* Wasn't a request or a response */
497     *type = RTSP_NOT_FIRST_LINE;
498     return FALSE;
499 }
500
501 static const char rtsp_content_type[]      = "Content-Type:";
502 static const char rtsp_transport[]         = "Transport:";
503 static const char rtsp_sps_server_port[]   = "server_port=";
504 static const char rtsp_cps_server_port[]   = "client_port=";
505 static const char rtsp_sps_dest_addr[]     = "dest_addr=";
506 static const char rtsp_cps_src_addr[]      = "src_addr=";
507 static const char rtsp_rtp_udp_default[]   = "rtp/avp";
508 static const char rtsp_rtp_udp[]           = "rtp/avp/udp";
509 static const char rtsp_rtp_tcp[]           = "rtp/avp/tcp";
510 static const char rtsp_rdt_feature_level[] = "RDTFeatureLevel";
511 static const char rtsp_real_rdt[]          = "x-real-rdt/";
512 static const char rtsp_real_tng[]          = "x-pn-tng/"; /* synonym for x-real-rdt */
513 static const char rtsp_inter[]             = "interleaved=";
514
515 static void
516 rtsp_create_conversation(packet_info *pinfo, proto_item *ti,
517                          const guchar *line_begin, size_t line_len,
518                          gint rdt_feature_level,
519                          rtsp_type_t rtsp_type_packet)
520 {
521     conversation_t  *conv;
522     guchar    buf[256];
523     guchar   *tmp;
524     gboolean  rtp_udp_transport = FALSE;
525     gboolean  rtp_tcp_transport = FALSE;
526     gboolean  rdt_transport = FALSE;
527     guint     c_data_port, c_mon_port;
528     guint     s_data_port, s_mon_port;
529     guint     ipv4_1, ipv4_2, ipv4_3, ipv4_4;
530     gboolean  is_video      = FALSE; /* FIX ME - need to indicate video or not */
531     address   src_addr;
532     address   dst_addr;
533
534     if (rtsp_type_packet != RTSP_REPLY) {
535         return;
536     }
537
538     src_addr=pinfo->src;
539     dst_addr=pinfo->dst;
540
541     /* Copy line into buf */
542     if (line_len > sizeof(buf) - 1)
543     {
544         /* Don't overflow the buffer. */
545         line_len = sizeof(buf) - 1;
546     }
547     memcpy(buf, line_begin, line_len);
548     buf[line_len] = '\0';
549
550     /* Get past "Transport:" and spaces */
551     tmp = buf + STRLEN_CONST(rtsp_transport);
552     while (*tmp && g_ascii_isspace(*tmp))
553         tmp++;
554
555     /* Work out which transport type is here */
556     if (g_ascii_strncasecmp(tmp, rtsp_rtp_udp, strlen(rtsp_rtp_udp)) == 0)
557     {
558         rtp_udp_transport = TRUE;
559     }
560     else if (g_ascii_strncasecmp(tmp, rtsp_rtp_tcp, strlen(rtsp_rtp_tcp)) == 0)
561     {
562         rtp_tcp_transport = TRUE;
563     }
564     else if (g_ascii_strncasecmp(tmp, rtsp_rtp_udp_default, strlen(rtsp_rtp_udp_default)) == 0)
565     {
566         rtp_udp_transport = TRUE;
567     }
568     else if (g_ascii_strncasecmp(tmp, rtsp_real_rdt, strlen(rtsp_real_rdt)) == 0 ||
569                  g_ascii_strncasecmp(tmp, rtsp_real_tng, strlen(rtsp_real_tng)) == 0)
570     {
571         rdt_transport = TRUE;
572     }
573     else
574     {
575         /* Give up on unknown transport types */
576         expert_add_info(pinfo, ti, &ei_rtsp_unknown_transport_type);
577         return;
578     }
579
580     c_data_port = c_mon_port = 0;
581     s_data_port = s_mon_port = 0;
582
583     /* Look for server port */
584     if ((tmp = strstr(buf, rtsp_sps_server_port))) {
585         tmp += strlen(rtsp_sps_server_port);
586         if (sscanf(tmp, "%u-%u", &s_data_port, &s_mon_port) < 1) {
587             expert_add_info(pinfo, ti, &ei_rtsp_bad_server_port);
588             return;
589         }
590     }
591     else if ((tmp = strstr(buf, rtsp_sps_dest_addr))) {
592         tmp += strlen(rtsp_sps_dest_addr);
593         if (sscanf(tmp, "\":%u\"", &s_data_port) == 1) {
594             /* :9 mean ignore */
595             if (s_data_port == 9) {
596                 s_data_port = 0;
597             }
598         }
599         else if (sscanf(tmp, "\"%u.%u.%u.%u:%u\"", &ipv4_1, &ipv4_2, &ipv4_3, &ipv4_4, &s_data_port) == 5) {
600             guchar *tmp2;
601             guchar *tmp3;
602             guint32 ip4_addr;
603
604             /* Skip leading " */
605             tmp++;
606             tmp2=strstr(tmp,":");
607             tmp3=g_strndup(tmp,tmp2-tmp);
608             if (!str_to_ip(tmp3, &ip4_addr)) {
609                 g_free(tmp3);
610                 expert_add_info(pinfo, ti, &ei_rtsp_bad_server_ip_address);
611                 return;
612             }
613             set_address(&dst_addr, AT_IPv4, 4, &ip4_addr);
614             g_free(tmp3);
615         }
616         else if (sscanf(tmp, "\"%u.%u.%u.%u\"", &ipv4_1, &ipv4_2, &ipv4_3, &ipv4_4) == 4) {
617             guchar *tmp2;
618             guchar *tmp3;
619             guint32 ip4_addr;
620
621             /* Skip leading " */
622             tmp++;
623             tmp2=strstr(tmp,"\"");
624             tmp3=g_strndup(tmp,tmp2-tmp);
625             if (!str_to_ip(tmp3, &ip4_addr)) {
626                 g_free(tmp3);
627                 expert_add_info(pinfo, ti, &ei_rtsp_bad_server_ip_address);
628                 return;
629             }
630             set_address(&dst_addr, AT_IPv4, 4, &ip4_addr);
631             g_free(tmp3);
632         }
633         else
634         {
635             expert_add_info(pinfo, ti, &ei_rtsp_bad_server_port);
636             return;
637         }
638     }
639
640
641     /* Look for client port */
642     if ((tmp = strstr(buf, rtsp_cps_server_port))) {
643         tmp += strlen(rtsp_cps_server_port);
644         if (sscanf(tmp, "%u-%u", &c_data_port, &c_mon_port) < 1) {
645             expert_add_info(pinfo, ti, &ei_rtsp_bad_client_port);
646             return;
647         }
648     }
649     else if ((tmp = strstr(buf, rtsp_cps_src_addr))) {
650         tmp += strlen(rtsp_cps_src_addr);
651         if (sscanf(tmp, "\"%u.%u.%u.%u:%u\"", &ipv4_1, &ipv4_2, &ipv4_3, &ipv4_4, &c_data_port) == 5) {
652             guchar *tmp2;
653             guchar *tmp3;
654             guint32 ip4_addr;
655
656             /* Skip leading " */
657             tmp++;
658             tmp2=strstr(tmp,":");
659             tmp3=g_strndup(tmp,tmp2-tmp);
660             if (!str_to_ip(tmp3, &ip4_addr)) {
661                 g_free(tmp3);
662                 expert_add_info(pinfo, ti, &ei_rtsp_bad_client_ip_address);
663                 return;
664             }
665             set_address(&src_addr, AT_IPv4, 4, &ip4_addr);
666             g_free(tmp3);
667         }
668     }
669
670     /* Deal with RTSP TCP-interleaved conversations. */
671     if (strstr(buf, rtsp_inter) != NULL) {
672         rtsp_conversation_data_t    *data;
673         guint               s_data_chan, s_mon_chan;
674         int             i;
675
676         /* Move tmp to beyone interleaved string */
677         tmp = strstr(buf, rtsp_inter);
678         tmp += strlen(rtsp_inter);
679         /* Look for channel number(s) */
680         i = sscanf(tmp, "%u-%u", &s_data_chan, &s_mon_chan);
681         if (i < 1)
682         {
683             expert_add_info(pinfo, ti, &ei_rtsp_bad_interleaved_channel);
684             return;
685         }
686
687         /* At least data channel present, look for conversation (presumably TCP) */
688         conv = find_or_create_conversation(pinfo);
689
690         /* Look for previous data */
691         data = (rtsp_conversation_data_t *)conversation_get_proto_data(conv, proto_rtsp);
692
693         /* Create new data if necessary */
694         if (!data)
695         {
696             data = wmem_new0(wmem_file_scope(), rtsp_conversation_data_t);
697             conversation_add_proto_data(conv, proto_rtsp, data);
698         }
699
700         /* Now set the dissector handle of the interleaved channel
701            according to the transport protocol used */
702         if (rtp_tcp_transport)
703         {
704             if (s_data_chan < RTSP_MAX_INTERLEAVED) {
705                 data->interleaved[s_data_chan].dissector =
706                     rtp_handle;
707             }
708             if (i > 1 && s_mon_chan < RTSP_MAX_INTERLEAVED) {
709                 data->interleaved[s_mon_chan].dissector =
710                     rtcp_handle;
711             }
712         }
713         else if (rdt_transport)
714         {
715             if (s_data_chan < RTSP_MAX_INTERLEAVED) {
716                 data->interleaved[s_data_chan].dissector =
717                     rdt_handle;
718             }
719         }
720         return;
721     }
722     /* Noninterleaved options follow */
723     /*
724      * We only want to match on the destination address, not the
725      * source address, because the server might send back a packet
726      * from an address other than the address to which its client
727      * sent the packet, so we construct a conversation with no
728      * second address.
729      */
730     else if (rtp_udp_transport)
731     {
732         /* RTP only if indicated */
733         if (c_data_port)
734         {
735             rtp_add_address(pinfo, PT_UDP, &dst_addr, c_data_port, s_data_port,
736                             "RTSP", pinfo->num, is_video, NULL);
737         }
738
739         /* RTCP only if indicated */
740         if (c_mon_port)
741         {
742             rtcp_add_address(pinfo, &pinfo->dst, c_mon_port, s_mon_port,
743                              "RTSP", pinfo->num);
744         }
745     }
746     else if (rtp_tcp_transport)
747     {
748         /* RTP only if indicated */
749         rtp_add_address(pinfo, PT_TCP, &src_addr, c_data_port, s_data_port,
750                         "RTSP", pinfo->num, is_video, NULL);
751     }
752     else if (rdt_transport)
753     {
754         /* Real Data Transport */
755         rdt_add_address(pinfo, &pinfo->dst, c_data_port, s_data_port,
756                         "RTSP", rdt_feature_level);
757     }
758     return;
759 }
760
761 static const char rtsp_content_length[] = "Content-Length:";
762
763 static int
764 rtsp_get_content_length(const guchar *line_begin, size_t line_len)
765 {
766     guchar  buf[256];
767     guchar *tmp;
768     guint32 content_length;
769     const char *p;
770     const guchar *up;
771
772     if (line_len > sizeof(buf) - 1) {
773         /*
774          * Don't overflow the buffer.
775          */
776         line_len = sizeof(buf) - 1;
777     }
778     memcpy(buf, line_begin, line_len);
779     buf[line_len] = '\0';
780
781     tmp = buf + STRLEN_CONST(rtsp_content_length);
782     while (*tmp && g_ascii_isspace(*tmp))
783         tmp++;
784     ws_strtoi32(tmp, &p, &content_length);
785     up = p;
786     if (up == tmp || (*up != '\0' && !g_ascii_isspace(*up)))
787         return -1;  /* not a valid number */
788     return (int)content_length;
789 }
790
791 static const char rtsp_Session[] = "Session:";
792 static const char rtsp_X_Vig_Msisdn[] = "X-Vig-Msisdn";
793
794 static int
795 dissect_rtspmessage(tvbuff_t *tvb, int offset, packet_info *pinfo,
796     proto_tree *tree)
797 {
798     proto_tree   *rtsp_tree = NULL;
799     proto_tree   *sub_tree  = NULL;
800     proto_item   *ti_top    = NULL;
801     const guchar *line;
802     gint          next_offset;
803     const guchar *linep, *lineend;
804     int           orig_offset;
805     int           first_linelen, linelen;
806     int           line_end_offset;
807     int           colon_offset;
808     gboolean      is_request_or_reply;
809     gboolean      body_requires_content_len;
810     gboolean      saw_req_resp_or_header;
811     guchar        c;
812     rtsp_type_t   rtsp_type_packet;
813     rtsp_type_t   rtsp_type_line;
814     gboolean      is_header;
815     int           datalen;
816     int           content_length;
817     int           reported_datalen;
818     int           value_offset;
819     int           value_len;
820     e164_info_t   e164_info;
821     gint          rdt_feature_level = 0;
822     gchar        *media_type_str_lower_case = NULL;
823     int           semi_colon_offset;
824     int           par_end_offset;
825     gchar        *frame_label = NULL;
826     gchar        *session_id  = NULL;
827     voip_packet_info_t *stat_info = NULL;
828
829     rtsp_stat_info = wmem_new(wmem_packet_scope(), rtsp_info_value_t);
830     rtsp_stat_info->framenum = pinfo->num;
831     rtsp_stat_info->response_code = 0;
832     rtsp_stat_info->request_method = NULL;
833     rtsp_stat_info->request_uri = NULL;
834     rtsp_stat_info->rtsp_host = NULL;
835
836     /*
837      * Is this a request or response?
838      *
839      * Note that "tvb_find_line_end()" will return a value that
840      * is not longer than what's in the buffer, so the
841      * "tvb_get_ptr()" call won't throw an exception.
842      */
843     first_linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
844
845     /*
846      * Is the first line a request or response?
847      */
848     line = tvb_get_ptr(tvb, offset, first_linelen);
849     is_request_or_reply = is_rtsp_request_or_reply(line, first_linelen,
850         &rtsp_type_packet);
851     if (is_request_or_reply) {
852         /*
853          * Yes, it's a request or response.
854          * Do header desegmentation if we've been told to,
855          * and do body desegmentation if we've been told to and
856          * we find a Content-Length header.
857          */
858         if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
859             rtsp_desegment_headers, rtsp_desegment_body)) {
860             /*
861              * More data needed for desegmentation.
862              */
863             return -1;
864         }
865     }
866
867     /*
868      * RFC 2326 says that a content length must be specified
869      * in requests that have a body, although section 4.4 speaks
870      * of a server closing the connection indicating the end of
871      * a reply body.
872      *
873      * We assume that an absent content length in a request means
874      * that we don't have a body, and that an absent content length
875      * in a reply means that the reply body runs to the end of
876      * the connection.  If the first line is neither, we assume
877      * that whatever follows a blank line should be treated as a
878      * body; there's not much else we can do, as we're jumping
879      * into the message in the middle.
880      *
881      * XXX - if there was no Content-Length entity header, we should
882      * accumulate all data until the end of the connection.
883      * That'd require that the TCP dissector call subdissectors
884      * for all frames with FIN, even if they contain no data,
885      * which would require subdissectors to deal intelligently
886      * with empty segments.
887      */
888     if (rtsp_type_packet == RTSP_REQUEST)
889         body_requires_content_len = TRUE;
890     else
891         body_requires_content_len = FALSE;
892
893     line = tvb_get_ptr(tvb, offset, first_linelen);
894     if (is_request_or_reply) {
895         if ( rtsp_type_packet == RTSP_REPLY ) {
896             frame_label = wmem_strdup_printf(wmem_packet_scope(),
897                   "Reply: %s", format_text(wmem_packet_scope(), line, first_linelen));
898         }
899         else {
900             frame_label = format_text(wmem_packet_scope(), line, first_linelen);
901         }
902     }
903
904     col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTSP");
905     /*
906         * Put the first line from the buffer into the summary
907         * if it's an RTSP request or reply (but leave out the
908         * line terminator).
909         * Otherwise, just call it a continuation.
910         *
911         * Note that "tvb_find_line_end()" will return a value that
912         * is not longer than what's in the buffer, so the
913         * "tvb_get_ptr()" call won't throw an exception.
914         */
915     if (is_request_or_reply)
916         if ( rtsp_type_packet == RTSP_REPLY ) {
917             col_set_str(pinfo->cinfo, COL_INFO, "Reply: ");
918             col_append_str(pinfo->cinfo, COL_INFO,
919                 format_text(wmem_packet_scope(), line, first_linelen));
920         }
921         else {
922             col_add_str(pinfo->cinfo, COL_INFO,
923                 format_text(wmem_packet_scope(), line, first_linelen));
924         }
925
926     else
927         col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
928
929     orig_offset = offset;
930     if (tree) {
931         ti_top = proto_tree_add_item(tree, proto_rtsp, tvb, offset, -1,
932                                      ENC_NA);
933         rtsp_tree = proto_item_add_subtree(ti_top, ett_rtsp);
934     }
935
936     /*
937      * We haven't yet seen a Content-Length header.
938      */
939     content_length = -1;
940
941     /*
942      * Process the packet data, a line at a time.
943      */
944     saw_req_resp_or_header = FALSE; /* haven't seen anything yet */
945     while (tvb_offset_exists(tvb, offset)) {
946         /*
947          * We haven't yet concluded that this is a header.
948          */
949         is_header = FALSE;
950
951         /*
952          * Find the end of the line.
953          */
954         linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
955         if (linelen < 0)
956             return -1;
957         line_end_offset = offset + linelen;
958         /*
959          * colon_offset may be -1
960          */
961         colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
962
963
964         /*
965          * Get a buffer that refers to the line.
966          */
967         line = tvb_get_ptr(tvb, offset, linelen);
968         lineend = line + linelen;
969
970         /*
971          * OK, does it look like an RTSP request or response?
972          */
973         is_request_or_reply = is_rtsp_request_or_reply(line, linelen, &rtsp_type_line);
974         if (is_request_or_reply)
975             goto is_rtsp;
976
977         /*
978          * No.  Does it look like a blank line (as would appear
979          * at the end of an RTSP request)?
980          */
981         if (linelen == 0)
982             goto is_rtsp;   /* Yes. */
983
984         /*
985          * No.  Does it look like a header?
986          */
987         linep = line;
988         while (linep < lineend) {
989             c = *linep++;
990
991             /*
992              * This must be a CHAR, and must not be a CTL, to be part
993              * of a token; that means it must be printable ASCII.
994              *
995              * XXX - what about leading LWS on continuation
996              * lines of a header?
997              */
998             if (!g_ascii_isprint(c))
999                 break;
1000
1001             switch (c) {
1002
1003             case '(':
1004             case ')':
1005             case '<':
1006             case '>':
1007             case '@':
1008             case ',':
1009             case ';':
1010             case '\\':
1011             case '"':
1012             case '/':
1013             case '[':
1014             case ']':
1015             case '?':
1016             case '=':
1017             case '{':
1018             case '}':
1019                 /*
1020                  * It's a tspecial, so it's not
1021                  * part of a token, so it's not
1022                  * a field name for the beginning
1023                  * of a header.
1024                  */
1025                 goto not_rtsp;
1026
1027             case ':':
1028                 /*
1029                  * This ends the token; we consider
1030                  * this to be a header.
1031                  */
1032                 is_header = TRUE;
1033                 goto is_rtsp;
1034
1035             case ' ':
1036             case '\t':
1037                 /*
1038                  * LWS (RFC-2616, 4.2); continue the previous
1039                  * header.
1040                  */
1041                 goto is_rtsp;
1042             }
1043         }
1044
1045         /*
1046          * We haven't seen the colon, but everything else looks
1047          * OK for a header line.
1048          *
1049          * If we've already seen an RTSP request or response
1050          * line, or a header line, and we're at the end of
1051          * the tvbuff, we assume this is an incomplete header
1052          * line.  (We quit this loop after seeing a blank line,
1053          * so if we've seen a request or response line, or a
1054          * header line, this is probably more of the request
1055          * or response we're presumably seeing.  There is some
1056          * risk of false positives, but the same applies for
1057          * full request or response lines or header lines,
1058          * although that's less likely.)
1059          *
1060          * We throw an exception in that case, by checking for
1061          * the existence of the next byte after the last one
1062          * in the line.  If it exists, "tvb_ensure_bytes_exist()"
1063          * throws no exception, and we fall through to the
1064          * "not RTSP" case.  If it doesn't exist,
1065          * "tvb_ensure_bytes_exist()" will throw the appropriate
1066          * exception.
1067          */
1068         if (saw_req_resp_or_header)
1069             tvb_ensure_bytes_exist(tvb, offset, linelen + 1);
1070
1071     not_rtsp:
1072         /*
1073          * We don't consider this part of an RTSP request or
1074          * reply, so we don't display it.
1075          */
1076         break;
1077
1078     is_rtsp:
1079         /*
1080          * Process this line.
1081          */
1082         if (linelen == 0) {
1083             /*
1084              * This is a blank line, which means that
1085              * whatever follows it isn't part of this
1086              * request or reply.
1087              */
1088             proto_tree_add_format_text(rtsp_tree, tvb, offset, next_offset - offset);
1089             offset = next_offset;
1090             break;
1091         }
1092
1093         /*
1094          * Not a blank line - either a request, a reply, or a header
1095          * line.
1096          */
1097         saw_req_resp_or_header = TRUE;
1098         if (rtsp_tree) {
1099
1100             switch (rtsp_type_line)
1101             {
1102                 case RTSP_REQUEST:
1103                     process_rtsp_request(tvb, offset, line, linelen, next_offset, rtsp_tree);
1104                     break;
1105
1106                 case RTSP_REPLY:
1107                     process_rtsp_reply(tvb, offset, line, linelen, next_offset, rtsp_tree);
1108                     break;
1109
1110                 case RTSP_NOT_FIRST_LINE:
1111                     /* Drop through, it may well be a header line */
1112                     break;
1113             }
1114         }
1115
1116         if (is_header)
1117         {
1118             /* We know that colon_offset must be set */
1119
1120             /* Skip whitespace after the colon. */
1121             value_offset = colon_offset + 1;
1122             while ((value_offset < line_end_offset) &&
1123                    ((c = tvb_get_guint8(tvb, value_offset)) == ' ' || c == '\t'))
1124             {
1125                 value_offset++;
1126             }
1127             value_len = line_end_offset - value_offset;
1128
1129             /*
1130              * Process some headers specially.
1131              */
1132 #define HDR_MATCHES(header) \
1133     ( (size_t)linelen > STRLEN_CONST(header) && \
1134      g_ascii_strncasecmp(line, (header), STRLEN_CONST(header)) == 0)
1135
1136             if (HDR_MATCHES(rtsp_transport))
1137             {
1138                 proto_item *ti;
1139                 ti = proto_tree_add_string(rtsp_tree, hf_rtsp_transport, tvb,
1140                                            offset, linelen,
1141                                            tvb_format_text(tvb, value_offset,
1142                                                            value_len));
1143
1144                 /*
1145                  * Based on the port numbers specified
1146                  * in the Transport: header, set up
1147                  * a conversation that will be dissected
1148                  * with the appropriate dissector.
1149                  */
1150                 rtsp_create_conversation(pinfo, ti, line, linelen, rdt_feature_level, rtsp_type_packet);
1151             } else if (HDR_MATCHES(rtsp_content_type))
1152             {
1153                 proto_tree_add_string(rtsp_tree, hf_rtsp_content_type,
1154                                       tvb, offset, linelen,
1155                                       tvb_format_text(tvb, value_offset,
1156                                                       value_len));
1157
1158                 offset = offset + (int)STRLEN_CONST(rtsp_content_type);
1159                 /* Skip wsp */
1160                 offset = tvb_skip_wsp(tvb, offset, value_len);
1161                 semi_colon_offset = tvb_find_guint8(tvb, value_offset, value_len, ';');
1162                 if ( semi_colon_offset != -1) {
1163                     /* m-parameter present */
1164                     par_end_offset = tvb_skip_wsp_return(tvb, semi_colon_offset-1);
1165                     value_len = par_end_offset - offset;
1166                 }
1167
1168                 media_type_str_lower_case = ascii_strdown_inplace(
1169                     (gchar *)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, value_len, ENC_ASCII));
1170
1171             } else if (HDR_MATCHES(rtsp_content_length))
1172             {
1173                 guint32 clength;
1174                 gboolean clength_valid;
1175                 proto_item* pi;
1176                 clength_valid = ws_strtou32(tvb_format_text(tvb, value_offset, value_len),
1177                     NULL, &clength);
1178                 pi = proto_tree_add_uint(rtsp_tree, hf_rtsp_content_length,
1179                                     tvb, offset, linelen, clength);
1180                 if (!clength_valid)
1181                     expert_add_info(pinfo, pi, &ei_rtsp_content_length_invalid);
1182
1183                 /*
1184                  * Only the amount specified by the
1185                  * Content-Length: header should be treated
1186                  * as payload.
1187                  */
1188                 content_length = rtsp_get_content_length(line, linelen);
1189
1190             } else if (HDR_MATCHES(rtsp_Session))
1191             {
1192                 session_id = tvb_format_text(tvb, value_offset, value_len);
1193                 /* Put the value into the protocol tree */
1194                 proto_tree_add_string(rtsp_tree, hf_rtsp_session, tvb,
1195                                       offset, linelen,
1196                                       session_id);
1197
1198             } else if (HDR_MATCHES(rtsp_X_Vig_Msisdn)) {
1199                 /*
1200                  * Extract the X_Vig_Msisdn string
1201                  */
1202                 if (colon_offset != -1)
1203                 {
1204                     proto_item *ti;
1205                     /* Put the value into the protocol tree */
1206                     ti = proto_tree_add_string(rtsp_tree, hf_rtsp_X_Vig_Msisdn,tvb,
1207                                                offset, linelen ,
1208                                                tvb_format_text(tvb, value_offset, value_len));
1209                     sub_tree = proto_item_add_subtree(ti, ett_rtsp_method);
1210
1211                     e164_info.e164_number_type = CALLING_PARTY_NUMBER;
1212                     e164_info.nature_of_address = 0;
1213
1214                     e164_info.E164_number_str = tvb_get_string_enc(wmem_packet_scope(), tvb, value_offset,
1215                                                                   value_len, ENC_ASCII);
1216                     e164_info.E164_number_length = value_len;
1217                     dissect_e164_number(tvb, sub_tree, value_offset,
1218                                         value_len, e164_info);
1219                 }
1220             } else if (HDR_MATCHES(rtsp_rdt_feature_level))
1221             {
1222                 gboolean rdt_feature_level_valid;
1223                 proto_item* pi;
1224                 rdt_feature_level_valid = ws_strtou32(tvb_format_text(tvb, value_offset, value_len),
1225                     NULL, &rdt_feature_level);
1226                 pi = proto_tree_add_uint(rtsp_tree, hf_rtsp_rdtfeaturelevel,
1227                 tvb, offset, linelen, rdt_feature_level);
1228                 if (!rdt_feature_level_valid)
1229                     expert_add_info(pinfo, pi, &ei_rtsp_rdtfeaturelevel_invalid);
1230             }
1231             else
1232             {
1233                 /* Default case for headers. Show line as text */
1234                 proto_tree_add_format_text(rtsp_tree, tvb, offset, next_offset - offset);
1235             }
1236         }
1237         else if (rtsp_type_line == RTSP_NOT_FIRST_LINE)
1238         {
1239             /* Catch-all for all other lines... Show line as text.
1240                TODO: should these be shown as errors? */
1241             proto_tree_add_format_text(rtsp_tree, tvb, offset, next_offset - offset);
1242         }
1243
1244         offset = next_offset;
1245     }
1246
1247     if (session_id) {
1248         stat_info = wmem_new0(wmem_packet_scope(), voip_packet_info_t);
1249         stat_info->protocol_name = wmem_strdup(wmem_packet_scope(), "RTSP");
1250         stat_info->call_id = session_id;
1251         stat_info->frame_label = frame_label;
1252         stat_info->call_state = VOIP_CALL_SETUP;
1253         stat_info->call_active_state = VOIP_ACTIVE;
1254         stat_info->frame_comment = frame_label;
1255         tap_queue_packet(voip_tap, pinfo, stat_info);
1256     }
1257
1258     /*
1259      * Have now read all of the lines of this message.
1260      *
1261      * If a content length was supplied, the amount of data to be
1262      * processed as RTSP payload is the minimum of the content
1263      * length and the amount of data remaining in the frame.
1264      *
1265      * If no content length was supplied (or if a bad content length
1266      * was supplied), the amount of data to be processed is the amount
1267      * of data remaining in the frame.
1268      */
1269     datalen = tvb_captured_length_remaining(tvb, offset);
1270     reported_datalen = tvb_reported_length_remaining(tvb, offset);
1271     if (content_length != -1) {
1272         /*
1273          * Content length specified; display only that amount
1274          * as payload.
1275          */
1276         if (datalen > content_length)
1277             datalen = content_length;
1278
1279         /*
1280          * XXX - limit the reported length in the tvbuff we'll
1281          * hand to a subdissector to be no greater than the
1282          * content length.
1283          *
1284          * We really need both unreassembled and "how long it'd
1285          * be if it were reassembled" lengths for tvbuffs, so
1286          * that we throw the appropriate exceptions for
1287          * "not enough data captured" (running past the length),
1288          * "packet needed reassembly" (within the length but
1289          * running past the unreassembled length), and
1290          * "packet is malformed" (running past the reassembled
1291          * length).
1292          */
1293         if (reported_datalen > content_length)
1294             reported_datalen = content_length;
1295     } else {
1296         /*
1297          * No content length specified; if this message doesn't
1298          * have a body if no content length is specified, process
1299          * nothing as payload.
1300          */
1301         if (body_requires_content_len)
1302             datalen = 0;
1303     }
1304
1305     if (datalen > 0) {
1306         /*
1307          * There's stuff left over; process it.
1308          */
1309         tvbuff_t *new_tvb;
1310
1311         /*
1312          * Now create a tvbuff for the Content-type stuff and
1313          * dissect it.
1314          *
1315          * The amount of data to be processed that's
1316          * available in the tvbuff is "datalen", which
1317          * is the minimum of the amount of data left in
1318          * the tvbuff and any specified content length.
1319          *
1320          * The amount of data to be processed that's in
1321          * this frame, regardless of whether it was
1322          * captured or not, is "reported_datalen",
1323          * which, if no content length was specified,
1324          * is -1, i.e. "to the end of the frame.
1325          */
1326         new_tvb = tvb_new_subset_length_caplen(tvb, offset, datalen,
1327                 reported_datalen);
1328
1329         if (media_type_str_lower_case &&
1330             dissector_try_string(media_type_dissector_table,
1331                 media_type_str_lower_case,
1332                 new_tvb, pinfo, rtsp_tree, NULL)){
1333
1334         }else {
1335             /*
1336              * Fix up the top-level item so that it doesn't
1337              * include the SDP stuff.
1338              */
1339             if (ti_top != NULL)
1340                 proto_item_set_len(ti_top, offset);
1341
1342             if (tvb_get_guint8(tvb, offset) == RTSP_FRAMEHDR) {
1343                 /*
1344                  * This is interleaved stuff; don't
1345                  * treat it as raw data - set "datalen"
1346                  * to 0, so we won't skip the offset
1347                  * past it, which will cause our
1348                  * caller to process that stuff itself.
1349                  */
1350                 datalen = 0;
1351             } else {
1352                 proto_tree_add_bytes_format(rtsp_tree, hf_rtsp_data, tvb, offset,
1353                     datalen, NULL, "Data (%d bytes)",
1354                     reported_datalen);
1355             }
1356         }
1357
1358         /*
1359          * We've processed "datalen" bytes worth of data
1360          * (which may be no data at all); advance the
1361          * offset past whatever data we've processed.
1362          */
1363         offset += datalen;
1364     }
1365
1366     tap_queue_packet(rtsp_tap, pinfo, rtsp_stat_info);
1367
1368     return offset - orig_offset;
1369 }
1370
1371 static void
1372 process_rtsp_request(tvbuff_t *tvb, int offset, const guchar *data,
1373                      size_t linelen, size_t next_line_offset, proto_tree *tree)
1374 {
1375     proto_tree   *sub_tree;
1376     proto_item   *ti;
1377     const guchar *lineend  = data + linelen;
1378     guint        ii;
1379     const guchar *url;
1380     const guchar *url_start;
1381     guchar       *tmp_url;
1382
1383     /* Request Methods */
1384     for (ii = 0; ii < RTSP_NMETHODS; ii++) {
1385         size_t len = strlen(rtsp_methods[ii]);
1386         if (linelen >= len &&
1387             g_ascii_strncasecmp(rtsp_methods[ii], data, len) == 0 &&
1388             (len == linelen || g_ascii_isspace(data[len])))
1389             break;
1390     }
1391     if (ii == RTSP_NMETHODS) {
1392         /*
1393          * We got here because "is_rtsp_request_or_reply()" returned
1394          * RTSP_REQUEST, so we know one of the request methods
1395          * matched, so we "can't get here".
1396          */
1397         DISSECTOR_ASSERT_NOT_REACHED();
1398     }
1399
1400     /* Add a tree for this request */
1401     ti = proto_tree_add_string(tree, hf_rtsp_request, tvb, offset,
1402                               (gint) (next_line_offset - offset),
1403                               tvb_format_text(tvb, offset, (gint) (next_line_offset - offset)));
1404     sub_tree = proto_item_add_subtree(ti, ett_rtsp_method);
1405
1406
1407     /* Add method name to tree */
1408     proto_tree_add_string(sub_tree, hf_rtsp_method, tvb, offset,
1409                           (gint) strlen(rtsp_methods[ii]), rtsp_methods[ii]);
1410
1411     /* URL */
1412     url = data;
1413     /* Skip method name again */
1414     while (url < lineend && !g_ascii_isspace(*url))
1415         url++;
1416     /* Skip spaces */
1417     while (url < lineend && g_ascii_isspace(*url))
1418         url++;
1419     /* URL starts here */
1420     url_start = url;
1421     /* Scan to end of URL */
1422     while (url < lineend && !g_ascii_isspace(*url))
1423         url++;
1424     /* Create a URL-sized buffer and copy contents */
1425     tmp_url = wmem_strndup(wmem_packet_scope(), url_start, url - url_start);
1426
1427     /* Add URL to tree */
1428     proto_tree_add_string(sub_tree, hf_rtsp_url, tvb,
1429                           offset + (gint) (url_start - data), (gint) (url - url_start), tmp_url);
1430 }
1431
1432 /* Read first line of a reply message */
1433 static void
1434 process_rtsp_reply(tvbuff_t *tvb, int offset, const guchar *data,
1435     size_t linelen, size_t next_line_offset, proto_tree *tree)
1436 {
1437     proto_tree   *sub_tree;
1438     proto_item   *ti;
1439     const guchar *lineend  = data + linelen;
1440     const guchar *status   = data;
1441     const guchar *status_start;
1442     guint         status_i;
1443
1444     /* Add a tree for this request */
1445     ti = proto_tree_add_string(tree, hf_rtsp_response, tvb, offset,
1446                                (gint) (next_line_offset - offset),
1447                                tvb_format_text(tvb, offset, (gint) (next_line_offset - offset)));
1448     sub_tree = proto_item_add_subtree(ti, ett_rtsp_method);
1449
1450
1451     /* status code */
1452
1453     /* Skip protocol/version */
1454     while (status < lineend && !g_ascii_isspace(*status))
1455         status++;
1456     /* Skip spaces */
1457     while (status < lineend && g_ascii_isspace(*status))
1458         status++;
1459
1460     /* Actual code number now */
1461     status_start = status;
1462     status_i = 0;
1463     while (status < lineend && g_ascii_isdigit(*status))
1464         status_i = status_i * 10 + *status++ - '0';
1465
1466     /* Add field to tree */
1467     proto_tree_add_uint(sub_tree, hf_rtsp_status, tvb,
1468                         offset + (gint) (status_start - data),
1469                         (gint) (status - status_start), status_i);
1470 }
1471
1472 static int
1473 dissect_rtsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1474 {
1475     int offset = 0;
1476     int len;
1477
1478     while (tvb_reported_length_remaining(tvb, offset) != 0) {
1479         len = (tvb_get_guint8(tvb, offset) == RTSP_FRAMEHDR)
1480             ? dissect_rtspinterleaved(tvb, offset, pinfo, tree)
1481             : dissect_rtspmessage(tvb, offset, pinfo, tree);
1482         if (len == -1)
1483             break;
1484         offset += len;
1485
1486         /*
1487          * OK, we've set the Protocol and Info columns for the
1488          * first RTSP message; set fence so changes are kept for
1489          * subsequent RTSP messages.
1490          */
1491         col_set_fence(pinfo->cinfo, COL_INFO);
1492     }
1493     return tvb_captured_length(tvb);
1494 }
1495
1496 void
1497 proto_register_rtsp(void)
1498 {
1499     static gint *ett[] = {
1500         &ett_rtspframe,
1501         &ett_rtsp,
1502         &ett_rtsp_method,
1503     };
1504     static hf_register_info hf[] = {
1505         { &hf_rtsp_request,
1506             { "Request", "rtsp.request", FT_STRING, BASE_NONE, NULL, 0,
1507             NULL, HFILL }},
1508         { &hf_rtsp_response,
1509             { "Response", "rtsp.response", FT_STRING, BASE_NONE, NULL, 0,
1510             NULL, HFILL }},
1511         { &hf_rtsp_method,
1512             { "Method", "rtsp.method", FT_STRING, BASE_NONE, NULL, 0,
1513             NULL, HFILL }},
1514         { &hf_rtsp_content_type,
1515             { "Content-type", "rtsp.content-type", FT_STRING, BASE_NONE, NULL, 0,
1516             NULL, HFILL }},
1517         { &hf_rtsp_content_length,
1518             { "Content-length", "rtsp.content-length", FT_UINT32, BASE_DEC, NULL, 0,
1519             NULL, HFILL }},
1520         { &hf_rtsp_url,
1521             { "URL", "rtsp.url", FT_STRING, BASE_NONE, NULL, 0,
1522             NULL, HFILL }},
1523         { &hf_rtsp_status,
1524             { "Status", "rtsp.status", FT_UINT32, BASE_DEC, NULL, 0,
1525             NULL, HFILL }},
1526         { &hf_rtsp_session,
1527             { "Session", "rtsp.session", FT_STRING, BASE_NONE, NULL, 0,
1528             NULL, HFILL }},
1529         { &hf_rtsp_transport,
1530             { "Transport", "rtsp.transport", FT_STRING, BASE_NONE, NULL, 0,
1531             NULL, HFILL }},
1532         { &hf_rtsp_rdtfeaturelevel,
1533             { "RDTFeatureLevel", "rtsp.rdt-feature-level", FT_UINT32, BASE_DEC, NULL, 0,
1534             NULL, HFILL }},
1535         { &hf_rtsp_X_Vig_Msisdn,
1536             { "X-Vig-Msisdn", "rtsp.X_Vig_Msisdn", FT_STRING, BASE_NONE, NULL, 0,
1537             NULL, HFILL }},
1538         { &hf_rtsp_magic,
1539             { "Magic", "rtsp.magic", FT_UINT8, BASE_HEX, NULL, 0x0,
1540             NULL, HFILL }},
1541         { &hf_rtsp_channel,
1542             { "Channel", "rtsp.channel", FT_UINT8, BASE_HEX, NULL, 0x0,
1543             NULL, HFILL }},
1544         { &hf_rtsp_length,
1545             { "Length", "rtsp.length", FT_UINT16, BASE_DEC, NULL, 0x0,
1546             NULL, HFILL }},
1547         { &hf_rtsp_data,
1548             { "Data", "rtsp.data", FT_BYTES, BASE_NONE, NULL, 0x0,
1549             NULL, HFILL }},
1550     };
1551
1552     static ei_register_info ei[] = {
1553         { &ei_rtsp_unknown_transport_type,
1554           { "rtsp.unknown_transport_type", PI_UNDECODED, PI_WARN, "Unknown transport type",  EXPFILL }},
1555         { &ei_rtsp_bad_server_port,
1556           { "rtsp.bad_server_port", PI_UNDECODED, PI_WARN, "Bad server_port",  EXPFILL }},
1557         { &ei_rtsp_bad_client_port,
1558           { "rtsp.bad_client_port", PI_UNDECODED, PI_WARN, "Bad client port",  EXPFILL }},
1559         { &ei_rtsp_bad_interleaved_channel,
1560           { "rtsp.bad_interleaved_channel", PI_UNDECODED, PI_WARN, "Bad interleaved_channel",  EXPFILL }},
1561         { &ei_rtsp_content_length_invalid,
1562           { "rtsp.content-length.invalid", PI_MALFORMED, PI_ERROR, "Invalid content length", EXPFILL }},
1563         { &ei_rtsp_rdtfeaturelevel_invalid,
1564           { "rtsp.rdt-feature-level.invalid", PI_MALFORMED, PI_ERROR, "Invalid RDTFeatureLevel", EXPFILL }},
1565         { &ei_rtsp_bad_server_ip_address,
1566           { "rtsp.bad_client_ip_address", PI_MALFORMED, PI_ERROR, "Bad server IP address", EXPFILL }},
1567         { &ei_rtsp_bad_client_ip_address,
1568           { "rtsp.bad_client_ip_address", PI_MALFORMED, PI_ERROR, "Bad client IP address", EXPFILL }}
1569     };
1570
1571     module_t *rtsp_module;
1572     expert_module_t *expert_rtsp;
1573
1574     proto_rtsp = proto_register_protocol("Real Time Streaming Protocol", "RTSP", "rtsp");
1575
1576     proto_register_field_array(proto_rtsp, hf, array_length(hf));
1577     proto_register_subtree_array(ett, array_length(ett));
1578
1579     expert_rtsp = expert_register_protocol(proto_rtsp);
1580     expert_register_field_array(expert_rtsp, ei, array_length(ei));
1581
1582     /* Make this dissector findable by name */
1583     rtsp_handle = register_dissector("rtsp", dissect_rtsp, proto_rtsp);
1584
1585     /* Register our configuration options, particularly our ports */
1586
1587     rtsp_module = prefs_register_protocol(proto_rtsp, NULL);
1588
1589     prefs_register_obsolete_preference(rtsp_module, "tcp.alternate_port");
1590
1591     prefs_register_bool_preference(rtsp_module, "desegment_headers",
1592         "Reassemble RTSP headers spanning multiple TCP segments",
1593         "Whether the RTSP dissector should reassemble headers "
1594         "of a request spanning multiple TCP segments. "
1595         " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1596         &rtsp_desegment_headers);
1597     prefs_register_bool_preference(rtsp_module, "desegment_body",
1598         "Trust the \"Content-length:\" header when desegmenting",
1599         "Whether the RTSP dissector should use the "
1600         "\"Content-length:\" value to desegment the body "
1601         "of a request spanning multiple TCP segments",
1602         &rtsp_desegment_body);
1603
1604     /*
1605      * Heuristic dissectors SHOULD register themselves in
1606      * this table using the standard heur_dissector_add()
1607      * function.
1608      */
1609     heur_subdissector_list = register_heur_dissector_list("rtsp", proto_rtsp);
1610
1611     /*
1612      * Register for tapping
1613      */
1614     rtsp_tap = register_tap("rtsp"); /* RTSP statistics tap */
1615 }
1616
1617 void
1618 proto_reg_handoff_rtsp(void)
1619 {
1620     rtp_handle = find_dissector_add_dependency("rtp", proto_rtsp);
1621     rtp_rfc4571_handle = find_dissector_add_dependency("rtp.rfc4571", proto_rtsp);
1622     rtcp_handle = find_dissector_add_dependency("rtcp", proto_rtsp);
1623     rdt_handle = find_dissector_add_dependency("rdt", proto_rtsp);
1624     media_type_dissector_table = find_dissector_table("media_type");
1625     voip_tap = find_tap_id("voip");
1626
1627     /* Set our port number for future use */
1628     dissector_add_uint_range_with_preference("tcp.port", RTSP_TCP_PORT_RANGE, rtsp_handle);
1629
1630     /* XXX: Do the following only once ?? */
1631     stats_tree_register("rtsp","rtsp","RTSP/Packet Counter", 0, rtsp_stats_tree_packet, rtsp_stats_tree_init, NULL );
1632
1633 }
1634
1635 /*
1636  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1637  *
1638  * Local variables:
1639  * c-basic-offset: 4
1640  * tab-width: 8
1641  * indent-tabs-mode: space
1642  * End:
1643  *
1644  * vi: set shiftwidth=4 tabstop=8 expandtab:
1645  * :indentSize=4:tabSize=8:noTabs=true:
1646  */