1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2003-2015 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 
34 //
35 // Common cross platform services
36 //
37 #if defined(WIN32)
38 #   include <winsock2.h>
39 #   define dnssd_InvalidSocket  INVALID_SOCKET
40 #   define dnssd_SocketValid(s) ((s) != INVALID_SOCKET)
41 #   define dnssd_EWOULDBLOCK    WSAEWOULDBLOCK
42 #   define dnssd_EINTR          WSAEINTR
43 #   define dnssd_ECONNRESET     WSAECONNRESET
44 #   define dnssd_socklen_t      int
45 #   define dnssd_close(sock)    closesocket(sock)
46 #   define dnssd_errno          WSAGetLastError()
47 #   define dnssd_strerror(X)    win32_strerror(X)
48 #   define ssize_t              int
49 #   define getpid               _getpid
50 #   define unlink               _unlink
51 extern char *win32_strerror(int inErrorCode);
52 #else
53 #   include <sys/types.h>
54 #   include <unistd.h>
55 #   include <sys/un.h>
56 #   include <string.h>
57 #   include <stdio.h>
58 #   include <stdlib.h>
59 #   include <sys/stat.h>
60 #   include <sys/socket.h>
61 #   include <netinet/in.h>
62 #   include <arpa/inet.h>
63 #   define dnssd_InvalidSocket  -1
64 #   define dnssd_SocketValid(s) ((s) >= 0)
65 #   define dnssd_EWOULDBLOCK    EWOULDBLOCK
66 #   define dnssd_EINTR          EINTR
67 #   define dnssd_ECONNRESET     ECONNRESET
68 #   define dnssd_EPIPE          EPIPE
69 #   define dnssd_socklen_t      unsigned int
70 #   define dnssd_close(sock)    close(sock)
71 #   define dnssd_errno          errno
72 #   define dnssd_strerror(X)    strerror(X)
73 #endif
74 
75 #if defined(USE_TCP_LOOPBACK)
76 #   define AF_DNSSD             AF_INET
77 #   define MDNS_TCP_SERVERADDR  "127.0.0.1"
78 #   define MDNS_TCP_SERVERPORT  5354
79 #   define LISTENQ              5
80 #   define dnssd_sockaddr_t     struct sockaddr_in
81 #else
82 #   define AF_DNSSD             AF_LOCAL
83 #   ifndef MDNS_UDS_SERVERPATH
84 #       define MDNS_UDS_SERVERPATH  "/var/run/mDNSResponder"
85 #   endif
86 #   define MDNS_UDS_SERVERPATH_ENVVAR "DNSSD_UDS_PATH"
87 #   define LISTENQ              100
88 // longest legal control path length
89 #   define MAX_CTLPATH          (sizeof(((struct sockaddr_un*)0)->sun_path))
90 #   define dnssd_sockaddr_t     struct sockaddr_un
91 #endif
92 
93 // Compatibility workaround
94 #ifndef AF_LOCAL
95 #define AF_LOCAL    AF_UNIX
96 #endif
97 
98 // General UDS constants
99 #define TXT_RECORD_INDEX ((uint32_t)(-1))   // record index for default text record
100 
101 // IPC data encoding constants and types
102 #define VERSION 1
103 #define IPC_FLAGS_NOREPLY 1 // set flag if no asynchronous replies are to be sent to client
104 
105 // Structure packing macro. If we're not using GNUC, it's not fatal. Most compilers naturally pack the on-the-wire
106 // structures correctly anyway, so a plain "struct" is usually fine. In the event that structures are not packed
107 // correctly, our compile-time assertion checks will catch it and prevent inadvertent generation of non-working code.
108 #ifndef packedstruct
109  #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
110   #define packedstruct struct __attribute__((__packed__))
111   #define packedunion  union  __attribute__((__packed__))
112  #else
113   #define packedstruct struct
114   #define packedunion  union
115  #endif
116 #endif
117 
118 typedef enum
119 {
120     request_op_none = 0,    // No request yet received on this connection
121     connection_request = 1, // connected socket via DNSServiceConnect()
122     reg_record_request,     // reg/remove record only valid for connected sockets
123     remove_record_request,
124     enumeration_request,
125     reg_service_request,
126     browse_request,
127     resolve_request,
128     query_request,
129     reconfirm_record_request,
130     add_record_request,
131     update_record_request,
132     setdomain_request,      // Up to here is in Tiger and B4W 1.0.3
133     getproperty_request,    // New in B4W 1.0.4
134     port_mapping_request,   // New in Leopard and B4W 2.0
135     addrinfo_request,
136     send_bpf,               // New in SL
137     getpid_request,
138     release_request,
139     connection_delegate_request,
140 
141     cancel_request = 63
142 } request_op_t;
143 
144 typedef enum
145 {
146     enumeration_reply_op = 64,
147     reg_service_reply_op,
148     browse_reply_op,
149     resolve_reply_op,
150     query_reply_op,
151     reg_record_reply_op,    // Up to here is in Tiger and B4W 1.0.3
152     getproperty_reply_op,   // New in B4W 1.0.4
153     port_mapping_reply_op,  // New in Leopard and B4W 2.0
154     addrinfo_reply_op
155 } reply_op_t;
156 
157 #if defined(_WIN64)
158 #   pragma pack(push,4)
159 #endif
160 
161 // Define context object big enough to hold a 64-bit pointer,
162 // to accomodate 64-bit clients communicating with 32-bit daemon.
163 // There's no reason for the daemon to ever be a 64-bit process, but its clients might be
164 typedef packedunion
165 {
166     void *context;
167     uint32_t u32[2];
168 } client_context_t;
169 
170 typedef packedstruct
171 {
172     uint32_t version;
173     uint32_t datalen;
174     uint32_t ipc_flags;
175     uint32_t op;        // request_op_t or reply_op_t
176     client_context_t client_context; // context passed from client, returned by server in corresponding reply
177     uint32_t reg_index;            // identifier for a record registered via DNSServiceRegisterRecord() on a
178     // socket connected by DNSServiceCreateConnection().  Must be unique in the scope of the connection, such that and
179     // index/socket pair uniquely identifies a record.  (Used to select records for removal by DNSServiceRemoveRecord())
180 } ipc_msg_hdr;
181 
182 #if defined(_WIN64)
183 #   pragma pack(pop)
184 #endif
185 
186 // routines to write to and extract data from message buffers.
187 // caller responsible for bounds checking.
188 // ptr is the address of the pointer to the start of the field.
189 // it is advanced to point to the next field, or the end of the message
190 
191 // Keep these out of the general namespace -- they're only used internally
192 // by the library.
193 #define put_uint32		__dnssd_ipc_put_uint32
194 #define get_uint32		__dnssd_ipc_get_uint32
195 #define put_uint16		__dnssd_ipc_put_uint16
196 #define get_uint16		__dnssd_ipc_get_uint16
197 #define put_string		__dnssd_ipc_put_string
198 #define get_string		__dnssd_ipc_get_string
199 #define put_rdata		__dnssd_ipc_put_rdata
200 #define get_rdata		__dnssd_ipc_get_rdata
201 #define ConvertHeaderBytes	__dnssd_ipc_ConvertHeaderBytes
202 
203 void put_uint32(const uint32_t l, char **ptr);
204 uint32_t get_uint32(const char **ptr, const char *end);
205 
206 void put_uint16(uint16_t s, char **ptr);
207 uint16_t get_uint16(const char **ptr, const char *end);
208 
209 #define put_flags put_uint32
210 #define get_flags get_uint32
211 
212 #define put_error_code put_uint32
213 #define get_error_code get_uint32
214 
215 int put_string(const char *str, char **ptr);
216 int get_string(const char **ptr, const char *const end, char *buffer, int buflen);
217 
218 void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr);
219 const char *get_rdata(const char **ptr, const char *end, int rdlen);  // return value is rdata pointed to by *ptr -
220 // rdata is not copied from buffer.
221 
222 void ConvertHeaderBytes(ipc_msg_hdr *hdr);
223 
224 struct CompileTimeAssertionChecks_dnssd_ipc
225 {
226     // Check that the compiler generated our on-the-wire packet format structure definitions
227     // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries.
228 #ifndef __lint__
229     char assert0[(sizeof(client_context_t) ==  8) ? 1 : -1];
230     char assert1[(sizeof(ipc_msg_hdr)      == 28) ? 1 : -1];
231 #endif
232 };
233 
234 #endif // DNSSD_IPC_H
235