dnssd_clientstub.c revision 4904:cd464a980538
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 $ 31Revision 1.53 2006/09/07 04:43:12 herscher 32Fix compile error on Win32 platform by moving inclusion of syslog.h 33 34Revision 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 37Revision 1.51 2006/07/24 23:45:55 cheshire 38<rdar://problem/4605276> DNSServiceReconfirmRecord() should return error code 39 40Revision 1.50 2006/06/28 08:22:27 cheshire 41<rdar://problem/4605264> dnssd_clientstub.c needs to report unlink failures in syslog 42 43Revision 1.49 2006/06/28 07:58:59 cheshire 44Minor textual tidying 45 46Revision 1.48 2005/06/30 18:01:00 shersche 47<rdar://problem/4096913> Clients shouldn't wait ten seconds to connect to mDNSResponder 48 49Revision 1.47 2005/03/31 02:19:56 cheshire 50<rdar://problem/4021486> Fix build warnings 51Reviewed by: Scott Herscher 52 53Revision 1.46 2005/03/21 00:39:31 shersche 54<rdar://problem/4021486> Fix build warnings on Win32 platform 55 56Revision 1.45 2005/02/01 01:25:06 shersche 57Define sleep() to be Sleep() for Windows compatibility 58 59Revision 1.44 2005/01/27 22:57:56 cheshire 60Fix compile errors on gcc4 61 62Revision 1.43 2005/01/27 00:02:29 cheshire 63<rdar://problem/3947461> Handle case where client runs before daemon has finished launching 64 65Revision 1.42 2005/01/11 02:01:02 shersche 66Use dnssd_close() rather than close() for Windows compatibility 67 68Revision 1.41 2004/12/23 17:34:26 ksekar 69<rdar://problem/3931319> Calls leak sockets if mDNSResponder is not running 70 71Revision 1.40 2004/11/23 03:39:47 cheshire 72Let interface name/index mapping capability live directly in JNISupport.c, 73instead of having to call through to the daemon via IPC to get this information. 74 75Revision 1.39 2004/11/12 03:22:00 rpantos 76rdar://problem/3809541 Add DNSSDMapIfIndexToName, DNSSDMapNameToIfIndex. 77 78Revision 1.38 2004/11/02 02:51:23 cheshire 79<rdar://problem/3526342> Remove overly-restrictive flag checks 80 81Revision 1.37 2004/10/14 01:43:35 cheshire 82Fix opaque port passing problem 83 84Revision 1.36 2004/10/06 02:22:19 cheshire 85Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)" 86 87Revision 1.35 2004/10/01 22:15:55 rpantos 88rdar://problem/3824265: Replace APSL in client lib with BSD license. 89 90Revision 1.34 2004/09/17 22:36:13 cheshire 91Add comment explaining that deliver_request frees the message it sends 92 93Revision 1.33 2004/09/17 01:17:31 ksekar 94Remove double-free of msg header, freed automatically by deliver_request() 95 96Revision 1.32 2004/09/17 01:08:55 cheshire 97Renamed 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 102Revision 1.31 2004/09/16 23:37:19 cheshire 103Free hdr before returning 104 105Revision 1.30 2004/09/16 23:14:24 cheshire 106Changes for Windows compatibility 107 108Revision 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 111Revision 1.28 2004/08/11 17:10:04 cheshire 112Fix signed/unsigned warnings 113 114Revision 1.27 2004/08/11 00:54:16 cheshire 115Change "hdr->op.request_op" to just "hdr->op" 116 117Revision 1.26 2004/07/26 06:07:27 shersche 118fix bugs when using an error socket to communicate with the daemon 119 120Revision 1.25 2004/07/26 05:54:02 shersche 121DNSServiceProcessResult() returns NoError if socket read returns EWOULDBLOCK 122 123Revision 1.24 2004/07/20 06:46:21 shersche 124<rdar://problem/3730123> fix endless loop in read_all() if recv returns 0 125Bug #: 3730123 126 127Revision 1.23 2004/06/29 00:48:38 cheshire 128Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; 129use an explicit while() loop instead. 130 131Revision 1.22 2004/06/26 03:16:34 shersche 132clean up warning messages on Win32 platform 133 134Submitted by: herscher 135 136Revision 1.21 2004/06/18 04:53:56 rpantos 137Use platform layer for socket types. Introduce USE_TCP_LOOPBACK. Remove dependency on mDNSEmbeddedAPI.h. 138 139Revision 1.20 2004/06/12 00:50:22 cheshire 140Changes for Windows compatibility 141 142Revision 1.19 2004/05/25 18:29:33 cheshire 143Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c, 144so that it's also accessible to dnssd_clientshim.c (single address space) clients. 145 146Revision 1.18 2004/05/18 23:51:27 cheshire 147Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers 148 149Revision 1.17 2004/05/06 18:42:58 ksekar 150General 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 154Revision 1.16 2004/03/12 22:00:37 cheshire 155Added: #include <sys/socket.h> 156 157Revision 1.15 2004/01/20 18:36:29 ksekar 158Propagated Libinfo fix for <rdar://problem/3483971>: SU: 159DNSServiceUpdateRecord() doesn't allow you to update the TXT record 160into TOT mDNSResponder. 161 162Revision 1.14 2004/01/19 22:39:17 cheshire 163Don't use "MSG_WAITALL"; it makes send() return "Invalid argument" on Linux; 164use an explicit while() loop instead. (In any case, this should only make a difference 165with non-blocking sockets, which we don't use on the client side right now.) 166 167Revision 1.13 2004/01/19 21:46:52 cheshire 168Fix compiler warning 169 170Revision 1.12 2003/12/23 20:46:47 ksekar 171<rdar://problem/3497428>: sync dnssd files between libinfo & mDNSResponder 172 173Revision 1.11 2003/12/08 21:11:42 rpantos 174Changes necessary to support mDNSResponder on Linux. 175 176Revision 1.10 2003/10/13 23:50:53 ksekar 177Updated dns_sd clientstub files to bring copies in synch with 178top-of-tree Libinfo: A memory leak in dnssd_clientstub.c is fixed, 179and comments in dns_sd.h are improved. 180 181Revision 1.9 2003/08/15 21:30:39 cheshire 182Bring up to date with LibInfo version 183 184Revision 1.8 2003/08/13 23:54:52 ksekar 185Bringing dnssd_clientstub.c up to date with Libinfo, per radar 3376640 186 187Revision 1.7 2003/08/12 19:56:25 cheshire 188Update 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 213extern BOOL IsSystemServiceDisabled(); 214 215#define sleep(X) Sleep((X) * 1000) 216 217static 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 240typedef 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 250typedef 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 262static 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 277static 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 305static 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) 353static 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 416static 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 494cleanup: 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 510int 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. 518DNSServiceErrorType 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 549void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef) 550 { 551 if (!sdRef) return; 552 if (sdRef->sockfd > 0) dnssd_close(sdRef->sockfd); 553 free(sdRef); 554 } 555 556static 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 583DNSServiceErrorType 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 639error: 640 if (msg) free(msg); 641 if (*sdRef) { free(*sdRef); *sdRef = NULL; } 642 return kDNSServiceErr_Unknown; 643 } 644 645static 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 672DNSServiceErrorType 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 727error: 728 if (msg) free(msg); 729 if (*sdRef) { free(*sdRef); *sdRef = NULL; } 730 return kDNSServiceErr_Unknown; 731 } 732 733static 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 753DNSServiceErrorType 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 803error: 804 if (msg) free(msg); 805 if (*sdRef) { free(*sdRef); *sdRef = NULL; } 806 return kDNSServiceErr_Unknown; 807 } 808 809DNSServiceErrorType 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 833static 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 852DNSServiceErrorType 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 929error: 930 if (msg) free(msg); 931 if (*sdRef) { free(*sdRef); *sdRef = NULL; } 932 return kDNSServiceErr_Unknown; 933 } 934 935static 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 952DNSServiceErrorType 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 999error: 1000 if (msg) free(msg); 1001 if (*sdRef) { free(*sdRef); *sdRef = NULL; } 1002 return kDNSServiceErr_Unknown; 1003 } 1004 1005static 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 1024DNSServiceErrorType 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 1035DNSServiceErrorType 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 1094error: 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() 1102DNSServiceErrorType 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 1146error: 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 1154DNSServiceErrorType 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 1185DNSServiceErrorType 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 1210DNSServiceErrorType 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