*
* @APPLE_LICENSE_HEADER_START@
*
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
+ *
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
Change History (most recent first):
$Log: dnssd_clientstub.c,v $
+Revision 1.19 2004/05/25 18:29:33 cheshire
+Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c,
+so that it's also accessible to dnssd_clientshim.c (single address space) clients.
+
+Revision 1.18 2004/05/18 23:51:27 cheshire
+Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
+
+Revision 1.17 2004/05/06 18:42:58 ksekar
+General dns_sd.h API cleanup, including the following radars:
+<rdar://problem/3592068>: Remove flags with zero value
+<rdar://problem/3479569>: Passing in NULL causes a crash.
+
+Revision 1.16 2004/03/12 22:00:37 cheshire
+Added: #include <sys/socket.h>
+
+Revision 1.15 2004/01/20 18:36:29 ksekar
+Propagated Libinfo fix for <rdar://problem/3483971>: SU:
+DNSServiceUpdateRecord() doesn't allow you to update the TXT record
+into TOT mDNSResponder.
+
+Revision 1.14 2004/01/19 22:39:17 cheshire
+Don't use "MSG_WAITALL"; it makes send() return "Invalid argument" on Linux;
+use an explicit while() loop instead. (In any case, this should only make a difference
+with non-blocking sockets, which we don't use on the client side right now.)
+
+Revision 1.13 2004/01/19 21:46:52 cheshire
+Fix compiler warning
+
+Revision 1.12 2003/12/23 20:46:47 ksekar
+<rdar://problem/3497428>: sync dnssd files between libinfo & mDNSResponder
+
+Revision 1.11 2003/12/08 21:11:42 rpantos
+Changes necessary to support mDNSResponder on Linux.
+
+Revision 1.10 2003/10/13 23:50:53 ksekar
+Updated dns_sd clientstub files to bring copies in synch with
+top-of-tree Libinfo: A memory leak in dnssd_clientstub.c is fixed,
+and comments in dns_sd.h are improved.
+
Revision 1.9 2003/08/15 21:30:39 cheshire
Bring up to date with LibInfo version
*/
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
#include "dnssd_ipc.h"
+
#define CTL_PATH_PREFIX "/tmp/dnssd_clippath."
// error socket (if needed) is named "dnssd_clipath.[pid].xxx:n" where xxx are the
// last 3 digits of the time (in seconds) and n is the 6-digit microsecond time
static ipc_msg_hdr *create_hdr(int op, int *len, char **data_start, int reuse_socket);
static int my_read(int sd, char *buf, int len);
static int my_write(int sd, char *buf, int len);
-static int domain_ends_in_dot(const char *dom);
// server response handlers
static void handle_query_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *msg);
static void handle_browse_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data);
void *app_callback;
void *app_context;
uint32_t max_index; //largest assigned record index - 0 if no additl. recs registered
- } _DNSServiceRef_t;
+ } _DNSServiceRef_t;
typedef struct _DNSRecordRef_t
{
if (my_read(sdRef->sockfd, data, hdr.datalen) < 0)
return kDNSServiceErr_Unknown;
sdRef->process_reply(sdRef, &hdr, data);
- return kDNSServiceErr_Unknown;
+ free(data);
+ return kDNSServiceErr_NoError;
}
DNSServiceErrorType DNSServiceResolve
(
- DNSServiceRef *sdRef,
+ DNSServiceRef *sdRef,
const DNSServiceFlags flags,
const uint32_t interfaceIndex,
- const char *name,
- const char *regtype,
- const char *domain,
+ const char *name,
+ const char *regtype,
+ const char *domain,
const DNSServiceResolveReply callBack,
- void *context
+ void *context
)
{
char *msg = NULL, *ptr;
if (!sdRef) return kDNSServiceErr_BadParam;
*sdRef = NULL;
+ if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam;
+
// calculate total message length
len = sizeof(flags);
len += sizeof(interfaceIndex);
uint32_t ifi;
DNSServiceErrorType err;
char *txtrecord;
-
- (void)hdr; //unused
+ int str_error = 0;
+ (void)hdr; //unused
flags = get_flags(&data);
ifi = get_long(&data);
err = get_error_code(&data);
- get_string(&data, fullname, kDNSServiceMaxDomainName);
- get_string(&data, target, kDNSServiceMaxDomainName);
+ if (get_string(&data, fullname, kDNSServiceMaxDomainName) < 0) str_error = 1;
+ if (get_string(&data, target, kDNSServiceMaxDomainName) < 0) str_error = 1;
port = get_short(&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, txtlen, txtrecord, sdr->app_context);
}
DNSServiceErrorType DNSServiceQueryRecord
(
- DNSServiceRef *sdRef,
- const DNSServiceFlags flags,
- const uint32_t interfaceIndex,
- const char *name,
- const uint16_t rrtype,
- const uint16_t rrclass,
- const DNSServiceQueryRecordReply callBack,
- void *context
+ DNSServiceRef *sdRef,
+ const DNSServiceFlags flags,
+ const uint32_t interfaceIndex,
+ const char *name,
+ const uint16_t rrtype,
+ const uint16_t rrclass,
+ const DNSServiceQueryRecordReply callBack,
+ void *context
)
{
char *msg = NULL, *ptr;
DNSServiceFlags flags;
uint32_t interfaceIndex, ttl;
DNSServiceErrorType errorCode;
- char name[256];
+ char name[kDNSServiceMaxDomainName];
uint16_t rrtype, rrclass, rdlen;
char *rdata;
+ int str_error = 0;
(void)hdr;//Unused
flags = get_flags(&data);
interfaceIndex = get_long(&data);
errorCode = get_error_code(&data);
- (get_string(&data, name, 256) < 0);
+ 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 (!rdata) return;
- ((DNSServiceQueryRecordReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, name, rrtype, rrclass,
- rdlen, rdata, ttl, sdr->app_context);
+ 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;
}
DNSServiceFlags flags;
uint32_t interfaceIndex;
DNSServiceErrorType errorCode;
- char replyName[256], replyType[256], replyDomain[256];
- (void)hdr;//Unused
+ char replyName[256], replyType[kDNSServiceMaxDomainName],
+ replyDomain[kDNSServiceMaxDomainName];
+ int str_error = 0;
+ (void)hdr;//Unused
flags = get_flags(&data);
interfaceIndex = get_long(&data);
errorCode = get_error_code(&data);
- get_string(&data, replyName, 256);
- get_string(&data, replyType, 256);
- get_string(&data, replyDomain, 256);
- ((DNSServiceBrowseReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, replyName, replyType, replyDomain, sdr->app_context);
+ 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);
}
error:
if (msg) free(msg);
- if (*sdRef) { free(*sdRef); *sdRef = NULL; }
+ if (*sdRef) { free(*sdRef); *sdRef = NULL; }
return kDNSServiceErr_Unknown;
}
DNSServiceFlags flags;
uint32_t interfaceIndex;
DNSServiceErrorType errorCode;
- char name[256], regtype[256], domain[256];
- (void)hdr;//Unused
+ char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName];
+ int str_error = 0;
+ (void)hdr;//Unused
flags = get_flags(&data);
interfaceIndex = get_long(&data);
errorCode = get_error_code(&data);
- get_string(&data, name, 256);
- get_string(&data, regtype, 256);
- get_string(&data, domain, 256);
+ 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);
}
if (!sdRef) return kDNSServiceErr_BadParam;
*sdRef = NULL;
- len = sizeof(DNSServiceFlags);
+ if (flags != kDNSServiceFlagsBrowseDomains && flags != kDNSServiceFlagsRegistrationDomains)
+ return kDNSServiceErr_BadParam;
+
+ len = sizeof(DNSServiceFlags);
len += sizeof(uint32_t);
hdr = create_hdr(enumeration_request, &len, &ptr, 1);
DNSServiceFlags flags;
uint32_t interfaceIndex;
DNSServiceErrorType err;
- char domain[256];
- (void)hdr;//Unused
+ char domain[kDNSServiceMaxDomainName];
+ int str_error = 0;
+ (void)hdr;//Unused
flags = get_flags(&data);
interfaceIndex = get_long(&data);
err = get_error_code(&data);
- get_string(&data, domain, 256);
+ 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 DNSServiceRegisterRecord
(
- const DNSServiceRef sdRef,
- DNSRecordRef *RecordRef,
- const DNSServiceFlags flags,
- const uint32_t interfaceIndex,
- const char *fullname,
- const uint16_t rrtype,
- const uint16_t rrclass,
- const uint16_t rdlen,
- const void *rdata,
- const uint32_t ttl,
- const DNSServiceRegisterRecordReply callBack,
- void *context
+ const DNSServiceRef sdRef,
+ DNSRecordRef *RecordRef,
+ const DNSServiceFlags flags,
+ const uint32_t interfaceIndex,
+ const char *fullname,
+ const uint16_t rrtype,
+ const uint16_t rrclass,
+ const uint16_t rdlen,
+ const void *rdata,
+ const uint32_t ttl,
+ const DNSServiceRegisterRecordReply callBack,
+ void *context
)
{
char *msg = NULL, *ptr;
return kDNSServiceErr_BadReference;
*RecordRef = NULL;
- len = sizeof(DNSServiceFlags);
+ if (flags != kDNSServiceFlagsShared && flags != kDNSServiceFlagsUnique)
+ return kDNSServiceErr_BadReference;
+
+ len = sizeof(DNSServiceFlags);
len += 2 * sizeof(uint32_t); // interfaceIndex, ttl
len += 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen
len += strlen(fullname) + 1;
//sdRef returned by DNSServiceRegister()
DNSServiceErrorType DNSServiceAddRecord
(
- const DNSServiceRef sdRef,
- DNSRecordRef *RecordRef,
+ const DNSServiceRef sdRef,
+ DNSRecordRef *RecordRef,
const DNSServiceFlags flags,
- const uint16_t rrtype,
- const uint16_t rdlen,
- const void *rdata,
- const uint32_t ttl
+ const uint16_t rrtype,
+ const uint16_t rdlen,
+ const void *rdata,
+ const uint32_t ttl
)
{
ipc_msg_hdr *hdr;
//DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord
DNSServiceErrorType DNSServiceUpdateRecord
(
- const DNSServiceRef sdRef,
- DNSRecordRef RecordRef,
+ const DNSServiceRef sdRef,
+ DNSRecordRef RecordRef,
const DNSServiceFlags flags,
- const uint16_t rdlen,
- const void *rdata,
- const uint32_t ttl
+ const uint16_t rdlen,
+ const void *rdata,
+ const uint32_t ttl
)
{
ipc_msg_hdr *hdr;
int len = 0;
char *ptr;
- if (!sdRef || !RecordRef || !sdRef->max_index)
- return kDNSServiceErr_BadReference;
+ if (!sdRef) return kDNSServiceErr_BadReference;
len += sizeof(uint16_t);
len += rdlen;
DNSServiceErrorType DNSServiceRemoveRecord
(
const DNSServiceRef sdRef,
- const DNSRecordRef RecordRef,
+ const DNSRecordRef RecordRef,
const DNSServiceFlags flags
)
{
}
-int DNSServiceConstructFullName
- (
- char *fullName,
- const char *service, /* may be NULL */
- const char *regtype,
- const char *domain
- )
- {
- int len;
- u_char c;
- char *fn = fullName;
- const char *s = service;
- const char *r = regtype;
- const char *d = domain;
-
- if (service)
- {
- while(*s)
- {
- c = *s++;
- if (c == '.' || (c == '\\')) *fn++ = '\\'; // escape dot and backslash literals
- else if (c <= ' ') // escape non-printable characters
- {
- *fn++ = '\\';
- *fn++ = (char) ('0' + (c / 100));
- *fn++ = (char) ('0' + (c / 10) % 10);
- c = (u_char)('0' + (c % 10));
- }
- *fn++ = c;
- }
- *fn++ = '.';
- }
-
- if (!regtype) return -1;
- len = strlen(regtype);
- if (domain_ends_in_dot(regtype)) len--;
- if (len < 4) return -1; // regtype must end in _udp or _tcp
- if (strncmp((regtype + len - 4), "_tcp", 4) && strncmp((regtype + len - 4), "_udp", 4)) return -1;
- while(*r)
- *fn++ = *r++;
- if (!domain_ends_in_dot(regtype)) *fn++ = '.';
-
- if (!domain) return -1;
- len = strlen(domain);
- if (!len) return -1;
- while(*d)
- *fn++ = *d++;
- if (!domain_ends_in_dot(domain)) *fn++ = '.';
- *fn = '\0';
- return 0;
- }
-
-static int domain_ends_in_dot(const char *dom)
- {
- while(*dom && *(dom + 1))
- {
- if (*dom == '\\') // advance past escaped byte sequence
- {
- if (*(dom + 1) >= '0' && *(dom + 1) <= '9') dom += 4;
- else dom += 2;
- }
- else dom++; // else read one character
- }
- return (*dom == '.');
- }
-
-
-
// return a connected service ref (deallocate with DNSServiceRefDeallocate)
static DNSServiceRef connect_to_server(void)
{
if (!sdr) return NULL;
if ((sdr->sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
- {
+ {
free(sdr);
return NULL;
- }
+ }
saddr.sun_family = AF_LOCAL;
strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH);
if (connect(sdr->sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
- {
+ {
free(sdr);
return NULL;
- }
- return sdr;
+ }
+ return sdr;
}
int my_write(int sd, char *buf, int len)
{
- if (send(sd, buf, len, MSG_WAITALL) != len) return -1;
+ 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;
}
bzero(&caddr, sizeof(caddr));
caddr.sun_family = AF_LOCAL;
- caddr.sun_len = sizeof(struct sockaddr_un);
- path = (char *)msg + sizeof(ipc_msg_hdr);
+#ifndef NOT_HAVE_SA_LEN // According to Stevens (section 3.2), there is no portable way to
+ // determine whether sa_len is defined on a particular platform.
+ caddr.sun_len = sizeof(struct sockaddr_un);
+#endif
+ path = (char *)msg + sizeof(ipc_msg_hdr);
strcpy(caddr.sun_path, path);
mask = umask(0);
if (bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr)) < 0)
- {
- umask(mask);
+ {
+ umask(mask);
goto cleanup;
- }
+ }
umask(mask);
listen(listenfd, 1);
}
}
cleanup:
if (!reuse_sd && listenfd > 0) close(listenfd);
- if (!reuse_sd && errsd > 0) close(errsd);
+ if (!reuse_sd && errsd > 0) close(errsd);
if (!reuse_sd && path) unlink(path);
if (msg) free(msg);
return err;
if (!reuse_socket)
{
- if (gettimeofday(&time, NULL) < 0) return NULL;
- sprintf(ctrl_path, "%s%d-%.3x-%.6u", CTL_PATH_PREFIX, (int)getpid(),
- time.tv_sec & 0xFFF, time.tv_usec);
-
+ 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;
}