X-Git-Url: https://git.saurik.com/apple/libinfo.git/blobdiff_plain/ccd4a120fd72e1cd2071458320f7a1914ef55421..c29bb6474e693870dcd24352d6f5c9049a3210d8:/mdns.subproj/dnssd_clientstub.c diff --git a/mdns.subproj/dnssd_clientstub.c b/mdns.subproj/dnssd_clientstub.c index eed342f..e2e4fc1 100644 --- a/mdns.subproj/dnssd_clientstub.c +++ b/mdns.subproj/dnssd_clientstub.c @@ -1,32 +1,198 @@ -/* - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. +/* -*- Mode: C; tab-width: 4 -*- * - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ + * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Change History (most recent first): + +$Log: dnssd_clientstub.c,v $ +Revision 1.20.70.3 2006/05/02 16:17:04 majka +Make NumTries unsigned. + +Revision 1.20.70.2 2006/05/01 21:43:09 majka +Additional change (make NumTries static) for 4527193 +SUChardLondon Libinfo-222.4.6 + +Revision 1.20.70.1 2006/05/01 16:10:54 majka +Libinfo-222_4_5 is equivalent to Chardonnay Libinfo-222.0.5 + +Revision 1.20.60.1 2006/04/27 21:33:30 majka +Integrated 4527193 + +Revision 1.20 2005/02/03 00:39:05 majka +Integrated 3942900 + +Revision 1.19.4.1 2005/02/02 00:47:40 ksekar + dnd-sd shows the wrong port numbers + +Revision 1.19 2004/12/23 23:10:59 majka +*** empty log message *** + +Revision 1.18.8.1 2004/12/23 17:32:56 ksekar + Rendevzous calls leak sockets if mDNSResponder is not running + +Revision 1.18 2004/12/14 18:02:00 majka +*** empty log message *** + +Revision 1.17.36.1 2004/12/13 17:22:39 ksekar + Deprecate the DNSServiceDiscovery.h API in Tiger + Add kDNSServiceInterfaceForceMulticast to header + Remove overly-restrictive flag checks + +Revision 1.17 2004/09/22 20:05:38 majka +Integrated +3725573 - Need Error Codes for handling Lighthouse setup failure on NAT +3805822 - Socket-based APIs aren't endian-safe +3806739 - DNSServiceSetDefaultDomainForUser header comments incorrect + +Revision 1.16.2.1 2004/09/20 21:54:33 ksekar + Socket-based APIs aren't endian-safe + +Revision 1.16 2004/09/17 20:19:00 majka +Integrated 3804522 + +Revision 1.15.2.1 2004/09/17 20:15:30 ksekar +*** empty log message *** + +Revision 1.15 2004/09/16 23:45:24 majka +Integrated 3775315 and 3765280. + +Revision 1.14.4.1 2004/09/02 19:43:41 ksekar +: Sync dns-sd client files between Libinfo and +mDNSResponder projects + +Revision 1.28 2004/08/11 17:10:04 cheshire +Fix signed/unsigned warnings + +Revision 1.27 2004/08/11 00:54:16 cheshire +Change "hdr->op.request_op" to just "hdr->op" + +Revision 1.26 2004/07/26 06:07:27 shersche +fix bugs when using an error socket to communicate with the daemon + +Revision 1.25 2004/07/26 05:54:02 shersche +DNSServiceProcessResult() returns NoError if socket read returns EWOULDBLOCK + +Revision 1.24 2004/07/20 06:46:21 shersche + fix endless loop in my_read() if recv returns 0 +Bug #: 3730123 + +Revision 1.23 2004/06/29 00:48:38 cheshire +Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; +use an explicit while() loop instead. + +Revision 1.22 2004/06/26 03:16:34 shersche +clean up warning messages on Win32 platform + +Submitted by: herscher + +Revision 1.21 2004/06/18 04:53:56 rpantos +Use platform layer for socket types. Introduce USE_TCP_LOOPBACK. Remove dependency on mDNSClientAPI.h. + +Revision 1.20 2004/06/12 00:50:22 cheshire +Changes for Windows compatibility + +Revision 1.19 2004/05/25 18:29:33 cheshire +Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c, +so that it's also accessible to dnssd_clientshim.c (single address space) clients. + +Revision 1.18 2004/05/18 23:51:27 cheshire +Tidy up all checkin comments to use consistent "" format for bug numbers + +Revision 1.17 2004/05/06 18:42:58 ksekar +General dns_sd.h API cleanup, including the following radars: +: Remove flags with zero value +: Passing in NULL causes a crash. + +Revision 1.16 2004/03/12 22:00:37 cheshire +Added: #include + +Revision 1.15 2004/01/20 18:36:29 ksekar +Propagated Libinfo fix for : SU: +DNSServiceUpdateRecord() doesn't allow you to update the TXT record +into TOT mDNSResponder. + +Revision 1.14 2004/01/19 22:39:17 cheshire +Don't use "MSG_WAITALL"; it makes send() return "Invalid argument" on Linux; +use an explicit while() loop instead. (In any case, this should only make a difference +with non-blocking sockets, which we don't use on the client side right now.) + +Revision 1.13 2004/01/19 21:46:52 cheshire +Fix compiler warning + +Revision 1.12 2003/12/23 20:46:47 ksekar +: sync dnssd files between libinfo & mDNSResponder + +Revision 1.11 2003/12/08 21:11:42 rpantos +Changes necessary to support mDNSResponder on Linux. + +Revision 1.10 2003/10/13 23:50:53 ksekar +Updated dns_sd clientstub files to bring copies in synch with +top-of-tree Libinfo: A memory leak in dnssd_clientstub.c is fixed, +and comments in dns_sd.h are improved. + +Revision 1.9 2003/08/15 21:30:39 cheshire +Bring up to date with LibInfo version + +Revision 1.8 2003/08/13 23:54:52 ksekar +Bringing dnssd_clientstub.c up to date with Libinfo, per radar 3376640 + +Revision 1.7 2003/08/12 19:56:25 cheshire +Update to APSL 2.0 + */ -#include "dnssd_ipc.h" #include +#include +#if defined(_WIN32) +#include +#include +#define sockaddr_mdns sockaddr_in +#define AF_MDNS AF_INET +#else #include +#include +#define sockaddr_mdns sockaddr_un +#define AF_MDNS AF_LOCAL +#endif + +#include "dnssd_ipc.h" + +#if defined(_WIN32) +// disable warning: "'type cast' : from data pointer 'void *' to +// function pointer" +#pragma warning(disable:4055) +// disable warning: "nonstandard extension, function/data pointer +// conversion in expression" +#pragma warning(disable:4152) + +#define sleep(X) Sleep((X) * 1000) + +static int g_initWinsock = 0; +#endif #define CTL_PATH_PREFIX "/tmp/dnssd_clippath." @@ -34,101 +200,337 @@ // last 3 digits of the time (in seconds) and n is the 6-digit microsecond time // general utility functions -static DNSServiceRef connect_to_server(void); -DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reuse_sd); -static ipc_msg_hdr *create_hdr(int op, int *len, char **data_start, int reuse_socket); -static int my_read(int sd, char *buf, int len); -static int my_write(int sd, char *buf, int len); -static int domain_ends_in_dot(const char *dom); -// server response handlers -static void handle_query_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *msg); -static void handle_browse_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data); -static void handle_regservice_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data); -static void handle_regrecord_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data); -static void handle_enumeration_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data); -static void handle_resolve_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data); - typedef struct _DNSServiceRef_t { - int sockfd; // connected socket between client and daemon - int op; // request/reply_op_t + dnssd_sock_t sockfd; // connected socket between client and daemon + uint32_t op; // request_op_t or reply_op_t process_reply_callback process_reply; void *app_callback; void *app_context; uint32_t max_index; //largest assigned record index - 0 if no additl. recs registered - } _DNSServiceRef_t; + } _DNSServiceRef_t; typedef struct _DNSRecordRef_t { void *app_context; DNSServiceRegisterRecordReply app_callback; DNSRecordRef recref; - int record_index; // index is unique to the ServiceDiscoveryRef + uint32_t record_index; // index is unique to the ServiceDiscoveryRef DNSServiceRef sdr; } _DNSRecordRef_t; - // exported functions -int DNSServiceRefSockFD(DNSServiceRef sdRef) +// write len bytes. return 0 on success, -1 on error +static int my_write(dnssd_sock_t sd, char *buf, int len) + { + // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead. + //if (send(sd, buf, len, MSG_WAITALL) != len) return -1; + while (len) + { + ssize_t num_written = send(sd, buf, len, 0); + if (num_written < 0 || num_written > len) return -1; + buf += num_written; + len -= num_written; + } + return 0; + } + +// read len bytes. return 0 on success, -1 on error +static int my_read(dnssd_sock_t sd, char *buf, int len) + { + // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead. + //if (recv(sd, buf, len, MSG_WAITALL) != len) return -1; + while (len) + { + ssize_t num_read = recv(sd, buf, len, 0); + if ((num_read == 0) || (num_read < 0) || (num_read > len)) return -1; + buf += num_read; + len -= num_read; + } + return 0; + } + +/* create_hdr + * + * allocate and initialize an ipc message header. value of len should initially be the + * length of the data, and is set to the value of the data plus the header. data_start + * is set to point to the beginning of the data section. reuse_socket should be non-zero + * for calls that can receive an immediate error return value on their primary socket. + * if zero, the path to a control socket is appended at the beginning of the message buffer. + * data_start is set past this string. + */ + +static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int reuse_socket) + { + char *msg = NULL; + ipc_msg_hdr *hdr; + int datalen; + char ctrl_path[256]; + + if (!reuse_socket) + { +#if defined(USE_TCP_LOOPBACK) + *len += 2; // Allocate space for two-byte port number +#else + struct timeval time; + if (gettimeofday(&time, NULL) < 0) return NULL; + sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(), + (unsigned long)(time.tv_sec & 0xFFF), (unsigned long)(time.tv_usec)); + *len += strlen(ctrl_path) + 1; +#endif + } + + datalen = (int) *len; + *len += sizeof(ipc_msg_hdr); + + // write message to buffer + msg = malloc(*len); + if (!msg) return NULL; + + bzero(msg, *len); + hdr = (void *)msg; + hdr->datalen = datalen; + hdr->version = VERSION; + hdr->op = op; + if (reuse_socket) hdr->flags |= IPC_FLAGS_REUSE_SOCKET; + *data_start = msg + sizeof(ipc_msg_hdr); +#if defined(USE_TCP_LOOPBACK) + // Put dummy data in for the port, since we don't know what + // it is yet. The data will get filled in before we + // send the message. This happens in deliver_request(). + if (!reuse_socket) put_short(0, data_start); +#else + if (!reuse_socket) put_string(ctrl_path, data_start); +#endif + return hdr; + } + + // return a connected service ref (deallocate with DNSServiceRefDeallocate) +static DNSServiceRef connect_to_server(void) + { + dnssd_sockaddr_t saddr; + DNSServiceRef sdr; + static unsigned int NumTries = 0; + +#if defined(_WIN32) + if (!g_initWinsock) + { + WSADATA wsaData; + DNSServiceErrorType err; + + g_initWinsock = 1; + + err = WSAStartup( MAKEWORD( 2, 2 ), &wsaData ); + + if (err != 0) return NULL; + } +#endif + + sdr = malloc(sizeof(_DNSServiceRef_t)); + if (!sdr) return(NULL); + sdr->sockfd = socket(AF_DNSSD, SOCK_STREAM, 0); + if (sdr->sockfd == dnssd_InvalidSocket) { free(sdr); return NULL; } +#if defined(USE_TCP_LOOPBACK) + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR); + saddr.sin_port = htons(MDNS_TCP_SERVERPORT); +#else + saddr.sun_family = AF_LOCAL; + strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH); +#endif + while (1) + { + int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr)); + if (!err) break; // If we succeeded, return sdr + // If we failed, then it may be because the daemon is still launching. + // This can happen for processes that launch early in the boot process, while the + // daemon is still coming up. Rather than fail here, we'll wait a bit and try again. + // If, after ten seconds, we still can't connect to the daemon, + // then we give up and return a failure code. + if (++NumTries < 3) + sleep(1); // Sleep a bit, then try again + else + { + dnssd_close(sdr->sockfd); + sdr->sockfd = dnssd_InvalidSocket; + free(sdr); + return NULL; + } + } + return sdr; + } + +static DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reuse_sd) + { + ipc_msg_hdr *hdr = msg; + uint32_t datalen = hdr->datalen; + dnssd_sockaddr_t caddr, daddr; // (client and daemon address structs) + char *data = (char *)msg + sizeof(ipc_msg_hdr); + dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket; + int ret; + unsigned int len = sizeof(caddr); + DNSServiceErrorType err = kDNSServiceErr_Unknown; + + if (!hdr || sdr->sockfd < 0) return kDNSServiceErr_Unknown; + + if (!reuse_sd) + { + // setup temporary error socket + if ((listenfd = socket(AF_DNSSD, SOCK_STREAM, 0)) < 0) + goto cleanup; + bzero(&caddr, sizeof(caddr)); + +#if defined(USE_TCP_LOOPBACK) + { + union { uint16_t s; u_char b[2]; } port; + caddr.sin_family = AF_INET; + caddr.sin_port = 0; + caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR); + ret = bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr)); + if (ret < 0) goto cleanup; + if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) goto cleanup; + listen(listenfd, 1); + port.s = caddr.sin_port; + data[0] = port.b[0]; // don't switch the byte order, as the + data[1] = port.b[1]; // daemon expects it in network byte order + } +#else + { + mode_t mask = umask(0); + caddr.sun_family = AF_LOCAL; +#ifndef NOT_HAVE_SA_LEN // According to Stevens (section 3.2), there is no portable way to + // determine whether sa_len is defined on a particular platform. + caddr.sun_len = sizeof(struct sockaddr_un); +#endif + strcpy(caddr.sun_path, data); + ret = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr)); + umask(mask); + if (ret < 0) goto cleanup; + listen(listenfd, 1); + } +#endif + } + + ConvertHeaderBytes(hdr); + if (my_write(sdr->sockfd, msg, datalen + sizeof(ipc_msg_hdr)) < 0) + goto cleanup; + free(msg); + msg = NULL; + + if (reuse_sd) errsd = sdr->sockfd; + else + { + len = sizeof(daddr); + errsd = accept(listenfd, (struct sockaddr *)&daddr, &len); + if (errsd < 0) goto cleanup; + } + + if (my_read(errsd, (char*)&err, (int)sizeof(err)) < 0) + err = kDNSServiceErr_Unknown; + else + err = ntohl(err); + +cleanup: + if (!reuse_sd && listenfd > 0) dnssd_close(listenfd); + if (!reuse_sd && errsd > 0) dnssd_close(errsd); +#if !defined(USE_TCP_LOOPBACK) + if (!reuse_sd && data) unlink(data); +#endif + if (msg) free(msg); + return err; + } + +int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef) { if (!sdRef) return -1; - return sdRef->sockfd; + return (int) sdRef->sockfd; } // handle reply from server, calling application client callback. If there is no reply // from the daemon on the socket contained in sdRef, the call will block. -DNSServiceErrorType DNSServiceProcessResult(DNSServiceRef sdRef) +DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef) { ipc_msg_hdr hdr; char *data; - if (!sdRef || sdRef->sockfd < 0 || !sdRef->process_reply) + if (!sdRef || sdRef->sockfd < 0 || !sdRef->process_reply) return kDNSServiceErr_BadReference; - if (my_read(sdRef->sockfd, (void *)&hdr, sizeof(hdr)) < 0) - return kDNSServiceErr_Unknown; + if (my_read(sdRef->sockfd, (void *)&hdr, sizeof(hdr)) < 0) + // return NoError on EWOULDBLOCK. This will handle the case + // where a non-blocking socket is told there is data, but + // it was a false positive. + return (dnssd_errno() == dnssd_EWOULDBLOCK) ? kDNSServiceErr_NoError : kDNSServiceErr_Unknown; + ConvertHeaderBytes(&hdr); if (hdr.version != VERSION) return kDNSServiceErr_Incompatible; data = malloc(hdr.datalen); if (!data) return kDNSServiceErr_NoMemory; - if (my_read(sdRef->sockfd, data, hdr.datalen) < 0) + if (my_read(sdRef->sockfd, data, hdr.datalen) < 0) return kDNSServiceErr_Unknown; sdRef->process_reply(sdRef, &hdr, data); free(data); return kDNSServiceErr_NoError; } - -void DNSServiceRefDeallocate(DNSServiceRef sdRef) +void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef) { if (!sdRef) return; - if (sdRef->sockfd > 0) close(sdRef->sockfd); + if (sdRef->sockfd > 0) dnssd_close(sdRef->sockfd); free(sdRef); } +static void handle_resolve_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) + { + DNSServiceFlags flags; + char fullname[kDNSServiceMaxDomainName]; + char target[kDNSServiceMaxDomainName]; + uint16_t txtlen; + union { uint16_t s; u_char b[2]; } port; + uint32_t ifi; + DNSServiceErrorType err; + char *txtrecord; + int str_error = 0; + (void)hdr; //unused + + flags = get_flags(&data); + ifi = get_long(&data); + err = get_error_code(&data); + if (get_string(&data, fullname, kDNSServiceMaxDomainName) < 0) str_error = 1; + if (get_string(&data, target, kDNSServiceMaxDomainName) < 0) str_error = 1; + port.b[0] = *data++; + port.b[1] = *data++; + txtlen = get_short(&data); + txtrecord = get_rdata(&data, txtlen); + + if (!err && str_error) err = kDNSServiceErr_Unknown; + ((DNSServiceResolveReply)sdr->app_callback)(sdr, flags, ifi, err, fullname, target, port.s, txtlen, txtrecord, sdr->app_context); + } -DNSServiceErrorType DNSServiceResolve +DNSServiceErrorType DNSSD_API DNSServiceResolve ( DNSServiceRef *sdRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain, - const DNSServiceResolveReply callBack, + DNSServiceResolveReply callBack, void *context ) { char *msg = NULL, *ptr; - int len; + size_t len; ipc_msg_hdr *hdr; DNSServiceRef sdr; DNSServiceErrorType err; - + if (!sdRef) return kDNSServiceErr_BadParam; *sdRef = NULL; - + + if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam; + // calculate total message length len = sizeof(flags); len += sizeof(interfaceIndex); @@ -145,7 +547,7 @@ DNSServiceErrorType DNSServiceResolve put_string(name, &ptr); put_string(regtype, &ptr); put_string(domain, &ptr); - + sdr = connect_to_server(); if (!sdr) goto error; err = deliver_request(msg, sdr, 1); @@ -159,7 +561,7 @@ DNSServiceErrorType DNSServiceResolve sdr->app_callback = callBack; sdr->app_context = context; *sdRef = sdr; - + return err; error: @@ -167,53 +569,52 @@ error: if (*sdRef) { free(*sdRef); *sdRef = NULL; } return kDNSServiceErr_Unknown; } - - -static void handle_resolve_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) + +static void handle_query_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) { DNSServiceFlags flags; - char fullname[kDNSServiceMaxDomainName]; - char target[kDNSServiceMaxDomainName]; - uint16_t port, txtlen; - uint32_t ifi; - DNSServiceErrorType err; - char *txtrecord; - - (void)hdr; //unused - + uint32_t interfaceIndex, ttl; + DNSServiceErrorType errorCode; + char name[kDNSServiceMaxDomainName]; + uint16_t rrtype, rrclass, rdlen; + char *rdata; + int str_error = 0; + (void)hdr;//Unused + flags = get_flags(&data); - ifi = get_long(&data); - err = get_error_code(&data); - get_string(&data, fullname, kDNSServiceMaxDomainName); - get_string(&data, target, kDNSServiceMaxDomainName); - port = get_short(&data); - txtlen = get_short(&data); - txtrecord = get_rdata(&data, txtlen); - - ((DNSServiceResolveReply)sdr->app_callback)(sdr, flags, ifi, err, fullname, target, port, txtlen, txtrecord, sdr->app_context); - } - - + interfaceIndex = get_long(&data); + errorCode = get_error_code(&data); + if (get_string(&data, name, kDNSServiceMaxDomainName) < 0) str_error = 1; + rrtype = get_short(&data); + rrclass = get_short(&data); + rdlen = get_short(&data); + rdata = get_rdata(&data, rdlen); + ttl = get_long(&data); + if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown; + ((DNSServiceQueryRecordReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, name, rrtype, rrclass, + rdlen, rdata, ttl, sdr->app_context); + return; + } -DNSServiceErrorType DNSServiceQueryRecord +DNSServiceErrorType DNSSD_API DNSServiceQueryRecord ( DNSServiceRef *sdRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *name, - const uint16_t rrtype, - const uint16_t rrclass, - const DNSServiceQueryRecordReply callBack, + uint16_t rrtype, + uint16_t rrclass, + DNSServiceQueryRecordReply callBack, void *context ) { char *msg = NULL, *ptr; - int len; + size_t len; ipc_msg_hdr *hdr; DNSServiceRef sdr; DNSServiceErrorType err; - + if (!sdRef) return kDNSServiceErr_BadParam; *sdRef = NULL; @@ -257,45 +658,39 @@ error: return kDNSServiceErr_Unknown; } - -static void handle_query_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) +static void handle_browse_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) { - DNSServiceFlags flags; - uint32_t interfaceIndex, ttl; - DNSServiceErrorType errorCode; - char name[256]; - uint16_t rrtype, rrclass, rdlen; - char *rdata; - (void)hdr;//Unused + DNSServiceFlags flags; + uint32_t interfaceIndex; + DNSServiceErrorType errorCode; + char replyName[256], replyType[kDNSServiceMaxDomainName], + replyDomain[kDNSServiceMaxDomainName]; + int str_error = 0; + (void)hdr;//Unused flags = get_flags(&data); interfaceIndex = get_long(&data); errorCode = get_error_code(&data); - (get_string(&data, name, 256) < 0); - rrtype = get_short(&data); - rrclass = get_short(&data); - rdlen = get_short(&data); - rdata = get_rdata(&data, rdlen); - ttl = get_long(&data); - if (!rdata) return; - ((DNSServiceQueryRecordReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, name, rrtype, rrclass, - rdlen, rdata, ttl, sdr->app_context); - return; + if (get_string(&data, replyName, 256) < 0) str_error = 1; + if (get_string(&data, replyType, kDNSServiceMaxDomainName) < 0) str_error = 1; + if (get_string(&data, replyDomain, kDNSServiceMaxDomainName) < 0) str_error = 1; + if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown; + ((DNSServiceBrowseReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, replyName, replyType, replyDomain, sdr->app_context); } -DNSServiceErrorType DNSServiceBrowse +DNSServiceErrorType DNSSD_API DNSServiceBrowse ( DNSServiceRef *sdRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *regtype, const char *domain, - const DNSServiceBrowseReply callBack, + DNSServiceBrowseReply callBack, void *context ) { char *msg = NULL, *ptr; - int len; + size_t len; ipc_msg_hdr *hdr; DNSServiceRef sdr; DNSServiceErrorType err; @@ -339,48 +734,71 @@ error: return kDNSServiceErr_Unknown; } +DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser +( + DNSServiceFlags flags, + const char *domain + ) + { + DNSServiceRef sdr; + DNSServiceErrorType err; + char *ptr = NULL; + size_t len = sizeof(flags) + strlen(domain) + 1; + ipc_msg_hdr *hdr = create_hdr(setdomain_request, &len, &ptr, 1); + + if (!hdr) return kDNSServiceErr_Unknown; + put_flags(flags, &ptr); + put_string(domain, &ptr); + sdr = connect_to_server(); + if (!sdr) { free(hdr); return kDNSServiceErr_Unknown; } + err = deliver_request((char *)hdr, sdr, 1); // deliver_request frees the message for us + DNSServiceRefDeallocate(sdr); + return err; + } -static void handle_browse_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) +static void handle_regservice_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) { - DNSServiceFlags flags; - uint32_t interfaceIndex; - DNSServiceErrorType errorCode; - char replyName[256], replyType[256], replyDomain[256]; + DNSServiceFlags flags; + uint32_t interfaceIndex; + DNSServiceErrorType errorCode; + char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName]; + int str_error = 0; (void)hdr;//Unused flags = get_flags(&data); interfaceIndex = get_long(&data); errorCode = get_error_code(&data); - get_string(&data, replyName, 256); - get_string(&data, replyType, 256); - get_string(&data, replyDomain, 256); - ((DNSServiceBrowseReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, replyName, replyType, replyDomain, sdr->app_context); + if (get_string(&data, name, 256) < 0) str_error = 1; + if (get_string(&data, regtype, kDNSServiceMaxDomainName) < 0) str_error = 1; + if (get_string(&data, domain, kDNSServiceMaxDomainName) < 0) str_error = 1; + if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown; + ((DNSServiceRegisterReply)sdr->app_callback)(sdr, flags, errorCode, name, regtype, domain, sdr->app_context); } - -DNSServiceErrorType DNSServiceRegister +DNSServiceErrorType DNSSD_API DNSServiceRegister ( DNSServiceRef *sdRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, - const char *name, - const char *regtype, - const char *domain, - const char *host, - const uint16_t port, - const uint16_t txtLen, - const void *txtRecord, - const DNSServiceRegisterReply callBack, - void *context + DNSServiceFlags flags, + uint32_t interfaceIndex, + const char *name, + const char *regtype, + const char *domain, + const char *host, + uint16_t PortInNetworkByteOrder, + uint16_t txtLen, + const void *txtRecord, + DNSServiceRegisterReply callBack, + void *context ) { char *msg = NULL, *ptr; - int len; + size_t len; ipc_msg_hdr *hdr; DNSServiceRef sdr; DNSServiceErrorType err; + union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder }; if (!sdRef) return kDNSServiceErr_BadParam; *sdRef = NULL; @@ -389,8 +807,8 @@ DNSServiceErrorType DNSServiceRegister if (!regtype) return kDNSServiceErr_BadParam; if (!domain) domain = ""; if (!host) host = ""; - if (!txtRecord) (char *)txtRecord = ""; - + if (!txtRecord) txtRecord = (void*)""; + // auto-name must also have auto-rename if (!name[0] && (flags & kDNSServiceFlagsNoAutoRename)) return kDNSServiceErr_BadParam; @@ -414,7 +832,8 @@ DNSServiceErrorType DNSServiceRegister put_string(regtype, &ptr); put_string(domain, &ptr); put_string(host, &ptr); - put_short(port, &ptr); + *ptr++ = port.b[0]; + *ptr++ = port.b[1]; put_short(txtLen, &ptr); put_rdata(txtLen, txtRecord, &ptr); @@ -426,7 +845,7 @@ DNSServiceErrorType DNSServiceRegister DNSServiceRefDeallocate(sdr); return err; } - + sdr->op = reg_service_request; sdr->process_reply = callBack ? handle_regservice_response : NULL; sdr->app_callback = callBack; @@ -434,51 +853,52 @@ DNSServiceErrorType DNSServiceRegister *sdRef = sdr; return err; - + error: if (msg) free(msg); if (*sdRef) { free(*sdRef); *sdRef = NULL; } return kDNSServiceErr_Unknown; } - -static void handle_regservice_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) +static void handle_enumeration_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) { DNSServiceFlags flags; uint32_t interfaceIndex; - DNSServiceErrorType errorCode; - char name[256], regtype[256], domain[256]; + DNSServiceErrorType err; + char domain[kDNSServiceMaxDomainName]; + int str_error = 0; (void)hdr;//Unused flags = get_flags(&data); interfaceIndex = get_long(&data); - errorCode = get_error_code(&data); - get_string(&data, name, 256); - get_string(&data, regtype, 256); - get_string(&data, domain, 256); - ((DNSServiceRegisterReply)sdr->app_callback)(sdr, flags, errorCode, name, regtype, domain, sdr->app_context); + err = get_error_code(&data); + if (get_string(&data, domain, kDNSServiceMaxDomainName) < 0) str_error = 1; + if (!err && str_error) err = kDNSServiceErr_Unknown; + ((DNSServiceDomainEnumReply)sdr->app_callback)(sdr, flags, interfaceIndex, err, domain, sdr->app_context); } -DNSServiceErrorType DNSServiceEnumerateDomains +DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains ( DNSServiceRef *sdRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, - const DNSServiceDomainEnumReply callBack, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceDomainEnumReply callBack, void *context ) { char *msg = NULL, *ptr; - int len; + size_t len; ipc_msg_hdr *hdr; DNSServiceRef sdr; DNSServiceErrorType err; - + int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0; + int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0; + if (f1 + f2 != 1) return kDNSServiceErr_BadParam; if (!sdRef) return kDNSServiceErr_BadParam; *sdRef = NULL; - len = sizeof(DNSServiceFlags); + len = sizeof(DNSServiceFlags); len += sizeof(uint32_t); hdr = create_hdr(enumeration_request, &len, &ptr, 1); @@ -510,24 +930,26 @@ error: return kDNSServiceErr_Unknown; } - -static void handle_enumeration_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) +static void handle_regrecord_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) { DNSServiceFlags flags; uint32_t interfaceIndex; - DNSServiceErrorType err; - char domain[256]; - (void)hdr;//Unused + DNSServiceErrorType errorCode; + DNSRecordRef rref = hdr->client_context.context; + if (sdr->op != connection) + { + rref->app_callback(rref->sdr, rref, 0, kDNSServiceErr_Unknown, rref->app_context); + return; + } flags = get_flags(&data); interfaceIndex = get_long(&data); - err = get_error_code(&data); - get_string(&data, domain, 256); - ((DNSServiceDomainEnumReply)sdr->app_callback)(sdr, flags, interfaceIndex, err, domain, sdr->app_context); - } + errorCode = get_error_code(&data); + rref->app_callback(rref->sdr, rref, flags, errorCode, rref->app_context); + } -DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef) +DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef) { if (!sdRef) return kDNSServiceErr_BadParam; *sdRef = connect_to_server(); @@ -538,54 +960,36 @@ DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef) return 0; } - - -static void handle_regrecord_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) - { - DNSServiceFlags flags; - uint32_t interfaceIndex; - DNSServiceErrorType errorCode; - DNSRecordRef rref = hdr->client_context.context; - - if (sdr->op != connection) - { - rref->app_callback(rref->sdr, rref, 0, kDNSServiceErr_Unknown, rref->app_context); - return; - } - flags = get_flags(&data); - interfaceIndex = get_long(&data); - errorCode = get_error_code(&data); - - rref->app_callback(rref->sdr, rref, flags, errorCode, rref->app_context); - } - -DNSServiceErrorType DNSServiceRegisterRecord +DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord ( - const DNSServiceRef sdRef, - DNSRecordRef *RecordRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, + DNSServiceRef sdRef, + DNSRecordRef *RecordRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *fullname, - const uint16_t rrtype, - const uint16_t rrclass, - const uint16_t rdlen, + uint16_t rrtype, + uint16_t rrclass, + uint16_t rdlen, const void *rdata, - const uint32_t ttl, - const DNSServiceRegisterRecordReply callBack, + uint32_t ttl, + DNSServiceRegisterRecordReply callBack, void *context ) { char *msg = NULL, *ptr; - int len; + size_t len; ipc_msg_hdr *hdr = NULL; DNSServiceRef tmp = NULL; DNSRecordRef rref = NULL; - - if (!sdRef || sdRef->op != connection || sdRef->sockfd < 0) + int f1 = (flags & kDNSServiceFlagsShared) != 0; + int f2 = (flags & kDNSServiceFlagsUnique) != 0; + if (f1 + f2 != 1) return kDNSServiceErr_BadParam; + + if (!sdRef || sdRef->op != connection || sdRef->sockfd < 0) return kDNSServiceErr_BadReference; *RecordRef = NULL; - - len = sizeof(DNSServiceFlags); + + len = sizeof(DNSServiceFlags); len += 2 * sizeof(uint32_t); // interfaceIndex, ttl len += 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen len += strlen(fullname) + 1; @@ -611,8 +1015,8 @@ DNSServiceErrorType DNSServiceRegisterRecord rref->sdr = sdRef; *RecordRef = rref; hdr->client_context.context = rref; - hdr->reg_index = rref->record_index; - + hdr->reg_index = rref->record_index; + return deliver_request(msg, sdRef, 0); error: @@ -623,26 +1027,26 @@ error: } //sdRef returned by DNSServiceRegister() -DNSServiceErrorType DNSServiceAddRecord +DNSServiceErrorType DNSSD_API DNSServiceAddRecord ( - const DNSServiceRef sdRef, + DNSServiceRef sdRef, DNSRecordRef *RecordRef, - const DNSServiceFlags flags, - const uint16_t rrtype, - const uint16_t rdlen, + DNSServiceFlags flags, + uint16_t rrtype, + uint16_t rdlen, const void *rdata, - const uint32_t ttl + uint32_t ttl ) { ipc_msg_hdr *hdr; - int len = 0; + size_t len = 0; char *ptr; DNSRecordRef rref; - if (!sdRef || (sdRef->op != reg_service_request) || !RecordRef) + if (!sdRef || (sdRef->op != reg_service_request) || !RecordRef) return kDNSServiceErr_BadReference; *RecordRef = NULL; - + len += 2 * sizeof(uint16_t); //rrtype, rdlen len += rdlen; len += sizeof(uint32_t); @@ -664,7 +1068,7 @@ DNSServiceErrorType DNSServiceAddRecord rref->sdr = sdRef; *RecordRef = rref; hdr->client_context.context = rref; - hdr->reg_index = rref->record_index; + hdr->reg_index = rref->record_index; return deliver_request((char *)hdr, sdRef, 0); error: @@ -673,26 +1077,24 @@ error: if (*RecordRef) *RecordRef = NULL; return kDNSServiceErr_Unknown; } - //DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord -DNSServiceErrorType DNSServiceUpdateRecord +DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord ( - const DNSServiceRef sdRef, + DNSServiceRef sdRef, DNSRecordRef RecordRef, - const DNSServiceFlags flags, - const uint16_t rdlen, + DNSServiceFlags flags, + uint16_t rdlen, const void *rdata, - const uint32_t ttl + uint32_t ttl ) { ipc_msg_hdr *hdr; - int len = 0; + size_t len = 0; char *ptr; - if (!sdRef || !RecordRef || !sdRef->max_index) - return kDNSServiceErr_BadReference; - + if (!sdRef) return kDNSServiceErr_BadReference; + len += sizeof(uint16_t); len += rdlen; len += sizeof(uint32_t); @@ -707,24 +1109,22 @@ DNSServiceErrorType DNSServiceUpdateRecord put_long(ttl, &ptr); return deliver_request((char *)hdr, sdRef, 0); } - - -DNSServiceErrorType DNSServiceRemoveRecord +DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord ( - const DNSServiceRef sdRef, - const DNSRecordRef RecordRef, - const DNSServiceFlags flags + DNSServiceRef sdRef, + DNSRecordRef RecordRef, + DNSServiceFlags flags ) { ipc_msg_hdr *hdr; - int len = 0; + size_t len = 0; char *ptr; DNSServiceErrorType err; - if (!sdRef || !RecordRef || !sdRef->max_index) + if (!sdRef || !RecordRef || !sdRef->max_index) return kDNSServiceErr_BadReference; - + len += sizeof(flags); hdr = create_hdr(remove_record_request, &len, &ptr, 0); if (!hdr) return kDNSServiceErr_Unknown; @@ -735,20 +1135,19 @@ DNSServiceErrorType DNSServiceRemoveRecord return err; } - -void DNSServiceReconfirmRecord +void DNSSD_API DNSServiceReconfirmRecord ( - const DNSServiceFlags flags, - const uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *fullname, - const uint16_t rrtype, - const uint16_t rrclass, - const uint16_t rdlen, + uint16_t rrtype, + uint16_t rrclass, + uint16_t rdlen, const void *rdata ) { char *ptr; - int len; + size_t len; ipc_msg_hdr *hdr; DNSServiceRef tmp; @@ -769,224 +1168,9 @@ void DNSServiceReconfirmRecord put_short(rrclass, &ptr); put_short(rdlen, &ptr); put_rdata(rdlen, rdata, &ptr); - my_write(tmp->sockfd, (char *)hdr, len); + ConvertHeaderBytes(hdr); + my_write(tmp->sockfd, (char *)hdr, (int) len); + free(hdr); DNSServiceRefDeallocate(tmp); } - - -int DNSServiceConstructFullName - ( - char *fullName, - const char *service, /* may be NULL */ - const char *regtype, - const char *domain - ) - { - int len; - u_char c; - char *fn = fullName; - const char *s = service; - const char *r = regtype; - const char *d = domain; - - if (service) - { - while(*s) - { - c = *s++; - if (c == '.' || (c == '\\')) *fn++ = '\\'; // escape dot and backslash literals - else if (c <= ' ') // escape non-printable characters - { - *fn++ = '\\'; - *fn++ = (char) ('0' + (c / 100)); - *fn++ = (char) ('0' + (c / 10) % 10); - c = (u_char)('0' + (c % 10)); - } - *fn++ = c; - } - *fn++ = '.'; - } - - if (!regtype) return -1; - len = strlen(regtype); - if (domain_ends_in_dot(regtype)) len--; - if (len < 4) return -1; // regtype must end in _udp or _tcp - if (strncmp((regtype + len - 4), "_tcp", 4) && strncmp((regtype + len - 4), "_udp", 4)) return -1; - while(*r) - *fn++ = *r++; - if (!domain_ends_in_dot(regtype)) *fn++ = '.'; - - if (!domain) return -1; - len = strlen(domain); - if (!len) return -1; - while(*d) - *fn++ = *d++; - if (!domain_ends_in_dot(domain)) *fn++ = '.'; - *fn = '\0'; - return 0; - } - -static int domain_ends_in_dot(const char *dom) - { - while(*dom && *(dom + 1)) - { - if (*dom == '\\') // advance past escaped byte sequence - { - if (*(dom + 1) >= '0' && *(dom + 1) <= '9') dom += 4; - else dom += 2; - } - else dom++; // else read one character - } - return (*dom == '.'); - } - - - - // return a connected service ref (deallocate with DNSServiceRefDeallocate) -static DNSServiceRef connect_to_server(void) - { - struct sockaddr_un saddr; - DNSServiceRef sdr; - - sdr = malloc(sizeof(_DNSServiceRef_t)); - if (!sdr) return NULL; - - if ((sdr->sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) - { - free(sdr); - return NULL; - } - - saddr.sun_family = AF_LOCAL; - strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH); - if (connect(sdr->sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) - { - free(sdr); - return NULL; - } - return sdr; - } - - - - -int my_write(int sd, char *buf, int len) - { - if (send(sd, buf, len, MSG_WAITALL) != len) return -1; - return 0; - } - - -// read len bytes. return 0 on success, -1 on error -int my_read(int sd, char *buf, int len) - { - if (recv(sd, buf, len, MSG_WAITALL) != len) return -1; - return 0; - } - - -DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reuse_sd) - { - ipc_msg_hdr *hdr = msg; - mode_t mask; - struct sockaddr_un caddr, daddr; // (client and daemon address structs) - char *path = NULL; - int listenfd = -1, errsd = -1, len; - DNSServiceErrorType err = kDNSServiceErr_Unknown; - - if (!hdr || sdr->sockfd < 0) return kDNSServiceErr_Unknown; - - if (!reuse_sd) - { - // setup temporary error socket - if ((listenfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) - goto cleanup; - - bzero(&caddr, sizeof(caddr)); - caddr.sun_family = AF_LOCAL; - caddr.sun_len = sizeof(struct sockaddr_un); - path = (char *)msg + sizeof(ipc_msg_hdr); - strcpy(caddr.sun_path, path); - mask = umask(0); - if (bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr)) < 0) - { - umask(mask); - goto cleanup; - } - umask(mask); - listen(listenfd, 1); - } - - if (my_write(sdr->sockfd, msg, hdr->datalen + sizeof(ipc_msg_hdr)) < 0) - goto cleanup; - free(msg); - msg = NULL; - if (reuse_sd) errsd = sdr->sockfd; - else - { - len = sizeof(daddr); - errsd = accept(listenfd, (struct sockaddr *)&daddr, &len); - if (errsd < 0) goto cleanup; - } - - len = recv(errsd, &err, sizeof(err), MSG_WAITALL); - if (len != sizeof(err)) - { - err = kDNSServiceErr_Unknown; - } -cleanup: - if (!reuse_sd && listenfd > 0) close(listenfd); - if (!reuse_sd && errsd > 0) close(errsd); - if (!reuse_sd && path) unlink(path); - if (msg) free(msg); - return err; - } - - - -/* create_hdr - * - * allocate and initialize an ipc message header. value of len should initially be the - * length of the data, and is set to the value of the data plus the header. data_start - * is set to point to the beginning of the data section. reuse_socket should be non-zero - * for calls that can receive an immediate error return value on their primary socket. - * if zero, the path to a control socket is appended at the beginning of the message buffer. - * data_start is set past this string. - */ - -static ipc_msg_hdr *create_hdr(int op, int *len, char **data_start, int reuse_socket) - { - char *msg = NULL; - ipc_msg_hdr *hdr; - int datalen; - char ctrl_path[256]; - struct timeval time; - - if (!reuse_socket) - { - if (gettimeofday(&time, NULL) < 0) return NULL; - sprintf(ctrl_path, "%s%d-%.3x-%.6u", CTL_PATH_PREFIX, (int)getpid(), - time.tv_sec & 0xFFF, time.tv_usec); - - *len += strlen(ctrl_path) + 1; - } - - - datalen = *len; - *len += sizeof(ipc_msg_hdr); - - // write message to buffer - msg = malloc(*len); - if (!msg) return NULL; - - bzero(msg, *len); - hdr = (void *)msg; - hdr->datalen = datalen; - hdr->version = VERSION; - hdr->op.request_op = op; - if (reuse_socket) hdr->flags |= IPC_FLAGS_REUSE_SOCKET; - *data_start = msg + sizeof(ipc_msg_hdr); - if (!reuse_socket) put_string(ctrl_path, data_start); - return hdr; - }