From Lars Ruoff (who also contributed the previous change; my apologies
[obnox/wireshark/wip.git] / req_resp_hdrs.c
1 /* req_resp_hdrs.c
2  * Routines handling protocols with a request/response line, headers,
3  * a blank line, and an optional body.
4  *
5  * $Id: req_resp_hdrs.c,v 1.3 2003/12/29 22:33:18 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <glib.h>
31 #include <epan/packet.h>
32 #include <epan/strutil.h>
33
34 #include "req_resp_hdrs.h"
35
36 /*
37  * Optionally do reassembly of the request/response line, headers, and body.
38  */
39 gboolean
40 req_resp_hdrs_do_reassembly(tvbuff_t *tvb, packet_info *pinfo,
41     gboolean desegment_headers, gboolean desegment_body)
42 {
43         gint            offset = 0;
44         gint            next_offset;
45         gint            next_offset_sav;
46         gint            length_remaining, reported_length_remaining;
47         int             linelen;
48         long int        content_length;
49         gboolean        content_length_found = FALSE;
50
51         /*
52          * Do header desegmentation if we've been told to.
53          *
54          * RFC 2616 defines HTTP messages as being either of the
55          * Request or the Response type
56          * (HTTP-message = Request | Response).
57          * Request and Response are defined as:
58          *     Request = Request-Line
59          *         *(( general-header
60          *         | request-header
61          *         | entity-header ) CRLF)
62          *         CRLF
63          *         [ message-body ]
64          *     Response = Status-Line
65          *         *(( general-header
66          *         | response-header
67          *         | entity-header ) CRLF)
68          *         CRLF
69          *         [ message-body ]
70          * that's why we can always assume two consecutive line
71          * endings (we allow CR, LF, or CRLF, as some clients
72          * or servers might not use a full CRLF) to mark the end
73          * of the headers.  The worst thing that would happen
74          * otherwise would be the packet not being desegmented
75          * or being interpreted as only headers.
76          *
77          * RFC 2326 says RTSP works the same way; RFC 3261 says SIP
78          * works the same way.
79          */
80
81         /*
82          * If header desegmentation is activated, check that all
83          * headers are in this tvbuff (search for an empty line
84          * marking end of headers) or request one more byte (we
85          * don't know how many bytes we'll need, so we just ask
86          * for one).
87          */
88         if (desegment_headers && pinfo->can_desegment) {
89                 next_offset = offset;
90                 for (;;) {
91                         next_offset_sav = next_offset;
92
93                         length_remaining = tvb_length_remaining(tvb,
94                             next_offset);
95                         reported_length_remaining =
96                             tvb_reported_length_remaining(tvb, next_offset);
97
98                         /*
99                          * Request one more byte if there're no
100                          * bytes left in the reported data (if there're
101                          * bytes left in the reported data, but not in
102                          * the available data, requesting more bytes
103                          * won't help, as those bytes weren't captured).
104                          */
105                         if (reported_length_remaining < 1) {
106                                 pinfo->desegment_offset = offset;
107                                 pinfo->desegment_len = 1;
108                                 return FALSE;
109                         }
110
111                         /*
112                          * Request one more byte if we cannot find a
113                          * header (i.e. a line end).
114                          */
115                         linelen = tvb_find_line_end(tvb, next_offset,
116                             -1, &next_offset, TRUE);
117                         if (linelen == -1 &&
118                             length_remaining >= reported_length_remaining) {
119                                 /*
120                                  * Not enough data; ask for one more
121                                  * byte.
122                                  */
123                                 pinfo->desegment_offset = offset;
124                                 pinfo->desegment_len = 1;
125                                 return FALSE;
126                         } else if (linelen == 0) {
127                                 /*
128                                  * We found the end of the headers.
129                                  */
130                                 break;
131                         }
132
133                         /*
134                          * Is this a Content-Length header?
135                          * If not, it either means that we are in
136                          * a different header line, or that we are
137                          * at the end of the headers, or that there
138                          * isn't enough data; the two latter cases
139                          * have already been handled above.
140                          */
141                         if (desegment_body) {
142                                 /*
143                                  * Check if we've found Content-Length.
144                                  */
145                                 if (tvb_strncaseeql(tvb, next_offset_sav,
146                                     "Content-Length:", 15) == 0) {
147                                         if (sscanf(
148                                             tvb_get_string(tvb,
149                                                 next_offset_sav + 15,
150                                                 linelen - 15),
151                                             "%li", &content_length)
152                                             == 1)
153                                                 content_length_found = TRUE;
154                                 }
155                         }
156                 }
157         }
158
159         /*
160          * The above loop ends when we reached the end of the headers, so
161          * there should be content_length byte after the 4 terminating bytes
162          * and next_offset points to after the end of the headers.
163          */
164         if (desegment_body && content_length_found) {
165                 /* next_offset has been set because content-length was found */
166                 if (!tvb_bytes_exist(tvb, next_offset, content_length)) {
167                         length_remaining = tvb_length_remaining(tvb,
168                             next_offset);
169                         reported_length_remaining =
170                             tvb_reported_length_remaining(tvb, next_offset);
171                         if (length_remaining < reported_length_remaining) {
172                                 /*
173                                  * It's a waste of time asking for more
174                                  * data, because that data wasn't captured.
175                                  */
176                                 return TRUE;
177                         }
178                         if (length_remaining == -1)
179                                 length_remaining = 0;
180                         pinfo->desegment_offset = offset;
181                         pinfo->desegment_len =
182                             content_length - length_remaining;
183                         return FALSE;
184                 }
185         }
186
187         /*
188          * No further desegmentation needed.
189          */
190         return TRUE;
191 }