15 #ifndef __NET_MDNSIMPL_H__
16 #define __NET_MDNSIMPL_H__
31 #include <sys/socket.h>
32 #include <netinet/in.h>
39 #define MDNS_INVALID_POS ((size_t)-1)
41 #define MDNS_STRING_CONST(s) (s), (sizeof((s)) - 1)
42 #define MDNS_STRING_FORMAT(s) (int)((s).length), s.str
44 #define MDNS_POINTER_OFFSET(p, ofs) ((void*)((char*)(p) + (ptrdiff_t)(ofs)))
45 #define MDNS_POINTER_OFFSET_CONST(p, ofs) ((const void*)((const char*)(p) + (ptrdiff_t)(ofs)))
46 #define MDNS_POINTER_DIFF(a, b) ((size_t)((const char*)(a) - (const char*)(b)))
48 #define MDNS_PORT 5353
49 #define MDNS_UNICAST_RESPONSE 0x8000U
50 #define MDNS_CACHE_FLUSH 0x8000U
58 uint16_t rclass, uint32_t ttl,
const void*
data,
size_t size,
59 size_t name_offset,
size_t name_length,
size_t record_offset,
60 size_t record_length,
void* user_data);
113 mdns_socket_open_ipv4(
struct sockaddr_in* saddr);
121 mdns_socket_setup_ipv4(
int sock,
struct sockaddr_in* saddr);
129 mdns_socket_open_ipv6(
struct sockaddr_in6* saddr);
137 mdns_socket_setup_ipv6(
int sock,
struct sockaddr_in6* saddr);
141 mdns_socket_close(
int sock);
153 mdns_discovery_send(
int sock);
164 mdns_discovery_answer(
int sock,
const void* address,
size_t address_size,
void*
buffer,
165 size_t capacity,
const char* record,
size_t length);
175 size_t capacity, uint16_t query_id);
183 void* user_data,
int query_id);
191 mdns_query_answer(
int sock,
const void* address,
size_t address_size,
void*
buffer,
size_t capacity,
192 uint16_t query_id,
const char* service,
size_t service_length,
193 const char* hostname,
size_t hostname_length, uint32_t ipv4,
const uint8_t* ipv6,
194 uint16_t port,
const char* txt,
size_t txt_length);
199 mdns_string_extract(
const void*
buffer,
size_t size,
size_t*
offset,
char* str,
size_t capacity);
202 mdns_string_skip(
const void*
buffer,
size_t size,
size_t*
offset);
205 mdns_string_equal(
const void* buffer_lhs,
size_t size_lhs,
size_t* ofs_lhs,
const void* buffer_rhs,
206 size_t size_rhs,
size_t* ofs_rhs);
209 mdns_string_make(
void* data,
size_t capacity,
const char*
name,
size_t length);
212 mdns_string_make_ref(
void* data,
size_t capacity,
size_t ref_offset);
215 mdns_string_make_with_ref(
void* data,
size_t capacity,
const char*
name,
size_t length,
220 char* strbuffer,
size_t capacity);
224 char* strbuffer,
size_t capacity);
226 static struct sockaddr_in*
228 struct sockaddr_in* addr);
230 static struct sockaddr_in6*
232 struct sockaddr_in6* addr);
241 mdns_socket_open_ipv4(
struct sockaddr_in* saddr) {
242 int sock = (
int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
245 if (mdns_socket_setup_ipv4(sock, saddr)) {
246 mdns_socket_close(sock);
253 mdns_socket_setup_ipv4(
int sock,
struct sockaddr_in* saddr) {
254 unsigned char ttl = 1;
255 unsigned char loopback = 1;
256 unsigned int reuseaddr = 1;
259 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (
const char*)&reuseaddr,
sizeof(reuseaddr));
261 setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (
const char*)&reuseaddr,
sizeof(reuseaddr));
263 setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (
const char*)&ttl,
sizeof(ttl));
264 setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (
const char*)&loopback,
sizeof(loopback));
266 memset(&req, 0,
sizeof(req));
267 req.imr_multiaddr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U));
269 req.imr_interface = saddr->sin_addr;
270 if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (
char*)&req,
sizeof(req)))
273 struct sockaddr_in sock_addr;
276 memset(saddr, 0,
sizeof(
struct sockaddr_in));
277 saddr->sin_family = AF_INET;
278 saddr->sin_addr.s_addr = INADDR_ANY;
280 saddr->sin_len =
sizeof(
struct sockaddr_in);
283 setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (
const char*)&saddr->sin_addr,
284 sizeof(saddr->sin_addr));
286 saddr->sin_addr.s_addr = INADDR_ANY;
290 if (bind(sock, (
struct sockaddr*)saddr,
sizeof(
struct sockaddr_in)))
294 unsigned long param = 1;
295 ioctlsocket(sock, FIONBIO, ¶m);
297 const int flags = fcntl(sock, F_GETFL, 0);
298 fcntl(sock, F_SETFL, flags | O_NONBLOCK);
305 mdns_socket_open_ipv6(
struct sockaddr_in6* saddr) {
306 int sock = (
int)socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
309 if (mdns_socket_setup_ipv6(sock, saddr)) {
310 mdns_socket_close(sock);
317 mdns_socket_setup_ipv6(
int sock,
struct sockaddr_in6* saddr) {
319 unsigned int loopback = 1;
320 unsigned int reuseaddr = 1;
321 struct ipv6_mreq req;
323 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (
const char*)&reuseaddr,
sizeof(reuseaddr));
325 setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (
const char*)&reuseaddr,
sizeof(reuseaddr));
327 setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (
const char*)&hops,
sizeof(hops));
328 setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (
const char*)&loopback,
sizeof(loopback));
330 memset(&req, 0,
sizeof(req));
331 req.ipv6mr_multiaddr.s6_addr[0] = 0xFF;
332 req.ipv6mr_multiaddr.s6_addr[1] = 0x02;
333 req.ipv6mr_multiaddr.s6_addr[15] = 0xFB;
334 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (
char*)&req,
sizeof(req)))
337 struct sockaddr_in6 sock_addr;
340 memset(saddr, 0,
sizeof(
struct sockaddr_in6));
341 saddr->sin6_family = AF_INET6;
342 saddr->sin6_addr = in6addr_any;
344 saddr->sin6_len =
sizeof(
struct sockaddr_in6);
347 unsigned int ifindex = 0;
348 setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (
const char*)&ifindex,
sizeof(ifindex));
350 saddr->sin6_addr = in6addr_any;
354 if (bind(sock, (
struct sockaddr*)saddr,
sizeof(
struct sockaddr_in6)))
358 unsigned long param = 1;
359 ioctlsocket(sock, FIONBIO, ¶m);
361 const int flags = fcntl(sock, F_GETFL, 0);
362 fcntl(sock, F_SETFL, flags | O_NONBLOCK);
369 mdns_socket_close(
int sock) {
378 mdns_is_string_ref(uint8_t
val) {
379 return (0xC0 == (val & 0xC0));
383 mdns_get_next_substring(
const void* rawdata,
size_t size,
size_t offset) {
384 const uint8_t*
buffer = (
const uint8_t*)rawdata;
386 if (!buffer[offset]) {
390 if (mdns_is_string_ref(buffer[offset])) {
391 if (size < offset + 2)
401 size_t length = (size_t)buffer[offset++];
402 if (size < offset + length)
412 mdns_string_skip(
const void* buffer,
size_t size,
size_t* offset) {
416 substr = mdns_get_next_substring(buffer, size, cur);
431 mdns_string_equal(
const void* buffer_lhs,
size_t size_lhs,
size_t* ofs_lhs,
const void* buffer_rhs,
432 size_t size_rhs,
size_t* ofs_rhs) {
433 size_t lhs_cur = *ofs_lhs;
434 size_t rhs_cur = *ofs_rhs;
440 lhs_substr = mdns_get_next_substring(buffer_lhs, size_lhs, lhs_cur);
441 rhs_substr = mdns_get_next_substring(buffer_rhs, size_rhs, rhs_cur);
447 (
const char*)buffer_lhs + lhs_substr.
offset, rhs_substr.
length))
450 lhs_end = lhs_cur + 2;
452 rhs_end = rhs_cur + 2;
455 }
while (lhs_substr.
length);
458 lhs_end = lhs_cur + 1;
462 rhs_end = rhs_cur + 1;
469 mdns_string_extract(
const void* buffer,
size_t size,
size_t* offset,
char* str,
size_t capacity) {
477 size_t remain = capacity;
479 substr = mdns_get_next_substring(buffer, size, cur);
485 size_t to_copy = (substr.
length < remain) ? substr.
length : remain;
486 memcpy(dst, (
const char*)buffer + substr.
offset, to_copy);
501 result.
length = capacity - remain;
506 mdns_string_find(
const char* str,
size_t length,
char c,
size_t offset) {
508 if (offset >= length)
510 found = memchr(str + offset, c, length - offset);
512 return (
size_t)((
const char*)found - str);
517 mdns_string_make(
void* data,
size_t capacity,
const char*
name,
size_t length) {
520 size_t remain = capacity;
521 unsigned char* dest = (
unsigned char*)data;
522 while ((last_pos < length) &&
523 ((pos = mdns_string_find(name, length,
'.', last_pos)) !=
MDNS_INVALID_POS)) {
524 size_t sublength = pos - last_pos;
525 if (sublength < remain) {
526 *dest = (
unsigned char)sublength;
527 memcpy(dest + 1, name + last_pos, sublength);
528 dest += sublength + 1;
529 remain -= sublength + 1;
535 if (last_pos < length) {
536 size_t sublength = length - last_pos;
537 if (sublength < remain) {
538 *dest = (
unsigned char)sublength;
539 memcpy(dest + 1, name + last_pos, sublength);
540 dest += sublength + 1;
541 remain -= sublength + 1;
553 mdns_string_make_ref(
void* data,
size_t capacity,
size_t ref_offset) {
556 uint16_t* udata = (uint16_t*)data;
557 *udata++ = htons(0xC000 | (uint16_t)ref_offset);
562 mdns_string_make_with_ref(
void* data,
size_t capacity,
const char* name,
size_t length,
564 void* remaindata = mdns_string_make(data, capacity, name, length);
566 if (!data || !capacity)
568 return mdns_string_make_ref(
MDNS_POINTER_OFFSET(remaindata, -1), capacity + 1, ref_offset);
572 mdns_records_parse(
int sock,
const struct sockaddr* from,
size_t addrlen,
const void* buffer,
576 int do_callback = (callback ? 1 : 0);
577 for (
size_t i = 0; i < records; ++i) {
578 size_t name_offset = *
offset;
579 mdns_string_skip(buffer, size, offset);
580 size_t name_length = (*offset) - name_offset;
581 const uint16_t* data = (
const uint16_t*)((
const char*)buffer + (*offset));
583 uint16_t rtype = ntohs(*data++);
584 uint16_t rclass = ntohs(*data++);
585 uint32_t ttl = ntohl(*(
const uint32_t*)(
const void*)data);
587 uint16_t length = ntohs(*data++);
593 if (callback(sock, from, addrlen, type, query_id, rtype, rclass, ttl, buffer, size,
594 name_offset, name_length, *offset, length, user_data))
604 mdns_unicast_send(
int sock,
const void* address,
size_t address_size,
const void* buffer,
606 if (sendto(sock, (
const char*)buffer, (mdns_size_t)size, 0, (
const struct sockaddr*)address,
607 (socklen_t)address_size) < 0)
613 mdns_multicast_send(
int sock,
const void* buffer,
size_t size) {
614 struct sockaddr_storage addr_storage;
615 struct sockaddr_in addr;
616 struct sockaddr_in6 addr6;
617 struct sockaddr* saddr = (
struct sockaddr*)&addr_storage;
618 socklen_t saddrlen =
sizeof(
struct sockaddr_storage);
619 if (getsockname(sock, saddr, &saddrlen))
621 if (saddr->sa_family == AF_INET6) {
622 memset(&addr6, 0,
sizeof(addr6));
623 addr6.sin6_family = AF_INET6;
625 addr6.sin6_len =
sizeof(addr6);
627 addr6.sin6_addr.s6_addr[0] = 0xFF;
628 addr6.sin6_addr.s6_addr[1] = 0x02;
629 addr6.sin6_addr.s6_addr[15] = 0xFB;
630 addr6.sin6_port = htons((
unsigned short)
MDNS_PORT);
631 saddr = (
struct sockaddr*)&addr6;
632 saddrlen =
sizeof(addr6);
634 memset(&addr, 0,
sizeof(addr));
635 addr.sin_family = AF_INET;
637 addr.sin_len =
sizeof(addr);
639 addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U));
640 addr.sin_port = htons((
unsigned short)
MDNS_PORT);
641 saddr = (
struct sockaddr*)&addr;
642 saddrlen =
sizeof(addr);
645 if (sendto(sock, (
const char*)
buffer, (
mdns_size_t)size, 0, saddr, saddrlen) < 0)
650 static const uint8_t mdns_services_query[] = {
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x09,
'_',
's',
'e',
'r',
'v',
'i',
'c',
'e',
's', 0x07,
'_',
'd',
'n',
's',
'-',
's',
'd',
661 0x04,
'_',
'u',
'd',
'p', 0x05,
'l',
'o',
'c',
'a',
'l', 0x00,
668 mdns_discovery_send(
int sock) {
669 return mdns_multicast_send(sock, mdns_services_query,
sizeof(mdns_services_query));
675 struct sockaddr_in6 addr;
676 struct sockaddr* saddr = (
struct sockaddr*)&addr;
677 socklen_t addrlen =
sizeof(addr);
678 memset(&addr, 0,
sizeof(addr));
680 saddr->sa_len =
sizeof(addr);
682 int ret = recvfrom(sock, (
char*)buffer, (mdns_size_t)capacity, 0, saddr, &addrlen);
686 size_t data_size = (size_t)ret;
688 uint16_t* data = (uint16_t*)buffer;
690 uint16_t query_id = ntohs(*data++);
691 uint16_t
flags = ntohs(*data++);
692 uint16_t questions = ntohs(*data++);
693 uint16_t answer_rrs = ntohs(*data++);
694 uint16_t authority_rrs = ntohs(*data++);
695 uint16_t additional_rrs = ntohs(*data++);
698 if (query_id || (flags != 0x8400))
709 for (i = 0; i < questions; ++i) {
710 size_t ofs = (size_t)((
char*)data - (
char*)buffer);
711 size_t verify_ofs = 12;
713 if (!mdns_string_equal(buffer, data_size, &ofs, mdns_services_query,
714 sizeof(mdns_services_query), &verify_ofs))
716 data = (uint16_t*)((
char*)buffer + ofs);
718 uint16_t rtype = ntohs(*data++);
719 uint16_t rclass = ntohs(*data++);
727 for (i = 0; i < answer_rrs; ++i) {
728 size_t ofs = (size_t)((
char*)data - (
char*)buffer);
729 size_t verify_ofs = 12;
731 size_t name_offset = ofs;
732 int is_answer = mdns_string_equal(buffer, data_size, &ofs, mdns_services_query,
733 sizeof(mdns_services_query), &verify_ofs);
734 size_t name_length = ofs - name_offset;
735 data = (uint16_t*)((
char*)buffer + ofs);
737 uint16_t rtype = ntohs(*data++);
738 uint16_t rclass = ntohs(*data++);
739 uint32_t ttl = ntohl(*(uint32_t*)(
void*)data);
741 uint16_t length = ntohs(*data++);
742 if (length >= (data_size - ofs))
745 if (is_answer && do_callback) {
747 ofs = (size_t)((
char*)data - (
char*)buffer);
749 buffer, data_size, name_offset, name_length, ofs, length, user_data))
752 data = (uint16_t*)((
char*)data +
length);
755 size_t offset = (size_t)((
char*)data - (
char*)buffer);
757 mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
759 records += mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
769 struct sockaddr_in6 addr;
770 struct sockaddr* saddr = (
struct sockaddr*)&addr;
771 socklen_t addrlen =
sizeof(addr);
772 memset(&addr, 0,
sizeof(addr));
774 saddr->sa_len =
sizeof(addr);
776 int ret = recvfrom(sock, (
char*)buffer, (mdns_size_t)capacity, 0, saddr, &addrlen);
780 size_t data_size = (size_t)ret;
781 uint16_t* data = (uint16_t*)buffer;
783 uint16_t query_id = ntohs(*data++);
784 uint16_t flags = ntohs(*data++);
785 uint16_t questions = ntohs(*data++);
795 for (
int iquestion = 0; iquestion < questions; ++iquestion) {
796 size_t question_offset = (size_t)((
char*)data - (
char*)buffer);
797 size_t offset = question_offset;
798 size_t verify_ofs = 12;
799 if (mdns_string_equal(buffer, data_size, &offset, mdns_services_query,
800 sizeof(mdns_services_query), &verify_ofs)) {
801 if (flags || (questions != 1))
804 offset = question_offset;
805 if (!mdns_string_skip(buffer, data_size, &offset))
808 size_t length = offset - question_offset;
809 data = (uint16_t*)((
char*)buffer +
offset);
811 uint16_t rtype = ntohs(*data++);
812 uint16_t rclass = ntohs(*data++);
820 buffer, data_size, question_offset, length, question_offset, length,
830 mdns_discovery_answer(
int sock,
const void* address,
size_t address_size,
void* buffer,
831 size_t capacity,
const char* record,
size_t length) {
832 if (capacity < (
sizeof(mdns_services_query) + 32 + length))
835 uint16_t* data = (uint16_t*)buffer;
837 memcpy(data, mdns_services_query,
sizeof(mdns_services_query));
839 uint16_t* flags = data + 1;
840 *flags = htons(0x8400U);
842 uint16_t* answers = data + 3;
846 data = (uint16_t*)((
char*)buffer +
sizeof(mdns_services_query));
848 *data++ = htons(0xC000U | 12U);
854 *(uint32_t*)data = htonl(10);
857 uint16_t* record_length = data++;
858 uint8_t* record_data = (uint8_t*)data;
859 size_t remain = capacity - (
sizeof(mdns_services_query) + 10);
860 record_data = (uint8_t*)mdns_string_make(record_data, remain, record, length);
861 *record_length = htons((uint16_t)(record_data - (uint8_t*)data));
864 ptrdiff_t tosend = (
char*)record_data - (
char*)
buffer;
865 return mdns_unicast_send(sock, address, address_size, buffer, (
size_t)tosend);
869 mdns_query_send(
int sock,
NET_mDNSRecordType type,
const char* name,
size_t length,
void* buffer,
870 size_t capacity, uint16_t query_id) {
871 if (capacity < (17 + length))
876 struct sockaddr_storage addr_storage;
877 struct sockaddr* saddr = (
struct sockaddr*)&addr_storage;
878 socklen_t saddrlen =
sizeof(addr_storage);
879 if (getsockname(sock, saddr, &saddrlen) == 0) {
880 if ((saddr->sa_family == AF_INET) &&
881 (ntohs(((
struct sockaddr_in*)saddr)->sin_port) ==
MDNS_PORT))
883 else if ((saddr->sa_family == AF_INET6) &&
884 (ntohs(((
struct sockaddr_in6*)saddr)->sin6_port) ==
MDNS_PORT))
888 uint16_t* data = (uint16_t*)buffer;
890 *data++ = htons(query_id);
901 data = (uint16_t*)mdns_string_make(data, capacity - 17, name, length);
905 *data++ = htons(type);
907 *data++ = htons(rclass);
909 ptrdiff_t tosend = (
char*)data - (
char*)
buffer;
910 if (mdns_multicast_send(sock, buffer, (
size_t)tosend))
917 void* user_data,
int only_query_id) {
918 struct sockaddr_in6 addr;
919 struct sockaddr* saddr = (
struct sockaddr*)&addr;
920 socklen_t addrlen =
sizeof(addr);
921 memset(&addr, 0,
sizeof(addr));
923 saddr->sa_len =
sizeof(addr);
925 int ret = recvfrom(sock, (
char*)buffer, (mdns_size_t)capacity, 0, saddr, &addrlen);
929 size_t data_size = (size_t)ret;
930 uint16_t* data = (uint16_t*)buffer;
932 uint16_t query_id = ntohs(*data++);
933 uint16_t flags = ntohs(*data++);
934 uint16_t questions = ntohs(*data++);
935 uint16_t answer_rrs = ntohs(*data++);
936 uint16_t authority_rrs = ntohs(*data++);
937 uint16_t additional_rrs = ntohs(*data++);
940 if ((only_query_id > 0) && (query_id != only_query_id))
948 for (i = 0; i < questions; ++i) {
949 size_t ofs = (size_t)((
char*)data - (
char*)buffer);
950 if (!mdns_string_skip(buffer, data_size, &ofs))
952 data = (uint16_t*)((
char*)buffer + ofs);
953 uint16_t rtype = ntohs(*data++);
954 uint16_t rclass = ntohs(*data++);
956 (
void)
sizeof(rclass);
961 records += mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
964 mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
966 records += mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
973 mdns_query_answer(
int sock,
const void* address,
size_t address_size,
void* buffer,
size_t capacity,
974 uint16_t query_id,
const char* service,
size_t service_length,
975 const char* hostname,
size_t hostname_length, uint32_t ipv4,
const uint8_t* ipv6,
976 uint16_t port,
const char* txt,
size_t txt_length) {
977 if (capacity < (
sizeof(
struct mdns_header_t) + 32 + service_length + hostname_length))
980 int unicast = (address_size ? 1 : 0);
981 int use_ipv4 = (ipv4 != 0);
982 int use_ipv6 = (ipv6 != 0);
983 int use_txt = (txt && txt_length && (txt_length <= 255));
987 uint32_t ttl = (unicast ? 10 : 60);
988 uint32_t a_ttl = ttl;
992 header->
query_id = (address_size ? htons(query_id) : 0);
993 header->
flags = htons(0x8400);
994 header->
questions = htons(unicast ? 1 : 0);
997 header->
additional_rrs = htons((
unsigned short)(1 + use_ipv4 + use_ipv6 + use_txt));
1001 size_t remain, service_offset = 0, local_offset = 0, full_offset, host_offset;
1006 remain = capacity - service_offset;
1007 data = mdns_string_make(data, remain, service, service_length);
1010 if (!data || (remain <= 4))
1013 udata = (uint16_t*)data;
1015 *udata++ = htons(question_rclass);
1023 data = mdns_string_make_ref(data, remain, service_offset);
1026 remain = capacity - service_offset;
1027 data = mdns_string_make(data, remain, service, service_length);
1031 if (!data || (remain <= 10))
1033 udata = (uint16_t*)data;
1035 *udata++ = htons(rclass);
1036 *(uint32_t*)udata = htonl(ttl);
1038 uint16_t* record_length = udata++;
1042 remain = capacity - full_offset;
1043 data = mdns_string_make_with_ref(data, remain, hostname, hostname_length, service_offset);
1045 if (!data || (remain <= 10))
1051 data = mdns_string_make_ref(data, remain, full_offset);
1053 if (!data || (remain <= 10))
1055 udata = (uint16_t*)data;
1057 *udata++ = htons(rclass);
1058 *(uint32_t*)udata = htonl(ttl);
1060 record_length = udata++;
1061 *udata++ = htons(0);
1062 *udata++ = htons(0);
1063 *udata++ = htons(port);
1067 remain = capacity - host_offset;
1068 data = mdns_string_make_with_ref(data, remain, hostname, hostname_length, local_offset);
1070 if (!data || (remain <= 10))
1076 data = mdns_string_make_ref(data, remain, host_offset);
1078 if (!data || (remain <= 14))
1080 udata = (uint16_t*)data;
1082 *udata++ = htons(rclass);
1083 *(uint32_t*)udata = htonl(a_ttl);
1085 *udata++ = htons(4);
1086 *(uint32_t*)udata = ipv4;
1094 data = mdns_string_make_ref(data, remain, host_offset);
1096 if (!data || (remain <= 26))
1098 udata = (uint16_t*)data;
1100 *udata++ = htons(rclass);
1101 *(uint32_t*)udata = htonl(a_ttl);
1103 *udata++ = htons(16);
1104 memcpy(udata, ipv6, 16);
1111 data = mdns_string_make_ref(data, remain, full_offset);
1113 if (!data || (remain <= (11 + txt_length)))
1115 udata = (uint16_t*)data;
1117 *udata++ = htons(rclass);
1118 *(uint32_t*)udata = htonl(ttl);
1120 *udata++ = htons((
unsigned short)(txt_length + 1));
1121 char* txt_record = (
char*)udata;
1122 *txt_record++ = (char)txt_length;
1123 memcpy(txt_record, txt, txt_length);
1131 return mdns_unicast_send(sock, address, address_size, buffer, tosend);
1132 return mdns_multicast_send(sock, buffer, tosend);
1136 mdns_record_parse_ptr(
const void* buffer,
size_t size,
size_t offset,
size_t length,
1137 char* strbuffer,
size_t capacity) {
1139 if ((size >= offset + length) && (length >= 2))
1140 return mdns_string_extract(buffer, size, &offset, strbuffer, capacity);
1146 mdns_record_parse_srv(
const void* buffer,
size_t size,
size_t offset,
size_t length,
1147 char* strbuffer,
size_t capacity) {
1156 if ((size >= offset + length) && (length >= 8)) {
1157 const uint16_t* recorddata = (
const uint16_t*)((
const char*)buffer +
offset);
1158 srv.
priority = ntohs(*recorddata++);
1159 srv.
weight = ntohs(*recorddata++);
1160 srv.
port = ntohs(*recorddata++);
1162 srv.
name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity);
1167 static struct sockaddr_in*
1168 mdns_record_parse_a(
const void* buffer,
size_t size,
size_t offset,
size_t length,
1169 struct sockaddr_in* addr) {
1170 memset(addr, 0,
sizeof(
struct sockaddr_in));
1171 addr->sin_family = AF_INET;
1173 addr->sin_len =
sizeof(
struct sockaddr_in);
1175 if ((size >= offset + length) && (length == 4))
1176 addr->sin_addr.s_addr = *(
const uint32_t*)((
const char*)buffer +
offset);
1180 static struct sockaddr_in6*
1181 mdns_record_parse_aaaa(
const void* buffer,
size_t size,
size_t offset,
size_t length,
1182 struct sockaddr_in6* addr) {
1183 memset(addr, 0,
sizeof(
struct sockaddr_in6));
1184 addr->sin6_family = AF_INET6;
1186 addr->sin6_len =
sizeof(
struct sockaddr_in6);
1188 if ((size >= offset + length) && (length == 16))
1189 addr->sin6_addr = *(
const struct in6_addr*)((
const char*)buffer +
offset);
1194 mdns_record_parse_txt(
const void* buffer,
size_t size,
size_t offset,
size_t length,
1197 const char* strdata;
1198 size_t separator, sublength;
1199 size_t end = offset +
length;
1204 while ((offset < end) && (parsed < capacity)) {
1205 strdata = (
const char*)buffer + offset;
1206 sublength = *(
const unsigned char*)strdata;
1209 offset += sublength + 1;
1212 for (
size_t c = 0; c < sublength; ++
c) {
1214 if ((strdata[c] < 0x20) || (strdata[
c] > 0x7E))
1216 if (strdata[c] ==
'=') {
1225 if (separator < sublength) {
1226 records[parsed].
key.
str = strdata;
1228 records[parsed].
value.
str = strdata + separator + 1;
1229 records[parsed].
value.
length = sublength - (separator + 1);
1231 records[parsed].
key.
str = strdata;
1245 #endif // __NET_MDNSIMPL_H__
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
#define MDNS_UNICAST_RESPONSE
GLuint GLsizei GLsizei * length
**But if you need a result
#define MDNS_POINTER_DIFF(a, b)
int(* mdns_record_callback_fn)(int sock, const struct sockaddr *from, size_t addrlen, NET_mDNSEntryType entry, uint16_t query_id, uint16_t rtype, uint16_t rclass, uint32_t ttl, const void *data, size_t size, size_t name_offset, size_t name_length, size_t record_offset, size_t record_length, void *user_data)
int SYSstrncasecmp(const char *a, const char *b, size_t n)
GLuint const GLchar * name
enum mdns_class mdns_class_t
#define MDNS_POINTER_OFFSET(p, ofs)