Remove unmaintained components: lucid, fastindex, niu

This commit is contained in:
Jo-Philipp Wich 2014-06-11 12:37:19 +00:00
parent 2d05a6135a
commit 91b97bc9f6
79 changed files with 0 additions and 6799 deletions

View file

@ -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 ###

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -1,2 +0,0 @@
include ../../build/module.mk
include ../../build/config.mk

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,2 +0,0 @@
include ../../build/config.mk
include ../../build/module.mk

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,2 +0,0 @@
include ../../build/config.mk
include ../../build/module.mk

View file

@ -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.

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1 +0,0 @@
local f = Form("reboot", "Rebooting Device", "Device is rebooting. Please wait...")

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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%>

View file

@ -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 />

View file

@ -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"> &gt; <%:Toggle display of Routing Information%> &lt; </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 %>

View file

@ -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 />

View file

@ -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>

View file

@ -1 +0,0 @@
NULL

View file

@ -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 />

View file

@ -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%>

View file

@ -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>

View file

@ -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&#38;keepcfg=<%=keepconfig and "1" or "0"%>" style="border:1px solid black; width:100%; height:150px"></iframe>
<% end %>
<%+footer%>

View file

@ -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&#8659; <%=("%.2f"):format(wanul)%> GB&#8657;
</td>
</tr>
<% end %>
<% if lanul and landl then %>
<tr>
<th>Local Traffic: </th><td>
<%=("%.2f"):format(landl)%> GB&#8659; <%=("%.2f"):format(lanul)%> GB&#8657;
</td>
</tr>
<% end %>
<% if fwav then %>
<tr>
<th>Firewall: </th><td>
<%=fwon and translate("active") or translate("inactive")%>
</td>
</tr>
<% end %>
</table>
<br />

View file

@ -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%>

View file

@ -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