1*4904Srs200217 /* -*- Mode: C; tab-width: 4 -*-
2*4904Srs200217 *
3*4904Srs200217 * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
4*4904Srs200217 *
5*4904Srs200217 * Redistribution and use in source and binary forms, with or without
6*4904Srs200217 * modification, are permitted provided that the following conditions are met:
7*4904Srs200217 *
8*4904Srs200217 * 1. Redistributions of source code must retain the above copyright notice,
9*4904Srs200217 * this list of conditions and the following disclaimer.
10*4904Srs200217 * 2. Redistributions in binary form must reproduce the above copyright notice,
11*4904Srs200217 * this list of conditions and the following disclaimer in the documentation
12*4904Srs200217 * and/or other materials provided with the distribution.
13*4904Srs200217 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
14*4904Srs200217 * contributors may be used to endorse or promote products derived from this
15*4904Srs200217 * software without specific prior written permission.
16*4904Srs200217 *
17*4904Srs200217 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18*4904Srs200217 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19*4904Srs200217 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20*4904Srs200217 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21*4904Srs200217 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22*4904Srs200217 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23*4904Srs200217 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24*4904Srs200217 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25*4904Srs200217 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26*4904Srs200217 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*4904Srs200217
28*4904Srs200217 Change History (most recent first):
29*4904Srs200217
30*4904Srs200217 $Log: dnssd_clientstub.c,v $
31*4904Srs200217 Revision 1.53 2006/09/07 04:43:12 herscher
32*4904Srs200217 Fix compile error on Win32 platform by moving inclusion of syslog.h
33*4904Srs200217
34*4904Srs200217 Revision 1.52 2006/08/15 23:04:21 mkrochma
35*4904Srs200217 <rdar://problem/4090354> Client should be able to specify service name w/o callback
36*4904Srs200217
37*4904Srs200217 Revision 1.51 2006/07/24 23:45:55 cheshire
38*4904Srs200217 <rdar://problem/4605276> DNSServiceReconfirmRecord() should return error code
39*4904Srs200217
40*4904Srs200217 Revision 1.50 2006/06/28 08:22:27 cheshire
41*4904Srs200217 <rdar://problem/4605264> dnssd_clientstub.c needs to report unlink failures in syslog
42*4904Srs200217
43*4904Srs200217 Revision 1.49 2006/06/28 07:58:59 cheshire
44*4904Srs200217 Minor textual tidying
45*4904Srs200217
46*4904Srs200217 Revision 1.48 2005/06/30 18:01:00 shersche
47*4904Srs200217 <rdar://problem/4096913> Clients shouldn't wait ten seconds to connect to mDNSResponder
48*4904Srs200217
49*4904Srs200217 Revision 1.47 2005/03/31 02:19:56 cheshire
50*4904Srs200217 <rdar://problem/4021486> Fix build warnings
51*4904Srs200217 Reviewed by: Scott Herscher
52*4904Srs200217
53*4904Srs200217 Revision 1.46 2005/03/21 00:39:31 shersche
54*4904Srs200217 <rdar://problem/4021486> Fix build warnings on Win32 platform
55*4904Srs200217
56*4904Srs200217 Revision 1.45 2005/02/01 01:25:06 shersche
57*4904Srs200217 Define sleep() to be Sleep() for Windows compatibility
58*4904Srs200217
59*4904Srs200217 Revision 1.44 2005/01/27 22:57:56 cheshire
60*4904Srs200217 Fix compile errors on gcc4
61*4904Srs200217
62*4904Srs200217 Revision 1.43 2005/01/27 00:02:29 cheshire
63*4904Srs200217 <rdar://problem/3947461> Handle case where client runs before daemon has finished launching
64*4904Srs200217
65*4904Srs200217 Revision 1.42 2005/01/11 02:01:02 shersche
66*4904Srs200217 Use dnssd_close() rather than close() for Windows compatibility
67*4904Srs200217
68*4904Srs200217 Revision 1.41 2004/12/23 17:34:26 ksekar
69*4904Srs200217 <rdar://problem/3931319> Calls leak sockets if mDNSResponder is not running
70*4904Srs200217
71*4904Srs200217 Revision 1.40 2004/11/23 03:39:47 cheshire
72*4904Srs200217 Let interface name/index mapping capability live directly in JNISupport.c,
73*4904Srs200217 instead of having to call through to the daemon via IPC to get this information.
74*4904Srs200217
75*4904Srs200217 Revision 1.39 2004/11/12 03:22:00 rpantos
76*4904Srs200217 rdar://problem/3809541 Add DNSSDMapIfIndexToName, DNSSDMapNameToIfIndex.
77*4904Srs200217
78*4904Srs200217 Revision 1.38 2004/11/02 02:51:23 cheshire
79*4904Srs200217 <rdar://problem/3526342> Remove overly-restrictive flag checks
80*4904Srs200217
81*4904Srs200217 Revision 1.37 2004/10/14 01:43:35 cheshire
82*4904Srs200217 Fix opaque port passing problem
83*4904Srs200217
84*4904Srs200217 Revision 1.36 2004/10/06 02:22:19 cheshire
85*4904Srs200217 Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
86*4904Srs200217
87*4904Srs200217 Revision 1.35 2004/10/01 22:15:55 rpantos
88*4904Srs200217 rdar://problem/3824265: Replace APSL in client lib with BSD license.
89*4904Srs200217
90*4904Srs200217 Revision 1.34 2004/09/17 22:36:13 cheshire
91*4904Srs200217 Add comment explaining that deliver_request frees the message it sends
92*4904Srs200217
93*4904Srs200217 Revision 1.33 2004/09/17 01:17:31 ksekar
94*4904Srs200217 Remove double-free of msg header, freed automatically by deliver_request()
95*4904Srs200217
96*4904Srs200217 Revision 1.32 2004/09/17 01:08:55 cheshire
97*4904Srs200217 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
98*4904Srs200217 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
99*4904Srs200217 declared in that file are ONLY appropriate to single-address-space embedded applications.
100*4904Srs200217 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
101*4904Srs200217
102*4904Srs200217 Revision 1.31 2004/09/16 23:37:19 cheshire
103*4904Srs200217 Free hdr before returning
104*4904Srs200217
105*4904Srs200217 Revision 1.30 2004/09/16 23:14:24 cheshire
106*4904Srs200217 Changes for Windows compatibility
107*4904Srs200217
108*4904Srs200217 Revision 1.29 2004/09/16 21:46:38 ksekar
109*4904Srs200217 <rdar://problem/3665304> Need SPI for LoginWindow to associate a UID with a Wide Area domain
110*4904Srs200217
111*4904Srs200217 Revision 1.28 2004/08/11 17:10:04 cheshire
112*4904Srs200217 Fix signed/unsigned warnings
113*4904Srs200217
114*4904Srs200217 Revision 1.27 2004/08/11 00:54:16 cheshire
115*4904Srs200217 Change "hdr->op.request_op" to just "hdr->op"
116*4904Srs200217
117*4904Srs200217 Revision 1.26 2004/07/26 06:07:27 shersche
118*4904Srs200217 fix bugs when using an error socket to communicate with the daemon
119*4904Srs200217
120*4904Srs200217 Revision 1.25 2004/07/26 05:54:02 shersche
121*4904Srs200217 DNSServiceProcessResult() returns NoError if socket read returns EWOULDBLOCK
122*4904Srs200217
123*4904Srs200217 Revision 1.24 2004/07/20 06:46:21 shersche
124*4904Srs200217 <rdar://problem/3730123> fix endless loop in read_all() if recv returns 0
125*4904Srs200217 Bug #: 3730123
126*4904Srs200217
127*4904Srs200217 Revision 1.23 2004/06/29 00:48:38 cheshire
128*4904Srs200217 Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions;
129*4904Srs200217 use an explicit while() loop instead.
130*4904Srs200217
131*4904Srs200217 Revision 1.22 2004/06/26 03:16:34 shersche
132*4904Srs200217 clean up warning messages on Win32 platform
133*4904Srs200217
134*4904Srs200217 Submitted by: herscher
135*4904Srs200217
136*4904Srs200217 Revision 1.21 2004/06/18 04:53:56 rpantos
137*4904Srs200217 Use platform layer for socket types. Introduce USE_TCP_LOOPBACK. Remove dependency on mDNSEmbeddedAPI.h.
138*4904Srs200217
139*4904Srs200217 Revision 1.20 2004/06/12 00:50:22 cheshire
140*4904Srs200217 Changes for Windows compatibility
141*4904Srs200217
142*4904Srs200217 Revision 1.19 2004/05/25 18:29:33 cheshire
143*4904Srs200217 Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c,
144*4904Srs200217 so that it's also accessible to dnssd_clientshim.c (single address space) clients.
145*4904Srs200217
146*4904Srs200217 Revision 1.18 2004/05/18 23:51:27 cheshire
147*4904Srs200217 Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
148*4904Srs200217
149*4904Srs200217 Revision 1.17 2004/05/06 18:42:58 ksekar
150*4904Srs200217 General dns_sd.h API cleanup, including the following radars:
151*4904Srs200217 <rdar://problem/3592068>: Remove flags with zero value
152*4904Srs200217 <rdar://problem/3479569>: Passing in NULL causes a crash.
153*4904Srs200217
154*4904Srs200217 Revision 1.16 2004/03/12 22:00:37 cheshire
155*4904Srs200217 Added: #include <sys/socket.h>
156*4904Srs200217
157*4904Srs200217 Revision 1.15 2004/01/20 18:36:29 ksekar
158*4904Srs200217 Propagated Libinfo fix for <rdar://problem/3483971>: SU:
159*4904Srs200217 DNSServiceUpdateRecord() doesn't allow you to update the TXT record
160*4904Srs200217 into TOT mDNSResponder.
161*4904Srs200217
162*4904Srs200217 Revision 1.14 2004/01/19 22:39:17 cheshire
163*4904Srs200217 Don't use "MSG_WAITALL"; it makes send() return "Invalid argument" on Linux;
164*4904Srs200217 use an explicit while() loop instead. (In any case, this should only make a difference
165*4904Srs200217 with non-blocking sockets, which we don't use on the client side right now.)
166*4904Srs200217
167*4904Srs200217 Revision 1.13 2004/01/19 21:46:52 cheshire
168*4904Srs200217 Fix compiler warning
169*4904Srs200217
170*4904Srs200217 Revision 1.12 2003/12/23 20:46:47 ksekar
171*4904Srs200217 <rdar://problem/3497428>: sync dnssd files between libinfo & mDNSResponder
172*4904Srs200217
173*4904Srs200217 Revision 1.11 2003/12/08 21:11:42 rpantos
174*4904Srs200217 Changes necessary to support mDNSResponder on Linux.
175*4904Srs200217
176*4904Srs200217 Revision 1.10 2003/10/13 23:50:53 ksekar
177*4904Srs200217 Updated dns_sd clientstub files to bring copies in synch with
178*4904Srs200217 top-of-tree Libinfo: A memory leak in dnssd_clientstub.c is fixed,
179*4904Srs200217 and comments in dns_sd.h are improved.
180*4904Srs200217
181*4904Srs200217 Revision 1.9 2003/08/15 21:30:39 cheshire
182*4904Srs200217 Bring up to date with LibInfo version
183*4904Srs200217
184*4904Srs200217 Revision 1.8 2003/08/13 23:54:52 ksekar
185*4904Srs200217 Bringing dnssd_clientstub.c up to date with Libinfo, per radar 3376640
186*4904Srs200217
187*4904Srs200217 Revision 1.7 2003/08/12 19:56:25 cheshire
188*4904Srs200217 Update to APSL 2.0
189*4904Srs200217
190*4904Srs200217 */
191*4904Srs200217
192*4904Srs200217 #pragma ident "%Z%%M% %I% %E% SMI"
193*4904Srs200217
194*4904Srs200217 #include <errno.h>
195*4904Srs200217 #include <stdlib.h>
196*4904Srs200217
197*4904Srs200217 #include "dnssd_ipc.h"
198*4904Srs200217
199*4904Srs200217 #if defined(_WIN32)
200*4904Srs200217
201*4904Srs200217 #include <winsock2.h>
202*4904Srs200217 #include <windows.h>
203*4904Srs200217
204*4904Srs200217 #define sockaddr_mdns sockaddr_in
205*4904Srs200217 #define AF_MDNS AF_INET
206*4904Srs200217
207*4904Srs200217 // disable warning: "'type cast' : from data pointer 'void *' to function pointer"
208*4904Srs200217 #pragma warning(disable:4055)
209*4904Srs200217
210*4904Srs200217 // disable warning: "nonstandard extension, function/data pointer conversion in expression"
211*4904Srs200217 #pragma warning(disable:4152)
212*4904Srs200217
213*4904Srs200217 extern BOOL IsSystemServiceDisabled();
214*4904Srs200217
215*4904Srs200217 #define sleep(X) Sleep((X) * 1000)
216*4904Srs200217
217*4904Srs200217 static int g_initWinsock = 0;
218*4904Srs200217
219*4904Srs200217 #else
220*4904Srs200217
221*4904Srs200217 #include <sys/time.h>
222*4904Srs200217 #include <sys/socket.h>
223*4904Srs200217 #include <syslog.h>
224*4904Srs200217
225*4904Srs200217 #define sockaddr_mdns sockaddr_un
226*4904Srs200217 #define AF_MDNS AF_LOCAL
227*4904Srs200217
228*4904Srs200217 #endif
229*4904Srs200217
230*4904Srs200217 // <rdar://problem/4096913> Specifies how many times we'll try and connect to the
231*4904Srs200217 // server.
232*4904Srs200217
233*4904Srs200217 #define DNSSD_CLIENT_MAXTRIES 4
234*4904Srs200217
235*4904Srs200217 #define CTL_PATH_PREFIX "/tmp/dnssd_clippath."
236*4904Srs200217 // error socket (if needed) is named "dnssd_clipath.[pid].xxx:n" where xxx are the
237*4904Srs200217 // last 3 digits of the time (in seconds) and n is the 6-digit microsecond time
238*4904Srs200217
239*4904Srs200217 // general utility functions
240*4904Srs200217 typedef struct _DNSServiceRef_t
241*4904Srs200217 {
242*4904Srs200217 dnssd_sock_t sockfd; // connected socket between client and daemon
243*4904Srs200217 uint32_t op; // request_op_t or reply_op_t
244*4904Srs200217 process_reply_callback process_reply;
245*4904Srs200217 void *app_callback;
246*4904Srs200217 void *app_context;
247*4904Srs200217 uint32_t max_index; //largest assigned record index - 0 if no additl. recs registered
248*4904Srs200217 } _DNSServiceRef_t;
249*4904Srs200217
250*4904Srs200217 typedef struct _DNSRecordRef_t
251*4904Srs200217 {
252*4904Srs200217 void *app_context;
253*4904Srs200217 DNSServiceRegisterRecordReply app_callback;
254*4904Srs200217 DNSRecordRef recref;
255*4904Srs200217 uint32_t record_index; // index is unique to the ServiceDiscoveryRef
256*4904Srs200217 DNSServiceRef sdr;
257*4904Srs200217 } _DNSRecordRef_t;
258*4904Srs200217
259*4904Srs200217 // exported functions
260*4904Srs200217
261*4904Srs200217 // write len bytes. return 0 on success, -1 on error
write_all(dnssd_sock_t sd,char * buf,int len)262*4904Srs200217 static int write_all(dnssd_sock_t sd, char *buf, int len)
263*4904Srs200217 {
264*4904Srs200217 // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
265*4904Srs200217 //if (send(sd, buf, len, MSG_WAITALL) != len) return -1;
266*4904Srs200217 while (len)
267*4904Srs200217 {
268*4904Srs200217 ssize_t num_written = send(sd, buf, len, 0);
269*4904Srs200217 if (num_written < 0 || num_written > len) return -1;
270*4904Srs200217 buf += num_written;
271*4904Srs200217 len -= num_written;
272*4904Srs200217 }
273*4904Srs200217 return 0;
274*4904Srs200217 }
275*4904Srs200217
276*4904Srs200217 // read len bytes. return 0 on success, -1 on error
read_all(dnssd_sock_t sd,char * buf,int len)277*4904Srs200217 static int read_all(dnssd_sock_t sd, char *buf, int len)
278*4904Srs200217 {
279*4904Srs200217 // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
280*4904Srs200217 //if (recv(sd, buf, len, MSG_WAITALL) != len) return -1;
281*4904Srs200217 while (len)
282*4904Srs200217 {
283*4904Srs200217 ssize_t num_read = recv(sd, buf, len, 0);
284*4904Srs200217 if ((num_read == -1) && (errno == EINTR))
285*4904Srs200217 continue;
286*4904Srs200217 if ((num_read < 0) || (num_read > len)) return -1;
287*4904Srs200217 // Return error -2 when no data received and errno is not set
288*4904Srs200217 if (num_read == 0) return -2;
289*4904Srs200217 buf += num_read;
290*4904Srs200217 len -= num_read;
291*4904Srs200217 }
292*4904Srs200217 return 0;
293*4904Srs200217 }
294*4904Srs200217
295*4904Srs200217 /* create_hdr
296*4904Srs200217 *
297*4904Srs200217 * allocate and initialize an ipc message header. value of len should initially be the
298*4904Srs200217 * length of the data, and is set to the value of the data plus the header. data_start
299*4904Srs200217 * is set to point to the beginning of the data section. reuse_socket should be non-zero
300*4904Srs200217 * for calls that can receive an immediate error return value on their primary socket.
301*4904Srs200217 * if zero, the path to a control socket is appended at the beginning of the message buffer.
302*4904Srs200217 * data_start is set past this string.
303*4904Srs200217 */
304*4904Srs200217
create_hdr(uint32_t op,size_t * len,char ** data_start,int reuse_socket)305*4904Srs200217 static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int reuse_socket)
306*4904Srs200217 {
307*4904Srs200217 char *msg = NULL;
308*4904Srs200217 ipc_msg_hdr *hdr;
309*4904Srs200217 int datalen;
310*4904Srs200217 #if !defined(USE_TCP_LOOPBACK)
311*4904Srs200217 char ctrl_path[256];
312*4904Srs200217 #endif
313*4904Srs200217
314*4904Srs200217 if (!reuse_socket)
315*4904Srs200217 {
316*4904Srs200217 #if defined(USE_TCP_LOOPBACK)
317*4904Srs200217 *len += 2; // Allocate space for two-byte port number
318*4904Srs200217 #else
319*4904Srs200217 struct timeval time;
320*4904Srs200217 if (gettimeofday(&time, NULL) < 0) return NULL;
321*4904Srs200217 sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(),
322*4904Srs200217 (unsigned long)(time.tv_sec & 0xFFF), (unsigned long)(time.tv_usec));
323*4904Srs200217 *len += strlen(ctrl_path) + 1;
324*4904Srs200217 #endif
325*4904Srs200217 }
326*4904Srs200217
327*4904Srs200217 datalen = (int) *len;
328*4904Srs200217 *len += sizeof(ipc_msg_hdr);
329*4904Srs200217
330*4904Srs200217 // write message to buffer
331*4904Srs200217 msg = malloc(*len);
332*4904Srs200217 if (!msg) return NULL;
333*4904Srs200217
334*4904Srs200217 bzero(msg, *len);
335*4904Srs200217 hdr = (void *)msg;
336*4904Srs200217 hdr->datalen = datalen;
337*4904Srs200217 hdr->version = VERSION;
338*4904Srs200217 hdr->op = op;
339*4904Srs200217 if (reuse_socket) hdr->flags |= IPC_FLAGS_REUSE_SOCKET;
340*4904Srs200217 *data_start = msg + sizeof(ipc_msg_hdr);
341*4904Srs200217 #if defined(USE_TCP_LOOPBACK)
342*4904Srs200217 // Put dummy data in for the port, since we don't know what
343*4904Srs200217 // it is yet. The data will get filled in before we
344*4904Srs200217 // send the message. This happens in deliver_request().
345*4904Srs200217 if (!reuse_socket) put_short(0, data_start);
346*4904Srs200217 #else
347*4904Srs200217 if (!reuse_socket) put_string(ctrl_path, data_start);
348*4904Srs200217 #endif
349*4904Srs200217 return hdr;
350*4904Srs200217 }
351*4904Srs200217
352*4904Srs200217 // return a connected service ref (deallocate with DNSServiceRefDeallocate)
connect_to_server(void)353*4904Srs200217 static DNSServiceRef connect_to_server(void)
354*4904Srs200217 {
355*4904Srs200217 dnssd_sockaddr_t saddr;
356*4904Srs200217 DNSServiceRef sdr;
357*4904Srs200217 int NumTries = 0;
358*4904Srs200217
359*4904Srs200217 #if defined(_WIN32)
360*4904Srs200217 if (!g_initWinsock)
361*4904Srs200217 {
362*4904Srs200217 WSADATA wsaData;
363*4904Srs200217 DNSServiceErrorType err;
364*4904Srs200217
365*4904Srs200217 g_initWinsock = 1;
366*4904Srs200217
367*4904Srs200217 err = WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
368*4904Srs200217
369*4904Srs200217 if (err != 0) return NULL;
370*4904Srs200217 }
371*4904Srs200217
372*4904Srs200217 // <rdar://problem/4096913> If the system service is disabled, we only want to try
373*4904Srs200217 // to connect once
374*4904Srs200217
375*4904Srs200217 if ( IsSystemServiceDisabled() )
376*4904Srs200217 {
377*4904Srs200217 NumTries = DNSSD_CLIENT_MAXTRIES;
378*4904Srs200217 }
379*4904Srs200217
380*4904Srs200217 #endif
381*4904Srs200217
382*4904Srs200217 sdr = malloc(sizeof(_DNSServiceRef_t));
383*4904Srs200217 if (!sdr) return(NULL);
384*4904Srs200217 sdr->sockfd = socket(AF_DNSSD, SOCK_STREAM, 0);
385*4904Srs200217 if (sdr->sockfd == dnssd_InvalidSocket) { free(sdr); return NULL; }
386*4904Srs200217 #if defined(USE_TCP_LOOPBACK)
387*4904Srs200217 saddr.sin_family = AF_INET;
388*4904Srs200217 saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
389*4904Srs200217 saddr.sin_port = htons(MDNS_TCP_SERVERPORT);
390*4904Srs200217 #else
391*4904Srs200217 saddr.sun_family = AF_LOCAL;
392*4904Srs200217 strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH);
393*4904Srs200217 #endif
394*4904Srs200217 while (1)
395*4904Srs200217 {
396*4904Srs200217 int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr));
397*4904Srs200217 if (!err) break; // If we succeeded, return sdr
398*4904Srs200217 // If we failed, then it may be because the daemon is still launching.
399*4904Srs200217 // This can happen for processes that launch early in the boot process, while the
400*4904Srs200217 // daemon is still coming up. Rather than fail here, we'll wait a bit and try again.
401*4904Srs200217 // If, after four seconds, we still can't connect to the daemon,
402*4904Srs200217 // then we give up and return a failure code.
403*4904Srs200217 if (++NumTries < DNSSD_CLIENT_MAXTRIES)
404*4904Srs200217 sleep(1); // Sleep a bit, then try again
405*4904Srs200217 else
406*4904Srs200217 {
407*4904Srs200217 dnssd_close(sdr->sockfd);
408*4904Srs200217 sdr->sockfd = dnssd_InvalidSocket;
409*4904Srs200217 free(sdr);
410*4904Srs200217 return NULL;
411*4904Srs200217 }
412*4904Srs200217 }
413*4904Srs200217 return sdr;
414*4904Srs200217 }
415*4904Srs200217
deliver_request(void * msg,DNSServiceRef sdr,int reuse_sd)416*4904Srs200217 static DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reuse_sd)
417*4904Srs200217 {
418*4904Srs200217 ipc_msg_hdr *hdr = msg;
419*4904Srs200217 uint32_t datalen = hdr->datalen;
420*4904Srs200217 dnssd_sockaddr_t caddr, daddr; // (client and daemon address structs)
421*4904Srs200217 char *const data = (char *)msg + sizeof(ipc_msg_hdr);
422*4904Srs200217 dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
423*4904Srs200217 int ret;
424*4904Srs200217 dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr);
425*4904Srs200217 DNSServiceErrorType err = kDNSServiceErr_Unknown;
426*4904Srs200217
427*4904Srs200217 if (!hdr || sdr->sockfd < 0) return kDNSServiceErr_Unknown;
428*4904Srs200217
429*4904Srs200217 if (!reuse_sd)
430*4904Srs200217 {
431*4904Srs200217 // setup temporary error socket
432*4904Srs200217 if ((listenfd = socket(AF_DNSSD, SOCK_STREAM, 0)) < 0)
433*4904Srs200217 goto cleanup;
434*4904Srs200217 bzero(&caddr, sizeof(caddr));
435*4904Srs200217
436*4904Srs200217 #if defined(USE_TCP_LOOPBACK)
437*4904Srs200217 {
438*4904Srs200217 union { uint16_t s; u_char b[2]; } port;
439*4904Srs200217 caddr.sin_family = AF_INET;
440*4904Srs200217 caddr.sin_port = 0;
441*4904Srs200217 caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
442*4904Srs200217 ret = bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr));
443*4904Srs200217 if (ret < 0) goto cleanup;
444*4904Srs200217 if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) goto cleanup;
445*4904Srs200217 listen(listenfd, 1);
446*4904Srs200217 port.s = caddr.sin_port;
447*4904Srs200217 data[0] = port.b[0]; // don't switch the byte order, as the
448*4904Srs200217 data[1] = port.b[1]; // daemon expects it in network byte order
449*4904Srs200217 }
450*4904Srs200217 #else
451*4904Srs200217 {
452*4904Srs200217 mode_t mask = umask(0);
453*4904Srs200217 caddr.sun_family = AF_LOCAL;
454*4904Srs200217 // According to Stevens (section 3.2), there is no portable way to
455*4904Srs200217 // determine whether sa_len is defined on a particular platform.
456*4904Srs200217 #ifndef NOT_HAVE_SA_LEN
457*4904Srs200217 caddr.sun_len = sizeof(struct sockaddr_un);
458*4904Srs200217 #endif
459*4904Srs200217 //syslog(LOG_WARNING, "deliver_request: creating UDS: %s\n", data);
460*4904Srs200217 strcpy(caddr.sun_path, data);
461*4904Srs200217 ret = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
462*4904Srs200217 umask(mask);
463*4904Srs200217 if (ret < 0) goto cleanup;
464*4904Srs200217 listen(listenfd, 1);
465*4904Srs200217 }
466*4904Srs200217 #endif
467*4904Srs200217 }
468*4904Srs200217
469*4904Srs200217 ConvertHeaderBytes(hdr);
470*4904Srs200217 //syslog(LOG_WARNING, "deliver_request writing %ld bytes\n", datalen + sizeof(ipc_msg_hdr));
471*4904Srs200217 //syslog(LOG_WARNING, "deliver_request name is %s\n", (char *)msg + sizeof(ipc_msg_hdr));
472*4904Srs200217 if (write_all(sdr->sockfd, msg, datalen + sizeof(ipc_msg_hdr)) < 0)
473*4904Srs200217 goto cleanup;
474*4904Srs200217 free(msg);
475*4904Srs200217 msg = NULL;
476*4904Srs200217
477*4904Srs200217 if (reuse_sd) errsd = sdr->sockfd;
478*4904Srs200217 else
479*4904Srs200217 {
480*4904Srs200217 //syslog(LOG_WARNING, "deliver_request: accept\n");
481*4904Srs200217 len = sizeof(daddr);
482*4904Srs200217 errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
483*4904Srs200217 //syslog(LOG_WARNING, "deliver_request: accept returned %d\n", errsd);
484*4904Srs200217 if (errsd < 0) goto cleanup;
485*4904Srs200217 }
486*4904Srs200217
487*4904Srs200217 if (read_all(errsd, (char*)&err, (int)sizeof(err)) < 0)
488*4904Srs200217 err = kDNSServiceErr_Unknown;
489*4904Srs200217 else
490*4904Srs200217 err = ntohl(err);
491*4904Srs200217
492*4904Srs200217 //syslog(LOG_WARNING, "deliver_request: retrieved error code %d\n", err);
493*4904Srs200217
494*4904Srs200217 cleanup:
495*4904Srs200217 if (!reuse_sd)
496*4904Srs200217 {
497*4904Srs200217 if (listenfd > 0) dnssd_close(listenfd);
498*4904Srs200217 if (errsd > 0) dnssd_close(errsd);
499*4904Srs200217 #if !defined(USE_TCP_LOOPBACK)
500*4904Srs200217 // syslog(LOG_WARNING, "deliver_request: removing UDS: %s\n", data);
501*4904Srs200217 if (unlink(data) != 0)
502*4904Srs200217 syslog(LOG_WARNING, "WARNING: unlink(\"%s\") failed errno %d (%s)", data, errno, strerror(errno));
503*4904Srs200217 // else syslog(LOG_WARNING, "deliver_request: removed UDS: %s\n", data);
504*4904Srs200217 #endif
505*4904Srs200217 }
506*4904Srs200217 if (msg) free(msg);
507*4904Srs200217 return err;
508*4904Srs200217 }
509*4904Srs200217
DNSServiceRefSockFD(DNSServiceRef sdRef)510*4904Srs200217 int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
511*4904Srs200217 {
512*4904Srs200217 if (!sdRef) return -1;
513*4904Srs200217 return (int) sdRef->sockfd;
514*4904Srs200217 }
515*4904Srs200217
516*4904Srs200217 // handle reply from server, calling application client callback. If there is no reply
517*4904Srs200217 // from the daemon on the socket contained in sdRef, the call will block.
DNSServiceProcessResult(DNSServiceRef sdRef)518*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
519*4904Srs200217 {
520*4904Srs200217 ipc_msg_hdr hdr;
521*4904Srs200217 char *data;
522*4904Srs200217 int rderr;
523*4904Srs200217
524*4904Srs200217 if (!sdRef || sdRef->sockfd < 0 || !sdRef->process_reply)
525*4904Srs200217 return kDNSServiceErr_BadReference;
526*4904Srs200217
527*4904Srs200217 rderr = read_all(sdRef->sockfd, (void *)&hdr, sizeof(hdr));
528*4904Srs200217 if (rderr < 0) {
529*4904Srs200217 // return NoError on EWOULDBLOCK. This will handle the case
530*4904Srs200217 // where a non-blocking socket is told there is data, but
531*4904Srs200217 // it was a false positive. Can check errno when error
532*4904Srs200217 // code returned is -1
533*4904Srs200217 if ((rderr == -1) && (dnssd_errno() == dnssd_EWOULDBLOCK))
534*4904Srs200217 return kDNSServiceErr_NoError;
535*4904Srs200217 return kDNSServiceErr_Unknown;
536*4904Srs200217 }
537*4904Srs200217 ConvertHeaderBytes(&hdr);
538*4904Srs200217 if (hdr.version != VERSION)
539*4904Srs200217 return kDNSServiceErr_Incompatible;
540*4904Srs200217 data = malloc(hdr.datalen);
541*4904Srs200217 if (!data) return kDNSServiceErr_NoMemory;
542*4904Srs200217 if (read_all(sdRef->sockfd, data, hdr.datalen) < 0)
543*4904Srs200217 return kDNSServiceErr_Unknown;
544*4904Srs200217 sdRef->process_reply(sdRef, &hdr, data);
545*4904Srs200217 free(data);
546*4904Srs200217 return kDNSServiceErr_NoError;
547*4904Srs200217 }
548*4904Srs200217
DNSServiceRefDeallocate(DNSServiceRef sdRef)549*4904Srs200217 void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef)
550*4904Srs200217 {
551*4904Srs200217 if (!sdRef) return;
552*4904Srs200217 if (sdRef->sockfd > 0) dnssd_close(sdRef->sockfd);
553*4904Srs200217 free(sdRef);
554*4904Srs200217 }
555*4904Srs200217
handle_resolve_response(DNSServiceRef sdr,ipc_msg_hdr * hdr,char * data)556*4904Srs200217 static void handle_resolve_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
557*4904Srs200217 {
558*4904Srs200217 DNSServiceFlags flags;
559*4904Srs200217 char fullname[kDNSServiceMaxDomainName];
560*4904Srs200217 char target[kDNSServiceMaxDomainName];
561*4904Srs200217 uint16_t txtlen;
562*4904Srs200217 union { uint16_t s; u_char b[2]; } port;
563*4904Srs200217 uint32_t ifi;
564*4904Srs200217 DNSServiceErrorType err;
565*4904Srs200217 unsigned char *txtrecord;
566*4904Srs200217 int str_error = 0;
567*4904Srs200217 (void)hdr; //unused
568*4904Srs200217
569*4904Srs200217 flags = get_flags(&data);
570*4904Srs200217 ifi = get_long(&data);
571*4904Srs200217 err = get_error_code(&data);
572*4904Srs200217 if (get_string(&data, fullname, kDNSServiceMaxDomainName) < 0) str_error = 1;
573*4904Srs200217 if (get_string(&data, target, kDNSServiceMaxDomainName) < 0) str_error = 1;
574*4904Srs200217 port.b[0] = *data++;
575*4904Srs200217 port.b[1] = *data++;
576*4904Srs200217 txtlen = get_short(&data);
577*4904Srs200217 txtrecord = (unsigned char *)get_rdata(&data, txtlen);
578*4904Srs200217
579*4904Srs200217 if (!err && str_error) err = kDNSServiceErr_Unknown;
580*4904Srs200217 ((DNSServiceResolveReply)sdr->app_callback)(sdr, flags, ifi, err, fullname, target, port.s, txtlen, txtrecord, sdr->app_context);
581*4904Srs200217 }
582*4904Srs200217
DNSServiceResolve(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,const char * name,const char * regtype,const char * domain,DNSServiceResolveReply callBack,void * context)583*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceResolve
584*4904Srs200217 (
585*4904Srs200217 DNSServiceRef *sdRef,
586*4904Srs200217 DNSServiceFlags flags,
587*4904Srs200217 uint32_t interfaceIndex,
588*4904Srs200217 const char *name,
589*4904Srs200217 const char *regtype,
590*4904Srs200217 const char *domain,
591*4904Srs200217 DNSServiceResolveReply callBack,
592*4904Srs200217 void *context
593*4904Srs200217 )
594*4904Srs200217 {
595*4904Srs200217 char *msg = NULL, *ptr;
596*4904Srs200217 size_t len;
597*4904Srs200217 ipc_msg_hdr *hdr;
598*4904Srs200217 DNSServiceRef sdr;
599*4904Srs200217 DNSServiceErrorType err;
600*4904Srs200217
601*4904Srs200217 if (!sdRef) return kDNSServiceErr_BadParam;
602*4904Srs200217 *sdRef = NULL;
603*4904Srs200217
604*4904Srs200217 if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam;
605*4904Srs200217
606*4904Srs200217 // calculate total message length
607*4904Srs200217 len = sizeof(flags);
608*4904Srs200217 len += sizeof(interfaceIndex);
609*4904Srs200217 len += strlen(name) + 1;
610*4904Srs200217 len += strlen(regtype) + 1;
611*4904Srs200217 len += strlen(domain) + 1;
612*4904Srs200217
613*4904Srs200217 hdr = create_hdr(resolve_request, &len, &ptr, 1);
614*4904Srs200217 if (!hdr) goto error;
615*4904Srs200217 msg = (void *)hdr;
616*4904Srs200217
617*4904Srs200217 put_flags(flags, &ptr);
618*4904Srs200217 put_long(interfaceIndex, &ptr);
619*4904Srs200217 put_string(name, &ptr);
620*4904Srs200217 put_string(regtype, &ptr);
621*4904Srs200217 put_string(domain, &ptr);
622*4904Srs200217
623*4904Srs200217 sdr = connect_to_server();
624*4904Srs200217 if (!sdr) goto error;
625*4904Srs200217 err = deliver_request(msg, sdr, 1);
626*4904Srs200217 if (err)
627*4904Srs200217 {
628*4904Srs200217 DNSServiceRefDeallocate(sdr);
629*4904Srs200217 return err;
630*4904Srs200217 }
631*4904Srs200217 sdr->op = resolve_request;
632*4904Srs200217 sdr->process_reply = handle_resolve_response;
633*4904Srs200217 sdr->app_callback = callBack;
634*4904Srs200217 sdr->app_context = context;
635*4904Srs200217 *sdRef = sdr;
636*4904Srs200217
637*4904Srs200217 return err;
638*4904Srs200217
639*4904Srs200217 error:
640*4904Srs200217 if (msg) free(msg);
641*4904Srs200217 if (*sdRef) { free(*sdRef); *sdRef = NULL; }
642*4904Srs200217 return kDNSServiceErr_Unknown;
643*4904Srs200217 }
644*4904Srs200217
handle_query_response(DNSServiceRef sdr,ipc_msg_hdr * hdr,char * data)645*4904Srs200217 static void handle_query_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
646*4904Srs200217 {
647*4904Srs200217 DNSServiceFlags flags;
648*4904Srs200217 uint32_t interfaceIndex, ttl;
649*4904Srs200217 DNSServiceErrorType errorCode;
650*4904Srs200217 char name[kDNSServiceMaxDomainName];
651*4904Srs200217 uint16_t rrtype, rrclass, rdlen;
652*4904Srs200217 char *rdata;
653*4904Srs200217 int str_error = 0;
654*4904Srs200217 (void)hdr;//Unused
655*4904Srs200217
656*4904Srs200217 flags = get_flags(&data);
657*4904Srs200217 interfaceIndex = get_long(&data);
658*4904Srs200217 errorCode = get_error_code(&data);
659*4904Srs200217 if (get_string(&data, name, kDNSServiceMaxDomainName) < 0) str_error = 1;
660*4904Srs200217 rrtype = get_short(&data);
661*4904Srs200217 rrclass = get_short(&data);
662*4904Srs200217 rdlen = get_short(&data);
663*4904Srs200217 rdata = get_rdata(&data, rdlen);
664*4904Srs200217 ttl = get_long(&data);
665*4904Srs200217
666*4904Srs200217 if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown;
667*4904Srs200217 ((DNSServiceQueryRecordReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, name, rrtype, rrclass,
668*4904Srs200217 rdlen, rdata, ttl, sdr->app_context);
669*4904Srs200217 return;
670*4904Srs200217 }
671*4904Srs200217
DNSServiceQueryRecord(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,const char * name,uint16_t rrtype,uint16_t rrclass,DNSServiceQueryRecordReply callBack,void * context)672*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
673*4904Srs200217 (
674*4904Srs200217 DNSServiceRef *sdRef,
675*4904Srs200217 DNSServiceFlags flags,
676*4904Srs200217 uint32_t interfaceIndex,
677*4904Srs200217 const char *name,
678*4904Srs200217 uint16_t rrtype,
679*4904Srs200217 uint16_t rrclass,
680*4904Srs200217 DNSServiceQueryRecordReply callBack,
681*4904Srs200217 void *context
682*4904Srs200217 )
683*4904Srs200217 {
684*4904Srs200217 char *msg = NULL, *ptr;
685*4904Srs200217 size_t len;
686*4904Srs200217 ipc_msg_hdr *hdr;
687*4904Srs200217 DNSServiceRef sdr;
688*4904Srs200217 DNSServiceErrorType err;
689*4904Srs200217
690*4904Srs200217 if (!sdRef) return kDNSServiceErr_BadParam;
691*4904Srs200217 *sdRef = NULL;
692*4904Srs200217
693*4904Srs200217 if (!name) name = "\0";
694*4904Srs200217
695*4904Srs200217 // calculate total message length
696*4904Srs200217 len = sizeof(flags);
697*4904Srs200217 len += sizeof(uint32_t); //interfaceIndex
698*4904Srs200217 len += strlen(name) + 1;
699*4904Srs200217 len += 2 * sizeof(uint16_t); // rrtype, rrclass
700*4904Srs200217
701*4904Srs200217 hdr = create_hdr(query_request, &len, &ptr, 1);
702*4904Srs200217 if (!hdr) goto error;
703*4904Srs200217 msg = (void *)hdr;
704*4904Srs200217
705*4904Srs200217 put_flags(flags, &ptr);
706*4904Srs200217 put_long(interfaceIndex, &ptr);
707*4904Srs200217 put_string(name, &ptr);
708*4904Srs200217 put_short(rrtype, &ptr);
709*4904Srs200217 put_short(rrclass, &ptr);
710*4904Srs200217
711*4904Srs200217 sdr = connect_to_server();
712*4904Srs200217 if (!sdr) goto error;
713*4904Srs200217 err = deliver_request(msg, sdr, 1);
714*4904Srs200217 if (err)
715*4904Srs200217 {
716*4904Srs200217 DNSServiceRefDeallocate(sdr);
717*4904Srs200217 return err;
718*4904Srs200217 }
719*4904Srs200217
720*4904Srs200217 sdr->op = query_request;
721*4904Srs200217 sdr->process_reply = handle_query_response;
722*4904Srs200217 sdr->app_callback = callBack;
723*4904Srs200217 sdr->app_context = context;
724*4904Srs200217 *sdRef = sdr;
725*4904Srs200217 return err;
726*4904Srs200217
727*4904Srs200217 error:
728*4904Srs200217 if (msg) free(msg);
729*4904Srs200217 if (*sdRef) { free(*sdRef); *sdRef = NULL; }
730*4904Srs200217 return kDNSServiceErr_Unknown;
731*4904Srs200217 }
732*4904Srs200217
handle_browse_response(DNSServiceRef sdr,ipc_msg_hdr * hdr,char * data)733*4904Srs200217 static void handle_browse_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
734*4904Srs200217 {
735*4904Srs200217 DNSServiceFlags flags;
736*4904Srs200217 uint32_t interfaceIndex;
737*4904Srs200217 DNSServiceErrorType errorCode;
738*4904Srs200217 char replyName[256], replyType[kDNSServiceMaxDomainName],
739*4904Srs200217 replyDomain[kDNSServiceMaxDomainName];
740*4904Srs200217 int str_error = 0;
741*4904Srs200217 (void)hdr;//Unused
742*4904Srs200217
743*4904Srs200217 flags = get_flags(&data);
744*4904Srs200217 interfaceIndex = get_long(&data);
745*4904Srs200217 errorCode = get_error_code(&data);
746*4904Srs200217 if (get_string(&data, replyName, 256) < 0) str_error = 1;
747*4904Srs200217 if (get_string(&data, replyType, kDNSServiceMaxDomainName) < 0) str_error = 1;
748*4904Srs200217 if (get_string(&data, replyDomain, kDNSServiceMaxDomainName) < 0) str_error = 1;
749*4904Srs200217 if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown;
750*4904Srs200217 ((DNSServiceBrowseReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, replyName, replyType, replyDomain, sdr->app_context);
751*4904Srs200217 }
752*4904Srs200217
DNSServiceBrowse(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,const char * regtype,const char * domain,DNSServiceBrowseReply callBack,void * context)753*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceBrowse
754*4904Srs200217 (
755*4904Srs200217 DNSServiceRef *sdRef,
756*4904Srs200217 DNSServiceFlags flags,
757*4904Srs200217 uint32_t interfaceIndex,
758*4904Srs200217 const char *regtype,
759*4904Srs200217 const char *domain,
760*4904Srs200217 DNSServiceBrowseReply callBack,
761*4904Srs200217 void *context
762*4904Srs200217 )
763*4904Srs200217 {
764*4904Srs200217 char *msg = NULL, *ptr;
765*4904Srs200217 size_t len;
766*4904Srs200217 ipc_msg_hdr *hdr;
767*4904Srs200217 DNSServiceRef sdr;
768*4904Srs200217 DNSServiceErrorType err;
769*4904Srs200217
770*4904Srs200217 if (!sdRef) return kDNSServiceErr_BadParam;
771*4904Srs200217 *sdRef = NULL;
772*4904Srs200217
773*4904Srs200217 if (!domain) domain = "";
774*4904Srs200217
775*4904Srs200217 len = sizeof(flags);
776*4904Srs200217 len += sizeof(interfaceIndex);
777*4904Srs200217 len += strlen(regtype) + 1;
778*4904Srs200217 len += strlen(domain) + 1;
779*4904Srs200217
780*4904Srs200217 hdr = create_hdr(browse_request, &len, &ptr, 1);
781*4904Srs200217 if (!hdr) goto error;
782*4904Srs200217 msg = (char *)hdr;
783*4904Srs200217 put_flags(flags, &ptr);
784*4904Srs200217 put_long(interfaceIndex, &ptr);
785*4904Srs200217 put_string(regtype, &ptr);
786*4904Srs200217 put_string(domain, &ptr);
787*4904Srs200217
788*4904Srs200217 sdr = connect_to_server();
789*4904Srs200217 if (!sdr) goto error;
790*4904Srs200217 err = deliver_request(msg, sdr, 1);
791*4904Srs200217 if (err)
792*4904Srs200217 {
793*4904Srs200217 DNSServiceRefDeallocate(sdr);
794*4904Srs200217 return err;
795*4904Srs200217 }
796*4904Srs200217 sdr->op = browse_request;
797*4904Srs200217 sdr->process_reply = handle_browse_response;
798*4904Srs200217 sdr->app_callback = callBack;
799*4904Srs200217 sdr->app_context = context;
800*4904Srs200217 *sdRef = sdr;
801*4904Srs200217 return err;
802*4904Srs200217
803*4904Srs200217 error:
804*4904Srs200217 if (msg) free(msg);
805*4904Srs200217 if (*sdRef) { free(*sdRef); *sdRef = NULL; }
806*4904Srs200217 return kDNSServiceErr_Unknown;
807*4904Srs200217 }
808*4904Srs200217
DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags,const char * domain)809*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser
810*4904Srs200217 (
811*4904Srs200217 DNSServiceFlags flags,
812*4904Srs200217 const char *domain
813*4904Srs200217 )
814*4904Srs200217 {
815*4904Srs200217 DNSServiceRef sdr;
816*4904Srs200217 DNSServiceErrorType err;
817*4904Srs200217 char *ptr = NULL;
818*4904Srs200217 size_t len = sizeof(flags) + strlen(domain) + 1;
819*4904Srs200217 ipc_msg_hdr *hdr = create_hdr(setdomain_request, &len, &ptr, 1);
820*4904Srs200217
821*4904Srs200217 if (!hdr) return kDNSServiceErr_Unknown;
822*4904Srs200217 put_flags(flags, &ptr);
823*4904Srs200217 put_string(domain, &ptr);
824*4904Srs200217
825*4904Srs200217 sdr = connect_to_server();
826*4904Srs200217 if (!sdr) { free(hdr); return kDNSServiceErr_Unknown; }
827*4904Srs200217 err = deliver_request((char *)hdr, sdr, 1); // deliver_request frees the message for us
828*4904Srs200217 DNSServiceRefDeallocate(sdr);
829*4904Srs200217 return err;
830*4904Srs200217 }
831*4904Srs200217
832*4904Srs200217
handle_regservice_response(DNSServiceRef sdr,ipc_msg_hdr * hdr,char * data)833*4904Srs200217 static void handle_regservice_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
834*4904Srs200217 {
835*4904Srs200217 DNSServiceFlags flags;
836*4904Srs200217 uint32_t interfaceIndex;
837*4904Srs200217 DNSServiceErrorType errorCode;
838*4904Srs200217 char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName];
839*4904Srs200217 int str_error = 0;
840*4904Srs200217 (void)hdr;//Unused
841*4904Srs200217
842*4904Srs200217 flags = get_flags(&data);
843*4904Srs200217 interfaceIndex = get_long(&data);
844*4904Srs200217 errorCode = get_error_code(&data);
845*4904Srs200217 if (get_string(&data, name, 256) < 0) str_error = 1;
846*4904Srs200217 if (get_string(&data, regtype, kDNSServiceMaxDomainName) < 0) str_error = 1;
847*4904Srs200217 if (get_string(&data, domain, kDNSServiceMaxDomainName) < 0) str_error = 1;
848*4904Srs200217 if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown;
849*4904Srs200217 ((DNSServiceRegisterReply)sdr->app_callback)(sdr, flags, errorCode, name, regtype, domain, sdr->app_context);
850*4904Srs200217 }
851*4904Srs200217
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)852*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceRegister
853*4904Srs200217 (
854*4904Srs200217 DNSServiceRef *sdRef,
855*4904Srs200217 DNSServiceFlags flags,
856*4904Srs200217 uint32_t interfaceIndex,
857*4904Srs200217 const char *name,
858*4904Srs200217 const char *regtype,
859*4904Srs200217 const char *domain,
860*4904Srs200217 const char *host,
861*4904Srs200217 uint16_t PortInNetworkByteOrder,
862*4904Srs200217 uint16_t txtLen,
863*4904Srs200217 const void *txtRecord,
864*4904Srs200217 DNSServiceRegisterReply callBack,
865*4904Srs200217 void *context
866*4904Srs200217 )
867*4904Srs200217 {
868*4904Srs200217 char *msg = NULL, *ptr;
869*4904Srs200217 size_t len;
870*4904Srs200217 ipc_msg_hdr *hdr;
871*4904Srs200217 DNSServiceRef sdr;
872*4904Srs200217 DNSServiceErrorType err;
873*4904Srs200217 union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder };
874*4904Srs200217
875*4904Srs200217 if (!sdRef) return kDNSServiceErr_BadParam;
876*4904Srs200217 *sdRef = NULL;
877*4904Srs200217
878*4904Srs200217 if (!name) name = "";
879*4904Srs200217 if (!regtype) return kDNSServiceErr_BadParam;
880*4904Srs200217 if (!domain) domain = "";
881*4904Srs200217 if (!host) host = "";
882*4904Srs200217 if (!txtRecord) txtRecord = (void*)"";
883*4904Srs200217
884*4904Srs200217 // auto-name must also have auto-rename
885*4904Srs200217 if (!name[0] && (flags & kDNSServiceFlagsNoAutoRename))
886*4904Srs200217 return kDNSServiceErr_BadParam;
887*4904Srs200217
888*4904Srs200217 // no callback must have auto-rename
889*4904Srs200217 if (!callBack && (flags & kDNSServiceFlagsNoAutoRename)) return kDNSServiceErr_BadParam;
890*4904Srs200217
891*4904Srs200217 len = sizeof(DNSServiceFlags);
892*4904Srs200217 len += sizeof(uint32_t); // interfaceIndex
893*4904Srs200217 len += strlen(name) + strlen(regtype) + strlen(domain) + strlen(host) + 4;
894*4904Srs200217 len += 2 * sizeof(uint16_t); // port, txtLen
895*4904Srs200217 len += txtLen;
896*4904Srs200217
897*4904Srs200217 hdr = create_hdr(reg_service_request, &len, &ptr, 1);
898*4904Srs200217 if (!hdr) goto error;
899*4904Srs200217 if (!callBack) hdr->flags |= IPC_FLAGS_NOREPLY;
900*4904Srs200217 msg = (char *)hdr;
901*4904Srs200217 put_flags(flags, &ptr);
902*4904Srs200217 put_long(interfaceIndex, &ptr);
903*4904Srs200217 put_string(name, &ptr);
904*4904Srs200217 put_string(regtype, &ptr);
905*4904Srs200217 put_string(domain, &ptr);
906*4904Srs200217 put_string(host, &ptr);
907*4904Srs200217 *ptr++ = port.b[0];
908*4904Srs200217 *ptr++ = port.b[1];
909*4904Srs200217 put_short(txtLen, &ptr);
910*4904Srs200217 put_rdata(txtLen, txtRecord, &ptr);
911*4904Srs200217
912*4904Srs200217 sdr = connect_to_server();
913*4904Srs200217 if (!sdr) goto error;
914*4904Srs200217 err = deliver_request(msg, sdr, 1);
915*4904Srs200217 if (err)
916*4904Srs200217 {
917*4904Srs200217 DNSServiceRefDeallocate(sdr);
918*4904Srs200217 return err;
919*4904Srs200217 }
920*4904Srs200217
921*4904Srs200217 sdr->op = reg_service_request;
922*4904Srs200217 sdr->process_reply = callBack ? handle_regservice_response : NULL;
923*4904Srs200217 sdr->app_callback = callBack;
924*4904Srs200217 sdr->app_context = context;
925*4904Srs200217 *sdRef = sdr;
926*4904Srs200217
927*4904Srs200217 return err;
928*4904Srs200217
929*4904Srs200217 error:
930*4904Srs200217 if (msg) free(msg);
931*4904Srs200217 if (*sdRef) { free(*sdRef); *sdRef = NULL; }
932*4904Srs200217 return kDNSServiceErr_Unknown;
933*4904Srs200217 }
934*4904Srs200217
handle_enumeration_response(DNSServiceRef sdr,ipc_msg_hdr * hdr,char * data)935*4904Srs200217 static void handle_enumeration_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
936*4904Srs200217 {
937*4904Srs200217 DNSServiceFlags flags;
938*4904Srs200217 uint32_t interfaceIndex;
939*4904Srs200217 DNSServiceErrorType err;
940*4904Srs200217 char domain[kDNSServiceMaxDomainName];
941*4904Srs200217 int str_error = 0;
942*4904Srs200217 (void)hdr;//Unused
943*4904Srs200217
944*4904Srs200217 flags = get_flags(&data);
945*4904Srs200217 interfaceIndex = get_long(&data);
946*4904Srs200217 err = get_error_code(&data);
947*4904Srs200217 if (get_string(&data, domain, kDNSServiceMaxDomainName) < 0) str_error = 1;
948*4904Srs200217 if (!err && str_error) err = kDNSServiceErr_Unknown;
949*4904Srs200217 ((DNSServiceDomainEnumReply)sdr->app_callback)(sdr, flags, interfaceIndex, err, domain, sdr->app_context);
950*4904Srs200217 }
951*4904Srs200217
DNSServiceEnumerateDomains(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceDomainEnumReply callBack,void * context)952*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
953*4904Srs200217 (
954*4904Srs200217 DNSServiceRef *sdRef,
955*4904Srs200217 DNSServiceFlags flags,
956*4904Srs200217 uint32_t interfaceIndex,
957*4904Srs200217 DNSServiceDomainEnumReply callBack,
958*4904Srs200217 void *context
959*4904Srs200217 )
960*4904Srs200217 {
961*4904Srs200217 char *msg = NULL, *ptr;
962*4904Srs200217 size_t len;
963*4904Srs200217 ipc_msg_hdr *hdr;
964*4904Srs200217 DNSServiceRef sdr;
965*4904Srs200217 DNSServiceErrorType err;
966*4904Srs200217 int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0;
967*4904Srs200217 int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0;
968*4904Srs200217 if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
969*4904Srs200217
970*4904Srs200217 if (!sdRef) return kDNSServiceErr_BadParam;
971*4904Srs200217 *sdRef = NULL;
972*4904Srs200217
973*4904Srs200217 len = sizeof(DNSServiceFlags);
974*4904Srs200217 len += sizeof(uint32_t);
975*4904Srs200217
976*4904Srs200217 hdr = create_hdr(enumeration_request, &len, &ptr, 1);
977*4904Srs200217 if (!hdr) goto error;
978*4904Srs200217 msg = (void *)hdr;
979*4904Srs200217
980*4904Srs200217 put_flags(flags, &ptr);
981*4904Srs200217 put_long(interfaceIndex, &ptr);
982*4904Srs200217
983*4904Srs200217 sdr = connect_to_server();
984*4904Srs200217 if (!sdr) goto error;
985*4904Srs200217 err = deliver_request(msg, sdr, 1);
986*4904Srs200217 if (err)
987*4904Srs200217 {
988*4904Srs200217 DNSServiceRefDeallocate(sdr);
989*4904Srs200217 return err;
990*4904Srs200217 }
991*4904Srs200217
992*4904Srs200217 sdr->op = enumeration_request;
993*4904Srs200217 sdr->process_reply = handle_enumeration_response;
994*4904Srs200217 sdr->app_callback = callBack;
995*4904Srs200217 sdr->app_context = context;
996*4904Srs200217 *sdRef = sdr;
997*4904Srs200217 return err;
998*4904Srs200217
999*4904Srs200217 error:
1000*4904Srs200217 if (msg) free(msg);
1001*4904Srs200217 if (*sdRef) { free(*sdRef); *sdRef = NULL; }
1002*4904Srs200217 return kDNSServiceErr_Unknown;
1003*4904Srs200217 }
1004*4904Srs200217
handle_regrecord_response(DNSServiceRef sdr,ipc_msg_hdr * hdr,char * data)1005*4904Srs200217 static void handle_regrecord_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
1006*4904Srs200217 {
1007*4904Srs200217 DNSServiceFlags flags;
1008*4904Srs200217 uint32_t interfaceIndex;
1009*4904Srs200217 DNSServiceErrorType errorCode;
1010*4904Srs200217 DNSRecordRef rref = hdr->client_context.context;
1011*4904Srs200217
1012*4904Srs200217 if (sdr->op != connection)
1013*4904Srs200217 {
1014*4904Srs200217 rref->app_callback(rref->sdr, rref, 0, kDNSServiceErr_Unknown, rref->app_context);
1015*4904Srs200217 return;
1016*4904Srs200217 }
1017*4904Srs200217 flags = get_flags(&data);
1018*4904Srs200217 interfaceIndex = get_long(&data);
1019*4904Srs200217 errorCode = get_error_code(&data);
1020*4904Srs200217
1021*4904Srs200217 rref->app_callback(rref->sdr, rref, flags, errorCode, rref->app_context);
1022*4904Srs200217 }
1023*4904Srs200217
DNSServiceCreateConnection(DNSServiceRef * sdRef)1024*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef)
1025*4904Srs200217 {
1026*4904Srs200217 if (!sdRef) return kDNSServiceErr_BadParam;
1027*4904Srs200217 *sdRef = connect_to_server();
1028*4904Srs200217 if (!*sdRef)
1029*4904Srs200217 return kDNSServiceErr_Unknown;
1030*4904Srs200217 (*sdRef)->op = connection;
1031*4904Srs200217 (*sdRef)->process_reply = handle_regrecord_response;
1032*4904Srs200217 return 0;
1033*4904Srs200217 }
1034*4904Srs200217
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)1035*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
1036*4904Srs200217 (
1037*4904Srs200217 DNSServiceRef sdRef,
1038*4904Srs200217 DNSRecordRef *RecordRef,
1039*4904Srs200217 DNSServiceFlags flags,
1040*4904Srs200217 uint32_t interfaceIndex,
1041*4904Srs200217 const char *fullname,
1042*4904Srs200217 uint16_t rrtype,
1043*4904Srs200217 uint16_t rrclass,
1044*4904Srs200217 uint16_t rdlen,
1045*4904Srs200217 const void *rdata,
1046*4904Srs200217 uint32_t ttl,
1047*4904Srs200217 DNSServiceRegisterRecordReply callBack,
1048*4904Srs200217 void *context
1049*4904Srs200217 )
1050*4904Srs200217 {
1051*4904Srs200217 char *msg = NULL, *ptr;
1052*4904Srs200217 size_t len;
1053*4904Srs200217 ipc_msg_hdr *hdr = NULL;
1054*4904Srs200217 DNSServiceRef tmp = NULL;
1055*4904Srs200217 DNSRecordRef rref = NULL;
1056*4904Srs200217 int f1 = (flags & kDNSServiceFlagsShared) != 0;
1057*4904Srs200217 int f2 = (flags & kDNSServiceFlagsUnique) != 0;
1058*4904Srs200217 if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
1059*4904Srs200217
1060*4904Srs200217 if (!sdRef || sdRef->op != connection || sdRef->sockfd < 0)
1061*4904Srs200217 return kDNSServiceErr_BadReference;
1062*4904Srs200217 *RecordRef = NULL;
1063*4904Srs200217
1064*4904Srs200217 len = sizeof(DNSServiceFlags);
1065*4904Srs200217 len += 2 * sizeof(uint32_t); // interfaceIndex, ttl
1066*4904Srs200217 len += 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen
1067*4904Srs200217 len += strlen(fullname) + 1;
1068*4904Srs200217 len += rdlen;
1069*4904Srs200217
1070*4904Srs200217 hdr = create_hdr(reg_record_request, &len, &ptr, 0);
1071*4904Srs200217 if (!hdr) goto error;
1072*4904Srs200217 msg = (char *)hdr;
1073*4904Srs200217 put_flags(flags, &ptr);
1074*4904Srs200217 put_long(interfaceIndex, &ptr);
1075*4904Srs200217 put_string(fullname, &ptr);
1076*4904Srs200217 put_short(rrtype, &ptr);
1077*4904Srs200217 put_short(rrclass, &ptr);
1078*4904Srs200217 put_short(rdlen, &ptr);
1079*4904Srs200217 put_rdata(rdlen, rdata, &ptr);
1080*4904Srs200217 put_long(ttl, &ptr);
1081*4904Srs200217
1082*4904Srs200217 rref = malloc(sizeof(_DNSRecordRef_t));
1083*4904Srs200217 if (!rref) goto error;
1084*4904Srs200217 rref->app_context = context;
1085*4904Srs200217 rref->app_callback = callBack;
1086*4904Srs200217 rref->record_index = sdRef->max_index++;
1087*4904Srs200217 rref->sdr = sdRef;
1088*4904Srs200217 *RecordRef = rref;
1089*4904Srs200217 hdr->client_context.context = rref;
1090*4904Srs200217 hdr->reg_index = rref->record_index;
1091*4904Srs200217
1092*4904Srs200217 return deliver_request(msg, sdRef, 0);
1093*4904Srs200217
1094*4904Srs200217 error:
1095*4904Srs200217 if (rref) free(rref);
1096*4904Srs200217 if (tmp) free(tmp);
1097*4904Srs200217 if (hdr) free(hdr);
1098*4904Srs200217 return kDNSServiceErr_Unknown;
1099*4904Srs200217 }
1100*4904Srs200217
1101*4904Srs200217 //sdRef returned by DNSServiceRegister()
DNSServiceAddRecord(DNSServiceRef sdRef,DNSRecordRef * RecordRef,DNSServiceFlags flags,uint16_t rrtype,uint16_t rdlen,const void * rdata,uint32_t ttl)1102*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceAddRecord
1103*4904Srs200217 (
1104*4904Srs200217 DNSServiceRef sdRef,
1105*4904Srs200217 DNSRecordRef *RecordRef,
1106*4904Srs200217 DNSServiceFlags flags,
1107*4904Srs200217 uint16_t rrtype,
1108*4904Srs200217 uint16_t rdlen,
1109*4904Srs200217 const void *rdata,
1110*4904Srs200217 uint32_t ttl
1111*4904Srs200217 )
1112*4904Srs200217 {
1113*4904Srs200217 ipc_msg_hdr *hdr;
1114*4904Srs200217 size_t len = 0;
1115*4904Srs200217 char *ptr;
1116*4904Srs200217 DNSRecordRef rref;
1117*4904Srs200217
1118*4904Srs200217 if (!sdRef || (sdRef->op != reg_service_request) || !RecordRef)
1119*4904Srs200217 return kDNSServiceErr_BadReference;
1120*4904Srs200217 *RecordRef = NULL;
1121*4904Srs200217
1122*4904Srs200217 len += 2 * sizeof(uint16_t); //rrtype, rdlen
1123*4904Srs200217 len += rdlen;
1124*4904Srs200217 len += sizeof(uint32_t);
1125*4904Srs200217 len += sizeof(DNSServiceFlags);
1126*4904Srs200217
1127*4904Srs200217 hdr = create_hdr(add_record_request, &len, &ptr, 0);
1128*4904Srs200217 if (!hdr) return kDNSServiceErr_Unknown;
1129*4904Srs200217 put_flags(flags, &ptr);
1130*4904Srs200217 put_short(rrtype, &ptr);
1131*4904Srs200217 put_short(rdlen, &ptr);
1132*4904Srs200217 put_rdata(rdlen, rdata, &ptr);
1133*4904Srs200217 put_long(ttl, &ptr);
1134*4904Srs200217
1135*4904Srs200217 rref = malloc(sizeof(_DNSRecordRef_t));
1136*4904Srs200217 if (!rref) goto error;
1137*4904Srs200217 rref->app_context = NULL;
1138*4904Srs200217 rref->app_callback = NULL;
1139*4904Srs200217 rref->record_index = sdRef->max_index++;
1140*4904Srs200217 rref->sdr = sdRef;
1141*4904Srs200217 *RecordRef = rref;
1142*4904Srs200217 hdr->client_context.context = rref;
1143*4904Srs200217 hdr->reg_index = rref->record_index;
1144*4904Srs200217 return deliver_request((char *)hdr, sdRef, 0);
1145*4904Srs200217
1146*4904Srs200217 error:
1147*4904Srs200217 if (hdr) free(hdr);
1148*4904Srs200217 if (rref) free(rref);
1149*4904Srs200217 if (*RecordRef) *RecordRef = NULL;
1150*4904Srs200217 return kDNSServiceErr_Unknown;
1151*4904Srs200217 }
1152*4904Srs200217
1153*4904Srs200217 //DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord
DNSServiceUpdateRecord(DNSServiceRef sdRef,DNSRecordRef RecordRef,DNSServiceFlags flags,uint16_t rdlen,const void * rdata,uint32_t ttl)1154*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
1155*4904Srs200217 (
1156*4904Srs200217 DNSServiceRef sdRef,
1157*4904Srs200217 DNSRecordRef RecordRef,
1158*4904Srs200217 DNSServiceFlags flags,
1159*4904Srs200217 uint16_t rdlen,
1160*4904Srs200217 const void *rdata,
1161*4904Srs200217 uint32_t ttl
1162*4904Srs200217 )
1163*4904Srs200217 {
1164*4904Srs200217 ipc_msg_hdr *hdr;
1165*4904Srs200217 size_t len = 0;
1166*4904Srs200217 char *ptr;
1167*4904Srs200217
1168*4904Srs200217 if (!sdRef) return kDNSServiceErr_BadReference;
1169*4904Srs200217
1170*4904Srs200217 len += sizeof(uint16_t);
1171*4904Srs200217 len += rdlen;
1172*4904Srs200217 len += sizeof(uint32_t);
1173*4904Srs200217 len += sizeof(DNSServiceFlags);
1174*4904Srs200217
1175*4904Srs200217 hdr = create_hdr(update_record_request, &len, &ptr, 0);
1176*4904Srs200217 if (!hdr) return kDNSServiceErr_Unknown;
1177*4904Srs200217 hdr->reg_index = RecordRef ? RecordRef->record_index : TXT_RECORD_INDEX;
1178*4904Srs200217 put_flags(flags, &ptr);
1179*4904Srs200217 put_short(rdlen, &ptr);
1180*4904Srs200217 put_rdata(rdlen, rdata, &ptr);
1181*4904Srs200217 put_long(ttl, &ptr);
1182*4904Srs200217 return deliver_request((char *)hdr, sdRef, 0);
1183*4904Srs200217 }
1184*4904Srs200217
DNSServiceRemoveRecord(DNSServiceRef sdRef,DNSRecordRef RecordRef,DNSServiceFlags flags)1185*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
1186*4904Srs200217 (
1187*4904Srs200217 DNSServiceRef sdRef,
1188*4904Srs200217 DNSRecordRef RecordRef,
1189*4904Srs200217 DNSServiceFlags flags
1190*4904Srs200217 )
1191*4904Srs200217 {
1192*4904Srs200217 ipc_msg_hdr *hdr;
1193*4904Srs200217 size_t len = 0;
1194*4904Srs200217 char *ptr;
1195*4904Srs200217 DNSServiceErrorType err;
1196*4904Srs200217
1197*4904Srs200217 if (!sdRef || !RecordRef || !sdRef->max_index)
1198*4904Srs200217 return kDNSServiceErr_BadReference;
1199*4904Srs200217
1200*4904Srs200217 len += sizeof(flags);
1201*4904Srs200217 hdr = create_hdr(remove_record_request, &len, &ptr, 0);
1202*4904Srs200217 if (!hdr) return kDNSServiceErr_Unknown;
1203*4904Srs200217 hdr->reg_index = RecordRef->record_index;
1204*4904Srs200217 put_flags(flags, &ptr);
1205*4904Srs200217 err = deliver_request((char *)hdr, sdRef, 0);
1206*4904Srs200217 if (!err) free(RecordRef);
1207*4904Srs200217 return err;
1208*4904Srs200217 }
1209*4904Srs200217
DNSServiceReconfirmRecord(DNSServiceFlags flags,uint32_t interfaceIndex,const char * fullname,uint16_t rrtype,uint16_t rrclass,uint16_t rdlen,const void * rdata)1210*4904Srs200217 DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
1211*4904Srs200217 (
1212*4904Srs200217 DNSServiceFlags flags,
1213*4904Srs200217 uint32_t interfaceIndex,
1214*4904Srs200217 const char *fullname,
1215*4904Srs200217 uint16_t rrtype,
1216*4904Srs200217 uint16_t rrclass,
1217*4904Srs200217 uint16_t rdlen,
1218*4904Srs200217 const void *rdata
1219*4904Srs200217 )
1220*4904Srs200217 {
1221*4904Srs200217 char *ptr;
1222*4904Srs200217 size_t len;
1223*4904Srs200217 ipc_msg_hdr *hdr;
1224*4904Srs200217 DNSServiceRef tmp;
1225*4904Srs200217
1226*4904Srs200217 len = sizeof(DNSServiceFlags);
1227*4904Srs200217 len += sizeof(uint32_t);
1228*4904Srs200217 len += strlen(fullname) + 1;
1229*4904Srs200217 len += 3 * sizeof(uint16_t);
1230*4904Srs200217 len += rdlen;
1231*4904Srs200217 tmp = connect_to_server();
1232*4904Srs200217 if (!tmp) return(kDNSServiceErr_Unknown);
1233*4904Srs200217 hdr = create_hdr(reconfirm_record_request, &len, &ptr, 1);
1234*4904Srs200217 if (!hdr) return(kDNSServiceErr_Unknown);
1235*4904Srs200217
1236*4904Srs200217 put_flags(flags, &ptr);
1237*4904Srs200217 put_long(interfaceIndex, &ptr);
1238*4904Srs200217 put_string(fullname, &ptr);
1239*4904Srs200217 put_short(rrtype, &ptr);
1240*4904Srs200217 put_short(rrclass, &ptr);
1241*4904Srs200217 put_short(rdlen, &ptr);
1242*4904Srs200217 put_rdata(rdlen, rdata, &ptr);
1243*4904Srs200217 ConvertHeaderBytes(hdr);
1244*4904Srs200217 write_all(tmp->sockfd, (char *)hdr, (int) len);
1245*4904Srs200217 free(hdr);
1246*4904Srs200217 DNSServiceRefDeallocate(tmp);
1247*4904Srs200217 return(kDNSServiceErr_NoError);
1248*4904Srs200217 }
1249*4904Srs200217
1250