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