Remove unmaintained components: lucid, fastindex, niu
This commit is contained in:
parent
2d05a6135a
commit
91b97bc9f6
79 changed files with 0 additions and 6799 deletions
|
@ -158,13 +158,9 @@ ifneq ($(CONFIG_PACKAGE_luci-lib-nixio_cyassl),)
|
|||
endif
|
||||
|
||||
|
||||
$(eval $(call library,fastindex,Fastindex indexing module,+PACKAGE_luci-lib-fastindex:liblua))
|
||||
$(eval $(call library,httpclient,HTTP(S) client library,+luci-lib-web +luci-lib-nixio))
|
||||
$(eval $(call library,ipkg,LuCI IPKG/OPKG call abstraction library))
|
||||
$(eval $(call library,json,LuCI JSON library))
|
||||
$(eval $(call library,lucid,LuCId Full-Stack Webserver,+luci-lib-nixio +luci-lib-web +luci-lib-px5g))
|
||||
$(eval $(call library,lucid-http,LuCId HTTP Backend,+luci-lib-lucid))
|
||||
$(eval $(call library,lucid-rpc,LuCId RPC Backend,+luci-lib-lucid))
|
||||
$(eval $(call library,nixio,NIXIO POSIX library,+PACKAGE_luci-lib-nixio_openssl:libopenssl +PACKAGE_luci-lib-nixio_cyassl:libcyassl))
|
||||
$(eval $(call library,px5g,RSA/X.509 Key Generator (required for LuCId SSL support),+luci-lib-nixio))
|
||||
$(eval $(call library,sys,LuCI Linux/POSIX system library))
|
||||
|
@ -238,7 +234,6 @@ $(eval $(call module,admin-mini,LuCI Essentials - stripped down and user-friendl
|
|||
$(eval $(call module,admin-full,LuCI Administration - full-featured for full control,+luci-mod-admin-core +luci-lib-ipkg))
|
||||
$(eval $(call module,failsafe,LuCI Fail-Safe - Fail-Safe sysupgrade module,+luci-mod-admin-core))
|
||||
$(eval $(call module,rpc,LuCI RPC - JSON-RPC API,+luci-lib-json))
|
||||
$(eval $(call module,niu,NIU - Next Generation Interface,+luci-mod-admin-core @BROKEN))
|
||||
|
||||
|
||||
### Applications ###
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
include ../../build/module.mk
|
||||
include ../../build/config.mk
|
||||
include ../../build/gccconfig.mk
|
||||
|
||||
%.o: %.c
|
||||
$(COMPILE) $(LUA_CFLAGS) $(FPIC) -c -o $@ $<
|
||||
|
||||
compile: src/fastindex.o
|
||||
mkdir -p dist$(LUCI_LIBRARYDIR)
|
||||
$(LINK) $(SHLIB_FLAGS) -o dist$(LUCI_LIBRARYDIR)/fastindex.so src/fastindex.o $(LUA_SHLIBS)
|
||||
|
||||
clean:
|
||||
rm -f src/*.o
|
|
@ -1,379 +0,0 @@
|
|||
/*
|
||||
* fastindex - fast lua module indexing plugin
|
||||
* Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE /* XXX: portability hack for timestamp */
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <glob.h>
|
||||
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
#include "list.h"
|
||||
|
||||
#define MODNAME "luci.fastindex"
|
||||
#define DEFAULT_BUFLEN 1024
|
||||
|
||||
//#define DEBUG 1
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DPRINTF(...) fprintf(stderr, __VA_ARGS__)
|
||||
#else
|
||||
#define DPRINTF(...) do {} while (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* list_for_each_offset - iterate over a list, start with the provided pointer
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_offset(pos, head, offset) \
|
||||
for (pos = (offset)->next; pos != (offset); \
|
||||
pos = ((pos->next == (head)) && ((offset) != (head)) ? (head)->next : pos->next))
|
||||
|
||||
static char *namespace = NULL;
|
||||
|
||||
struct fastindex_entry {
|
||||
struct list_head list;
|
||||
time_t timestamp;
|
||||
int checked;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct fastindex_pattern {
|
||||
struct list_head list;
|
||||
char pattern[];
|
||||
};
|
||||
|
||||
struct fastindex {
|
||||
lua_State *L;
|
||||
int checked;
|
||||
char *func;
|
||||
struct list_head patterns;
|
||||
struct list_head *last;
|
||||
struct list_head entries;
|
||||
int ofs;
|
||||
char *buf;
|
||||
int buflen;
|
||||
};
|
||||
|
||||
static inline struct fastindex *
|
||||
to_fastindex(struct lua_State *L)
|
||||
{
|
||||
struct fastindex *f;
|
||||
lua_getfield(L, lua_upvalueindex(1), "__data");
|
||||
f = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return f;
|
||||
}
|
||||
|
||||
static int
|
||||
fastindex_module(lua_State *L)
|
||||
{
|
||||
const char *s;
|
||||
s = luaL_checkstring(L, 1);
|
||||
|
||||
if (s) {
|
||||
if (namespace)
|
||||
free(namespace);
|
||||
namespace = strdup(s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fastindex_entry *
|
||||
find_entry(struct fastindex *f, char *name)
|
||||
{
|
||||
struct list_head *p;
|
||||
|
||||
if (!f->last)
|
||||
f->last = &f->entries;
|
||||
|
||||
list_for_each_offset(p, &f->entries, f->last) {
|
||||
struct fastindex_entry *e;
|
||||
e = container_of(p, struct fastindex_entry, list);
|
||||
if (!strcmp(e->name, name))
|
||||
return e;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct fastindex_entry *
|
||||
new_entry(struct fastindex *f, char *name)
|
||||
{
|
||||
struct fastindex_entry *e;
|
||||
|
||||
e = malloc(sizeof(struct fastindex_entry));
|
||||
if (!e)
|
||||
goto error;
|
||||
|
||||
memset(e, 0, sizeof(struct fastindex_entry));
|
||||
e->name = strdup(name);
|
||||
if (!e->name) {
|
||||
free(e);
|
||||
goto error;
|
||||
}
|
||||
INIT_LIST_HEAD(&e->list);
|
||||
|
||||
return e;
|
||||
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void free_entry(struct fastindex_entry *e)
|
||||
{
|
||||
list_del(&e->list);
|
||||
free(e->name);
|
||||
free(e);
|
||||
}
|
||||
|
||||
int bufferwriter(lua_State *L, const void *p, size_t sz, void *ud)
|
||||
{
|
||||
struct fastindex *f = ud;
|
||||
|
||||
while (f->ofs + sz > f->buflen) {
|
||||
char *b = f->buf;
|
||||
f->buflen *= 2;
|
||||
f->buf = realloc(f->buf, f->buflen);
|
||||
if (!f->buf) {
|
||||
free(b);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
memcpy(f->buf + f->ofs, p, sz);
|
||||
f->ofs += sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
load_index(struct fastindex *f, struct fastindex_entry *e)
|
||||
{
|
||||
lua_State *L;
|
||||
|
||||
DPRINTF("Loading module: %s\n", e->name);
|
||||
|
||||
if (!f->buf)
|
||||
f->buf = malloc(f->buflen);
|
||||
|
||||
if (!f->buf)
|
||||
luaL_error(f->L, "Out of memory!\n");
|
||||
|
||||
f->ofs = 0;
|
||||
L = luaL_newstate();
|
||||
if (!L)
|
||||
return;
|
||||
|
||||
namespace = NULL;
|
||||
luaL_openlibs(L);
|
||||
lua_pushcfunction(L, fastindex_module);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "module");
|
||||
|
||||
do {
|
||||
if (luaL_dofile(L, e->name)) {
|
||||
DPRINTF("Warning: unable to open module '%s'\n", e->name);
|
||||
break;
|
||||
}
|
||||
|
||||
lua_getglobal(L, f->func);
|
||||
lua_dump(L, bufferwriter, f);
|
||||
DPRINTF("Got %d bytes\n", f->ofs);
|
||||
if (f->ofs == 0)
|
||||
break;
|
||||
lua_createtable(f->L, (namespace ? 2 : 1), 0);
|
||||
luaL_loadbuffer(f->L, f->buf, f->ofs, "tmp");
|
||||
lua_rawseti(f->L, -2, 1);
|
||||
if (namespace) {
|
||||
DPRINTF("Module has namespace '%s'\n", namespace);
|
||||
lua_pushstring(f->L, namespace);
|
||||
lua_rawseti(f->L, -2, 2);
|
||||
free(namespace);
|
||||
namespace = NULL;
|
||||
}
|
||||
lua_setfield(f->L, -2, e->name);
|
||||
} while (0);
|
||||
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fastindex_scan(lua_State *L)
|
||||
{
|
||||
struct list_head *tmp, *p;
|
||||
struct fastindex *f;
|
||||
glob_t gl;
|
||||
int i;
|
||||
int gl_flags = GLOB_NOESCAPE | GLOB_NOSORT | GLOB_MARK;
|
||||
|
||||
f = to_fastindex(L);
|
||||
f->checked++;
|
||||
|
||||
|
||||
if (list_empty(&f->patterns))
|
||||
return 0;
|
||||
|
||||
lua_getfield(L, lua_upvalueindex(1), "indexes");
|
||||
list_for_each(p, &f->patterns) {
|
||||
struct fastindex_pattern *pt = container_of(p, struct fastindex_pattern, list);
|
||||
glob(pt->pattern, gl_flags, NULL, &gl);
|
||||
gl_flags |= GLOB_APPEND;
|
||||
}
|
||||
for (i = 0; i < gl.gl_pathc; i++) {
|
||||
struct fastindex_entry *e;
|
||||
struct stat st;
|
||||
|
||||
if (stat(gl.gl_pathv[i], &st))
|
||||
continue;
|
||||
|
||||
if ((st.st_mode & S_IFMT) != S_IFREG)
|
||||
continue;
|
||||
|
||||
e = find_entry(f, gl.gl_pathv[i]);
|
||||
if (!e) {
|
||||
e = new_entry(f, gl.gl_pathv[i]);
|
||||
list_add_tail(&e->list, &f->entries);
|
||||
}
|
||||
|
||||
e->checked = f->checked;
|
||||
if ((e->timestamp < st.st_mtime)) {
|
||||
load_index(f, e);
|
||||
e->timestamp = st.st_mtime;
|
||||
}
|
||||
}
|
||||
globfree(&gl);
|
||||
list_for_each_safe(p, tmp, &f->entries) {
|
||||
struct fastindex_entry *e = container_of(p, struct fastindex_entry, list);
|
||||
if (e->checked < f->checked) {
|
||||
lua_pushnil(f->L);
|
||||
lua_setfield(f->L, -2, e->name);
|
||||
free_entry(e);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fastindex_free(lua_State *L)
|
||||
{
|
||||
struct fastindex *f;
|
||||
struct list_head *p, *tmp;
|
||||
|
||||
f = lua_touserdata(L, -1);
|
||||
list_for_each_safe(p, tmp, &f->patterns) {
|
||||
struct fastindex_pattern *pt;
|
||||
pt = container_of(p, struct fastindex_pattern, list);
|
||||
list_del(p);
|
||||
free(pt);
|
||||
}
|
||||
list_for_each_safe(p, tmp, &f->entries) {
|
||||
struct fastindex_entry *e;
|
||||
e = container_of(p, struct fastindex_entry, list);
|
||||
free_entry(e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fastindex_add(lua_State *L)
|
||||
{
|
||||
struct fastindex_pattern *pt;
|
||||
struct fastindex *f;
|
||||
const char *str;
|
||||
|
||||
f = to_fastindex(L);
|
||||
str = luaL_checkstring(L, 1);
|
||||
if (!str)
|
||||
luaL_error(L, "Invalid argument");
|
||||
|
||||
pt = malloc(sizeof(struct fastindex_pattern) + strlen(str) + 1);
|
||||
if (!pt)
|
||||
luaL_error(L, "Out of memory");
|
||||
|
||||
INIT_LIST_HEAD(&pt->list);
|
||||
strcpy(pt->pattern, str);
|
||||
list_add(&pt->list, &f->patterns);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg fastindex_m[] = {
|
||||
{ "add", fastindex_add },
|
||||
{ "scan", fastindex_scan },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static int
|
||||
fastindex_new(lua_State *L)
|
||||
{
|
||||
struct fastindex *f;
|
||||
const char *func;
|
||||
|
||||
func = luaL_checkstring(L, 1);
|
||||
|
||||
f = lua_newuserdata(L, sizeof(struct fastindex));
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, fastindex_free);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setmetatable(L, -3);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_setfield(L, -2, "__data");
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_setfield(L, -2, "indexes");
|
||||
lua_pushvalue(L, -2);
|
||||
luaI_openlib(L, NULL, fastindex_m, 1);
|
||||
|
||||
memset(f, 0, sizeof(struct fastindex));
|
||||
f->L = L;
|
||||
f->buflen = DEFAULT_BUFLEN;
|
||||
INIT_LIST_HEAD(&f->entries);
|
||||
INIT_LIST_HEAD(&f->patterns);
|
||||
|
||||
f->func = strdup(func);
|
||||
if (!f->func) {
|
||||
if (f->func)
|
||||
free(f->func);
|
||||
luaL_error(L, "Out of memory\n");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg fastindex[] = {
|
||||
{ "new", fastindex_new },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
int
|
||||
luaopen_luci_fastindex(lua_State *L)
|
||||
{
|
||||
luaL_register(L, MODNAME, fastindex);
|
||||
return 0;
|
||||
}
|
|
@ -1,601 +0,0 @@
|
|||
#ifndef _LINUX_LIST_H
|
||||
#define _LINUX_LIST_H
|
||||
|
||||
#include <stddef.h>
|
||||
/**
|
||||
* container_of - cast a member of a structure out to the containing structure
|
||||
* @ptr: the pointer to the member.
|
||||
* @type: the type of the container struct this is embedded in.
|
||||
* @member: the name of the member within the struct.
|
||||
*
|
||||
*/
|
||||
#ifndef container_of
|
||||
#define container_of(ptr, type, member) ( \
|
||||
(type *)( (char *)ptr - offsetof(type,member) ))
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
static inline void INIT_LIST_HEAD(struct list_head *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head * prev, struct list_head * next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty() on entry does not return true after this, the entry is
|
||||
* in an undefined state.
|
||||
*/
|
||||
static inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->next = NULL;
|
||||
entry->prev = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_replace - replace old entry by new one
|
||||
* @old : the element to be replaced
|
||||
* @new : the new element to insert
|
||||
*
|
||||
* If @old was empty, it will be overwritten.
|
||||
*/
|
||||
static inline void list_replace(struct list_head *old,
|
||||
struct list_head *new)
|
||||
{
|
||||
new->next = old->next;
|
||||
new->next->prev = new;
|
||||
new->prev = old->prev;
|
||||
new->prev->next = new;
|
||||
}
|
||||
|
||||
static inline void list_replace_init(struct list_head *old,
|
||||
struct list_head *new)
|
||||
{
|
||||
list_replace(old, new);
|
||||
INIT_LIST_HEAD(old);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static inline void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move - delete from one list and add as another's head
|
||||
* @list: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move_tail - delete from one list and add as another's tail
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add_tail(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_is_last - tests whether @list is the last entry in list @head
|
||||
* @list: the entry to test
|
||||
* @head: the head of the list
|
||||
*/
|
||||
static inline int list_is_last(const struct list_head *list,
|
||||
const struct list_head *head)
|
||||
{
|
||||
return list->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty(const struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty_careful - tests whether a list is empty and not being modified
|
||||
* @head: the list to test
|
||||
*
|
||||
* Description:
|
||||
* tests whether a list is empty _and_ checks that no other CPU might be
|
||||
* in the process of modifying either member (next or prev)
|
||||
*
|
||||
* NOTE: using list_empty_careful() without synchronization
|
||||
* can only be safe if the only activity that can happen
|
||||
* to the list entry is list_del_init(). Eg. it cannot be used
|
||||
* if another CPU could re-list_add() it.
|
||||
*/
|
||||
static inline int list_empty_careful(const struct list_head *head)
|
||||
{
|
||||
struct list_head *next = head->next;
|
||||
return (next == head) && (next == head->prev);
|
||||
}
|
||||
|
||||
static inline void __list_splice(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static inline void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*
|
||||
* The list at @list is reinitialised
|
||||
*/
|
||||
static inline void list_splice_init(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list)) {
|
||||
__list_splice(list, head);
|
||||
INIT_LIST_HEAD(list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
container_of(ptr, type, member)
|
||||
|
||||
/**
|
||||
* list_first_entry - get the first element from a list
|
||||
* @ptr: the list head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Note, that list is expected to be not empty.
|
||||
*/
|
||||
#define list_first_entry(ptr, type, member) \
|
||||
list_entry((ptr)->next, type, member)
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); \
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* __list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*
|
||||
* This variant differs from list_for_each() in that it's the
|
||||
* simplest possible list iteration code, no prefetching is done.
|
||||
* Use this for code that knows the list to be very short (empty
|
||||
* or 1 entry) most of the time.
|
||||
*/
|
||||
#define __list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev - iterate over a list backwards
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); \
|
||||
pos = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev_safe(pos, n, head) \
|
||||
for (pos = (head)->prev, n = pos->prev; \
|
||||
pos != (head); \
|
||||
pos = n, n = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_reverse - iterate backwards over list of given type.
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_reverse(pos, head, member) \
|
||||
for (pos = list_entry((head)->prev, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.prev, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
|
||||
* @pos: the type * to use as a start point
|
||||
* @head: the head of the list
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
|
||||
*/
|
||||
#define list_prepare_entry(pos, head, member) \
|
||||
((pos) ? : list_entry(head, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue - continue iteration over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Continue to iterate over list of given type, continuing after
|
||||
* the current position.
|
||||
*/
|
||||
#define list_for_each_entry_continue(pos, head, member) \
|
||||
for (pos = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue_reverse - iterate backwards from the given point
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Start to iterate over list of given type backwards, continuing after
|
||||
* the current position.
|
||||
*/
|
||||
#define list_for_each_entry_continue_reverse(pos, head, member) \
|
||||
for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.prev, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_from - iterate over list of given type from the current point
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate over list of given type, continuing from current position.
|
||||
*/
|
||||
#define list_for_each_entry_from(pos, head, member) \
|
||||
for (; &pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_continue
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate over list of given type, continuing after current point,
|
||||
* safe against removal of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_continue(pos, n, head, member) \
|
||||
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_from
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate over list of given type from current point, safe against
|
||||
* removal of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_from(pos, n, head, member) \
|
||||
for (n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_reverse
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate backwards over list of given type, safe against removal
|
||||
* of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->prev, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.prev, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
|
||||
|
||||
/*
|
||||
* Double linked lists with a single pointer list head.
|
||||
* Mostly useful for hash tables where the two pointer list head is
|
||||
* too wasteful.
|
||||
* You lose the ability to access the tail in O(1).
|
||||
*/
|
||||
|
||||
struct hlist_head {
|
||||
struct hlist_node *first;
|
||||
};
|
||||
|
||||
struct hlist_node {
|
||||
struct hlist_node *next, **pprev;
|
||||
};
|
||||
|
||||
#define HLIST_HEAD_INIT { .first = NULL }
|
||||
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
|
||||
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
|
||||
static inline void INIT_HLIST_NODE(struct hlist_node *h)
|
||||
{
|
||||
h->next = NULL;
|
||||
h->pprev = NULL;
|
||||
}
|
||||
|
||||
static inline int hlist_unhashed(const struct hlist_node *h)
|
||||
{
|
||||
return !h->pprev;
|
||||
}
|
||||
|
||||
static inline int hlist_empty(const struct hlist_head *h)
|
||||
{
|
||||
return !h->first;
|
||||
}
|
||||
|
||||
static inline void __hlist_del(struct hlist_node *n)
|
||||
{
|
||||
struct hlist_node *next = n->next;
|
||||
struct hlist_node **pprev = n->pprev;
|
||||
*pprev = next;
|
||||
if (next)
|
||||
next->pprev = pprev;
|
||||
}
|
||||
|
||||
static inline void hlist_del(struct hlist_node *n)
|
||||
{
|
||||
__hlist_del(n);
|
||||
n->next = NULL;
|
||||
n->pprev = NULL;
|
||||
}
|
||||
|
||||
static inline void hlist_del_init(struct hlist_node *n)
|
||||
{
|
||||
if (!hlist_unhashed(n)) {
|
||||
__hlist_del(n);
|
||||
INIT_HLIST_NODE(n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
|
||||
{
|
||||
struct hlist_node *first = h->first;
|
||||
n->next = first;
|
||||
if (first)
|
||||
first->pprev = &n->next;
|
||||
h->first = n;
|
||||
n->pprev = &h->first;
|
||||
}
|
||||
|
||||
|
||||
/* next must be != NULL */
|
||||
static inline void hlist_add_before(struct hlist_node *n,
|
||||
struct hlist_node *next)
|
||||
{
|
||||
n->pprev = next->pprev;
|
||||
n->next = next;
|
||||
next->pprev = &n->next;
|
||||
*(n->pprev) = n;
|
||||
}
|
||||
|
||||
static inline void hlist_add_after(struct hlist_node *n,
|
||||
struct hlist_node *next)
|
||||
{
|
||||
next->next = n->next;
|
||||
n->next = next;
|
||||
next->pprev = &n->next;
|
||||
|
||||
if(next->next)
|
||||
next->next->pprev = &next->next;
|
||||
}
|
||||
|
||||
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
|
||||
|
||||
#define hlist_for_each(pos, head) \
|
||||
for (pos = (head)->first; pos; pos = pos->next)
|
||||
|
||||
#define hlist_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->first; pos; pos = n)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry - iterate over list of given type
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry(tpos, pos, head, member) \
|
||||
for (pos = (head)->first; pos && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry_continue(tpos, pos, member) \
|
||||
for (pos = (pos)->next; pos && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry_from(tpos, pos, member) \
|
||||
for (; pos && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||
* @n: another &struct hlist_node to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
|
||||
for (pos = (head)->first; \
|
||||
pos && ({ n = pos->next; 1; }) && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = n)
|
||||
|
||||
#endif
|
|
@ -1,2 +0,0 @@
|
|||
include ../../build/module.mk
|
||||
include ../../build/config.mk
|
|
@ -1,17 +0,0 @@
|
|||
LuCId HTTP/1.1 Server Slave
|
||||
|
||||
*** Abstract ***
|
||||
The LuCId HTTP-Server Slave is an HTTP/1.1 implementation for the LuCId
|
||||
superserver loosely based on the LuCI HTTP stack. It supports keep-alive,
|
||||
pipelining, basic authentication, kernel-mode file transfer (sendfile()
|
||||
through nixio), address and hostname based virtual hosts, custom 404 pages,
|
||||
E-Tags, conditional headers, directory indexing and partial file transfers.
|
||||
|
||||
|
||||
*** Workflow ***
|
||||
After receiving an incoming connection from LuCId, the slave parses the request
|
||||
and prepares the environment for the acion handler. After that the virtual host
|
||||
will be dispatched and the request will be passed on to the respective handler.
|
||||
The handler will enforce access restrictions if configured and then returns a
|
||||
status code a set of response headers, as well as a content resource that will
|
||||
be sent to the user.
|
|
@ -1,36 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local require, ipairs, pcall = require, ipairs, pcall
|
||||
local srv = require "luci.lucid.http.server"
|
||||
|
||||
module "luci.lucid.http"
|
||||
|
||||
--- Prepare the HTTP-daemon and its associated publishers.
|
||||
-- @param publisher Table of publishers
|
||||
-- @return factory callback or nil, error message
|
||||
function factory(publisher)
|
||||
local server = srv.Server()
|
||||
for _, r in ipairs(publisher) do
|
||||
local t = r[".type"]
|
||||
local s, mod = pcall(require, "luci.lucid.http." .. (r[".type"] or ""))
|
||||
if s and mod then
|
||||
mod.factory(server, r)
|
||||
else
|
||||
return nil, mod
|
||||
end
|
||||
end
|
||||
|
||||
return function(...) return server:process(...) end
|
||||
end
|
|
@ -1,50 +0,0 @@
|
|||
--[[
|
||||
LuCId HTTP-Slave
|
||||
(c) 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local ipairs, require, tostring, type = ipairs, require, tostring, type
|
||||
local file = require "luci.lucid.http.handler.file"
|
||||
local srv = require "luci.lucid.http.server"
|
||||
|
||||
module "luci.lucid.http.DirectoryPublisher"
|
||||
|
||||
|
||||
--- Prepare a directory publisher and assign it to a given Virtual Host.
|
||||
-- @param server HTTP daemon object
|
||||
-- @param config publisher configuration
|
||||
function factory(server, config)
|
||||
config.domain = config.domain or ""
|
||||
local vhost = server:get_vhosts()[config.domain]
|
||||
if not vhost then
|
||||
vhost = srv.VHost()
|
||||
server:set_vhost(config.domain, vhost)
|
||||
end
|
||||
|
||||
local handler = file.Simple(config.name, config.physical, config)
|
||||
if config.read then
|
||||
for _, r in ipairs(config.read) do
|
||||
if r:sub(1,1) == ":" then
|
||||
handler:restrict({interface = r:sub(2)})
|
||||
else
|
||||
handler:restrict({user = r})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if type(config.virtual) == "table" then
|
||||
for _, v in ipairs(config.virtual) do
|
||||
vhost:set_handler(v, handler)
|
||||
end
|
||||
else
|
||||
vhost:set_handler(config.virtual or "", handler)
|
||||
end
|
||||
end
|
|
@ -1,73 +0,0 @@
|
|||
--[[
|
||||
LuCId HTTP-Slave
|
||||
(c) 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local ipairs, pcall, type = ipairs, pcall, type
|
||||
local luci = require "luci.lucid.http.handler.luci"
|
||||
local srv = require "luci.lucid.http.server"
|
||||
|
||||
|
||||
module "luci.lucid.http.LuciWebPublisher"
|
||||
|
||||
|
||||
--- Prepare a LuCI web publisher and assign it to a given Virtual Host.
|
||||
-- @param server HTTP daemon object
|
||||
-- @param config publisher configuration
|
||||
function factory(server, config)
|
||||
pcall(function()
|
||||
require "luci.dispatcher"
|
||||
require "luci.cbi"
|
||||
end)
|
||||
|
||||
config.domain = config.domain or ""
|
||||
local vhost = server:get_vhosts()[config.domain]
|
||||
if not vhost then
|
||||
vhost = srv.VHost()
|
||||
server:set_vhost(config.domain, vhost)
|
||||
end
|
||||
|
||||
local prefix
|
||||
if config.physical and #config.physical > 0 then
|
||||
prefix = {}
|
||||
for k in config.physical:gmatch("[^/]+") do
|
||||
if #k > 0 then
|
||||
prefix[#prefix+1] = k
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local handler = luci.Luci(config.name, prefix)
|
||||
if config.exec then
|
||||
for _, r in ipairs(config.exec) do
|
||||
if r:sub(1,1) == ":" then
|
||||
handler:restrict({interface = r:sub(2)})
|
||||
else
|
||||
handler:restrict({user = r})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local mypath
|
||||
if type(config.virtual) == "table" then
|
||||
for _, v in ipairs(config.virtual) do
|
||||
mypath = mypath or v
|
||||
vhost:set_handler(v, handler)
|
||||
end
|
||||
else
|
||||
mypath = config.virtual
|
||||
vhost:set_handler(config.virtual or "", handler)
|
||||
end
|
||||
|
||||
if config.home then
|
||||
vhost.default = mypath
|
||||
end
|
||||
end
|
|
@ -1,33 +0,0 @@
|
|||
--[[
|
||||
LuCId HTTP-Slave
|
||||
(c) 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local ipairs = ipairs
|
||||
local catchall = require "luci.lucid.http.handler.catchall"
|
||||
local srv = require "luci.lucid.http.server"
|
||||
|
||||
module "luci.lucid.http.Redirector"
|
||||
|
||||
--- Prepare a redirector publisher and assign it to a given Virtual Host.
|
||||
-- @param server HTTP daemon object
|
||||
-- @param config publisher configuration
|
||||
function factory(server, config)
|
||||
config.domain = config.domain or ""
|
||||
local vhost = server:get_vhosts()[config.domain]
|
||||
if not vhost then
|
||||
vhost = srv.VHost()
|
||||
server:set_vhost(config.domain, vhost)
|
||||
end
|
||||
|
||||
local handler = catchall.Redirect(config.name, config.physical)
|
||||
vhost:set_handler(config.virtual or "", handler)
|
||||
end
|
|
@ -1,87 +0,0 @@
|
|||
--[[
|
||||
LuCId HTTP-Slave
|
||||
(c) 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local srv = require "luci.lucid.http.server"
|
||||
local proto = require "luci.http.protocol"
|
||||
local util = require "luci.util"
|
||||
local ip = require "luci.ip"
|
||||
local ipairs = ipairs
|
||||
|
||||
--- Catchall Handler
|
||||
-- @cstyle instance
|
||||
module "luci.lucid.http.handler.catchall"
|
||||
|
||||
--- Create a Redirect handler.
|
||||
-- @param name Name
|
||||
-- @param target Redirect Target
|
||||
-- @class function
|
||||
-- @return Redirect handler object
|
||||
Redirect = util.class(srv.Handler)
|
||||
|
||||
function Redirect.__init__(self, name, target)
|
||||
srv.Handler.__init__(self, name)
|
||||
self.target = target
|
||||
end
|
||||
|
||||
--- Handle a GET request.
|
||||
-- @param request Request object
|
||||
-- @return status code, header table, response source
|
||||
function Redirect.handle_GET(self, request)
|
||||
local target = self.target
|
||||
local protocol = request.env.HTTPS and "https://" or "http://"
|
||||
local server = request.env.SERVER_ADDR
|
||||
|
||||
if request.env.REMOTE_ADDR and not request.env.REMOTE_ADDR:find(":") then
|
||||
local compare = ip.IPv4(request.env.REMOTE_ADDR)
|
||||
for _, iface in ipairs(request.server.interfaces) do
|
||||
if iface.family == "inet" and iface.addr and iface.netmask then
|
||||
if ip.IPv4(iface.addr, iface.netmask):contains(compare) then
|
||||
server = iface.addr
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if server:find(":") then
|
||||
server = "[" .. server .. "]"
|
||||
end
|
||||
|
||||
if self.target:sub(1,1) == ":" then
|
||||
target = protocol .. server .. target
|
||||
end
|
||||
|
||||
local s, e = target:find("%TARGET%", 1, true)
|
||||
if s then
|
||||
local req = protocol .. (request.env.HTTP_HOST or server)
|
||||
.. request.env.REQUEST_URI
|
||||
target = target:sub(1, s-1) .. req .. target:sub(e+1)
|
||||
end
|
||||
|
||||
return 302, { Location = target }
|
||||
end
|
||||
|
||||
--- Handle a POST request.
|
||||
-- @class function
|
||||
-- @param request Request object
|
||||
-- @return status code, header table, response source
|
||||
Redirect.handle_POST = Redirect.handle_GET
|
||||
|
||||
--- Handle a HEAD request.
|
||||
-- @class function
|
||||
-- @param request Request object
|
||||
-- @return status code, header table, response source
|
||||
function Redirect.handle_HEAD(self, request)
|
||||
local stat, head = self:handle_GET(request)
|
||||
return stat, head
|
||||
end
|
|
@ -1,272 +0,0 @@
|
|||
--[[
|
||||
|
||||
HTTP server implementation for LuCI - file handler
|
||||
(c) 2008 Steven Barth <steven@midlink.org>
|
||||
(c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
]]--
|
||||
|
||||
local ipairs, type, tonumber = ipairs, type, tonumber
|
||||
local os = require "os"
|
||||
local nixio = require "nixio", require "nixio.util"
|
||||
local fs = require "nixio.fs"
|
||||
local util = require "luci.util"
|
||||
local ltn12 = require "luci.ltn12"
|
||||
local srv = require "luci.lucid.http.server"
|
||||
local string = require "string"
|
||||
|
||||
local prot = require "luci.http.protocol"
|
||||
local date = require "luci.http.protocol.date"
|
||||
local mime = require "luci.http.protocol.mime"
|
||||
local cond = require "luci.http.protocol.conditionals"
|
||||
|
||||
--- File system handler
|
||||
-- @cstyle instance
|
||||
module "luci.lucid.http.handler.file"
|
||||
|
||||
--- Create a simple file system handler.
|
||||
-- @class function
|
||||
-- @param name Name
|
||||
-- @param docroot Physical Document Root
|
||||
-- @param options Options
|
||||
-- @return Simple file system handler object
|
||||
Simple = util.class(srv.Handler)
|
||||
|
||||
function Simple.__init__(self, name, docroot, options)
|
||||
srv.Handler.__init__(self, name)
|
||||
self.docroot = docroot
|
||||
self.realdocroot = fs.realpath(self.docroot)
|
||||
|
||||
options = options or {}
|
||||
self.dirlist = not options.noindex
|
||||
self.error404 = options.error404
|
||||
end
|
||||
|
||||
--- Parse a range request.
|
||||
-- @param request Request object
|
||||
-- @param size File size
|
||||
-- @return offset, length, range header or boolean status
|
||||
function Simple.parse_range(self, request, size)
|
||||
if not request.headers.Range then
|
||||
return true
|
||||
end
|
||||
|
||||
local from, to = request.headers.Range:match("bytes=([0-9]*)-([0-9]*)")
|
||||
if not (from or to) then
|
||||
return true
|
||||
end
|
||||
|
||||
from, to = tonumber(from), tonumber(to)
|
||||
if not (from or to) then
|
||||
return true
|
||||
elseif not from then
|
||||
from, to = size - to, size - 1
|
||||
elseif not to then
|
||||
to = size - 1
|
||||
end
|
||||
|
||||
-- Not satisfiable
|
||||
if from >= size then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Normalize
|
||||
if to >= size then
|
||||
to = size - 1
|
||||
end
|
||||
|
||||
local range = "bytes " .. from .. "-" .. to .. "/" .. size
|
||||
return from, (1 + to - from), range
|
||||
end
|
||||
|
||||
--- Translate path and return file information.
|
||||
-- @param uri Request URI
|
||||
-- @return physical file path, file information
|
||||
function Simple.getfile(self, uri)
|
||||
if not self.realdocroot then
|
||||
self.realdocroot = fs.realpath(self.docroot)
|
||||
end
|
||||
local file = fs.realpath(self.docroot .. uri)
|
||||
if not file or file:sub(1, #self.realdocroot) ~= self.realdocroot then
|
||||
return uri
|
||||
end
|
||||
return file, fs.stat(file)
|
||||
end
|
||||
|
||||
--- Handle a GET request.
|
||||
-- @param request Request object
|
||||
-- @return status code, header table, response source
|
||||
function Simple.handle_GET(self, request)
|
||||
local file, stat = self:getfile(prot.urldecode(request.env.PATH_INFO, true))
|
||||
|
||||
if stat then
|
||||
if stat.type == "reg" then
|
||||
|
||||
-- Generate Entity Tag
|
||||
local etag = cond.mk_etag( stat )
|
||||
|
||||
-- Check conditionals
|
||||
local ok, code, hdrs
|
||||
|
||||
ok, code, hdrs = cond.if_modified_since( request, stat )
|
||||
if ok then
|
||||
ok, code, hdrs = cond.if_match( request, stat )
|
||||
if ok then
|
||||
ok, code, hdrs = cond.if_unmodified_since( request, stat )
|
||||
if ok then
|
||||
ok, code, hdrs = cond.if_none_match( request, stat )
|
||||
if ok then
|
||||
local f, err = nixio.open(file)
|
||||
|
||||
if f then
|
||||
local code = 200
|
||||
local o, s, r = self:parse_range(request, stat.size)
|
||||
|
||||
if not o then
|
||||
return self:failure(416, "Invalid Range")
|
||||
end
|
||||
|
||||
local headers = {
|
||||
["Cache-Control"] = "max-age=29030400",
|
||||
["Last-Modified"] = date.to_http( stat.mtime ),
|
||||
["Content-Type"] = mime.to_mime( file ),
|
||||
["ETag"] = etag,
|
||||
["Accept-Ranges"] = "bytes",
|
||||
}
|
||||
|
||||
if o == true then
|
||||
s = stat.size
|
||||
else
|
||||
code = 206
|
||||
headers["Content-Range"] = r
|
||||
f:seek(o)
|
||||
end
|
||||
|
||||
headers["Content-Length"] = s
|
||||
|
||||
-- Send Response
|
||||
return code, headers, srv.IOResource(f, s)
|
||||
else
|
||||
return self:failure( 403, err:gsub("^.+: ", "") )
|
||||
end
|
||||
else
|
||||
return code, hdrs
|
||||
end
|
||||
else
|
||||
return code, hdrs
|
||||
end
|
||||
else
|
||||
return code, hdrs
|
||||
end
|
||||
else
|
||||
return code, hdrs
|
||||
end
|
||||
|
||||
elseif stat.type == "dir" then
|
||||
|
||||
local ruri = request.env.REQUEST_URI:gsub("/$", "")
|
||||
local duri = prot.urldecode( ruri, true )
|
||||
local root = self.docroot
|
||||
|
||||
-- check for index files
|
||||
local index_candidates = {
|
||||
"index.html", "index.htm", "default.html", "default.htm",
|
||||
"index.txt", "default.txt"
|
||||
}
|
||||
|
||||
-- try to find an index file and redirect to it
|
||||
for i, candidate in ipairs( index_candidates ) do
|
||||
local istat = fs.stat(
|
||||
root .. "/" .. duri .. "/" .. candidate
|
||||
)
|
||||
|
||||
if istat ~= nil and istat.type == "reg" then
|
||||
return 302, { Location = ruri .. "/" .. candidate }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local html = string.format(
|
||||
'<?xml version="1.0" encoding="utf-8"?>\n' ..
|
||||
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' ..
|
||||
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n'..
|
||||
'<html xmlns="http://www.w3.org/1999/xhtml" ' ..
|
||||
'xml:lang="en" lang="en">\n' ..
|
||||
'<head>\n' ..
|
||||
'<title>Index of %s/</title>\n' ..
|
||||
'<style type="text/css">\n' ..
|
||||
'body { color:#000000 } ' ..
|
||||
'li { border-bottom:1px dotted #CCCCCC; padding:3px } ' ..
|
||||
'small { font-size:60%%; color:#333333 } ' ..
|
||||
'p { margin:0 }' ..
|
||||
'\n</style></head><body><h1>Index of %s/</h1><hr /><ul>'..
|
||||
'<li><p><a href="%s/../">../</a> ' ..
|
||||
'<small>(parent directory)</small><br />' ..
|
||||
'<small></small></li>',
|
||||
duri, duri, ruri
|
||||
)
|
||||
|
||||
local entries = fs.dir( file )
|
||||
|
||||
if type(entries) == "function" then
|
||||
for i, e in util.vspairs(nixio.util.consume(entries)) do
|
||||
local estat = fs.stat( file .. "/" .. e )
|
||||
|
||||
if estat.type == "dir" then
|
||||
html = html .. string.format(
|
||||
'<li><p><a href="%s/%s/">%s/</a> ' ..
|
||||
'<small>(directory)</small><br />' ..
|
||||
'<small>Changed: %s</small></li>',
|
||||
ruri, prot.urlencode( e ), e,
|
||||
date.to_http( estat.mtime )
|
||||
)
|
||||
else
|
||||
html = html .. string.format(
|
||||
'<li><p><a href="%s/%s">%s</a> ' ..
|
||||
'<small>(%s)</small><br />' ..
|
||||
'<small>Size: %i Bytes | ' ..
|
||||
'Changed: %s</small></li>',
|
||||
ruri, prot.urlencode( e ), e,
|
||||
mime.to_mime( e ),
|
||||
estat.size, date.to_http( estat.mtime )
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
html = html .. '</ul><hr /><address>LuCId-HTTPd' ..
|
||||
'</address></body></html>'
|
||||
|
||||
return 200, {
|
||||
["Date"] = date.to_http( os.time() );
|
||||
["Content-Type"] = "text/html; charset=utf-8";
|
||||
}, ltn12.source.string(html)
|
||||
else
|
||||
return self:failure(403, "Permission denied")
|
||||
end
|
||||
else
|
||||
return self:failure(403, "Unable to transmit " .. stat.type .. " " .. file)
|
||||
end
|
||||
else
|
||||
if self.error404 then
|
||||
return 302, { Location = self.error404 }
|
||||
else
|
||||
return self:failure(404, "No such file: " .. file)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Handle a HEAD request.
|
||||
-- @param request Request object
|
||||
-- @return status code, header table, response source
|
||||
function Simple.handle_HEAD(self, ...)
|
||||
local stat, head = self:handle_GET(...)
|
||||
return stat, head
|
||||
end
|
|
@ -1,113 +0,0 @@
|
|||
--[[
|
||||
LuCId HTTP-Slave
|
||||
(c) 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local dsp = require "luci.dispatcher"
|
||||
local util = require "luci.util"
|
||||
local http = require "luci.http"
|
||||
local ltn12 = require "luci.ltn12"
|
||||
local srv = require "luci.lucid.http.server"
|
||||
local coroutine = require "coroutine"
|
||||
local type = type
|
||||
|
||||
--- LuCI web handler
|
||||
-- @cstyle instance
|
||||
module "luci.lucid.http.handler.luci"
|
||||
|
||||
--- Create a LuCI web handler.
|
||||
-- @class function
|
||||
-- @param name Name
|
||||
-- @param prefix Dispatching prefix
|
||||
-- @return LuCI web handler object
|
||||
Luci = util.class(srv.Handler)
|
||||
|
||||
function Luci.__init__(self, name, prefix)
|
||||
srv.Handler.__init__(self, name)
|
||||
self.prefix = prefix
|
||||
dsp.indexcache = "/tmp/luci-indexcache"
|
||||
end
|
||||
|
||||
--- Handle a HEAD request.
|
||||
-- @param request Request object
|
||||
-- @return status code, header table, response source
|
||||
function Luci.handle_HEAD(self, ...)
|
||||
local stat, head = self:handle_GET(...)
|
||||
return stat, head
|
||||
end
|
||||
|
||||
--- Handle a POST request.
|
||||
-- @param request Request object
|
||||
-- @return status code, header table, response source
|
||||
function Luci.handle_POST(self, ...)
|
||||
return self:handle_GET(...)
|
||||
end
|
||||
|
||||
--- Handle a GET request.
|
||||
-- @param request Request object
|
||||
-- @return status code, header table, response source
|
||||
function Luci.handle_GET(self, request, sourcein)
|
||||
local r = http.Request(
|
||||
request.env,
|
||||
sourcein
|
||||
)
|
||||
|
||||
local res, id, data1, data2 = true, 0, nil, nil
|
||||
local headers = {}
|
||||
local status = 200
|
||||
local active = true
|
||||
|
||||
local x = coroutine.create(dsp.httpdispatch)
|
||||
while not id or id < 3 do
|
||||
res, id, data1, data2 = coroutine.resume(x, r, self.prefix)
|
||||
|
||||
if not res then
|
||||
status = 500
|
||||
headers["Content-Type"] = "text/plain"
|
||||
return status, headers, ltn12.source.string(id)
|
||||
end
|
||||
|
||||
if id == 1 then
|
||||
status = data1
|
||||
elseif id == 2 then
|
||||
if not headers[data1] then
|
||||
headers[data1] = data2
|
||||
elseif type(headers[data1]) ~= "table" then
|
||||
headers[data1] = {headers[data1], data2}
|
||||
else
|
||||
headers[data1][#headers[data1]+1] = data2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if id == 6 then
|
||||
while (coroutine.resume(x)) do end
|
||||
return status, headers, srv.IOResource(data1, data2)
|
||||
end
|
||||
|
||||
local function iter()
|
||||
local res, id, data = coroutine.resume(x)
|
||||
if not res then
|
||||
return nil, id
|
||||
elseif not id or not active then
|
||||
return true
|
||||
elseif id == 5 then
|
||||
active = false
|
||||
while (coroutine.resume(x)) do end
|
||||
return nil
|
||||
elseif id == 4 then
|
||||
return data
|
||||
end
|
||||
end
|
||||
|
||||
return status, headers, iter
|
||||
end
|
||||
|
|
@ -1,600 +0,0 @@
|
|||
--[[
|
||||
LuCId HTTP-Slave
|
||||
(c) 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local ipairs, pairs = ipairs, pairs
|
||||
local tostring, tonumber = tostring, tonumber
|
||||
local pcall, assert, type = pcall, assert, type
|
||||
local set_memory_limit = set_memory_limit
|
||||
|
||||
local os = require "os"
|
||||
local nixio = require "nixio"
|
||||
local util = require "luci.util"
|
||||
local ltn12 = require "luci.ltn12"
|
||||
local proto = require "luci.http.protocol"
|
||||
local table = require "table"
|
||||
local date = require "luci.http.protocol.date"
|
||||
|
||||
--- HTTP Daemon
|
||||
-- @cstyle instance
|
||||
module "luci.lucid.http.server"
|
||||
|
||||
VERSION = "1.0"
|
||||
|
||||
statusmsg = {
|
||||
[200] = "OK",
|
||||
[206] = "Partial Content",
|
||||
[301] = "Moved Permanently",
|
||||
[302] = "Found",
|
||||
[304] = "Not Modified",
|
||||
[400] = "Bad Request",
|
||||
[401] = "Unauthorized",
|
||||
[403] = "Forbidden",
|
||||
[404] = "Not Found",
|
||||
[405] = "Method Not Allowed",
|
||||
[408] = "Request Time-out",
|
||||
[411] = "Length Required",
|
||||
[412] = "Precondition Failed",
|
||||
[416] = "Requested range not satisfiable",
|
||||
[500] = "Internal Server Error",
|
||||
[503] = "Server Unavailable",
|
||||
}
|
||||
|
||||
--- Create a new IO resource response.
|
||||
-- @class function
|
||||
-- @param fd File descriptor
|
||||
-- @param len Length of data
|
||||
-- @return IO resource
|
||||
IOResource = util.class()
|
||||
|
||||
function IOResource.__init__(self, fd, len)
|
||||
self.fd, self.len = fd, len
|
||||
end
|
||||
|
||||
|
||||
--- Create a server handler.
|
||||
-- @class function
|
||||
-- @param name Name
|
||||
-- @return Handler
|
||||
Handler = util.class()
|
||||
|
||||
function Handler.__init__(self, name)
|
||||
self.name = name or tostring(self)
|
||||
end
|
||||
|
||||
--- Create a failure reply.
|
||||
-- @param code HTTP status code
|
||||
-- @param msg Status message
|
||||
-- @return status code, header table, response source
|
||||
function Handler.failure(self, code, msg)
|
||||
return code, { ["Content-Type"] = "text/plain" }, ltn12.source.string(msg)
|
||||
end
|
||||
|
||||
--- Add an access restriction.
|
||||
-- @param restriction Restriction specification
|
||||
function Handler.restrict(self, restriction)
|
||||
if not self.restrictions then
|
||||
self.restrictions = {restriction}
|
||||
else
|
||||
self.restrictions[#self.restrictions+1] = restriction
|
||||
end
|
||||
end
|
||||
|
||||
--- Enforce access restrictions.
|
||||
-- @param request Request object
|
||||
-- @return nil or HTTP statuscode, table of headers, response source
|
||||
function Handler.checkrestricted(self, request)
|
||||
if not self.restrictions then
|
||||
return
|
||||
end
|
||||
|
||||
local localif, user, pass
|
||||
|
||||
for _, r in ipairs(self.restrictions) do
|
||||
local stat = true
|
||||
if stat and r.interface then -- Interface restriction
|
||||
if not localif then
|
||||
for _, v in ipairs(request.server.interfaces) do
|
||||
if v.addr == request.env.SERVER_ADDR then
|
||||
localif = v.name
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if r.interface ~= localif then
|
||||
stat = false
|
||||
end
|
||||
end
|
||||
|
||||
if stat and r.user then -- User restriction
|
||||
local rh, pwe
|
||||
if not user then
|
||||
rh = (request.headers.Authorization or ""):match("Basic (.*)")
|
||||
rh = rh and nixio.bin.b64decode(rh) or ""
|
||||
user, pass = rh:match("(.*):(.*)")
|
||||
pass = pass or ""
|
||||
end
|
||||
pwe = nixio.getsp and nixio.getsp(r.user) or nixio.getpw(r.user)
|
||||
local pwh = (user == r.user) and pwe and (pwe.pwdp or pwe.passwd)
|
||||
if not pwh or #pwh < 1 or nixio.crypt(pass, pwh) ~= pwh then
|
||||
stat = false
|
||||
end
|
||||
end
|
||||
|
||||
if stat then
|
||||
request.env.HTTP_AUTH_USER, request.env.HTTP_AUTH_PASS = user, pass
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return 401, {
|
||||
["WWW-Authenticate"] = ('Basic realm=%q'):format(self.name),
|
||||
["Content-Type"] = 'text/plain'
|
||||
}, ltn12.source.string("Unauthorized")
|
||||
end
|
||||
|
||||
--- Process a request.
|
||||
-- @param request Request object
|
||||
-- @param sourcein Request data source
|
||||
-- @return HTTP statuscode, table of headers, response source
|
||||
function Handler.process(self, request, sourcein)
|
||||
local stat, code, hdr, sourceout
|
||||
|
||||
local stat, code, msg = self:checkrestricted(request)
|
||||
if stat then -- Access Denied
|
||||
return stat, code, msg
|
||||
end
|
||||
|
||||
-- Detect request Method
|
||||
local hname = "handle_" .. request.env.REQUEST_METHOD
|
||||
if self[hname] then
|
||||
-- Run the handler
|
||||
stat, code, hdr, sourceout = pcall(self[hname], self, request, sourcein)
|
||||
|
||||
-- Check for any errors
|
||||
if not stat then
|
||||
return self:failure(500, code)
|
||||
end
|
||||
else
|
||||
return self:failure(405, statusmsg[405])
|
||||
end
|
||||
|
||||
return code, hdr, sourceout
|
||||
end
|
||||
|
||||
|
||||
--- Create a Virtual Host.
|
||||
-- @class function
|
||||
-- @return Virtual Host
|
||||
VHost = util.class()
|
||||
|
||||
function VHost.__init__(self)
|
||||
self.handlers = {}
|
||||
end
|
||||
|
||||
--- Process a request and invoke the appropriate handler.
|
||||
-- @param request Request object
|
||||
-- @param ... Additional parameters passed to the handler
|
||||
-- @return HTTP statuscode, table of headers, response source
|
||||
function VHost.process(self, request, ...)
|
||||
local handler
|
||||
local hlen = -1
|
||||
local uri = request.env.SCRIPT_NAME
|
||||
local sc = ("/"):byte()
|
||||
|
||||
-- SCRIPT_NAME
|
||||
request.env.SCRIPT_NAME = ""
|
||||
|
||||
-- Call URI part
|
||||
request.env.PATH_INFO = uri
|
||||
|
||||
if self.default and uri == "/" then
|
||||
return 302, {Location = self.default}
|
||||
end
|
||||
|
||||
for k, h in pairs(self.handlers) do
|
||||
if #k > hlen then
|
||||
if uri == k or (uri:sub(1, #k) == k and uri:byte(#k+1) == sc) then
|
||||
handler = h
|
||||
hlen = #k
|
||||
request.env.SCRIPT_NAME = k
|
||||
request.env.PATH_INFO = uri:sub(#k+1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if handler then
|
||||
return handler:process(request, ...)
|
||||
else
|
||||
return 404, nil, ltn12.source.string("No such handler")
|
||||
end
|
||||
end
|
||||
|
||||
--- Get a list of registered handlers.
|
||||
-- @return Table of handlers
|
||||
function VHost.get_handlers(self)
|
||||
return self.handlers
|
||||
end
|
||||
|
||||
--- Register handler with a given URI prefix.
|
||||
-- @oaram match URI prefix
|
||||
-- @param handler Handler object
|
||||
function VHost.set_handler(self, match, handler)
|
||||
self.handlers[match] = handler
|
||||
end
|
||||
|
||||
-- Remap IPv6-IPv4-compatibility addresses back to IPv4 addresses.
|
||||
local function remapipv6(adr)
|
||||
local map = "::ffff:"
|
||||
if adr:sub(1, #map) == map then
|
||||
return adr:sub(#map+1)
|
||||
else
|
||||
return adr
|
||||
end
|
||||
end
|
||||
|
||||
-- Create a source that decodes chunked-encoded data from a socket.
|
||||
local function chunksource(sock, buffer)
|
||||
buffer = buffer or ""
|
||||
return function()
|
||||
local output
|
||||
local _, endp, count = buffer:find("^([0-9a-fA-F]+);?.-\r\n")
|
||||
while not count and #buffer <= 1024 do
|
||||
local newblock, code = sock:recv(1024 - #buffer)
|
||||
if not newblock then
|
||||
return nil, code
|
||||
end
|
||||
buffer = buffer .. newblock
|
||||
_, endp, count = buffer:find("^([0-9a-fA-F]+);?.-\r\n")
|
||||
end
|
||||
count = tonumber(count, 16)
|
||||
if not count then
|
||||
return nil, -1, "invalid encoding"
|
||||
elseif count == 0 then
|
||||
return nil
|
||||
elseif count + 2 <= #buffer - endp then
|
||||
output = buffer:sub(endp+1, endp+count)
|
||||
buffer = buffer:sub(endp+count+3)
|
||||
return output
|
||||
else
|
||||
output = buffer:sub(endp+1, endp+count)
|
||||
buffer = ""
|
||||
if count - #output > 0 then
|
||||
local remain, code = sock:recvall(count-#output)
|
||||
if not remain then
|
||||
return nil, code
|
||||
end
|
||||
output = output .. remain
|
||||
count, code = sock:recvall(2)
|
||||
else
|
||||
count, code = sock:recvall(count+2-#buffer+endp)
|
||||
end
|
||||
if not count then
|
||||
return nil, code
|
||||
end
|
||||
return output
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Create a sink that chunk-encodes data and writes it on a given socket.
|
||||
local function chunksink(sock)
|
||||
return function(chunk, err)
|
||||
if not chunk then
|
||||
return sock:writeall("0\r\n\r\n")
|
||||
else
|
||||
return sock:writeall(("%X\r\n%s\r\n"):format(#chunk, tostring(chunk)))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Create a server object.
|
||||
-- @class function
|
||||
-- @return Server object
|
||||
Server = util.class()
|
||||
|
||||
function Server.__init__(self)
|
||||
self.vhosts = {}
|
||||
end
|
||||
|
||||
--- Get a list of registered virtual hosts.
|
||||
-- @return Table of virtual hosts
|
||||
function Server.get_vhosts(self)
|
||||
return self.vhosts
|
||||
end
|
||||
|
||||
--- Register a virtual host with a given name.
|
||||
-- @param name Hostname
|
||||
-- @param vhost Virtual host object
|
||||
function Server.set_vhost(self, name, vhost)
|
||||
self.vhosts[name] = vhost
|
||||
end
|
||||
|
||||
--- Send a fatal error message to given client and close the connection.
|
||||
-- @param client Client socket
|
||||
-- @param code HTTP status code
|
||||
-- @param msg status message
|
||||
function Server.error(self, client, code, msg)
|
||||
hcode = tostring(code)
|
||||
|
||||
client:writeall( "HTTP/1.0 " .. hcode .. " " ..
|
||||
statusmsg[code] .. "\r\n" )
|
||||
client:writeall( "Connection: close\r\n" )
|
||||
client:writeall( "Content-Type: text/plain\r\n\r\n" )
|
||||
|
||||
if msg then
|
||||
client:writeall( "HTTP-Error " .. code .. ": " .. msg .. "\r\n" )
|
||||
end
|
||||
|
||||
client:close()
|
||||
end
|
||||
|
||||
local hdr2env = {
|
||||
["Content-Length"] = "CONTENT_LENGTH",
|
||||
["Content-Type"] = "CONTENT_TYPE",
|
||||
["Content-type"] = "CONTENT_TYPE",
|
||||
["Accept"] = "HTTP_ACCEPT",
|
||||
["Accept-Charset"] = "HTTP_ACCEPT_CHARSET",
|
||||
["Accept-Encoding"] = "HTTP_ACCEPT_ENCODING",
|
||||
["Accept-Language"] = "HTTP_ACCEPT_LANGUAGE",
|
||||
["Connection"] = "HTTP_CONNECTION",
|
||||
["Cookie"] = "HTTP_COOKIE",
|
||||
["Host"] = "HTTP_HOST",
|
||||
["Referer"] = "HTTP_REFERER",
|
||||
["User-Agent"] = "HTTP_USER_AGENT"
|
||||
}
|
||||
|
||||
--- Parse the request headers and prepare the environment.
|
||||
-- @param source line-based input source
|
||||
-- @return Request object
|
||||
function Server.parse_headers(self, source)
|
||||
local env = {}
|
||||
local req = {env = env, headers = {}}
|
||||
local line, err
|
||||
|
||||
repeat -- Ignore empty lines
|
||||
line, err = source()
|
||||
if not line then
|
||||
return nil, err
|
||||
end
|
||||
until #line > 0
|
||||
|
||||
env.REQUEST_METHOD, env.REQUEST_URI, env.SERVER_PROTOCOL =
|
||||
line:match("^([A-Z]+) ([^ ]+) (HTTP/1%.[01])$")
|
||||
|
||||
if not env.REQUEST_METHOD then
|
||||
return nil, "invalid magic"
|
||||
end
|
||||
|
||||
local key, envkey, val
|
||||
repeat
|
||||
line, err = source()
|
||||
if not line then
|
||||
return nil, err
|
||||
elseif #line > 0 then
|
||||
key, val = line:match("^([%w-]+)%s?:%s?(.*)")
|
||||
if key then
|
||||
req.headers[key] = val
|
||||
envkey = hdr2env[key]
|
||||
if envkey then
|
||||
env[envkey] = val
|
||||
end
|
||||
else
|
||||
return nil, "invalid header line"
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
until false
|
||||
|
||||
env.SCRIPT_NAME, env.QUERY_STRING = env.REQUEST_URI:match("([^?]*)%??(.*)")
|
||||
return req
|
||||
end
|
||||
|
||||
--- Handle a new client connection.
|
||||
-- @param client client socket
|
||||
-- @param env superserver environment
|
||||
function Server.process(self, client, env)
|
||||
local sourcein = function() end
|
||||
local sourcehdr = client:linesource()
|
||||
local sinkout
|
||||
local buffer
|
||||
|
||||
local close = false
|
||||
local stat, code, msg, message, err
|
||||
|
||||
env.config.memlimit = tonumber(env.config.memlimit)
|
||||
if env.config.memlimit and set_memory_limit then
|
||||
set_memory_limit(env.config.memlimit)
|
||||
end
|
||||
|
||||
client:setsockopt("socket", "rcvtimeo", 5)
|
||||
client:setsockopt("socket", "sndtimeo", 5)
|
||||
|
||||
repeat
|
||||
-- parse headers
|
||||
message, err = self:parse_headers(sourcehdr)
|
||||
|
||||
-- any other error
|
||||
if not message or err then
|
||||
if err == 11 then -- EAGAIN
|
||||
break
|
||||
else
|
||||
return self:error(client, 400, err)
|
||||
end
|
||||
end
|
||||
|
||||
-- Prepare sources and sinks
|
||||
buffer = sourcehdr(true)
|
||||
sinkout = client:sink()
|
||||
message.server = env
|
||||
|
||||
if client:is_tls_socket() then
|
||||
message.env.HTTPS = "on"
|
||||
end
|
||||
|
||||
-- Addresses
|
||||
message.env.REMOTE_ADDR = remapipv6(env.host)
|
||||
message.env.REMOTE_PORT = env.port
|
||||
|
||||
local srvaddr, srvport = client:getsockname()
|
||||
message.env.SERVER_ADDR = remapipv6(srvaddr)
|
||||
message.env.SERVER_PORT = srvport
|
||||
|
||||
-- keep-alive
|
||||
if message.env.SERVER_PROTOCOL == "HTTP/1.1" then
|
||||
close = (message.env.HTTP_CONNECTION == "close")
|
||||
else
|
||||
close = not message.env.HTTP_CONNECTION
|
||||
or message.env.HTTP_CONNECTION == "close"
|
||||
end
|
||||
|
||||
-- Uncomment this to disable keep-alive
|
||||
close = close or env.config.nokeepalive
|
||||
|
||||
if message.env.REQUEST_METHOD == "GET"
|
||||
or message.env.REQUEST_METHOD == "HEAD" then
|
||||
-- Be happy
|
||||
|
||||
elseif message.env.REQUEST_METHOD == "POST" then
|
||||
-- If we have a HTTP/1.1 client and an Expect: 100-continue header
|
||||
-- respond with HTTP 100 Continue message
|
||||
if message.env.SERVER_PROTOCOL == "HTTP/1.1"
|
||||
and message.headers.Expect == '100-continue' then
|
||||
client:writeall("HTTP/1.1 100 Continue\r\n\r\n")
|
||||
end
|
||||
|
||||
if message.headers['Transfer-Encoding'] and
|
||||
message.headers['Transfer-Encoding'] ~= "identity" then
|
||||
sourcein = chunksource(client, buffer)
|
||||
buffer = nil
|
||||
elseif message.env.CONTENT_LENGTH then
|
||||
local len = tonumber(message.env.CONTENT_LENGTH)
|
||||
if #buffer >= len then
|
||||
sourcein = ltn12.source.string(buffer:sub(1, len))
|
||||
buffer = buffer:sub(len+1)
|
||||
else
|
||||
sourcein = ltn12.source.cat(
|
||||
ltn12.source.string(buffer),
|
||||
client:blocksource(nil, len - #buffer)
|
||||
)
|
||||
end
|
||||
else
|
||||
return self:error(client, 411, statusmsg[411])
|
||||
end
|
||||
|
||||
close = true
|
||||
else
|
||||
return self:error(client, 405, statusmsg[405])
|
||||
end
|
||||
|
||||
|
||||
local host = self.vhosts[message.env.HTTP_HOST] or self.vhosts[""]
|
||||
if not host then
|
||||
return self:error(client, 404, "No virtual host found")
|
||||
end
|
||||
|
||||
local code, headers, sourceout = host:process(message, sourcein)
|
||||
headers = headers or {}
|
||||
|
||||
-- Post process response
|
||||
if sourceout then
|
||||
if util.instanceof(sourceout, IOResource) then
|
||||
if not headers["Content-Length"] then
|
||||
headers["Content-Length"] = sourceout.len
|
||||
end
|
||||
end
|
||||
if not headers["Content-Length"] and not close then
|
||||
if message.env.SERVER_PROTOCOL == "HTTP/1.1" then
|
||||
headers["Transfer-Encoding"] = "chunked"
|
||||
sinkout = chunksink(client)
|
||||
else
|
||||
close = true
|
||||
end
|
||||
end
|
||||
elseif message.env.REQUEST_METHOD ~= "HEAD" then
|
||||
headers["Content-Length"] = 0
|
||||
end
|
||||
|
||||
if close then
|
||||
headers["Connection"] = "close"
|
||||
else
|
||||
headers["Connection"] = "Keep-Alive"
|
||||
headers["Keep-Alive"] = "timeout=5, max=50"
|
||||
end
|
||||
|
||||
headers["Date"] = date.to_http(os.time())
|
||||
local header = {
|
||||
message.env.SERVER_PROTOCOL .. " " .. tostring(code) .. " "
|
||||
.. statusmsg[code],
|
||||
"Server: LuCId-HTTPd/" .. VERSION
|
||||
}
|
||||
|
||||
|
||||
for k, v in pairs(headers) do
|
||||
if type(v) == "table" then
|
||||
for _, h in ipairs(v) do
|
||||
header[#header+1] = k .. ": " .. h
|
||||
end
|
||||
else
|
||||
header[#header+1] = k .. ": " .. v
|
||||
end
|
||||
end
|
||||
|
||||
header[#header+1] = ""
|
||||
header[#header+1] = ""
|
||||
|
||||
-- Output
|
||||
stat, code, msg = client:writeall(table.concat(header, "\r\n"))
|
||||
|
||||
if sourceout and stat then
|
||||
local closefd
|
||||
if util.instanceof(sourceout, IOResource) then
|
||||
if not headers["Transfer-Encoding"] then
|
||||
stat, code, msg = sourceout.fd:copyz(client, sourceout.len)
|
||||
closefd = sourceout.fd
|
||||
sourceout = nil
|
||||
else
|
||||
closefd = sourceout.fd
|
||||
sourceout = sourceout.fd:blocksource(nil, sourceout.len)
|
||||
end
|
||||
end
|
||||
|
||||
if sourceout then
|
||||
stat, msg = ltn12.pump.all(sourceout, sinkout)
|
||||
end
|
||||
|
||||
if closefd then
|
||||
closefd:close()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Write errors
|
||||
if not stat then
|
||||
if msg then
|
||||
nixio.syslog("err", "Error sending data to " .. env.host ..
|
||||
": " .. msg .. "\n")
|
||||
end
|
||||
break
|
||||
end
|
||||
|
||||
if buffer then
|
||||
sourcehdr(buffer)
|
||||
end
|
||||
until close
|
||||
|
||||
client:shutdown()
|
||||
client:close()
|
||||
end
|
|
@ -1,2 +0,0 @@
|
|||
include ../../build/config.mk
|
||||
include ../../build/module.mk
|
|
@ -1,19 +0,0 @@
|
|||
LuCId JSON-RPC Server Slave
|
||||
|
||||
*** Abstract ***
|
||||
The LuCId JSON-RPC server slave implements the JSON-RPC 1.0 and 2.0 protocol
|
||||
to allow efficient light-weight remote procedure calling.
|
||||
It provides notification support and several unofficial protocol extensions such
|
||||
as:
|
||||
* Close notifications
|
||||
* Raw TCP switching to transfer BLOBs efficiently
|
||||
* Client notification
|
||||
|
||||
|
||||
*** Workflow ***
|
||||
After receiving an incoming connection from LuCId, the slave analyses the
|
||||
request and passes it to the matching handler. The handler will enforce
|
||||
access restriction and deserialize the payload data and invokes the assigned
|
||||
Lua function in a protected way. In case of a success the handler will serialize
|
||||
the response and send it to the client - otherwise a detailed error message
|
||||
will be returned.
|
|
@ -1,51 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Development Framework
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]
|
||||
|
||||
local require, ipairs, pcall = require, ipairs, pcall
|
||||
local srv = require "luci.lucid.rpc.server"
|
||||
|
||||
module "luci.lucid.rpc"
|
||||
|
||||
--- Prepare the RPC-daemon and its associated publishers.
|
||||
-- @param publisher Table of publishers
|
||||
-- @return factory callback or nil, error message
|
||||
function factory(publisher)
|
||||
local root = srv.Module()
|
||||
local server = srv.Server(root)
|
||||
|
||||
for _, r in ipairs(publisher) do
|
||||
for _, m in ipairs(r.export) do
|
||||
local s, mod = pcall(require, r.namespace .. "." .. m)
|
||||
if s and mod then
|
||||
local module = mod._factory()
|
||||
|
||||
if r.exec then
|
||||
for _, x in ipairs(r.exec) do
|
||||
if x:sub(1,1) == ":" then
|
||||
module:restrict({interface = x:sub(2)})
|
||||
else
|
||||
module:restrict({user = x})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
root:add(m, module)
|
||||
else
|
||||
return nil, mod
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return function(...) return server:process(...) end
|
||||
end
|
|
@ -1,85 +0,0 @@
|
|||
--[[
|
||||
LuCIRPCd
|
||||
(c) 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
local uci = require "luci.model.uci"
|
||||
local tostring, getmetatable, pairs = tostring, getmetatable, pairs
|
||||
local error, type = error, type
|
||||
local nixio = require "nixio"
|
||||
local srv = require "luci.lucid.rpc.server"
|
||||
|
||||
--- Remote UCI functions.
|
||||
module "luci.lucid.rpc.ruci"
|
||||
|
||||
-- Prepare the remote UCI functions.
|
||||
function _factory()
|
||||
local m = srv.Module("Remote UCI API")
|
||||
|
||||
for k, v in pairs(_M) do
|
||||
if type(v) == "function" and v ~= _factory then
|
||||
m:add(k, srv.Method.extended(v))
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
end
|
||||
|
||||
-- Get the associate RUCI instance.
|
||||
local function getinst(session, name)
|
||||
return session.ruci and session.ruci[name]
|
||||
end
|
||||
|
||||
-- Set a new RUCI instance.
|
||||
local function setinst(session, obj)
|
||||
session.ruci = session.ruci or {}
|
||||
local name = tostring(obj):match("0x([a-z0-9]+)")
|
||||
session.ruci[name] = obj
|
||||
return name
|
||||
end
|
||||
|
||||
|
||||
local Cursor = getmetatable(uci.cursor())
|
||||
|
||||
for name, func in pairs(Cursor) do
|
||||
_M[name] = function(session, inst, ...)
|
||||
inst = getinst(session, inst)
|
||||
return inst[name](inst, ...)
|
||||
end
|
||||
end
|
||||
|
||||
--- Generate a new RUCI cursor.
|
||||
-- @param session Session object
|
||||
-- @param ... Parameters passed to the UCI constructor
|
||||
-- @return RUCI instance
|
||||
function cursor(session, ...)
|
||||
return setinst(session, uci.cursor(...))
|
||||
end
|
||||
|
||||
--- Generate a new RUCI state cursor.
|
||||
-- @param session Session object
|
||||
-- @param ... Parameters passed to the UCI constructor
|
||||
-- @return RUCI instance
|
||||
function cursor_state(session, ...)
|
||||
return setinst(session, uci.cursor_state(...))
|
||||
end
|
||||
|
||||
--- Custom foreach function.
|
||||
-- @param session Session object
|
||||
-- @param inst RUCI instance
|
||||
-- @param config UCI config
|
||||
-- @param sectiontype UCI sectiontype
|
||||
-- @return section data
|
||||
function foreach(session, inst, config, sectiontype)
|
||||
local inst = getinst(session, inst)
|
||||
local secs = {}
|
||||
inst:foreach(config, sectiontype, function(s) secs[#secs+1] = s end)
|
||||
return secs
|
||||
end
|
|
@ -1,338 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Development Framework
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]
|
||||
|
||||
local ipairs, pairs = ipairs, pairs
|
||||
local tostring, tonumber = tostring, tonumber
|
||||
local pcall, assert, type, unpack = pcall, assert, type, unpack
|
||||
|
||||
local nixio = require "nixio"
|
||||
local json = require "luci.json"
|
||||
local util = require "luci.util"
|
||||
local table = require "table"
|
||||
local ltn12 = require "luci.ltn12"
|
||||
|
||||
--- RPC daemom.
|
||||
-- @cstyle instance
|
||||
module "luci.lucid.rpc.server"
|
||||
|
||||
RQLIMIT = 32 * nixio.const.buffersize
|
||||
VERSION = "1.0"
|
||||
|
||||
ERRNO_PARSE = -32700
|
||||
ERRNO_INVALID = -32600
|
||||
ERRNO_UNKNOWN = -32001
|
||||
ERRNO_TIMEOUT = -32000
|
||||
ERRNO_NOTFOUND = -32601
|
||||
ERRNO_NOACCESS = -32002
|
||||
ERRNO_INTERNAL = -32603
|
||||
ERRNO_NOSUPPORT = -32003
|
||||
|
||||
ERRMSG = {
|
||||
[ERRNO_PARSE] = "Parse error.",
|
||||
[ERRNO_INVALID] = "Invalid request.",
|
||||
[ERRNO_TIMEOUT] = "Connection timeout.",
|
||||
[ERRNO_UNKNOWN] = "Unknown error.",
|
||||
[ERRNO_NOTFOUND] = "Method not found.",
|
||||
[ERRNO_NOACCESS] = "Access denied.",
|
||||
[ERRNO_INTERNAL] = "Internal error.",
|
||||
[ERRNO_NOSUPPORT] = "Operation not supported."
|
||||
}
|
||||
|
||||
|
||||
--- Create an RPC method wrapper.
|
||||
-- @class function
|
||||
-- @param method Lua function
|
||||
-- @param description Method description
|
||||
-- @return Wrapped RPC method
|
||||
Method = util.class()
|
||||
|
||||
--- Create an extended wrapped RPC method.
|
||||
-- @class function
|
||||
-- @param method Lua function
|
||||
-- @param description Method description
|
||||
-- @return Wrapped RPC method
|
||||
function Method.extended(...)
|
||||
local m = Method(...)
|
||||
m.call = m.xcall
|
||||
return m
|
||||
end
|
||||
|
||||
function Method.__init__(self, method, description)
|
||||
self.description = description
|
||||
self.method = method
|
||||
end
|
||||
|
||||
--- Extended call the associated function.
|
||||
-- @param session Session storage
|
||||
-- @param argv Request parameters
|
||||
-- @return function call response
|
||||
function Method.xcall(self, session, argv)
|
||||
return self.method(session, unpack(argv))
|
||||
end
|
||||
|
||||
--- Standard call the associated function.
|
||||
-- @param session Session storage
|
||||
-- @param argv Request parameters
|
||||
-- @return function call response
|
||||
function Method.call(self, session, argv)
|
||||
return self.method(unpack(argv))
|
||||
end
|
||||
|
||||
--- Process a given request and create a JSON response.
|
||||
-- @param session Session storage
|
||||
-- @param request Requested method
|
||||
-- @param argv Request parameters
|
||||
function Method.process(self, session, request, argv)
|
||||
local stat, result = pcall(self.call, self, session, argv)
|
||||
|
||||
if stat then
|
||||
return { result=result }
|
||||
else
|
||||
return { error={
|
||||
code=ERRNO_UNKNOWN,
|
||||
message=ERRMSG[ERRNO_UNKNOWN],
|
||||
data=result
|
||||
} }
|
||||
end
|
||||
end
|
||||
|
||||
-- Remap IPv6-IPv4-compatibility addresses to IPv4 addresses
|
||||
local function remapipv6(adr)
|
||||
local map = "::ffff:"
|
||||
if adr:sub(1, #map) == map then
|
||||
return adr:sub(#map+1)
|
||||
else
|
||||
return adr
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Create an RPC module.
|
||||
-- @class function
|
||||
-- @param description Method description
|
||||
-- @return RPC module
|
||||
Module = util.class()
|
||||
|
||||
function Module.__init__(self, description)
|
||||
self.description = description
|
||||
self.handler = {}
|
||||
end
|
||||
|
||||
--- Add a handler.
|
||||
-- @param k key
|
||||
-- @param v handler
|
||||
function Module.add(self, k, v)
|
||||
self.handler[k] = v
|
||||
end
|
||||
|
||||
--- Add an access restriction.
|
||||
-- @param restriction Restriction specification
|
||||
function Module.restrict(self, restriction)
|
||||
if not self.restrictions then
|
||||
self.restrictions = {restriction}
|
||||
else
|
||||
self.restrictions[#self.restrictions+1] = restriction
|
||||
end
|
||||
end
|
||||
|
||||
--- Enforce access restrictions.
|
||||
-- @param request Request object
|
||||
-- @return nil or HTTP statuscode, table of headers, response source
|
||||
function Module.checkrestricted(self, session, request, argv)
|
||||
if not self.restrictions then
|
||||
return
|
||||
end
|
||||
|
||||
for _, r in ipairs(self.restrictions) do
|
||||
local stat = true
|
||||
if stat and r.interface then -- Interface restriction
|
||||
if not session.localif then
|
||||
for _, v in ipairs(session.env.interfaces) do
|
||||
if v.addr == session.localaddr then
|
||||
session.localif = v.name
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if r.interface ~= session.localif then
|
||||
stat = false
|
||||
end
|
||||
end
|
||||
|
||||
if stat and r.user and session.user ~= r.user then -- User restriction
|
||||
stat = false
|
||||
end
|
||||
|
||||
if stat then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return {error={code=ERRNO_NOACCESS, message=ERRMSG[ERRNO_NOACCESS]}}
|
||||
end
|
||||
|
||||
--- Register a handler, submodule or function.
|
||||
-- @param m entity
|
||||
-- @param descr description
|
||||
-- @return Module (self)
|
||||
function Module.register(self, m, descr)
|
||||
descr = descr or {}
|
||||
for k, v in pairs(m) do
|
||||
if util.instanceof(v, Method) then
|
||||
self.handler[k] = v
|
||||
elseif type(v) == "table" then
|
||||
self.handler[k] = Module()
|
||||
self.handler[k]:register(v, descr[k])
|
||||
elseif type(v) == "function" then
|
||||
self.handler[k] = Method(v, descr[k])
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Process a request.
|
||||
-- @param session Session storage
|
||||
-- @param request Request object
|
||||
-- @param argv Request parameters
|
||||
-- @return JSON response object
|
||||
function Module.process(self, session, request, argv)
|
||||
local first, last = request:match("^([^.]+).?(.*)$")
|
||||
|
||||
local stat = self:checkrestricted(session, request, argv)
|
||||
if stat then -- Access Denied
|
||||
return stat
|
||||
end
|
||||
|
||||
local hndl = first and self.handler[first]
|
||||
if not hndl then
|
||||
return {error={code=ERRNO_NOTFOUND, message=ERRMSG[ERRNO_NOTFOUND]}}
|
||||
end
|
||||
|
||||
session.chain[#session.chain+1] = self
|
||||
return hndl:process(session, last, argv)
|
||||
end
|
||||
|
||||
|
||||
--- Create a server object.
|
||||
-- @class function
|
||||
-- @param root Root module
|
||||
-- @return Server object
|
||||
Server = util.class()
|
||||
|
||||
function Server.__init__(self, root)
|
||||
self.root = root
|
||||
end
|
||||
|
||||
--- Get the associated root module.
|
||||
-- @return Root module
|
||||
function Server.get_root(self)
|
||||
return self.root
|
||||
end
|
||||
|
||||
--- Set a new root module.
|
||||
-- @param root Root module
|
||||
function Server.set_root(self, root)
|
||||
self.root = root
|
||||
end
|
||||
|
||||
--- Create a JSON reply.
|
||||
-- @param jsonrpc JSON-RPC version
|
||||
-- @param id Message id
|
||||
-- @param res Result
|
||||
-- @param err Error
|
||||
-- @reutrn JSON response source
|
||||
function Server.reply(self, jsonrpc, id, res, err)
|
||||
id = id or json.null
|
||||
|
||||
-- 1.0 compatibility
|
||||
if jsonrpc ~= "2.0" then
|
||||
jsonrpc = nil
|
||||
res = res or json.null
|
||||
err = err or json.null
|
||||
end
|
||||
|
||||
return json.Encoder(
|
||||
{id=id, result=res, error=err, jsonrpc=jsonrpc}, BUFSIZE
|
||||
):source()
|
||||
end
|
||||
|
||||
--- Handle a new client connection.
|
||||
-- @param client client socket
|
||||
-- @param env superserver environment
|
||||
function Server.process(self, client, env)
|
||||
local decoder
|
||||
local sinkout = client:sink()
|
||||
client:setopt("socket", "sndtimeo", 90)
|
||||
client:setopt("socket", "rcvtimeo", 90)
|
||||
|
||||
local close = false
|
||||
local session = {server = self, chain = {}, client = client, env = env,
|
||||
localaddr = remapipv6(client:getsockname())}
|
||||
local req, stat, response, result, cb
|
||||
|
||||
repeat
|
||||
local oldchunk = decoder and decoder.chunk
|
||||
decoder = json.ActiveDecoder(client:blocksource(nil, RQLIMIT))
|
||||
decoder.chunk = oldchunk
|
||||
|
||||
result, response, cb = nil, nil, nil
|
||||
|
||||
-- Read one request
|
||||
stat, req = pcall(decoder.get, decoder)
|
||||
|
||||
if stat then
|
||||
if type(req) == "table" and type(req.method) == "string"
|
||||
and (not req.params or type(req.params) == "table") then
|
||||
req.params = req.params or {}
|
||||
result, cb = self.root:process(session, req.method, req.params)
|
||||
if type(result) == "table" then
|
||||
if req.id ~= nil then
|
||||
response = self:reply(req.jsonrpc, req.id,
|
||||
result.result, result.error)
|
||||
end
|
||||
close = result.close
|
||||
else
|
||||
if req.id ~= nil then
|
||||
response = self:reply(req.jsonrpc, req.id, nil,
|
||||
{code=ERRNO_INTERNAL, message=ERRMSG[ERRNO_INTERNAL]})
|
||||
end
|
||||
end
|
||||
else
|
||||
response = self:reply(req.jsonrpc, req.id,
|
||||
nil, {code=ERRNO_INVALID, message=ERRMSG[ERRNO_INVALID]})
|
||||
end
|
||||
else
|
||||
if nixio.errno() ~= nixio.const.EAGAIN then
|
||||
response = self:reply("2.0", nil,
|
||||
nil, {code=ERRNO_PARSE, message=ERRMSG[ERRNO_PARSE]})
|
||||
--[[else
|
||||
response = self:reply("2.0", nil,
|
||||
nil, {code=ERRNO_TIMEOUT, message=ERRMSG_TIMEOUT})]]
|
||||
end
|
||||
close = true
|
||||
end
|
||||
|
||||
if response then
|
||||
ltn12.pump.all(response, sinkout)
|
||||
end
|
||||
|
||||
if cb then
|
||||
close = cb(client, session, self) or close
|
||||
end
|
||||
until close
|
||||
|
||||
client:shutdown()
|
||||
client:close()
|
||||
end
|
|
@ -1,101 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Development Framework
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]
|
||||
|
||||
local type, ipairs = type, ipairs
|
||||
local srv = require "luci.lucid.rpc.server"
|
||||
local nixio = require "nixio"
|
||||
local lucid = require "luci.lucid"
|
||||
|
||||
--- Internal system functions.
|
||||
module "luci.lucid.rpc.system"
|
||||
|
||||
-- Prepare the RPC module.
|
||||
function _factory()
|
||||
local mod = srv.Module("System functions"):register({
|
||||
echo = echo,
|
||||
void = void,
|
||||
multicall = srv.Method.extended(multicall),
|
||||
authenticate = srv.Method.extended(authenticate)
|
||||
})
|
||||
mod.checkrestricted = function(self, session, request, ...)
|
||||
if request ~= "authenticate" then
|
||||
return srv.Module.checkrestricted(self, session, request, ...)
|
||||
end
|
||||
end
|
||||
return mod
|
||||
end
|
||||
|
||||
--- Simple echo test function.
|
||||
-- @param object to be echoed object
|
||||
-- @return echo object
|
||||
function echo(object)
|
||||
return object
|
||||
end
|
||||
|
||||
--- Simple void test function.
|
||||
function void()
|
||||
|
||||
end
|
||||
|
||||
--- Accumulate different requests and execute them.
|
||||
-- @param session Session object
|
||||
-- @param ...
|
||||
-- @return overall response object
|
||||
function multicall(session, ...)
|
||||
local server, responses, response = session.server, {}, nil
|
||||
for k, req in ipairs({...}) do
|
||||
response = nil
|
||||
if type(req) == "table" and type(req.method) == "string"
|
||||
and (not req.params or type(req.params) == "table") then
|
||||
req.params = req.params or {}
|
||||
result = server.root:process(session, req.method, req.params)
|
||||
if type(result) == "table" then
|
||||
if req.id ~= nil then
|
||||
response = {jsonrpc=req.jsonrpc, id=req.id,
|
||||
result=result.result, error=result.error}
|
||||
end
|
||||
else
|
||||
if req.id ~= nil then
|
||||
response = {jsonrpc=req.jsonrpc, id=req.id,
|
||||
result=nil, error={code=srv.ERRNO_INTERNAL,
|
||||
message=srv.ERRMSG[ERRNO_INTERNAL]}}
|
||||
end
|
||||
end
|
||||
end
|
||||
responses[k] = response
|
||||
end
|
||||
return responses
|
||||
end
|
||||
|
||||
--- Create or use a new authentication token.
|
||||
-- @param session Session object
|
||||
-- @param type Authentication type
|
||||
-- @param entity Authentication enttity (username)
|
||||
-- @param key Authentication key (password)
|
||||
-- @return boolean status
|
||||
function authenticate(session, type, entity, key)
|
||||
if not type then
|
||||
session.user = nil
|
||||
return true
|
||||
elseif type == "plain" then
|
||||
local pwe = nixio.getsp and nixio.getsp(entity) or nixio.getpw(entity)
|
||||
local pwh = pwe and (pwe.pwdp or pwe.passwd)
|
||||
if not pwh or #pwh < 1 or nixio.crypt(key, pwh) ~= pwh then
|
||||
return nil
|
||||
else
|
||||
session.user = entity
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,2 +0,0 @@
|
|||
include ../../build/config.mk
|
||||
include ../../build/module.mk
|
|
@ -1,75 +0,0 @@
|
|||
LuCId Network Superserver in Lua
|
||||
|
||||
*** Abstract ***
|
||||
LuCId is a network superserver written in Lua based on the nixio POSIX library.
|
||||
It supports IPv4, IPv6, TLS, asynchronous and synchronous IO and can be extended
|
||||
to handle any kind of IO events on file descriptors. LuCId is also able to
|
||||
generate RSA private keys and self-signed certificates on demand if the px5g
|
||||
keymaster library is available. Both nixio and px5g are libraries created
|
||||
by the LuCI developers.
|
||||
|
||||
|
||||
*** Configuration ***
|
||||
LuCId uses the UCI Universal Configuration Interface as configuration backend.
|
||||
|
||||
There are 4 types of configuration sections and one named section defined:
|
||||
The main section of type "lucid" defines the basic framework parameters of LuCId
|
||||
These include:
|
||||
* pollinterval: Internal polling interval
|
||||
* threadlimit: Overall maximum number of child processes
|
||||
* daemonize: Whether to daemonize at startup
|
||||
* debug: Whether to enable debug output in syslog
|
||||
|
||||
|
||||
The "tcpserver" section type provides the framework for TCP servers:
|
||||
Parameters:
|
||||
* entrypoint: Lua module entrypoint (provides a prepare_daemon function)
|
||||
|
||||
The "daemon" sections define instances of servers.
|
||||
Parameters may include:
|
||||
* slave: Server slave
|
||||
* publisher: Publishers to be served by this daemon
|
||||
* enabled: Flag (0/1) whether this daemon should be started
|
||||
* address: List of ports / addresses to be bound too, if applicable
|
||||
* encryption: Flag (disabled/enabled) whether to enforce encryption
|
||||
* tls: Reference to the TLS configuration section to use
|
||||
|
||||
The "...Publisher" sections define services to be published through daemons.
|
||||
Publishers definitions should be daemon and protocol independent whenever
|
||||
possible. Publishers should also implement access restrictions for certain
|
||||
network interfaces and for specified UNIX user accounts.
|
||||
Publishers usually define but are not required to use the following Parameters:
|
||||
* name: Published Name
|
||||
* physical: Physical source path
|
||||
* virtual: Virtual resource path
|
||||
* domain: Any kind of domain or realm specification
|
||||
* read: ACL containing entities allowed to read the given resource
|
||||
* write: -"-
|
||||
* exec: -"-
|
||||
|
||||
The "tls" sections describe TLS security specifications for TCP servers.
|
||||
Parameters:
|
||||
* key: Private Key file
|
||||
* cert: Certificate file
|
||||
* type: Type of certificate and key files (pem, asn1)
|
||||
* generate: Flag (0/1) to determine whether LuCId should generate
|
||||
keys and self-signed certificates if the certificate is not available and
|
||||
the px5g RSA Keymaster is available
|
||||
|
||||
|
||||
|
||||
*** Workflow ***
|
||||
In the preparation phase LuCId loads its configuration using the specification
|
||||
given above and prepares its servers, daemons and publishers. It also allocates
|
||||
resources such as binding sockets or preparing encryption credentials.
|
||||
If everything could be setup correctly LuCId will daemonize - if requested. If
|
||||
any errors occur in the preparation phase, LuCId will write to the system logger
|
||||
and exit.
|
||||
|
||||
After daemonizing the main process is responsible for keeping a list of
|
||||
file descriptors that LuCId is polling regularly to handle incoming data events.
|
||||
Data events are for example new TCP connection attempts which could cause the
|
||||
superserver to fork a new process and invoke a registered handler.
|
||||
|
||||
Whenever a sub-process is about to be generate LuCId checks if given resource
|
||||
limits are still met.
|
|
@ -1,75 +0,0 @@
|
|||
config lucid main
|
||||
option pollinterval 15000
|
||||
option daemon 1
|
||||
option debug 1
|
||||
list supports tcpserver
|
||||
list supports server
|
||||
|
||||
config DirectoryPublisher webroot
|
||||
option name 'Webserver Share'
|
||||
option physical host/www
|
||||
option virtual ''
|
||||
option domain ''
|
||||
|
||||
config LuciWebPublisher luciweb
|
||||
option name 'LuCI Webapplication'
|
||||
option physical ''
|
||||
list virtual /luci
|
||||
option domain ''
|
||||
option home 1
|
||||
|
||||
config RPCPublisher mainrpc
|
||||
option namespace 'luci.lucid.rpc'
|
||||
list export system
|
||||
list export ruci
|
||||
list exec ':lo'
|
||||
list exec 'root'
|
||||
|
||||
config tcpserver httpd
|
||||
option entrypoint "luci.lucid.http"
|
||||
list supports DirectoryPublisher
|
||||
list supports LuciWebPublisher
|
||||
|
||||
config tcpserver rpcd
|
||||
option entrypoint "luci.lucid.rpc"
|
||||
list supports RPCPublisher
|
||||
|
||||
config daemon http
|
||||
option slave httpd
|
||||
list address 8080
|
||||
list publisher webroot
|
||||
list publisher luciweb
|
||||
option enabled 1
|
||||
|
||||
config daemon https
|
||||
option slave httpd
|
||||
list address 4443
|
||||
list publisher webroot
|
||||
list publisher luciweb
|
||||
option enabled 1
|
||||
option encryption enable
|
||||
option tls sdk_tls
|
||||
|
||||
config tls sdk_tls
|
||||
option generate 1
|
||||
option key /tmp/lucid-tls.key
|
||||
option cert /tmp/lucid-tls.cert
|
||||
option type asn1
|
||||
|
||||
config daemon rpc
|
||||
option slave rpcd
|
||||
list address 12900
|
||||
list publisher mainrpc
|
||||
option enabled 1
|
||||
|
||||
config 'daemon' 'splashr'
|
||||
option 'slave' 'httpd'
|
||||
list 'address' '8082'
|
||||
list 'publisher' 'splashredir'
|
||||
option 'enabled' '1'
|
||||
|
||||
config 'Redirector' 'splashredir'
|
||||
option 'name' 'Splashd'
|
||||
option 'virtual' '/'
|
||||
option 'physical' ':80/luci/splash'
|
||||
|
|
@ -1,348 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Development Framework
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]
|
||||
|
||||
local nixio = require "nixio"
|
||||
local table = require "table"
|
||||
local uci = require "luci.model.uci"
|
||||
local os = require "os"
|
||||
local io = require "io"
|
||||
|
||||
local pairs, require, pcall, assert, type = pairs, require, pcall, assert, type
|
||||
local ipairs, tonumber, collectgarbage = ipairs, tonumber, collectgarbage
|
||||
|
||||
|
||||
module "luci.lucid"
|
||||
|
||||
local slaves = {}
|
||||
local pollt = {}
|
||||
local tickt = {}
|
||||
local tpids = {}
|
||||
local tcount = 0
|
||||
local ifaddrs = nixio.getifaddrs()
|
||||
|
||||
cursor = uci.cursor()
|
||||
state = uci.cursor_state()
|
||||
UCINAME = "lucid"
|
||||
|
||||
local cursor = cursor
|
||||
local state = state
|
||||
local UCINAME = UCINAME
|
||||
local SSTATE = "/tmp/.lucid_store"
|
||||
|
||||
|
||||
--- Starts a new LuCId superprocess.
|
||||
function start()
|
||||
state:revert(UCINAME, "main")
|
||||
|
||||
prepare()
|
||||
|
||||
local detach = cursor:get(UCINAME, "main", "daemonize")
|
||||
if detach == "1" then
|
||||
local stat, code, msg = daemonize()
|
||||
if not stat then
|
||||
nixio.syslog("crit", "Unable to detach process: " .. msg .. "\n")
|
||||
ox.exit(2)
|
||||
end
|
||||
end
|
||||
|
||||
state:set(UCINAME, "main", "pid", nixio.getpid())
|
||||
state:save(UCINAME)
|
||||
|
||||
run()
|
||||
end
|
||||
|
||||
--- Returns the PID of the currently active LuCId process.
|
||||
function running()
|
||||
local pid = tonumber(state:get(UCINAME, "main", "pid"))
|
||||
return pid and nixio.kill(pid, 0) and pid
|
||||
end
|
||||
|
||||
--- Stops any running LuCId superprocess.
|
||||
function stop()
|
||||
local pid = tonumber(state:get(UCINAME, "main", "pid"))
|
||||
if pid then
|
||||
return nixio.kill(pid, nixio.const.SIGTERM)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Prepares the slaves, daemons and publishers, allocate resources.
|
||||
function prepare()
|
||||
local debug = tonumber((cursor:get(UCINAME, "main", "debug")))
|
||||
|
||||
nixio.openlog("lucid", "pid", "perror")
|
||||
if debug ~= 1 then
|
||||
nixio.setlogmask("warning")
|
||||
end
|
||||
|
||||
cursor:foreach(UCINAME, "daemon", function(config)
|
||||
if config.enabled ~= "1" then
|
||||
return
|
||||
end
|
||||
|
||||
local key = config[".name"]
|
||||
if not config.slave then
|
||||
nixio.syslog("crit", "Daemon "..key.." is missing a slave\n")
|
||||
os.exit(1)
|
||||
else
|
||||
nixio.syslog("info", "Initializing daemon " .. key)
|
||||
end
|
||||
|
||||
state:revert(UCINAME, key)
|
||||
|
||||
local daemon, code, err = prepare_daemon(config)
|
||||
if daemon then
|
||||
state:set(UCINAME, key, "status", "started")
|
||||
nixio.syslog("info", "Prepared daemon " .. key)
|
||||
else
|
||||
state:set(UCINAME, key, "status", "error")
|
||||
state:set(UCINAME, key, "error", err)
|
||||
nixio.syslog("err", "Failed to initialize daemon "..key..": "..
|
||||
err .. "\n")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Run the superprocess if prepared before.
|
||||
-- This main function of LuCId will wait for events on given file descriptors.
|
||||
function run()
|
||||
local pollint = tonumber((cursor:get(UCINAME, "main", "pollinterval")))
|
||||
local threadlimit = tonumber((cursor:get(UCINAME, "main", "threadlimit")))
|
||||
|
||||
while true do
|
||||
local stat, code = nixio.poll(pollt, pollint)
|
||||
|
||||
if stat and stat > 0 then
|
||||
local ok = false
|
||||
for _, polle in ipairs(pollt) do
|
||||
if polle.revents ~= 0 and polle.handler then
|
||||
ok = ok or polle.handler(polle)
|
||||
end
|
||||
end
|
||||
if not ok then
|
||||
-- Avoid high CPU usage if thread limit is reached
|
||||
nixio.nanosleep(0, 100000000)
|
||||
end
|
||||
elseif stat == 0 then
|
||||
ifaddrs = nixio.getifaddrs()
|
||||
end
|
||||
|
||||
for _, cb in ipairs(tickt) do
|
||||
cb()
|
||||
end
|
||||
|
||||
local pid, stat, code = nixio.wait(-1, "nohang")
|
||||
while pid and pid > 0 do
|
||||
nixio.syslog("info", "Buried thread: " .. pid)
|
||||
if tpids[pid] then
|
||||
tcount = tcount - 1
|
||||
if tpids[pid] ~= true then
|
||||
tpids[pid](pid, stat, code)
|
||||
end
|
||||
tpids[pid] = nil
|
||||
end
|
||||
pid, stat, code = nixio.wait(-1, "nohang")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Add a file descriptor for the main loop and associate handler functions.
|
||||
-- @param polle Table containing: {fd = FILE DESCRIPTOR, events = POLL EVENTS,
|
||||
-- handler = EVENT HANDLER CALLBACK}
|
||||
-- @see unregister_pollfd
|
||||
-- @return boolean status
|
||||
function register_pollfd(polle)
|
||||
pollt[#pollt+1] = polle
|
||||
return true
|
||||
end
|
||||
|
||||
--- Unregister a file desciptor and associate handler from the main loop.
|
||||
-- @param polle Poll descriptor
|
||||
-- @see register_pollfd
|
||||
-- @return boolean status
|
||||
function unregister_pollfd(polle)
|
||||
for k, v in ipairs(pollt) do
|
||||
if v == polle then
|
||||
table.remove(pollt, k)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Close all registered file descriptors from main loop.
|
||||
-- This is useful for forked child processes.
|
||||
function close_pollfds()
|
||||
for k, v in ipairs(pollt) do
|
||||
if v.fd and v.fd.close then
|
||||
v.fd:close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Register a tick function that will be called at each cycle of the main loop.
|
||||
-- @param cb Callback
|
||||
-- @see unregister_tick
|
||||
-- @return boolean status
|
||||
function register_tick(cb)
|
||||
tickt[#tickt+1] = cb
|
||||
return true
|
||||
end
|
||||
|
||||
--- Unregister a tick function from the main loop.
|
||||
-- @param cb Callback
|
||||
-- @see register_tick
|
||||
-- @return boolean status
|
||||
function unregister_tick(cb)
|
||||
for k, v in ipairs(tickt) do
|
||||
if v == cb then
|
||||
table.remove(tickt, k)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Tests whether a given number of processes can be created.
|
||||
-- @oaram num Processes to be created
|
||||
-- @return boolean status
|
||||
function try_process(num)
|
||||
local threadlimit = tonumber((cursor:get(UCINAME, "main", "threadlimit")))
|
||||
return not threadlimit or (threadlimit - tcount) >= (num or 1)
|
||||
end
|
||||
|
||||
--- Create a new child process from a Lua function and assign a destructor.
|
||||
-- @param threadcb main function of the new process
|
||||
-- @param waitcb destructor callback
|
||||
-- @return process identifier or nil, error code, error message
|
||||
function create_process(threadcb, waitcb)
|
||||
local threadlimit = tonumber(cursor:get(UCINAME, "main", "threadlimit"))
|
||||
if threadlimit and tcount >= threadlimit then
|
||||
nixio.syslog("warning", "Cannot create thread: process limit reached")
|
||||
return nil
|
||||
else
|
||||
collectgarbage("collect")
|
||||
end
|
||||
local pid, code, err = nixio.fork()
|
||||
if pid and pid ~= 0 then
|
||||
nixio.syslog("info", "Created thread: " .. pid)
|
||||
tpids[pid] = waitcb or true
|
||||
tcount = tcount + 1
|
||||
elseif pid == 0 then
|
||||
local code = threadcb()
|
||||
os.exit(code)
|
||||
else
|
||||
nixio.syslog("err", "Unable to fork(): " .. err)
|
||||
end
|
||||
return pid, code, err
|
||||
end
|
||||
|
||||
--- Prepare a daemon from a given configuration table.
|
||||
-- @param config Configuration data.
|
||||
-- @return boolean status or nil, error code, error message
|
||||
function prepare_daemon(config)
|
||||
nixio.syslog("info", "Preparing daemon " .. config[".name"])
|
||||
local modname = cursor:get(UCINAME, config.slave)
|
||||
if not modname then
|
||||
return nil, -1, "invalid slave"
|
||||
end
|
||||
|
||||
local stat, module = pcall(require, _NAME .. "." .. modname)
|
||||
if not stat or not module.prepare_daemon then
|
||||
return nil, -2, "slave type not supported"
|
||||
end
|
||||
|
||||
config.slave = prepare_slave(config.slave)
|
||||
|
||||
return module.prepare_daemon(config, _M)
|
||||
end
|
||||
|
||||
--- Prepare a slave.
|
||||
-- @param name slave name
|
||||
-- @return table containing slave module and configuration or nil, error message
|
||||
function prepare_slave(name)
|
||||
local slave = slaves[name]
|
||||
if not slave then
|
||||
local config = cursor:get_all(UCINAME, name)
|
||||
|
||||
local stat, module = pcall(require, config and config.entrypoint)
|
||||
if stat then
|
||||
slave = {module = module, config = config}
|
||||
end
|
||||
end
|
||||
|
||||
if slave then
|
||||
return slave
|
||||
else
|
||||
return nil, module
|
||||
end
|
||||
end
|
||||
|
||||
--- Return a list of available network interfaces on the host.
|
||||
-- @return table returned by nixio.getifaddrs()
|
||||
function get_interfaces()
|
||||
return ifaddrs
|
||||
end
|
||||
|
||||
--- Revoke process privileges.
|
||||
-- @param user new user name or uid
|
||||
-- @param group new group name or gid
|
||||
-- @return boolean status or nil, error code, error message
|
||||
function revoke_privileges(user, group)
|
||||
if nixio.getuid() == 0 then
|
||||
return nixio.setgid(group) and nixio.setuid(user)
|
||||
end
|
||||
end
|
||||
|
||||
--- Return a secure UCI cursor.
|
||||
-- @return UCI cursor
|
||||
function securestate()
|
||||
local stat = nixio.fs.stat(SSTATE) or {}
|
||||
local uid = nixio.getuid()
|
||||
if stat.type ~= "dir" or (stat.modedec % 100) ~= 0 or stat.uid ~= uid then
|
||||
nixio.fs.remover(SSTATE)
|
||||
if not nixio.fs.mkdir(SSTATE, 700) then
|
||||
local errno = nixio.errno()
|
||||
nixio.syslog("err", "Integrity check on secure state failed!")
|
||||
return nil, errno, nixio.perror(errno)
|
||||
end
|
||||
end
|
||||
|
||||
return uci.cursor(nil, SSTATE)
|
||||
end
|
||||
|
||||
--- Daemonize the process.
|
||||
-- @return boolean status or nil, error code, error message
|
||||
function daemonize()
|
||||
if nixio.getppid() == 1 then
|
||||
return
|
||||
end
|
||||
|
||||
local pid, code, msg = nixio.fork()
|
||||
if not pid then
|
||||
return nil, code, msg
|
||||
elseif pid > 0 then
|
||||
os.exit(0)
|
||||
end
|
||||
|
||||
nixio.setsid()
|
||||
nixio.chdir("/")
|
||||
|
||||
local devnull = nixio.open("/dev/null", nixio.open_flags("rdwr"))
|
||||
nixio.dup(devnull, nixio.stdin)
|
||||
nixio.dup(devnull, nixio.stdout)
|
||||
nixio.dup(devnull, nixio.stderr)
|
||||
|
||||
return true
|
||||
end
|
|
@ -1,254 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Development Framework
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]
|
||||
|
||||
local os = require "os"
|
||||
local fs = require "nixio.fs"
|
||||
local nixio = require "nixio"
|
||||
local lucid = require "luci.lucid"
|
||||
|
||||
local ipairs, type, require, setmetatable = ipairs, type, require, setmetatable
|
||||
local pairs, print, tostring, unpack = pairs, print, tostring, unpack
|
||||
local pcall = pcall
|
||||
|
||||
module "luci.lucid.tcpserver"
|
||||
|
||||
local cursor = lucid.cursor
|
||||
local UCINAME = lucid.UCINAME
|
||||
|
||||
local tcpsockets = {}
|
||||
|
||||
--- Prepare a daemon and allocate its resources. (superserver callback)
|
||||
-- @param config configuration table
|
||||
-- @param server LuCId basemodule
|
||||
-- @return binary data
|
||||
function prepare_daemon(config, server)
|
||||
nixio.syslog("info", "Preparing TCP-Daemon " .. config[".name"])
|
||||
if type(config.address) ~= "table" then
|
||||
config.address = {config.address}
|
||||
end
|
||||
|
||||
local sockets, socket, code, err = {}
|
||||
local sopts = {reuseaddr = 1}
|
||||
for _, addr in ipairs(config.address) do
|
||||
local host, port = addr:match("(.-):?([^:]*)")
|
||||
if not host then
|
||||
nixio.syslog("err", "Invalid address: " .. addr)
|
||||
return nil, -5, "invalid address format"
|
||||
elseif #host == 0 then
|
||||
host = nil
|
||||
end
|
||||
socket, code, err = prepare_socket(config.family, host, port, sopts)
|
||||
if socket then
|
||||
sockets[#sockets+1] = socket
|
||||
end
|
||||
end
|
||||
|
||||
nixio.syslog("info", "Sockets bound for " .. config[".name"])
|
||||
|
||||
if #sockets < 1 then
|
||||
return nil, -6, "no sockets bound"
|
||||
end
|
||||
|
||||
nixio.syslog("info", "Preparing publishers for " .. config[".name"])
|
||||
|
||||
local publisher = {}
|
||||
for k, pname in ipairs(config.publisher) do
|
||||
local pdata = cursor:get_all(UCINAME, pname)
|
||||
if pdata then
|
||||
publisher[#publisher+1] = pdata
|
||||
else
|
||||
nixio.syslog("err", "Publisher " .. pname .. " not found")
|
||||
end
|
||||
end
|
||||
|
||||
nixio.syslog("info", "Preparing TLS for " .. config[".name"])
|
||||
|
||||
local tls = prepare_tls(config.tls)
|
||||
if not tls and config.encryption == "enable" then
|
||||
for _, s in ipairs(sockets) do
|
||||
s:close()
|
||||
end
|
||||
return nil, -4, "Encryption requested, but no TLS context given"
|
||||
end
|
||||
|
||||
nixio.syslog("info", "Invoking daemon factory for " .. config[".name"])
|
||||
local handler, err = config.slave.module.factory(publisher, config)
|
||||
if not handler then
|
||||
for _, s in ipairs(sockets) do
|
||||
s:close()
|
||||
end
|
||||
return nil, -3, err
|
||||
else
|
||||
local pollin = nixio.poll_flags("in")
|
||||
for _, s in ipairs(sockets) do
|
||||
server.register_pollfd({
|
||||
fd = s,
|
||||
events = pollin,
|
||||
revents = 0,
|
||||
handler = accept,
|
||||
accept = handler,
|
||||
config = config,
|
||||
publisher = publisher,
|
||||
tls = tls
|
||||
})
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--- Accept a new TCP connection. (server callback)
|
||||
-- @param polle Poll descriptor
|
||||
-- @return handler process id or nil, error code, error message
|
||||
function accept(polle)
|
||||
if not lucid.try_process() then
|
||||
return false
|
||||
end
|
||||
local socket, host, port = polle.fd:accept()
|
||||
if not socket then
|
||||
return nixio.syslog("warning", "accept() failed: " .. port)
|
||||
end
|
||||
|
||||
socket:setblocking(true)
|
||||
|
||||
local function thread()
|
||||
lucid.close_pollfds()
|
||||
local inst = setmetatable({
|
||||
host = host, port = port, interfaces = lucid.get_interfaces()
|
||||
}, {__index = polle})
|
||||
if polle.config.encryption then
|
||||
socket = polle.tls:create(socket)
|
||||
if not socket:accept() then
|
||||
socket:close()
|
||||
return nixio.syslog("warning", "TLS handshake failed: " .. host)
|
||||
end
|
||||
end
|
||||
|
||||
return polle.accept(socket, inst)
|
||||
end
|
||||
|
||||
local stat = {lucid.create_process(thread)}
|
||||
socket:close()
|
||||
return unpack(stat)
|
||||
end
|
||||
|
||||
--- Prepare a TCP server socket.
|
||||
-- @param family protocol family ["inetany", "inet6", "inet"]
|
||||
-- @param host host
|
||||
-- @param port port
|
||||
-- @param opts table of socket options
|
||||
-- @param backlog socket backlog
|
||||
-- @return socket, final socket family
|
||||
function prepare_socket(family, host, port, opts, backlog)
|
||||
nixio.syslog("info", "Preparing socket for port " .. port)
|
||||
backlog = backlog or 1024
|
||||
family = family or "inetany"
|
||||
opts = opts or {}
|
||||
|
||||
local inetany = family == "inetany"
|
||||
family = inetany and "inet6" or family
|
||||
|
||||
local socket, code, err = nixio.socket(family, "stream")
|
||||
if not socket and inetany then
|
||||
family = "inet"
|
||||
socket, code, err = nixio.socket(family, "stream")
|
||||
end
|
||||
|
||||
if not socket then
|
||||
return nil, code, err
|
||||
end
|
||||
|
||||
for k, v in pairs(opts) do
|
||||
socket:setsockopt("socket", k, v)
|
||||
end
|
||||
|
||||
local stat, code, err = socket:bind(host, port)
|
||||
if not stat then
|
||||
return nil, code, err
|
||||
end
|
||||
|
||||
stat, code, err = socket:listen(backlog)
|
||||
if not stat then
|
||||
return nil, code, err
|
||||
end
|
||||
|
||||
socket:setblocking(false)
|
||||
|
||||
return socket, family
|
||||
end
|
||||
|
||||
--- Prepare a TLS server context and load keys and certificates.
|
||||
-- May invoke px5g to create keys and certificate on demand if available.
|
||||
-- @param tlskey TLS configuration identifier
|
||||
-- @return TLS server conext or nil
|
||||
function prepare_tls(tlskey)
|
||||
local tls
|
||||
if nixio.tls and tlskey and cursor:get(UCINAME, tlskey) then
|
||||
tls = nixio.tls("server")
|
||||
|
||||
local make = cursor:get(UCINAME, tlskey, "generate") == "1"
|
||||
local key = cursor:get(UCINAME, tlskey, "key")
|
||||
local xtype = make and "asn1" or cursor:get(UCINAME, tlskey, "type")
|
||||
local cert = cursor:get(UCINAME, tlskey, "cert")
|
||||
local ciphers = cursor:get(UCINAME, tlskey, "ciphers")
|
||||
|
||||
if make and (not fs.access(key) or not fs.access(cert)) then
|
||||
local CN = cursor:get(UCINAME, tlskey, "CN")
|
||||
local O = cursor:get(UCINAME, tlskey, "O")
|
||||
local bits = 2048
|
||||
|
||||
local data = {
|
||||
CN = CN or nixio.uname().nodename,
|
||||
O = not O and "LuCId Keymaster" or #O > 0 and O
|
||||
}
|
||||
|
||||
local stat, px5g = pcall(require, "px5g")
|
||||
if not stat then
|
||||
return nixio.syslog("err", "Unable to load PX5G Keymaster")
|
||||
end
|
||||
|
||||
nixio.syslog("warning", "PX5G: Generating private key")
|
||||
local rk = px5g.genkey(bits)
|
||||
local keyfile = nixio.open(key, "w", 600)
|
||||
if not rk or not keyfile or not keyfile:writeall(rk:asn1()) then
|
||||
return nixio.syslog("err", "Unable to generate private key")
|
||||
end
|
||||
keyfile:close()
|
||||
|
||||
nixio.syslog("warning", "PX5G: Generating self-signed certificate")
|
||||
if not fs.writefile(cert, rk:create_selfsigned(data,
|
||||
os.time(), os.time() + 3600 * 24 * 366 * 15)) then
|
||||
return nixio.syslog("err", "Unable to generate certificate")
|
||||
end
|
||||
end
|
||||
|
||||
if cert then
|
||||
if not tls:set_cert(cert, xtype) then
|
||||
nixio.syslog("err", "Unable to load certificate: " .. cert)
|
||||
end
|
||||
end
|
||||
if key then
|
||||
if not tls:set_key(key, xtype) then
|
||||
nixio.syslog("err", "Unable to load private key: " .. key)
|
||||
end
|
||||
end
|
||||
|
||||
if ciphers then
|
||||
if type(ciphers) == "table" then
|
||||
ciphers = table.concat(ciphers, ":")
|
||||
end
|
||||
tls:set_ciphers(ciphers)
|
||||
end
|
||||
end
|
||||
return tls
|
||||
end
|
|
@ -1,52 +0,0 @@
|
|||
config lucid main
|
||||
option pollinterval 15000
|
||||
option threadlimit 10
|
||||
option daemonize 1
|
||||
option debug 0
|
||||
list supports tcpserver
|
||||
list supports server
|
||||
|
||||
config DirectoryPublisher webroot
|
||||
option name 'Webserver Share'
|
||||
option physical /www
|
||||
option virtual ''
|
||||
option domain ''
|
||||
|
||||
config LuciWebPublisher luciweb
|
||||
option name 'LuCI Webapplication'
|
||||
option physical ''
|
||||
option home 1
|
||||
list virtual /luci
|
||||
list virtual /cgi-bin/luci
|
||||
option domain ''
|
||||
|
||||
config tcpserver httpd
|
||||
option entrypoint "luci.lucid.http"
|
||||
list supports DirectoryPublisher
|
||||
list supports LuciWebPublisher
|
||||
|
||||
config daemon http
|
||||
option slave httpd
|
||||
list address 80
|
||||
list publisher webroot
|
||||
list publisher luciweb
|
||||
option nokeepalive 1
|
||||
option memlimit 1572864
|
||||
option enabled 1
|
||||
|
||||
config daemon https
|
||||
option slave httpd
|
||||
list address 443
|
||||
list publisher webroot
|
||||
list publisher luciweb
|
||||
option nokeepalive 1
|
||||
option memlimit 1572864
|
||||
option enabled 1
|
||||
option tls maincert
|
||||
option encryption enable
|
||||
|
||||
config tls maincert
|
||||
option key /etc/nixio/rsa_main.der
|
||||
option cert /etc/nixio/cert_main.der
|
||||
option type asn1
|
||||
option generate 1
|
|
@ -1,43 +0,0 @@
|
|||
#!/bin/sh /etc/rc.common
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
NAME=lucid
|
||||
DESC="LuCId superserver"
|
||||
START=49
|
||||
|
||||
test -x $DAEMON || exit 0
|
||||
set -e
|
||||
|
||||
start() {
|
||||
echo -n "Starting $DESC: $NAME"
|
||||
lua -lluci.lucid -e 'luci.lucid.start()'
|
||||
echo "."
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo -n "Stopping $DESC: $NAME"
|
||||
lua -lluci.lucid -e 'luci.lucid.stop()'
|
||||
echo "."
|
||||
}
|
||||
|
||||
restart() {
|
||||
# echo -n "Restarting $DESC: $NAME... "
|
||||
# start-stop-daemon -K -s HUP -q -x $DAEMON
|
||||
# echo "done."
|
||||
stop
|
||||
sleep 3
|
||||
start
|
||||
}
|
||||
|
||||
reload() {
|
||||
#
|
||||
# If the daemon can reload its config files on the fly
|
||||
# for example by sending it SIGHUP, do it here.
|
||||
#
|
||||
# If the daemon responds to changes in its config file
|
||||
# directly anyway, make this a do-nothing entry.
|
||||
#
|
||||
# echo -n "Reloading $DESC configuration... "
|
||||
# start-stop-daemon -K -s 1 -q -x $DAEMON
|
||||
# echo "done."
|
||||
restart
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
The Oxygen Icon Theme
|
||||
Copyright (C) 2007 David Vignoni <david@icon-king.com>
|
||||
Copyright (C) 2007 Johann Ollivier Lapeyre <johann@oxygen-icons.org>
|
||||
Copyright (C) 2007 Kenneth Wimer <kwwii@bootsplash.org>
|
||||
Copyright (C) 2007 Nuno Fernades Pinheiro <nf.pinheiro@gmail.com>
|
||||
Copyright (C) 2007 Riccardo Iaconelli <riccardo@oxygen-icons.org>
|
||||
Copyright (C) 2007 David Miller <miller@oxygen-icons.org>
|
||||
|
||||
and others
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Clarification:
|
||||
|
||||
The GNU Lesser General Public License or LGPL is written for
|
||||
software libraries in the first place. We expressly want the LGPL to
|
||||
be valid for this artwork library too.
|
||||
|
||||
KDE Oxygen theme icons is a special kind of software library, it is an
|
||||
artwork library, it's elements can be used in a Graphical User Interface, or
|
||||
GUI.
|
||||
|
||||
Source code, for this library means:
|
||||
- where they exist, SVG;
|
||||
- otherwise, if applicable, the multi-layered formats xcf or psd, or
|
||||
otherwise png.
|
||||
|
||||
The LGPL in some sections obliges you to make the files carry
|
||||
notices. With images this is in some cases impossible or hardly useful.
|
||||
|
||||
With this library a notice is placed at a prominent place in the directory
|
||||
containing the elements. You may follow this practice.
|
||||
|
||||
The exception in section 5 of the GNU Lesser General Public License covers
|
||||
the use of elements of this art library in a GUI.
|
||||
|
||||
kde-artists [at] kde.org
|
|
@ -1,2 +0,0 @@
|
|||
include ../../build/config.mk
|
||||
include ../../build/module.mk
|
Binary file not shown.
Before Width: | Height: | Size: 645 B |
Binary file not shown.
Before Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.1 KiB |
|
@ -1,26 +0,0 @@
|
|||
fieldset.dbbox {
|
||||
float: left;
|
||||
margin: 1em;
|
||||
padding: 0.5em;
|
||||
background: #eeeeee;
|
||||
border: 1px solid #cccccc;
|
||||
border-radius: 5px;
|
||||
-khtml-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-o-border-radius: 5px;
|
||||
}
|
||||
|
||||
fieldset.dbbox h2 {
|
||||
background: url(icons32/folder.png) no-repeat right;
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
table.dbstattbl {
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.dbstattbl th {
|
||||
margin-right: 0.5em;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Development Framework
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local req = require
|
||||
module "luci.controller.niu.dashboard"
|
||||
|
||||
function index()
|
||||
local uci = require "luci.model.uci"
|
||||
|
||||
local root = node()
|
||||
if not root.lock then
|
||||
root.target = alias("niu")
|
||||
root.index = true
|
||||
end
|
||||
|
||||
entry({"niu"}, alias("niu", "dashboard"), "NIU", 10)
|
||||
entry({"niu", "dashboard"}, call("dashboard"), "Dashboard", 1).css =
|
||||
"niu.css"
|
||||
end
|
||||
|
||||
local require = req
|
||||
|
||||
function dashboard()
|
||||
local dsp = require "luci.dispatcher"
|
||||
local tpl = require "luci.template"
|
||||
local utl = require "luci.util"
|
||||
local uci = require "luci.model.uci"
|
||||
|
||||
local nds = dsp.node("niu").nodes
|
||||
tpl.render("niu/dashboard", {utl = utl, nodes = nds, dsp = dsp, tpl = tpl})
|
||||
end
|
|
@ -1,42 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Development Framework
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
module "luci.controller.niu.network"
|
||||
|
||||
function index()
|
||||
local toniu = {on_success_to={"niu"}}
|
||||
|
||||
local e = entry({"niu", "network"}, alias("niu"), "Network", 10)
|
||||
e.niu_dbtemplate = "niu/network"
|
||||
e.niu_dbtasks = true
|
||||
e.niu_dbicon = "icons32/network-workgroup.png"
|
||||
|
||||
entry({"niu", "network", "wan"},
|
||||
cbi("niu/network/wan", toniu), "Configure Internet Connection", 1)
|
||||
|
||||
entry({"niu", "network", "lan"},
|
||||
cbi("niu/network/lan", toniu), "Configure Local Network", 2)
|
||||
|
||||
uci.inst_state:foreach("dhcp", "dhcp", function(s)
|
||||
if s.interface == "lan" and s.ignore ~= "1" then
|
||||
entry({"niu", "network", "assign"}, cbi("niu/network/assign",
|
||||
toniu), "Manage Address Assignment", 30)
|
||||
end
|
||||
end)
|
||||
|
||||
if fs.access("/etc/config/ddns") then
|
||||
entry({"niu", "network", "ddns"}, cbi("niu/network/ddns", toniu),
|
||||
"Configure Dynamic-DNS names", 60)
|
||||
end
|
||||
end
|
|
@ -1,265 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Development Framework
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local require, pairs, unpack, tonumber = require, pairs, unpack, tonumber
|
||||
module "luci.controller.niu.system"
|
||||
|
||||
function index()
|
||||
local toniu = {on_success_to={"niu"}}
|
||||
|
||||
local e = entry({"niu", "system"}, alias("niu"), "System", 40)
|
||||
e.niu_dbtemplate = "niu/system"
|
||||
e.niu_dbtasks = true
|
||||
e.niu_dbicon = "icons32/preferences-system.png"
|
||||
|
||||
entry({"niu", "system", "general"},
|
||||
cbi("niu/system/general", toniu), "Configure Device", 1)
|
||||
|
||||
entry({"niu", "system", "backup"}, call("backup"), "Backup or Restore Settings", 2)
|
||||
entry({"niu", "system", "upgrade"}, call("upgrade"), "Upgrade Firmware", 30)
|
||||
end
|
||||
|
||||
function backup()
|
||||
local dsp = require "luci.dispatcher"
|
||||
local os, io = require "os", require "io"
|
||||
local uci = require "luci.model.uci".inst
|
||||
local nixio, nutl = require "nixio", require "nixio.util"
|
||||
local fs = require "nixio.fs"
|
||||
local http = require "luci.http"
|
||||
local tpl = require "luci.template"
|
||||
|
||||
local restore_fpi
|
||||
http.setfilehandler(
|
||||
function(meta, chunk, eof)
|
||||
if not restore_fpi then
|
||||
restore_fpi = io.popen("tar -xzC/ >/dev/null 2>&1", "w")
|
||||
end
|
||||
if chunk then
|
||||
restore_fpi:write(chunk)
|
||||
end
|
||||
if eof then
|
||||
restore_fpi:close()
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
local reset_avail = (fs.readfile("/proc/mtd") or ""):find('"rootfs_data"')
|
||||
local upload = http.formvalue("archive")
|
||||
local backup = http.formvalue("backup")
|
||||
local reset = reset_avail and http.formvalue("reset")
|
||||
local backup_cmd = "tar -cz %s 2>/dev/null"
|
||||
|
||||
if http.formvalue("cancel") then
|
||||
return http.redirect(dsp.build_url("niu"))
|
||||
end
|
||||
|
||||
if backup then
|
||||
local call = {"/bin/tar", "-cz"}
|
||||
for k, v in pairs(uci:get_all("luci", "flash_keep")) do
|
||||
if k:byte() ~= 46 then -- k[1] ~= "."
|
||||
nutl.consume(fs.glob(v), call)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
http.header(
|
||||
'Content-Disposition', 'attachment; filename="backup-%s-%s.tar.gz"' % {
|
||||
nixio.uname().nodename, os.date("%Y-%m-%d")
|
||||
}
|
||||
)
|
||||
http.prepare_content("application/x-targz")
|
||||
|
||||
|
||||
local fdin, fdout = nixio.pipe()
|
||||
local devnull = nixio.open("/dev/null", "r+")
|
||||
local proc = nixio.fork()
|
||||
|
||||
if proc == 0 then
|
||||
fdin:close()
|
||||
nixio.dup(devnull, nixio.stdin)
|
||||
nixio.dup(devnull, nixio.stderr)
|
||||
nixio.dup(fdout, nixio.stdout)
|
||||
nixio.exec(unpack(call))
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
fdout:close()
|
||||
http.splice(fdin)
|
||||
http.close()
|
||||
elseif (upload and #upload > 0) or reset then
|
||||
tpl.render("niu/system/reboot")
|
||||
if nixio.fork() == 0 then
|
||||
nixio.nanosleep(1)
|
||||
if reset then
|
||||
nixio.execp("mtd", "-r", "erase", "rootfs_data")
|
||||
else
|
||||
nixio.execp("reboot")
|
||||
end
|
||||
os.exit(1)
|
||||
end
|
||||
else
|
||||
tpl.render("niu/system/backup", {reset_avail = reset_avail})
|
||||
end
|
||||
end
|
||||
|
||||
function upgrade()
|
||||
local io, os, table = require "io", require "os", require "table"
|
||||
local uci = require "luci.store".uci_state
|
||||
local http = require "luci.http"
|
||||
local util = require "luci.util"
|
||||
local tpl = require "luci.template"
|
||||
local nixio = require "nixio", require "nixio.util", require "nixio.fs"
|
||||
|
||||
|
||||
local tmpfile = "/tmp/firmware.img"
|
||||
|
||||
local function image_supported()
|
||||
-- XXX: yay...
|
||||
return ( 0 == os.execute(
|
||||
". /lib/functions.sh; " ..
|
||||
"include /lib/upgrade; " ..
|
||||
"platform_check_image %q >/dev/null"
|
||||
% tmpfile
|
||||
) )
|
||||
end
|
||||
|
||||
local function image_checksum()
|
||||
return (util.exec("md5sum %q" % tmpfile):match("^([^%s]+)"))
|
||||
end
|
||||
|
||||
local function storage_size()
|
||||
local size = 0
|
||||
if nixio.fs.access("/proc/mtd") then
|
||||
for l in io.lines("/proc/mtd") do
|
||||
local d, s, e, n = l:match('^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+"([^%s]+)"')
|
||||
if n == "linux" then
|
||||
size = tonumber(s, 16)
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif nixio.fs.access("/proc/partitions") then
|
||||
for l in io.lines("/proc/partitions") do
|
||||
local x, y, b, n = l:match('^%s*(%d+)%s+(%d+)%s+([^%s]+)%s+([^%s]+)')
|
||||
if b and n and not n:match('[0-9]') then
|
||||
size = tonumber(b) * 1024
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return size
|
||||
end
|
||||
|
||||
|
||||
-- Install upload handler
|
||||
local file
|
||||
http.setfilehandler(
|
||||
function(meta, chunk, eof)
|
||||
if not nixio.fs.access(tmpfile) and not file and chunk and #chunk > 0 then
|
||||
file = io.open(tmpfile, "w")
|
||||
end
|
||||
if file and chunk then
|
||||
file:write(chunk)
|
||||
end
|
||||
if file and eof then
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
|
||||
-- Determine state
|
||||
local keep_avail = true
|
||||
local step = tonumber(http.formvalue("step") or 1)
|
||||
local has_image = nixio.fs.access(tmpfile)
|
||||
local has_support = image_supported()
|
||||
local has_platform = nixio.fs.access("/lib/upgrade/platform.sh")
|
||||
local has_upload = http.formvalue("image")
|
||||
|
||||
-- This does the actual flashing which is invoked inside an iframe
|
||||
-- so don't produce meaningful errors here because the the
|
||||
-- previous pages should arrange the stuff as required.
|
||||
if step == 4 then
|
||||
if has_platform and has_image and has_support then
|
||||
-- Mimetype text/plain
|
||||
http.prepare_content("text/plain")
|
||||
|
||||
local call = {}
|
||||
for k, v in pairs(uci:get_all("luci", "flash_keep")) do
|
||||
if k:byte() ~= 46 then -- k[1] ~= "."
|
||||
nixio.util.consume(nixio.fs.glob(v), call)
|
||||
end
|
||||
end
|
||||
|
||||
-- Now invoke sysupgrade
|
||||
local keepcfg = keep_avail and http.formvalue("keepcfg") == "1"
|
||||
local fd = io.popen("/sbin/luci-flash %s %q" %{
|
||||
keepcfg and "-k %q" % table.concat(call, " ") or "", tmpfile
|
||||
})
|
||||
|
||||
if fd then
|
||||
while true do
|
||||
local ln = fd:read("*l")
|
||||
if not ln then break end
|
||||
http.write(ln .. "\n")
|
||||
end
|
||||
fd:close()
|
||||
end
|
||||
|
||||
-- Make sure the device is rebooted
|
||||
if nixio.fork() == 0 then
|
||||
nixio.nanosleep(1)
|
||||
nixio.execp("reboot")
|
||||
os.exit(1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- This is step 1-3, which does the user interaction and
|
||||
-- image upload.
|
||||
--
|
||||
|
||||
-- Step 1: file upload, error on unsupported image format
|
||||
elseif not has_image or not has_support or step == 1 then
|
||||
-- If there is an image but user has requested step 1
|
||||
-- or type is not supported, then remove it.
|
||||
if has_image then
|
||||
nixio.fs.unlink(tmpfile)
|
||||
end
|
||||
|
||||
tpl.render("niu/system/upgrade", {
|
||||
step=1,
|
||||
bad_image=(has_image and not has_support or false),
|
||||
keepavail=keep_avail,
|
||||
supported=has_platform
|
||||
} )
|
||||
|
||||
-- Step 2: present uploaded file, show checksum, confirmation
|
||||
elseif step == 2 then
|
||||
tpl.render("niu/system/upgrade", {
|
||||
step=2,
|
||||
checksum=image_checksum(),
|
||||
filesize=nixio.fs.stat(tmpfile).size,
|
||||
flashsize=storage_size(),
|
||||
keepconfig=(keep_avail and http.formvalue("keepcfg") == "1")
|
||||
} )
|
||||
|
||||
-- Step 3: load iframe which calls the actual flash procedure
|
||||
elseif step == 3 then
|
||||
tpl.render("niu/system/upgrade", {
|
||||
step=3,
|
||||
keepconfig=(keep_avail and http.formvalue("keepcfg") == "1")
|
||||
} )
|
||||
end
|
||||
end
|
|
@ -1,45 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Development Framework
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local require = require
|
||||
module "luci.controller.niu.traffic"
|
||||
|
||||
function index()
|
||||
local toniu = {on_success_to={"niu"}}
|
||||
|
||||
local e = entry({"niu", "traffic"}, alias("niu"), "Network Traffic", 30)
|
||||
e.niu_dbtemplate = "niu/traffic"
|
||||
e.niu_dbtasks = true
|
||||
e.niu_dbicon = "icons32/preferences-system-network.png"
|
||||
|
||||
if fs.access("/etc/config/firewall") then
|
||||
entry({"niu", "traffic", "portfw"}, cbi("niu/traffic/portfw",
|
||||
toniu), "Manage Port Forwarding", 1)
|
||||
end
|
||||
|
||||
if fs.access("/etc/config/qos") then
|
||||
entry({"niu", "traffic", "qos"}, cbi("niu/traffic/qos",
|
||||
toniu), "Manage Prioritization (QoS)", 2)
|
||||
end
|
||||
|
||||
entry({"niu", "traffic", "routes"}, cbi("niu/traffic/routes",
|
||||
toniu), "Manage Traffic Routing", 30)
|
||||
|
||||
entry({"niu", "traffic", "conntrack"}, call("cnntrck"),
|
||||
"Display Local Network Activity", 50)
|
||||
end
|
||||
|
||||
function cnntrck()
|
||||
require "luci.template".render("niu/traffic/conntrack")
|
||||
end
|
|
@ -1,40 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Development Framework
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
module "luci.controller.niu.wireless"
|
||||
|
||||
function index()
|
||||
if not fs.access("/etc/config/wireless") then
|
||||
return
|
||||
end
|
||||
|
||||
local toniu = {on_success_to={"niu"}}
|
||||
|
||||
local e = entry({"niu", "wireless"}, alias("niu"), _("Wireless"), 20)
|
||||
--e.niu_dbtemplate = "niu/wireless"
|
||||
e.niu_dbtasks = true
|
||||
e.niu_dbicon = "icons32/network-wireless.png"
|
||||
|
||||
entry({"niu", "wireless", "ap"},
|
||||
cbi("niu/wireless/ap", toniu), _("Configure Private Access Point"), 1)
|
||||
|
||||
local bridge = false
|
||||
uci.inst:foreach("wireless", "wifi-device", function(s)
|
||||
if not bridge and (s.type == "mac80211" or s.type == "atheros") then
|
||||
entry({"niu", "wireless", "bridge"},
|
||||
cbi("niu/wireless/bridge", toniu), _("Join a local WDS network"), 2)
|
||||
bridge = true
|
||||
end
|
||||
end)
|
||||
end
|
|
@ -1,17 +0,0 @@
|
|||
local cursor = require "luci.model.uci".cursor()
|
||||
local d = Delegator()
|
||||
d.allow_finish = true
|
||||
d.allow_back = true
|
||||
d.allow_cancel = true
|
||||
|
||||
d:add("assign1", load("niu/network/assign1"))
|
||||
|
||||
function d.on_cancel()
|
||||
cursor:revert("dhcp")
|
||||
end
|
||||
|
||||
function d.on_done()
|
||||
cursor:commit("dhcp")
|
||||
end
|
||||
|
||||
return d
|
|
@ -1,96 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local sys = require "luci.sys"
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
|
||||
local function date_format(secs)
|
||||
local suff = {"min", "h", "d"}
|
||||
local mins = 0
|
||||
local hour = 0
|
||||
local days = 0
|
||||
|
||||
secs = math.floor(secs)
|
||||
if secs > 60 then
|
||||
mins = math.floor(secs / 60)
|
||||
secs = secs % 60
|
||||
end
|
||||
|
||||
if mins > 60 then
|
||||
hour = math.floor(mins / 60)
|
||||
mins = mins % 60
|
||||
end
|
||||
|
||||
if hour > 24 then
|
||||
days = math.floor(hour / 24)
|
||||
hour = hour % 24
|
||||
end
|
||||
|
||||
if days > 0 then
|
||||
return string.format("%.0fd %02.0fh %02.0fmin %02.0fs", days, hour, mins, secs)
|
||||
else
|
||||
return string.format("%02.0fh %02.0fmin %02.0fs", hour, mins, secs)
|
||||
end
|
||||
end
|
||||
|
||||
m2 = Map("dhcp", "Manage Address Assignment")
|
||||
|
||||
local leasefn, leasefp, leases
|
||||
uci:foreach("dhcp", "dnsmasq",
|
||||
function(section)
|
||||
leasefn = section.leasefile
|
||||
end
|
||||
)
|
||||
local leasefp = leasefn and fs.access(leasefn) and io.lines(leasefn)
|
||||
if leasefp then
|
||||
leases = {}
|
||||
for lease in leasefp do
|
||||
table.insert(leases, luci.util.split(lease, " "))
|
||||
end
|
||||
end
|
||||
|
||||
if leases then
|
||||
v = m2:section(Table, leases, translate("Active Leases"))
|
||||
ip = v:option(DummyValue, 3, translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
|
||||
|
||||
mac = v:option(DummyValue, 2, translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
|
||||
|
||||
ltime = v:option(DummyValue, 1, translate("Leasetime remaining"))
|
||||
function ltime.cfgvalue(self, ...)
|
||||
local value = DummyValue.cfgvalue(self, ...)
|
||||
return date_format(os.difftime(tonumber(value), os.time()))
|
||||
end
|
||||
end
|
||||
|
||||
s = m2:section(TypedSection, "host", "Static Assignment",
|
||||
"You can assign fixed addresses and DNS names to devices in you local network to make reaching them more easy.")
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
s.template = "cbi/tblsection"
|
||||
|
||||
hn = s:option(Value, "name", translate("Hostname"))
|
||||
mac = s:option(Value, "mac", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
|
||||
ip = s:option(Value, "ip", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
|
||||
sys.net.arptable(function(entry)
|
||||
ip:value(entry["IP address"])
|
||||
mac:value(
|
||||
entry["HW address"],
|
||||
entry["HW address"] .. " (" .. entry["IP address"] .. ")"
|
||||
)
|
||||
end)
|
||||
|
||||
|
||||
return m2
|
|
@ -1,18 +0,0 @@
|
|||
local uci = require "luci.model.uci"
|
||||
local cursor = uci.cursor()
|
||||
local d = Delegator()
|
||||
d.allow_finish = true
|
||||
d.allow_back = true
|
||||
d.allow_cancel = true
|
||||
|
||||
d:add("ddns1", load("niu/network/ddns1"))
|
||||
|
||||
function d.on_cancel()
|
||||
cursor:revert("ddns")
|
||||
end
|
||||
|
||||
function d.on_done()
|
||||
cursor:commit("ddns")
|
||||
end
|
||||
|
||||
return d
|
|
@ -1,71 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
local nxo = require "nixio"
|
||||
|
||||
m = Map("ddns", translate("Dynamic DNS"), translate("Dynamic DNS allows that this device can be reached with a fixed hostname while having a dynamically changing IP-Address."))
|
||||
|
||||
s = m:section(TypedSection, "service", "")
|
||||
s:depends("enabled", "1")
|
||||
s.addremove = true
|
||||
|
||||
s.defaults.enabled = "1"
|
||||
s.defaults.ip_network = "wan"
|
||||
s.defaults.ip_url = "http://checkip.dyndns.org http://www.whatismyip.com/automation/n09230945.asp"
|
||||
|
||||
|
||||
s:tab("general", translate("General Settings"))
|
||||
|
||||
svc = s:taboption("general", ListValue, "service_name", translate("Service"))
|
||||
svc:value("dyndns.org")
|
||||
svc:value("no-ip.com")
|
||||
svc:value("changeip.com")
|
||||
svc:value("zoneedit.com")
|
||||
|
||||
|
||||
s:taboption("general", Value, "username", translate("Username"))
|
||||
pw = s:taboption("general", Value, "password", translate("Password"))
|
||||
pw.password = true
|
||||
local dom = s:taboption("general", Value, "domain", translate("Hostname"))
|
||||
|
||||
local current = s:taboption("general", DummyValue, "_current", "Current IP-Address")
|
||||
|
||||
function current.render(self, section, ...)
|
||||
if dom:cfgvalue(section) then
|
||||
return DummyValue.render(self, section, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function current.value(self, section)
|
||||
local dns = nxo.getaddrinfo(dom:cfgvalue(section))
|
||||
if dns then
|
||||
for _, v in ipairs(dns) do
|
||||
if v.family == "inet" then
|
||||
return v.address
|
||||
end
|
||||
end
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
s:tab("expert", translate("Expert Settings"))
|
||||
|
||||
local src = s:taboption("expert", ListValue, "ip_source", "External IP Determination")
|
||||
src.default = "web"
|
||||
src:value("web", "CheckIP / WhatIsMyIP webservice")
|
||||
src:value("network", "External Address as seen locally")
|
||||
|
||||
|
||||
|
||||
return m
|
|
@ -1,161 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
local has_ipv6 = fs.access("/proc/net/ipv6_route")
|
||||
local has_pptp = fs.access("/usr/sbin/pptp")
|
||||
local has_pppd = fs.access("/usr/sbin/pppd")
|
||||
local has_pppoe = fs.glob("/usr/lib/pppd/*/rp-pppoe.so")()
|
||||
local has_pppoa = fs.glob("/usr/lib/pppd/*/pppoatm.so")()
|
||||
|
||||
|
||||
m = Map("network", "Configure Ethernet Adapter for Internet Connection")
|
||||
|
||||
s = m:section(NamedSection, "wan", "interface")
|
||||
s.addremove = false
|
||||
|
||||
s:tab("general", translate("General Settings"))
|
||||
s:tab("expert", translate("Expert Settings"))
|
||||
|
||||
p = s:taboption("general", ListValue, "proto", translate("Connection Protocol"))
|
||||
p.override_scheme = true
|
||||
p.default = "dhcp"
|
||||
p:value("dhcp", translate("Cable / Ethernet / DHCP"))
|
||||
if has_pppoe then p:value("pppoe", "DSL / PPPoE") end
|
||||
if has_pppoa then p:value("pppoa", "PPPoA") end
|
||||
if has_pptp then p:value("pptp", "PPTP") end
|
||||
p:value("static", translate("Static Ethernet"))
|
||||
|
||||
|
||||
|
||||
ipaddr = s:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
|
||||
ipaddr.rmempty = true
|
||||
ipaddr:depends("proto", "static")
|
||||
|
||||
nm = s:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
|
||||
nm.rmempty = true
|
||||
nm:depends("proto", "static")
|
||||
nm:value("255.255.255.0")
|
||||
nm:value("255.255.0.0")
|
||||
nm:value("255.0.0.0")
|
||||
|
||||
gw = s:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
|
||||
gw:depends("proto", "static")
|
||||
gw.rmempty = true
|
||||
|
||||
bcast = s:taboption("expert", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
|
||||
bcast:depends("proto", "static")
|
||||
|
||||
if has_ipv6 then
|
||||
ip6addr = s:taboption("expert", Value, "ip6addr", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Address"), translate("<abbr title=\"Classless Inter-Domain Routing\">CIDR</abbr>-Notation: address/prefix"))
|
||||
ip6addr:depends("proto", "static")
|
||||
|
||||
ip6gw = s:taboption("expert", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
|
||||
ip6gw:depends("proto", "static")
|
||||
end
|
||||
|
||||
dns = s:taboption("expert", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"))
|
||||
dns:depends("peerdns", "")
|
||||
|
||||
mtu = s:taboption("expert", Value, "mtu", "MTU")
|
||||
mtu.isinteger = true
|
||||
|
||||
mac = s:taboption("expert", Value, "macaddr", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
|
||||
|
||||
|
||||
srv = s:taboption("general", Value, "server", translate("<abbr title=\"Point-to-Point Tunneling Protocol\">PPTP</abbr>-Server"))
|
||||
srv:depends("proto", "pptp")
|
||||
srv.rmempty = true
|
||||
|
||||
if has_pppd or has_pppoe or has_pppoa or has_pptp then
|
||||
user = s:taboption("general", Value, "username", translate("Username"))
|
||||
user.rmempty = true
|
||||
user:depends("proto", "pptp")
|
||||
user:depends("proto", "pppoe")
|
||||
user:depends("proto", "pppoa")
|
||||
|
||||
pass = s:taboption("general", Value, "password", translate("Password"))
|
||||
pass.rmempty = true
|
||||
pass.password = true
|
||||
pass:depends("proto", "pptp")
|
||||
pass:depends("proto", "pppoe")
|
||||
pass:depends("proto", "pppoa")
|
||||
|
||||
ka = s:taboption("expert", Value, "keepalive",
|
||||
translate("Keep-Alive"),
|
||||
translate("Number of failed connection tests to initiate automatic reconnect")
|
||||
)
|
||||
ka.default = "5"
|
||||
ka:depends("proto", "pptp")
|
||||
ka:depends("proto", "pppoe")
|
||||
ka:depends("proto", "pppoa")
|
||||
|
||||
demand = s:taboption("expert", Value, "demand",
|
||||
translate("Automatic Disconnect"),
|
||||
translate("Time (in seconds) after which an unused connection will be closed")
|
||||
)
|
||||
demand:depends("proto", "pptp")
|
||||
demand:depends("proto", "pppoe")
|
||||
demand:depends("proto", "pppoa")
|
||||
end
|
||||
|
||||
if has_pppoa then
|
||||
encaps = s:taboption("expert", ListValue, "encaps", translate("PPPoA Encapsulation"))
|
||||
encaps:depends("proto", "pppoa")
|
||||
encaps:value("", translate("-- Please choose --"))
|
||||
encaps:value("vc", "VC")
|
||||
encaps:value("llc", "LLC")
|
||||
|
||||
vpi = s:taboption("expert", Value, "vpi", "VPI")
|
||||
vpi:depends("proto", "pppoa")
|
||||
|
||||
vci = s:taboption("expert", Value, "vci", "VCI")
|
||||
vci:depends("proto", "pppoa")
|
||||
end
|
||||
|
||||
if has_pptp or has_pppd or has_pppoe or has_pppoa or has_3g then
|
||||
--[[
|
||||
defaultroute = s:taboption("expert", Flag, "defaultroute",
|
||||
translate("Replace default route"),
|
||||
translate("Let pppd replace the current default route to use the PPP interface after successful connect")
|
||||
)
|
||||
defaultroute:depends("proto", "pppoa")
|
||||
defaultroute:depends("proto", "pppoe")
|
||||
defaultroute:depends("proto", "pptp")
|
||||
defaultroute.rmempty = false
|
||||
function defaultroute.cfgvalue(...)
|
||||
return ( AbstractValue.cfgvalue(...) or '1' )
|
||||
end
|
||||
]]
|
||||
peerdns = s:taboption("expert", Flag, "peerdns",
|
||||
translate("Use peer DNS"),
|
||||
translate("Configure the local DNS server to use the name servers adverticed by the PPP peer")
|
||||
)
|
||||
peerdns:depends("proto", "pppoa")
|
||||
peerdns:depends("proto", "pppoe")
|
||||
peerdns:depends("proto", "pptp")
|
||||
peerdns.rmempty = false
|
||||
peerdns.default = "1"
|
||||
|
||||
if has_ipv6 then
|
||||
ipv6 = s:taboption("expert", Flag, "ipv6", translate("Enable IPv6 on PPP link") )
|
||||
ipv6:depends("proto", "pppoa")
|
||||
ipv6:depends("proto", "pppoe")
|
||||
ipv6:depends("proto", "pptp")
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
|
@ -1,44 +0,0 @@
|
|||
local uci = require "luci.model.uci"
|
||||
local cursor = uci.cursor()
|
||||
local d = Delegator()
|
||||
d.allow_finish = true
|
||||
d.allow_back = true
|
||||
d.allow_cancel = true
|
||||
|
||||
d:add("lan1", "niu/network/lan1")
|
||||
|
||||
function d.on_cancel()
|
||||
cursor:revert("network")
|
||||
cursor:revert("dhcp")
|
||||
end
|
||||
|
||||
function d.on_done()
|
||||
if uci.inst_state:get("network", "lan", "ipaddr") ~= cursor:get("network", "lan", "ipaddr") then
|
||||
local cs = uci.cursor_state()
|
||||
cs:set("network", "lan", "_ipchanged", "1")
|
||||
cs:save("network")
|
||||
end
|
||||
|
||||
if cursor:get("network", "lan", "proto") == "dhcp" then
|
||||
local emergv4 = cursor:get("network", "lan", "_emergv4")
|
||||
if emergv4 then
|
||||
if cursor:get("network", "lan_ea") then
|
||||
cursor:set("network", "lan_ea", "ipaddr", emergv4)
|
||||
else
|
||||
cursor:section("network", "alias", "lan_ea", {
|
||||
ipaddr = emergv4,
|
||||
netmask = "255.255.255.0",
|
||||
network = "lan"
|
||||
})
|
||||
end
|
||||
else
|
||||
cursor:delete("network", "lan_ea")
|
||||
end
|
||||
end
|
||||
|
||||
cursor:set("network", "lan", "type", "bridge")
|
||||
cursor:commit("network")
|
||||
cursor:commit("dhcp")
|
||||
end
|
||||
|
||||
return d
|
|
@ -1,131 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local bridge = (arg[1] == "bridgelan")
|
||||
local niulib = require "luci.niulib"
|
||||
local fs = require "nixio.fs"
|
||||
local has_ipv6 = fs.access("/proc/net/ipv6_route")
|
||||
|
||||
m = Map("network", translate("Configure Local Network"), bridge and
|
||||
translate([[The wireless network will be connected directly to your local network.
|
||||
Make sure you to assign any address to this device that is in the same subnet
|
||||
of the other devices in your network but that is not already occupied.
|
||||
If you have a DHCP-Server in this network you may also choose DHCP for address configuration.]])
|
||||
or translate("These settings affect the devices in your local network. "..
|
||||
"Usually you do not need to change anything here for this device to work correctly."))
|
||||
|
||||
s = m:section(NamedSection, "lan", "interface", "Network Settings")
|
||||
s.addremove = false
|
||||
|
||||
s:tab("general", translate("General Settings"))
|
||||
s:tab("expert", translate("Expert Settings"))
|
||||
|
||||
p = s:taboption("expert", ListValue, "proto", translate("Address Configuration"))
|
||||
p.default = "static"
|
||||
p:value("static", translate("Static Configuration"))
|
||||
p:value("dhcp", "DHCP")
|
||||
|
||||
|
||||
ipaddr = s:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
|
||||
ipaddr.default = "192.168.0.1"
|
||||
ipaddr:depends("proto", "static")
|
||||
|
||||
nm = s:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
|
||||
nm.default = "255.255.255.0"
|
||||
nm:value("255.255.255.0")
|
||||
nm:value("255.255.0.0")
|
||||
nm:value("255.0.0.0")
|
||||
nm:depends("proto", "static")
|
||||
|
||||
|
||||
mac = s:taboption("expert", Value, "macaddr", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
|
||||
|
||||
mtu = s:taboption("expert", Value, "mtu", "MTU")
|
||||
mtu.isinteger = true
|
||||
|
||||
dns = s:taboption("expert", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"))
|
||||
dns:depends("peerdns", "")
|
||||
|
||||
|
||||
gw = s:taboption(bridge and "general" or "expert", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
|
||||
gw:depends("proto", "static")
|
||||
|
||||
bcast = s:taboption("expert", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
|
||||
bcast:depends("proto", "static")
|
||||
|
||||
|
||||
if has_ipv6 then
|
||||
ip6addr = s:taboption("expert", Value, "ip6addr", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Address"), translate("<abbr title=\"Classless Inter-Domain Routing\">CIDR</abbr>-Notation: address/prefix"))
|
||||
ip6addr:depends("proto", "static")
|
||||
ip6gw = s:taboption("expert", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
|
||||
ip6gw:depends("proto", "static")
|
||||
end
|
||||
|
||||
emerg = s:taboption("expert", Value, "_emergv4", translate("Emergency Access Address"),
|
||||
translate([[In case the DHCP request fails you will still be able to access this device using given IP
|
||||
by configuring your computer to an address in the same subnet and netmask 255.255.255.0.]]))
|
||||
emerg:depends("proto", "dhcp")
|
||||
emerg:value("", translate("disable"))
|
||||
emerg.default = "169.254.255.169"
|
||||
|
||||
|
||||
stp = s:taboption("expert", Flag, "stp", translate("Enable <abbr title=\"Spanning Tree Protocol\">STP</abbr>"),
|
||||
translate("Enables the Spanning Tree Protocol on this bridge"))
|
||||
|
||||
ifname_multi = s:taboption("expert", MultiValue, "ifname", translate("Interface"))
|
||||
ifname_multi.widget = "checkbox"
|
||||
for _, eth in ipairs(niulib.eth_get_available("lan")) do
|
||||
ifname_multi:value(eth, translate("Ethernet-Adapter (%s)") % eth)
|
||||
end
|
||||
|
||||
|
||||
m2 = Map("dhcp")
|
||||
|
||||
s = m2:section(TypedSection, "dhcp", "DHCP")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
s.dynamic = false
|
||||
|
||||
s:tab("general", translate("General Settings"))
|
||||
|
||||
s:depends("interface", "lan")
|
||||
|
||||
enable = s:taboption("general", ListValue, "ignore", translate("Automatic address assignment for network devices"),
|
||||
bridge and
|
||||
translate("Note: Be careful that you do not accidently two DHCP servers in the same network with overlapping address ranges.")
|
||||
or "")
|
||||
enable:value(0, translate("enable"), {["network.lan.proto"] = "static"})
|
||||
enable:value(1, translate("disable"))
|
||||
|
||||
|
||||
s:tab("expert", translate("Expert Settings"))
|
||||
start = s:taboption("expert", Value, "start", translate("First leased address"))
|
||||
start:depends("ignore", "0")
|
||||
start.default = "100"
|
||||
|
||||
limit = s:taboption("expert", Value, "limit", translate("Number of leased addresses"), "")
|
||||
limit:depends("ignore", "0")
|
||||
limit.default = "150"
|
||||
|
||||
time = s:taboption("expert", Value, "leasetime", translate("Lease Time"))
|
||||
time:depends("ignore", "0")
|
||||
time.default = "12h"
|
||||
|
||||
local dd = s:taboption("expert", Flag, "dynamicdhcp", translate("Also generate addresses for unknown devices"))
|
||||
dd.rmempty = false
|
||||
dd.default = "1"
|
||||
dd:depends("ignore", "0")
|
||||
|
||||
return m, m2
|
|
@ -1,88 +0,0 @@
|
|||
local cursor = require "luci.model.uci".cursor()
|
||||
|
||||
if not cursor:get("network", "wan") then
|
||||
cursor:section("network", "interface", "wan", {proto = "none"})
|
||||
cursor:save("network")
|
||||
end
|
||||
|
||||
if not cursor:get("wireless", "client") then
|
||||
cursor:section("wireless", "wifi-iface", "client",
|
||||
{device = "_", doth = "1", _niu = "1", mode = "sta"})
|
||||
cursor:save("wireless")
|
||||
end
|
||||
|
||||
local function deviceroute(self)
|
||||
cursor:unload("network")
|
||||
local wd = cursor:get("network", "wan", "_wandev") or ""
|
||||
|
||||
if wd == "none" then
|
||||
cursor:set("network", "wan", "proto", "none")
|
||||
end
|
||||
|
||||
if wd:find("ethernet:") == 1 then
|
||||
cursor:set("network", "wan", "defaultroute", "1")
|
||||
if wd:find("!", 10) == 10 then --Unbridge from LAN
|
||||
local ethdev = wd:sub(11)
|
||||
local ifname = cursor:get("network", "lan", "ifname")
|
||||
local newifname = {}
|
||||
for k in ifname:gmatch("[^ ]+") do
|
||||
if k ~= ifname then
|
||||
newifname[#newifname+1] = k
|
||||
end
|
||||
end
|
||||
cursor:set("network", "lan", "ifname", table.concat(newifname, " "))
|
||||
cursor:set("network", "wan", "_wandev", "ethernet:" .. ethdev)
|
||||
cursor:set("network", "wan", "ifname", ethdev)
|
||||
else
|
||||
cursor:set("network", "wan", "ifname", wd:sub(10))
|
||||
end
|
||||
self:set_route("etherwan")
|
||||
else
|
||||
cursor:delete("network", "wan", "ifname")
|
||||
end
|
||||
|
||||
if wd:find("wlan:") == 1 then
|
||||
local widev = wd:sub(6)
|
||||
if cursor:get("wireless", "client", "device") ~= widev then
|
||||
cursor:delete("wireless", "client", "network")
|
||||
cursor:set("wireless", "client", "mode", "sta")
|
||||
cursor:set("wireless", "client", "device", widev)
|
||||
cursor:delete_all("wireless", "wifi-iface", function(s)
|
||||
return s.device == widev and s._niu ~= "1"
|
||||
end)
|
||||
cursor:set("wireless", widev, "disabled", 0)
|
||||
end
|
||||
self:set_route("wlanwan1", "wlanwan2")
|
||||
else
|
||||
cursor:delete("wireless", "client", "device")
|
||||
cursor:delete("wireless", "client", "network")
|
||||
end
|
||||
|
||||
|
||||
cursor:save("wireless")
|
||||
cursor:save("network")
|
||||
end
|
||||
|
||||
|
||||
local d = Delegator()
|
||||
d.allow_finish = true
|
||||
d.allow_back = true
|
||||
d.allow_cancel = true
|
||||
|
||||
d:add("device", "niu/network/wandevice")
|
||||
d:add("deviceroute", deviceroute)
|
||||
d:set("etherwan", "niu/network/etherwan")
|
||||
d:set("wlanwan1", "niu/network/wlanwanscan")
|
||||
d:set("wlanwan2", "niu/network/wlanwan")
|
||||
|
||||
function d.on_cancel()
|
||||
cursor:revert("network")
|
||||
cursor:revert("wireless")
|
||||
end
|
||||
|
||||
function d.on_done()
|
||||
cursor:commit("network")
|
||||
cursor:commit("wireless")
|
||||
end
|
||||
|
||||
return d
|
|
@ -1,47 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local niulib = require "luci.niulib"
|
||||
|
||||
m = Map("network", "Configure Internet Connection")
|
||||
s = m:section(NamedSection, "wan", "interface", "Internet Connection Device")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
s:tab("general", translate("General Settings"))
|
||||
s:tab("expert", translate("Expert Settings"))
|
||||
|
||||
l = s:taboption("general", ListValue, "_wandev", "Internet Connection via")
|
||||
|
||||
for _, ifc in ipairs(niulib.eth_get_available("wan")) do
|
||||
l:value("ethernet:%s" % ifc, "Cable / DSL / Ethernet-Adapter (%s)" % ifc)
|
||||
end
|
||||
|
||||
for _, wifi in ipairs(niulib.wifi_get_available("client")) do
|
||||
l:value("wlan:%s" % wifi, "WLAN-Adapter (%s)" % wifi)
|
||||
end
|
||||
|
||||
for _, ifc in ipairs(niulib.eth_get_bridged("lan")) do
|
||||
l:value("ethernet:!%s" % ifc, "Used Ethernet-Adapter (%s)" % ifc, {_showused = "1"})
|
||||
end
|
||||
|
||||
l:value("none", "No Internet Connection")
|
||||
|
||||
v = s:taboption("expert", ListValue, "_showused", translate("Show ethernet adapters in use"))
|
||||
v:value("", translate("never"))
|
||||
v:value("1", translate("from LAN-bridge, unbridge on-demand"))
|
||||
|
||||
|
||||
|
||||
return m
|
|
@ -1,284 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local uci = require "luci.model.uci"
|
||||
local nixio = require "nixio"
|
||||
local iwinfo = require "iwinfo"
|
||||
|
||||
local bridge
|
||||
local iface = "client"
|
||||
local net = "wan"
|
||||
if arg[1] == "bridge" then
|
||||
bridge = true
|
||||
iface = "bridge"
|
||||
net = "lan"
|
||||
end
|
||||
|
||||
local cursor = uci.inst
|
||||
local state = uci.inst_state
|
||||
cursor:unload("wireless")
|
||||
state:unload("wireless")
|
||||
|
||||
local has_ipv6 = fs.access("/proc/net/ipv6_route")
|
||||
local device = cursor:get("wireless", iface, "device")
|
||||
local hwtype = cursor:get("wireless", device, "type")
|
||||
|
||||
|
||||
-- Bring up interface and scan --
|
||||
|
||||
if not state:get("wireless", iface, "network") then
|
||||
local olduci = uci.cursor(nil, "")
|
||||
local oldcl = olduci:get_all("wireless", iface)
|
||||
olduci:unload("wireless")
|
||||
|
||||
local newuci = uci.cursor()
|
||||
local newcl = newuci:get_all("wireless", iface)
|
||||
newcl.network = net
|
||||
|
||||
local proc = nixio.fork()
|
||||
if proc == 0 then
|
||||
newuci:delete("wireless", iface, "ssid")
|
||||
newuci:commit("wireless")
|
||||
nixio.exec("/sbin/wifi", "up", device)
|
||||
os.exit(1)
|
||||
end
|
||||
nixio.wait(proc)
|
||||
|
||||
newuci:delete("wireless", iface)
|
||||
newuci:section("wireless", "wifi-iface", iface, oldcl)
|
||||
newuci:commit("wireless")
|
||||
newuci:tset("wireless", iface, newcl)
|
||||
newuci:save("wireless")
|
||||
newuci:unload("wireless")
|
||||
|
||||
state:unload("wireless")
|
||||
end
|
||||
|
||||
local ifname = state:get("wireless", iface, "ifname") or "wlan0dummy"
|
||||
local iwlib = iwinfo.type(ifname) and iwinfo[iwinfo.type(ifname)]
|
||||
local suggest = {}
|
||||
local encrdep = {
|
||||
none = {{["!default"] = 1}},
|
||||
wep = {{["!default"] = 1}},
|
||||
psk = {{["!default"] = 1}},
|
||||
psk2 = {{["!default"] = 1}},
|
||||
wpa = {{["!default"] = 1}},
|
||||
wpa2 = {{["!default"] = 1}}
|
||||
}
|
||||
|
||||
if iwlib then
|
||||
suggest = iwlib.scanlist(ifname)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- Form definition --
|
||||
|
||||
m2 = Map("wireless", translate("Configure WLAN-Adapter for Client Connection"),
|
||||
bridge and ("<strong>" .. translate([[It is absolutely necessary that the network you are joining
|
||||
supports and allows bridging (WDS) otherwise your connection will fail.]]) .. "</strong> " ..
|
||||
translate([[Note: You can use the access point wizard to configure your
|
||||
private access point to increase the range of the network you are connected to.]])) or "")
|
||||
|
||||
s = m2:section(NamedSection, iface, "wifi-iface", translate("Wireless Settings"))
|
||||
s.addremove = false
|
||||
|
||||
s:tab("general", translate("General Settings"))
|
||||
s:tab("expert", translate("Expert Settings"))
|
||||
|
||||
local ssid = s:taboption("general", Value, "ssid", translate("Network Name (<abbr title=\"Extended Service Set Identifier\">ESSID</abbr>)"))
|
||||
ssid.rmempty = false
|
||||
|
||||
for _, v in ipairs(suggest) do
|
||||
if v.mode == "Master" then
|
||||
ssid:value(v.ssid)
|
||||
|
||||
if not v.wep then
|
||||
encrdep.wep[#encrdep.wep+1] = {ssid = v.ssid, ["!reverse"] = 1}
|
||||
end
|
||||
if v.wpa ~= 1 or (v.wpa == 1 and v.auth_suites[1] ~= "802.1x") then
|
||||
encrdep.wpa[#encrdep.wpa+1] = {ssid = v.ssid, ["!reverse"] = 1}
|
||||
end
|
||||
if v.wpa ~= 1 or (v.wpa == 1 and v.auth_suites[1] ~= "PSK") then
|
||||
encrdep.psk[#encrdep.psk+1] = {ssid = v.ssid, ["!reverse"] = 1}
|
||||
end
|
||||
if not v.wpa or v.wpa < 2 or (v.wpa >= 2 and v.auth_suites[1] ~= "802.1x") then
|
||||
encrdep.wpa2[#encrdep.wpa2+1] = {ssid = v.ssid, ["!reverse"] = 1}
|
||||
end
|
||||
if not v.wpa or v.wpa < 2 or (v.wpa >= 2 and v.auth_suites[1] ~= "PSK") then
|
||||
encrdep.psk2[#encrdep.psk2+1] = {ssid = v.ssid, ["!reverse"] = 1}
|
||||
end
|
||||
if v.wpa or v.wep then
|
||||
encrdep.none[#encrdep.none+1] = {ssid = v.ssid, ["!reverse"] = 1}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mode = s:taboption("expert", ListValue, "mode", translate("Operating Mode"))
|
||||
mode.override_values = true
|
||||
mode:value("sta", translate("Client"))
|
||||
|
||||
encr = s:taboption("general", ListValue, "encryption", translate("Encryption"))
|
||||
|
||||
|
||||
if hwtype == "mac80211" then
|
||||
if not bridge then
|
||||
mode:value("mesh", translate("Mesh (802.11s)"))
|
||||
local meshid = s:taboption("expert", Value, "mesh_id", translate("Mesh ID"))
|
||||
meshid:depends("mode", "mesh")
|
||||
end
|
||||
|
||||
local ps = s:taboption("expert", Flag, "powersave", translate("Enable Powersaving"))
|
||||
ps:depends("mode", "sta")
|
||||
elseif hwtype == "atheros" then
|
||||
s:taboption("expert", Flag, "bursting", translate("Allow Burst Transmissions"))
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- Encryption --
|
||||
|
||||
encr.override_values = true
|
||||
encr.override_depends = true
|
||||
encr:value("none", "No Encryption", unpack(encrdep.none))
|
||||
encr:value("wep", "WEP", unpack(encrdep.wep))
|
||||
|
||||
if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
|
||||
local supplicant = fs.access("/usr/sbin/wpa_supplicant") or os.getenv("LUCI_SYSROOT")
|
||||
if supplicant then
|
||||
encr:value("psk", "WPA", unpack(encrdep.psk))
|
||||
encr:value("wpa", "WPA-EAP", unpack(encrdep.wpa))
|
||||
encr:value("psk2", "WPA2", unpack(encrdep.psk2))
|
||||
encr:value("wpa2", "WPA2-EAP (802.11i)", unpack(encrdep.wpa2))
|
||||
end
|
||||
elseif hwtype == "broadcom" then
|
||||
encr:value("psk", "WPA", unpack(encrdep.psk))
|
||||
encr:value("psk2", "WPA2", unpack(encrdep.psk2))
|
||||
end
|
||||
|
||||
key = s:taboption("general", Value, "key", translate("Password"))
|
||||
key:depends("encryption", "wep")
|
||||
key:depends("encryption", "psk")
|
||||
key:depends("encryption", "psk2")
|
||||
key.rmempty = true
|
||||
key.password = true
|
||||
|
||||
if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
|
||||
eaptype = s:taboption("general", ListValue, "eap_type", translate("EAP-Method"))
|
||||
eaptype:value("TLS")
|
||||
eaptype:value("TTLS")
|
||||
eaptype:value("PEAP")
|
||||
eaptype:depends({encryption="wpa"})
|
||||
eaptype:depends({encryption="wpa2"})
|
||||
|
||||
cacert = s:taboption("general", FileUpload, "ca_cert", translate("Path to CA-Certificate"))
|
||||
cacert:depends({encryption="wpa"})
|
||||
cacert:depends({encryption="wpa2"})
|
||||
|
||||
privkey = s:taboption("general", FileUpload, "priv_key", translate("Path to Private Key"))
|
||||
privkey:depends({eap_type="TLS", encryption="wpa2"})
|
||||
privkey:depends({eap_type="TLS", encryption="wpa"})
|
||||
|
||||
privkeypwd = s:taboption("general", Value, "priv_key_pwd", translate("Password of Private Key"))
|
||||
privkeypwd:depends({eap_type="TLS", encryption="wpa2"})
|
||||
privkeypwd:depends({eap_type="TLS", encryption="wpa"})
|
||||
|
||||
|
||||
auth = s:taboption("general", Value, "auth", translate("Authentication"))
|
||||
auth:value("PAP")
|
||||
auth:value("CHAP")
|
||||
auth:value("MSCHAP")
|
||||
auth:value("MSCHAPV2")
|
||||
auth:depends({eap_type="PEAP", encryption="wpa2"})
|
||||
auth:depends({eap_type="PEAP", encryption="wpa"})
|
||||
auth:depends({eap_type="TTLS", encryption="wpa2"})
|
||||
auth:depends({eap_type="TTLS", encryption="wpa"})
|
||||
|
||||
|
||||
identity = s:taboption("general", Value, "identity", translate("Identity"))
|
||||
identity:depends({eap_type="PEAP", encryption="wpa2"})
|
||||
identity:depends({eap_type="PEAP", encryption="wpa"})
|
||||
identity:depends({eap_type="TTLS", encryption="wpa2"})
|
||||
identity:depends({eap_type="TTLS", encryption="wpa"})
|
||||
|
||||
password = s:taboption("general", Value, "password", translate("Password"))
|
||||
password:depends({eap_type="PEAP", encryption="wpa2"})
|
||||
password:depends({eap_type="PEAP", encryption="wpa"})
|
||||
password:depends({eap_type="TTLS", encryption="wpa2"})
|
||||
password:depends({eap_type="TTLS", encryption="wpa"})
|
||||
end
|
||||
|
||||
|
||||
|
||||
if not bridge then
|
||||
|
||||
m = Map("network")
|
||||
|
||||
s = m:section(NamedSection, net, "interface", translate("Address Settings"))
|
||||
s.addremove = false
|
||||
|
||||
s:tab("general", translate("General Settings"))
|
||||
s:tab("expert", translate("Expert Settings"))
|
||||
|
||||
p = s:taboption("general", ListValue, "proto", "Connection Type")
|
||||
p.override_scheme = true
|
||||
p.default = "dhcp"
|
||||
p:value("dhcp", "Automatic Configuration (DHCP)")
|
||||
p:value("static", "Static Configuration")
|
||||
|
||||
|
||||
|
||||
ipaddr = s:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
|
||||
ipaddr.rmempty = true
|
||||
ipaddr:depends("proto", "static")
|
||||
|
||||
nm = s:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
|
||||
nm.rmempty = true
|
||||
nm:depends("proto", "static")
|
||||
nm:value("255.255.255.0")
|
||||
nm:value("255.255.0.0")
|
||||
nm:value("255.0.0.0")
|
||||
|
||||
gw = s:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
|
||||
gw:depends("proto", "static")
|
||||
gw.rmempty = true
|
||||
|
||||
bcast = s:taboption("expert", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
|
||||
bcast:depends("proto", "static")
|
||||
|
||||
if has_ipv6 then
|
||||
ip6addr = s:taboption("expert", Value, "ip6addr", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Address"), translate("<abbr title=\"Classless Inter-Domain Routing\">CIDR</abbr>-Notation: address/prefix"))
|
||||
ip6addr:depends("proto", "static")
|
||||
|
||||
ip6gw = s:taboption("expert", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
|
||||
ip6gw:depends("proto", "static")
|
||||
end
|
||||
|
||||
dns = s:taboption("expert", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"))
|
||||
dns:depends("peerdns", "")
|
||||
|
||||
mtu = s:taboption("expert", Value, "mtu", "MTU")
|
||||
mtu.isinteger = true
|
||||
|
||||
mac = s:taboption("expert", Value, "macaddr", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
|
||||
|
||||
return m2, m
|
||||
|
||||
else
|
||||
|
||||
return m2
|
||||
|
||||
end
|
|
@ -1,12 +0,0 @@
|
|||
local t = Template("niu/network/wlanwanscan")
|
||||
function t.parse(self, ...)
|
||||
local state = Template.parse(self, ...)
|
||||
if Map.formvalue({readinput = true}, "cbi.delg.back") then
|
||||
return FORM_SKIP
|
||||
end
|
||||
if state == FORM_NODATA then
|
||||
self.delegator.disallow_pageactions = true
|
||||
end
|
||||
return state
|
||||
end
|
||||
return t
|
|
@ -1,34 +0,0 @@
|
|||
local cursor = require "luci.model.uci".cursor()
|
||||
local d = Delegator()
|
||||
d.allow_finish = true
|
||||
d.allow_back = true
|
||||
d.allow_cancel = true
|
||||
|
||||
d:add("general1", load("niu/system/general1"))
|
||||
|
||||
function d.on_cancel()
|
||||
cursor:revert("luci")
|
||||
end
|
||||
|
||||
function d.on_done()
|
||||
local pw1 = cursor:get("luci", "main", "_pw1")
|
||||
if pw1 and pw1 ~= "**********" then
|
||||
cursor:delete("luci", "main", "_pw1")
|
||||
require "luci.sys".user.setpasswd("root", pw1)
|
||||
end
|
||||
|
||||
local hn = cursor:get("luci", "main", "_uniquename")
|
||||
if hn then
|
||||
cursor:foreach("system", "system", function(s)
|
||||
cursor:set("system", s[".name"], "hostname", hn)
|
||||
end)
|
||||
cursor:commit("system")
|
||||
|
||||
require "nixio.fs".writefile("/proc/sys/kernel/hostname", hn)
|
||||
cursor:delete("luci", "main", "_uniquename")
|
||||
end
|
||||
|
||||
cursor:commit("luci")
|
||||
end
|
||||
|
||||
return d
|
|
@ -1,45 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local i18n = require "luci.i18n"
|
||||
local util = require "luci.util"
|
||||
local config = require "luci.config"
|
||||
|
||||
m = Map("luci", "Device Settings")
|
||||
|
||||
c = m:section(NamedSection, "main", "core", translate("Local Settings"))
|
||||
|
||||
hn = c:option(Value, "_uniquename", translate("Unique Devicename"))
|
||||
function hn:cfgvalue(self)
|
||||
return require "nixio.fs".readfile("/proc/sys/kernel/hostname")
|
||||
end
|
||||
|
||||
l = c:option(ListValue, "lang", translate("System Language"))
|
||||
l:value("auto")
|
||||
|
||||
local i18ndir = i18n.i18ndir .. "default."
|
||||
for k, v in util.kspairs(config.languages) do
|
||||
local file = i18ndir .. k:gsub("_", "-")
|
||||
if k:sub(1, 1) ~= "." and fs.access(file .. ".lmo") then
|
||||
l:value(k, v)
|
||||
end
|
||||
end
|
||||
|
||||
pw1 = c:option(Value, "_pw1", translate("Administrator Password"))
|
||||
pw1.password = true
|
||||
pw1.default = "**********"
|
||||
|
||||
|
||||
return m
|
|
@ -1 +0,0 @@
|
|||
local f = Form("reboot", "Rebooting Device", "Device is rebooting. Please wait...")
|
|
@ -1,20 +0,0 @@
|
|||
local uci = require "luci.model.uci"
|
||||
local cursor = uci.cursor()
|
||||
local d = Delegator()
|
||||
d.allow_finish = true
|
||||
d.allow_back = true
|
||||
d.allow_cancel = true
|
||||
|
||||
d:add("portfw1", load("niu/traffic/portfw1"))
|
||||
|
||||
function d.on_cancel()
|
||||
cursor:revert("firewall")
|
||||
cursor:revert("upnpd")
|
||||
end
|
||||
|
||||
function d.on_done()
|
||||
cursor:commit("firewall")
|
||||
cursor:commit("upnpd")
|
||||
end
|
||||
|
||||
return d
|
|
@ -1,65 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
local fs = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
|
||||
m = Map("firewall", translate("Manage Port Forwarding"))
|
||||
|
||||
s = m:section(TypedSection, "redirect", translate("Manual Port Forwarding"),
|
||||
translate([[To manually define a forwarding rule you have to specify at least
|
||||
the internal IP-address and port of the service that should be forwarded.
|
||||
If you ommit the external port it will be the same as the internal port.
|
||||
You also can forward a range of ports by using the syntax first-last Port
|
||||
(e.g. 1024-1030) in the port field.]]))
|
||||
s.template = "cbi/tblsection"
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
|
||||
name = s:option(Value, "_name", translate("Name"), translate("optional"))
|
||||
name.size = 10
|
||||
|
||||
iface = s:option(ListValue, "src", translate("Zone"))
|
||||
iface:value("wan", "Internet")
|
||||
iface.default = "wan"
|
||||
|
||||
proto = s:option(ListValue, "proto", translate("Protocol"))
|
||||
proto:value("tcp", "TCP")
|
||||
proto:value("udp", "UDP")
|
||||
proto:value("tcpudp", "TCP+UDP")
|
||||
|
||||
dport = s:option(Value, "src_dport", translate("Internal Port"))
|
||||
dport.size = 5
|
||||
|
||||
to = s:option(Value, "dest_ip", translate("Internal Address"), translate("Device running the service"))
|
||||
for i, dataset in ipairs(sys.net.arptable()) do
|
||||
to:value(dataset["IP address"])
|
||||
end
|
||||
|
||||
toport = s:option(Value, "dest_port", translate("External Port"), translate("optional"));
|
||||
toport.size = 5
|
||||
|
||||
local m2
|
||||
if fs.access("/etc/config/upnpd") then
|
||||
m2 = Map("upnpd")
|
||||
s = m2:section(NamedSection, "config", "upnpd", translate("Automatic Port Forwarding (UPnP IGD)"),
|
||||
translate([[Allows UPnP-capable applications to automatically forward ports on the router to their IP-Address.
|
||||
Be aware that this is a potential security risk as applications are not authenticated.]]))
|
||||
s.addremove = false
|
||||
|
||||
on = s:option(ListValue, "external_iface", translate("Port Forwarding Restrictions"))
|
||||
on:value("none", translate("Manual Forwarding Only"))
|
||||
on:value("wan", translate("Automatic and Manual Forwarding"))
|
||||
end
|
||||
|
||||
return m, m2
|
|
@ -1,36 +0,0 @@
|
|||
local uci = require "luci.model.uci"
|
||||
local cursor = uci.cursor()
|
||||
|
||||
if not cursor:get("qos", "wan", "_niuinit") then
|
||||
-- Load some more sensible default classifications
|
||||
cursor:delete_all("qos", "classify")
|
||||
cursor:section("qos", "classify", "dns",
|
||||
{target = "Priority", ports = "53", _name = "DNS"}
|
||||
)
|
||||
cursor:section("qos", "classify", "inet1",
|
||||
{target = "Normal", ports = "20,21,22,80,443", _name = "WWW, SSH, FTP"}
|
||||
)
|
||||
cursor:section("qos", "classify", "inet2",
|
||||
{target = "Normal", ports = "25,110,119,143", _name = "E-Mail, News"}
|
||||
)
|
||||
|
||||
cursor:set("qos", "wan", "_niuinit", "1")
|
||||
cursor:save("qos")
|
||||
end
|
||||
|
||||
local d = Delegator()
|
||||
d.allow_finish = true
|
||||
d.allow_back = true
|
||||
d.allow_cancel = true
|
||||
|
||||
d:add("qos1", load("niu/traffic/qos1"))
|
||||
|
||||
function d.on_cancel()
|
||||
cursor:revert("qos")
|
||||
end
|
||||
|
||||
function d.on_done()
|
||||
cursor:commit("qos")
|
||||
end
|
||||
|
||||
return d
|
|
@ -1,89 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local sys = require "luci.sys"
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
m = Map("qos", translate("Manage Prioritization (QoS)"), translate([[Different
|
||||
kinds of network traffic usually have different transmission requirements.
|
||||
For example the important factor for a large HTTP-download is bandwith whereas
|
||||
VoIP has a large focus on low packet latency. Prioritization takes these quality
|
||||
of service factors into account and optimizes priorities to allow reasonable
|
||||
performance for time critical services.]]))
|
||||
|
||||
s = m:section(NamedSection, "wan", "interface", translate("General Settings"),
|
||||
translate([[For QoS to work correctly you need to provide the upload and
|
||||
download speed of your internet connection. Values are in kilobits per second.
|
||||
For comparison a standard consumer ADSL connection has between 1000 and 25000
|
||||
kbps as donwload speed and between 128 and 1000 kbps upload speed.]]))
|
||||
s.addremove = false
|
||||
|
||||
local en = s:option(ListValue, "enabled", translate("Prioritization"))
|
||||
en:value("1", "Enable Quality of Service")
|
||||
en:value("0", "Disable")
|
||||
|
||||
local dl = s:option(Value, "download", translate("Maximum Download Speed"), "kbps")
|
||||
dl:depends("enabled", "1")
|
||||
|
||||
local ul = s:option(Value, "upload", translate("Maximum Upload Speed"), "kbps")
|
||||
ul:depends("enabled", "1")
|
||||
|
||||
s = m:section(TypedSection, "classify", translate("Finetuning"), translate([[
|
||||
The QoS application provides different useful default prioritization rules not
|
||||
listed here that cover many common use-cases. You however can add custom rules
|
||||
to finetune the prioritization process.]]))
|
||||
s.template = "cbi/tblsection"
|
||||
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
|
||||
n = s:option(Value, "_name", translate("Name"), translate("optional"))
|
||||
|
||||
srch = s:option(Value, "srchost", translate("Local IP-Address"))
|
||||
srch.rmempty = true
|
||||
srch:value("", translate("all"))
|
||||
for i, dataset in ipairs(sys.net.arptable()) do
|
||||
srch:value(dataset["IP address"])
|
||||
end
|
||||
|
||||
p = s:option(ListValue, "proto", translate("Protocol"))
|
||||
p:value("", translate("all"))
|
||||
p:value("tcp", "TCP")
|
||||
p:value("udp", "UDP")
|
||||
p.rmempty = true
|
||||
|
||||
ports = s:option(Value, "ports", translate("Ports"))
|
||||
ports.rmempty = true
|
||||
ports:value("", translate("any"))
|
||||
|
||||
if fs.access("/etc/l7-protocols") then
|
||||
l7 = s:option(ListValue, "layer7", translate("Service"))
|
||||
l7.rmempty = true
|
||||
l7:value("", translate("all"))
|
||||
for f in fs.glob("/etc/l7-protocols/*.pat") do
|
||||
l7:value(f:sub(19, #f-4))
|
||||
end
|
||||
end
|
||||
|
||||
s:option(Value, "connbytes", translate("Bytes sent"), translate("from[-to]"))
|
||||
|
||||
t = s:option(ListValue, "target", translate("Priority"))
|
||||
t:value("Priority", translate("Highest"))
|
||||
t:value("Express", translate("High"))
|
||||
t:value("Normal", translate("Normal"))
|
||||
t:value("Bulk", translate("Low"))
|
||||
t.default = "Normal"
|
||||
|
||||
return m
|
|
@ -1,17 +0,0 @@
|
|||
local cursor = require "luci.model.uci".cursor()
|
||||
local d = Delegator()
|
||||
d.allow_finish = true
|
||||
d.allow_back = true
|
||||
d.allow_cancel = true
|
||||
|
||||
d:add("routes1", load("niu/traffic/routes1"))
|
||||
|
||||
function d.on_cancel()
|
||||
cursor:revert("network")
|
||||
end
|
||||
|
||||
function d.on_done()
|
||||
cursor:commit("network")
|
||||
end
|
||||
|
||||
return d
|
|
@ -1,57 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
m = Map("network", translate("Manage Traffic Routing"),
|
||||
translate("With additional static routes you allow computers on your network to reach unannounced remote hosts or networks."))
|
||||
|
||||
local routes6 = luci.sys.net.routes6()
|
||||
local bit = require "bit"
|
||||
|
||||
m:append(Template("niu/network/rtable"))
|
||||
|
||||
s = m:section(TypedSection, "route", "Static IPv4 Routes")
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
|
||||
s.template = "cbi/tblsection"
|
||||
|
||||
iface1 = s:option(ListValue, "interface", translate("Interface"))
|
||||
|
||||
s:option(Value, "target", translate("Target"), translate("Host-<abbr title=\"Internet Protocol Address\">IP</abbr> or Network"))
|
||||
s:option(Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"), translate("if target is a network")).rmemepty = true
|
||||
s:option(Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
|
||||
|
||||
if routes6 then
|
||||
s = m:section(TypedSection, "route6", "Static IPv6 Routes")
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
|
||||
s.template = "cbi/tblsection"
|
||||
|
||||
iface2 = s:option(ListValue, "interface", translate("Interface"))
|
||||
|
||||
s:option(Value, "target", translate("Target"), translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Address or Network (CIDR)"))
|
||||
s:option(Value, "gateway", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway")).rmempty = true
|
||||
end
|
||||
|
||||
m.uci:foreach("network", "interface", function(s)
|
||||
if s[".name"] ~= "loopback" then
|
||||
iface:value(s[".name"])
|
||||
if iface2 then
|
||||
iface2:value(s[".name"])
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
return m
|
|
@ -1,52 +0,0 @@
|
|||
local cursor = require "luci.model.uci".cursor()
|
||||
|
||||
if not cursor:get("wireless", "ap") then
|
||||
cursor:section("wireless", "wifi-iface", "ap",
|
||||
{device = "_", doth = "1", _niu = "1", mode = "ap"})
|
||||
cursor:save("wireless")
|
||||
end
|
||||
|
||||
local function deviceroute(self)
|
||||
cursor:unload("wireless")
|
||||
local d = cursor:get("wireless", "ap", "device")
|
||||
local t = cursor:get("wireless", "ap", "_cfgtpl")
|
||||
if d ~= "none" then
|
||||
cursor:delete_all("wireless", "wifi-iface", function(s)
|
||||
return s.device == d and s._niu ~= "1"
|
||||
end)
|
||||
cursor:set("wireless", d, "disabled", 0)
|
||||
cursor:set("wireless", "ap", "network", "lan")
|
||||
if t and #t > 0 then
|
||||
cursor:delete("wireless", "ap", "_cfgtpl")
|
||||
cursor:set("wireless", "ap", "ssid", cursor:get("wireless", "bridge", "ssid"))
|
||||
cursor:set("wireless", "ap", "encryption", cursor:get("wireless", "bridge", "encryption"))
|
||||
cursor:set("wireless", "ap", "key", cursor:get("wireless", "bridge", "key"))
|
||||
cursor:set("wireless", "ap", "wds", "1")
|
||||
end
|
||||
|
||||
self:set_route("ap1")
|
||||
else
|
||||
cursor:delete("wireless", "ap", "network")
|
||||
end
|
||||
cursor:save("wireless")
|
||||
end
|
||||
|
||||
|
||||
local d = Delegator()
|
||||
d.allow_finish = true
|
||||
d.allow_back = true
|
||||
d.allow_cancel = true
|
||||
|
||||
d:add("device", "niu/wireless/apdevice")
|
||||
d:add("deviceroute", deviceroute)
|
||||
d:set("ap1", "niu/wireless/ap1")
|
||||
|
||||
function d.on_cancel()
|
||||
cursor:revert("wireless")
|
||||
end
|
||||
|
||||
function d.on_done()
|
||||
cursor:commit("wireless")
|
||||
end
|
||||
|
||||
return d
|
|
@ -1,310 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local iface = "ap"
|
||||
local ap = true
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
local cursor = require "luci.model.uci".inst
|
||||
local state = require "luci.model.uci".inst_state
|
||||
cursor:unload("wireless")
|
||||
|
||||
|
||||
local device = cursor:get("wireless", iface, "device")
|
||||
local hwtype = cursor:get("wireless", device, "type")
|
||||
|
||||
local nsantenna = cursor:get("wireless", device, "antenna")
|
||||
|
||||
local iw = nil
|
||||
local tx_powers = {}
|
||||
local chan = {}
|
||||
|
||||
state:foreach("wireless", "wifi-iface",
|
||||
function(s)
|
||||
if s.device == device and not iw then
|
||||
iw = sys.wifi.getiwinfo(s.ifname or s.device)
|
||||
chan = iw and iw.freqlist or { }
|
||||
tx_powers = iw.txpwrlist or { }
|
||||
end
|
||||
end)
|
||||
|
||||
local m
|
||||
|
||||
|
||||
if ap then
|
||||
m = Map("wireless", translate("Configure Access Point"))
|
||||
end
|
||||
|
||||
--- Device Settings ---
|
||||
s = m:section(NamedSection, device, "wifi-device", "Device Configuration")
|
||||
s.addremove = false
|
||||
|
||||
s:tab("general", translate("General Settings"))
|
||||
|
||||
ch = s:taboption("general", Value, "channel", translate("Channel"))
|
||||
ch:value("auto", translate("automatic"))
|
||||
for _, f in ipairs(chan) do
|
||||
ch:value(f.channel, "%i (%.3f GHz)" %{ f.channel, f.mhz / 1000 })
|
||||
end
|
||||
|
||||
|
||||
|
||||
s:tab("expert", translate("Expert Settings"))
|
||||
if hwtype == "mac80211" then
|
||||
local macaddr = cursor:get("wireless", device, "macaddr") or "!"
|
||||
local hwmode = cursor:get("wireless", device, "hwmode")
|
||||
local modes = {}
|
||||
local phy
|
||||
local allowed = {}
|
||||
for entry in fs.glob("/sys/class/ieee80211/*") do
|
||||
if (fs.readfile(entry .. "/macaddress") or ""):find(macaddr) == 1 then
|
||||
phy = entry:sub(22)
|
||||
end
|
||||
end
|
||||
if phy then
|
||||
local iwp = io.popen("iw phy " .. phy .. " info")
|
||||
local iwin = iwp:read("*a")
|
||||
|
||||
if iwp then
|
||||
iwp:close()
|
||||
local htcap = iwin:match("HT capabilities:%s*0x([0-9a-fA-F]+)")
|
||||
allowed.n = (htcap and tonumber(htcap, 16) or 0) > 0
|
||||
allowed.g = iwin:find("2412 MHz")
|
||||
allowed.a = iwin:find("5180 MHz")
|
||||
end
|
||||
end
|
||||
|
||||
if next(allowed) then
|
||||
mode = s:taboption("expert", ListValue, "hwmode", translate("Communication Protocol"))
|
||||
if allowed.n and allowed.g then
|
||||
mode:value("11ng", "802.11n (2.4 GHz)")
|
||||
end
|
||||
if allowed.n and allowed.a then
|
||||
mode:value("11na", "802.11n (5 GHz)")
|
||||
end
|
||||
if allowed.a then
|
||||
mode:value("11a", "802.11a (5 GHz)")
|
||||
end
|
||||
if allowed.g then
|
||||
mode:value("11g", "802.11g (2.4 GHz)")
|
||||
mode:value("11bg", "802.11b+g (2.4 GHz)")
|
||||
mode:value("11b", "802.11b (2.4 GHz)")
|
||||
end
|
||||
end
|
||||
|
||||
tp = s:taboption("expert",
|
||||
(tx_powers and #tx_powers > 0) and ListValue or Value,
|
||||
"txpower", translate("Transmission Power"), "dBm")
|
||||
|
||||
tp.rmempty = true
|
||||
tp:value("", translate("automatic"))
|
||||
for _, p in ipairs(iw and iw.txpwrlist or {}) do
|
||||
tp:value(p.dbm, "%i dBm (%i mW)" %{ p.dbm, p.mw })
|
||||
end
|
||||
elseif hwtype == "atheros" then
|
||||
tp = s:taboption("expert",
|
||||
(#tx_powers > 0) and ListValue or Value,
|
||||
"txpower", translate("Transmission Power"), "dBm")
|
||||
|
||||
tp.rmempty = true
|
||||
tp:value("", translate("automatic"))
|
||||
for _, p in ipairs(iw.txpwrlist) do
|
||||
tp:value(p.dbm, "%i dBm (%i mW)" %{ p.dbm, p.mw })
|
||||
end
|
||||
|
||||
mode = s:taboption("expert", ListValue, "hwmode", translate("Communication Protocol"))
|
||||
mode:value("", translate("automatic"))
|
||||
mode:value("11g", "802.11g")
|
||||
mode:value("11b", "802.11b")
|
||||
mode:value("11bg", "802.11b+g")
|
||||
mode:value("11a", "802.11a")
|
||||
mode:value("11gst", "802.11g + Turbo")
|
||||
mode:value("11ast", "802.11a + Turbo")
|
||||
|
||||
if nsantenna then -- NanoFoo
|
||||
local ant = s:taboption("expert", ListValue, "antenna", translate("Transmitter Antenna"))
|
||||
ant:value("auto")
|
||||
ant:value("vertical")
|
||||
ant:value("horizontal")
|
||||
ant:value("external")
|
||||
ant.default = "auto"
|
||||
end
|
||||
elseif hwtype == "broadcom" then
|
||||
tp = s:taboption("expert",
|
||||
(#tx_powers > 0) and ListValue or Value,
|
||||
"txpower", translate("Transmit Power"), "dBm")
|
||||
|
||||
tp.rmempty = true
|
||||
tp:value("", translate("automatic"))
|
||||
for _, p in ipairs(iw.txpwrlist) do
|
||||
tp:value(p.dbm, "%i dBm (%i mW)" %{ p.dbm, p.mw })
|
||||
end
|
||||
|
||||
mp = s:taboption("expert", ListValue, "macfilter", translate("MAC-Address Filter"))
|
||||
mp:value("", translate("disable"))
|
||||
mp:value("allow", translate("Allow listed only"))
|
||||
mp:value("deny", translate("Allow all except listed"))
|
||||
ml = s:taboption("expert", DynamicList, "maclist", translate("MAC-List"))
|
||||
ml:depends({macfilter="allow"})
|
||||
ml:depends({macfilter="deny"})
|
||||
|
||||
s:taboption("expert", Flag, "frameburst", translate("Allow Burst Transmissions"))
|
||||
elseif hwtype == "prism2" then
|
||||
s:taboption("expert", Value, "txpower", translate("Transmission Power"), "att units").rmempty = true
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
s = m:section(NamedSection, iface, "wifi-iface", translate("Interface Details"))
|
||||
s.addremove = false
|
||||
|
||||
s:tab("general", translate("General Settings"))
|
||||
s:tab("expert", translate("Expert Settings"))
|
||||
|
||||
|
||||
|
||||
local ssid = s:taboption("general", Value, "ssid", translate("Network Name (<abbr title=\"Extended Service Set Identifier\">ESSID</abbr>)"))
|
||||
|
||||
mode = s:taboption("expert", ListValue, "mode", translate("Operating Mode"))
|
||||
mode.override_values = true
|
||||
mode:value("ap", translate("Access Point"))
|
||||
|
||||
encr = s:taboption("expert", ListValue, "encryption", translate("Encryption"))
|
||||
|
||||
|
||||
if hwtype == "mac80211" then
|
||||
mode:value("mesh", translate("Mesh (802.11s)"))
|
||||
local meshid = s:taboption("expert", Value, "mesh_id", translate("Mesh ID"))
|
||||
meshid:depends("mode", "mesh")
|
||||
|
||||
s:taboption("expert", Flag, "wds", translate("Enable Bridging and Repeating (WDS)")):depends("mode", "ap")
|
||||
s:taboption("expert", Flag, "powersave", translate("Enable Powersaving")):depends("mode", "ap")
|
||||
elseif hwtype == "atheros" then
|
||||
-- mode:value("wds", translate("Static WDS"))
|
||||
|
||||
mp = s:taboption("expert", ListValue, "macpolicy", translate("MAC-Address Filter"))
|
||||
mp:value("", translate("disable"))
|
||||
mp:value("deny", translate("Allow listed only"))
|
||||
mp:value("allow", translate("Allow all except listed"))
|
||||
ml = s:taboption("expert", DynamicList, "maclist", translate("MAC-List"))
|
||||
ml:depends({macpolicy="allow"})
|
||||
ml:depends({macpolicy="deny"})
|
||||
|
||||
s:taboption("expert", Flag, "wds", translate("Enable Bridging and Repeating (WDS)"))
|
||||
|
||||
if ap then
|
||||
hidden = s:taboption("expert", Flag, "hidden", translate("Hide Access Point"))
|
||||
hidden:depends({mode="ap"})
|
||||
hidden:depends({mode="ap-wds"})
|
||||
|
||||
isolate = s:taboption("expert", Flag, "isolate", translate("Prevent communication between clients"))
|
||||
isolate:depends({mode="ap"})
|
||||
end
|
||||
|
||||
s:taboption("expert", Flag, "bursting", translate("Allow Burst Transmissions"))
|
||||
elseif hwtype == "broadcom" then
|
||||
if ap then
|
||||
hidden = s:taboption("expert", Flag, "hidden", translate("Hide Access Point"))
|
||||
hidden:depends({mode="ap"})
|
||||
hidden:depends({mode="wds"})
|
||||
|
||||
isolate = s:taboption("expert", Flag, "isolate", translate("Prevent communication between clients"))
|
||||
isolate:depends({mode="ap"})
|
||||
end
|
||||
elseif hwtype == "prism2" then
|
||||
mp = s:taboption("expert", ListValue, "macpolicy", translate("MAC-Address Filter"))
|
||||
mp:value("", translate("disable"))
|
||||
mp:value("deny", translate("Allow listed only"))
|
||||
mp:value("allow", translate("Allow all except listed"))
|
||||
|
||||
ml = s:taboption("expert", DynamicList, "maclist", translate("MAC-List"))
|
||||
ml:depends({macpolicy="allow"})
|
||||
ml:depends({macpolicy="deny"})
|
||||
|
||||
if ap then
|
||||
hidden = s:taboption("expert", Flag, "hidden", translate("Hide Access Point"))
|
||||
hidden:depends({mode="ap"})
|
||||
hidden:depends({mode="wds"})
|
||||
end
|
||||
end
|
||||
|
||||
-- Encryption --
|
||||
|
||||
encr.default = "wep" -- Early default
|
||||
encr.override_values = true
|
||||
encr.override_depends = true
|
||||
encr:value("none", "No Encryption")
|
||||
encr:value("wep", "WEP", {mode="ap"})
|
||||
|
||||
if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
|
||||
local hostapd = fs.access("/usr/sbin/hostapd") or os.getenv("LUCI_SYSROOT")
|
||||
local supplicant = fs.access("/usr/sbin/wpa_supplicant") or os.getenv("LUCI_SYSROOT")
|
||||
|
||||
if hostapd and not supplicant then
|
||||
encr:value("psk", "WPA", {mode="ap"})
|
||||
encr:value("wpa", "WPA-EAP", {mode="ap"})
|
||||
encr:value("psk-mixed", "WPA + WPA2", {mode="ap"})
|
||||
encr:value("psk2", "WPA2", {mode="ap"})
|
||||
encr:value("wpa2", "WPA2-EAP (802.11i)", {mode="ap"})
|
||||
encr.default = "psk-mixed"
|
||||
elseif not hostapd and supplicant then
|
||||
encr:value("psk", "WPA", {mode="mesh"})
|
||||
encr:value("psk2", "WPA2", {mode="mesh"})
|
||||
encr.default = "psk2"
|
||||
elseif hostapd and supplicant then
|
||||
encr:value("psk", "WPA", {mode="ap"}, {mode="mesh"})
|
||||
encr:value("wpa", "WPA-EAP", {mode="ap"})
|
||||
encr:value("psk-mixed", "WPA + WPA2", {mode="ap"})
|
||||
encr:value("psk2", "WPA2", {mode="ap"}, {mode="mesh"})
|
||||
encr:value("wpa2", "WPA2-EAP (802.11i)", {mode="ap"})
|
||||
encr.default = "psk-mixed"
|
||||
end
|
||||
elseif hwtype == "broadcom" then
|
||||
encr:value("psk", "WPA")
|
||||
encr:value("psk+psk2", "WPA + WPA2")
|
||||
encr:value("psk2", "WPA2")
|
||||
encr.default = "psk+psk2"
|
||||
end
|
||||
|
||||
server = s:taboption("general", Value, "server", translate("Radius-Server"))
|
||||
server:depends({mode="ap", encryption="wpa"})
|
||||
server:depends({mode="ap", encryption="wpa2"})
|
||||
server.rmempty = true
|
||||
|
||||
port = s:taboption("general", Value, "port", translate("Radius-Port"))
|
||||
port:depends({mode="ap", encryption="wpa"})
|
||||
port:depends({mode="ap", encryption="wpa2"})
|
||||
port.rmempty = true
|
||||
|
||||
key = s:taboption("general", Value, "key", translate("Password"))
|
||||
key:depends("encryption", "wep")
|
||||
key:depends("encryption", "psk")
|
||||
key:depends("encryption", "psk2")
|
||||
key:depends("encryption", "psk+psk2")
|
||||
key:depends("encryption", "psk-mixed")
|
||||
key:depends({mode="ap", encryption="wpa"})
|
||||
key:depends({mode="ap", encryption="wpa2"})
|
||||
key.rmempty = true
|
||||
key.password = true
|
||||
|
||||
if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
|
||||
nasid = s:taboption("general", Value, "nasid", translate("NAS ID"))
|
||||
nasid:depends({mode="ap", encryption="wpa"})
|
||||
nasid:depends({mode="ap", encryption="wpa2"})
|
||||
nasid.rmempty = true
|
||||
end
|
||||
return m
|
|
@ -1,46 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
local niulib = require "luci.niulib"
|
||||
local cursor = require "luci.model.uci".inst
|
||||
|
||||
m = Map("wireless", translate("Configure Private Access Point"))
|
||||
s = m:section(NamedSection, "ap", "wifi-iface", translate("Wireless Radio Device"),
|
||||
translate(
|
||||
"Select the wireless radio device that should be used to run the interface."..
|
||||
" Note that wireless radios will not show up here if you already use"..
|
||||
" them for other wireless services and are not capable of being used by"..
|
||||
" more than one service simultaneously or run this specific service at all."))
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
local l = s:option(ListValue, "device", translate("Wireless Device"))
|
||||
|
||||
for _, wifi in ipairs(niulib.wifi_get_available("ap")) do
|
||||
l:value(wifi, translate("WLAN-Adapter (%s)") % wifi)
|
||||
end
|
||||
l:value("none", translate("Disable Private Access Point"))
|
||||
|
||||
|
||||
local extend = cursor:get("wireless", "bridge", "network")
|
||||
and cursor:get("wireless", "bridge", "ssid")
|
||||
|
||||
if extend ~= cursor:get("wireless", "ap", "ssid") then
|
||||
local templ = s:option(ListValue, "_cfgtpl", translate("Configuration Template"))
|
||||
templ:depends({["!default"] = 1})
|
||||
templ:depends({["!reverse"] = 1, device = "none"})
|
||||
templ:value("", translate("Access Point (Current Settings)"))
|
||||
templ:value("bridge", translate("Extend network %s") % extend)
|
||||
end
|
||||
|
||||
return m
|
|
@ -1,33 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
local niulib = require "luci.niulib"
|
||||
|
||||
m = Map("wireless", translate("Join a local WDS network"))
|
||||
s = m:section(NamedSection, "bridge", "wifi-iface", translate("Wireless Radio Device"),
|
||||
translate(
|
||||
"Select the wireless radio device that should be used to run the interface."..
|
||||
" Note that wireless radios will not show up here if you already use"..
|
||||
" them for other wireless services and are not capable of being used by"..
|
||||
" more than one service simultaneously or run this specific service at all."))
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
l = s:option(ListValue, "device", translate("Wireless Device"))
|
||||
|
||||
for _, wifi in ipairs(niulib.wifi_get_available("bridge", {atheros = true, mac80211 = true})) do
|
||||
l:value(wifi, translate("WLAN-Adapter (%s)") % wifi)
|
||||
end
|
||||
l:value("none", translate("Disable Bridge"))
|
||||
|
||||
return m
|
|
@ -1,91 +0,0 @@
|
|||
local uci = require "luci.model.uci"
|
||||
local cursor = uci.cursor()
|
||||
|
||||
if not cursor:get("wireless", "bridge") then
|
||||
cursor:section("wireless", "wifi-iface", "bridge",
|
||||
{device = "_", doth = "1", _niu = "1", mode = "sta", wds = "1"})
|
||||
cursor:save("wireless")
|
||||
end
|
||||
|
||||
local function deviceroute(self)
|
||||
cursor:unload("wireless")
|
||||
local d = cursor:get("wireless", "bridge", "device")
|
||||
if d ~= "none" then
|
||||
local nc = uci.cursor(nil, "")
|
||||
cursor:delete_all("wireless", "wifi-iface", function(s)
|
||||
return s.device == d and s._niu ~= "1"
|
||||
end)
|
||||
if nc:get("wireless", "bridge", "network")
|
||||
~= cursor:get("wireless", "bridge", "network") then
|
||||
cursor:delete("wireless", "bridge", "network")
|
||||
end
|
||||
cursor:set("wireless", d, "disabled", 0)
|
||||
cursor:foreach("dhcp", "dhcp", function(s)
|
||||
if s.interface == "lan" and s.ignore ~= "1" then
|
||||
cursor:set("dhcp", s[".name"], "ignore", "1")
|
||||
end
|
||||
end)
|
||||
self:set_route("scan", "bridge", "bridgelan")
|
||||
else
|
||||
if cursor:get("wireless", "bridge", "network") then
|
||||
cursor:delete("wireless", "bridge", "network")
|
||||
cursor:foreach("dhcp", "dhcp", function(s)
|
||||
if s.interface == "lan" and s.ignore == "1" then
|
||||
cursor:set("dhcp", s[".name"], "ignore", "0")
|
||||
end
|
||||
end)
|
||||
self:set_route("lan")
|
||||
end
|
||||
end
|
||||
cursor:save("dhcp")
|
||||
cursor:save("wireless")
|
||||
end
|
||||
|
||||
|
||||
local d = Delegator()
|
||||
d.allow_finish = true
|
||||
d.allow_back = true
|
||||
d.allow_cancel = true
|
||||
|
||||
d:add("device", "niu/wireless/brdevice")
|
||||
d:add("deviceroute", deviceroute)
|
||||
d:set("scan", "niu/network/wlanwanscan")
|
||||
d:set("bridge", "niu/network/wlanwan")
|
||||
d:set("bridgelan", "niu/network/lan1")
|
||||
d:set("lan", "niu/network/lan1")
|
||||
|
||||
function d.on_cancel()
|
||||
cursor:revert("network")
|
||||
cursor:revert("wireless")
|
||||
cursor:revert("dhcp")
|
||||
end
|
||||
|
||||
function d.on_done()
|
||||
if uci.inst_state:get("network", "lan", "ipaddr") ~= cursor:get("network", "lan", "ipaddr") then
|
||||
local cs = uci.cursor_state()
|
||||
cs:set("network", "lan", "_ipchanged", "1")
|
||||
cs:save("network")
|
||||
end
|
||||
|
||||
if cursor:get("network", "lan", "proto") == "dhcp" then
|
||||
local emergv4 = cursor:get("network", "lan", "_emergv4")
|
||||
if emergv4 then
|
||||
if cursor:get("network", "lan_ea") then
|
||||
cursor:set("network", "lan_ea", "ipaddr", emergv4)
|
||||
else
|
||||
cursor:section("network", "alias", "lan_ea", {
|
||||
ipaddr = emergv4,
|
||||
netmask = "255.255.255.0",
|
||||
network = "lan"
|
||||
})
|
||||
end
|
||||
else
|
||||
cursor:delete("network", "lan_ea")
|
||||
end
|
||||
end
|
||||
cursor:commit("network")
|
||||
cursor:commit("wireless")
|
||||
cursor:commit("dhcp")
|
||||
end
|
||||
|
||||
return d
|
|
@ -1,81 +0,0 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2009 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local ipairs, pairs, require = ipairs, pairs, require
|
||||
local os = require "os"
|
||||
|
||||
local uci = require "luci.model.uci"
|
||||
local cursor = uci.inst
|
||||
local state = uci.inst_state
|
||||
|
||||
|
||||
module "luci.niulib"
|
||||
|
||||
function eth_get_available(except)
|
||||
local nw = require "luci.model.network"
|
||||
nw.init(cursor)
|
||||
|
||||
local ifs = {}
|
||||
for _, iface in ipairs(nw.get_interfaces()) do
|
||||
if iface:name():find("eth") == 1 then
|
||||
local net = iface:get_network()
|
||||
if not net or net:name() == except or os.getenv("LUCI_SYSROOT") then
|
||||
ifs[#ifs+1] = iface:name()
|
||||
end
|
||||
end
|
||||
end
|
||||
return ifs
|
||||
end
|
||||
|
||||
function eth_get_bridged(except)
|
||||
local devs = state:get("network", except, "device") or ""
|
||||
|
||||
local ifs = {}
|
||||
local cnt = 0
|
||||
for x in devs:gmatch("[^ ]+") do
|
||||
cnt = cnt + 1
|
||||
if x:find("eth") == 1 then
|
||||
ifs[#ifs+1] = x
|
||||
end
|
||||
end
|
||||
return cnt > 1 and ifs or {}
|
||||
end
|
||||
|
||||
function wifi_get_available(except, types)
|
||||
cursor:unload("wireless")
|
||||
|
||||
local iwinfo = require "iwinfo"
|
||||
local used = {}
|
||||
cursor:foreach("wireless", "wifi-iface", function(s)
|
||||
if s[".name"] ~= except and s._niu == 1 then
|
||||
used[s.device] = 1
|
||||
end
|
||||
end)
|
||||
|
||||
for k in pairs(used) do
|
||||
local t = iwinfo.type(k)
|
||||
if t and iwinfo[t] then
|
||||
used[k] = (iwinfo[t].mbssid_support(k) < 1)
|
||||
end
|
||||
end
|
||||
|
||||
local wifis = {}
|
||||
cursor:foreach("wireless", "wifi-device", function(s)
|
||||
if not used[s[".name"]] and (not types or types[s.type]) then
|
||||
wifis[#wifis+1] = s[".name"]
|
||||
end
|
||||
end)
|
||||
return wifis
|
||||
end
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
<%
|
||||
local dsp = require "luci.dispatcher"
|
||||
local utl = require "luci.util"
|
||||
|
||||
include("header")
|
||||
|
||||
local function cmp(a, b)
|
||||
return (nodes[a].order or 100) < (nodes[b].order or 100)
|
||||
end
|
||||
for k, v in utl.spairs(nodes, cmp) do
|
||||
if v.niu_dbtemplate or v.niu_dbtasks then
|
||||
%>
|
||||
<fieldset class="dbbox">
|
||||
<h2<% if v.niu_dbicon then %> style="background-image: url(<%=resource%>/<%=v.niu_dbicon%>)"<% end %>><%=v.title%></h2>
|
||||
<% if v.niu_dbtemplate then tpl.render(v.niu_dbtemplate) end %>
|
||||
<% if v.niu_dbtasks then %>
|
||||
<h4>Tasks:</h4>
|
||||
<ul>
|
||||
<%
|
||||
local nodes = dsp.node("niu", k).nodes
|
||||
local function cmp(a, b)
|
||||
return (nodes[a].order or 100) < (nodes[b].order or 100)
|
||||
end
|
||||
for k2, v2 in utl.spairs(nodes, cmp) do
|
||||
%>
|
||||
<li><a href="<%=dsp.build_url("niu", k, k2)%>"><%=v2.title%></a></li>
|
||||
<%
|
||||
end
|
||||
%>
|
||||
</ul>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
<%
|
||||
end
|
||||
end
|
||||
|
||||
%>
|
||||
|
||||
<%+footer%>
|
|
@ -1,75 +0,0 @@
|
|||
<%
|
||||
local uci = require "luci.model.uci"
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
local nws = {}
|
||||
uci.inst_state:foreach("network", "interface", function(s)
|
||||
nws[#nws+1] = s
|
||||
end)
|
||||
|
||||
if uci.inst_state:get("network", "lan", "_ipchanged") and
|
||||
uci.inst_state:revert("network", "lan", "_ipchanged") then
|
||||
include("niu/network/warn_ip_change")
|
||||
end
|
||||
|
||||
local wanon = uci.inst_state:get("network", "wan", "proto")
|
||||
local wanup = uci.inst_state:get("network", "wan", "up")
|
||||
local wanip = uci.inst_state:get("network", "wan", "ipaddr")
|
||||
|
||||
local leasefn
|
||||
uci.inst:foreach("dhcp", "dnsmasq",
|
||||
function(section)
|
||||
leasefn = section.leasefile
|
||||
end
|
||||
)
|
||||
|
||||
if leasefn then
|
||||
local ln = fs.access(leasefn, "r") and io.lines(leasefn)
|
||||
leasefn = 0
|
||||
while ln and ln() do
|
||||
leasefn = leasefn + 1
|
||||
end
|
||||
end
|
||||
|
||||
local arps
|
||||
if fs.access("/proc/net/arp", "r") then
|
||||
local ln = io.lines("/proc/net/arp")
|
||||
arps = -1
|
||||
while ln and ln() do
|
||||
arps = arps + 1
|
||||
end
|
||||
arps = arps >= 0 and arps
|
||||
end
|
||||
%>
|
||||
|
||||
<table class="dbstattbl">
|
||||
<% if wanon and wanon ~= "none" then %>
|
||||
<tr>
|
||||
<% if wanup then %>
|
||||
<th>Uplink Address:</th>
|
||||
<td><%=wanip%></td>
|
||||
<% else %>
|
||||
<th>Uplink:</th>
|
||||
<td><span style="color: darkred"><em>offline</em></span>
|
||||
</td>
|
||||
<% end %>
|
||||
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
<tr>
|
||||
<th>Local Address:</th><td>
|
||||
<%=uci.inst_state:get("network", "lan", "ipaddr")%>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<% if arps then %>
|
||||
<tr>
|
||||
<th>Active IP-Devices:</th><td><%=arps%><% if leasefn then %>
|
||||
(<%=leasefn%> assigned)
|
||||
<% end %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
</table>
|
||||
<br />
|
|
@ -1,112 +0,0 @@
|
|||
<%#
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2008-2009 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2009 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
-%>
|
||||
|
||||
<%-
|
||||
local fs = require "nixio.fs"
|
||||
local bit = require "nixio".bit
|
||||
local sys = require "luci.sys"
|
||||
local uci = require "luci.model.uci"
|
||||
local inst = uci.inst
|
||||
local state = uci.inst_state
|
||||
local http = require "luci.http"
|
||||
local style = true
|
||||
|
||||
|
||||
local ifc = {__index = function(self, key)
|
||||
local net = key
|
||||
state:foreach("network", "interface", function(s)
|
||||
if s.ifname == key then
|
||||
net = s[".name"]
|
||||
end
|
||||
end)
|
||||
rawset(self, key, net)
|
||||
return net
|
||||
end}
|
||||
setmetatable(ifc, ifc)
|
||||
|
||||
if http.formvalue("toggle_rtable") then
|
||||
local cursor = uci.cursor()
|
||||
local rt = cursor:get("network", "lan", "_showrtable") or "1"
|
||||
cursor:set("network", "lan", "_showrtable", rt == "1" and "0" or "1")
|
||||
cursor:save("network")
|
||||
cursor:unload("network")
|
||||
inst:unload("network")
|
||||
end
|
||||
-%>
|
||||
|
||||
<div><a href="?toggle_rtable=1"> > <%:Toggle display of Routing Information%> < </a></div>
|
||||
<br />
|
||||
|
||||
<% if inst:get("network", "lan", "_showrtable") ~= "0" then %>
|
||||
<div class="cbi-map" id="x-cbi-network">
|
||||
|
||||
<fieldset class="cbi-section" id="x-cbi-table-table">
|
||||
<legend><%_Active <abbr title="Internet Protocol Version 4">IPv4</abbr>-Routes%></legend>
|
||||
|
||||
<div class="cbi-section-node">
|
||||
<table class="cbi-section-table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Network%></th>
|
||||
<th class="cbi-section-table-cell"><%:Target%></th>
|
||||
<th class="cbi-section-table-cell"><%_<abbr title="Internet Protocol Version 4">IPv4</abbr>-Netmask%></th>
|
||||
<th class="cbi-section-table-cell"><%_<abbr title="Internet Protocol Version 4">IPv4</abbr>-Gateway%></th>
|
||||
<th class="cbi-section-table-cell"><%:Metric%></th>
|
||||
</tr>
|
||||
<% luci.sys.net.routes(function(rt) %>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<td class="cbi-value-field"><%=ifc[rt.device]%></td>
|
||||
<td class="cbi-value-field"><%=rt.dest:network():string()%></td>
|
||||
<td class="cbi-value-field"><%=rt.dest:mask():string()%></td>
|
||||
<td class="cbi-value-field"><%=rt.gateway:string()%></td>
|
||||
<td class="cbi-value-field"><%=rt.metric%></td>
|
||||
</tr>
|
||||
<% style = not style; end) %>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
<br />
|
||||
|
||||
<% if fs.access("/proc/net/ipv6_route") then style = true %>
|
||||
<fieldset class="cbi-section" id="x-cbi-table-table-2">
|
||||
<legend><%_Active <abbr title="Internet Protocol Version 6">IPv6</abbr>-Routes%></legend>
|
||||
|
||||
<div class="cbi-section-node">
|
||||
<table class="cbi-section-table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Network%></th>
|
||||
<th class="cbi-section-table-cell"><%:Target%></th>
|
||||
<th class="cbi-section-table-cell"><%_<abbr title="Internet Protocol Version 6">IPv6</abbr>-Gateway%></th>
|
||||
<th class="cbi-section-table-cell"><%:Metric%></th>
|
||||
</tr>
|
||||
<% luci.sys.net.routes6(function(rt) %>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<td class="cbi-value-field"><%=ifc[rt.device]%></td>
|
||||
<td class="cbi-value-field"><%=rt.dest:string()%></td>
|
||||
<td class="cbi-value-field"><%=rt.source:string()%></td>
|
||||
<td class="cbi-value-field"><%-
|
||||
local metr = rt.metric
|
||||
local lower = bit.band(metr, 0xffff)
|
||||
local higher = bit.rshift(bit.band(metr, 0xffff0000), 16)
|
||||
write(string.format("%04X%04X", higher, lower))
|
||||
-%></td>
|
||||
</tr>
|
||||
<% style = not style; end) %>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
<br />
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
|
@ -1,11 +0,0 @@
|
|||
<%
|
||||
local http = require "luci.http"
|
||||
local dsp = require "luci.dispatcher"
|
||||
local ip = require "luci.model.uci".inst:get("network", "lan", "ipaddr")
|
||||
local url = (http.getenv("HTTPS") and "https" or "http") .. "://" .. ip ..
|
||||
dsp.build_url("niu")
|
||||
%>
|
||||
|
||||
<div style="color: red">Warning! The device IP-address has been changed.<br />
|
||||
It will be available in a few seconds at <a href="<%=url%>"><%=url%></a></div>
|
||||
<br />
|
|
@ -1,7 +0,0 @@
|
|||
<div style="margin: auto">
|
||||
<h2>Scanning for wireless networks in range</h2>
|
||||
<div>This may take a few seconds. Please wait...</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
setTimeout(function() { document.forms.cbi.submit(); }, 100);
|
||||
</script>
|
|
@ -1 +0,0 @@
|
|||
NULL
|
|
@ -1,72 +0,0 @@
|
|||
<%
|
||||
local nxo = require "nixio"
|
||||
local fs = require "nixio.fs"
|
||||
local sinfo = nxo.sysinfo()
|
||||
local load1 = nxo.bit.div(sinfo.loads[1] * 100, 1)
|
||||
local load15 = nxo.bit.div(sinfo.loads[3] * 100, 1)
|
||||
|
||||
local meminfo = fs.readfile("/proc/meminfo")
|
||||
local totalram = nxo.bit.div(sinfo.totalram, 1024)
|
||||
local freeram = nxo.bit.div(sinfo.freeram, 1024)
|
||||
local buffers = nxo.bit.div(sinfo.bufferram, 1024)
|
||||
local cached = tonumber(meminfo:match("Cached:%s+([0-9]+)%s+"))
|
||||
local memused = nxo.bit.div(totalram - freeram - cached - buffers, 1024)
|
||||
totalram = nxo.bit.div(totalram, 1024)
|
||||
|
||||
local totalswap = nxo.bit.div(sinfo.totalswap, 1048576)
|
||||
local usedswap = totalswap - nxo.bit.div(sinfo.freeswap, 1048576)
|
||||
|
||||
|
||||
local function date_format(secs)
|
||||
local suff = {"min", "h", "d"}
|
||||
local mins = 0
|
||||
local hour = 0
|
||||
local days = 0
|
||||
|
||||
secs = nxo.bit.div(secs, 1)
|
||||
if secs > 60 then
|
||||
mins = nxo.bit.div(secs, 60)
|
||||
secs = secs % 60
|
||||
end
|
||||
|
||||
if mins > 60 then
|
||||
hour = nxo.bit.div(mins, 60)
|
||||
mins = mins % 60
|
||||
end
|
||||
|
||||
if hour > 24 then
|
||||
days = nxo.bit.div(hour, 24)
|
||||
hour = hour % 24
|
||||
end
|
||||
|
||||
if days > 0 then
|
||||
return string.format("%.0fd %02.0fh %02.0fmin", days, hour, mins)
|
||||
else
|
||||
return string.format("%02.0fh %02.0fmin", hour, mins)
|
||||
end
|
||||
end
|
||||
%>
|
||||
<table class="dbstattbl">
|
||||
<tr>
|
||||
<th>Load:</th>
|
||||
<td><%=load1%>% / <%=load15%>%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Memory:</th>
|
||||
<td><%=memused%> MiB / <%=totalram%> MiB</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<% if totalswap > 0 then %>
|
||||
<tr>
|
||||
<th>Swap:</th>
|
||||
<td><%=usedswap%> MiB / <%=totalswap%> MiB</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
<tr>
|
||||
<th>Uptime:</th>
|
||||
<td><%=date_format(sinfo.uptime)%></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
|
@ -1,41 +0,0 @@
|
|||
<%#
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
-%>
|
||||
<%+header%>
|
||||
<h2><a id="content" name="content"><%:System%></a></h2>
|
||||
<h3><%:Backup / Restore%></h3>
|
||||
<p><%:Here you can backup and restore your configuration and - if possible - reset this device to the default settings.%></p>
|
||||
<br />
|
||||
<div>
|
||||
<ul>
|
||||
<li><a href="<%=REQUEST_URI%>?backup=kthxbye"><%:Create backup%></a></li>
|
||||
<% if reset_avail then -%>
|
||||
<li><a href="<%=REQUEST_URI%>?reset=yarly" onclick="return confirm('<%:Proceed reverting all settings and resetting to firmware defaults?%>')"><%:Reset to defaults%></a></li>
|
||||
<% end -%>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<form method="post" action="<%=REQUEST_URI%>" enctype="multipart/form-data">
|
||||
<div class="left"><%:Backup Archive%>:</div>
|
||||
<div>
|
||||
<input type="file" size="30" name="archive" />
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" name="cancel" class="cbi-button cbi-input-cancel" value="<%:Cancel%>" />
|
||||
<input type="submit" class="cbi-button cbi-input-apply" value="<%:Restore backup%>" />
|
||||
</div>
|
||||
</form>
|
||||
<%+footer%>
|
|
@ -1,14 +0,0 @@
|
|||
Rebooting. Please wait...
|
||||
|
||||
<script type="text/javascript">
|
||||
window.setInterval(function() {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open('GET', '/', true);
|
||||
xmlHttp.onreadystatechange = function () {
|
||||
if (xmlHttp.readyState == 4 && req.status >= 200 && req.status < 400) {
|
||||
window.location = "/";
|
||||
}
|
||||
};
|
||||
xmlHttp.send(null);
|
||||
}, 10000);
|
||||
</script>
|
|
@ -1,105 +0,0 @@
|
|||
<%#
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2009 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<h2><a id="content" name="content"><%:System%></a></h2>
|
||||
<h3><%:Flash Firmware%></h3>
|
||||
|
||||
<% if step == 1 then %>
|
||||
<% if supported then %>
|
||||
<form method="post" action="<%=REQUEST_URI%>" enctype="multipart/form-data">
|
||||
<p>
|
||||
<%:Upload an OpenWrt image file to reflash the device.%>
|
||||
<% if bad_image then %>
|
||||
<br /><br />
|
||||
<div class="error"><%:The uploaded image file does not
|
||||
contain a supported format. Make sure that you choose the generic
|
||||
image format for your platform. %></div>
|
||||
<% end %>
|
||||
</p>
|
||||
<div>
|
||||
<%:Firmware image%>:<br />
|
||||
<input type="hidden" name="step" value="2" />
|
||||
<input type="file" size="30" name="image" />
|
||||
<br />
|
||||
<br />
|
||||
<% if keepavail then -%>
|
||||
<input type="checkbox" name="keepcfg" value="1" checked="checked" />
|
||||
<span class="bold"><%:Keep configuration files%></span>
|
||||
<% end -%>
|
||||
|
||||
<br />
|
||||
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Upload image%>" />
|
||||
</div>
|
||||
</form>
|
||||
<% else %>
|
||||
<div class="error"><%_ Sorry.
|
||||
OpenWrt does not support a system upgrade on this platform.<br />
|
||||
You need to manually flash your device. %></div>
|
||||
<% end %>
|
||||
<% elseif step == 2 then %>
|
||||
<p>
|
||||
<%_ The flash image was uploaded.
|
||||
Below is the checksum and file size listed,
|
||||
compare them with the original file to ensure data integrity.<br />
|
||||
Click "Proceed" below to start the flash procedure. %>
|
||||
|
||||
<% if flashsize > 0 and filesize > flashsize then %>
|
||||
<br /><br />
|
||||
<div class="error"><%:It appears that you try to
|
||||
flash an image that does not fit into the flash memory, please verify
|
||||
the image file! %></div>
|
||||
<% end %>
|
||||
|
||||
<br />
|
||||
<ul>
|
||||
<li><%:Checksum%>: <code><%=checksum%></code></li>
|
||||
<li><%:Size%>: <%
|
||||
local w = require "luci.tools.webadmin"
|
||||
write(w.byte_format(filesize))
|
||||
|
||||
if flashsize > 0 then
|
||||
write(luci.i18n.translatef(
|
||||
" (%s available)",
|
||||
w.byte_format(flashsize)
|
||||
))
|
||||
end
|
||||
%></li>
|
||||
</ul>
|
||||
</p>
|
||||
<div class="cbi-page-actions right">
|
||||
<form style="display:inline">
|
||||
<input type="hidden" name="step" value="3" />
|
||||
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
|
||||
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Proceed%>" />
|
||||
</form>
|
||||
<form style="display:inline">
|
||||
<input type="hidden" name="step" value="1" />
|
||||
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
|
||||
<input class="cbi-button cbi-button-reset" type="submit" value="<%:Cancel%>" />
|
||||
</form>
|
||||
</div>
|
||||
<% elseif step == 3 then %>
|
||||
<p><%_ The system is flashing now.<br />
|
||||
DO NOT POWER OFF THE DEVICE!<br />
|
||||
Wait a few minutes until you try to reconnect.
|
||||
It might be necessary to renew the address of your computer to reach the device
|
||||
again, depending on your settings. %></p>
|
||||
|
||||
<iframe src="<%=REQUEST_URI%>?step=4&keepcfg=<%=keepconfig and "1" or "0"%>" style="border:1px solid black; width:100%; height:150px"></iframe>
|
||||
<% end %>
|
||||
<%+footer%>
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
<%
|
||||
local uci = require "luci.model.uci"
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
local wanon = uci.inst_state:get("network", "wan", "up") == "1"
|
||||
local wanif = wanon and uci.inst_state:get("network", "wan", "ifname")
|
||||
local lanif = uci.inst_state:get("network", "lan", "ifname")
|
||||
local wanul, wandl, lanul, landl
|
||||
local devstats = fs.readfile("/proc/net/dev")
|
||||
|
||||
local fwav = fs.access("/etc/config/firewall", "r")
|
||||
local fwon = uci.inst_state:get("firewall", "core", "loaded") == "1"
|
||||
|
||||
if lanif then
|
||||
local rx, tx = devstats:match("%s*"..lanif..
|
||||
":%s*([0-9]+)%s+[0-9]+%s+[0-9]+%s+[0-9]+%s+"..
|
||||
"[0-9]+%s+[0-9]+%s+[0-9]+%s+[0-9]+%s+([0-9]+)")
|
||||
lanul = tx and (tonumber(tx) / 1000000000)
|
||||
landl = rx and (tonumber(rx) / 1000000000)
|
||||
end
|
||||
|
||||
if wanif then
|
||||
local rx, tx = devstats:match("%s*"..wanif..
|
||||
":%s*([0-9]+)%s+[0-9]+%s+[0-9]+%s+[0-9]+%s+"..
|
||||
"[0-9]+%s+[0-9]+%s+[0-9]+%s+[0-9]+%s+([0-9]+)")
|
||||
wanul = tx and (tonumber(tx) / 1000000000)
|
||||
wandl = rx and (tonumber(rx) / 1000000000)
|
||||
end
|
||||
|
||||
%>
|
||||
|
||||
<table class="dbstattbl">
|
||||
<% if wanul and wandl then %>
|
||||
<tr>
|
||||
<th>Uplink Traffic: </th><td>
|
||||
<%=("%.2f"):format(wandl)%> GB⇓ <%=("%.2f"):format(wanul)%> GB⇑
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
<% if lanul and landl then %>
|
||||
<tr>
|
||||
<th>Local Traffic: </th><td>
|
||||
<%=("%.2f"):format(landl)%> GB⇓ <%=("%.2f"):format(lanul)%> GB⇑
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
<% if fwav then %>
|
||||
<tr>
|
||||
<th>Firewall: </th><td>
|
||||
<%=fwon and translate("active") or translate("inactive")%>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
</table>
|
||||
<br />
|
|
@ -1,75 +0,0 @@
|
|||
<%#
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2008-2009 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2009 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
-%>
|
||||
|
||||
<%-
|
||||
local sys = require "luci.sys"
|
||||
local style = true
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<div class="cbi-map" id="cbi-conntrack">
|
||||
<h2><a id="content" name="content"><%:Active Connections%></a></h2>
|
||||
<div class="cbi-map-descr"><%:This page gives an overview over currently active network connections.%></div>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-table-table">
|
||||
<legend>ARP</legend>
|
||||
<div class="cbi-section-node">
|
||||
<table class="cbi-section-table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%_<abbr title="Internet Protocol Version 4">IPv4</abbr>-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%_<abbr title="Media Access Control">MAC</abbr>-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Interface%></th>
|
||||
</tr>
|
||||
|
||||
<% sys.net.arptable(function(e) %>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<td class="cbi-value-field"><%=e["IP address"]%></td>
|
||||
<td class="cbi-value-field"><%=e["HW address"]%></td>
|
||||
<td class="cbi-value-field"><%=e["Device"]%></td>
|
||||
</tr>
|
||||
<% style = not style; end) %>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
<br />
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-table-table">
|
||||
<legend><%:Active Connections%></legend>
|
||||
<div class="cbi-section-node">
|
||||
<table class="cbi-section-table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Network%></th>
|
||||
<th class="cbi-section-table-cell"><%:Protocol%></th>
|
||||
<th class="cbi-section-table-cell"><%:Source%></th>
|
||||
<th class="cbi-section-table-cell"><%:Destination%></th>
|
||||
</tr>
|
||||
|
||||
<% style = true; sys.net.conntrack(function(c) %>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<td class="cbi-value-field"><%=c.layer3:upper()%></td>
|
||||
<td class="cbi-value-field"><%=c.layer4:upper()%></td>
|
||||
<td class="cbi-value-field"><%=c.src%></td>
|
||||
<td class="cbi-value-field"><%=c.dst%></td>
|
||||
</tr>
|
||||
<% style = not style; end) %>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/sh
|
||||
# Disable some services by default
|
||||
|
||||
uci get luci.main._niuinit && exit 0
|
||||
uci set qos.wan.enabled=0
|
||||
uci set upnpd.config.external_iface=none
|
||||
uci set luci.main._niuinit=1
|
Loading…
Reference in a new issue