Clear the Info column before fetching anything from the packet, so that
[obnox/wireshark/wip.git] / packet-sdp.c
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: packet-sdp.c,v 1.18 2001/01/03 06:55:32 guy Exp $
8  *
9  * Ethereal - Network traffic analyzer
10  * By Gerald Combs <gerald@zing.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * 
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  * 
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  *
28  *
29  */
30
31 #include "config.h"
32
33 #ifdef HAVE_SYS_TYPES_H
34 #include <sys/types.h>
35 #endif
36
37 #include <string.h>
38 #include <ctype.h>
39
40 #include <glib.h>
41 #include "packet.h"
42 #include "strutil.h"
43
44 static int proto_sdp = -1;
45
46 static int ett_sdp = -1;
47
48 static void
49 dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
50 {
51         proto_tree      *sdp_tree;
52         proto_item      *ti;
53         gint            offset = 0;
54         const u_char    *line;
55         gint            next_offset;
56         int             linelen;
57         u_char          section;
58         u_char          type;
59         const u_char    *value;
60         int             valuelen;
61         const char      *typename;
62         int             datalen;
63
64         CHECK_DISPLAY_AS_DATA(proto_sdp, tvb, pinfo, tree);
65
66         pinfo->current_proto = "SDP";
67
68         /*
69          * As RFC 2327 says, "SDP is purely a format for session
70          * description - it does not incorporate a transport protocol,
71          * and is intended to use different transport protocols as
72          * appropriate including the Session Announcement Protocol,
73          * Session Initiation Protocol, Real-Time Streaming Protocol,
74          * electronic mail using the MIME extensions, and the
75          * Hypertext Transport Protocol."
76          *
77          * We therefore don't set the protocol or info columns;
78          * instead, we append to them, so that we don't erase
79          * what the protocol inside which the SDP stuff resides
80          * put there.
81          */
82         if (check_col(pinfo->fd, COL_PROTOCOL))
83                 col_append_str(pinfo->fd, COL_PROTOCOL, "/SDP");
84
85         if (check_col(pinfo->fd, COL_INFO)) {
86                 /* XXX: Needs description. */
87                 col_append_str(pinfo->fd, COL_INFO, ", with session description");
88         }
89
90         if (!tree)
91                 return;
92
93         ti = proto_tree_add_item(tree, proto_sdp, tvb, offset,
94             tvb_length_remaining(tvb, offset), FALSE);
95         sdp_tree = proto_item_add_subtree(ti, ett_sdp);
96
97         /*
98          * Show the SDP message a line at a time.
99          */
100         section = 0;
101         while (tvb_offset_exists(tvb, offset)) {
102                 /*
103                  * Find the end of the line.
104                  */
105                 linelen = tvb_find_line_end_unquoted(tvb, offset, -1,
106                     &next_offset);
107
108                 /*
109                  * Line must contain at least e.g. "v=".
110                  */
111                 if (linelen < 2)
112                         break;
113
114                 line = tvb_get_ptr(tvb, offset, next_offset - offset);
115                 type = line[0];
116                 if (line[1] != '=') {
117                         proto_tree_add_text(sdp_tree, tvb, offset,
118                             next_offset - offset,
119                             "Invalid line: %s",
120                             tvb_format_text(tvb, offset, next_offset - offset));
121                         offset = next_offset;
122                         continue;
123                 }
124                 value = line + 2;
125                 valuelen = linelen - 2;
126
127                 /*
128                  * Attributes.
129                  */
130                 switch (type) {
131                 case 'v':
132                         section = 'v';
133                         typename = "Session Description, version";
134                         break;
135                 case 'o':
136                         typename = "Owner/Creator, Session Id";
137                         break;
138                 case 's':
139                         typename = "Session Name";
140                         break;
141                 case 'i':
142                         if (section == 'v')
143                                 typename = "Session Information";
144                         else if (section == 'm')
145                                 typename = "Media Title";
146                         else
147                                 typename = "Misplaced";
148                         break;
149                 case 'u':
150                         typename = "URI of Description";
151                         break;
152                 case 'e':
153                         typename = "E-mail Address";
154                         break;
155                 case 'p':
156                         typename = "Phone Number";
157                         break;
158                 case 'c':
159                         typename = "Connection Information";
160                         break;
161                 case 'b':
162                         typename = "Bandwidth Information";
163                         break;
164                 case 't':
165                         section = 't';
166                         typename = "Time Description, active time";
167                         break;
168                 case 'r':
169                         typename = "Repeat Time";
170                         break;
171                 case 'm':
172                         section = 'm';
173                         typename = "Media Description, name and address";
174                         break;
175                 case 'k':
176                         typename = "Encryption Key";
177                         break;
178                 case 'a':
179                         if (section == 'v')
180                                 typename = "Session Attribute";
181                         else if (section == 'm')
182                                 typename = "Media Attribute";
183                         else
184                                 typename = "Misplaced";
185                         break;
186                 case 'z':
187                         typename = "Time Zone Adjustment";
188                         break;
189                 default:
190                         typename = "Unknown";
191                         break;
192                 }
193
194                 proto_tree_add_text(sdp_tree, tvb, offset,
195                     next_offset - offset,
196                     "%s (%c): %s", typename, type,
197                     format_text(value, valuelen));
198                 offset = next_offset;
199         }
200
201         datalen = tvb_length_remaining(tvb, offset);
202         if (datalen > 0) {
203                 proto_tree_add_text(sdp_tree, tvb, offset, datalen,
204                     "Data (%d bytes)", datalen);
205         }
206 }
207
208 void
209 proto_register_sdp(void)
210 {
211 /*        static hf_register_info hf[] = {
212                 { &variable,
213                 { "Name",           "sdp.abbreviation", TYPE, VALS_POINTER }},
214         };*/
215         static gint *ett[] = {
216                 &ett_sdp,
217         };
218
219         proto_sdp = proto_register_protocol("Session Description Protocol",
220             "SDP", "sdp");
221  /*       proto_register_field_array(proto_sdp, hf, array_length(hf));*/
222         proto_register_subtree_array(ett, array_length(ett));
223
224         /*
225          * Register the dissector by name, so other dissectors can
226          * grab it by name rather than just referring to it directly
227          * (you can't refer to it directly from a plugin dissector
228          * on Windows without stuffing it into the Big Transfer Vector).
229          */
230         register_dissector("sdp", dissect_sdp);
231 }