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