aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-http.c
diff options
context:
space:
mode:
authorLuis Ontanon <luis.ontanon@gmail.com>2005-07-24 01:42:41 +0000
committerLuis Ontanon <luis.ontanon@gmail.com>2005-07-24 01:42:41 +0000
commit4f5c0a8cb2a7f1f17c11ba14a8bea82530718551 (patch)
tree371effddca8e116582b2129a1dd25fd7def2080f /epan/dissectors/packet-http.c
parentec941c4a8cbbd3e1f7995baa730b5204753caf6b (diff)
move the stats_tree tap into the http dissector (not anymore in the plugin)
change several calls to g_memdup into ep_strndup, fix the free calls svn path=/trunk/; revision=15022
Diffstat (limited to 'epan/dissectors/packet-http.c')
-rw-r--r--epan/dissectors/packet-http.c317
1 files changed, 244 insertions, 73 deletions
diff --git a/epan/dissectors/packet-http.c b/epan/dissectors/packet-http.c
index 051b1b012a..73ebdfd9c0 100644
--- a/epan/dissectors/packet-http.c
+++ b/epan/dissectors/packet-http.c
@@ -41,6 +41,8 @@
#include <epan/packet.h>
#include <epan/strutil.h>
#include <epan/base64.h>
+#include <epan/emem.h>
+#include <epan/stats_tree.h>
#include <epan/req_resp_hdrs.h>
#include "packet-http.h"
@@ -192,6 +194,227 @@ static heur_dissector_list_t heur_subdissector_list;
static dissector_handle_t ntlmssp_handle=NULL;
static dissector_handle_t gssapi_handle=NULL;
+static const value_string vals_status_code[] = {
+ { 100, "Continue" },
+ { 101, "Switching Protocols" },
+ { 199, "Informational - Others" },
+
+ { 200, "OK"},
+ { 201, "Created"},
+ { 202, "Accepted"},
+ { 203, "Non-authoritative Information"},
+ { 204, "No Content"},
+ { 205, "Reset Content"},
+ { 206, "Partial Content"},
+ { 299, "Success - Others"},
+
+ { 300, "Multiple Choices"},
+ { 301, "Moved Permanently"},
+ { 302, "Moved Temporarily"},
+ { 303, "See Other"},
+ { 304, "Not Modified"},
+ { 305, "Use Proxy"},
+ { 399, "Redirection - Others"},
+
+ { 400, "Bad Request"},
+ { 401, "Unauthorized"},
+ { 402, "Payment Required"},
+ { 403, "Forbidden"},
+ { 404, "Not Found"},
+ { 405, "Method Not Allowed"},
+ { 406, "Not Acceptable"},
+ { 407, "Proxy Authentication Required"},
+ { 408, "Request Time-out"},
+ { 409, "Conflict"},
+ { 410, "Gone"},
+ { 411, "Length Required"},
+ { 412, "Precondition Failed"},
+ { 413, "Request Entity Too Large"},
+ { 414, "Request-URI Too Large"},
+ { 415, "Unsupported Media Type"},
+ { 499, "Client Error - Others"},
+
+ { 500, "Internal Server Error"},
+ { 501, "Not Implemented"},
+ { 502, "Bad Gateway"},
+ { 503, "Service Unavailable"},
+ { 504, "Gateway Time-out"},
+ { 505, "HTTP Version not supported"},
+ { 599, "Server Error - Others"},
+
+ { 0, NULL}
+};
+
+static const gchar* st_str_reqs = "HTTP Requests by Server";
+static const gchar* st_str_reqs_by_srv_addr = "HTTP Requests by Server Address";
+static const gchar* st_str_reqs_by_http_host = "HTTP Requests by HTTP Host";
+static const gchar* st_str_resps_by_srv_addr = "HTTP Responses by Server Address";
+
+static int st_node_reqs = -1;
+static int st_node_reqs_by_srv_addr = -1;
+static int st_node_reqs_by_http_host = -1;
+static int st_node_resps_by_srv_addr = -1;
+
+static void http_reqs_stats_tree_init(stats_tree* st) {
+ st_node_reqs = stats_tree_create_node(st, st_str_reqs, 0, TRUE);
+ st_node_reqs_by_srv_addr = stats_tree_create_node(st, st_str_reqs_by_srv_addr, st_node_reqs, TRUE);
+ st_node_reqs_by_http_host = stats_tree_create_node(st, st_str_reqs_by_http_host, st_node_reqs, TRUE);
+ st_node_resps_by_srv_addr = stats_tree_create_node(st, st_str_resps_by_srv_addr, 0, TRUE);
+}
+
+static int http_reqs_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p) {
+ const http_info_value_t* v = p;
+ int reqs_by_this_host;
+ int reqs_by_this_addr;
+ int resps_by_this_addr;
+ int i = v->response_code;
+ static gchar ip_str[256];
+
+
+ if (v->request_method) {
+ g_snprintf(ip_str,sizeof(ip_str),"%s",address_to_str(&pinfo->dst));
+
+ tick_stat_node(st, st_str_reqs, 0, FALSE);
+ tick_stat_node(st, st_str_reqs_by_srv_addr, st_node_reqs, TRUE);
+ tick_stat_node(st, st_str_reqs_by_http_host, st_node_reqs, TRUE);
+ reqs_by_this_addr = tick_stat_node(st, ip_str, st_node_reqs_by_srv_addr, TRUE);
+
+ if (v->http_host) {
+ reqs_by_this_host = tick_stat_node(st, v->http_host, st_node_reqs_by_http_host, TRUE);
+ tick_stat_node(st, ip_str, reqs_by_this_host, FALSE);
+
+ tick_stat_node(st, v->http_host, reqs_by_this_addr, FALSE);
+ }
+
+ return 1;
+
+ } else if (i != 0) {
+ g_snprintf(ip_str,sizeof(ip_str),"%s",address_to_str(&pinfo->src));
+
+ tick_stat_node(st, st_str_resps_by_srv_addr, 0, FALSE);
+ resps_by_this_addr = tick_stat_node(st, ip_str, st_node_resps_by_srv_addr, TRUE);
+
+ if ( (i>100)&&(i<400) ) {
+ tick_stat_node(st, "OK", resps_by_this_addr, FALSE);
+ } else {
+ tick_stat_node(st, "KO", resps_by_this_addr, FALSE);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int st_node_requests_by_host = -1;
+static const guint8* st_str_requests_by_host = "HTTP Requests by HTTP Host";
+
+static void http_req_stats_tree_init(stats_tree* st) {
+ st_node_requests_by_host = stats_tree_create_node(st, st_str_requests_by_host, 0, TRUE);
+}
+
+static int http_req_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p) {
+ const http_info_value_t* v = p;
+ int reqs_by_this_host;
+
+ if (v->request_method) {
+ tick_stat_node(st, st_str_requests_by_host, 0, FALSE);
+
+ if (v->http_host) {
+ reqs_by_this_host = tick_stat_node(st, v->http_host, st_node_requests_by_host, TRUE);
+
+ if (v->request_uri) {
+ tick_stat_node(st, v->request_uri, reqs_by_this_host, TRUE);
+ }
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static const guint8* st_str_packets = "Total HTTP Packets";
+static const guint8* st_str_requests = "HTTP Request Packets";
+static const guint8* st_str_responses = "HTTP Response Packets";
+static const guint8* st_str_resp_broken = "???: broken";
+static const guint8* st_str_resp_100 = "1xx: Informational";
+static const guint8* st_str_resp_200 = "2xx: Success";
+static const guint8* st_str_resp_300 = "3xx: Redirection";
+static const guint8* st_str_resp_400 = "4xx: Client Error";
+static const guint8* st_str_resp_500 = "5xx: Server Error";
+static const guint8* st_str_other = "Other HTTP Packets";
+
+static int st_node_packets = -1;
+static int st_node_requests = -1;
+static int st_node_responses = -1;
+static int st_node_resp_broken = -1;
+static int st_node_resp_100 = -1;
+static int st_node_resp_200 = -1;
+static int st_node_resp_300 = -1;
+static int st_node_resp_400 = -1;
+static int st_node_resp_500 = -1;
+static int st_node_other = -1;
+
+
+static void http_stats_tree_init(stats_tree* st) {
+ st_node_packets = stats_tree_create_node(st, st_str_packets, 0, TRUE);
+ st_node_requests = stats_tree_create_pivot(st, st_str_requests, st_node_packets);
+ st_node_responses = stats_tree_create_node(st, st_str_responses, st_node_packets, TRUE);
+ st_node_resp_broken = stats_tree_create_node(st, st_str_resp_broken, st_node_responses, TRUE);
+ st_node_resp_100 = stats_tree_create_node(st, st_str_resp_100, st_node_responses, TRUE);
+ st_node_resp_200 = stats_tree_create_node(st, st_str_resp_200, st_node_responses, TRUE);
+ st_node_resp_300 = stats_tree_create_node(st, st_str_resp_300, st_node_responses, TRUE);
+ st_node_resp_400 = stats_tree_create_node(st, st_str_resp_400, st_node_responses, TRUE);
+ st_node_resp_500 = stats_tree_create_node(st, st_str_resp_500, st_node_responses, TRUE);
+ st_node_other = stats_tree_create_node(st, st_str_other, st_node_packets,FALSE);
+}
+
+static int http_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p) {
+ const http_info_value_t* v = p;
+ guint i = v->response_code;
+ int resp_grp;
+ const guint8* resp_str;
+ static gchar str[64];
+
+ tick_stat_node(st, st_str_packets, 0, FALSE);
+
+ if (i) {
+ tick_stat_node(st, st_str_responses, st_node_packets, FALSE);
+
+ if ( (i<100)||(i>=600) ) {
+ resp_grp = st_node_resp_broken;
+ resp_str = st_str_resp_broken;
+ } else if (i<200) {
+ resp_grp = st_node_resp_100;
+ resp_str = st_str_resp_100;
+ } else if (i<300) {
+ resp_grp = st_node_resp_200;
+ resp_str = st_str_resp_200;
+ } else if (i<400) {
+ resp_grp = st_node_resp_300;
+ resp_str = st_str_resp_300;
+ } else if (i<500) {
+ resp_grp = st_node_resp_400;
+ resp_str = st_str_resp_400;
+ } else {
+ resp_grp = st_node_resp_500;
+ resp_str = st_str_resp_500;
+ }
+
+ tick_stat_node(st, resp_str, st_node_responses, FALSE);
+
+ g_snprintf(str, sizeof(str),"%u %s",i,match_strval(i,vals_status_code));
+ tick_stat_node(st, str, resp_grp, FALSE);
+ } else if (v->request_method) {
+ stats_tree_tick_pivot(st,st_node_requests,v->request_method);
+ } else {
+ tick_stat_node(st, st_str_other, st_node_packets, FALSE);
+ }
+
+ return 1;
+}
/* Return a tvb that contains the binary representation of a base64
string */
@@ -226,28 +449,6 @@ dissect_http_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
call_dissector(gssapi_handle, ntlmssp_tvb, pinfo, tree);
}
-static void
-cleanup_headers(void *arg)
-{
- headers_t *headers = arg;
-
- if (headers->content_type != NULL)
- g_free(headers->content_type);
- headers->content_type = NULL;
- /*
- * The content_type_parameters field actually points into the
- * content_type headers, so don't free it, as that'll double-free
- * some memory.
- */
- headers->content_type_parameters = NULL;
- if (headers->content_encoding != NULL)
- g_free(headers->content_encoding);
- headers->content_encoding = NULL;
- if (headers->transfer_encoding != NULL)
- g_free(headers->transfer_encoding);
- headers->transfer_encoding = NULL;
-}
-
/*
* TODO: remove this ugly global variable.
* XXX: do we really want to have to pass this from one function to another?
@@ -327,7 +528,7 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
}
/* we first allocate and initialize the current stat_info */
- stat_info = g_malloc(sizeof(http_info_value_t));
+ stat_info = ep_alloc(sizeof(http_info_value_t));
stat_info->framenum = framenum;
stat_info->response_code = 0;
stat_info->request_method = NULL;
@@ -336,17 +537,13 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
/* We'll then delete from the array all the stat_infos that do not belong to this frame */
i = stat_infos->len;
- while (i) {
+ while (i) {
--i;
si = g_ptr_array_index(stat_infos,i);
if ( si->framenum != framenum ) {
g_ptr_array_remove_index_fast(stat_infos,i);
- if (si->request_method) g_free(si->request_method);
- if (si->request_uri) g_free(si->request_uri);
- if (si->http_host) g_free(si->http_host);
- g_free(si);
}
}
@@ -409,7 +606,6 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
headers.content_encoding = NULL; /* content encoding not known yet */
headers.transfer_encoding = NULL; /* transfer encoding not known yet */
saw_req_resp_or_header = FALSE; /* haven't seen anything yet */
- CLEANUP_PUSH(cleanup_headers, &headers);
while (tvb_reported_length_remaining(tvb, offset) != 0) {
/*
* Find the end of the line.
@@ -878,13 +1074,9 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
* for that content type?
*/
save_private_data = pinfo->private_data;
- /*
- * XXX - this won't get freed if the subdissector
- * throws an exception. Do we really need to
- * strdup it?
- */
+
if (headers.content_type_parameters)
- pinfo->private_data = g_strdup(headers.content_type_parameters);
+ pinfo->private_data = ep_strdup(headers.content_type_parameters);
else
pinfo->private_data = NULL;
/*
@@ -945,12 +1137,6 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
offset += datalen;
}
- /*
- * Clean up any header stuff, by calling and popping the cleanup
- * handler.
- */
- CLEANUP_CALL_AND_POP;
-
tap_queue_packet(http_tap, pinfo, stat_info);
return offset - orig_offset;
@@ -981,7 +1167,7 @@ basic_request_dissector(tvbuff_t *tvb, proto_tree *tree, int offset,
tokenlen = get_token_len(line, lineend, &next_token);
if (tokenlen == 0)
return;
- stat_info->request_uri = tvb_get_string(tvb, offset, tokenlen);
+ stat_info->request_uri = (gchar*) tvb_get_string(tvb, offset, tokenlen);
proto_tree_add_string(tree, hf_http_request_uri, tvb, offset, tokenlen,
stat_info->request_uri);
offset += next_token - line;
@@ -1079,7 +1265,7 @@ chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
break;
}
- c = chunk_string;
+ c = (gchar*) chunk_string;
/*
* We don't care about the extensions.
@@ -1088,7 +1274,7 @@ chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
*c = '\0';
}
- if (sscanf(chunk_string, "%x", &chunk_size) != 1) {
+ if ( ( chunk_size = strtol((gchar*)chunk_string, NULL, 16) ) == 0 ) {
g_free(chunk_string);
break;
}
@@ -1385,9 +1571,7 @@ is_http_request_or_reply(const gchar *data, int linelen, http_type_t *type,
if (isHttpRequestOrReply && reqresp_dissector) {
*reqresp_dissector = basic_request_dissector;
if (!stat_info->request_method)
- stat_info->request_method = g_malloc( index+1 );
- strncpy( stat_info->request_method, data, index);
- stat_info->request_method[index] = '\0';
+ stat_info->request_method = ep_strndup(data, index+1);
}
}
@@ -1482,10 +1666,7 @@ process_header(tvbuff_t *tvb, int offset, int next_offset,
* Fetch the value.
*/
value_len = line_end_offset - value_offset;
- value = g_malloc(value_len + 1);
- memcpy(value, &line[value_offset - offset], value_len);
- value[value_len] = '\0';
- CLEANUP_PUSH(g_free, value);
+ value = ep_strndup(&line[value_offset - offset], value_len);
/*
* Add it to the protocol tree as a particular field,
@@ -1515,10 +1696,8 @@ process_header(tvbuff_t *tvb, int offset, int next_offset,
break;
case HDR_CONTENT_TYPE:
- if (eh_ptr->content_type != NULL)
- g_free(eh_ptr->content_type);
- eh_ptr->content_type = g_malloc(value_len + 1);
- memcpy(eh_ptr->content_type, value, value_len + 1);
+ eh_ptr->content_type = (gchar*) ep_memdup((guint8*)value,value_len + 1);
+
for (i = 0; i < value_len; i++) {
c = value[i];
if (c == ';' || isspace(c)) {
@@ -1577,31 +1756,18 @@ process_header(tvbuff_t *tvb, int offset, int next_offset,
break;
case HDR_CONTENT_ENCODING:
- if (eh_ptr->content_encoding != NULL)
- g_free(eh_ptr->content_encoding);
- eh_ptr->content_encoding = g_malloc(value_len + 1);
- memcpy(eh_ptr->content_encoding, value, value_len);
- eh_ptr->content_encoding[value_len] = '\0';
+ eh_ptr->content_encoding = ep_strndup(value, value_len);
break;
case HDR_TRANSFER_ENCODING:
- if (eh_ptr->transfer_encoding != NULL)
- g_free(eh_ptr->transfer_encoding);
- eh_ptr->transfer_encoding = g_malloc(value_len + 1);
- memcpy(eh_ptr->transfer_encoding, value, value_len);
- eh_ptr->transfer_encoding[value_len] = '\0';
+ eh_ptr->transfer_encoding = ep_strndup(value, value_len);
break;
- case HDR_HOST:
- stat_info->http_host = g_strdup(value);
+ case HDR_HOST:
+ stat_info->http_host = ep_strndup(value, value_len);
break;
+
}
-
- /*
- * Free the value, by calling and popping the cleanup
- * handler for it.
- */
- CLEANUP_CALL_AND_POP;
}
}
@@ -1986,6 +2152,11 @@ proto_reg_handoff_http(void)
ntlmssp_handle = find_dissector("ntlmssp");
gssapi_handle = find_dissector("gssapi");
+
+ stats_tree_register("http","http","HTTP/Packet Counter", http_stats_tree_packet, http_stats_tree_init, NULL );
+ stats_tree_register("http","http_req","HTTP/Requests", http_req_stats_tree_packet, http_req_stats_tree_init, NULL );
+ stats_tree_register("http","http_srv","HTTP/Load Distribution",http_reqs_stats_tree_packet,http_reqs_stats_tree_init, NULL );
+
}
/*