Server: monitor dnsmasq, create events for DHCP lease trigger, fix teelogger

This commit is contained in:
MaMe82
2018-10-26 11:41:24 +02:00
parent c05452c459
commit b15be2bf8f
6 changed files with 236 additions and 136 deletions

View File

@@ -178,7 +178,7 @@ func ConstructEventTrigger(triggerType common_web.EvtTriggerType) *pb.Event {
} }
} }
func ConstructEventTriggerDHCPLease(iface, mac, ip string) *pb.Event { func ConstructEventTriggerDHCPLease(iface, mac, ip string, hostname string) *pb.Event {
return &pb.Event{ return &pb.Event{
Type: common_web.EVT_TRIGGER, Type: common_web.EVT_TRIGGER,
Values: []*pb.EventValue{ Values: []*pb.EventValue{
@@ -186,6 +186,7 @@ func ConstructEventTriggerDHCPLease(iface, mac, ip string) *pb.Event {
{Val: &pb.EventValue_Tstring{Tstring: iface}}, {Val: &pb.EventValue_Tstring{Tstring: iface}},
{Val: &pb.EventValue_Tstring{Tstring: mac}}, {Val: &pb.EventValue_Tstring{Tstring: mac}},
{Val: &pb.EventValue_Tstring{Tstring: ip}}, {Val: &pb.EventValue_Tstring{Tstring: ip}},
{Val: &pb.EventValue_Tstring{Tstring: hostname}},
}, },
} }
} }

View File

@@ -1,24 +1,27 @@
package service package service
import ( import (
"errors"
"fmt"
//"github.com/docker/libcontainer/netlink" //"github.com/docker/libcontainer/netlink"
"github.com/mame82/P4wnP1_go/netlink" "github.com/mame82/P4wnP1_go/netlink"
"net"
"log"
"io/ioutil"
"os"
"fmt"
pb "github.com/mame82/P4wnP1_go/proto" pb "github.com/mame82/P4wnP1_go/proto"
"errors" "github.com/mame82/P4wnP1_go/service/util"
"io/ioutil"
"log"
"net"
"os"
"os/exec"
"sync"
) )
var ( var (
ErrUnmanagedInterface = errors.New("Not a managed network interface") ErrUnmanagedInterface = errors.New("Not a managed network interface")
) )
func NewNetworkManager() (nm *NetworkManager, err error){ func NewNetworkManager(rootService *Service) (nm *NetworkManager, err error){
nm = &NetworkManager{ nm = &NetworkManager{
rootSvc: rootService,
ManagedInterfaces: make(map[string]*NetworkInterfaceManager), ManagedInterfaces: make(map[string]*NetworkInterfaceManager),
} }
@@ -42,10 +45,11 @@ func NewNetworkManager() (nm *NetworkManager, err error){
type NetworkManager struct { type NetworkManager struct {
ManagedInterfaces map[string]*NetworkInterfaceManager ManagedInterfaces map[string]*NetworkInterfaceManager
rootSvc *Service
} }
func (nm *NetworkManager) AddManagedInterface(startupConfig *pb.EthernetInterfaceSettings) (err error) { func (nm *NetworkManager) AddManagedInterface(startupConfig *pb.EthernetInterfaceSettings) (err error) {
nim,err := NewNetworkInterfaceManager(startupConfig.Name, startupConfig) nim,err := NewNetworkInterfaceManager(nm, startupConfig.Name, startupConfig)
if err != nil { return err } if err != nil { return err }
nm.ManagedInterfaces[startupConfig.Name] = nim nm.ManagedInterfaces[startupConfig.Name] = nim
return return
@@ -78,14 +82,41 @@ type NetworkInterfaceState struct {
// ToDo: interface watcher (up/down --> auto redeploy) // ToDo: interface watcher (up/down --> auto redeploy)
type NetworkInterfaceManager struct { type NetworkInterfaceManager struct {
nm *NetworkManager
InterfaceName string InterfaceName string
state *NetworkInterfaceState state *NetworkInterfaceState
CmdDnsmasq *exec.Cmd
mutexDnsmasq *sync.Mutex
LoggerDnsmasq *util.TeeLogger
leaseMonitor *dnsmasqLeaseMonitor
} }
func (nim *NetworkInterfaceManager) GetState() (res *NetworkInterfaceState) { func (nim *NetworkInterfaceManager) GetState() (res *NetworkInterfaceState) {
return nim.state return nim.state
} }
func (nim *NetworkInterfaceManager) OnHandedOutDhcpLease(lease *DhcpLease) {
fmt.Printf("Lease monitor %s LEASE: %v\n", nim.InterfaceName, lease)
// should never happen (dnsmasq output parsing error otherwise)
if nim.InterfaceName != lease.Iface {
fmt.Println("Interface of handed out DHCP lease doesn't match managed interface, ignoring ...")
return
}
//generate trigger event
nim.nm.rootSvc.SubSysEvent.Emit(ConstructEventTriggerDHCPLease(lease.Iface, lease.Mac.String(), lease.Ip.String(), lease.Host))
}
func (nim *NetworkInterfaceManager) OnReceivedDhcpRelease(release *DhcpLease) {
fmt.Printf("Lease monitor %s RELEASE: %v\n", nim.InterfaceName, release)
// should never happen (dnsmasq output parsing error otherwise)
if nim.InterfaceName != release.Iface {
fmt.Println("Interface for received DHCP release doesn't match managed interface, ignoring ...")
return
}
}
func (nim *NetworkInterfaceManager) ReDeploy() (err error) { func (nim *NetworkInterfaceManager) ReDeploy() (err error) {
/* /*
if settings, existing := ServiceState.StoredNetworkSettings[ifName]; existing { if settings, existing := ServiceState.StoredNetworkSettings[ifName]; existing {
@@ -110,10 +141,8 @@ func (nim *NetworkInterfaceManager) DeploySettings(settings *pb.EthernetInterfac
} }
//stop DHCP server / client if still running //stop DHCP server / client if still running
running, _, err := IsDHCPServerRunning(settings.Name) nim.StopDHCPServer()
if (err == nil) && running {StopDHCPServer(settings.Name)} nim.StopDHCPClient()
running, _, err = IsDHCPClientRunning(settings.Name)
if (err == nil) && running {StopDHCPClient(settings.Name)}
switch settings.Mode { switch settings.Mode {
case pb.EthernetInterfaceSettings_MANUAL: case pb.EthernetInterfaceSettings_MANUAL:
@@ -172,7 +201,7 @@ func (nim *NetworkInterfaceManager) DeploySettings(settings *pb.EthernetInterfac
err = DHCPCreateConfigFile(settings.DhcpServerSettings, confName) err = DHCPCreateConfigFile(settings.DhcpServerSettings, confName)
if err != nil {return err} if err != nil {return err}
//stop already running DHCPServers for the interface //stop already running DHCPServers for the interface
StopDHCPServer(ifName) nim.StopDHCPServer()
//special case: if the interface name is USB_ETHERNET_BRIDGE_NAME, we delete the old lease file //special case: if the interface name is USB_ETHERNET_BRIDGE_NAME, we delete the old lease file
// the flushing of still running leases is needed, as after USB reinit, RNDIS hosts aren't guaranteed to // the flushing of still running leases is needed, as after USB reinit, RNDIS hosts aren't guaranteed to
@@ -189,7 +218,7 @@ func (nim *NetworkInterfaceManager) DeploySettings(settings *pb.EthernetInterfac
} }
//start the DHCP server //start the DHCP server
err = StartDHCPServer(ifName, confName) err = nim.StartDHCPServer(confName)
if err != nil {return err} if err != nil {return err}
} else { } else {
log.Printf("Setting Interface %s to DOWN\n", iface.Name) log.Printf("Setting Interface %s to DOWN\n", iface.Name)
@@ -206,7 +235,7 @@ func (nim *NetworkInterfaceManager) DeploySettings(settings *pb.EthernetInterfac
err = netlink.NetworkSetMulticast(iface, true) err = netlink.NetworkSetMulticast(iface, true)
if err != nil { return err } if err != nil { return err }
StartDHCPClient(settings.Name) nim.StartDHCPClient()
} else { } else {
log.Printf("Setting Interface %s to DOWN\n", iface.Name) log.Printf("Setting Interface %s to DOWN\n", iface.Name)
err = netlink.NetworkLinkDown(iface) err = netlink.NetworkLinkDown(iface)
@@ -224,40 +253,23 @@ func (nim *NetworkInterfaceManager) DeploySettings(settings *pb.EthernetInterfac
return nil return nil
} }
func NewNetworkInterfaceManager(ifaceName string, startupSettings *pb.EthernetInterfaceSettings) (nim *NetworkInterfaceManager, err error) { func NewNetworkInterfaceManager(nm *NetworkManager, ifaceName string, startupSettings *pb.EthernetInterfaceSettings) (nim *NetworkInterfaceManager, err error) {
nim = &NetworkInterfaceManager{ nim = &NetworkInterfaceManager{
nm: nm,
InterfaceName: ifaceName, InterfaceName: ifaceName,
state: &NetworkInterfaceState{}, state: &NetworkInterfaceState{},
mutexDnsmasq: &sync.Mutex{},
LoggerDnsmasq: util.NewTeeLogger(false),
} }
nim.leaseMonitor = NewDnsmasqLeaseMonitor(nim)
//nim.LoggerDnsmasq.SetPrefix("dnsmasq-" + ifaceName + ": ")
nim.LoggerDnsmasq.AddOutput(nim.leaseMonitor)
nim.state.CurrentSettings = startupSettings nim.state.CurrentSettings = startupSettings
nim.ReDeploy() nim.ReDeploy()
// Deploy startup configuration, to have an initial, defined state
/*
// Startup settings (always DHCP client, Interface up)
nim.state.CurrentSettings = &pb.EthernetInterfaceSettings{
Name: ifaceName,
Mode: pb.EthernetInterfaceSettings_DHCP_CLIENT,
Enabled: true,
SettingsInUse: true,
DhcpServerSettings: &pb.DHCPServerSettings{
CallbackScript: "",
DoNotBindInterface: false,
LeaseFile: nameLeaseFileDHCPSrv(ifaceName),
ListenInterface: ifaceName,
ListenPort: 0,
NotAuthoritative: false,
Options: map[uint32]string{
3: "",
6: "",
},
Ranges: []*pb.DHCPServerRange{},
StaticHosts: []*pb.DHCPServerStaticHost{},
},
}
*/
return return
} }

View File

@@ -3,17 +3,22 @@
package service package service
import ( import (
pb "github.com/mame82/P4wnP1_go/proto" "bufio"
"bytes"
"errors"
"fmt" "fmt"
"github.com/mame82/P4wnP1_go/common_web"
pb "github.com/mame82/P4wnP1_go/proto"
"io/ioutil" "io/ioutil"
"log"
"net"
"os" "os"
"os/exec" "os/exec"
"log" "regexp"
"errors"
"strconv" "strconv"
"syscall"
"strings" "strings"
"github.com/mame82/P4wnP1_go/common_web" "syscall"
"time"
) )
/* /*
@@ -35,14 +40,13 @@ func leaseFileDHCPSrv(s *pb.DHCPServerSettings) (lf string) {
return common_web.NameLeaseFileDHCPSrv(s.ListenInterface) //default lease file return common_web.NameLeaseFileDHCPSrv(s.ListenInterface) //default lease file
} }
func NameConfigFileDHCPSrv(nameIface string) string { func NameConfigFileDHCPSrv(nameIface string) string {
return fmt.Sprintf("/tmp/dnsmasq_%s.conf", nameIface) return fmt.Sprintf("/tmp/dnsmasq_%s.conf", nameIface)
} }
func StartDHCPClient(nameIface string) (err error) { func (nim *NetworkInterfaceManager) StartDHCPClient() (err error) {
nameIface := nim.InterfaceName
log.Printf("Starting DHCP client for interface '%s'...\n", nameIface) log.Printf("Starting DHCP client for interface '%s'...\n", nameIface)
//check if interface is valid //check if interface is valid
@@ -65,7 +69,8 @@ func StartDHCPClient(nameIface string) (err error) {
return nil return nil
} }
func IsDHCPClientRunning(nameIface string) (running bool, pid int, err error) { func (nim *NetworkInterfaceManager) IsDHCPClientRunning() (running bool, pid int, err error) {
nameIface := nim.InterfaceName
if_exists,_ := CheckInterfaceExistence(nameIface) if_exists,_ := CheckInterfaceExistence(nameIface)
if !if_exists { if !if_exists {
return false, 0, errors.New(fmt.Sprintf("The given interface '%s' doesn't exist", nameIface)) return false, 0, errors.New(fmt.Sprintf("The given interface '%s' doesn't exist", nameIface))
@@ -102,8 +107,9 @@ func IsDHCPClientRunning(nameIface string) (running bool, pid int, err error) {
} }
func StopDHCPClient(nameIface string) (err error) { func (nim *NetworkInterfaceManager) StopDHCPClient() (err error) {
log.Printf("Stoping DHCP client for interface '%s'...\n", nameIface) nameIface := nim.InterfaceName
log.Printf("Stopping DHCP client for interface '%s'...\n", nameIface)
//check if interface is valid //check if interface is valid
if_exists,_ := CheckInterfaceExistence(nameIface) if_exists,_ := CheckInterfaceExistence(nameIface)
@@ -125,10 +131,20 @@ func StopDHCPClient(nameIface string) (err error) {
return nil return nil
} }
func (nim *NetworkInterfaceManager) StartDHCPServer(configPath string) (err error) {
nim.mutexDnsmasq.Lock()
defer nim.mutexDnsmasq.Unlock()
//stop dnsmasq if already running
if nim.CmdDnsmasq != nil {
// avoid deadlock
nim.mutexDnsmasq.Unlock()
nim.StopDHCPServer()
nim.mutexDnsmasq.Lock()
}
func StartDHCPServer(nameIface string, configPath string) (err error) { nameIface := nim.InterfaceName
log.Printf("Starting DHCP server for interface '%s' with config '%s'...\n", nameIface, configPath) log.Printf("Starting dnsmasq for interface '%s' with config '%s'...\n", nameIface, configPath)
//check if interface is valid //check if interface is valid
if_exists,_ := CheckInterfaceExistence(nameIface) if_exists,_ := CheckInterfaceExistence(nameIface)
@@ -136,91 +152,46 @@ func StartDHCPServer(nameIface string, configPath string) (err error) {
return errors.New(fmt.Sprintf("The given interface '%s' doesn't exist", nameIface)) return errors.New(fmt.Sprintf("The given interface '%s' doesn't exist", nameIface))
} }
//Check if there's already a DHCP server running for the given interface
running, _, err := IsDHCPServerRunning(nameIface)
if err != nil { return errors.New(fmt.Sprintf("Error fetching state of DHCP server: %v\n", err)) }
if running {return errors.New(fmt.Sprintf("Error starting DHCP server for interface '%s', there is already a DHCP server running\n", nameIface))}
//We use the run command and allow dnsmasq to daemonize nim.CmdDnsmasq = exec.Command("/usr/sbin/dnsmasq", "--log-facility=-", "-k", "-x", pidFileDHCPSrv(nameIface), "-C", configPath)
proc := exec.Command("/usr/sbin/dnsmasq", "-x", pidFileDHCPSrv(nameIface), "-C", configPath) nim.CmdDnsmasq.Stdout = nim.LoggerDnsmasq.LogWriter
//dnsmasq_out, err := proc.CombinedOutput() nim.CmdDnsmasq.Stderr = nim.LoggerDnsmasq.LogWriter
err = proc.Run()
if err != nil { return err}
//fmt.Printf("Dnsmasq out %s\n", dnsmasq_out) err = nim.CmdDnsmasq.Start()
if err != nil {
nim.CmdDnsmasq.Wait()
return errors.New(fmt.Sprintf("Error starting dnsmasq '%v'", err))
}
log.Printf("... DHCP server for interface '%s' started\n", nameIface) log.Printf("... DHCP server for interface '%s' started\n", nameIface)
return nil return nil
} }
func (nim *NetworkInterfaceManager) StopDHCPServer() (err error) {
eSuccess := fmt.Sprintf("... dnsmasq for interface '%s' stopped", nim.InterfaceName)
eCantStop := fmt.Sprintf("... couldn't terminate dnsmasq for interface '%s'", nim.InterfaceName)
func IsDHCPServerRunning(nameIface string) (running bool, pid int, err error) { log.Println("... killing dnsmasq")
if_exists,_ := CheckInterfaceExistence(nameIface) nim.mutexDnsmasq.Lock()
if !if_exists { defer nim.mutexDnsmasq.Unlock()
return false, 0, errors.New(fmt.Sprintf("The given interface '%s' doesn't exist", nameIface))
if nim.CmdDnsmasq == nil {
log.Printf("... dnsmasq for interface '%s' isn't running, no need to stop it\n", nim.InterfaceName)
return nil
} }
pid_file := pidFileDHCPSrv(nameIface) err = ProcSoftKill(nim.CmdDnsmasq, time.Second)
if err != nil { return errors.New(eCantStop) }
//Check if the pidFile exists
if _, err := os.Stat(pid_file); os.IsNotExist(err) {
return false, 0,nil //file doesn't exist, so we assume dnsmasq isn't running
}
//File exists, read the PID nim.CmdDnsmasq = nil
content, err := ioutil.ReadFile(pid_file) log.Println(eSuccess)
if err != nil { return false, 0, err}
pid, err = strconv.Atoi(strings.TrimSuffix(string(content), "\n"))
if err != nil { return false, 0, errors.New(fmt.Sprintf("Error parsing PID file %s: %v", pid_file, err))}
//With PID given, check if the process is indeed running (pid_file could stay, even if the dnsmasq process has died already)
err_kill := syscall.Kill(pid, 0) //sig 0: doesn't send a signal, but error checking is still performed
switch err_kill{
case nil:
//ToDo: Check if the running process image is indeed dnsmasq
return true, pid, nil //Process is running
case syscall.ESRCH:
//Process doesn't exist
return false, pid, nil
case syscall.EPERM:
//process exists, but we have no access permission
return true, pid, err_kill
default:
return false, pid, err_kill
}
}
func StopDHCPServer(nameIface string) (err error) {
//don't check if interface is valid, to allow closing of orphaned DHCP procs (interface went down while running)
log.Printf("Stopping DHCP server for interface '%s' ...\n", nameIface)
running,pid,err := IsDHCPServerRunning(nameIface)
if err != nil { return }
if running {
//send SIGTERM
err = syscall.Kill(pid, syscall.SIGTERM)
if err != nil { return }
} else {
log.Printf("... DHCP server for interface '%s' wasn't started\n", nameIface)
}
running,pid,err = IsDHCPServerRunning(nameIface)
if err != nil { return }
if (running) {
log.Printf("... couldn't terminate DHCP server for interface '%s'\n", nameIface)
} else {
log.Printf("... DHCP server for interface '%s' stopped\n", nameIface)
}
//Delete PID file
os.Remove(pidFileDHCPSrv(nameIface))
//Deleting leaseFile
os.Remove(common_web.NameLeaseFileDHCPSrv(nameIface))
return nil return nil
} }
func DHCPCreateConfigFile(s *pb.DHCPServerSettings, filename string) (err error) { func DHCPCreateConfigFile(s *pb.DHCPServerSettings, filename string) (err error) {
file_content, err := DHCPCreateConfigFileString(s) file_content, err := DHCPCreateConfigFileString(s)
if err != nil {return} if err != nil {return}
@@ -245,12 +216,19 @@ func DHCPCreateConfigFileString(s *pb.DHCPServerSettings) (config string, err er
//Iterate over Ranges //Iterate over Ranges
for _, pRange := range s.Ranges { for _, pRange := range s.Ranges {
//ToDo: regex check for leaseTime //ToDo: regex check for leaseTime
/*
If the lease time is
given, then leases will be given for that length of time. The
lease time is in seconds, or minutes (eg 45m) or hours (eg 1h)
or "infinite". If not given, the default lease time is one
hour. The minimum lease time is two minutes
*/
//ToDo: check rangeLower + rangeUpper to be valid IP addresses //ToDo: check rangeLower + rangeUpper to be valid IP addresses
if len(pRange.LeaseTime) > 0 { if len(pRange.LeaseTime) > 0 {
config += fmt.Sprintf("dhcp-range=%s,%s,%s\n", pRange.RangeLower, pRange.RangeUpper, pRange.LeaseTime) config += fmt.Sprintf("dhcp-range=%s,%s,%s\n", pRange.RangeLower, pRange.RangeUpper, pRange.LeaseTime)
} else { } else {
//default to 5 minute lease //default to 5 minute lease
config += fmt.Sprintf("dhcp-range=%s,%s,5m\n", pRange.RangeLower, pRange.RangeUpper) config += fmt.Sprintf("dhcp-range=%s,%s\n", pRange.RangeLower, pRange.RangeUpper)
} }
} }
@@ -282,3 +260,86 @@ func DHCPCreateConfigFileString(s *pb.DHCPServerSettings) (config string, err er
return return
} }
// Lease/Release tracker
var reLease = regexp.MustCompile(".*DHCPACK\\((.*)\\) ([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}) ([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}) (.*)")
var reRelease = regexp.MustCompile(".*DHCPRELEASE\\((.*)\\) ([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}) ([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})")
type DhcpLease struct {
Release bool
Iface string
Ip net.IP
Mac net.HardwareAddr
Host string //only used for lease, not release
}
type dnsmasqLeaseMonitor struct {
nim *NetworkInterfaceManager
}
func (m *dnsmasqLeaseMonitor) Write(p []byte) (n int, err error) {
/*
dnsmasq-wlan0: 16:53:49 dnsmasq-dhcp[1855]: 1450307105 DHCPACK(wlan0) 172.24.0.18 34:e6:xx:xx:xx:xx who-knows
dnsmasq-wlan0: 16:53:58 dnsmasq-dhcp[1855]: 4200697351 DHCPRELEASE(wlan0) 172.24.0.18 34:e6:xx:xx:xx:xx
*/
lineScanner := bufio.NewScanner(bytes.NewReader(p))
lineScanner.Split(bufio.ScanLines)
for lineScanner.Scan() {
line := string(lineScanner.Bytes())
switch {
case strings.Contains(line, "DHCPACK"):
//fmt.Printf("Lease monitor %s LEASE: %s\n", m.nim.InterfaceName, line)
leaseMatches := reLease.FindStringSubmatch(line)
if len(leaseMatches) > 3 {
lease := &DhcpLease{}
lease.Iface = leaseMatches[1]
lease.Ip = net.ParseIP(leaseMatches[2])
mac,errP := net.ParseMAC(leaseMatches[3])
if errP != nil { continue } //ignore if mac address couldn't be parsed
lease.Mac = mac
if len(leaseMatches) > 4 {
//assume 4th match is hostname
lease.Host = leaseMatches[4]
}
m.nim.OnHandedOutDhcpLease(lease)
}
/*
for i,m := range leaseMatches {
fmt.Printf("\tRegex lease %d: %s\n", i, m)
}
*/
case strings.Contains(line, "DHCPRELEASE"):
//fmt.Printf("Lease monitor %s RELEASE: %s\n", m.nim.InterfaceName, line)
leaseMatches := reRelease.FindStringSubmatch(line)
if len(leaseMatches) > 3 {
release := &DhcpLease{}
release.Iface = leaseMatches[1]
release.Ip = net.ParseIP(leaseMatches[2])
mac,errP := net.ParseMAC(leaseMatches[3])
if errP != nil { continue } //ignore if mac address couldn't be parsed
release.Mac = mac
release.Release = true
m.nim.OnReceivedDhcpRelease(release)
}
}
}
return len(p),nil
}
func NewDnsmasqLeaseMonitor(nim *NetworkInterfaceManager) *dnsmasqLeaseMonitor {
return &dnsmasqLeaseMonitor{
nim: nim,
}
}

View File

@@ -135,7 +135,7 @@ func NewService() (svc *Service, err error) {
svc.SubSysEvent = NewEventManager(20) svc.SubSysEvent = NewEventManager(20)
svc.SubSysLed = NewLedService() svc.SubSysLed = NewLedService()
svc.SubSysNetwork, err = NewNetworkManager() svc.SubSysNetwork, err = NewNetworkManager(svc) //Depends on EvenSubSys
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -400,7 +400,7 @@ func (tam *TriggerActionManager) executeActionStartHidScript(evt *pb.Event, ta *
case triggerTypeGpioIn: case triggerTypeGpioIn:
gpioPin := ta.Trigger.(*pb.TriggerAction_GpioIn).GpioIn.GpioNum gpioPin := ta.Trigger.(*pb.TriggerAction_GpioIn).GpioIn.GpioNum
gpioPinName := pb.GPIONum_name[int32(gpioPin)] gpioPinName := pb.GPIONum_name[int32(gpioPin)]
preScript += fmt.Sprintf("var GPIO_PIN=%s;\n", gpioPinName) preScript += fmt.Sprintf("var GPIO_PIN='%s';\n", gpioPinName)
case triggerTypeGroupReceiveSequence: case triggerTypeGroupReceiveSequence:
groupName := ta.Trigger.(*pb.TriggerAction_GroupReceiveSequence).GroupReceiveSequence.GroupName groupName := ta.Trigger.(*pb.TriggerAction_GroupReceiveSequence).GroupReceiveSequence.GroupName
values := ta.Trigger.(*pb.TriggerAction_GroupReceiveSequence).GroupReceiveSequence.Values values := ta.Trigger.(*pb.TriggerAction_GroupReceiveSequence).GroupReceiveSequence.Values
@@ -425,12 +425,14 @@ func (tam *TriggerActionManager) executeActionStartHidScript(evt *pb.Event, ta *
iface := evt.Values[1].GetTstring() iface := evt.Values[1].GetTstring()
mac := evt.Values[2].GetTstring() mac := evt.Values[2].GetTstring()
ip := evt.Values[3].GetTstring() ip := evt.Values[3].GetTstring()
preScript += fmt.Sprintf("var DHCP_LEASE_IFACE=%s;\n", iface) host := evt.Values[4].GetTstring()
preScript += fmt.Sprintf("var DHCP_LEASE_MAC=%s;\n", mac) preScript += fmt.Sprintf("var DHCP_LEASE_IFACE='%s';\n", iface)
preScript += fmt.Sprintf("var DHCP_LEASE_IP=%s;\n", ip) preScript += fmt.Sprintf("var DHCP_LEASE_MAC='%s';\n", mac)
preScript += fmt.Sprintf("var DHCP_LEASE_IP='%s';\n", ip)
preScript += fmt.Sprintf("var DHCP_LEASE_HOST='%s';\n", host)
case triggerTypeSshLogin: case triggerTypeSshLogin:
loginUser := evt.Values[1].GetTstring() loginUser := evt.Values[1].GetTstring()
preScript += fmt.Sprintf("var SSH_LOGIN_USER=%s;\n", loginUser) preScript += fmt.Sprintf("var SSH_LOGIN_USER='%s';\n", loginUser)
} }
@@ -490,10 +492,12 @@ func (tam *TriggerActionManager) executeActionBashScript(evt *pb.Event, ta *pb.T
iface := evt.Values[1].GetTstring() iface := evt.Values[1].GetTstring()
mac := evt.Values[2].GetTstring() mac := evt.Values[2].GetTstring()
ip := evt.Values[3].GetTstring() ip := evt.Values[3].GetTstring()
host := evt.Values[4].GetTstring()
env = append(env, env = append(env,
fmt.Sprintf("DHCP_LEASE_IFACE=%s", iface), fmt.Sprintf("DHCP_LEASE_IFACE=%s", iface),
fmt.Sprintf("DHCP_LEASE_MAC=%s", mac), fmt.Sprintf("DHCP_LEASE_MAC=%s", mac),
fmt.Sprintf("DHCP_LEASE_IP=%s", ip), fmt.Sprintf("DHCP_LEASE_IP=%s", ip),
fmt.Sprintf("DHCP_LEASE_HOST=\"%s\"", host),
) )
case triggerTypeSshLogin: case triggerTypeSshLogin:
loginUser := evt.Values[1].GetTstring() loginUser := evt.Values[1].GetTstring()
@@ -530,7 +534,8 @@ func (tam *TriggerActionManager) executeActionLog(evt *pb.Event, ta *pb.TriggerA
iface := evt.Values[1].GetTstring() iface := evt.Values[1].GetTstring()
mac := evt.Values[2].GetTstring() mac := evt.Values[2].GetTstring()
ip := evt.Values[3].GetTstring() ip := evt.Values[3].GetTstring()
logMessage += fmt.Sprintf(" (DHCP_LEASE_IFACE=%s, DHCP_LEASE_MAC=%s, DHCP_LEASE_IP=%s)", iface, mac, ip) host := evt.Values[4].GetTstring()
logMessage += fmt.Sprintf(" (DHCP_LEASE_IFACE=%s, DHCP_LEASE_MAC=%s, DHCP_LEASE_IP=%s, DHCP_LEASE_HOST='%s')", iface, mac, ip, host)
case triggerTypeSshLogin: case triggerTypeSshLogin:
loginUser := evt.Values[1].GetTstring() loginUser := evt.Values[1].GetTstring()
logMessage += fmt.Sprintf(" (SSH_LOGIN_USER=%s)", loginUser) logMessage += fmt.Sprintf(" (SSH_LOGIN_USER=%s)", loginUser)

View File

@@ -1,10 +1,12 @@
package util package util
import ( import (
"bufio"
"bytes"
"io" "io"
"log" "log"
"sync"
"os" "os"
"sync"
) )
type TeeLogger struct { type TeeLogger struct {
@@ -18,11 +20,29 @@ type sublogger struct {
*TeeLogger *TeeLogger
} }
/*
// struct to present an additional io.Writer, wrapping TeeLogger to ise its Print() method // struct to present an additional io.Writer, wrapping TeeLogger to ise its Print() method
func (sl sublogger) Write(p []byte) (n int, err error) { func (sl sublogger) Write(p []byte) (n int, err error) {
sl.TeeLogger.Print(string(p)) sl.TeeLogger.Print(string(p))
return len(p), nil return len(p), nil
} }
*/
// struct to present an additional io.Writer, wrapping TeeLogger to ise its Print() method
func (sl sublogger) Write(p []byte) (n int, err error) {
//fmt.Printf("%s: %s", lw.Prefix, string(p))
lineScanner := bufio.NewScanner(bytes.NewReader(p))
lineScanner.Split(bufio.ScanLines)
for lineScanner.Scan() {
sl.TeeLogger.Print(string(lineScanner.Bytes()))
//fmt.Printf("%s: %s\n", lw.Prefix, string(lineScanner.Bytes()))
}
return len(p),nil
}
func NewTeeLogger(addStdout bool) (res *TeeLogger) { func NewTeeLogger(addStdout bool) (res *TeeLogger) {
res = &TeeLogger{ res = &TeeLogger{
@@ -38,6 +58,7 @@ func NewTeeLogger(addStdout bool) (res *TeeLogger) {
res.LogWriter = sublogger{ TeeLogger: res } res.LogWriter = sublogger{ TeeLogger: res }
res.SetFlags(log.Ltime) res.SetFlags(log.Ltime)
res.SetOutput(res) res.SetOutput(res)
log.Println()
return res return res
} }