2023-02-09 10:40:34 +07:00
|
|
|
/*
|
|
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
2024-01-04 16:28:16 +07:00
|
|
|
* Copyright (c) 2022-2024, daeuniverse Organization <dae@v2raya.org>
|
2023-02-09 10:40:34 +07:00
|
|
|
*/
|
|
|
|
|
|
|
|
package netutils
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-03-13 15:40:37 +07:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
2023-04-23 12:27:29 +07:00
|
|
|
"net/netip"
|
|
|
|
"sync"
|
|
|
|
|
2024-04-24 01:22:50 +07:00
|
|
|
"github.com/daeuniverse/outbound/netproxy"
|
2023-07-09 15:02:17 +07:00
|
|
|
dnsmessage "github.com/miekg/dns"
|
2023-03-29 17:14:06 +07:00
|
|
|
"github.com/sirupsen/logrus"
|
2023-02-09 10:40:34 +07:00
|
|
|
)
|
|
|
|
|
|
|
|
type Ip46 struct {
|
|
|
|
Ip4 netip.Addr
|
|
|
|
Ip6 netip.Addr
|
|
|
|
}
|
|
|
|
|
2023-06-04 10:38:05 +07:00
|
|
|
func ResolveIp46(ctx context.Context, dialer netproxy.Dialer, dns netip.AddrPort, host string, network string, race bool) (ipv46 *Ip46, err error) {
|
2023-03-29 17:14:06 +07:00
|
|
|
var log *logrus.Logger
|
|
|
|
if _log := ctx.Value("logger"); _log != nil {
|
|
|
|
log = _log.(*logrus.Logger)
|
|
|
|
defer func() {
|
|
|
|
if err == nil {
|
|
|
|
log.Tracef("ResolveIp46 %v using %v: A(%v) AAAA(%v)", host, systemDns, ipv46.Ip4, ipv46.Ip6)
|
|
|
|
} else {
|
|
|
|
log.Tracef("ResolveIp46 %v using %v: %v", host, systemDns, err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
2023-03-13 15:40:37 +07:00
|
|
|
var wg sync.WaitGroup
|
|
|
|
wg.Add(2)
|
|
|
|
var err4, err6 error
|
|
|
|
var addrs4, addrs6 []netip.Addr
|
|
|
|
ctx4, cancel4 := context.WithCancel(ctx)
|
|
|
|
ctx6, cancel6 := context.WithCancel(ctx)
|
|
|
|
go func() {
|
|
|
|
defer func() {
|
|
|
|
wg.Done()
|
|
|
|
cancel4()
|
|
|
|
if race {
|
|
|
|
cancel6()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
var e error
|
2023-06-04 10:38:05 +07:00
|
|
|
addrs4, e = ResolveNetip(ctx4, dialer, dns, host, dnsmessage.TypeA, network)
|
2023-03-13 15:40:37 +07:00
|
|
|
if err != nil && !errors.Is(e, context.Canceled) {
|
|
|
|
err4 = e
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if len(addrs4) == 0 {
|
|
|
|
addrs4 = []netip.Addr{{}}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
go func() {
|
|
|
|
defer func() {
|
|
|
|
wg.Done()
|
|
|
|
cancel6()
|
|
|
|
if race {
|
|
|
|
cancel4()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
var e error
|
2023-06-04 10:38:05 +07:00
|
|
|
addrs6, e = ResolveNetip(ctx6, dialer, dns, host, dnsmessage.TypeAAAA, network)
|
2023-03-13 15:40:37 +07:00
|
|
|
if err != nil && !errors.Is(e, context.Canceled) {
|
|
|
|
err6 = e
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if len(addrs6) == 0 {
|
|
|
|
addrs6 = []netip.Addr{{}}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
wg.Wait()
|
|
|
|
if err4 != nil || err6 != nil {
|
|
|
|
if err4 != nil && err6 != nil {
|
|
|
|
return nil, fmt.Errorf("%w: %v", err4, err6)
|
|
|
|
}
|
|
|
|
if err4 != nil {
|
|
|
|
return nil, err4
|
|
|
|
} else {
|
|
|
|
return nil, err6
|
|
|
|
}
|
2023-02-09 10:40:34 +07:00
|
|
|
}
|
|
|
|
return &Ip46{
|
|
|
|
Ip4: addrs4[0],
|
|
|
|
Ip6: addrs6[0],
|
|
|
|
}, nil
|
|
|
|
}
|