Skip to content
Snippets Groups Projects
Commit 0f9ab5e3 authored by Christof Schulze's avatar Christof Schulze Committed by Andreas Ziegler
Browse files

gluon-mesh-babel: add new package

parent 6241ba54
No related branches found
No related tags found
No related merge requests found
Showing
with 1191 additions and 0 deletions
...@@ -46,6 +46,22 @@ prefix6 ...@@ -46,6 +46,22 @@ prefix6
prefix6 = 'fdca::ffee:babe:1::/64' prefix6 = 'fdca::ffee:babe:1::/64'
node_prefix6
The ipv6 prefix from which the unique IP-addresses for nodes are selected
in babel-based networks. This may overlap with prefix6. e.g.
::
node_prefix6 = 'fdca::ffee:babe:2::/64'
node_client_prefix6
The ipv6 prefix from which the client-specific IP-address is calculated that
is assigned to each node by l3roamd to allow efficient communication when
roaming. This is exclusively useful when running a routing mesh protocol
like babel. e.g.
::
node_client_prefix6 = 'fdca::ffee:babe:3::/64'
timezone timezone
The timezone of your community live in, e.g. The timezone of your community live in, e.g.
:: ::
...@@ -260,6 +276,9 @@ mesh_vpn ...@@ -260,6 +276,9 @@ mesh_vpn
and *gluon-mesh-vpn-tunneldigger* should be installed with the current and *gluon-mesh-vpn-tunneldigger* should be installed with the current
implementation. implementation.
**Note:** It may be interesting to include the package *gluon-iptables-clamp-mss-to-pmtu*
in the build when using *gluon-mesh-babel* to work around icmp blackholes on the internet.
:: ::
mesh_vpn = { mesh_vpn = {
......
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-mesh-babel
PKG_VERSION:=1
PKG_BUILD_DEPENDS := libbabelhelper
PKG_BUILD_DEPENDS += libjson-c
include ../gluon.mk
define Package/gluon-mesh-babel
TITLE:=Babel mesh
DEPENDS:=+gluon-core +babeld +mmfd +libiwinfo +libgluonutil +firewall +libjson-c +libnl-tiny +libubus +libubox +libblobmsg-json +libbabelhelper +luabitop
PROVIDES:=gluon-mesh-provider
endef
define Package/gluon-mesh-babel/install
$(Gluon/Build/Install)
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_DIR) $(1)/usr/lib/respondd
$(CP) $(PKG_BUILD_DIR)/babel-respondd.so $(1)/usr/lib/respondd/mesh-babel.so
$(INSTALL_DIR) $(1)/lib/gluon/status-page/providers
$(INSTALL_BIN) $(PKG_BUILD_DIR)/neighbours-babel $(1)/lib/gluon/status-page/providers/
endef
$(eval $(call BuildPackageGluon,gluon-mesh-babel))
need_string_match(in_domain({'node_prefix6'}), '^[%x:]+/64$')
need_string_match(in_domain({'node_client_prefix6'}), '^[%x:]+/64$')
need_string_match(in_domain({'next_node', 'ip6'}), '^[%x:]+$', false)
need_string_match(in_domain({'next_node', 'ip4'}), '^%d+.%d+.%d+.%d+$', false)
need_string_match(in_domain({'next_node', 'mac'}), '^%x[02468aAcCeE]:%x%x:%x%x:%x%x:%x%x:%x%x$', false)
#!/bin/sh
case "$ACTION"
in
ifup)
echo 1 > /sys/devices/virtual/net/br-client/bridge/multicast_snooping
echo 2 > /sys/devices/virtual/net/br-client/bridge/multicast_router
;;
esac
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=45
PORT=33123
DAEMON=/usr/sbin/babeld
pidfile=/var/run/gluon-babeld.pid
CONFIGFILE=/etc/gluon-babeld.conf
BABELOPTSFILE=/tmp/addn-babelopts
touch $BABELOPTSFILE
start_service() {
procd_open_instance
procd_set_param command $DAEMON
procd_append_param command -D -I "$pidfile" -G "$PORT" -c "$CONFIGFILE" $(cat $BABELOPTSFILE) babeldummydoesnotexist
procd_set_param respawn ${respawn_threshold:-60} ${respawn_timeout:-5} ${respawn_retry:-0}
procd_set_param stderr 1
procd_set_param stdout 1
procd_close_instance
}
echotobabel() {
local count=0
local line="$1"
while ! (echo -e "$line" | nc ::1 "$PORT" >/dev/null 2>&1)
do
sleep 1
echo retrying to connect to babeld in PID $$, waited ${count}s >&2
count=$((count+1))
done
return 0
}
waitforsocket() {
echotobabel "dump"
[ $? -gt 0 ] && { echo "Failed to connect to babeld socket on port $PORT, assuming the service was not started properly"; exit 43; }
}
reload_service() {
waitforsocket
for i in $(ubus call network.interface dump | jsonfilter -e "@.interface[@.proto='gluon_mesh' && @.up=true].device")
do
if ! echotobabel dump|grep "add interface"|grep -q $i
then
echotobabel "interface $i update-interval 300"
fi
done
for i in $(echotobabel "dump"|grep "add interface"|cut -d" " -f3)
do
if ! ubus call network.interface dump | jsonfilter -e "@.interface[@.proto='gluon_mesh' && @.up=true].device"|grep -q $i
then
echotobabel "flush interface $i"
fi
done
}
service_triggers() {
local script=$(readlink "$initscript")
local name=$(basename "${script:-$initscript}")
procd_open_trigger
procd_add_raw_trigger "interface.*" 0 "/etc/init.d/$name" reload
procd_close_trigger
}
service_started() {
# make sure the init script does not finish until babeld is actually up.
# unfortunately procd will still start multiple instances of the same script which is why waitforsocket is also run on reload
waitforsocket
}
stop_service(){
kill $(pgrep -P 1 babeld)
}
status() {
kill -USR1 $(pgrep -P 1 babeld)
}
mmfd
#!/usr/bin/lua
local site = require "gluon.site"
io.write("-i local-node --default-lifetime 900 -a " .. site.prefix6())
if site.dns() and site.dns.servers() then
io.write(" --rdnss " .. site.next_node.ip6())
end
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
local site = require "gluon.site"
uci:section('firewall', 'zone', 'l3roamd', {
name = 'l3roamd',
input = 'ACCEPT',
output = 'ACCEPT',
forward = 'REJECT',
device = 'l3roam+',
log = '1',
})
uci:section('firewall', 'zone', 'mmfd', {
name = 'mmfd',
input = 'REJECT',
output = 'accept',
forward = 'REJECT',
device = 'mmfd+',
log = '1',
})
-- forwardings and respective rules
uci:section('firewall', 'forwarding', 'fcc', {
src = 'local_client',
dest = 'local_client',
})
uci:section('firewall', 'forwarding', 'fcm', {
src = 'local_client',
dest = 'mesh',
})
uci:section('firewall', 'forwarding', 'fmc', {
src = 'mesh',
dest = 'local_client',
})
uci:section('firewall', 'forwarding', 'fmm', {
src = 'mesh',
dest = 'mesh',
})
uci:section('firewall', 'forwarding', 'flc', {
src = 'l3roamd',
dest = 'local_client',
})
uci:section('firewall', 'forwarding', 'fcl', {
src = 'local_client',
dest = 'l3roamd',
})
uci:section('firewall', 'rule', 'mesh_respondd_mcast_ll', {
src = 'mesh',
src_ip = 'fe80::/64' ,
dest_port = '1001',
proto = 'udp',
target = 'ACCEPT',
})
uci:section('firewall', 'rule', 'mesh_respondd_mcast2', {
src = 'mesh',
src_ip = site.node_prefix6(),
dest_port = '1001',
proto = 'udp',
target = 'ACCEPT',
})
uci:section('firewall', 'rule', 'mmfd_respondd_ll', {
src = 'mmfd',
src_ip = 'fe80::/64',
dest_port = '1001',
proto = 'udp',
target = 'ACCEPT',
})
uci:section('firewall', 'rule', 'mmfd_respondd_mesh', {
src = 'mmfd',
src_ip = site.node_prefix6(),
dest_port = '1001',
proto = 'udp',
target = 'ACCEPT',
})
uci:section('firewall', 'rule', 'mesh_mmfd', {
src = 'mesh',
src_ip = 'fe80::/64',
dest_port = '27275',
proto = 'udp',
target = 'ACCEPT',
})
uci:section('firewall', 'rule', 'mesh_babel', {
src = 'mesh',
src_ip = 'fe80::/64',
dest_port = '6696',
proto = 'udp',
target = 'ACCEPT',
})
uci:save('firewall')
#!/usr/bin/lua
local bit = require 'bit'
local sysconfig = require 'gluon.sysconfig'
local uci = require('simple-uci').cursor()
local site = require 'gluon.site'
function IPv6(address)
--[[
(c) 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
(c) 2008 Steven Barth <steven@midlink.org>
Licensed under the Apache License, Version 2.0 (the "License").
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
]]--
local data = {}
local borderl = address:sub(1, 1) == ":" and 2 or 1
local borderh, zeroh, chunk, block
if #address > 45 then return nil end
repeat
borderh = address:find(":", borderl, true)
if not borderh then break end
block = tonumber(address:sub(borderl, borderh - 1), 16)
if block and block <= 0xFFFF then
data[#data+1] = block
else
if zeroh or borderh - borderl > 1 then return nil end
zeroh = #data + 1
end
borderl = borderh + 1
until #data == 7
chunk = address:sub(borderl)
if #chunk > 0 and #chunk <= 4 then
block = tonumber(chunk, 16)
if not block or block > 0xFFFF then return nil end
data[#data+1] = block
elseif #chunk > 4 then
if #data == 7 or #chunk > 15 then return nil end
borderl = 1
for i=1, 4 do
borderh = chunk:find(".", borderl, true)
if not borderh and i < 4 then return nil end
borderh = borderh and borderh - 1
block = tonumber(chunk:sub(borderl, borderh))
if not block or block > 255 then return nil end
if i == 1 or i == 3 then
data[#data+1] = block * 256
else
data[#data] = data[#data] + block
end
borderl = borderh and borderh + 2
end
end
if zeroh then
if #data == 8 then return nil end
while #data < 8 do
table.insert(data, zeroh, 0)
end
end
if #data == 8 then
return data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]
end
end
function mac_to_ip(prefix, mac)
local m1, m2, m3, m6, m7, m8 = string.match(mac, '(%x%x):(%x%x):(%x%x):(%x%x):(%x%x):(%x%x)')
local m4 = 0xff
local m5 = 0xfe
m1 = bit.bxor(tonumber(m1, 16), 0x02)
local h1 = 0x100 * m1 + tonumber(m2, 16)
local h2 = 0x100 * tonumber(m3, 16) + m4
local h3 = 0x100 * m5 + tonumber(m6, 16)
local h4 = 0x100 * tonumber(m7, 16) + tonumber(m8, 16)
local prefix, plen = string.match(prefix, '(.*)/(%d+)')
plen = tonumber(plen, 10)
local p1, p2, p3, p4, p5, p6, p7, p8 = IPv6(prefix)
return string.format("%x:%x:%x:%x:%x:%x:%x:%x/%d", p1, p2, p3, p4, h1, h2, h3, h4, 128)
end
local ip = mac_to_ip(site.node_prefix6(), sysconfig.primary_mac)
uci:set('network', 'loopback', 'ip6addr', ip)
uci:save('network')
#!/usr/bin/lua
local site = require 'gluon.site'
local babelconf='/etc/gluon-babeld.conf'
file = io.open(babelconf, "w")
file:write("ipv6-subtrees true\n")
file:write("reflect-kernel-metric true\n")
file:write("export-table 254\n")
file:write("log-file /dev/stderr\n")
file:write("import-table 254\n")
file:write("out ip " .. site.next_node.ip6() .. "/128 deny\n")
file:write("redistribute ip " .. site.next_node.ip6() .. "/128 deny\n")
file:write("redistribute ip " .. site.prefix6() .. " eq 128 allow\n")
file:write("redistribute ip " .. site.node_client_prefix6() .. " eq 128 allow\n")
file:write("redistribute ip " .. site.node_prefix6() .. " eq 128 allow\n")
file:write("redistribute local if br-wan deny\n")
file:write("redistribute local ip 0.0.0.0/0 deny\n")
file:close()
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
uci:delete('network', 'mmfd')
uci:section('network', 'interface', 'mmfd', {
proto = 'static',
ifname = 'mmfd0',
ip6addr = 'fe80::1/64'
})
uci:save('network')
all: babel-respondd.so neighbours-babel
CFLAGS += -Wall -g -fPIC -D_GNU_SOURCE
ifeq ($(origin PKG_CONFIG), undefined)
PKG_CONFIG = pkg-config
ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),)
$(error $(PKG_CONFIG) not found)
endif
endif
ifeq ($(origin LIBBABEL_CFLAGS) $(origin LIBBABEL_LDLIBS), undefined undefined)
LIBBABEL_NAME ?= libbabelhelper
ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBBABEL_NAME) 2>/dev/null),)
$(error No $(LIBBABEL_NAME) development libraries found!)
endif
LIBBABEL_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBBABEL_NAME))
LIBBABEL_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBBABEL_NAME))
endif
CFLAGS += $(LIBBABEL_CFLAGS)
LDLIBS += $(LIBBABEL_LDLIBS)
CFLAGS_JSONC = $(shell pkg-config --cflags json-c)
LDFLAGS_JSONC = $(shell pkg-config --libs json-c)
babel-respondd.so: babel-respondd.c handle_neighbour.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -shared $(LDFLAGS_JSONC) -o $@ $^ -lgluonutil -lblobmsg_json -lubox -lubus -liwinfo -luci
neighbours-babel: neighbours-babel.c handle_neighbour.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_JSONC) $(LDFLAGS) $(LDLIBS) $(LDFLAGS_JSONC) -o $@ $^
This diff is collapsed.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "handle_neighbour.h"
#include <libbabelhelper/babelhelper.h>
bool handle_neighbour(char **data, void *arg) {
struct json_object *obj = (struct json_object*)arg;
if (data[NEIGHBOUR]) {
struct json_object *neigh = json_object_new_object();
if (data[RXCOST])
json_object_object_add(neigh, "rxcost", json_object_new_int(atoi(data[RXCOST])));
if (data[TXCOST])
json_object_object_add(neigh, "txcost", json_object_new_int(atoi(data[TXCOST])));
if (data[COST])
json_object_object_add(neigh, "cost", json_object_new_int(atoi(data[COST])));
if (data[REACH])
json_object_object_add(neigh, "reachability", json_object_new_double(strtod(data[REACH], NULL)));
if (data[IF])
json_object_object_add(neigh, "ifname", json_object_new_string(data[IF]));
if (data[ADDRESS])
json_object_object_add(obj, data[ADDRESS] , neigh);
}
return true;
}
#include <json-c/json.h>
#include <stdbool.h>
bool handle_neighbour(char **line, void *arg);
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <json-c/json.h>
#include <libbabelhelper/babelhelper.h>
#include "handle_neighbour.h"
int main(void) {
struct json_object *neighbours;
printf("Content-type: text/event-stream\n\n");
fflush(stdout);
struct babelhelper_ctx bhelper_ctx = {};
while (1) {
neighbours = json_object_new_object();
if (!neighbours)
continue;
bhelper_ctx.debug = false;
babelhelper_readbabeldata(&bhelper_ctx, (void*)neighbours, handle_neighbour);
printf("data: %s\n\n", json_object_to_json_string(neighbours));
fflush(stdout);
json_object_put(neighbours);
neighbours = NULL;
sleep(10);
}
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment