dnssd_clientstub.c [plain text]
#include <errno.h>
#include <stdlib.h>
#if defined(_WIN32)
#include <winsock2.h>
#include <windows.h>
#define sockaddr_mdns sockaddr_in
#define AF_MDNS AF_INET
#else
#include <sys/time.h>
#include <sys/socket.h>
#define sockaddr_mdns sockaddr_un
#define AF_MDNS AF_LOCAL
#endif
#include "dnssd_ipc.h"
#if defined(_WIN32)
#pragma warning(disable:4055)
#pragma warning(disable:4152)
#define sleep(X) Sleep((X) * 1000)
static int g_initWinsock = 0;
#endif
#define CTL_PATH_PREFIX "/tmp/dnssd_clippath."
typedef struct _DNSServiceRef_t
{
dnssd_sock_t sockfd; uint32_t op; process_reply_callback process_reply;
void *app_callback;
void *app_context;
uint32_t max_index; } _DNSServiceRef_t;
typedef struct _DNSRecordRef_t
{
void *app_context;
DNSServiceRegisterRecordReply app_callback;
DNSRecordRef recref;
uint32_t record_index; DNSServiceRef sdr;
} _DNSRecordRef_t;
static int my_write(dnssd_sock_t sd, char *buf, int len)
{
while (len)
{
ssize_t num_written = send(sd, buf, len, 0);
if (num_written < 0 || num_written > len) return -1;
buf += num_written;
len -= num_written;
}
return 0;
}
static int my_read(dnssd_sock_t sd, char *buf, int len)
{
while (len)
{
ssize_t num_read = recv(sd, buf, len, 0);
if ((num_read == 0) || (num_read < 0) || (num_read > len)) return -1;
buf += num_read;
len -= num_read;
}
return 0;
}
static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int reuse_socket)
{
char *msg = NULL;
ipc_msg_hdr *hdr;
int datalen;
char ctrl_path[256];
if (!reuse_socket)
{
#if defined(USE_TCP_LOOPBACK)
*len += 2; #else
struct timeval time;
if (gettimeofday(&time, NULL) < 0) return NULL;
sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(),
(unsigned long)(time.tv_sec & 0xFFF), (unsigned long)(time.tv_usec));
*len += strlen(ctrl_path) + 1;
#endif
}
datalen = (int) *len;
*len += sizeof(ipc_msg_hdr);
msg = malloc(*len);
if (!msg) return NULL;
bzero(msg, *len);
hdr = (void *)msg;
hdr->datalen = datalen;
hdr->version = VERSION;
hdr->op = op;
if (reuse_socket) hdr->flags |= IPC_FLAGS_REUSE_SOCKET;
*data_start = msg + sizeof(ipc_msg_hdr);
#if defined(USE_TCP_LOOPBACK)
if (!reuse_socket) put_short(0, data_start);
#else
if (!reuse_socket) put_string(ctrl_path, data_start);
#endif
return hdr;
}
static DNSServiceRef connect_to_server(void)
{
dnssd_sockaddr_t saddr;
DNSServiceRef sdr;
static unsigned int NumTries = 0;
#if defined(_WIN32)
if (!g_initWinsock)
{
WSADATA wsaData;
DNSServiceErrorType err;
g_initWinsock = 1;
err = WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
if (err != 0) return NULL;
}
#endif
sdr = malloc(sizeof(_DNSServiceRef_t));
if (!sdr) return(NULL);
sdr->sockfd = socket(AF_DNSSD, SOCK_STREAM, 0);
if (sdr->sockfd == dnssd_InvalidSocket) { free(sdr); return NULL; }
#if defined(USE_TCP_LOOPBACK)
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
saddr.sin_port = htons(MDNS_TCP_SERVERPORT);
#else
saddr.sun_family = AF_LOCAL;
strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH);
#endif
while (1)
{
int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr));
if (!err) break; if (++NumTries < 3)
sleep(1); else
{
dnssd_close(sdr->sockfd);
sdr->sockfd = dnssd_InvalidSocket;
free(sdr);
return NULL;
}
}
return sdr;
}
static DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reuse_sd)
{
ipc_msg_hdr *hdr = msg;
uint32_t datalen = hdr->datalen;
dnssd_sockaddr_t caddr, daddr; char *data = (char *)msg + sizeof(ipc_msg_hdr);
dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
int ret;
unsigned int len = sizeof(caddr);
DNSServiceErrorType err = kDNSServiceErr_Unknown;
if (!hdr || sdr->sockfd < 0) return kDNSServiceErr_Unknown;
if (!reuse_sd)
{
if ((listenfd = socket(AF_DNSSD, SOCK_STREAM, 0)) < 0)
goto cleanup;
bzero(&caddr, sizeof(caddr));
#if defined(USE_TCP_LOOPBACK)
{
union { uint16_t s; u_char b[2]; } port;
caddr.sin_family = AF_INET;
caddr.sin_port = 0;
caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
ret = bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr));
if (ret < 0) goto cleanup;
if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) goto cleanup;
listen(listenfd, 1);
port.s = caddr.sin_port;
data[0] = port.b[0]; data[1] = port.b[1]; }
#else
{
mode_t mask = umask(0);
caddr.sun_family = AF_LOCAL;
#ifndef NOT_HAVE_SA_LEN // According to Stevens (section 3.2), there is no portable way to
caddr.sun_len = sizeof(struct sockaddr_un);
#endif
strcpy(caddr.sun_path, data);
ret = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
umask(mask);
if (ret < 0) goto cleanup;
listen(listenfd, 1);
}
#endif
}
ConvertHeaderBytes(hdr);
if (my_write(sdr->sockfd, msg, datalen + sizeof(ipc_msg_hdr)) < 0)
goto cleanup;
free(msg);
msg = NULL;
if (reuse_sd) errsd = sdr->sockfd;
else
{
len = sizeof(daddr);
errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
if (errsd < 0) goto cleanup;
}
if (my_read(errsd, (char*)&err, (int)sizeof(err)) < 0)
err = kDNSServiceErr_Unknown;
else
err = ntohl(err);
cleanup:
if (!reuse_sd && listenfd > 0) dnssd_close(listenfd);
if (!reuse_sd && errsd > 0) dnssd_close(errsd);
#if !defined(USE_TCP_LOOPBACK)
if (!reuse_sd && data) unlink(data);
#endif
if (msg) free(msg);
return err;
}
int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
{
if (!sdRef) return -1;
return (int) sdRef->sockfd;
}
DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
{
ipc_msg_hdr hdr;
char *data;
if (!sdRef || sdRef->sockfd < 0 || !sdRef->process_reply)
return kDNSServiceErr_BadReference;
if (my_read(sdRef->sockfd, (void *)&hdr, sizeof(hdr)) < 0)
return (dnssd_errno() == dnssd_EWOULDBLOCK) ? kDNSServiceErr_NoError : kDNSServiceErr_Unknown;
ConvertHeaderBytes(&hdr);
if (hdr.version != VERSION)
return kDNSServiceErr_Incompatible;
data = malloc(hdr.datalen);
if (!data) return kDNSServiceErr_NoMemory;
if (my_read(sdRef->sockfd, data, hdr.datalen) < 0)
return kDNSServiceErr_Unknown;
sdRef->process_reply(sdRef, &hdr, data);
free(data);
return kDNSServiceErr_NoError;
}
void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef)
{
if (!sdRef) return;
if (sdRef->sockfd > 0) dnssd_close(sdRef->sockfd);
free(sdRef);
}
static void handle_resolve_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
{
DNSServiceFlags flags;
char fullname[kDNSServiceMaxDomainName];
char target[kDNSServiceMaxDomainName];
uint16_t txtlen;
union { uint16_t s; u_char b[2]; } port;
uint32_t ifi;
DNSServiceErrorType err;
char *txtrecord;
int str_error = 0;
(void)hdr;
flags = get_flags(&data);
ifi = get_long(&data);
err = get_error_code(&data);
if (get_string(&data, fullname, kDNSServiceMaxDomainName) < 0) str_error = 1;
if (get_string(&data, target, kDNSServiceMaxDomainName) < 0) str_error = 1;
port.b[0] = *data++;
port.b[1] = *data++;
txtlen = get_short(&data);
txtrecord = get_rdata(&data, txtlen);
if (!err && str_error) err = kDNSServiceErr_Unknown;
((DNSServiceResolveReply)sdr->app_callback)(sdr, flags, ifi, err, fullname, target, port.s, txtlen, txtrecord, sdr->app_context);
}
DNSServiceErrorType DNSSD_API DNSServiceResolve
(
DNSServiceRef *sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
const char *name,
const char *regtype,
const char *domain,
DNSServiceResolveReply callBack,
void *context
)
{
char *msg = NULL, *ptr;
size_t len;
ipc_msg_hdr *hdr;
DNSServiceRef sdr;
DNSServiceErrorType err;
if (!sdRef) return kDNSServiceErr_BadParam;
*sdRef = NULL;
if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam;
len = sizeof(flags);
len += sizeof(interfaceIndex);
len += strlen(name) + 1;
len += strlen(regtype) + 1;
len += strlen(domain) + 1;
hdr = create_hdr(resolve_request, &len, &ptr, 1);
if (!hdr) goto error;
msg = (void *)hdr;
put_flags(flags, &ptr);
put_long(interfaceIndex, &ptr);
put_string(name, &ptr);
put_string(regtype, &ptr);
put_string(domain, &ptr);
sdr = connect_to_server();
if (!sdr) goto error;
err = deliver_request(msg, sdr, 1);
if (err)
{
DNSServiceRefDeallocate(sdr);
return err;
}
sdr->op = resolve_request;
sdr->process_reply = handle_resolve_response;
sdr->app_callback = callBack;
sdr->app_context = context;
*sdRef = sdr;
return err;
error:
if (msg) free(msg);
if (*sdRef) { free(*sdRef); *sdRef = NULL; }
return kDNSServiceErr_Unknown;
}
static void handle_query_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
{
DNSServiceFlags flags;
uint32_t interfaceIndex, ttl;
DNSServiceErrorType errorCode;
char name[kDNSServiceMaxDomainName];
uint16_t rrtype, rrclass, rdlen;
char *rdata;
int str_error = 0;
(void)hdr;
flags = get_flags(&data);
interfaceIndex = get_long(&data);
errorCode = get_error_code(&data);
if (get_string(&data, name, kDNSServiceMaxDomainName) < 0) str_error = 1;
rrtype = get_short(&data);
rrclass = get_short(&data);
rdlen = get_short(&data);
rdata = get_rdata(&data, rdlen);
ttl = get_long(&data);
if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown;
((DNSServiceQueryRecordReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, name, rrtype, rrclass,
rdlen, rdata, ttl, sdr->app_context);
return;
}
DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
(
DNSServiceRef *sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
const char *name,
uint16_t rrtype,
uint16_t rrclass,
DNSServiceQueryRecordReply callBack,
void *context
)
{
char *msg = NULL, *ptr;
size_t len;
ipc_msg_hdr *hdr;
DNSServiceRef sdr;
DNSServiceErrorType err;
if (!sdRef) return kDNSServiceErr_BadParam;
*sdRef = NULL;
if (!name) name = "\0";
len = sizeof(flags);
len += sizeof(uint32_t); len += strlen(name) + 1;
len += 2 * sizeof(uint16_t);
hdr = create_hdr(query_request, &len, &ptr, 1);
if (!hdr) goto error;
msg = (void *)hdr;
put_flags(flags, &ptr);
put_long(interfaceIndex, &ptr);
put_string(name, &ptr);
put_short(rrtype, &ptr);
put_short(rrclass, &ptr);
sdr = connect_to_server();
if (!sdr) goto error;
err = deliver_request(msg, sdr, 1);
if (err)
{
DNSServiceRefDeallocate(sdr);
return err;
}
sdr->op = query_request;
sdr->process_reply = handle_query_response;
sdr->app_callback = callBack;
sdr->app_context = context;
*sdRef = sdr;
return err;
error:
if (msg) free(msg);
if (*sdRef) { free(*sdRef); *sdRef = NULL; }
return kDNSServiceErr_Unknown;
}
static void handle_browse_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
{
DNSServiceFlags flags;
uint32_t interfaceIndex;
DNSServiceErrorType errorCode;
char replyName[256], replyType[kDNSServiceMaxDomainName],
replyDomain[kDNSServiceMaxDomainName];
int str_error = 0;
(void)hdr;
flags = get_flags(&data);
interfaceIndex = get_long(&data);
errorCode = get_error_code(&data);
if (get_string(&data, replyName, 256) < 0) str_error = 1;
if (get_string(&data, replyType, kDNSServiceMaxDomainName) < 0) str_error = 1;
if (get_string(&data, replyDomain, kDNSServiceMaxDomainName) < 0) str_error = 1;
if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown;
((DNSServiceBrowseReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, replyName, replyType, replyDomain, sdr->app_context);
}
DNSServiceErrorType DNSSD_API DNSServiceBrowse
(
DNSServiceRef *sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
const char *regtype,
const char *domain,
DNSServiceBrowseReply callBack,
void *context
)
{
char *msg = NULL, *ptr;
size_t len;
ipc_msg_hdr *hdr;
DNSServiceRef sdr;
DNSServiceErrorType err;
if (!sdRef) return kDNSServiceErr_BadParam;
*sdRef = NULL;
if (!domain) domain = "";
len = sizeof(flags);
len += sizeof(interfaceIndex);
len += strlen(regtype) + 1;
len += strlen(domain) + 1;
hdr = create_hdr(browse_request, &len, &ptr, 1);
if (!hdr) goto error;
msg = (char *)hdr;
put_flags(flags, &ptr);
put_long(interfaceIndex, &ptr);
put_string(regtype, &ptr);
put_string(domain, &ptr);
sdr = connect_to_server();
if (!sdr) goto error;
err = deliver_request(msg, sdr, 1);
if (err)
{
DNSServiceRefDeallocate(sdr);
return err;
}
sdr->op = browse_request;
sdr->process_reply = handle_browse_response;
sdr->app_callback = callBack;
sdr->app_context = context;
*sdRef = sdr;
return err;
error:
if (msg) free(msg);
if (*sdRef) { free(*sdRef); *sdRef = NULL; }
return kDNSServiceErr_Unknown;
}
DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser
(
DNSServiceFlags flags,
const char *domain
)
{
DNSServiceRef sdr;
DNSServiceErrorType err;
char *ptr = NULL;
size_t len = sizeof(flags) + strlen(domain) + 1;
ipc_msg_hdr *hdr = create_hdr(setdomain_request, &len, &ptr, 1);
if (!hdr) return kDNSServiceErr_Unknown;
put_flags(flags, &ptr);
put_string(domain, &ptr);
sdr = connect_to_server();
if (!sdr) { free(hdr); return kDNSServiceErr_Unknown; }
err = deliver_request((char *)hdr, sdr, 1); DNSServiceRefDeallocate(sdr);
return err;
}
static void handle_regservice_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
{
DNSServiceFlags flags;
uint32_t interfaceIndex;
DNSServiceErrorType errorCode;
char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName];
int str_error = 0;
(void)hdr;
flags = get_flags(&data);
interfaceIndex = get_long(&data);
errorCode = get_error_code(&data);
if (get_string(&data, name, 256) < 0) str_error = 1;
if (get_string(&data, regtype, kDNSServiceMaxDomainName) < 0) str_error = 1;
if (get_string(&data, domain, kDNSServiceMaxDomainName) < 0) str_error = 1;
if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown;
((DNSServiceRegisterReply)sdr->app_callback)(sdr, flags, errorCode, name, regtype, domain, sdr->app_context);
}
DNSServiceErrorType DNSSD_API DNSServiceRegister
(
DNSServiceRef *sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
const char *name,
const char *regtype,
const char *domain,
const char *host,
uint16_t PortInNetworkByteOrder,
uint16_t txtLen,
const void *txtRecord,
DNSServiceRegisterReply callBack,
void *context
)
{
char *msg = NULL, *ptr;
size_t len;
ipc_msg_hdr *hdr;
DNSServiceRef sdr;
DNSServiceErrorType err;
union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder };
if (!sdRef) return kDNSServiceErr_BadParam;
*sdRef = NULL;
if (!name) name = "";
if (!regtype) return kDNSServiceErr_BadParam;
if (!domain) domain = "";
if (!host) host = "";
if (!txtRecord) txtRecord = (void*)"";
if (!name[0] && (flags & kDNSServiceFlagsNoAutoRename))
return kDNSServiceErr_BadParam;
if (!callBack && name[0]) return kDNSServiceErr_BadParam;
len = sizeof(DNSServiceFlags);
len += sizeof(uint32_t); len += strlen(name) + strlen(regtype) + strlen(domain) + strlen(host) + 4;
len += 2 * sizeof(uint16_t); len += txtLen;
hdr = create_hdr(reg_service_request, &len, &ptr, 1);
if (!hdr) goto error;
if (!callBack) hdr->flags |= IPC_FLAGS_NOREPLY;
msg = (char *)hdr;
put_flags(flags, &ptr);
put_long(interfaceIndex, &ptr);
put_string(name, &ptr);
put_string(regtype, &ptr);
put_string(domain, &ptr);
put_string(host, &ptr);
*ptr++ = port.b[0];
*ptr++ = port.b[1];
put_short(txtLen, &ptr);
put_rdata(txtLen, txtRecord, &ptr);
sdr = connect_to_server();
if (!sdr) goto error;
err = deliver_request(msg, sdr, 1);
if (err)
{
DNSServiceRefDeallocate(sdr);
return err;
}
sdr->op = reg_service_request;
sdr->process_reply = callBack ? handle_regservice_response : NULL;
sdr->app_callback = callBack;
sdr->app_context = context;
*sdRef = sdr;
return err;
error:
if (msg) free(msg);
if (*sdRef) { free(*sdRef); *sdRef = NULL; }
return kDNSServiceErr_Unknown;
}
static void handle_enumeration_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
{
DNSServiceFlags flags;
uint32_t interfaceIndex;
DNSServiceErrorType err;
char domain[kDNSServiceMaxDomainName];
int str_error = 0;
(void)hdr;
flags = get_flags(&data);
interfaceIndex = get_long(&data);
err = get_error_code(&data);
if (get_string(&data, domain, kDNSServiceMaxDomainName) < 0) str_error = 1;
if (!err && str_error) err = kDNSServiceErr_Unknown;
((DNSServiceDomainEnumReply)sdr->app_callback)(sdr, flags, interfaceIndex, err, domain, sdr->app_context);
}
DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
(
DNSServiceRef *sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
DNSServiceDomainEnumReply callBack,
void *context
)
{
char *msg = NULL, *ptr;
size_t len;
ipc_msg_hdr *hdr;
DNSServiceRef sdr;
DNSServiceErrorType err;
int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0;
int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0;
if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
if (!sdRef) return kDNSServiceErr_BadParam;
*sdRef = NULL;
len = sizeof(DNSServiceFlags);
len += sizeof(uint32_t);
hdr = create_hdr(enumeration_request, &len, &ptr, 1);
if (!hdr) goto error;
msg = (void *)hdr;
put_flags(flags, &ptr);
put_long(interfaceIndex, &ptr);
sdr = connect_to_server();
if (!sdr) goto error;
err = deliver_request(msg, sdr, 1);
if (err)
{
DNSServiceRefDeallocate(sdr);
return err;
}
sdr->op = enumeration_request;
sdr->process_reply = handle_enumeration_response;
sdr->app_callback = callBack;
sdr->app_context = context;
*sdRef = sdr;
return err;
error:
if (msg) free(msg);
if (*sdRef) { free(*sdRef); *sdRef = NULL; }
return kDNSServiceErr_Unknown;
}
static void handle_regrecord_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
{
DNSServiceFlags flags;
uint32_t interfaceIndex;
DNSServiceErrorType errorCode;
DNSRecordRef rref = hdr->client_context.context;
if (sdr->op != connection)
{
rref->app_callback(rref->sdr, rref, 0, kDNSServiceErr_Unknown, rref->app_context);
return;
}
flags = get_flags(&data);
interfaceIndex = get_long(&data);
errorCode = get_error_code(&data);
rref->app_callback(rref->sdr, rref, flags, errorCode, rref->app_context);
}
DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef)
{
if (!sdRef) return kDNSServiceErr_BadParam;
*sdRef = connect_to_server();
if (!*sdRef)
return kDNSServiceErr_Unknown;
(*sdRef)->op = connection;
(*sdRef)->process_reply = handle_regrecord_response;
return 0;
}
DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
(
DNSServiceRef sdRef,
DNSRecordRef *RecordRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
const char *fullname,
uint16_t rrtype,
uint16_t rrclass,
uint16_t rdlen,
const void *rdata,
uint32_t ttl,
DNSServiceRegisterRecordReply callBack,
void *context
)
{
char *msg = NULL, *ptr;
size_t len;
ipc_msg_hdr *hdr = NULL;
DNSServiceRef tmp = NULL;
DNSRecordRef rref = NULL;
int f1 = (flags & kDNSServiceFlagsShared) != 0;
int f2 = (flags & kDNSServiceFlagsUnique) != 0;
if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
if (!sdRef || sdRef->op != connection || sdRef->sockfd < 0)
return kDNSServiceErr_BadReference;
*RecordRef = NULL;
len = sizeof(DNSServiceFlags);
len += 2 * sizeof(uint32_t); len += 3 * sizeof(uint16_t); len += strlen(fullname) + 1;
len += rdlen;
hdr = create_hdr(reg_record_request, &len, &ptr, 0);
if (!hdr) goto error;
msg = (char *)hdr;
put_flags(flags, &ptr);
put_long(interfaceIndex, &ptr);
put_string(fullname, &ptr);
put_short(rrtype, &ptr);
put_short(rrclass, &ptr);
put_short(rdlen, &ptr);
put_rdata(rdlen, rdata, &ptr);
put_long(ttl, &ptr);
rref = malloc(sizeof(_DNSRecordRef_t));
if (!rref) goto error;
rref->app_context = context;
rref->app_callback = callBack;
rref->record_index = sdRef->max_index++;
rref->sdr = sdRef;
*RecordRef = rref;
hdr->client_context.context = rref;
hdr->reg_index = rref->record_index;
return deliver_request(msg, sdRef, 0);
error:
if (rref) free(rref);
if (tmp) free(tmp);
if (hdr) free(hdr);
return kDNSServiceErr_Unknown;
}
DNSServiceErrorType DNSSD_API DNSServiceAddRecord
(
DNSServiceRef sdRef,
DNSRecordRef *RecordRef,
DNSServiceFlags flags,
uint16_t rrtype,
uint16_t rdlen,
const void *rdata,
uint32_t ttl
)
{
ipc_msg_hdr *hdr;
size_t len = 0;
char *ptr;
DNSRecordRef rref;
if (!sdRef || (sdRef->op != reg_service_request) || !RecordRef)
return kDNSServiceErr_BadReference;
*RecordRef = NULL;
len += 2 * sizeof(uint16_t); len += rdlen;
len += sizeof(uint32_t);
len += sizeof(DNSServiceFlags);
hdr = create_hdr(add_record_request, &len, &ptr, 0);
if (!hdr) return kDNSServiceErr_Unknown;
put_flags(flags, &ptr);
put_short(rrtype, &ptr);
put_short(rdlen, &ptr);
put_rdata(rdlen, rdata, &ptr);
put_long(ttl, &ptr);
rref = malloc(sizeof(_DNSRecordRef_t));
if (!rref) goto error;
rref->app_context = NULL;
rref->app_callback = NULL;
rref->record_index = sdRef->max_index++;
rref->sdr = sdRef;
*RecordRef = rref;
hdr->client_context.context = rref;
hdr->reg_index = rref->record_index;
return deliver_request((char *)hdr, sdRef, 0);
error:
if (hdr) free(hdr);
if (rref) free(rref);
if (*RecordRef) *RecordRef = NULL;
return kDNSServiceErr_Unknown;
}
DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
(
DNSServiceRef sdRef,
DNSRecordRef RecordRef,
DNSServiceFlags flags,
uint16_t rdlen,
const void *rdata,
uint32_t ttl
)
{
ipc_msg_hdr *hdr;
size_t len = 0;
char *ptr;
if (!sdRef) return kDNSServiceErr_BadReference;
len += sizeof(uint16_t);
len += rdlen;
len += sizeof(uint32_t);
len += sizeof(DNSServiceFlags);
hdr = create_hdr(update_record_request, &len, &ptr, 0);
if (!hdr) return kDNSServiceErr_Unknown;
hdr->reg_index = RecordRef ? RecordRef->record_index : TXT_RECORD_INDEX;
put_flags(flags, &ptr);
put_short(rdlen, &ptr);
put_rdata(rdlen, rdata, &ptr);
put_long(ttl, &ptr);
return deliver_request((char *)hdr, sdRef, 0);
}
DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
(
DNSServiceRef sdRef,
DNSRecordRef RecordRef,
DNSServiceFlags flags
)
{
ipc_msg_hdr *hdr;
size_t len = 0;
char *ptr;
DNSServiceErrorType err;
if (!sdRef || !RecordRef || !sdRef->max_index)
return kDNSServiceErr_BadReference;
len += sizeof(flags);
hdr = create_hdr(remove_record_request, &len, &ptr, 0);
if (!hdr) return kDNSServiceErr_Unknown;
hdr->reg_index = RecordRef->record_index;
put_flags(flags, &ptr);
err = deliver_request((char *)hdr, sdRef, 0);
if (!err) free(RecordRef);
return err;
}
void DNSSD_API DNSServiceReconfirmRecord
(
DNSServiceFlags flags,
uint32_t interfaceIndex,
const char *fullname,
uint16_t rrtype,
uint16_t rrclass,
uint16_t rdlen,
const void *rdata
)
{
char *ptr;
size_t len;
ipc_msg_hdr *hdr;
DNSServiceRef tmp;
len = sizeof(DNSServiceFlags);
len += sizeof(uint32_t);
len += strlen(fullname) + 1;
len += 3 * sizeof(uint16_t);
len += rdlen;
tmp = connect_to_server();
if (!tmp) return;
hdr = create_hdr(reconfirm_record_request, &len, &ptr, 1);
if (!hdr) return;
put_flags(flags, &ptr);
put_long(interfaceIndex, &ptr);
put_string(fullname, &ptr);
put_short(rrtype, &ptr);
put_short(rrclass, &ptr);
put_short(rdlen, &ptr);
put_rdata(rdlen, rdata, &ptr);
ConvertHeaderBytes(hdr);
my_write(tmp->sockfd, (char *)hdr, (int) len);
free(hdr);
DNSServiceRefDeallocate(tmp);
}