1 /* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 2003-2024 Apple 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 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 29 #ifndef DNSSD_IPC_H 30 #define DNSSD_IPC_H 31 32 #include "dns_sd.h" 33 #include "general.h" 34 35 // 36 // Common cross platform services 37 // 38 #if defined(WIN32) 39 # include <winsock2.h> 40 # define dnssd_InvalidSocket INVALID_SOCKET 41 # define dnssd_SocketValid(s) ((s) != INVALID_SOCKET) 42 # define dnssd_EWOULDBLOCK WSAEWOULDBLOCK 43 # define dnssd_EINTR WSAEINTR 44 # define dnssd_ECONNRESET WSAECONNRESET 45 # define dnssd_socklen_t int 46 # define dnssd_close(sock) closesocket(sock) 47 # define dnssd_errno WSAGetLastError() 48 # define dnssd_strerror(X) win32_strerror(X) 49 # define ssize_t int 50 # define getpid _getpid 51 # define unlink _unlink 52 extern char *win32_strerror(int inErrorCode); 53 #else 54 # include <sys/types.h> 55 # include <unistd.h> 56 # include <sys/un.h> 57 # include <string.h> 58 # include <stdio.h> 59 # include <stdlib.h> 60 # include <sys/stat.h> 61 # include <sys/socket.h> 62 # include <netinet/in.h> 63 # include <arpa/inet.h> 64 # define dnssd_InvalidSocket -1 65 # define dnssd_SocketValid(s) ((s) >= 0) 66 # define dnssd_EWOULDBLOCK EWOULDBLOCK 67 # define dnssd_EINTR EINTR 68 # define dnssd_ECONNRESET ECONNRESET 69 # define dnssd_EPIPE EPIPE 70 # define dnssd_socklen_t unsigned int 71 # define dnssd_close(sock) close(sock) 72 # define dnssd_errno errno 73 # define dnssd_strerror(X) strerror(X) 74 #endif 75 76 #if defined(USE_TCP_LOOPBACK) 77 # define AF_DNSSD AF_INET 78 # define MDNS_TCP_SERVERADDR "127.0.0.1" 79 #ifdef WIN32_CENTENNIAL 80 # define MDNS_TCP_SERVERPORT_CENTENNIAL 53545 81 #endif 82 # define MDNS_TCP_SERVERPORT 5354 83 # define LISTENQ 5 84 # define dnssd_sockaddr_t struct sockaddr_in 85 #else 86 # define AF_DNSSD AF_LOCAL 87 # ifndef MDNS_UDS_SERVERPATH 88 # define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder" 89 # endif 90 # define MDNS_UDS_SERVERPATH_ENVVAR "DNSSD_UDS_PATH" 91 # define LISTENQ 100 92 // longest legal control path length 93 # define MAX_CTLPATH (sizeof(((struct sockaddr_un*)0)->sun_path)) 94 # define dnssd_sockaddr_t struct sockaddr_un 95 #endif 96 97 // Compatibility workaround 98 #ifndef AF_LOCAL 99 #define AF_LOCAL AF_UNIX 100 #endif 101 102 // General UDS constants 103 #define TXT_RECORD_INDEX ((uint32_t)(-1)) // record index for default text record 104 105 // IPC data encoding constants and types 106 #define VERSION 1 107 #define IPC_FLAGS_NOREPLY (1U << 0) // Set flag if no asynchronous replies are to be sent to client. 108 #define IPC_FLAGS_TRAILING_TLVS (1U << 1) // Set flag if TLVs follow the standard request data. 109 #define IPC_FLAGS_NOERRSD (1U << 2) // Set flag if flag kDNSServiceFlagsMoreComing is set on client side. 110 111 #define IPC_TLV_TYPE_RESOLVER_CONFIG_PLIST_DATA 1 // An nw_resolver_config as a binary property list. 112 #define IPC_TLV_TYPE_REQUIRE_PRIVACY 2 // A uint8. Non-zero means privacy required, zero means not required. 113 #define IPC_TLV_TYPE_SERVICE_ATTR_AAAA_POLICY 3 // A uint32 for a DNSServiceAAAAPolicy value. 114 #define IPC_TLV_TYPE_SERVICE_ATTR_FAILOVER_POLICY 4 // A uint32 for a DNSServiceFailoverPolicy value. 115 #define IPC_TLV_TYPE_SERVICE_ATTR_TIMESTAMP 5 // A uint32 value for the time, in seconds, since Jan 1st 1970 UTC. 116 #define IPC_TLV_TYPE_SERVICE_ATTR_VALIDATION_POLICY 6 // A uint32 for a DNSServiceValidationPolicy value. 117 #define IPC_TLV_TYPE_SERVICE_ATTR_VALIDATION_DATA 7 // A ptr for the validation data. 118 #define IPC_TLV_TYPE_GET_TRACKER_STR 8 // A uint8. If non-zero, include tracker domain if applicable. 119 #define IPC_TLV_TYPE_SERVICE_ATTR_TRACKER_STR 9 // A null-terminated string. The domain (original hostname or resolved CNAME) 120 // that was identified as a tracker 121 #define IPC_TLV_TYPE_RESOLVER_OVERRIDE 10 // UUID of resolver configuration to use as an override. [1] 122 #define IPC_TLV_TYPE_SERVICE_ATTR_HOST_KEY_HASH 11 // A uint32 value for a host key hash. 123 124 // Notes: 125 // 1. If this TLV is specified, then the UUID identifies the libnetwork resolver configuration to use for the DNS-SD 126 // API operation (currently limited to DNSServiceQueryRecordWithAttribute()). This overrides the normal DNS service 127 // select process. 128 129 // Structure packing macro. If we're not using GNUC, it's not fatal. Most compilers naturally pack the on-the-wire 130 // structures correctly anyway, so a plain "struct" is usually fine. In the event that structures are not packed 131 // correctly, our compile-time assertion checks will catch it and prevent inadvertent generation of non-working code. 132 #ifndef packedstruct 133 #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9))) 134 #define packedstruct struct __attribute__((__packed__)) 135 #define packedunion union __attribute__((__packed__)) 136 #else 137 #define packedstruct struct 138 #define packedunion union 139 #endif 140 #endif 141 142 typedef enum 143 { 144 request_op_none = 0, // No request yet received on this connection 145 connection_request = 1, // connected socket via DNSServiceConnect() 146 reg_record_request, // reg/remove record only valid for connected sockets 147 remove_record_request, 148 enumeration_request, 149 reg_service_request, 150 browse_request, 151 resolve_request, 152 query_request, 153 reconfirm_record_request, 154 add_record_request, 155 update_record_request, 156 setdomain_request, // Up to here is in Tiger and B4W 1.0.3 157 getproperty_request, // New in B4W 1.0.4 158 port_mapping_request, // New in Leopard and B4W 2.0 159 addrinfo_request, 160 send_bpf_OBSOLETE, // New in SL (obsolete in 2023) 161 getpid_request, 162 release_request, 163 connection_delegate_request, 164 165 cancel_request = 63 166 } request_op_t; 167 168 typedef enum 169 { 170 enumeration_reply_op = 64, 171 reg_service_reply_op, 172 browse_reply_op, 173 resolve_reply_op, 174 query_reply_op, 175 reg_record_reply_op, // Up to here is in Tiger and B4W 1.0.3 176 getproperty_reply_op, // New in B4W 1.0.4 177 port_mapping_reply_op, // New in Leopard and B4W 2.0 178 addrinfo_reply_op, 179 async_error_op 180 } reply_op_t; 181 182 #if defined(_WIN64) 183 # pragma pack(push,4) 184 #endif 185 186 // Define context object big enough to hold a 64-bit pointer, 187 // to accomodate 64-bit clients communicating with 32-bit daemon. 188 // There's no reason for the daemon to ever be a 64-bit process, but its clients might be 189 typedef packedunion 190 { 191 void *context; 192 uint32_t u32[2]; 193 } client_context_t; 194 195 typedef packedstruct 196 { 197 uint32_t version; 198 uint32_t datalen; 199 uint32_t ipc_flags; 200 uint32_t op; // request_op_t or reply_op_t 201 client_context_t client_context; // context passed from client, returned by server in corresponding reply 202 uint32_t reg_index; // identifier for a record registered via DNSServiceRegisterRecord() on a 203 // socket connected by DNSServiceCreateConnection(). Must be unique in the scope of the connection, such that and 204 // index/socket pair uniquely identifies a record. (Used to select records for removal by DNSServiceRemoveRecord()) 205 } ipc_msg_hdr; 206 207 #if defined(_WIN64) 208 # pragma pack(pop) 209 #endif 210 211 // routines to write to and extract data from message buffers. 212 // caller responsible for bounds checking. 213 // ptr is the address of the pointer to the start of the field. 214 // it is advanced to point to the next field, or the end of the message 215 216 void put_uint32(const uint32_t l, uint8_t **ptr); 217 uint32_t get_uint32(const uint8_t **ptr, const uint8_t *end); 218 219 void put_uint16(uint16_t s, uint8_t **ptr); 220 uint16_t get_uint16(const uint8_t **ptr, const uint8_t *end); 221 222 #define put_flags put_uint32 223 #define get_flags get_uint32 224 225 #define put_error_code put_uint32 226 #define get_error_code get_uint32 227 228 int put_string(const char *str, uint8_t **ptr); 229 int get_string(const uint8_t **ptr, const uint8_t *end, char *buffer, size_t buflen); 230 231 void put_rdata(const size_t rdlen, const uint8_t *rdata, uint8_t **ptr); 232 const uint8_t *get_rdata(const uint8_t **ptr, const uint8_t *end, int rdlen); // return value is rdata pointed to by *ptr - 233 // rdata is not copied from buffer. 234 235 size_t get_required_tlv_length(uint16_t value_length); 236 size_t get_required_tlv_string_length(const char *str_value); 237 size_t get_required_tlv_uint8_length(void); 238 size_t get_required_tlv_uint32_length(void); 239 size_t put_tlv(uint16_t type, uint16_t length, const uint8_t *value, uint8_t **ptr, const uint8_t *limit); 240 void put_tlv_string(const uint16_t type, const char *const str_value, uint8_t **const ptr, const uint8_t *const limit, 241 int *const out_error); 242 void put_tlv_uint8(uint16_t type, uint8_t u8, uint8_t **ptr, const uint8_t *limit); 243 void put_tlv_uint16(uint16_t type, uint16_t u16, uint8_t **ptr, const uint8_t *limit); 244 size_t put_tlv_uint32(uint16_t type, uint32_t u32, uint8_t **ptr, const uint8_t *limit); 245 size_t put_tlv_uuid(uint16_t type, const uint8_t uuid[MDNS_STATIC_ARRAY_PARAM MDNS_UUID_SIZE], uint8_t **ptr, 246 const uint8_t *limit); 247 const uint8_t *get_tlv(const uint8_t *src, const uint8_t *end, uint16_t type, size_t *out_length); 248 const char *get_tlv_string(const uint8_t *const start, const uint8_t *const end, const uint16_t type); 249 uint32_t get_tlv_uint32(const uint8_t *src, const uint8_t *end, uint16_t type, int *out_error); 250 const uint8_t *get_tlv_uuid(const uint8_t *src, const uint8_t *end, uint16_t type); 251 252 void ConvertHeaderBytes(ipc_msg_hdr *hdr); 253 254 struct CompileTimeAssertionChecks_dnssd_ipc 255 { 256 // Check that the compiler generated our on-the-wire packet format structure definitions 257 // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries. 258 #ifndef __lint__ 259 char assert0[(sizeof(client_context_t) == 8) ? 1 : -1]; 260 char assert1[(sizeof(ipc_msg_hdr) == 28) ? 1 : -1]; 261 #endif 262 }; 263 264 #endif // DNSSD_IPC_H 265