/* Consumer - Once an IP has been resolved, add it to dwithe hostnames * hash structure. */ static void dns_worker (void GO_UNUSED (*ptr_data)) { char *ip = NULL, *host = NULL; while (1) { pthread_mutex_lock (&gdns_thread.mutex); /* wait until an item has been added to the queue */ while (gqueue_empty (gdns_queue)) pthread_cond_wait (&gdns_thread.not_empty, &gdns_thread.mutex); ip = gqueue_dequeue (gdns_queue); pthread_mutex_unlock (&gdns_thread.mutex); host = reverse_ip (ip); pthread_mutex_lock (&gdns_thread.mutex); if (!active_gdns) { if (host) free (host); break; } /* insert the corresponding IP -> hostname map */ if (host != NULL && active_gdns) { ht_insert_hostname (ip, host); free (host); } pthread_cond_signal (&gdns_thread.not_full); pthread_mutex_unlock (&gdns_thread.mutex); } }
static void set_host_sub_list (GHolder * h, GSubList * sub_list) { GMetrics *nmetrics; #ifdef HAVE_LIBGEOIP char city[CITY_LEN] = ""; char continent[CONTINENT_LEN] = ""; char country[COUNTRY_LEN] = ""; #endif char *host = h->items[h->idx].metrics->data, *hostname = NULL; #ifdef HAVE_LIBGEOIP /* add geolocation child nodes */ set_geolocation (host, continent, country, city); /* country */ if (country[0] != '\0') { set_host_child_metrics (country, MTRC_ID_COUNTRY, &nmetrics); add_sub_item_back (sub_list, h->module, nmetrics); h->items[h->idx].sub_list = sub_list; h->sub_items_size++; } /* city */ if (city[0] != '\0') { set_host_child_metrics (city, MTRC_ID_CITY, &nmetrics); add_sub_item_back (sub_list, h->module, nmetrics); h->items[h->idx].sub_list = sub_list; h->sub_items_size++; } #endif /* hostname */ if (conf.enable_html_resolver && conf.output_html) { hostname = reverse_ip (host); set_host_child_metrics (hostname, MTRC_ID_HOSTNAME, &nmetrics); add_sub_item_back (sub_list, h->module, nmetrics); h->items[h->idx].sub_list = sub_list; h->sub_items_size++; free (hostname); } }
static int reverse_ip(const char *host, char *reverse) { char *period; int offset, len; period = strchr(host, '.'); if (!period) { len = strlen(host); egg_memcpy(reverse, host, len); return(len); } else { len = period - host; offset = reverse_ip(host+len+1, reverse); reverse[offset++] = '.'; egg_memcpy(reverse+offset, host, len); reverse[offset+len] = 0; return(offset+len); } }
/* Perform an async dns reverse lookup. This does ip -> host. For host -> ip * use egg_dns_lookup(). We return a dns id that you can use to cancel the * lookup. */ int egg_dns_reverse(const char *ip, interval_t timeout, dns_callback_t callback, void *client_data) { dns_query_t *q; int i, cache_id; sdprintf("egg_dns_reverse(%s, %d)", ip, timeout); if (!is_dotted_ip(ip)) { /* If it's not a valid ip, don't even make the request. */ callback(-1, client_data, ip, NULL); return(-1); } /* Ok, see if we have it in our host cache. */ for (i = 0; i < nhosts; i++) { if (!egg_strcasecmp(hosts[i].ip, ip)) { dns_answer_t answer; answer_init(&answer); answer_add(&answer, hosts[i].host); callback(-1, client_data, ip, answer.list); answer_free(&answer); return(-1); } } cache_id = cache_find(ip); if (cache_id >= 0) { shuffleArray(cache[cache_id].answer.list, cache[cache_id].answer.len); callback(-1, client_data, ip, cache[cache_id].answer.list); return(-1); } /* check if the query was already made */ if (find_query(ip)) return(-1); q = alloc_query(client_data, callback, ip); /* We need to transform the ip address into the proper form * for reverse lookup. */ if (strchr(ip, ':')) { char temp[128] = ""; socket_ipv6_to_dots(ip, temp); sdprintf("dots: %s", temp); size_t iplen = strlen(temp) + 9 + 1; q->ip = (char *) my_calloc(1, iplen); // reverse_ip(temp, q->ip); strlcat(q->ip, temp, iplen); strlcat(q->ip, "ip6.arpa", iplen); sdprintf("reversed ipv6 ip: %s", q->ip); } else { size_t iplen = strlen(ip) + 13 + 1; q->ip = (char *) my_calloc(1, iplen); reverse_ip(ip, q->ip); strlcat(q->ip, ".in-addr.arpa", iplen); } dns_send_query(q); // /* setup timer to detect dead ns */ // dns_create_timeout_timer(&q, ip, timeout); return(q->id); }
/** * Generate JSON on complete fields for the following modules: * REQUESTS, REQUESTS_STATIC, NOT_FOUND, HOSTS */ static void print_json_complete (FILE * fp, GHolder * holder, int process) { #ifdef HAVE_LIBGEOIP char country[COUNTRY_LEN] = ""; char city[CITY_LEN] = ""; #endif char *data, *host, *method = NULL, *protocol = NULL; float percent; GHolder *h = holder; int i, j, hits; unsigned long long bw, usecs; for (i = 0; i < 4; i++) { switch (i) { case 0: h = holder + REQUESTS; fprintf (fp, "\t\"%s\": [\n", REQUE_ID); break; case 1: h = holder + REQUESTS_STATIC; fprintf (fp, "\t\"%s\": [\n", STATI_ID); break; case 2: h = holder + NOT_FOUND; fprintf (fp, "\t\"%s\": [\n", FOUND_ID); break; case 3: h = holder + HOSTS; fprintf (fp, "\t\"%s\": [\n", HOSTS_ID); break; } for (j = 0; j < h->idx; j++) { hits = h->items[j].hits; data = h->items[j].data; percent = get_percentage (process, hits); percent = percent < 0 ? 0 : percent; bw = h->items[j].bw; usecs = h->items[j].usecs; method = h->items[j].method; protocol = h->items[j].protocol; fprintf (fp, "\t\t{\n"); fprintf (fp, "\t\t\t\"hits\": \"%d\",\n", hits); fprintf (fp, "\t\t\t\"percent\": \"%4.2f%%\",\n", percent); fprintf (fp, "\t\t\t\"data\": \""); escape_json_output (fp, data); fprintf (fp, "\",\n"); fprintf (fp, "\t\t\t\"bytes\": \"%lld\"", bw); if (h->module == HOSTS) { if (conf.enable_html_resolver) { host = reverse_ip (data); fprintf (fp, ",\n\t\t\t\"host\": \""); escape_json_output (fp, host); fprintf (fp, "\""); free (host); } #ifdef HAVE_LIBGEOIP geoip_get_country (data, country); fprintf (fp, ",\n\t\t\t\"country\": \""); escape_json_output (fp, country); fprintf (fp, "\""); if (conf.geoip_city_data) { geoip_get_city (data, city); fprintf (fp, ",\n\t\t\t\"city\": \""); escape_json_output (fp, city); fprintf (fp, "\""); } #endif } if (conf.serve_usecs) fprintf (fp, ",\n\t\t\t\"time_served\": \"%lld\"", usecs); if (conf.append_protocol && protocol) fprintf (fp, ",\n\t\t\t\"protocol\": \"%s\"", protocol); if (conf.append_method && method) fprintf (fp, ",\n\t\t\t\"method\": \"%s\"", method); fprintf (fp, "\n\t\t}"); if (j != h->idx - 1) fprintf (fp, ",\n"); else fprintf (fp, "\n"); } if (i != 3) fprintf (fp, "\t],\n"); else fprintf (fp, "\t]\n"); } }
static void print_html_hosts (FILE * fp, GHolder * h, int process) { GAgents *agents; char *data, *bandwidth, *usecs, *ag, *ptr_value, *host; float percent, l; int hits; int i, j, max, until = 0, delims = 0, colspan = 6; size_t alloc = 0; #ifdef HAVE_LIBGEOIP const char *location = NULL; colspan++; #endif if (h->idx == 0) return; print_html_h2 (fp, HOSTS_HEAD, HOSTS_ID); print_p (fp, HOSTS_DESC); print_html_begin_table (fp); print_html_begin_thead (fp); fprintf (fp, "<tr>"); fprintf (fp, "<th></th>"); fprintf (fp, "<th>Hits</th>"); fprintf (fp, "<th>%%</th>"); fprintf (fp, "<th>Bandwidth</th>"); if (conf.serve_usecs) { colspan++; fprintf (fp, "<th>Time served</th>"); } fprintf (fp, "<th>IP</th>"); #ifdef HAVE_LIBGEOIP fprintf (fp, "<th>Country</th>"); #endif if (conf.enable_html_resolver) { colspan++; fprintf (fp, "<th>Hostname</th>"); } fprintf (fp, "<th style=\"width:100%%;text-align:right;\">"); fprintf (fp, "<span class=\"r\" onclick=\"t(this)\">◀</span>"); fprintf (fp, "</th>"); fprintf (fp, "</tr>"); print_html_end_thead (fp); print_html_begin_tbody (fp); until = h->idx < MAX_CHOICES ? h->idx : MAX_CHOICES; max = 0; for (i = 0; i < until; i++) { if (h->items[i].hits > max) max = h->items[i].hits; } for (i = 0; i < until; i++) { hits = h->items[i].hits; data = h->items[i].data; percent = get_percentage (process, hits); percent = percent < 0 ? 0 : percent; bandwidth = filesize_str (h->items[i].bw); l = get_percentage (max, hits); l = l < 1 ? 1 : l; #ifdef HAVE_LIBTOKYOCABINET ag = tc_db_get_str (ht_hosts_agents, data); #else ag = g_hash_table_lookup (ht_hosts_agents, data); #endif print_html_begin_tr (fp, i > OUTPUT_N ? 1 : 0); fprintf (fp, "<td>"); if (ag != NULL) fprintf (fp, "<span class=\"s\" onclick=\"a(this)\">▶</span>"); else fprintf (fp, "<span class=\"s\">-</span>"); fprintf (fp, "</td>"); fprintf (fp, "<td>%d</td>", hits); fprintf (fp, "<td>%4.2f%%</td>", percent); fprintf (fp, "<td>"); clean_output (fp, bandwidth); fprintf (fp, "</td>"); /* usecs */ if (conf.serve_usecs) { usecs = usecs_to_str (h->items[i].usecs); fprintf (fp, "<td>"); clean_output (fp, usecs); fprintf (fp, "</td>"); free (usecs); } fprintf (fp, "<td>%s</td>", data); #ifdef HAVE_LIBGEOIP location = get_geoip_data (data); fprintf (fp, "<td style=\"white-space:nowrap;\">%s</td>", location); #endif if (conf.enable_html_resolver) { host = reverse_ip (data); fprintf (fp, "<td style=\"white-space:nowrap;\">%s</td>", host); free (host); } fprintf (fp, "<td class=\"graph\">"); fprintf (fp, "<div class=\"bar\" style=\"width:%f%%\"></div>", l); fprintf (fp, "</td>"); print_html_end_tr (fp); /* render agents for each host */ if (ag != NULL) { ptr_value = (char *) ag; delims = count_occurrences (ptr_value, '|'); /* round-up + padding */ alloc = ((strlen (ptr_value) + 300 - 1) / 300) + delims + 1; agents = xmalloc (alloc * sizeof (GAgents)); memset (agents, 0, alloc * sizeof (GAgents)); /* split agents into struct */ split_agent_str (ptr_value, agents, 300); fprintf (fp, "<tr class=\"agent-hide\">\n"); fprintf (fp, "<td colspan=\"%d\">\n", colspan); fprintf (fp, "<div>"); fprintf (fp, "<table class=\"pure-table-striped\">"); /* output agents from struct */ for (j = 0; (j < 10) && (agents[j].agents != NULL); j++) { print_html_begin_tr (fp, 0); fprintf (fp, "<td>"); clean_output (fp, agents[j].agents); fprintf (fp, "</td>"); print_html_end_tr (fp); } fprintf (fp, "</table>\n"); fprintf (fp, "</div>\n"); fprintf (fp, "</td>\n"); print_html_end_tr (fp); for (j = 0; (agents[j].agents != NULL); j++) free (agents[j].agents); free (agents); #ifdef HAVE_LIBTOKYOCABINET if (ag) free (ag); #endif } free (bandwidth); } print_html_end_tbody (fp); print_html_end_table (fp); }