Compare commits
16 Commits
fix-client
...
v0.105.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1789c96c7f | ||
|
|
8811c8817e | ||
|
|
5aa0ca9319 | ||
|
|
90054974bc | ||
|
|
9f774d776c | ||
|
|
8ead755b67 | ||
|
|
90ebc4d8c9 | ||
|
|
400b76d47b | ||
|
|
8aa8be2921 | ||
|
|
52575d0247 | ||
|
|
7e1b4ca6fe | ||
|
|
a234b63da1 | ||
|
|
94e783d572 | ||
|
|
91403d0b95 | ||
|
|
d6a059e395 | ||
|
|
f893df7e64 |
26
CHANGELOG.md
26
CHANGELOG.md
@@ -13,19 +13,32 @@ and this project adheres to
|
||||
## [v0.106.0] - 2021-04-26
|
||||
-->
|
||||
|
||||
<!--
|
||||
## [v0.105.2] - 2021-02-24
|
||||
-->
|
||||
## [v0.105.2] - 2021-03-10
|
||||
|
||||
### Fixed
|
||||
|
||||
- Incomplete hostnames with trailing zero-bytes handling ([#2582]).
|
||||
- Wrong DNS-over-TLS ALPN configuration ([#2681]).
|
||||
- Inconsistent responses for messages with EDNS0 and AD when DNS caching is
|
||||
enabled ([#2600]).
|
||||
- Incomplete OpenWRT detection ([#2757]).
|
||||
- DHCP lease's `expired` field incorrect time format ([#2692]).
|
||||
- Incomplete DNS upstreams validation ([#2674]).
|
||||
- Wrong parsing of DHCP options of the `ip` type ([#2688]).
|
||||
|
||||
[#2582]: https://github.com/AdguardTeam/AdGuardHome/issues/2582
|
||||
[#2600]: https://github.com/AdguardTeam/AdGuardHome/issues/2600
|
||||
[#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674
|
||||
[#2681]: https://github.com/AdguardTeam/AdGuardHome/issues/2681
|
||||
[#2688]: https://github.com/AdguardTeam/AdGuardHome/issues/2688
|
||||
[#2692]: https://github.com/AdguardTeam/AdGuardHome/issues/2692
|
||||
[#2757]: https://github.com/AdguardTeam/AdGuardHome/issues/2757
|
||||
|
||||
### Security
|
||||
|
||||
- Session token doesn't contain user's information anymore ([#2470]).
|
||||
|
||||
[#2470]: https://github.com/AdguardTeam/AdGuardHome/issues/2470
|
||||
|
||||
|
||||
|
||||
@@ -210,11 +223,12 @@ and this project adheres to
|
||||
|
||||
|
||||
<!--
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.2...HEAD
|
||||
[v0.105.2]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.1...v0.105.2
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.106.0...HEAD
|
||||
[v0.106.0]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.2...v0.106.0
|
||||
-->
|
||||
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.1...HEAD
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.2...HEAD
|
||||
[v0.105.2]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.1...v0.105.2
|
||||
[v0.105.1]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.0...v0.105.1
|
||||
[v0.105.0]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.104.3...v0.105.0
|
||||
[v0.104.3]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.104.2...v0.104.3
|
||||
|
||||
@@ -3,7 +3,7 @@ import React, {
|
||||
useEffect,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import propTypes from 'prop-types';
|
||||
import throttle from 'lodash/throttle';
|
||||
@@ -25,19 +25,21 @@ const InfiniteTable = ({
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const loader = useRef(null);
|
||||
const loadingRef = useRef(null);
|
||||
|
||||
const {
|
||||
isEntireLog,
|
||||
processingGetLogs,
|
||||
} = useSelector((state) => state.queryLogs, shallowEqual);
|
||||
|
||||
const isEntireLog = useSelector((state) => state.queryLogs.isEntireLog);
|
||||
const processingGetLogs = useSelector((state) => state.queryLogs.processingGetLogs);
|
||||
const loading = isLoading || processingGetLogs;
|
||||
|
||||
const listener = useCallback(() => {
|
||||
if (loader.current && isScrolledIntoView(loader.current)) {
|
||||
if (!loadingRef.current && loader.current && isScrolledIntoView(loader.current)) {
|
||||
dispatch(getLogs());
|
||||
}
|
||||
}, [loader.current, isScrolledIntoView, getLogs]);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
loadingRef.current = processingGetLogs;
|
||||
}, [processingGetLogs]);
|
||||
|
||||
useEffect(() => {
|
||||
listener();
|
||||
|
||||
2
go.mod
2
go.mod
@@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/AdguardTeam/dnsproxy v0.33.9
|
||||
github.com/AdguardTeam/dnsproxy v0.35.5
|
||||
github.com/AdguardTeam/golibs v0.4.4
|
||||
github.com/AdguardTeam/urlfilter v0.14.3
|
||||
github.com/NYTimes/gziphandler v1.1.1
|
||||
|
||||
4
go.sum
4
go.sum
@@ -18,8 +18,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
|
||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/AdguardTeam/dnsproxy v0.33.9 h1:HUwywkhUV/M73E7qWcBAF+SdsNq742s82Lvox4pr/tM=
|
||||
github.com/AdguardTeam/dnsproxy v0.33.9/go.mod h1:dkI9VWh43XlOzF2XogDm1EmoVl7PANOR4isQV6X9LZs=
|
||||
github.com/AdguardTeam/dnsproxy v0.35.5 h1:SsRF0eDzuLGaSUDKABIu9Mn1joi4v4kvEU1vju2DQPQ=
|
||||
github.com/AdguardTeam/dnsproxy v0.35.5/go.mod h1:dkI9VWh43XlOzF2XogDm1EmoVl7PANOR4isQV6X9LZs=
|
||||
github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
||||
github.com/AdguardTeam/golibs v0.4.2 h1:7M28oTZFoFwNmp8eGPb3ImmYbxGaJLyQXeIFVHjME0o=
|
||||
github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -463,7 +464,16 @@ func (s *v4Server) processRequest(req, resp *dhcpv4.DHCPv4) (*Lease, bool) {
|
||||
}
|
||||
|
||||
if lease.Expiry.Unix() != leaseExpireStatic {
|
||||
lease.Hostname = string(hostname)
|
||||
// The trimming is required since some devices include trailing
|
||||
// zero-byte in DHCP option length calculation.
|
||||
//
|
||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/2582.
|
||||
//
|
||||
// TODO(e.burkov): Remove after the trimming for hostname option
|
||||
// will be added into github.com/insomniacslk/dhcp module.
|
||||
hostnameStr := strings.TrimRight(string(hostname), "\x00")
|
||||
|
||||
lease.Hostname = hostnameStr
|
||||
s.commitLease(lease)
|
||||
} else if len(lease.Hostname) != 0 {
|
||||
o := &optFQDN{
|
||||
|
||||
@@ -276,14 +276,24 @@ func (s *Server) prepareUpstreamSettings() error {
|
||||
upstreams = s.conf.UpstreamDNS
|
||||
}
|
||||
upstreams = filterOutComments(upstreams)
|
||||
upstreamConfig, err := proxy.ParseUpstreamsConfig(upstreams, s.conf.BootstrapDNS, DefaultTimeout)
|
||||
upstreamConfig, err := proxy.ParseUpstreamsConfig(upstreams,
|
||||
upstream.Options{
|
||||
Bootstrap: s.conf.BootstrapDNS,
|
||||
Timeout: DefaultTimeout,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dns: proxy.ParseUpstreamsConfig: %w", err)
|
||||
}
|
||||
|
||||
if len(upstreamConfig.Upstreams) == 0 {
|
||||
log.Info("warning: no default upstream servers specified, using %v", defaultDNS)
|
||||
uc, err := proxy.ParseUpstreamsConfig(defaultDNS, s.conf.BootstrapDNS, DefaultTimeout)
|
||||
uc, err := proxy.ParseUpstreamsConfig(defaultDNS,
|
||||
upstream.Options{
|
||||
Bootstrap: s.conf.BootstrapDNS,
|
||||
Timeout: DefaultTimeout,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dns: failed to parse default upstreams: %v", err)
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ func (req *dnsConfig) checkBootstrap() (string, error) {
|
||||
return boot, fmt.Errorf("invalid bootstrap server address: empty")
|
||||
}
|
||||
|
||||
if _, err := upstream.NewResolver(boot, 0); err != nil {
|
||||
if _, err := upstream.NewResolver(boot, upstream.Options{Timeout: 0}); err != nil {
|
||||
return boot, fmt.Errorf("invalid bootstrap server address: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -315,7 +315,12 @@ func ValidateUpstreams(upstreams []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := proxy.ParseUpstreamsConfig(upstreams, []string{}, DefaultTimeout)
|
||||
_, err := proxy.ParseUpstreamsConfig(upstreams,
|
||||
upstream.Options{
|
||||
Bootstrap: []string{},
|
||||
Timeout: DefaultTimeout,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,13 +2,10 @@ package home
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -20,8 +17,12 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
cookieTTL = 365 * 24 // in hours
|
||||
// cookieTTL is given in hours.
|
||||
cookieTTL = 365 * 24
|
||||
sessionCookieName = "agh_session"
|
||||
|
||||
// sessionTokenSize is the length of session token in bytes.
|
||||
sessionTokenSize = 16
|
||||
)
|
||||
|
||||
type session struct {
|
||||
@@ -285,16 +286,29 @@ type loginJSON struct {
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
func getSession(u *User) ([]byte, error) {
|
||||
maxSalt := big.NewInt(math.MaxUint32)
|
||||
salt, err := rand.Int(rand.Reader, maxSalt)
|
||||
// newSessionToken returns cryptographically secure randomly generated slice of
|
||||
// bytes of sessionTokenSize length.
|
||||
//
|
||||
// TODO(e.burkov): Think about using byte array instead of byte slice.
|
||||
func newSessionToken() (data []byte, err error) {
|
||||
randData := make([]byte, sessionTokenSize)
|
||||
|
||||
_, err = rand.Read(randData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := []byte(fmt.Sprintf("%s%s%s", salt, u.Name, u.PasswordHash))
|
||||
hash := sha256.Sum256(d)
|
||||
return hash[:], nil
|
||||
return randData, nil
|
||||
}
|
||||
|
||||
// cookieTimeFormat is the format to be used in (time.Time).Format for cookie's
|
||||
// expiry field.
|
||||
const cookieTimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||
|
||||
// cookieExpiryFormat returns the formatted exp to be used in cookie string.
|
||||
// It's quite simple for now, but probably will be expanded in the future.
|
||||
func cookieExpiryFormat(exp time.Time) (formatted string) {
|
||||
return exp.Format(cookieTimeFormat)
|
||||
}
|
||||
|
||||
func (a *Auth) httpCookie(req loginJSON) (string, error) {
|
||||
@@ -303,24 +317,23 @@ func (a *Auth) httpCookie(req loginJSON) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
sess, err := getSession(&u)
|
||||
sess, err := newSessionToken()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
expire := now.Add(cookieTTL * time.Hour)
|
||||
expstr := expire.Format(time.RFC1123)
|
||||
expstr = expstr[:len(expstr)-len("UTC")] // "UTC" -> "GMT"
|
||||
expstr += "GMT"
|
||||
|
||||
s := session{}
|
||||
s.userName = u.Name
|
||||
s.expire = uint32(now.Unix()) + a.sessionTTL
|
||||
a.addSession(sess, &s)
|
||||
a.addSession(sess, &session{
|
||||
userName: u.Name,
|
||||
expire: uint32(now.Unix()) + a.sessionTTL,
|
||||
})
|
||||
|
||||
return fmt.Sprintf("%s=%s; Path=/; HttpOnly; Expires=%s",
|
||||
sessionCookieName, hex.EncodeToString(sess), expstr), nil
|
||||
return fmt.Sprintf(
|
||||
"%s=%s; Path=/; HttpOnly; Expires=%s",
|
||||
sessionCookieName, hex.EncodeToString(sess),
|
||||
cookieExpiryFormat(now.Add(cookieTTL*time.Hour)),
|
||||
), nil
|
||||
}
|
||||
|
||||
func handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package home
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -11,6 +13,7 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
@@ -24,14 +27,34 @@ func prepareTestDir() string {
|
||||
return dir
|
||||
}
|
||||
|
||||
func TestNewSessionToken(t *testing.T) {
|
||||
// Successful case.
|
||||
token, err := newSessionToken()
|
||||
require.Nil(t, err)
|
||||
assert.Len(t, token, sessionTokenSize)
|
||||
|
||||
// Break the rand.Reader.
|
||||
prevReader := rand.Reader
|
||||
t.Cleanup(func() {
|
||||
rand.Reader = prevReader
|
||||
})
|
||||
rand.Reader = &bytes.Buffer{}
|
||||
|
||||
// Unsuccessful case.
|
||||
token, err = newSessionToken()
|
||||
require.NotNil(t, err)
|
||||
assert.Empty(t, token)
|
||||
}
|
||||
|
||||
func TestAuth(t *testing.T) {
|
||||
dir := prepareTestDir()
|
||||
defer func() { _ = os.RemoveAll(dir) }()
|
||||
t.Cleanup(func() { _ = os.RemoveAll(dir) })
|
||||
fn := filepath.Join(dir, "sessions.db")
|
||||
|
||||
users := []User{
|
||||
{Name: "name", PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2"},
|
||||
}
|
||||
users := []User{{
|
||||
Name: "name",
|
||||
PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2",
|
||||
}}
|
||||
a := InitAuth(fn, nil, 60)
|
||||
s := session{}
|
||||
|
||||
@@ -41,7 +64,7 @@ func TestAuth(t *testing.T) {
|
||||
assert.Equal(t, checkSessionNotFound, a.checkSession("notfound"))
|
||||
a.RemoveSession("notfound")
|
||||
|
||||
sess, err := getSession(&users[0])
|
||||
sess, err := newSessionToken()
|
||||
assert.Nil(t, err)
|
||||
sessStr := hex.EncodeToString(sess)
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/util"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/utils"
|
||||
)
|
||||
@@ -295,7 +296,12 @@ func (clients *clientsContainer) FindUpstreams(ip string) *proxy.UpstreamConfig
|
||||
}
|
||||
|
||||
if c.upstreamConfig == nil {
|
||||
config, err := proxy.ParseUpstreamsConfig(c.Upstreams, config.DNS.BootstrapDNS, dnsforward.DefaultTimeout)
|
||||
config, err := proxy.ParseUpstreamsConfig(c.Upstreams,
|
||||
upstream.Options{
|
||||
Bootstrap: config.DNS.BootstrapDNS,
|
||||
Timeout: dnsforward.DefaultTimeout,
|
||||
},
|
||||
)
|
||||
if err == nil {
|
||||
c.upstreamConfig = &config
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ func TestHome(t *testing.T) {
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// test DNS over UDP
|
||||
r, err := upstream.NewResolver("127.0.0.1:5354", 3*time.Second)
|
||||
r, err := upstream.NewResolver("127.0.0.1:5354", upstream.Options{Timeout: 3 * time.Second})
|
||||
assert.Nil(t, err)
|
||||
addrs, err := r.LookupIPAddr(context.TODO(), "static.adguard.com")
|
||||
assert.Nil(t, err)
|
||||
|
||||
@@ -21,7 +21,7 @@ type onChangedT func()
|
||||
// AutoHosts - automatic DNS records
|
||||
type AutoHosts struct {
|
||||
// lock protects table and tableReverse.
|
||||
lock sync.Mutex
|
||||
lock sync.RWMutex
|
||||
// table is the host-to-IPs map.
|
||||
table map[string][]net.IP
|
||||
// tableReverse is the IP-to-hosts map.
|
||||
@@ -119,15 +119,14 @@ func (a *AutoHosts) Process(host string, qtype uint16) []net.IP {
|
||||
}
|
||||
|
||||
var ipsCopy []net.IP
|
||||
a.lock.Lock()
|
||||
a.lock.RLock()
|
||||
defer a.lock.RUnlock()
|
||||
|
||||
if ips, ok := a.table[host]; ok {
|
||||
ipsCopy = make([]net.IP, len(ips))
|
||||
copy(ipsCopy, ips)
|
||||
}
|
||||
|
||||
a.lock.Unlock()
|
||||
|
||||
log.Debug("AutoHosts: answer: %s -> %v", host, ipsCopy)
|
||||
return ipsCopy
|
||||
}
|
||||
@@ -145,8 +144,8 @@ func (a *AutoHosts) ProcessReverse(addr string, qtype uint16) (hosts []string) {
|
||||
|
||||
ipStr := ipReal.String()
|
||||
|
||||
a.lock.Lock()
|
||||
defer a.lock.Unlock()
|
||||
a.lock.RLock()
|
||||
defer a.lock.RUnlock()
|
||||
|
||||
hosts = a.tableReverse[ipStr]
|
||||
|
||||
@@ -161,8 +160,8 @@ func (a *AutoHosts) ProcessReverse(addr string, qtype uint16) (hosts []string) {
|
||||
|
||||
// List returns an IP-to-hostnames table. It is safe for concurrent use.
|
||||
func (a *AutoHosts) List() (ipToHosts map[string][]string) {
|
||||
a.lock.Lock()
|
||||
defer a.lock.Unlock()
|
||||
a.lock.RLock()
|
||||
defer a.lock.RUnlock()
|
||||
|
||||
ipToHosts = make(map[string][]string, len(a.tableReverse))
|
||||
for k, v := range a.tableReverse {
|
||||
@@ -339,10 +338,13 @@ func (a *AutoHosts) updateHosts() {
|
||||
}
|
||||
}
|
||||
|
||||
a.lock.Lock()
|
||||
a.table = table
|
||||
a.tableReverse = tableRev
|
||||
a.lock.Unlock()
|
||||
func() {
|
||||
a.lock.Lock()
|
||||
defer a.lock.Unlock()
|
||||
|
||||
a.table = table
|
||||
a.tableReverse = tableRev
|
||||
}()
|
||||
|
||||
a.notify()
|
||||
}
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
@@ -64,16 +66,43 @@ func SplitNext(str *string, splitBy byte) string {
|
||||
return strings.TrimSpace(s)
|
||||
}
|
||||
|
||||
// IsOpenWRT checks if OS is OpenWRT.
|
||||
// IsOpenWRT returns true if host OS is OpenWRT.
|
||||
func IsOpenWRT() bool {
|
||||
if runtime.GOOS != "linux" {
|
||||
return false
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadFile("/etc/os-release")
|
||||
const etcDir = "/etc"
|
||||
|
||||
// TODO(e.burkov): Take care of dealing with fs package after updating
|
||||
// Go version to 1.16.
|
||||
fileInfos, err := ioutil.ReadDir(etcDir)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return strings.Contains(string(body), "OpenWrt")
|
||||
// fNameSubstr is a part of a name of the desired file.
|
||||
const fNameSubstr = "release"
|
||||
osNameData := []byte("OpenWrt")
|
||||
|
||||
for _, fileInfo := range fileInfos {
|
||||
if fileInfo.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
if !strings.Contains(fileInfo.Name(), fNameSubstr) {
|
||||
continue
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadFile(filepath.Join(etcDir, fileInfo.Name()))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if bytes.Contains(body, osNameData) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1279,6 +1279,8 @@
|
||||
'type': 'string'
|
||||
'edns_cs_enabled':
|
||||
'type': 'boolean'
|
||||
'disable_ipv6':
|
||||
'type': 'boolean'
|
||||
'dnssec_enabled':
|
||||
'type': 'boolean'
|
||||
'cache_size':
|
||||
|
||||
@@ -11,8 +11,10 @@ set -e -f -u
|
||||
readonly awk_program='/^v[0-9]+\.[0-9]+\.[0-9]+.*$/ {
|
||||
if (!$4) {
|
||||
# The last tag is a full release version, so bump the
|
||||
# minor one to get the next one.
|
||||
# minor release number and zero the patch release number
|
||||
# to get the next release.
|
||||
$2++;
|
||||
$3 = 0;
|
||||
}
|
||||
|
||||
print($1 "." $2 "." $3);
|
||||
|
||||
Reference in New Issue
Block a user