forked from osmocom/wireshark
Request-response tracking and response-time calculation for HTTP. svn path=/trunk/; revision=47694
This commit is contained in:
parent
9dc510fc8e
commit
0f8735b8a3
|
@ -52,6 +52,7 @@
|
|||
#include <epan/prefs.h>
|
||||
#include <epan/expert.h>
|
||||
#include <epan/uat.h>
|
||||
#include <epan/wmem/wmem.h>
|
||||
|
||||
typedef enum _http_type {
|
||||
HTTP_REQUEST,
|
||||
|
@ -109,6 +110,13 @@ static int hf_http_sec_websocket_version = -1;
|
|||
static int hf_http_set_cookie = -1;
|
||||
static int hf_http_last_modified = -1;
|
||||
static int hf_http_x_forwarded_for = -1;
|
||||
static int hf_http_request_in = -1;
|
||||
static int hf_http_response_in = -1;
|
||||
static int hf_http_next_request_in = -1;
|
||||
static int hf_http_next_response_in = -1;
|
||||
static int hf_http_prev_request_in = -1;
|
||||
static int hf_http_prev_response_in = -1;
|
||||
static int hf_http_response_ts = -1;
|
||||
|
||||
static gint ett_http = -1;
|
||||
static gint ett_http_ntlmssp = -1;
|
||||
|
@ -590,7 +598,7 @@ get_http_conversation_data(packet_info *pinfo)
|
|||
conv_data = conversation_get_proto_data(conversation, proto_http);
|
||||
if(!conv_data) {
|
||||
/* Setup the conversation structure itself */
|
||||
conv_data = se_alloc0(sizeof(http_conv_t));
|
||||
conv_data = wmem_alloc0(wmem_file_scope(), sizeof(http_conv_t));
|
||||
|
||||
conversation_add_proto_data(conversation, proto_http,
|
||||
conv_data);
|
||||
|
@ -599,6 +607,60 @@ get_http_conversation_data(packet_info *pinfo)
|
|||
return conv_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* create a new http_req_res_t and add it to the conversation.
|
||||
* @return the new allocated object which is already added to the linked list
|
||||
*/
|
||||
static http_req_res_t* push_req_res(http_conv_t *conv_data)
|
||||
{
|
||||
http_req_res_t *req_res = wmem_alloc0(wmem_file_scope(), sizeof(http_req_res_t));
|
||||
nstime_set_unset(&(req_res->req_ts));
|
||||
req_res->number = ++conv_data->req_res_num;
|
||||
|
||||
if (! conv_data->req_res_tail) {
|
||||
conv_data->req_res_tail = req_res;
|
||||
} else {
|
||||
req_res->prev = conv_data->req_res_tail;
|
||||
conv_data->req_res_tail->next = req_res;
|
||||
conv_data->req_res_tail = req_res;
|
||||
}
|
||||
|
||||
return req_res;
|
||||
}
|
||||
|
||||
/**
|
||||
* push a request frame number and its time stamp to the conversation data.
|
||||
*/
|
||||
static void push_req(http_conv_t *conv_data, packet_info *pinfo)
|
||||
{
|
||||
/* a request will always create a new http_req_res_t object */
|
||||
http_req_res_t *req_res = push_req_res(conv_data);
|
||||
|
||||
req_res->req_framenum = pinfo->fd->num;
|
||||
req_res->req_ts = pinfo->fd->abs_ts;
|
||||
|
||||
p_add_proto_data(pinfo->fd, proto_http, req_res);
|
||||
}
|
||||
|
||||
/**
|
||||
* push a response frame number to the conversation data.
|
||||
*/
|
||||
static void push_res(http_conv_t *conv_data, packet_info *pinfo)
|
||||
{
|
||||
/* a response will create a new http_req_res_t object: if no
|
||||
object exists, or if one exists for another response. In
|
||||
both cases the corresponding request was not
|
||||
detected/included in the conversation. In all other cases
|
||||
the http_req_res_t object created by the request is
|
||||
used. */
|
||||
http_req_res_t *req_res = conv_data->req_res_tail;
|
||||
if (!req_res || req_res->res_framenum > 0) {
|
||||
req_res = push_req_res(conv_data);
|
||||
}
|
||||
req_res->res_framenum = pinfo->fd->num;
|
||||
p_add_proto_data(pinfo->fd, proto_http, req_res);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: remove this ugly global variable.
|
||||
* XXX: do we really want to have to pass this from one function to another?
|
||||
|
@ -945,7 +1007,20 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
PROTO_ITEM_SET_GENERATED(e_ti);
|
||||
}
|
||||
|
||||
if (!PINFO_FD_VISITED(pinfo)) {
|
||||
if (http_type == HTTP_REQUEST) {
|
||||
push_req(conv_data, pinfo);
|
||||
} else if (http_type == HTTP_RESPONSE) {
|
||||
push_res(conv_data, pinfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (tree) {
|
||||
proto_item *pi;
|
||||
http_req_res_t *curr = p_get_proto_data(pinfo->fd, proto_http);
|
||||
http_req_res_t *prev = curr ? curr->prev : NULL;
|
||||
http_req_res_t *next = curr ? curr->next : NULL;
|
||||
|
||||
switch (http_type) {
|
||||
|
||||
case HTTP_NOTIFICATION:
|
||||
|
@ -958,12 +1033,64 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
hidden_item = proto_tree_add_boolean(http_tree,
|
||||
hf_http_response, tvb, 0, 0, 1);
|
||||
PROTO_ITEM_SET_HIDDEN(hidden_item);
|
||||
|
||||
if (curr) {
|
||||
nstime_t delta;
|
||||
|
||||
pi = proto_tree_add_text(http_tree, tvb, 0, 0, "HTTP response %u/%u", curr->number, conv_data->req_res_num);
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
|
||||
if (! nstime_is_unset(&(curr->req_ts))) {
|
||||
nstime_delta(&delta, &pinfo->fd->abs_ts, &(curr->req_ts));
|
||||
pi = proto_tree_add_time(http_tree, hf_http_response_ts, tvb, 0, 0, &delta);
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
}
|
||||
}
|
||||
if (prev && prev->req_framenum) {
|
||||
pi = proto_tree_add_uint(http_tree, hf_http_prev_request_in, tvb, 0, 0, prev->req_framenum);
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
}
|
||||
if (prev && prev->res_framenum) {
|
||||
pi = proto_tree_add_uint(http_tree, hf_http_prev_response_in, tvb, 0, 0, prev->res_framenum);
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
}
|
||||
if (curr && curr->req_framenum) {
|
||||
pi = proto_tree_add_uint(http_tree, hf_http_request_in, tvb, 0, 0, curr->req_framenum);
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
}
|
||||
if (next && next->req_framenum) {
|
||||
pi = proto_tree_add_uint(http_tree, hf_http_next_request_in, tvb, 0, 0, next->req_framenum);
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
}
|
||||
if (next && next->res_framenum) {
|
||||
pi = proto_tree_add_uint(http_tree, hf_http_next_response_in, tvb, 0, 0, next->res_framenum);
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case HTTP_REQUEST:
|
||||
hidden_item = proto_tree_add_boolean(http_tree,
|
||||
hf_http_request, tvb, 0, 0, 1);
|
||||
PROTO_ITEM_SET_HIDDEN(hidden_item);
|
||||
|
||||
if (curr) {
|
||||
pi = proto_tree_add_text(http_tree, tvb, 0, 0, "HTTP request %u/%u", curr->number, conv_data->req_res_num);
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
}
|
||||
if (prev && prev->req_framenum) {
|
||||
pi = proto_tree_add_uint(http_tree, hf_http_prev_request_in, tvb, 0, 0, prev->req_framenum);
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
}
|
||||
if (curr && curr->res_framenum) {
|
||||
pi = proto_tree_add_uint(http_tree, hf_http_response_in, tvb, 0, 0, curr->res_framenum);
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
}
|
||||
if (next && next->req_framenum) {
|
||||
pi = proto_tree_add_uint(http_tree, hf_http_next_request_in, tvb, 0, 0, next->req_framenum);
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case HTTP_OTHERS:
|
||||
|
@ -2713,7 +2840,35 @@ proto_register_http(void)
|
|||
{ &hf_http_x_forwarded_for,
|
||||
{ "X-Forwarded-For", "http.x_forwarded_for",
|
||||
FT_STRING, BASE_NONE, NULL, 0x0,
|
||||
"HTTP X-Forwarded-For", HFILL }}
|
||||
"HTTP X-Forwarded-For", HFILL }},
|
||||
{ &hf_http_request_in,
|
||||
{ "Request in frame", "http.request_in",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0,
|
||||
"This packet is a response to the packet with this number", HFILL }},
|
||||
{ &hf_http_response_in,
|
||||
{ "Response in frame","http.response_in",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0,
|
||||
"This packet will be responded in the packet with this number", HFILL }},
|
||||
{ &hf_http_next_request_in,
|
||||
{ "Next request in frame", "http.next_request_in",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0,
|
||||
"The next HTTP request starts in packet number", HFILL }},
|
||||
{ &hf_http_next_response_in,
|
||||
{ "Next response in frame","http.next_response_in",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0,
|
||||
"The next HTTP response starts in packet number", HFILL }},
|
||||
{ &hf_http_prev_request_in,
|
||||
{ "Prev request in frame", "http.prev_request_in",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0,
|
||||
"The previous HTTP request starts in packet number", HFILL }},
|
||||
{ &hf_http_prev_response_in,
|
||||
{ "Prev response in frame","http.prev_response_in",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0,
|
||||
"The previous HTTP response starts in packet number", HFILL }},
|
||||
{ &hf_http_response_ts,
|
||||
{ "Time since request", "http.response_ts",
|
||||
FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
|
||||
"Time since the request was send", HFILL }},
|
||||
};
|
||||
static gint *ett[] = {
|
||||
&ett_http,
|
||||
|
@ -2954,3 +3109,16 @@ proto_reg_handoff_message_http(void)
|
|||
|
||||
reinit_http();
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: true
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=8 tabstop=8:
|
||||
* :indentSize=8:tabSize=8:
|
||||
*/
|
||||
|
|
|
@ -48,7 +48,23 @@ typedef struct _http_eo_t {
|
|||
const guint8 *payload_data;
|
||||
} http_eo_t;
|
||||
|
||||
/* Conversation data - used for the http_payload_subdissector() function. */
|
||||
/** information about a request and response on a HTTP conversation. */
|
||||
typedef struct _http_req_res_t {
|
||||
/** the running number on the conversation */
|
||||
guint32 number;
|
||||
/** frame number of the request */
|
||||
guint32 req_framenum;
|
||||
/** frame number of the corresponding response */
|
||||
guint32 res_framenum;
|
||||
/** timestamp of the request */
|
||||
nstime_t req_ts;
|
||||
/** pointer to the next element in the linked list, NULL for the tail node */
|
||||
struct _http_req_res_t *next;
|
||||
/** pointer to the previous element in the linked list, NULL for the head node */
|
||||
struct _http_req_res_t *prev;
|
||||
} http_req_res_t;
|
||||
|
||||
/** Conversation data of a HTTP connection. */
|
||||
typedef struct _http_conv_t {
|
||||
guint response_code;
|
||||
gchar *http_host;
|
||||
|
@ -56,6 +72,10 @@ typedef struct _http_conv_t {
|
|||
gchar *request_uri;
|
||||
guint8 upgrade;
|
||||
guint32 startframe; /* First frame of proxied connection */
|
||||
/** the tail node of req_res */
|
||||
http_req_res_t *req_res_tail;
|
||||
/** the number of requests on the conversation. */
|
||||
guint32 req_res_num;
|
||||
} http_conv_t;
|
||||
|
||||
#endif /* __PACKET_HTTP_H__ */
|
||||
|
|
Loading…
Reference in New Issue