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