diff --git a/luci-app-zerotier/Makefile b/luci-app-zerotier/Makefile
new file mode 100644
index 00000000..93cea593
--- /dev/null
+++ b/luci-app-zerotier/Makefile
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-3.0-only
+#
+# Copyright (C) 2022 ImmortalWrt.org
+
+include $(TOPDIR)/rules.mk
+
+LUCI_TITLE:=LuCI for Zerotier
+LUCI_DEPENDS:=+zerotier +jsonfilter +ucode
+LUCI_PKGARCH:=all
+
+define Package/$(PKG_NAME)/conffiles
+/etc/zerotier/
+endef
+
+include $(TOPDIR)/feeds/luci/luci.mk
+
+# call BuildPackage - OpenWrt buildroot signature
diff --git a/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js b/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js
new file mode 100644
index 00000000..a26d437d
--- /dev/null
+++ b/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-3.0-only
+ *
+ * Copyright (C) 2022 ImmortalWrt.org
+ */
+
+'use strict';
+'require form';
+'require poll';
+'require rpc';
+'require uci';
+'require view';
+
+var callServiceList = rpc.declare({
+ object: 'service',
+ method: 'list',
+ params: ['name'],
+ expect: { '': {} }
+});
+
+function getServiceStatus() {
+ return L.resolveDefault(callServiceList('zerotier'), {}).then(function (res) {
+ var isRunning = false;
+ try {
+ isRunning = res['zerotier']['instances']['instance1']['running'];
+ } catch (e) { }
+ return isRunning;
+ });
+}
+
+function renderStatus(isRunning) {
+ var spanTemp = '%s %s';
+ var renderHTML;
+ if (isRunning) {
+ renderHTML = String.format(spanTemp, 'green', _('ZeroTier'), _('RUNNING'));
+ } else {
+ renderHTML = String.format(spanTemp, 'red', _('ZeroTier'), _('NOT RUNNING'));
+ }
+
+ return renderHTML;
+}
+
+return view.extend({
+ load: function() {
+ return Promise.all([
+ uci.load('zerotier')
+ ]);
+ },
+
+ render: function(data) {
+ var m, s, o;
+
+ m = new form.Map('zerotier', _('ZeroTier'),
+ _('ZeroTier is an open source, cross-platform and easy to use virtual LAN.'));
+
+ s = m.section(form.TypedSection);
+ s.anonymous = true;
+ s.render = function () {
+ poll.add(function () {
+ return L.resolveDefault(getServiceStatus()).then(function (res) {
+ var view = document.getElementById("service_status");
+ view.innerHTML = renderStatus(res);
+ });
+ });
+
+ return E('div', { class: 'cbi-section', id: 'status_bar' }, [
+ E('p', { id: 'service_status' }, _('Collecting data ...'))
+ ]);
+ }
+
+ s = m.section(form.NamedSection, 'sample_config', 'config');
+
+ o = s.option(form.Flag, 'enabled', _('Enable'));
+ o.default = o.disabled;
+ o.rmempty = false;
+
+ o = s.option(form.DynamicList, 'join', _('Network ID'));
+ o.rmempty = false;
+
+ o = s.option(form.Flag, 'nat', _('Auto NAT clients'),
+ _('Allow ZeroTier clients access your LAN network.'));
+ o.default = o.disabled;
+ o.rmempty = false;
+
+ o = s.option(form.Button, '_panel', _('ZeroTier Central'),
+ _('Create or manage your ZeroTier network, and auth clients who could access.'));
+ o.inputtitle = _('Open website');
+ o.inputstyle = 'apply';
+ o.onclick = function () {
+ window.open("https://my.zerotier.com/network", '_blank');
+ }
+
+ return m.render();
+ }
+});
diff --git a/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js b/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js
new file mode 100644
index 00000000..de726662
--- /dev/null
+++ b/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: GPL-3.0-only
+ *
+ * Copyright (C) 2022 ImmortalWrt.org
+ */
+
+'use strict';
+'require fs';
+'require ui';
+'require view';
+
+return view.extend({
+ load: function() {
+ return fs.exec('/sbin/ifconfig').then(function(res) {
+ if (res.code !== 0 || !res.stdout || res.stdout.trim() === '') {
+ ui.addNotification(null, E('p', {}, _('Unable to get interface info: %s.').format(res.message)));
+ return '';
+ }
+
+ var interfaces = res.stdout.match(/zt[a-z0-9]+/g);
+ if (!interfaces || interfaces.length === 0)
+ return 'No interface online.';
+
+ var promises = interfaces.map(function(name) {
+ return fs.exec('/sbin/ifconfig', [name]);
+ });
+
+ return Promise.all(promises).then(function(results) {
+ var data = results.map(function(res, index) {
+ if (res.code !== 0 || !res.stdout || res.stdout.trim() === '') {
+ ui.addNotification(null, E('p', {}, _('Unable to get interface %s info: %s.').format(interfaces[index], res.message)));
+ return null;
+ }
+ return {
+ name: interfaces[index],
+ stdout: res.stdout.trim()
+ };
+ }).filter(Boolean);
+
+ return data.map(function(info) {
+ var lines = info.stdout.split('\n');
+ var parsedInfo = {
+ name: info.name
+ };
+
+ lines.forEach(function(line) {
+ if (line.includes('HWaddr')) {
+ parsedInfo.mac = line.split('HWaddr')[1].trim().split(' ')[0];
+ } else if (line.includes('inet addr:')) {
+ parsedInfo.ipv4 = line.split('inet addr:')[1].trim().split(' ')[0];
+ } else if (line.includes('inet6 addr:')) {
+ parsedInfo.ipv6 = line.split('inet6 addr:')[1].trim().split('/')[0];
+ } else if (line.includes('MTU:')) {
+ parsedInfo.mtu = line.split('MTU:')[1].trim().split(' ')[0];
+ } else if (line.includes('RX bytes:')) {
+ var rxMatch = line.match(/RX bytes:\d+ \(([\d.]+\s*[a-zA-Z]+)\)/);
+ if (rxMatch && rxMatch[1]) {
+ parsedInfo.rxBytes = rxMatch[1];
+ }
+ var txMatch = line.match(/TX bytes:\d+ \(([\d.]+\s*[a-zA-Z]+)\)/);
+ if (txMatch && txMatch[1]) {
+ parsedInfo.txBytes = txMatch[1];
+ }
+ }
+ });
+
+ return parsedInfo;
+ });
+ });
+ });
+ },
+
+ render: function(data) {
+ var title = E('h2', {class: 'content'}, _('ZeroTier'));
+ var desc = E('div', {class: 'cbi-map-descr'}, _('ZeroTier is an open source, cross-platform and easy to use virtual LAN.'));
+
+ if (!Array.isArray(data)) {
+ return E('div', {}, [title, desc, E('div', {}, _('No interface online.'))]);
+ }
+ var rows = data.flatMap(function(interfaceData) {
+ return [
+ E('th', {class: 'th', colspan: '2'}, _('Network Interface Information')),
+ E('tr', {class: 'tr'}, [
+ E('td', {class: 'td left', width: '25%'}, _('Interface Name')),
+ E('td', {class: 'td left', width: '25%'}, interfaceData.name)
+ ]),
+ E('tr', {class: 'tr'}, [
+ E('td', {class: 'td left', width: '25%'}, _('MAC Address')),
+ E('td', {class: 'td left', width: '25%'}, interfaceData.mac)
+ ]),
+ E('tr', {class: 'tr'}, [
+ E('td', {class: 'td left', width: '25%'}, _('IPv4 Address')),
+ E('td', {class: 'td left', width: '25%'}, interfaceData.ipv4)
+ ]),
+ E('tr', {class: 'tr'}, [
+ E('td', {class: 'td left', width: '25%'}, _('IPv6 Address')),
+ E('td', {class: 'td left', width: '25%'}, interfaceData.ipv6)
+ ]),
+ E('tr', {class: 'tr'}, [
+ E('td', {class: 'td left', width: '25%'}, _('MTU')),
+ E('td', {class: 'td left', width: '25%'}, interfaceData.mtu)
+ ]),
+ E('tr', {class: 'tr'}, [
+ E('td', {class: 'td left', width: '25%'}, _('Total Download')),
+ E('td', {class: 'td left', width: '25%'}, interfaceData.rxBytes)
+ ]),
+ E('tr', {class: 'tr'}, [
+ E('td', {class: 'td left', width: '25%'}, _('Total Upload')),
+ E('td', {class: 'td left', width: '25%'}, interfaceData.txBytes)
+ ])
+ ];
+ });
+
+ return E('div', {}, [title, desc, E('table', { 'class': 'table' }, rows)]);
+ },
+
+ handleSaveApply: null,
+ handleSave: null,
+ handleReset: null
+});
diff --git a/luci-app-zerotier/po/templates/zerotier.pot b/luci-app-zerotier/po/templates/zerotier.pot
new file mode 100644
index 00000000..b8619f45
--- /dev/null
+++ b/luci-app-zerotier/po/templates/zerotier.pot
@@ -0,0 +1,112 @@
+msgid ""
+msgstr "Content-Type: text/plain; charset=UTF-8"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:80
+msgid "Allow ZeroTier clients access your LAN network."
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:79
+msgid "Auto NAT clients"
+msgstr ""
+
+#: applications/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json:14
+msgid "Base settings"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:66
+msgid "Collecting data ..."
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:85
+msgid ""
+"Create or manage your ZeroTier network, and auth clients who could access."
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:72
+msgid "Enable"
+msgstr ""
+
+#: applications/luci-app-zerotier/root/usr/share/rpcd/acl.d/luci-app-zerotier.json:3
+msgid "Grant access to ZeroTier configuration"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:91
+msgid "IPv4 Address"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:95
+msgid "IPv6 Address"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:83
+msgid "Interface Name"
+msgstr ""
+
+#: applications/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json:22
+msgid "Interface info"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:87
+msgid "MAC Address"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:99
+msgid "MTU"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:36
+msgid "NOT RUNNING"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:76
+msgid "Network ID"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:81
+msgid "Network Interface Information"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:77
+msgid "No interface online."
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:86
+msgid "Open website"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:34
+msgid "RUNNING"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:103
+msgid "Total Download"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:107
+msgid "Total Upload"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:30
+msgid "Unable to get interface %s info: %s."
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:15
+msgid "Unable to get interface info: %s."
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:34
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:36
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:52
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:73
+#: applications/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json:3
+msgid "ZeroTier"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:84
+msgid "ZeroTier Central"
+msgstr ""
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:53
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:74
+msgid "ZeroTier is an open source, cross-platform and easy to use virtual LAN."
+msgstr ""
diff --git a/luci-app-zerotier/po/zh-cn b/luci-app-zerotier/po/zh-cn
new file mode 120000
index 00000000..8d69574d
--- /dev/null
+++ b/luci-app-zerotier/po/zh-cn
@@ -0,0 +1 @@
+zh_Hans
\ No newline at end of file
diff --git a/luci-app-zerotier/po/zh_Hans/zerotier.po b/luci-app-zerotier/po/zh_Hans/zerotier.po
new file mode 100644
index 00000000..76f51b53
--- /dev/null
+++ b/luci-app-zerotier/po/zh_Hans/zerotier.po
@@ -0,0 +1,118 @@
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: zh_Hans\n"
+"MIME-Version: 1.0\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:80
+msgid "Allow ZeroTier clients access your LAN network."
+msgstr "允许 ZeroTier 客户端访问您的局域网。"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:79
+msgid "Auto NAT clients"
+msgstr "自动客户端 NAT"
+
+#: applications/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json:14
+msgid "Base settings"
+msgstr "基本设置"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:66
+msgid "Collecting data ..."
+msgstr "收集数据中 ..."
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:85
+msgid ""
+"Create or manage your ZeroTier network, and auth clients who could access."
+msgstr "创建或管理您的 ZeroTier 网络,并允许客户端接入。"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:72
+msgid "Enable"
+msgstr "启用"
+
+#: applications/luci-app-zerotier/root/usr/share/rpcd/acl.d/luci-app-zerotier.json:3
+msgid "Grant access to ZeroTier configuration"
+msgstr "授予访问 ZeroTier 配置的权限"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:91
+msgid "IPv4 Address"
+msgstr "IPv4 地址"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:95
+msgid "IPv6 Address"
+msgstr "IPv6 地址"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:83
+msgid "Interface Name"
+msgstr "接口名称"
+
+#: applications/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json:22
+msgid "Interface info"
+msgstr "接口信息"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:87
+msgid "MAC Address"
+msgstr "MAC 地址"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:99
+msgid "MTU"
+msgstr "MTU"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:36
+msgid "NOT RUNNING"
+msgstr "未运行"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:76
+msgid "Network ID"
+msgstr "网络 ID"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:81
+msgid "Network Interface Information"
+msgstr "网络接口信息"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:77
+msgid "No interface online."
+msgstr "没有在线的接口。"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:86
+msgid "Open website"
+msgstr "打开网站"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:34
+msgid "RUNNING"
+msgstr "运行中"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:103
+msgid "Total Download"
+msgstr "总下载"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:107
+msgid "Total Upload"
+msgstr "总上传"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:30
+msgid "Unable to get interface %s info: %s."
+msgstr "无法获取接口 %s 的信息:%s。"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:15
+msgid "Unable to get interface info: %s."
+msgstr "无法获取接口信息:%s。"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:34
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:36
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:52
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:73
+#: applications/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json:3
+msgid "ZeroTier"
+msgstr "ZeroTier"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:84
+msgid "ZeroTier Central"
+msgstr "ZeroTier 管理中心"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:53
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:74
+msgid "ZeroTier is an open source, cross-platform and easy to use virtual LAN."
+msgstr "ZeroTier 是一个开源、跨平台且易于使用的虚拟局域网 VPN。"
diff --git a/luci-app-zerotier/po/zh_Hant/zerotier.po b/luci-app-zerotier/po/zh_Hant/zerotier.po
new file mode 100644
index 00000000..9a6f0b3e
--- /dev/null
+++ b/luci-app-zerotier/po/zh_Hant/zerotier.po
@@ -0,0 +1,118 @@
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: zh_Hant\n"
+"MIME-Version: 1.0\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:80
+msgid "Allow ZeroTier clients access your LAN network."
+msgstr "允許 ZeroTier 用戶端訪問您的區域網路"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:79
+msgid "Auto NAT clients"
+msgstr "自動 NAT 用戶端"
+
+#: applications/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json:14
+msgid "Base settings"
+msgstr "基礎設定"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:66
+msgid "Collecting data ..."
+msgstr "收集資料中..."
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:85
+msgid ""
+"Create or manage your ZeroTier network, and auth clients who could access."
+msgstr "新建或管理您的 ZeroTier 網路,並授權用戶端訪問"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:72
+msgid "Enable"
+msgstr "啟用"
+
+#: applications/luci-app-zerotier/root/usr/share/rpcd/acl.d/luci-app-zerotier.json:3
+msgid "Grant access to ZeroTier configuration"
+msgstr "允許訪問 ZeroTier 的配置"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:91
+msgid "IPv4 Address"
+msgstr "IPv4 位址"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:95
+msgid "IPv6 Address"
+msgstr "IPv6 位址"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:83
+msgid "Interface Name"
+msgstr "介面名稱"
+
+#: applications/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json:22
+msgid "Interface info"
+msgstr "介面資訊"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:87
+msgid "MAC Address"
+msgstr "MAC 位址"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:99
+msgid "MTU"
+msgstr "MTU"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:36
+msgid "NOT RUNNING"
+msgstr "尚未執行"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:76
+msgid "Network ID"
+msgstr "網路 ID"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:81
+msgid "Network Interface Information"
+msgstr "網路介面資訊"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:77
+msgid "No interface online."
+msgstr "沒有介面在線上。"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:86
+msgid "Open website"
+msgstr "開啟網站"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:34
+msgid "RUNNING"
+msgstr "正在執行"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:103
+msgid "Total Download"
+msgstr "總下載量"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:107
+msgid "Total Upload"
+msgstr "總上傳量"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:30
+msgid "Unable to get interface %s info: %s."
+msgstr "無法取得介面 %s 的資訊:%s"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:15
+msgid "Unable to get interface info: %s."
+msgstr "無法取得介面資訊:%s"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:34
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:36
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:52
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:73
+#: applications/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json:3
+msgid "ZeroTier"
+msgstr "ZeroTier"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:84
+msgid "ZeroTier Central"
+msgstr "ZeroTier 管理中心"
+
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/base.js:53
+#: applications/luci-app-zerotier/htdocs/luci-static/resources/view/zerotier/interface.js:74
+msgid "ZeroTier is an open source, cross-platform and easy to use virtual LAN."
+msgstr "ZeroTier 是一個開源、跨平台且易於使用的虛擬區域網路 VPN"
diff --git a/luci-app-zerotier/root/etc/hotplug.d/iface/40-zerotier b/luci-app-zerotier/root/etc/hotplug.d/iface/40-zerotier
new file mode 100644
index 00000000..6e977a11
--- /dev/null
+++ b/luci-app-zerotier/root/etc/hotplug.d/iface/40-zerotier
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+zero_enable="$(uci get zerotier.sample_config.enabled)"
+nat_enable="$(uci get zerotier.sample_config.nat)"
+
+[ "$ACTION" = ifup -o "$ACTION" = ifupdate ] || exit 0
+[ "$ACTION" = ifupdate -a -z "$IFUPDATE_ADDRESSES" -a -z "$IFUPDATE_DATA" ] && exit 0
+[ "$zero_enable" -eq "1" -a "${nat_enable}" -eq "1" ] || exit 0
+/etc/zerotier.start > /tmp/zero.log 2>&1 &
diff --git a/luci-app-zerotier/root/etc/init.d/zerotier b/luci-app-zerotier/root/etc/init.d/zerotier
new file mode 100755
index 00000000..e145d406
--- /dev/null
+++ b/luci-app-zerotier/root/etc/init.d/zerotier
@@ -0,0 +1,112 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+
+USE_PROCD=1
+
+PROG=/usr/bin/zerotier-one
+CONFIG_PATH=/var/lib/zerotier-one
+
+service_triggers() {
+ procd_add_reload_trigger "zerotier"
+ procd_add_interface_trigger "interface.*.up" wan /etc/init.d/zerotier restart
+}
+
+section_enabled() {
+ config_get_bool enabled "$1" 'enabled' 0
+ [ $enabled -gt 0 ]
+}
+
+start_instance() {
+ local cfg="$1"
+ local port secret config_path
+ local ARGS=""
+
+ if ! section_enabled "$cfg"; then
+ echo "disabled in config"
+ return 1
+ fi
+
+ config_get_bool port $cfg 'port'
+ config_get secret $cfg 'secret'
+
+ # Remove existing link or folder
+ [ -d /etc/config/zero ] || mkdir -p /etc/config/zero
+ config_path=/etc/config/zero
+ rm -rf $CONFIG_PATH
+
+ # Create link from CONFIG_PATH to config_path
+ if [ -n "$config_path" -a "$config_path" != $CONFIG_PATH ]; then
+ if [ ! -d "$config_path" ]; then
+ echo "ZeroTier config_path does not exist: $config_path"
+ return
+ fi
+
+ ln -s $config_path $CONFIG_PATH
+ fi
+
+ mkdir -p $CONFIG_PATH/networks.d
+
+ if [ -n "$port" ]; then
+ ARGS="$ARGS -p$port"
+ fi
+
+ if [ "$secret" = "generate" ]; then
+ echo "Generate secret - please wait..."
+ local sf="/tmp/zt.$cfg.secret"
+
+ zerotier-idtool generate "$sf" > /dev/null
+ [ $? -ne 0 ] && return 1
+
+ secret="$(cat $sf)"
+ rm "$sf"
+
+ uci set zerotier.$cfg.secret="$secret"
+ uci commit zerotier
+ fi
+
+ if [ -n "$secret" ]; then
+ echo "$secret" > $CONFIG_PATH/identity.secret
+ # make sure there is not previous identity.public
+ rm -f $CONFIG_PATH/identity.public
+ fi
+
+ add_join() {
+ # an (empty) config file will cause ZT to join a network
+ touch $CONFIG_PATH/networks.d/$1.conf
+ }
+
+ config_list_foreach $cfg 'join' add_join
+
+ procd_open_instance
+ procd_set_param command $PROG $ARGS $CONFIG_PATH
+ procd_set_param stderr 1
+ procd_close_instance
+}
+
+start_service() {
+ config_load 'zerotier'
+ config_foreach start_instance 'zerotier'
+ touch /tmp/zero.log && /etc/zerotier.start > /tmp/zero.log 2>&1 &
+}
+
+stop_instance() {
+ rm -f /tmp/zero.log
+ local cfg="$1"
+
+ /etc/zerotier.stop > /tmp/zero.log 2>&1 &
+
+ # Remove existing link or folder
+ rm -f $CONFIG_PATH/networks.d/*.conf
+ rm -rf $CONFIG_PATH
+}
+
+stop_service() {
+ config_load 'zerotier'
+ config_foreach stop_instance 'zerotier'
+}
+
+reload_service() {
+ stop
+ start
+}
diff --git a/luci-app-zerotier/root/etc/uci-defaults/40_luci-zerotier b/luci-app-zerotier/root/etc/uci-defaults/40_luci-zerotier
new file mode 100755
index 00000000..96639fb3
--- /dev/null
+++ b/luci-app-zerotier/root/etc/uci-defaults/40_luci-zerotier
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+uci -q batch <<-EOF >/dev/null
+ delete ucitrack.@zerotier[-1]
+ commit ucitrack
+
+ delete firewall.zerotier
+ commit firewall
+EOF
+
+rm -f /tmp/luci-indexcache
+exit 0
diff --git a/luci-app-zerotier/root/etc/zerotier.start b/luci-app-zerotier/root/etc/zerotier.start
new file mode 100755
index 00000000..77487a08
--- /dev/null
+++ b/luci-app-zerotier/root/etc/zerotier.start
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+zero_enable="$(uci get zerotier.sample_config.enabled)"
+
+[ "${zero_enable}" -ne "1" ] && exit 0
+
+[ -f "/tmp/zero.log" ] && {
+ while [ -z "$(ifconfig | grep 'zt' | awk '{print $1}')" ]
+ do
+ sleep 2
+ done
+}
+
+nat_enable="$(uci get zerotier.sample_config.nat)"
+zt0="$(ifconfig | grep 'zt' | awk '{print $1}')"
+echo "${zt0}" > "/tmp/zt.nif"
+
+[ "${nat_enable}" -eq "1" ] && {
+ for i in ${zt0}
+ do
+ ip_segment=""
+ iptables -I FORWARD -i "$i" -j ACCEPT
+ iptables -I FORWARD -o "$i" -j ACCEPT
+ iptables -t nat -I POSTROUTING -o "$i" -j MASQUERADE
+ ip_segment="$(ip route | grep "dev $i proto kernel" | awk '{print $1}')"
+ iptables -t nat -I POSTROUTING -s "${ip_segment}" -j MASQUERADE
+ done
+}
diff --git a/luci-app-zerotier/root/etc/zerotier.stop b/luci-app-zerotier/root/etc/zerotier.stop
new file mode 100755
index 00000000..cbe7ec4b
--- /dev/null
+++ b/luci-app-zerotier/root/etc/zerotier.stop
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+zt0="$(ifconfig | grep 'zt' | awk '{print $1}')"
+[ -z "${zt0}" ] && zt0="$(cat "/tmp/zt.nif")"
+
+for i in ${zt0}
+do
+ ip_segment=""
+ iptables -D FORWARD -i "$i" -j ACCEPT 2>/dev/null
+ iptables -D FORWARD -o "$i" -j ACCEPT 2>/dev/null
+ iptables -t nat -D POSTROUTING -o "$i" -j MASQUERADE 2>/dev/null
+ ip_segment="$(ip route | grep "dev $i proto" | awk '{print $1}')"
+ iptables -t nat -D POSTROUTING -s "${ip_segment}" -j MASQUERADE 2>/dev/null
+ echo "zt interface $i is stopped!"
+done
diff --git a/luci-app-zerotier/root/etc/zerotier/zerotier.log b/luci-app-zerotier/root/etc/zerotier/zerotier.log
new file mode 100644
index 00000000..e69de29b
diff --git a/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json b/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json
new file mode 100644
index 00000000..956d9e47
--- /dev/null
+++ b/luci-app-zerotier/root/usr/share/luci/menu.d/luci-app-zerotier.json
@@ -0,0 +1,29 @@
+{
+ "admin/vpn/zerotier": {
+ "title": "ZeroTier",
+ "order": 90,
+ "action": {
+ "type": "firstchild"
+ },
+ "depends": {
+ "acl": [ "luci-app-zerotier" ],
+ "uci": { "zerotier": true }
+ }
+ },
+ "admin/vpn/zerotier/base": {
+ "title": "Base settings",
+ "order": 10,
+ "action": {
+ "type": "view",
+ "path": "zerotier/base"
+ }
+ },
+ "admin/vpn/zerotier/interface": {
+ "title": "Interface info",
+ "order": 20,
+ "action": {
+ "type": "view",
+ "path": "zerotier/interface"
+ }
+ }
+}
diff --git a/luci-app-zerotier/root/usr/share/rpcd/acl.d/luci-app-zerotier.json b/luci-app-zerotier/root/usr/share/rpcd/acl.d/luci-app-zerotier.json
new file mode 100644
index 00000000..656cb3c0
--- /dev/null
+++ b/luci-app-zerotier/root/usr/share/rpcd/acl.d/luci-app-zerotier.json
@@ -0,0 +1,17 @@
+{
+ "luci-app-zerotier": {
+ "description": "Grant access to ZeroTier configuration",
+ "read": {
+ "file": {
+ "/sbin/ifconfig": [ "exec" ]
+ },
+ "ubus": {
+ "service": [ "list" ]
+ },
+ "uci": [ "zerotier" ]
+ },
+ "write": {
+ "uci": [ "zerotier" ]
+ }
+ }
+}
diff --git a/netdata/Makefile b/netdata/Makefile
new file mode 100644
index 00000000..1f07ddd9
--- /dev/null
+++ b/netdata/Makefile
@@ -0,0 +1,104 @@
+#
+# Copyright (C) 2008-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=netdata
+PKG_VERSION:=1.38.1
+PKG_RELEASE:=3
+
+PKG_MAINTAINER:=Josef Schlehofer , Daniel Engberg
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:my-netdata:netdata
+
+PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/netdata/netdata/releases/download/v$(PKG_VERSION)
+PKG_HASH:=e32a5427f0c00550210dbbf0046c2621313955256edf836db686e2bc270b8d10
+PKG_BUILD_DIR=$(BUILD_DIR)/$(PKG_NAME)-v$(PKG_VERSION)
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_DEPENDS:=protobuf/host
+PKG_FIXUP:=autoreconf
+PKG_BUILD_FLAGS:=no-mips16 gc-sections
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/netdata
+ SECTION:=admin
+ CATEGORY:=Administration
+ DEPENDS:=+zlib +libuuid +libuv +libmnl +libjson-c +libopenssl \
+ +libstdcpp +libatomic +protobuf +openssl-util +curl +bash
+ TITLE:=Real-time performance monitoring tool
+ URL:=https://www.netdata.cloud/
+endef
+
+define Package/netdata/description
+ netdata is a highly optimized Linux daemon providing real-time performance
+ monitoring for Linux systems, applications and SNMP devices over the web.
+
+ If you want to use Python plugins install python3, python3-yaml and
+ python3-urllib3
+endef
+
+TARGET_CFLAGS := $(filter-out -O%,$(TARGET_CFLAGS)) -O3
+
+CONFIGURE_ARGS += \
+ --with-zlib \
+ --with-math \
+ --disable-x86-sse \
+ --enable-lto \
+ --disable-ebpf \
+ --without-libcap \
+ --disable-dbengine \
+ --disable-compression \
+ --disable-plugin-nfacct \
+ --disable-plugin-freeipmi \
+ --disable-plugin-cups \
+ --disable-plugin-xenstat \
+ --disable-exporting-prometheus-remote-write \
+ --disable-unit-tests \
+ --disable-ml
+
+define Build/Configure
+ $(SED) 's/m4_esyscmd(\[git describe .*\])/$(PKG_VERSION)/' $(PKG_BUILD_DIR)/configure.ac
+ $(Build/Configure/Default)
+endef
+
+define Package/netdata/conffiles
+/etc/netdata/
+endef
+
+define Package/netdata/install
+ $(INSTALL_DIR) $(1)/etc/netdata/custom-plugins.d
+ $(CP) $(PKG_INSTALL_DIR)/etc/netdata $(1)/etc
+ $(CP) ./files/netdata.conf $(1)/etc/netdata
+ touch $(1)/etc/netdata/.opt-out-from-anonymous-statistics
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/netdata $(1)/usr/lib
+ $(CP) $(1)/usr/lib/netdata/conf.d/health_alarm_notify.conf $(1)/etc
+ $(CP) $(1)/usr/lib/netdata/plugins.d/tc-qos-helper.sh $(1)/etc
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/netdata $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/netdatacli $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/netdata-claim.sh $(1)/usr/sbin
+ $(INSTALL_DIR) $(1)/usr/share/netdata
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/netdata $(1)/usr/share
+ rm $(1)/usr/share/netdata/web/demo*html
+ rm $(1)/usr/share/netdata/web/fonts/*.svg
+ rm $(1)/usr/share/netdata/web/fonts/*.ttf
+ rm $(1)/usr/share/netdata/web/fonts/*.woff
+ rm $(1)/usr/share/netdata/web/images/*.png
+ rm $(1)/usr/share/netdata/web/images/*.gif
+ rm $(1)/usr/share/netdata/web/images/*.ico
+ rm -rf $(1)/usr/share/netdata/web/old
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/netdata.init $(1)/etc/init.d/netdata
+endef
+
+$(eval $(call BuildPackage,netdata))
diff --git a/netdata/files/netdata.conf b/netdata/files/netdata.conf
new file mode 100644
index 00000000..4a247daa
--- /dev/null
+++ b/netdata/files/netdata.conf
@@ -0,0 +1,32 @@
+# Full configuration can be retrieved from the running
+# server at http://localhost:19999/netdata.conf
+#
+# Example:
+# curl -o /etc/netdata/netdata.conf http://localhost:19999/netdata.conf
+#
+
+[global]
+ update every = 2
+ memory deduplication (ksm) = no
+ debug log = syslog
+ error log = syslog
+ access log = none
+ run as user = root
+
+[web]
+ allow connections from = localhost 10.* 192.168.* 172.16.* 172.17.* 172.18.* 172.19.* 172.20.* 172.21.* 172.22.* 172.23.* 172.24.* 172.25.* 172.26.* 172.27.* 172.28.* 172.29.* 172.30.* 172.31.*
+ allow dashboard from = localhost 10.* 192.168.* 172.16.* 172.17.* 172.18.* 172.19.* 172.20.* 172.21.* 172.22.* 172.23.* 172.24.* 172.25.* 172.26.* 172.27.* 172.28.* 172.29.* 172.30.* 172.31.*
+
+[plugins]
+ cgroups = no
+ apps = no
+ charts.d = no
+ fping = no
+ node.d = no
+ python.d = no
+
+[health]
+ enabled = no
+
+[plugin:proc:ipc]
+ shared memory totals = no
diff --git a/netdata/files/netdata.init b/netdata/files/netdata.init
new file mode 100644
index 00000000..06ef6e8b
--- /dev/null
+++ b/netdata/files/netdata.init
@@ -0,0 +1,29 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+USE_PROCD=1
+
+APPBINARY=/usr/sbin/netdata
+CONFIGFILE=/etc/netdata/netdata.conf
+
+start_service() {
+ local cloud_claim_token cloud_claim_rooms
+ config_get cloud_claim_token "config" "cloud_claim_token"
+ config_get cloud_claim_rooms "config" "cloud_claim_rooms"
+
+ mkdir -m 0755 -p /var/cache/netdata
+ chown nobody /var/cache/netdata
+ mkdir -m 0755 -p /var/lib/netdata
+ chown nobody /var/lib/netdata
+ mkdir -m 0755 -p /var/log/netdata
+ chown nobody /var/log/netdata
+
+ procd_open_instance
+ procd_set_param command $APPBINARY -D -c $CONFIGFILE
+ if [ -n "$cloud_claim_token" ] && [ -n "$cloud_claim_rooms" ]; then
+ procd_append_param command -W "claim -token=$cloud_claim_token -rooms=$cloud_claim_rooms"
+ fi
+ procd_set_param file $CONFIGFILE
+ procd_set_param respawn
+ procd_close_instance
+}
diff --git a/netdata/patches/001-disable-plugins-by-default.patch b/netdata/patches/001-disable-plugins-by-default.patch
new file mode 100644
index 00000000..a55670b6
--- /dev/null
+++ b/netdata/patches/001-disable-plugins-by-default.patch
@@ -0,0 +1,22 @@
+--- a/collectors/charts.d.plugin/charts.d.conf
++++ b/collectors/charts.d.plugin/charts.d.conf
+@@ -30,7 +30,7 @@
+
+ # the default enable/disable for all charts.d collectors
+ # the default is "yes"
+-# enable_all_charts="yes"
++enable_all_charts="no"
+
+ # BY DEFAULT ENABLED MODULES
+ # ap=yes
+--- a/collectors/python.d.plugin/python.d.conf
++++ b/collectors/python.d.plugin/python.d.conf
+@@ -7,7 +7,7 @@
+ #
+
+ # Enable / disable the whole python.d.plugin (all its modules)
+-enabled: yes
++enabled: no
+
+ # ----------------------------------------------------------------------
+ # Enable / Disable python.d.plugin modules
diff --git a/netdata/patches/002-patch-collectors_python.d.plugin_Makefile.am.patch b/netdata/patches/002-patch-collectors_python.d.plugin_Makefile.am.patch
new file mode 100644
index 00000000..29cc33e0
--- /dev/null
+++ b/netdata/patches/002-patch-collectors_python.d.plugin_Makefile.am.patch
@@ -0,0 +1,112 @@
+--- a/collectors/python.d.plugin/Makefile.am
++++ b/collectors/python.d.plugin/Makefile.am
+@@ -124,109 +124,3 @@ dist_third_party_DATA = \
+ python_modules/third_party/monotonic.py \
+ python_modules/third_party/filelock.py \
+ $(NULL)
+-
+-pythonyaml2dir=$(pythonmodulesdir)/pyyaml2
+-dist_pythonyaml2_DATA = \
+- python_modules/pyyaml2/__init__.py \
+- python_modules/pyyaml2/composer.py \
+- python_modules/pyyaml2/constructor.py \
+- python_modules/pyyaml2/cyaml.py \
+- python_modules/pyyaml2/dumper.py \
+- python_modules/pyyaml2/emitter.py \
+- python_modules/pyyaml2/error.py \
+- python_modules/pyyaml2/events.py \
+- python_modules/pyyaml2/loader.py \
+- python_modules/pyyaml2/nodes.py \
+- python_modules/pyyaml2/parser.py \
+- python_modules/pyyaml2/reader.py \
+- python_modules/pyyaml2/representer.py \
+- python_modules/pyyaml2/resolver.py \
+- python_modules/pyyaml2/scanner.py \
+- python_modules/pyyaml2/serializer.py \
+- python_modules/pyyaml2/tokens.py \
+- $(NULL)
+-
+-pythonyaml3dir=$(pythonmodulesdir)/pyyaml3
+-dist_pythonyaml3_DATA = \
+- python_modules/pyyaml3/__init__.py \
+- python_modules/pyyaml3/composer.py \
+- python_modules/pyyaml3/constructor.py \
+- python_modules/pyyaml3/cyaml.py \
+- python_modules/pyyaml3/dumper.py \
+- python_modules/pyyaml3/emitter.py \
+- python_modules/pyyaml3/error.py \
+- python_modules/pyyaml3/events.py \
+- python_modules/pyyaml3/loader.py \
+- python_modules/pyyaml3/nodes.py \
+- python_modules/pyyaml3/parser.py \
+- python_modules/pyyaml3/reader.py \
+- python_modules/pyyaml3/representer.py \
+- python_modules/pyyaml3/resolver.py \
+- python_modules/pyyaml3/scanner.py \
+- python_modules/pyyaml3/serializer.py \
+- python_modules/pyyaml3/tokens.py \
+- $(NULL)
+-
+-python_urllib3dir=$(pythonmodulesdir)/urllib3
+-dist_python_urllib3_DATA = \
+- python_modules/urllib3/__init__.py \
+- python_modules/urllib3/_collections.py \
+- python_modules/urllib3/connection.py \
+- python_modules/urllib3/connectionpool.py \
+- python_modules/urllib3/exceptions.py \
+- python_modules/urllib3/fields.py \
+- python_modules/urllib3/filepost.py \
+- python_modules/urllib3/response.py \
+- python_modules/urllib3/poolmanager.py \
+- python_modules/urllib3/request.py \
+- $(NULL)
+-
+-python_urllib3_utildir=$(python_urllib3dir)/util
+-dist_python_urllib3_util_DATA = \
+- python_modules/urllib3/util/__init__.py \
+- python_modules/urllib3/util/connection.py \
+- python_modules/urllib3/util/request.py \
+- python_modules/urllib3/util/response.py \
+- python_modules/urllib3/util/retry.py \
+- python_modules/urllib3/util/selectors.py \
+- python_modules/urllib3/util/ssl_.py \
+- python_modules/urllib3/util/timeout.py \
+- python_modules/urllib3/util/url.py \
+- python_modules/urllib3/util/wait.py \
+- $(NULL)
+-
+-python_urllib3_packagesdir=$(python_urllib3dir)/packages
+-dist_python_urllib3_packages_DATA = \
+- python_modules/urllib3/packages/__init__.py \
+- python_modules/urllib3/packages/ordered_dict.py \
+- python_modules/urllib3/packages/six.py \
+- $(NULL)
+-
+-python_urllib3_backportsdir=$(python_urllib3_packagesdir)/backports
+-dist_python_urllib3_backports_DATA = \
+- python_modules/urllib3/packages/backports/__init__.py \
+- python_modules/urllib3/packages/backports/makefile.py \
+- $(NULL)
+-
+-python_urllib3_ssl_match_hostnamedir=$(python_urllib3_packagesdir)/ssl_match_hostname
+-dist_python_urllib3_ssl_match_hostname_DATA = \
+- python_modules/urllib3/packages/ssl_match_hostname/__init__.py \
+- python_modules/urllib3/packages/ssl_match_hostname/_implementation.py \
+- $(NULL)
+-
+-python_urllib3_contribdir=$(python_urllib3dir)/contrib
+-dist_python_urllib3_contrib_DATA = \
+- python_modules/urllib3/contrib/__init__.py \
+- python_modules/urllib3/contrib/appengine.py \
+- python_modules/urllib3/contrib/ntlmpool.py \
+- python_modules/urllib3/contrib/pyopenssl.py \
+- python_modules/urllib3/contrib/securetransport.py \
+- python_modules/urllib3/contrib/socks.py \
+- $(NULL)
+-
+-python_urllib3_securetransportdir=$(python_urllib3_contribdir)/_securetransport
+-dist_python_urllib3_securetransport_DATA = \
+- python_modules/urllib3/contrib/_securetransport/__init__.py \
+- python_modules/urllib3/contrib/_securetransport/bindings.py \
+- python_modules/urllib3/contrib/_securetransport/low_level.py \
+- $(NULL)
diff --git a/netdata/patches/003-patch-collectors_python.d.plugin_python__modules_bases_loaders.py.patch b/netdata/patches/003-patch-collectors_python.d.plugin_python__modules_bases_loaders.py.patch
new file mode 100644
index 00000000..6a686df7
--- /dev/null
+++ b/netdata/patches/003-patch-collectors_python.d.plugin_python__modules_bases_loaders.py.patch
@@ -0,0 +1,14 @@
+--- a/collectors/python.d.plugin/python_modules/bases/loaders.py
++++ b/collectors/python.d.plugin/python_modules/bases/loaders.py
+@@ -10,9 +10,9 @@ PY_VERSION = version_info[:2]
+
+ try:
+ if PY_VERSION > (3, 1):
+- from pyyaml3 import SafeLoader as YamlSafeLoader
++ from yaml import SafeLoader as YamlSafeLoader
+ else:
+- from pyyaml2 import SafeLoader as YamlSafeLoader
++ from yaml import SafeLoader as YamlSafeLoader
+ except ImportError:
+ from yaml import SafeLoader as YamlSafeLoader
+
diff --git a/netdata/patches/004-fix-libjudy-compile.patch b/netdata/patches/004-fix-libjudy-compile.patch
new file mode 100644
index 00000000..4a4c6645
--- /dev/null
+++ b/netdata/patches/004-fix-libjudy-compile.patch
@@ -0,0 +1,387 @@
+--- a/.gitignore
++++ b/.gitignore
+@@ -227,7 +227,3 @@ Session.*.vim
+
+ # Jupyter notebook checkpoints
+ .ipynb_checkpoints
+-
+-# Judy stuff
+-JudyLTables.c
+-judyltablesgen
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -503,15 +503,10 @@ libjudy_a_SOURCES = libnetdata/libjudy/s
+ libnetdata/libjudy/src/JudyL/JudyLNextEmpty.c \
+ libnetdata/libjudy/src/JudyL/JudyLPrev.c \
+ libnetdata/libjudy/src/JudyL/JudyLPrevEmpty.c \
++ libnetdata/libjudy/src/JudyL/JudyLTables.c \
+ libnetdata/libjudy/src/JudyHS/JudyHS.c \
+ $(NULL)
+
+-nodist_libjudy_a_SOURCES = JudyLTables.c
+-
+-BUILT_SOURCES += JudyLTables.c
+-
+-CLEANFILES += JudyLTables.c
+-
+ libjudy_a_CFLAGS = $(LIBJUDY_CFLAGS) -DJUDYL -I$(abs_top_srcdir)/libnetdata/libjudy/src -I$(abs_top_srcdir)/libnetdata/libjudy/src/JudyCommon -Wno-sign-compare -Wno-implicit-fallthrough
+
+ libnetdata/libjudy/src/JudyL/libjudy_a-JudyLPrev.$(OBJEXT) : CFLAGS += -DJUDYPREV
+@@ -521,16 +516,6 @@ libnetdata/libjudy/src/JudyL/libjudy_a-J
+ libnetdata/libjudy/src/JudyL/libjudy_a-JudyLByCount.$(OBJEXT) : CFLAGS += -DNOSMARTJBB -DNOSMARTJBU -DNOSMARTJLB
+ libnetdata/libjudy/src/JudyL/libjudy_a-j__udyLGet.$(OBJEXT) : CFLAGS += -DJUDYGETINLINE
+
+-noinst_PROGRAMS = judyltablesgen
+-
+-judyltablesgen_SOURCES = libnetdata/libjudy/src/JudyL/JudyLTablesGen.c
+-judyltablesgen_CFLAGS = $(LIBJUDY_CFLAGS) -DJUDYL -I$(abs_top_srcdir)/libnetdata/libjudy/src -I$(abs_top_srcdir)/libnetdata/libjudy/src/JudyCommon -Wno-sign-compare -Wno-implicit-fallthrough
+-
+-$(builddir)/judyltablesgen$(EXEEXT) : CFLAGS += -Wno-format -Wno-format-security
+-
+-JudyLTables.c: $(abs_top_srcdir)/libnetdata/libjudy/src/JudyL/JudyLTablesGen.c $(builddir)/judyltablesgen$(EXEEXT)
+- $(builddir)/judyltablesgen$(EXEEXT)
+-
+ libjudy_a-JudyLTables.$(OBJEXT) : CFLAGS += -I$(abs_top_srcdir)/libnetdata/libjudy/src/JudyL
+
+ if ENABLE_DBENGINE
+--- /dev/null
++++ b/libnetdata/libjudy/src/JudyL/JudyLTables.c
+@@ -0,0 +1,338 @@
++// @(#) From generation tool: $Revision: 4.37 $ $Source: /judy/src/JudyCommon/JudyTables.c $
++// Pregenerated and modified by hand. Do not overwrite!
++
++#include "JudyL.h"
++// Leave the malloc() sizes readable in the binary (via strings(1)):
++#ifdef JU_64BIT
++const char * JudyLMallocSizes = "JudyLMallocSizes = 3, 5, 7, 11, 15, 23, 32, 47, 64, Leaf1 = 13";
++#else // JU_32BIT
++const char * JudyLMallocSizes = "JudyLMallocSizes = 3, 5, 7, 11, 15, 23, 32, 47, 64, Leaf1 = 25";
++#endif // JU_64BIT
++
++#ifdef JU_64BIT
++// object uses 64 words
++// cJU_BITSPERSUBEXPB = 32
++const uint8_t
++j__L_BranchBJPPopToWords[cJU_BITSPERSUBEXPB + 1] =
++{
++ 0,
++ 3, 5, 7, 11, 11, 15, 15, 23,
++ 23, 23, 23, 32, 32, 32, 32, 32,
++ 47, 47, 47, 47, 47, 47, 47, 64,
++ 64, 64, 64, 64, 64, 64, 64, 64
++};
++
++// object uses 15 words
++// cJL_LEAF1_MAXPOP1 = 13
++const uint8_t
++j__L_Leaf1PopToWords[cJL_LEAF1_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 3, 5, 5, 7, 7, 11, 11,
++ 11, 15, 15, 15, 15
++};
++const uint8_t
++j__L_Leaf1Offset[cJL_LEAF1_MAXPOP1 + 1] =
++{
++ 0,
++ 1, 1, 1, 1, 1, 1, 2, 2,
++ 2, 2, 2, 2, 2
++};
++
++// object uses 64 words
++// cJL_LEAF2_MAXPOP1 = 51
++const uint8_t
++j__L_Leaf2PopToWords[cJL_LEAF2_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 3, 5, 5, 7, 11, 11, 11,
++ 15, 15, 15, 15, 23, 23, 23, 23,
++ 23, 23, 32, 32, 32, 32, 32, 32,
++ 32, 47, 47, 47, 47, 47, 47, 47,
++ 47, 47, 47, 47, 47, 64, 64, 64,
++ 64, 64, 64, 64, 64, 64, 64, 64,
++ 64, 64, 64
++};
++const uint8_t
++j__L_Leaf2Offset[cJL_LEAF2_MAXPOP1 + 1] =
++{
++ 0,
++ 1, 1, 1, 1, 2, 3, 3, 3,
++ 3, 3, 3, 3, 5, 5, 5, 5,
++ 5, 5, 7, 7, 7, 7, 7, 7,
++ 7, 10, 10, 10, 10, 10, 10, 10,
++ 10, 10, 10, 10, 10, 13, 13, 13,
++ 13, 13, 13, 13, 13, 13, 13, 13,
++ 13, 13, 13
++};
++
++// object uses 64 words
++// cJL_LEAF3_MAXPOP1 = 46
++const uint8_t
++j__L_Leaf3PopToWords[cJL_LEAF3_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 3, 5, 7, 7, 11, 11, 11,
++ 15, 15, 23, 23, 23, 23, 23, 23,
++ 32, 32, 32, 32, 32, 32, 32, 47,
++ 47, 47, 47, 47, 47, 47, 47, 47,
++ 47, 47, 64, 64, 64, 64, 64, 64,
++ 64, 64, 64, 64, 64, 64
++};
++const uint8_t
++j__L_Leaf3Offset[cJL_LEAF3_MAXPOP1 + 1] =
++{
++ 0,
++ 1, 1, 2, 2, 2, 3, 3, 3,
++ 4, 4, 6, 6, 6, 6, 6, 6,
++ 9, 9, 9, 9, 9, 9, 9, 13,
++ 13, 13, 13, 13, 13, 13, 13, 13,
++ 13, 13, 18, 18, 18, 18, 18, 18,
++ 18, 18, 18, 18, 18, 18
++};
++
++// object uses 63 words
++// cJL_LEAF4_MAXPOP1 = 42
++const uint8_t
++j__L_Leaf4PopToWords[cJL_LEAF4_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 3, 5, 7, 11, 11, 11, 15,
++ 15, 15, 23, 23, 23, 23, 23, 32,
++ 32, 32, 32, 32, 32, 47, 47, 47,
++ 47, 47, 47, 47, 47, 47, 47, 63,
++ 63, 63, 63, 63, 63, 63, 63, 63,
++ 63, 63
++};
++const uint8_t
++j__L_Leaf4Offset[cJL_LEAF4_MAXPOP1 + 1] =
++{
++ 0,
++ 1, 1, 2, 2, 4, 4, 4, 5,
++ 5, 5, 8, 8, 8, 8, 8, 11,
++ 11, 11, 11, 11, 11, 16, 16, 16,
++ 16, 16, 16, 16, 16, 16, 16, 21,
++ 21, 21, 21, 21, 21, 21, 21, 21,
++ 21, 21
++};
++
++// object uses 64 words
++// cJL_LEAF5_MAXPOP1 = 39
++const uint8_t
++j__L_Leaf5PopToWords[cJL_LEAF5_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 5, 5, 7, 11, 11, 15, 15,
++ 15, 23, 23, 23, 23, 23, 32, 32,
++ 32, 32, 32, 47, 47, 47, 47, 47,
++ 47, 47, 47, 47, 64, 64, 64, 64,
++ 64, 64, 64, 64, 64, 64, 64
++};
++const uint8_t
++j__L_Leaf5Offset[cJL_LEAF5_MAXPOP1 + 1] =
++{
++ 0,
++ 2, 2, 2, 3, 4, 4, 6, 6,
++ 6, 9, 9, 9, 9, 9, 12, 12,
++ 12, 12, 12, 18, 18, 18, 18, 18,
++ 18, 18, 18, 18, 25, 25, 25, 25,
++ 25, 25, 25, 25, 25, 25, 25
++};
++
++// object uses 63 words
++// cJL_LEAF6_MAXPOP1 = 36
++const uint8_t
++j__L_Leaf6PopToWords[cJL_LEAF6_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 5, 7, 7, 11, 11, 15, 15,
++ 23, 23, 23, 23, 23, 32, 32, 32,
++ 32, 32, 47, 47, 47, 47, 47, 47,
++ 47, 47, 63, 63, 63, 63, 63, 63,
++ 63, 63, 63, 63
++};
++const uint8_t
++j__L_Leaf6Offset[cJL_LEAF6_MAXPOP1 + 1] =
++{
++ 0,
++ 1, 3, 3, 3, 5, 5, 6, 6,
++ 10, 10, 10, 10, 10, 14, 14, 14,
++ 14, 14, 20, 20, 20, 20, 20, 20,
++ 20, 20, 27, 27, 27, 27, 27, 27,
++ 27, 27, 27, 27
++};
++
++// object uses 64 words
++// cJL_LEAF7_MAXPOP1 = 34
++const uint8_t
++j__L_Leaf7PopToWords[cJL_LEAF7_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 5, 7, 11, 11, 15, 15, 15,
++ 23, 23, 23, 23, 32, 32, 32, 32,
++ 32, 47, 47, 47, 47, 47, 47, 47,
++ 47, 64, 64, 64, 64, 64, 64, 64,
++ 64, 64
++};
++const uint8_t
++j__L_Leaf7Offset[cJL_LEAF7_MAXPOP1 + 1] =
++{
++ 0,
++ 1, 3, 3, 5, 5, 7, 7, 7,
++ 11, 11, 11, 11, 15, 15, 15, 15,
++ 15, 22, 22, 22, 22, 22, 22, 22,
++ 22, 30, 30, 30, 30, 30, 30, 30,
++ 30, 30
++};
++
++// object uses 63 words
++// cJL_LEAFW_MAXPOP1 = 31
++const uint8_t
++j__L_LeafWPopToWords[cJL_LEAFW_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 5, 7, 11, 11, 15, 15, 23,
++ 23, 23, 23, 32, 32, 32, 32, 47,
++ 47, 47, 47, 47, 47, 47, 47, 63,
++ 63, 63, 63, 63, 63, 63, 63
++};
++const uint8_t
++j__L_LeafWOffset[cJL_LEAFW_MAXPOP1 + 1] =
++{
++ 0,
++ 2, 3, 4, 6, 6, 8, 8, 12,
++ 12, 12, 12, 16, 16, 16, 16, 24,
++ 24, 24, 24, 24, 24, 24, 24, 32,
++ 32, 32, 32, 32, 32, 32, 32
++};
++
++// object uses 64 words
++// cJU_BITSPERSUBEXPL = 64
++const uint8_t
++j__L_LeafVPopToWords[cJU_BITSPERSUBEXPL + 1] =
++{
++ 0,
++ 3, 3, 3, 5, 5, 7, 7, 11,
++ 11, 11, 11, 15, 15, 15, 15, 23,
++ 23, 23, 23, 23, 23, 23, 23, 32,
++ 32, 32, 32, 32, 32, 32, 32, 32,
++ 47, 47, 47, 47, 47, 47, 47, 47,
++ 47, 47, 47, 47, 47, 47, 47, 64,
++ 64, 64, 64, 64, 64, 64, 64, 64,
++ 64, 64, 64, 64, 64, 64, 64, 64
++};
++#else // JU_32BIT
++// object uses 64 words
++// cJU_BITSPERSUBEXPB = 32
++const uint8_t
++j__L_BranchBJPPopToWords[cJU_BITSPERSUBEXPB + 1] =
++{
++ 0,
++ 3, 5, 7, 11, 11, 15, 15, 23,
++ 23, 23, 23, 32, 32, 32, 32, 32,
++ 47, 47, 47, 47, 47, 47, 47, 64,
++ 64, 64, 64, 64, 64, 64, 64, 64
++};
++
++// object uses 32 words
++// cJL_LEAF1_MAXPOP1 = 25
++const uint8_t
++j__L_Leaf1PopToWords[cJL_LEAF1_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 3, 5, 5, 7, 11, 11, 11,
++ 15, 15, 15, 15, 23, 23, 23, 23,
++ 23, 23, 32, 32, 32, 32, 32, 32,
++ 32
++};
++const uint8_t
++j__L_Leaf1Offset[cJL_LEAF1_MAXPOP1 + 1] =
++{
++ 0,
++ 1, 1, 1, 1, 2, 3, 3, 3,
++ 3, 3, 3, 3, 5, 5, 5, 5,
++ 5, 5, 7, 7, 7, 7, 7, 7,
++ 7
++};
++
++// object uses 63 words
++// cJL_LEAF2_MAXPOP1 = 42
++const uint8_t
++j__L_Leaf2PopToWords[cJL_LEAF2_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 3, 5, 7, 11, 11, 11, 15,
++ 15, 15, 23, 23, 23, 23, 23, 32,
++ 32, 32, 32, 32, 32, 47, 47, 47,
++ 47, 47, 47, 47, 47, 47, 47, 63,
++ 63, 63, 63, 63, 63, 63, 63, 63,
++ 63, 63
++};
++const uint8_t
++j__L_Leaf2Offset[cJL_LEAF2_MAXPOP1 + 1] =
++{
++ 0,
++ 1, 1, 2, 2, 4, 4, 4, 5,
++ 5, 5, 8, 8, 8, 8, 8, 11,
++ 11, 11, 11, 11, 11, 16, 16, 16,
++ 16, 16, 16, 16, 16, 16, 16, 21,
++ 21, 21, 21, 21, 21, 21, 21, 21,
++ 21, 21
++};
++
++// object uses 63 words
++// cJL_LEAF3_MAXPOP1 = 36
++const uint8_t
++j__L_Leaf3PopToWords[cJL_LEAF3_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 5, 7, 7, 11, 11, 15, 15,
++ 23, 23, 23, 23, 23, 32, 32, 32,
++ 32, 32, 47, 47, 47, 47, 47, 47,
++ 47, 47, 63, 63, 63, 63, 63, 63,
++ 63, 63, 63, 63
++};
++const uint8_t
++j__L_Leaf3Offset[cJL_LEAF3_MAXPOP1 + 1] =
++{
++ 0,
++ 1, 3, 3, 3, 5, 5, 6, 6,
++ 10, 10, 10, 10, 10, 14, 14, 14,
++ 14, 14, 20, 20, 20, 20, 20, 20,
++ 20, 20, 27, 27, 27, 27, 27, 27,
++ 27, 27, 27, 27
++};
++
++// object uses 63 words
++// cJL_LEAFW_MAXPOP1 = 31
++const uint8_t
++j__L_LeafWPopToWords[cJL_LEAFW_MAXPOP1 + 1] =
++{
++ 0,
++ 3, 5, 7, 11, 11, 15, 15, 23,
++ 23, 23, 23, 32, 32, 32, 32, 47,
++ 47, 47, 47, 47, 47, 47, 47, 63,
++ 63, 63, 63, 63, 63, 63, 63
++};
++const uint8_t
++j__L_LeafWOffset[cJL_LEAFW_MAXPOP1 + 1] =
++{
++ 0,
++ 2, 3, 4, 6, 6, 8, 8, 12,
++ 12, 12, 12, 16, 16, 16, 16, 24,
++ 24, 24, 24, 24, 24, 24, 24, 32,
++ 32, 32, 32, 32, 32, 32, 32
++};
++
++// object uses 32 words
++// cJU_BITSPERSUBEXPL = 32
++const uint8_t
++j__L_LeafVPopToWords[cJU_BITSPERSUBEXPL + 1] =
++{
++ 0,
++ 3, 3, 3, 5, 5, 7, 7, 11,
++ 11, 11, 11, 15, 15, 15, 15, 23,
++ 23, 23, 23, 23, 23, 23, 23, 32,
++ 32, 32, 32, 32, 32, 32, 32, 32
++};
++#endif // JU_64BIT
diff --git a/netdata/root/etc/config/netdata b/netdata/root/etc/config/netdata
new file mode 100644
index 00000000..ba7d544e
--- /dev/null
+++ b/netdata/root/etc/config/netdata
@@ -0,0 +1,3 @@
+config netdata 'config'
+ option cloud_claim_token ''
+ option cloud_claim_rooms ''
diff --git a/parted/Config.in b/parted/Config.in
new file mode 100644
index 00000000..2a90b635
--- /dev/null
+++ b/parted/Config.in
@@ -0,0 +1,14 @@
+menu "Configuration"
+ depends on PACKAGE_parted
+
+config PARTED_READLINE
+ bool "Use readline library"
+ depends on PACKAGE_parted
+ default y
+
+config PARTED_LVM2
+ bool "Support LVM"
+ depends on PACKAGE_parted
+ default n
+
+endmenu
diff --git a/parted/Makefile b/parted/Makefile
new file mode 100644
index 00000000..2e86a1ad
--- /dev/null
+++ b/parted/Makefile
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=parted
+PKG_VERSION:=3.6
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=http://ftp.gnu.org/gnu/parted/
+PKG_HASH:=3b43dbe33cca0f9a18601ebab56b7852b128ec1a3df3a9b30ccde5e73359e612
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:parted_project:parted
+PKG_MAINTAINER:=Oskari Rauta
+
+PKG_CONFIG_DEPENDS:= \
+ CONFIG_PARTED_LVM2 \
+ CONFIG_PARTED_READLINE
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libparted
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=GNU Parted library
+ DEPENDS:=+libblkid +libuuid +PARTED_LVM2:libdevmapper
+endef
+
+define Package/libparted/description
+ GNU Parted shared library
+endef
+
+define Package/parted
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=GNU Parted
+ SUBMENU:=Disc
+ DEPENDS:=+libparted +PARTED_READLINE:libreadline +PARTED_READLINE:libncurses
+endef
+
+define Package/parted/description
+ GNU Parted manipulates partition tables. This is useful for
+ creating space for new operating systems, reorganizing
+ disk usage, copying data on hard disks and disk imaging.
+endef
+
+define Package/parted/config
+ source "$(SOURCE)/Config.in"
+endef
+
+CONFIGURE_ARGS += \
+ $(if $(CONFIG_PARTED_READLINE),--with-readline,--without-readline) \
+ $(if $(CONFIG_PARTED_LVM2),--enable-device-mapper,--disable-device-mapper)
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/parted $(1)/usr/lib/ $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so** $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/parted/*.h $(1)/usr/include/parted/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/*.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/libparted/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so** $(1)/usr/lib/
+endef
+
+define Package/parted/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/parted $(1)/sbin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/partprobe $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,libparted))
+$(eval $(call BuildPackage,parted))
diff --git a/parted/test.sh b/parted/test.sh
new file mode 100644
index 00000000..eecb15f7
--- /dev/null
+++ b/parted/test.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+case "$1" in
+ "parted")
+ test $(/sbin/parted --version | grep '^Copyright' | wc -l) -gt 0
+ ;;
+esac
diff --git a/socat/Makefile b/socat/Makefile
new file mode 100644
index 00000000..4afaf7e7
--- /dev/null
+++ b/socat/Makefile
@@ -0,0 +1,96 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=socat
+PKG_VERSION:=1.8.0.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://www.dest-unreach.org/socat/download
+PKG_HASH:=e1de683dd22ee0e3a6c6bbff269abe18ab0c9d7eb650204f125155b9005faca7
+
+PKG_MAINTAINER:=Ted Hess
+PKG_LICENSE:=GPL-2.0-or-later OpenSSL
+PKG_LICENSE_FILES:=COPYING COPYING.OpenSSL
+PKG_CPE_ID:=cpe:/a:dest-unreach:socat
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/socat
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=+libpthread +librt +SOCAT_SSL:libopenssl
+ TITLE:=A multipurpose relay (SOcket CAT)
+ URL:=http://www.dest-unreach.org/socat/
+endef
+
+define Package/socat/description
+ SoCat (for SOcket CAT) establishes two bidirectional byte streams and
+ transfers data between them.
+ Data channels may be files, pipes, devices (terminal or modem, etc.), or
+ sockets (Unix, IPv4, IPv6, raw, UDP, TCP, SSL). It provides forking,
+ logging and tracing, different modes for interprocess communication and
+ many more options.
+endef
+
+define Package/socat/config
+config SOCAT_SSL
+ bool "SSL support"
+ depends on PACKAGE_socat
+ default n
+ help
+ Implements SSL support in socat (using libopenssl).
+endef
+
+define Package/socat/conffiles
+/etc/config/socat
+endef
+
+CONFIGURE_ARGS += \
+ --disable-libwrap \
+ --disable-readline \
+ --enable-termios
+
+## procan.c fails to compile when ccache is enabled
+MAKE_FLAGS += CC="$(TARGET_CC_NOCACHE)"
+
+ifneq ($(CONFIG_SOCAT_SSL),y)
+ CONFIGURE_ARGS+= --disable-openssl
+endif
+
+# PowerPC has different TERMIOS bits
+ifneq ($(findstring powerpc,$(CONFIG_ARCH)),)
+ CONFIGURE_VARS += \
+ sc_cv_sys_crdly_shift=12 \
+ sc_cv_sys_tabdly_shift=10 \
+ sc_cv_sys_csize_shift=8
+else
+ CONFIGURE_VARS += \
+ sc_cv_sys_crdly_shift=9 \
+ sc_cv_sys_tabdly_shift=11 \
+ sc_cv_sys_csize_shift=4
+endif
+
+CONFIGURE_VARS += \
+ sc_cv_termios_ispeed="no" \
+ ac_cv_header_bsd_libutil_h=no \
+ ac_cv_lib_bsd_openpty=no \
+ BUILD_DATE=$(SOURCE_DATE_EPOCH)
+
+define Package/socat/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/socat $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/socat.config $(1)/etc/config/socat
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/socat.init $(1)/etc/init.d/socat
+endef
+
+$(eval $(call BuildPackage,socat))
diff --git a/socat/files/socat.config b/socat/files/socat.config
new file mode 100644
index 00000000..196ab9c4
--- /dev/null
+++ b/socat/files/socat.config
@@ -0,0 +1,6 @@
+# forward port 8000 on IPv6 to IPv4 host port 80
+# change enable to '1' to use this example
+config socat 'http'
+ option enable '0'
+ option SocatOptions '-d -d TCP6-LISTEN:8000,fork TCP4:192.168.1.20:80'
+ option user 'nobody'
diff --git a/socat/files/socat.init b/socat/files/socat.init
new file mode 100644
index 00000000..03573a01
--- /dev/null
+++ b/socat/files/socat.init
@@ -0,0 +1,61 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008-2014 OpenWrt.org
+
+START=99
+STOP=99
+
+USE_PROCD=1
+PROG=/usr/bin/socat
+NAME=socat
+
+validate_section_socat()
+{
+ uci_load_validate socat socat "$1" "$2" \
+ 'enable:bool:1' \
+ 'SocatOptions:or(string, list(string))' \
+ 'user:string:root'
+}
+
+append_param_command()
+{
+ procd_append_param command "$1"
+}
+
+socat_instance()
+{
+ local is_list
+ local user
+
+ [ "$2" = 0 ] || {
+ echo "validation failed"
+ return 1
+ }
+
+ [ "$enable" = "0" ] && return 1
+
+ procd_open_instance
+ procd_set_param command "$PROG"
+ config_get is_list "$1" SocatOptions_LENGTH
+ if [ -z "$is_list" ]; then
+ procd_append_param command $SocatOptions
+ else
+ config_list_foreach "$1" SocatOptions append_param_command
+ fi
+ config_get user "$1" user
+ if [ -n "$user" ]; then
+ procd_set_param user $user
+ fi
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_close_instance
+}
+
+start_service () {
+ config_load "$NAME"
+ config_foreach validate_section_socat socat socat_instance
+}
+
+service_triggers() {
+ procd_add_reload_trigger "$NAME"
+ procd_add_validation validate_section_socat
+}
diff --git a/socat/patches/200-openssl-deprecated.patch b/socat/patches/200-openssl-deprecated.patch
new file mode 100644
index 00000000..a9582845
--- /dev/null
+++ b/socat/patches/200-openssl-deprecated.patch
@@ -0,0 +1,11 @@
+--- a/xio-openssl.c
++++ b/xio-openssl.c
+@@ -8,6 +8,8 @@
+ #if WITH_OPENSSL /* make this address configure dependend */
+ #include
+ #include
++#include
++#include
+
+ #include "xioopen.h"
+