2 * Routines for HTTP packet disassembly
4 * Guy Harris <guy@alum.mit.edu>
6 * $Id: packet-http.c,v 1.39 2001/09/04 01:01:46 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@zing.org>
10 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #ifdef HAVE_SYS_TYPES_H
35 #include <sys/types.h>
45 #include "packet-http.h"
47 typedef enum _http_type {
54 static int proto_http = -1;
55 static int hf_http_notification = -1;
56 static int hf_http_response = -1;
57 static int hf_http_request = -1;
59 static gint ett_http = -1;
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;
85 dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
89 proto_tree *http_tree = NULL;
90 proto_item *ti = NULL;
94 const u_char *linep, *lineend;
97 http_type_t http_type;
100 switch (pinfo->match_port) {
102 case TCP_PORT_SSDP: /* TCP_PORT_SSDP = UDP_PORT_SSDP */
113 if (check_col(pinfo->fd, COL_PROTOCOL))
114 col_set_str(pinfo->fd, COL_PROTOCOL, proto_tag);
115 if (check_col(pinfo->fd, COL_INFO)) {
117 * Put the first line from the buffer into the summary
118 * if it's an HTTP request or reply (but leave out the
120 * Otherwise, just call it a continuation.
122 * Note that "tvb_find_line_end()" will return a value that
123 * is not longer than what's in the buffer, so the
124 * "tvb_get_ptr()" call won't throw an exception.
126 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset);
127 line = tvb_get_ptr(tvb, offset, linelen);
128 http_type = HTTP_OTHERS; /* type not known yet */
129 if (is_http_request_or_reply(line, linelen, &http_type))
130 col_add_str(pinfo->fd, COL_INFO,
131 format_text(line, linelen));
133 col_set_str(pinfo->fd, COL_INFO, "Continuation");
137 ti = proto_tree_add_item(tree, proto_http, tvb, offset,
138 tvb_length_remaining(tvb, offset), FALSE);
139 http_tree = proto_item_add_subtree(ti, ett_http);
143 * Process the packet data, a line at a time.
145 http_type = HTTP_OTHERS; /* type not known yet */
146 while (tvb_offset_exists(tvb, offset)) {
148 * Find the end of the line.
150 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset);
153 * Get a buffer that refers to the line.
155 line = tvb_get_ptr(tvb, offset, linelen);
156 lineend = line + linelen;
159 * OK, does it look like an HTTP request or response?
161 if (is_http_request_or_reply(line, linelen, &http_type))
165 * No. Does it look like a blank line (as would appear
166 * at the end of an HTTP request)?
172 * No. Does it look like a MIME header?
175 while (linep < lineend) {
178 break; /* not printable, not a MIME header */
198 * It's a tspecial, so it's not part of a
199 * token, so it's not a field name for the
200 * beginning of a MIME header.
206 * This ends the token; we consider this
207 * to be a MIME header.
215 * We don't consider this part of an HTTP request or
216 * reply, so we don't display it.
217 * (Yeah, that means we don't display, say, a text/http
218 * page, but you can get that from the data pane.)
227 proto_tree_add_text(http_tree, tvb, offset,
228 next_offset - offset, "%s",
229 tvb_format_text(tvb, offset, next_offset - offset));
231 offset = next_offset;
237 case HTTP_NOTIFICATION:
238 proto_tree_add_boolean_hidden(http_tree,
239 hf_http_notification, tvb, 0, 0, 1);
243 proto_tree_add_boolean_hidden(http_tree,
244 hf_http_response, tvb, 0, 0, 1);
248 proto_tree_add_boolean_hidden(http_tree,
249 hf_http_request, tvb, 0, 0, 1);
258 datalen = tvb_length_remaining(tvb, offset);
260 tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, -1, -1);
263 * OK, has some subdissector asked that they be called
264 * if something was on some particular port?
266 if (dissector_try_port(subdissector_table, pinfo->match_port,
267 next_tvb, pinfo, tree)) {
269 * Yes. Fix up the top-level item so that it
270 * doesn't include the stuff for that protocol.
273 proto_item_set_len(ti, offset);
275 dissect_data(tvb, offset, pinfo, http_tree);
280 * XXX - this won't handle HTTP 0.9 replies, but they're all data
284 is_http_request_or_reply(const u_char *data, int linelen, http_type_t *type)
287 * From RFC 2774 - An HTTP Extension Framework
289 * Support the command prefix that identifies the presence of
290 * a "mandatory" header.
292 if (strncmp(data, "M-", 2) == 0) {
298 * From draft-cohen-gena-client-01.txt, available from the uPnP forum:
299 * NOTIFY, SUBSCRIBE, UNSUBSCRIBE
301 * From draft-ietf-dasl-protocol-00.txt, a now vanished Microsoft draft:
305 if (strncmp(data, "GET ", 4) == 0 ||
306 strncmp(data, "PUT ", 4) == 0) {
307 if (*type == HTTP_OTHERS)
308 *type = HTTP_REQUEST;
313 if (strncmp(data, "HEAD ", 5) == 0 ||
314 strncmp(data, "POST ", 5) == 0) {
315 if (*type == HTTP_OTHERS)
316 *type = HTTP_REQUEST;
319 if (strncmp(data, "HTTP/", 5) == 0) {
320 if (*type == HTTP_OTHERS)
321 *type = HTTP_RESPONSE;
322 return TRUE; /* response */
326 if (strncmp(data, "TRACE ", 6) == 0) {
327 if (*type == HTTP_OTHERS)
328 *type = HTTP_REQUEST;
333 if (strncmp(data, "DELETE ", 7) == 0) {
334 if (*type == HTTP_OTHERS)
335 *type = HTTP_REQUEST;
338 if (strncmp(data, "NOTIFY ", 7) == 0 ||
339 strncmp(data, "SEARCH ", 7) == 0) {
340 if (*type == HTTP_OTHERS)
341 *type = HTTP_NOTIFICATION;
346 if (strncmp(data, "OPTIONS ", 8) == 0 ||
347 strncmp(data, "CONNECT ", 8) == 0) {
348 if (*type == HTTP_OTHERS)
349 *type = HTTP_REQUEST;
354 if (strncmp(data, "SUBSCRIBE ", 10) == 0) {
355 if (*type == HTTP_OTHERS)
356 *type = HTTP_NOTIFICATION;
361 if (strncmp(data, "UNSUBSCRIBE ", 10) == 0) {
362 if (*type == HTTP_OTHERS)
363 *type = HTTP_NOTIFICATION;
371 proto_register_http(void)
373 static hf_register_info hf[] = {
374 { &hf_http_notification,
375 { "Notification", "http.notification",
376 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
377 "TRUE if HTTP notification", HFILL }},
379 { "Response", "http.response",
380 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
381 "TRUE if HTTP response", HFILL }},
383 { "Request", "http.request",
384 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
385 "TRUE if HTTP request", HFILL }},
387 static gint *ett[] = {
391 proto_http = proto_register_protocol("Hypertext Transfer Protocol",
393 proto_register_field_array(proto_http, hf, array_length(hf));
394 proto_register_subtree_array(ett, array_length(ett));
396 register_dissector("http", dissect_http, proto_http);
399 * Dissectors shouldn't register themselves in this table;
400 * instead, they should call "http_dissector_add()", and
401 * we'll register the port number they specify as a port
402 * for HTTP, and register them in our subdissector table.
404 * This only works for protocols such as IPP that run over
405 * HTTP on a specific non-HTTP port.
407 subdissector_table = register_dissector_table("http.port");
411 * Called by dissectors for protocols that run atop HTTP/TCP.
414 http_dissector_add(guint32 port, dissector_t dissector, int proto)
417 * Register ourselves as the handler for that port number
420 dissector_add("tcp.port", port, dissect_http, proto_http);
423 * And register them in *our* table for that port.
425 dissector_add("http.port", port, dissector, proto);
429 proto_reg_handoff_http(void)
431 dissector_add("tcp.port", TCP_PORT_HTTP, dissect_http, proto_http);
432 dissector_add("tcp.port", TCP_ALT_PORT_HTTP, dissect_http, proto_http);
433 dissector_add("tcp.port", TCP_PORT_PROXY_HTTP, dissect_http,
435 dissector_add("tcp.port", TCP_PORT_PROXY_ADMIN_HTTP, dissect_http,
439 * XXX - is there anything to dissect in the body of an SSDP
440 * request or reply? I.e., should there be an SSDP dissector?
442 dissector_add("tcp.port", TCP_PORT_SSDP, dissect_http, proto_http);
443 dissector_add("udp.port", UDP_PORT_SSDP, dissect_http, proto_http);