olsr stuffs

This commit is contained in:
Maciej Krüger 2022-03-22 20:55:21 +01:00 committed by Alexander List
parent b3eb380e6f
commit dec697a996
14 changed files with 531 additions and 2 deletions

View File

@ -199,7 +199,7 @@ end
-- 6: owe1
-- 7: wan_radio1 (private WLAN); mesh VPN
function M.generate_mac(i)
if i > 7 or i < 0 then return nil end -- max allowed id (0b111)
if i > 15 or i < 0 then return nil end -- max allowed id (0b111)
local hashed = string.sub(hash.md5(sysconfig.primary_mac), 0, 12)
local m1, m2, m3, m4, m5, m6 = string.match(hashed, '(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)')
@ -214,7 +214,7 @@ function M.generate_mac(i)
-- vary on a single hardware interface, since some chips are using
-- a hardware MAC filter. (e.g 'rt305x')
m6 = bit.band(m6, 0xF8) -- zero the last three bits (space needed for counting)
m6 = bit.band(m6, 0xF0) -- zero the last four bits (space needed for counting)
m6 = m6 + i -- add virtual interface id
return string.format('%02x:%s:%s:%s:%s:%02x', m1, m2, m3, m4, m5, m6)

View File

@ -0,0 +1,7 @@
#!/bin/sh
. /lib/gluon/autoupdater/lib.sh
start_enabled olsrd
start_enabled olsrd2

View File

@ -0,0 +1,7 @@
#!/bin/sh
. /lib/gluon/autoupdater/lib.sh
stop olsrd
stop olsrd2

View File

@ -0,0 +1,4 @@
#!/bin/sh
service olsrd stop
service olsrd2 stop

View File

@ -0,0 +1,4 @@
#!/bin/sh
service olsrd start
service olsrd2 start

View File

@ -0,0 +1,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-static-ip
PKG_VERSION:=1
include ../gluon.mk
define Package/gluon-static-ip
TITLE:=Static IP assignment and configuration for gluon
DEPENDS:=+gluon-core +luci-lib-ip
endef
$(eval $(call BuildPackageGluon,gluon-static-ip))

View File

@ -0,0 +1,6 @@
-- TODO: conditional range required when tmp set
need_string({'tmpIp4'}, false)
need_number({'tmpIp4Range'}, false)
need_string({'tmpIp6'}, false)
need_number({'tmpIp6Range'}, false)

View File

