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