/* -*- Mode: C; tab-width: 4 -*- * * Copyright (c) 2003-2020 Apple 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 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. */ #ifndef DNSSD_IPC_H #define DNSSD_IPC_H #include "dns_sd.h" // // Common cross platform services // #if defined(WIN32) # include # define dnssd_InvalidSocket INVALID_SOCKET # define dnssd_SocketValid(s) ((s) != INVALID_SOCKET) # define dnssd_EWOULDBLOCK WSAEWOULDBLOCK # define dnssd_EINTR WSAEINTR # define dnssd_ECONNRESET WSAECONNRESET # define dnssd_socklen_t int # define dnssd_close(sock) closesocket(sock) # define dnssd_errno WSAGetLastError() # define dnssd_strerror(X) win32_strerror(X) # define ssize_t int # define getpid _getpid # define unlink _unlink extern char *win32_strerror(int inErrorCode); #else # include # include # include # include # include # include # include # include # include # include # define dnssd_InvalidSocket -1 # define dnssd_SocketValid(s) ((s) >= 0) # define dnssd_EWOULDBLOCK EWOULDBLOCK # define dnssd_EINTR EINTR # define dnssd_ECONNRESET ECONNRESET # define dnssd_EPIPE EPIPE # define dnssd_socklen_t unsigned int # define dnssd_close(sock) close(sock) # define dnssd_errno errno # define dnssd_strerror(X) strerror(X) #endif #if defined(USE_TCP_LOOPBACK) # define AF_DNSSD AF_INET # define MDNS_TCP_SERVERADDR "127.0.0.1" # define MDNS_TCP_SERVERPORT 5354 # define LISTENQ 5 # define dnssd_sockaddr_t struct sockaddr_in #else # define AF_DNSSD AF_LOCAL # ifndef MDNS_UDS_SERVERPATH # define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder" # endif # define MDNS_UDS_SERVERPATH_ENVVAR "DNSSD_UDS_PATH" # define LISTENQ 100 // longest legal control path length # define MAX_CTLPATH (sizeof(((struct sockaddr_un*)0)->sun_path)) # define dnssd_sockaddr_t struct sockaddr_un #endif // Compatibility workaround #ifndef AF_LOCAL #define AF_LOCAL AF_UNIX #endif // General UDS constants #define TXT_RECORD_INDEX ((uint32_t)(-1)) // record index for default text record // IPC data encoding constants and types #define VERSION 1 #define IPC_FLAGS_NOREPLY (1U << 0) // Set flag if no asynchronous replies are to be sent to client. #define IPC_FLAGS_TRAILING_TLVS (1U << 1) // Set flag if TLVs follow the standard request data. #define IPC_TLV_TYPE_RESOLVER_CONFIG_PLIST_DATA 1 // An nw_resolver_config as a binary property list. #define IPC_TLV_TYPE_REQUIRE_PRIVACY 2 // A uint8. Non-zero means privacy is required, zero means not required. // Structure packing macro. If we're not using GNUC, it's not fatal. Most compilers naturally pack the on-the-wire // structures correctly anyway, so a plain "struct" is usually fine. In the event that structures are not packed // correctly, our compile-time assertion checks will catch it and prevent inadvertent generation of non-working code. #ifndef packedstruct #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9))) #define packedstruct struct __attribute__((__packed__)) #define packedunion union __attribute__((__packed__)) #else #define packedstruct struct #define packedunion union #endif #endif typedef enum { request_op_none = 0, // No request yet received on this connection connection_request = 1, // connected socket via DNSServiceConnect() reg_record_request, // reg/remove record only valid for connected sockets remove_record_request, enumeration_request, reg_service_request, browse_request, resolve_request, query_request, reconfirm_record_request, add_record_request, update_record_request, setdomain_request, // Up to here is in Tiger and B4W 1.0.3 getproperty_request, // New in B4W 1.0.4 port_mapping_request, // New in Leopard and B4W 2.0 addrinfo_request, send_bpf, // New in SL getpid_request, release_request, connection_delegate_request, cancel_request = 63 } request_op_t; typedef enum { enumeration_reply_op = 64, reg_service_reply_op, browse_reply_op, resolve_reply_op, query_reply_op, reg_record_reply_op, // Up to here is in Tiger and B4W 1.0.3 getproperty_reply_op, // New in B4W 1.0.4 port_mapping_reply_op, // New in Leopard and B4W 2.0 addrinfo_reply_op } reply_op_t; #if defined(_WIN64) # pragma pack(push,4) #elif !defined(__GNUC__) # pragma pack(1) #endif // Define context object big enough to hold a 64-bit pointer, // to accomodate 64-bit clients communicating with 32-bit daemon. // There's no reason for the daemon to ever be a 64-bit process, but its clients might be typedef packedunion { void *context; uint32_t u32[2]; } client_context_t; typedef packedstruct { uint32_t version; uint32_t datalen; uint32_t ipc_flags; uint32_t op; // request_op_t or reply_op_t client_context_t client_context; // context passed from client, returned by server in corresponding reply uint32_t reg_index; // identifier for a record registered via DNSServiceRegisterRecord() on a // socket connected by DNSServiceCreateConnection(). Must be unique in the scope of the connection, such that and // index/socket pair uniquely identifies a record. (Used to select records for removal by DNSServiceRemoveRecord()) } ipc_msg_hdr; #if defined(_WIN64) # pragma pack(pop) #elif !defined(__GNUC__) # pragma pack() #endif // routines to write to and extract data from message buffers. // caller responsible for bounds checking. // ptr is the address of the pointer to the start of the field. // it is advanced to point to the next field, or the end of the message void put_uint32(const uint32_t l, char **ptr); uint32_t get_uint32(const char **ptr, const char *end); void put_uint16(uint16_t s, char **ptr); uint16_t get_uint16(const char **ptr, const char *end); #define put_flags put_uint32 #define get_flags get_uint32 #define put_error_code put_uint32 #define get_error_code get_uint32 int put_string(const char *str, char **ptr); int get_string(const char **ptr, const char *const end, char *buffer, int buflen); void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr); const char *get_rdata(const char **ptr, const char *end, int rdlen); // return value is rdata pointed to by *ptr - // rdata is not copied from buffer. #if APPLE_OSX_mDNSResponder size_t get_required_tlv16_length(const uint16_t valuelen); void put_tlv16(const uint16_t type, const uint16_t length, const uint8_t *value, char **ptr); #endif void ConvertHeaderBytes(ipc_msg_hdr *hdr); struct CompileTimeAssertionChecks_dnssd_ipc { // Check that the compiler generated our on-the-wire packet format structure definitions // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries. char assert0[(sizeof(client_context_t) == 8) ? 1 : -1]; char assert1[(sizeof(ipc_msg_hdr) == 28) ? 1 : -1]; }; #endif // DNSSD_IPC_H