{josuah.net} | {panoramix-labs.fr} (DIR) • {josuah.net} (DIR) • {panoramix-labs.fr} {git} | {cv} | {links} | {quotes} | {ascii} | {tgtimes} | {gopher} | {mail} (DIR) • {git} (BIN) • {cv} (DIR) • {links} (DIR) • {quotes} (DIR) • {ascii} (HTM) • {tgtimes} (DIR) • {gopher} ━━━━━━ netini ━━━━━━ (TXT) `git://git.josuah.net/netini` - {0.4} (IMG) {{network graph generated by netini}} Network layer topology in red, physical connexions in grey. What is it for? ─────────────── Plotting networks is extremely useful for understanding how it works and troubleshoot problems. Particularly when you do not know the network in advance. In theory, from an access to that place's router and switches, using arp tables and mac address tables, you can guess some of the L1/L2/L3 topology. netini is a toolset doing this: build network graph out of simple declarative config files, and generate config files out of raw command output from routers and switches. How to use it? ────────────── (DIR) The {netini-dot(1)} tool generating the plots is reading a trivial .ini format from all files passed as argument: Example for a network named `sky`: ┊ [net] ┊ name = skynet-wan-knet ┊ ip = 92.118.99.140/30 ┊ ┊ [net] ┊ name = skynet-lan-user ┊ ip = 10.191.10.0/23 ┊ vlan = 10 ┊ ┊ [net] ┊ name = skynet-lan-server ┊ ip = 10.191.20.0/24 ┊ vlan = 20 ┊ ┊ [net] ┊ name = skynet-lan-admin ┊ ip = 10.191.30.0/24 ┊ vlan = 20 ┊ ┊ [host] ┊ name = skynet-modem-knet-1 ┊ ip = 92.118.99.141 ┊ ┊ [host] ┊ name = skynet-router-1 ┊ ip = 92.118.99.142 ┊ ip = 10.191.10.1 ┊ ip = 10.191.20.1 ┊ ip = 10.191.30.1 ┊ ┊ [host] ┊ name = skynet-switch-1 ┊ ip = 10.191.30.2 ┊ link = skynet-router-1 ┊ link = 0c:1c:20:69:d8:d8 ┊ link = 08:4a:cf:e6:d0:08 ┊ link = e8:5b:5b:b1:5d:db ┊ link = 5c:d2:e4:1b:1e:ee ┊ ┊ [host] ┊ name = skynet-switch-2 ┊ ip = 10.191.30.2 ┊ link = skynet-router-1 ┊ link = 00:c0:a3:91:9d:e2 ┊ link = 48:9d:24:c9:f8:79 ┊ link = f4:32:3d:40:c6:18 ┊ link = 84:18:26:bd:88:2d ┊ ┊ [host] ┊ name = skynet-workstation-1 ┊ ip = 10.191.10.1 ┊ link = 0c:1c:20:69:d8:d8 ┊ ┊ [host] ┊ name = skynet-workstation-2 ┊ ip = 10.191.10.1 ┊ link = 08:4a:cf:e6:d0:08 ┊ ... All hosts with IPs that fit a network are linked automatically to it on the plot. `link=` variables in hosts permit to build L1 links by using a hostname, a MAC address or an IP as value. Any other detail might be added, and will be shown on the item label. Other tools are available to generate parts of these configuration files from command output coming from local hosts or routers. How is the matching done? ───────────────────────── Connecting hosts to networks is done by defining a network with subnet, and adding IPs that belong to that network to the hosts. The classic IP matching algorythm does the wiring job on its own. This means that autogenerated output can For link-layer, the `link=` entries of hosts bind them to other hosts. What does it looks like in practice? ──────────────────────────────────── From this from `arp -a` (or `ip neigh show` on Linux, randomly generated here): ┊ 10.191.10.130 dev wlan0 lladdr 0c:1c:20:69:d8:d8 ref 1 used 0/0/0 probes 6 REACHABLE ┊ 10.191.10.65 dev wlan0 lladdr 08:4a:cf:e6:d0:08 ref 1 used 0/0/0 probes 6 REACHABLE ┊ 10.191.10.28 dev wlan0 lladdr e8:5b:5b:b1:5d:db ref 1 used 0/0/0 probes 6 REACHABLE ┊ 10.191.10.85 dev wlan0 lladdr 08:00:33:00:b7:2e ref 1 used 0/0/0 probes 6 REACHABLE ┊ 10.191.11.239 dev wlan0 lladdr 5c:d2:e4:1b:1e:ee ref 1 used 0/0/0 probes 6 REACHABLE ┊ 10.191.11.105 dev wlan0 lladdr 74:6e:e4:71:05:25 ref 1 used 0/0/0 probes 6 REACHABLE ┊ 10.191.20.36 dev wlan0 lladdr 68:d4:82:66:29:7b ref 1 used 0/0/0 probes 6 REACHABLE ┊ 10.191.20.247 dev wlan0 lladdr ac:19:9f:03:6c:f2 ref 1 used 0/0/0 probes 6 REACHABLE ┊ 10.191.20.113 dev wlan0 lladdr 00:c0:a3:91:9d:e2 ref 1 used 0/0/0 probes 6 REACHABLE ┊ 10.191.20.178 dev wlan0 lladdr 48:9d:24:c9:f8:79 ref 1 used 0/0/0 probes 6 REACHABLE ┊ 10.191.20.11 dev wlan0 lladdr f4:32:3d:40:c6:18 ref 1 used 0/0/0 probes 6 REACHABLE ┊ 10.191.20.31 dev wlan0 lladdr 84:18:26:bd:88:2d ref 1 used 0/0/0 probes 6 REACHABLE `netini-arp linux skynet` turns it into this: ┊ [host] ┊ name = skynet-Kakao-1 ┊ ip = 10.191.10.130 ┊ mac = 0c:1c:20:69:d8:d8 ┊ ┊ [host] ┊ name = skynet-Kakao-2 ┊ ip = 10.191.10.65 ┊ mac = 0c:1c:20:69:d8:d9 ┊ ┊ [host] ┊ name = skynet-LgElectronics-1 ┊ ip = 10.191.10.28 ┊ mac = e8:5b:5b:b1:5d:db ┊ ┊ [host] ┊ name = skynet-BauschAndLomb-1 ┊ ip = 10.191.10.85 ┊ mac = 08:00:33:00:b7:2e ┊ ┊ [host] ┊ name = skynet-IntelOrate-1 ┊ ip = 10.191.11.239 ┊ mac = 5c:d2:e4:1b:1e:ee ┊ ┊ [host] ┊ name = skynet-AsiaVitalMponents-1 ┊ ip = 10.191.11.105 ┊ mac = 74:6e:e4:71:05:25 ┊ ┊ [host] ┊ name = skynet-ShenzhenGongjinElectronics-1 ┊ ip = 10.191.20.36 ┊ mac = 68:d4:82:66:29:7b ┊ ┊ [host] ┊ name = skynet-SungrowPowerSupply-1 ┊ ip = 10.191.20.247 ┊ mac = ac:19:9f:03:6c:f2 ┊ ┊ [host] ┊ name = skynet-DualEnterprises-1 ┊ ip = 10.191.20.113 ┊ mac = 00:c0:a3:91:9d:e2 ┊ ┊ [host] ┊ name = skynet-BlackberryRts-1 ┊ ip = 10.191.20.178 ┊ mac = 48:9d:24:c9:f8:79 ┊ ┊ [host] ┊ name = skynet-SichuanTianyiKangheMmunications-1 ┊ ip = 10.191.20.11 ┊ mac = f4:32:3d:40:c6:18 ┊ ┊ [host] ┊ name = skynet-Osram-1 ┊ ip = 10.191.20.31 ┊ mac = 84:18:26:bd:88:2d `netini-dot` turns it into this: ┊ graph G { ┊ { "skynet-Kakao-1" [shape=rectangle; label="skynet-Kakao-1\nip 10.191.10.130\nmac 0c:1c:20:69:d8:d8\n"] } ┊ { "skynet-GuangdongOppoMobileTelecommunications-1" [shape=rectangle; label="skynet-GuangdongOppoMobileTelecommunications-1\nip 10.191.10.65\nmac 08:4a:cf:e6:d0:08\n"] } ┊ { "skynet-LgElectronics-1" [shape=rectangle; label="skynet-LgElectronics-1\nip 10.191.10.28\nmac e8:5b:5b:b1:5d:db\n"] } ┊ { "skynet-BauschAndLomb-1" [shape=rectangle; label="skynet-BauschAndLomb-1\nip 10.191.10.85\nmac 08:00:33:00:b7:2e\n"] } ┊ { "skynet-IntelOrate-1" [shape=rectangle; label="skynet-IntelOrate-1\nip 10.191.11.239\nmac 5c:d2:e4:1b:1e:ee\n"] } ┊ { "skynet-AsiaVitalMponents-1" [shape=rectangle; label="skynet-AsiaVitalMponents-1\nip 10.191.11.105\nmac 74:6e:e4:71:05:25\n"] } ┊ { "skynet-ShenzhenGongjinElectronics-1" [shape=rectangle; label="skynet-ShenzhenGongjinElectronics-1\nip 10.191.20.36\nmac 68:d4:82:66:29:7b\n"] } ┊ { "skynet-SungrowPowerSupply-1" [shape=rectangle; label="skynet-SungrowPowerSupply-1\nip 10.191.20.247\nmac ac:19:9f:03:6c:f2\n"] } ┊ { "skynet-DualEnterprises-1" [shape=rectangle; label="skynet-DualEnterprises-1\nip 10.191.20.113\nmac 00:c0:a3:91:9d:e2\n"] } ┊ { "skynet-BlackberryRts-1" [shape=rectangle; label="skynet-BlackberryRts-1\nip 10.191.20.178\nmac 48:9d:24:c9:f8:79\n"] } ┊ { "skynet-SichuanTianyiKangheMmunications-1" [shape=rectangle; label="skynet-SichuanTianyiKangheMmunications-1\nip 10.191.20.11\nmac f4:32:3d:40:c6:18\n"] } ┊ { "skynet-Osram-1" [shape=rectangle; label="skynet-Osram-1\nip 10.191.20.31\nmac 84:18:26:bd:88:2d\n"] } ┊ } (HTM) Finally plotted by {graphviz}. Note that extra data can be added at each step, and `netini-merge` lets one have manual entries that override the autogenerated ones. How did you get these device brand names out of numbers? ──────────────────────────────────────────────────────── Each MAC address has its 6 first bytes ("OUI") associated to a manufacturer, so the `netini-oui` tool downloads the definition a [`oui.csv`(http://standards-oui.ieee.org/oui/oui.csv) from IANA to resolve the OUI identifiers. The heuristics comes from a WireShark python script. More features? ────────────── Mail me your suggestions as a request or as a patch.