Squelch an MSVC++ complaint.
[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.20 2001/01/25 06:14:14 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         /*
65          * As RFC 2327 says, "SDP is purely a format for session
66          * description - it does not incorporate a transport protocol,
67          * and is intended to use different transport protocols as
68          * appropriate including the Session Announcement Protocol,
69          * Session Initiation Protocol, Real-Time Streaming Protocol,
70          * electronic mail using the MIME extensions, and the
71          * Hypertext Transport Protocol."
72          *
73          * We therefore don't set the protocol or info columns;
74          * instead, we append to them, so that we don't erase
75          * what the protocol inside which the SDP stuff resides
76          * put there.
77          */
78         if (check_col(pinfo->fd, COL_PROTOCOL))
79                 col_append_str(pinfo->fd, COL_PROTOCOL, "/SDP");
80
81         if (check_col(pinfo->fd, COL_INFO)) {
82                 /* XXX: Needs description. */
83                 col_append_str(pinfo->fd, COL_INFO, ", with session description");
84         }
85
86         if (!tree)
87                 return;
88
89         ti = proto_tree_add_item(tree, proto_sdp, tvb, offset,
90             tvb_length_remaining(tvb, offset), FALSE);
91         sdp_tree = proto_item_add_subtree(ti, ett_sdp);
92
93         /*
94          * Show the SDP message a line at a time.
95          */
96         section = 0;
97         while (tvb_offset_exists(tvb, offset)) {
98                 /*
99                  * Find the end of the line.
100                  */
101                 linelen = tvb_find_line_end_unquoted(tvb, offset, -1,
102                     &next_offset);
103
104                 /*
105                  * Line must contain at least e.g. "v=".
106                  */
107                 if (linelen < 2)
108                         break;
109
110                 line = tvb_get_ptr(tvb, offset, next_offset - offset);
111                 type = line[0];
112                 if (line[1] != '=') {
113                         proto_tree_add_text(sdp_tree, tvb, offset,
114                             next_offset - offset,
115                             "Invalid line: %s",
116                             tvb_format_text(tvb, offset, next_offset - offset));
117                         offset = next_offset;
118                         continue;
119                 }
120                 value = line + 2;
121                 valuelen = linelen - 2;
122
123                 /*
124                  * Attributes.
125                  */
126                 switch (type) {
127                 case 'v':
128                         section = 'v';
129                         typename = "Session Description, version";
130                         break;
131                 case 'o':
132                         typename = "Owner/Creator, Session Id";
133                         break;
134                 case 's':
135                         typename = "Session Name";
136                         break;
137                 case 'i':
138                         if (section == 'v')
139                                 typename = "Session Information";
140                         else if (section == 'm')
141                                 typename = "Media Title";
142                         else
143                                 typename = "Misplaced";
144                         break;
145                 case 'u':
146                         typename = "URI of Description";
147                         break;
148                 case 'e':
149                         typename = "E-mail Address";
150                         break;
151                 case 'p':
152                         typename = "Phone Number";
153                         break;
154                 case 'c':
155                         typename = "Connection Information";
156                         break;
157                 case 'b':
158                         typename = "Bandwidth Information";
159                         break;
160                 case 't':
161                         section = 't';
162                         typename = "Time Description, active time";
163                         break;
164                 case 'r':
165                         typename = "Repeat Time";
166                         break;
167                 case 'm':
168                         section = 'm';
169                         typename = "Media Description, name and address";
170                         break;
171                 case 'k':
172                         typename = "Encryption Key";
173                         break;
174                 case 'a':
175                         if (section == 'v')
176                                 typename = "Session Attribute";
177                         else if (section == 'm')
178                                 typename = "Media Attribute";
179                         else
180                                 typename = "Misplaced";
181                         break;
182                 case 'z':
183                         typename = "Time Zone Adjustment";
184                         break;
185                 default:
186                         typename = "Unknown";
187                         break;
188                 }
189
190                 proto_tree_add_text(sdp_tree, tvb, offset,
191                     next_offset - offset,
192                     "%s (%c): %s", typename, type,
193                     format_text(value, valuelen));
194                 offset = next_offset;
195         }
196
197         datalen = tvb_length_remaining(tvb, offset);
198         if (datalen > 0) {
199                 proto_tree_add_text(sdp_tree, tvb, offset, datalen,
200                     "Data (%d bytes)", datalen);
201         }
202 }
203
204 void
205 proto_register_sdp(void)
206 {
207 /*        static hf_register_info hf[] = {
208                 { &variable,
209                 { "Name",           "sdp.abbreviation", TYPE, VALS_POINTER }},
210         };*/
211         static gint *ett[] = {
212                 &ett_sdp,
213         };
214
215         proto_sdp = proto_register_protocol("Session Description Protocol",
216             "SDP", "sdp");
217  /*       proto_register_field_array(proto_sdp, hf, array_length(hf));*/
218         proto_register_subtree_array(ett, array_length(ett));
219
220         /*
221          * Register the dissector by name, so other dissectors can
222          * grab it by name rather than just referring to it directly
223          * (you can't refer to it directly from a plugin dissector
224          * on Windows without stuffing it into the Big Transfer Vector).
225          */
226         register_dissector("sdp", dissect_sdp, proto_sdp);
227 }