diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e19aab..b861fd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ # Change Log All notable changes to this project will be documented in this file. +## [v1.0.4] - 2023-10-12 +### Added +- Configurable `timeout` for `arp-scan` [#65](https://github.com/aceberg/WatchYourLAN/issues/65) + ## [v1.0.3] - 2023-10-08 ### Fixed - Github Action workflow for binary release diff --git a/README.md b/README.md index df1bd12..71e748c 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Configuration can be done through config file or environment variables | Variable | Description | Default | | -------- | ----------- | ------- | +| ARP_TIMEOUT | Per host timeout for arp-scan (in milliseconds) | 500 | | AUTH | Enable Session-Cookie authentication | false | | AUTH_EXPIRE | Session expiration time. A number and suffix: **m, h, d** or **M**. | 7d | | AUTH_USER | Username | "" | diff --git a/internal/conf/config.go b/internal/conf/config.go index 51b478b..2689cca 100644 --- a/internal/conf/config.go +++ b/internal/conf/config.go @@ -21,10 +21,12 @@ func Get(path string) (config models.Conf, authConf auth.Conf) { viper.SetDefault("COLOR", "light") viper.SetDefault("IGNOREIP", "no") viper.SetDefault("LOGLEVEL", "verbose") + viper.SetDefault("HISTORY_DAYS", "30") + viper.SetDefault("ARP_TIMEOUT", "500") + viper.SetDefault("AUTH_USER", "") viper.SetDefault("AUTH_PASSWORD", "") viper.SetDefault("AUTH_EXPIRE", "7d") - viper.SetDefault("HISTORY_DAYS", "30") viper.SetConfigFile(path) viper.SetConfigType("yaml") @@ -44,6 +46,8 @@ func Get(path string) (config models.Conf, authConf auth.Conf) { config.IgnoreIP = viper.Get("IGNOREIP").(string) config.LogLevel = viper.Get("LOGLEVEL").(string) config.HistDays = viper.Get("HISTORY_DAYS").(string) + config.ArpTimeout = viper.Get("ARP_TIMEOUT").(string) + authConf.Auth = viper.GetBool("AUTH") authConf.User, _ = viper.Get("AUTH_USER").(string) authConf.Password, _ = viper.Get("AUTH_PASSWORD").(string) @@ -72,6 +76,7 @@ func Write(path string, config models.Conf, authConf auth.Conf) { viper.Set("IGNOREIP", config.IgnoreIP) viper.Set("LOGLEVEL", config.LogLevel) viper.Set("HISTORY_DAYS", config.HistDays) + viper.Set("ARP_TIMEOUT", config.ArpTimeout) viper.Set("auth", authConf.Auth) viper.Set("auth_user", authConf.User) diff --git a/internal/models/models.go b/internal/models/models.go index e4f89b9..c9c602f 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -6,20 +6,21 @@ import ( // Conf - app config type Conf struct { - Iface string - DbPath string - GuiIP string - GuiPort string - Timeout int - ShoutURL string - Theme string - Color string - IgnoreIP string - LogLevel string - NodePath string - Icon string - Auth bool - HistDays string + Iface string + DbPath string + GuiIP string + GuiPort string + Timeout int + ShoutURL string + Theme string + Color string + IgnoreIP string + LogLevel string + NodePath string + Icon string + Auth bool + HistDays string + ArpTimeout string } // Host - one host diff --git a/internal/scan/arpscan.go b/internal/scan/arpscan.go index 6f1f974..09c9fab 100644 --- a/internal/scan/arpscan.go +++ b/internal/scan/arpscan.go @@ -10,7 +10,7 @@ import ( ) func scanIface(iface string) string { - cmd, err := exec.Command("arp-scan", "-glNx", "-I", iface).Output() + cmd, err := exec.Command("arp-scan", "-glNx", "-t", appConfig.ArpTimeout, "-I", iface).Output() if err != nil { return string("") } @@ -40,15 +40,15 @@ func parseOutput(text string) []models.Host { } // Scan all interfaces -func arpScan(allIfaces string, logLevel string) []models.Host { +func arpScan() []models.Host { var text string var foundHosts = []models.Host{} - perString := strings.Split(allIfaces, " ") + perString := strings.Split(appConfig.Iface, " ") for _, iface := range perString { text = scanIface(iface) - if logLevel != "short" { + if appConfig.LogLevel != "short" { log.Println("INFO: scanning interface", iface) log.Println("INFO: found IPs:", text) } diff --git a/internal/scan/start.go b/internal/scan/start.go index 5e0c407..770df5f 100644 --- a/internal/scan/start.go +++ b/internal/scan/start.go @@ -28,7 +28,7 @@ func Start(config models.Conf, quit chan bool) { plusDate := lastDate.Add(time.Duration(appConfig.Timeout) * time.Second) if nowDate.After(plusDate) { - structHosts = arpScan(appConfig.Iface, appConfig.LogLevel) // arpscan.go + structHosts = arpScan() // arpscan.go dbHosts = db.Select(appConfig.DbPath) toMap() diff --git a/internal/web/config.go b/internal/web/config.go index e14b3bc..eacdfd7 100644 --- a/internal/web/config.go +++ b/internal/web/config.go @@ -42,6 +42,7 @@ func saveConfigHandler(w http.ResponseWriter, r *http.Request) { AppConfig.IgnoreIP = r.FormValue("ignoreip") AppConfig.LogLevel = r.FormValue("loglevel") AppConfig.HistDays = r.FormValue("history") + AppConfig.ArpTimeout = r.FormValue("arp_timeout") timeout := r.FormValue("timeout") AppConfig.Timeout, err = strconv.Atoi(timeout) diff --git a/internal/web/templates/config.html b/internal/web/templates/config.html index e39a2d2..acdf766 100644 --- a/internal/web/templates/config.html +++ b/internal/web/templates/config.html @@ -24,7 +24,7 @@ Timeout (seconds) - + Shoutrrr URL @@ -71,7 +71,23 @@ Keep history (days) - + + + + Arp Timeout + + + @@ -92,6 +108,7 @@

● If you want to detect unknown hosts by MAC only, set Ignore IP to "yes"

Log Level defines how much log output you want to see

● The Clear table button below will delete all records from table. If you want to delete a single host, click on its MAC and press Delete host button

+

Arp Timeout per host timeout for arp-scan (in milliseconds). Default: 500


diff --git a/internal/web/templates/version b/internal/web/templates/version index ebd8a3d..6b82dc6 100644 --- a/internal/web/templates/version +++ b/internal/web/templates/version @@ -1 +1 @@ -VERSION=1.0.3 \ No newline at end of file +VERSION=1.0.4 \ No newline at end of file