mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Merge pull request #4769 from Kelimion/mdns
Add tentative mDNS/Bonjour/Avahi query support to `net.resolve`
This commit is contained in:
@@ -95,6 +95,7 @@ Resolve_Error :: enum u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DNS_Error :: enum u32 {
|
DNS_Error :: enum u32 {
|
||||||
|
None = 0,
|
||||||
Invalid_Hostname_Error = 1,
|
Invalid_Hostname_Error = 1,
|
||||||
Invalid_Hosts_Config_Error,
|
Invalid_Hosts_Config_Error,
|
||||||
Invalid_Resolv_Config_Error,
|
Invalid_Resolv_Config_Error,
|
||||||
@@ -147,6 +148,9 @@ IP6_Loopback :: IP6_Address{0, 0, 0, 0, 0, 0, 0, 1}
|
|||||||
IP4_Any := IP4_Address{}
|
IP4_Any := IP4_Address{}
|
||||||
IP6_Any := IP6_Address{}
|
IP6_Any := IP6_Address{}
|
||||||
|
|
||||||
|
IP4_mDNS_Broadcast := Endpoint{address=IP4_Address{224, 0, 0, 251}, port=5353}
|
||||||
|
IP6_mDNS_Broadcast := Endpoint{address=IP6_Address{65282, 0, 0, 0, 0, 0, 0, 251}, port = 5353}
|
||||||
|
|
||||||
Endpoint :: struct {
|
Endpoint :: struct {
|
||||||
address: Address,
|
address: Address,
|
||||||
port: int,
|
port: int,
|
||||||
|
|||||||
+16
-8
@@ -132,7 +132,14 @@ resolve_ip4 :: proc(hostname_and_maybe_port: string) -> (ep4: Endpoint, err: Net
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
case Host:
|
case Host:
|
||||||
recs, _ := get_dns_records_from_os(t.hostname, .IP4, context.temp_allocator)
|
recs: []DNS_Record
|
||||||
|
|
||||||
|
if ODIN_OS != .Windows && strings.has_suffix(t.hostname, ".local") {
|
||||||
|
recs, _ = get_dns_records_from_nameservers(t.hostname, .IP4, {IP4_mDNS_Broadcast}, nil, context.temp_allocator)
|
||||||
|
} else {
|
||||||
|
recs, _ = get_dns_records_from_os(t.hostname, .IP4, context.temp_allocator)
|
||||||
|
}
|
||||||
|
|
||||||
if len(recs) == 0 {
|
if len(recs) == 0 {
|
||||||
err = .Unable_To_Resolve
|
err = .Unable_To_Resolve
|
||||||
return
|
return
|
||||||
@@ -159,7 +166,14 @@ resolve_ip6 :: proc(hostname_and_maybe_port: string) -> (ep6: Endpoint, err: Net
|
|||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
case Host:
|
case Host:
|
||||||
recs, _ := get_dns_records_from_os(t.hostname, .IP6, context.temp_allocator)
|
recs: []DNS_Record
|
||||||
|
|
||||||
|
if ODIN_OS != .Windows && strings.has_suffix(t.hostname, ".local") {
|
||||||
|
recs, _ = get_dns_records_from_nameservers(t.hostname, .IP6, {IP6_mDNS_Broadcast}, nil, context.temp_allocator)
|
||||||
|
} else {
|
||||||
|
recs, _ = get_dns_records_from_os(t.hostname, .IP6, context.temp_allocator)
|
||||||
|
}
|
||||||
|
|
||||||
if len(recs) == 0 {
|
if len(recs) == 0 {
|
||||||
err = .Unable_To_Resolve
|
err = .Unable_To_Resolve
|
||||||
return
|
return
|
||||||
@@ -255,12 +269,6 @@ get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type
|
|||||||
return nil, .Connection_Error
|
return nil, .Connection_Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// recv_sz, _, recv_err := recv_udp(conn, dns_response_buf[:])
|
|
||||||
// if recv_err == UDP_Recv_Error.Timeout {
|
|
||||||
// continue
|
|
||||||
// } else if recv_err != nil {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
recv_sz, _ := recv_udp(conn, dns_response_buf[:]) or_continue
|
recv_sz, _ := recv_udp(conn, dns_response_buf[:]) or_continue
|
||||||
if recv_sz == 0 {
|
if recv_sz == 0 {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -29,9 +29,14 @@ import win "core:sys/windows"
|
|||||||
_get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) {
|
_get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
|
options := win.DNS_QUERY_OPTIONS{}
|
||||||
|
if strings.has_suffix(hostname, ".local") {
|
||||||
|
options = {.MULTICAST_ONLY, .MULTICAST_WAIT} // 0x00020500
|
||||||
|
}
|
||||||
|
|
||||||
host_cstr := strings.clone_to_cstring(hostname, context.temp_allocator)
|
host_cstr := strings.clone_to_cstring(hostname, context.temp_allocator)
|
||||||
rec: ^win.DNS_RECORD
|
rec: ^win.DNS_RECORD
|
||||||
res := win.DnsQuery_UTF8(host_cstr, u16(type), 0, nil, &rec, nil)
|
res := win.DnsQuery_UTF8(host_cstr, u16(type), options, nil, &rec, nil)
|
||||||
|
|
||||||
switch u32(res) {
|
switch u32(res) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ Socket_Option :: enum c.int {
|
|||||||
Send_Buffer_Size = c.int(linux.Socket_Option.SNDBUF),
|
Send_Buffer_Size = c.int(linux.Socket_Option.SNDBUF),
|
||||||
Receive_Timeout = c.int(linux.Socket_Option.RCVTIMEO),
|
Receive_Timeout = c.int(linux.Socket_Option.RCVTIMEO),
|
||||||
Send_Timeout = c.int(linux.Socket_Option.SNDTIMEO),
|
Send_Timeout = c.int(linux.Socket_Option.SNDTIMEO),
|
||||||
|
Broadcast = c.int(linux.Socket_Option.BROADCAST),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrappers and unwrappers for system-native types
|
// Wrappers and unwrappers for system-native types
|
||||||
@@ -337,7 +338,8 @@ _set_option :: proc(sock: Any_Socket, option: Socket_Option, value: any, loc :=
|
|||||||
.Reuse_Address,
|
.Reuse_Address,
|
||||||
.Keep_Alive,
|
.Keep_Alive,
|
||||||
.Out_Of_Bounds_Data_Inline,
|
.Out_Of_Bounds_Data_Inline,
|
||||||
.TCP_Nodelay:
|
.TCP_Nodelay,
|
||||||
|
.Broadcast:
|
||||||
// TODO: verify whether these are options or not on Linux
|
// TODO: verify whether these are options or not on Linux
|
||||||
// .Broadcast, <-- yes
|
// .Broadcast, <-- yes
|
||||||
// .Conditional_Accept,
|
// .Conditional_Accept,
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ foreign import "system:Dnsapi.lib"
|
|||||||
|
|
||||||
@(default_calling_convention="system")
|
@(default_calling_convention="system")
|
||||||
foreign Dnsapi {
|
foreign Dnsapi {
|
||||||
DnsQuery_UTF8 :: proc(name: cstring, type: u16, options: DWORD, extra: PVOID, results: ^^DNS_RECORD, reserved: PVOID) -> DNS_STATUS ---
|
DnsQuery_UTF8 :: proc(name: cstring, type: u16, options: DNS_QUERY_OPTIONS, extra: PVOID, results: ^^DNS_RECORD, reserved: PVOID) -> DNS_STATUS ---
|
||||||
DnsRecordListFree :: proc(list: ^DNS_RECORD, options: DWORD) ---
|
DnsRecordListFree :: proc(list: ^DNS_RECORD, options: DWORD) ---
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4576,6 +4576,31 @@ DNS_SRV_DATAA :: struct {
|
|||||||
_: WORD, // padding
|
_: WORD, // padding
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See https://learn.microsoft.com/en-us/windows/win32/dns/dns-constants
|
||||||
|
DNS_QUERY_OPTION :: enum DWORD {
|
||||||
|
ACCEPT_TRUNCATED_RESPONSE = 0,
|
||||||
|
DNS_QUERY_USE_TCP_ONLY = 1,
|
||||||
|
NO_RECURSION = 2,
|
||||||
|
BYPASS_CACHE = 3,
|
||||||
|
NO_WIRE_QUERY = 4,
|
||||||
|
NO_LOCAL_NAME = 5,
|
||||||
|
NO_HOSTS_FILE = 6,
|
||||||
|
NO_NETBT = 7,
|
||||||
|
WIRE_ONLY = 8,
|
||||||
|
RETURN_MESSAGE = 9,
|
||||||
|
MULTICAST_ONLY = 10,
|
||||||
|
NO_MULTICAST = 11,
|
||||||
|
TREAT_AS_FQDN = 12,
|
||||||
|
ADDRCONFIG = 13,
|
||||||
|
DUAL_ADDR = 14,
|
||||||
|
MULTICAST_WAIT = 17,
|
||||||
|
MULTICAST_VERIFY = 18,
|
||||||
|
DONT_RESET_TTL_VALUES = 20,
|
||||||
|
DISABLE_IDN_ENCODING = 21,
|
||||||
|
APPEND_MULTILABEL = 23,
|
||||||
|
}
|
||||||
|
DNS_QUERY_OPTIONS :: bit_set[DNS_QUERY_OPTION; DWORD]
|
||||||
|
|
||||||
SOCKADDR :: struct {
|
SOCKADDR :: struct {
|
||||||
sa_family: ADDRESS_FAMILY,
|
sa_family: ADDRESS_FAMILY,
|
||||||
sa_data: [14]CHAR,
|
sa_data: [14]CHAR,
|
||||||
|
|||||||
Reference in New Issue
Block a user