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