Tethereal/tethereal -> TShark/tshark.
[gd/wireshark/.git] / epan / dissectors / packet-http.c
1 /* packet-http.c
2  * Routines for HTTP packet disassembly
3  * RFC 1945 (HTTP/1.0)
4  * RFC 2616 (HTTP/1.1)
5  *
6  * Guy Harris <guy@alum.mit.edu>
7  *
8  * Copyright 2004, Jerry Talkington <jtalkington@users.sourceforge.net>
9  * Copyright 2002, Tim Potter <tpot@samba.org>
10  * Copyright 1999, Andrew Tridgell <tridge@samba.org>
11  *
12  * $Id$
13  *
14  * Wireshark - Network traffic analyzer
15  * By Gerald Combs <gerald@wireshark.org>
16  * Copyright 1998 Gerald Combs
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License
20  * as published by the Free Software Foundation; either version 2
21  * of the License, or (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include <string.h>
38 #include <ctype.h>
39
40 #include <glib.h>
41 #include <epan/packet.h>
42 #include <epan/strutil.h>
43 #include <epan/base64.h>
44 #include <epan/emem.h>
45 #include <epan/stats_tree.h>
46
47 #include <epan/req_resp_hdrs.h>
48 #include "packet-http.h"
49 #include <epan/prefs.h>
50 #include <epan/expert.h>
51
52 typedef enum _http_type {
53         HTTP_REQUEST,
54         HTTP_RESPONSE,
55         HTTP_NOTIFICATION,
56         HTTP_OTHERS
57 } http_type_t;
58
59 #include <epan/tap.h>
60
61 static int http_tap = -1;
62
63 static int proto_http = -1;
64 static int hf_http_notification = -1;
65 static int hf_http_response = -1;
66 static int hf_http_request = -1;
67 static int hf_http_basic = -1;
68 static int hf_http_request_method = -1;
69 static int hf_http_request_uri = -1;
70 static int hf_http_version = -1;
71 static int hf_http_response_code = -1;
72 static int hf_http_authorization = -1;
73 static int hf_http_proxy_authenticate = -1;
74 static int hf_http_proxy_authorization = -1;
75 static int hf_http_www_authenticate = -1;
76 static int hf_http_content_type = -1;
77 static int hf_http_content_length = -1;
78 static int hf_http_content_encoding = -1;
79 static int hf_http_transfer_encoding = -1;
80 static int hf_http_user_agent = -1;
81 static int hf_http_host = -1;
82 static int hf_http_connection = -1;
83 static int hf_http_cookie = -1;
84 static int hf_http_accept = -1;
85 static int hf_http_referer = -1;
86 static int hf_http_accept_language = -1;
87 static int hf_http_accept_encoding = -1;
88 static int hf_http_date = -1;
89 static int hf_http_cache_control = -1;
90 static int hf_http_server = -1;
91 static int hf_http_location = -1;
92 static int hf_http_set_cookie = -1;
93 static int hf_http_last_modified = -1;
94 static int hf_http_x_forwarded_for = -1;
95
96 static gint ett_http = -1;
97 static gint ett_http_ntlmssp = -1;
98 static gint ett_http_request = -1;
99 static gint ett_http_chunked_response = -1;
100 static gint ett_http_chunk_data = -1;
101 static gint ett_http_encoded_entity = -1;
102
103 static dissector_handle_t data_handle;
104 static dissector_handle_t media_handle;
105 static dissector_handle_t http_handle;
106
107 /*
108  * desegmentation of HTTP headers
109  * (when we are over TCP or another protocol providing the desegmentation API)
110  */
111 static gboolean http_desegment_headers = TRUE;
112
113 /*
114  * desegmentation of HTTP bodies
115  * (when we are over TCP or another protocol providing the desegmentation API)
116  * TODO let the user filter on content-type the bodies he wants desegmented
117  */
118 static gboolean http_desegment_body = TRUE;
119
120 /*
121  * De-chunking of content-encoding: chunk entity bodies.
122  */
123 static gboolean http_dechunk_body = TRUE;
124
125 /*
126  * Decompression of zlib encoded entities.
127  */
128 #ifdef HAVE_LIBZ
129 static gboolean http_decompress_body = TRUE;
130 #else
131 static gboolean http_decompress_body = FALSE;
132 #endif
133
134
135 #define TCP_PORT_HTTP                   80
136 #define TCP_PORT_PROXY_HTTP             3128
137 #define TCP_PORT_PROXY_ADMIN_HTTP       3132
138 #define TCP_ALT_PORT_HTTP               8080
139 #define TCP_RADAN_HTTP                  8088
140 #define TCP_PORT_HKP                    11371
141 #define TCP_PORT_DAAP                   3689
142 /*
143  * SSDP is implemented atop HTTP (yes, it really *does* run over UDP).
144  */
145 #define TCP_PORT_SSDP                   1900
146 #define UDP_PORT_SSDP                   1900
147
148 /* 
149  * tcp alternate port
150  */
151 static guint http_alternate_tcp_port = 0;
152 static guint alternate_tcp_port = 0;
153
154 /*
155  * Protocols implemented atop HTTP.
156  */
157 typedef enum {
158         PROTO_HTTP,             /* just HTTP */
159         PROTO_SSDP,             /* Simple Service Discovery Protocol */
160         PROTO_DAAP              /* Digital Audio Access Protocol */
161 } http_proto_t;
162
163 typedef void (*ReqRespDissector)(tvbuff_t*, proto_tree*, int, const guchar*,
164     const guchar*);
165
166 /*
167  * Structure holding information from headers needed by main
168  * HTTP dissector code.
169  */
170 typedef struct {
171         char    *content_type;
172         char    *content_type_parameters;
173         gboolean have_content_length;
174         long    content_length; /* XXX - make it 64-bit? */
175         char    *content_encoding;
176         char    *transfer_encoding;
177 } headers_t;
178
179 static int is_http_request_or_reply(const gchar *data, int linelen,
180     http_type_t *type, ReqRespDissector *reqresp_dissector);
181 static int chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
182                 proto_tree *tree, int offset);
183 static void process_header(tvbuff_t *tvb, int offset, int next_offset,
184     const guchar *line, int linelen, int colon_offset, packet_info *pinfo,
185     proto_tree *tree, headers_t *eh_ptr);
186 static gint find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len);
187 static gboolean check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb,
188     packet_info *pinfo, gchar *value);
189 static gboolean check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb,
190     gchar *value);
191
192 static dissector_table_t port_subdissector_table;
193 static dissector_table_t media_type_subdissector_table;
194 static heur_dissector_list_t heur_subdissector_list;
195
196 static dissector_handle_t ntlmssp_handle=NULL;
197 static dissector_handle_t gssapi_handle=NULL;
198
199 static const value_string vals_status_code[] = {
200         { 100, "Continue" },
201         { 101, "Switching Protocols" },
202         { 102, "Processing" },
203         { 199, "Informational - Others" },
204         
205         { 200, "OK"},
206         { 201, "Created"},
207         { 202, "Accepted"},
208         { 203, "Non-authoritative Information"},
209         { 204, "No Content"},
210         { 205, "Reset Content"},
211         { 206, "Partial Content"},
212         { 207, "Multi-Status"},
213         { 299, "Success - Others"},
214         
215         { 300, "Multiple Choices"},
216         { 301, "Moved Permanently"},
217         { 302, "Found"},
218         { 303, "See Other"},
219         { 304, "Not Modified"},
220         { 305, "Use Proxy"},
221         { 307, "Temporary Redirect"},
222         { 399, "Redirection - Others"},
223         
224         { 400, "Bad Request"},
225         { 401, "Unauthorized"},
226         { 402, "Payment Required"},
227         { 403, "Forbidden"},
228         { 404, "Not Found"},
229         { 405, "Method Not Allowed"},
230         { 406, "Not Acceptable"},
231         { 407, "Proxy Authentication Required"},
232         { 408, "Request Time-out"},
233         { 409, "Conflict"},
234         { 410, "Gone"},
235         { 411, "Length Required"},
236         { 412, "Precondition Failed"},
237         { 413, "Request Entity Too Large"},
238         { 414, "Request-URI Too Long"},
239         { 415, "Unsupported Media Type"},
240         { 416, "Requested Range Not Satisfiable"},
241         { 417, "Expectation Failed"},
242         { 422, "Unprocessable Entity"},
243         { 423, "Locked"},
244         { 424, "Failed Dependency"},
245         { 499, "Client Error - Others"},
246         
247         { 500, "Internal Server Error"},
248         { 501, "Not Implemented"},
249         { 502, "Bad Gateway"},
250         { 503, "Service Unavailable"},
251         { 504, "Gateway Time-out"},
252         { 505, "HTTP Version not supported"},
253         { 507, "Insufficient Storage"},
254         { 599, "Server Error - Others"},
255         
256         { 0,    NULL}
257 };
258
259 static const gchar* st_str_reqs = "HTTP Requests by Server";
260 static const gchar* st_str_reqs_by_srv_addr = "HTTP Requests by Server Address";
261 static const gchar* st_str_reqs_by_http_host = "HTTP Requests by HTTP Host";
262 static const gchar* st_str_resps_by_srv_addr = "HTTP Responses by Server Address";
263
264 static int st_node_reqs = -1;
265 static int st_node_reqs_by_srv_addr = -1;
266 static int st_node_reqs_by_http_host = -1;
267 static int st_node_resps_by_srv_addr = -1;
268
269 static void http_reqs_stats_tree_init(stats_tree* st) {
270         st_node_reqs = stats_tree_create_node(st, st_str_reqs, 0, TRUE);
271         st_node_reqs_by_srv_addr = stats_tree_create_node(st, st_str_reqs_by_srv_addr, st_node_reqs, TRUE);
272         st_node_reqs_by_http_host = stats_tree_create_node(st, st_str_reqs_by_http_host, st_node_reqs, TRUE);
273         st_node_resps_by_srv_addr = stats_tree_create_node(st, st_str_resps_by_srv_addr, 0, TRUE);
274 }
275
276 static int http_reqs_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p) {
277         const http_info_value_t* v = p;
278         int reqs_by_this_host;
279         int reqs_by_this_addr;
280         int resps_by_this_addr;
281         int i = v->response_code;
282         static gchar ip_str[256];
283         
284         
285         if (v->request_method) {
286                 g_snprintf(ip_str,sizeof(ip_str),"%s",address_to_str(&pinfo->dst));
287                 
288                 tick_stat_node(st, st_str_reqs, 0, FALSE);
289                 tick_stat_node(st, st_str_reqs_by_srv_addr, st_node_reqs, TRUE);
290                 tick_stat_node(st, st_str_reqs_by_http_host, st_node_reqs, TRUE);
291                 reqs_by_this_addr = tick_stat_node(st, ip_str, st_node_reqs_by_srv_addr, TRUE);
292                 
293                 if (v->http_host) {
294                         reqs_by_this_host = tick_stat_node(st, v->http_host, st_node_reqs_by_http_host, TRUE);
295                         tick_stat_node(st, ip_str, reqs_by_this_host, FALSE);
296                         
297                         tick_stat_node(st, v->http_host, reqs_by_this_addr, FALSE);
298                 }
299                 
300                 return 1;
301                 
302         } else if (i != 0) {
303                 g_snprintf(ip_str,sizeof(ip_str),"%s",address_to_str(&pinfo->src));
304                 
305                 tick_stat_node(st, st_str_resps_by_srv_addr, 0, FALSE);
306                 resps_by_this_addr = tick_stat_node(st, ip_str, st_node_resps_by_srv_addr, TRUE);
307                 
308                 if ( (i>100)&&(i<400) ) {
309                         tick_stat_node(st, "OK", resps_by_this_addr, FALSE);
310                 } else {
311                         tick_stat_node(st, "KO", resps_by_this_addr, FALSE);
312                 }
313                 
314                 return 1;
315         }
316         
317         return 0;
318 }
319
320
321 static int st_node_requests_by_host = -1;
322 static const guint8* st_str_requests_by_host = "HTTP Requests by HTTP Host";
323
324 static void http_req_stats_tree_init(stats_tree* st) {
325         st_node_requests_by_host = stats_tree_create_node(st, st_str_requests_by_host, 0, TRUE);
326 }
327
328 static int http_req_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p) {
329         const http_info_value_t* v = p;
330         int reqs_by_this_host;
331         
332         if (v->request_method) {
333                 tick_stat_node(st, st_str_requests_by_host, 0, FALSE);
334                 
335                 if (v->http_host) {
336                         reqs_by_this_host = tick_stat_node(st, v->http_host, st_node_requests_by_host, TRUE);
337                         
338                         if (v->request_uri) {
339                                 tick_stat_node(st, v->request_uri, reqs_by_this_host, TRUE);
340                         }
341                 }
342                 
343                 return 1;
344         }
345         
346         return 0;
347 }
348
349 static const guint8* st_str_packets = "Total HTTP Packets";
350 static const guint8* st_str_requests = "HTTP Request Packets";
351 static const guint8* st_str_responses = "HTTP Response Packets";
352 static const guint8* st_str_resp_broken = "???: broken";
353 static const guint8* st_str_resp_100 = "1xx: Informational";
354 static const guint8* st_str_resp_200 = "2xx: Success";
355 static const guint8* st_str_resp_300 = "3xx: Redirection";
356 static const guint8* st_str_resp_400 = "4xx: Client Error";
357 static const guint8* st_str_resp_500 = "5xx: Server Error";
358 static const guint8* st_str_other = "Other HTTP Packets";
359
360 static int st_node_packets = -1;
361 static int st_node_requests = -1;
362 static int st_node_responses = -1;
363 static int st_node_resp_broken = -1;
364 static int st_node_resp_100 = -1;
365 static int st_node_resp_200 = -1;
366 static int st_node_resp_300 = -1;
367 static int st_node_resp_400 = -1;
368 static int st_node_resp_500 = -1;
369 static int st_node_other = -1;
370
371
372 static void http_stats_tree_init(stats_tree* st) {
373         st_node_packets = stats_tree_create_node(st, st_str_packets, 0, TRUE);  
374         st_node_requests = stats_tree_create_pivot(st, st_str_requests, st_node_packets);
375         st_node_responses = stats_tree_create_node(st, st_str_responses, st_node_packets, TRUE);
376         st_node_resp_broken = stats_tree_create_node(st, st_str_resp_broken, st_node_responses, TRUE);
377         st_node_resp_100    = stats_tree_create_node(st, st_str_resp_100,    st_node_responses, TRUE);
378         st_node_resp_200    = stats_tree_create_node(st, st_str_resp_200,    st_node_responses, TRUE);
379         st_node_resp_300    = stats_tree_create_node(st, st_str_resp_300,    st_node_responses, TRUE);
380         st_node_resp_400    = stats_tree_create_node(st, st_str_resp_400,    st_node_responses, TRUE);
381         st_node_resp_500    = stats_tree_create_node(st, st_str_resp_500,    st_node_responses, TRUE);
382         st_node_other = stats_tree_create_node(st, st_str_other, st_node_packets,FALSE);
383 }
384
385 static int http_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p) {
386         const http_info_value_t* v = p;
387         guint i = v->response_code;
388         int resp_grp;
389         const guint8* resp_str;
390         static gchar str[64];
391         
392         tick_stat_node(st, st_str_packets, 0, FALSE);
393         
394         if (i) {
395                 tick_stat_node(st, st_str_responses, st_node_packets, FALSE);
396                 
397                 if ( (i<100)||(i>=600) ) {
398                         resp_grp = st_node_resp_broken;
399                         resp_str = st_str_resp_broken;
400                 } else if (i<200) {
401                         resp_grp = st_node_resp_100;
402                         resp_str = st_str_resp_100;
403                 } else if (i<300) {
404                         resp_grp = st_node_resp_200;
405                         resp_str = st_str_resp_200;
406                 } else if (i<400) {
407                         resp_grp = st_node_resp_300;
408                         resp_str = st_str_resp_300;
409                 } else if (i<500) {
410                         resp_grp = st_node_resp_400;
411                         resp_str = st_str_resp_400;
412                 } else {
413                         resp_grp = st_node_resp_500;
414                         resp_str = st_str_resp_500;
415                 }
416                 
417                 tick_stat_node(st, resp_str, st_node_responses, FALSE);
418                 
419                 g_snprintf(str, sizeof(str),"%u %s",i,match_strval(i,vals_status_code));
420                 tick_stat_node(st, str, resp_grp, FALSE);
421         } else if (v->request_method) {
422                 stats_tree_tick_pivot(st,st_node_requests,v->request_method);
423         } else {
424                 tick_stat_node(st, st_str_other, st_node_packets, FALSE);               
425         }
426         
427         return 1;
428 }
429
430 /* Return a tvb that contains the binary representation of a base64
431    string */
432
433 static tvbuff_t *
434 base64_to_tvb(const char *base64)
435 {
436         tvbuff_t *tvb;
437         char *data = g_strdup(base64);
438         size_t len;
439
440         len = epan_base64_decode(data);
441         tvb = tvb_new_real_data((const guint8 *)data, len, len);
442
443         tvb_set_free_cb(tvb, g_free);
444
445         return tvb;
446 }
447
448 static void
449 dissect_http_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
450     const char *line)
451 {
452         tvbuff_t *ntlmssp_tvb;
453
454         ntlmssp_tvb = base64_to_tvb(line);
455         tvb_set_child_real_data_tvbuff(tvb, ntlmssp_tvb);
456         add_new_data_source(pinfo, ntlmssp_tvb, "NTLMSSP / GSSAPI Data");
457         if (tvb_strneql(ntlmssp_tvb, 0, "NTLMSSP", 7) == 0)
458                 call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo, tree);
459         else
460                 call_dissector(gssapi_handle, ntlmssp_tvb, pinfo, tree);
461 }
462
463 /*
464  * TODO: remove this ugly global variable.
465  * XXX: do we really want to have to pass this from one function to another?
466  */
467 static http_info_value_t        *stat_info;
468
469 static int
470 dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
471     proto_tree *tree)
472 {
473         http_proto_t    proto;
474         const char      *proto_tag;
475         proto_tree      *http_tree = NULL;
476         proto_item      *ti = NULL;
477         const guchar    *line;
478         gint            next_offset;
479         const guchar    *linep, *lineend;
480         int             orig_offset;
481         int             first_linelen, linelen;
482         gboolean        is_request_or_reply;
483         gboolean        saw_req_resp_or_header;
484         guchar          c;
485         http_type_t     http_type;
486         proto_item      *hdr_item = NULL;
487         ReqRespDissector reqresp_dissector;
488         proto_tree      *req_tree;
489         int             colon_offset;
490         headers_t       headers;
491         int             datalen;
492         int             reported_datalen = -1;
493         dissector_handle_t handle;
494         gboolean        dissected;
495         /*guint         i;*/
496         guint32 framenum = pinfo->fd->num;
497         /*http_info_value_t *si;*/
498
499         /*
500          * Is this a request or response?
501          *
502          * Note that "tvb_find_line_end()" will return a value that
503          * is not longer than what's in the buffer, so the
504          * "tvb_get_ptr()" call won't throw an exception.
505          */
506         first_linelen = tvb_find_line_end(tvb, offset,
507             tvb_ensure_length_remaining(tvb, offset), &next_offset,
508             FALSE);
509         /*
510          * Is the first line a request or response?
511          */
512         line = tvb_get_ptr(tvb, offset, first_linelen);
513         http_type = HTTP_OTHERS;        /* type not known yet */
514         is_request_or_reply = is_http_request_or_reply((const gchar *)line,
515             first_linelen, &http_type, NULL);
516         if (is_request_or_reply) {
517                 /*
518                  * Yes, it's a request or response.
519                  * Do header desegmentation if we've been told to,
520                  * and do body desegmentation if we've been told to and
521                  * we find a Content-Length header.
522                  */
523                 if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
524                     http_desegment_headers, http_desegment_body)) {
525                         /*
526                          * More data needed for desegmentation.
527                          */
528                         return -1;
529                 }
530         }
531
532         /* we first allocate and initialize the current stat_info */ 
533         stat_info = ep_alloc(sizeof(http_info_value_t));
534         stat_info->framenum = framenum;
535         stat_info->response_code = 0;
536         stat_info->request_method = NULL;
537         stat_info->request_uri = NULL;
538         stat_info->http_host = NULL;
539
540         switch (pinfo->match_port) {
541
542         case TCP_PORT_SSDP:     /* TCP_PORT_SSDP = UDP_PORT_SSDP */
543                 proto = PROTO_SSDP;
544                 proto_tag = "SSDP";
545                 break;
546
547         case TCP_PORT_DAAP:     
548                 proto = PROTO_DAAP;
549                 proto_tag = "DAAP";
550                 break;
551
552         default:
553                 proto = PROTO_HTTP;
554                 proto_tag = "HTTP";
555                 break;
556         }
557
558         if (check_col(pinfo->cinfo, COL_PROTOCOL))
559                 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);
560         if (check_col(pinfo->cinfo, COL_INFO)) {
561                 /*
562                  * Put the first line from the buffer into the summary
563                  * if it's an HTTP request or reply (but leave out the
564                  * line terminator).
565                  * Otherwise, just call it a continuation.
566                  *
567                  * Note that "tvb_find_line_end()" will return a value that
568                  * is not longer than what's in the buffer, so the
569                  * "tvb_get_ptr()" call won't throw an exception.
570                  */
571                 line = tvb_get_ptr(tvb, offset, first_linelen);
572                 if (is_request_or_reply)
573                         col_add_str(pinfo->cinfo, COL_INFO,
574                             format_text(line, first_linelen));
575                 else
576                         col_set_str(pinfo->cinfo, COL_INFO, "Continuation or non-HTTP traffic");
577         }
578
579         orig_offset = offset;
580         if (tree) {
581                 ti = proto_tree_add_item(tree, proto_http, tvb, offset, -1,
582                     FALSE);
583                 http_tree = proto_item_add_subtree(ti, ett_http);
584         }
585
586         /*
587          * Process the packet data, a line at a time.
588          */
589         http_type = HTTP_OTHERS;        /* type not known yet */
590         headers.content_type = NULL;    /* content type not known yet */
591         headers.content_type_parameters = NULL; /* content type parameters too */
592         headers.have_content_length = FALSE;    /* content length not known yet */
593         headers.content_encoding = NULL; /* content encoding not known yet */
594         headers.transfer_encoding = NULL; /* transfer encoding not known yet */
595         saw_req_resp_or_header = FALSE; /* haven't seen anything yet */
596         while (tvb_reported_length_remaining(tvb, offset) != 0) {
597                 /*
598                  * Find the end of the line.
599                  * XXX - what if we don't find it because the packet
600                  * is cut short by a snapshot length or the header is
601                  * split across TCP segments?  How much dissection should
602                  * we do on it?
603                  */
604                 linelen = tvb_find_line_end(tvb, offset,
605                     tvb_ensure_length_remaining(tvb, offset), &next_offset,
606                     FALSE);
607                 if (linelen < 0)
608                         return -1;
609
610                 /*
611                  * Get a buffer that refers to the line.
612                  */
613                 line = tvb_get_ptr(tvb, offset, linelen);
614                 lineend = line + linelen;
615                 colon_offset = -1;
616
617                 /*
618                  * OK, does it look like an HTTP request or response?
619                  */
620                 reqresp_dissector = NULL;
621                 is_request_or_reply =
622                     is_http_request_or_reply((const gchar *)line,
623                     linelen, &http_type, &reqresp_dissector);
624                 if (is_request_or_reply)
625                         goto is_http;
626
627                 /*
628                  * No.  Does it look like a blank line (as would appear
629                  * at the end of an HTTP request)?
630                  */
631                 if (linelen == 0)
632                         goto is_http;   /* Yes. */
633
634                 /*
635                  * No.  Does it look like a header?
636                  */
637                 linep = line;
638                 colon_offset = offset;
639                 while (linep < lineend) {
640                         c = *linep++;
641
642                         /*
643                          * This must be a CHAR to be part of a token; that
644                          * means it must be ASCII.
645                          */
646                         if (!isascii(c))
647                                 break;  /* not ASCII, thus not a CHAR */
648
649                         /*
650                          * This mustn't be a CTL to be part of a token.
651                          *
652                          * XXX - what about leading LWS on continuation
653                          * lines of a header?
654                          */
655                         if (iscntrl(c))
656                                 break;  /* CTL, not part of a header */
657
658                         /*
659                          * This mustn't be a SEP to be part of a token;
660                          * a ':' ends the token, everything else is an
661                          * indication that this isn't a header.
662                          */
663                         switch (c) {
664
665                         case '(':
666                         case ')':
667                         case '<':
668                         case '>':
669                         case '@':
670                         case ',':
671                         case ';':
672                         case '\\':
673                         case '"':
674                         case '/':
675                         case '[':
676                         case ']':
677                         case '?':
678                         case '=':
679                         case '{':
680                         case '}':
681                         case ' ':
682                                 /*
683                                  * It's a separator, so it's not part of a
684                                  * token, so it's not a field name for the
685                                  * beginning of a header.
686                                  *
687                                  * (We don't have to check for HT; that's
688                                  * already been ruled out by "iscntrl()".)
689                                  */
690                                 goto not_http;
691
692                         case ':':
693                                 /*
694                                  * This ends the token; we consider this
695                                  * to be a header.
696                                  */
697                                 goto is_http;
698
699                         default:
700                                 colon_offset++;
701                                 break;
702                         }
703                 }
704
705                 /*
706                  * We haven't seen the colon, but everything else looks
707                  * OK for a header line.
708                  *
709                  * If we've already seen an HTTP request or response
710                  * line, or a header line, and we're at the end of
711                  * the tvbuff, we assume this is an incomplete header
712                  * line.  (We quit this loop after seeing a blank line,
713                  * so if we've seen a request or response line, or a
714                  * header line, this is probably more of the request
715                  * or response we're presumably seeing.  There is some
716                  * risk of false positives, but the same applies for
717                  * full request or response lines or header lines,
718                  * although that's less likely.)
719                  *
720                  * We throw an exception in that case, by checking for
721                  * the existence of the next byte after the last one
722                  * in the line.  If it exists, "tvb_ensure_bytes_exist()"
723                  * throws no exception, and we fall through to the
724                  * "not HTTP" case.  If it doesn't exist,
725                  * "tvb_ensure_bytes_exist()" will throw the appropriate
726                  * exception.
727                  */
728                 if (saw_req_resp_or_header)
729                         tvb_ensure_bytes_exist(tvb, offset, linelen + 1);
730
731         not_http:
732                 /*
733                  * We don't consider this part of an HTTP request or
734                  * reply, so we don't display it.
735                  * (Yeah, that means we don't display, say, a text/http
736                  * page, but you can get that from the data pane.)
737                  */
738                 break;
739
740         is_http:
741                 /*
742                  * Process this line.
743                  */
744                 if (linelen == 0) {
745                         /*
746                          * This is a blank line, which means that
747                          * whatever follows it isn't part of this
748                          * request or reply.
749                          */
750                         proto_tree_add_text(http_tree, tvb, offset,
751                             next_offset - offset, "%s",
752                             tvb_format_text(tvb, offset, next_offset - offset));
753                         offset = next_offset;
754                         break;
755                 }
756
757                 /*
758                  * Not a blank line - either a request, a reply, or a header
759                  * line.
760                  */
761                 saw_req_resp_or_header = TRUE;
762                 if (is_request_or_reply) {
763                         if (tree) {
764                                 hdr_item = proto_tree_add_text(http_tree, tvb,
765                                     offset, next_offset - offset, "%s",
766                                     tvb_format_text(tvb, offset,
767                                       next_offset - offset));
768                         }
769                         expert_add_info_format(pinfo, hdr_item, PI_SEQUENCE, PI_CHAT, 
770                                 "%s",
771                                 tvb_format_text(tvb, offset, next_offset - offset));
772                         if (reqresp_dissector) {
773                                 if (tree) req_tree = proto_item_add_subtree(hdr_item, ett_http_request);
774                                 else req_tree = NULL;
775                                 
776                                 reqresp_dissector(tvb, req_tree, offset, line, lineend);
777                         }
778                 } else {
779                         /*
780                          * Header.
781                          */
782                         process_header(tvb, offset, next_offset, line, linelen,
783                             colon_offset, pinfo, http_tree, &headers);
784                 }
785                 offset = next_offset;
786         }
787
788         if (tree) {
789                 switch (http_type) {
790
791                 case HTTP_NOTIFICATION:
792                         proto_tree_add_boolean_hidden(http_tree,
793                             hf_http_notification, tvb, 0, 0, 1);
794                         break;
795
796                 case HTTP_RESPONSE:
797                         proto_tree_add_boolean_hidden(http_tree,
798                             hf_http_response, tvb, 0, 0, 1);
799                         break;
800
801                 case HTTP_REQUEST:
802                         proto_tree_add_boolean_hidden(http_tree,
803                             hf_http_request, tvb, 0, 0, 1);
804                         break;
805
806                 case HTTP_OTHERS:
807                 default:
808                         break;
809                 }
810         }
811
812         /*
813          * If a content length was supplied, the amount of data to be
814          * processed as HTTP payload is the minimum of the content
815          * length and the amount of data remaining in the frame.
816          *
817          * If no content length was supplied (or if a bad content length
818          * was supplied), the amount of data to be processed is the amount
819          * of data remaining in the frame.
820          *
821          * If there was no Content-Length entity header, we should
822          * accumulate all data until the end of the connection.
823          * That'd require that the TCP dissector call subdissectors
824          * for all frames with FIN, even if they contain no data,
825          * which would require subdissectors to deal intelligently
826          * with empty segments.
827          *
828          * Acccording to RFC 2616, however, 1xx responses, 204 responses,
829          * and 304 responses MUST NOT include a message body; if no
830          * content length is specified for them, we don't attempt to
831          * dissect the body.
832          *
833          * XXX - it says the same about responses to HEAD requests;
834          * unless there's a way to determine from the response
835          * whether it's a response to a HEAD request, we have to
836          * keep information about the request and associate that with
837          * the response in order to handle that.
838          */
839         datalen = tvb_length_remaining(tvb, offset);
840         if (headers.have_content_length && headers.content_length != -1) {
841                 if (datalen > headers.content_length)
842                         datalen = headers.content_length;
843
844                 /*
845                  * XXX - limit the reported length in the tvbuff we'll
846                  * hand to a subdissector to be no greater than the
847                  * content length.
848                  *
849                  * We really need both unreassembled and "how long it'd
850                  * be if it were reassembled" lengths for tvbuffs, so
851                  * that we throw the appropriate exceptions for
852                  * "not enough data captured" (running past the length),
853                  * "packet needed reassembly" (within the length but
854                  * running past the unreassembled length), and
855                  * "packet is malformed" (running past the reassembled
856                  * length).
857                  */
858                 reported_datalen = tvb_reported_length_remaining(tvb, offset);
859                 if (reported_datalen > headers.content_length)
860                         reported_datalen = headers.content_length;
861         } else {
862                 switch (http_type) {
863
864                 case HTTP_REQUEST:
865                         /*
866                          * Requests have no content if there's no
867                          * Content-Length header and no Transfer-Encoding
868                          * header.
869                          */
870                         if (headers.transfer_encoding == NULL)
871                                 datalen = 0;
872                         else
873                                 reported_datalen = -1;
874                         break;
875
876                 case HTTP_RESPONSE:
877                         if ((stat_info->response_code/100) == 1 ||
878                             stat_info->response_code == 204 ||
879                             stat_info->response_code == 304)
880                                 datalen = 0;    /* no content! */
881                         else {
882                                 /*
883                                  * XXX - responses to HEAD requests,
884                                  * and possibly other responses,
885                                  * "MUST NOT" include a
886                                  * message-body.
887                                  */
888                                 reported_datalen = -1;
889                         }
890                         break;
891
892                 default:
893                         /*
894                          * XXX - what about HTTP_NOTIFICATION?
895                          */
896                         reported_datalen = -1;
897                         break;
898                 }
899         }
900
901         if (datalen > 0) {
902                 /*
903                  * There's stuff left over; process it.
904                  */
905                 tvbuff_t *next_tvb;
906                 void *save_private_data = NULL;
907                 gint chunks_decoded = 0;
908
909                 /*
910                  * Create a tvbuff for the payload.
911                  *
912                  * The amount of data to be processed that's
913                  * available in the tvbuff is "datalen", which
914                  * is the minimum of the amount of data left in
915                  * the tvbuff and any specified content length.
916                  *
917                  * The amount of data to be processed that's in
918                  * this frame, regardless of whether it was
919                  * captured or not, is "reported_datalen",
920                  * which, if no content length was specified,
921                  * is -1, i.e. "to the end of the frame.
922                  */
923                 next_tvb = tvb_new_subset(tvb, offset, datalen,
924                     reported_datalen);
925                 /*
926                  * BEWARE - next_tvb is a subset of another tvb,
927                  * so we MUST NOT attempt tvb_free(next_tvb);
928                  */
929
930                 /*
931                  * Handle *transfer* encodings other than "identity".
932                  */
933                 if (headers.transfer_encoding != NULL &&
934                     strcasecmp(headers.transfer_encoding, "identity") != 0) {
935                         if (http_dechunk_body &&
936                             (strncasecmp(headers.transfer_encoding, "chunked", 7)
937                             == 0)) {
938
939                                 chunks_decoded = chunked_encoding_dissector(
940                                     &next_tvb, pinfo, http_tree, 0);
941
942                                 if (chunks_decoded <= 0) {
943                                         /*
944                                          * The chunks weren't reassembled,
945                                          * or there was a single zero
946                                          * length chunk.
947                                          */
948                                         goto body_dissected;
949                                 } else {
950                                         /*
951                                          * Add a new data source for the
952                                          * de-chunked data.
953                                          */
954                                         tvb_set_child_real_data_tvbuff(tvb,
955                                                 next_tvb);
956                                         add_new_data_source(pinfo, next_tvb,
957                                                 "De-chunked entity body");
958                                 }
959                         } else {
960                                 /*
961                                  * We currently can't handle, for example,
962                                  * "gzip", "compress", or "deflate" as
963                                  * *transfer* encodings; just handle them
964                                  * as data for now.
965                                  */
966                                 call_dissector(data_handle, next_tvb, pinfo,
967                                     http_tree);
968                                 goto body_dissected;
969                         }
970                 }
971                 /*
972                  * At this point, any chunked *transfer* coding has been removed
973                  * (the entity body has been dechunked) so it can be presented
974                  * for the following operation (*content* encoding), or it has
975                  * been been handed off to the data dissector.
976                  *
977                  * Handle *content* encodings other than "identity" (which
978                  * shouldn't appear in a Content-Encoding header, but
979                  * we handle it in any case).
980                  */
981                 if (headers.content_encoding != NULL &&
982                     strcasecmp(headers.content_encoding, "identity") != 0) {
983                         /*
984                          * We currently can't handle, for example, "compress";
985                          * just handle them as data for now.
986                          *
987                          * After July 7, 2004 the LZW patent expires, so support
988                          * might be added then.  However, I don't think that
989                          * anybody ever really implemented "compress", due to
990                          * the aforementioned patent.
991                          */
992                         tvbuff_t *uncomp_tvb = NULL;
993                         proto_item *e_ti = NULL;
994                         proto_tree *e_tree = NULL;
995
996                         if (http_decompress_body &&
997                             (strcasecmp(headers.content_encoding, "gzip") == 0 ||
998                             strcasecmp(headers.content_encoding, "deflate")
999                             == 0)) {
1000
1001                                 uncomp_tvb = tvb_uncompress(next_tvb, 0,
1002                                     tvb_length(next_tvb));
1003                         }
1004
1005                         /*
1006                          * Add the encoded entity to the protocol tree
1007                          */
1008                         e_ti = proto_tree_add_text(http_tree, next_tvb,
1009                                         0, tvb_length(next_tvb),
1010                                         "Content-encoded entity body (%s): %u bytes",
1011                                         headers.content_encoding,
1012                     tvb_length(next_tvb));
1013                         e_tree = proto_item_add_subtree(e_ti,
1014                                         ett_http_encoded_entity);
1015
1016                         if (uncomp_tvb != NULL) {
1017                                 /*
1018                                  * Decompression worked
1019                                  */
1020
1021                                 /* XXX - Don't free this, since it's possible
1022                                  * that the data was only partially
1023                                  * decompressed, such as when desegmentation
1024                                  * isn't enabled.
1025                                  *
1026                                 tvb_free(next_tvb);
1027                                 */
1028                 proto_item_append_text(e_ti, " -> %u bytes", tvb_length(uncomp_tvb));
1029                                 next_tvb = uncomp_tvb;
1030                                 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1031                                 add_new_data_source(pinfo, next_tvb,
1032                                     "Uncompressed entity body");
1033                         } else {
1034                                 if (chunks_decoded > 1) {
1035                                         tvb_set_child_real_data_tvbuff(tvb,
1036                                             next_tvb);
1037                                         add_new_data_source(pinfo, next_tvb,
1038                                             "Compressed entity body");
1039                                 }
1040                                 call_dissector(data_handle, next_tvb, pinfo,
1041                                     e_tree);
1042
1043                                 goto body_dissected;
1044                         }
1045                 }
1046                 /*
1047                  * Note that a new data source is added for the entity body
1048                  * only if it was content-encoded and/or transfer-encoded.
1049                  */
1050
1051                 /*
1052                  * Do subdissector checks.
1053                  *
1054                  * First, check whether some subdissector asked that they
1055                  * be called if something was on some particular port.
1056                  */
1057                 handle = dissector_get_port_handle(port_subdissector_table,
1058                     pinfo->match_port);
1059                 if (handle == NULL && headers.content_type != NULL) {
1060                         /*
1061                          * We didn't find any subdissector that
1062                          * registered for the port, and we have a
1063                          * Content-Type value.  Is there any subdissector
1064                          * for that content type?
1065                          */
1066                         save_private_data = pinfo->private_data;
1067
1068                         if (headers.content_type_parameters)
1069                                 pinfo->private_data = ep_strdup(headers.content_type_parameters);
1070                         else
1071                                 pinfo->private_data = NULL;
1072                         /*
1073                          * Calling the string handle for the media type
1074                          * dissector table will set pinfo->match_string
1075                          * to headers.content_type for us.
1076                          */
1077                         pinfo->match_string = headers.content_type;
1078                         handle = dissector_get_string_handle(
1079                             media_type_subdissector_table,
1080                             headers.content_type);
1081                         /*
1082                          * Calling the default media handle otherwise
1083                          */
1084                         if (handle == NULL) {
1085                             handle = media_handle;
1086                         }
1087                 }
1088                 if (handle != NULL) {
1089                         /*
1090                          * We have a subdissector - call it.
1091                          */
1092                         dissected = call_dissector(handle, next_tvb, pinfo,
1093                             tree);
1094                 } else {
1095                         /*
1096                          * We don't have a subdissector - try the heuristic
1097                          * subdissectors.
1098                          */
1099                         dissected = dissector_try_heuristic(
1100                             heur_subdissector_list, next_tvb, pinfo, tree);
1101                 }
1102                 if (dissected) {
1103                         /*
1104                          * The subdissector dissected the body.
1105                          * Fix up the top-level item so that it doesn't
1106                          * include the stuff for that protocol.
1107                          */
1108                         if (ti != NULL)
1109                                 proto_item_set_len(ti, offset);
1110                 } else {
1111                         call_dissector(data_handle, next_tvb, pinfo,
1112                             http_tree);
1113                 }
1114
1115         body_dissected:
1116                 /*
1117                  * Do *not* attempt at freeing the private data;
1118                  * it may be in use by subdissectors.
1119                  */
1120                 if (save_private_data)
1121                         pinfo->private_data = save_private_data;
1122                 /*
1123                  * We've processed "datalen" bytes worth of data
1124                  * (which may be no data at all); advance the
1125                  * offset past whatever data we've processed.
1126                  */
1127                 offset += datalen;
1128         }
1129
1130         tap_queue_packet(http_tap, pinfo, stat_info);
1131
1132         return offset - orig_offset;
1133 }
1134
1135 /* This can be used to dissect an HTTP request until such time
1136  * that a more complete dissector is written for that HTTP request.
1137  * This simple dissector only puts the request method, URI, and
1138  * protocol version into a sub-tree.
1139  */
1140 static void
1141 basic_request_dissector(tvbuff_t *tvb, proto_tree *tree, int offset,
1142     const guchar *line, const guchar *lineend)
1143 {
1144         const guchar *next_token;
1145         int tokenlen;
1146         
1147         /* The first token is the method. */
1148         tokenlen = get_token_len(line, lineend, &next_token);
1149         if (tokenlen == 0)
1150                 return;
1151         proto_tree_add_item(tree, hf_http_request_method, tvb, offset, tokenlen,
1152             FALSE);
1153         offset += next_token - line;
1154         line = next_token;
1155
1156         /* The next token is the URI. */
1157         tokenlen = get_token_len(line, lineend, &next_token);
1158         if (tokenlen == 0)
1159                 return;
1160         stat_info->request_uri = (gchar*) tvb_get_ephemeral_string(tvb, offset, tokenlen);
1161         proto_tree_add_string(tree, hf_http_request_uri, tvb, offset, tokenlen,
1162             stat_info->request_uri);
1163         offset += next_token - line;
1164         line = next_token;
1165
1166         /* Everything to the end of the line is the version. */
1167         tokenlen = lineend - line;
1168         if (tokenlen == 0)
1169                 return;
1170         proto_tree_add_item(tree, hf_http_version, tvb, offset, tokenlen,
1171             FALSE);
1172 }
1173
1174 static void
1175 basic_response_dissector(tvbuff_t *tvb, proto_tree *tree, int offset,
1176     const guchar *line, const guchar *lineend)
1177 {
1178         const guchar *next_token;
1179         int tokenlen;
1180         gchar response_chars[4];
1181         
1182         /* The first token is the version. */
1183         tokenlen = get_token_len(line, lineend, &next_token);
1184         if (tokenlen == 0)
1185                 return;
1186         proto_tree_add_item(tree, hf_http_version, tvb, offset, tokenlen,
1187             FALSE);
1188         offset += next_token - line;
1189         line = next_token;
1190
1191         /* The next token is the status code. */
1192         tokenlen = get_token_len(line, lineend, &next_token);
1193         if (tokenlen < 3)
1194                 return;
1195         memcpy(response_chars, line, 3);
1196         response_chars[3] = '\0';
1197         
1198         stat_info->response_code = strtoul(response_chars,NULL,10);
1199         
1200         proto_tree_add_uint(tree, hf_http_response_code, tvb, offset, 3,
1201             stat_info->response_code);
1202 }
1203
1204 /*
1205  * Dissect the http data chunks and add them to the tree.
1206  */
1207 static int
1208 chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
1209     proto_tree *tree, int offset)
1210 {
1211         guint8 *chunk_string = NULL;
1212         guint32 chunk_size = 0;
1213         gint chunk_offset = 0;
1214         guint32 datalen = 0;
1215         gint linelen = 0;
1216         gint chunks_decoded = 0;
1217         tvbuff_t *tvb = NULL;
1218         tvbuff_t *new_tvb = NULL;
1219         gint chunked_data_size = 0;
1220         proto_tree *subtree = NULL;
1221         proto_item *ti = NULL;
1222
1223         if (tvb_ptr == NULL || *tvb_ptr == NULL) {
1224                 return 0;
1225         }
1226
1227         tvb = *tvb_ptr;
1228
1229         datalen = tvb_reported_length_remaining(tvb, offset);
1230
1231         if (tree) {
1232                 ti = proto_tree_add_text(tree, tvb, offset, datalen,
1233                     "HTTP chunked response");
1234                 subtree = proto_item_add_subtree(ti, ett_http_chunked_response);
1235         }
1236
1237
1238         while (datalen != 0) {
1239                 proto_item *chunk_ti = NULL;
1240                 proto_tree *chunk_subtree = NULL;
1241                 tvbuff_t *data_tvb = NULL;
1242                 gchar *c = NULL;
1243
1244                 linelen = tvb_find_line_end(tvb, offset, -1, &chunk_offset, TRUE);
1245
1246                 if (linelen <= 0) {
1247                         /* Can't get the chunk size line */
1248                         break;
1249                 }
1250
1251                 chunk_string = tvb_get_ephemeral_string(tvb, offset, linelen);
1252
1253                 if (chunk_string == NULL) {
1254                         /* Can't get the chunk size line */
1255                         break;
1256                 }
1257
1258                 c = (gchar*) chunk_string;
1259
1260                 /*
1261                  * We don't care about the extensions.
1262                  */
1263                 if ((c = strchr(c, ';'))) {
1264                         *c = '\0';
1265                 }
1266
1267                 if ( ( chunk_size = strtol((gchar*)chunk_string, NULL, 16) ) == 0 ) {
1268                         break;
1269                 }
1270
1271
1272                 if (chunk_size > datalen) {
1273                         /*
1274                          * The chunk size is more than what's in the tvbuff,
1275                          * so either the user hasn't enabled decoding, or all
1276                          * of the segments weren't captured.
1277                          */
1278                         chunk_size = datalen;
1279                 }/* else if (new_tvb == NULL) {
1280                         new_tvb = tvb_new_composite();
1281                 }
1282
1283
1284
1285                 if (new_tvb != NULL && chunk_size != 0) {
1286                         tvbuff_t *chunk_tvb = NULL;
1287
1288                         chunk_tvb = tvb_new_subset(tvb, chunk_offset,
1289                             chunk_size, datalen);
1290
1291                         tvb_composite_append(new_tvb, chunk_tvb);
1292
1293                 }
1294                 */
1295
1296                 chunked_data_size += chunk_size;
1297
1298                 if (chunk_size != 0) {
1299                         guint8 *raw_data = g_malloc(chunked_data_size);
1300                         gint raw_len = 0;
1301
1302                         if (new_tvb != NULL) {
1303                                 raw_len = tvb_length_remaining(new_tvb, 0);
1304                                 tvb_memcpy(new_tvb, raw_data, 0, raw_len);
1305
1306                                 tvb_free(new_tvb);
1307                         }
1308
1309                         tvb_memcpy(tvb, (guint8 *)(raw_data + raw_len),
1310                             chunk_offset, chunk_size);
1311
1312                         new_tvb = tvb_new_real_data(raw_data,
1313                             chunked_data_size, chunked_data_size);
1314                         tvb_set_free_cb(new_tvb, g_free);
1315
1316                 }
1317
1318                 if (subtree) {
1319                         if (chunk_size == 0) {
1320                                 chunk_ti = proto_tree_add_text(subtree, tvb,
1321                                     offset,
1322                                     chunk_offset - offset + chunk_size + 2,
1323                                     "Data chunk (last chunk)");
1324                         } else {
1325                                 chunk_ti = proto_tree_add_text(subtree, tvb,
1326                                     offset,
1327                                     chunk_offset - offset + chunk_size + 2,
1328                                     "Data chunk (%u octets)", chunk_size);
1329                         }
1330
1331                         chunk_subtree = proto_item_add_subtree(chunk_ti,
1332                             ett_http_chunk_data);
1333
1334                         proto_tree_add_text(chunk_subtree, tvb, offset,
1335                             chunk_offset - offset, "Chunk size: %u octets",
1336                             chunk_size);
1337
1338                         data_tvb = tvb_new_subset(tvb, chunk_offset, chunk_size,
1339                             datalen);
1340
1341
1342                         if (chunk_size > 0) {
1343                                 /*
1344                                  * XXX - just use "proto_tree_add_text()"?
1345                                  * This means that, in TShark, you get
1346                                  * the entire chunk dumped out in hex,
1347                                  * in addition to whatever dissection is
1348                                  * done on the reassembled data.
1349                                  */
1350                                 call_dissector(data_handle, data_tvb, pinfo,
1351                                     chunk_subtree);
1352                         }
1353
1354                         proto_tree_add_text(chunk_subtree, tvb, chunk_offset +
1355                             chunk_size, 2, "Chunk boundary");
1356                 }
1357
1358                 chunks_decoded++;
1359                 offset = chunk_offset + chunk_size + 2;
1360                 datalen = tvb_reported_length_remaining(tvb, offset);
1361         }
1362
1363         if (new_tvb != NULL) {
1364
1365                 /* Placeholder for the day that composite tvbuffer's will work.
1366                 tvb_composite_finalize(new_tvb);
1367                 / * tvb_set_reported_length(new_tvb, chunked_data_size); * /
1368                 */
1369
1370                 /*
1371                  * XXX - Don't free this, since the tvbuffer that was passed
1372                  * may be used if the data spans multiple frames and reassembly
1373                  * isn't enabled.
1374                  *
1375                 tvb_free(*tvb_ptr);
1376                  */
1377                 *tvb_ptr = new_tvb;
1378
1379         } else {
1380                 /*
1381                  * We didn't create a new tvb, so don't allow sub dissectors
1382                  * try to decode the non-existant entity body.
1383                  */
1384                 chunks_decoded = -1;
1385         }
1386
1387         return chunks_decoded;
1388
1389 }
1390
1391
1392 /*
1393  * XXX - this won't handle HTTP 0.9 replies, but they're all data
1394  * anyway.
1395  */
1396 static int
1397 is_http_request_or_reply(const gchar *data, int linelen, http_type_t *type,
1398                 ReqRespDissector *reqresp_dissector)
1399 {
1400         int isHttpRequestOrReply = FALSE;
1401         int prefix_len = 0;
1402
1403         /*
1404          * From RFC 2774 - An HTTP Extension Framework
1405          *
1406          * Support the command prefix that identifies the presence of
1407          * a "mandatory" header.
1408          */
1409         if (linelen >= 2 && strncmp(data, "M-", 2) == 0) {
1410                 data += 2;
1411                 linelen -= 2;
1412                 prefix_len = 2;
1413         }
1414
1415         /*
1416          * From draft-cohen-gena-client-01.txt, available from the uPnP forum:
1417          *      NOTIFY, SUBSCRIBE, UNSUBSCRIBE
1418          *
1419          * From draft-ietf-dasl-protocol-00.txt, a now vanished Microsoft draft:
1420          *      SEARCH
1421          */
1422         if (linelen >= 5 && strncmp(data, "HTTP/", 5) == 0) {
1423                 *type = HTTP_RESPONSE;
1424                 isHttpRequestOrReply = TRUE;    /* response */
1425                 if (reqresp_dissector)
1426                         *reqresp_dissector = basic_response_dissector;
1427         } else {
1428                 const guchar * ptr = (const guchar *)data;
1429                 int              index = 0;
1430
1431                 /* Look for the space following the Method */
1432                 while (index < linelen) {
1433                         if (*ptr == ' ')
1434                                 break;
1435                         else {
1436                                 ptr++;
1437                                 index++;
1438                         }
1439                 }
1440
1441                 /* Check the methods that have same length */
1442                 switch (index) {
1443
1444                 case 3:
1445                         if (strncmp(data, "GET", index) == 0 ||
1446                             strncmp(data, "PUT", index) == 0) {
1447                                 *type = HTTP_REQUEST;
1448                                 isHttpRequestOrReply = TRUE;
1449                         }
1450                         else if (strncmp(data, "ICY", index) == 0) {
1451                                 *type = HTTP_RESPONSE;
1452                                 isHttpRequestOrReply = TRUE;
1453                         }
1454                         break;
1455
1456                 case 4:
1457                         if (strncmp(data, "COPY", index) == 0 ||
1458                             strncmp(data, "HEAD", index) == 0 ||
1459                             strncmp(data, "LOCK", index) == 0 ||
1460                             strncmp(data, "MOVE", index) == 0 ||
1461                             strncmp(data, "POLL", index) == 0 ||
1462                             strncmp(data, "POST", index) == 0) {
1463                                 *type = HTTP_REQUEST;
1464                                 isHttpRequestOrReply = TRUE;
1465                         }
1466                         break;
1467
1468                 case 5:
1469                         if (strncmp(data, "BCOPY", index) == 0 ||
1470                                 strncmp(data, "BMOVE", index) == 0 ||
1471                                 strncmp(data, "MKCOL", index) == 0 ||
1472                                 strncmp(data, "TRACE", index) == 0 ||
1473                                 strncmp(data, "LABEL", index) == 0 ||  /* RFC 3253 8.2 */
1474                                 strncmp(data, "MERGE", index) == 0) {  /* RFC 3253 11.2 */
1475                                 *type = HTTP_REQUEST;
1476                                 isHttpRequestOrReply = TRUE;
1477                         }
1478                         break;
1479
1480                 case 6:
1481                         if (strncmp(data, "DELETE", index) == 0 ||
1482                                 strncmp(data, "SEARCH", index) == 0 ||
1483                                 strncmp(data, "UNLOCK", index) == 0 ||
1484                                 strncmp(data, "REPORT", index) == 0 ||  /* RFC 3253 3.6 */
1485                                 strncmp(data, "UPDATE", index) == 0) {  /* RFC 3253 7.1 */
1486                                 *type = HTTP_REQUEST;
1487                                 isHttpRequestOrReply = TRUE;
1488                         }
1489                         else if (strncmp(data, "NOTIFY", index) == 0) {
1490                                 *type = HTTP_NOTIFICATION;
1491                                 isHttpRequestOrReply = TRUE;
1492                         }
1493                         break;
1494
1495                 case 7:
1496                         if (strncmp(data, "BDELETE", index) == 0 ||
1497                             strncmp(data, "CONNECT", index) == 0 ||
1498                             strncmp(data, "OPTIONS", index) == 0 ||
1499                             strncmp(data, "CHECKIN", index) == 0) {  /* RFC 3253 4.4, 9.4 */
1500                                 *type = HTTP_REQUEST;
1501                                 isHttpRequestOrReply = TRUE;
1502                         }
1503                         break;
1504
1505                 case 8:
1506                         if (strncmp(data, "PROPFIND", index) == 0 ||
1507                             strncmp(data, "CHECKOUT", index) == 0 || /* RFC 3253 4.3, 9.3 */
1508                             strncmp(data, "CCM_POST", index) == 0) {
1509                                 *type = HTTP_REQUEST;
1510                                 isHttpRequestOrReply = TRUE;
1511                         }
1512                         break;
1513
1514                 case 9:
1515                         if (strncmp(data, "SUBSCRIBE", index) == 0) {
1516                                 *type = HTTP_NOTIFICATION;
1517                                 isHttpRequestOrReply = TRUE;
1518                         } else if (strncmp(data, "PROPPATCH", index) == 0 ||
1519                             strncmp(data, "BPROPFIND", index) == 0) {
1520                                 *type = HTTP_REQUEST;
1521                                 isHttpRequestOrReply = TRUE;
1522                         }
1523                         break;
1524
1525                 case 10:
1526                         if (strncmp(data, "BPROPPATCH", index) == 0 ||
1527                                 strncmp(data, "UNCHECKOUT", index) == 0 ||  /* RFC 3253 4.5 */
1528                                 strncmp(data, "MKACTIVITY", index) == 0) {  /* RFC 3253 13.5 */
1529                                 *type = HTTP_REQUEST;
1530                                 isHttpRequestOrReply = TRUE;
1531                         }
1532                         break;
1533
1534                 case 11:
1535                         if (strncmp(data, "MKWORKSPACE", index) == 0) {  /* RFC 3253 6.3 */
1536                                 *type = HTTP_REQUEST;
1537                                 isHttpRequestOrReply = TRUE;
1538                         } else if (strncmp(data, "UNSUBSCRIBE", index) == 0) {
1539                                 *type = HTTP_NOTIFICATION;
1540                                 isHttpRequestOrReply = TRUE;
1541                         } else if (strncmp(data, "RPC_CONNECT", index) == 0) {
1542                                 *type = HTTP_REQUEST;
1543                                 isHttpRequestOrReply = TRUE;
1544                         }
1545                         break;
1546
1547                 case 15:
1548                         if (strncmp(data, "VERSION-CONTROL", index) == 0) {  /* RFC 3253 3.5 */
1549                                 *type = HTTP_REQUEST;
1550                                 isHttpRequestOrReply = TRUE;
1551                         }
1552                         break;
1553
1554                 case 16:
1555                         if (strncmp(data, "BASELINE-CONTROL", index) == 0) {  /* RFC 3253 12.6 */
1556                                 *type = HTTP_REQUEST;
1557                                 isHttpRequestOrReply = TRUE;
1558                         }
1559                         break;
1560
1561                 default:
1562                         break;
1563                 }
1564
1565                 if (isHttpRequestOrReply && reqresp_dissector) {
1566                         *reqresp_dissector = basic_request_dissector;
1567                         if (!stat_info->request_method)
1568                                 stat_info->request_method = ep_strndup(data, index+1);
1569                 }
1570         }
1571
1572         return isHttpRequestOrReply;
1573 }
1574
1575 /*
1576  * Process headers.
1577  */
1578 typedef struct {
1579         const char      *name;
1580         gint            *hf;
1581         int             special;
1582 } header_info;
1583
1584 #define HDR_NO_SPECIAL          0
1585 #define HDR_AUTHORIZATION       1
1586 #define HDR_AUTHENTICATE        2
1587 #define HDR_CONTENT_TYPE        3
1588 #define HDR_CONTENT_LENGTH      4
1589 #define HDR_CONTENT_ENCODING    5
1590 #define HDR_TRANSFER_ENCODING   6
1591 #define HDR_HOST  7
1592
1593 static const header_info headers[] = {
1594         { "Authorization", &hf_http_authorization, HDR_AUTHORIZATION },
1595         { "Proxy-Authorization", &hf_http_proxy_authorization, HDR_AUTHORIZATION },
1596         { "Proxy-Authenticate", &hf_http_proxy_authenticate, HDR_AUTHENTICATE },
1597         { "WWW-Authenticate", &hf_http_www_authenticate, HDR_AUTHENTICATE },
1598         { "Content-Type", &hf_http_content_type, HDR_CONTENT_TYPE },
1599         { "Content-Length", &hf_http_content_length, HDR_CONTENT_LENGTH },
1600         { "Content-Encoding", &hf_http_content_encoding, HDR_CONTENT_ENCODING },
1601         { "Transfer-Encoding", &hf_http_transfer_encoding, HDR_TRANSFER_ENCODING },
1602         { "User-Agent", &hf_http_user_agent, HDR_NO_SPECIAL },
1603         { "Host", &hf_http_host, HDR_HOST },
1604         { "Connection", &hf_http_connection, HDR_NO_SPECIAL },
1605         { "Cookie", &hf_http_cookie, HDR_NO_SPECIAL },
1606         { "Accept", &hf_http_accept, HDR_NO_SPECIAL },
1607         { "Referer", &hf_http_referer, HDR_NO_SPECIAL },
1608         { "Accept-Language", &hf_http_accept_language, HDR_NO_SPECIAL },
1609         { "Accept-Encoding", &hf_http_accept_encoding, HDR_NO_SPECIAL },
1610         { "Date", &hf_http_date, HDR_NO_SPECIAL },
1611         { "Cache-Control", &hf_http_cache_control, HDR_NO_SPECIAL },
1612         { "Server", &hf_http_server, HDR_NO_SPECIAL },
1613         { "Location", &hf_http_location, HDR_NO_SPECIAL },
1614         { "Set-Cookie", &hf_http_set_cookie, HDR_NO_SPECIAL },
1615         { "Last-Modified", &hf_http_last_modified, HDR_NO_SPECIAL },
1616         { "X-Forwarded-For", &hf_http_x_forwarded_for, HDR_NO_SPECIAL },
1617 };
1618
1619 static void
1620 process_header(tvbuff_t *tvb, int offset, int next_offset,
1621     const guchar *line, int linelen, int colon_offset,
1622     packet_info *pinfo, proto_tree *tree, headers_t *eh_ptr)
1623 {
1624         int len;
1625         int line_end_offset;
1626         int header_len;
1627         gint hf_index;
1628         guchar c;
1629         int value_offset;
1630         int value_len;
1631         char *value;
1632         char *p;
1633         guchar *up;
1634         proto_item *hdr_item;
1635         int i;
1636
1637         len = next_offset - offset;
1638         line_end_offset = offset + linelen;
1639         header_len = colon_offset - offset;
1640         hf_index = find_header_hf_value(tvb, offset, header_len);
1641
1642         if (hf_index == -1) {
1643                 /*
1644                  * Not a header we know anything about.  Just put it into
1645                  * the tree as text.
1646                  */
1647                 if (tree) {
1648                         proto_tree_add_text(tree, tvb, offset, len,
1649                             "%s", format_text(line, len));
1650                 }
1651         } else {
1652                 /*
1653                  * Skip whitespace after the colon.
1654                  */
1655                 value_offset = colon_offset + 1;
1656                 while (value_offset < line_end_offset
1657                     && ((c = line[value_offset - offset]) == ' ' || c == '\t'))
1658                         value_offset++;
1659
1660                 /*
1661                  * Fetch the value.
1662                  */
1663                 value_len = line_end_offset - value_offset;
1664                 value = ep_strndup(&line[value_offset - offset], value_len);
1665
1666                 /*
1667                  * Add it to the protocol tree as a particular field,
1668                  * but display the line as is.
1669                  */
1670                 if (tree) {
1671                         hdr_item = proto_tree_add_string_format(tree,
1672                             *headers[hf_index].hf, tvb, offset, len,
1673                             value, "%s", format_text(line, len));
1674                 } else
1675                         hdr_item = NULL;
1676
1677                 /*
1678                  * Do any special processing that particular headers
1679                  * require.
1680                  */
1681                 switch (headers[hf_index].special) {
1682
1683                 case HDR_AUTHORIZATION:
1684                         if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))
1685                                 break;  /* dissected NTLMSSP */
1686                         check_auth_basic(hdr_item, tvb, value);
1687                         break;
1688
1689                 case HDR_AUTHENTICATE:
1690                         check_auth_ntlmssp(hdr_item, tvb, pinfo, value);
1691                         break;
1692
1693                 case HDR_CONTENT_TYPE:
1694                         eh_ptr->content_type = (gchar*) ep_memdup((guint8*)value,value_len + 1);
1695
1696                         for (i = 0; i < value_len; i++) {
1697                                 c = value[i];
1698                                 if (c == ';' || isspace(c)) {
1699                                         /*
1700                                          * End of subtype - either
1701                                          * white space or a ";"
1702                                          * separating the subtype from
1703                                          * a parameter.
1704                                          */
1705                                         break;
1706                                 }
1707
1708                                 /*
1709                                  * Map the character to lower case;
1710                                  * content types are case-insensitive.
1711                                  */
1712                                 eh_ptr->content_type[i] = tolower(eh_ptr->content_type[i]);
1713                         }
1714                         eh_ptr->content_type[i] = '\0';
1715                         /*
1716                          * Now find the start of the optional parameters;
1717                          * skip the optional white space and the semicolon
1718                          * if this has not been done before.
1719                          */
1720                         i++;
1721                         while (i < value_len) {
1722                                 c = eh_ptr->content_type[i];
1723                                 if (c == ';' || isspace(c))
1724                                         /* Skip till start of parameters */
1725                                         i++;
1726                                 else
1727                                         break;
1728                         }
1729                         if (i < value_len)
1730                                 eh_ptr->content_type_parameters = eh_ptr->content_type + i;
1731                         else
1732                                 eh_ptr->content_type_parameters = NULL;
1733                         break;
1734
1735                 case HDR_CONTENT_LENGTH:
1736                         eh_ptr->content_length = strtol(value, &p, 10);
1737                         up = (guchar *)p;
1738                         if (eh_ptr->content_length < 0 || p == value ||
1739                             (*up != '\0' && !isspace(*up))) {
1740                                 /*
1741                                  * Content length not valid; pretend
1742                                  * we don't have it.
1743                                  */
1744                                 eh_ptr->have_content_length = FALSE;
1745                         } else {
1746                                 /*
1747                                  * We do have a valid content length.
1748                                  */
1749                                 eh_ptr->have_content_length = TRUE;
1750                         }
1751                         break;
1752
1753                 case HDR_CONTENT_ENCODING:
1754                         eh_ptr->content_encoding = ep_strndup(value, value_len);
1755                         break;
1756
1757                 case HDR_TRANSFER_ENCODING:
1758                         eh_ptr->transfer_encoding = ep_strndup(value, value_len);
1759                         break;
1760                         
1761                 case HDR_HOST: 
1762                         stat_info->http_host = ep_strndup(value, value_len);
1763                         break;
1764                         
1765                 }
1766         }
1767 }
1768
1769 /* Returns index of header tag in headers */
1770 static gint
1771 find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len)
1772 {
1773         guint i;
1774
1775         for (i = 0; i < array_length(headers); i++) {
1776                 if (header_len == strlen(headers[i].name) &&
1777                     tvb_strncaseeql(tvb, offset,
1778                                                 headers[i].name, header_len) == 0)
1779                         return i;
1780         }
1781
1782         return -1;
1783 }
1784
1785 /*
1786  * Dissect Microsoft's abomination called NTLMSSP over HTTP.
1787  */
1788 static gboolean
1789 check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo,
1790     gchar *value)
1791 {
1792         static const char *ntlm_headers[] = {
1793                 "NTLM ",
1794                 "Negotiate ",
1795                 NULL
1796         };
1797         const char **header;
1798         size_t hdrlen;
1799         proto_tree *hdr_tree;
1800
1801         /*
1802          * Check for NTLM credentials and challenge; those can
1803          * occur with WWW-Authenticate.
1804          */
1805         for (header = &ntlm_headers[0]; *header != NULL; header++) {
1806                 hdrlen = strlen(*header);
1807                 if (strncmp(value, *header, hdrlen) == 0) {
1808                         if (hdr_item != NULL) {
1809                                 hdr_tree = proto_item_add_subtree(hdr_item,
1810                                     ett_http_ntlmssp);
1811                         } else
1812                                 hdr_tree = NULL;
1813                         value += hdrlen;
1814                         dissect_http_ntlmssp(tvb, pinfo, hdr_tree, value);
1815                         return TRUE;
1816                 }
1817         }
1818         return FALSE;
1819 }
1820
1821 /*
1822  * Dissect HTTP Basic authorization.
1823  */
1824 static gboolean
1825 check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb, gchar *value)
1826 {
1827         static const char *basic_headers[] = {
1828                 "Basic ",
1829                 NULL
1830         };
1831         const char **header;
1832         size_t hdrlen;
1833         proto_tree *hdr_tree;
1834         size_t len;
1835
1836         for (header = &basic_headers[0]; *header != NULL; header++) {
1837                 hdrlen = strlen(*header);
1838                 if (strncmp(value, *header, hdrlen) == 0) {
1839                         if (hdr_item != NULL) {
1840                                 hdr_tree = proto_item_add_subtree(hdr_item,
1841                                     ett_http_ntlmssp);
1842                         } else
1843                                 hdr_tree = NULL;
1844                         value += hdrlen;
1845
1846                         len = epan_base64_decode(value);
1847                         value[len] = '\0';
1848                         proto_tree_add_string(hdr_tree, hf_http_basic, tvb,
1849                             0, 0, value);
1850
1851                         return TRUE;
1852                 }
1853         }
1854         return FALSE;
1855 }
1856
1857 static void
1858 dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1859 {
1860         int             offset = 0;
1861         int             len;
1862
1863         while (tvb_reported_length_remaining(tvb, offset) != 0) {
1864                 len = dissect_http_message(tvb, offset, pinfo, tree);
1865                 if (len == -1)
1866                         break;
1867                 offset += len;
1868
1869                 /*
1870                  * OK, we've set the Protocol and Info columns for the
1871                  * first HTTP message; make the columns non-writable,
1872                  * so that we don't change it for subsequent HTTP messages.
1873                  */
1874                 col_set_writable(pinfo->cinfo, FALSE);
1875         }
1876 }
1877
1878 static void
1879 dissect_http_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1880 {
1881         dissect_http_message(tvb, 0, pinfo, tree);
1882 }
1883
1884 static void reinit_http(void) {
1885         if ( http_alternate_tcp_port != alternate_tcp_port ) {
1886                 
1887                 if (alternate_tcp_port)
1888                         dissector_delete("tcp.port", alternate_tcp_port, http_handle );
1889                 
1890                 if (http_alternate_tcp_port)
1891                         dissector_add("tcp.port", http_alternate_tcp_port, http_handle);
1892                 
1893                 alternate_tcp_port = http_alternate_tcp_port;
1894         }       
1895 }
1896
1897 void
1898 proto_register_http(void)
1899 {
1900         static hf_register_info hf[] = {
1901             { &hf_http_notification,
1902               { "Notification",         "http.notification",
1903                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1904                 "TRUE if HTTP notification", HFILL }},
1905             { &hf_http_response,
1906               { "Response",             "http.response",
1907                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1908                 "TRUE if HTTP response", HFILL }},
1909             { &hf_http_request,
1910               { "Request",              "http.request",
1911                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1912                 "TRUE if HTTP request", HFILL }},
1913             { &hf_http_basic,
1914               { "Credentials",          "http.authbasic",
1915                 FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1916             { &hf_http_request_method,
1917               { "Request Method",       "http.request.method",
1918                 FT_STRING, BASE_NONE, NULL, 0x0,
1919                 "HTTP Request Method", HFILL }},
1920             { &hf_http_request_uri,
1921               { "Request URI",  "http.request.uri",
1922                 FT_STRING, BASE_NONE, NULL, 0x0,
1923                 "HTTP Request-URI", HFILL }},
1924             { &hf_http_version,
1925               { "Request Version",      "http.request.version",
1926                 FT_STRING, BASE_NONE, NULL, 0x0,
1927                 "HTTP Request HTTP-Version", HFILL }},
1928             { &hf_http_response_code,
1929               { "Response Code",        "http.response.code",
1930                 FT_UINT16, BASE_DEC, NULL, 0x0,
1931                 "HTTP Response Code", HFILL }},
1932             { &hf_http_authorization,
1933               { "Authorization",        "http.authorization",
1934                 FT_STRING, BASE_NONE, NULL, 0x0,
1935                 "HTTP Authorization header", HFILL }},
1936             { &hf_http_proxy_authenticate,
1937               { "Proxy-Authenticate",   "http.proxy_authenticate",
1938                 FT_STRING, BASE_NONE, NULL, 0x0,
1939                 "HTTP Proxy-Authenticate header", HFILL }},
1940             { &hf_http_proxy_authorization,
1941               { "Proxy-Authorization",  "http.proxy_authorization",
1942                 FT_STRING, BASE_NONE, NULL, 0x0,
1943                 "HTTP Proxy-Authorization header", HFILL }},
1944             { &hf_http_www_authenticate,
1945               { "WWW-Authenticate",     "http.www_authenticate",
1946                 FT_STRING, BASE_NONE, NULL, 0x0,
1947                 "HTTP WWW-Authenticate header", HFILL }},
1948             { &hf_http_content_type,
1949               { "Content-Type", "http.content_type",
1950                 FT_STRING, BASE_NONE, NULL, 0x0,
1951                 "HTTP Content-Type header", HFILL }},
1952             { &hf_http_content_length,
1953               { "Content-Length",       "http.content_length",
1954                 FT_STRING, BASE_NONE, NULL, 0x0,
1955                 "HTTP Content-Length header", HFILL }},
1956             { &hf_http_content_encoding,
1957               { "Content-Encoding",     "http.content_encoding",
1958                 FT_STRING, BASE_NONE, NULL, 0x0,
1959                 "HTTP Content-Encoding header", HFILL }},
1960             { &hf_http_transfer_encoding,
1961               { "Transfer-Encoding",    "http.transfer_encoding",
1962                 FT_STRING, BASE_NONE, NULL, 0x0,
1963                 "HTTP Transfer-Encoding header", HFILL }},
1964             { &hf_http_user_agent,
1965               { "User-Agent",   "http.user_agent",
1966                 FT_STRING, BASE_NONE, NULL, 0x0,
1967                 "HTTP User-Agent header", HFILL }},
1968             { &hf_http_host,
1969               { "Host", "http.host",
1970                 FT_STRING, BASE_NONE, NULL, 0x0,
1971                 "HTTP Host", HFILL }},
1972             { &hf_http_connection,
1973               { "Connection",   "http.connection",
1974                 FT_STRING, BASE_NONE, NULL, 0x0,
1975                 "HTTP Connection", HFILL }},
1976             { &hf_http_cookie,
1977               { "Cookie",       "http.cookie",
1978                 FT_STRING, BASE_NONE, NULL, 0x0,
1979                 "HTTP Cookie", HFILL }},
1980             { &hf_http_accept,
1981               { "Accept",       "http.accept",
1982                 FT_STRING, BASE_NONE, NULL, 0x0,
1983                 "HTTP Accept", HFILL }},
1984             { &hf_http_referer,
1985               { "Referer",      "http.referer",
1986                 FT_STRING, BASE_NONE, NULL, 0x0,
1987                 "HTTP Referer", HFILL }},
1988             { &hf_http_accept_language,
1989               { "Accept-Language",      "http.accept_language",
1990                 FT_STRING, BASE_NONE, NULL, 0x0,
1991             "HTTP Accept Language", HFILL }},
1992             { &hf_http_accept_encoding,
1993               { "Accept Encoding",      "http.accept_encoding",
1994                 FT_STRING, BASE_NONE, NULL, 0x0,
1995                 "HTTP Accept Encoding", HFILL }},
1996             { &hf_http_date,
1997               { "Date", "http.date",
1998                 FT_STRING, BASE_NONE, NULL, 0x0,
1999                 "HTTP Date", HFILL }},
2000             { &hf_http_cache_control,
2001               { "Cache-Control",        "http.cache_control",
2002                 FT_STRING, BASE_NONE, NULL, 0x0,
2003                 "HTTP Cache Control", HFILL }},
2004             { &hf_http_server,
2005               { "Server",       "http.server",
2006                 FT_STRING, BASE_NONE, NULL, 0x0,
2007                 "HTTP Server", HFILL }},
2008             { &hf_http_location,
2009               { "Location",     "http.location",
2010                 FT_STRING, BASE_NONE, NULL, 0x0,
2011                 "HTTP Location", HFILL }},
2012             { &hf_http_set_cookie,
2013               { "Set-Cookie",   "http.set_cookie",
2014                 FT_STRING, BASE_NONE, NULL, 0x0,
2015                 "HTTP Set Cookie", HFILL }},
2016             { &hf_http_last_modified,
2017               { "Last-Modified",        "http.last_modified",
2018                 FT_STRING, BASE_NONE, NULL, 0x0,
2019                 "HTTP Last Modified", HFILL }},
2020             { &hf_http_x_forwarded_for,
2021               { "X-Forwarded-For",      "http.x_forwarded_for",
2022                 FT_STRING, BASE_NONE, NULL, 0x0,
2023                 "HTTP X-Forwarded-For", HFILL }},
2024         };
2025         static gint *ett[] = {
2026                 &ett_http,
2027                 &ett_http_ntlmssp,
2028                 &ett_http_request,
2029                 &ett_http_chunked_response,
2030                 &ett_http_chunk_data,
2031                 &ett_http_encoded_entity,
2032         };
2033         module_t *http_module;
2034
2035         proto_http = proto_register_protocol("Hypertext Transfer Protocol",
2036             "HTTP", "http");
2037         proto_register_field_array(proto_http, hf, array_length(hf));
2038         proto_register_subtree_array(ett, array_length(ett));
2039         register_dissector("http", dissect_http, proto_http);
2040         http_module = prefs_register_protocol(proto_http, reinit_http);
2041         prefs_register_bool_preference(http_module, "desegment_headers",
2042             "Reassemble HTTP headers spanning multiple TCP segments",
2043             "Whether the HTTP dissector should reassemble headers "
2044             "of a request spanning multiple TCP segments. "
2045                 "To use this option, you must also enable "
2046         "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2047             &http_desegment_headers);
2048         prefs_register_bool_preference(http_module, "desegment_body",
2049             "Reassemble HTTP bodies spanning multiple TCP segments",
2050             "Whether the HTTP dissector should use the "
2051             "\"Content-length:\" value, if present, to reassemble "
2052             "the body of a request spanning multiple TCP segments, "
2053             "and reassemble chunked data spanning multiple TCP segments. "
2054                 "To use this option, you must also enable "
2055         "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2056             &http_desegment_body);
2057         prefs_register_bool_preference(http_module, "dechunk_body",
2058             "Reassemble chunked transfer-coded bodies",
2059             "Whether to reassemble bodies of entities that are transfered "
2060             "using the \"Transfer-Encoding: chunked\" method",
2061             &http_dechunk_body);
2062 #ifdef HAVE_LIBZ
2063         prefs_register_bool_preference(http_module, "decompress_body",
2064             "Uncompress entity bodies",
2065             "Whether to uncompress entity bodies that are compressed "
2066             "using \"Content-Encoding: \"",
2067             &http_decompress_body);
2068 #endif
2069         prefs_register_uint_preference(http_module, "tcp_alternate_port",
2070                                                                    "Alternate TCP port",
2071                                                                    "Decode packets on this TCP port as HTTP",
2072                                                                    10,&http_alternate_tcp_port);
2073         
2074         http_handle = create_dissector_handle(dissect_http, proto_http);
2075
2076         /*
2077          * Dissectors shouldn't register themselves in this table;
2078          * instead, they should call "http_dissector_add()", and
2079          * we'll register the port number they specify as a port
2080          * for HTTP, and register them in our subdissector table.
2081          *
2082          * This only works for protocols such as IPP that run over
2083          * HTTP on a specific non-HTTP port.
2084          */
2085         port_subdissector_table = register_dissector_table("http.port",
2086             "TCP port for protocols using HTTP", FT_UINT16, BASE_DEC);
2087
2088         /*
2089          * Dissectors can register themselves in this table.
2090          * It's just "media_type", not "http.content_type", because
2091          * it's an Internet media type, usable by other protocols as well.
2092          */
2093         media_type_subdissector_table =
2094             register_dissector_table("media_type",
2095                 "Internet media type", FT_STRING, BASE_NONE);
2096
2097         /*
2098          * Heuristic dissectors SHOULD register themselves in
2099          * this table using the standard heur_dissector_add()
2100          * function.
2101          */
2102         register_heur_dissector_list("http", &heur_subdissector_list);
2103
2104         /*
2105          * Register for tapping
2106          */
2107         http_tap = register_tap("http");
2108 }
2109
2110 /*
2111  * Called by dissectors for protocols that run atop HTTP/TCP.
2112  */
2113 void
2114 http_dissector_add(guint32 port, dissector_handle_t handle)
2115 {
2116         /*
2117          * Register ourselves as the handler for that port number
2118          * over TCP.
2119          */
2120         dissector_add("tcp.port", port, http_handle);
2121
2122         /*
2123          * And register them in *our* table for that port.
2124          */
2125         dissector_add("http.port", port, handle);
2126 }
2127
2128 void
2129 proto_reg_handoff_http(void)
2130 {
2131         dissector_handle_t http_udp_handle;
2132
2133         data_handle = find_dissector("data");
2134         media_handle = find_dissector("media");
2135
2136         dissector_add("tcp.port", TCP_PORT_HTTP, http_handle);
2137         dissector_add("tcp.port", TCP_PORT_PROXY_HTTP, http_handle);
2138         dissector_add("tcp.port", TCP_ALT_PORT_HTTP, http_handle);
2139         dissector_add("tcp.port", TCP_RADAN_HTTP, http_handle);
2140         dissector_add("tcp.port", TCP_PORT_PROXY_ADMIN_HTTP, http_handle);
2141         dissector_add("tcp.port", TCP_PORT_HKP, http_handle);
2142
2143         /*
2144          * XXX - is there anything to dissect in the body of an SSDP
2145          * request or reply?  I.e., should there be an SSDP dissector?
2146          */
2147         dissector_add("tcp.port", TCP_PORT_SSDP, http_handle);
2148         http_udp_handle = create_dissector_handle(dissect_http_udp, proto_http);
2149         dissector_add("udp.port", UDP_PORT_SSDP, http_udp_handle);
2150
2151         ntlmssp_handle = find_dissector("ntlmssp");
2152         gssapi_handle = find_dissector("gssapi");
2153         
2154         stats_tree_register("http","http","HTTP/Packet Counter", http_stats_tree_packet, http_stats_tree_init, NULL );
2155         stats_tree_register("http","http_req","HTTP/Requests", http_req_stats_tree_packet, http_req_stats_tree_init, NULL );
2156         stats_tree_register("http","http_srv","HTTP/Load Distribution",http_reqs_stats_tree_packet,http_reqs_stats_tree_init, NULL );
2157         
2158 }
2159
2160 /*
2161  * Content-Type: message/http
2162  */
2163
2164 static gint proto_message_http = -1;
2165 static gint ett_message_http = -1;
2166 static dissector_handle_t message_http_handle;
2167
2168 static void
2169 dissect_message_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2170 {
2171         proto_tree      *subtree;
2172         proto_item      *ti;
2173         gint            offset = 0, next_offset;
2174         gint            len;
2175
2176         if (check_col(pinfo->cinfo, COL_INFO))
2177                 col_append_str(pinfo->cinfo, COL_INFO, " (message/http)");
2178         if (tree) {
2179                 ti = proto_tree_add_item(tree, proto_message_http,
2180                                 tvb, 0, -1, FALSE);
2181                 subtree = proto_item_add_subtree(ti, ett_message_http);
2182                 while (tvb_reported_length_remaining(tvb, offset) != 0) {
2183                         len = tvb_find_line_end(tvb, offset,
2184                                         tvb_ensure_length_remaining(tvb, offset),
2185                                         &next_offset, FALSE);
2186                         if (len == -1)
2187                                 break;
2188                         proto_tree_add_text(subtree, tvb, offset, next_offset - offset,
2189                                         "%s", tvb_format_text(tvb, offset, len));
2190                         offset = next_offset;
2191                 }
2192         }
2193 }
2194
2195 void
2196 proto_register_message_http(void)
2197 {
2198         static gint *ett[] = {
2199                 &ett_message_http,
2200         };
2201
2202         proto_message_http = proto_register_protocol(
2203                         "Media Type: message/http",
2204                         "message/http",
2205                         "message-http"
2206         );
2207         proto_register_subtree_array(ett, array_length(ett));
2208         message_http_handle = create_dissector_handle(dissect_message_http,
2209                         proto_message_http);
2210 }
2211
2212 void
2213 proto_reg_handoff_message_http(void)
2214 {
2215         message_http_handle = create_dissector_handle(dissect_message_http,
2216                         proto_message_http);
2217
2218         dissector_add_string("media_type", "message/http", message_http_handle);
2219 }