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