├── .dockerignore ├── .gitignore ├── .gitlab-ci.yml ├── AddressPool.js ├── Adopt.js ├── BrowserDevice.js ├── BrowserEval.js ├── CaptureManager.js ├── ClientManager.js ├── Config.js ├── Database.js ├── DeviceInstance.js ├── DeviceInstanceManager.js ├── DeviceManager.js ├── DeviceState.js ├── Dockerfile ├── Maps.js ├── MonitorManager.js ├── NetworkScanner.js ├── OID.js ├── Pup.js ├── README.md ├── TopologyAnalyzer.js ├── TopologyManager.js ├── VLANManager.js ├── WiFiManager.js ├── assets └── overview.jpg ├── device ├── ap │ ├── engenius │ │ └── eap1250 │ │ │ ├── image.js │ │ │ ├── index.js │ │ │ ├── mib │ │ │ ├── ENGENIUS-PRIVATE-MIB.mib │ │ │ └── IEEE802dot11-MIB.mib │ │ │ ├── read │ │ │ ├── ip+clients.js │ │ │ ├── lag.js │ │ │ ├── mac+physical.js │ │ │ ├── name+version.js │ │ │ ├── radios.js │ │ │ ├── statistics.js │ │ │ └── wifi.js │ │ │ └── write │ │ │ ├── commit.js │ │ │ ├── keychain.js │ │ │ ├── name.js │ │ │ └── snmp.js │ └── tp-link │ │ ├── eap225-outdoor │ │ ├── image.js │ │ └── index.js │ │ ├── eap225 │ │ ├── image.js │ │ ├── index.js │ │ ├── mib │ │ │ └── EAP_Private-Mibs_1.0 │ │ │ │ ├── EAP │ │ │ │ ├── clientMib │ │ │ │ │ ├── client.mib │ │ │ │ │ └── clientTable.mib │ │ │ │ └── systemTools │ │ │ │ │ └── systemTools.mib │ │ │ │ └── TPLINK.mib │ │ ├── read │ │ │ ├── clients.js │ │ │ ├── hardware.js │ │ │ ├── ip.js │ │ │ ├── name.js │ │ │ ├── physical.js │ │ │ ├── radios.js │ │ │ ├── statistics.js │ │ │ └── wifi.js │ │ └── write │ │ │ ├── name.js │ │ │ └── snmp.js │ │ └── tl-wa855re │ │ ├── image.js │ │ ├── index.js │ │ ├── read │ │ ├── _helpers.js │ │ ├── clients.js │ │ ├── name+ip.js │ │ └── radios.js │ │ └── write │ │ └── name.js ├── router │ ├── netgate │ │ └── xg-7100-1u │ │ │ └── index.js │ └── pfsense │ │ ├── community │ │ ├── image.js │ │ └── index.js │ │ └── generic │ │ ├── image.js │ │ ├── index.js │ │ └── mib │ │ ├── BEGEMOT-IP-MIB.mib │ │ ├── BEGEMOT-MIB.mib │ │ ├── BEGEMOT-MIB2-MIB.mib │ │ ├── BEGEMOT-NETGRAPH.mib │ │ └── BEGEMOT-PF-MIB.mib └── switch │ ├── d-link │ └── dgs-1100-05 │ │ ├── image.js │ │ ├── index.js │ │ ├── read │ │ ├── clients.js │ │ ├── igmp.js │ │ ├── lag.js │ │ ├── mirror.js │ │ ├── name+ip.js │ │ ├── physical.js │ │ ├── snmp.js │ │ ├── statistics.js │ │ └── vlan.js │ │ └── write │ │ ├── commit.js │ │ ├── igmp.js │ │ ├── ip.js │ │ ├── keychain.js │ │ ├── lag.js │ │ ├── mirror.js │ │ ├── name.js │ │ ├── physical.js │ │ ├── snmp.js │ │ └── vlan.js │ ├── mikrotik │ ├── crs309-1g-8s+ │ │ ├── image.js │ │ └── index.js │ ├── css106-5g-1s │ │ ├── image.js │ │ ├── index.js │ │ └── read │ │ │ └── lag.js │ └── generic │ │ ├── image.js │ │ ├── index.js │ │ ├── mib │ │ ├── BRIDGE-MIB.mib │ │ ├── IF-MIB.mib │ │ ├── MIKROTIK-MIB.mib │ │ └── SNMPv2-MIB.mib │ │ ├── read │ │ ├── clients.js │ │ ├── mirror.js │ │ ├── name+ip.js │ │ ├── physical.js │ │ ├── snmp.js │ │ ├── statistics.js │ │ └── vlan.js │ │ └── write │ │ ├── igmp.js │ │ ├── ip.js │ │ ├── ivl.js │ │ ├── keychain.js │ │ ├── mirror.js │ │ ├── name.js │ │ ├── physical.js │ │ ├── snmp.js │ │ └── vlan.js │ ├── netgear │ ├── gs110emx │ │ ├── image.js │ │ ├── index.js │ │ ├── read │ │ │ ├── igmp.js │ │ │ ├── lag.js │ │ │ ├── limits.js │ │ │ ├── mirror.js │ │ │ ├── name+ip.js │ │ │ ├── physical.js │ │ │ ├── statistics.js │ │ │ └── vlan.js │ │ └── write │ │ │ ├── keychain.js │ │ │ ├── limits.js │ │ │ ├── name+ip.js │ │ │ ├── physical.js │ │ │ └── vlan.js │ └── gs305e │ │ ├── image.js │ │ ├── index.js │ │ ├── read │ │ ├── igmp.js │ │ ├── lag.js │ │ ├── mirror.js │ │ ├── name+ip.js │ │ ├── physical.js │ │ ├── statistics.js │ │ └── vlan.js │ │ └── write │ │ ├── igmp.js │ │ ├── ip.js │ │ ├── keychain.js │ │ ├── mirror.js │ │ ├── name.js │ │ ├── physical.js │ │ └── vlan.js │ ├── tp-link │ ├── generic1 │ │ ├── image.js │ │ ├── index.js │ │ └── login.js │ ├── generic2 │ │ ├── index.js │ │ └── login.js │ ├── t2500g-10ts │ │ ├── image.js │ │ └── index.js │ ├── t2600g-28ts │ │ ├── image.js │ │ ├── index.js │ │ ├── read │ │ │ ├── clients.js │ │ │ ├── igmp.js │ │ │ ├── ip.js │ │ │ ├── lag.js │ │ │ ├── mirror.js │ │ │ ├── name+physical.js │ │ │ ├── slow-statistics.js │ │ │ ├── snmp.js │ │ │ ├── statistics.js │ │ │ └── vlan.js │ │ └── write │ │ │ ├── commit.js │ │ │ ├── ip.js │ │ │ ├── keychain.js │ │ │ ├── mirror.js │ │ │ ├── name.js │ │ │ ├── physical.js │ │ │ └── snmp.js │ ├── tl-sg105e │ │ ├── image.js │ │ └── index.js │ ├── tl-sg105pe │ │ ├── image.js │ │ └── index.js │ ├── tl-sg108e │ │ ├── image.js │ │ ├── index.js │ │ ├── read │ │ │ ├── igmp.js │ │ │ ├── lag.js │ │ │ ├── limits.js │ │ │ ├── mirror.js │ │ │ ├── name+ip.js │ │ │ ├── physical.js │ │ │ ├── statistics.js │ │ │ └── vlan.js │ │ └── write │ │ │ ├── commit.js │ │ │ ├── igmp.js │ │ │ ├── ip.js │ │ │ ├── keychain.js │ │ │ ├── lag.js │ │ │ ├── limits.js │ │ │ ├── mirror.js │ │ │ ├── name.js │ │ │ ├── physical.js │ │ │ └── vlan.js │ └── tl-sg108pe │ │ ├── image.js │ │ └── index.js │ └── trendnet │ ├── teg-30284 │ ├── image.js │ ├── index.js │ ├── mib │ │ └── TEG-30284_MIB_V1.00.022.mib │ ├── read │ │ ├── clients.js │ │ ├── igmp.js │ │ ├── ip.js │ │ ├── lag.js │ │ ├── limits.js │ │ ├── mirror.js │ │ ├── name.js │ │ ├── physical.js │ │ ├── snmp.js │ │ ├── statistics.js │ │ └── vlan.js │ └── write │ │ ├── commit.js │ │ ├── dns.js │ │ ├── igmp.js │ │ ├── ip.js │ │ ├── ivl.js │ │ ├── keychain.js │ │ ├── lag.js │ │ ├── limits.js │ │ ├── mirror.js │ │ ├── name.js │ │ ├── physical.js │ │ ├── snmp.js │ │ └── vlan.js │ └── teg-s80es │ ├── image.js │ ├── index.js │ ├── mib │ ├── IF-MIB.mib │ └── rfc1213.mib │ ├── read │ ├── clients.js │ ├── hardware.js │ ├── igmp.js │ ├── ip.js │ ├── lag.js │ ├── mirror.js │ ├── name.js │ ├── physical.js │ ├── snmp.js │ ├── statistics.js │ └── vlan.js │ └── write │ ├── commit.js │ ├── igmp.js │ ├── ip.js │ ├── keychain.js │ ├── lag.js │ ├── mirror.js │ ├── name.js │ ├── physical.js │ ├── snmp.js │ └── vlan.js ├── discovery ├── arp.js ├── ddp.js ├── escp.js ├── index.js ├── mdns.js ├── mndp.js ├── net.js ├── nsdp.js └── omada.js ├── docker-compose.yml ├── docs └── supported-devices.txt ├── minkebox └── skeleton ├── monitors └── SpeedTest.js ├── package-lock.json ├── package.json ├── pages ├── CRButtons.html ├── Capture │ ├── Controls.html │ ├── Full │ │ ├── Arp.html │ │ ├── Dns.html │ │ ├── IPV4Unknown.html │ │ ├── Icmp.html │ │ ├── Igmp.html │ │ ├── Tcp.html │ │ ├── Udp.html │ │ └── mDns.html │ ├── Msg │ │ ├── Fail.html │ │ ├── Started.html │ │ ├── Starting.html │ │ ├── Stopped.html │ │ └── Stopping.html │ ├── Part │ │ ├── Data.html │ │ ├── Dns.html │ │ ├── DnsRR.html │ │ ├── Ethernet.html │ │ ├── Frame.html │ │ ├── IPV4.html │ │ ├── Icmp.html │ │ ├── Tcp.html │ │ └── Udp.html │ ├── Port.html │ ├── Proto │ │ ├── Arp.html │ │ ├── Dns.html │ │ ├── IPV4Unknown.html │ │ ├── Icmp.html │ │ ├── Igmp.html │ │ ├── Tcp.html │ │ ├── Udp.html │ │ └── mDns.html │ ├── Selected.html │ ├── Tab.html │ └── index.js ├── Clients │ ├── List.html │ ├── Selected.html │ ├── Summary.html │ ├── Tab.html │ └── index.js ├── Config │ ├── Adoption │ │ ├── Tab.html │ │ └── index.js │ ├── Checkbox.html │ ├── Input.html │ ├── Monitor │ │ ├── List.html │ │ ├── SpeedTestSelect.html │ │ ├── Tab.html │ │ └── index.js │ ├── Other │ │ ├── Tab.html │ │ └── index.js │ └── Tribox.html ├── Device │ ├── Address.html │ ├── AuthButton.html │ ├── AuthModal.html │ ├── Card.html │ ├── Details.html │ ├── IPDiscoveryModal.html │ ├── List.html │ ├── ListAll.html │ ├── PortInfo.html │ ├── PortLayout.html │ ├── PortMonitors.html │ ├── PortSettings.html │ ├── Radios.html │ ├── Scan.html │ ├── ScanStatus.html │ ├── Selected.html │ ├── Settings.html │ ├── Spinner.html │ ├── Tab.html │ └── index.js ├── Link │ ├── List.html │ ├── Selected.html │ ├── Summary.html │ ├── Tab.html │ ├── Topology.html │ ├── TopologyStatus.html │ └── index.js ├── Main.html ├── Main.js ├── Modal1.html ├── Modal2.html ├── Network │ ├── DeleteVLAN.html │ ├── List.html │ ├── Network.html │ ├── NewVLAN.html │ ├── Port.html │ ├── Selected.html │ ├── Summary.html │ ├── Tab.html │ ├── TopologyNotice.html │ └── index.js ├── Page.js ├── Pages.js ├── RO.html ├── RW.html ├── RWCheckbox.html ├── RWSelect.html ├── Template.js ├── Viz │ ├── Img │ │ ├── APs.html │ │ ├── Clients.html │ │ ├── Firewall.html │ │ ├── Internet.html │ │ └── Switches.html │ ├── Mon │ │ ├── Bubbles.html │ │ ├── Gauge.html │ │ └── Time.html │ ├── Overview.html │ ├── Tab.html │ └── index.js ├── WiFi │ ├── List.html │ ├── NewWiFi.html │ ├── Selected.html │ ├── Summary.html │ ├── Tab.html │ └── index.js ├── main.css └── script.js ├── server.js └── utils ├── Barrier.js ├── Debounce.js ├── HelperApps.js └── TypeConversion.js /.dockerignore: -------------------------------------------------------------------------------- 1 | docs/** 2 | db/** 3 | node_modules/** 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | db 4 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | include: 2 | - project: 'ericvh/gitlab-ci-arm-template' 3 | file: '/.gitlab-ci.yml' 4 | 5 | variables: 6 | CI_COMMIT_TAG: "dev" 7 | CI_BUILDX_ARCHS: "linux/arm64,linux/amd64" 8 | -------------------------------------------------------------------------------- /AddressPool.js: -------------------------------------------------------------------------------- 1 | const DeviceInstanceManager = require('./DeviceInstanceManager'); 2 | const ClientManager = require('./ClientManager'); 3 | 4 | class AddressPool { 5 | 6 | constructor(start, end) { 7 | const sp = start.split('.'); 8 | const ep = end.split('.'); 9 | this.base = sp.slice(0, 3).join('.'); 10 | if (this.base != ep.slice(0, 3).join('.')) { 11 | throw new Error(`Bad base: ${this.base}`); 12 | } 13 | this.start = parseInt(sp[3]); 14 | this.end = parseInt(ep[3]); 15 | } 16 | 17 | allocateAddress() { 18 | for (let a = this.start; a < this.end; a++) { 19 | const address = `${this.base}.${a}`; 20 | // Check if we have a device with this IP 21 | if (DeviceInstanceManager.getDeviceByIP(address)) { 22 | continue; 23 | } 24 | // Check if we have a client with this IP 25 | if (ClientManager.getClientByIP(address)) { 26 | continue; 27 | } 28 | return address; 29 | } 30 | return null; 31 | } 32 | 33 | } 34 | 35 | module.exports = { 36 | 37 | pools: {}, 38 | 39 | getInstance: function(start, end) { 40 | let pool = this.pools[`${start}:${end}`]; 41 | if (!pool) { 42 | pool = new AddressPool(start, end); 43 | this.pools[`${start}:${end}`] = pool; 44 | } 45 | return pool; 46 | } 47 | 48 | }; 49 | 50 | -------------------------------------------------------------------------------- /DeviceManager.js: -------------------------------------------------------------------------------- 1 | const FS = require('fs'); 2 | const BrowserDevice = require('./BrowserDevice'); 3 | const DeviceState = require('./DeviceState'); 4 | 5 | class DeviceManager { 6 | 7 | constructor() { 8 | this.devices = []; 9 | this._loadAllDevices(); 10 | } 11 | 12 | _loadAllDevices() { 13 | // Put some helpers in global scope 14 | global.OID = require('./OID'); 15 | global.Maps = require('./Maps'); 16 | 17 | this._loadDevices(`${__dirname}/device`); 18 | } 19 | 20 | _loadDevices(dir) { 21 | FS.readdirSync(dir, { encoding: 'utf8', withFileTypes: true }).forEach(entry => { 22 | if (entry.isDirectory()) { 23 | this._loadDevices(`${dir}/${entry.name}`); 24 | } 25 | else if (entry.name === 'index.js') { 26 | const description = require(dir); 27 | switch (description.type || 'browser') { 28 | case 'browser': 29 | this.devices.push(new BrowserDevice(description)); 30 | break; 31 | default: 32 | break; 33 | } 34 | } 35 | }); 36 | } 37 | 38 | getDevices() { 39 | return this.devices; 40 | } 41 | 42 | fromDB(dbDevice, dbState) { 43 | const device = this.devices.find(device => device.description.id === dbDevice.dmId); 44 | if (!device) { 45 | return null; 46 | } 47 | const devinst = device.newInstance(dbDevice, DeviceState.fromDB(dbState)); 48 | devinst._authenticated = true; 49 | return devinst; 50 | } 51 | } 52 | 53 | module.exports = new DeviceManager(); 54 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.12 2 | 3 | ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true 4 | 5 | COPY . /app 6 | 7 | RUN apk add nodejs npm git chromium libpcap-dev build-base python3;\ 8 | mv /app/minkebox /; \ 9 | cd /app ; npm install --production ;\ 10 | apk del git npm build-base python3 11 | 12 | EXPOSE 8080/tcp 13 | VOLUME /app/db 14 | 15 | #HEALTHCHECK --interval=60s --timeout=5s --start-period=5s --retries=3 CMD ifconfig eth0 || exit 1 16 | 17 | CMD [ "/bin/sh", "-c", "(cd /app ; node server.js)" ] 18 | -------------------------------------------------------------------------------- /Maps.js: -------------------------------------------------------------------------------- 1 | // Helper and common maps 2 | 3 | const TypeConversion = require('./utils/TypeConversion'); 4 | 5 | module.exports = { 6 | 7 | Null: v => v, 8 | 9 | toMacAddress: mac => mac.replace(/-/g,':').toLowerCase(), 10 | 11 | toHex: v => `0x${v.toString(16)}`, 12 | 13 | toHex2: v => { 14 | const r = `${v.toString(16)}`; 15 | return '0x' + `0${r}`.substr(-2*Math.ceil(r.length / 2)); 16 | }, 17 | 18 | intToIPAddress: ip32 => { 19 | let ip = ip32 % 256; 20 | for (let i = 3; i > 0; i--) { 21 | ip32 = Math.floor(ip32 / 256); 22 | ip = `${ip}.${ip32 % 256}`; 23 | } 24 | return ip; 25 | }, 26 | 27 | toNatural: TypeConversion.toNatural 28 | 29 | }; 30 | -------------------------------------------------------------------------------- /assets/overview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minkebox/minkenet/12330d37d97bb4df5785d5f052835d9852dd2638/assets/overview.jpg -------------------------------------------------------------------------------- /device/ap/engenius/eap1250/read/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | types: { 5 | static: 0, 6 | active: 0 7 | } 8 | } 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /device/ap/engenius/eap1250/read/mac+physical.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | $1: { 3 | $: 'fetch', 4 | arg: { 5 | $: 'eval', 6 | arg: `window.location.pathname.replace(/(tok=.*admin).*/,'$1')+'/network/iface_status2/lan'` 7 | }, 8 | type: 'jsonp', 9 | values: { 10 | system: { 11 | macAddress: { 12 | 0: { 13 | $: 'jsonp', 14 | arg: '$[0].macaddr', 15 | map: Maps.toMacAddress 16 | } 17 | } 18 | }, 19 | network: { 20 | physical: { 21 | port: { 22 | '0': { 23 | id: '$[0].id', 24 | status: { 25 | $: 'jsonp', 26 | arg: '$[0].is_up', 27 | map: { 28 | true: 'up', 29 | false: 'down' 30 | } 31 | }, 32 | framesize: { 33 | $: 'literal', 34 | arg: '1500' 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /device/ap/engenius/eap1250/read/name+version.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'navigate', 4 | arg: { 5 | $: 'eval', 6 | arg: `window.location.pathname.replace(/(tok=.*admin).*/,'$1')+'/status/overview'` 7 | }, 8 | values: { 9 | name: '[myid=Device_Name_text]', 10 | firmware: { 11 | version: '[myid=fw_ver_text]' 12 | }, 13 | hardware: { 14 | version: { 15 | $: 'selector', 16 | arg: '#dev_info .title-option:nth-child(12) td:last-child', 17 | map: Maps.Null 18 | } 19 | } 20 | } 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /device/ap/engenius/eap1250/read/statistics.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | 0: { 6 | statistics: { 7 | $: 'oid', 8 | arg: '1.3.6.1.2.1.2.2.1', 9 | values: { 10 | $: 'fn', 11 | arg: ctx => { 12 | const base = ctx.context[1][3][6][1][2][1][2][2][1]; 13 | const names = OID.getKeyValues('', base[2]); 14 | const idx = Object.keys(names)[Object.values(names).findIndex(v => v === 'eth1')]; 15 | if (idx) { 16 | return { 17 | rx: { 18 | bytes: base[10][idx], 19 | unicast: base[11][idx], 20 | multicast: base[12][idx], 21 | discareded: base[13][idx], 22 | errors: base[14][idx], 23 | unknownprotos: base[15][idx] 24 | }, 25 | tx: { 26 | bytes: base[16][idx], 27 | unicast: base[17][idx], 28 | multicast: base[18][idx], 29 | discareded: base[19][idx], 30 | errors: base[20][idx], 31 | } 32 | }; 33 | } 34 | return null; 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /device/ap/engenius/eap1250/read/wifi.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | wireless: { 4 | station: { 5 | $: 'iterate', 6 | limit: 8, 7 | arg: itr => [{ 8 | $: 'navigate', 9 | arg: { 10 | $: 'eval', 11 | arg: `window.location.pathname.replace(/(tok=.*admin).*/,'$1')+'/network/wifi_Encryption_Combined?wifi0_select_opmode=ap&wifi1_select_opmode=ap&displayMode=ap&checkbox2G=0&checkbox5G=0&netId=wifi0.network${itr.index + 1}'` 12 | }, 13 | values: { 14 | hidden: `#cbid\\.wireless\\.wifi0_ssid_${itr.index + 1}\\.hidden1`, 15 | isolate: { 16 | enable: `#cbid\\.wireless\\.wifi0_ssid_${itr.index + 1}\\.isolate1` 17 | }, 18 | steering: { 19 | enable: `#cbid\\.wireless\\.wifi0_ssid_${itr.index + 1}\\.bandsteer_en1`, 20 | preference: { 21 | $: 'selector', 22 | arg: `#select\\.bandsteer`, 23 | map: { 24 | 1: 'force', 25 | 2: 'prefer', 26 | 3: 'balance' 27 | } 28 | }, 29 | minrssi: `[name="cbid\\.wireless\\.wifi0_ssid_${itr.index + 1}\\.bandsteerrssi"]` 30 | }, 31 | security: { 32 | passphrase: `#cbid\\.wireless\\.wifi0_ssid_${itr.index + 1}\\.key` 33 | }, 34 | fastroaming: { 35 | enable: `#cbid\\.wireless\\.wifi0_ssid_${itr.index + 1}\\.fastroamingEnable1` 36 | } 37 | } 38 | }] 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /device/ap/engenius/eap1250/write/commit.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | $: 'navigate', 3 | arg: { 4 | $: 'eval', 5 | arg: `window.location.pathname.replace(/(tok=.*admin).*/,'$1')+'/uci/changes'` 6 | }, 7 | values: { 8 | $: 'click+nav', 9 | arg: 'input[myid=button_apply]' 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /device/ap/engenius/eap1250/write/keychain.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | keychain: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: { 8 | $: 'eval', 9 | arg: `window.location.pathname.replace(/(tok=.*admin).*/,'$1')+'/system/admin'` 10 | }, 11 | method: 'post', 12 | params: { 13 | usr_name: 'admin', 14 | cur_pw: { $: 'kv', arg: 'system.keychain.password', options: { original: true } }, 15 | pw1: { $: 'kv', arg: 'system.keychain.password' }, 16 | pw2: { $: 'kv', arg: 'system.keychain.password' }, 17 | submitType: 1, 18 | 'cbi.apply': 'Apply' 19 | } 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /device/ap/engenius/eap1250/write/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | name: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: { 8 | $: 'eval', 9 | arg: `window.location.pathname.replace(/(tok=.*admin).*/,'$1')+'/network/wireless_device'` 10 | }, 11 | method: 'post', 12 | params: { 13 | 'cbid.system.system.SystemName': { $: 'kv' } 14 | } 15 | } 16 | } 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /device/ap/engenius/eap1250/write/snmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | snmp: { 4 | enable: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: { 9 | $: 'eval', 10 | arg: `window.location.pathname.replace(/(tok=.*admin).*/,'$1')+'/network/advanced'` 11 | }, 12 | method: 'post', 13 | params: { 14 | 'SnmpEnable': { $: 'kv', map: { true: 1, false: 0 } } 15 | } 16 | } 17 | } 18 | } 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/mib/EAP_Private-Mibs_1.0/EAP/clientMib/client.mib: -------------------------------------------------------------------------------- 1 | EAP-CLIENT-MIB DEFINITIONS ::= BEGIN 2 | 3 | IMPORTS 4 | MODULE-IDENTITY 5 | FROM SNMPv2-SMI 6 | eap 7 | FROM TPLINK; 8 | 9 | clientStatis MODULE-IDENTITY 10 | LAST-UPDATED "201610170000z" 11 | ORGANIZATION "TPLINK" 12 | CONTACT-INFO "www.tplink.com" 13 | DESCRIPTION 14 | "Private MIB for clients statistics." 15 | REVISION "201610170000z" 16 | DESCRIPTION 17 | "Initial version of this MIB module." 18 | ::= { eap 1 } 19 | 20 | clientCount OBJECT-TYPE 21 | SYNTAX INTEGER (1..1000) 22 | MAX-ACCESS read-only 23 | STATUS current 24 | DESCRIPTION 25 | "this used to get the count of clients" 26 | ::= { clientStatis 1 } 27 | clientTable OBJECT IDENTIFIER ::= { clientStatis 2 } 28 | END 29 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/mib/EAP_Private-Mibs_1.0/EAP/clientMib/clientTable.mib: -------------------------------------------------------------------------------- 1 | EAP-CLIENTTABLE-MIB DEFINITIONS ::= BEGIN 2 | 3 | IMPORTS 4 | MODULE-IDENTITY,OBJECT-TYPE 5 | FROM SNMPv2-SMI 6 | clientStatis 7 | FROM EAP-CLIENT-MIB; 8 | 9 | clientTable OBJECT-TYPE 10 | SYNTAX SEQUENCE OF ClientEntry 11 | MAX-ACCESS not-accessible 12 | STATUS current 13 | DESCRIPTION 14 | "This object indicates the wireless clients status associated with this EAP device." 15 | ::= { clientStatis 2 } 16 | clientEntry OBJECT-TYPE 17 | SYNTAX ClientEntry 18 | MAX-ACCESS not-accessible 19 | STATUS current 20 | DESCRIPTION 21 | "Clients Entry" 22 | INDEX{clientIndex} 23 | ::= { clientTable 1 } 24 | ClientEntry ::= 25 | SEQUENCE 26 | { 27 | clientIndex INTEGER, 28 | macAddress OCTET STRING 29 | } 30 | clientIndex OBJECT-TYPE 31 | SYNTAX INTEGER 32 | MAX-ACCESS read-only 33 | STATUS current 34 | DESCRIPTION 35 | "This object indicates the index of the client." 36 | ::= { clientEntry 1 } 37 | macAddress OBJECT-TYPE 38 | SYNTAX OCTET STRING 39 | MAX-ACCESS read-only 40 | STATUS current 41 | DESCRIPTION 42 | "This object indicates the MAC Address of wireless clients." 43 | ::= { clientEntry 2 } 44 | END 45 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/mib/EAP_Private-Mibs_1.0/EAP/systemTools/systemTools.mib: -------------------------------------------------------------------------------- 1 | EAP-SYSTEMTOOLS-MIB DEFINITIONS ::= BEGIN 2 | 3 | IMPORTS 4 | OBJECT-TYPE 5 | FROM SNMPv2-SMI 6 | systemTools 7 | FROM TPLINK; 8 | 9 | systemToolReboot OBJECT-TYPE 10 | SYNTAX INTEGER{ 11 | notReboot(0), --normal state 12 | reboot(1) 13 | } 14 | MAX-ACCESS read-write 15 | STATUS current 16 | DESCRIPTION 17 | "this used to determine whether to reboot or not" 18 | ::= { systemTools 1 } 19 | END 20 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/mib/EAP_Private-Mibs_1.0/TPLINK.mib: -------------------------------------------------------------------------------- 1 | TPLINK DEFINITIONS ::= BEGIN 2 | 3 | --iso OBJECT IDENTIFIER ::= { 1 } 4 | --org OBJECT IDENTIFIER ::= { iso 3 } 5 | --dod OBJECT IDENTIFIER ::= { org 6 } 6 | --internet OBJECT IDENTIFIER ::= { dod 1 } 7 | --private OBJECT IDENTIFIER ::= { internet 4 } 8 | --enterprises OBJECT IDENTIFIER ::= { private 1 } 9 | 10 | IMPORTS 11 | enterprises FROM RFC1155-SMI; 12 | 13 | tplink OBJECT IDENTIFIER ::= { enterprises 11863 } 14 | ap OBJECT IDENTIFIER ::= { tplink 10 } 15 | 16 | eap OBJECT IDENTIFIER ::= { ap 1 } 17 | --clientStatis OBJECT IDENTIFIER ::= { eap 1 } 18 | systemTools OBJECT IDENTIFIER ::= { eap 2} 19 | 20 | END 21 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/read/clients.js: -------------------------------------------------------------------------------- 1 | const Maps = require("../../../../../Maps"); 2 | 3 | module.exports = { 4 | network: { 5 | clients: { 6 | $: 'fetch', 7 | arg: '/data/status.client.user.json?operation=load', 8 | values: { 9 | $: 'iterate', 10 | arg: itr => [{ 11 | mac: { $: null, arg: `data.${itr.index}.MAC`, map: Maps.toMacAddress }, 12 | ssid: `data.${itr.index}.SSID`, 13 | ip: `data.${itr.index}.IP`, 14 | hostname: `data.${itr.index}.hostname` 15 | }] 16 | } 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/read/hardware.js: -------------------------------------------------------------------------------- 1 | const Maps = require("../../../../../Maps"); 2 | 3 | module.exports = { 4 | system: { 5 | $: 'fetch', 6 | arg: '/data/status.device.json?operation=read', 7 | type: 'jsonp', 8 | values: { 9 | firmware: { 10 | version: 'data.firmwareVersion' 11 | }, 12 | hardware: { 13 | version: { $: 'jsonp', arg: 'data.hardwareVersion', map: Maps.Null } 14 | } 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/read/ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | ipv4$1: { 4 | $: 'oid', 5 | arg: '1.3.6.1.2.1.4.20.1', 6 | values: { 7 | $: 'fn', 8 | arg: ctx => { 9 | const base = ctx.context[1][3][6][1][2][1][4][20][1]; 10 | const addrs = OID.getValues(base[1]); 11 | const masks = OID.getValues(base[3]); 12 | for (let i = 0; i < addrs.length; i++) { 13 | if (addrs[i] !== '127.0.0.1') { 14 | return { 15 | address: addrs[i], 16 | netmask: masks[i] 17 | }; 18 | } 19 | } 20 | return {}; 21 | } 22 | } 23 | }, 24 | ipv4$2: { 25 | gateway: { $: 'oid', arg: '1.3.6.1.2.1.4.21.1.7.0.0.0.0' } 26 | }, 27 | ipv4$3: { 28 | $: 'fetch', 29 | arg: '/data/lan.json', 30 | type: 'jsonp', 31 | values: { 32 | mode: { 33 | $: null, 34 | arg: 'data.connType', 35 | map: { 36 | dynamic: 'dhcp', 37 | static: 'static' 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/read/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | name: { $: 'oid', arg: OID.system.name }, 4 | location: { $: 'oid', arg: OID.system.location }, 5 | contact: { $: 'oid', arg: OID.system.contact } 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/read/physical.js: -------------------------------------------------------------------------------- 1 | const BASE = '1.3.6.1.2.1.2.2'; 2 | 3 | module.exports = { 4 | $: 'oid', 5 | arg: BASE, 6 | values: { 7 | network: { 8 | physical: { 9 | port: { 10 | 0: { 11 | id: { $: null, arg: `${BASE}.1.2.2` }, 12 | status: { $: null, arg: `${BASE}.1.8.2`, map: { 1: 'up', 2: 'down' } }, 13 | framesize: { $: null, arg: `${BASE}.1.4.2` }, 14 | type: { $: null, arg: `${BASE}.1.5.2`, map: { 0: '-', 10000000: '100M', 1000000000: '1G', } } 15 | } 16 | } 17 | } 18 | }, 19 | system: { 20 | macAddress: { 21 | 0: { $: null, arg: `${BASE}.1.6.2`, map: OID.toMacAddress } 22 | } 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/read/statistics.js: -------------------------------------------------------------------------------- 1 | const OID = require("../../../../../OID"); 2 | 3 | module.exports = { 4 | $: 'oid', 5 | arg: OID.network.physical.$, 6 | values: { 7 | network: { 8 | physical: { 9 | port: { 10 | '0': { 11 | statistics: { 12 | rx: { 13 | bytes: `${OID.network.physical.statistics.rx.bytes}.2`, 14 | unicast: `${OID.network.physical.statistics.rx.unicast}.2`, 15 | multicast: `${OID.network.physical.statistics.rx.multicast}.2`, 16 | discarded: `${OID.network.physical.statistics.rx.discarded}.2`, 17 | errors: `${OID.network.physical.statistics.rx.errors}.2`, 18 | unknownprotos: `${OID.network.physical.statistics.rx.unknownprotos}.2` 19 | }, 20 | tx: { 21 | bytes: `${OID.network.physical.statistics.tx.bytes}.2`, 22 | unicast: `${OID.network.physical.statistics.tx.unicast}.2`, 23 | multicast: `${OID.network.physical.statistics.tx.multicast}.2`, 24 | discarded: `${OID.network.physical.statistics.tx.discarded}.2`, 25 | errors: `${OID.network.physical.statistics.tx.errors}.2` 26 | } 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/write/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'guard', 4 | key: 'system.name,system.location,system.contact', 5 | arg: { 6 | name: { $: 'oid+set', arg: OID.system.name }, 7 | location: { $: 'oid+set', arg: OID.system.location }, 8 | contact: { $: 'oid+set', arg: OID.system.contact }, 9 | } 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /device/ap/tp-link/eap225/write/snmp.js: -------------------------------------------------------------------------------- 1 | // 2 | // Note. Used to enable SNMP, so we can't use OIDs here. 3 | // 4 | module.exports = { 5 | system: { 6 | snmp: { 7 | enable: { 8 | $: 'guard', 9 | arg: { 10 | $: 'fetch', 11 | arg: '/data/snmp.json', 12 | method: 'post', 13 | params: { 14 | operation: 'write', 15 | snmpEnable: { $: 'kv', arg: 'system.snmp.enable' } 16 | } 17 | } 18 | } 19 | } 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /device/ap/tp-link/tl-wa855re/read/_helpers.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | convert(val) { 4 | const a = {}; 5 | val.split('\n').forEach(line => { 6 | const p = line.replace('\r', '').split(' '); 7 | let k = null; 8 | let v = null; 9 | if (p.length === 2) { 10 | k = p[0]; 11 | v = p[1]; 12 | } 13 | else if (p.length === 3) { 14 | k = `${p[0]}_${p[1]}`; 15 | v = p[2]; 16 | } 17 | if (k) { 18 | while (k in a) { 19 | k = `${k}_`; 20 | } 21 | a[k] = v; 22 | } 23 | }); 24 | return a; 25 | } 26 | 27 | }; 28 | -------------------------------------------------------------------------------- /device/ap/tp-link/tl-wa855re/read/name+ip.js: -------------------------------------------------------------------------------- 1 | const Helpers = require('./_helpers'); 2 | 3 | module.exports = { 4 | system: { 5 | $: 'fetch', 6 | arg: { 7 | $: 'fn', 8 | arg: async ctx => '/?code=2&asyn=0&id=' + encodeURIComponent(await ctx.eval('eval', 'jQuery.su.url.session')) 9 | }, 10 | method: 'post', 11 | params: '4|1,0,0#1|1,0,0#8|1,0,0', 12 | transform: Helpers.convert, 13 | type: 'jsonp', 14 | values: { 15 | name: 'hostName', 16 | macAddress: { 17 | 0: { 18 | $: 'jsonp', 19 | arg: 'mac_0', 20 | map: Maps.toMacAddress 21 | } 22 | }, 23 | ipv4: { 24 | mode: { 25 | $: 'jsonp', 26 | arg: 'mode', 27 | map: { 28 | 1: 'static', 29 | 0: 'dhcp' 30 | } 31 | }, 32 | address: 'ip', 33 | netmask: 'mask', 34 | gateway: 'gateway', 35 | dns: 'dns_0' 36 | } 37 | } 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /device/ap/tp-link/tl-wa855re/write/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'guard', 4 | key: 'system.name', 5 | arg: { 6 | $: 'fetch', 7 | arg: { 8 | $: 'fn', 9 | arg: async ctx => '/?code=1&asyn=0&id=' + encodeURIComponent(await ctx.eval('eval', 'jQuery.su.url.session')) 10 | }, 11 | method: 'post', 12 | params: { 13 | $: 'fn', 14 | arg: ctx => `id 8|1,0,0\nhostName ${ctx.readKV('system.name')}` 15 | } 16 | } 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /device/router/netgate/xg-7100-1u/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minkebox/minkenet/12330d37d97bb4df5785d5f052835d9852dd2638/device/router/netgate/xg-7100-1u/index.js -------------------------------------------------------------------------------- /device/router/pfsense/community/index.js: -------------------------------------------------------------------------------- 1 | const Device = { 2 | 3 | name: 'pfSense Community', 4 | id: 'pfsense/community', 5 | image: require('./image'), 6 | 7 | properties: { 8 | switch: false, 9 | router: true, 10 | firewall: true, 11 | ap: false 12 | }, 13 | 14 | identify: { 15 | http: { 16 | ipv4: 'dhcp', 17 | loggedIn: { 18 | $: 'eval', 19 | arg: `document.querySelector("a.navbar-brand span").innerText == 'COMMUNITY EDITION'` 20 | } 21 | } 22 | }, 23 | 24 | login: { 25 | path: '/', 26 | username: { 27 | select: '#usernamefld' 28 | }, 29 | password: { 30 | select: '#passwordfld' 31 | }, 32 | activate: { 33 | $: 'click', 34 | select: `input[name=login]` 35 | } 36 | } 37 | }; 38 | 39 | module.exports = Device; 40 | -------------------------------------------------------------------------------- /device/router/pfsense/generic/index.js: -------------------------------------------------------------------------------- 1 | const Device = { 2 | 3 | name: 'pfSense', 4 | id: 'pfsense/unknown', 5 | image: require('./image'), 6 | generic: true, 7 | 8 | properties: { 9 | router: true, 10 | firewall: true 11 | }, 12 | 13 | identify: { 14 | http: { 15 | ipv4: [ 'dhcp' ], 16 | loggedOut: { 17 | $: 'eval', 18 | arg: `!!document.querySelector("a[href='https://pfsense.org']")` 19 | } 20 | } 21 | }, 22 | 23 | login: { 24 | path: '/', 25 | username: '#usernamefld', 26 | password: '#passwordfld', 27 | activate: `input[name=login]`, 28 | valid: '' 29 | }, 30 | 31 | constants: { 32 | system: { 33 | hardware: { 34 | model: 'Generic pfSense' 35 | }, 36 | keychain: { 37 | username: 'admin', 38 | password: 'pfsense' 39 | }, 40 | ipv4: { 41 | address: '', 42 | port: 80 43 | } 44 | } 45 | } 46 | }; 47 | 48 | module.exports = Device; 49 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/read/clients.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | clients: { 4 | $: 'fetch', 5 | frame: 'mf0', 6 | arg: { 7 | $: 'eval', 8 | arg: `top.RT + 'DS/DFT.js'` 9 | }, 10 | type: 'eval', 11 | values: { 12 | $: 'iterate', 13 | arg: itr => [{ 14 | mac: { $: 'eval', arg: `ds_DFT[${itr.index}][1]`, map: Maps.toMacAddress }, 15 | vlan: `ds_DFT[${itr.index}][2]`, 16 | portnr: `ds_DFT[${itr.index}][0] - 1` 17 | }] 18 | } 19 | } 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/read/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | snoop: { 5 | $: 'fetch', 6 | frame: 'mf0', 7 | arg: { 8 | $: 'eval', 9 | arg: `top.RT + 'DS/IGMP.js'` 10 | }, 11 | type: 'eval', 12 | values: '!!ds_IGMPSEn' 13 | } 14 | } 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/read/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | types: { 5 | static: 1, 6 | active: 0 7 | }, 8 | port: { 9 | $: 'fetch', 10 | frame: 'mf0', 11 | arg: { 12 | $: 'eval', 13 | arg: `top.RT + 'DS/trunking.js'` 14 | }, 15 | type: 'eval', 16 | values: { 17 | $: 'eval', 18 | arg: 'ds_TrunkList[0]', 19 | map: ports => { 20 | const r = {}; 21 | for (let i = 0; i < ports.length; i++) { 22 | if (ports[i] == '1') { 23 | r[i] = { type: 'static', group: 1 }; 24 | } 25 | else { 26 | r[i] = { type: 'none' }; 27 | } 28 | } 29 | return r; 30 | } 31 | } 32 | } 33 | } 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/read/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'fetch', 6 | frame: 'mf0', 7 | arg: { 8 | $: 'eval', 9 | arg: `top.RT + 'DS/Mirror.js'` 10 | }, 11 | type: 'eval', 12 | values: { 13 | enable: `!!ds_MirrorEn`, 14 | target: `ds_MirrTag - 1`, 15 | port: { 16 | $: 'fn', 17 | arg: async ctx => { 18 | const en = await ctx.eval({ $: 'eval', arg: 'ds_MirrorEn' }); 19 | const src = await ctx.eval({ $: 'eval', arg: 'ds_MirrSrc '}); 20 | const ports = {}; 21 | const port = {}; 22 | if (en === 1 || en === 3) { 23 | port.ingress = true; 24 | } 25 | if (en === 2 || en === 3) { 26 | port.egress = true; 27 | } 28 | for (let i = 0; i < src.length; i++) { 29 | if (src[i] === '1') { 30 | ports[i] = port; 31 | } 32 | } 33 | return ports; 34 | } 35 | } 36 | } 37 | } 38 | } 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/read/name+ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'fetch', 4 | frame: 'mf0', 5 | arg: { 6 | $: 'eval', 7 | arg: `top.RT + 'DS/Switch.js'` 8 | }, 9 | type: 'eval', 10 | values: { 11 | name: 'ds_SysInfo[0]', 12 | location: `ds_SysInfo[1]`, 13 | contact: `ds_SysInfo[2]`, 14 | macAddress: { 15 | 0: { 16 | $: 'eval', 17 | arg: 'g_DeviceInfo[2]', 18 | map: Maps.toMacAddress 19 | } 20 | }, 21 | firmware: { 22 | version: 'g_SwitchInfo[1]' 23 | }, 24 | hardware: { 25 | version: 'g_DeviceInfo[0]' 26 | }, 27 | ipv4: { 28 | mode: { 29 | $: 'eval', 30 | arg: 'ds_IPInfo[0]', 31 | map: { 32 | 0: 'static', 33 | 1: 'dhcp' 34 | } 35 | }, 36 | address: 'ds_IPInfo[1]', 37 | netmask: 'ds_IPInfo[2]', 38 | gateway: 'ds_IPInfo[3]' 39 | } 40 | }, 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/read/snmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | snmp: { 4 | $: 'fetch', 5 | frame: 'mf0', 6 | arg: { 7 | $: 'eval', 8 | arg: `top.RT + 'DS/SNMP_Global.js'` 9 | }, 10 | type: 'eval', 11 | values: { 12 | enable: '!!ds_Snmp[0]' 13 | } 14 | } 15 | } 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/read/statistics.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'fetch', 6 | frame: 'mf0', 7 | arg: { 8 | $: 'eval', 9 | arg: `top.RT + 'DS/Statistics.js'` 10 | }, 11 | type: 'eval', 12 | values: { 13 | $: 'iterate', 14 | arg: itr => [{ 15 | statistics: { 16 | rx: { 17 | packets: `ds_Statistics[${itr.index}][1]`, 18 | errors: `ds_Statistics[${itr.index}][3]` 19 | }, 20 | tx: { 21 | packets: `ds_Statistics[${itr.index}][0]`, 22 | errors: `ds_Statistics[${itr.index}][2]` 23 | } 24 | } 25 | }] 26 | } 27 | } 28 | } 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/read/vlan.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | vlans: { 4 | $: 'fetch', 5 | frame: 'mf0', 6 | arg: { 7 | $: 'eval', 8 | arg: `top.RT + 'DS/QVLAN.js'` 9 | }, 10 | type: 'eval', 11 | values: { 12 | '8021q': '!!ds_QVEnable', 13 | ivl: '!ds_AsyVlanEn', 14 | vlan: { 15 | $: 'iterate', 16 | arg: itr => [ 17 | `ds_QVLANList[${itr.index}][0]`, 18 | { 19 | name: `ds_QVLANList[${itr.index}][1]`, 20 | management: `ds_QVLANList[${itr.index}][1] == ds_MgtVID`, 21 | port: { 22 | $: 'eval', 23 | arg: `ds_QVLANList[${itr.index}][2]`, 24 | map: ports => { 25 | const r = {}; 26 | for (let p = 0; p < ports.length; p++) { 27 | switch (ports[p]) { 28 | case 'U': 29 | r[p] = { tagged: false }; 30 | break; 31 | case 'T': 32 | r[p] = { tagged: true }; 33 | break; 34 | case '0': 35 | default: 36 | break; 37 | } 38 | } 39 | return r; 40 | } 41 | } 42 | } 43 | ] 44 | }, 45 | pvid: { 46 | $: 'iterate', 47 | arg: itr => [{ 48 | pvid: `ds_PVID[${itr.index}]` 49 | }] 50 | } 51 | } 52 | } 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/write/commit.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | $: 'fetch', 3 | arg: '/cgi/save.cgi', 4 | method: 'post' 5 | }; 6 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/write/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | snoop: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/cgi/IGMPSNState.cgi', 9 | method: 'post', 10 | params: { 11 | IGS: { 12 | $: 'kv', 13 | map: { 14 | true: 1, 15 | false: 0 16 | } 17 | } 18 | } 19 | } 20 | } 21 | } 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/write/ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | ipv4: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/cgi/set_ip.cgi', 8 | method: 'post', 9 | params: { 10 | ip: { $: 'kv', arg: 'system.ipv4.address' }, 11 | submask: { $: 'kv', arg: 'system.ipv4.netmask' }, 12 | gateway: { $: 'kv', arg: 'system.ipv4.gateway' }, 13 | dhcp: { 14 | $: 'kv', 15 | arg: 'system.ipv4.mode', 16 | map: { 17 | static: '0', 18 | dhcp: '1' 19 | } 20 | }, 21 | dhcptm: '7' 22 | } 23 | } 24 | } 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/write/keychain.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | keychain: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/cgi/changing_pw.cgi', 8 | method: 'post', 9 | params: { 10 | old_pass: { $: 'kv', arg: 'system.keychain.password', options: { original: true } }, 11 | new_pass: { $: 'kv', arg: 'system.keychain.password' }, 12 | renew_pass: { $: 'kv', arg: 'system.keychain.password' } 13 | } 14 | } 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/write/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fn', 7 | arg: async ctx => { 8 | const ports = ctx.readKV(`${ctx.path}.port`); 9 | const group = [ 0, 0, 0, 0, 0 ]; 10 | for (let p in ports) { 11 | if (ports[p].type === 'static') { 12 | group[p] = 1; 13 | } 14 | } 15 | await ctx.eval({ 16 | $: 'fetch', 17 | arg: '/cgi/TrunkingStatus.cgi', 18 | method: 'post', 19 | params: { 20 | enabled_flag: 1 21 | } 22 | }); 23 | const members = groups.join(''); 24 | if (members === '00000') { 25 | await ctx.eval({ 26 | $: 'fetch', 27 | arg: '/cgi/TrunkingDelMems.cgi', 28 | method: 'post', 29 | params: { 30 | Group: 1, 31 | GroupMember: '' 32 | } 33 | }); 34 | } 35 | else { 36 | await ctx.eval({ 37 | $: 'fetch', 38 | arg: '/cgi/TrunkingSetting.cgi', 39 | method: 'post', 40 | params: { 41 | Group: 1, 42 | GroupMember: members 43 | } 44 | }); 45 | } 46 | } 47 | } 48 | } 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/write/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/cgi/PortMirroring.cgi', 9 | method: 'post', 10 | params: { 11 | $: 'fn', 12 | arg: async ctx => { 13 | const mirror = ctx.readKV(ctx.path); 14 | if (!mirror.enable) { 15 | return { 16 | cEn: 0, 17 | sMode: 0, 18 | sTagP: 1, 19 | SrcList: '' 20 | } 21 | } 22 | const ports = '00000000'; 23 | let mode = 0; 24 | for (let p in mirror.port) { 25 | if (mirror.port[p].ingress) { 26 | ports[p] = 1; 27 | mode |= 1; 28 | } 29 | if (mirror.port[p].egress) { 30 | ports[p] = 1; 31 | mode |= 2; 32 | } 33 | } 34 | return { 35 | cEn: 1, 36 | sMode: mode ? mode - 1 : 0, 37 | sTagP: mirror.target + 1, 38 | SrcList: ports 39 | }; 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/write/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'guard', 4 | arg: { 5 | $: 'fetch', 6 | arg: '/cgi/set_sys.cgi', 7 | method: 'post', 8 | params: { 9 | sys: { $: 'kv', arg: 'system.name' }, 10 | loc: { $: 'kv', arg: 'system.locatiom' }, 11 | con: { $: 'kv', arg: 'system.contact' }, 12 | SysTimeout: '36000' 13 | } 14 | } 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/write/physical.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'foreach', 6 | arg: itr => [{ 7 | $: 'guard', 8 | arg: { 9 | $: 'fetch', 10 | arg: '/cgi/set_port.cgi', 11 | method: 'post', 12 | params: { 13 | port_f: itr.index + 1, 14 | port_t: itr.index + 1, 15 | stats: { $: 'kv', arg: `${itr.path}.enable`, map: { true: 1, false: 0 } }, 16 | speed: { 17 | $: 'kv', 18 | arg: `${itr.path}.speed`, 19 | map: { 20 | 'auto': 0, 21 | '10M (H)': 1, 22 | '10M': 2, 23 | '100M (H)': 3, 24 | '100M': 4, 25 | '1G': 5 26 | } 27 | }, 28 | flow: { $: 'kv', arg: `${itr.path}.flowcontrol`, map: { true: 1, false: 0 } }, 29 | desc: { $: 'kv', arg: `${itr.path}.name` } 30 | } 31 | } 32 | }] 33 | } 34 | } 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /device/switch/d-link/dgs-1100-05/write/snmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | snmp: { 4 | enable: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/cgi/snmp_global.cgi', 9 | method: 'post', 10 | params: { 11 | item: '00000', 12 | Trap: 0, 13 | Snmp: { 14 | $: 'kv', 15 | map: { 16 | true: 1, 17 | false: 0 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /device/switch/mikrotik/css106-5g-1s/read/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | types: { 5 | static: 0, 6 | active: 0 7 | } 8 | } 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/index.js: -------------------------------------------------------------------------------- 1 | const Device = { 2 | 3 | name: 'MikroTik SwOS', 4 | id: 'mikrotik/unknown', 5 | image: require('./image'), 6 | generic: true, 7 | 8 | layout: { 9 | ports: [ 10 | [ 0 ] 11 | ] 12 | }, 13 | 14 | properties: { 15 | switch: true 16 | }, 17 | 18 | identify: { 19 | http: { 20 | ipv4: [ 'dhcp', '192.168.88.1' ], 21 | loggedOut: { 22 | $: 'eval', 23 | arg: 'document.title === "MikroTik SwOS"' 24 | } 25 | } 26 | }, 27 | 28 | basicAuth: { 29 | path: '/index.html' 30 | }, 31 | 32 | constants: { 33 | system: { 34 | hardware: { 35 | manufacturer: 'Mikrotik', 36 | model: 'Generic SwOS' 37 | }, 38 | keychain: { 39 | username: 'admin', 40 | password: '' 41 | }, 42 | ipv4: { 43 | address: '', 44 | port: 80 45 | } 46 | } 47 | } 48 | }; 49 | 50 | module.exports = Device; 51 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/read/clients.js: -------------------------------------------------------------------------------- 1 | function mac(m) { 2 | return m.replace(/(..)(?!$)/g,'$1:'); 3 | } 4 | 5 | module.exports = { 6 | network: { 7 | clients: { 8 | $: 'fetch', 9 | arg: '/!dhost.b', 10 | transform: v => `$R=${v}`, 11 | type: 'eval', 12 | values: { 13 | $: 'iterate', 14 | arg: itr => [{ 15 | mac: { $: 'eval', arg: `$R[${itr.index}].adr`, map: mac }, 16 | portnr: `$R[${itr.index}].prt`, 17 | vlan: `$R[${itr.index}].vid` 18 | }] 19 | } 20 | } 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/read/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'fetch', 6 | arg: '/fwd.b', 7 | transform: v => `$R=${v}`, 8 | type: 'eval', 9 | values: { 10 | enable: { $: 'literal', arg: true }, 11 | target: '$R.mrto - 1', 12 | port: { 13 | $: 'fn', 14 | arg: async ctx => { 15 | const ports = {}; 16 | const nrports = ctx.readKV('network.physical.ports.nr.total'); 17 | const im = await ctx.eval({ $: 'eval', arg: '$R.imr '}); 18 | const om = await ctx.eval({ $: 'eval', arg: '$R.omr '}); 19 | for (let j = 0; j < nrports; j++) { 20 | const val = {}; 21 | if (!!(im & (1 << j))) { 22 | val.ingress = true; 23 | } 24 | if (!!(om & (1 << j))) { 25 | val.egress = true; 26 | } 27 | for (const k in val) { 28 | ports[j] = val; 29 | break; 30 | } 31 | } 32 | return ports; 33 | } 34 | } 35 | } 36 | } 37 | } 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/read/name+ip.js: -------------------------------------------------------------------------------- 1 | function str(v) { 2 | return Buffer.from(v, 'hex').toString('utf8'); 3 | } 4 | 5 | function mac(m) { 6 | return m.replace(/(..)(?!$)/g,'$1:'); 7 | } 8 | 9 | module.exports = { 10 | $1: { 11 | $: 'fetch', 12 | arg: '/sys.b', 13 | transform: v => `$R=${v}`, 14 | type: 'eval', 15 | values: { 16 | system: { 17 | name: { $: 'eval', arg: '$R.id', map: str }, 18 | macAddress: { 19 | 0: { $: 'eval', arg: '$R.mac', map: mac } 20 | }, 21 | firmware: { 22 | version: { $: 'eval', arg: '$R.ver', map: str } 23 | }, 24 | ipv4: { 25 | mode: { $: 'eval', arg: '$R.iptp', map: { 0: 'dhcp', 1: 'static', 2: 'dhcp' } }, 26 | address: { $: 'eval', arg: `'cip' in $R ? $R.cip : $R.ip`, map: Maps.intToIPAddress } 27 | } 28 | }, 29 | network: { 30 | vlans: { 31 | ivl: { $: 'eval', arg: '$R.ivl', map: { 0: false, 1: true } }, 32 | vlan: { 33 | $: 'fn', 34 | arg: async ctx => { 35 | const vid = await ctx.eval({ $: 'eval', arg: '$R.avln' }); 36 | if (vid) { 37 | return { [vid]: { management: true } }; 38 | } 39 | else { 40 | return {}; 41 | } 42 | } 43 | } 44 | }, 45 | igmp: { 46 | snoop: { $: 'eval', arg: '$R.igmp', map: { 0: false, 1: true } } 47 | } 48 | } 49 | } 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/read/physical.js: -------------------------------------------------------------------------------- 1 | function str(v) { 2 | return Buffer.from(v, 'hex').toString('utf8'); 3 | } 4 | 5 | module.exports = { 6 | network: { 7 | physical: { 8 | port: { 9 | $: 'fetch', 10 | arg: '/link.b', 11 | transform: v => `$R=${v}`, 12 | type: 'eval', 13 | values: { 14 | $: 'iterate', 15 | arg: itr => [{ 16 | id: `${itr.index + 1}`, 17 | name: { $: 'eval', arg: `$R.nm[${itr.index}]`, map: str }, 18 | status: { $: 'eval', arg: `!!($R.lnk & (1 << ${itr.index}))`, map: { true: 'up', false: 'down' } }, 19 | type: { $: 'eval', arg: `$R.spd[${itr.index}]`, map: { 2: '1G', 3: '10G', 7: '-' } }, 20 | framesize: { 21 | $: 'fn', 22 | arg: ctx => { 23 | switch (ctx.readKV('system.hardware.model')) { 24 | case 'CSS106-5G-1S': 25 | return 9198; 26 | case 'CRS309-1G-8S+': 27 | return 10218; 28 | default: 29 | return 1518; 30 | } 31 | } 32 | }, 33 | flowcontrol: `!!($R.fct & (1 << ${itr.index}))`, 34 | speed: { 35 | $: 'eval', 36 | arg: `($R.an & (1 << ${itr.index})) ? 'A' : $R.spdc[${itr.index}]`, 37 | map: { 38 | A: 'auto', 39 | 0: '10M', 40 | 1: '100M', 41 | 2: '1G' 42 | } 43 | }, 44 | enable: `!!($R.en & (1 << ${itr.index}))` 45 | }] 46 | } 47 | } 48 | } 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/read/snmp.js: -------------------------------------------------------------------------------- 1 | function str(v) { 2 | return Buffer.from(v, 'hex').toString('utf8'); 3 | } 4 | 5 | module.exports = { 6 | system: { 7 | $: 'fetch', 8 | arg: '/snmp.b', 9 | transform: v => `$R=${v}`, 10 | type: 'eval', 11 | values: { 12 | snmp: { 13 | enable: `!!$R.en` 14 | }, 15 | location: { $: 'eval', arg: '$R.loc', map: str }, 16 | contact: { $: 'eval', arg: '$R.ci', map: str } 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/write/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | snoop: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/sys.b', 9 | method: 'post', 10 | wait: 0.1, 11 | params: { 12 | $: 'kv', 13 | arg: 'network.igmp.snoop', 14 | map: v => `{igmp:'${v ? '0x01' : '0x00'}'}` 15 | } 16 | } 17 | } 18 | } 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/write/ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | ipv4: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/sys.b', 8 | method: 'post', 9 | wait: 0.1, 10 | params: { 11 | $: 'fn', 12 | arg: async function() { 13 | const mode = this.readKV('system.ipv4.mode') === 'static' ? 1 : 0; 14 | const ip = this.readKV('system.ipv4.address').split('.').reduce((ipInt, octet) => (ipInt << 8) + parseInt(octet), 0) >>> 0; 15 | return `{iptp:0x0${mode},sip:0x${ip}}`; 16 | } 17 | } 18 | } 19 | } 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/write/ivl.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | vlans: { 4 | ivl: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/sys.b', 9 | method: 'post', 10 | wait: 0.1, 11 | params: { 12 | $: 'kv', 13 | arg: 'network.vlans.ivl', 14 | map: v => `{ivl:'${v ? '0x01' : '0x00'}'}` 15 | } 16 | } 17 | } 18 | } 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/write/keychain.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | keychain: { 4 | $: 'guard', 5 | arg: { 6 | $1: { 7 | $: 'navigate', 8 | arg: '/index.html#system' 9 | }, 10 | $2: { 11 | oldPassword: { 12 | $: 'type', 13 | arg: '#content table:nth-child(2) tr:nth-child(1) input', 14 | value: { $: 'kv', arg: 'system.keychain.password', options: { original: true } } 15 | }, 16 | newPassword: { 17 | $: 'type', 18 | arg: '#content table:nth-child(2) tr:nth-child(1) input', 19 | value: { $: 'kv', arg: 'system.keychain.password' } 20 | }, 21 | rePassword: { 22 | $: 'type', 23 | arg: '#content table:nth-child(2) tr:nth-child(1) input', 24 | value: { $: 'kv', arg: 'system.keychain.password' } 25 | } 26 | }, 27 | $3: { 28 | $: 'click', 29 | arg: '#content table:nth-child(2) .btn' 30 | } 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/write/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/fwd.b', 9 | method: 'post', 10 | wait: 0.1, 11 | params: { 12 | $: 'fn', 13 | arg: ctx => { 14 | const mrto = 1 << ctx.readKV(`${ctx.path}.target`); 15 | let imr = 0; 16 | let omr = 0; 17 | if (ctx.readKV(`${ctx.path}.enable`)) { 18 | const ports = ctx.readKV(`${ctx.path}.port`); 19 | for (let p in ports) { 20 | if (ports[p].ingress) { 21 | imr |= 1 << p; 22 | } 23 | if (ports[p].egress) { 24 | omr |= 1 << p; 25 | } 26 | } 27 | } 28 | return `{mrto:${Maps.toHex2(mrto)},imr:${Maps.toHex2(imr)},omr:${Maps.toHex2(omr)}}` 29 | } 30 | } 31 | } 32 | } 33 | } 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/write/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | name: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/sys.b', 8 | method: 'post', 9 | wait: 0.1, 10 | params: { 11 | $: 'kv', 12 | arg: 'system.name', 13 | map: s => `{id:'${Buffer.from(s).toString('hex')}'}` 14 | } 15 | } 16 | } 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/write/physical.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/link.b', 9 | method: 'post', 10 | wait: 0.1, 11 | params: { 12 | $: 'fn', 13 | arg: async function() { 14 | const nm = []; 15 | const spdc = []; 16 | let fct = 0; 17 | let en = 0; 18 | let an = 0; 19 | const port = this.readKV('network.physical.port'); 20 | for (let k in port) { 21 | const key = parseInt(k); 22 | nm.push(`'${Buffer.from(port[key].name).toString('hex')}'`); 23 | const bit = 1 << key; 24 | en |= port[key].enable ? bit : 0; 25 | fct |= port[key].flowcontrol ? bit : 0; 26 | switch (port[key].speed) { 27 | case '10M': 28 | spdc[key] = 0; 29 | break; 30 | case '100M': 31 | spdc[key] = 1; 32 | break; 33 | case '1G': 34 | spdc[key] = 2; 35 | break; 36 | case 'auto': 37 | default: 38 | an |= bit; 39 | spdc[key] = 0; 40 | break; 41 | } 42 | } 43 | return `{en:${Maps.toHex2(en)},nm:[${nm}],an:${Maps.toHex2(an)},spdc:[${spdc.map(v => Maps.toHex2(v))}],dpxc:0x01ff,fctc:${Maps.toHex2(fct)},fctr:${Maps.toHex2(fct)}}`; 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /device/switch/mikrotik/generic/write/snmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'guard', 4 | key: 'system.snmp.enable,system.contact,system.location', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/snmp.b', 8 | method: 'post', 9 | params: { 10 | $: 'fn', 11 | arg: ctx => { 12 | const enable = ctx.readKV('system.snmp.enable') ? '0x01' : '0x00'; 13 | const location = Buffer.from(ctx.readKV('system.location')).toString('hex'); 14 | const contact = Buffer.from(ctx.readKV('system.contact')).toString('hex'); 15 | return `{en:${enable},loc:'${location}',ci:'${contact}'}`; 16 | } 17 | } 18 | } 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /device/switch/netgear/gs110emx/read/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | $: 'navigate', 5 | arg: { 6 | $: 'eval', 7 | arg: `"/iss/specific/igs_conf.html?Gambit=" + top.GAMBIT` 8 | }, 9 | frame: 'maincontent', 10 | values: { 11 | snoop: `input[name=GLOBAL_STATUS][value="1"]` 12 | } 13 | } 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /device/switch/netgear/gs110emx/read/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | types: { 5 | static: 5, 6 | active: 5 7 | } 8 | } 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /device/switch/netgear/gs110emx/read/limits.js: -------------------------------------------------------------------------------- 1 | const Mbits = (v) => v / 8 * 1024 * 1024; 2 | 3 | module.exports = { 4 | network: { 5 | physical: { 6 | port: { 7 | $: 'navigate', 8 | arg: { 9 | $: 'eval', 10 | arg: `"/iss/specific/port_ratectrl.html?Gambit=" + top.GAMBIT` 11 | }, 12 | frame: 'maincontent', 13 | values: { 14 | $: 'iterate', 15 | arg: itr => [{ 16 | limit: { 17 | ingress: { 18 | $: null, 19 | arg: `.portID:nth-child(${itr.index + 3}) input[name=IN_RATE_LIMIT]`, 20 | map: { 21 | 0: 0, 22 | 1: 0, 23 | 2: Mbits(1), 24 | 3: Mbits(5), 25 | 4: Mbits(10), 26 | 5: Mbits(50), 27 | 6: Mbits(100), 28 | 7: Mbits(500), 29 | } 30 | }, 31 | egress: { 32 | $: null, 33 | arg: `.portID:nth-child(${itr.index + 3}) input[name=RATE_LIMIT]`, 34 | map: { 35 | 0: 0, 36 | 1: 0, 37 | 2: Mbits(1), 38 | 3: Mbits(5), 39 | 4: Mbits(10), 40 | 5: Mbits(50), 41 | 6: Mbits(100), 42 | 7: Mbits(500), 43 | } 44 | } 45 | } 46 | }] 47 | } 48 | } 49 | } 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /device/switch/netgear/gs110emx/read/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'navigate', 6 | arg: { 7 | $: 'eval', 8 | arg: `"/iss/specific/port_monitorconfig.html?Gambit=" + top.GAMBIT` 9 | }, 10 | frame: 'maincontent', 11 | values: { 12 | enable: `input[value="0"]`, 13 | target: { 14 | $: 'fn', 15 | arg: async ctx => { 16 | for (let i = 0; i < 10; i++) { 17 | if (await ctx.eval({ $: 'selector', arg: `#tblDisplayDst .portMember:nth-child(${i + 2}) .checked` }) !== null) { 18 | return i; 19 | } 20 | } 21 | return 0; 22 | } 23 | }, 24 | port: { 25 | $: 'iterate', 26 | limit: 10, 27 | arg: itr => [{ 28 | ingress: { 29 | $: 'selector', 30 | arg: `#tblDisplaySrc .portMember:nth-child(${itr.index + 2}) .checked`, 31 | map: v => true, 32 | fallback: false 33 | }, 34 | egress: { 35 | $: 'selector', 36 | arg: `#tblDisplaySrc .portMember:nth-child(${itr.index + 2}) .checked`, 37 | map: v => true, 38 | fallback: false 39 | } 40 | }] 41 | } 42 | } 43 | } 44 | } 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /device/switch/netgear/gs110emx/read/name+ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'navigate', 4 | arg: { 5 | $: 'eval', 6 | arg: `"/iss/specific/sysInfo.html?Gambit=" + top.GAMBIT` 7 | }, 8 | frame: 'maincontent', 9 | values: { 10 | name: `#tbl1 input[name=switch_name]`, 11 | macAddress: { 12 | 0: '#tbl1 tr:nth-child(4) td:nth-child(2)' 13 | }, 14 | firmware: { 15 | version: '#tbl1 tr:nth-child(5) td:nth-child(2)' 16 | }, 17 | ipv4: { 18 | mode: { 19 | $: 'selector', 20 | arg: '#tbl1 select[name=dhcp_mode]', 21 | map: { 22 | 1: 'dhcp', 23 | 2: 'static' 24 | } 25 | }, 26 | address: '#tbl1 input[name=IP_ADDRESS]', 27 | netmask: '#tbl1 input[name=SUBNET_MASK]', 28 | gateway: '#tbl1 input[name=GATEWAY_ADDRESS]' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /device/switch/netgear/gs110emx/read/statistics.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'navigate', 6 | arg: { 7 | $: 'eval', 8 | arg: `"/iss/specific/interface_stats.html?Gambit=" + top.GAMBIT` 9 | }, 10 | frame: 'maincontent', 11 | values: { 12 | $: 'iterate', 13 | arg: itr => [{ 14 | statistics: { 15 | rx: { 16 | bytes: `.portID:nth-child(${itr.index + 2}) .def:nth-child(2)`, 17 | errors: `.portID:nth-child(${itr.index + 2}) .def:nth-child(4)`, 18 | crc: `.portID:nth-child(${itr.index + 2}) .def:nth-child(4)` 19 | }, 20 | tx: { 21 | bytes: `.portID:nth-child(${itr.index + 2}) .def:nth-child(3)` 22 | } 23 | } 24 | }] 25 | } 26 | } 27 | } 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /device/switch/netgear/gs110emx/write/keychain.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | keychain: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/iss/specific/password.html', 8 | method: 'post', 9 | params: { 10 | Gambit: { $: 'eval', arg: 'top.GAMBIT' }, 11 | oldPassword: { $: 'kv', arg: 'system.keychain.password', options: { original: true } }, 12 | newPassword: { $: 'kv', arg: 'system.keychain.password' }, 13 | reNewPassword: { $: 'kv', arg: 'system.keychain.password' }, 14 | ACTION: '' 15 | } 16 | } 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /device/switch/netgear/gs110emx/write/name+ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'guard', 4 | key: 'system.name,system.ipv4', 5 | arg: { 6 | $: 'fetch', 7 | arg: `/iss/specific/sysInfo.html`, 8 | method: 'post', 9 | params: { 10 | Gambit: { 11 | $: 'eval', 12 | arg: 'top.GAMBIT' 13 | }, 14 | refreshFlag: 0, 15 | switch_name: { 16 | $: 'kv', 17 | arg: 'system.name', 18 | }, 19 | dhcp_mode: { 20 | $: 'kv', 21 | name: 'system.ipv4.mode', 22 | map: { 23 | dhcp: 1, 24 | static: 2 25 | } 26 | }, 27 | IP_ADDRESS: { 28 | $: 'kv', 29 | arg: 'system.ipv4.address' 30 | }, 31 | SUBNET_MASK: { 32 | $: 'kv', 33 | arg: 'system.ipv4.netmask' 34 | }, 35 | GATEWAY_ADDRESS: { 36 | $: 'kv', 37 | arg: 'system.ipv4.gateway' 38 | }, 39 | ACTION: 'Apply' 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /device/switch/netgear/gs305e/read/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | $: 'navigate', 5 | arg: '/igmp.cgi', 6 | frame: 'maincontent', 7 | values: { 8 | snoop: `input[name=status][value="1"]` 9 | } 10 | } 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /device/switch/netgear/gs305e/read/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | types: { 5 | static: 0, 6 | active: 0 7 | } 8 | } 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /device/switch/netgear/gs305e/read/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'navigate', 6 | arg: '/mirror.cgi', 7 | frame: 'maincontent', 8 | values: { 9 | enable: { 10 | $: 'selector', 11 | arg: `#mirroring`, 12 | map: { 13 | 0: true, 14 | 1: false 15 | } 16 | }, 17 | target: { 18 | $: `selector`, 19 | arg: `#DestiPort`, 20 | map: v => v - 1 21 | }, 22 | port: { 23 | $: `iterate`, 24 | limit: 5, 25 | arg: itr => [{ 26 | ingress: { 27 | $: 'selector', 28 | arg: `#unit1 .portMember:nth-child(${itr.index + 1}) .portImage.checked`, 29 | map: v => true, 30 | fallback: false 31 | }, 32 | egress: { 33 | $: 'selector', 34 | arg: `#unit1 .portMember:nth-child(${itr.index + 1}) .portImage.checked`, 35 | map: v => true, 36 | fallback: false 37 | } 38 | }] 39 | } 40 | } 41 | } 42 | } 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /device/switch/netgear/gs305e/read/name+ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'navigate', 4 | arg: '/switch_info.cgi', 5 | frame: 'maincontent', 6 | values: { 7 | name: `#switch_name`, 8 | macAddress: { 9 | 0: { 10 | $: `selector`, 11 | arg: `#tbl2 tr:nth-child(4) td:last-child`, 12 | map: Maps.toMacAddress 13 | } 14 | }, 15 | firmware: { 16 | version: `#tbl2 tr:nth-child(6) td:last-child`, 17 | }, 18 | ipv4: { 19 | mode: { 20 | $: `selector`, 21 | arg: `#dhcpMode`, 22 | map: { 23 | 0: 'static', 24 | 1: 'dhcp' 25 | } 26 | }, 27 | address: `#ip_address`, 28 | netmask: `#subnet_mask`, 29 | gateway: `#gateway_address` 30 | } 31 | } 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /device/switch/netgear/gs305e/read/statistics.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'navigate', 6 | arg: '/portStatistics.cgi', 7 | frame: 'maincontent', 8 | values: { 9 | $: 'iterate', 10 | limit: 5, 11 | arg: itr => [ 12 | { 13 | statistics: { 14 | rx: { 15 | bytes: `.portID:nth-child(${itr.index + 3}) .def:nth-child(2)`, 16 | errors: `.portID:nth-child(${itr.index + 3}) .def:nth-child(8)`, 17 | crc: `.portID:nth-child(${itr.index + 3}) .def:nth-child(8)` 18 | }, 19 | tx: { 20 | bytes: `.portID:nth-child(${itr.index + 3}) .def:nth-child(5)` 21 | } 22 | } 23 | } 24 | ] 25 | } 26 | } 27 | } 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /device/switch/netgear/gs305e/write/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | snoop: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/igmp.cgi', 9 | method: 'post', 10 | frame: 'maincontent', 11 | params: { 12 | status: { 13 | $: 'kv', 14 | map: { 15 | true: 1, 16 | false: 0 17 | } 18 | }, 19 | hash: { $: 'selector', arg: '#hash' } 20 | } 21 | } 22 | } 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /device/switch/netgear/gs305e/write/ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | // 4 | // IP 5 | // Note: This will change the IP address which means you will *not* be able to talk 6 | // to the device after this. Put it at the end! 7 | // 8 | ipv4: { 9 | $: 'guard', 10 | arg: { 11 | $: 'fetch', 12 | arg: '/switch_info.cgi', 13 | method: 'post', 14 | frame: 'maincontent', 15 | wait: 1, 16 | params: { 17 | dhcpMode: { 18 | $: 'kv', 19 | arg: 'system.ipv4.mode', 20 | map: { 21 | static: '0', 22 | dhcp: '1' 23 | } 24 | }, 25 | ip_address: { $: 'kv', arg: 'system.ipv4.address' }, 26 | subnet_mask: { $: 'kv', arg: 'system.ipv4.netmask' }, 27 | gateway_address: { $: 'kv', arg: 'system.ipv4.gateway' }, 28 | hash: { $: 'selector', arg: '#hash' } 29 | } 30 | } 31 | } 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /device/switch/netgear/gs305e/write/keychain.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | keychain: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/user.cgi', 8 | method: 'post', 9 | frame: 'maincontent', 10 | params: { 11 | oldPassword: { $: 'kv', arg: 'system.keychain.password', options: { original: true } }, 12 | newPassword: { $: 'kv', arg: 'system.keychain.password' }, 13 | reNewPassword: { $: 'kv', arg: 'system.keychain.password' }, 14 | hash: { $: 'selector', arg: '#hash' } 15 | } 16 | } 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /device/switch/netgear/gs305e/write/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/mirror.cgi', 9 | method: 'post', 10 | frame: 'maincontent', 11 | params: { 12 | mirroring: { $: 'kv', map: { true: 0, false: 1 } }, 13 | select: { $: 'kv', map: v => v + 1 }, 14 | hiddenMem: { 15 | $: 'fn', 16 | arg: ctx => { 17 | ports = ctx.readKV('network.mirror.0.port'); 18 | const mem = '00000'; 19 | for (let p in ports) { 20 | const port = ports[p] || {}; 21 | if (port.ingress || port.egress) { 22 | mem[p] = '1'; 23 | } 24 | } 25 | return mem; 26 | } 27 | }, 28 | hash: { $: 'selector', arg: '#hash' } 29 | } 30 | } 31 | } 32 | } 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /device/switch/netgear/gs305e/write/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | name: { 4 | $: 'guard', 5 | arg: { 6 | $1: { 7 | $: 'frame', 8 | frame: 'maincontent', 9 | arg: { 10 | $0: { 11 | $: 'navigate', 12 | arg: '/switch_info.cgi' 13 | }, 14 | $1: { 15 | $: 'type', 16 | arg: `#switch_name` 17 | } 18 | } 19 | }, 20 | $2: { 21 | $: 'click', 22 | arg: '#btn_Apply' 23 | } 24 | } 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /device/switch/netgear/gs305e/write/physical.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'foreach', 6 | arg: itr => [{ 7 | $: 'guard', 8 | arg: { 9 | $: 'fetch', 10 | arg: '/status.cgi', 11 | method: 'post', 12 | frame: 'maincontent', 13 | params: { 14 | SPEED: { 15 | $: 'fn', 16 | arg: ctx => { 17 | const speed = ctx.readKV(`${itr.path}.speed`); 18 | const enable = ctx.readKV(`${itr.path}.enable`); 19 | if (!enable) { 20 | return 2; 21 | } 22 | else switch (speed) { 23 | case 'auto': 24 | default: 25 | return 1; 26 | case '10M (H)': 27 | return 3; 28 | case '10M': 29 | return 4; 30 | case '100M (H)': 31 | return 5; 32 | case '100M': 33 | return 6; 34 | } 35 | } 36 | }, 37 | FLOW_CONTROL: { 38 | $: 'kv', 39 | arg: `${itr.path}.flowcontrol`, 40 | map: { 41 | true: 1, 42 | false: 2 43 | } 44 | }, 45 | [`port${itr.index + 1}`]: 'checked', 46 | hash: { 47 | $: 'selector', 48 | arg: '#hash' 49 | } 50 | } 51 | } 52 | }] 53 | } 54 | } 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /device/switch/tp-link/generic1/index.js: -------------------------------------------------------------------------------- 1 | const Device = { 2 | 3 | name: 'Unknown TP-Link', 4 | id: 'tplink/unknown', 5 | image: require('./image'), 6 | generic: true, 7 | 8 | layout: { 9 | ports: [ 10 | [ 0 ] 11 | ] 12 | }, 13 | 14 | properties: { 15 | switch: true 16 | }, 17 | 18 | identify: { 19 | http: { 20 | ipv4: 'dhcp', 21 | loggedOut: { 22 | $: 'eval', 23 | arg: `document.querySelector('#t_corporation').innerText.toLowerCase().indexOf('tp-link') !== -1` 24 | } 25 | } 26 | }, 27 | 28 | login: require('./login'), 29 | 30 | constants: { 31 | system: { 32 | hardware: { 33 | manufacturer: 'TP-Link', 34 | model: 'Generic' 35 | }, 36 | keychain: { 37 | username: 'admin', 38 | password: 'admin' 39 | }, 40 | ipv4: { 41 | address: '', 42 | port: 80 43 | } 44 | } 45 | }, 46 | }; 47 | 48 | module.exports = Device; 49 | -------------------------------------------------------------------------------- /device/switch/tp-link/generic1/login.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | path: '/', 3 | username: '#username', 4 | password: '#password', 5 | activate: '#logon', 6 | valid: 'frameset' 7 | }; 8 | -------------------------------------------------------------------------------- /device/switch/tp-link/generic2/index.js: -------------------------------------------------------------------------------- 1 | const Device = { 2 | 3 | name: 'Unknown TP-Link', 4 | id: 'tplink/unknown', 5 | image: require('../generic1/image'), 6 | generic: true, 7 | 8 | layout: { 9 | ports: [ 10 | [ 0 ] 11 | ] 12 | }, 13 | 14 | properties: { 15 | switch: true 16 | }, 17 | 18 | identify: { 19 | http: { 20 | ipv4: [ 'dhcp', '192.168.0.1' ], 21 | loggedOut: { 22 | $: 'eval', 23 | arg: `document.querySelector('.icon-logo').innerText.toLowerCase().indexOf('tp-link') !== -1` 24 | } 25 | } 26 | }, 27 | 28 | login: require('./login'), 29 | 30 | constants: { 31 | system: { 32 | hardware: { 33 | manufacturer: 'TP-Link', 34 | model: 'Generic' 35 | }, 36 | keychain: { 37 | username: 'admin', 38 | password: 'admin' 39 | }, 40 | ipv4: { 41 | address: '', 42 | port: 80 43 | } 44 | } 45 | }, 46 | }; 47 | 48 | module.exports = Device; 49 | -------------------------------------------------------------------------------- /device/switch/tp-link/generic2/login.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | path: '/', 3 | username: '#login-username input', 4 | password: '#login-password input', 5 | activate: '#login-btn .button-button', 6 | valid: '#top' 7 | }; 8 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2500g-10ts/index.js: -------------------------------------------------------------------------------- 1 | const Device = { 2 | 3 | name: 'T2500G-10TS', 4 | id: 'tplink/t2500g10ts', 5 | productUrl: 'https://www.tp-link.com/us/business-networking/managed-switch/t2500g-10ts/', 6 | image: require('./image'), 7 | 8 | layout: { 9 | ports: [ 10 | [ 0, 1, 2, 3, 4, 5, 6, 7, 'S', 8, 9 ] 11 | ] 12 | }, 13 | 14 | properties: { 15 | switch: true 16 | }, 17 | 18 | identify: { 19 | http: { 20 | ipv4: [ 'dhcp', '192.168.0.1' ], 21 | loggedIn: { 22 | $: 'eval', 23 | arg: `document.title.toLowerCase().indexOf('t2500g-10ts') !== -1` 24 | } 25 | } 26 | }, 27 | 28 | login: require('../generic2/login'), 29 | 30 | constants: { 31 | system: { 32 | hardware: { 33 | manufacturer: 'TP-Link', 34 | model: 'T2500G-10TS' 35 | }, 36 | keychain: { 37 | username: 'admin', 38 | password: 'admin' 39 | }, 40 | ipv4: { 41 | address: '', 42 | port: 80 43 | } 44 | }, 45 | network: { 46 | physical: { 47 | ports: { 48 | nr: { 49 | total: 10, 50 | '1G': 8, 51 | 'sfp': 2 52 | } 53 | } 54 | } 55 | } 56 | }, 57 | 58 | read: { 59 | }, 60 | write: { 61 | }, 62 | commit: null 63 | 64 | }; 65 | 66 | module.exports = Device; 67 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/read/clients.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | clients: { 4 | $: 'navigate', 5 | arg: '/userRpm/AddressFormDisplayRpm.htm', 6 | frame: 'mainFrame', 7 | type: 'eval', 8 | values: { 9 | $: 'iterate', 10 | arg: itr => [{ 11 | mac: { 12 | $: 'eval', 13 | arg: `Info[1][${itr.index}][0]`, 14 | map: Maps.toMacAddress 15 | }, 16 | vlan: `Info[1][${itr.index}][1]`, 17 | portnr: { 18 | $: 'eval', 19 | arg: `Info[1][${itr.index}][2]`, 20 | map: p => p.split('/')[2] - 1 21 | } 22 | }] 23 | } 24 | } 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/read/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | snoop: { 5 | $: 'navigate', 6 | arg: `/userRpm/IgmpConfigRpm.htm`, 7 | frame: 'mainFrame', 8 | values: { 9 | $: 'eval', 10 | arg: `!!enable` 11 | } 12 | } 13 | } 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/read/ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | ipv4: { 4 | $: 'navigate', 5 | arg: `/userRpm/VlanInterfaceDetailRpm.htm`, 6 | frame: 'mainFrame', 7 | params: { 8 | id: '1', 9 | type: '1', 10 | _tid_: { 11 | $: 'eval', 12 | arg: 'top.g_tid' 13 | } 14 | }, 15 | type: 'eval', 16 | values: { 17 | mode: { 18 | $: 'eval', 19 | arg: `intfBasicInfo.mode`, 20 | map: { 21 | DHCP: 'dhcp', 22 | Static: 'static' 23 | } 24 | }, 25 | address: `intfBasicInfo.ip.split('/')[0]`, 26 | netmask: `intfBasicInfo.ip.split('/')[1]` 27 | } 28 | } 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/read/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | $: 'navigate', 5 | arg: '/userRpm/TrunkViewRpm.htm', 6 | frame: 'mainFrame', 7 | type: 'eval', 8 | values: { 9 | $: 'fn', 10 | arg: async ctx => { 11 | info = JSON.parse(await ctx.eval('eval', 'JSON.stringify(info)')); 12 | const ports = {}; 13 | for (let i = 0; i < 28; i++) { 14 | ports[i] = { type: 'none', group: 0 }; 15 | } 16 | for (let i = 0; i < info.length; i++) { 17 | let type = 'none'; 18 | switch (info[i][1]) { 19 | case 1: 20 | type = 'static'; 21 | break; 22 | case 2: 23 | type = 'active'; 24 | break; 25 | case 3: 26 | type = 'passive'; 27 | break; 28 | default: 29 | break; 30 | } 31 | const group = info[i][0]; 32 | info[i][2].split(',').forEach(s => { 33 | if (s !== 'N/A') { 34 | s = s.split('/')[2].split('-'); 35 | const limit = parseInt(s[1] || s[0]); 36 | for (let j = parseInt(s[0]); j <= limit; j++) { 37 | ports[j - 1] = { type: type, group: group }; 38 | } 39 | } 40 | }); 41 | } 42 | return { 43 | types: { 44 | static: 14, 45 | active: 14 46 | }, 47 | port: ports 48 | } 49 | } 50 | } 51 | } 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/read/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'navigate', 6 | arg: '/userRpm/PortMirrorSetRpm.htm', 7 | frame: 'mainFrame', 8 | values: { 9 | enable: { $: 'literal', arg: true }, 10 | target: { 11 | $: 'eval', 12 | arg: `MirrorInfo[2] ? MirrorInfo[2].split('/')[2] - 1 : 0` 13 | }, 14 | port: { 15 | $: 'iterate', 16 | limit: 28, 17 | arg: itr => [{ 18 | ingress: { 19 | $: 'eval', 20 | arg: `!!info[1][1]` 21 | }, 22 | egress: { 23 | $: 'eval', 24 | arg: `!!info[1][2]` 25 | } 26 | }] 27 | } 28 | } 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/read/slow-statistics.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'iterate', 6 | limit: 28, 7 | arg: itr => [{ 8 | $: 'navigate', 9 | arg: `/userRpm/MibCounterRpm.htm`, 10 | frame: 'mainFrame', 11 | params: { 12 | refresh_enable: 0, 13 | refresh_frequency: 300, 14 | sel_port: `1/0/${itr.index + 1}`, 15 | selUnit: 1, 16 | _tid_: { 17 | $: 'eval', 18 | arg: 'top.g_tid' 19 | } 20 | }, 21 | type: 'eval', 22 | values: { 23 | statistics: { 24 | rx: { 25 | broadcast: 'rx_value[0]', 26 | multicast: 'rx_value[1]', 27 | unicast: 'rx_value[2]', 28 | jumbo: 'rx_value[3]', 29 | alignment: 'rx_value[4]', 30 | undersized: 'rx_value[5]' 31 | }, 32 | tx: { 33 | broadcast: 'tx_value[0]', 34 | multicast: 'tx_value[1]', 35 | unicast: 'tx_value[2]', 36 | jumbo: 'tx_value[3]', 37 | collisions: 'tx_value[4]' 38 | } 39 | } 40 | } 41 | }] 42 | } 43 | } 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/read/snmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | snmp: { 4 | enable: { 5 | $: 'navigate', 6 | arg: '/userRpm/SnmpGlobalRpm.htm', 7 | frame: 'mainFrame', 8 | values: { 9 | $: 'eval', 10 | arg: '!!gSNMPv3GloConfInfo[3]' 11 | } 12 | } 13 | } 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/read/statistics.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'navigate', 6 | arg: '/userRpm/MibBrowseRpm.htm', 7 | frame: 'mainFrame', 8 | type: 'eval', 9 | values: { 10 | $: 'iterate', 11 | arg: itr => [{ 12 | statistics: { 13 | rx: { 14 | bytes: `info[1][${itr.index}][3]`, 15 | packets: `info[1][${itr.index}][1]` 16 | }, 17 | tx: { 18 | bytes: `info[1][${itr.index}][4]`, 19 | packets: `info[1][${itr.index}][2]` 20 | } 21 | } 22 | }] 23 | } 24 | } 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/write/commit.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | $: 'fetch', 3 | arg: '/userRpm/ConfigsaveFileRpm.htm', 4 | params: { 5 | _tid_: { 6 | $: 'eval', 7 | arg: 'top.g_tid' 8 | } 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/write/ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | ipv4: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/userRpm/VlanInterfaceEditRpm.htm', 8 | wait: 1, 9 | params: { 10 | apply: 'true', 11 | id: '1', 12 | type: '1', 13 | admin_status: '1', 14 | mode: { 15 | $: 'kv', 16 | arg: 'system.ipv4.mode', 17 | map: { 18 | static: '1', 19 | dhcp: '2' 20 | } 21 | }, 22 | ip: { $: 'kv', arg: 'system.ipv4.address' }, 23 | mask: { $: 'kv', arg: 'system.ipv4.netmask' }, 24 | text: '', 25 | _tid_: { 26 | $: 'eval', 27 | arg: 'top.g_tid' 28 | } 29 | } 30 | } 31 | } 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/write/keychain.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | keychain: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/userRpm/UserManageRpm.htm', 8 | params: { 9 | type: 'modify', 10 | username: 'admin', 11 | usertype: 3, 12 | userstatus: 0, 13 | pwdmode: 1, 14 | changepwd: true, 15 | oldpwd: { $: 'kv', arg: 'system.keychain.password', options: { original: true } }, 16 | pwd: { $: 'kv', arg: 'system.keychain.password' }, 17 | confirmpwd: { $: 'kv', arg: 'system.keychain.password' }, 18 | _tid_: { 19 | $: 'eval', 20 | arg: 'top.g_tid' 21 | } 22 | } 23 | } 24 | } 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/write/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'guard', 6 | arg: { 7 | port: { 8 | $: 'foreach', 9 | arg: ctx => [{ 10 | $: 'guard', 11 | arg: { 12 | $: 'fetch', 13 | arg: '', 14 | method: 'post', 15 | params: { 16 | SrcSubmit: true, 17 | session: 1, 18 | ingress: { $: 'kv', arg: `${ctx.path}.ingress`, map: { true: 1, false: 0 }}, 19 | egress: { $: 'kv', arg: `${ctx.path}.egress`, map: { true: 1, false: 0 }}, 20 | portlist: `1/0/${ctx.key + 1}`, 21 | _tid_: { 22 | $: 'eval', 23 | arg: 'top.g_tid' 24 | } 25 | } 26 | } 27 | }] 28 | } 29 | } 30 | } 31 | } 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/write/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'guard', 4 | arg: { 5 | $: 'fetch', 6 | arg: '/userRpm/SystemDescriRpm.htm', 7 | params: { 8 | sysName: { $: 'kv', arg: 'system.name' }, 9 | sysLocation: { $: 'kv', arg: 'system.location' }, 10 | sysContact: { $: 'kv', arg: 'system.contact' }, 11 | submit: 'Apply', 12 | _tid_: { 13 | $: 'eval', 14 | arg: 'top.g_tid' 15 | } 16 | } 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/write/physical.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | $: 'foreach', 5 | arg: ctx => [{ 6 | $: 'guard', 7 | arg: { 8 | $: 'fetch', 9 | arg: '/userRpm/PortStatusSetRpm.htm', 10 | params: { 11 | submit: 1, 12 | desc: { 13 | $: 'kv', 14 | arg: `${ctx.path}.name` 15 | }, 16 | status: { 17 | $: 'kv', 18 | arg: `${ctx.path}.enable`, 19 | map: { 20 | true: 1, 21 | false: 0 22 | } 23 | }, 24 | speed: { 25 | $: 'kv', 26 | arg: `${ctx.path}.speed`, 27 | map: { 28 | 'auto': 0, 29 | '10M': 1, 30 | '100M': 2, 31 | '1G': 3 32 | } 33 | }, 34 | duplex: -1, 35 | flowctrl: { 36 | $: 'kv', 37 | arg: `${ctx.path}.flowcontrol`, 38 | map: { 39 | true: 1, 40 | false: 0 41 | } 42 | }, 43 | jumbo: { 44 | $: 'kv', 45 | arg: `${ctx.path}.jumbo`, 46 | map: { 47 | true: 1, 48 | false: 0 49 | } 50 | }, 51 | row: `1/0/${ctx.key}`, 52 | _tid_: { 53 | $: 'eval', 54 | arg: 'top.g_tid' 55 | } 56 | } 57 | } 58 | }] 59 | } 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /device/switch/tp-link/t2600g-28ts/write/snmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | snmp: { 4 | enable: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/userRpm/SnmpGlobalRpm.htm', 9 | params: { 10 | snmpState: { 11 | $: 'kv', 12 | arg: 'system.snmp.enable', 13 | map: { 14 | true: 1, 15 | false: 0 16 | } 17 | }, 18 | button: 'stateSubmit', 19 | _tid_: { 20 | $: 'eval', 21 | arg: 'top.g_tid' 22 | } 23 | } 24 | } 25 | } 26 | } 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/read/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | snoop: { 5 | $: 'navigate', 6 | arg: '/IgmpSnoopingRpm.htm', 7 | frame: 'mainFrame', 8 | values: { 9 | $: 'eval', 10 | arg: 'igmp_ds.state', 11 | map: { 12 | 1: true, 13 | 0: false 14 | } 15 | } 16 | } 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/read/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | $: 'navigate', 5 | arg: '/PortTrunkRpm.htm', 6 | frame: 'mainFrame', 7 | values: { 8 | $: 'fn', 9 | arg: async ctx => { 10 | const p = []; 11 | const nr = await ctx.eval('eval', 'trunk_conf.maxTrunkNum'); 12 | const nrports = await ctx.eval('eval', 'trunk_conf.portNum'); 13 | for (let i = 0; i < nr; i++) { 14 | p[i] = await ctx.eval('eval', `trunk_conf.portStr_g${i + 1}`); 15 | } 16 | const ports = {}; 17 | for (let i = 0; i < nrports; i++) { 18 | ports[i] = { type: 'none', group: 0 }; 19 | for (let j = 0; j < nr; j++) { 20 | if (p[j][i]) { 21 | ports[i] = { type: 'static', group: j + 1 }; 22 | break; 23 | } 24 | } 25 | } 26 | return { 27 | types: { 28 | static: nr, 29 | active: 0 30 | }, 31 | port: ports 32 | }; 33 | } 34 | } 35 | } 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/read/limits.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'navigate', 6 | arg: '/QosBandWidthControlRpm.htm', 7 | frame: 'mainFrame', 8 | values: { 9 | $: 'fn', 10 | arg: async ctx => { 11 | const bcInfo = await ctx.eval('eval', 'bcInfo'); 12 | const port = {}; 13 | for (let i = 0; i < bcInfo.length; i += 3) { 14 | port[i / 3] = { 15 | limit: { 16 | ingress: bcInfo[i] / 8 * 1024, 17 | egress: bcInfo[i + 1] / 8 * 1024 18 | } 19 | } 20 | } 21 | return port; 22 | } 23 | } 24 | } 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/read/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'navigate', 6 | arg: '/PortMirrorRpm.htm', 7 | frame: 'mainFrame', 8 | type: 'eval', 9 | values: { 10 | enable: '!!window.MirrEn', 11 | target: { 12 | $: 'eval', 13 | arg: 'window.MirrPort', 14 | map: v => v - 1 15 | }, 16 | port: { 17 | $: 'fn', 18 | arg: async ctx => { 19 | const ports = {}; 20 | const nrports = await ctx.eval('eval', 'window.max_port_num'); 21 | const info = JSON.parse(await ctx.eval('eval', 'JSON.stringify(window.mirr_info)')); 22 | for (let i = 0; i < nrports; i++) { 23 | const port = {}; 24 | if (info.ingress[i]) { 25 | port.ingress = true; 26 | } 27 | if (info.egress[i]) { 28 | port.egress = true; 29 | } 30 | for (const k in port) { 31 | ports[i] = port; 32 | break; 33 | } 34 | } 35 | return ports; 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/read/name+ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'navigate', 4 | arg: '/SystemInfoRpm.htm', 5 | frame: 'mainFrame', 6 | values: { 7 | name: `#tDevDscr`, 8 | firmware: { 9 | version: `#sp_firewareversion` 10 | }, 11 | hardware: { 12 | version: `#sp_hardwareversion` 13 | }, 14 | macAddress: { 15 | 0: { 16 | $: 'selector', 17 | arg: '#sp_macaddress', 18 | map: mac => mac.toLowerCase(mac) 19 | } 20 | }, 21 | ipv4: { 22 | address: '#sp_ipaddress', 23 | netmask: '#sp_netmask', 24 | gateway: '#sp_gateway', 25 | mode: { 26 | $: 'navigate', 27 | arg: '/IpSettingRpm.htm', 28 | values: { 29 | $mode: { 30 | $: 'selector', 31 | arg: '#check_dhcp', 32 | map: { 33 | enable: 'dhcp', 34 | disable: 'static' 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/read/statistics.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'navigate', 6 | arg: '/PortStatisticsRpm.htm', 7 | frame: 'mainFrame', 8 | values: { 9 | $: 'iterate', 10 | arg: itr => [{ 11 | statistics: { 12 | rx: { 13 | packets: `form[name=port_statistics] tr:nth-child(${itr.index + 2}) td:nth-child(6)`, 14 | errors: `form[name=port_statistics] tr:nth-child(${itr.index + 2}) td:nth-child(7)` 15 | }, 16 | tx: { 17 | packets: `form[name=port_statistics] tr:nth-child(${itr.index + 2}) td:nth-child(4)`, 18 | errors: `form[name=port_statistics] tr:nth-child(${itr.index + 2}) td:nth-child(5)` 19 | } 20 | } 21 | }] 22 | } 23 | } 24 | } 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/read/vlan.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | vlans: { 4 | $: 'navigate', 5 | arg: '/Vlan8021QRpm.htm', 6 | frame: 'mainFrame', 7 | values: { 8 | $: 'fn', 9 | arg: async function() { 10 | const str = await this.eval('eval', 'JSON.stringify(window.qvlan_ds)'); 11 | const info = JSON.parse(str); 12 | const vlans = {}; 13 | for (let i = 0; i < info.vids.length; i++) { 14 | const u = info.untagMbrs[i]; 15 | const t = info.tagMbrs[i]; 16 | const port = {}; 17 | for (p = 0; p < 8; p++) { 18 | if (t & (1 << p)) { 19 | port[p] = { tagged: true }; 20 | } 21 | else if (u & (1 << p)) { 22 | port[p] = { tagged: false }; 23 | } 24 | } 25 | if (Object.keys(port).length) { 26 | vlans[info.vids[i]] = { 27 | name: info.names[i], 28 | port: port 29 | }; 30 | } 31 | } 32 | return { 33 | '8021q': info.state ? true : false, 34 | vlan: vlans 35 | }; 36 | } 37 | }, 38 | pvid: { 39 | $: 'navigate', 40 | arg: '/Vlan8021QPvidRpm.htm', 41 | frame: 'mainFrame', 42 | type: 'eval', 43 | values: { 44 | $: 'iterate', 45 | arg: itr => [{ 46 | pvid: `pvid_ds.pvids[${itr.index}]` 47 | }] 48 | } 49 | } 50 | } 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/write/commit.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | $: `fetch`, 3 | arg: `/savingconfig.cgi`, 4 | method: 'post', 5 | params: { 6 | action_op: 'save' 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/write/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | snoop: { 5 | $: `guard`, 6 | arg: { 7 | $: `fetch`, 8 | arg: `/igmpSnooping.cgi`, 9 | params: { 10 | igmp_mode: { 11 | $: `kv`, 12 | arg: `network.igmp.snoop`, 13 | map: { 14 | true: 1, 15 | false: 0 16 | } 17 | }, 18 | reportSu_mode: 0, 19 | Apply: 'Apply' 20 | } 21 | } 22 | } 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/write/ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | ipv4: { 4 | $: `guard`, 5 | arg: { 6 | $: `fetch`, 7 | arg: `/ip_setting.cgi`, 8 | wait: 1, 9 | params: { 10 | dhcpSetting: { 11 | $: `kv`, 12 | arg: `system.ipv4.mode`, 13 | map: { 14 | static: 'disable', 15 | dhcp: 'enable' 16 | } 17 | }, 18 | ip_address: { $: `kv`, arg: `system.ipv4.address` }, 19 | ip_netmask: { $: `kv`, arg: `system.ipv4.netmask` }, 20 | ip_gateway: { $: `kv`, arg: `system.ipv4.gateway` } 21 | } 22 | } 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/write/keychain.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | keychain: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/usr_account_set.cgi', 8 | params: { 9 | txt_username: 'admin', 10 | txt_oldpwd: { $: 'kv', arg: 'system.keychain.password', options: { original: true } }, 11 | txt_userpwd: { $: 'kv', arg: 'system.keychain.password' }, 12 | txt_confirmpwd: { $: 'kv', arg: 'system.keychain.password' } 13 | } 14 | } 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/write/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fn', 7 | arg: async ctx => { 8 | const ports = ctx.readKV(`${ctx.path}.port`); 9 | const oports = ctx.readKV(`${ctx.path}.port`, { original: true }); 10 | const groups = {}; 11 | const ogroups = {}; 12 | for (let p in ports) { 13 | if (ports[p].type === 'static') { 14 | const g = groups[ports[p].group] || (groups[ports[p].group] = []); 15 | g.push(p); 16 | } 17 | else if (oports[p].type === 'static') { 18 | ogroups[ports[p].group] = true; 19 | } 20 | } 21 | for (let g in groups) { 22 | const portids = groups[g].map(p => `portid=${p}`).join('&'); 23 | await ctx.eval('fetch', `/port_trunk_set.cgi?groupId=${g}&${portids}&setapply=Apply`); 24 | } 25 | for (let g in ogroups) { 26 | await ctx.eval('fetch', `/port_trunk_display.cgi?chk_trunk=${g}&setDelete=Delete`); 27 | } 28 | } 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/write/limits.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'foreach', 6 | arg: itr => [{ 7 | limit: { 8 | $: `guard`, 9 | arg: { 10 | $: `fetch`, 11 | arg: `/qos_bandwidth_set.cgi`, 12 | method: 'post', 13 | params: { 14 | igrRate: { 15 | $: 'kv', 16 | arg: `${itr.path}.limit.ingress`, 17 | map: v => v * 8 / 1024 18 | }, 19 | egrRate: { 20 | $: 'kv', 21 | arg: `${itr.path}.limit.egress`, 22 | map: v => v * 8 / 1024 23 | }, 24 | [`sel_${itr.index + 1}`]: 1, 25 | apply: 'Apply' 26 | } 27 | } 28 | } 29 | }] 30 | } 31 | } 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/write/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'guard', 6 | arg: { 7 | $1: { 8 | $: `fetch`, 9 | arg: `/mirror_enabled_set.cgi`, 10 | params: { 11 | state: { 12 | $: `kv`, 13 | arg: 'network.mirror.0.enable', 14 | map: { 15 | true: 1, 16 | false: 0 17 | } 18 | }, 19 | mirroringport: { 20 | $: 'kv', 21 | arg: 'network.mirror.0.target', 22 | map: v => v + 1 23 | }, 24 | mirrorenable: 'Apply' 25 | } 26 | }, 27 | port: { 28 | $: 'foreach', 29 | arg: itr => [{ 30 | $: 'fetch', 31 | arg: '/mirrored_port_set.cgi', 32 | params: { 33 | mirroredport: itr.key + 1, 34 | ingressState: { 35 | $: 'kv', 36 | arg: `${itr.path}.ingress`, 37 | map: { 38 | true: 1, 39 | false: 0 40 | } 41 | }, 42 | egressState: { 43 | $: 'kv', 44 | arg: `${itr.path}.egress`, 45 | map: { 46 | true: 1, 47 | false: 0 48 | } 49 | }, 50 | mirrored_submit: 'Apply' 51 | } 52 | }] 53 | } 54 | } 55 | } 56 | } 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/write/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | name: { 4 | $: `guard`, 5 | arg: { 6 | $: `fetch`, 7 | arg: `/system_name_set.cgi`, 8 | params: { 9 | sysName: { $: `kv` } 10 | } 11 | } 12 | } 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /device/switch/tp-link/tl-sg108e/write/physical.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'foreach', 6 | arg: itr => [{ 7 | $: `guard`, 8 | key : `${itr.path}.enable,${itr.path}.speed,${itr.path}.flowcontrol`, 9 | arg: { 10 | $: `fetch`, 11 | arg: `/port_setting.cgi`, 12 | wait: 1, // Sometimes hangs, so best we only wait for a little while before moving on 13 | params: { 14 | portid: itr.index + 1, 15 | state: { 16 | $: 'kv', 17 | arg: `${itr.path}.enable`, 18 | map: { 19 | true: 1, 20 | false: 0 21 | } 22 | }, 23 | speed: { 24 | $: 'kv', 25 | arg: `${itr.path}.speed`, 26 | map: { 27 | 'auto': 1, 28 | '10M (H)': 2, 29 | '10M': 3, 30 | '100M (H)': 4, 31 | '100M': 5, 32 | '1G': 6 33 | } 34 | }, 35 | flowcontrol: { 36 | $: 'kv', 37 | arg: `${itr.path}.flowcontrol`, 38 | map: { 39 | true: 1, 40 | false: 0 41 | } 42 | }, 43 | apply: 'Apply' 44 | } 45 | } 46 | }] 47 | } 48 | } 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/read/clients.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | clients: { 4 | $: 'oid', 5 | arg: '1.3.6.1.4.1.28866.3.1.5.2.1.1', 6 | values: { 7 | $: 'fn', 8 | arg: ctx => { 9 | const base = ctx.context[1][3][6][1][4][1][28866][3][1][5][2][1][1]; 10 | function f(v) { 11 | const l = []; 12 | function _f(v) { 13 | if (typeof v === 'object') { 14 | for (let k in v) { 15 | _f(v[k]); 16 | } 17 | } 18 | else { 19 | l.push(v); 20 | } 21 | } 22 | _f(v); 23 | return l; 24 | } 25 | const vlans = f(base[1]); 26 | const macs = f(base[2]); 27 | const ports = f(base[3]); 28 | const values = {}; 29 | for (let k in macs) { 30 | values[k] = { 31 | mac: OID.toMacAddress(macs[k]), 32 | vlan: vlans[k], 33 | portnr: ports[k][0] === 'p' ? `lag${ports[k].substring(2)}` : (parseInt(ports[k]) - 1) 34 | }; 35 | } 36 | return values; 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/read/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | snoop: { 5 | $: 'oid', 6 | arg: '1.3.6.1.4.1.28866.3.1.11.2.1.1.0', 7 | map: { 8 | 2: false, 9 | 1: true 10 | } 11 | } 12 | } 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/read/ip.js: -------------------------------------------------------------------------------- 1 | const OID = require("../../../../../OID"); 2 | 3 | module.exports = { 4 | system: { 5 | ipv4$1: { 6 | $: 'oid', 7 | arg: '1.3.6.1.4.1.28866.3.1.16.3', 8 | values: { 9 | mode: { 10 | $: 'jsonp', 11 | arg: '1.3.6.1.4.1.28866.3.1.16.3.1.0', 12 | map: { 13 | 1: 'static', 14 | 2: 'dhcp' 15 | } 16 | }, 17 | address: '1.3.6.1.4.1.28866.3.1.16.3.2.0', 18 | netmask: '1.3.6.1.4.1.28866.3.1.16.3.3.0', 19 | gateway: '1.3.6.1.4.1.28866.3.1.16.3.4.0' 20 | } 21 | }, 22 | ipv4$2: { 23 | dns: { 24 | $: 'oid', 25 | arg: '1.3.6.1.4.1.28866.3.1.28.1.1.0', 26 | map: OID.toIPAddress 27 | } 28 | } 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/read/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | $: 'oid', 5 | arg: '1.3.6.1.4.1.28866.3.1.7.2.1.1', 6 | values: { 7 | $: 'fn', 8 | arg: ctx => { 9 | const map = { 1: 'active', 2: 'passive', 3: 'static', 4: 'none' }; 10 | const nr = 8; 11 | const nrports = 28; 12 | const base = ctx.context[1][3][6][1][4][1][28866][3][1][7][2][1][1]; 13 | const members = base[3]; 14 | const mode = base[2]; 15 | const ports = {}; 16 | for (let j = 0; j < nrports; j++) { 17 | ports[j] = { type: 'none', group: 0 }; 18 | } 19 | for (let i = 0; i < nr; i++) { 20 | const idx = i + nrports + 1; 21 | const type = map[mode[idx]] || 'none'; 22 | if (type !== 'none') { 23 | const p = Buffer.from(members[idx], 'latin1') 24 | for (let j = 0; j < nrports; j++) { 25 | if (p[Math.floor(j / 8)] & (0x80 >> (j % 8))) { 26 | ports[j] = { type: type, group: i + 1 }; 27 | } 28 | } 29 | } 30 | } 31 | return { 32 | types: { 33 | static: nr, 34 | active: nr 35 | }, 36 | port: ports 37 | }; 38 | } 39 | } 40 | } 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/read/limits.js: -------------------------------------------------------------------------------- 1 | const BASE = '1.3.6.1.4.1.28866.3.1.3.1.1'; 2 | 3 | module.exports = { 4 | network: { 5 | physical: { 6 | port: { 7 | $: 'oid', 8 | arg: BASE, 9 | values: { 10 | $: 'iterate', 11 | arg: itr => [{ 12 | limit: { 13 | egress: { 14 | $: null, 15 | arg: `${BASE}.2.${itr.key + 1}`, 16 | map: v => v * 8192 17 | }, 18 | ingress: { 19 | $: null, 20 | arg: `${BASE}.3.${itr.key + 1}`, 21 | map: v => v * 8192 22 | } 23 | } 24 | }] 25 | } 26 | } 27 | } 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/read/mirror.js: -------------------------------------------------------------------------------- 1 | const BASE = '1.3.6.1.4.1.28866.3.1.10'; 2 | 3 | module.exports = { 4 | network: { 5 | mirror: { 6 | 0: { 7 | $: 'oid', 8 | arg: BASE, 9 | values: { 10 | enable: { 11 | $: 'jsonp', 12 | arg: `${BASE}.1.0`, 13 | map: { 14 | 2: false, 15 | 1: true 16 | } 17 | }, 18 | target: { 19 | $: 'jsonp', 20 | arg: `${BASE}.2.0`, 21 | map: v => v - 1 22 | }, 23 | port: { 24 | $: 'fn', 25 | arg: ctx => { 26 | const ports = {}; 27 | const nrports = 28; 28 | const ingress = Buffer.from(ctx.context[1][3][6][1][4][1][28866][3][1][10][3][0], 'latin1'); 29 | const egress = Buffer.from(ctx.context[1][3][6][1][4][1][28866][3][1][10][4][0], 'latin1'); 30 | for (let j = 0; j < nrports; j++) { 31 | const val = {}; 32 | if (ingress[Math.floor(j / 8)] & (0x80 >> (j % 8))) { 33 | val.ingress = true; 34 | } 35 | if (egress[Math.floor(j / 8)] & (0x80 >> (j % 8))) { 36 | val.egress = true; 37 | } 38 | for (const k in val) { 39 | ports[j] = val; 40 | break; 41 | } 42 | } 43 | return ports; 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/read/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | name: { $: 'oid', arg: OID.system.name }, 4 | location: { $: 'oid', arg: OID.system.location }, 5 | contact: { $: 'oid', arg: OID.system.contact }, 6 | firmware: { 7 | version: { $: 'oid', arg: '1.3.6.1.4.1.28866.3.1.16.1.2.0' } 8 | }, 9 | macAddress: { 10 | 0: { 11 | $: 'oid', 12 | arg: '1.3.6.1.4.1.28866.3.1.16.2.1.0', 13 | map: OID.toMacAddress 14 | } 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/read/snmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | snmp: { 4 | enable: { 5 | $: 'fetch', 6 | frame: 'myframe', 7 | arg: '/iss/specific/rpc.js', 8 | method: 'post', 9 | params: { 10 | Gambit: { 11 | $: 'eval', 12 | arg: 'GetInputGambit()' 13 | }, 14 | RPC: { 15 | $: 'tojson', 16 | arg: { 17 | method: 'CommonGet', 18 | id: 0, 19 | params: { 20 | Template: 'snmpGlobal' 21 | } 22 | } 23 | } 24 | }, 25 | type: 'jsonp', 26 | values: { 27 | $: 'jsonp', 28 | arg: `result.snmpGlobalState`, 29 | map: { 30 | 2: false, 31 | 1: true 32 | } 33 | } 34 | } 35 | } 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/read/statistics.js: -------------------------------------------------------------------------------- 1 | const BASE = '1.3.6.1.4.1.28866.3.1.23.1.1'; 2 | 3 | module.exports = { 4 | network: { 5 | physical: { 6 | port: { 7 | $: 'oid', 8 | arg: BASE, 9 | values: { 10 | $: 'iterate', 11 | arg: itr => [{ 12 | statistics: { 13 | rx: { 14 | bytes: `${BASE}.2.${itr.index + 1}`, 15 | unicast: `${BASE}.3.${itr.index + 1}`, 16 | multicast: `${BASE}.4.${itr.index + 1}`, 17 | discarded: `${BASE}.5.${itr.index + 1}`, 18 | errors: `${BASE}.6.${itr.index + 1}`, 19 | undersized: `${BASE}.14.${itr.index + 1}`, 20 | oversized: `${BASE}.15.${itr.index + 1}`, 21 | crc: `${BASE}.13.${itr.index + 1}`, 22 | collisions: `${BASE}.17.${itr.index + 1}`, 23 | drop: `${BASE}.12.${itr.index + 1}`, 24 | fragments: `${BASE}.16.${itr.index + 1}` 25 | }, 26 | tx: { 27 | bytes: `${BASE}.7.${itr.index + 1}`, 28 | unicast: `${BASE}.8.${itr.index + 1}`, 29 | multicast: `${BASE}.9.${itr.index + 1}`, 30 | discarded: `${BASE}.10.${itr.index + 1}`, 31 | errors: `${BASE}.11.${itr.index + 1}`, 32 | } 33 | } 34 | }] 35 | } 36 | } 37 | } 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/write/commit.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | $: 'fetch', 3 | arg: '/iss/specific/rpc.js', 4 | frame: 'myframe', 5 | method: 'post', 6 | params: { 7 | Gambit: { 8 | $: 'eval', 9 | arg: 'GetInputGambit()' 10 | }, 11 | RPC: { 12 | $: 'tojson', 13 | arg: { 14 | method: 'CommonSet', 15 | id: 0, 16 | params: { 17 | Template: 'sysConfig', 18 | configOper: '3' 19 | } 20 | } 21 | } 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/write/dns.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | ipv4: { 4 | dns: { 5 | $: 'guard', 6 | arg: { 7 | $: 'oid+set', 8 | arg: '1.3.6.1.4.1.28866.3.1.28.1.1.0', 9 | map: v => Buffer.from(v.split('.')) 10 | } 11 | } 12 | } 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/write/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | snoop: { 5 | $: 'guard', 6 | arg: { 7 | $: 'oid+set', 8 | arg: '1.3.6.1.4.1.28866.3.1.11.2.1.1.0', 9 | map: { 10 | false: 2, 11 | true: 1 12 | } 13 | } 14 | } 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/write/ip.js: -------------------------------------------------------------------------------- 1 | // 2 | // Note. We cannot set the IP address using OIDs, but we can this way. 3 | // 4 | module.exports = { 5 | system: { 6 | ipv4: { 7 | $: 'guard', 8 | arg: { 9 | $: 'fetch', 10 | arg: '/iss/specific/rpc.js', 11 | frame: 'myframe', 12 | method: 'post', 13 | wait: 1, 14 | params: { 15 | Gambit: { 16 | $: 'eval', 17 | arg: 'GetInputGambit()' 18 | }, 19 | RPC: { 20 | $: 'tojson', 21 | arg: { 22 | method: 'Ipv4Info_Set', 23 | id: 0, 24 | params: { 25 | ipv4sysIpAddrCfgMode: { 26 | $: 'kv', 27 | arg: 'system.ipv4.mode', 28 | map: { 29 | static: 1, 30 | dhcp: 2 31 | } 32 | }, 33 | ipv4sysIpAddr: { $: 'kv', arg: 'system.ipv4.address' }, 34 | ipv4SysIpSubnetMask: { $: 'kv', arg: 'system.ipv4.netmask' }, 35 | ipv4SysGateway: { $: 'kv', arg: 'system.ipv4.gateway' } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/write/ivl.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | vlans: { 4 | ivl: { 5 | $: 'oid+set', 6 | arg: '1.3.6.1.4.1.28866.3.1.25.1.1.0', 7 | map: { 8 | false: 2, 9 | true: 1 10 | } 11 | } 12 | } 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/write/keychain.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | keychain: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/iss/specific/rpc.js', 8 | frame: 'myframe', 9 | method: 'post', 10 | params: { 11 | Gambit: { 12 | $: 'eval', 13 | arg: 'GetInputGambit()' 14 | }, 15 | RPC: { 16 | $: 'tojson', 17 | arg: { 18 | method: 'BatchPost', 19 | id: 0, 20 | params: { 21 | FuncName: 'UserAccountModify', 22 | userName: 'admin', 23 | userPassword: { $: 'kv', arg: 'system.keychain.password' } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/write/limits.js: -------------------------------------------------------------------------------- 1 | const BASE = '1.3.6.1.4.1.28866.3.1.3.1.1'; 2 | 3 | module.exports = { 4 | network: { 5 | physical: { 6 | port: { 7 | $: 'foreach', 8 | arg: itr => [{ 9 | limit: { 10 | egress: { 11 | $: 'guard', 12 | arg: { 13 | $: 'oid+set', 14 | arg: `${BASE}.2.${itr.key + 1}`, 15 | map: v => Math.ceil(v / 8192) 16 | } 17 | }, 18 | ingress: { 19 | $: 'guard', 20 | arg: { 21 | $: 'oid+set', 22 | arg: `${BASE}.3.${itr.key + 1}`, 23 | map: v => Math.ceil(v / 8192) 24 | } 25 | } 26 | } 27 | }] 28 | } 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/write/mirror.js: -------------------------------------------------------------------------------- 1 | const BASE = '1.3.6.1.4.1.28866.3.1.10'; 2 | 3 | module.exports = { 4 | network: { 5 | mirror: { 6 | 0: { 7 | $: 'guard', 8 | arg: { 9 | enable: { 10 | $: 'oid+set', 11 | arg: `${BASE}.1.0`, 12 | map: { 13 | true: 1, 14 | false: 2 15 | } 16 | }, 17 | $1: { 18 | $: 'guard', 19 | key: { $: 'kv', arg: 'network.mirror.0.enable' }, 20 | arg: { 21 | target: { 22 | $: 'oid+set', 23 | arg: `${BASE}.2.0`, 24 | map: v => v + 1 25 | }, 26 | port: { 27 | $: 'fn', 28 | arg: async ctx => { 29 | const ports = ctx.readKV(ctx.path); 30 | const ingress = [ 0, 0, 0, 0 ]; 31 | const egress = [ 0, 0, 0, 0 ]; 32 | for (let p in ports) { 33 | if (ports[p].ingress) { 34 | ingress[Math.floor(p / 8)] |= 0x80 >> (p % 8); 35 | } 36 | if (ports[p].egress) { 37 | egress[Math.floor(p / 8)] |= 0x80 >> (p % 8); 38 | } 39 | } 40 | await ctx.eval({ $: 'oid+set', arg: `${BASE}.3.0`, value: Buffer.from(ingress) }); 41 | await ctx.eval({ $: 'oid+set', arg: `${BASE}.4.0`, value: Buffer.from(egress) }); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/write/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'guard', 4 | key: 'system.name,system.location,system.contact', 5 | arg: { 6 | name: { $: 'oid+set', arg: OID.system.name }, 7 | location: { $: 'oid+set', arg: OID.system.location }, 8 | contact: { $: 'oid+set', arg: OID.system.contact }, 9 | } 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-30284/write/snmp.js: -------------------------------------------------------------------------------- 1 | // 2 | // Note. Used to enable SNMP, so we can't use OIDs here. 3 | // 4 | module.exports = { 5 | system: { 6 | snmp: { 7 | enable: { 8 | $: 'guard', 9 | arg: { 10 | $: 'fetch', 11 | arg: '/iss/specific/rpc.js', 12 | frame: 'myframe', 13 | method: 'post', 14 | params: { 15 | Gambit: { 16 | $: 'eval', 17 | arg: 'GetInputGambit()' 18 | }, 19 | RPC: { 20 | $: 'tojson', 21 | arg: { 22 | method: 'CommonSet', 23 | id: 0, 24 | params: { 25 | Template: 'snmpGlobal', 26 | snmpGlobalState: { 27 | $: 'kv', 28 | arg: 'system.snmp.enable', 29 | map: { 30 | true: 1, 31 | false: 2 32 | } 33 | } 34 | } 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/read/clients.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | clients: { 4 | $: 'fetch', 5 | arg: `/DS/DFT.js`, 6 | values: { 7 | $: 'iterate', 8 | arg: itr => [{ 9 | mac: { $: 'eval', arg: `ds_DFT[${itr.index}][1]`, map: Maps.toMacAddress }, 10 | vlan: `ds_DFT[${itr.index}][2]`, 11 | portnr: `ds_DFT[${itr.index}][0] - 1` 12 | }] 13 | } 14 | } 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/read/hardware.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system$1: { 3 | firmware: { 4 | $: 'fetch', 5 | arg: `/DS/ConfigBlink.js`, 6 | values: { 7 | version: `g_SwitchInfo[1]` 8 | } 9 | } 10 | }, 11 | system$2: { 12 | $: 'fetch', 13 | arg: `/DS/Device.js`, 14 | values: { 15 | macAddress: { 16 | 0: `g_DeviceInfo[2].toLowerCase()` 17 | }, 18 | hardware: { 19 | version: `g_DeviceInfo[0]` 20 | } 21 | } 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/read/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | snoop: { 5 | $: 'fetch', 6 | arg: '/DS/IGMP.js', 7 | values: { $: 'eval', arg: '!!ds_IGMPSEn' } 8 | } 9 | } 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/read/ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | ipv4: { 4 | $: 'fetch', 5 | arg: `/DS/IPv4.js`, 6 | values: { 7 | mode: { 8 | $: 'eval', 9 | arg: `ds_IPInfo[0]`, 10 | map: { 11 | 0: 'static', 12 | 1: 'dhcp' 13 | } 14 | }, 15 | address: `ds_IPInfo[1]`, 16 | netmask: `ds_IPInfo[2]`, 17 | gateway: `ds_IPInfo[3]` 18 | } 19 | } 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/read/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | types: { 5 | static: 2, 6 | active: 0 7 | }, 8 | port: { 9 | $: 'fetch', 10 | arg: '/DS/Trunking.js', 11 | values: { 12 | $: 'fn', 13 | arg: async ctx => { 14 | const list = JSON.parse(await ctx.eval('eval', 'JSON.stringify(ds_TrunkList)')); 15 | const ports = {}; 16 | for (let i = 0; i < list[0].length; i++) { 17 | if (list[0][i] == '1') { 18 | ports[i] = { type: 'static', group: 1 }; 19 | } 20 | else if (list[1][i] == '1') { 21 | ports[i] = { type: 'static', group: 2 }; 22 | } 23 | else { 24 | ports[i] = { type: 'none' }; 25 | } 26 | } 27 | return ports; 28 | } 29 | } 30 | } 31 | } 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/read/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'fetch', 6 | arg: '/DS/Mirror.js', 7 | values: { 8 | enable: `!!ds_MirrorEn`, 9 | target: `ds_MirrTag - 1`, 10 | port: { 11 | $: 'fn', 12 | arg: async ctx => { 13 | const en = await ctx.eval({ $: 'eval', arg: 'ds_MirrorEn' }); 14 | const src = await ctx.eval({ $: 'eval', arg: 'ds_MirrSrc '}); 15 | const ports = {}; 16 | const port = {}; 17 | if (en === 1 || en === 3) { 18 | port.ingress = true; 19 | } 20 | if (en === 2 || en === 3) { 21 | port.egress = true; 22 | } 23 | for (let i = 0; i < src.length; i++) { 24 | if (src[i] === '1') { 25 | ports[i] = port; 26 | } 27 | } 28 | return ports; 29 | } 30 | } 31 | } 32 | } 33 | } 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/read/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'fetch', 4 | arg: `/DS/sys.js`, 5 | values: { 6 | name: `ds_SysInfo[0]`, 7 | location: `ds_SysInfo[1]`, 8 | contact: `ds_SysInfo[2]` 9 | } 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/read/snmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | snmp: { 4 | $: 'fetch', 5 | arg: '/DS/SNMP_Global.js', 6 | values: { 7 | enable: '!!ds_Snmp[0]' 8 | } 9 | } 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/read/statistics.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'fetch', 6 | arg: `/DS/Statistics.js`, 7 | values: { 8 | $: 'iterate', 9 | arg: itr => [{ 10 | statistics: { 11 | rx: { 12 | packets: `ds_Statistics[${itr.index}][1]`, 13 | errors: `ds_Statistics[${itr.index}][3]` 14 | }, 15 | tx: { 16 | packets: `ds_Statistics[${itr.index}][0]`, 17 | errors: `ds_Statistics[${itr.index}][2]` 18 | } 19 | } 20 | }] 21 | } 22 | } 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/read/vlan.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | vlans$1: { 4 | ivl: { 5 | $: 'fetch', 6 | arg: '/DS/AsyVlan.js', 7 | values: { 8 | $: 'eval', 9 | arg: '!ds_AsyVlanEn' 10 | } 11 | } 12 | }, 13 | vlans$2: { 14 | $: 'fetch', 15 | arg: `/DS/QVLAN.js`, 16 | values: { 17 | vlan: { 18 | $: 'iterate', 19 | arg: itr => [ 20 | `ds_QVLANList[${itr.index}][0]`, 21 | { 22 | name: `ds_QVLANList[${itr.index}][1]`, 23 | management: `ds_QVLANList[${itr.index}][0] == ds_MgtVID`, 24 | port: { 25 | $: `eval`, 26 | arg: `ds_QVLANList[${itr.index}][2]`, 27 | map: ports => { 28 | const r = {}; 29 | for (let p = 0; p < ports.length; p++) { 30 | switch (ports[p]) { 31 | case 'U': 32 | r[p] = { tagged: false }; 33 | break; 34 | case 'T': 35 | r[p] = { tagged: true }; 36 | break; 37 | case '0': 38 | default: 39 | break; 40 | } 41 | } 42 | return r; 43 | } 44 | } 45 | } 46 | ] 47 | }, 48 | pvid: { 49 | $: 'iterate', 50 | arg: itr => [{ 51 | pvid: `ds_PVID[${itr.index}]` 52 | }] 53 | } 54 | } 55 | } 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/write/commit.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | $: 'fetch', 3 | arg: '/cgi/save.cgi', 4 | method: 'post' 5 | }; 6 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/write/igmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | igmp: { 4 | snoop: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/cgi/IGMPSNState.cgi', 9 | method: 'post', 10 | params: { 11 | IGS: { 12 | $: 'kv', 13 | map: { 14 | true: 1, 15 | false: 0 16 | } 17 | } 18 | } 19 | } 20 | } 21 | } 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/write/ip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | ipv4: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/cgi/set_ip.cgi', 8 | method: 'post', 9 | params: { 10 | ip: { $: 'kv', arg: 'system.ipv4.address' }, 11 | submask: { $: 'kv', arg: 'system.ipv4.netmask' }, 12 | gateway: { $: 'kv', arg: 'system.ipv4.gateway' }, 13 | dhcp: { 14 | $: 'kv', 15 | arg: 'system.ipv4.mode', 16 | map: { 17 | static: '0', 18 | dhcp: '1' 19 | } 20 | }, 21 | dhcptm: '7' 22 | } 23 | } 24 | } 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/write/keychain.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | keychain: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fetch', 7 | arg: '/cgi/changing_pw.cgi', 8 | method: 'post', 9 | params: { 10 | old_pass: { $: 'kv', arg: 'system.keychain.password', options: { original: true } }, 11 | new_pass: { $: 'kv', arg: 'system.keychain.password' }, 12 | renew_pass: { $: 'kv', arg: 'system.keychain.password' } 13 | } 14 | } 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/write/lag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | lags: { 4 | $: 'guard', 5 | arg: { 6 | $: 'fn', 7 | arg: async ctx => { 8 | const ports = ctx.readKV(`${ctx.path}.port`); 9 | const groups = [[ 0, 0, 0, 0, 0, 0, 0, 0 ],[ 0, 0, 0, 0, 0, 0, 0, 0 ]]; 10 | for (let p in ports) { 11 | if (ports[p].type === 'static') { 12 | groups[port[p].group - 1][p] = 1; 13 | } 14 | } 15 | await ctx.eval({ 16 | $: 'fetch', 17 | arg: '/cgi/TrunkingStatus.cgi', 18 | method: 'post', 19 | params: { 20 | enabled_flag: 1 21 | } 22 | }); 23 | for (let i = 0; i < groups.length; i++) { 24 | const members = groups[i].join(''); 25 | if (members === '00000000') { 26 | await ctx.eval({ 27 | $: 'fetch', 28 | arg: '/cgi/TrunkingDelMems.cgi', 29 | method: 'post', 30 | params: { 31 | Group: i + 1, 32 | GroupMember: '' 33 | } 34 | }); 35 | } 36 | else { 37 | await ctx.eval({ 38 | $: 'fetch', 39 | arg: '/cgi/TrunkingSetting.cgi', 40 | method: 'post', 41 | params: { 42 | Group: i + 1, 43 | GroupMember: members 44 | } 45 | }); 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/write/mirror.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | mirror: { 4 | 0: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/cgi/PortMirroring.cgi', 9 | method: 'post', 10 | params: { 11 | $: 'fn', 12 | arg: async ctx => { 13 | const mirror = ctx.readKV(ctx.path); 14 | if (!mirror.enable) { 15 | return { 16 | cEn: 0, 17 | sMode: 0, 18 | sTagP: 1, 19 | SrcList: '' 20 | } 21 | } 22 | const ports = '00000000'; 23 | let mode = 0; 24 | for (let p in mirror.port) { 25 | if (mirror.port[p].ingress) { 26 | ports[p] = 1; 27 | mode |= 1; 28 | } 29 | if (mirror.port[p].egress) { 30 | ports[p] = 1; 31 | mode |= 2; 32 | } 33 | } 34 | return { 35 | cEn: 1, 36 | sMode: mode ? mode - 1 : 0, 37 | sTagP: mirror.target + 1, 38 | SrcList: ports 39 | }; 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/write/name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | $: 'guard', 4 | arg: { 5 | $: 'fetch', 6 | arg: '/cgi/set_sys.cgi', 7 | method: 'post', 8 | params: { 9 | sys: { $: 'kv', arg: 'system.name' }, 10 | loc: { $: 'kv', arg: 'system.location' }, 11 | con: { $: 'kv', arg: 'system.contact' } 12 | } 13 | } 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/write/physical.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | network: { 3 | physical: { 4 | port: { 5 | $: 'foreach', 6 | arg: itr => [{ 7 | $: 'guard', 8 | arg: { 9 | $: 'fetch', 10 | arg: '/cgi/set_port.cgi', 11 | method: 'post', 12 | params: { 13 | port_f: itr.index + 1, 14 | port_t: itr.index + 1, 15 | stats: { $: 'kv', arg: `${itr.path}.enable`, map: { true: 1, false: 0 } }, 16 | speed: { 17 | $: 'kv', 18 | arg: `${itr.path}.speed`, 19 | map: { 20 | 'auto': 0, 21 | '10M (H)': 1, 22 | '10M': 2, 23 | '100M (H)': 3, 24 | '100M': 4, 25 | '1G': 5 26 | } 27 | }, 28 | flow: { $: 'kv', arg: `${itr.path}.flowcontrol`, map: { true: 1, false: 0 } }, 29 | desc: { $: 'kv', arg: `${itr.path}.name` } 30 | } 31 | } 32 | }] 33 | } 34 | } 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /device/switch/trendnet/teg-s80es/write/snmp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | system: { 3 | snmp: { 4 | enable: { 5 | $: 'guard', 6 | arg: { 7 | $: 'fetch', 8 | arg: '/cgi/snmp_global.cgi', 9 | method: 'post', 10 | params: { 11 | item: '00000', 12 | Trap: 0, 13 | Snmp: { 14 | $: 'kv', 15 | map: { 16 | true: 1, 17 | false: 0 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | services: 3 | minkenet: 4 | container_name: minkenet 5 | image: registry.minkebox.net/minkebox/minkenet 6 | volumes: 7 | - ${DB-db}:/app/db 8 | network_mode: "host" 9 | cap_add: 10 | - NET_ADMIN 11 | environment: 12 | - DEBUG=${DEBUG-} 13 | shm_size: 256M 14 | volumes: 15 | db: 16 | -------------------------------------------------------------------------------- /docs/supported-devices.txt: -------------------------------------------------------------------------------- 1 | See: https://docs.google.com/spreadsheets/d/1IRWM9tUPkBWphhKQYXIbKk8vsFlKSJIeVVGTNb8R0LM/edit?usp=sharing 2 | -------------------------------------------------------------------------------- /minkebox/skeleton: -------------------------------------------------------------------------------- 1 | { 2 | name: `MinkeNet`, 3 | description: `Manage and monitor cheap network equipment just like it was the expensive stuff.`, 4 | uuid: `6BD1A75A-8DC2-4F11-AFDC-6E537E83E32B`, 5 | image: `registry.minkebox.net/minkebox/minkenet`, 6 | tags: [ 7 | `Monitoring`, 8 | `Networking` 9 | ], 10 | actions: [ 11 | ], 12 | properties: [ 13 | { 14 | type: `Feature`, 15 | name: `+NET_ADMIN` 16 | }, 17 | { 18 | type: `Feature`, 19 | name: `shm`, 20 | value: `512` 21 | }, 22 | { 23 | type: `Environment`, 24 | name: `DEBUG`, 25 | value: `` 26 | }, 27 | { 28 | type: `Network`, 29 | name: `primary`, 30 | value: `host` 31 | }, 32 | { 33 | type: `Directory`, 34 | name: `/app/db`, 35 | backup: true 36 | }, 37 | { 38 | type: `Port`, 39 | name: `8080/tcp`, 40 | port: 8080, 41 | protocol: `TCP`, 42 | web: { 43 | path: `/`, 44 | tab: `newtab` 45 | } 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /monitors/SpeedTest.js: -------------------------------------------------------------------------------- 1 | const EventEmitter = require('events'); 2 | const SpeedTestNet = require('speedtest-net'); 3 | const ConfigDB = require('../Config'); 4 | const Log = require('debug')('speedtest'); 5 | 6 | const SPEEDTEST_TIMER = 60 * 60 * 1000; // 1 hour 7 | 8 | class SpeedTest extends EventEmitter { 9 | 10 | start() { 11 | this.last = null; 12 | ConfigDB.on('update', evt => { 13 | if (evt.key === 'monitor.wan.speedtest.enabled') { 14 | this.enable(evt.value); 15 | } 16 | }); 17 | this.enable(ConfigDB.read('monitor.wan.speedtest.enabled')); 18 | } 19 | 20 | enable(yes) { 21 | if (yes) { 22 | if (!this._speedtest) { 23 | this.last = null; 24 | this._speedtest = setInterval(() => this._run(), SPEEDTEST_TIMER); 25 | this._run(); 26 | } 27 | } 28 | else { 29 | if (this._speedtest) { 30 | clearInterval(this._speedtest); 31 | this.last = null; 32 | this._speedtest = null; 33 | } 34 | } 35 | } 36 | 37 | getWanSpeed() { 38 | if (!this.last) { 39 | return null; 40 | } 41 | return { 42 | latency: this.last.ping.latency, 43 | upload: this.last.upload.bandwidth, 44 | download: this.last.download.bandwidth 45 | }; 46 | } 47 | 48 | _run() { 49 | SpeedTestNet({ 50 | acceptLicense: true, 51 | acceptGdpr: true, 52 | serverId: ConfigDB.read('monitor.wan.speedtest.id') 53 | }).then(result => { 54 | this.last = result; 55 | this.emit('update'); 56 | }).catch(err => { 57 | Log(err); 58 | }); 59 | } 60 | 61 | } 62 | 63 | module.exports = new SpeedTest(); 64 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "minkenet", 3 | "description": "MinkeNet", 4 | "license": "BSD-3-Clause", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://gitlab.com/minkebox/minkenet.git" 8 | }, 9 | "dependencies": { 10 | "bootstrap": "^4.5.3", 11 | "debug": "^4.3.1", 12 | "devextreme": "^20.2.4", 13 | "dns-packet": "^5.2.1", 14 | "fast-glob": "^3.2.4", 15 | "handlebars": "^4.7.6", 16 | "jquery": "^3.5.1", 17 | "jsonpath-plus": "^4.0.0", 18 | "koa": "^2.13.0", 19 | "koa-cache-control": "^2.0.0", 20 | "koa-router": "^10.0.0", 21 | "koa-websocket": "^6.0.0", 22 | "macaddress": "^0.5.1", 23 | "nanotimer": "^0.3.15", 24 | "nedb": "^1.8.0", 25 | "net-snmp": "^2.10.0", 26 | "node-mndp": "git+https://github.com/patagonaa/node-mndp.git", 27 | "oui": "^11.0.58", 28 | "pcap": "git+https://github.com/aanon4/node_pcap.git", 29 | "popper.js": "^1.16.1", 30 | "puppeteer": "^8.0.0", 31 | "sortablejs": "^1.13.0", 32 | "speedtest-net": "^2.2.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /pages/CRButtons.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /pages/Capture/Full/Arp.html: -------------------------------------------------------------------------------- 1 |
Analyze the connections between the various switches, routers and access points in your Network 6 | to determine how they are interconnected. This information is used to visualize your 7 | network as well as help build vlans and other network structures which span devices. 8 |
9 |10 | This process injects traffic into your network. For best results analyse a quieter network, and avoid 11 | accessing your device UIs. 12 |
' 13 | update_id='topology-update' 14 | primary='Begin' 15 | primary_active='Running...' 16 | secondary='Cancel' 17 | event='topology.analyze' 18 | primary_event='start' 19 | secondary_event='stop' 20 | }} 21 | -------------------------------------------------------------------------------- /pages/Link/TopologyStatus.html: -------------------------------------------------------------------------------- 1 | {{#if (eq op 'connecting')}} 2 | Connecting to devices 3 | {{else if (eq op 'baseline')}} 4 | {{#if (eq attempt 0)}} 5 | Establishing network baseline 6 | {{else}} 7 | Re-establishing network baseline 8 | {{/if}} 9 | {{else if (eq op 'probe')}} 10 | {{#if (eq attempt 0)}} 11 | Analyzing {{device.properties.system.ipv4.address.$}} {{device.name}} 12 | {{else}} 13 | Analyzing ({{attempt}}) {{device.properties.system.ipv4.address.$}} {{device.name}} 14 | {{/if}} 15 | {{else if (eq op 'probes-complete')}} 16 | {{else if (eq op 'analyzing')}} 17 | Analyzing network 18 | {{else if (eq op 'complete')}} 19 | {{#if success}} 20 | Success 21 | {{else}} 22 | 23 | {{#if (eq reason 'canceled')}} 24 | {{else if (eq reason 'connecting')}} 25 | Failed to connect to one or more devices 26 | {{else if (eq reason 'baseline')}} 27 | Failed to collect baseline network data from devices. Make sure nothing else is accessing your devices during this test. 28 | {{else if (eq reason 'probes')}} 29 | Failed probing for one or more devices. This can happen randoming when some device will suddenly stops responding for a few seconds 30 | or because something else is accessing a device. 31 | {{else if (eq reason 'busy')}} 32 | Network is too busy to successfully analyze 33 | {{else if (eq reason 'topology')}} 34 | Successfully probed network but failed to determine network topology. 35 | {{else}} 36 | Unknown failure 37 | {{/if}} 38 | 39 | {{/if}} 40 | {{/if}} 41 | -------------------------------------------------------------------------------- /pages/Modal1.html: -------------------------------------------------------------------------------- 1 |