1*48a54d36SAndroid Build Coastguard Worker /* -*- Mode: C; tab-width: 4 -*-
2*48a54d36SAndroid Build Coastguard Worker *
3*48a54d36SAndroid Build Coastguard Worker * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
4*48a54d36SAndroid Build Coastguard Worker *
5*48a54d36SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
6*48a54d36SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
7*48a54d36SAndroid Build Coastguard Worker *
8*48a54d36SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright notice,
9*48a54d36SAndroid Build Coastguard Worker * this list of conditions and the following disclaimer.
10*48a54d36SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright notice,
11*48a54d36SAndroid Build Coastguard Worker * this list of conditions and the following disclaimer in the documentation
12*48a54d36SAndroid Build Coastguard Worker * and/or other materials provided with the distribution.
13*48a54d36SAndroid Build Coastguard Worker * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
14*48a54d36SAndroid Build Coastguard Worker * contributors may be used to endorse or promote products derived from this
15*48a54d36SAndroid Build Coastguard Worker * software without specific prior written permission.
16*48a54d36SAndroid Build Coastguard Worker *
17*48a54d36SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18*48a54d36SAndroid Build Coastguard Worker * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19*48a54d36SAndroid Build Coastguard Worker * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20*48a54d36SAndroid Build Coastguard Worker * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21*48a54d36SAndroid Build Coastguard Worker * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22*48a54d36SAndroid Build Coastguard Worker * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23*48a54d36SAndroid Build Coastguard Worker * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24*48a54d36SAndroid Build Coastguard Worker * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25*48a54d36SAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26*48a54d36SAndroid Build Coastguard Worker * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*48a54d36SAndroid Build Coastguard Worker */
28*48a54d36SAndroid Build Coastguard Worker
29*48a54d36SAndroid Build Coastguard Worker #include <errno.h>
30*48a54d36SAndroid Build Coastguard Worker #include <stdlib.h>
31*48a54d36SAndroid Build Coastguard Worker
32*48a54d36SAndroid Build Coastguard Worker #include "dnssd_ipc.h"
33*48a54d36SAndroid Build Coastguard Worker
34*48a54d36SAndroid Build Coastguard Worker static int gDaemonErr = kDNSServiceErr_NoError;
35*48a54d36SAndroid Build Coastguard Worker
36*48a54d36SAndroid Build Coastguard Worker #if defined(_WIN32)
37*48a54d36SAndroid Build Coastguard Worker
38*48a54d36SAndroid Build Coastguard Worker #define _SSIZE_T
39*48a54d36SAndroid Build Coastguard Worker #include <CommonServices.h>
40*48a54d36SAndroid Build Coastguard Worker #include <DebugServices.h>
41*48a54d36SAndroid Build Coastguard Worker #include <winsock2.h>
42*48a54d36SAndroid Build Coastguard Worker #include <ws2tcpip.h>
43*48a54d36SAndroid Build Coastguard Worker #include <windows.h>
44*48a54d36SAndroid Build Coastguard Worker #include <stdarg.h>
45*48a54d36SAndroid Build Coastguard Worker
46*48a54d36SAndroid Build Coastguard Worker #define sockaddr_mdns sockaddr_in
47*48a54d36SAndroid Build Coastguard Worker #define AF_MDNS AF_INET
48*48a54d36SAndroid Build Coastguard Worker
49*48a54d36SAndroid Build Coastguard Worker // Disable warning: "'type cast' : from data pointer 'void *' to function pointer"
50*48a54d36SAndroid Build Coastguard Worker #pragma warning(disable:4055)
51*48a54d36SAndroid Build Coastguard Worker
52*48a54d36SAndroid Build Coastguard Worker // Disable warning: "nonstandard extension, function/data pointer conversion in expression"
53*48a54d36SAndroid Build Coastguard Worker #pragma warning(disable:4152)
54*48a54d36SAndroid Build Coastguard Worker
55*48a54d36SAndroid Build Coastguard Worker extern BOOL IsSystemServiceDisabled();
56*48a54d36SAndroid Build Coastguard Worker
57*48a54d36SAndroid Build Coastguard Worker #define sleep(X) Sleep((X) * 1000)
58*48a54d36SAndroid Build Coastguard Worker
59*48a54d36SAndroid Build Coastguard Worker static int g_initWinsock = 0;
60*48a54d36SAndroid Build Coastguard Worker #define LOG_WARNING kDebugLevelWarning
61*48a54d36SAndroid Build Coastguard Worker #define LOG_INFO kDebugLevelInfo
syslog(int priority,const char * message,...)62*48a54d36SAndroid Build Coastguard Worker static void syslog( int priority, const char * message, ...)
63*48a54d36SAndroid Build Coastguard Worker {
64*48a54d36SAndroid Build Coastguard Worker va_list args;
65*48a54d36SAndroid Build Coastguard Worker int len;
66*48a54d36SAndroid Build Coastguard Worker char * buffer;
67*48a54d36SAndroid Build Coastguard Worker DWORD err = WSAGetLastError();
68*48a54d36SAndroid Build Coastguard Worker (void) priority;
69*48a54d36SAndroid Build Coastguard Worker va_start( args, message );
70*48a54d36SAndroid Build Coastguard Worker len = _vscprintf( message, args ) + 1;
71*48a54d36SAndroid Build Coastguard Worker buffer = malloc( len * sizeof(char) );
72*48a54d36SAndroid Build Coastguard Worker if ( buffer ) { vsprintf( buffer, message, args ); OutputDebugString( buffer ); free( buffer ); }
73*48a54d36SAndroid Build Coastguard Worker WSASetLastError( err );
74*48a54d36SAndroid Build Coastguard Worker }
75*48a54d36SAndroid Build Coastguard Worker #else
76*48a54d36SAndroid Build Coastguard Worker
77*48a54d36SAndroid Build Coastguard Worker #ifndef __ANDROID__
78*48a54d36SAndroid Build Coastguard Worker #include <fcntl.h> // For O_RDWR etc.
79*48a54d36SAndroid Build Coastguard Worker #else
80*48a54d36SAndroid Build Coastguard Worker #include <fcntl.h>
81*48a54d36SAndroid Build Coastguard Worker #define LOG_TAG "libmdns"
82*48a54d36SAndroid Build Coastguard Worker #endif // !__ANDROID__
83*48a54d36SAndroid Build Coastguard Worker #include <sys/time.h>
84*48a54d36SAndroid Build Coastguard Worker #include <sys/socket.h>
85*48a54d36SAndroid Build Coastguard Worker #include <syslog.h>
86*48a54d36SAndroid Build Coastguard Worker
87*48a54d36SAndroid Build Coastguard Worker #define sockaddr_mdns sockaddr_un
88*48a54d36SAndroid Build Coastguard Worker #define AF_MDNS AF_LOCAL
89*48a54d36SAndroid Build Coastguard Worker
90*48a54d36SAndroid Build Coastguard Worker #endif
91*48a54d36SAndroid Build Coastguard Worker
92*48a54d36SAndroid Build Coastguard Worker // <rdar://problem/4096913> Specifies how many times we'll try and connect to the server.
93*48a54d36SAndroid Build Coastguard Worker
94*48a54d36SAndroid Build Coastguard Worker #define DNSSD_CLIENT_MAXTRIES 4
95*48a54d36SAndroid Build Coastguard Worker
96*48a54d36SAndroid Build Coastguard Worker // Uncomment the line below to use the old error return mechanism of creating a temporary named socket (e.g. in /var/tmp)
97*48a54d36SAndroid Build Coastguard Worker //#define USE_NAMED_ERROR_RETURN_SOCKET 1
98*48a54d36SAndroid Build Coastguard Worker
99*48a54d36SAndroid Build Coastguard Worker #define DNSSD_CLIENT_TIMEOUT 10 // In seconds
100*48a54d36SAndroid Build Coastguard Worker
101*48a54d36SAndroid Build Coastguard Worker #ifndef CTL_PATH_PREFIX
102*48a54d36SAndroid Build Coastguard Worker #define CTL_PATH_PREFIX "/var/tmp/dnssd_result_socket."
103*48a54d36SAndroid Build Coastguard Worker #endif
104*48a54d36SAndroid Build Coastguard Worker
105*48a54d36SAndroid Build Coastguard Worker typedef struct
106*48a54d36SAndroid Build Coastguard Worker {
107*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr ipc_hdr;
108*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags cb_flags;
109*48a54d36SAndroid Build Coastguard Worker uint32_t cb_interface;
110*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType cb_err;
111*48a54d36SAndroid Build Coastguard Worker } CallbackHeader;
112*48a54d36SAndroid Build Coastguard Worker
113*48a54d36SAndroid Build Coastguard Worker typedef struct _DNSServiceRef_t DNSServiceOp;
114*48a54d36SAndroid Build Coastguard Worker typedef struct _DNSRecordRef_t DNSRecord;
115*48a54d36SAndroid Build Coastguard Worker
116*48a54d36SAndroid Build Coastguard Worker // client stub callback to process message from server and deliver results to client application
117*48a54d36SAndroid Build Coastguard Worker typedef void (*ProcessReplyFn)(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *msg, const char *const end);
118*48a54d36SAndroid Build Coastguard Worker
119*48a54d36SAndroid Build Coastguard Worker #define ValidatorBits 0x12345678
120*48a54d36SAndroid Build Coastguard Worker #define DNSServiceRefValid(X) (dnssd_SocketValid((X)->sockfd) && (((X)->sockfd ^ (X)->validator) == ValidatorBits))
121*48a54d36SAndroid Build Coastguard Worker
122*48a54d36SAndroid Build Coastguard Worker // When using kDNSServiceFlagsShareConnection, there is one primary _DNSServiceOp_t, and zero or more subordinates
123*48a54d36SAndroid Build Coastguard Worker // For the primary, the 'next' field points to the first subordinate, and its 'next' field points to the next, and so on.
124*48a54d36SAndroid Build Coastguard Worker // For the primary, the 'primary' field is NULL; for subordinates the 'primary' field points back to the associated primary
125*48a54d36SAndroid Build Coastguard Worker //
126*48a54d36SAndroid Build Coastguard Worker // _DNS_SD_LIBDISPATCH is defined where libdispatch/GCD is available. This does not mean that the application will use the
127*48a54d36SAndroid Build Coastguard Worker // DNSServiceSetDispatchQueue API. Hence any new code guarded with _DNS_SD_LIBDISPATCH should still be backwards compatible.
128*48a54d36SAndroid Build Coastguard Worker struct _DNSServiceRef_t
129*48a54d36SAndroid Build Coastguard Worker {
130*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *next; // For shared connection
131*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *primary; // For shared connection
132*48a54d36SAndroid Build Coastguard Worker dnssd_sock_t sockfd; // Connected socket between client and daemon
133*48a54d36SAndroid Build Coastguard Worker dnssd_sock_t validator; // Used to detect memory corruption, double disposals, etc.
134*48a54d36SAndroid Build Coastguard Worker client_context_t uid; // For shared connection requests, each subordinate DNSServiceRef has its own ID,
135*48a54d36SAndroid Build Coastguard Worker // unique within the scope of the same shared parent DNSServiceRef
136*48a54d36SAndroid Build Coastguard Worker uint32_t op; // request_op_t or reply_op_t
137*48a54d36SAndroid Build Coastguard Worker uint32_t max_index; // Largest assigned record index - 0 if no additional records registered
138*48a54d36SAndroid Build Coastguard Worker uint32_t logcounter; // Counter used to control number of syslog messages we write
139*48a54d36SAndroid Build Coastguard Worker int *moreptr; // Set while DNSServiceProcessResult working on this particular DNSServiceRef
140*48a54d36SAndroid Build Coastguard Worker ProcessReplyFn ProcessReply; // Function pointer to the code to handle received messages
141*48a54d36SAndroid Build Coastguard Worker void *AppCallback; // Client callback function and context
142*48a54d36SAndroid Build Coastguard Worker void *AppContext;
143*48a54d36SAndroid Build Coastguard Worker DNSRecord *rec;
144*48a54d36SAndroid Build Coastguard Worker #if _DNS_SD_LIBDISPATCH
145*48a54d36SAndroid Build Coastguard Worker dispatch_source_t disp_source;
146*48a54d36SAndroid Build Coastguard Worker dispatch_queue_t disp_queue;
147*48a54d36SAndroid Build Coastguard Worker #endif
148*48a54d36SAndroid Build Coastguard Worker };
149*48a54d36SAndroid Build Coastguard Worker
150*48a54d36SAndroid Build Coastguard Worker struct _DNSRecordRef_t
151*48a54d36SAndroid Build Coastguard Worker {
152*48a54d36SAndroid Build Coastguard Worker DNSRecord *recnext;
153*48a54d36SAndroid Build Coastguard Worker void *AppContext;
154*48a54d36SAndroid Build Coastguard Worker DNSServiceRegisterRecordReply AppCallback;
155*48a54d36SAndroid Build Coastguard Worker DNSRecordRef recref;
156*48a54d36SAndroid Build Coastguard Worker uint32_t record_index; // index is unique to the ServiceDiscoveryRef
157*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *sdr;
158*48a54d36SAndroid Build Coastguard Worker };
159*48a54d36SAndroid Build Coastguard Worker
160*48a54d36SAndroid Build Coastguard Worker // Write len bytes. Return 0 on success, -1 on error
write_all(dnssd_sock_t sd,char * buf,size_t len)161*48a54d36SAndroid Build Coastguard Worker static int write_all(dnssd_sock_t sd, char *buf, size_t len)
162*48a54d36SAndroid Build Coastguard Worker {
163*48a54d36SAndroid Build Coastguard Worker // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
164*48a54d36SAndroid Build Coastguard Worker //if (send(sd, buf, len, MSG_WAITALL) != len) return -1;
165*48a54d36SAndroid Build Coastguard Worker while (len)
166*48a54d36SAndroid Build Coastguard Worker {
167*48a54d36SAndroid Build Coastguard Worker ssize_t num_written = send(sd, buf, (long)len, 0);
168*48a54d36SAndroid Build Coastguard Worker if (num_written < 0 || (size_t)num_written > len)
169*48a54d36SAndroid Build Coastguard Worker {
170*48a54d36SAndroid Build Coastguard Worker // Should never happen. If it does, it indicates some OS bug,
171*48a54d36SAndroid Build Coastguard Worker // or that the mDNSResponder daemon crashed (which should never happen).
172*48a54d36SAndroid Build Coastguard Worker #if !defined(__ppc__) && defined(SO_ISDEFUNCT)
173*48a54d36SAndroid Build Coastguard Worker int defunct;
174*48a54d36SAndroid Build Coastguard Worker socklen_t dlen = sizeof (defunct);
175*48a54d36SAndroid Build Coastguard Worker if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0)
176*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub write_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
177*48a54d36SAndroid Build Coastguard Worker if (!defunct)
178*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
179*48a54d36SAndroid Build Coastguard Worker (long)num_written, (long)len,
180*48a54d36SAndroid Build Coastguard Worker (num_written < 0) ? dnssd_errno : 0,
181*48a54d36SAndroid Build Coastguard Worker (num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
182*48a54d36SAndroid Build Coastguard Worker else
183*48a54d36SAndroid Build Coastguard Worker syslog(LOG_INFO, "dnssd_clientstub write_all(%d) DEFUNCT", sd);
184*48a54d36SAndroid Build Coastguard Worker #else
185*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
186*48a54d36SAndroid Build Coastguard Worker (long)num_written, (long)len,
187*48a54d36SAndroid Build Coastguard Worker (num_written < 0) ? dnssd_errno : 0,
188*48a54d36SAndroid Build Coastguard Worker (num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
189*48a54d36SAndroid Build Coastguard Worker #endif
190*48a54d36SAndroid Build Coastguard Worker return -1;
191*48a54d36SAndroid Build Coastguard Worker }
192*48a54d36SAndroid Build Coastguard Worker buf += num_written;
193*48a54d36SAndroid Build Coastguard Worker len -= num_written;
194*48a54d36SAndroid Build Coastguard Worker }
195*48a54d36SAndroid Build Coastguard Worker return 0;
196*48a54d36SAndroid Build Coastguard Worker }
197*48a54d36SAndroid Build Coastguard Worker
198*48a54d36SAndroid Build Coastguard Worker enum { read_all_success = 0, read_all_fail = -1, read_all_wouldblock = -2 };
199*48a54d36SAndroid Build Coastguard Worker
200*48a54d36SAndroid Build Coastguard Worker // Read len bytes. Return 0 on success, read_all_fail on error, or read_all_wouldblock for
read_all(dnssd_sock_t sd,char * buf,int len)201*48a54d36SAndroid Build Coastguard Worker static int read_all(dnssd_sock_t sd, char *buf, int len)
202*48a54d36SAndroid Build Coastguard Worker {
203*48a54d36SAndroid Build Coastguard Worker // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
204*48a54d36SAndroid Build Coastguard Worker //if (recv(sd, buf, len, MSG_WAITALL) != len) return -1;
205*48a54d36SAndroid Build Coastguard Worker
206*48a54d36SAndroid Build Coastguard Worker while (len)
207*48a54d36SAndroid Build Coastguard Worker {
208*48a54d36SAndroid Build Coastguard Worker ssize_t num_read = recv(sd, buf, len, 0);
209*48a54d36SAndroid Build Coastguard Worker // It is valid to get an interrupted system call error e.g., somebody attaching
210*48a54d36SAndroid Build Coastguard Worker // in a debugger, retry without failing
211*48a54d36SAndroid Build Coastguard Worker if ((num_read < 0) && (errno == EINTR)) { syslog(LOG_INFO, "dnssd_clientstub read_all: EINTR continue"); continue; }
212*48a54d36SAndroid Build Coastguard Worker if ((num_read == 0) || (num_read < 0) || (num_read > len))
213*48a54d36SAndroid Build Coastguard Worker {
214*48a54d36SAndroid Build Coastguard Worker int printWarn = 0;
215*48a54d36SAndroid Build Coastguard Worker int defunct = 0;
216*48a54d36SAndroid Build Coastguard Worker // Should never happen. If it does, it indicates some OS bug,
217*48a54d36SAndroid Build Coastguard Worker // or that the mDNSResponder daemon crashed (which should never happen).
218*48a54d36SAndroid Build Coastguard Worker #if defined(WIN32)
219*48a54d36SAndroid Build Coastguard Worker // <rdar://problem/7481776> Suppress logs for "A non-blocking socket operation
220*48a54d36SAndroid Build Coastguard Worker // could not be completed immediately"
221*48a54d36SAndroid Build Coastguard Worker if (WSAGetLastError() != WSAEWOULDBLOCK)
222*48a54d36SAndroid Build Coastguard Worker printWarn = 1;
223*48a54d36SAndroid Build Coastguard Worker #endif
224*48a54d36SAndroid Build Coastguard Worker #if !defined(__ppc__) && defined(SO_ISDEFUNCT)
225*48a54d36SAndroid Build Coastguard Worker {
226*48a54d36SAndroid Build Coastguard Worker socklen_t dlen = sizeof (defunct);
227*48a54d36SAndroid Build Coastguard Worker if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0)
228*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub read_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
229*48a54d36SAndroid Build Coastguard Worker }
230*48a54d36SAndroid Build Coastguard Worker if (!defunct)
231*48a54d36SAndroid Build Coastguard Worker printWarn = 1;
232*48a54d36SAndroid Build Coastguard Worker #endif
233*48a54d36SAndroid Build Coastguard Worker if (printWarn)
234*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub read_all(%d) failed %ld/%ld %d %s", sd,
235*48a54d36SAndroid Build Coastguard Worker (long)num_read, (long)len,
236*48a54d36SAndroid Build Coastguard Worker (num_read < 0) ? dnssd_errno : 0,
237*48a54d36SAndroid Build Coastguard Worker (num_read < 0) ? dnssd_strerror(dnssd_errno) : "");
238*48a54d36SAndroid Build Coastguard Worker else if (defunct)
239*48a54d36SAndroid Build Coastguard Worker syslog(LOG_INFO, "dnssd_clientstub read_all(%d) DEFUNCT", sd);
240*48a54d36SAndroid Build Coastguard Worker return (num_read < 0 && dnssd_errno == dnssd_EWOULDBLOCK) ? read_all_wouldblock : read_all_fail;
241*48a54d36SAndroid Build Coastguard Worker }
242*48a54d36SAndroid Build Coastguard Worker buf += num_read;
243*48a54d36SAndroid Build Coastguard Worker len -= num_read;
244*48a54d36SAndroid Build Coastguard Worker }
245*48a54d36SAndroid Build Coastguard Worker return read_all_success;
246*48a54d36SAndroid Build Coastguard Worker }
247*48a54d36SAndroid Build Coastguard Worker
248*48a54d36SAndroid Build Coastguard Worker // Returns 1 if more bytes remain to be read on socket descriptor sd, 0 otherwise
more_bytes(dnssd_sock_t sd)249*48a54d36SAndroid Build Coastguard Worker static int more_bytes(dnssd_sock_t sd)
250*48a54d36SAndroid Build Coastguard Worker {
251*48a54d36SAndroid Build Coastguard Worker struct timeval tv = { 0, 0 };
252*48a54d36SAndroid Build Coastguard Worker fd_set readfds;
253*48a54d36SAndroid Build Coastguard Worker fd_set *fs;
254*48a54d36SAndroid Build Coastguard Worker int ret;
255*48a54d36SAndroid Build Coastguard Worker
256*48a54d36SAndroid Build Coastguard Worker if (sd < FD_SETSIZE)
257*48a54d36SAndroid Build Coastguard Worker {
258*48a54d36SAndroid Build Coastguard Worker fs = &readfds;
259*48a54d36SAndroid Build Coastguard Worker FD_ZERO(fs);
260*48a54d36SAndroid Build Coastguard Worker }
261*48a54d36SAndroid Build Coastguard Worker else
262*48a54d36SAndroid Build Coastguard Worker {
263*48a54d36SAndroid Build Coastguard Worker // Compute the number of longs needed for storing "sd". Internally fd_set is stored
264*48a54d36SAndroid Build Coastguard Worker // as an array of longs with one bit for each fd and hence we need to compute
265*48a54d36SAndroid Build Coastguard Worker // the number of longs needed rather than the number of bytes. If "sd" is 64, we need
266*48a54d36SAndroid Build Coastguard Worker // two longs and not just one.
267*48a54d36SAndroid Build Coastguard Worker int nfdbits = sizeof (unsigned long) * 8;
268*48a54d36SAndroid Build Coastguard Worker int nlongs = (sd/nfdbits) + 1;
269*48a54d36SAndroid Build Coastguard Worker fs = (fd_set *)calloc(nlongs, sizeof(unsigned long));
270*48a54d36SAndroid Build Coastguard Worker if (fs == NULL) { syslog(LOG_WARNING, "dnssd_clientstub more_bytes: malloc failed"); return 0; }
271*48a54d36SAndroid Build Coastguard Worker }
272*48a54d36SAndroid Build Coastguard Worker
273*48a54d36SAndroid Build Coastguard Worker #ifdef __BIONIC__
274*48a54d36SAndroid Build Coastguard Worker // The regular FD_SET() macro in Bionic is unaware of the above workaround,
275*48a54d36SAndroid Build Coastguard Worker // and would abort on sd >= 1024. Use the unchecked __FD_SET() instead.
276*48a54d36SAndroid Build Coastguard Worker __FD_SET(sd, fs);
277*48a54d36SAndroid Build Coastguard Worker #else
278*48a54d36SAndroid Build Coastguard Worker FD_SET(sd, fs);
279*48a54d36SAndroid Build Coastguard Worker #endif
280*48a54d36SAndroid Build Coastguard Worker ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv);
281*48a54d36SAndroid Build Coastguard Worker if (fs != &readfds) free(fs);
282*48a54d36SAndroid Build Coastguard Worker return (ret > 0);
283*48a54d36SAndroid Build Coastguard Worker }
284*48a54d36SAndroid Build Coastguard Worker
285*48a54d36SAndroid Build Coastguard Worker // Wait for daemon to write to socket
wait_for_daemon(dnssd_sock_t sock,int timeout)286*48a54d36SAndroid Build Coastguard Worker static int wait_for_daemon(dnssd_sock_t sock, int timeout)
287*48a54d36SAndroid Build Coastguard Worker {
288*48a54d36SAndroid Build Coastguard Worker #ifndef WIN32
289*48a54d36SAndroid Build Coastguard Worker // At this point the next operation (accept() or read()) on this socket may block for a few milliseconds waiting
290*48a54d36SAndroid Build Coastguard Worker // for the daemon to respond, but that's okay -- the daemon is a trusted service and we know if won't take more
291*48a54d36SAndroid Build Coastguard Worker // than a few milliseconds to respond. So we'll forego checking for readability of the socket.
292*48a54d36SAndroid Build Coastguard Worker (void) sock;
293*48a54d36SAndroid Build Coastguard Worker (void) timeout;
294*48a54d36SAndroid Build Coastguard Worker #else
295*48a54d36SAndroid Build Coastguard Worker // Windows on the other hand suffers from 3rd party software (primarily 3rd party firewall software) that
296*48a54d36SAndroid Build Coastguard Worker // interferes with proper functioning of the TCP protocol stack. Because of this and because we depend on TCP
297*48a54d36SAndroid Build Coastguard Worker // to communicate with the system service, we want to make sure that the next operation on this socket (accept() or
298*48a54d36SAndroid Build Coastguard Worker // read()) doesn't block indefinitely.
299*48a54d36SAndroid Build Coastguard Worker if (!gDaemonErr)
300*48a54d36SAndroid Build Coastguard Worker {
301*48a54d36SAndroid Build Coastguard Worker struct timeval tv;
302*48a54d36SAndroid Build Coastguard Worker fd_set set;
303*48a54d36SAndroid Build Coastguard Worker
304*48a54d36SAndroid Build Coastguard Worker FD_ZERO(&set);
305*48a54d36SAndroid Build Coastguard Worker FD_SET(sock, &set);
306*48a54d36SAndroid Build Coastguard Worker tv.tv_sec = timeout;
307*48a54d36SAndroid Build Coastguard Worker tv.tv_usec = 0;
308*48a54d36SAndroid Build Coastguard Worker if (!select((int)(sock + 1), &set, NULL, NULL, &tv))
309*48a54d36SAndroid Build Coastguard Worker {
310*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub wait_for_daemon timed out");
311*48a54d36SAndroid Build Coastguard Worker gDaemonErr = kDNSServiceErr_Timeout;
312*48a54d36SAndroid Build Coastguard Worker }
313*48a54d36SAndroid Build Coastguard Worker }
314*48a54d36SAndroid Build Coastguard Worker #endif
315*48a54d36SAndroid Build Coastguard Worker return gDaemonErr;
316*48a54d36SAndroid Build Coastguard Worker }
317*48a54d36SAndroid Build Coastguard Worker
318*48a54d36SAndroid Build Coastguard Worker /* create_hdr
319*48a54d36SAndroid Build Coastguard Worker *
320*48a54d36SAndroid Build Coastguard Worker * allocate and initialize an ipc message header. Value of len should initially be the
321*48a54d36SAndroid Build Coastguard Worker * length of the data, and is set to the value of the data plus the header. data_start
322*48a54d36SAndroid Build Coastguard Worker * is set to point to the beginning of the data section. SeparateReturnSocket should be
323*48a54d36SAndroid Build Coastguard Worker * non-zero for calls that can't receive an immediate error return value on their primary
324*48a54d36SAndroid Build Coastguard Worker * socket, and therefore require a separate return path for the error code result.
325*48a54d36SAndroid Build Coastguard Worker * if zero, the path to a control socket is appended at the beginning of the message buffer.
326*48a54d36SAndroid Build Coastguard Worker * data_start is set past this string.
327*48a54d36SAndroid Build Coastguard Worker */
create_hdr(uint32_t op,size_t * len,char ** data_start,int SeparateReturnSocket,DNSServiceOp * ref)328*48a54d36SAndroid Build Coastguard Worker static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int SeparateReturnSocket, DNSServiceOp *ref)
329*48a54d36SAndroid Build Coastguard Worker {
330*48a54d36SAndroid Build Coastguard Worker char *msg = NULL;
331*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
332*48a54d36SAndroid Build Coastguard Worker int datalen;
333*48a54d36SAndroid Build Coastguard Worker #if !defined(USE_TCP_LOOPBACK)
334*48a54d36SAndroid Build Coastguard Worker char ctrl_path[64] = ""; // "/var/tmp/dnssd_result_socket.xxxxxxxxxx-xxx-xxxxxx"
335*48a54d36SAndroid Build Coastguard Worker #endif
336*48a54d36SAndroid Build Coastguard Worker
337*48a54d36SAndroid Build Coastguard Worker if (SeparateReturnSocket)
338*48a54d36SAndroid Build Coastguard Worker {
339*48a54d36SAndroid Build Coastguard Worker #if defined(USE_TCP_LOOPBACK)
340*48a54d36SAndroid Build Coastguard Worker *len += 2; // Allocate space for two-byte port number
341*48a54d36SAndroid Build Coastguard Worker #elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
342*48a54d36SAndroid Build Coastguard Worker struct timeval tv;
343*48a54d36SAndroid Build Coastguard Worker if (gettimeofday(&tv, NULL) < 0)
344*48a54d36SAndroid Build Coastguard Worker { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: gettimeofday failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); return NULL; }
345*48a54d36SAndroid Build Coastguard Worker sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(),
346*48a54d36SAndroid Build Coastguard Worker (unsigned long)(tv.tv_sec & 0xFFF), (unsigned long)(tv.tv_usec));
347*48a54d36SAndroid Build Coastguard Worker *len += strlen(ctrl_path) + 1;
348*48a54d36SAndroid Build Coastguard Worker #else
349*48a54d36SAndroid Build Coastguard Worker *len += 1; // Allocate space for single zero byte (empty C string)
350*48a54d36SAndroid Build Coastguard Worker #endif
351*48a54d36SAndroid Build Coastguard Worker }
352*48a54d36SAndroid Build Coastguard Worker
353*48a54d36SAndroid Build Coastguard Worker datalen = (int) *len;
354*48a54d36SAndroid Build Coastguard Worker *len += sizeof(ipc_msg_hdr);
355*48a54d36SAndroid Build Coastguard Worker
356*48a54d36SAndroid Build Coastguard Worker // Write message to buffer
357*48a54d36SAndroid Build Coastguard Worker msg = malloc(*len);
358*48a54d36SAndroid Build Coastguard Worker if (!msg) { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: malloc failed"); return NULL; }
359*48a54d36SAndroid Build Coastguard Worker
360*48a54d36SAndroid Build Coastguard Worker memset(msg, 0, *len);
361*48a54d36SAndroid Build Coastguard Worker hdr = (ipc_msg_hdr *)msg;
362*48a54d36SAndroid Build Coastguard Worker hdr->version = VERSION;
363*48a54d36SAndroid Build Coastguard Worker hdr->datalen = datalen;
364*48a54d36SAndroid Build Coastguard Worker hdr->ipc_flags = 0;
365*48a54d36SAndroid Build Coastguard Worker hdr->op = op;
366*48a54d36SAndroid Build Coastguard Worker hdr->client_context = ref->uid;
367*48a54d36SAndroid Build Coastguard Worker hdr->reg_index = 0;
368*48a54d36SAndroid Build Coastguard Worker *data_start = msg + sizeof(ipc_msg_hdr);
369*48a54d36SAndroid Build Coastguard Worker #if defined(USE_TCP_LOOPBACK)
370*48a54d36SAndroid Build Coastguard Worker // Put dummy data in for the port, since we don't know what it is yet.
371*48a54d36SAndroid Build Coastguard Worker // The data will get filled in before we send the message. This happens in deliver_request().
372*48a54d36SAndroid Build Coastguard Worker if (SeparateReturnSocket) put_uint16(0, data_start);
373*48a54d36SAndroid Build Coastguard Worker #else
374*48a54d36SAndroid Build Coastguard Worker if (SeparateReturnSocket) put_string(ctrl_path, data_start);
375*48a54d36SAndroid Build Coastguard Worker #endif
376*48a54d36SAndroid Build Coastguard Worker return hdr;
377*48a54d36SAndroid Build Coastguard Worker }
378*48a54d36SAndroid Build Coastguard Worker
FreeDNSRecords(DNSServiceOp * sdRef)379*48a54d36SAndroid Build Coastguard Worker static void FreeDNSRecords(DNSServiceOp *sdRef)
380*48a54d36SAndroid Build Coastguard Worker {
381*48a54d36SAndroid Build Coastguard Worker DNSRecord *rec = sdRef->rec;
382*48a54d36SAndroid Build Coastguard Worker while (rec)
383*48a54d36SAndroid Build Coastguard Worker {
384*48a54d36SAndroid Build Coastguard Worker DNSRecord *next = rec->recnext;
385*48a54d36SAndroid Build Coastguard Worker free(rec);
386*48a54d36SAndroid Build Coastguard Worker rec = next;
387*48a54d36SAndroid Build Coastguard Worker }
388*48a54d36SAndroid Build Coastguard Worker }
389*48a54d36SAndroid Build Coastguard Worker
FreeDNSServiceOp(DNSServiceOp * x)390*48a54d36SAndroid Build Coastguard Worker static void FreeDNSServiceOp(DNSServiceOp *x)
391*48a54d36SAndroid Build Coastguard Worker {
392*48a54d36SAndroid Build Coastguard Worker // We don't use our DNSServiceRefValid macro here because if we're cleaning up after a socket() call failed
393*48a54d36SAndroid Build Coastguard Worker // then sockfd could legitimately contain a failing value (e.g. dnssd_InvalidSocket)
394*48a54d36SAndroid Build Coastguard Worker if ((x->sockfd ^ x->validator) != ValidatorBits)
395*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub attempt to dispose invalid DNSServiceRef %p %08X %08X", x, x->sockfd, x->validator);
396*48a54d36SAndroid Build Coastguard Worker else
397*48a54d36SAndroid Build Coastguard Worker {
398*48a54d36SAndroid Build Coastguard Worker x->next = NULL;
399*48a54d36SAndroid Build Coastguard Worker x->primary = NULL;
400*48a54d36SAndroid Build Coastguard Worker x->sockfd = dnssd_InvalidSocket;
401*48a54d36SAndroid Build Coastguard Worker x->validator = 0xDDDDDDDD;
402*48a54d36SAndroid Build Coastguard Worker x->op = request_op_none;
403*48a54d36SAndroid Build Coastguard Worker x->max_index = 0;
404*48a54d36SAndroid Build Coastguard Worker x->logcounter = 0;
405*48a54d36SAndroid Build Coastguard Worker x->moreptr = NULL;
406*48a54d36SAndroid Build Coastguard Worker x->ProcessReply = NULL;
407*48a54d36SAndroid Build Coastguard Worker x->AppCallback = NULL;
408*48a54d36SAndroid Build Coastguard Worker x->AppContext = NULL;
409*48a54d36SAndroid Build Coastguard Worker #if _DNS_SD_LIBDISPATCH
410*48a54d36SAndroid Build Coastguard Worker if (x->disp_source) dispatch_release(x->disp_source);
411*48a54d36SAndroid Build Coastguard Worker x->disp_source = NULL;
412*48a54d36SAndroid Build Coastguard Worker x->disp_queue = NULL;
413*48a54d36SAndroid Build Coastguard Worker #endif
414*48a54d36SAndroid Build Coastguard Worker // DNSRecords may have been added to subordinate sdRef e.g., DNSServiceRegister/DNSServiceAddRecord
415*48a54d36SAndroid Build Coastguard Worker // or on the main sdRef e.g., DNSServiceCreateConnection/DNSServiveRegisterRecord. DNSRecords may have
416*48a54d36SAndroid Build Coastguard Worker // been freed if the application called DNSRemoveRecord
417*48a54d36SAndroid Build Coastguard Worker FreeDNSRecords(x);
418*48a54d36SAndroid Build Coastguard Worker free(x);
419*48a54d36SAndroid Build Coastguard Worker }
420*48a54d36SAndroid Build Coastguard Worker }
421*48a54d36SAndroid Build Coastguard Worker
422*48a54d36SAndroid Build Coastguard Worker // Return a connected service ref (deallocate with DNSServiceRefDeallocate)
ConnectToServer(DNSServiceRef * ref,DNSServiceFlags flags,uint32_t op,ProcessReplyFn ProcessReply,void * AppCallback,void * AppContext)423*48a54d36SAndroid Build Coastguard Worker static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags flags, uint32_t op, ProcessReplyFn ProcessReply, void *AppCallback, void *AppContext)
424*48a54d36SAndroid Build Coastguard Worker {
425*48a54d36SAndroid Build Coastguard Worker #if APPLE_OSX_mDNSResponder
426*48a54d36SAndroid Build Coastguard Worker int NumTries = DNSSD_CLIENT_MAXTRIES;
427*48a54d36SAndroid Build Coastguard Worker #else
428*48a54d36SAndroid Build Coastguard Worker int NumTries = 0;
429*48a54d36SAndroid Build Coastguard Worker #endif
430*48a54d36SAndroid Build Coastguard Worker
431*48a54d36SAndroid Build Coastguard Worker dnssd_sockaddr_t saddr;
432*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *sdr;
433*48a54d36SAndroid Build Coastguard Worker
434*48a54d36SAndroid Build Coastguard Worker if (!ref) { syslog(LOG_WARNING, "dnssd_clientstub DNSService operation with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
435*48a54d36SAndroid Build Coastguard Worker
436*48a54d36SAndroid Build Coastguard Worker if (flags & kDNSServiceFlagsShareConnection)
437*48a54d36SAndroid Build Coastguard Worker {
438*48a54d36SAndroid Build Coastguard Worker if (!*ref)
439*48a54d36SAndroid Build Coastguard Worker {
440*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with NULL DNSServiceRef");
441*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadParam;
442*48a54d36SAndroid Build Coastguard Worker }
443*48a54d36SAndroid Build Coastguard Worker if (!DNSServiceRefValid(*ref) || (*ref)->op != connection_request || (*ref)->primary)
444*48a54d36SAndroid Build Coastguard Worker {
445*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with invalid DNSServiceRef %p %08X %08X",
446*48a54d36SAndroid Build Coastguard Worker (*ref), (*ref)->sockfd, (*ref)->validator);
447*48a54d36SAndroid Build Coastguard Worker *ref = NULL;
448*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadReference;
449*48a54d36SAndroid Build Coastguard Worker }
450*48a54d36SAndroid Build Coastguard Worker }
451*48a54d36SAndroid Build Coastguard Worker
452*48a54d36SAndroid Build Coastguard Worker #if defined(_WIN32)
453*48a54d36SAndroid Build Coastguard Worker if (!g_initWinsock)
454*48a54d36SAndroid Build Coastguard Worker {
455*48a54d36SAndroid Build Coastguard Worker WSADATA wsaData;
456*48a54d36SAndroid Build Coastguard Worker g_initWinsock = 1;
457*48a54d36SAndroid Build Coastguard Worker if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { *ref = NULL; return kDNSServiceErr_ServiceNotRunning; }
458*48a54d36SAndroid Build Coastguard Worker }
459*48a54d36SAndroid Build Coastguard Worker // <rdar://problem/4096913> If the system service is disabled, we only want to try to connect once
460*48a54d36SAndroid Build Coastguard Worker if (IsSystemServiceDisabled()) NumTries = DNSSD_CLIENT_MAXTRIES;
461*48a54d36SAndroid Build Coastguard Worker #endif
462*48a54d36SAndroid Build Coastguard Worker
463*48a54d36SAndroid Build Coastguard Worker sdr = malloc(sizeof(DNSServiceOp));
464*48a54d36SAndroid Build Coastguard Worker if (!sdr) { syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: malloc failed"); *ref = NULL; return kDNSServiceErr_NoMemory; }
465*48a54d36SAndroid Build Coastguard Worker sdr->next = NULL;
466*48a54d36SAndroid Build Coastguard Worker sdr->primary = NULL;
467*48a54d36SAndroid Build Coastguard Worker sdr->sockfd = dnssd_InvalidSocket;
468*48a54d36SAndroid Build Coastguard Worker sdr->validator = sdr->sockfd ^ ValidatorBits;
469*48a54d36SAndroid Build Coastguard Worker sdr->op = op;
470*48a54d36SAndroid Build Coastguard Worker sdr->max_index = 0;
471*48a54d36SAndroid Build Coastguard Worker sdr->logcounter = 0;
472*48a54d36SAndroid Build Coastguard Worker sdr->moreptr = NULL;
473*48a54d36SAndroid Build Coastguard Worker sdr->uid.u32[0] = 0;
474*48a54d36SAndroid Build Coastguard Worker sdr->uid.u32[1] = 0;
475*48a54d36SAndroid Build Coastguard Worker sdr->ProcessReply = ProcessReply;
476*48a54d36SAndroid Build Coastguard Worker sdr->AppCallback = AppCallback;
477*48a54d36SAndroid Build Coastguard Worker sdr->AppContext = AppContext;
478*48a54d36SAndroid Build Coastguard Worker sdr->rec = NULL;
479*48a54d36SAndroid Build Coastguard Worker #if _DNS_SD_LIBDISPATCH
480*48a54d36SAndroid Build Coastguard Worker sdr->disp_source = NULL;
481*48a54d36SAndroid Build Coastguard Worker sdr->disp_queue = NULL;
482*48a54d36SAndroid Build Coastguard Worker #endif
483*48a54d36SAndroid Build Coastguard Worker
484*48a54d36SAndroid Build Coastguard Worker if (flags & kDNSServiceFlagsShareConnection)
485*48a54d36SAndroid Build Coastguard Worker {
486*48a54d36SAndroid Build Coastguard Worker DNSServiceOp **p = &(*ref)->next; // Append ourselves to end of primary's list
487*48a54d36SAndroid Build Coastguard Worker while (*p) p = &(*p)->next;
488*48a54d36SAndroid Build Coastguard Worker *p = sdr;
489*48a54d36SAndroid Build Coastguard Worker // Preincrement counter before we use it -- it helps with debugging if we know the all-zeroes ID should never appear
490*48a54d36SAndroid Build Coastguard Worker if (++(*ref)->uid.u32[0] == 0) ++(*ref)->uid.u32[1]; // In parent DNSServiceOp increment UID counter
491*48a54d36SAndroid Build Coastguard Worker sdr->primary = *ref; // Set our primary pointer
492*48a54d36SAndroid Build Coastguard Worker sdr->sockfd = (*ref)->sockfd; // Inherit primary's socket
493*48a54d36SAndroid Build Coastguard Worker sdr->validator = (*ref)->validator;
494*48a54d36SAndroid Build Coastguard Worker sdr->uid = (*ref)->uid;
495*48a54d36SAndroid Build Coastguard Worker //printf("ConnectToServer sharing socket %d\n", sdr->sockfd);
496*48a54d36SAndroid Build Coastguard Worker }
497*48a54d36SAndroid Build Coastguard Worker else
498*48a54d36SAndroid Build Coastguard Worker {
499*48a54d36SAndroid Build Coastguard Worker #ifdef SO_NOSIGPIPE
500*48a54d36SAndroid Build Coastguard Worker const unsigned long optval = 1;
501*48a54d36SAndroid Build Coastguard Worker #endif
502*48a54d36SAndroid Build Coastguard Worker *ref = NULL;
503*48a54d36SAndroid Build Coastguard Worker sdr->sockfd = socket(AF_DNSSD, SOCK_STREAM, 0);
504*48a54d36SAndroid Build Coastguard Worker sdr->validator = sdr->sockfd ^ ValidatorBits;
505*48a54d36SAndroid Build Coastguard Worker if (!dnssd_SocketValid(sdr->sockfd))
506*48a54d36SAndroid Build Coastguard Worker {
507*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: socket failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
508*48a54d36SAndroid Build Coastguard Worker FreeDNSServiceOp(sdr);
509*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_NoMemory;
510*48a54d36SAndroid Build Coastguard Worker }
511*48a54d36SAndroid Build Coastguard Worker #ifdef SO_NOSIGPIPE
512*48a54d36SAndroid Build Coastguard Worker // Some environments (e.g. OS X) support turning off SIGPIPE for a socket
513*48a54d36SAndroid Build Coastguard Worker if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0)
514*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_NOSIGPIPE failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
515*48a54d36SAndroid Build Coastguard Worker #endif
516*48a54d36SAndroid Build Coastguard Worker #if defined(USE_TCP_LOOPBACK)
517*48a54d36SAndroid Build Coastguard Worker saddr.sin_family = AF_INET;
518*48a54d36SAndroid Build Coastguard Worker saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
519*48a54d36SAndroid Build Coastguard Worker saddr.sin_port = htons(MDNS_TCP_SERVERPORT);
520*48a54d36SAndroid Build Coastguard Worker #else
521*48a54d36SAndroid Build Coastguard Worker saddr.sun_family = AF_LOCAL;
522*48a54d36SAndroid Build Coastguard Worker strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH);
523*48a54d36SAndroid Build Coastguard Worker #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
524*48a54d36SAndroid Build Coastguard Worker {
525*48a54d36SAndroid Build Coastguard Worker int defunct = 1;
526*48a54d36SAndroid Build Coastguard Worker if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
527*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
528*48a54d36SAndroid Build Coastguard Worker }
529*48a54d36SAndroid Build Coastguard Worker #endif
530*48a54d36SAndroid Build Coastguard Worker #endif
531*48a54d36SAndroid Build Coastguard Worker
532*48a54d36SAndroid Build Coastguard Worker while (1)
533*48a54d36SAndroid Build Coastguard Worker {
534*48a54d36SAndroid Build Coastguard Worker int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr));
535*48a54d36SAndroid Build Coastguard Worker if (!err) break; // If we succeeded, return sdr
536*48a54d36SAndroid Build Coastguard Worker // If we failed, then it may be because the daemon is still launching.
537*48a54d36SAndroid Build Coastguard Worker // This can happen for processes that launch early in the boot process, while the
538*48a54d36SAndroid Build Coastguard Worker // daemon is still coming up. Rather than fail here, we'll wait a bit and try again.
539*48a54d36SAndroid Build Coastguard Worker // If, after four seconds, we still can't connect to the daemon,
540*48a54d36SAndroid Build Coastguard Worker // then we give up and return a failure code.
541*48a54d36SAndroid Build Coastguard Worker if (++NumTries < DNSSD_CLIENT_MAXTRIES) sleep(1); // Sleep a bit, then try again
542*48a54d36SAndroid Build Coastguard Worker else { dnssd_close(sdr->sockfd); FreeDNSServiceOp(sdr); return kDNSServiceErr_ServiceNotRunning; }
543*48a54d36SAndroid Build Coastguard Worker }
544*48a54d36SAndroid Build Coastguard Worker //printf("ConnectToServer opened socket %d\n", sdr->sockfd);
545*48a54d36SAndroid Build Coastguard Worker }
546*48a54d36SAndroid Build Coastguard Worker
547*48a54d36SAndroid Build Coastguard Worker *ref = sdr;
548*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_NoError;
549*48a54d36SAndroid Build Coastguard Worker }
550*48a54d36SAndroid Build Coastguard Worker
551*48a54d36SAndroid Build Coastguard Worker #define deliver_request_bailout(MSG) \
552*48a54d36SAndroid Build Coastguard Worker do { syslog(LOG_WARNING, "dnssd_clientstub deliver_request: %s failed %d (%s)", (MSG), dnssd_errno, dnssd_strerror(dnssd_errno)); goto cleanup; } while(0)
553*48a54d36SAndroid Build Coastguard Worker
deliver_request(ipc_msg_hdr * hdr,DNSServiceOp * sdr)554*48a54d36SAndroid Build Coastguard Worker static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
555*48a54d36SAndroid Build Coastguard Worker {
556*48a54d36SAndroid Build Coastguard Worker uint32_t datalen = hdr->datalen; // We take a copy here because we're going to convert hdr->datalen to network byte order
557*48a54d36SAndroid Build Coastguard Worker #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
558*48a54d36SAndroid Build Coastguard Worker char *const data = (char *)hdr + sizeof(ipc_msg_hdr);
559*48a54d36SAndroid Build Coastguard Worker #endif
560*48a54d36SAndroid Build Coastguard Worker dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
561*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err = kDNSServiceErr_Unknown; // Default for the "goto cleanup" cases
562*48a54d36SAndroid Build Coastguard Worker int MakeSeparateReturnSocket = 0;
563*48a54d36SAndroid Build Coastguard Worker
564*48a54d36SAndroid Build Coastguard Worker // Note: need to check hdr->op, not sdr->op.
565*48a54d36SAndroid Build Coastguard Worker // hdr->op contains the code for the specific operation we're currently doing, whereas sdr->op
566*48a54d36SAndroid Build Coastguard Worker // contains the original parent DNSServiceOp (e.g. for an add_record_request, hdr->op will be
567*48a54d36SAndroid Build Coastguard Worker // add_record_request but the parent sdr->op will be connection_request or reg_service_request)
568*48a54d36SAndroid Build Coastguard Worker if (sdr->primary ||
569*48a54d36SAndroid Build Coastguard Worker hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request)
570*48a54d36SAndroid Build Coastguard Worker MakeSeparateReturnSocket = 1;
571*48a54d36SAndroid Build Coastguard Worker
572*48a54d36SAndroid Build Coastguard Worker if (!DNSServiceRefValid(sdr))
573*48a54d36SAndroid Build Coastguard Worker {
574*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub deliver_request: invalid DNSServiceRef %p %08X %08X", sdr, sdr->sockfd, sdr->validator);
575*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadReference;
576*48a54d36SAndroid Build Coastguard Worker }
577*48a54d36SAndroid Build Coastguard Worker
578*48a54d36SAndroid Build Coastguard Worker if (!hdr) { syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr"); return kDNSServiceErr_Unknown; }
579*48a54d36SAndroid Build Coastguard Worker
580*48a54d36SAndroid Build Coastguard Worker if (MakeSeparateReturnSocket)
581*48a54d36SAndroid Build Coastguard Worker {
582*48a54d36SAndroid Build Coastguard Worker #if defined(USE_TCP_LOOPBACK)
583*48a54d36SAndroid Build Coastguard Worker {
584*48a54d36SAndroid Build Coastguard Worker union { uint16_t s; u_char b[2]; } port;
585*48a54d36SAndroid Build Coastguard Worker dnssd_sockaddr_t caddr;
586*48a54d36SAndroid Build Coastguard Worker dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr);
587*48a54d36SAndroid Build Coastguard Worker listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
588*48a54d36SAndroid Build Coastguard Worker if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("TCP socket");
589*48a54d36SAndroid Build Coastguard Worker
590*48a54d36SAndroid Build Coastguard Worker caddr.sin_family = AF_INET;
591*48a54d36SAndroid Build Coastguard Worker caddr.sin_port = 0;
592*48a54d36SAndroid Build Coastguard Worker caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
593*48a54d36SAndroid Build Coastguard Worker if (bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr)) < 0) deliver_request_bailout("TCP bind");
594*48a54d36SAndroid Build Coastguard Worker if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) deliver_request_bailout("TCP getsockname");
595*48a54d36SAndroid Build Coastguard Worker if (listen(listenfd, 1) < 0) deliver_request_bailout("TCP listen");
596*48a54d36SAndroid Build Coastguard Worker port.s = caddr.sin_port;
597*48a54d36SAndroid Build Coastguard Worker data[0] = port.b[0]; // don't switch the byte order, as the
598*48a54d36SAndroid Build Coastguard Worker data[1] = port.b[1]; // daemon expects it in network byte order
599*48a54d36SAndroid Build Coastguard Worker }
600*48a54d36SAndroid Build Coastguard Worker #elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
601*48a54d36SAndroid Build Coastguard Worker {
602*48a54d36SAndroid Build Coastguard Worker mode_t mask;
603*48a54d36SAndroid Build Coastguard Worker int bindresult;
604*48a54d36SAndroid Build Coastguard Worker dnssd_sockaddr_t caddr;
605*48a54d36SAndroid Build Coastguard Worker listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
606*48a54d36SAndroid Build Coastguard Worker if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET socket");
607*48a54d36SAndroid Build Coastguard Worker
608*48a54d36SAndroid Build Coastguard Worker caddr.sun_family = AF_LOCAL;
609*48a54d36SAndroid Build Coastguard Worker // According to Stevens (section 3.2), there is no portable way to
610*48a54d36SAndroid Build Coastguard Worker // determine whether sa_len is defined on a particular platform.
611*48a54d36SAndroid Build Coastguard Worker #ifndef NOT_HAVE_SA_LEN
612*48a54d36SAndroid Build Coastguard Worker caddr.sun_len = sizeof(struct sockaddr_un);
613*48a54d36SAndroid Build Coastguard Worker #endif
614*48a54d36SAndroid Build Coastguard Worker strcpy(caddr.sun_path, data);
615*48a54d36SAndroid Build Coastguard Worker mask = umask(0);
616*48a54d36SAndroid Build Coastguard Worker bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
617*48a54d36SAndroid Build Coastguard Worker umask(mask);
618*48a54d36SAndroid Build Coastguard Worker if (bindresult < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET bind");
619*48a54d36SAndroid Build Coastguard Worker if (listen(listenfd, 1) < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET listen");
620*48a54d36SAndroid Build Coastguard Worker }
621*48a54d36SAndroid Build Coastguard Worker #else
622*48a54d36SAndroid Build Coastguard Worker {
623*48a54d36SAndroid Build Coastguard Worker dnssd_sock_t sp[2];
624*48a54d36SAndroid Build Coastguard Worker if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0) deliver_request_bailout("socketpair");
625*48a54d36SAndroid Build Coastguard Worker else
626*48a54d36SAndroid Build Coastguard Worker {
627*48a54d36SAndroid Build Coastguard Worker errsd = sp[0]; // We'll read our four-byte error code from sp[0]
628*48a54d36SAndroid Build Coastguard Worker listenfd = sp[1]; // We'll send sp[1] to the daemon
629*48a54d36SAndroid Build Coastguard Worker #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
630*48a54d36SAndroid Build Coastguard Worker {
631*48a54d36SAndroid Build Coastguard Worker int defunct = 1;
632*48a54d36SAndroid Build Coastguard Worker if (setsockopt(errsd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
633*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
634*48a54d36SAndroid Build Coastguard Worker }
635*48a54d36SAndroid Build Coastguard Worker #endif
636*48a54d36SAndroid Build Coastguard Worker }
637*48a54d36SAndroid Build Coastguard Worker }
638*48a54d36SAndroid Build Coastguard Worker #endif
639*48a54d36SAndroid Build Coastguard Worker }
640*48a54d36SAndroid Build Coastguard Worker
641*48a54d36SAndroid Build Coastguard Worker #if !defined(USE_TCP_LOOPBACK) && !defined(USE_NAMED_ERROR_RETURN_SOCKET)
642*48a54d36SAndroid Build Coastguard Worker // If we're going to make a separate error return socket, and pass it to the daemon
643*48a54d36SAndroid Build Coastguard Worker // using sendmsg, then we'll hold back one data byte to go with it.
644*48a54d36SAndroid Build Coastguard Worker // On some versions of Unix (including Leopard) sending a control message without
645*48a54d36SAndroid Build Coastguard Worker // any associated data does not work reliably -- e.g. one particular issue we ran
646*48a54d36SAndroid Build Coastguard Worker // into is that if the receiving program is in a kqueue loop waiting to be notified
647*48a54d36SAndroid Build Coastguard Worker // of the received message, it doesn't get woken up when the control message arrives.
648*48a54d36SAndroid Build Coastguard Worker if (MakeSeparateReturnSocket || sdr->op == send_bpf) datalen--; // Okay to use sdr->op when checking for op == send_bpf
649*48a54d36SAndroid Build Coastguard Worker #endif
650*48a54d36SAndroid Build Coastguard Worker
651*48a54d36SAndroid Build Coastguard Worker // At this point, our listening socket is set up and waiting, if necessary, for the daemon to connect back to
652*48a54d36SAndroid Build Coastguard Worker ConvertHeaderBytes(hdr);
653*48a54d36SAndroid Build Coastguard Worker //syslog(LOG_WARNING, "dnssd_clientstub deliver_request writing %lu bytes", (unsigned long)(datalen + sizeof(ipc_msg_hdr)));
654*48a54d36SAndroid Build Coastguard Worker //if (MakeSeparateReturnSocket) syslog(LOG_WARNING, "dnssd_clientstub deliver_request name is %s", data);
655*48a54d36SAndroid Build Coastguard Worker #if TEST_SENDING_ONE_BYTE_AT_A_TIME
656*48a54d36SAndroid Build Coastguard Worker unsigned int i;
657*48a54d36SAndroid Build Coastguard Worker for (i=0; i<datalen + sizeof(ipc_msg_hdr); i++)
658*48a54d36SAndroid Build Coastguard Worker {
659*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub deliver_request writing %d", i);
660*48a54d36SAndroid Build Coastguard Worker if (write_all(sdr->sockfd, ((char *)hdr)+i, 1) < 0)
661*48a54d36SAndroid Build Coastguard Worker { syslog(LOG_WARNING, "write_all (byte %u) failed", i); goto cleanup; }
662*48a54d36SAndroid Build Coastguard Worker usleep(10000);
663*48a54d36SAndroid Build Coastguard Worker }
664*48a54d36SAndroid Build Coastguard Worker #else
665*48a54d36SAndroid Build Coastguard Worker if (write_all(sdr->sockfd, (char *)hdr, datalen + sizeof(ipc_msg_hdr)) < 0)
666*48a54d36SAndroid Build Coastguard Worker {
667*48a54d36SAndroid Build Coastguard Worker // write_all already prints an error message if there is an error writing to
668*48a54d36SAndroid Build Coastguard Worker // the socket except for DEFUNCT. Logging here is unnecessary and also wrong
669*48a54d36SAndroid Build Coastguard Worker // in the case of DEFUNCT sockets
670*48a54d36SAndroid Build Coastguard Worker syslog(LOG_INFO, "dnssd_clientstub deliver_request ERROR: write_all(%d, %lu bytes) failed",
671*48a54d36SAndroid Build Coastguard Worker sdr->sockfd, (unsigned long)(datalen + sizeof(ipc_msg_hdr)));
672*48a54d36SAndroid Build Coastguard Worker goto cleanup;
673*48a54d36SAndroid Build Coastguard Worker }
674*48a54d36SAndroid Build Coastguard Worker #endif
675*48a54d36SAndroid Build Coastguard Worker
676*48a54d36SAndroid Build Coastguard Worker if (!MakeSeparateReturnSocket) errsd = sdr->sockfd;
677*48a54d36SAndroid Build Coastguard Worker if (MakeSeparateReturnSocket || sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf
678*48a54d36SAndroid Build Coastguard Worker {
679*48a54d36SAndroid Build Coastguard Worker #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
680*48a54d36SAndroid Build Coastguard Worker // At this point we may block in accept for a few milliseconds waiting for the daemon to connect back to us,
681*48a54d36SAndroid Build Coastguard Worker // but that's okay -- the daemon is a trusted service and we know if won't take more than a few milliseconds to respond.
682*48a54d36SAndroid Build Coastguard Worker dnssd_sockaddr_t daddr;
683*48a54d36SAndroid Build Coastguard Worker dnssd_socklen_t len = sizeof(daddr);
684*48a54d36SAndroid Build Coastguard Worker if ((err = wait_for_daemon(listenfd, DNSSD_CLIENT_TIMEOUT)) != kDNSServiceErr_NoError) goto cleanup;
685*48a54d36SAndroid Build Coastguard Worker errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
686*48a54d36SAndroid Build Coastguard Worker if (!dnssd_SocketValid(errsd)) deliver_request_bailout("accept");
687*48a54d36SAndroid Build Coastguard Worker #else
688*48a54d36SAndroid Build Coastguard Worker
689*48a54d36SAndroid Build Coastguard Worker #if APPLE_OSX_mDNSResponder
690*48a54d36SAndroid Build Coastguard Worker // On Leopard, the stock definitions of the CMSG_* macros in /usr/include/sys/socket.h,
691*48a54d36SAndroid Build Coastguard Worker // while arguably correct in theory, nonetheless in practice produce code that doesn't work on 64-bit machines
692*48a54d36SAndroid Build Coastguard Worker // For details see <rdar://problem/5565787> Bonjour API broken for 64-bit apps (SCM_RIGHTS sendmsg fails)
693*48a54d36SAndroid Build Coastguard Worker #undef CMSG_DATA
694*48a54d36SAndroid Build Coastguard Worker #define CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + (sizeof(struct cmsghdr)))
695*48a54d36SAndroid Build Coastguard Worker #undef CMSG_SPACE
696*48a54d36SAndroid Build Coastguard Worker #define CMSG_SPACE(l) ((sizeof(struct cmsghdr)) + (l))
697*48a54d36SAndroid Build Coastguard Worker #undef CMSG_LEN
698*48a54d36SAndroid Build Coastguard Worker #define CMSG_LEN(l) ((sizeof(struct cmsghdr)) + (l))
699*48a54d36SAndroid Build Coastguard Worker #endif
700*48a54d36SAndroid Build Coastguard Worker
701*48a54d36SAndroid Build Coastguard Worker struct iovec vec = { ((char *)hdr) + sizeof(ipc_msg_hdr) + datalen, 1 }; // Send the last byte along with the SCM_RIGHTS
702*48a54d36SAndroid Build Coastguard Worker struct msghdr msg;
703*48a54d36SAndroid Build Coastguard Worker struct cmsghdr *cmsg;
704*48a54d36SAndroid Build Coastguard Worker char cbuf[CMSG_SPACE(sizeof(dnssd_sock_t))];
705*48a54d36SAndroid Build Coastguard Worker
706*48a54d36SAndroid Build Coastguard Worker if (sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf
707*48a54d36SAndroid Build Coastguard Worker {
708*48a54d36SAndroid Build Coastguard Worker int i;
709*48a54d36SAndroid Build Coastguard Worker char p[12]; // Room for "/dev/bpf999" with terminating null
710*48a54d36SAndroid Build Coastguard Worker for (i=0; i<100; i++)
711*48a54d36SAndroid Build Coastguard Worker {
712*48a54d36SAndroid Build Coastguard Worker snprintf(p, sizeof(p), "/dev/bpf%d", i);
713*48a54d36SAndroid Build Coastguard Worker listenfd = open(p, O_RDWR, 0);
714*48a54d36SAndroid Build Coastguard Worker //if (dnssd_SocketValid(listenfd)) syslog(LOG_WARNING, "Sending fd %d for %s", listenfd, p);
715*48a54d36SAndroid Build Coastguard Worker if (!dnssd_SocketValid(listenfd) && dnssd_errno != EBUSY)
716*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "Error opening %s %d (%s)", p, dnssd_errno, dnssd_strerror(dnssd_errno));
717*48a54d36SAndroid Build Coastguard Worker if (dnssd_SocketValid(listenfd) || dnssd_errno != EBUSY) break;
718*48a54d36SAndroid Build Coastguard Worker }
719*48a54d36SAndroid Build Coastguard Worker }
720*48a54d36SAndroid Build Coastguard Worker
721*48a54d36SAndroid Build Coastguard Worker msg.msg_name = 0;
722*48a54d36SAndroid Build Coastguard Worker msg.msg_namelen = 0;
723*48a54d36SAndroid Build Coastguard Worker msg.msg_iov = &vec;
724*48a54d36SAndroid Build Coastguard Worker msg.msg_iovlen = 1;
725*48a54d36SAndroid Build Coastguard Worker msg.msg_control = cbuf;
726*48a54d36SAndroid Build Coastguard Worker msg.msg_controllen = CMSG_LEN(sizeof(dnssd_sock_t));
727*48a54d36SAndroid Build Coastguard Worker msg.msg_flags = 0;
728*48a54d36SAndroid Build Coastguard Worker cmsg = CMSG_FIRSTHDR(&msg);
729*48a54d36SAndroid Build Coastguard Worker cmsg->cmsg_len = CMSG_LEN(sizeof(dnssd_sock_t));
730*48a54d36SAndroid Build Coastguard Worker cmsg->cmsg_level = SOL_SOCKET;
731*48a54d36SAndroid Build Coastguard Worker cmsg->cmsg_type = SCM_RIGHTS;
732*48a54d36SAndroid Build Coastguard Worker *((dnssd_sock_t *)CMSG_DATA(cmsg)) = listenfd;
733*48a54d36SAndroid Build Coastguard Worker
734*48a54d36SAndroid Build Coastguard Worker #if TEST_KQUEUE_CONTROL_MESSAGE_BUG
735*48a54d36SAndroid Build Coastguard Worker sleep(1);
736*48a54d36SAndroid Build Coastguard Worker #endif
737*48a54d36SAndroid Build Coastguard Worker
738*48a54d36SAndroid Build Coastguard Worker #if DEBUG_64BIT_SCM_RIGHTS
739*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d %ld %ld %ld/%ld/%ld/%ld",
740*48a54d36SAndroid Build Coastguard Worker errsd, listenfd, sizeof(dnssd_sock_t), sizeof(void*),
741*48a54d36SAndroid Build Coastguard Worker sizeof(struct cmsghdr) + sizeof(dnssd_sock_t),
742*48a54d36SAndroid Build Coastguard Worker CMSG_LEN(sizeof(dnssd_sock_t)), (long)CMSG_SPACE(sizeof(dnssd_sock_t)),
743*48a54d36SAndroid Build Coastguard Worker (long)((char*)CMSG_DATA(cmsg) + 4 - cbuf));
744*48a54d36SAndroid Build Coastguard Worker #endif // DEBUG_64BIT_SCM_RIGHTS
745*48a54d36SAndroid Build Coastguard Worker
746*48a54d36SAndroid Build Coastguard Worker if (sendmsg(sdr->sockfd, &msg, 0) < 0)
747*48a54d36SAndroid Build Coastguard Worker {
748*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub deliver_request ERROR: sendmsg failed read sd=%d write sd=%d errno %d (%s)",
749*48a54d36SAndroid Build Coastguard Worker errsd, listenfd, dnssd_errno, dnssd_strerror(dnssd_errno));
750*48a54d36SAndroid Build Coastguard Worker err = kDNSServiceErr_Incompatible;
751*48a54d36SAndroid Build Coastguard Worker goto cleanup;
752*48a54d36SAndroid Build Coastguard Worker }
753*48a54d36SAndroid Build Coastguard Worker
754*48a54d36SAndroid Build Coastguard Worker #if DEBUG_64BIT_SCM_RIGHTS
755*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d okay", errsd, listenfd);
756*48a54d36SAndroid Build Coastguard Worker #endif // DEBUG_64BIT_SCM_RIGHTS
757*48a54d36SAndroid Build Coastguard Worker
758*48a54d36SAndroid Build Coastguard Worker #endif
759*48a54d36SAndroid Build Coastguard Worker // Close our end of the socketpair *before* blocking in read_all to get the four-byte error code.
760*48a54d36SAndroid Build Coastguard Worker // Otherwise, if the daemon closes our socket (or crashes), we block in read_all() forever
761*48a54d36SAndroid Build Coastguard Worker // because the socket is not closed (we still have an open reference to it ourselves).
762*48a54d36SAndroid Build Coastguard Worker dnssd_close(listenfd);
763*48a54d36SAndroid Build Coastguard Worker listenfd = dnssd_InvalidSocket; // Make sure we don't close it a second time in the cleanup handling below
764*48a54d36SAndroid Build Coastguard Worker }
765*48a54d36SAndroid Build Coastguard Worker
766*48a54d36SAndroid Build Coastguard Worker // At this point we may block in read_all for a few milliseconds waiting for the daemon to send us the error code,
767*48a54d36SAndroid Build Coastguard Worker // but that's okay -- the daemon is a trusted service and we know if won't take more than a few milliseconds to respond.
768*48a54d36SAndroid Build Coastguard Worker if (sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf
769*48a54d36SAndroid Build Coastguard Worker err = kDNSServiceErr_NoError;
770*48a54d36SAndroid Build Coastguard Worker else if ((err = wait_for_daemon(errsd, DNSSD_CLIENT_TIMEOUT)) == kDNSServiceErr_NoError)
771*48a54d36SAndroid Build Coastguard Worker {
772*48a54d36SAndroid Build Coastguard Worker if (read_all(errsd, (char*)&err, (int)sizeof(err)) < 0)
773*48a54d36SAndroid Build Coastguard Worker err = kDNSServiceErr_ServiceNotRunning; // On failure read_all will have written a message to syslog for us
774*48a54d36SAndroid Build Coastguard Worker else
775*48a54d36SAndroid Build Coastguard Worker err = ntohl(err);
776*48a54d36SAndroid Build Coastguard Worker }
777*48a54d36SAndroid Build Coastguard Worker
778*48a54d36SAndroid Build Coastguard Worker //syslog(LOG_WARNING, "dnssd_clientstub deliver_request: retrieved error code %d", err);
779*48a54d36SAndroid Build Coastguard Worker
780*48a54d36SAndroid Build Coastguard Worker cleanup:
781*48a54d36SAndroid Build Coastguard Worker if (MakeSeparateReturnSocket)
782*48a54d36SAndroid Build Coastguard Worker {
783*48a54d36SAndroid Build Coastguard Worker if (dnssd_SocketValid(listenfd)) dnssd_close(listenfd);
784*48a54d36SAndroid Build Coastguard Worker if (dnssd_SocketValid(errsd)) dnssd_close(errsd);
785*48a54d36SAndroid Build Coastguard Worker #if defined(USE_NAMED_ERROR_RETURN_SOCKET)
786*48a54d36SAndroid Build Coastguard Worker // syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removing UDS: %s", data);
787*48a54d36SAndroid Build Coastguard Worker if (unlink(data) != 0)
788*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub WARNING: unlink(\"%s\") failed errno %d (%s)", data, dnssd_errno, dnssd_strerror(dnssd_errno));
789*48a54d36SAndroid Build Coastguard Worker // else syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removed UDS: %s", data);
790*48a54d36SAndroid Build Coastguard Worker #endif
791*48a54d36SAndroid Build Coastguard Worker }
792*48a54d36SAndroid Build Coastguard Worker
793*48a54d36SAndroid Build Coastguard Worker free(hdr);
794*48a54d36SAndroid Build Coastguard Worker return err;
795*48a54d36SAndroid Build Coastguard Worker }
796*48a54d36SAndroid Build Coastguard Worker
DNSServiceRefSockFD(DNSServiceRef sdRef)797*48a54d36SAndroid Build Coastguard Worker int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
798*48a54d36SAndroid Build Coastguard Worker {
799*48a54d36SAndroid Build Coastguard Worker if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with NULL DNSServiceRef"); return dnssd_InvalidSocket; }
800*48a54d36SAndroid Build Coastguard Worker
801*48a54d36SAndroid Build Coastguard Worker if (!DNSServiceRefValid(sdRef))
802*48a54d36SAndroid Build Coastguard Worker {
803*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with invalid DNSServiceRef %p %08X %08X",
804*48a54d36SAndroid Build Coastguard Worker sdRef, sdRef->sockfd, sdRef->validator);
805*48a54d36SAndroid Build Coastguard Worker return dnssd_InvalidSocket;
806*48a54d36SAndroid Build Coastguard Worker }
807*48a54d36SAndroid Build Coastguard Worker
808*48a54d36SAndroid Build Coastguard Worker if (sdRef->primary)
809*48a54d36SAndroid Build Coastguard Worker {
810*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef);
811*48a54d36SAndroid Build Coastguard Worker return dnssd_InvalidSocket;
812*48a54d36SAndroid Build Coastguard Worker }
813*48a54d36SAndroid Build Coastguard Worker
814*48a54d36SAndroid Build Coastguard Worker return (int) sdRef->sockfd;
815*48a54d36SAndroid Build Coastguard Worker }
816*48a54d36SAndroid Build Coastguard Worker
817*48a54d36SAndroid Build Coastguard Worker #if _DNS_SD_LIBDISPATCH
CallbackWithError(DNSServiceRef sdRef,DNSServiceErrorType error)818*48a54d36SAndroid Build Coastguard Worker static void CallbackWithError(DNSServiceRef sdRef, DNSServiceErrorType error)
819*48a54d36SAndroid Build Coastguard Worker {
820*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *sdr = sdRef;
821*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *sdrNext;
822*48a54d36SAndroid Build Coastguard Worker DNSRecord *rec;
823*48a54d36SAndroid Build Coastguard Worker DNSRecord *recnext;
824*48a54d36SAndroid Build Coastguard Worker int morebytes;
825*48a54d36SAndroid Build Coastguard Worker
826*48a54d36SAndroid Build Coastguard Worker while (sdr)
827*48a54d36SAndroid Build Coastguard Worker {
828*48a54d36SAndroid Build Coastguard Worker // We can't touch the sdr after the callback as it can be deallocated in the callback
829*48a54d36SAndroid Build Coastguard Worker sdrNext = sdr->next;
830*48a54d36SAndroid Build Coastguard Worker morebytes = 1;
831*48a54d36SAndroid Build Coastguard Worker sdr->moreptr = &morebytes;
832*48a54d36SAndroid Build Coastguard Worker switch (sdr->op)
833*48a54d36SAndroid Build Coastguard Worker {
834*48a54d36SAndroid Build Coastguard Worker case resolve_request:
835*48a54d36SAndroid Build Coastguard Worker if (sdr->AppCallback)((DNSServiceResolveReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL, sdr->AppContext);
836*48a54d36SAndroid Build Coastguard Worker break;
837*48a54d36SAndroid Build Coastguard Worker case query_request:
838*48a54d36SAndroid Build Coastguard Worker if (sdr->AppCallback)((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL, 0, sdr->AppContext);
839*48a54d36SAndroid Build Coastguard Worker break;
840*48a54d36SAndroid Build Coastguard Worker case addrinfo_request:
841*48a54d36SAndroid Build Coastguard Worker if (sdr->AppCallback)((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, NULL, 0, sdr->AppContext);
842*48a54d36SAndroid Build Coastguard Worker break;
843*48a54d36SAndroid Build Coastguard Worker case browse_request:
844*48a54d36SAndroid Build Coastguard Worker if (sdr->AppCallback)((DNSServiceBrowseReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, NULL, sdr->AppContext);
845*48a54d36SAndroid Build Coastguard Worker break;
846*48a54d36SAndroid Build Coastguard Worker case reg_service_request:
847*48a54d36SAndroid Build Coastguard Worker if (sdr->AppCallback)((DNSServiceRegisterReply) sdr->AppCallback)(sdr, 0, error, NULL, 0, NULL, sdr->AppContext);
848*48a54d36SAndroid Build Coastguard Worker break;
849*48a54d36SAndroid Build Coastguard Worker case enumeration_request:
850*48a54d36SAndroid Build Coastguard Worker if (sdr->AppCallback)((DNSServiceDomainEnumReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, sdr->AppContext);
851*48a54d36SAndroid Build Coastguard Worker break;
852*48a54d36SAndroid Build Coastguard Worker case sethost_request:
853*48a54d36SAndroid Build Coastguard Worker if (sdr->AppCallback)((DNSServiceSetHostReply) sdr->AppCallback)(sdr, 0, error, NULL, sdr->AppContext);
854*48a54d36SAndroid Build Coastguard Worker break;
855*48a54d36SAndroid Build Coastguard Worker case connection_request:
856*48a54d36SAndroid Build Coastguard Worker // This means Register Record, walk the list of DNSRecords to do the callback
857*48a54d36SAndroid Build Coastguard Worker rec = sdr->rec;
858*48a54d36SAndroid Build Coastguard Worker while (rec)
859*48a54d36SAndroid Build Coastguard Worker {
860*48a54d36SAndroid Build Coastguard Worker recnext = rec->recnext;
861*48a54d36SAndroid Build Coastguard Worker if (rec->AppCallback) ((DNSServiceRegisterRecordReply)rec->AppCallback)(sdr, 0, 0, error, rec->AppContext);
862*48a54d36SAndroid Build Coastguard Worker // The Callback can call DNSServiceRefDeallocate which in turn frees sdr and all the records.
863*48a54d36SAndroid Build Coastguard Worker // Detect that and return early
864*48a54d36SAndroid Build Coastguard Worker if (!morebytes){syslog(LOG_WARNING, "dnssdclientstub:Record: CallbackwithError morebytes zero"); return;}
865*48a54d36SAndroid Build Coastguard Worker rec = recnext;
866*48a54d36SAndroid Build Coastguard Worker }
867*48a54d36SAndroid Build Coastguard Worker break;
868*48a54d36SAndroid Build Coastguard Worker case port_mapping_request:
869*48a54d36SAndroid Build Coastguard Worker if (sdr->AppCallback)((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, 0, 0, error, 0, 0, 0, 0, 0, sdr->AppContext);
870*48a54d36SAndroid Build Coastguard Worker break;
871*48a54d36SAndroid Build Coastguard Worker default:
872*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub CallbackWithError called with bad op %d", sdr->op);
873*48a54d36SAndroid Build Coastguard Worker }
874*48a54d36SAndroid Build Coastguard Worker // If DNSServiceRefDeallocate was called in the callback, morebytes will be zero. It means
875*48a54d36SAndroid Build Coastguard Worker // all other sdrefs have been freed. This happens for shared connections where the
876*48a54d36SAndroid Build Coastguard Worker // DNSServiceRefDeallocate on the first sdRef frees all other sdrefs.
877*48a54d36SAndroid Build Coastguard Worker if (!morebytes){syslog(LOG_WARNING, "dnssdclientstub:sdRef: CallbackwithError morebytes zero"); return;}
878*48a54d36SAndroid Build Coastguard Worker sdr = sdrNext;
879*48a54d36SAndroid Build Coastguard Worker }
880*48a54d36SAndroid Build Coastguard Worker }
881*48a54d36SAndroid Build Coastguard Worker #endif // _DNS_SD_LIBDISPATCH
882*48a54d36SAndroid Build Coastguard Worker
883*48a54d36SAndroid Build Coastguard Worker // Handle reply from server, calling application client callback. If there is no reply
884*48a54d36SAndroid Build Coastguard Worker // from the daemon on the socket contained in sdRef, the call will block.
DNSServiceProcessResult(DNSServiceRef sdRef)885*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
886*48a54d36SAndroid Build Coastguard Worker {
887*48a54d36SAndroid Build Coastguard Worker int morebytes = 0;
888*48a54d36SAndroid Build Coastguard Worker
889*48a54d36SAndroid Build Coastguard Worker if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
890*48a54d36SAndroid Build Coastguard Worker
891*48a54d36SAndroid Build Coastguard Worker if (!DNSServiceRefValid(sdRef))
892*48a54d36SAndroid Build Coastguard Worker {
893*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
894*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadReference;
895*48a54d36SAndroid Build Coastguard Worker }
896*48a54d36SAndroid Build Coastguard Worker
897*48a54d36SAndroid Build Coastguard Worker if (sdRef->primary)
898*48a54d36SAndroid Build Coastguard Worker {
899*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef);
900*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadReference;
901*48a54d36SAndroid Build Coastguard Worker }
902*48a54d36SAndroid Build Coastguard Worker
903*48a54d36SAndroid Build Coastguard Worker if (!sdRef->ProcessReply)
904*48a54d36SAndroid Build Coastguard Worker {
905*48a54d36SAndroid Build Coastguard Worker static int num_logs = 0;
906*48a54d36SAndroid Build Coastguard Worker if (num_logs < 10) syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with DNSServiceRef with no ProcessReply function");
907*48a54d36SAndroid Build Coastguard Worker if (num_logs < 1000) num_logs++; else sleep(1);
908*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadReference;
909*48a54d36SAndroid Build Coastguard Worker }
910*48a54d36SAndroid Build Coastguard Worker
911*48a54d36SAndroid Build Coastguard Worker do
912*48a54d36SAndroid Build Coastguard Worker {
913*48a54d36SAndroid Build Coastguard Worker CallbackHeader cbh;
914*48a54d36SAndroid Build Coastguard Worker char *data;
915*48a54d36SAndroid Build Coastguard Worker
916*48a54d36SAndroid Build Coastguard Worker // return NoError on EWOULDBLOCK. This will handle the case
917*48a54d36SAndroid Build Coastguard Worker // where a non-blocking socket is told there is data, but it was a false positive.
918*48a54d36SAndroid Build Coastguard Worker // On error, read_all will write a message to syslog for us, so don't need to duplicate that here
919*48a54d36SAndroid Build Coastguard Worker // Note: If we want to properly support using non-blocking sockets in the future
920*48a54d36SAndroid Build Coastguard Worker int result = read_all(sdRef->sockfd, (void *)&cbh.ipc_hdr, sizeof(cbh.ipc_hdr));
921*48a54d36SAndroid Build Coastguard Worker if (result == read_all_fail)
922*48a54d36SAndroid Build Coastguard Worker {
923*48a54d36SAndroid Build Coastguard Worker // Set the ProcessReply to NULL before callback as the sdRef can get deallocated
924*48a54d36SAndroid Build Coastguard Worker // in the callback.
925*48a54d36SAndroid Build Coastguard Worker sdRef->ProcessReply = NULL;
926*48a54d36SAndroid Build Coastguard Worker #if _DNS_SD_LIBDISPATCH
927*48a54d36SAndroid Build Coastguard Worker // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult
928*48a54d36SAndroid Build Coastguard Worker // is not called by the application and hence need to communicate the error. Cancel the
929*48a54d36SAndroid Build Coastguard Worker // source so that we don't get any more events
930*48a54d36SAndroid Build Coastguard Worker if (sdRef->disp_source)
931*48a54d36SAndroid Build Coastguard Worker {
932*48a54d36SAndroid Build Coastguard Worker dispatch_source_cancel(sdRef->disp_source);
933*48a54d36SAndroid Build Coastguard Worker dispatch_release(sdRef->disp_source);
934*48a54d36SAndroid Build Coastguard Worker sdRef->disp_source = NULL;
935*48a54d36SAndroid Build Coastguard Worker CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning);
936*48a54d36SAndroid Build Coastguard Worker }
937*48a54d36SAndroid Build Coastguard Worker #endif
938*48a54d36SAndroid Build Coastguard Worker // Don't touch sdRef anymore as it might have been deallocated
939*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_ServiceNotRunning;
940*48a54d36SAndroid Build Coastguard Worker }
941*48a54d36SAndroid Build Coastguard Worker else if (result == read_all_wouldblock)
942*48a54d36SAndroid Build Coastguard Worker {
943*48a54d36SAndroid Build Coastguard Worker if (morebytes && sdRef->logcounter < 100)
944*48a54d36SAndroid Build Coastguard Worker {
945*48a54d36SAndroid Build Coastguard Worker sdRef->logcounter++;
946*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult error: select indicated data was waiting but read_all returned EWOULDBLOCK");
947*48a54d36SAndroid Build Coastguard Worker }
948*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_NoError;
949*48a54d36SAndroid Build Coastguard Worker }
950*48a54d36SAndroid Build Coastguard Worker
951*48a54d36SAndroid Build Coastguard Worker ConvertHeaderBytes(&cbh.ipc_hdr);
952*48a54d36SAndroid Build Coastguard Worker if (cbh.ipc_hdr.version != VERSION)
953*48a54d36SAndroid Build Coastguard Worker {
954*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult daemon version %d does not match client version %d", cbh.ipc_hdr.version, VERSION);
955*48a54d36SAndroid Build Coastguard Worker sdRef->ProcessReply = NULL;
956*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_Incompatible;
957*48a54d36SAndroid Build Coastguard Worker }
958*48a54d36SAndroid Build Coastguard Worker
959*48a54d36SAndroid Build Coastguard Worker data = malloc(cbh.ipc_hdr.datalen);
960*48a54d36SAndroid Build Coastguard Worker if (!data) return kDNSServiceErr_NoMemory;
961*48a54d36SAndroid Build Coastguard Worker if (read_all(sdRef->sockfd, data, cbh.ipc_hdr.datalen) < 0) // On error, read_all will write a message to syslog for us
962*48a54d36SAndroid Build Coastguard Worker {
963*48a54d36SAndroid Build Coastguard Worker // Set the ProcessReply to NULL before callback as the sdRef can get deallocated
964*48a54d36SAndroid Build Coastguard Worker // in the callback.
965*48a54d36SAndroid Build Coastguard Worker sdRef->ProcessReply = NULL;
966*48a54d36SAndroid Build Coastguard Worker #if _DNS_SD_LIBDISPATCH
967*48a54d36SAndroid Build Coastguard Worker // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult
968*48a54d36SAndroid Build Coastguard Worker // is not called by the application and hence need to communicate the error. Cancel the
969*48a54d36SAndroid Build Coastguard Worker // source so that we don't get any more events
970*48a54d36SAndroid Build Coastguard Worker if (sdRef->disp_source)
971*48a54d36SAndroid Build Coastguard Worker {
972*48a54d36SAndroid Build Coastguard Worker dispatch_source_cancel(sdRef->disp_source);
973*48a54d36SAndroid Build Coastguard Worker dispatch_release(sdRef->disp_source);
974*48a54d36SAndroid Build Coastguard Worker sdRef->disp_source = NULL;
975*48a54d36SAndroid Build Coastguard Worker CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning);
976*48a54d36SAndroid Build Coastguard Worker }
977*48a54d36SAndroid Build Coastguard Worker #endif
978*48a54d36SAndroid Build Coastguard Worker // Don't touch sdRef anymore as it might have been deallocated
979*48a54d36SAndroid Build Coastguard Worker free(data);
980*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_ServiceNotRunning;
981*48a54d36SAndroid Build Coastguard Worker }
982*48a54d36SAndroid Build Coastguard Worker else
983*48a54d36SAndroid Build Coastguard Worker {
984*48a54d36SAndroid Build Coastguard Worker const char *ptr = data;
985*48a54d36SAndroid Build Coastguard Worker cbh.cb_flags = get_flags (&ptr, data + cbh.ipc_hdr.datalen);
986*48a54d36SAndroid Build Coastguard Worker cbh.cb_interface = get_uint32 (&ptr, data + cbh.ipc_hdr.datalen);
987*48a54d36SAndroid Build Coastguard Worker cbh.cb_err = get_error_code(&ptr, data + cbh.ipc_hdr.datalen);
988*48a54d36SAndroid Build Coastguard Worker
989*48a54d36SAndroid Build Coastguard Worker // CAUTION: We have to handle the case where the client calls DNSServiceRefDeallocate from within the callback function.
990*48a54d36SAndroid Build Coastguard Worker // To do this we set moreptr to point to morebytes. If the client does call DNSServiceRefDeallocate(),
991*48a54d36SAndroid Build Coastguard Worker // then that routine will clear morebytes for us, and cause us to exit our loop.
992*48a54d36SAndroid Build Coastguard Worker morebytes = more_bytes(sdRef->sockfd);
993*48a54d36SAndroid Build Coastguard Worker if (morebytes)
994*48a54d36SAndroid Build Coastguard Worker {
995*48a54d36SAndroid Build Coastguard Worker cbh.cb_flags |= kDNSServiceFlagsMoreComing;
996*48a54d36SAndroid Build Coastguard Worker sdRef->moreptr = &morebytes;
997*48a54d36SAndroid Build Coastguard Worker }
998*48a54d36SAndroid Build Coastguard Worker if (ptr) sdRef->ProcessReply(sdRef, &cbh, ptr, data + cbh.ipc_hdr.datalen);
999*48a54d36SAndroid Build Coastguard Worker // Careful code here:
1000*48a54d36SAndroid Build Coastguard Worker // If morebytes is non-zero, that means we set sdRef->moreptr above, and the operation was not
1001*48a54d36SAndroid Build Coastguard Worker // cancelled out from under us, so now we need to clear sdRef->moreptr so we don't leave a stray
1002*48a54d36SAndroid Build Coastguard Worker // dangling pointer pointing to a long-gone stack variable.
1003*48a54d36SAndroid Build Coastguard Worker // If morebytes is zero, then one of two thing happened:
1004*48a54d36SAndroid Build Coastguard Worker // (a) morebytes was 0 above, so we didn't set sdRef->moreptr, so we don't need to clear it
1005*48a54d36SAndroid Build Coastguard Worker // (b) morebytes was 1 above, and we set sdRef->moreptr, but the operation was cancelled (with DNSServiceRefDeallocate()),
1006*48a54d36SAndroid Build Coastguard Worker // so we MUST NOT try to dereference our stale sdRef pointer.
1007*48a54d36SAndroid Build Coastguard Worker if (morebytes) sdRef->moreptr = NULL;
1008*48a54d36SAndroid Build Coastguard Worker }
1009*48a54d36SAndroid Build Coastguard Worker free(data);
1010*48a54d36SAndroid Build Coastguard Worker } while (morebytes);
1011*48a54d36SAndroid Build Coastguard Worker
1012*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_NoError;
1013*48a54d36SAndroid Build Coastguard Worker }
1014*48a54d36SAndroid Build Coastguard Worker
DNSServiceRefDeallocate(DNSServiceRef sdRef)1015*48a54d36SAndroid Build Coastguard Worker void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef)
1016*48a54d36SAndroid Build Coastguard Worker {
1017*48a54d36SAndroid Build Coastguard Worker if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with NULL DNSServiceRef"); return; }
1018*48a54d36SAndroid Build Coastguard Worker
1019*48a54d36SAndroid Build Coastguard Worker if (!DNSServiceRefValid(sdRef)) // Also verifies dnssd_SocketValid(sdRef->sockfd) for us too
1020*48a54d36SAndroid Build Coastguard Worker {
1021*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
1022*48a54d36SAndroid Build Coastguard Worker return;
1023*48a54d36SAndroid Build Coastguard Worker }
1024*48a54d36SAndroid Build Coastguard Worker
1025*48a54d36SAndroid Build Coastguard Worker // If we're in the middle of a DNSServiceProcessResult() invocation for this DNSServiceRef, clear its morebytes flag to break it out of its while loop
1026*48a54d36SAndroid Build Coastguard Worker if (sdRef->moreptr) *(sdRef->moreptr) = 0;
1027*48a54d36SAndroid Build Coastguard Worker
1028*48a54d36SAndroid Build Coastguard Worker if (sdRef->primary) // If this is a subordinate DNSServiceOp, just send a 'stop' command
1029*48a54d36SAndroid Build Coastguard Worker {
1030*48a54d36SAndroid Build Coastguard Worker DNSServiceOp **p = &sdRef->primary->next;
1031*48a54d36SAndroid Build Coastguard Worker while (*p && *p != sdRef) p = &(*p)->next;
1032*48a54d36SAndroid Build Coastguard Worker if (*p)
1033*48a54d36SAndroid Build Coastguard Worker {
1034*48a54d36SAndroid Build Coastguard Worker char *ptr;
1035*48a54d36SAndroid Build Coastguard Worker size_t len = 0;
1036*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr = create_hdr(cancel_request, &len, &ptr, 0, sdRef);
1037*48a54d36SAndroid Build Coastguard Worker if (hdr)
1038*48a54d36SAndroid Build Coastguard Worker {
1039*48a54d36SAndroid Build Coastguard Worker ConvertHeaderBytes(hdr);
1040*48a54d36SAndroid Build Coastguard Worker write_all(sdRef->sockfd, (char *)hdr, len);
1041*48a54d36SAndroid Build Coastguard Worker free(hdr);
1042*48a54d36SAndroid Build Coastguard Worker }
1043*48a54d36SAndroid Build Coastguard Worker *p = sdRef->next;
1044*48a54d36SAndroid Build Coastguard Worker FreeDNSServiceOp(sdRef);
1045*48a54d36SAndroid Build Coastguard Worker }
1046*48a54d36SAndroid Build Coastguard Worker }
1047*48a54d36SAndroid Build Coastguard Worker else // else, make sure to terminate all subordinates as well
1048*48a54d36SAndroid Build Coastguard Worker {
1049*48a54d36SAndroid Build Coastguard Worker #if _DNS_SD_LIBDISPATCH
1050*48a54d36SAndroid Build Coastguard Worker // The cancel handler will close the fd if a dispatch source has been set
1051*48a54d36SAndroid Build Coastguard Worker if (sdRef->disp_source)
1052*48a54d36SAndroid Build Coastguard Worker {
1053*48a54d36SAndroid Build Coastguard Worker // By setting the ProcessReply to NULL, we make sure that we never call
1054*48a54d36SAndroid Build Coastguard Worker // the application callbacks ever, after returning from this function. We
1055*48a54d36SAndroid Build Coastguard Worker // assume that DNSServiceRefDeallocate is called from the serial queue
1056*48a54d36SAndroid Build Coastguard Worker // that was passed to DNSServiceSetDispatchQueue. Hence, dispatch_source_cancel
1057*48a54d36SAndroid Build Coastguard Worker // should cancel all the blocks on the queue and hence there should be no more
1058*48a54d36SAndroid Build Coastguard Worker // callbacks when we return from this function. Setting ProcessReply to NULL
1059*48a54d36SAndroid Build Coastguard Worker // provides extra protection.
1060*48a54d36SAndroid Build Coastguard Worker sdRef->ProcessReply = NULL;
1061*48a54d36SAndroid Build Coastguard Worker dispatch_source_cancel(sdRef->disp_source);
1062*48a54d36SAndroid Build Coastguard Worker dispatch_release(sdRef->disp_source);
1063*48a54d36SAndroid Build Coastguard Worker sdRef->disp_source = NULL;
1064*48a54d36SAndroid Build Coastguard Worker }
1065*48a54d36SAndroid Build Coastguard Worker // if disp_queue is set, it means it used the DNSServiceSetDispatchQueue API. In that case,
1066*48a54d36SAndroid Build Coastguard Worker // when the source was cancelled, the fd was closed in the handler. Currently the source
1067*48a54d36SAndroid Build Coastguard Worker // is cancelled only when the mDNSResponder daemon dies
1068*48a54d36SAndroid Build Coastguard Worker else if (!sdRef->disp_queue) dnssd_close(sdRef->sockfd);
1069*48a54d36SAndroid Build Coastguard Worker #else
1070*48a54d36SAndroid Build Coastguard Worker dnssd_close(sdRef->sockfd);
1071*48a54d36SAndroid Build Coastguard Worker #endif
1072*48a54d36SAndroid Build Coastguard Worker // Free DNSRecords added in DNSRegisterRecord if they have not
1073*48a54d36SAndroid Build Coastguard Worker // been freed in DNSRemoveRecord
1074*48a54d36SAndroid Build Coastguard Worker while (sdRef)
1075*48a54d36SAndroid Build Coastguard Worker {
1076*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *p = sdRef;
1077*48a54d36SAndroid Build Coastguard Worker sdRef = sdRef->next;
1078*48a54d36SAndroid Build Coastguard Worker FreeDNSServiceOp(p);
1079*48a54d36SAndroid Build Coastguard Worker }
1080*48a54d36SAndroid Build Coastguard Worker }
1081*48a54d36SAndroid Build Coastguard Worker }
1082*48a54d36SAndroid Build Coastguard Worker
DNSServiceGetProperty(const char * property,void * result,uint32_t * size)1083*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceGetProperty(const char *property, void *result, uint32_t *size)
1084*48a54d36SAndroid Build Coastguard Worker {
1085*48a54d36SAndroid Build Coastguard Worker char *ptr;
1086*48a54d36SAndroid Build Coastguard Worker size_t len = strlen(property) + 1;
1087*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1088*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *tmp;
1089*48a54d36SAndroid Build Coastguard Worker uint32_t actualsize;
1090*48a54d36SAndroid Build Coastguard Worker
1091*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err = ConnectToServer(&tmp, 0, getproperty_request, NULL, NULL, NULL);
1092*48a54d36SAndroid Build Coastguard Worker if (err) return err;
1093*48a54d36SAndroid Build Coastguard Worker
1094*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(getproperty_request, &len, &ptr, 0, tmp);
1095*48a54d36SAndroid Build Coastguard Worker if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
1096*48a54d36SAndroid Build Coastguard Worker
1097*48a54d36SAndroid Build Coastguard Worker put_string(property, &ptr);
1098*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, tmp); // Will free hdr for us
1099*48a54d36SAndroid Build Coastguard Worker if (read_all(tmp->sockfd, (char*)&actualsize, (int)sizeof(actualsize)) < 0)
1100*48a54d36SAndroid Build Coastguard Worker { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; }
1101*48a54d36SAndroid Build Coastguard Worker
1102*48a54d36SAndroid Build Coastguard Worker actualsize = ntohl(actualsize);
1103*48a54d36SAndroid Build Coastguard Worker if (read_all(tmp->sockfd, (char*)result, actualsize < *size ? actualsize : *size) < 0)
1104*48a54d36SAndroid Build Coastguard Worker { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; }
1105*48a54d36SAndroid Build Coastguard Worker DNSServiceRefDeallocate(tmp);
1106*48a54d36SAndroid Build Coastguard Worker
1107*48a54d36SAndroid Build Coastguard Worker // Swap version result back to local process byte order
1108*48a54d36SAndroid Build Coastguard Worker if (!strcmp(property, kDNSServiceProperty_DaemonVersion) && *size >= 4)
1109*48a54d36SAndroid Build Coastguard Worker *(uint32_t*)result = ntohl(*(uint32_t*)result);
1110*48a54d36SAndroid Build Coastguard Worker
1111*48a54d36SAndroid Build Coastguard Worker *size = actualsize;
1112*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_NoError;
1113*48a54d36SAndroid Build Coastguard Worker }
1114*48a54d36SAndroid Build Coastguard Worker
handle_resolve_response(DNSServiceOp * const sdr,const CallbackHeader * const cbh,const char * data,const char * end)1115*48a54d36SAndroid Build Coastguard Worker static void handle_resolve_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *end)
1116*48a54d36SAndroid Build Coastguard Worker {
1117*48a54d36SAndroid Build Coastguard Worker char fullname[kDNSServiceMaxDomainName];
1118*48a54d36SAndroid Build Coastguard Worker char target[kDNSServiceMaxDomainName];
1119*48a54d36SAndroid Build Coastguard Worker uint16_t txtlen;
1120*48a54d36SAndroid Build Coastguard Worker union { uint16_t s; u_char b[2]; } port;
1121*48a54d36SAndroid Build Coastguard Worker unsigned char *txtrecord;
1122*48a54d36SAndroid Build Coastguard Worker
1123*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, fullname, kDNSServiceMaxDomainName);
1124*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, target, kDNSServiceMaxDomainName);
1125*48a54d36SAndroid Build Coastguard Worker if (!data || data + 2 > end) goto fail;
1126*48a54d36SAndroid Build Coastguard Worker
1127*48a54d36SAndroid Build Coastguard Worker port.b[0] = *data++;
1128*48a54d36SAndroid Build Coastguard Worker port.b[1] = *data++;
1129*48a54d36SAndroid Build Coastguard Worker txtlen = get_uint16(&data, end);
1130*48a54d36SAndroid Build Coastguard Worker txtrecord = (unsigned char *)get_rdata(&data, end, txtlen);
1131*48a54d36SAndroid Build Coastguard Worker
1132*48a54d36SAndroid Build Coastguard Worker if (!data) goto fail;
1133*48a54d36SAndroid Build Coastguard Worker ((DNSServiceResolveReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, fullname, target, port.s, txtlen, txtrecord, sdr->AppContext);
1134*48a54d36SAndroid Build Coastguard Worker return;
1135*48a54d36SAndroid Build Coastguard Worker // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
1136*48a54d36SAndroid Build Coastguard Worker fail:
1137*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub handle_resolve_response: error reading result from daemon");
1138*48a54d36SAndroid Build Coastguard Worker }
1139*48a54d36SAndroid Build Coastguard Worker
DNSServiceResolve(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,const char * name,const char * regtype,const char * domain,DNSServiceResolveReply callBack,void * context)1140*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceResolve
1141*48a54d36SAndroid Build Coastguard Worker (
1142*48a54d36SAndroid Build Coastguard Worker DNSServiceRef *sdRef,
1143*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1144*48a54d36SAndroid Build Coastguard Worker uint32_t interfaceIndex,
1145*48a54d36SAndroid Build Coastguard Worker const char *name,
1146*48a54d36SAndroid Build Coastguard Worker const char *regtype,
1147*48a54d36SAndroid Build Coastguard Worker const char *domain,
1148*48a54d36SAndroid Build Coastguard Worker DNSServiceResolveReply callBack,
1149*48a54d36SAndroid Build Coastguard Worker void *context
1150*48a54d36SAndroid Build Coastguard Worker )
1151*48a54d36SAndroid Build Coastguard Worker {
1152*48a54d36SAndroid Build Coastguard Worker char *ptr;
1153*48a54d36SAndroid Build Coastguard Worker size_t len;
1154*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1155*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err;
1156*48a54d36SAndroid Build Coastguard Worker
1157*48a54d36SAndroid Build Coastguard Worker if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam;
1158*48a54d36SAndroid Build Coastguard Worker
1159*48a54d36SAndroid Build Coastguard Worker // Need a real InterfaceID for WakeOnResolve
1160*48a54d36SAndroid Build Coastguard Worker if ((flags & kDNSServiceFlagsWakeOnResolve) != 0 &&
1161*48a54d36SAndroid Build Coastguard Worker ((interfaceIndex == kDNSServiceInterfaceIndexAny) ||
1162*48a54d36SAndroid Build Coastguard Worker (interfaceIndex == kDNSServiceInterfaceIndexLocalOnly) ||
1163*48a54d36SAndroid Build Coastguard Worker (interfaceIndex == kDNSServiceInterfaceIndexUnicast) ||
1164*48a54d36SAndroid Build Coastguard Worker (interfaceIndex == kDNSServiceInterfaceIndexP2P)))
1165*48a54d36SAndroid Build Coastguard Worker {
1166*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadParam;
1167*48a54d36SAndroid Build Coastguard Worker }
1168*48a54d36SAndroid Build Coastguard Worker
1169*48a54d36SAndroid Build Coastguard Worker err = ConnectToServer(sdRef, flags, resolve_request, handle_resolve_response, callBack, context);
1170*48a54d36SAndroid Build Coastguard Worker if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL
1171*48a54d36SAndroid Build Coastguard Worker
1172*48a54d36SAndroid Build Coastguard Worker // Calculate total message length
1173*48a54d36SAndroid Build Coastguard Worker len = sizeof(flags);
1174*48a54d36SAndroid Build Coastguard Worker len += sizeof(interfaceIndex);
1175*48a54d36SAndroid Build Coastguard Worker len += strlen(name) + 1;
1176*48a54d36SAndroid Build Coastguard Worker len += strlen(regtype) + 1;
1177*48a54d36SAndroid Build Coastguard Worker len += strlen(domain) + 1;
1178*48a54d36SAndroid Build Coastguard Worker
1179*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(resolve_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
1180*48a54d36SAndroid Build Coastguard Worker if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
1181*48a54d36SAndroid Build Coastguard Worker
1182*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1183*48a54d36SAndroid Build Coastguard Worker put_uint32(interfaceIndex, &ptr);
1184*48a54d36SAndroid Build Coastguard Worker put_string(name, &ptr);
1185*48a54d36SAndroid Build Coastguard Worker put_string(regtype, &ptr);
1186*48a54d36SAndroid Build Coastguard Worker put_string(domain, &ptr);
1187*48a54d36SAndroid Build Coastguard Worker
1188*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, *sdRef); // Will free hdr for us
1189*48a54d36SAndroid Build Coastguard Worker if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
1190*48a54d36SAndroid Build Coastguard Worker return err;
1191*48a54d36SAndroid Build Coastguard Worker }
1192*48a54d36SAndroid Build Coastguard Worker
handle_query_response(DNSServiceOp * const sdr,const CallbackHeader * const cbh,const char * data,const char * const end)1193*48a54d36SAndroid Build Coastguard Worker static void handle_query_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
1194*48a54d36SAndroid Build Coastguard Worker {
1195*48a54d36SAndroid Build Coastguard Worker uint32_t ttl;
1196*48a54d36SAndroid Build Coastguard Worker char name[kDNSServiceMaxDomainName];
1197*48a54d36SAndroid Build Coastguard Worker uint16_t rrtype, rrclass, rdlen;
1198*48a54d36SAndroid Build Coastguard Worker const char *rdata;
1199*48a54d36SAndroid Build Coastguard Worker
1200*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, name, kDNSServiceMaxDomainName);
1201*48a54d36SAndroid Build Coastguard Worker rrtype = get_uint16(&data, end);
1202*48a54d36SAndroid Build Coastguard Worker rrclass = get_uint16(&data, end);
1203*48a54d36SAndroid Build Coastguard Worker rdlen = get_uint16(&data, end);
1204*48a54d36SAndroid Build Coastguard Worker rdata = get_rdata(&data, end, rdlen);
1205*48a54d36SAndroid Build Coastguard Worker ttl = get_uint32(&data, end);
1206*48a54d36SAndroid Build Coastguard Worker
1207*48a54d36SAndroid Build Coastguard Worker if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_query_response: error reading result from daemon");
1208*48a54d36SAndroid Build Coastguard Worker else ((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, name, rrtype, rrclass, rdlen, rdata, ttl, sdr->AppContext);
1209*48a54d36SAndroid Build Coastguard Worker // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
1210*48a54d36SAndroid Build Coastguard Worker }
1211*48a54d36SAndroid Build Coastguard Worker
DNSServiceQueryRecord(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,const char * name,uint16_t rrtype,uint16_t rrclass,DNSServiceQueryRecordReply callBack,void * context)1212*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
1213*48a54d36SAndroid Build Coastguard Worker (
1214*48a54d36SAndroid Build Coastguard Worker DNSServiceRef *sdRef,
1215*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1216*48a54d36SAndroid Build Coastguard Worker uint32_t interfaceIndex,
1217*48a54d36SAndroid Build Coastguard Worker const char *name,
1218*48a54d36SAndroid Build Coastguard Worker uint16_t rrtype,
1219*48a54d36SAndroid Build Coastguard Worker uint16_t rrclass,
1220*48a54d36SAndroid Build Coastguard Worker DNSServiceQueryRecordReply callBack,
1221*48a54d36SAndroid Build Coastguard Worker void *context
1222*48a54d36SAndroid Build Coastguard Worker )
1223*48a54d36SAndroid Build Coastguard Worker {
1224*48a54d36SAndroid Build Coastguard Worker char *ptr;
1225*48a54d36SAndroid Build Coastguard Worker size_t len;
1226*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1227*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err = ConnectToServer(sdRef, flags, query_request, handle_query_response, callBack, context);
1228*48a54d36SAndroid Build Coastguard Worker if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL
1229*48a54d36SAndroid Build Coastguard Worker
1230*48a54d36SAndroid Build Coastguard Worker if (!name) name = "\0";
1231*48a54d36SAndroid Build Coastguard Worker
1232*48a54d36SAndroid Build Coastguard Worker // Calculate total message length
1233*48a54d36SAndroid Build Coastguard Worker len = sizeof(flags);
1234*48a54d36SAndroid Build Coastguard Worker len += sizeof(uint32_t); // interfaceIndex
1235*48a54d36SAndroid Build Coastguard Worker len += strlen(name) + 1;
1236*48a54d36SAndroid Build Coastguard Worker len += 2 * sizeof(uint16_t); // rrtype, rrclass
1237*48a54d36SAndroid Build Coastguard Worker
1238*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(query_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
1239*48a54d36SAndroid Build Coastguard Worker if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
1240*48a54d36SAndroid Build Coastguard Worker
1241*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1242*48a54d36SAndroid Build Coastguard Worker put_uint32(interfaceIndex, &ptr);
1243*48a54d36SAndroid Build Coastguard Worker put_string(name, &ptr);
1244*48a54d36SAndroid Build Coastguard Worker put_uint16(rrtype, &ptr);
1245*48a54d36SAndroid Build Coastguard Worker put_uint16(rrclass, &ptr);
1246*48a54d36SAndroid Build Coastguard Worker
1247*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, *sdRef); // Will free hdr for us
1248*48a54d36SAndroid Build Coastguard Worker if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
1249*48a54d36SAndroid Build Coastguard Worker return err;
1250*48a54d36SAndroid Build Coastguard Worker }
1251*48a54d36SAndroid Build Coastguard Worker
handle_addrinfo_response(DNSServiceOp * const sdr,const CallbackHeader * const cbh,const char * data,const char * const end)1252*48a54d36SAndroid Build Coastguard Worker static void handle_addrinfo_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
1253*48a54d36SAndroid Build Coastguard Worker {
1254*48a54d36SAndroid Build Coastguard Worker char hostname[kDNSServiceMaxDomainName];
1255*48a54d36SAndroid Build Coastguard Worker uint16_t rrtype, rrclass, rdlen;
1256*48a54d36SAndroid Build Coastguard Worker const char *rdata;
1257*48a54d36SAndroid Build Coastguard Worker uint32_t ttl;
1258*48a54d36SAndroid Build Coastguard Worker
1259*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, hostname, kDNSServiceMaxDomainName);
1260*48a54d36SAndroid Build Coastguard Worker rrtype = get_uint16(&data, end);
1261*48a54d36SAndroid Build Coastguard Worker rrclass = get_uint16(&data, end);
1262*48a54d36SAndroid Build Coastguard Worker rdlen = get_uint16(&data, end);
1263*48a54d36SAndroid Build Coastguard Worker rdata = get_rdata (&data, end, rdlen);
1264*48a54d36SAndroid Build Coastguard Worker ttl = get_uint32(&data, end);
1265*48a54d36SAndroid Build Coastguard Worker
1266*48a54d36SAndroid Build Coastguard Worker // We only generate client callbacks for A and AAAA results (including NXDOMAIN results for
1267*48a54d36SAndroid Build Coastguard Worker // those types, if the client has requested those with the kDNSServiceFlagsReturnIntermediates).
1268*48a54d36SAndroid Build Coastguard Worker // Other result types, specifically CNAME referrals, are not communicated to the client, because
1269*48a54d36SAndroid Build Coastguard Worker // the DNSServiceGetAddrInfoReply interface doesn't have any meaningful way to communiate CNAME referrals.
1270*48a54d36SAndroid Build Coastguard Worker if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_addrinfo_response: error reading result from daemon");
1271*48a54d36SAndroid Build Coastguard Worker else if (rrtype == kDNSServiceType_A || rrtype == kDNSServiceType_AAAA)
1272*48a54d36SAndroid Build Coastguard Worker {
1273*48a54d36SAndroid Build Coastguard Worker struct sockaddr_in sa4;
1274*48a54d36SAndroid Build Coastguard Worker struct sockaddr_in6 sa6;
1275*48a54d36SAndroid Build Coastguard Worker const struct sockaddr *const sa = (rrtype == kDNSServiceType_A) ? (struct sockaddr*)&sa4 : (struct sockaddr*)&sa6;
1276*48a54d36SAndroid Build Coastguard Worker if (rrtype == kDNSServiceType_A)
1277*48a54d36SAndroid Build Coastguard Worker {
1278*48a54d36SAndroid Build Coastguard Worker memset(&sa4, 0, sizeof(sa4));
1279*48a54d36SAndroid Build Coastguard Worker #ifndef NOT_HAVE_SA_LEN
1280*48a54d36SAndroid Build Coastguard Worker sa4.sin_len = sizeof(struct sockaddr_in);
1281*48a54d36SAndroid Build Coastguard Worker #endif
1282*48a54d36SAndroid Build Coastguard Worker sa4.sin_family = AF_INET;
1283*48a54d36SAndroid Build Coastguard Worker // sin_port = 0;
1284*48a54d36SAndroid Build Coastguard Worker if (!cbh->cb_err) memcpy(&sa4.sin_addr, rdata, rdlen);
1285*48a54d36SAndroid Build Coastguard Worker }
1286*48a54d36SAndroid Build Coastguard Worker else
1287*48a54d36SAndroid Build Coastguard Worker {
1288*48a54d36SAndroid Build Coastguard Worker memset(&sa6, 0, sizeof(sa6));
1289*48a54d36SAndroid Build Coastguard Worker #ifndef NOT_HAVE_SA_LEN
1290*48a54d36SAndroid Build Coastguard Worker sa6.sin6_len = sizeof(struct sockaddr_in6);
1291*48a54d36SAndroid Build Coastguard Worker #endif
1292*48a54d36SAndroid Build Coastguard Worker sa6.sin6_family = AF_INET6;
1293*48a54d36SAndroid Build Coastguard Worker // sin6_port = 0;
1294*48a54d36SAndroid Build Coastguard Worker // sin6_flowinfo = 0;
1295*48a54d36SAndroid Build Coastguard Worker // sin6_scope_id = 0;
1296*48a54d36SAndroid Build Coastguard Worker if (!cbh->cb_err)
1297*48a54d36SAndroid Build Coastguard Worker {
1298*48a54d36SAndroid Build Coastguard Worker memcpy(&sa6.sin6_addr, rdata, rdlen);
1299*48a54d36SAndroid Build Coastguard Worker if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr)) sa6.sin6_scope_id = cbh->cb_interface;
1300*48a54d36SAndroid Build Coastguard Worker }
1301*48a54d36SAndroid Build Coastguard Worker }
1302*48a54d36SAndroid Build Coastguard Worker ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, hostname, sa, ttl, sdr->AppContext);
1303*48a54d36SAndroid Build Coastguard Worker // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
1304*48a54d36SAndroid Build Coastguard Worker }
1305*48a54d36SAndroid Build Coastguard Worker }
1306*48a54d36SAndroid Build Coastguard Worker
DNSServiceGetAddrInfo(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,uint32_t protocol,const char * hostname,DNSServiceGetAddrInfoReply callBack,void * context)1307*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
1308*48a54d36SAndroid Build Coastguard Worker (
1309*48a54d36SAndroid Build Coastguard Worker DNSServiceRef *sdRef,
1310*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1311*48a54d36SAndroid Build Coastguard Worker uint32_t interfaceIndex,
1312*48a54d36SAndroid Build Coastguard Worker uint32_t protocol,
1313*48a54d36SAndroid Build Coastguard Worker const char *hostname,
1314*48a54d36SAndroid Build Coastguard Worker DNSServiceGetAddrInfoReply callBack,
1315*48a54d36SAndroid Build Coastguard Worker void *context /* may be NULL */
1316*48a54d36SAndroid Build Coastguard Worker )
1317*48a54d36SAndroid Build Coastguard Worker {
1318*48a54d36SAndroid Build Coastguard Worker char *ptr;
1319*48a54d36SAndroid Build Coastguard Worker size_t len;
1320*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1321*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err;
1322*48a54d36SAndroid Build Coastguard Worker
1323*48a54d36SAndroid Build Coastguard Worker if (!hostname) return kDNSServiceErr_BadParam;
1324*48a54d36SAndroid Build Coastguard Worker
1325*48a54d36SAndroid Build Coastguard Worker err = ConnectToServer(sdRef, flags, addrinfo_request, handle_addrinfo_response, callBack, context);
1326*48a54d36SAndroid Build Coastguard Worker if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL
1327*48a54d36SAndroid Build Coastguard Worker
1328*48a54d36SAndroid Build Coastguard Worker // Calculate total message length
1329*48a54d36SAndroid Build Coastguard Worker len = sizeof(flags);
1330*48a54d36SAndroid Build Coastguard Worker len += sizeof(uint32_t); // interfaceIndex
1331*48a54d36SAndroid Build Coastguard Worker len += sizeof(uint32_t); // protocol
1332*48a54d36SAndroid Build Coastguard Worker len += strlen(hostname) + 1;
1333*48a54d36SAndroid Build Coastguard Worker
1334*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(addrinfo_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
1335*48a54d36SAndroid Build Coastguard Worker if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
1336*48a54d36SAndroid Build Coastguard Worker
1337*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1338*48a54d36SAndroid Build Coastguard Worker put_uint32(interfaceIndex, &ptr);
1339*48a54d36SAndroid Build Coastguard Worker put_uint32(protocol, &ptr);
1340*48a54d36SAndroid Build Coastguard Worker put_string(hostname, &ptr);
1341*48a54d36SAndroid Build Coastguard Worker
1342*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, *sdRef); // Will free hdr for us
1343*48a54d36SAndroid Build Coastguard Worker if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
1344*48a54d36SAndroid Build Coastguard Worker return err;
1345*48a54d36SAndroid Build Coastguard Worker }
1346*48a54d36SAndroid Build Coastguard Worker
handle_browse_response(DNSServiceOp * const sdr,const CallbackHeader * const cbh,const char * data,const char * const end)1347*48a54d36SAndroid Build Coastguard Worker static void handle_browse_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
1348*48a54d36SAndroid Build Coastguard Worker {
1349*48a54d36SAndroid Build Coastguard Worker char replyName[256], replyType[kDNSServiceMaxDomainName], replyDomain[kDNSServiceMaxDomainName];
1350*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, replyName, 256);
1351*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, replyType, kDNSServiceMaxDomainName);
1352*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, replyDomain, kDNSServiceMaxDomainName);
1353*48a54d36SAndroid Build Coastguard Worker if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_browse_response: error reading result from daemon");
1354*48a54d36SAndroid Build Coastguard Worker else ((DNSServiceBrowseReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, replyName, replyType, replyDomain, sdr->AppContext);
1355*48a54d36SAndroid Build Coastguard Worker // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
1356*48a54d36SAndroid Build Coastguard Worker }
1357*48a54d36SAndroid Build Coastguard Worker
DNSServiceBrowse(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,const char * regtype,const char * domain,DNSServiceBrowseReply callBack,void * context)1358*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceBrowse
1359*48a54d36SAndroid Build Coastguard Worker (
1360*48a54d36SAndroid Build Coastguard Worker DNSServiceRef *sdRef,
1361*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1362*48a54d36SAndroid Build Coastguard Worker uint32_t interfaceIndex,
1363*48a54d36SAndroid Build Coastguard Worker const char *regtype,
1364*48a54d36SAndroid Build Coastguard Worker const char *domain,
1365*48a54d36SAndroid Build Coastguard Worker DNSServiceBrowseReply callBack,
1366*48a54d36SAndroid Build Coastguard Worker void *context
1367*48a54d36SAndroid Build Coastguard Worker )
1368*48a54d36SAndroid Build Coastguard Worker {
1369*48a54d36SAndroid Build Coastguard Worker char *ptr;
1370*48a54d36SAndroid Build Coastguard Worker size_t len;
1371*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1372*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err = ConnectToServer(sdRef, flags, browse_request, handle_browse_response, callBack, context);
1373*48a54d36SAndroid Build Coastguard Worker if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL
1374*48a54d36SAndroid Build Coastguard Worker
1375*48a54d36SAndroid Build Coastguard Worker if (!domain) domain = "";
1376*48a54d36SAndroid Build Coastguard Worker len = sizeof(flags);
1377*48a54d36SAndroid Build Coastguard Worker len += sizeof(interfaceIndex);
1378*48a54d36SAndroid Build Coastguard Worker len += strlen(regtype) + 1;
1379*48a54d36SAndroid Build Coastguard Worker len += strlen(domain) + 1;
1380*48a54d36SAndroid Build Coastguard Worker
1381*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(browse_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
1382*48a54d36SAndroid Build Coastguard Worker if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
1383*48a54d36SAndroid Build Coastguard Worker
1384*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1385*48a54d36SAndroid Build Coastguard Worker put_uint32(interfaceIndex, &ptr);
1386*48a54d36SAndroid Build Coastguard Worker put_string(regtype, &ptr);
1387*48a54d36SAndroid Build Coastguard Worker put_string(domain, &ptr);
1388*48a54d36SAndroid Build Coastguard Worker
1389*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, *sdRef); // Will free hdr for us
1390*48a54d36SAndroid Build Coastguard Worker if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
1391*48a54d36SAndroid Build Coastguard Worker return err;
1392*48a54d36SAndroid Build Coastguard Worker }
1393*48a54d36SAndroid Build Coastguard Worker
handle_hostname_changed_response(DNSServiceOp * const sdr,const CallbackHeader * const cbh,const char * data,const char * const end)1394*48a54d36SAndroid Build Coastguard Worker static void handle_hostname_changed_response(
1395*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *const sdr,
1396*48a54d36SAndroid Build Coastguard Worker const CallbackHeader *const cbh,
1397*48a54d36SAndroid Build Coastguard Worker const char *data,
1398*48a54d36SAndroid Build Coastguard Worker const char *const end)
1399*48a54d36SAndroid Build Coastguard Worker {
1400*48a54d36SAndroid Build Coastguard Worker char replyHostname[256];
1401*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, replyHostname, sizeof(replyHostname));
1402*48a54d36SAndroid Build Coastguard Worker if (!data) syslog(LOG_WARNING,
1403*48a54d36SAndroid Build Coastguard Worker "dnssd_clientstub handle_hostname_changed_response: error reading result from daemon");
1404*48a54d36SAndroid Build Coastguard Worker else ((DNSHostnameChangedReply)sdr->AppCallback)(
1405*48a54d36SAndroid Build Coastguard Worker sdr, cbh->cb_flags, cbh->cb_err, replyHostname, sdr->AppContext);
1406*48a54d36SAndroid Build Coastguard Worker }
1407*48a54d36SAndroid Build Coastguard Worker
DNSSetHostname(DNSServiceRef * sdRef,DNSServiceFlags flags,const char * hostname,DNSHostnameChangedReply callBack,void * context)1408*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSSetHostname
1409*48a54d36SAndroid Build Coastguard Worker (
1410*48a54d36SAndroid Build Coastguard Worker DNSServiceRef *sdRef,
1411*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1412*48a54d36SAndroid Build Coastguard Worker const char *hostname,
1413*48a54d36SAndroid Build Coastguard Worker DNSHostnameChangedReply callBack,
1414*48a54d36SAndroid Build Coastguard Worker void *context
1415*48a54d36SAndroid Build Coastguard Worker )
1416*48a54d36SAndroid Build Coastguard Worker {
1417*48a54d36SAndroid Build Coastguard Worker char *ptr;
1418*48a54d36SAndroid Build Coastguard Worker size_t len;
1419*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1420*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err = ConnectToServer(sdRef, flags, sethost_request,
1421*48a54d36SAndroid Build Coastguard Worker handle_hostname_changed_response, callBack, context);
1422*48a54d36SAndroid Build Coastguard Worker if (err) return err;
1423*48a54d36SAndroid Build Coastguard Worker len = sizeof(flags);
1424*48a54d36SAndroid Build Coastguard Worker len += strlen(hostname) + 1;
1425*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(sethost_request, &len, &ptr,
1426*48a54d36SAndroid Build Coastguard Worker (*sdRef)->primary ? 1 : 0, *sdRef);
1427*48a54d36SAndroid Build Coastguard Worker if (!hdr)
1428*48a54d36SAndroid Build Coastguard Worker {
1429*48a54d36SAndroid Build Coastguard Worker DNSServiceRefDeallocate(*sdRef);
1430*48a54d36SAndroid Build Coastguard Worker *sdRef = NULL;
1431*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_NoMemory;
1432*48a54d36SAndroid Build Coastguard Worker }
1433*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1434*48a54d36SAndroid Build Coastguard Worker put_string(hostname, &ptr);
1435*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, *sdRef);
1436*48a54d36SAndroid Build Coastguard Worker if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
1437*48a54d36SAndroid Build Coastguard Worker return err;
1438*48a54d36SAndroid Build Coastguard Worker }
1439*48a54d36SAndroid Build Coastguard Worker
1440*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain);
DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags,const char * domain)1441*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain)
1442*48a54d36SAndroid Build Coastguard Worker {
1443*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *tmp;
1444*48a54d36SAndroid Build Coastguard Worker char *ptr;
1445*48a54d36SAndroid Build Coastguard Worker size_t len = sizeof(flags) + strlen(domain) + 1;
1446*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1447*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err = ConnectToServer(&tmp, 0, setdomain_request, NULL, NULL, NULL);
1448*48a54d36SAndroid Build Coastguard Worker if (err) return err;
1449*48a54d36SAndroid Build Coastguard Worker
1450*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(setdomain_request, &len, &ptr, 0, tmp);
1451*48a54d36SAndroid Build Coastguard Worker if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
1452*48a54d36SAndroid Build Coastguard Worker
1453*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1454*48a54d36SAndroid Build Coastguard Worker put_string(domain, &ptr);
1455*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, tmp); // Will free hdr for us
1456*48a54d36SAndroid Build Coastguard Worker DNSServiceRefDeallocate(tmp);
1457*48a54d36SAndroid Build Coastguard Worker return err;
1458*48a54d36SAndroid Build Coastguard Worker }
1459*48a54d36SAndroid Build Coastguard Worker
handle_regservice_response(DNSServiceOp * const sdr,const CallbackHeader * const cbh,const char * data,const char * const end)1460*48a54d36SAndroid Build Coastguard Worker static void handle_regservice_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
1461*48a54d36SAndroid Build Coastguard Worker {
1462*48a54d36SAndroid Build Coastguard Worker char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName];
1463*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, name, 256);
1464*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, regtype, kDNSServiceMaxDomainName);
1465*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, domain, kDNSServiceMaxDomainName);
1466*48a54d36SAndroid Build Coastguard Worker if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_regservice_response: error reading result from daemon");
1467*48a54d36SAndroid Build Coastguard Worker else ((DNSServiceRegisterReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_err, name, regtype, domain, sdr->AppContext);
1468*48a54d36SAndroid Build Coastguard Worker // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
1469*48a54d36SAndroid Build Coastguard Worker }
1470*48a54d36SAndroid Build Coastguard Worker
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)1471*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceRegister
1472*48a54d36SAndroid Build Coastguard Worker (
1473*48a54d36SAndroid Build Coastguard Worker DNSServiceRef *sdRef,
1474*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1475*48a54d36SAndroid Build Coastguard Worker uint32_t interfaceIndex,
1476*48a54d36SAndroid Build Coastguard Worker const char *name,
1477*48a54d36SAndroid Build Coastguard Worker const char *regtype,
1478*48a54d36SAndroid Build Coastguard Worker const char *domain,
1479*48a54d36SAndroid Build Coastguard Worker const char *host,
1480*48a54d36SAndroid Build Coastguard Worker uint16_t PortInNetworkByteOrder,
1481*48a54d36SAndroid Build Coastguard Worker uint16_t txtLen,
1482*48a54d36SAndroid Build Coastguard Worker const void *txtRecord,
1483*48a54d36SAndroid Build Coastguard Worker DNSServiceRegisterReply callBack,
1484*48a54d36SAndroid Build Coastguard Worker void *context
1485*48a54d36SAndroid Build Coastguard Worker )
1486*48a54d36SAndroid Build Coastguard Worker {
1487*48a54d36SAndroid Build Coastguard Worker char *ptr;
1488*48a54d36SAndroid Build Coastguard Worker size_t len;
1489*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1490*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err;
1491*48a54d36SAndroid Build Coastguard Worker union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder };
1492*48a54d36SAndroid Build Coastguard Worker
1493*48a54d36SAndroid Build Coastguard Worker if (!name) name = "";
1494*48a54d36SAndroid Build Coastguard Worker if (!regtype) return kDNSServiceErr_BadParam;
1495*48a54d36SAndroid Build Coastguard Worker if (!domain) domain = "";
1496*48a54d36SAndroid Build Coastguard Worker if (!host) host = "";
1497*48a54d36SAndroid Build Coastguard Worker if (!txtRecord) txtRecord = (void*)"";
1498*48a54d36SAndroid Build Coastguard Worker
1499*48a54d36SAndroid Build Coastguard Worker // No callback must have auto-rename
1500*48a54d36SAndroid Build Coastguard Worker if (!callBack && (flags & kDNSServiceFlagsNoAutoRename)) return kDNSServiceErr_BadParam;
1501*48a54d36SAndroid Build Coastguard Worker
1502*48a54d36SAndroid Build Coastguard Worker err = ConnectToServer(sdRef, flags, reg_service_request, callBack ? handle_regservice_response : NULL, callBack, context);
1503*48a54d36SAndroid Build Coastguard Worker if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL
1504*48a54d36SAndroid Build Coastguard Worker
1505*48a54d36SAndroid Build Coastguard Worker len = sizeof(DNSServiceFlags);
1506*48a54d36SAndroid Build Coastguard Worker len += sizeof(uint32_t); // interfaceIndex
1507*48a54d36SAndroid Build Coastguard Worker len += strlen(name) + strlen(regtype) + strlen(domain) + strlen(host) + 4;
1508*48a54d36SAndroid Build Coastguard Worker len += 2 * sizeof(uint16_t); // port, txtLen
1509*48a54d36SAndroid Build Coastguard Worker len += txtLen;
1510*48a54d36SAndroid Build Coastguard Worker
1511*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(reg_service_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
1512*48a54d36SAndroid Build Coastguard Worker if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
1513*48a54d36SAndroid Build Coastguard Worker if (!callBack) hdr->ipc_flags |= IPC_FLAGS_NOREPLY;
1514*48a54d36SAndroid Build Coastguard Worker
1515*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1516*48a54d36SAndroid Build Coastguard Worker put_uint32(interfaceIndex, &ptr);
1517*48a54d36SAndroid Build Coastguard Worker put_string(name, &ptr);
1518*48a54d36SAndroid Build Coastguard Worker put_string(regtype, &ptr);
1519*48a54d36SAndroid Build Coastguard Worker put_string(domain, &ptr);
1520*48a54d36SAndroid Build Coastguard Worker put_string(host, &ptr);
1521*48a54d36SAndroid Build Coastguard Worker *ptr++ = port.b[0];
1522*48a54d36SAndroid Build Coastguard Worker *ptr++ = port.b[1];
1523*48a54d36SAndroid Build Coastguard Worker put_uint16(txtLen, &ptr);
1524*48a54d36SAndroid Build Coastguard Worker put_rdata(txtLen, txtRecord, &ptr);
1525*48a54d36SAndroid Build Coastguard Worker
1526*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, *sdRef); // Will free hdr for us
1527*48a54d36SAndroid Build Coastguard Worker if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
1528*48a54d36SAndroid Build Coastguard Worker return err;
1529*48a54d36SAndroid Build Coastguard Worker }
1530*48a54d36SAndroid Build Coastguard Worker
handle_enumeration_response(DNSServiceOp * const sdr,const CallbackHeader * const cbh,const char * data,const char * const end)1531*48a54d36SAndroid Build Coastguard Worker static void handle_enumeration_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
1532*48a54d36SAndroid Build Coastguard Worker {
1533*48a54d36SAndroid Build Coastguard Worker char domain[kDNSServiceMaxDomainName];
1534*48a54d36SAndroid Build Coastguard Worker get_string(&data, end, domain, kDNSServiceMaxDomainName);
1535*48a54d36SAndroid Build Coastguard Worker if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_enumeration_response: error reading result from daemon");
1536*48a54d36SAndroid Build Coastguard Worker else ((DNSServiceDomainEnumReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, domain, sdr->AppContext);
1537*48a54d36SAndroid Build Coastguard Worker // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
1538*48a54d36SAndroid Build Coastguard Worker }
1539*48a54d36SAndroid Build Coastguard Worker
DNSServiceEnumerateDomains(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceDomainEnumReply callBack,void * context)1540*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
1541*48a54d36SAndroid Build Coastguard Worker (
1542*48a54d36SAndroid Build Coastguard Worker DNSServiceRef *sdRef,
1543*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1544*48a54d36SAndroid Build Coastguard Worker uint32_t interfaceIndex,
1545*48a54d36SAndroid Build Coastguard Worker DNSServiceDomainEnumReply callBack,
1546*48a54d36SAndroid Build Coastguard Worker void *context
1547*48a54d36SAndroid Build Coastguard Worker )
1548*48a54d36SAndroid Build Coastguard Worker {
1549*48a54d36SAndroid Build Coastguard Worker char *ptr;
1550*48a54d36SAndroid Build Coastguard Worker size_t len;
1551*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1552*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err;
1553*48a54d36SAndroid Build Coastguard Worker
1554*48a54d36SAndroid Build Coastguard Worker int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0;
1555*48a54d36SAndroid Build Coastguard Worker int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0;
1556*48a54d36SAndroid Build Coastguard Worker if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
1557*48a54d36SAndroid Build Coastguard Worker
1558*48a54d36SAndroid Build Coastguard Worker err = ConnectToServer(sdRef, flags, enumeration_request, handle_enumeration_response, callBack, context);
1559*48a54d36SAndroid Build Coastguard Worker if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL
1560*48a54d36SAndroid Build Coastguard Worker
1561*48a54d36SAndroid Build Coastguard Worker len = sizeof(DNSServiceFlags);
1562*48a54d36SAndroid Build Coastguard Worker len += sizeof(uint32_t);
1563*48a54d36SAndroid Build Coastguard Worker
1564*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(enumeration_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
1565*48a54d36SAndroid Build Coastguard Worker if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
1566*48a54d36SAndroid Build Coastguard Worker
1567*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1568*48a54d36SAndroid Build Coastguard Worker put_uint32(interfaceIndex, &ptr);
1569*48a54d36SAndroid Build Coastguard Worker
1570*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, *sdRef); // Will free hdr for us
1571*48a54d36SAndroid Build Coastguard Worker if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
1572*48a54d36SAndroid Build Coastguard Worker return err;
1573*48a54d36SAndroid Build Coastguard Worker }
1574*48a54d36SAndroid Build Coastguard Worker
ConnectionResponse(DNSServiceOp * const sdr,const CallbackHeader * const cbh,const char * const data,const char * const end)1575*48a54d36SAndroid Build Coastguard Worker static void ConnectionResponse(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *const data, const char *const end)
1576*48a54d36SAndroid Build Coastguard Worker {
1577*48a54d36SAndroid Build Coastguard Worker DNSRecordRef rref = cbh->ipc_hdr.client_context.context;
1578*48a54d36SAndroid Build Coastguard Worker (void)data; // Unused
1579*48a54d36SAndroid Build Coastguard Worker
1580*48a54d36SAndroid Build Coastguard Worker //printf("ConnectionResponse got %d\n", cbh->ipc_hdr.op);
1581*48a54d36SAndroid Build Coastguard Worker if (cbh->ipc_hdr.op != reg_record_reply_op)
1582*48a54d36SAndroid Build Coastguard Worker {
1583*48a54d36SAndroid Build Coastguard Worker // When using kDNSServiceFlagsShareConnection, need to search the list of associated DNSServiceOps
1584*48a54d36SAndroid Build Coastguard Worker // to find the one this response is intended for, and then call through to its ProcessReply handler.
1585*48a54d36SAndroid Build Coastguard Worker // We start with our first subordinate DNSServiceRef -- don't want to accidentally match the parent DNSServiceRef.
1586*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *op = sdr->next;
1587*48a54d36SAndroid Build Coastguard Worker while (op && (op->uid.u32[0] != cbh->ipc_hdr.client_context.u32[0] || op->uid.u32[1] != cbh->ipc_hdr.client_context.u32[1]))
1588*48a54d36SAndroid Build Coastguard Worker op = op->next;
1589*48a54d36SAndroid Build Coastguard Worker // Note: We may sometimes not find a matching DNSServiceOp, in the case where the client has
1590*48a54d36SAndroid Build Coastguard Worker // cancelled the subordinate DNSServiceOp, but there are still messages in the pipeline from the daemon
1591*48a54d36SAndroid Build Coastguard Worker if (op && op->ProcessReply) op->ProcessReply(op, cbh, data, end);
1592*48a54d36SAndroid Build Coastguard Worker // WARNING: Don't touch op or sdr after this -- client may have called DNSServiceRefDeallocate
1593*48a54d36SAndroid Build Coastguard Worker return;
1594*48a54d36SAndroid Build Coastguard Worker }
1595*48a54d36SAndroid Build Coastguard Worker
1596*48a54d36SAndroid Build Coastguard Worker if (sdr->op == connection_request)
1597*48a54d36SAndroid Build Coastguard Worker rref->AppCallback(rref->sdr, rref, cbh->cb_flags, cbh->cb_err, rref->AppContext);
1598*48a54d36SAndroid Build Coastguard Worker else
1599*48a54d36SAndroid Build Coastguard Worker {
1600*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub ConnectionResponse: sdr->op != connection_request");
1601*48a54d36SAndroid Build Coastguard Worker rref->AppCallback(rref->sdr, rref, 0, kDNSServiceErr_Unknown, rref->AppContext);
1602*48a54d36SAndroid Build Coastguard Worker }
1603*48a54d36SAndroid Build Coastguard Worker // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
1604*48a54d36SAndroid Build Coastguard Worker }
1605*48a54d36SAndroid Build Coastguard Worker
DNSServiceCreateConnection(DNSServiceRef * sdRef)1606*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef)
1607*48a54d36SAndroid Build Coastguard Worker {
1608*48a54d36SAndroid Build Coastguard Worker char *ptr;
1609*48a54d36SAndroid Build Coastguard Worker size_t len = 0;
1610*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1611*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err = ConnectToServer(sdRef, 0, connection_request, ConnectionResponse, NULL, NULL);
1612*48a54d36SAndroid Build Coastguard Worker if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL
1613*48a54d36SAndroid Build Coastguard Worker
1614*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(connection_request, &len, &ptr, 0, *sdRef);
1615*48a54d36SAndroid Build Coastguard Worker if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
1616*48a54d36SAndroid Build Coastguard Worker
1617*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, *sdRef); // Will free hdr for us
1618*48a54d36SAndroid Build Coastguard Worker if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
1619*48a54d36SAndroid Build Coastguard Worker return err;
1620*48a54d36SAndroid Build Coastguard Worker }
1621*48a54d36SAndroid Build Coastguard Worker
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)1622*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
1623*48a54d36SAndroid Build Coastguard Worker (
1624*48a54d36SAndroid Build Coastguard Worker DNSServiceRef sdRef,
1625*48a54d36SAndroid Build Coastguard Worker DNSRecordRef *RecordRef,
1626*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1627*48a54d36SAndroid Build Coastguard Worker uint32_t interfaceIndex,
1628*48a54d36SAndroid Build Coastguard Worker const char *fullname,
1629*48a54d36SAndroid Build Coastguard Worker uint16_t rrtype,
1630*48a54d36SAndroid Build Coastguard Worker uint16_t rrclass,
1631*48a54d36SAndroid Build Coastguard Worker uint16_t rdlen,
1632*48a54d36SAndroid Build Coastguard Worker const void *rdata,
1633*48a54d36SAndroid Build Coastguard Worker uint32_t ttl,
1634*48a54d36SAndroid Build Coastguard Worker DNSServiceRegisterRecordReply callBack,
1635*48a54d36SAndroid Build Coastguard Worker void *context
1636*48a54d36SAndroid Build Coastguard Worker )
1637*48a54d36SAndroid Build Coastguard Worker {
1638*48a54d36SAndroid Build Coastguard Worker char *ptr;
1639*48a54d36SAndroid Build Coastguard Worker size_t len;
1640*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr = NULL;
1641*48a54d36SAndroid Build Coastguard Worker DNSRecordRef rref = NULL;
1642*48a54d36SAndroid Build Coastguard Worker DNSRecord **p;
1643*48a54d36SAndroid Build Coastguard Worker int f1 = (flags & kDNSServiceFlagsShared) != 0;
1644*48a54d36SAndroid Build Coastguard Worker int f2 = (flags & kDNSServiceFlagsUnique) != 0;
1645*48a54d36SAndroid Build Coastguard Worker if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
1646*48a54d36SAndroid Build Coastguard Worker
1647*48a54d36SAndroid Build Coastguard Worker if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
1648*48a54d36SAndroid Build Coastguard Worker
1649*48a54d36SAndroid Build Coastguard Worker if (!DNSServiceRefValid(sdRef))
1650*48a54d36SAndroid Build Coastguard Worker {
1651*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
1652*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadReference;
1653*48a54d36SAndroid Build Coastguard Worker }
1654*48a54d36SAndroid Build Coastguard Worker
1655*48a54d36SAndroid Build Coastguard Worker if (sdRef->op != connection_request)
1656*48a54d36SAndroid Build Coastguard Worker {
1657*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with non-DNSServiceCreateConnection DNSServiceRef %p %d", sdRef, sdRef->op);
1658*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadReference;
1659*48a54d36SAndroid Build Coastguard Worker }
1660*48a54d36SAndroid Build Coastguard Worker
1661*48a54d36SAndroid Build Coastguard Worker *RecordRef = NULL;
1662*48a54d36SAndroid Build Coastguard Worker
1663*48a54d36SAndroid Build Coastguard Worker len = sizeof(DNSServiceFlags);
1664*48a54d36SAndroid Build Coastguard Worker len += 2 * sizeof(uint32_t); // interfaceIndex, ttl
1665*48a54d36SAndroid Build Coastguard Worker len += 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen
1666*48a54d36SAndroid Build Coastguard Worker len += strlen(fullname) + 1;
1667*48a54d36SAndroid Build Coastguard Worker len += rdlen;
1668*48a54d36SAndroid Build Coastguard Worker
1669*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(reg_record_request, &len, &ptr, 1, sdRef);
1670*48a54d36SAndroid Build Coastguard Worker if (!hdr) return kDNSServiceErr_NoMemory;
1671*48a54d36SAndroid Build Coastguard Worker
1672*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1673*48a54d36SAndroid Build Coastguard Worker put_uint32(interfaceIndex, &ptr);
1674*48a54d36SAndroid Build Coastguard Worker put_string(fullname, &ptr);
1675*48a54d36SAndroid Build Coastguard Worker put_uint16(rrtype, &ptr);
1676*48a54d36SAndroid Build Coastguard Worker put_uint16(rrclass, &ptr);
1677*48a54d36SAndroid Build Coastguard Worker put_uint16(rdlen, &ptr);
1678*48a54d36SAndroid Build Coastguard Worker put_rdata(rdlen, rdata, &ptr);
1679*48a54d36SAndroid Build Coastguard Worker put_uint32(ttl, &ptr);
1680*48a54d36SAndroid Build Coastguard Worker
1681*48a54d36SAndroid Build Coastguard Worker rref = malloc(sizeof(DNSRecord));
1682*48a54d36SAndroid Build Coastguard Worker if (!rref) { free(hdr); return kDNSServiceErr_NoMemory; }
1683*48a54d36SAndroid Build Coastguard Worker rref->AppContext = context;
1684*48a54d36SAndroid Build Coastguard Worker rref->AppCallback = callBack;
1685*48a54d36SAndroid Build Coastguard Worker rref->record_index = sdRef->max_index++;
1686*48a54d36SAndroid Build Coastguard Worker rref->sdr = sdRef;
1687*48a54d36SAndroid Build Coastguard Worker rref->recnext = NULL;
1688*48a54d36SAndroid Build Coastguard Worker *RecordRef = rref;
1689*48a54d36SAndroid Build Coastguard Worker hdr->client_context.context = rref;
1690*48a54d36SAndroid Build Coastguard Worker hdr->reg_index = rref->record_index;
1691*48a54d36SAndroid Build Coastguard Worker
1692*48a54d36SAndroid Build Coastguard Worker p = &(sdRef)->rec;
1693*48a54d36SAndroid Build Coastguard Worker while (*p) p = &(*p)->recnext;
1694*48a54d36SAndroid Build Coastguard Worker *p = rref;
1695*48a54d36SAndroid Build Coastguard Worker
1696*48a54d36SAndroid Build Coastguard Worker return deliver_request(hdr, sdRef); // Will free hdr for us
1697*48a54d36SAndroid Build Coastguard Worker }
1698*48a54d36SAndroid Build Coastguard Worker
1699*48a54d36SAndroid Build Coastguard Worker // sdRef returned by DNSServiceRegister()
DNSServiceAddRecord(DNSServiceRef sdRef,DNSRecordRef * RecordRef,DNSServiceFlags flags,uint16_t rrtype,uint16_t rdlen,const void * rdata,uint32_t ttl)1700*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceAddRecord
1701*48a54d36SAndroid Build Coastguard Worker (
1702*48a54d36SAndroid Build Coastguard Worker DNSServiceRef sdRef,
1703*48a54d36SAndroid Build Coastguard Worker DNSRecordRef *RecordRef,
1704*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1705*48a54d36SAndroid Build Coastguard Worker uint16_t rrtype,
1706*48a54d36SAndroid Build Coastguard Worker uint16_t rdlen,
1707*48a54d36SAndroid Build Coastguard Worker const void *rdata,
1708*48a54d36SAndroid Build Coastguard Worker uint32_t ttl
1709*48a54d36SAndroid Build Coastguard Worker )
1710*48a54d36SAndroid Build Coastguard Worker {
1711*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1712*48a54d36SAndroid Build Coastguard Worker size_t len = 0;
1713*48a54d36SAndroid Build Coastguard Worker char *ptr;
1714*48a54d36SAndroid Build Coastguard Worker DNSRecordRef rref;
1715*48a54d36SAndroid Build Coastguard Worker DNSRecord **p;
1716*48a54d36SAndroid Build Coastguard Worker
1717*48a54d36SAndroid Build Coastguard Worker if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
1718*48a54d36SAndroid Build Coastguard Worker if (!RecordRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSRecordRef pointer"); return kDNSServiceErr_BadParam; }
1719*48a54d36SAndroid Build Coastguard Worker if (sdRef->op != reg_service_request)
1720*48a54d36SAndroid Build Coastguard Worker {
1721*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with non-DNSServiceRegister DNSServiceRef %p %d", sdRef, sdRef->op);
1722*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadReference;
1723*48a54d36SAndroid Build Coastguard Worker }
1724*48a54d36SAndroid Build Coastguard Worker
1725*48a54d36SAndroid Build Coastguard Worker if (!DNSServiceRefValid(sdRef))
1726*48a54d36SAndroid Build Coastguard Worker {
1727*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
1728*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadReference;
1729*48a54d36SAndroid Build Coastguard Worker }
1730*48a54d36SAndroid Build Coastguard Worker
1731*48a54d36SAndroid Build Coastguard Worker *RecordRef = NULL;
1732*48a54d36SAndroid Build Coastguard Worker
1733*48a54d36SAndroid Build Coastguard Worker len += 2 * sizeof(uint16_t); // rrtype, rdlen
1734*48a54d36SAndroid Build Coastguard Worker len += rdlen;
1735*48a54d36SAndroid Build Coastguard Worker len += sizeof(uint32_t);
1736*48a54d36SAndroid Build Coastguard Worker len += sizeof(DNSServiceFlags);
1737*48a54d36SAndroid Build Coastguard Worker
1738*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(add_record_request, &len, &ptr, 1, sdRef);
1739*48a54d36SAndroid Build Coastguard Worker if (!hdr) return kDNSServiceErr_NoMemory;
1740*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1741*48a54d36SAndroid Build Coastguard Worker put_uint16(rrtype, &ptr);
1742*48a54d36SAndroid Build Coastguard Worker put_uint16(rdlen, &ptr);
1743*48a54d36SAndroid Build Coastguard Worker put_rdata(rdlen, rdata, &ptr);
1744*48a54d36SAndroid Build Coastguard Worker put_uint32(ttl, &ptr);
1745*48a54d36SAndroid Build Coastguard Worker
1746*48a54d36SAndroid Build Coastguard Worker rref = malloc(sizeof(DNSRecord));
1747*48a54d36SAndroid Build Coastguard Worker if (!rref) { free(hdr); return kDNSServiceErr_NoMemory; }
1748*48a54d36SAndroid Build Coastguard Worker rref->AppContext = NULL;
1749*48a54d36SAndroid Build Coastguard Worker rref->AppCallback = NULL;
1750*48a54d36SAndroid Build Coastguard Worker rref->record_index = sdRef->max_index++;
1751*48a54d36SAndroid Build Coastguard Worker rref->sdr = sdRef;
1752*48a54d36SAndroid Build Coastguard Worker rref->recnext = NULL;
1753*48a54d36SAndroid Build Coastguard Worker *RecordRef = rref;
1754*48a54d36SAndroid Build Coastguard Worker hdr->reg_index = rref->record_index;
1755*48a54d36SAndroid Build Coastguard Worker
1756*48a54d36SAndroid Build Coastguard Worker p = &(sdRef)->rec;
1757*48a54d36SAndroid Build Coastguard Worker while (*p) p = &(*p)->recnext;
1758*48a54d36SAndroid Build Coastguard Worker *p = rref;
1759*48a54d36SAndroid Build Coastguard Worker
1760*48a54d36SAndroid Build Coastguard Worker return deliver_request(hdr, sdRef); // Will free hdr for us
1761*48a54d36SAndroid Build Coastguard Worker }
1762*48a54d36SAndroid Build Coastguard Worker
1763*48a54d36SAndroid Build Coastguard Worker // DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord
DNSServiceUpdateRecord(DNSServiceRef sdRef,DNSRecordRef RecordRef,DNSServiceFlags flags,uint16_t rdlen,const void * rdata,uint32_t ttl)1764*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
1765*48a54d36SAndroid Build Coastguard Worker (
1766*48a54d36SAndroid Build Coastguard Worker DNSServiceRef sdRef,
1767*48a54d36SAndroid Build Coastguard Worker DNSRecordRef RecordRef,
1768*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1769*48a54d36SAndroid Build Coastguard Worker uint16_t rdlen,
1770*48a54d36SAndroid Build Coastguard Worker const void *rdata,
1771*48a54d36SAndroid Build Coastguard Worker uint32_t ttl
1772*48a54d36SAndroid Build Coastguard Worker )
1773*48a54d36SAndroid Build Coastguard Worker {
1774*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1775*48a54d36SAndroid Build Coastguard Worker size_t len = 0;
1776*48a54d36SAndroid Build Coastguard Worker char *ptr;
1777*48a54d36SAndroid Build Coastguard Worker
1778*48a54d36SAndroid Build Coastguard Worker if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
1779*48a54d36SAndroid Build Coastguard Worker
1780*48a54d36SAndroid Build Coastguard Worker if (!DNSServiceRefValid(sdRef))
1781*48a54d36SAndroid Build Coastguard Worker {
1782*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
1783*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadReference;
1784*48a54d36SAndroid Build Coastguard Worker }
1785*48a54d36SAndroid Build Coastguard Worker
1786*48a54d36SAndroid Build Coastguard Worker // Note: RecordRef is allowed to be NULL
1787*48a54d36SAndroid Build Coastguard Worker
1788*48a54d36SAndroid Build Coastguard Worker len += sizeof(uint16_t);
1789*48a54d36SAndroid Build Coastguard Worker len += rdlen;
1790*48a54d36SAndroid Build Coastguard Worker len += sizeof(uint32_t);
1791*48a54d36SAndroid Build Coastguard Worker len += sizeof(DNSServiceFlags);
1792*48a54d36SAndroid Build Coastguard Worker
1793*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(update_record_request, &len, &ptr, 1, sdRef);
1794*48a54d36SAndroid Build Coastguard Worker if (!hdr) return kDNSServiceErr_NoMemory;
1795*48a54d36SAndroid Build Coastguard Worker hdr->reg_index = RecordRef ? RecordRef->record_index : TXT_RECORD_INDEX;
1796*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1797*48a54d36SAndroid Build Coastguard Worker put_uint16(rdlen, &ptr);
1798*48a54d36SAndroid Build Coastguard Worker put_rdata(rdlen, rdata, &ptr);
1799*48a54d36SAndroid Build Coastguard Worker put_uint32(ttl, &ptr);
1800*48a54d36SAndroid Build Coastguard Worker return deliver_request(hdr, sdRef); // Will free hdr for us
1801*48a54d36SAndroid Build Coastguard Worker }
1802*48a54d36SAndroid Build Coastguard Worker
DNSServiceRemoveRecord(DNSServiceRef sdRef,DNSRecordRef RecordRef,DNSServiceFlags flags)1803*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
1804*48a54d36SAndroid Build Coastguard Worker (
1805*48a54d36SAndroid Build Coastguard Worker DNSServiceRef sdRef,
1806*48a54d36SAndroid Build Coastguard Worker DNSRecordRef RecordRef,
1807*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags
1808*48a54d36SAndroid Build Coastguard Worker )
1809*48a54d36SAndroid Build Coastguard Worker {
1810*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1811*48a54d36SAndroid Build Coastguard Worker size_t len = 0;
1812*48a54d36SAndroid Build Coastguard Worker char *ptr;
1813*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err;
1814*48a54d36SAndroid Build Coastguard Worker
1815*48a54d36SAndroid Build Coastguard Worker if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
1816*48a54d36SAndroid Build Coastguard Worker if (!RecordRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSRecordRef"); return kDNSServiceErr_BadParam; }
1817*48a54d36SAndroid Build Coastguard Worker if (!sdRef->max_index) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with bad DNSServiceRef"); return kDNSServiceErr_BadReference; }
1818*48a54d36SAndroid Build Coastguard Worker
1819*48a54d36SAndroid Build Coastguard Worker if (!DNSServiceRefValid(sdRef))
1820*48a54d36SAndroid Build Coastguard Worker {
1821*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
1822*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadReference;
1823*48a54d36SAndroid Build Coastguard Worker }
1824*48a54d36SAndroid Build Coastguard Worker
1825*48a54d36SAndroid Build Coastguard Worker len += sizeof(flags);
1826*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(remove_record_request, &len, &ptr, 1, sdRef);
1827*48a54d36SAndroid Build Coastguard Worker if (!hdr) return kDNSServiceErr_NoMemory;
1828*48a54d36SAndroid Build Coastguard Worker hdr->reg_index = RecordRef->record_index;
1829*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1830*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, sdRef); // Will free hdr for us
1831*48a54d36SAndroid Build Coastguard Worker if (!err)
1832*48a54d36SAndroid Build Coastguard Worker {
1833*48a54d36SAndroid Build Coastguard Worker // This RecordRef could have been allocated in DNSServiceRegisterRecord or DNSServiceAddRecord.
1834*48a54d36SAndroid Build Coastguard Worker // If so, delink from the list before freeing
1835*48a54d36SAndroid Build Coastguard Worker DNSRecord **p = &sdRef->rec;
1836*48a54d36SAndroid Build Coastguard Worker while (*p && *p != RecordRef) p = &(*p)->recnext;
1837*48a54d36SAndroid Build Coastguard Worker if (*p) *p = RecordRef->recnext;
1838*48a54d36SAndroid Build Coastguard Worker free(RecordRef);
1839*48a54d36SAndroid Build Coastguard Worker }
1840*48a54d36SAndroid Build Coastguard Worker return err;
1841*48a54d36SAndroid Build Coastguard Worker }
1842*48a54d36SAndroid Build Coastguard Worker
DNSServiceReconfirmRecord(DNSServiceFlags flags,uint32_t interfaceIndex,const char * fullname,uint16_t rrtype,uint16_t rrclass,uint16_t rdlen,const void * rdata)1843*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
1844*48a54d36SAndroid Build Coastguard Worker (
1845*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1846*48a54d36SAndroid Build Coastguard Worker uint32_t interfaceIndex,
1847*48a54d36SAndroid Build Coastguard Worker const char *fullname,
1848*48a54d36SAndroid Build Coastguard Worker uint16_t rrtype,
1849*48a54d36SAndroid Build Coastguard Worker uint16_t rrclass,
1850*48a54d36SAndroid Build Coastguard Worker uint16_t rdlen,
1851*48a54d36SAndroid Build Coastguard Worker const void *rdata
1852*48a54d36SAndroid Build Coastguard Worker )
1853*48a54d36SAndroid Build Coastguard Worker {
1854*48a54d36SAndroid Build Coastguard Worker char *ptr;
1855*48a54d36SAndroid Build Coastguard Worker size_t len;
1856*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1857*48a54d36SAndroid Build Coastguard Worker DNSServiceOp *tmp;
1858*48a54d36SAndroid Build Coastguard Worker
1859*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL);
1860*48a54d36SAndroid Build Coastguard Worker if (err) return err;
1861*48a54d36SAndroid Build Coastguard Worker
1862*48a54d36SAndroid Build Coastguard Worker len = sizeof(DNSServiceFlags);
1863*48a54d36SAndroid Build Coastguard Worker len += sizeof(uint32_t);
1864*48a54d36SAndroid Build Coastguard Worker len += strlen(fullname) + 1;
1865*48a54d36SAndroid Build Coastguard Worker len += 3 * sizeof(uint16_t);
1866*48a54d36SAndroid Build Coastguard Worker len += rdlen;
1867*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(reconfirm_record_request, &len, &ptr, 0, tmp);
1868*48a54d36SAndroid Build Coastguard Worker if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
1869*48a54d36SAndroid Build Coastguard Worker
1870*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1871*48a54d36SAndroid Build Coastguard Worker put_uint32(interfaceIndex, &ptr);
1872*48a54d36SAndroid Build Coastguard Worker put_string(fullname, &ptr);
1873*48a54d36SAndroid Build Coastguard Worker put_uint16(rrtype, &ptr);
1874*48a54d36SAndroid Build Coastguard Worker put_uint16(rrclass, &ptr);
1875*48a54d36SAndroid Build Coastguard Worker put_uint16(rdlen, &ptr);
1876*48a54d36SAndroid Build Coastguard Worker put_rdata(rdlen, rdata, &ptr);
1877*48a54d36SAndroid Build Coastguard Worker
1878*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, tmp); // Will free hdr for us
1879*48a54d36SAndroid Build Coastguard Worker DNSServiceRefDeallocate(tmp);
1880*48a54d36SAndroid Build Coastguard Worker return err;
1881*48a54d36SAndroid Build Coastguard Worker }
1882*48a54d36SAndroid Build Coastguard Worker
handle_port_mapping_response(DNSServiceOp * const sdr,const CallbackHeader * const cbh,const char * data,const char * const end)1883*48a54d36SAndroid Build Coastguard Worker static void handle_port_mapping_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
1884*48a54d36SAndroid Build Coastguard Worker {
1885*48a54d36SAndroid Build Coastguard Worker union { uint32_t l; u_char b[4]; } addr;
1886*48a54d36SAndroid Build Coastguard Worker uint8_t protocol;
1887*48a54d36SAndroid Build Coastguard Worker union { uint16_t s; u_char b[2]; } internalPort;
1888*48a54d36SAndroid Build Coastguard Worker union { uint16_t s; u_char b[2]; } externalPort;
1889*48a54d36SAndroid Build Coastguard Worker uint32_t ttl;
1890*48a54d36SAndroid Build Coastguard Worker
1891*48a54d36SAndroid Build Coastguard Worker if (!data || data + 13 > end) goto fail;
1892*48a54d36SAndroid Build Coastguard Worker
1893*48a54d36SAndroid Build Coastguard Worker addr .b[0] = *data++;
1894*48a54d36SAndroid Build Coastguard Worker addr .b[1] = *data++;
1895*48a54d36SAndroid Build Coastguard Worker addr .b[2] = *data++;
1896*48a54d36SAndroid Build Coastguard Worker addr .b[3] = *data++;
1897*48a54d36SAndroid Build Coastguard Worker protocol = *data++;
1898*48a54d36SAndroid Build Coastguard Worker internalPort.b[0] = *data++;
1899*48a54d36SAndroid Build Coastguard Worker internalPort.b[1] = *data++;
1900*48a54d36SAndroid Build Coastguard Worker externalPort.b[0] = *data++;
1901*48a54d36SAndroid Build Coastguard Worker externalPort.b[1] = *data++;
1902*48a54d36SAndroid Build Coastguard Worker ttl = get_uint32(&data, end);
1903*48a54d36SAndroid Build Coastguard Worker if (!data) goto fail;
1904*48a54d36SAndroid Build Coastguard Worker
1905*48a54d36SAndroid Build Coastguard Worker ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, addr.l, protocol, internalPort.s, externalPort.s, ttl, sdr->AppContext);
1906*48a54d36SAndroid Build Coastguard Worker return;
1907*48a54d36SAndroid Build Coastguard Worker // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
1908*48a54d36SAndroid Build Coastguard Worker
1909*48a54d36SAndroid Build Coastguard Worker fail:
1910*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub handle_port_mapping_response: error reading result from daemon");
1911*48a54d36SAndroid Build Coastguard Worker }
1912*48a54d36SAndroid Build Coastguard Worker
DNSServiceNATPortMappingCreate(DNSServiceRef * sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,uint32_t protocol,uint16_t internalPortInNetworkByteOrder,uint16_t externalPortInNetworkByteOrder,uint32_t ttl,DNSServiceNATPortMappingReply callBack,void * context)1913*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
1914*48a54d36SAndroid Build Coastguard Worker (
1915*48a54d36SAndroid Build Coastguard Worker DNSServiceRef *sdRef,
1916*48a54d36SAndroid Build Coastguard Worker DNSServiceFlags flags,
1917*48a54d36SAndroid Build Coastguard Worker uint32_t interfaceIndex,
1918*48a54d36SAndroid Build Coastguard Worker uint32_t protocol, /* TCP and/or UDP */
1919*48a54d36SAndroid Build Coastguard Worker uint16_t internalPortInNetworkByteOrder,
1920*48a54d36SAndroid Build Coastguard Worker uint16_t externalPortInNetworkByteOrder,
1921*48a54d36SAndroid Build Coastguard Worker uint32_t ttl, /* time to live in seconds */
1922*48a54d36SAndroid Build Coastguard Worker DNSServiceNATPortMappingReply callBack,
1923*48a54d36SAndroid Build Coastguard Worker void *context /* may be NULL */
1924*48a54d36SAndroid Build Coastguard Worker )
1925*48a54d36SAndroid Build Coastguard Worker {
1926*48a54d36SAndroid Build Coastguard Worker char *ptr;
1927*48a54d36SAndroid Build Coastguard Worker size_t len;
1928*48a54d36SAndroid Build Coastguard Worker ipc_msg_hdr *hdr;
1929*48a54d36SAndroid Build Coastguard Worker union { uint16_t s; u_char b[2]; } internalPort = { internalPortInNetworkByteOrder };
1930*48a54d36SAndroid Build Coastguard Worker union { uint16_t s; u_char b[2]; } externalPort = { externalPortInNetworkByteOrder };
1931*48a54d36SAndroid Build Coastguard Worker
1932*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType err = ConnectToServer(sdRef, flags, port_mapping_request, handle_port_mapping_response, callBack, context);
1933*48a54d36SAndroid Build Coastguard Worker if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL
1934*48a54d36SAndroid Build Coastguard Worker
1935*48a54d36SAndroid Build Coastguard Worker len = sizeof(flags);
1936*48a54d36SAndroid Build Coastguard Worker len += sizeof(interfaceIndex);
1937*48a54d36SAndroid Build Coastguard Worker len += sizeof(protocol);
1938*48a54d36SAndroid Build Coastguard Worker len += sizeof(internalPort);
1939*48a54d36SAndroid Build Coastguard Worker len += sizeof(externalPort);
1940*48a54d36SAndroid Build Coastguard Worker len += sizeof(ttl);
1941*48a54d36SAndroid Build Coastguard Worker
1942*48a54d36SAndroid Build Coastguard Worker hdr = create_hdr(port_mapping_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
1943*48a54d36SAndroid Build Coastguard Worker if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
1944*48a54d36SAndroid Build Coastguard Worker
1945*48a54d36SAndroid Build Coastguard Worker put_flags(flags, &ptr);
1946*48a54d36SAndroid Build Coastguard Worker put_uint32(interfaceIndex, &ptr);
1947*48a54d36SAndroid Build Coastguard Worker put_uint32(protocol, &ptr);
1948*48a54d36SAndroid Build Coastguard Worker *ptr++ = internalPort.b[0];
1949*48a54d36SAndroid Build Coastguard Worker *ptr++ = internalPort.b[1];
1950*48a54d36SAndroid Build Coastguard Worker *ptr++ = externalPort.b[0];
1951*48a54d36SAndroid Build Coastguard Worker *ptr++ = externalPort.b[1];
1952*48a54d36SAndroid Build Coastguard Worker put_uint32(ttl, &ptr);
1953*48a54d36SAndroid Build Coastguard Worker
1954*48a54d36SAndroid Build Coastguard Worker err = deliver_request(hdr, *sdRef); // Will free hdr for us
1955*48a54d36SAndroid Build Coastguard Worker if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
1956*48a54d36SAndroid Build Coastguard Worker return err;
1957*48a54d36SAndroid Build Coastguard Worker }
1958*48a54d36SAndroid Build Coastguard Worker
1959*48a54d36SAndroid Build Coastguard Worker #if _DNS_SD_LIBDISPATCH
DNSServiceSetDispatchQueue(DNSServiceRef service,dispatch_queue_t queue)1960*48a54d36SAndroid Build Coastguard Worker DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue
1961*48a54d36SAndroid Build Coastguard Worker (
1962*48a54d36SAndroid Build Coastguard Worker DNSServiceRef service,
1963*48a54d36SAndroid Build Coastguard Worker dispatch_queue_t queue
1964*48a54d36SAndroid Build Coastguard Worker )
1965*48a54d36SAndroid Build Coastguard Worker {
1966*48a54d36SAndroid Build Coastguard Worker int dnssd_fd = DNSServiceRefSockFD(service);
1967*48a54d36SAndroid Build Coastguard Worker if (dnssd_fd == dnssd_InvalidSocket) return kDNSServiceErr_BadParam;
1968*48a54d36SAndroid Build Coastguard Worker if (!queue)
1969*48a54d36SAndroid Build Coastguard Worker {
1970*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub: DNSServiceSetDispatchQueue dispatch queue NULL");
1971*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadParam;
1972*48a54d36SAndroid Build Coastguard Worker }
1973*48a54d36SAndroid Build Coastguard Worker if (service->disp_queue)
1974*48a54d36SAndroid Build Coastguard Worker {
1975*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSetDispatchQueue dispatch queue set already");
1976*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadParam;
1977*48a54d36SAndroid Build Coastguard Worker }
1978*48a54d36SAndroid Build Coastguard Worker if (service->disp_source)
1979*48a54d36SAndroid Build Coastguard Worker {
1980*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch source set already");
1981*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_BadParam;
1982*48a54d36SAndroid Build Coastguard Worker }
1983*48a54d36SAndroid Build Coastguard Worker service->disp_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, dnssd_fd, 0, queue);
1984*48a54d36SAndroid Build Coastguard Worker if (!service->disp_source)
1985*48a54d36SAndroid Build Coastguard Worker {
1986*48a54d36SAndroid Build Coastguard Worker syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch_source_create failed");
1987*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_NoMemory;
1988*48a54d36SAndroid Build Coastguard Worker }
1989*48a54d36SAndroid Build Coastguard Worker service->disp_queue = queue;
1990*48a54d36SAndroid Build Coastguard Worker dispatch_source_set_event_handler(service->disp_source, ^{DNSServiceProcessResult(service);});
1991*48a54d36SAndroid Build Coastguard Worker dispatch_source_set_cancel_handler(service->disp_source, ^{dnssd_close(dnssd_fd);});
1992*48a54d36SAndroid Build Coastguard Worker dispatch_resume(service->disp_source);
1993*48a54d36SAndroid Build Coastguard Worker return kDNSServiceErr_NoError;
1994*48a54d36SAndroid Build Coastguard Worker }
1995*48a54d36SAndroid Build Coastguard Worker #endif // _DNS_SD_LIBDISPATCH
1996