diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..3cdceded --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,55 @@ +# options for analysis running +run: + # default concurrency is a available CPU number + concurrency: 4 + + # timeout for analysis, e.g. 30s, 5m, default is 1m + deadline: 2m + + # which files to skip: they will be analyzed, but issues from them + # won't be reported. Default value is empty list, but there is + # no need to include all autogenerated files, we confidently recognize + # autogenerated files. If it's not please let us know. + skip-files: + - ".*generated.*" + - dnsfilter/rule_to_regexp.go + + +# all available settings of specific linters +linters-settings: + errcheck: + # [deprecated] comma-separated list of pairs of the form pkg:regex + # the regex is used to ignore names within pkg. (default "fmt:.*"). + # see https://github.com/kisielk/errcheck#the-deprecated-method for details + ignore: fmt:.*,net:SetReadDeadline,net/http:^Write + gocyclo: + min-complexity: 20 + lll: + line-length: 200 + +linters: + enable-all: true + disable: + - interfacer + - gocritic + - scopelint + - gochecknoglobals + - gochecknoinits + - prealloc + - maligned + - goconst # disabled until it's possible to configure + fast: true + +issues: + # List of regexps of issue texts to exclude, empty list by default. + # But independently from this option we use default exclude patterns, + # it can be disabled by `exclude-use-default: false`. To list all + # excluded by default patterns execute `golangci-lint run --help` + exclude: + # structcheck cannot detect usages while they're there + - .parentalServer. is unused + - .safeBrowsingServer. is unused + # errcheck + - Error return value of .s.closeConn. is not checked + # goconst + - string .forcesafesearch.google.com. has 3 occurrences \ No newline at end of file diff --git a/config.go b/config.go index 040acf6e..ed96e874 100644 --- a/config.go +++ b/config.go @@ -10,7 +10,7 @@ import ( "github.com/AdguardTeam/AdGuardHome/dnsfilter" "github.com/AdguardTeam/AdGuardHome/dnsforward" "github.com/hmage/golibs/log" - "gopkg.in/yaml.v2" + yaml "gopkg.in/yaml.v2" ) const ( diff --git a/control.go b/control.go index a60421e8..4600c184 100644 --- a/control.go +++ b/control.go @@ -15,7 +15,7 @@ import ( "github.com/AdguardTeam/dnsproxy/upstream" "github.com/hmage/golibs/log" "github.com/miekg/dns" - "gopkg.in/asaskevich/govalidator.v4" + govalidator "gopkg.in/asaskevich/govalidator.v4" ) const updatePeriod = time.Minute * 30 @@ -321,27 +321,27 @@ func handleFilteringStatus(w http.ResponseWriter, r *http.Request) { } func handleFilteringAddURL(w http.ResponseWriter, r *http.Request) { - filter := filter{} - err := json.NewDecoder(r.Body).Decode(&filter) + f := filter{} + err := json.NewDecoder(r.Body).Decode(&f) if err != nil { httpError(w, http.StatusBadRequest, "Failed to parse request body json: %s", err) return } - if len(filter.URL) == 0 { + if len(f.URL) == 0 { http.Error(w, "URL parameter was not specified", 400) return } - if valid := govalidator.IsRequestURL(filter.URL); !valid { + if valid := govalidator.IsRequestURL(f.URL); !valid { http.Error(w, "URL parameter is not valid request URL", 400) return } // Check for duplicates for i := range config.Filters { - if config.Filters[i].URL == filter.URL { - errorText := fmt.Sprintf("Filter URL already added -- %s", filter.URL) + if config.Filters[i].URL == f.URL { + errorText := fmt.Sprintf("Filter URL already added -- %s", f.URL) log.Println(errorText) http.Error(w, errorText, http.StatusBadRequest) return @@ -349,34 +349,34 @@ func handleFilteringAddURL(w http.ResponseWriter, r *http.Request) { } // Set necessary properties - filter.ID = assignUniqueFilterID() - filter.Enabled = true + f.ID = assignUniqueFilterID() + f.Enabled = true // Download the filter contents - ok, err := filter.update(true) + ok, err := f.update(true) if err != nil { - errorText := fmt.Sprintf("Couldn't fetch filter from url %s: %s", filter.URL, err) + errorText := fmt.Sprintf("Couldn't fetch filter from url %s: %s", f.URL, err) log.Println(errorText) http.Error(w, errorText, http.StatusBadRequest) return } - if filter.RulesCount == 0 { - errorText := fmt.Sprintf("Filter at the url %s has no rules (maybe it points to blank page?)", filter.URL) + if f.RulesCount == 0 { + errorText := fmt.Sprintf("Filter at the url %s has no rules (maybe it points to blank page?)", f.URL) log.Println(errorText) http.Error(w, errorText, http.StatusBadRequest) return } if !ok { - errorText := fmt.Sprintf("Filter at the url %s is invalid (maybe it points to blank page?)", filter.URL) + errorText := fmt.Sprintf("Filter at the url %s is invalid (maybe it points to blank page?)", f.URL) log.Println(errorText) http.Error(w, errorText, http.StatusBadRequest) return } // Save the filter contents - err = filter.save() + err = f.save() if err != nil { - errorText := fmt.Sprintf("Failed to save filter %d due to %s", filter.ID, err) + errorText := fmt.Sprintf("Failed to save filter %d due to %s", f.ID, err) log.Println(errorText) http.Error(w, errorText, http.StatusBadRequest) return @@ -384,7 +384,7 @@ func handleFilteringAddURL(w http.ResponseWriter, r *http.Request) { // URL is deemed valid, append it to filters, update config, write new filter file and tell dns to reload it // TODO: since we directly feed filters in-memory, revisit if writing configs is always necessary - config.Filters = append(config.Filters, filter) + config.Filters = append(config.Filters, f) err = writeAllConfigs() if err != nil { errorText := fmt.Sprintf("Couldn't write config file: %s", err) @@ -393,9 +393,14 @@ func handleFilteringAddURL(w http.ResponseWriter, r *http.Request) { return } - reconfigureDNSServer() + err = reconfigureDNSServer() + if err != nil { + errorText := fmt.Sprintf("Couldn't reconfigure the DNS server: %s", err) + log.Println(errorText) + http.Error(w, errorText, http.StatusInternalServerError) + } - _, err = fmt.Fprintf(w, "OK %d rules\n", filter.RulesCount) + _, err = fmt.Fprintf(w, "OK %d rules\n", f.RulesCount) if err != nil { errorText := fmt.Sprintf("Couldn't write body: %s", err) log.Println(errorText) diff --git a/dhcp.go b/dhcp.go index 0e8503be..90d6a88a 100644 --- a/dhcp.go +++ b/dhcp.go @@ -101,9 +101,9 @@ func handleDHCPInterfaces(w http.ResponseWriter, r *http.Request) { MTU: ifaces[i].MTU, HardwareAddr: ifaces[i].HardwareAddr.String(), } - addrs, err := ifaces[i].Addrs() - if err != nil { - httpError(w, http.StatusInternalServerError, "Failed to get addresses for interface %v: %s", ifaces[i].Name, err) + addrs, errAddrs := ifaces[i].Addrs() + if errAddrs != nil { + httpError(w, http.StatusInternalServerError, "Failed to get addresses for interface %v: %s", ifaces[i].Name, errAddrs) return } for _, addr := range addrs { @@ -155,7 +155,7 @@ func handleDHCPFindActiveServer(w http.ResponseWriter, r *http.Request) { } func startDHCPServer() error { - if config.DHCP.Enabled == false { + if !config.DHCP.Enabled { // not enabled, don't do anything return nil } diff --git a/dhcpd/check_other_dhcp.go b/dhcpd/check_other_dhcp.go index 76be82f9..b2d64b9f 100644 --- a/dhcpd/check_other_dhcp.go +++ b/dhcpd/check_other_dhcp.go @@ -59,7 +59,7 @@ func CheckIfOtherDHCPServersPresent(ifaceName string) (bool, error) { maxUDPsizeRaw := make([]byte, 2) binary.BigEndian.PutUint16(maxUDPsizeRaw, 1500) leaseTimeRaw := make([]byte, 4) - leaseTime := uint32(math.RoundToEven(time.Duration(time.Hour * 24 * 90).Seconds())) + leaseTime := uint32(math.RoundToEven((time.Hour * 24 * 90).Seconds())) binary.BigEndian.PutUint32(leaseTimeRaw, leaseTime) options := []dhcp4.Option{ {Code: dhcp4.OptionParameterRequestList, Value: requestList}, diff --git a/dhcpd/dhcpd.go b/dhcpd/dhcpd.go index df80fac3..0fcb8168 100644 --- a/dhcpd/dhcpd.go +++ b/dhcpd/dhcpd.go @@ -83,6 +83,7 @@ func (s *Server) Start(config *ServerConfig) error { s.leaseStart, err = parseIPv4(s.RangeStart) if err != nil { + s.closeConn() // in case it was already started return wrapErrPrint(err, "Failed to parse range start address %s", s.RangeStart) } @@ -178,7 +179,7 @@ func (s *Server) reserveLease(p dhcp4.Packet) (*Lease, error) { } // not assigned a lease, create new one, find IP from LRU log.Tracef("Lease not found for %s: creating new one", hwaddr) - ip, err := s.findFreeIP(p, hwaddr) + ip, err := s.findFreeIP(hwaddr) if err != nil { return nil, wrapErrPrint(err, "Couldn't find free IP for the lease %s", hwaddr.String()) } @@ -202,7 +203,7 @@ func (s *Server) locateLease(p dhcp4.Packet) *Lease { return nil } -func (s *Server) findFreeIP(p dhcp4.Packet, hwaddr net.HardwareAddr) (net.IP, error) { +func (s *Server) findFreeIP(hwaddr net.HardwareAddr) (net.IP, error) { // if IP pool is nil, lazy initialize it if s.IPpool == nil { s.IPpool = make(map[[4]byte]net.HardwareAddr) @@ -227,7 +228,7 @@ func (s *Server) findFreeIP(p dhcp4.Packet, hwaddr net.HardwareAddr) (net.IP, er if foundIP == nil { // TODO: LRU - return nil, fmt.Errorf("Couldn't find free entry in IP pool") + return nil, fmt.Errorf("couldn't find free entry in IP pool") } s.reserveIP(foundIP, hwaddr) @@ -281,7 +282,7 @@ func (s *Server) ServeDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options dh case dhcp4.Request: // Broadcast From Client - I'll take that IP (Also start for renewals) // start/renew a lease -- update lease time // some clients (OSX) just go right ahead and do Request first from previously known IP, if they get NAK, they restart full cycle with Discover then Request - return s.handleDHCP4Request(p, msgType, options) + return s.handleDHCP4Request(p, options) case dhcp4.Decline: // Broadcast From Client - Sorry I can't use that IP log.Tracef("Got from client: Decline") @@ -306,7 +307,7 @@ func (s *Server) ServeDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options dh return nil } -func (s *Server) handleDHCP4Request(p dhcp4.Packet, msgType dhcp4.MessageType, options dhcp4.Options) dhcp4.Packet { +func (s *Server) handleDHCP4Request(p dhcp4.Packet, options dhcp4.Options) dhcp4.Packet { log.Tracef("Got from client: Request") if server, ok := options[dhcp4.OptionServerIdentifier]; ok && !net.IP(server).Equal(s.ipnet.IP) { log.Tracef("Request message not for this DHCP server (%v vs %v)", server, s.ipnet.IP) @@ -315,7 +316,7 @@ func (s *Server) handleDHCP4Request(p dhcp4.Packet, msgType dhcp4.MessageType, o reqIP := net.IP(options[dhcp4.OptionRequestedIPAddress]) if reqIP == nil { - reqIP = net.IP(p.CIAddr()) + reqIP = p.CIAddr() } if reqIP.To4() == nil { diff --git a/dhcpd/standalone/main.go b/dhcpd/standalone/main.go index fff02664..9154e063 100644 --- a/dhcpd/standalone/main.go +++ b/dhcpd/standalone/main.go @@ -76,9 +76,9 @@ func main() { panic(err) } log.Printf("Now serving DHCP") - signal_channel := make(chan os.Signal) - signal.Notify(signal_channel, syscall.SIGINT, syscall.SIGTERM) - <-signal_channel + signalChannel := make(chan os.Signal) + signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM) + <-signalChannel } diff --git a/dns.go b/dns.go index e4325e9c..12c71def 100644 --- a/dns.go +++ b/dns.go @@ -52,7 +52,7 @@ func generateServerConfig() dnsforward.ServerConfig { func startDNSServer() error { if isRunning() { - return fmt.Errorf("Unable to start forwarding DNS server: Already running") + return fmt.Errorf("unable to start forwarding DNS server: Already running") } newconfig := generateServerConfig() diff --git a/dnsfilter/dnsfilter_test.go b/dnsfilter/dnsfilter_test.go index 857cdf08..9692a60d 100644 --- a/dnsfilter/dnsfilter_test.go +++ b/dnsfilter/dnsfilter_test.go @@ -869,7 +869,7 @@ func BenchmarkLotsOfRulesLotsOfHosts(b *testing.B) { for n := 0; n < b.N; n++ { havedata := scanner.Scan() if !havedata { - hostnames.Seek(0, 0) + _, _ = hostnames.Seek(0, 0) scanner = bufio.NewScanner(hostnames) havedata = scanner.Scan() } @@ -906,7 +906,7 @@ func BenchmarkLotsOfRulesLotsOfHostsParallel(b *testing.B) { for pb.Next() { havedata := scanner.Scan() if !havedata { - hostnames.Seek(0, 0) + _, _ = hostnames.Seek(0, 0) scanner = bufio.NewScanner(hostnames) havedata = scanner.Scan() } diff --git a/dnsforward/querylog.go b/dnsforward/querylog.go index 903edeb6..fc51d165 100644 --- a/dnsforward/querylog.go +++ b/dnsforward/querylog.go @@ -108,7 +108,12 @@ func logRequest(question *dns.Msg, answer *dns.Msg, result *dnsfilter.Result, el if len(flushBuffer) > 0 { // write to file // do it in separate goroutine -- we are stalling DNS response this whole time - go flushToFile(flushBuffer) + go func() { + err := flushToFile(flushBuffer) + if err != nil { + log.Printf("Failed to flush the query log: %s", err) + } + }() } } diff --git a/dnsforward/stats.go b/dnsforward/stats.go index 76db1d99..cbc25af7 100644 --- a/dnsforward/stats.go +++ b/dnsforward/stats.go @@ -340,11 +340,11 @@ func HandleStatsHistory(w http.ResponseWriter, r *http.Request) { // check if start and time times are within supported time range timeRange := timeUnit * statsHistoryElements if startTime.Add(timeRange).Before(now) { - http.Error(w, "start_time parameter is outside of supported range", 501) + http.Error(w, "start_time parameter is outside of supported range", http.StatusBadRequest) return } if endTime.Add(timeRange).Before(now) { - http.Error(w, "end_time parameter is outside of supported range", 501) + http.Error(w, "end_time parameter is outside of supported range", http.StatusBadRequest) return } diff --git a/helpers.go b/helpers.go index 3ba42544..28412a58 100644 --- a/helpers.go +++ b/helpers.go @@ -39,7 +39,7 @@ func safeWriteFile(path string, data []byte) error { func ensure(method string, handler func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { if r.Method != method { - http.Error(w, "This request must be "+method, 405) + http.Error(w, "This request must be "+method, http.StatusMethodNotAllowed) return } handler(w, r) diff --git a/upgrade.go b/upgrade.go index 452df4d0..4b142de6 100644 --- a/upgrade.go +++ b/upgrade.go @@ -7,7 +7,7 @@ import ( "path/filepath" "github.com/hmage/golibs/log" - "gopkg.in/yaml.v2" + yaml "gopkg.in/yaml.v2" ) const currentSchemaVersion = 2 // used for upgrading from old configs to new config