diff --git a/config.go b/config.go index 1f7464b2..8566de68 100644 --- a/config.go +++ b/config.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "sync" + "time" "github.com/AdguardTeam/AdGuardHome/dnsfilter" "github.com/AdguardTeam/AdGuardHome/dnsforward" @@ -31,6 +32,7 @@ type configuration struct { DNS dnsConfig `yaml:"dns"` Filters []filter `yaml:"filters"` UserRules []string `yaml:"user_rules"` + DHCP dhcpState `yaml:"dhcp"` sync.RWMutex `yaml:"-"` @@ -48,6 +50,30 @@ type dnsConfig struct { var defaultDNS = []string{"tls://1.1.1.1", "tls://1.0.0.1"} +// field ordering is important -- yaml fields will mirror ordering from here +type dhcpState struct { + dhcpConfig + Leases []dhcpLease +} + +// field ordering is important -- yaml fields will mirror ordering from here +type dhcpConfig struct { + Enabled bool + GatewayIP string `json:"gateway_ip" yaml:"gateway_ip"` + SubnetMask string `json:"subnet_mask" yaml:"subnet_mask"` + RangeStart string `json:"range_start" yaml:"range_start"` + RangeEnd string `json:"range_end" yaml:"range_end"` + LeaseDuration time.Duration `json:"lease_duration" yaml:"lease_duration"` +} + +// field ordering is important -- yaml fields will mirror ordering from here +type dhcpLease struct { + HWAddr [6]byte `json:"mac" yaml:"hwaddr"` + IP string `json:"ip"` // json by default keeps IP uppercase but we need lowercase + Hostname string + Expires time.Time +} + // initialize to default values, will be changed later when reading config or parsing command line var config = configuration{ ourConfigFilename: "AdGuardHome.yaml", @@ -72,6 +98,9 @@ var config = configuration{ {Filter: dnsfilter.Filter{ID: 3}, Enabled: false, URL: "https://hosts-file.net/ad_servers.txt", Name: "hpHosts - Ad and Tracking servers only"}, {Filter: dnsfilter.Filter{ID: 4}, Enabled: false, URL: "http://www.malwaredomainlist.com/hostslist/hosts.txt", Name: "MalwareDomainList.com Hosts List"}, }, + DHCP: dhcpState{dhcpConfig: dhcpConfig{ + LeaseDuration: time.Hour * 12, + }}, SchemaVersion: currentSchemaVersion, } diff --git a/control.go b/control.go index 78235a48..0b00f08c 100644 --- a/control.go +++ b/control.go @@ -719,4 +719,7 @@ func registerControlHandlers() { http.HandleFunc("/control/safesearch/enable", optionalAuth(ensurePOST(handleSafeSearchEnable))) http.HandleFunc("/control/safesearch/disable", optionalAuth(ensurePOST(handleSafeSearchDisable))) http.HandleFunc("/control/safesearch/status", optionalAuth(ensureGET(handleSafeSearchStatus))) + http.HandleFunc("/control/dhcp/status", optionalAuth(ensureGET(handleDHCPStatus))) + http.HandleFunc("/control/dhcp/set_config", optionalAuth(ensurePOST(handleDHCPSetConfig))) + http.HandleFunc("/control/dhcp/find_active_dhcp", optionalAuth(ensurePOST(handleDHCPFindActiveServer))) } diff --git a/dhcp.go b/dhcp.go new file mode 100644 index 00000000..5a6fc490 --- /dev/null +++ b/dhcp.go @@ -0,0 +1,45 @@ +package main + +import ( + "encoding/json" + "math/rand" + "net/http" +) + +func handleDHCPStatus(w http.ResponseWriter, r *http.Request) { + status := map[string]interface{}{ + "config": config.DHCP.dhcpConfig, + "leases": config.DHCP.Leases, + } + + w.Header().Set("Content-Type", "application/json") + err := json.NewEncoder(w).Encode(status) + if err != nil { + httpError(w, http.StatusInternalServerError, "Unable to marshal DHCP status json: %s", err) + return + } +} + +func handleDHCPSetConfig(w http.ResponseWriter, r *http.Request) { + newconfig := dhcpConfig{} + err := json.NewDecoder(r.Body).Decode(&newconfig) + if err != nil { + httpError(w, http.StatusBadRequest, "Failed to parse new DHCP config json: %s", err) + return + } + + config.DHCP.dhcpConfig = newconfig +} + +// TODO: implement +func handleDHCPFindActiveServer(w http.ResponseWriter, r *http.Request) { + found := map[string]bool{ + "found": rand.Intn(2) == 1, + } + w.Header().Set("Content-Type", "application/json") + err := json.NewEncoder(w).Encode(found) + if err != nil { + httpError(w, http.StatusBadRequest, "Failed to marshal DHCP found json: %s", err) + return + } +}