@ -0,0 +1,198 @@
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
local site = require 'gluon.site'
local wireless = require 'gluon.wireless'
local ip = require 'luci.ip' -- luci-lib-ip
local util = require 'gluon.util'
local IPV4_PREFIX_MAX = 32
local IPV6_PREFIX_MAX = 128
function hex2bin(str)
local map = {
['0'] = '0000',
['1'] = '0001',
['2'] = '0010',
['3'] = '0011',
['4'] = '0100',
['5'] = '0101',
['6'] = '0110',
['7'] = '0111',
['8'] = '1000',
['9'] = '1001',
['A'] = '1010',
['B'] = '1011',
['C'] = '1100',
['D'] = '1101',
['E'] = '1110',
['F'] = '1111',
}
return str:gsub('[0-9A-F]', map)
end
-- since we have a limit of 32 bit integers we.. uhm... do some hex2bin and then convert it byte by byte to a hex ipv6 block string
-- (the ip lib is in c and handles this stuff just fine)
function ipnum(macaddr, prefixOverflow, hex)
local binaryMac = hex2bin(macaddr:gsub(':', ''):upper()):sub(-prefixOverflow)
if not hex then
return tonumber(binaryMac, 2)
end
-- pad with 0s until we have block sized packets
while string.len(binaryMac) % 16 ~= 0 do
binaryMac = '0' .. binaryMac
end
local out = ''
for i=0,string.len(binaryMac)/16-1 do
if out ~= '' then
out = out .. ':'
end
out = out .. string.format("%02x", tonumber(binaryMac:sub(1+i*16,(i+1)*16), 2))
end
return out
end
local function static_ip(name, ifname, macaddr, actually_use)
-- actually_use = if ip should be applied to interface or not
-- if set and actually_use=false then it will be removed
local static4 = uci:get('gluon-static-ip', name, 'ip4')
local static6 = uci:get('gluon-static-ip', name, 'ip6')
if site.prefix4() then
if not static4 and site.tmpIp4() and name ~= 'loopback' then
local tmp4 = ip.new(site.tmpIp4())
-- magic that turns mac into random number
local ipnum = ipnum(macaddr, IPV4_PREFIX_MAX - site.tmpIp4Range())
-- the rare case where we get 0 or 1 as our mac based number
if ipnum < 2 then
ipnum = 2
end
static4 = tmp4:add(ipnum):string()
end
end
if site.prefix6() then
if not static6 and site.tmpIp6() and (site.tmpIp6Everywhere() or name == 'loopback') then
local tmp6 = ip.new(site.tmpIp6())
-- magic that turns mac into random number
local ipnum = ipnum(macaddr, IPV6_PREFIX_MAX - site.tmpIp6Range(), true)
-- the rare case where we get 0 or 1 as our mac based number
if tonumber(ipnum:gsub(':', ''), 16) < 2 then
ipnum = 2
end
static6 = tmp6:add('::' .. ipnum):string()
end
end
uci:section('gluon-static-ip', 'interface', name, {
ip4 = static4,
ip6 = static6,
})
if actually_use then
-- we have to set proto to static as otherwise we won't have the ip assigned
-- TODO: maybe modify the protos instead to allow reading static ips and using them?
-- NOTE: wan also uses dhcp/static directly
uci:set('network', name, 'proto', 'static')
if site.prefix4 and static4 then
local ip4 = ip.new(static4)
if not ip4 or not ip4:is4() then
print('E: ' .. name .. ' has invalid ip4 ' .. static4)
return
end
uci:set('network', name, 'ipaddr', ip4:host():string())
uci:set('network', name, 'netmask', ip4:mask():string())
elseif name ~= 'loopback' then
if uci:get('network', name, 'ipaddr') then
uci:del('network', name, 'ipaddr')
end
if uci:get('network', name, 'netmask') then
uci:del('network', name, 'netmask')
end
end
if site.prefix6 and static6 then
local ip6 = ip.new(static6)
if not ip6 or not ip6:is6() then
print('E: ' .. name .. ' has invalid ip6 ' .. static6)
return
end
uci:set('network', name, 'ip6addr', ip6:string())
else
if uci:get('network', name, 'ip6addr') then
uci:del('network', name, 'ip6addr')
end
end
else
if uci:get('network', name, 'proto') == 'static' then
uci:del('network', name, 'ipaddr')
uci:del('network', name, 'netmask')
uci:del('network', name, 'ip6addr')
end
end
end
wireless.foreach_radio(uci, function(radio, index, config)
local function do_config(type)
net = type .. radio['.name']
use = uci:get('wireless', net, 'disabled') ~= '1'
static_ip(net, uci:get('wireless', net, 'ifname'), uci:get('wireless', net, 'macaddr'), use)
end
do_config('mesh_')
if uci:get('network', 'ibss_' .. radio['.name'], 'proto') then
do_config('ibss_')
end
end)
local function apply_network(name, use, mac)
if not uci:get('network', name, 'proto') then
print('warn: non-existent network ' .. name)
return
end
not_disabled = uci:get('network', name, 'disabled') ~= '1'
if use == nil then
use = not_disabled
end
macaddr = uci:get('network', name, 'macaddr')
if not macaddr then
macaddr = util.generate_mac(mac)
uci:set('network', name, 'macaddr', macaddr)
end
static_ip(name, uci:get('network', name, 'ifname'), macaddr, use)
end
if pcall(function() require 'gluon.mesh-vpn' end) then
local vpn_core = require 'gluon.mesh-vpn'
apply_network('mesh_vpn', vpn_core.enabled(), 7)
end
local uplink_mesh = not uci:get_bool('network', 'mesh_uplink', 'disabled')
apply_network('mesh_uplink', uplink_mesh, 10)
local other_mesh = not uci:get_bool('network', 'mesh_other', 'disabled')
apply_network('mesh_other', other_mesh, 11)
apply_network('loopback', true, 12)
uci:save('gluon-static-ip')
uci:save('network')

View File

@ -0,0 +1,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-web-static-ip
include ../gluon.mk
define Package/gluon-web-static-ip
DEPENDS:=+gluon-web-admin +gluon-static-ip
TITLE:=UI for managing static IPs
endef
$(eval $(call BuildPackageGluon,gluon-web-static-ip))

View File

