2023-04-03 16:29:07 +03:00
|
|
|
package querylog
|
|
|
|
|
|
|
|
import (
|
2024-11-21 20:19:39 +03:00
|
|
|
"context"
|
|
|
|
"log/slog"
|
2023-04-03 16:29:07 +03:00
|
|
|
"net"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
|
|
|
"github.com/AdguardTeam/golibs/errors"
|
2024-11-21 20:19:39 +03:00
|
|
|
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
2023-04-03 16:29:07 +03:00
|
|
|
"github.com/miekg/dns"
|
|
|
|
)
|
|
|
|
|
|
|
|
// logEntry represents a single entry in the file.
|
|
|
|
type logEntry struct {
|
|
|
|
// client is the found client information, if any.
|
|
|
|
client *Client
|
|
|
|
|
|
|
|
Time time.Time `json:"T"`
|
|
|
|
|
|
|
|
QHost string `json:"QH"`
|
|
|
|
QType string `json:"QT"`
|
|
|
|
QClass string `json:"QC"`
|
|
|
|
|
|
|
|
ReqECS string `json:"ECS,omitempty"`
|
|
|
|
|
|
|
|
ClientID string `json:"CID,omitempty"`
|
|
|
|
ClientProto ClientProto `json:"CP"`
|
|
|
|
|
|
|
|
Upstream string `json:",omitempty"`
|
|
|
|
|
|
|
|
Answer []byte `json:",omitempty"`
|
|
|
|
OrigAnswer []byte `json:",omitempty"`
|
|
|
|
|
2024-04-24 19:08:54 +03:00
|
|
|
// TODO(s.chzhen): Use netip.Addr.
|
2023-04-03 16:29:07 +03:00
|
|
|
IP net.IP `json:"IP"`
|
|
|
|
|
|
|
|
Result filtering.Result
|
|
|
|
|
|
|
|
Elapsed time.Duration
|
|
|
|
|
|
|
|
Cached bool `json:",omitempty"`
|
|
|
|
AuthenticatedData bool `json:"AD,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// shallowClone returns a shallow clone of e.
|
|
|
|
func (e *logEntry) shallowClone() (clone *logEntry) {
|
|
|
|
cloneVal := *e
|
|
|
|
|
|
|
|
return &cloneVal
|
|
|
|
}
|
|
|
|
|
|
|
|
// addResponse adds data from resp to e.Answer if resp is not nil. If isOrig is
|
|
|
|
// true, addResponse sets the e.OrigAnswer field instead of e.Answer. Any
|
|
|
|
// errors are logged.
|
2024-11-21 20:19:39 +03:00
|
|
|
func (e *logEntry) addResponse(ctx context.Context, l *slog.Logger, resp *dns.Msg, isOrig bool) {
|
2023-04-03 16:29:07 +03:00
|
|
|
if resp == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var err error
|
|
|
|
if isOrig {
|
|
|
|
e.OrigAnswer, err = resp.Pack()
|
|
|
|
err = errors.Annotate(err, "packing orig answer: %w")
|
2023-04-13 20:51:57 +03:00
|
|
|
} else {
|
|
|
|
e.Answer, err = resp.Pack()
|
|
|
|
err = errors.Annotate(err, "packing answer: %w")
|
2023-04-03 16:29:07 +03:00
|
|
|
}
|
2024-11-21 20:19:39 +03:00
|
|
|
|
2023-04-03 16:29:07 +03:00
|
|
|
if err != nil {
|
2024-11-21 20:19:39 +03:00
|
|
|
l.ErrorContext(ctx, "adding data from response", slogutil.KeyError, err)
|
2023-04-03 16:29:07 +03:00
|
|
|
}
|
|
|
|
}
|
2023-05-24 16:33:15 +03:00
|
|
|
|
|
|
|
// parseDNSRewriteResultIPs fills logEntry's DNSRewriteResult response records
|
|
|
|
// with the IP addresses parsed from the raw strings.
|
|
|
|
func (e *logEntry) parseDNSRewriteResultIPs() {
|
|
|
|
for rrType, rrValues := range e.Result.DNSRewriteResult.Response {
|
|
|
|
switch rrType {
|
|
|
|
case dns.TypeA, dns.TypeAAAA:
|
|
|
|
for i, v := range rrValues {
|
|
|
|
s, _ := v.(string)
|
|
|
|
rrValues[i] = net.ParseIP(s)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
// Go on.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|