2 * Routines for HTTP packet disassembly
4 * Guy Harris <guy@alum.mit.edu>
6 * $Id: packet-http.c,v 1.47 2002/04/01 21:12:30 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_SYS_TYPES_H
32 #include <sys/types.h>
39 #include <epan/packet.h>
40 #include <epan/strutil.h>
42 #include "packet-http.h"
44 typedef enum _http_type {
51 static int proto_http = -1;
52 static int hf_http_notification = -1;
53 static int hf_http_response = -1;
54 static int hf_http_request = -1;
56 static gint ett_http = -1;
58 static dissector_handle_t data_handle;
59 static dissector_handle_t http_handle;
61 #define TCP_PORT_HTTP 80
62 #define TCP_PORT_PROXY_HTTP 3128
63 #define TCP_PORT_PROXY_ADMIN_HTTP 3132
64 #define TCP_ALT_PORT_HTTP 8080
67 * SSDP is implemented atop HTTP (yes, it really *does* run over UDP).
69 #define TCP_PORT_SSDP 1900
70 #define UDP_PORT_SSDP 1900
73 * Protocols implemented atop HTTP.
76 PROTO_HTTP, /* just HTTP */
77 PROTO_SSDP /* Simple Service Discovery Protocol */
80 static int is_http_request_or_reply(const u_char *data, int linelen, http_type_t *type);
82 static dissector_table_t subdissector_table;
83 static heur_dissector_list_t heur_subdissector_list;
86 dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
90 proto_tree *http_tree = NULL;
91 proto_item *ti = NULL;
95 const u_char *linep, *lineend;
98 http_type_t http_type;
101 switch (pinfo->match_port) {
103 case TCP_PORT_SSDP: /* TCP_PORT_SSDP = UDP_PORT_SSDP */
114 if (check_col(pinfo->cinfo, COL_PROTOCOL))
115 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);
116 if (check_col(pinfo->cinfo, COL_INFO)) {
118 * Put the first line from the buffer into the summary
119 * if it's an HTTP request or reply (but leave out the
121 * Otherwise, just call it a continuation.
123 * Note that "tvb_find_line_end()" will return a value that
124 * is not longer than what's in the buffer, so the
125 * "tvb_get_ptr()" call won't throw an exception.
127 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset);
128 line = tvb_get_ptr(tvb, offset, linelen);
129 http_type = HTTP_OTHERS; /* type not known yet */
130 if (is_http_request_or_reply(line, linelen, &http_type))
131 col_add_str(pinfo->cinfo, COL_INFO,
132 format_text(line, linelen));
134 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
138 ti = proto_tree_add_item(tree, proto_http, tvb, offset, -1,
140 http_tree = proto_item_add_subtree(ti, ett_http);
144 * Process the packet data, a line at a time.
146 http_type = HTTP_OTHERS; /* type not known yet */
147 while (tvb_offset_exists(tvb, offset)) {
149 * Find the end of the line.
151 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset);
154 * Get a buffer that refers to the line.
156 line = tvb_get_ptr(tvb, offset, linelen);
157 lineend = line + linelen;
160 * OK, does it look like an HTTP request or response?
162 if (is_http_request_or_reply(line, linelen, &http_type))
166 * No. Does it look like a blank line (as would appear
167 * at the end of an HTTP request)?
173 * No. Does it look like a MIME header?
176 while (linep < lineend) {
179 break; /* not printable, not a MIME header */
199 * It's a tspecial, so it's not part of a
200 * token, so it's not a field name for the
201 * beginning of a MIME header.
207 * This ends the token; we consider this
208 * to be a MIME header.
216 * We don't consider this part of an HTTP request or
217 * reply, so we don't display it.
218 * (Yeah, that means we don't display, say, a text/http
219 * page, but you can get that from the data pane.)
228 proto_tree_add_text(http_tree, tvb, offset,
229 next_offset - offset, "%s",
230 tvb_format_text(tvb, offset, next_offset - offset));
232 offset = next_offset;
238 case HTTP_NOTIFICATION:
239 proto_tree_add_boolean_hidden(http_tree,
240 hf_http_notification, tvb, 0, 0, 1);
244 proto_tree_add_boolean_hidden(http_tree,
245 hf_http_response, tvb, 0, 0, 1);
249 proto_tree_add_boolean_hidden(http_tree,
250 hf_http_request, tvb, 0, 0, 1);
259 datalen = tvb_length_remaining(tvb, offset);
261 tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, -1, -1);
264 * OK, has some subdissector asked that they be called
265 * if something was on some particular port?
267 if (dissector_try_port(subdissector_table, pinfo->match_port,
268 next_tvb, pinfo, tree)) {
270 * Yes. Fix up the top-level item so that it
271 * doesn't include the stuff for that protocol.
274 proto_item_set_len(ti, offset);
275 } else if(dissector_try_heuristic(heur_subdissector_list,
276 next_tvb,pinfo,tree)){
278 * Yes. Fix up the top-level item so that it
279 * doesn't include the stuff for that protocol.
282 proto_item_set_len(ti, offset);
284 call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, http_tree);
289 * XXX - this won't handle HTTP 0.9 replies, but they're all data
293 is_http_request_or_reply(const u_char *data, int linelen, http_type_t *type)
295 int isHttpRequestOrReply = FALSE;
298 * From RFC 2774 - An HTTP Extension Framework
300 * Support the command prefix that identifies the presence of
301 * a "mandatory" header.
303 if (linelen >= 2 && strncmp(data, "M-", 2) == 0) {
309 * From draft-cohen-gena-client-01.txt, available from the uPnP forum:
310 * NOTIFY, SUBSCRIBE, UNSUBSCRIBE
312 * From draft-ietf-dasl-protocol-00.txt, a now vanished Microsoft draft:
315 if (linelen >= 5 && strncmp(data, "HTTP/", 5) == 0) {
316 *type = HTTP_RESPONSE;
317 isHttpRequestOrReply = TRUE; /* response */
319 u_char * ptr = (u_char *)data;
322 /* Look for the space following the Method */
323 while (index < linelen) {
332 /* Check the methods that have same length */
336 if (strncmp(data, "GET", index) == 0 ||
337 strncmp(data, "PUT", index) == 0) {
338 *type = HTTP_REQUEST;
339 isHttpRequestOrReply = TRUE;
344 if (strncmp(data, "COPY", index) == 0 ||
345 strncmp(data, "HEAD", index) == 0 ||
346 strncmp(data, "LOCK", index) == 0 ||
347 strncmp(data, "MOVE", index) == 0 ||
348 strncmp(data, "POLL", index) == 0 ||
349 strncmp(data, "POST", index) == 0) {
350 *type = HTTP_REQUEST;
351 isHttpRequestOrReply = TRUE;
356 if (strncmp(data, "BCOPY", index) == 0 ||
357 strncmp(data, "BMOVE", index) == 0 ||
358 strncmp(data, "MKCOL", index) == 0 ||
359 strncmp(data, "TRACE", index) == 0) {
360 *type = HTTP_REQUEST;
361 isHttpRequestOrReply = TRUE;
366 if (strncmp(data, "DELETE", index) == 0 ||
367 strncmp(data, "SEARCH", index) == 0 ||
368 strncmp(data, "UNLOCK", index) == 0) {
369 *type = HTTP_REQUEST;
370 isHttpRequestOrReply = TRUE;
372 else if (strncmp(data, "NOTIFY", index) == 0) {
373 *type = HTTP_NOTIFICATION;
374 isHttpRequestOrReply = TRUE;
379 if (strncmp(data, "BDELETE", index) == 0 ||
380 strncmp(data, "CONNECT", index) == 0 ||
381 strncmp(data, "OPTIONS", index) == 0) {
382 *type = HTTP_REQUEST;
383 isHttpRequestOrReply = TRUE;
388 if (strncmp(data, "PROPFIND", index) == 0) {
389 *type = HTTP_REQUEST;
390 isHttpRequestOrReply = TRUE;
395 if (strncmp(data, "SUBSCRIBE", index) == 0) {
396 *type = HTTP_NOTIFICATION;
397 isHttpRequestOrReply = TRUE;
398 } else if (strncmp(data, "PROPPATCH", index) == 0 ||
399 strncmp(data, "BPROPFIND", index) == 0) {
400 *type = HTTP_REQUEST;
401 isHttpRequestOrReply = TRUE;
406 if (strncmp(data, "BPROPPATCH", index) == 0) {
407 *type = HTTP_REQUEST;
408 isHttpRequestOrReply = TRUE;
413 if (strncmp(data, "UNSUBSCRIBE", index) == 0) {
414 *type = HTTP_NOTIFICATION;
415 isHttpRequestOrReply = TRUE;
424 return isHttpRequestOrReply;
429 proto_register_http(void)
431 static hf_register_info hf[] = {
432 { &hf_http_notification,
433 { "Notification", "http.notification",
434 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
435 "TRUE if HTTP notification", HFILL }},
437 { "Response", "http.response",
438 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
439 "TRUE if HTTP response", HFILL }},
441 { "Request", "http.request",
442 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
443 "TRUE if HTTP request", HFILL }},
445 static gint *ett[] = {
449 proto_http = proto_register_protocol("Hypertext Transfer Protocol",
451 proto_register_field_array(proto_http, hf, array_length(hf));
452 proto_register_subtree_array(ett, array_length(ett));
454 register_dissector("http", dissect_http, proto_http);
455 http_handle = find_dissector("http");
458 * Dissectors shouldn't register themselves in this table;
459 * instead, they should call "http_dissector_add()", and
460 * we'll register the port number they specify as a port
461 * for HTTP, and register them in our subdissector table.
463 * This only works for protocols such as IPP that run over
464 * HTTP on a specific non-HTTP port.
466 subdissector_table = register_dissector_table("http.port",
467 "TCP port for protocols using HTTP", FT_UINT16, BASE_DEC);
470 * Heuristic dissectors SHOULD register themselves in
471 * this table using the standard heur_dissector_add()
475 register_heur_dissector_list("http",&heur_subdissector_list);
480 * Called by dissectors for protocols that run atop HTTP/TCP.
483 http_dissector_add(guint32 port, dissector_handle_t handle)
486 * Register ourselves as the handler for that port number
489 dissector_add("tcp.port", port, http_handle);
492 * And register them in *our* table for that port.
494 dissector_add("http.port", port, handle);
498 proto_reg_handoff_http(void)
500 data_handle = find_dissector("data");
501 dissector_add("tcp.port", TCP_PORT_HTTP, http_handle);
502 dissector_add("tcp.port", TCP_ALT_PORT_HTTP, http_handle);
503 dissector_add("tcp.port", TCP_PORT_PROXY_HTTP, http_handle);
504 dissector_add("tcp.port", TCP_PORT_PROXY_ADMIN_HTTP, http_handle);
507 * XXX - is there anything to dissect in the body of an SSDP
508 * request or reply? I.e., should there be an SSDP dissector?
510 dissector_add("tcp.port", TCP_PORT_SSDP, http_handle);
511 dissector_add("udp.port", UDP_PORT_SSDP, http_handle);