Pull request: 2509 type-safety vol.1
Merge in DNS/adguard-home from 2509-type-safety to master Updates #2509. Squashed commit of the following: commit 535968eb7de3a9e0817ddb57bc2320e5c5a55086 Author: Eugene Burkov <e.burkov@adguard.com> Date: Wed Jan 20 15:06:16 2021 +0300 dhcpd: fix comments commit dc79b80381fe7a8ecec6f9659fd23710c9229f59 Author: Eugene Burkov <e.burkov@adguard.com> Date: Wed Jan 20 14:08:10 2021 +0300 all: improve docs commit 156ebf6c9bad95f82cd121f019f3b59b77b18ba6 Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Jan 19 17:08:15 2021 +0300 all: improve JSON encoding and decoding
This commit is contained in:
parent
715df4cd92
commit
5a50efadb2
|
@ -3,6 +3,8 @@ package dhcpd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -33,6 +35,39 @@ type Lease struct {
|
||||||
Expiry time.Time `json:"expires"`
|
Expiry time.Time `json:"expires"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface for *Lease.
|
||||||
|
func (l *Lease) MarshalJSON() ([]byte, error) {
|
||||||
|
type lease Lease
|
||||||
|
return json.Marshal(&struct {
|
||||||
|
HWAddr string `json:"mac"`
|
||||||
|
*lease
|
||||||
|
}{
|
||||||
|
HWAddr: l.HWAddr.String(),
|
||||||
|
lease: (*lease)(l),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the json.Unmarshaler interface for *Lease.
|
||||||
|
func (l *Lease) UnmarshalJSON(data []byte) (err error) {
|
||||||
|
type lease Lease
|
||||||
|
aux := struct {
|
||||||
|
HWAddr string `json:"mac"`
|
||||||
|
*lease
|
||||||
|
}{
|
||||||
|
lease: (*lease)(l),
|
||||||
|
}
|
||||||
|
if err = json.Unmarshal(data, &aux); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
l.HWAddr, err = net.ParseMAC(aux.HWAddr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't parse MAC address: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ServerConfig - DHCP server configuration
|
// ServerConfig - DHCP server configuration
|
||||||
// field ordering is important -- yaml fields will mirror ordering from here
|
// field ordering is important -- yaml fields will mirror ordering from here
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/sysutil"
|
"github.com/AdguardTeam/AdGuardHome/internal/sysutil"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/util"
|
"github.com/AdguardTeam/AdGuardHome/internal/util"
|
||||||
|
@ -22,25 +21,6 @@ func httpError(r *http.Request, w http.ResponseWriter, code int, format string,
|
||||||
http.Error(w, text, code)
|
http.Error(w, text, code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// []Lease -> JSON
|
|
||||||
func convertLeases(inputLeases []Lease, includeExpires bool) []map[string]string {
|
|
||||||
leases := []map[string]string{}
|
|
||||||
for _, l := range inputLeases {
|
|
||||||
lease := map[string]string{
|
|
||||||
"mac": l.HWAddr.String(),
|
|
||||||
"ip": l.IP.String(),
|
|
||||||
"hostname": l.Hostname,
|
|
||||||
}
|
|
||||||
|
|
||||||
if includeExpires {
|
|
||||||
lease["expires"] = l.Expiry.Format(time.RFC3339)
|
|
||||||
}
|
|
||||||
|
|
||||||
leases = append(leases, lease)
|
|
||||||
}
|
|
||||||
return leases
|
|
||||||
}
|
|
||||||
|
|
||||||
type v4ServerConfJSON struct {
|
type v4ServerConfJSON struct {
|
||||||
GatewayIP net.IP `json:"gateway_ip"`
|
GatewayIP net.IP `json:"gateway_ip"`
|
||||||
SubnetMask net.IP `json:"subnet_mask"`
|
SubnetMask net.IP `json:"subnet_mask"`
|
||||||
|
@ -49,22 +29,12 @@ type v4ServerConfJSON struct {
|
||||||
LeaseDuration uint32 `json:"lease_duration"`
|
LeaseDuration uint32 `json:"lease_duration"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func v4ServerConfToJSON(c V4ServerConf) v4ServerConfJSON {
|
|
||||||
return v4ServerConfJSON{
|
|
||||||
GatewayIP: c.GatewayIP,
|
|
||||||
SubnetMask: c.SubnetMask,
|
|
||||||
RangeStart: c.RangeStart,
|
|
||||||
RangeEnd: c.RangeEnd,
|
|
||||||
LeaseDuration: c.LeaseDuration,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func v4JSONToServerConf(j v4ServerConfJSON) V4ServerConf {
|
func v4JSONToServerConf(j v4ServerConfJSON) V4ServerConf {
|
||||||
return V4ServerConf{
|
return V4ServerConf{
|
||||||
GatewayIP: j.GatewayIP.To4(),
|
GatewayIP: j.GatewayIP,
|
||||||
SubnetMask: j.SubnetMask.To4(),
|
SubnetMask: j.SubnetMask,
|
||||||
RangeStart: j.RangeStart.To4(),
|
RangeStart: j.RangeStart,
|
||||||
RangeEnd: j.RangeEnd.To4(),
|
RangeEnd: j.RangeEnd,
|
||||||
LeaseDuration: j.LeaseDuration,
|
LeaseDuration: j.LeaseDuration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,13 +44,6 @@ type v6ServerConfJSON struct {
|
||||||
LeaseDuration uint32 `json:"lease_duration"`
|
LeaseDuration uint32 `json:"lease_duration"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func v6ServerConfToJSON(c V6ServerConf) v6ServerConfJSON {
|
|
||||||
return v6ServerConfJSON{
|
|
||||||
RangeStart: c.RangeStart,
|
|
||||||
LeaseDuration: c.LeaseDuration,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func v6JSONToServerConf(j v6ServerConfJSON) V6ServerConf {
|
func v6JSONToServerConf(j v6ServerConfJSON) V6ServerConf {
|
||||||
return V6ServerConf{
|
return V6ServerConf{
|
||||||
RangeStart: j.RangeStart,
|
RangeStart: j.RangeStart,
|
||||||
|
@ -88,25 +51,30 @@ func v6JSONToServerConf(j v6ServerConfJSON) V6ServerConf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dhcpStatusResponse is the response for /control/dhcp/status endpoint.
|
||||||
|
type dhcpStatusResponse struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
IfaceName string `json:"interface_name"`
|
||||||
|
V4 V4ServerConf `json:"v4"`
|
||||||
|
V6 V6ServerConf `json:"v6"`
|
||||||
|
Leases []Lease `json:"leases"`
|
||||||
|
StaticLeases []Lease `json:"static_leases"`
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) handleDHCPStatus(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) handleDHCPStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
leases := convertLeases(s.Leases(LeasesDynamic), true)
|
status := &dhcpStatusResponse{
|
||||||
staticLeases := convertLeases(s.Leases(LeasesStatic), false)
|
Enabled: s.conf.Enabled,
|
||||||
|
IfaceName: s.conf.InterfaceName,
|
||||||
v4conf := V4ServerConf{}
|
V4: V4ServerConf{},
|
||||||
s.srv4.WriteDiskConfig4(&v4conf)
|
V6: V6ServerConf{},
|
||||||
|
|
||||||
v6conf := V6ServerConf{}
|
|
||||||
s.srv6.WriteDiskConfig6(&v6conf)
|
|
||||||
|
|
||||||
status := map[string]interface{}{
|
|
||||||
"enabled": s.conf.Enabled,
|
|
||||||
"interface_name": s.conf.InterfaceName,
|
|
||||||
"v4": v4ServerConfToJSON(v4conf),
|
|
||||||
"v6": v6ServerConfToJSON(v6conf),
|
|
||||||
"leases": leases,
|
|
||||||
"static_leases": staticLeases,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.srv4.WriteDiskConfig4(&status.V4)
|
||||||
|
s.srv6.WriteDiskConfig6(&status.V6)
|
||||||
|
|
||||||
|
status.Leases = s.Leases(LeasesDynamic)
|
||||||
|
status.StaticLeases = s.Leases(LeasesStatic)
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
err := json.NewEncoder(w).Encode(status)
|
err := json.NewEncoder(w).Encode(status)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -115,12 +83,6 @@ func (s *Server) handleDHCPStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type staticLeaseJSON struct {
|
|
||||||
HWAddr string `json:"mac"`
|
|
||||||
IP net.IP `json:"ip"`
|
|
||||||
Hostname string `json:"hostname"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type dhcpServerConfigJSON struct {
|
type dhcpServerConfigJSON struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
InterfaceName string `json:"interface_name"`
|
InterfaceName string `json:"interface_name"`
|
||||||
|
@ -233,7 +195,7 @@ type netInterfaceJSON struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handleDHCPInterfaces(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) handleDHCPInterfaces(w http.ResponseWriter, r *http.Request) {
|
||||||
response := map[string]interface{}{}
|
response := map[string]netInterfaceJSON{}
|
||||||
|
|
||||||
ifaces, err := util.GetValidNetInterfaces()
|
ifaces, err := util.GetValidNetInterfaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -295,6 +257,40 @@ func (s *Server) handleDHCPInterfaces(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dhcpSearchOtherResult contains information about other DHCP server for
|
||||||
|
// specific network interface.
|
||||||
|
type dhcpSearchOtherResult struct {
|
||||||
|
Found string `json:"found,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// dhcpStaticIPStatus contains information about static IP address for DHCP
|
||||||
|
// server.
|
||||||
|
type dhcpStaticIPStatus struct {
|
||||||
|
Static string `json:"static"`
|
||||||
|
IP string `json:"ip,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// dhcpSearchV4Result contains information about DHCPv4 server for specific
|
||||||
|
// network interface.
|
||||||
|
type dhcpSearchV4Result struct {
|
||||||
|
OtherServer dhcpSearchOtherResult `json:"other_server"`
|
||||||
|
StaticIP dhcpStaticIPStatus `json:"static_ip"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// dhcpSearchV6Result contains information about DHCPv6 server for specific
|
||||||
|
// network interface.
|
||||||
|
type dhcpSearchV6Result struct {
|
||||||
|
OtherServer dhcpSearchOtherResult `json:"other_server"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// dhcpSearchResult is a response for /control/dhcp/find_active_dhcp endpoint.
|
||||||
|
type dhcpSearchResult struct {
|
||||||
|
V4 dhcpSearchV4Result `json:"v4"`
|
||||||
|
V6 dhcpSearchV6Result `json:"v6"`
|
||||||
|
}
|
||||||
|
|
||||||
// Perform the following tasks:
|
// Perform the following tasks:
|
||||||
// . Search for another DHCP server running
|
// . Search for another DHCP server running
|
||||||
// . Check if a static IP is configured for the network interface
|
// . Check if a static IP is configured for the network interface
|
||||||
|
@ -317,50 +313,42 @@ func (s *Server) handleDHCPFindActiveServer(w http.ResponseWriter, r *http.Reque
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result := dhcpSearchResult{
|
||||||
|
V4: dhcpSearchV4Result{
|
||||||
|
OtherServer: dhcpSearchOtherResult{},
|
||||||
|
StaticIP: dhcpStaticIPStatus{},
|
||||||
|
},
|
||||||
|
V6: dhcpSearchV6Result{
|
||||||
|
OtherServer: dhcpSearchOtherResult{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
found4, err4 := CheckIfOtherDHCPServersPresentV4(interfaceName)
|
found4, err4 := CheckIfOtherDHCPServersPresentV4(interfaceName)
|
||||||
|
|
||||||
staticIP := map[string]interface{}{}
|
|
||||||
isStaticIP, err := sysutil.IfaceHasStaticIP(interfaceName)
|
isStaticIP, err := sysutil.IfaceHasStaticIP(interfaceName)
|
||||||
staticIPStatus := "yes"
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
staticIPStatus = "error"
|
result.V4.StaticIP.Static = "error"
|
||||||
staticIP["error"] = err.Error()
|
result.V4.StaticIP.Error = err.Error()
|
||||||
} else if !isStaticIP {
|
} else if !isStaticIP {
|
||||||
staticIPStatus = "no"
|
result.V4.StaticIP.Static = "no"
|
||||||
staticIP["ip"] = util.GetSubnet(interfaceName)
|
result.V4.StaticIP.IP = util.GetSubnet(interfaceName)
|
||||||
}
|
}
|
||||||
staticIP["static"] = staticIPStatus
|
|
||||||
|
|
||||||
v4 := map[string]interface{}{}
|
|
||||||
othSrv := map[string]interface{}{}
|
|
||||||
foundVal := "no"
|
|
||||||
if found4 {
|
if found4 {
|
||||||
foundVal = "yes"
|
result.V4.OtherServer.Found = "yes"
|
||||||
} else if err4 != nil {
|
} else if err4 != nil {
|
||||||
foundVal = "error"
|
result.V4.OtherServer.Found = "error"
|
||||||
othSrv["error"] = err4.Error()
|
result.V4.OtherServer.Error = err4.Error()
|
||||||
}
|
}
|
||||||
othSrv["found"] = foundVal
|
|
||||||
v4["other_server"] = othSrv
|
|
||||||
v4["static_ip"] = staticIP
|
|
||||||
|
|
||||||
found6, err6 := CheckIfOtherDHCPServersPresentV6(interfaceName)
|
found6, err6 := CheckIfOtherDHCPServersPresentV6(interfaceName)
|
||||||
|
|
||||||
v6 := map[string]interface{}{}
|
|
||||||
othSrv = map[string]interface{}{}
|
|
||||||
foundVal = "no"
|
|
||||||
if found6 {
|
if found6 {
|
||||||
foundVal = "yes"
|
result.V6.OtherServer.Found = "yes"
|
||||||
} else if err6 != nil {
|
} else if err6 != nil {
|
||||||
foundVal = "error"
|
result.V6.OtherServer.Found = "error"
|
||||||
othSrv["error"] = err6.Error()
|
result.V6.OtherServer.Error = err6.Error()
|
||||||
}
|
}
|
||||||
othSrv["found"] = foundVal
|
|
||||||
v6["other_server"] = othSrv
|
|
||||||
|
|
||||||
result := map[string]interface{}{}
|
|
||||||
result["v4"] = v4
|
|
||||||
result["v6"] = v6
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
err = json.NewEncoder(w).Encode(result)
|
err = json.NewEncoder(w).Encode(result)
|
||||||
|
@ -371,7 +359,7 @@ func (s *Server) handleDHCPFindActiveServer(w http.ResponseWriter, r *http.Reque
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handleDHCPAddStaticLease(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) handleDHCPAddStaticLease(w http.ResponseWriter, r *http.Request) {
|
||||||
lj := staticLeaseJSON{}
|
lj := Lease{}
|
||||||
err := json.NewDecoder(r.Body).Decode(&lj)
|
err := json.NewDecoder(r.Body).Decode(&lj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(r, w, http.StatusBadRequest, "json.Decode: %s", err)
|
httpError(r, w, http.StatusBadRequest, "json.Decode: %s", err)
|
||||||
|
@ -387,21 +375,10 @@ func (s *Server) handleDHCPAddStaticLease(w http.ResponseWriter, r *http.Request
|
||||||
|
|
||||||
ip4 := lj.IP.To4()
|
ip4 := lj.IP.To4()
|
||||||
|
|
||||||
mac, err := net.ParseMAC(lj.HWAddr)
|
|
||||||
lease := Lease{
|
|
||||||
HWAddr: mac,
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip4 == nil {
|
if ip4 == nil {
|
||||||
lease.IP = lj.IP.To16()
|
lj.IP = lj.IP.To16()
|
||||||
|
|
||||||
if err != nil {
|
err = s.srv6.AddStaticLease(lj)
|
||||||
httpError(r, w, http.StatusBadRequest, "invalid MAC")
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = s.srv6.AddStaticLease(lease)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(r, w, http.StatusBadRequest, "%s", err)
|
httpError(r, w, http.StatusBadRequest, "%s", err)
|
||||||
}
|
}
|
||||||
|
@ -409,9 +386,8 @@ func (s *Server) handleDHCPAddStaticLease(w http.ResponseWriter, r *http.Request
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lease.IP = ip4
|
lj.IP = ip4
|
||||||
lease.Hostname = lj.Hostname
|
err = s.srv4.AddStaticLease(lj)
|
||||||
err = s.srv4.AddStaticLease(lease)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(r, w, http.StatusBadRequest, "%s", err)
|
httpError(r, w, http.StatusBadRequest, "%s", err)
|
||||||
|
|
||||||
|
@ -420,7 +396,7 @@ func (s *Server) handleDHCPAddStaticLease(w http.ResponseWriter, r *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handleDHCPRemoveStaticLease(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) handleDHCPRemoveStaticLease(w http.ResponseWriter, r *http.Request) {
|
||||||
lj := staticLeaseJSON{}
|
lj := Lease{}
|
||||||
err := json.NewDecoder(r.Body).Decode(&lj)
|
err := json.NewDecoder(r.Body).Decode(&lj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(r, w, http.StatusBadRequest, "json.Decode: %s", err)
|
httpError(r, w, http.StatusBadRequest, "json.Decode: %s", err)
|
||||||
|
@ -436,21 +412,10 @@ func (s *Server) handleDHCPRemoveStaticLease(w http.ResponseWriter, r *http.Requ
|
||||||
|
|
||||||
ip4 := lj.IP.To4()
|
ip4 := lj.IP.To4()
|
||||||
|
|
||||||
mac, err := net.ParseMAC(lj.HWAddr)
|
|
||||||
lease := Lease{
|
|
||||||
HWAddr: mac,
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip4 == nil {
|
if ip4 == nil {
|
||||||
lease.IP = lj.IP.To16()
|
lj.IP = lj.IP.To16()
|
||||||
|
|
||||||
if err != nil {
|
err = s.srv6.RemoveStaticLease(lj)
|
||||||
httpError(r, w, http.StatusBadRequest, "invalid MAC")
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = s.srv6.RemoveStaticLease(lease)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(r, w, http.StatusBadRequest, "%s", err)
|
httpError(r, w, http.StatusBadRequest, "%s", err)
|
||||||
}
|
}
|
||||||
|
@ -458,9 +423,8 @@ func (s *Server) handleDHCPRemoveStaticLease(w http.ResponseWriter, r *http.Requ
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lease.IP = ip4
|
lj.IP = ip4
|
||||||
lease.Hostname = lj.Hostname
|
err = s.srv4.RemoveStaticLease(lj)
|
||||||
err = s.srv4.RemoveStaticLease(lease)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(r, w, http.StatusBadRequest, "%s", err)
|
httpError(r, w, http.StatusBadRequest, "%s", err)
|
||||||
|
|
||||||
|
|
|
@ -33,22 +33,22 @@ type DHCPServer interface {
|
||||||
|
|
||||||
// V4ServerConf - server configuration
|
// V4ServerConf - server configuration
|
||||||
type V4ServerConf struct {
|
type V4ServerConf struct {
|
||||||
Enabled bool `yaml:"-"`
|
Enabled bool `yaml:"-" json:"-"`
|
||||||
InterfaceName string `yaml:"-"`
|
InterfaceName string `yaml:"-" json:"-"`
|
||||||
|
|
||||||
GatewayIP net.IP `yaml:"gateway_ip"`
|
GatewayIP net.IP `yaml:"gateway_ip" json:"gateway_ip"`
|
||||||
SubnetMask net.IP `yaml:"subnet_mask"`
|
SubnetMask net.IP `yaml:"subnet_mask" json:"subnet_mask"`
|
||||||
|
|
||||||
// The first & the last IP address for dynamic leases
|
// The first & the last IP address for dynamic leases
|
||||||
// Bytes [0..2] of the last allowed IP address must match the first IP
|
// Bytes [0..2] of the last allowed IP address must match the first IP
|
||||||
RangeStart net.IP `yaml:"range_start"`
|
RangeStart net.IP `yaml:"range_start" json:"range_start"`
|
||||||
RangeEnd net.IP `yaml:"range_end"`
|
RangeEnd net.IP `yaml:"range_end" json:"range_end"`
|
||||||
|
|
||||||
LeaseDuration uint32 `yaml:"lease_duration"` // in seconds
|
LeaseDuration uint32 `yaml:"lease_duration" json:"lease_duration"` // in seconds
|
||||||
|
|
||||||
// IP conflict detector: time (ms) to wait for ICMP reply
|
// IP conflict detector: time (ms) to wait for ICMP reply
|
||||||
// 0: disable
|
// 0: disable
|
||||||
ICMPTimeout uint32 `yaml:"icmp_timeout_msec"`
|
ICMPTimeout uint32 `yaml:"icmp_timeout_msec" json:"-"`
|
||||||
|
|
||||||
// Custom Options.
|
// Custom Options.
|
||||||
//
|
//
|
||||||
|
@ -58,7 +58,7 @@ type V4ServerConf struct {
|
||||||
//
|
//
|
||||||
// Option with IP data (only 1 IP is supported):
|
// Option with IP data (only 1 IP is supported):
|
||||||
// DEC_CODE ip IP_ADDR
|
// DEC_CODE ip IP_ADDR
|
||||||
Options []string `yaml:"options"`
|
Options []string `yaml:"options" json:"-"`
|
||||||
|
|
||||||
ipStart net.IP // starting IP address for dynamic leases
|
ipStart net.IP // starting IP address for dynamic leases
|
||||||
ipEnd net.IP // ending IP address for dynamic leases
|
ipEnd net.IP // ending IP address for dynamic leases
|
||||||
|
@ -74,17 +74,17 @@ type V4ServerConf struct {
|
||||||
|
|
||||||
// V6ServerConf - server configuration
|
// V6ServerConf - server configuration
|
||||||
type V6ServerConf struct {
|
type V6ServerConf struct {
|
||||||
Enabled bool `yaml:"-"`
|
Enabled bool `yaml:"-" json:"-"`
|
||||||
InterfaceName string `yaml:"-"`
|
InterfaceName string `yaml:"-" json:"-"`
|
||||||
|
|
||||||
// The first IP address for dynamic leases
|
// The first IP address for dynamic leases
|
||||||
// The last allowed IP address ends with 0xff byte
|
// The last allowed IP address ends with 0xff byte
|
||||||
RangeStart string `yaml:"range_start"`
|
RangeStart string `yaml:"range_start" json:"range_start"`
|
||||||
|
|
||||||
LeaseDuration uint32 `yaml:"lease_duration"` // in seconds
|
LeaseDuration uint32 `yaml:"lease_duration" json:"lease_duration"` // in seconds
|
||||||
|
|
||||||
RaSlaacOnly bool `yaml:"ra_slaac_only"` // send ICMPv6.RA packets without MO flags
|
RaSlaacOnly bool `yaml:"ra_slaac_only" json:"-"` // send ICMPv6.RA packets without MO flags
|
||||||
RaAllowSlaac bool `yaml:"ra_allow_slaac"` // send ICMPv6.RA packets with MO flags
|
RaAllowSlaac bool `yaml:"ra_allow_slaac" json:"-"` // send ICMPv6.RA packets with MO flags
|
||||||
|
|
||||||
ipStart net.IP // starting IP address for dynamic leases
|
ipStart net.IP // starting IP address for dynamic leases
|
||||||
leaseTime time.Duration // the time during which a dynamic lease is considered valid
|
leaseTime time.Duration // the time during which a dynamic lease is considered valid
|
||||||
|
|
|
@ -77,7 +77,10 @@ func (s *v4Server) blacklisted(l *Lease) bool {
|
||||||
|
|
||||||
// GetLeases returns the list of current DHCP leases (thread-safe)
|
// GetLeases returns the list of current DHCP leases (thread-safe)
|
||||||
func (s *v4Server) GetLeases(flags int) []Lease {
|
func (s *v4Server) GetLeases(flags int) []Lease {
|
||||||
var result []Lease
|
// The function shouldn't return nil value because zero-length slice
|
||||||
|
// behaves differently in cases like marshalling. Our front-end also
|
||||||
|
// requires non-nil value in the response.
|
||||||
|
result := []Lease{}
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
|
|
||||||
s.leasesLock.Lock()
|
s.leasesLock.Lock()
|
||||||
|
|
|
@ -72,7 +72,10 @@ func (s *v6Server) ResetLeases(ll []*Lease) {
|
||||||
|
|
||||||
// GetLeases - get current leases
|
// GetLeases - get current leases
|
||||||
func (s *v6Server) GetLeases(flags int) []Lease {
|
func (s *v6Server) GetLeases(flags int) []Lease {
|
||||||
var result []Lease
|
// The function shouldn't return nil value because zero-length slice
|
||||||
|
// behaves differently in cases like marshalling. Our front-end also
|
||||||
|
// requires non-nil value in the response.
|
||||||
|
result := []Lease{}
|
||||||
s.leasesLock.Lock()
|
s.leasesLock.Lock()
|
||||||
for _, lease := range s.leases {
|
for _, lease := range s.leases {
|
||||||
if lease.Expiry.Unix() == leaseExpireStatic {
|
if lease.Expiry.Unix() == leaseExpireStatic {
|
||||||
|
|
|
@ -346,16 +346,12 @@ func (d *DNSFilter) handleSafeBrowsingDisable(w http.ResponseWriter, r *http.Req
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNSFilter) handleSafeBrowsingStatus(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleSafeBrowsingStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
data := map[string]interface{}{
|
|
||||||
"enabled": d.Config.SafeBrowsingEnabled,
|
|
||||||
}
|
|
||||||
jsonVal, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
httpError(r, w, http.StatusInternalServerError, "Unable to marshal status json: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_, err = w.Write(jsonVal)
|
err := json.NewEncoder(w).Encode(&struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
}{
|
||||||
|
Enabled: d.Config.SafeBrowsingEnabled,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(r, w, http.StatusInternalServerError, "Unable to write response json: %s", err)
|
httpError(r, w, http.StatusInternalServerError, "Unable to write response json: %s", err)
|
||||||
return
|
return
|
||||||
|
@ -373,17 +369,12 @@ func (d *DNSFilter) handleParentalDisable(w http.ResponseWriter, r *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNSFilter) handleParentalStatus(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleParentalStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
data := map[string]interface{}{
|
|
||||||
"enabled": d.Config.ParentalEnabled,
|
|
||||||
}
|
|
||||||
jsonVal, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
httpError(r, w, http.StatusInternalServerError, "Unable to marshal status json: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_, err = w.Write(jsonVal)
|
err := json.NewEncoder(w).Encode(&struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
}{
|
||||||
|
Enabled: d.Config.ParentalEnabled,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(r, w, http.StatusInternalServerError, "Unable to write response json: %s", err)
|
httpError(r, w, http.StatusInternalServerError, "Unable to write response json: %s", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -133,17 +133,12 @@ func (d *DNSFilter) handleSafeSearchDisable(w http.ResponseWriter, r *http.Reque
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNSFilter) handleSafeSearchStatus(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleSafeSearchStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
data := map[string]interface{}{
|
|
||||||
"enabled": d.Config.SafeSearchEnabled,
|
|
||||||
}
|
|
||||||
jsonVal, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
httpError(r, w, http.StatusInternalServerError, "Unable to marshal status json: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_, err = w.Write(jsonVal)
|
err := json.NewEncoder(w).Encode(&struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
}{
|
||||||
|
Enabled: d.Config.SafeSearchEnabled,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(r, w, http.StatusInternalServerError, "Unable to write response json: %s", err)
|
httpError(r, w, http.StatusInternalServerError, "Unable to write response json: %s", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -350,7 +350,26 @@
|
||||||
'application/json':
|
'application/json':
|
||||||
'schema':
|
'schema':
|
||||||
'$ref': '#/components/schemas/DhcpStatus'
|
'$ref': '#/components/schemas/DhcpStatus'
|
||||||
'501':
|
'500':
|
||||||
|
'content':
|
||||||
|
'application/json':
|
||||||
|
'schema':
|
||||||
|
'$ref': '#/components/schemas/Error'
|
||||||
|
'description': 'Not implemented (for example, on Windows).'
|
||||||
|
'/dhcp/interfaces':
|
||||||
|
'get':
|
||||||
|
'tags':
|
||||||
|
- 'dhcp'
|
||||||
|
'operationId': 'dhcpInterfaces'
|
||||||
|
'summary': 'Gets the available interfaces'
|
||||||
|
'responses':
|
||||||
|
'200':
|
||||||
|
'description': 'OK.'
|
||||||
|
'content':
|
||||||
|
'application/json':
|
||||||
|
'schema':
|
||||||
|
'$ref': '#/components/schemas/NetInterfaces'
|
||||||
|
'500':
|
||||||
'content':
|
'content':
|
||||||
'application/json':
|
'application/json':
|
||||||
'schema':
|
'schema':
|
||||||
|
@ -1620,6 +1639,12 @@
|
||||||
'type': 'array'
|
'type': 'array'
|
||||||
'items':
|
'items':
|
||||||
'$ref': '#/components/schemas/DhcpStaticLease'
|
'$ref': '#/components/schemas/DhcpStaticLease'
|
||||||
|
'NetInterfaces':
|
||||||
|
'type': 'object'
|
||||||
|
'description': >
|
||||||
|
Network interfaces dictionary, keys are interface names.
|
||||||
|
'additionalProperties':
|
||||||
|
'$ref': '#/components/schemas/NetInterface'
|
||||||
|
|
||||||
'DhcpSearchResult':
|
'DhcpSearchResult':
|
||||||
'type': 'object'
|
'type': 'object'
|
||||||
|
@ -1650,7 +1675,12 @@
|
||||||
'properties':
|
'properties':
|
||||||
'found':
|
'found':
|
||||||
'type': 'string'
|
'type': 'string'
|
||||||
'description': 'yes|no|error'
|
'enum':
|
||||||
|
- 'yes'
|
||||||
|
- 'no'
|
||||||
|
- 'error'
|
||||||
|
'description': >
|
||||||
|
The result of searching the other DHCP server.
|
||||||
'example': 'no'
|
'example': 'no'
|
||||||
'error':
|
'error':
|
||||||
'type': 'string'
|
'type': 'string'
|
||||||
|
@ -1662,7 +1692,12 @@
|
||||||
'properties':
|
'properties':
|
||||||
'static':
|
'static':
|
||||||
'type': 'string'
|
'type': 'string'
|
||||||
'description': 'yes|no|error'
|
'enum':
|
||||||
|
- 'yes'
|
||||||
|
- 'no'
|
||||||
|
- 'error'
|
||||||
|
'description': >
|
||||||
|
The result of determining static IP address.
|
||||||
'example': 'yes'
|
'example': 'yes'
|
||||||
'ip':
|
'ip':
|
||||||
'type': 'string'
|
'type': 'string'
|
||||||
|
@ -2015,11 +2050,7 @@
|
||||||
'format': 'uint16'
|
'format': 'uint16'
|
||||||
'example': 80
|
'example': 80
|
||||||
'interfaces':
|
'interfaces':
|
||||||
'type': 'object'
|
'$ref': '#/components/schemas/NetInterfaces'
|
||||||
'description': >
|
|
||||||
Network interfaces dictionary, keys are interface names.
|
|
||||||
'additionalProperties':
|
|
||||||
'$ref': '#/components/schemas/NetInterface'
|
|
||||||
'AddressesInfoBeta':
|
'AddressesInfoBeta':
|
||||||
'type': 'object'
|
'type': 'object'
|
||||||
'description': 'AdGuard Home addresses configuration'
|
'description': 'AdGuard Home addresses configuration'
|
||||||
|
|
Loading…
Reference in New Issue