Home | History | Annotate | Line # | Download | only in mDNSShared
      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