diff --git a/config-respondd_example.toml b/config-respondd_example.toml index 32a3314..2c25c71 100644 --- a/config-respondd_example.toml +++ b/config-respondd_example.toml @@ -1,15 +1,26 @@ # how ofter the cache respond of a respondd request is calculated data_interval = "3m" -# if set true, respond will contain data from batman interface -multi_instance = false +interfaces = [ "wlp4s0" ] [[listen]] -address = "ff02::2:1001" +address = "ff02::2:1001" interface = "" -port = 1001 +port = 1001 -# manuelle data for respond -[data.nodeinfo.location] -latitude = 53.112446246 +[defaults] +node_id = "" +hostname = "" +site_code = "ffhb" +domain_code = "" +vpn = false + +[defaults.location] +latitude = 53.112446246 longitude = 8.734087944 + + +# if divergent configuration of defaults are wanted by respond on interface/zones example with bat0 +[zones.bat0] +node_id = "" +hostname = "" diff --git a/respond/daemon/config.go b/respond/daemon/config.go new file mode 100644 index 0000000..227bfa2 --- /dev/null +++ b/respond/daemon/config.go @@ -0,0 +1,53 @@ +package respondd + +import ( + "io/ioutil" + "strings" + + "github.com/FreifunkBremen/yanic/data" + "github.com/FreifunkBremen/yanic/lib/duration" +) + +func trim(s string) string { + return strings.TrimSpace(strings.Trim(s, "\n")) +} + +type Daemon struct { + DataInterval duration.Duration `toml:"data_interval"` + Listen []struct { + Address string `toml:"address"` + Interface string `toml:"interface"` + Port int `toml:"port"` + } `toml:"listen"` + InterfacesBatman []string `toml:"interfaces_batman"` + Interfaces []string `toml:"interfaces"` + + dataByInterface map[string]*data.ResponseData + + Answer *AnswerConfig `toml:"defaults"` + AnswerByZones map[string]*AnswerConfig `toml:"zones"` +} + +type AnswerConfig struct { + NodeID string `toml:"node_id"` + Hostname string `toml:"hostname"` + SiteCode string `toml:"site_code"` + DomainCode string `toml:"domain_code"` + Location *data.Location `json:"location,omitempty"` + VPN bool `toml:"vpn"` +} + +func (d *Daemon) getAnswer(iface string) (*AnswerConfig, string) { + config := d.Answer + if v, ok := d.AnswerByZones[iface]; iface == "" && ok { + config = v + } + + nodeID := config.NodeID + if nodeID == "" { + if v, err := ioutil.ReadFile("/etc/machine-id"); err == nil { + nodeID = trim(string(v))[:12] + } + } + return config, nodeID +} diff --git a/respond/daemon/data.go b/respond/daemon/data.go index e04f465..51b1ef3 100644 --- a/respond/daemon/data.go +++ b/respond/daemon/data.go @@ -1,63 +1,29 @@ package respondd import ( - "io/ioutil" - "os" - "strings" - "github.com/FreifunkBremen/yanic/data" ) -func trim(s string) string { - return strings.TrimSpace(strings.Trim(s, "\n")) -} - func (d *Daemon) updateData() { - nodeID := "" - // Nodeinfo - if d.Data.Nodeinfo == nil { - d.Data.Nodeinfo = &data.Nodeinfo{} - } else { - nodeID = d.Data.Nodeinfo.NodeID - } - if d.Data.Nodeinfo.Hostname == "" { - d.Data.Nodeinfo.Hostname, _ = os.Hostname() - } - - // Statistics - if d.Data.Statistics == nil { - d.Data.Statistics = &data.Statistics{} - } else if nodeID == "" { - nodeID = d.Data.Statistics.NodeID - } - - // Neighbours - if d.Data.Neighbours == nil { - d.Data.Neighbours = &data.Neighbours{} - } else if nodeID == "" { - nodeID = d.Data.Neighbours.NodeID - } - - if nodeID == "" && !d.MultiInstance { - if v, err := ioutil.ReadFile("/etc/machine-id"); err == nil { - nodeID = trim(string(v))[:12] + for iface, iData := range d.dataByInterface { + if iData.Nodeinfo == nil { + iData.Nodeinfo = &data.Nodeinfo{} } - } - d.Data.Nodeinfo.NodeID = nodeID - d.Data.Statistics.NodeID = nodeID - d.Data.Neighbours.NodeID = nodeID - - for _, data := range d.dataByInterface { - data.Nodeinfo = d.Data.Nodeinfo + if iData.Statistics == nil { + iData.Statistics = &data.Statistics{} + } + if iData.Neighbours == nil { + iData.Neighbours = &data.Neighbours{} + } + d.updateNodeinfo(iface, iData) + d.updateStatistics(iface, iData) + d.updateNeighbours(iface, iData) } } func (d *Daemon) getData(iface string) *data.ResponseData { - if !d.MultiInstance { - return d.Data - } - if data, ok := d.dataByInterface[iface]; ok { - return data + if iData, ok := d.dataByInterface[iface]; ok { + return iData } d.dataByInterface[iface] = &data.ResponseData{} d.updateData() diff --git a/respond/daemon/main.go b/respond/daemon/main.go index 2acd29b..b9a4048 100644 --- a/respond/daemon/main.go +++ b/respond/daemon/main.go @@ -7,24 +7,12 @@ import ( "github.com/bdlm/log" "github.com/FreifunkBremen/yanic/data" - "github.com/FreifunkBremen/yanic/lib/duration" ) -type Daemon struct { - MultiInstance bool `toml:"multi_instance"` - DataInterval duration.Duration `toml:"data_interval"` - Listen []struct { - Address string `toml:"address"` - Interface string `toml:"interface"` - Port int `toml:"port"` - } `toml:"listen"` - Data *data.ResponseData `toml:"data"` - dataByInterface map[string]*data.ResponseData -} - func (d *Daemon) Start() { - if d.Data == nil { - d.Data = &data.ResponseData{} + d.dataByInterface = make(map[string]*data.ResponseData) + if d.AnswerByZones == nil { + d.AnswerByZones = make(map[string]*AnswerConfig) } d.updateData() diff --git a/respond/daemon/neighbours.go b/respond/daemon/neighbours.go new file mode 100644 index 0000000..b9344b0 --- /dev/null +++ b/respond/daemon/neighbours.go @@ -0,0 +1,10 @@ +package respondd + +import ( + "github.com/FreifunkBremen/yanic/data" +) + +func (d *Daemon) updateNeighbours(iface string, data *data.ResponseData) { + _, nodeID := d.getAnswer(iface) + data.Neighbours.NodeID = nodeID +} diff --git a/respond/daemon/nodeinfo.go b/respond/daemon/nodeinfo.go new file mode 100644 index 0000000..b1546b6 --- /dev/null +++ b/respond/daemon/nodeinfo.go @@ -0,0 +1,69 @@ +package respondd + +import ( + "fmt" + "os" + "runtime" + "net" + + "github.com/FreifunkBremen/yanic/data" +) + +func (d *Daemon) updateNodeinfo(iface string, data *data.ResponseData) { + config, nodeID := d.getAnswer(iface) + data.Nodeinfo.NodeID = nodeID + + if config.Hostname == "" { + data.Nodeinfo.Hostname, _ = os.Hostname() + } else { + data.Nodeinfo.Hostname = config.Hostname + } + + data.Nodeinfo.VPN = config.VPN + data.Nodeinfo.Location = config.Location + + data.Nodeinfo.System.SiteCode = config.SiteCode + data.Nodeinfo.System.DomainCode = config.DomainCode + + data.Nodeinfo.Hardware.Nproc = runtime.NumCPU() + + if data.Nodeinfo.Network.Mac == "" { + data.Nodeinfo.Network.Mac = fmt.Sprintf("%s:%s:%s:%s:%s:%s", nodeID[0:2], nodeID[2:4], nodeID[4:6], nodeID[6:8], nodeID[8:10], nodeID[10:12]) + } + + if iface == "" { + data.Nodeinfo.Network.Addresses = []string{} + for _, i := range d.Interfaces { + addrs := getAddresses(i) + data.Nodeinfo.Network.Addresses = append(data.Nodeinfo.Network.Addresses, addrs...) + } + } else { + data.Nodeinfo.Network.Addresses = getAddresses(iface) + } +} + +func getAddresses(iface string) (addrs []string) { + in, err := net.InterfaceByName(iface) + if err != nil { + return + } + inAddrs, err := in.Addrs() + if err != nil { + return + } + for _, a := range inAddrs { + var ip net.IP + switch v := a.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + default: + continue + } + if ip4 := ip.To4(); ip4 == nil { + addrs = append(addrs, ip.String()) + } + } + return +} diff --git a/respond/daemon/statistics.go b/respond/daemon/statistics.go new file mode 100644 index 0000000..0796980 --- /dev/null +++ b/respond/daemon/statistics.go @@ -0,0 +1,15 @@ +package respondd + +import ( + "github.com/shirou/gopsutil/host" + + "github.com/FreifunkBremen/yanic/data" +) + +func (d *Daemon) updateStatistics(iface string, data *data.ResponseData) { + _, nodeID := d.getAnswer(iface) + data.Statistics.NodeID = nodeID + if uptime, err := host.Uptime(); err == nil { + data.Statistics.Uptime = float64(uptime) + } +}