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 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 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 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) 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 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 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. 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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() 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 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 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 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