From f3b58f6d3633040ab7e02c3ec2a38f924bc3ed02 Mon Sep 17 00:00:00 2001 From: cos Date: Fri, 23 Feb 2018 15:03:11 +0100 Subject: Initial commit. --- LICENSE | 29 +++++++++++++++ README.md | 36 +++++++++++++++++++ hisgle.go | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 hisgle.go diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ba49ae1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +Copyright (c) 2018 Martin Samuelsson. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the + distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e5c41b3 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +There are two kinds of people in this world. Those who use just one single +smartphone for all their information technology needs, and those who suddenly +find themselves with more devices than they can keep track of without having +information about them written down somewhere. + +If you are anything like me, sharing home with a couple of actively used +laptops, several smartphones, document and label printers, physical servers, +virtual servers and IoT things doing all kinds of weirdness, then just maybe +hisgle might be helpful to you too. + +I've implemented hisgle (Host Inventory Script, Go Learning Experience) having +no less than 131 devices with individual mac addresses. Remembering exactly +where all of them were networkwise was becoming a challenge, so I put them all +in a database with the following structure: + + CREATE TABLE devices (name, mac, interface); + CREATE TABLE addresses (mac, vlan, ipv4); + CREATE TABLE aliases (alias, target); + CREATE TABLE networks (vlan, description TEXT, ipv4); + +Invoking hisgle generates ethers and hosts files which can be read directly by +dnsmasq on e.g. OpenWRT routers. + +A typical command line would be: + + hisgle --database=/somewhere/devices.db hosts 4 5 104 + +Above line would generate a hosts file for vlan:s 4, 5 and 104. You might want +to create a script which generates, copies and reloads hosts and ethers files +for all your routers. That's what the script I run whenever updating my list +of devices does. + +Wanting to try using the Go language for a something helped giving a name to +this script. This is the first time I attempt writing something at all in Go. +I'm sure there are heaps of things which could be improved, but I'm happy for +now with a script which does what I need. diff --git a/hisgle.go b/hisgle.go new file mode 100644 index 0000000..2ef755a --- /dev/null +++ b/hisgle.go @@ -0,0 +1,122 @@ +package main + +import ( "fmt" + "log" + "os" + "strconv" ) + +// http://go-database-sql.org/importing.html +// _ "github.com/mattn/go-sqlite3" +// _ "code.google.com/p/gosqlite/sqlite3" +import ( + "database/sql" + _ "github.com/mxk/go-sqlite/sqlite3" + "github.com/pborman/getopt" +) + +func ethers(db *sql.DB, vlan int) { + var ( + mac string + ipv4 string + ) + +//CREATE TABLE devices (name, mac, interface); +//CREATE TABLE addresses (mac, vlan, ipv4); + + rows, err := db.Query("SELECT mac, ipv4 FROM addresses WHERE vlan=?", vlan) + if err != nil { + log.Fatal(err) + } + for rows.Next() { + err := rows.Scan(&mac, &ipv4) + if err != nil { + log.Fatal(err) + } + fmt.Println(mac, " ", ipv4) + } +} + +func hosts(db *sql.DB, vlan int) { + var ( + ipv4 string + name string + alias string + ) + +//CREATE TABLE devices (name, mac, interface); +//CREATE TABLE addresses (mac, vlan, ipv4); + + rows, err := db.Query("SELECT a.ipv4, d.name FROM addresses AS a JOIN devices AS d ON a.mac=d.mac WHERE vlan=?", vlan) + if err != nil { + log.Fatal(err) + } + for rows.Next() { + err := rows.Scan(&ipv4, &name) + if err != nil { + log.Fatal(err) + } + fmt.Print(ipv4, "\t", name) + +// CREATE TABLE aliases (alias, target); + rows, err := db.Query("SELECT alias FROM aliases WHERE target=?", name) + if err != nil { + log.Fatal(err) + } + for rows.Next() { + err := rows.Scan(&alias) + if err != nil { + log.Fatal(err) + } + fmt.Print(" ", alias) + } + fmt.Println() + } +} + +func main() { + var ( + description string + ipv4 string + ) + + optDatabase := getopt.StringLong("database", 'd', "", "Path to SQLite3 database file with device addresses") + optHelp := getopt.BoolLong("help", 0, "Help") + getopt.SetParameters("{ethers|hosts} list_of_networks") + getopt.Parse() + + if *optHelp { + getopt.Usage() + os.Exit(0) + } + args := getopt.Args() + + db, err := sql.Open("sqlite3", *optDatabase) + if err != nil { + log.Fatal(err) + } + + for _, arg := range args[1:] { + vlan, _ := strconv.Atoi(arg) + rows, err := db.Query("SELECT description, ipv4 FROM networks WHERE vlan=?", vlan) + if err != nil { + log.Fatal(err) + } + for rows.Next() { + err := rows.Scan(&description, &ipv4) + if err != nil { + log.Fatal(err) + } + fmt.Print("\n# ", description, ", ", ipv4, "\n") + fmt.Println("# vlan:", vlan) + switch args[0] { + case "ethers": + ethers(db, vlan) + case "hosts": + hosts(db, vlan) + default: + os.Exit(1) + } + } + } + defer db.Close() +} -- cgit v1.2.3