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