Skip to content
Snippets Groups Projects
Commit 216c9ce3 authored by Matthias Schiffer's avatar Matthias Schiffer
Browse files

Merge gluon packages

The gluon packages will be maintained in the gluon main repository in the
future.
parents 750d9587 c4f7a526
No related branches found
No related tags found
No related merge requests found
Showing
with 546 additions and 0 deletions
local util = require 'gluon.util'
local os = os
local string = string
module 'gluon.users'
function add_user(username, uid, gid)
util.lock('/var/lock/passwd')
util.replace_prefix('/etc/passwd', username .. ':', string.format('%s:*:%u:%u::/var:/bin/false\n', username, uid, gid))
util.replace_prefix('/etc/shadow', username .. ':', string.format('%s:*:0:0:99999:7:::\n', username))
util.unlock('/var/lock/passwd')
end
function remove_user(username)
util.lock('/var/lock/passwd')
util.replace_prefix('/etc/passwd', username .. ':')
util.replace_prefix('/etc/shadow', username .. ':')
util.unlock('/var/lock/passwd')
end
function add_group(groupname, gid)
util.lock('/var/lock/group')
util.replace_prefix('/etc/group', groupname .. ':', string.format('%s:x:%u:\n', groupname, gid))
util.unlock('/var/lock/group')
end
function remove_group(groupname)
util.lock('/var/lock/group')
util.replace_prefix('/etc/group', groupname .. ':')
util.unlock('/var/lock/group')
end
-- Writes all lines from the file input to the file output except those starting with prefix
-- Doesn't close the output file, but returns the file object
local function do_filter_prefix(input, output, prefix)
local f = io.open(output, 'w+')
local l = prefix:len()
for line in io.lines(input) do
if line:sub(1, l) ~= prefix then
f:write(line, '\n')
end
end
return f
end
local function escape_args(ret, arg0, ...)
if not arg0 then
return ret
end
return escape_args(ret .. "'" .. string.gsub(arg0, "'", "'\\''") .. "' ", ...)
end
local os = os
local string = string
local tonumber = tonumber
local nixio = require 'nixio'
local sysconfig = require 'gluon.sysconfig'
module 'gluon.util'
function exec(...)
return os.execute(escape_args('', ...))
end
-- Removes all lines starting with a prefix from a file, optionally adding a new one
function replace_prefix(file, prefix, add)
local tmp = file .. '.tmp'
local f = do_filter_prefix(file, tmp, prefix)
if add then
f:write(add)
end
f:close()
os.rename(tmp, file)
end
function lock(file)
exec('lock', file)
end
function unlock(file)
exec('lock', '-u', file)
end
function node_id()
return string.gsub(sysconfig.primary_mac, ':', '')
end
-- Generates a (hopefully) unique MAC address
-- The first parameter defines the function and the second
-- parameter an ID to add to the MAC address
-- Functions and IDs defined so far:
-- (1, 0): WAN (for mesh-on-WAN)
-- (1, 1): LAN (for mesh-on-LAN)
-- (2, n): client interface for the n'th radio
-- (3, n): adhoc interface for n'th radio
-- (4, 0): mesh VPN
function generate_mac(f, i)
local m1, m2, m3, m4, m5, m6 = string.match(sysconfig.primary_mac, '(%x%x):(%x%x):(%x%x):(%x%x):(%x%x):(%x%x)')
m1 = nixio.bit.bor(tonumber(m1, 16), 0x02)
m2 = (tonumber(m2, 16)+f) % 0x100
m3 = (tonumber(m3, 16)+i) % 0x100
return string.format('%02x:%02x:%02x:%s:%s:%s', m1, m2, m3, m4, m5, m6)
end
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-cron
PKG_VERSION:=1
PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/gluon-cron
SECTION:=gluon
CATEGORY:=Gluon
TITLE:=Cron support
DEPENDS:=+gluon-core
endef
define Package/gluon-cron/description
Gluon community wifi mesh firmware framework: cron support
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Configure
endef
define Build/Compile
CFLAGS="$(TARGET_CFLAGS)" CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS)
endef
define Package/gluon-cron/install
$(CP) ./files/* $(1)/
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/gluon-crond $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,gluon-cron))
#!/bin/sh /etc/rc.common
# Copyright (C) 2013 Project Gluon
START=50
SERVICE_USE_PID=1
SERVICE_WRITE_PID=1
SERVICE_DAEMONIZE=1
CRONDIR=/lib/gluon/cron
start () {
service_start /usr/sbin/gluon-crond "$CRONDIR"
}
stop() {
service_stop /usr/sbin/gluon-crond
}
all: gluon-crond
gluon-crond: gluon-crond.c
/*
Copyright (c) 2013, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <dirent.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
typedef struct job {
struct job *next;
uint64_t minutes;
uint32_t hours;
uint32_t doms;
uint16_t months;
uint8_t dows;
char *command;
} job_t;
static const char const *const MONTHS[12] = {
"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"
};
static const char const *const WEEKDAYS[7] = {
"sun", "mon", "tue", "wed", "thu", "fri", "sat"
};
static const char *crondir;
static job_t *jobs = NULL;
static void usage(void) {
fprintf(stderr, "Usage: gluon-crond <crondir>\n");
}
static inline uint64_t bit(unsigned b) {
return ((uint64_t)1) << b;
}
static int strict_atoi(const char *s) {
char *end;
int ret = strtol(s, &end, 10);
if (*end)
return -1;
else
return ret;
}
static uint64_t parse_strings(const char *input, const char *const *strings, size_t n) {
size_t i;
for (i = 0; i < n; i++) {
if (strcasecmp(input, strings[i]) == 0)
return bit(i);
}
return 0;
}
static uint64_t parse_times(char *input, int min, int n) {
uint64_t ret = 0;
int step = 1;
char *comma = strchr(input, ',');
if (comma) {
*comma = 0;
ret = parse_times(comma+1, min, n);
if (!ret)
return 0;
}
char *slash = strchr(input, '/');
if (slash) {
*slash = 0;
step = strict_atoi(slash+1);
if (step <= 0)
return 0;
}
int begin, end;
char *minus = strchr(input, '-');
if (minus) {
*minus = 0;
begin = strict_atoi(input);
end = strict_atoi(minus+1);
}
else if (strcmp(input, "*") == 0) {
begin = min;
end = min+n-1;
}
else {
begin = end = strict_atoi(input);
}
if (begin < min || end < min)
return 0;
int i;
for (i = begin-min; i <= end-min; i += step)
ret |= bit(i % n);
return ret;
}
static int handle_line(const char *line) {
job_t job = {};
int ret = -1;
char *columns[5];
int i;
int len;
int matches = sscanf(line, "%ms %ms %ms %ms %ms %n", &columns[0], &columns[1], &columns[2], &columns[3], &columns[4], &len);
if (matches != 5 && matches != 6) {
if (matches <= 0)
ret = 0;
goto end;
}
job.minutes = parse_times(columns[0], 0, 60);
if (!job.minutes)
goto end;
job.hours = parse_times(columns[1], 0, 24);
if (!job.hours)
goto end;
job.doms = parse_times(columns[2], 1, 31);
if (!job.doms)
goto end;
job.months = parse_strings(columns[3], MONTHS, 12);
if (!job.months)
job.months = parse_times(columns[3], 1, 12);
if (!job.months)
goto end;
job.dows = parse_strings(columns[4], WEEKDAYS, 7);
if (!job.dows)
job.dows = parse_times(columns[4], 0, 7);
if (!job.dows)
goto end;
job.command = strdup(line+len);
job_t *jobp = malloc(sizeof(job_t));
*jobp = job;
jobp->next = jobs;
jobs = jobp;
ret = 0;
end:
for (i = 0; i < matches && i < 5; i++)
free(columns[i]);
return ret;
}
static void read_crontab(const char *name) {
FILE *file = fopen(name, "r");
if (!file) {
syslog(LOG_WARNING, "unable to read crontab `%s'", name);
return;
}
char line[16384];
unsigned lineno = 0;
while (fgets(line, sizeof(line), file)) {
lineno++;
char *comment = strchr(line, '#');
if (comment)
*comment = 0;
if (handle_line(line))
syslog(LOG_WARNING, "syntax error in `%s', line %u", name, lineno);
}
fclose(file);
}
static void read_crondir(void) {
DIR *dir;
if (chdir(crondir) || ((dir = opendir(".")) == NULL)) {
fprintf(stderr, "Unable to read crondir `%s'\n", crondir);
usage();
exit(1);
}
struct dirent *ent;
while ((ent = readdir(dir)) != NULL) {
if (ent->d_name[0] == '.')
continue;
read_crontab(ent->d_name);
}
closedir(dir);
}
static void run_job(const job_t *job) {
pid_t pid = fork();
if (pid == 0) {
execl("/bin/sh", "/bin/sh", "-c", job->command, (char*)NULL);
syslog(LOG_ERR, "unable to run job: exec failed");
_exit(1);
}
else if (pid < 0) {
syslog(LOG_ERR, "unable to run job: fork failed");
}
}
static void check_job(const job_t *job, const struct tm *tm) {
if (!(job->minutes & bit(tm->tm_min)))
return;
if (!(job->hours & bit(tm->tm_hour)))
return;
if (!(job->doms & bit(tm->tm_mday-1)))
return;
if (!(job->months & bit(tm->tm_mon)))
return;
if (!(job->dows & bit(tm->tm_wday)))
return;
run_job(job);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
usage();
exit(argc < 2 ? 0 : 1);
}
crondir = argv[1];
signal(SIGCHLD, SIG_IGN);
read_crondir();
time_t t = time(NULL);
struct tm *tm = localtime(&t);
int minute = tm->tm_min;
while (1) {
sleep(60 - t%60);
t = time(NULL);
tm = localtime(&t);
minute = (minute+1)%60;
if (tm->tm_min != minute) {
/* clock has moved, don't execute jobs */
minute = tm->tm_min;
continue;
}
job_t *job;
for (job = jobs; job; job = job->next)
check_job(job, tm);
}
}
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-ebtables-filter-multicast
PKG_VERSION:=1
PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/gluon-ebtables-filter-multicast
SECTION:=gluon
CATEGORY:=Gluon
TITLE:=Ebtables filters for multicast packets
DEPENDS:=+gluon-core +gluon-ebtables
endef
define Package/gluon-ebtables-filter-multicast/description
Gluon community wifi mesh firmware framework: Ebtables filters for multicast packets
These filters drop non-essential multicast traffic before it enters the mesh.
Allowed protocols are: DHCP, DHCPv6, ARP, ICMP, ICMPv6, BitTorrent local peer discovery, BABEL and OSPF
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/gluon-ebtables-filter-multicast/install
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,gluon-ebtables-filter-multicast))
chain('MULTICAST_OUT', 'DROP')
rule 'MULTICAST_OUT -p ARP --arp-opcode Reply --arp-ip-src 0.0.0.0 -j DROP'
rule 'MULTICAST_OUT -p ARP --arp-opcode Request --arp-ip-dst 0.0.0.0 -j DROP'
rule 'MULTICAST_OUT -p ARP -j RETURN'
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol udp --ip6-destination-port 6696 -j RETURN'
rule 'MULTICAST_OUT -p IPv4 --ip-destination 239.192.152.143 --ip-protocol udp --ip-destination-port 6771 -j RETURN'
rule 'MULTICAST_OUT -p IPv4 --ip-protocol udp --ip-destination-port 67 -j RETURN'
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol udp --ip6-destination-port 547 -j RETURN'
rule 'MULTICAST_OUT -p IPv4 --ip-protocol icmp -j RETURN'
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol 0 -j RETURN' -- hop-by-hop
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp -j RETURN'
rule 'MULTICAST_OUT -p IPv4 --ip-protocol igmp -j RETURN'
rule 'MULTICAST_OUT -p IPv4 --ip-protocol ospf -j RETURN'
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ospf -j RETURN'
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol udp --ip6-destination ff02::9 --ip6-destination-port 521 -j RETURN'
rule 'FORWARD --logical-out br-client -o bat0 -d Multicast -j MULTICAST_OUT'
rule 'OUTPUT --logical-out br-client -o bat0 -d Multicast -j MULTICAST_OUT'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment