diff --git a/service/resolved/resolve1.go b/service/resolved/resolve1.go index dadc975b..a02d0343 100644 --- a/service/resolved/resolve1.go +++ b/service/resolved/resolve1.go @@ -5,12 +5,10 @@ package resolved import ( "context" "errors" - "fmt" "net/netip" "os" "os/user" "path/filepath" - "slices" "strconv" "strings" "syscall" @@ -79,17 +77,27 @@ type LinkDomain struct { func (t *resolve1Manager) getLink(ifIndex int32) (*TransportLink, *dbus.Error) { link, loaded := t.links[ifIndex] if !loaded { - link = &TransportLink{} - t.links[ifIndex] = link iif, err := t.network.InterfaceFinder().ByIndex(int(ifIndex)) if err != nil { return nil, wrapError(err) } - link.iif = iif + link = &TransportLink{iif: iif} + t.links[ifIndex] = link } return link, nil } +func (t *resolve1Manager) interfaceName(ifIndex int32) string { + if ifIndex == 0 { + return "*" + } + iif, err := t.network.InterfaceFinder().ByIndex(int(ifIndex)) + if err != nil { + return F.ToString(ifIndex) + } + return iif.Name +} + func (t *resolve1Manager) getSenderProcess(sender dbus.Sender) (int32, error) { var senderPid int32 dbusObject := t.systemBus.Object("org.freedesktop.DBus", "/org/freedesktop/DBus") @@ -203,12 +211,6 @@ func familyToString(family int32) string { } func (t *resolve1Manager) ResolveHostname(sender dbus.Sender, ifIndex int32, hostname string, family int32, flags uint64) (addresses []Address, canonical string, outflags uint64, err *dbus.Error) { - t.linkAccess.Lock() - link, err := t.getLink(ifIndex) - if err != nil { - return - } - t.linkAccess.Unlock() var strategy C.DomainStrategy switch family { case syscall.AF_UNSPEC: @@ -218,12 +220,12 @@ func (t *resolve1Manager) ResolveHostname(sender dbus.Sender, ifIndex int32, hos case syscall.AF_INET6: strategy = C.DomainStrategyIPv6Only } - ctx := t.logRequest(sender, "ResolveHostname ", link.iif.Name, " ", hostname, " ", familyToString(family), " ", flags) + ctx := t.logRequest(sender, "ResolveHostname", t.interfaceName(ifIndex), hostname, familyToString(family), flags) responseAddresses, lookupErr := t.dnsRouter.Lookup(ctx, hostname, adapter.DNSQueryOptions{ LookupStrategy: strategy, }) if lookupErr != nil { - err = wrapError(err) + err = wrapError(lookupErr) return } addresses = common.Map(responseAddresses, func(it netip.Addr) Address { @@ -244,48 +246,27 @@ func (t *resolve1Manager) ResolveHostname(sender dbus.Sender, ifIndex int32, hos } func (t *resolve1Manager) ResolveAddress(sender dbus.Sender, ifIndex int32, family int32, address []byte, flags uint64) (names []Name, outflags uint64, err *dbus.Error) { - t.linkAccess.Lock() - link, err := t.getLink(ifIndex) - if err != nil { - return - } - t.linkAccess.Unlock() addr, ok := netip.AddrFromSlice(address) if !ok { err = wrapError(E.New("invalid address")) return } - var nibbles []string - for _, v := range slices.Backward(address) { - b := v - nibbles = append(nibbles, fmt.Sprintf("%x", b&0x0F)) - nibbles = append(nibbles, fmt.Sprintf("%x", b>>4)) - } - var ptrDomain string - if addr.Is4() { - ptrDomain = strings.Join(nibbles, ".") + ".in-addr.arpa." - } else { - ptrDomain = strings.Join(nibbles, ".") + ".ip6.arpa." - } request := &mDNS.Msg{ MsgHdr: mDNS.MsgHdr{ RecursionDesired: true, }, Question: []mDNS.Question{ { - Name: mDNS.Fqdn(ptrDomain), + Name: common.Must1(mDNS.ReverseAddr(addr.String())), Qtype: mDNS.TypePTR, Qclass: mDNS.ClassINET, }, }, } - ctx := t.logRequest(sender, "ResolveAddress ", link.iif.Name, familyToString(family), addr, flags) - var metadata adapter.InboundContext - metadata.InboundType = t.Type() - metadata.Inbound = t.Tag() - response, lookupErr := t.dnsRouter.Exchange(adapter.WithContext(ctx, &metadata), request, adapter.DNSQueryOptions{}) + ctx := t.logRequest(sender, "ResolveAddress", t.interfaceName(ifIndex), familyToString(family), addr, flags) + response, lookupErr := t.dnsRouter.Exchange(ctx, request, adapter.DNSQueryOptions{}) if lookupErr != nil { - err = wrapError(err) + err = wrapError(lookupErr) return } if response.Rcode != mDNS.RcodeSuccess { @@ -305,12 +286,6 @@ func (t *resolve1Manager) ResolveAddress(sender dbus.Sender, ifIndex int32, fami } func (t *resolve1Manager) ResolveRecord(sender dbus.Sender, ifIndex int32, hostname string, qClass uint16, qType uint16, flags uint64) (records []ResourceRecord, outflags uint64, err *dbus.Error) { - t.linkAccess.Lock() - link, err := t.getLink(ifIndex) - if err != nil { - return - } - t.linkAccess.Unlock() request := &mDNS.Msg{ MsgHdr: mDNS.MsgHdr{ RecursionDesired: true, @@ -323,11 +298,8 @@ func (t *resolve1Manager) ResolveRecord(sender dbus.Sender, ifIndex int32, hostn }, }, } - ctx := t.logRequest(sender, "ResolveRecord", link.iif.Name, hostname, mDNS.Class(qClass), mDNS.Type(qType), flags) - var metadata adapter.InboundContext - metadata.InboundType = t.Type() - metadata.Inbound = t.Tag() - response, exchangeErr := t.dnsRouter.Exchange(adapter.WithContext(ctx, &metadata), request, adapter.DNSQueryOptions{}) + ctx := t.logRequest(sender, "ResolveRecord", t.interfaceName(ifIndex), hostname, mDNS.Class(qClass), mDNS.Type(qType), flags) + response, exchangeErr := t.dnsRouter.Exchange(ctx, request, adapter.DNSQueryOptions{}) if exchangeErr != nil { err = wrapError(exchangeErr) return @@ -353,13 +325,6 @@ func (t *resolve1Manager) ResolveRecord(sender dbus.Sender, ifIndex int32, hostn } func (t *resolve1Manager) ResolveService(sender dbus.Sender, ifIndex int32, hostname string, sType string, domain string, family int32, flags uint64) (srvData []SRVRecord, txtData []TXTRecord, canonicalName string, canonicalType string, canonicalDomain string, outflags uint64, err *dbus.Error) { - t.linkAccess.Lock() - link, err := t.getLink(ifIndex) - if err != nil { - return - } - t.linkAccess.Unlock() - serviceName := hostname if hostname != "" && !strings.HasSuffix(hostname, ".") { serviceName += "." @@ -373,7 +338,7 @@ func (t *resolve1Manager) ResolveService(sender dbus.Sender, ifIndex int32, host serviceName += "." } - ctx := t.logRequest(sender, "ResolveService ", link.iif.Name, " ", hostname, " ", sType, " ", domain, " ", familyToString(family), " ", flags) + ctx := t.logRequest(sender, "ResolveService", t.interfaceName(ifIndex), hostname, sType, domain, familyToString(family), flags) srvRequest := &mDNS.Msg{ MsgHdr: mDNS.MsgHdr{ @@ -387,10 +352,7 @@ func (t *resolve1Manager) ResolveService(sender dbus.Sender, ifIndex int32, host }, }, } - var metadata adapter.InboundContext - metadata.InboundType = t.Type() - metadata.Inbound = t.Tag() - srvResponse, exchangeErr := t.dnsRouter.Exchange(adapter.WithContext(ctx, &metadata), srvRequest, adapter.DNSQueryOptions{}) + srvResponse, exchangeErr := t.dnsRouter.Exchange(ctx, srvRequest, adapter.DNSQueryOptions{}) if exchangeErr != nil { err = wrapError(exchangeErr) return @@ -606,8 +568,12 @@ func (t *resolve1Manager) RevertLink(sender dbus.Sender, ifIndex int32) *dbus.Er return wrapError(err) } delete(t.links, ifIndex) + t.defaultRouteSequence = common.Filter(t.defaultRouteSequence, func(it int32) bool { return it != ifIndex }) t.log(sender, "RevertLink ", link.iif.Name) - return t.postUpdate(link) + if t.deleteCallback != nil { + t.deleteCallback(link) + } + return nil } // TODO: implement RegisterService, UnregisterService diff --git a/service/resolved/service.go b/service/resolved/service.go index a634b9b2..f0d1aa0f 100644 --- a/service/resolved/service.go +++ b/service/resolved/service.go @@ -185,12 +185,12 @@ func (i *Service) exchangePacket0(ctx context.Context, buffer *buf.Buffer, oob [ func (i *Service) onNetworkUpdate() { i.linkAccess.Lock() defer i.linkAccess.Unlock() - var deleteIfIndex []int for ifIndex, link := range i.links { - iif, err := i.network.InterfaceFinder().ByIndex(int(ifIndex)) - if err != nil || iif != link.iif { - deleteIfIndex = append(deleteIfIndex, int(ifIndex)) + netInterface, err := net.InterfaceByIndex(int(ifIndex)) + if err == nil && netInterface.Name == link.iif.Name { + continue } + delete(i.links, ifIndex) i.defaultRouteSequence = common.Filter(i.defaultRouteSequence, func(it int32) bool { return it != ifIndex }) @@ -198,9 +198,6 @@ func (i *Service) onNetworkUpdate() { i.deleteCallback(link) } } - for _, ifIndex := range deleteIfIndex { - delete(i.links, int32(ifIndex)) - } } func (conf *TransportLink) nameList(ndots int, name string) []string { diff --git a/service/resolved/transport.go b/service/resolved/transport.go index 858cb6b0..2f476a76 100644 --- a/service/resolved/transport.go +++ b/service/resolved/transport.go @@ -192,7 +192,7 @@ func (t *Transport) updateTransports(link *TransportLink) error { Enabled: true, ServerName: serverAddr.String(), })) - transports = append(transports, transport.NewTLSRaw(t.logger, t.TransportAdapter, serverDialer, M.SocksaddrFrom(serverAddr, 53), tlsConfig)) + transports = append(transports, transport.NewTLSRaw(t.logger, t.TransportAdapter, serverDialer, M.SocksaddrFrom(serverAddr, 853), tlsConfig)) } else { transports = append(transports, transport.NewUDPRaw(t.logger, t.TransportAdapter, serverDialer, M.SocksaddrFrom(serverAddr, 53))) @@ -203,7 +203,11 @@ func (t *Transport) updateTransports(link *TransportLink) error { if !ok { return os.ErrInvalid } + serverPort := address.Port if link.dnsOverTLS { + if serverPort == 0 { + serverPort = 853 + } var serverName string if address.Name != "" { serverName = address.Name @@ -214,10 +218,13 @@ func (t *Transport) updateTransports(link *TransportLink) error { Enabled: true, ServerName: serverName, })) - transports = append(transports, transport.NewTLSRaw(t.logger, t.TransportAdapter, serverDialer, M.SocksaddrFrom(serverAddr, address.Port), tlsConfig)) + transports = append(transports, transport.NewTLSRaw(t.logger, t.TransportAdapter, serverDialer, M.SocksaddrFrom(serverAddr, serverPort), tlsConfig)) } else { - transports = append(transports, transport.NewUDPRaw(t.logger, t.TransportAdapter, serverDialer, M.SocksaddrFrom(serverAddr, address.Port))) + if serverPort == 0 { + serverPort = 53 + } + transports = append(transports, transport.NewUDPRaw(t.logger, t.TransportAdapter, serverDialer, M.SocksaddrFrom(serverAddr, serverPort))) } } t.linkServers[link] = &LinkServers{ @@ -248,7 +255,7 @@ func (t *Transport) PreferredDomain(domain string) bool { if linkDomain.Domain == "." { continue } - if mDNS.IsSubDomain(linkDomain.Domain, domain) { + if mDNS.IsSubDomain(mDNS.Fqdn(linkDomain.Domain), domain) { return true } } @@ -273,15 +280,25 @@ func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, func (t *Transport) ExchangeAsync(ctx context.Context, message *mDNS.Msg, callback func(response *mDNS.Msg, err error)) { question := message.Question[0] - var selectedLink *TransportLink + var ( + selectedLink *TransportLink + selectedLabels int + names []string + ) t.service.linkAccess.RLock() for _, link := range t.service.links { for _, domain := range link.domain { if domain.Domain == "." && domain.RoutingOnly && !t.acceptDefaultResolvers { continue } - if mDNS.IsSubDomain(domain.Domain, question.Name) { + domainName := mDNS.Fqdn(domain.Domain) + if !mDNS.IsSubDomain(domainName, question.Name) { + continue + } + labels := mDNS.CountLabel(domainName) + if selectedLink == nil || labels > selectedLabels { selectedLink = link + selectedLabels = labels } } } @@ -293,6 +310,9 @@ func (t *Transport) ExchangeAsync(ctx context.Context, message *mDNS.Msg, callba } } } + if selectedLink != nil { + names = selectedLink.nameList(t.ndots, question.Name) + } t.service.linkAccess.RUnlock() if selectedLink == nil { callback(dns.FixedResponseStatus(message, mDNS.RcodeNameError), nil) @@ -305,7 +325,6 @@ func (t *Transport) ExchangeAsync(ctx context.Context, message *mDNS.Msg, callba callback(dns.FixedResponseStatus(message, mDNS.RcodeNameError), nil) return } - names := servers.Link.nameList(t.ndots, question.Name) if len(names) == 0 { callback(nil, E.New("invalid domain: ", question.Name)) return