@@ -11,6 +11,7 @@ import (
1111 "net"
1212 "net/netip"
1313 "strconv"
14+ "strings"
1415 "sync/atomic"
1516
1617 "github.com/celzero/firestack/intra/log"
@@ -27,7 +28,7 @@ type DNSOptions struct {
2728}
2829
2930func (d * DNSOptions ) String () string {
30- if ( d == nil ) || ( len ( d . ipp ) <= 0 ) {
31+ if d == nil {
3132 return "<nil>"
3233 }
3334 return d .AddrPort ()
@@ -80,7 +81,7 @@ func NewDNSOptionsFromNetIp(ipp netip.AddrPort) (*DNSOptions, error) {
8081 }, nil
8182}
8283
83- func NewDNSOptionsFromHostname (hostOrHostPort , ipcsv string ) (* DNSOptions , error ) {
84+ func NewDNSOptionsFromHostname (hostOrHostPort , ipOrIPPortCsv string ) (* DNSOptions , error ) {
8485 if len (hostOrHostPort ) <= 0 {
8586 return nil , errDnsOptArg
8687 }
@@ -90,18 +91,51 @@ func NewDNSOptionsFromHostname(hostOrHostPort, ipcsv string) (*DNSOptions, error
9091 if len (domain ) <= 0 {
9192 domain = hostOrHostPort
9293 }
94+
95+ portFromHostPort := len (port ) > 0
9396 portu16 := uint16 (53 )
94- if len (port ) == 0 {
95- port = "53"
96- } else {
97+ if portFromHostPort {
9798 if u64 , _ := strconv .ParseUint (port , 10 , 16 ); u64 > 0 {
9899 portu16 = uint16 (u64 )
100+ } else {
101+ port = "53"
102+ portFromHostPort = false // as if len(port) == 0
103+ }
104+ }
105+
106+ ips := make ([]netip.Addr , 0 )
107+ ports := make ([]uint16 , 0 )
108+ for ipp := range strings .SplitSeq (ipOrIPPortCsv , "," ) {
109+ if addr , err := netip .ParseAddrPort (ipp ); err == nil {
110+ ips = append (ips , addr .Addr ())
111+ if port := addr .Port (); port > 0 {
112+ ports = append (ports , port )
113+ }
114+ } else if addr , err := netip .ParseAddr (ipp ); err == nil {
115+ ips = append (ips , addr )
116+ } else {
117+ log .W ("dnsopt: invalid ip/ipport for %s; ipp(%s); err(%v)" , hostOrHostPort , ipp , err )
99118 }
100119 }
101120
121+ portFromIPPort := len (ports ) > 0
122+ if portFromHostPort {
123+ // skip other checks
124+ } else if portFromIPPort {
125+ // TODO: support multiple ports?
126+ port = strconv .Itoa (int (ports [0 ]))
127+ portu16 = ports [0 ]
128+ } else {
129+ // default port
130+ port = "53"
131+ portu16 = 53
132+ }
133+
134+ log .I ("dnsopt: for %s; len(ips) = %d; port = %s; portFromHostPort? %t; portFromIPPort? %t" ,
135+ hostOrHostPort , len (ips ), port , portFromHostPort , portFromIPPort )
102136 return & DNSOptions {
103137 hostport : net .JoinHostPort (domain , port ),
104- hostips : ipcsv , // may be empty, and may be ip:port
138+ hostips : ipOrIPPortCsv , // may be empty, and may be ip:port
105139 port : portu16 ,
106140 }, nil
107141}
0 commit comments