Network Mapper v2.0 instructions
Almquist Shell Script written for POSIX systems like OpenWRT, Linux and WSL2/WSLg
---------------------------------------
Dependencies
---------------------------------------
This was written in the Almquist Shell (ASH) scripting language for OpenWRT devices, but has been tested to run on Ubuntu on WSLg (which runs Bourne Again Shell, or Bash).
Further information on the Almquist Shell can be found at:
https://en.wikipedia.org/wiki/Almquist_shell
https://www.in-ulm.de/~mascheck/various/ash/
The graphical front-end that you see in yuor browser is rendered by the D3 Javascript Visualizer by Mike Bostock and Observable, Inc., which you can grab here:
https://d3js.org/d3.v7.js
or in minified form here:
https://d3js.org/d3.v7.min.js
Well, okay, it also relies on the fact that that your device (computer, router, whatever) has its TCP/IP stack installed, obviously. But aside from needing TCP/IP, the Almquist Shell and D3... yeah, this is all self-contained!
---------------------------------------
Installation
---------------------------------------
On OpenWRT, place networkmap.sh, update_all.sh, get_ipv6.sh and get_dhcp.sh in /www/cgi-bin/ and your networkmap.js, networkmap.json and networkmap.html in /www/. Keep this readme file safe.
In the archive:
├── readme.txt (this very file)
├── d3.v7.js
├── d3.v7.min.js
├── networkmap.js
├── networkmap.json
├── networkmap.html
└── /cgi-bin/
├── networkmap.sh
├── update_all.sh
├── get_dhcp.sh
└── get_ipv6.sh
Folder Structure of involved files:
user-provided/generated:
/etc
└── config
└── dhcp
/tmp
├── dhcp.leases
└── hosts
└── odhcpd
Provided by this package:
/www
├── d3.v7.js
├── d3.v7.min.js
├── get_dhcp.sh
├── get_ipv6.sh
├── networkmap.js
├── networkmap.json
├── networkmap-topology.json
├── networkmap.html
└── cgi-bin
└── networkmap.sh
I've also included two tools, get_dhcp.sh and get_ipv6.sh to help with determining addresses. Unless you made them yourself, networkmap.json and networkmap-topology.json won't exist yet, as it has to be compiled from your network information. Don't panic if networkmap.json isn't initially compiled, either, as the section below will detail how to generate or make your own!
---------------------------------------
How to run this prorgam
---------------------------------------
Step 1:
ensure you have a copy of your router's /tmp/dhcp.leases file at YOUR computer's /tmp/dhcp.leases
You may also need:
/tmp/hosts/odhcpd
/tmp/ipv6list
/tmp/mac_ipv4_map
/tmp/mac_ipv6_map
as well as the output of:
ip neigh show
ip -6 neigh show
and for wifi clients/repeater stations and information:
iw dev phy0-ap0 station dump
iw dev phy1-ap0 station dump
NOTE: Your router's wifi interface may be named differently depending on your hardware and software (OpenWRT version, drivers, and so on), such as wlan0, or radio0.
These instrucitons also assume you have iw and wpad available instead of hostapd_cli. I'm sure hostapd_cli works just fine but I have not tested it with that, as i have wpad and iw instead.
This program's shell script (networkmap.sh) should be run in /www/cgi-bin/ on OpenWRT, with chmod of +x (executable) from terminal/ssh. It can also run elsewhere on linux machines, just ensure that /etc/config/dhcp and /tmp/dhcp.leases exist.
Step 2:
run this program:
sh +x networkmapper.sh
Step 3:
if it complains about no networkmap.json or networkmap-topology file (or generates an empty one), don't panic! just make a networkmap-topology.json file with these contents as an example:
```
{
"links": [
{ "source": "YourRouter", "target": "YourRepeaterRouter1" },
{ "source": "YourRepeaterRouter1", "target": "Device0OnRepeater1" },
{ "source": "YourRepeaterRouter1", "target": "Device1OnRepeater1" },
{ "source": "YourRouter", "target": "YourRepeaterRouter2" },
{ "source": "YourRepeaterRouter2", "target": "Device0OnRepeater2" },
{ "source": "YourRepeaterRouter2", "target": "Device1OnRepeater2" },
{ "source": "YourRouter", "target": "YourLaptop" },
{ "source": "YourRouter", "target": "YourPC" },
{ "source": "YourRouter", "target": "YourTablet" },
{ "source": "YourRouter", "target": "YourTV" },
{ "source": "YourRouter", "target": "YourGameConsole" },
{ "source": "YourRouter", "target": "YourPhone" },
{ "source": "YourRouter", "target": "YourNetPrinter" },
{ "source": "YourRouter", "target": "YourNetCam" },
{ "source": "YourRouter", "target": "YourNRaspberryPi" },
{ "source": "YourRouter", "target": "YourVM" },
{ "source": "YourRouter", "target": "YourModem" },
],
"nodes": [
{
"id": "YourRouter",
"ip": "192.168.1.1",
"type": "router",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "AA:BB:CC:DD:EE:FF",
"ipv6": [] },
{
"id": "YourRepeaterRouter1",
"ip": "192.168.1.2",
"type": "router",
"connection": "ethernet",
"online": true, "lastSeen": 0,
"mac": "",
"ipv6": []
},
{
"id": "YourRepeaterRouter2",
"ip": "192.168.1.3",
"type": "switch",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": []
},
{
"id": "Device0OnRepeater1",
"ip": "192.168.1.100",
"type": "pc",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": []
},
{
"id": "Device1OnRepeater1",
"ip": "192.168.1.101",
"type": "pc",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": []
},
{
"id": "Device0OnRepeater2",
"ip": "192.168.1.200",
"type": "pc",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": [] },
{
"id": "Device1OnRepeater2",
"ip": "192.168.1.201",
"type": "pc",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": [] },
{
"id": "YourPC",
"ip": "192.168.1.11",
"type": "pc",
"connection": "ethernet",
"online": true, "lastSeen": 0,
"mac": "",
"ipv6": []
},
{
"id": "YourTablet",
"ip": "192.168.1.12",
"type": "tablet",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": []
},
{
"id":"YourPC",
"ip":"192.168.1.11",
"type":"pc",
"connection":"wifi",
"online":true,
"lastSeen":1768628101,
"mac":"11:22:33:44:55:66",
"ipv6":[]
},
{
"id": "YourGameConsole",
"ip": "192.168.1.14",
"type": "console",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": []
},
{
"id": "YourPhone",
"ip": "192.168.1.15",
"type": "phone",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": []
},
{
"id": "YourNetCam",
"ip": "192.168.1.16",
"type": "camera",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": []
},
{
"id": "YourNetPrinter",
"ip": "192.168.17.",
"type": printer",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": []
},
{
"id": "YourRaspberryPi",
"ip": "192.168.18.",
"type": iot",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "AA:BB:CC:DD:EE:FF",
"ipv6": []
},
{
"id": "YourVM",
"ip": "192.168.1.99",
"type": "vm",
"connection": "wifi",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": []
},
{
"id": "YourModem",
"ip": "192.168.100.1",
"type": "modem",
"connection": "ethernet",
"online": true,
"lastSeen": 0,
"mac": "",
"ipv6": []
}
]
}
```
NOTE: YOU really should change these values (names, IP addresses, and so on) to match whatever items are in your router's DHCP configuration. OpenWRT stores these in /etc/config/dhcp in all the cases i've seen.
You can daisy-chain things along like Router -> Repeater -> Device by telling them their relationship in the links section.
In Version 1, the IPv6 addresses must be seperated via
, otherwise the addresses will be on a single line.
like this:
"ipv6":["2001:1970:aaaa:bbbb:54eb:cccc:dddd:1234","fe80::1234:5678:fe08:90ab","fd38:1234:5678:0:90ab:cdef:abcd:ab12","2001:1970:dead:beef:cafe:1234:5678:abcd"]
and if you had multiple and wnated them on seperate likes, you hadwrite them like THIS:
"ipv6": ["2001:1970::1"
fe80::feed:face:dead:beef
fd38:i5ee:cafe::1"]
but now, V2 supports BOTH methods! I also changed up the json in this case to be a bit more vertical to be easier to read by human eyes, instead of being on a single long line, but both are notationally identical to JSON parsers.
The trade-off is that you MUST make the networkmap-topology.json file to show your network's node relations to each other, so the computer can then determine the best star map for it.
basically:
networkma[-topology.js is the user-defined relations file. This is how you tell the script "this computer is connected to the router this way, this computer is connected to the main router through THIS repeater, and the repeater is connected to the router THIS way...
networkmap.json is the fully-fleshed out network map that the computer sorts and organizes from that information, adding MAC, IPv4, IPv6 addresses and so on.
Where do you get he MAC, IPv4 and IPv6 information?
well... you can get them via the get_dhcp.sh and get_ipv6.sh. as a bonus, those also list the mac addresses of the other machines listed!
While you still have to manually put them into networkmap-topology.json (it will render networkmap.json for you after you run sh /www/cgi-bin/networkmap.sh), it sure beats running these commands:
```
ip neigh show
ip -6 neigh show
iw dev phy0-ap0 station dump
iw dev phy1-ap0 station dump
```
and then inserting the code manually from those! at least get_dhcp.sh and get_ipv6.sh give you very clean, human-readable text!
Step 4:
run this program:
sh +x networkmapper.sh again to generate the networkmap.json file from networkmap-topology.json file.
Step 5:
Inspect networkmap.html to ensure both networkmap.js and d3.v7.js (or d3.v7.min.js) are present in the header, such as via
```