Bring back the --base functionality.
authorEmil Mikulic <emikulic@gmail.com>
Sat, 25 Jan 2014 10:04:25 +0000 (21:04 +1100)
committerEmil Mikulic <emikulic@gmail.com>
Sat, 25 Jan 2014 14:07:28 +0000 (01:07 +1100)
This is mostly a rollback of "Replace the --base code with relative paths."
except we keep the relative paths.

Requested by: Lonnie Abelbeck

darkstat.8.in
darkstat.c
http.c
http.h

index e786af3..6b3bdb0 100644 (file)
@@ -38,6 +38,8 @@ darkstat \- network statistics gatherer
 ] [
 .BI \-b " bindaddr"
 ] [
+.BI \-\-base " path"
+] [
 .BI \-f " filter"
 ] [
 .BI \-l " network/netmask"
@@ -169,6 +171,25 @@ Bind the web interface to the specified address.
 The default is to listen on all interfaces.
 .\"
 .TP
+.BI \-\-base " path"
+.RS
+Specify the path of the base URL.
+This can be useful if \fIdarkstat\fR is accessed via a reverse proxy.
+
+For example, if you use Apache's \fImod_proxy\fR and want to avoid a
+complicated setup with \fImod_proxy_html\fR (and \fImod_header\fR to unset
+the \fIAccept-Encoding\fR header), just set the base path to something like
+\fIstats\fR and use a config similar to the following snippet:
+
+.IP
+ ProxyPass /stats/ http://localhost:667/stats/
+ ProxyPassReverse /stats/ http://localhost:667/stats/
+.PP
+
+The default is \fI/\fR (i.e. the root).
+.RE
+.\"
+.TP
 .BI \-f " filter"
 Use the specified filter expression when capturing traffic.
 The filter syntax is beyond the scope of this manual page;
index a0e8f62..2cb5fbd 100644 (file)
@@ -127,6 +127,9 @@ static void cb_local_only(const char *arg _unused_)
 const char *opt_chroot_dir = NULL;
 static void cb_chroot(const char *arg) { opt_chroot_dir = arg; }
 
+const char *opt_base = NULL;
+static void cb_base(const char *arg) { opt_base = arg; }
+
 const char *opt_privdrop_user = NULL;
 static void cb_user(const char *arg) { opt_privdrop_user = arg; }
 
@@ -219,6 +222,7 @@ static struct cmdline_arg cmdline_args[] = {
    {"-p",             "port",            cb_port,         0},
    {"-b",             "bindaddr",        cb_bindaddr,    -1},
    {"-l",             "network/netmask", cb_local,        0},
+   {"--base",         "path",            cb_base,         0},
    {"--local-only",   NULL,              cb_local_only,   0},
    {"--snaplen",      "bytes",           cb_snaplen,      0},
    {"--pppoe",        NULL,              cb_pppoe,        0},
@@ -412,6 +416,7 @@ main(int argc, char **argv)
    /* do this first as it forks - minimize memory use */
    if (opt_want_dns) dns_init(opt_privdrop_user);
    cap_start(opt_want_promisc); /* needs root */
+   http_init_base(opt_base);
    http_listen(opt_bindport);
    ncache_init(); /* must do before chroot() */
 
diff --git a/http.c b/http.c
index 20e788c..831abd7 100644 (file)
--- a/http.c
+++ b/http.c
@@ -37,6 +37,8 @@
 #include <unistd.h>
 #include <zlib.h>
 
+static char *http_base_url = NULL;
+
 static const char mime_type_xml[] = "text/xml";
 static const char mime_type_html[] = "text/html; charset=us-ascii";
 static const char mime_type_css[] = "text/css";
@@ -636,6 +638,17 @@ static void process_get(struct connection *conn)
         return;
     }
 
+    /* make relative (or fail) */
+    decoded_url = safe_url;
+    if (!str_starts_with(decoded_url, http_base_url))
+    {
+        default_reply(conn, 404, "Not Found",
+            "The page you requested could not be found.");
+        free(decoded_url);
+        return;
+    }
+    safe_url = decoded_url + strlen(http_base_url) - 1;
+
     if (strcmp(safe_url, "/") == 0) {
         struct str *buf = html_front_page();
         str_extract(buf, &(conn->reply_length), &(conn->reply));
@@ -647,7 +660,7 @@ static void process_get(struct connection *conn)
         if (buf == NULL) {
             default_reply(conn, 404, "Not Found",
                 "The page you requested could not be found.");
-            free(safe_url);
+            free(decoded_url);
             return;
         }
         str_extract(buf, &(conn->reply_length), &(conn->reply));
@@ -667,10 +680,10 @@ static void process_get(struct connection *conn)
     else {
         default_reply(conn, 404, "Not Found",
             "The page you requested could not be found.");
-        free(safe_url);
+        free(decoded_url);
         return;
     }
-    free(safe_url);
+    free(decoded_url);
 
     process_gzip(conn);
     assert(conn->mime_type != NULL);
@@ -886,6 +899,40 @@ static void poll_send_reply(struct connection *conn)
     if (conn->reply_sent == conn->reply_length) conn->state = DONE;
 }
 
+
+
+/* --------------------------------------------------------------------------
+ * Initialize the base url.
+ */
+void http_init_base(const char *url) {
+    char *slashed_url, *safe_url;
+    size_t urllen;
+
+    if (url == NULL) {
+        http_base_url = strdup("/");
+        return;
+    }
+
+    /* Make sure that the url has leading and trailing slashes. */
+    urllen = strlen(url);
+    slashed_url = xmalloc(urllen+3);
+    slashed_url[0] = '/';
+    memcpy(slashed_url+1, url, urllen); /* don't copy NUL */
+    slashed_url[urllen+1] = '/';
+    slashed_url[urllen+2] = '\0';
+
+    /* Clean the url. */
+    safe_url = make_safe_uri(slashed_url);
+    free(slashed_url);
+    if (safe_url == NULL) {
+        verbosef("invalid base \"%s\", ignored", url);
+        http_base_url = strdup("/"); /* set to default */
+        return;
+    } else {
+        http_base_url = safe_url;
+    }
+}
+
 /* Use getaddrinfo to figure out what type of socket to create and
  * what to bind it to.  "bindaddr" can be NULL.  Remember to freeaddrinfo()
  * the result.
@@ -975,11 +1022,12 @@ static void http_listen_one(struct addrinfo *ai,
     if (listen(sockin, 128) == -1)
         err(1, "listen() failed");
 
-    verbosef("listening on http://%s%s%s:%u/",
+    verbosef("listening on http://%s%s%s:%u%s",
         (ai->ai_family == AF_INET6) ? "[" : "",
         ipaddr,
         (ai->ai_family == AF_INET6) ? "]" : "",
-        bindport);
+        bindport,
+        http_base_url);
 
     /* add to insocks */
     insocks = xrealloc(insocks, sizeof(*insocks) * (insock_num + 1));
@@ -1135,6 +1183,8 @@ void http_stop(void) {
     struct connection *conn;
     unsigned int i;
 
+    free(http_base_url);
+
     /* Close listening sockets. */
     for (i=0; i<insock_num; i++)
         close(insocks[i]);
diff --git a/http.h b/http.h
index 567d048..6820cde 100644 (file)
--- a/http.h
+++ b/http.h
@@ -8,6 +8,7 @@
 #include <sys/select.h>
 #include <netinet/in.h>
 
+void http_init_base(const char *url);
 void http_add_bindaddr(const char *bindaddr);
 void http_listen(const unsigned short bindport);
 void http_fd_set(fd_set *recv_set, fd_set *send_set, int *max_fd,