@ -0,0 +1,69 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2021-12-19 10:29+0100\n"
"Last-Translator: Maciej Krüger <mkg20001@gmail.com>\n"
"Language-Team: German\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.0\n"
msgid "Static IPs"
msgstr "Statische IPs"
msgid "Configure the IPv4 addresses of your node."
msgstr "Konfiguriere die IPv4 Addressen deines Knotens."
msgid "Configure the IPv6 addresses of your node."
msgstr "Konfiguriere die IPv6 Addressen deines Knotens."
msgid "enabled"
msgstr "aktiviert"
msgid "disabled"
msgstr "deaktiviert"
msgid ""
"The address %s for \"%s\" is an address in the temporary address range %s.<br />"
"It should be replaced by a properly assigned address as soon as possible."
msgstr ""
"Die Addresse %s für \"%s\" ist eine Addresse aus dem temporären "
"Addressbereich %s.<br />Sie sollte umgehend mit einer korrekt zugewiesenen "
"Addresse ersetzt werden."
msgid ""
"The address %s for \"%s\" is an address in the temporary address range %s.<br />"
"If you are planning to use this interface, you will need to replace this "
"address with a properly assigned one."
msgstr ""
"Die Addresse %s für \"%s\" ist eine Addresse aus dem temporären "
"Addressbereich %s.<br />Wenn du planst dieses Interface zu verwenden, solltest du "
"diese Addresse mit einer korrekt zugewiesenen Addresse ersetzen."
msgid "IPv4 for %s (%s)"
msgstr "IPv4 für %s (%s)"
msgid "IPv6 for %s (%s)"
msgstr "IPv6 für %s (%s)"
msgid "IBSS (legacy) Mesh on %s"
msgstr "IBSS (veraltet) Mesh auf %s"
msgid "Mesh on %s"
msgstr "Mesh auf %s"
msgid "Mesh VPN"
msgstr "Mesh VPN"
msgid "Mesh on WAN"
msgstr "Mesh auf WAN"
msgid "Mesh on LAN"
msgstr "Mesh auf LAN"
msgid "this node"
msgstr "diesen Knoten"

View File

@ -0,0 +1,57 @@
#, fuzzy
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.0\n"
msgid "Static IPs"
msgstr ""
msgid "Configure the IPv4 addresses of your node."
msgstr ""
msgid "Configure the IPv6 addresses of your node."
msgstr ""
msgid "enabled"
msgstr ""
msgid "disabled"
msgstr ""
msgid "The address %s for \"%s\" is an address in the temporary address range %s.<br />It should be replaced by a properly assigned address as soon as possible."
msgstr ""
msgid "The address %s for \"%s\" is an address in the temporary address range %s.<br />If you are planning to use this interface, you will need to replace this address with a properly assigned one."
msgstr ""
msgid "IPv4 for %s (%s)"
msgstr ""
msgid "IPv6 for %s (%s)"
msgstr ""
msgid "IBSS (legacy) Mesh on %s"
msgstr ""
msgid "Mesh on %s"
msgstr ""
msgid "Mesh VPN"
msgstr ""
msgid "Mesh on WAN"
msgstr ""
msgid "Mesh on LAN"
msgstr ""
msgid "this node"
msgstr ""

View File

@ -0,0 +1,3 @@
package 'gluon-web-static-ip'
entry({"admin", "staticip"}, model("admin/staticip"), _("Static IPs"), 30)

View File

