2 * Routines for HTTP packet disassembly
4 * Guy Harris <guy@alum.mit.edu>
6 * $Id: packet-http.c,v 1.34 2001/01/11 05:36:09 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 typedef enum _http_type {
52 static int proto_http = -1;
53 static int hf_http_notification = -1;
54 static int hf_http_response = -1;
55 static int hf_http_request = -1;
57 static gint ett_http = -1;
59 #define TCP_PORT_HTTP 80
60 #define TCP_PORT_PROXY_HTTP 3128
61 #define TCP_PORT_PROXY_ADMIN_HTTP 3132
62 #define TCP_ALT_PORT_HTTP 8080
64 #define TCP_PORT_IPP 631
66 #define TCP_PORT_SSDP 1900
67 #define UDP_PORT_SSDP 1900
70 * Protocols implemented atop HTTP.
73 PROTO_HTTP, /* just HTTP */
74 PROTO_IPP, /* Internet Printing Protocol */
75 PROTO_SSDP /* Simple Service Discovery Protocol */
78 static int is_http_request_or_reply(const u_char *data, int linelen, http_type_t *type);
80 static dissector_handle_t ipp_handle;
83 dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
87 proto_tree *http_tree = NULL;
88 proto_item *ti = NULL;
92 const u_char *linep, *lineend;
95 http_type_t http_type;
98 CHECK_DISPLAY_AS_DATA(proto_http, tvb, pinfo, tree);
100 pinfo->current_proto = "HTTP";
102 switch (pinfo->match_port) {
109 case TCP_PORT_SSDP: /* TCP_PORT_SSDP = UDP_PORT_SSDP */
120 if (check_col(pinfo->fd, COL_PROTOCOL))
121 col_set_str(pinfo->fd, COL_PROTOCOL, proto_tag);
122 if (check_col(pinfo->fd, COL_INFO)) {
124 * Put the first line from the buffer into the summary
125 * if it's an HTTP request or reply (but leave out the
127 * Otherwise, just call it a continuation.
129 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset);
130 line = tvb_get_ptr(tvb, offset, linelen);
131 http_type = HTTP_OTHERS; /* type not known yet */
132 if (is_http_request_or_reply(line, linelen, &http_type))
133 col_add_str(pinfo->fd, COL_INFO,
134 format_text(line, linelen));
136 col_set_str(pinfo->fd, COL_INFO, "Continuation");
140 ti = proto_tree_add_item(tree, proto_http, tvb, offset,
141 tvb_length_remaining(tvb, offset), FALSE);
142 http_tree = proto_item_add_subtree(ti, ett_http);
145 * Process the packet data, a line at a time.
147 http_type = HTTP_OTHERS; /* type not known yet */
148 while (tvb_offset_exists(tvb, offset)) {
150 * Find the end of the line.
152 linelen = tvb_find_line_end(tvb, offset, -1,
156 * Get a buffer that refers to the line.
158 line = tvb_get_ptr(tvb, offset, linelen);
159 lineend = line + linelen;
162 * OK, does it look like an HTTP request or
165 if (is_http_request_or_reply(line, linelen, &http_type))
169 * No. Does it look like a blank line (as would
170 * appear at the end of an HTTP request)?
176 * No. Does it look like a MIME header?
179 while (linep < lineend) {
182 break; /* not printable, not a MIME header */
202 * It's a tspecial, so it's not
203 * part of a token, so it's not
204 * a field name for the beginning
211 * This ends the token; we consider
212 * this to be a MIME header.
220 * We don't consider this part of an HTTP request or
221 * reply, so we don't display it.
222 * (Yeah, that means we don't display, say, a
223 * text/http page, but you can get that from the
232 proto_tree_add_text(http_tree, tvb, offset,
233 next_offset - offset, "%s",
234 tvb_format_text(tvb, offset, next_offset - offset));
235 offset = next_offset;
240 case HTTP_NOTIFICATION:
241 proto_tree_add_boolean_hidden(http_tree,
242 hf_http_notification, tvb, 0, 0, 1);
246 proto_tree_add_boolean_hidden(http_tree,
247 hf_http_response, tvb, 0, 0, 1);
251 proto_tree_add_boolean_hidden(http_tree,
252 hf_http_request, tvb, 0, 0, 1);
261 datalen = tvb_length_remaining(tvb, offset);
263 if (proto == PROTO_IPP) {
264 tvbuff_t *new_tvb = tvb_new_subset(tvb, offset, -1, -1);
267 * Fix up the top-level item so that it doesn't
268 * include the IPP stuff.
271 proto_item_set_len(ti, offset);
273 call_dissector(ipp_handle, new_tvb, pinfo, tree);
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" }},
379 { "Response", "http.response",
380 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
381 "TRUE if HTTP response" }},
383 { "Request", "http.request",
384 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
385 "TRUE if HTTP request" }},
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));
398 proto_reg_handoff_http(void)
400 dissector_add("tcp.port", TCP_PORT_HTTP, dissect_http, proto_http);
401 dissector_add("tcp.port", TCP_ALT_PORT_HTTP, dissect_http, proto_http);
402 dissector_add("tcp.port", TCP_PORT_PROXY_HTTP, dissect_http,
404 dissector_add("tcp.port", TCP_PORT_PROXY_ADMIN_HTTP, dissect_http,
408 * XXX - this is a bit ugly; we probably really want to have
409 * protocols based atop HTTP call a routine to register
410 * themselves with the HTTP dissector, giving an optional
411 * port number (if the port number is "missing", e.g. -1 or 0,
412 * the protocol would be assumed to use a standard HTTP port),
413 * and an optional Content-Type: value (or some other way for
414 * the dissector to tell what the next protocol is).
416 * The HTTP dissector would register itself for the port in
417 * question (if it's not missing), and would use either the
418 * port number or the Content-Type: (or whatever) value to
419 * determine whether to hand the payload to that dissector.
421 * It would also pass a protocol number, so we could arrange
422 * that the HTTP part of an IPP packet be dissected iff HTTP
423 * is enabled, and the IPP part be dissected iff IPP is enabled.
425 dissector_add("tcp.port", TCP_PORT_IPP, dissect_http, proto_http);
428 * XXX - is there anything to dissect in the body of an SSDP
429 * request or reply? I.e., should there be an SSDP dissector?
431 dissector_add("tcp.port", TCP_PORT_SSDP, dissect_http, proto_http);
432 dissector_add("udp.port", UDP_PORT_SSDP, dissect_http, proto_http);
435 * Get a handle for the IPP dissector.
437 ipp_handle = find_dissector("ipp");