blob: 9f485c47e86ca1faf0483a2e0808a4359759f5d3 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package netstack
import (
"fmt"
"net"
"syscall/zx/fidl"
"syslog"
"netstack/dns"
fidlnet "fidl/fuchsia/net"
"gvisor.dev/gvisor/pkg/tcpip"
)
type nameLookupImpl struct {
dnsClient *dns.Client
}
var _ fidlnet.NameLookupWithCtx = (*nameLookupImpl)(nil)
func (sp *nameLookupImpl) LookupIp(_ fidl.Context, hostname string, options fidlnet.LookupIpOptions) (fidlnet.NameLookupLookupIpResult, error) {
var result fidlnet.NameLookupLookupIpResult
var response fidlnet.NameLookupLookupIpResponse
var ips []tcpip.Address
if hostname == "localhost" {
ips = []tcpip.Address{
ipv4Loopback,
ipv6Loopback,
}
} else {
var err error
ips, err = sp.dnsClient.LookupIP(hostname)
if err != nil {
syslog.VLogTf(syslog.DebugVerbosity, "DNS", "lookup failed with internal error: %s", err)
result.SetErr(fidlnet.LookupErrorInternalError)
return result, nil
}
if len(ips) == 0 {
result.SetErr(fidlnet.LookupErrorNotFound)
return result, nil
}
}
for _, ip := range ips {
// TODO(wesleyac): Consider handling IPv4-mapped addresses as IPv4 addresses
if ip4 := ip.To4(); ip4 != "" && (options&fidlnet.LookupIpOptionsV4Addrs) != 0 {
var addr fidlnet.Ipv4Address
copy(addr.Addr[:], ip4)
response.Addr.Ipv4Addrs = append(response.Addr.Ipv4Addrs, addr)
} else if options&fidlnet.LookupIpOptionsV6Addrs != 0 {
var addr fidlnet.Ipv6Address
copy(addr.Addr[:], ip)
response.Addr.Ipv6Addrs = append(response.Addr.Ipv6Addrs, addr)
}
}
result.SetResponse(response)
return result, nil
}
// This only supports localhost right now, since the netstack DNS client doesn't support reverse DNS.
func (sp *nameLookupImpl) LookupHostname(_ fidl.Context, addr fidlnet.IpAddress) (fidlnet.NameLookupLookupHostnameResult, error) {
var result fidlnet.NameLookupLookupHostnameResult
switch typ := addr.Which(); typ {
case fidlnet.IpAddressIpv4:
if net.IP(addr.Ipv4.Addr[:]).IsLoopback() {
result.SetResponse(fidlnet.NameLookupLookupHostnameResponse{Hostname: "localhost"})
return result, nil
}
case fidlnet.IpAddressIpv6:
if net.IP(addr.Ipv6.Addr[:]).IsLoopback() {
result.SetResponse(fidlnet.NameLookupLookupHostnameResponse{Hostname: "localhost"})
return result, nil
}
default:
panic(fmt.Sprintf("unknown address type: %v", typ))
}
result.SetErr(fidlnet.LookupErrorNotFound)
return result, nil
}