@ -0,0 +1,149 @@
local uci = require("simple-uci").cursor()
local wireless = require 'gluon.wireless'
local ip = require 'luci.ip'
local site = require 'gluon.site'
local sysconfig = require 'gluon.sysconfig'
local util = require 'gluon.util'
local mesh_interfaces = util.get_role_interfaces(uci, 'mesh')
local uplink_interfaces = util.get_role_interfaces(uci, 'uplink')
local mesh_interfaces_uplink = {}
local mesh_interfaces_other = {}
for _, iface in ipairs(mesh_interfaces) do
if util.contains(uplink_interfaces, iface) then
table.insert(mesh_interfaces_uplink, iface)
else
table.insert(mesh_interfaces_other, iface)
end
end
local f = Form(translate("Static IPs"))
local s4 = site.prefix4() and f:section(Section, nil, translate(
'Configure the IPv4 addresses of your node.'
))
local s6 = site.prefix6() and f:section(Section, nil, translate(
'Configure the IPv6 addresses of your node.'
))
local function translate_format(str, ...)
return string.format(translate(str), ...)
end
local function intf_setting(intf, desc, enabled)
local status = enabled and translate("enabled") or translate("disabled")
if site.prefix4() and intf ~= 'loopback' then
local v4addr = uci:get('gluon-static-ip', intf, 'ip4')
if site.tmpIp4() and v4addr then
local tmp = ip.new(site.tmpIp4(), site.tmpIp4Range())
local isTmp = tmp:contains(ip.new(v4addr):host())
if isTmp then
local w = Warning()
if enabled then
w:setcontent(translate_format('The address %s for "%s" is an address in the temporary address range %s.<br />It should be replaced by a properly assigned address as soon as possible.',
v4addr, desc, tmp:string()))
else
w:setcontent(translate_format('The address %s for "%s" is an address in the temporary address range %s.<br />If you are planning to use this interface, you will need to replace this address with a properly assigned one.',
v4addr, desc, tmp:string()))
end
s4:append(w)
end
end
local v4 = s4:option(Value, intf .. '_ip4', translate_format("IPv4 for %s (%s)", desc, status), translate("IPv4 CIDR (e.g. 1.2.3.4/12)"))
-- TODO: datatype = "ip4cidr"
v4.datatype = "maxlength(32)"
v4.default = v4addr
v4.required = site.tmpIp4()
function v4:write(data)
-- TODO: validate via datatype
if data == '' and not site.tmpIp4() then
data = null
end
if data and (not ip.new(data) or not ip.new(data):is4()) then
error('Not a valid IPv4 for ' .. intf)
end
uci:set("gluon-static-ip", intf, "ip4", data)
end
end
if site.prefix6() then
local v6addr = uci:get('gluon-static-ip', intf, 'ip6')
if site.tmpIp6() and v6addr then
local tmp = ip.new(site.tmpIp6(), site.tmpIp6Range())
local isTmp = tmp:contains(ip.new(v6addr):host())
if isTmp then
local w = Warning()
if enabled then
w:setcontent(translate_format('The address %s for "%s" is an address in the temporary address range %s.<br />It should be replaced by a properly assigned address as soon as possible.',
v6addr, desc, tmp:string()))
else
w:setcontent(translate_format('The address %s for "%s" is an address in the temporary address range %s.<br />If you are planning to use this interface, you will need to replace this address with a properly assigned one.',
v6addr, desc, tmp:string()))
end
s6:append(w)
end
end
local v6 = s6:option(Value, intf .. '_ip6', translate_format("IPv6 for %s (%s)", desc, status), translate("IPv6 CIDR (e.g. aa:bb:cc:dd:ee::ff/64)"))
-- TODO: datatype = "ip6cidr"
v6.datatype = "maxlength(132)"
v6.default = v6addr
function v6:write(data)
-- TODO: validate via datatype
if data == '' and (not site.tmpIp6() or (not site.tmpIp6Everywhere() or intf ~= 'loopback')) then
data = null
end
if data and (not ip.new(data) or not ip.new(data):is6()) then
error('Not a valid IPv6 for ' .. intf)
end
uci:set("gluon-static-ip", intf, "ip6", data)
end
end
end
intf_setting('loopback', translate('this node'), true)
wireless.foreach_radio(uci, function(radio, index, config)
local function do_conf(type, desc)
local net = type .. radio['.name']
intf_setting(net, desc, not uci:get_bool('wireless', net, 'disabled'))
end
if uci:get('network', 'ibss_' .. radio['.name'], 'proto') then
do_conf('ibss_', translate_format('IBSS (legacy) Mesh on %s', radio['.name']))
end
do_conf('mesh_', translate_format('Mesh on %s', radio['.name']))
end)
if pcall(function() require 'gluon.mesh-vpn' end) then
local vpn_core = require 'gluon.mesh-vpn'
intf_setting('mesh_vpn', 'Mesh VPN', vpn_core.enabled())
end
local wan_mesh = not uci:get_bool('network', 'mesh_wan', 'disabled')
intf_setting('mesh_uplink', 'Mesh on WAN', #mesh_interfaces_uplink)
if sysconfig.lan_ifname then
intf_setting('mesh_other', 'Mesh on LAN', #mesh_interfaces_other)
end
function f:write()
uci:save("gluon-static-ip")
end
return f