mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-09-10 18:34:18 +08:00
🌴 Sync 2026-03-05 23:51:42
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
PKG_NAME:=luci-proto-tinc
|
||||
PKG_VERSION:=1.0.0
|
||||
PKG_RELEASE:=1
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/luci-proto-tinc
|
||||
SECTION:=net
|
||||
CATEGORY:=protocols
|
||||
TITLE:=Protocol for TincVPN
|
||||
PKGARCH:=all
|
||||
DEPENDS:=+tinc
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./files/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Package/luci-proto-tinc/install
|
||||
$(INSTALL_DIR) $(1)/lib/netifd/proto
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/netifd/proto/tinc.sh $(1)/lib/netifd/proto
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/netifd/tinc.script $(1)/lib/netifd
|
||||
$(INSTALL_DIR) $(1)/www/luci-static/resources/protocol
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/www/luci-static/resources/protocol/tinc.js $(1)/www/luci-static/resources/protocol
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,luci-proto-tinc))
|
||||
@@ -0,0 +1,2 @@
|
||||
.PHONY: all
|
||||
all:
|
||||
@@ -0,0 +1,118 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -x /usr/sbin/tincd ] || exit 0
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
. /lib/functions.sh
|
||||
. ../netifd-proto.sh
|
||||
init_proto "$@"
|
||||
}
|
||||
|
||||
proto_tinc_append() {
|
||||
append "$3" "$1"
|
||||
}
|
||||
|
||||
proto_tinc_init_config() {
|
||||
no_device=1
|
||||
available=1
|
||||
renew_handler=1
|
||||
|
||||
proto_config_add_string ipaddr
|
||||
proto_config_add_string ip6addr
|
||||
proto_config_add_string name
|
||||
proto_config_add_string bindtoaddr
|
||||
proto_config_add_string 'mode:or("router","switch","hub")'
|
||||
proto_config_add_string 'priority:or("low","normal","high")'
|
||||
proto_config_add_string 'strict_subnets:or("no","yes")'
|
||||
proto_config_add_array 'connect:list(string)'
|
||||
proto_config_add_array 'option:list(string)'
|
||||
proto_config_add_array 'subnet:list(string)'
|
||||
proto_config_add_array 'route:list(string)'
|
||||
proto_config_add_int mtu
|
||||
}
|
||||
|
||||
proto_tinc_setup() {
|
||||
local config="$1"
|
||||
|
||||
local ipaddr ip6addr name bindtoaddr connect connects mode priority strict_subnets option options subnet subnets route routes mtu
|
||||
json_get_vars ipaddr ip6addr name bindtoaddr mode priority strict_subnets mtu
|
||||
json_for_each_item proto_tinc_append connect connects
|
||||
json_for_each_item proto_tinc_append option options
|
||||
json_for_each_item proto_tinc_append subnet subnets
|
||||
json_for_each_item proto_tinc_append route routes
|
||||
|
||||
proto_export CONFIG="$config"
|
||||
proto_export IPADDR="$ipaddr"
|
||||
proto_export IP6ADDR="$ip6addr"
|
||||
proto_export ROUTES="$routes"
|
||||
proto_export MTU="$mtu"
|
||||
|
||||
config_dir="/etc/tinc/$config"
|
||||
tmp_config_dir="/tmp/tinc/$config"
|
||||
tmp_config_file="$tmp_config_dir/tinc.conf"
|
||||
|
||||
rm -rf $tmp_config_dir
|
||||
cp -rf $config_dir $tmp_config_dir
|
||||
cp -f /lib/netifd/tinc.script $tmp_config_dir/tinc-up
|
||||
chmod 755 $tmp_config_dir/tinc-up
|
||||
|
||||
mkdir -p $config_dir/hosts $tmp_config_dir/hosts
|
||||
{
|
||||
echo "Name=$name"
|
||||
echo "Interface=tinc-$config"
|
||||
echo "Mode=$mode"
|
||||
|
||||
[ -z "$bindtoaddr" ] || echo "BindToAddress=$bindtoaddr"
|
||||
[ -z "$priority" ] || echo "ProcessPriority=$priority"
|
||||
[ -z "$strict_subnets" ] || echo "StrictSubnets=$strict_subnets"
|
||||
|
||||
for host in $connects; do
|
||||
echo "ConnectTo=$host"
|
||||
done
|
||||
|
||||
for option in $options; do
|
||||
echo "$option"
|
||||
done
|
||||
} > $tmp_config_file
|
||||
|
||||
if [ ! -f $tmp_config_dir/hosts/$name ]; then
|
||||
tincd -c $tmp_config_dir -K
|
||||
cp -f $tmp_config_dir/*.priv $config_dir
|
||||
cp -rf $tmp_config_dir/hosts $config_dir
|
||||
fi
|
||||
|
||||
{
|
||||
if [ -n "$ipaddr" ]; then
|
||||
echo "Subnet=${ipaddr%%/*}/32"
|
||||
fi
|
||||
if [ -n "$ip6addr" ]; then
|
||||
echo "Subnet=${ip6addr%%/*}/128"
|
||||
fi
|
||||
for subnet in $subnets; do
|
||||
echo "Subnet=$subnet"
|
||||
done
|
||||
cat $config_dir/hosts/$name
|
||||
} > $tmp_config_dir/hosts/$name
|
||||
|
||||
proto_run_command "$config" /usr/sbin/tincd \
|
||||
-c $tmp_config_dir \
|
||||
--no-detach \
|
||||
--pidfile=/var/run/tinc.${config}.pid \
|
||||
--logfile=/tmp/log/tinc.${config}.log
|
||||
}
|
||||
|
||||
proto_tinc_teardown() {
|
||||
local config="$1"
|
||||
logger -t tinc "stopping..."
|
||||
proto_kill_command "$config" 9
|
||||
}
|
||||
|
||||
proto_tinc_renew() {
|
||||
local iface="$1"
|
||||
logger -t tinc "renew $iface ..."
|
||||
}
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
add_protocol tinc
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /lib/netifd/netifd-proto.sh
|
||||
|
||||
add_route() {
|
||||
local route="$1"
|
||||
local next version target mask gw metric
|
||||
version="${route%%,*}"
|
||||
next="${route#*,}"
|
||||
target="${next%%/*}"
|
||||
next="${route#*/}"
|
||||
mask="${next%%,*}"
|
||||
next="${next#*,}"
|
||||
if [ "$next" != "$mask" ]; then
|
||||
gw="${next%%,*}"
|
||||
next="${next#*,}"
|
||||
if [ "$next" == "$gw" ]; then
|
||||
metric="$gw"
|
||||
gw=""
|
||||
else
|
||||
metric="${next#*,}"
|
||||
fi
|
||||
fi
|
||||
if [ "$version" == "4" ]; then
|
||||
echo proto_add_ipv4_route \"$target\" \"$mask\" \"$gw\" \"\" \"$metric\"
|
||||
else
|
||||
echo proto_add_ipv6_route \"$target\" \"$mask\" \"$gw\" \"$metric\"
|
||||
fi
|
||||
}
|
||||
|
||||
proto_init_update "$INTERFACE" 1
|
||||
|
||||
if [ -n "$IPADDR" ]; then
|
||||
proto_add_ipv4_address "${IPADDR%%/*}" "${IPADDR##*/}"
|
||||
fi
|
||||
|
||||
if [ -n "$IP6ADDR" ]; then
|
||||
proto_add_ipv6_address "${IP6ADDR%%/*}" "${IP6ADDR##*/}"
|
||||
fi
|
||||
|
||||
# version,target/mask,gw,metric
|
||||
# version,target/mask,metric
|
||||
# version,target/mask
|
||||
|
||||
for route in $ROUTES; do
|
||||
eval $(add_route $route)
|
||||
done
|
||||
|
||||
echo "MTU:$MTU">>/tmp/debug.txt
|
||||
if [ -n "$MTU" ]; then
|
||||
ip link set $INTERFACE mtu $MTU
|
||||
fi
|
||||
|
||||
proto_send_update "$CONFIG"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/etc/tinc/
|
||||
@@ -0,0 +1,157 @@
|
||||
'use strict';
|
||||
'require uci';
|
||||
'require form';
|
||||
'require network';
|
||||
'require fs';
|
||||
'require ui';
|
||||
|
||||
network.registerPatternVirtual(/^tinc-.+$/);
|
||||
function getHosts(section_id) {
|
||||
return fs.list('/etc/tinc/' + section_id + '/hosts').then(function (lines) {
|
||||
return lines.map(function (file) {
|
||||
if (file.type === 'file') {
|
||||
return file.name;
|
||||
}
|
||||
});
|
||||
}).then(L.bind(function (names) {
|
||||
this.names = names;
|
||||
return this.super('load', section_id);
|
||||
}, this));
|
||||
}
|
||||
return network.registerProtocol('tinc', {
|
||||
IPAddr: form.Value.extend({
|
||||
validate: function (section_id, value) {
|
||||
var str = this.formvalue(section_id);
|
||||
if (str.length > 0) {
|
||||
var m = str.match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,3}$/);
|
||||
if (!m) {
|
||||
return _('Expecting: valid IPv4 CIDR');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
IP6Addr: form.Value.extend({
|
||||
validate: function (section_id, value) {
|
||||
var str = this.formvalue(section_id);
|
||||
if (str.length > 0) {
|
||||
var m = str.match(/^([\da-fA-F]{1,4}:){6}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^::([\da-fA-F]{1,4}:){0,4}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^([\da-fA-F]{1,4}:):([\da-fA-F]{1,4}:){0,3}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^([\da-fA-F]{1,4}:){2}:([\da-fA-F]{1,4}:){0,2}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^([\da-fA-F]{1,4}:){3}:([\da-fA-F]{1,4}:){0,1}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^([\da-fA-F]{1,4}:){4}:((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^:((:[\da-fA-F]{1,4}){1,6}|:)(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^[\da-fA-F]{1,4}:((:[\da-fA-F]{1,4}){1,5}|:)(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^([\da-fA-F]{1,4}:){2}((:[\da-fA-F]{1,4}){1,4}|:)(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^([\da-fA-F]{1,4}:){3}((:[\da-fA-F]{1,4}){1,3}|:)(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^([\da-fA-F]{1,4}:){4}((:[\da-fA-F]{1,4}){1,2}|:)(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^([\da-fA-F]{1,4}:){5}:([\da-fA-F]{1,4})?(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$|^([\da-fA-F]{1,4}:){6}:(\/([1-9]?\d|(1([0-1]\d|2[0-8]))))?$/);
|
||||
if (!m) {
|
||||
return _('Expecting: valid IPv6 CIDR');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
Name: form.Value.extend({
|
||||
validate: function (section_id, value) {
|
||||
var str = this.formvalue(section_id);
|
||||
if (str.length > 16 || !str.match(/^[a-zA-Z0-9_\-.]+$/)) {
|
||||
return _('valid node name');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
BindToAddress: form.Value.extend({
|
||||
validate: function (section_id, value) {
|
||||
var str = this.formvalue(section_id);
|
||||
if (str.length > 0 && !str.match(/^\*\ \d+$/)) {
|
||||
return _('Format: <address> [<port>]');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
DropDownList: form.ListValue.extend({
|
||||
renderWidget: function (section_id, option_index, cfgvalue) {
|
||||
var values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
|
||||
var widget = new ui.Dropdown(values, this.choices, {
|
||||
id: this.cbid(section_id),
|
||||
sort: this.sort,
|
||||
multiple: this.multiple,
|
||||
optional: this.optional,
|
||||
select_placeholder: E('em', _(this.placeholder || 'unspecified')),
|
||||
optional: this.optional || this.rmempty,
|
||||
});
|
||||
return widget.render();
|
||||
}
|
||||
}),
|
||||
ConnectTo: form.ListValue.extend({
|
||||
load: getHosts,
|
||||
filter: function (section_id, value) {
|
||||
return true;
|
||||
},
|
||||
renderWidget: function (section_id, option_index, cfgvalue) {
|
||||
var values = L.toArray((cfgvalue != null) ? cfgvalue : this.default)
|
||||
, choices = {};
|
||||
for (var i = 0; i < this.names.length; i++) {
|
||||
choices[this.names[i]] = E('span', {
|
||||
'class': 'zonebadge',
|
||||
}, E('label', _(this.names[i])));
|
||||
}
|
||||
var widget = new ui.Dropdown(values, choices, {
|
||||
id: this.cbid(section_id),
|
||||
sort: true,
|
||||
multiple: true,
|
||||
select_placeholder: E('em', _(this.placeholder || 'unspecified')),
|
||||
});
|
||||
return widget.render();
|
||||
}
|
||||
}),
|
||||
Option: form.DynamicList.extend({
|
||||
validate: function (section_id, value) {
|
||||
var val = this.formvalue(section_id),
|
||||
i;
|
||||
for (i = 0; i < val.length; i++) {
|
||||
if (val[i].length > 0 && !val[i].match(/^[a-zA-Z0-9_\-]+=[a-zA-Z0-9_\-]+$/)) {
|
||||
return _('Expecting: valid option');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
Route: form.DynamicList.extend({
|
||||
validate: function (section_id, value) {
|
||||
var val = this.formvalue(section_id),
|
||||
i;
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
getI18n: function () {
|
||||
return _('TincVPN');
|
||||
},
|
||||
getIfname: function () {
|
||||
return this._ubus('l3_device') || 'tinc-%s'.format(this.sid);
|
||||
},
|
||||
getOpkgPackage: function () {
|
||||
return 'tinc';
|
||||
},
|
||||
containsDevice: function (ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
renderFormOptions: function (s) {
|
||||
var dev = this.getL3Device() || this.getDevice(),
|
||||
o;
|
||||
o = s.taboption('general', this.IPAddr, 'ipaddr', _('IPv4 Address'));
|
||||
o.datatype = 'cidr';
|
||||
o = s.taboption('general', this.IP6Addr, 'ip6addr', _('IPv6 Address'));
|
||||
o.datatype = 'cidr6';
|
||||
o.optional = true
|
||||
o = s.taboption('general', this.Name, 'name', _('Name'));
|
||||
s.taboption('general', this.BindToAddress, 'bindtoaddr', _('BindToAddress'));
|
||||
s.taboption('general', this.ConnectTo, 'connect', _('ConnectTo'));
|
||||
o = s.taboption('general', this.DropDownList, 'mode', _('Mode'));
|
||||
o.choices = { 'router': 'router', 'switch': 'switch', 'hub': 'hub' };
|
||||
o = s.taboption('general', this.DropDownList, 'priority', _('ProcessPriority'));
|
||||
o.choices = { 'low': 'low', 'normal': 'normal', 'high': 'high' };
|
||||
o = s.taboption('general', this.DropDownList, 'strict_subnets', _('StrictSubnets'));
|
||||
o.choices = { 'yes': 'yes', 'no': 'no' };
|
||||
s.taboption('general', this.Option, 'option', _('Extra option'));
|
||||
o = s.taboption('general', form.DynamicList, 'subnet', _('Subnet'));
|
||||
o.datatype = 'cidr';
|
||||
s.taboption('general', this.Route, 'route', _('Route'));
|
||||
o = s.taboption('general', form.Value, 'mtu', _('Override MTU'));
|
||||
o.placeholder = dev ? (dev.getMTU() || '1400') : '1400';
|
||||
o.datatype = 'range(68, 9200)';
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user