Compare commits
6 Commits
4927-refac
...
1464-owrt-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da2a8daff2 | ||
|
|
5fbf28b9cf | ||
|
|
dced8a5a83 | ||
|
|
33a98aa937 | ||
|
|
e822443600 | ||
|
|
82f36341e3 |
@@ -64,6 +64,7 @@ Contents:
|
||||
* API: Log in
|
||||
* API: Log out
|
||||
* API: Get current user info
|
||||
* Replace dnsmasq on OpenWRT
|
||||
|
||||
|
||||
## Relations between subsystems
|
||||
@@ -1594,3 +1595,70 @@ Response:
|
||||
}
|
||||
|
||||
If no client is configured then authentication is disabled and server sends an empty response.
|
||||
|
||||
|
||||
## Replace dnsmasq on OpenWRT
|
||||
|
||||
`/etc/init.d/dnsmasq` script creates a dnsmasq.conf file and then starts dnsmasq.
|
||||
To replace dnsmasq we have to read system configuration files and update (create new, if necessary) our .yaml file accordingly.
|
||||
|
||||
If started as:
|
||||
|
||||
./AdGuardHome --import-openwrt-config
|
||||
|
||||
* Read `/etc/config/network`:
|
||||
|
||||
config interface 'lan'
|
||||
option netmask '255.255.255.0'
|
||||
option ipaddr '192.168.8.1'
|
||||
|
||||
* Read `/etc/config/dhcp`:
|
||||
|
||||
config dhcp 'lan'
|
||||
option start '100'
|
||||
option limit '150'
|
||||
option leasetime '12h'
|
||||
|
||||
config dnsmasq
|
||||
option leasefile '/tmp/dhcp.leases'
|
||||
|
||||
* Write this yaml configuration:
|
||||
|
||||
dhcp:
|
||||
enabled: true
|
||||
interface_name: "br-lan"
|
||||
gateway_ip: "192.168.8.1"
|
||||
subnet_mask: "255.255.255.0"
|
||||
range_start: "192.168.8.100"
|
||||
range_end: "192.168.8.249"
|
||||
lease_duration: 86400
|
||||
icmp_timeout_msec: 1000
|
||||
dnsmasq_leasefile "/tmp/dhcp.leases"
|
||||
|
||||
* Read `/etc/config/dhcp`:
|
||||
|
||||
config host '123412341234'
|
||||
option mac '12:34:12:34:12:34'
|
||||
option ip '192.168.8.2'
|
||||
option name 'hostname'
|
||||
|
||||
* Add a static lease to leases.db:
|
||||
|
||||
12:34:12:34:12:34 | 192.168.8.2 | hostname
|
||||
|
||||
* Read `/etc/resolv.conf`:
|
||||
|
||||
nameserver <IP1>
|
||||
nameserver <IP2>
|
||||
|
||||
* Write this yaml configuration:
|
||||
|
||||
dns:
|
||||
bootstrap_dns:
|
||||
- IP1
|
||||
- IP2
|
||||
|
||||
And service script starts AGH like this:
|
||||
|
||||
.../AdGuardHome --import-openwrt-config
|
||||
.../AdGuardHome
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/golibs/file"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/krolaw/dhcp4"
|
||||
ping "github.com/sparrc/go-ping"
|
||||
@@ -43,6 +44,9 @@ type ServerConfig struct {
|
||||
RangeEnd string `json:"range_end" yaml:"range_end"`
|
||||
LeaseDuration uint32 `json:"lease_duration" yaml:"lease_duration"` // in seconds
|
||||
|
||||
// File path to an additional leases file in dnsmasq format
|
||||
DnsmasqFilePath string `json:"-" yaml:"dnsmasq_leasefile"`
|
||||
|
||||
// IP conflict detector: time (ms) to wait for ICMP reply.
|
||||
// 0: disable
|
||||
ICMPTimeout uint32 `json:"icmp_timeout_msec" yaml:"icmp_timeout_msec"`
|
||||
@@ -139,12 +143,59 @@ func (s *Server) Init(config ServerConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Save - save leases in DB
|
||||
func (s *Server) Save() {
|
||||
s.dbStore()
|
||||
}
|
||||
|
||||
// SetOnLeaseChanged - set callback
|
||||
func (s *Server) SetOnLeaseChanged(onLeaseChanged onLeaseChangedT) {
|
||||
s.onLeaseChanged = onLeaseChanged
|
||||
}
|
||||
|
||||
// Write DHCP leases in dnsmasq format
|
||||
// Format: UNIX_TIME MAC IP HOSTNAME CLIENT_ID
|
||||
func writeDnsmasqLeases(leases []Lease) string {
|
||||
s := ""
|
||||
|
||||
for _, l := range leases {
|
||||
|
||||
t := l.Expiry.Unix()
|
||||
if t == leaseExpireStatic {
|
||||
t = 0
|
||||
}
|
||||
|
||||
host := l.Hostname
|
||||
if len(host) == 0 {
|
||||
host = "*"
|
||||
}
|
||||
|
||||
cid := "*"
|
||||
|
||||
s += fmt.Sprintf("%d %s %s %s %s\n",
|
||||
t, l.HWAddr.String(), l.IP.String(), host, cid)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Server) notify(flags int) {
|
||||
if len(s.conf.DnsmasqFilePath) != 0 {
|
||||
switch flags {
|
||||
case LeaseChangedAdded:
|
||||
fallthrough
|
||||
case LeaseChangedAddedStatic:
|
||||
fallthrough
|
||||
case LeaseChangedRemovedStatic:
|
||||
l := s.Leases(LeasesAll)
|
||||
data := writeDnsmasqLeases(l)
|
||||
err := file.SafeWrite(s.conf.DnsmasqFilePath, []byte(data))
|
||||
if err != nil {
|
||||
log.Error("file write: %s: %s", s.conf.DnsmasqFilePath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if s.onLeaseChanged == nil {
|
||||
return
|
||||
}
|
||||
@@ -608,6 +659,11 @@ func (s *Server) handleDecline(p dhcp4.Packet, options dhcp4.Options) dhcp4.Pack
|
||||
|
||||
// AddStaticLease adds a static lease (thread-safe)
|
||||
func (s *Server) AddStaticLease(l Lease) error {
|
||||
return s.AddStaticLeaseWithFlags(l, true)
|
||||
}
|
||||
|
||||
// AddStaticLeaseWithFlags - add a static lease (thread-safe)
|
||||
func (s *Server) AddStaticLeaseWithFlags(l Lease, flush bool) error {
|
||||
if len(l.IP) != 4 {
|
||||
return fmt.Errorf("Invalid IP")
|
||||
}
|
||||
@@ -627,7 +683,9 @@ func (s *Server) AddStaticLease(l Lease) error {
|
||||
}
|
||||
s.leases = append(s.leases, &l)
|
||||
s.reserveIP(l.IP, l.HWAddr)
|
||||
s.dbStore()
|
||||
if flush {
|
||||
s.dbStore()
|
||||
}
|
||||
s.leasesLock.Unlock()
|
||||
s.notify(LeaseChangedAddedStatic)
|
||||
return nil
|
||||
|
||||
@@ -242,3 +242,15 @@ func TestNormalizeLeases(t *testing.T) {
|
||||
assert.True(t, bytes.Equal(leases[1].HWAddr, []byte{2, 2, 3, 4}))
|
||||
assert.True(t, bytes.Equal(leases[2].HWAddr, []byte{1, 2, 3, 5}))
|
||||
}
|
||||
|
||||
func TestWriteDnsmasqLeases(t *testing.T) {
|
||||
leases := []Lease{}
|
||||
l := Lease{}
|
||||
l.Expiry = time.Unix(1587559766, 0)
|
||||
l.HWAddr, _ = net.ParseMAC("12:34:12:34:12:34")
|
||||
l.IP = net.ParseIP("192.168.8.2")
|
||||
l.Hostname = "hostname"
|
||||
leases = append(leases, l)
|
||||
data := "1587559766 12:34:12:34:12:34 192.168.8.2 hostname *\n"
|
||||
assert.Equal(t, data, writeDnsmasqLeases(leases))
|
||||
}
|
||||
|
||||
22
home/home.go
22
home/home.go
@@ -138,12 +138,9 @@ func Main(version string, channel string, armVer string) {
|
||||
// run is a blocking method!
|
||||
// nolint
|
||||
func run(args options) {
|
||||
// config file path can be overridden by command-line arguments:
|
||||
Context.configFilename = "AdGuardHome.yaml"
|
||||
if args.configFilename != "" {
|
||||
Context.configFilename = args.configFilename
|
||||
} else {
|
||||
// Default config file name
|
||||
Context.configFilename = "AdGuardHome.yaml"
|
||||
}
|
||||
|
||||
// configure working dir and config path
|
||||
@@ -460,6 +457,8 @@ type options struct {
|
||||
checkConfig bool // Check configuration and exit
|
||||
disableUpdate bool // If set, don't check for updates
|
||||
|
||||
hasImportOpenwrtConfig bool // 'import-openwrt-config' argument is specified
|
||||
|
||||
// service control action (see service.ControlAction array + "status" command)
|
||||
serviceControlAction string
|
||||
|
||||
@@ -498,6 +497,9 @@ func loadOptions() options {
|
||||
{"pidfile", "", "Path to a file where PID is stored", func(value string) { o.pidFile = value }, nil},
|
||||
{"check-config", "", "Check configuration and exit", nil, func() { o.checkConfig = true }},
|
||||
{"no-check-update", "", "Don't check for updates", nil, func() { o.disableUpdate = true }},
|
||||
{"import-openwrt-config", "", "Create or update YAML configuration file from OpenWRT system configuration", nil, func() {
|
||||
o.hasImportOpenwrtConfig = true
|
||||
}},
|
||||
{"verbose", "v", "Enable verbose output", nil, func() { o.verbose = true }},
|
||||
{"version", "", "Show the version and exit", nil, func() {
|
||||
fmt.Printf("AdGuardHome %s\n", versionString)
|
||||
@@ -550,6 +552,18 @@ func loadOptions() options {
|
||||
}
|
||||
}
|
||||
|
||||
if o.verbose {
|
||||
log.SetLevel(log.DEBUG)
|
||||
}
|
||||
|
||||
if o.hasImportOpenwrtConfig {
|
||||
err := importOpenwrtConfig(o.configFilename)
|
||||
if err != nil {
|
||||
log.Fatalf("%s", err)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
|
||||
364
home/openwrt.go
Normal file
364
home/openwrt.go
Normal file
@@ -0,0 +1,364 @@
|
||||
package home
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/dhcpd"
|
||||
"github.com/AdguardTeam/AdGuardHome/util"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
)
|
||||
|
||||
type openwrtConfig struct {
|
||||
// network:
|
||||
netmask string
|
||||
ipaddr string
|
||||
|
||||
// dhcp:
|
||||
dhcpStart string
|
||||
dhcpLimit string
|
||||
dhcpLeasetime string
|
||||
dhcpDnsmasqLeaseFile string
|
||||
|
||||
// dhcp static leases:
|
||||
leases []dhcpd.Lease
|
||||
|
||||
// resolv.conf:
|
||||
nameservers []string
|
||||
|
||||
// yaml.dhcp:
|
||||
iface string
|
||||
gwIP string
|
||||
snMask string
|
||||
rangeStart string
|
||||
rangeEnd string
|
||||
leaseDur uint32
|
||||
|
||||
// yaml.dns.bootstrap_dns:
|
||||
bsDNS []string
|
||||
}
|
||||
|
||||
// Parse command line: "option name 'value'"
|
||||
func parseCmd(line string) (string, string, string) {
|
||||
word1 := util.SplitNext(&line, ' ')
|
||||
word2 := util.SplitNext(&line, ' ')
|
||||
word3 := util.SplitNext(&line, ' ')
|
||||
if len(word3) > 2 && word3[0] == '\'' && word3[len(word3)-1] == '\'' {
|
||||
// 'value' -> value
|
||||
word3 = word3[1:]
|
||||
word3 = word3[:len(word3)-1]
|
||||
}
|
||||
return word1, word2, word3
|
||||
}
|
||||
|
||||
// Parse system configuration data
|
||||
// nolint(gocyclo)
|
||||
func (oc *openwrtConfig) readConf(data []byte, section string, iface string) {
|
||||
state := 0
|
||||
sr := strings.NewReader(string(data))
|
||||
r := bufio.NewReader(sr)
|
||||
for {
|
||||
line, err := r.ReadString('\n')
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) == 0 {
|
||||
if state >= 2 {
|
||||
return
|
||||
}
|
||||
state = 0
|
||||
}
|
||||
|
||||
word1, word2, word3 := parseCmd(line)
|
||||
|
||||
switch state {
|
||||
case 0:
|
||||
if word1 == "config" {
|
||||
state = 1
|
||||
if word2 == section && word3 == iface {
|
||||
// found the needed section
|
||||
if word2 == "interface" {
|
||||
state = 2 // found the needed interface
|
||||
} else if word2 == "dhcp" {
|
||||
state = 3
|
||||
} else if word2 == "dnsmasq" {
|
||||
state = 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case 1:
|
||||
// not interested
|
||||
break
|
||||
|
||||
case 2:
|
||||
if word1 != "option" {
|
||||
break
|
||||
}
|
||||
switch word2 {
|
||||
case "netmask":
|
||||
oc.netmask = word3
|
||||
case "ipaddr":
|
||||
oc.ipaddr = word3
|
||||
}
|
||||
|
||||
case 3:
|
||||
if word1 != "option" {
|
||||
break
|
||||
}
|
||||
switch word2 {
|
||||
case "start":
|
||||
oc.dhcpStart = word3
|
||||
case "limit":
|
||||
oc.dhcpLimit = word3
|
||||
case "leasetime":
|
||||
oc.dhcpLeasetime = word3
|
||||
}
|
||||
|
||||
case 4:
|
||||
if word1 != "option" {
|
||||
break
|
||||
}
|
||||
switch word2 {
|
||||
case "leasefile":
|
||||
oc.dhcpDnsmasqLeaseFile = word3
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse static DHCP leases from system configuration data
|
||||
func (oc *openwrtConfig) readConfDHCPStatic(data []byte) error {
|
||||
state := 0
|
||||
sr := strings.NewReader(string(data))
|
||||
r := bufio.NewReader(sr)
|
||||
lease := dhcpd.Lease{}
|
||||
for {
|
||||
line, err := r.ReadString('\n')
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) == 0 {
|
||||
if len(lease.HWAddr) != 0 && len(lease.IP) != 0 {
|
||||
oc.leases = append(oc.leases, lease)
|
||||
}
|
||||
lease = dhcpd.Lease{}
|
||||
state = 0
|
||||
}
|
||||
|
||||
word1, word2, word3 := parseCmd(line)
|
||||
|
||||
switch state {
|
||||
case 0:
|
||||
if word1 == "config" {
|
||||
state = 1
|
||||
if word2 == "host" {
|
||||
state = 2
|
||||
}
|
||||
}
|
||||
|
||||
case 1:
|
||||
// not interested
|
||||
break
|
||||
|
||||
case 2:
|
||||
if word1 != "option" {
|
||||
break
|
||||
}
|
||||
switch word2 {
|
||||
case "mac":
|
||||
lease.HWAddr, err = net.ParseMAC(word3)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case "ip":
|
||||
lease.IP = net.ParseIP(word3)
|
||||
if lease.IP == nil || lease.IP.To4() == nil {
|
||||
return fmt.Errorf("Invalid IP address")
|
||||
}
|
||||
|
||||
case "name":
|
||||
lease.Hostname = word3
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(lease.HWAddr) != 0 && len(lease.IP) != 0 {
|
||||
oc.leases = append(oc.leases, lease)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parse "/etc/resolv.conf" data
|
||||
func (oc *openwrtConfig) readResolvConf(data []byte) {
|
||||
lines := string(data)
|
||||
|
||||
for len(lines) != 0 {
|
||||
line := util.SplitNext(&lines, '\n')
|
||||
key := util.SplitNext(&line, ' ')
|
||||
if key == "nameserver" {
|
||||
val := util.SplitNext(&line, ' ')
|
||||
oc.nameservers = append(oc.nameservers, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert system config parameters to our yaml config format
|
||||
func (oc *openwrtConfig) prepareOutput() error {
|
||||
oc.iface = "br-lan"
|
||||
|
||||
ipAddr := net.ParseIP(oc.ipaddr)
|
||||
if ipAddr == nil || ipAddr.To4() == nil {
|
||||
return fmt.Errorf("Invalid IP: %s", oc.ipaddr)
|
||||
}
|
||||
oc.gwIP = oc.ipaddr
|
||||
|
||||
ip := net.ParseIP(oc.netmask)
|
||||
if ip == nil || ip.To4() == nil {
|
||||
return fmt.Errorf("Invalid IP: %s", oc.netmask)
|
||||
}
|
||||
oc.snMask = oc.netmask
|
||||
|
||||
nStart, err := strconv.Atoi(oc.dhcpStart)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid 'start': %s", oc.dhcpStart)
|
||||
}
|
||||
rangeStart := make(net.IP, 4)
|
||||
copy(rangeStart, ipAddr.To4())
|
||||
rangeStart[3] = byte(nStart)
|
||||
oc.rangeStart = rangeStart.String()
|
||||
|
||||
nLim, err := strconv.Atoi(oc.dhcpLimit)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid 'start': %s", oc.dhcpLimit)
|
||||
}
|
||||
n := nStart + nLim - 1
|
||||
if n <= 0 || n > 255 {
|
||||
return fmt.Errorf("Invalid 'start' or 'limit': %s/%s", oc.dhcpStart, oc.dhcpLimit)
|
||||
}
|
||||
rangeEnd := make(net.IP, 4)
|
||||
copy(rangeEnd, ipAddr.To4())
|
||||
rangeEnd[3] = byte(n)
|
||||
oc.rangeEnd = rangeEnd.String()
|
||||
|
||||
if len(oc.dhcpLeasetime) == 0 || oc.dhcpLeasetime[len(oc.dhcpLeasetime)-1] != 'h' {
|
||||
return fmt.Errorf("Invalid leasetime: %s", oc.dhcpLeasetime)
|
||||
}
|
||||
n, err = strconv.Atoi(oc.dhcpLeasetime[:len(oc.dhcpLeasetime)-1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid leasetime: %s", oc.dhcpLeasetime)
|
||||
}
|
||||
oc.leaseDur = uint32(n) * 60 * 60
|
||||
|
||||
for _, s := range oc.nameservers {
|
||||
if net.ParseIP(s) == nil {
|
||||
continue
|
||||
}
|
||||
oc.bsDNS = append(oc.bsDNS, s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Process - read and process system configuration data
|
||||
func (oc *openwrtConfig) Process() error {
|
||||
data, err := ioutil.ReadFile("/etc/config/network")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oc.readConf(data, "interface", "lan")
|
||||
|
||||
data, err = ioutil.ReadFile("/etc/config/dhcp")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oc.readConf(data, "dhcp", "lan")
|
||||
oc.readConf(data, "dnsmasq", "")
|
||||
|
||||
err = oc.prepareOutput()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = oc.readConfDHCPStatic(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read system configuration files and write our configuration files
|
||||
func importOpenwrtConfig(configFn string) error {
|
||||
oc := openwrtConfig{}
|
||||
err := oc.Process()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// config file path can be overridden by command-line arguments:
|
||||
Context.configFilename = "AdGuardHome.yaml"
|
||||
if len(configFn) != 0 {
|
||||
Context.configFilename = configFn
|
||||
}
|
||||
|
||||
initConfig()
|
||||
if util.FileExists(config.getConfigFilename()) {
|
||||
err = upgradeConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = parseConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
config.DNS.BootstrapDNS = oc.bsDNS
|
||||
|
||||
config.DHCP.Enabled = true
|
||||
config.DHCP.InterfaceName = oc.iface
|
||||
config.DHCP.GatewayIP = oc.gwIP
|
||||
config.DHCP.SubnetMask = oc.snMask
|
||||
config.DHCP.RangeStart = oc.rangeStart
|
||||
config.DHCP.RangeEnd = oc.rangeEnd
|
||||
config.DHCP.LeaseDuration = oc.leaseDur
|
||||
config.DHCP.DnsmasqFilePath = oc.dhcpDnsmasqLeaseFile
|
||||
|
||||
err = config.write()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dconf := dhcpd.ServerConfig{
|
||||
WorkDir: Context.workDir,
|
||||
}
|
||||
ds := dhcpd.Create(dconf)
|
||||
if ds == nil {
|
||||
return fmt.Errorf("can't initialize DHCP module")
|
||||
}
|
||||
for _, ocl := range oc.leases {
|
||||
l := dhcpd.Lease{
|
||||
HWAddr: ocl.HWAddr,
|
||||
IP: ocl.IP.To4(),
|
||||
Hostname: ocl.Hostname,
|
||||
}
|
||||
err = ds.AddStaticLeaseWithFlags(l, false)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
log.Debug("Static DHCP lease: %s -> %s (%s)",
|
||||
l.HWAddr, l.IP, l.Hostname)
|
||||
}
|
||||
ds.Save()
|
||||
|
||||
return nil
|
||||
}
|
||||
104
home/openwrt_test.go
Normal file
104
home/openwrt_test.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package home
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestReadConf(t *testing.T) {
|
||||
oc := openwrtConfig{}
|
||||
|
||||
// "interface"
|
||||
data := []byte(` config interface 'lan'
|
||||
option netmask '255.255.255.0'
|
||||
option ipaddr '192.168.8.1'`)
|
||||
oc.readConf(data, "interface", "lan")
|
||||
assert.Equal(t, "255.255.255.0", oc.netmask)
|
||||
assert.Equal(t, "192.168.8.1", oc.ipaddr)
|
||||
|
||||
// "dhcp"
|
||||
data = []byte(` config dhcp 'unknown'
|
||||
|
||||
config dhcp 'lan'
|
||||
option start '100'
|
||||
option limit '150'
|
||||
option leasetime '12h'
|
||||
|
||||
config dhcp 'unknown'`)
|
||||
oc.readConf(data, "dhcp", "lan")
|
||||
assert.Equal(t, "100", oc.dhcpStart)
|
||||
assert.Equal(t, "150", oc.dhcpLimit)
|
||||
assert.Equal(t, "12h", oc.dhcpLeasetime)
|
||||
|
||||
// resolv.conf
|
||||
data = []byte(` # comment
|
||||
nameserver abab::1234
|
||||
|
||||
nameserver 1.2.3.4`)
|
||||
oc.readResolvConf(data)
|
||||
assert.Equal(t, "abab::1234", oc.nameservers[0])
|
||||
assert.Equal(t, "1.2.3.4", oc.nameservers[1])
|
||||
|
||||
// prepareOutput()
|
||||
err := oc.prepareOutput()
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, "br-lan", oc.iface)
|
||||
assert.Equal(t, "192.168.8.1", oc.gwIP)
|
||||
assert.Equal(t, "255.255.255.0", oc.snMask)
|
||||
assert.Equal(t, "192.168.8.100", oc.rangeStart)
|
||||
assert.Equal(t, "192.168.8.249", oc.rangeEnd)
|
||||
assert.Equal(t, uint32(43200), oc.leaseDur)
|
||||
assert.Equal(t, "abab::1234", oc.bsDNS[0])
|
||||
assert.Equal(t, "1.2.3.4", oc.bsDNS[1])
|
||||
|
||||
tmp := oc.ipaddr
|
||||
oc.dhcpStart = "invalid" // not an IP
|
||||
assert.True(t, oc.prepareOutput() != nil)
|
||||
oc.ipaddr = tmp
|
||||
|
||||
tmp = oc.dhcpStart
|
||||
oc.dhcpStart = "invalid" // not an integer
|
||||
assert.True(t, oc.prepareOutput() != nil)
|
||||
oc.dhcpStart = "256" //byte overflow
|
||||
assert.True(t, oc.prepareOutput() != nil)
|
||||
oc.dhcpStart = tmp
|
||||
|
||||
tmp = oc.dhcpLimit
|
||||
oc.dhcpLimit = "invalid" // not an integer
|
||||
assert.True(t, oc.prepareOutput() != nil)
|
||||
oc.dhcpLimit = "200" //byte overflow
|
||||
assert.True(t, oc.prepareOutput() != nil)
|
||||
oc.dhcpLimit = tmp
|
||||
|
||||
tmp = oc.dhcpLeasetime
|
||||
oc.dhcpLeasetime = "12m" // not an 'h'
|
||||
assert.True(t, oc.prepareOutput() != nil)
|
||||
oc.dhcpLeasetime = "invalid" // not an integer
|
||||
assert.True(t, oc.prepareOutput() != nil)
|
||||
oc.dhcpLeasetime = tmp
|
||||
|
||||
// dhcp static leases
|
||||
data = []byte(`config host '123412341234'
|
||||
option mac '12:34:12:34:12:34'
|
||||
option ip '192.168.8.2'
|
||||
option name 'hostname'`)
|
||||
assert.True(t, nil == oc.readConfDHCPStatic(data))
|
||||
assert.Equal(t, 1, len(oc.leases))
|
||||
assert.Equal(t, "12:34:12:34:12:34", oc.leases[0].HWAddr.String())
|
||||
assert.Equal(t, "192.168.8.2", oc.leases[0].IP.String())
|
||||
assert.Equal(t, "hostname", oc.leases[0].Hostname)
|
||||
|
||||
// "dnsmasq"
|
||||
// Note: "config dnsmasq ''" will also work
|
||||
data = []byte(`
|
||||
config dhcp 'unknown'
|
||||
option asdf '100'
|
||||
|
||||
config dnsmasq
|
||||
option asdf '100'
|
||||
option leasefile '/tmp/dhcp.leases'
|
||||
option leasetime '12h'`)
|
||||
oc.readConf(data, "dnsmasq", "")
|
||||
assert.Equal(t, "/tmp/dhcp.leases", oc.dhcpDnsmasqLeaseFile)
|
||||
}
|
||||
Reference in New Issue
Block a user