2 * Routines for HTTP packet disassembly
4 * Guy Harris <guy@alum.mit.edu>
6 * $Id: packet-http.c,v 1.44 2001/12/10 00:25:28 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>
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,
139 tvb_length_remaining(tvb, offset), FALSE);
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)
296 * From RFC 2774 - An HTTP Extension Framework
298 * Support the command prefix that identifies the presence of
299 * a "mandatory" header.
301 if (strncmp(data, "M-", 2) == 0) {
307 * From draft-cohen-gena-client-01.txt, available from the uPnP forum:
308 * NOTIFY, SUBSCRIBE, UNSUBSCRIBE
310 * From draft-ietf-dasl-protocol-00.txt, a now vanished Microsoft draft:
314 if (strncmp(data, "GET ", 4) == 0 ||
315 strncmp(data, "PUT ", 4) == 0) {
316 if (*type == HTTP_OTHERS)
317 *type = HTTP_REQUEST;
322 if (strncmp(data, "HEAD ", 5) == 0 ||
323 strncmp(data, "POST ", 5) == 0) {
324 if (*type == HTTP_OTHERS)
325 *type = HTTP_REQUEST;
328 if (strncmp(data, "HTTP/", 5) == 0) {
329 if (*type == HTTP_OTHERS)
330 *type = HTTP_RESPONSE;
331 return TRUE; /* response */
335 if (strncmp(data, "TRACE ", 6) == 0) {
336 if (*type == HTTP_OTHERS)
337 *type = HTTP_REQUEST;
342 if (strncmp(data, "DELETE ", 7) == 0) {
343 if (*type == HTTP_OTHERS)
344 *type = HTTP_REQUEST;
347 if (strncmp(data, "NOTIFY ", 7) == 0 ||
348 strncmp(data, "SEARCH ", 7) == 0) {
349 if (*type == HTTP_OTHERS)
350 *type = HTTP_NOTIFICATION;
355 if (strncmp(data, "OPTIONS ", 8) == 0 ||
356 strncmp(data, "CONNECT ", 8) == 0) {
357 if (*type == HTTP_OTHERS)
358 *type = HTTP_REQUEST;
363 if (strncmp(data, "SUBSCRIBE ", 10) == 0) {
364 if (*type == HTTP_OTHERS)
365 *type = HTTP_NOTIFICATION;
370 if (strncmp(data, "UNSUBSCRIBE ", 10) == 0) {
371 if (*type == HTTP_OTHERS)
372 *type = HTTP_NOTIFICATION;
380 proto_register_http(void)
382 static hf_register_info hf[] = {
383 { &hf_http_notification,
384 { "Notification", "http.notification",
385 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
386 "TRUE if HTTP notification", HFILL }},
388 { "Response", "http.response",
389 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
390 "TRUE if HTTP response", HFILL }},
392 { "Request", "http.request",
393 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
394 "TRUE if HTTP request", HFILL }},
396 static gint *ett[] = {
400 proto_http = proto_register_protocol("Hypertext Transfer Protocol",
402 proto_register_field_array(proto_http, hf, array_length(hf));
403 proto_register_subtree_array(ett, array_length(ett));
405 register_dissector("http", dissect_http, proto_http);
406 http_handle = find_dissector("http");
409 * Dissectors shouldn't register themselves in this table;
410 * instead, they should call "http_dissector_add()", and
411 * we'll register the port number they specify as a port
412 * for HTTP, and register them in our subdissector table.
414 * This only works for protocols such as IPP that run over
415 * HTTP on a specific non-HTTP port.
417 subdissector_table = register_dissector_table("http.port",
418 "TCP port for protocols using HTTP", FT_UINT16, BASE_DEC);
421 * Heuristic dissectors SHOULD register themselves in
422 * this table using the standard heur_dissector_add()
426 register_heur_dissector_list("http",&heur_subdissector_list);
431 * Called by dissectors for protocols that run atop HTTP/TCP.
434 http_dissector_add(guint32 port, dissector_handle_t handle)
437 * Register ourselves as the handler for that port number
440 dissector_add("tcp.port", port, http_handle);
443 * And register them in *our* table for that port.
445 dissector_add("http.port", port, handle);
449 proto_reg_handoff_http(void)
451 data_handle = find_dissector("data");
452 dissector_add("tcp.port", TCP_PORT_HTTP, http_handle);
453 dissector_add("tcp.port", TCP_ALT_PORT_HTTP, http_handle);
454 dissector_add("tcp.port", TCP_PORT_PROXY_HTTP, http_handle);
455 dissector_add("tcp.port", TCP_PORT_PROXY_ADMIN_HTTP, http_handle);
458 * XXX - is there anything to dissect in the body of an SSDP
459 * request or reply? I.e., should there be an SSDP dissector?
461 dissector_add("tcp.port", TCP_PORT_SSDP, http_handle);
462 dissector_add("udp.port", UDP_PORT_SSDP, http_handle);