mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-01 09:43:56 +08:00
🎨 Sync 2026-06-01 00:37:26
This commit is contained in:
1 parent
339355db74
commit
c9bef8341c
136 files changed
+16024
-844
No files matched your search
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"admin/services/upnp": {
|
||||
"title": "UPnP IGD & PCP",
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "upnp/upnp"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-app-upnp" ],
|
||||
"uci": { "upnpd": true }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"luci-app-upnp": {
|
||||
"description": "Grant access to UPnP IGD & PCP/NAT-PMP service configuration",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"luci.upnp": [ "get_status" ],
|
||||
"luci": [ "setInitAction" ]
|
||||
},
|
||||
"uci": [ "upnpd" ]
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"luci.upnp": [ "delete_rule" ]
|
||||
},
|
||||
"uci": [ "upnpd" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env ucode
|
||||
|
||||
// Copyright 2022 Jo-Philipp Wich <jo@mein.io>
|
||||
// Licensed to the public under the Apache License 2.0.
|
||||
|
||||
'use strict';
|
||||
|
||||
import { access, open, popen } from 'fs';
|
||||
import { connect } from 'ubus';
|
||||
import { cursor } from 'uci';
|
||||
|
||||
const uci = cursor();
|
||||
const leasefilepath = uci.get('upnpd', 'config', 'upnp_lease_file') || '/var/run/miniupnpd.leases';
|
||||
|
||||
const methods = {
|
||||
get_status: {
|
||||
call: function(req) {
|
||||
const ubus = connect();
|
||||
const rules = [];
|
||||
const leases = [];
|
||||
const leasefile = open(leasefilepath, 'r');
|
||||
if (leasefile) {
|
||||
for (let line = leasefile.read('line'); length(line); line = leasefile.read('line')) {
|
||||
const record = split(line, ':', 6);
|
||||
if (length(record) == 6) {
|
||||
let descr = trim(record[5]);
|
||||
let m = match(descr, /^PCP [A-Z]+ ([0-9a-f]{24})$/);
|
||||
if (m) descr = 'PCP (nonce ' + m[1] + ')';
|
||||
else if (match(descr, /^NAT-PMP \d+ \w+$/)) descr = 'NAT-PMP';
|
||||
else if (match(descr, /^IGD2 pinhole$/)) descr = 'UPnP IGDv2 IPv6';
|
||||
else if (!match(descr, /^UPnP IGD/)) descr = 'UPnP IGD / ' + descr;
|
||||
push(leases, {
|
||||
proto: uc(record[0]),
|
||||
extport: +record[1],
|
||||
intaddr: arrtoip(iptoarr(record[2])),
|
||||
intport: +record[3],
|
||||
expires: record[4] - timelocal(localtime()),
|
||||
descr: descr
|
||||
});
|
||||
}
|
||||
}
|
||||
leasefile.close();
|
||||
}
|
||||
|
||||
// Workaround daemon bug with iptables >= 1.8.8 by parsing MINIUPNPD-POSTROUTING
|
||||
// See https://github.com/miniupnp/miniupnp/issues/837
|
||||
//const ipt = popen('iptables --line-numbers -t nat -xnvL MINIUPNPD 2>/dev/null');
|
||||
const ipt = popen('iptables --line-numbers -t nat -xnvL MINIUPNPD-POSTROUTING 2>/dev/null');
|
||||
if (ipt) {
|
||||
for (let line = ipt.read('line'); length(line); line = ipt.read('line')) {
|
||||
//let m = match(line, /^([0-9]+) .+ ([ut].p) dpt:([0-9]+) to:(\S+):([0-9]+)/);
|
||||
let m = match(line, /^([0-9]+) .+ \* +([0-9.]+) .+ ([ut].p) spt:([0-9]+) .+ ports: ([0-9]+)/);
|
||||
if (m) {
|
||||
push(rules, {
|
||||
num: m[1],
|
||||
intaddr: arrtoip(iptoarr(m[2])),
|
||||
intport: +m[4],
|
||||
extport: +m[5],
|
||||
proto: uc(m[3])
|
||||
});
|
||||
}
|
||||
}
|
||||
ipt.close();
|
||||
}
|
||||
|
||||
const nft = popen('nft --handle list chain inet fw4 upnp_prerouting 2>/dev/null');
|
||||
if (nft) {
|
||||
for (let line = nft.read('line'), num = 1; length(line); line = nft.read('line')) {
|
||||
let m = match(line, /^\t\tiif ".+" @nh,72,8 (0x6|0x11) th dport ([0-9]+).* dnat ip to ([0-9.]+):([0-9]+)/);
|
||||
if (m) {
|
||||
push(rules, {
|
||||
num: `${num}`,
|
||||
intaddr: arrtoip(iptoarr(m[3])),
|
||||
intport: +m[4],
|
||||
extport: +m[2],
|
||||
proto: (m[1] == '0x6') ? 'TCP' : 'UDP'
|
||||
});
|
||||
num++;
|
||||
}
|
||||
}
|
||||
nft.close();
|
||||
}
|
||||
|
||||
return ubus.defer('luci-rpc', 'getHostHints', {}, function(rc, host_hints) {
|
||||
for (let rule in rules) {
|
||||
for (let lease in leases) {
|
||||
if (lease.proto == rule.proto &&
|
||||
lease.intaddr == rule.intaddr &&
|
||||
lease.intport == rule.intport &&
|
||||
lease.extport == rule.extport) {
|
||||
rule.expires = lease.expires;
|
||||
rule.descr = lease.descr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (let mac, hint in host_hints) {
|
||||
if (rule.intaddr in hint.ipaddrs) {
|
||||
rule.host_hint = hint.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
req.reply({ rules });
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
delete_rule: {
|
||||
args: { token: 'token' },
|
||||
call: function(req) {
|
||||
const idx = +req.args?.token;
|
||||
if (idx > 0) {
|
||||
if (access(leasefilepath)) {
|
||||
system(['sed', '-i', '-e', `${idx}d`, leasefilepath]);
|
||||
system(['/etc/init.d/miniupnpd', 'restart']);
|
||||
}
|
||||
return { result: 'OK' };
|
||||
}
|
||||
return { result: 'Bad request' };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return { 'luci.upnp': methods };
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"config": "upnpd",
|
||||
"init": "miniupnpd"
|
||||
}
|
||||
Reference in new issue
Block a user