2018-12-12 17:22:45 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2018-12-29 13:40:29 +00:00
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
2018-12-12 17:22:45 +00:00
|
|
|
"net/http"
|
2018-12-29 13:40:29 +00:00
|
|
|
"strings"
|
2018-12-28 18:01:31 +00:00
|
|
|
"time"
|
2018-12-28 14:17:51 +00:00
|
|
|
|
|
|
|
"github.com/AdguardTeam/AdGuardHome/dhcpd"
|
2018-12-29 16:12:22 +00:00
|
|
|
"github.com/hmage/golibs/log"
|
2018-12-28 18:01:16 +00:00
|
|
|
"github.com/joomcode/errorx"
|
2018-12-12 17:22:45 +00:00
|
|
|
)
|
|
|
|
|
2018-12-28 14:17:51 +00:00
|
|
|
var dhcpServer = dhcpd.Server{}
|
|
|
|
|
2018-12-12 17:22:45 +00:00
|
|
|
func handleDHCPStatus(w http.ResponseWriter, r *http.Request) {
|
2018-12-28 18:01:31 +00:00
|
|
|
rawLeases := dhcpServer.Leases()
|
|
|
|
leases := []map[string]string{}
|
|
|
|
for i := range rawLeases {
|
|
|
|
lease := map[string]string{
|
2018-12-29 14:04:40 +00:00
|
|
|
"mac": rawLeases[i].HWAddr.String(),
|
|
|
|
"ip": rawLeases[i].IP.String(),
|
|
|
|
"hostname": rawLeases[i].Hostname,
|
|
|
|
"expires": rawLeases[i].Expiry.Format(time.RFC3339),
|
2018-12-28 18:01:31 +00:00
|
|
|
}
|
|
|
|
leases = append(leases, lease)
|
|
|
|
|
|
|
|
}
|
2018-12-12 17:22:45 +00:00
|
|
|
status := map[string]interface{}{
|
2018-12-28 14:17:51 +00:00
|
|
|
"config": config.DHCP,
|
2018-12-28 18:01:31 +00:00
|
|
|
"leases": leases,
|
2018-12-12 17:22:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2018-12-28 14:17:51 +00:00
|
|
|
newconfig := dhcpd.ServerConfig{}
|
2018-12-12 17:22:45 +00:00
|
|
|
err := json.NewDecoder(r.Body).Decode(&newconfig)
|
|
|
|
if err != nil {
|
|
|
|
httpError(w, http.StatusBadRequest, "Failed to parse new DHCP config json: %s", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-12-28 14:17:51 +00:00
|
|
|
if newconfig.Enabled {
|
|
|
|
err := dhcpServer.Start(&newconfig)
|
|
|
|
if err != nil {
|
|
|
|
httpError(w, http.StatusBadRequest, "Failed to start DHCP server: %s", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !newconfig.Enabled {
|
2019-01-24 17:11:01 +00:00
|
|
|
err := dhcpServer.Stop()
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("failed to stop the DHCP server: %s", err)
|
|
|
|
}
|
2018-12-28 14:17:51 +00:00
|
|
|
}
|
|
|
|
config.DHCP = newconfig
|
2018-12-28 17:49:27 +00:00
|
|
|
httpUpdateConfigReloadDNSReturnOK(w, r)
|
2018-12-12 17:22:45 +00:00
|
|
|
}
|
|
|
|
|
2018-12-21 12:52:59 +00:00
|
|
|
func handleDHCPInterfaces(w http.ResponseWriter, r *http.Request) {
|
|
|
|
response := map[string]interface{}{}
|
|
|
|
|
2019-01-29 17:41:57 +00:00
|
|
|
ifaces, err := getValidNetInterfaces()
|
2018-12-21 12:52:59 +00:00
|
|
|
if err != nil {
|
2019-01-29 17:41:57 +00:00
|
|
|
httpError(w, http.StatusInternalServerError, "Couldn't get interfaces: %s", err)
|
2018-12-21 12:52:59 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range ifaces {
|
2019-01-29 17:41:57 +00:00
|
|
|
response[ifaces[i].Name] = ifaces[i]
|
2018-12-21 12:52:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
err = json.NewEncoder(w).Encode(response)
|
|
|
|
if err != nil {
|
|
|
|
httpError(w, http.StatusInternalServerError, "Failed to marshal json with available interfaces: %s", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-12 17:22:45 +00:00
|
|
|
func handleDHCPFindActiveServer(w http.ResponseWriter, r *http.Request) {
|
2018-12-29 13:39:29 +00:00
|
|
|
body, err := ioutil.ReadAll(r.Body)
|
|
|
|
if err != nil {
|
|
|
|
errorText := fmt.Sprintf("failed to read request body: %s", err)
|
|
|
|
log.Println(errorText)
|
|
|
|
http.Error(w, errorText, http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
interfaceName := strings.TrimSpace(string(body))
|
|
|
|
if interfaceName == "" {
|
|
|
|
errorText := fmt.Sprintf("empty interface name specified")
|
|
|
|
log.Println(errorText)
|
|
|
|
http.Error(w, errorText, http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
found, err := dhcpd.CheckIfOtherDHCPServersPresent(interfaceName)
|
2018-12-28 17:50:00 +00:00
|
|
|
result := map[string]interface{}{}
|
2018-12-28 14:17:51 +00:00
|
|
|
if err != nil {
|
2018-12-28 17:50:00 +00:00
|
|
|
result["error"] = err.Error()
|
|
|
|
} else {
|
|
|
|
result["found"] = found
|
2018-12-12 17:22:45 +00:00
|
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
2018-12-28 14:17:51 +00:00
|
|
|
err = json.NewEncoder(w).Encode(result)
|
2018-12-12 17:22:45 +00:00
|
|
|
if err != nil {
|
2018-12-21 12:52:59 +00:00
|
|
|
httpError(w, http.StatusInternalServerError, "Failed to marshal DHCP found json: %s", err)
|
2018-12-12 17:22:45 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2018-12-28 18:01:16 +00:00
|
|
|
|
|
|
|
func startDHCPServer() error {
|
2019-01-25 13:01:27 +00:00
|
|
|
if !config.DHCP.Enabled {
|
2018-12-29 12:04:14 +00:00
|
|
|
// not enabled, don't do anything
|
|
|
|
return nil
|
|
|
|
}
|
2018-12-28 18:01:16 +00:00
|
|
|
err := dhcpServer.Start(&config.DHCP)
|
|
|
|
if err != nil {
|
|
|
|
return errorx.Decorate(err, "Couldn't start DHCP server")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2019-02-04 10:54:53 +00:00
|
|
|
|
|
|
|
func stopDHCPServer() error {
|
|
|
|
if !config.DHCP.Enabled {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if !dhcpServer.Enabled {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
err := dhcpServer.Stop()
|
|
|
|
if err != nil {
|
|
|
|
return errorx.Decorate(err, "Couldn't stop DHCP server")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|