corz.org uses cookies to remember that you've seen this notice explaining that corz.org uses cookies, okay!
corz.org text viewer..
[currently viewing: / public/ mac/ soft/ stuff/ www.c - raw]
static int refresh;
static char cellbg_1[] = "\"
static char cellbg_2[] = "\"
static void html_graph(content *cnt, const char *title,
const int GRAPHWIDTH, const int GRAPHHEIGHT,
const int64 graph_in[], const int64 graph_out[],
const int pos, const int GRAPH_SIZE)
{
int i, total_width = 0, total_strips = 0, skip,
incr = (graph_in == graph_day_in);
double divisor;
int64 max_transfer;
char *maximum;
int64 *local_in, *local_out;
local_in = (int64*)malloc(sizeof(int64) * GRAPH_SIZE);
local_out = (int64*)malloc(sizeof(int64) * GRAPH_SIZE);
if (!local_in || !local_out)
freakout("Ran out of memory in html_graph()");
memcpy(local_in, graph_in, sizeof(int64) * GRAPH_SIZE);
memcpy(local_out, graph_out, sizeof(int64) * GRAPH_SIZE);
SET64(max_transfer, 0,0);
for (i=0; i<GRAPH_SIZE; i++)
{
int64 tmp;
tmp = graph_in[i];
i64add64(tmp, graph_out[i]);
max_transfer = i64max(max_transfer, tmp);
}
c_appendf(cnt,
"<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\">"
"<tr><td bgcolor=\"
"<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\">"
"<tr><td align=\"center\">"
"<font color=\"
"(<b><font color=" _IN ">%s</font></b> %s "
"<b><font color=" _OUT ">%s</font></b>)<br>"
"%s %'Lu %s</td></tr>"
"<tr><td bgcolor=\"
"<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\">",
title, _("in"), _("and"), _("out"),
_("Maximum:"), max_transfer, _("bytes"));
c_appendf(cnt,
"<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\">"
"<tr><td bgcolor=\"
"<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\">"
"<tr><td align=\"center\">"
"<font color=\"
"(<b><font color=" _IN ">%s</font></b> %s "
"<b><font color=" _OUT ">%s</font></b>)<br>"
"%s %s %s</td></tr>"
"<tr><td bgcolor=\"
"<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\">",
title, _("in"), _("and"), _("out"),
_("Maximum:"), maximum = strint64(max_transfer), _("bytes"));
free(maximum);
divisor = db_i64div32(max_transfer, GRAPHHEIGHT);
if (divisor < 1.0) divisor = 1.0;
c_appends(cnt, "<tr>");
i = pos;
do
{
int in, out, blank, width;
char alt[64];
char *in64, *out64;
i++;
if (i >= GRAPH_SIZE) i = 0;
width = (GRAPHWIDTH - total_width - 2*GRAPH_SIZE) /
(GRAPH_SIZE - total_strips);
total_strips++;
total_width += width;
in = i_i64divdb(graph_in[i], divisor);
out = i_i64divdb(graph_out[i], divisor);
blank = GRAPHHEIGHT - in - out;
snprintf(alt, 64, "%d: %s %s / %s %s",
i+incr,
in64 = strint64(graph_in[i]), _("in"),
out64 = strint64(graph_out[i]), _("out"));
free(in64);
free(out64);
snprintf(alt, 64, "%d: %'Lu %s / %'Lu %s",
i+incr,
graph_in[i], _("in"),
graph_out[i], _("out"));
c_appends(cnt, "<td valign=\"bottom\">");
if (blank)
{
c_appendf(cnt,
"<img src=\"i/x\" width=\"%d\" height=\"%d\">",
width, blank);
}
if (in) c_appendf(cnt,
"%s<img src=\"i/i\" width=\"%d\" height=\"%d\" "
"alt=\"%s\" title=\"%s\">",
(blank)?"<br>":"", width, in, alt, alt);
if (out) c_appendf(cnt,
"%s<img src=\"i/o\" width=\"%d\" height=\"%d\" "
"alt=\"%s\" title=\"%s\">",
(in||blank)?"<br>":"", width, out, alt,
alt);
c_appends(cnt, "</td>");
}
while (i != pos);
c_appends(cnt, "</tr>");
if (GRAPH_SIZE > 31)
{
c_appends(cnt, "<tr align=\"center\">");
skip = 3;
}
else
{
c_appends(cnt, "<tr align=\"right\">");
skip = 2;
}
for (i=0; i<GRAPH_SIZE; i+=skip)
{
int num = (i+pos+2) % GRAPH_SIZE;
if (GRAPH_SIZE == 31 && i+skip >= GRAPH_SIZE)
c_appends(cnt, "<td><font size=\"-3\">"
" </font></td>");
else
c_appendf(cnt,
"<td colspan=\"%d\"><font size=\"-3\">"
"%d"
"</font></td>",
skip, num+incr);
}
c_appends(cnt,
"</tr>");
c_appends(cnt,
"</table>"
"</td></tr></table></td></tr></table>");
free(local_in);
free(local_out);
}
static const char css[] =
"<style type=\"text/css\">"
"A{color:
"A:hover{color:
"A.black{color:
"A.black:hover{color:
"text-decoration:underline;}"
"</style>";
static char *linkbox = NULL;
static void init_linkbox(void)
{
char buf[1024];
sprintf(buf,
"<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">"
"<tr><td bgcolor=\"
" " PACKAGE " v" VERSION " "
"</b></font></td>"
"<td bgcolor=\"
"<table border=\"0\" cellspacing=\"1\" cellpadding=\"2\">"
"<tr><td bgcolor=\"
"<a href=\"/\">%s</a> | "
"<a href=\"hosts-total.html\">%s</a> | "
"<a href=\"ports-total.html\">%s</a> | "
"<a href=\"protocols.html\">%s</a> | "
"<a href=\"graphs.html\">%s</a> | "
"<a href=\"" HOMEPAGE "\">%s</a>"
"</td></tr></table>"
"</td></tr></table>",
_("main"), _("hosts"), _("ports"), _("protocols"),
_("graphs"), _("homepage")
);
linkbox = strdup(buf);
if (!linkbox) freakout("WWW: ran out of memory for linkbox");
}
static void refresh_header(content *cnt, const char *title)
{
if (refresh) c_appendf(cnt,
"<html><head><title>darkstat : %s</title>"
"<meta http-equiv=\"refresh\" content=\"%d\">"
"%s</head><body>%s<br>",
title, refresh, css, linkbox);
else c_appendf(cnt,
"<html><head><title>darkstat : %s</title>"
"%s</head><body>%s<br>",
title, css, linkbox);
}
static void refresh_footer(content *cnt)
{
if (refresh == 0)
{
c_appends(cnt, "<br><form method=\"GET\">");
c_appendf(cnt, _("Want this page refreshed every %s seconds?"),
"<input type=\"text\" name=\"refresh\" value=\"5\" "
"size=\"4\">");
c_appendf(cnt, " <input type=\"submit\" value=\"%s\"></form>"
"</body></html>",
_("Yes"));
}
else
{
char buf[70];
snprintf(buf, 70, "<input type=\"text\" name=\"refresh\" "
"value=\"%d\" size=\"4\">", refresh);
c_appends(cnt, "<br><form method=\"GET\">");
c_appendf(cnt, _("This page is being refreshed "
"every %s seconds."), buf);
c_appendf(cnt, "<input type=\"submit\" value=\"%s\"> "
"<input type=\"submit\" value=\"%s\" name=\"cutitout\">"
"</form></body></html>",
_("Change"), _("Stop"));
}
}
static content *www_frontpage(void)
{
char *x_packets, *x_data, *x_hosts;
content *cnt = c_new();
time_t uptime = t_already + (time(NULL) - t_start);
dword days, hours, minutes;
refresh_header(cnt, _("main"));
c_appends(cnt,
"<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\">");
c_appendf(cnt,
"<tr><td align=\"right\"><b>%s</b></td>"
"<td>%'Lu</td></tr>"
"<tr><td align=\"right\"><b>%s</b></td>"
"<td>%'Lu %s</td></tr>"
"<tr><td align=\"right\"><b>%s</b></td>"
"<td>%'u</td></tr>",
_("Packets captured:"), num_packets,
_("Data off the wire:"), total_data, _("bytes"),
_("Unique hosts:"), host_db_used() );
c_appendf(cnt,
"<tr><td align=\"right\"><b>%s</b></td>"
"<td>%s</td></tr>"
"<tr><td align=\"right\"><b>%s</b></td>"
"<td>%s %s</td></tr>"
"<tr><td align=\"right\"><b>%s</b></td>"
"<td>%s</td></tr>" ,
_("Packets captured:"), x_packets = strint64(num_packets),
_("Data off the wire:"), x_data = strint64(total_data), _("bytes"),
_("Unique hosts:"), x_hosts = strint32(host_db_used()) );
free(x_packets);
free(x_data);
free(x_hosts);
days = uptime / S_DAY;
uptime -= days * S_DAY;
hours = uptime / S_HR;
uptime -= hours * S_HR;
minutes = uptime / S_MIN;
uptime -= minutes * S_MIN;
c_appendf(cnt, "<tr><td align=\"right\"><b>%s:</b></td><td>",
_("Counting"));
if (days)
c_appendf(cnt, "%u %s ", days, _("days"));
if (days || hours)
c_appendf(cnt, "%u %s ", hours, _("hours"));
if (days || hours || minutes)
c_appendf(cnt, "%u %s ", minutes, _("minutes"));
c_appendf(cnt, "%u %s ", uptime, _("seconds"));
c_appendf(cnt, "<tr><td align=\"right\"><b>%s</b></td>"
"<td>%s</td></tr></table><br>",
_("Running since:"), asctime(localtime(&t_start)) );
pthread_mutex_lock(&graph_mutex);
graph_calibrate_to_clock();
html_graph(cnt, _("Last 60 seconds"), 400, 200,
graph_sec_in, graph_sec_out, g_secs, GRAPH_SECS);
pthread_mutex_unlock(&graph_mutex);
c_appendf(cnt,
"<br>%s ::[ "
"%s<a href=\"/dns-on.html\">%s</a>%s | "
"%s<a href=\"/dns-off.html\">%s</a>%s | "
"%s<a href=\"/dns-cycle.html\">%s</a>%s "
"]::<br>",
_("DNS resolution is"),
(want_resolve==ON)?"<b>":"", _("on"), (want_resolve==ON)?"</b>":"",
(want_resolve==OFF)?"<b>":"", _("off"), (want_resolve==OFF)?"</b>":"",
(want_resolve==IN_PROGRESS)?"<b>":"", _("cycling once"),
(want_resolve==IN_PROGRESS)?"</b>":""
);
refresh_footer(cnt);
return cnt;
}
static content *www_graphs(void)
{
content *cnt = c_new();
refresh_header(cnt, _("graphs"));
c_appends(cnt,
"<table border=\"0\">"
"<tr><td align=\"center\">");
pthread_mutex_lock(&graph_mutex);
graph_calibrate_to_clock();
html_graph(cnt, _("Last 60 seconds"), 300, 200,
graph_sec_in, graph_sec_out, g_secs, GRAPH_SECS);
c_appends(cnt, "</td><td align=\"center\">");
html_graph(cnt, _("Last 60 minutes"), 300, 200,
graph_min_in, graph_min_out, g_mins, GRAPH_MINS);
c_appends(cnt, "</td></tr><tr><td align=\"center\">");
html_graph(cnt, _("Last 24 hours"), 300, 200,
graph_hr_in, graph_hr_out, g_hrs, GRAPH_HRS);
c_appends(cnt, "</td><td align=\"center\">");
html_graph(cnt, _("Last 30 days"), 300, 200,
graph_day_in, graph_day_out, g_days, GRAPH_DAYS);
pthread_mutex_unlock(&graph_mutex);
c_appends(cnt, "</td></tr></table>");
refresh_footer(cnt);
return cnt;
}
static content *www_hosts(const sort_type st, const int limited)
{
int i;
content *cnt = c_new();
host_record **list;
int listend, used = host_db_used();
char *cellbg = cellbg_2;
refresh_header(cnt, _("hosts"));
pthread_mutex_lock(&db_mutex);
if (limited)
c_appendf(cnt,
_("Hosts (sorted by %s, top %d)"),
(st==IN)?_("incoming"):(st==OUT)?_("outgoing"):
(st==TOTAL)?_("total"):(st==MAIN)?_("IP"):"ERROR",
min(HOST_REPORT_LIMIT, used));
else
c_appendf(cnt,
_("Hosts (sorted by %s)"),
(st==IN)?_("incoming"):(st==OUT)?_("outgoing"):
(st==TOTAL)?_("total"):(st==MAIN)?_("IP"):"ERROR");
list = host_db_sort(st);
pthread_mutex_unlock(&db_mutex);
c_appendf(cnt, "<br><br>"
"<table border=\"0\" cellpadding=\"1\" cellspacing=\"0\">"
"<tr><td bgcolor=\"
"<table border=\"0\" cellspacing=\"0\" cellpadding=\"2\"><tr>"
"<td><font color=\"
"<b><a class=\"black\" href=\"hosts-ip.html\">%s</a></b>"
" (<a class=\"black\" href=\"hosts-ip-full.html\">%s</a>)"
"</font></td>"
"<td><font color=\"
"<td><font color=\"
"<b><a class=\"black\" href=\"hosts-in.html\">%s</a></b>"
" (<a class=\"black\" href=\"hosts-in-full.html\">%s</a>)"
"</font></td>"
"<td><font color=\"
"<b><a class=\"black\" href=\"hosts-out.html\">%s</a></b>"
" (<a class=\"black\" href=\"hosts-out-full.html\">%s</a>)"
"</font></td>"
"<td><font color=\"
"<b><a class=\"black\" href=\"hosts-total.html\">%s</a></b>"
" (<a class=\"black\" href=\"hosts-total-full.html\">%s</a>)"
"</font></td>"
"</tr>",
_("IP"), _("full"),
_("Hostname"),
_("In"), _("full"),
_("Out"), _("full"),
_("Total"), _("full")
);
if (limited)
listend = used-HOST_REPORT_LIMIT;
else
listend = 0;
if (listend < 0) listend = 0;
for (i=used-1; i>=listend; i--)
{
host_record *h;
int64 t64;
char *data_in, *data_out, *total;
cellbg = (cellbg == cellbg_1) ? cellbg_2 : cellbg_1;
h = list[i];
t64 = h->data_in;
i64add64(t64, h->data_out);
c_appendf(cnt,
"<tr>"
"<td bgcolor=%s>%d.%d.%d.%d</td>"
"<td bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%'Lu</td>"
"<td align=\"right\" bgcolor=%s>%'Lu</td>"
"<td align=\"right\" bgcolor=%s>%'Lu</td></tr>",
cellbg, (h->ip_addr >> 24) & 255,
(h->ip_addr >> 16) & 255,
(h->ip_addr >> 8) & 255,
h->ip_addr & 255,
cellbg, h->hostname?h->hostname:" ",
cellbg, h->data_in,
cellbg, h->data_out,
cellbg, h->data_in + h->data_out);
c_appendf(cnt,
"<tr>"
"<td bgcolor=%s>%d.%d.%d.%d</td>"
"<td bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%s</td></tr>",
cellbg, (h->ip_addr >> 24) & 255,
(h->ip_addr >> 16) & 255,
(h->ip_addr >> 8) & 255,
h->ip_addr & 255,
cellbg, h->hostname?h->hostname:" ",
cellbg, data_in = strint64(h->data_in),
cellbg, data_out = strint64(h->data_out),
cellbg, total = strint64(t64));
free(data_in);
free(data_out);
free(total);
}
free(list);
c_appends(cnt,
"</table>"
"</td></tr></table>");
refresh_footer(cnt);
return cnt;
}
static content *www_ports(const sort_type st, const int limited)
{
content *cnt = c_new();
int i;
port_record **list;
int listend;
char *cellbg = cellbg_2;
refresh_header(cnt, _("ports"));
pthread_mutex_lock(&db_mutex);
if (limited)
c_appendf(cnt,
_("Ports (TCP, sorted by %s, top %d)"),
(st==IN)?_("incoming"):(st==OUT)?_("outgoing"):
(st==TOTAL)?_("total"):(st==MAIN)?_("port number"):
"ERROR",
min(PORT_REPORT_LIMIT, port_db.used));
else
c_appendf(cnt,
_("Ports (TCP, sorted by %s)"),
(st==IN)?_("incoming"):(st==OUT)?_("outgoing"):
(st==TOTAL)?_("total"):(st==MAIN)?_("port number"):
"ERROR");
c_appendf(cnt, "<br><br>"
"<table border=\"0\" cellpadding=\"1\" cellspacing=\"0\">"
"<tr><td bgcolor=\"
"<table border=\"0\" cellspacing=\"1\" cellpadding=\"2\">"
"<tr>"
"<td colspan=\"2\"><font color=\"
"<b><a class=\"black\" href=\"ports-num.html\">%s</a></b>"
" (<a class=\"black\" href=\"ports-num-full.html\">%s</a>)"
"</font></td>"
"<td><font color=\"
"<b><a class=\"black\" href=\"ports-in.html\">%s</a></b>"
" (<a class=\"black\" href=\"ports-in-full.html\">%s</a>)"
"</font></td>"
"<td><font color=\"
"<b><a class=\"black\" href=\"ports-out.html\">%s</a></b>"
" (<a class=\"black\" href=\"ports-out-full.html\">%s</a>)"
"</font></td>"
"<td><font color=\"
"<b><a class=\"black\" href=\"ports-total.html\">%s</a></b>"
" (<a class=\"black\" href=\"ports-total-full.html\">%s</a>)"
"</font></td>"
"</tr>",
_("Port"), _("full"),
_("In"), _("full"),
_("Out"), _("full"),
_("Total"), _("full")
);
list = port_db_sort(st);
if (limited)
listend = port_db.used-PORT_REPORT_LIMIT;
else
listend = 0;
if (listend < 0) listend = 0;
for (i=port_db.used-1; i>=listend; i--)
{
port_record *p;
int64 t64;
char *data_in, *data_out, *total;
const char *name;
cellbg = (cellbg == cellbg_1) ? cellbg_2 : cellbg_1;
p = list[i];
t64 = p->data_in;
i64add64(t64, p->data_out);
name = service_name(p->port);
if (!name) name = "(unknown)";
c_appendf(cnt,
"<tr>"
"<td bgcolor=%s>%d</td>"
"<td bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%'Lu</td>"
"<td align=\"right\" bgcolor=%s>%'Lu</td>"
"<td align=\"right\" bgcolor=%s>%'Lu</td></tr>",
cellbg,p->port,
cellbg,name,
cellbg,p->data_in,
cellbg,p->data_out,
cellbg,t64);
c_appendf(cnt,
"<tr>"
"<td bgcolor=%s>%d</td>"
"<td bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%s</td></tr>",
cellbg,p->port,
cellbg,name,
cellbg,data_in = strint64(p->data_in),
cellbg,data_out = strint64(p->data_out),
cellbg,total = strint64(t64));
free(data_in);
free(data_out);
free(total);
}
pthread_mutex_unlock(&db_mutex);
free(list);
c_appends(cnt,
"</table>"
"</td></tr></table>");
refresh_footer(cnt);
return cnt;
}
static content *www_protocols(void)
{
content *cnt = c_new();
char *cellbg = cellbg_2;
int i;
int64 zero;
SET64(zero, 0, 0);
refresh_header(cnt, _("protocols"));
c_appendf(cnt,
"<table border=\"0\" cellpadding=\"1\" cellspacing=\"0\">"
"<tr><td bgcolor=\"
"<table border=\"0\" cellspacing=\"1\" cellpadding=\"2\"><tr>"
"<td colspan=\"2\" bgcolor=\"
"<font color=\"
"<td bgcolor=\"
"<font color=\"
"<td bgcolor=\"
"<font color=\"
"<td bgcolor=\"
"<font color=\"
"<td bgcolor=\"
"<font color=\"
_("Protocol"), _("In"), _("Out"), _("Other"), _("Total"));
for (i=0; i<256; i++)
if (i64bigger(proto_in[i], zero) || i64bigger(proto_out[i], zero) ||
i64bigger(proto_other[i], zero))
{
int64 t64;
char *data_in, *data_out, *data_other, *total;
cellbg = (cellbg == cellbg_1) ? cellbg_2 : cellbg_1;
t64 = proto_in[i];
i64add64(t64, proto_out[i]);
i64add64(t64, proto_other[i]);
c_appendf(cnt,
"<tr><td bgcolor=%s align=\"right\">%d</td>"
"<td bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%'Lu</td>"
"<td align=\"right\" bgcolor=%s>%'Lu</td>"
"<td align=\"right\" bgcolor=%s>%'Lu</td>"
"<td align=\"right\" bgcolor=%s>%'Lu</td></tr>\n",
cellbg,i, cellbg,proto_name(i),
cellbg,proto_in[i],
cellbg,proto_out[i],
cellbg,proto_other[i],
cellbg,t64);
c_appendf(cnt,
"<tr><td bgcolor=%s align=\"right\">%d</td>"
"<td bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%s</td>"
"<td align=\"right\" bgcolor=%s>%s</td></tr>\n",
cellbg,i, cellbg,proto_name(i),
cellbg,data_in = strint64(proto_in[i]),
cellbg,data_out = strint64(proto_out[i]),
cellbg,data_other = strint64(proto_other[i]),
cellbg,total = strint64(t64));
free(data_in);
free(data_out);
free(data_other);
free(total);
}
c_appends(cnt,
"</table>"
"</td></tr></table>");
refresh_footer(cnt);
return cnt;
}
static inline content *new_gif(void)
{
content *cnt = c_new();
assert(GIF_SIZE <= cnt->pool);
memcpy(cnt->buf, gif, GIF_SIZE);
cnt->used = GIF_SIZE;
return cnt;
}
static content *info_menu(void)
{
content *c = c_new();
c_appendf(c,
"<html><head>"
"<title>%s</title>"
"</head><body>"
"<h1>%s</h1>", _("Info"), _("Info")
);
c_appendf(c,
"<a href=\"/info/bytes-total.txt\">%s</a>",
_("Data off the wire")
);
c_appendf(c,
"</body></html>"
);
return c;
}
static content *info_bytes_total(void)
{
char *x_data;
content *cnt = c_new();
c_appendf(cnt, "%'Lu", total_data);
c_appendf(cnt, "%s", x_data = strint64(total_data));
free(x_data);
return cnt;
}
static content *www_unimplemented(void)
{
content *c = c_new();
c_appendf(c,
"<html><body>"
"<h1>%s</h1>%s"
"</body></html>",
_("Not Implemented"),
_("Whatever the heck you just requested, I can't generate.")
);
return c;
}
static content *www_notfound(void)
{
content *c = c_new();
c_appendf(c,
"<html><body>"
"<h1>%s</h1>%s"
"</body></html>",
_("Not Found"),
_("Whatever you just requested, I don't have.")
);
return c;
}
static content *redirect(const char *url)
{
content *c = c_new();
c_appendf(c,
"<html><head>"
"<meta http-equiv=\"REFRESH\" content=\"0; URL=%s\">"
"</head>"
"<body>Moved <a href=\"%s\">here</a>.</body></html>",
url, url);
return c;
}
static SOCKET sb_socket[SCOREBOARD];
static int sb_state[SCOREBOARD];
static char sb_request[SCOREBOARD][MAX_REQ_SIZE];
static content *sb_reply[SCOREBOARD];
static ssize_t sb_sent[SCOREBOARD];
static void kill_connection(const int slot)
{
if (sb_socket[slot] != -1)
{
shutdown(sb_socket[slot], SHUT_WR);
close(sb_socket[slot]);
}
sb_socket[slot] = -1;
sb_state[slot] = STATE_OPEN;
sb_request[slot][0] = 0;
if (sb_reply[slot]) c_delete(&(sb_reply[slot]));
assert(sb_reply[slot] == NULL);
sb_sent[slot] = 0;
}
static int get_url(const char *request, const char *url)
{
char d = request[strlen(url)];
if (memcmp(request, url, strlen(url)) != 0) return 0;
if (d == '\r' || d == '\n' || d == ' ' || d == '?') return 1;
else return 0;
}
static void http_200_ok(content *hdr, const int is_cachable)
{
char datebuf[200];
time_t now = time(NULL);
struct tm *tm = gmtime(&now);
strftime(datebuf, 200,
"%a, %e %b %Y %H:%M:%S GMT", tm);
c_appendf(hdr,
"HTTP/1.1 200 OK\r\n"
"Date: %s\r\n"
"Last-Modified: %s\r\n",
datebuf, datebuf);
if (!is_cachable)
c_appendf(hdr, "Expires: %s\r\n", datebuf);
else
{
now += 86400;
tm = gmtime(&now);
strftime(datebuf, 200,
"%a, %e %b %Y %H:%M:%S GMT", tm);
c_appendf(hdr, "Expires: %s\r\n", datebuf);
}
}
static void handle_connection(const int slot)
{
content *hdr, *cnt;
char *request = sb_request[slot], *tmp, *tmp2;
int pos, recvd, is_gif = 0, is_txt = 0;
SOCKET incoming = sb_socket[slot];
assert(incoming != -1);
if (sb_state[slot] == STATE_REQUEST)
{
pos = strlen(request);
recvd = recv(incoming, request+pos, MAX_REQ_SIZE-1-pos,
MSG_NOSIGNAL);
request[pos+recvd] = 0;
if (recvd == MAX_REQ_SIZE-1-pos)
{
if (verbose)
printf("WWW(%d): Request %d exceeded "
"size of %d.\n",
getpid(), slot, MAX_REQ_SIZE);
kill_connection(slot);
return;
}
if (recvd < 1)
{
if (verbose)
printf("WWW(%d): Request %d broke off.\n",
getpid(), slot);
kill_connection(slot);
return;
}
if (
(strcmp(request+strlen(request)-2, "\n\n") == 0) ||
(strcmp(request+strlen(request)-2, "\r\r") == 0) ||
(strcmp(request+strlen(request)-4, "\r\n\r\n") == 0) ||
(strcmp(request+strlen(request)-4, "\n\r\n\r") == 0) )
{
sb_state[slot] = STATE_REQCOMPLETE;
shutdown(incoming, 0);
hdr = c_new();
refresh = 0;
tmp = strstr(request, "Referer: ");
if (!tmp) tmp = request + MAX_REQ_SIZE;
tmp2 = strstr(request, "?refresh=");
if (tmp2 && tmp2 < tmp) refresh = atoi(tmp2+9);
tmp2 = strstr(request, "cutitout=");
if (tmp2 && tmp2 < tmp) refresh = 0;
if (!CMP("GET ")) {
c_appends(hdr, "HTTP/1.1 501 Not Implemented\r\n");
cnt = www_unimplemented();
}
else if GET("/")
cnt = www_frontpage();
else if GET("/hosts-total.html")
cnt = www_hosts(TOTAL,1);
else if GET("/hosts-total-full.html")
cnt = www_hosts(TOTAL,0);
else if GET("/hosts-ip.html")
cnt = www_hosts(MAIN,1);
else if GET("/hosts-ip-full.html")
cnt = www_hosts(MAIN,0);
else if GET("/hosts-in.html")
cnt = www_hosts(IN,1);
else if GET("/hosts-in-full.html")
cnt = www_hosts(IN,0);
else if GET("/hosts-out.html")
cnt = www_hosts(OUT,1);
else if GET("/hosts-out-full.html")
cnt = www_hosts(OUT,0);
else if GET("/ports-total.html")
cnt = www_ports(TOTAL,1);
else if GET("/ports-total-full.html")
cnt = www_ports(TOTAL,0);
else if GET("/ports-num.html")
cnt = www_ports(MAIN,1);
else if GET("/ports-num-full.html")
cnt = www_ports(MAIN,0);
else if GET("/ports-in.html")
cnt = www_ports(IN,1);
else if GET("/ports-in-full.html")
cnt = www_ports(IN,0);
else if GET("/ports-out.html")
cnt = www_ports(OUT,1);
else if GET("/ports-out-full.html")
cnt = www_ports(OUT,0);
else if GET("/protocols.html")
cnt = www_protocols();
else if GET("/graphs.html")
cnt = www_graphs();
else if CMP("GET /i/")
{
if (strstr(request,"If-Modified-Since:"))
{
sb_reply[slot] = hdr;
c_appends(sb_reply[slot],
"HTTP/1.1 304 Not Modified\r\n");
sb_state[slot] = STATE_REPLY;
return;
}
cnt = new_gif();
is_gif = 1;
if GET("/i/i")
{
cnt->buf[GIF_RED] = _I_R;
cnt->buf[GIF_GREEN] = _I_G;
cnt->buf[GIF_BLUE] = _I_B;
}
else if GET("/i/o")
{
cnt->buf[GIF_RED] = _O_R;
cnt->buf[GIF_GREEN] = _O_G;
cnt->buf[GIF_BLUE] = _O_B;
}
else
cnt->buf[GIF_PIXEL] = GIF_TRANSPARENT;
}
else if CMP("GET /dns-")
{
c_appends(hdr,
"HTTP/1.1 302 Found\r\n"
"Location: /\r\n");
if GET("/dns-on.html") want_resolve = ON;
else if GET("/dns-off.html") want_resolve = OFF;
else if GET("/dns-cycle.html") want_resolve = IN_PROGRESS;
cnt = redirect("/");
}
else if CMP("GET /info")
{
if GET("/info") {
c_appends(hdr,
"HTTP/1.1 302 Found\r\n"
"Location: /info/\r\n");
cnt = redirect("/info/");
}
else if GET("/info/") cnt = info_menu();
else if GET("/info/bytes-total.txt")
{
is_txt = 1;
cnt = info_bytes_total();
}
}
else
{
c_appends(hdr, "HTTP/1.1 404 Not Found\r\n");
cnt = www_notfound();
}
if (!hdr->used) http_200_ok(hdr, is_gif);
if (is_gif)
{
c_appends(hdr,
"Cache-Control: public\r\n"
"Content-Type: image/gif\r\n");
}
else
{
c_appends(hdr,
"Cache-Control: no-cache, must-revalidate, "
"max-age=0\r\n");
if (is_txt)
c_appends(hdr,
"Content-Type: text/plain\r\n");
else
c_appends(hdr,
"Content-Type: text/html; "
"charset=UTF-8\r\n");
}
c_appendf(hdr, "Content-Length: %d\r\n"
"Connection: close\r\n"
"\r\n",
cnt->used);
sb_reply[slot] = hdr;
sb_sent[slot] = 0;
c_appendsl(sb_reply[slot], cnt->buf, cnt->used);
c_delete(&cnt);
sb_state[slot] = STATE_REPLY;
}
return;
}
if (sb_state[slot] == STATE_REPLY)
{
ssize_t sent = send(incoming,
sb_reply[slot]->buf + sb_sent[slot],
sb_reply[slot]->used - sb_sent[slot],
MSG_NOSIGNAL);
if (sent < 1)
{
if (verbose)
printf("WWW(%d): Slot %d died during "
"reply sending.\n",
getpid(), slot);
kill_connection(slot);
return;
}
if ((unsigned)sent == sb_reply[slot]->used - sb_sent[slot])
kill_connection(slot);
else
{
if (verbose)
printf("sent %d+%d, used %d\n",
sb_sent[slot], sent,
sb_reply[slot]->used);
sb_sent[slot] += sent;
}
}
}
static RETSIGTYPE broken_pipe(int signum unused)
{
if (verbose) printf("WWW: Suppressed SIGPIPE.\n");
}
SOCKET sockin;
void www_poll(void)
{
int i, max_fd, sb_open = -1;
struct timeval timeout;
fd_set r_fd, w_fd;
max_fd = sockin;
FD_ZERO(&r_fd);
FD_ZERO(&w_fd);
for (i=0; i<SCOREBOARD; i++)
{
if (sb_socket[i] != -1)
max_fd = max(max_fd, sb_socket[i]);
else
sb_open = i;
if (sb_state[i] == STATE_REQUEST)
FD_SET(sb_socket[i], &r_fd);
if (sb_state[i] == STATE_REPLY)
FD_SET(sb_socket[i], &w_fd);
}
if (sb_open != -1)
FD_SET(sockin, &r_fd);
timeout.tv_sec = POLLDELAY;
timeout.tv_usec = 0;
if (select(max_fd+1, &r_fd, &w_fd, NULL, &timeout) == -1)
return;
if (FD_ISSET(sockin, &r_fd))
{
struct sockaddr_in addrin;
int sin_size;
SOCKET incoming;
assert(sb_open != -1);
sin_size = sizeof(struct sockaddr);
incoming = accept(sockin, (struct sockaddr *)&addrin,
&sin_size);
if (incoming < 0)
{
if (verbose)
printf("WWW: Lost a connection in accept()\n");
}
else
{
if (verbose)
printf("WWW: Got a connection from %s:%d\n",
inet_ntoa(addrin.sin_addr),
ntohs(addrin.sin_port));
sb_socket[sb_open] = incoming;
sb_state[sb_open] = STATE_REQUEST;
}
}
for (i=0; i<SCOREBOARD; i++)
if (sb_socket[i] != -1)
if (FD_ISSET(sb_socket[i], &r_fd) ||
FD_ISSET(sb_socket[i], &w_fd))
handle_connection(i);
}
void www_main(void *ignored unused)
{
struct sockaddr_in addrin;
int sockopt = 1, i;
for (i=0; i<SCOREBOARD; i++)
{
sb_socket[i] = -1;
sb_state[i] = STATE_OPEN;
sb_request[i][0] = 0;
sb_reply[i] = NULL;
sb_sent[i] = 0;
}
sockin = socket(AF_INET, SOCK_STREAM, 0);
if (sockin < 0) freakout("WWW: Problem creating socket");
if (setsockopt(sockin, SOL_SOCKET, SO_REUSEADDR,
(char*)&sockopt, sizeof(sockopt)) < 0)
freakout("WWW: Can't REUSEADDR");
addrin.sin_family = AF_INET;
addrin.sin_port = htons(webport);
if (webip == -1)
addrin.sin_addr.s_addr = INADDR_ANY;
else
addrin.sin_addr.s_addr = htonl(webip);
bzero(&(addrin.sin_zero), 8);
if (bind(sockin, (struct sockaddr *)&addrin,
sizeof(struct sockaddr)) < 0)
{
printf("WWW: The web port is %d, the IP is %s.\n",
webport, inet_ntoa(addrin.sin_addr));
if (webport < 1024)
freakout("WWW: Problem binding socket to port < 1024."
" Are you not root?");
else
freakout("WWW: Problem binding socket."
" Is the web port taken?");
}
if (listen(sockin, SCOREBOARD) < 0)
freakout("WWW: Problem listen()ing to socket");
printf("WWW: Thread is awake and awaiting connections.\n");
up_www = 1;
printf(_("WWW: You are using the English language version.\n"));
printf("WWW: Compiled without NLS\n");
init_linkbox();
if (!MSG_NOSIGNAL)
signal(SIGPIPE, broken_pipe);
while (!shutting_down) www_poll();
close(sockin);
for (i=0; i<SCOREBOARD; i++)
kill_connection(i);
printf("WWW: Thread down.\n");
up_www = 0;
pthread_exit(0);
}
_("")
_("Data off the wire:")
_("cycling once")