local path = luci.dispatcher.context.requestpath
local iface = path[#path]
- local fs = require "luci.fs"
- if fs.access("/var/lib/luci-bwc/if/%s" % iface) then
- luci.http.prepare_content("application/json")
-
- local bwc = io.popen("luci-bwc -i %q 2>/dev/null" % iface)
- if bwc then
- luci.http.write("[")
-
- while true do
- local ln = bwc:read("*l")
- if not ln then break end
- luci.http.write(ln)
- end
-
- luci.http.write("]")
- bwc:close()
+ luci.http.prepare_content("application/json")
+
+ local bwc = io.popen("luci-bwc -i %q 2>/dev/null" % iface)
+ if bwc then
+ luci.http.write("[")
+
+ while true do
+ local ln = bwc:read("*l")
+ if not ln then break end
+ luci.http.write(ln)
end
- return
+ luci.http.write("]")
+ bwc:close()
end
-
- luci.http.status(404, "No data available")
end
function action_load()
- local fs = require "luci.fs"
- if fs.access("/var/lib/luci-bwc/load") then
- luci.http.prepare_content("application/json")
-
- local bwc = io.popen("luci-bwc -l 2>/dev/null")
- if bwc then
- luci.http.write("[")
-
- while true do
- local ln = bwc:read("*l")
- if not ln then break end
- luci.http.write(ln)
- end
-
- luci.http.write("]")
- bwc:close()
+ luci.http.prepare_content("application/json")
+
+ local bwc = io.popen("luci-bwc -l 2>/dev/null")
+ if bwc then
+ luci.http.write("[")
+
+ while true do
+ local ln = bwc:read("*l")
+ if not ln then break end
+ luci.http.write(ln)
end
- return
+ luci.http.write("]")
+ bwc:close()
end
-
- luci.http.status(404, "No data available")
end
function action_connections()
- local fs = require "luci.fs"
local sys = require "luci.sys"
luci.http.prepare_content("application/json")
luci.http.write("{ connections: ")
luci.http.write_json(sys.net.conntrack())
- if fs.access("/var/lib/luci-bwc/connections") then
- local bwc = io.popen("luci-bwc -c 2>/dev/null")
- if bwc then
- luci.http.write(", statistics: [")
+ local bwc = io.popen("luci-bwc -c 2>/dev/null")
+ if bwc then
+ luci.http.write(", statistics: [")
- while true do
- local ln = bwc:read("*l")
- if not ln then break end
- luci.http.write(ln)
- end
-
- luci.http.write("]")
- bwc:close()
+ while true do
+ local ln = bwc:read("*l")
+ if not ln then break end
+ luci.http.write(ln)
end
+
+ luci.http.write("]")
+ bwc:close()
end
luci.http.write(" }")
#include <time.h>
#include <errno.h>
#include <unistd.h>
+#include <signal.h>
#include <sys/stat.h>
#include <sys/mman.h>
#define STEP_COUNT 60
#define STEP_TIME 1
+#define TIMEOUT 10
+
+#define PID_PATH "/var/run/luci-bwc.pid"
#define DB_PATH "/var/lib/luci-bwc"
#define DB_IF_FILE DB_PATH "/if/%s"
#define ntohll htonll
+static int readpid(void)
+{
+ int fd;
+ int pid = -1;
+ char buf[9] = { 0 };
+
+ if ((fd = open(PID_PATH, O_RDONLY)) > -1)
+ {
+ if (read(fd, buf, sizeof(buf)))
+ {
+ buf[8] = 0;
+ pid = atoi(buf);
+ }
+
+ close(fd);
+ }
+
+ return pid;
+}
+
+static int writepid(void)
+{
+ int fd;
+ int wlen;
+ char buf[9] = { 0 };
+
+ if ((fd = open(PID_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0600)) > -1)
+ {
+ wlen = snprintf(buf, sizeof(buf), "%i", getpid());
+ write(fd, buf, wlen);
+ close(fd);
+
+ return 0;
+ }
+
+ return -1;
+}
+
+static int timeout = TIMEOUT;
+static int countdown = -1;
+
+static void reset_countdown(int sig)
+{
+ countdown = timeout;
+
+}
+
static int init_directory(char *path)
{
return -1;
}
+static inline uint64_t timeof(void *entry)
+{
+ return ((struct traffic_entry *)entry)->time;
+}
+
static int update_file(const char *path, void *entry, int esize)
{
int rv = -1;
if ((map != NULL) && (map != MAP_FAILED))
{
- memmove(map, map + esize, esize * (STEP_COUNT-1));
- memcpy(map + esize * (STEP_COUNT-1), entry, esize);
+ if (timeof(entry) > timeof(map + esize * (STEP_COUNT-1)))
+ {
+ memmove(map, map + esize, esize * (STEP_COUNT-1));
+ memcpy(map + esize * (STEP_COUNT-1), entry, esize);
+ }
munmap(map, esize * STEP_COUNT);
return update_file(path, &e, sizeof(struct load_entry));
}
-static int run_daemon(int nofork)
+static int run_daemon(char *progname)
{
FILE *info;
uint64_t rxb, txb, rxp, txp;
char line[1024];
char ifname[16];
+ struct sigaction sa;
+
struct stat s;
const char *ipc = stat("/proc/net/nf_conntrack", &s)
? "/proc/net/ip_conntrack" : "/proc/net/nf_conntrack";
- if (!nofork)
+ switch (fork())
{
- switch (fork())
- {
- case -1:
- perror("fork()");
- return -1;
+ case -1:
+ perror("fork()");
+ return -1;
- case 0:
- if (chdir("/") < 0)
- {
- perror("chdir()");
- exit(1);
- }
+ case 0:
+ if (chdir("/") < 0)
+ {
+ perror("chdir()");
+ exit(1);
+ }
- close(0);
- close(1);
- close(2);
- break;
+ close(0);
+ close(1);
+ close(2);
+ break;
- default:
- exit(0);
- }
+ default:
+ return 0;
}
+ /* setup USR1 signal handler to reset timer */
+ sa.sa_handler = reset_countdown;
+ sa.sa_flags = SA_RESTART;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGUSR1, &sa, NULL);
+
+ /* write pid */
+ if (writepid())
+ {
+ fprintf(stderr, "Failed to write pid file: %s\n", strerror(errno));
+ return 1;
+ }
/* go */
- while (1)
+ for (reset_countdown(0); countdown >= 0; countdown--)
{
+ /* alter progname for ps, top */
+ sprintf(progname, "luci-bwc %d", countdown);
+
if ((info = fopen("/proc/net/dev", "r")) != NULL)
{
while (fgets(line, sizeof(line), info))
sleep(STEP_TIME);
}
+
+ unlink(PID_PATH);
+
+ return 0;
+}
+
+static int check_daemon(char *progname)
+{
+ int pid;
+
+ if ((pid = readpid()) < 0 || kill(pid, 0) < 0)
+ {
+ /* daemon ping failed, try to start it up */
+ if (run_daemon(progname))
+ {
+ fprintf(stderr,
+ "Failed to ping daemon and unable to start it up: %s\n",
+ strerror(errno));
+
+ return 1;
+ }
+ }
+ else if (kill(pid, SIGUSR1))
+ {
+ fprintf(stderr, "Failed to send signal: %s\n", strerror(errno));
+ return 1;
+ }
+
+ return 0;
}
-static int run_dump_ifname(const char *ifname)
+static int run_dump_ifname(char *progname, const char *ifname)
{
int i;
char path[1024];
snprintf(path, sizeof(path), DB_IF_FILE, ifname);
+ if (check_daemon(progname))
+ {
+ return 1;
+ }
+
if (mmap_file(path, sizeof(struct traffic_entry), &m))
{
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
return 0;
}
-static int run_dump_conns(void)
+static int run_dump_conns(char *progname)
{
int i;
char path[1024];
snprintf(path, sizeof(path), DB_CN_FILE);
+ if (check_daemon(progname))
+ {
+ return 1;
+ }
+
if (mmap_file(path, sizeof(struct conn_entry), &m))
{
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
return 0;
}
-static int run_dump_load(void)
+static int run_dump_load(char *progname)
{
int i;
char path[1024];
snprintf(path, sizeof(path), DB_LD_FILE);
+ if (check_daemon(progname))
+ {
+ return 1;
+ }
+
if (mmap_file(path, sizeof(struct load_entry), &m))
{
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
int main(int argc, char *argv[])
{
int opt;
- int daemon = 0;
- int nofork = 0;
- while ((opt = getopt(argc, argv, "dfi:cl")) > -1)
+ while ((opt = getopt(argc, argv, "t:i:cl")) > -1)
{
switch (opt)
{
- case 'd':
- daemon = 1;
- break;
-
- case 'f':
- nofork = 1;
+ case 't':
+ timeout = atoi(optarg);
break;
case 'i':
if (optarg)
- return run_dump_ifname(optarg);
+ return run_dump_ifname(argv[0], optarg);
break;
case 'c':
- return run_dump_conns();
+ return run_dump_conns(argv[0]);
case 'l':
- return run_dump_load();
+ return run_dump_load(argv[0]);
default:
break;
}
}
- if (daemon)
- return run_daemon(nofork);
-
- else
- fprintf(stderr,
- "Usage:\n"
- " %s -d [-f]\n"
- " %s -i ifname\n"
- " %s -c\n"
- " %s -l\n",
- argv[0], argv[0], argv[0], argv[0]
- );
+ fprintf(stderr,
+ "Usage:\n"
+ " %s [-t timeout] -i ifname\n"
+ " %s [-t timeout] -c\n"
+ " %s [-t timeout] -l\n",
+ argv[0], argv[0], argv[0]
+ );
return 1;
}