Home | History | Annotate | Line # | Download | only in mDNSCore
      1 /*
      2  * Copyright (c) 2002-2024 Apple Inc. All rights reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     https://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef __mDNSDebug_h
     18 #define __mDNSDebug_h
     19 
     20 #include "mDNSFeatures.h"
     21 
     22 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
     23 #include <os/log.h>
     24 #include "mDNSDebugShared.h"
     25 #endif
     26 
     27 // Set MDNS_DEBUGMSGS to 0 to optimize debugf() calls out of the compiled code
     28 // Set MDNS_DEBUGMSGS to 1 to generate normal debugging messages
     29 // Set MDNS_DEBUGMSGS to 2 to generate verbose debugging messages
     30 // MDNS_DEBUGMSGS is normally set in the project options (or makefile) but can also be set here if desired
     31 // (If you edit the file here to turn on MDNS_DEBUGMSGS while you're debugging some code, be careful
     32 // not to accidentally check-in that change by mistake when you check in your other changes.)
     33 
     34 #ifndef MDNS_DEBUGMSGS
     35 #define MDNS_DEBUGMSGS 0
     36 #endif
     37 
     38 // Set MDNS_CHECK_PRINTF_STYLE_FUNCTIONS to 1 to enable extra GCC compiler warnings
     39 // Note: You don't normally want to do this, because it generates a bunch of
     40 // spurious warnings for the following custom extensions implemented by mDNS_vsnprintf:
     41 //    warning: `#' flag used with `%s' printf format    (for %#s              -- pascal string format)
     42 //    warning: repeated `#' flag in format              (for %##s             -- DNS name string format)
     43 //    warning: double format, pointer arg (arg 2)       (for %.4a, %.16a, %#a -- IP address formats)
     44 #ifndef MDNS_CHECK_PRINTF_STYLE_FUNCTIONS
     45 #define MDNS_CHECK_PRINTF_STYLE_FUNCTIONS 0
     46 #endif
     47 
     48 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
     49 typedef os_log_t mDNSLogCategory_t;
     50 
     51 typedef os_log_type_t mDNSLogLevel_t;
     52 #define MDNS_LOG_FAULT      OS_LOG_TYPE_FAULT
     53 #define MDNS_LOG_ERROR      OS_LOG_TYPE_ERROR
     54 #define MDNS_LOG_WARNING    OS_LOG_TYPE_DEFAULT
     55 #define MDNS_LOG_DEFAULT    OS_LOG_TYPE_DEFAULT
     56 #define MDNS_LOG_INFO       OS_LOG_TYPE_INFO
     57 #define MDNS_LOG_DEBUG      OS_LOG_TYPE_DEBUG
     58 #else
     59 typedef const char * mDNSLogCategory_t;
     60 typedef enum
     61 {
     62     MDNS_LOG_FAULT   = 1,
     63     MDNS_LOG_ERROR   = 2,
     64     MDNS_LOG_WARNING = 3,
     65     MDNS_LOG_DEFAULT = 4,
     66     MDNS_LOG_INFO    = 5,
     67     MDNS_LOG_DEBUG   = 6
     68 } mDNSLogLevel_t;
     69 #endif
     70 
     71 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
     72 
     73     #define MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(NAME)                       \
     74         extern os_log_t mDNSLogCategory_ ## NAME;                           \
     75         extern os_log_t mDNSLogCategory_ ## NAME ## _redacted
     76 
     77     MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(Default);
     78     MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(State);
     79     MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(mDNS);
     80     MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(uDNS);
     81     MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(SPS);
     82     MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(NAT);
     83     MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(D2D);
     84     MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(XPC);
     85     MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(Analytics);
     86     MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(DNSSEC);
     87 
     88     #define MDNS_LOG_CATEGORY_DEFINITION(NAME)  mDNSLogCategory_ ## NAME
     89 #else
     90     #define MDNS_LOG_CATEGORY_DEFINITION(NAME)  # NAME
     91 #endif
     92 
     93 #define MDNS_LOG_CATEGORY_DEFAULT   MDNS_LOG_CATEGORY_DEFINITION(Default)
     94 #define MDNS_LOG_CATEGORY_STATE     MDNS_LOG_CATEGORY_DEFINITION(State)
     95 #define MDNS_LOG_CATEGORY_MDNS      MDNS_LOG_CATEGORY_DEFINITION(mDNS)
     96 #define MDNS_LOG_CATEGORY_UDNS      MDNS_LOG_CATEGORY_DEFINITION(uDNS)
     97 #define MDNS_LOG_CATEGORY_SPS       MDNS_LOG_CATEGORY_DEFINITION(SPS)
     98 #define MDNS_LOG_CATEGORY_NAT       MDNS_LOG_CATEGORY_DEFINITION(NAT)
     99 #define MDNS_LOG_CATEGORY_D2D       MDNS_LOG_CATEGORY_DEFINITION(D2D)
    100 #define MDNS_LOG_CATEGORY_XPC       MDNS_LOG_CATEGORY_DEFINITION(XPC)
    101 #define MDNS_LOG_CATEGORY_ANALYTICS MDNS_LOG_CATEGORY_DEFINITION(Analytics)
    102 #define MDNS_LOG_CATEGORY_DNSSEC    MDNS_LOG_CATEGORY_DEFINITION(DNSSEC)
    103 
    104 // Use MDNS_LOG_CATEGORY_DISABLED to disable a log temporarily.
    105 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    106     #define MDNS_LOG_CATEGORY_DISABLED OS_LOG_DISABLED
    107 #else
    108     #define MDNS_LOG_CATEGORY_DISABLED "Log Disabled"
    109 #endif
    110 
    111 // Set this symbol to 1 to answer remote queries for our Address, and reverse mapping PTR
    112 #define ANSWER_REMOTE_HOSTNAME_QUERIES 0
    113 
    114 // Set this symbol to 1 to do extra debug checks on malloc() and free()
    115 // Set this symbol to 2 to write a log message for every malloc() and free()
    116 #ifndef MDNS_MALLOC_DEBUGGING
    117 #define MDNS_MALLOC_DEBUGGING 0
    118 #endif
    119 
    120 #if (MDNS_MALLOC_DEBUGGING > 0) && defined(WIN32)
    121 #error "Malloc debugging does not yet work on Windows"
    122 #endif
    123 
    124 #define ForceAlerts 0
    125 //#define LogTimeStamps 1
    126 
    127 // Developer-settings section ends here
    128 
    129 #if MDNS_CHECK_PRINTF_STYLE_FUNCTIONS
    130 #define IS_A_PRINTF_STYLE_FUNCTION(F,A) __attribute__ ((format(printf,F,A)))
    131 #else
    132 #define IS_A_PRINTF_STYLE_FUNCTION(F,A)
    133 #endif
    134 
    135 #ifdef __cplusplus
    136 extern "C" {
    137 #endif
    138 
    139 // Variable argument macro support. Use ANSI C99 __VA_ARGS__ where possible. Otherwise, use the next best thing.
    140 
    141 #if (defined(__GNUC__))
    142     #if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 2)))
    143         #define MDNS_C99_VA_ARGS        1
    144         #define MDNS_GNU_VA_ARGS        0
    145     #else
    146         #define MDNS_C99_VA_ARGS        0
    147         #define MDNS_GNU_VA_ARGS        1
    148     #endif
    149     #define MDNS_HAS_VA_ARG_MACROS      1
    150 #elif (_MSC_VER >= 1400) // Visual Studio 2005 and later
    151     #define MDNS_C99_VA_ARGS            1
    152     #define MDNS_GNU_VA_ARGS            0
    153     #define MDNS_HAS_VA_ARG_MACROS      1
    154 #elif (defined(__MWERKS__))
    155     #define MDNS_C99_VA_ARGS            1
    156     #define MDNS_GNU_VA_ARGS            0
    157     #define MDNS_HAS_VA_ARG_MACROS      1
    158 #else
    159     #define MDNS_C99_VA_ARGS            0
    160     #define MDNS_GNU_VA_ARGS            0
    161     #define MDNS_HAS_VA_ARG_MACROS      0
    162 #endif
    163 
    164 #if (MDNS_HAS_VA_ARG_MACROS)
    165     #if (MDNS_C99_VA_ARGS)
    166         #define MDNS_LOG_DEFINITION(LEVEL, ...) \
    167             do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_CATEGORY_DEFAULT, LEVEL, __VA_ARGS__); } while (0)
    168 
    169         #define debug_noop(...)   do {} while(0)
    170         #define LogMsg(...)       LogMsgWithLevel(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, __VA_ARGS__)
    171         #define LogOperation(...) MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  __VA_ARGS__)
    172         #define LogSPS(...)       MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  __VA_ARGS__)
    173         #define LogInfo(...)      MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  __VA_ARGS__)
    174         #define LogDebug(...)     MDNS_LOG_DEFINITION(MDNS_LOG_DEBUG, __VA_ARGS__)
    175     #elif (MDNS_GNU_VA_ARGS)
    176         #define MDNS_LOG_DEFINITION(LEVEL, ARGS...) \
    177             do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_CATEGORY_DEFAULT, LEVEL, ARGS); } while (0)
    178 
    179         #define debug_noop(ARGS...)   do {} while (0)
    180         #define LogMsg(ARGS... )      LogMsgWithLevel(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, ARGS)
    181         #define LogOperation(ARGS...) MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  ARGS)
    182         #define LogSPS(ARGS...)       MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  ARGS)
    183         #define LogInfo(ARGS...)      MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  ARGS)
    184         #define LogDebug(ARGS...)     MDNS_LOG_DEFINITION(MDNS_LOG_DEBUG, ARGS)
    185     #else
    186         #error "Unknown variadic macros"
    187     #endif
    188 #else
    189 // If your platform does not support variadic macros, you need to define the following variadic functions.
    190 // See mDNSShared/mDNSDebug.c for sample implementation
    191     #define debug_noop 1 ? (void)0 : (void)
    192     #define LogMsg LogMsg_
    193     #define LogOperation (mDNS_LoggingEnabled == 0) ? ((void)0) : LogOperation_
    194     #define LogSPS       (mDNS_LoggingEnabled == 0) ? ((void)0) : LogSPS_
    195     #define LogInfo      (mDNS_LoggingEnabled == 0) ? ((void)0) : LogInfo_
    196     #define LogDebug     (mDNS_LoggingEnabled == 0) ? ((void)0) : LogDebug_
    197 extern void LogMsg_(const char *format, ...)       IS_A_PRINTF_STYLE_FUNCTION(1,2);
    198 extern void LogOperation_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
    199 extern void LogSPS_(const char *format, ...)       IS_A_PRINTF_STYLE_FUNCTION(1,2);
    200 extern void LogInfo_(const char *format, ...)      IS_A_PRINTF_STYLE_FUNCTION(1,2);
    201 extern void LogDebug_(const char *format, ...)     IS_A_PRINTF_STYLE_FUNCTION(1,2);
    202 #endif
    203 
    204 
    205 #if MDNS_DEBUGMSGS
    206 #define debugf debugf_
    207 extern void debugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
    208 #else
    209 #define debugf debug_noop
    210 #endif
    211 
    212 #if MDNS_DEBUGMSGS > 1
    213 #define verbosedebugf verbosedebugf_
    214 extern void verbosedebugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
    215 #else
    216 #define verbosedebugf debug_noop
    217 #endif
    218 
    219 extern int mDNS_LoggingEnabled;
    220 extern int mDNS_DebugLoggingEnabled;
    221 extern int mDNS_PacketLoggingEnabled;
    222 extern int mDNS_McastLoggingEnabled;
    223 extern int mDNS_McastTracingEnabled;
    224 extern int mDNS_DebugMode;          // If non-zero, LogMsg() writes to stderr instead of syslog
    225 
    226 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
    227 extern int gNumOfSensitiveLoggingEnabledQuestions;
    228 extern int gSensitiveLoggingEnabled; // If true, LogRedact() will redact all private level logs. The content of state
    229                                         // dump that is related to user's privacy will also be redacted.
    230 #endif
    231 
    232 extern const char ProgramName[];
    233 
    234 extern void LogMsgWithLevel(mDNSLogCategory_t category, mDNSLogLevel_t level, const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
    235 // LogMsgNoIdent needs to be fixed so that it logs without the ident prefix like it used to
    236 // (or completely overhauled to use the new "log to a separate file" facility)
    237 #define LogMsgNoIdent LogMsg
    238 
    239 #define LogFatalError LogMsg
    240 
    241 #if MDNS_MALLOC_DEBUGGING >= 1
    242 extern void *mallocL(const char *msg, mDNSu32 size);
    243 extern void *callocL(const char *msg, mDNSu32 size);
    244 extern void freeL(const char *msg, void *x);
    245 #define LogMemCorruption LogMsg
    246 #else
    247 #define mallocL(MSG, SIZE) mdns_malloc(SIZE)
    248 #define callocL(MSG, SIZE) mdns_calloc(1, SIZE)
    249 #define freeL(MSG, PTR) mdns_free(PTR)
    250 #endif
    251 
    252 #ifdef __cplusplus
    253 }
    254 #endif
    255 
    256 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    257 
    258 /** @brief Write a log message to system's log storage(memory or disk).
    259  *
    260  *  On Apple platform, os_log() will be called to log a message.
    261  *
    262  *  @param CATEGORY         A custom log object previously created by the os_log_create function, and such an object is
    263  *                          used to specify "subsystem" and "category". For mDNSResponder, the subsystem should always
    264  *                          be set to "com.apple.mDNSResponder"; and the category is used for categorization and
    265  *                          filtering of related log messages within the subsystems settings. We have 4 categories that
    266  *                          are pre-defined: MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_CATEGORY_UDNS,
    267  *                          MDNS_LOG_CATEGORY_SPS. If these categories are not enough, use os_log_create to create more.
    268  *
    269  *  @param LEVEL            The log level that determines the importance of the message. The levels are, in order of
    270  *                          decreasing importance:
    271  *                              MDNS_LOG_FAULT      Fault-level messages are intended for capturing system-level errors
    272  *                                                  that are critical to the system. They are always saved in the data store.
    273  *                              MDNS_LOG_ERROR      Error-level messages are intended for reporting process-level errors
    274  *                                                  that are unexpected and incorrect during the normal operation. They
    275  *                                                  are always saved in the data store.
    276  *                              MDNS_LOG_WARNING    Warning-level messages are intended for capturing unexpected and
    277  *                                                  possible incorrect behavior that might be used later to root cause
    278  *                                                  an error or fault. They are are initially stored in memory buffers
    279  *                                                  and then moved to a data store.
    280  *                              MDNS_LOG_DEFAULT    Default-level messages are intended for reporting things that might
    281  *                                                  result a failure. They are are initially stored in memory buffers
    282  *                                                  and then moved to a data store.
    283  *                              MDNS_LOG_INFO       Info-level messages are intended for capturing information that may
    284  *                                                  be helpful, but isnt essential, for troubleshooting errors. They
    285  *                                                  are initially stored in memory buffers, but will only be moved into
    286  *                                                  data store when faults and, optionally, errors occur.
    287  *                              MDNS_LOG_DEBUG      Debug-level messages are intended for information that may be useful
    288  *                                                  during development or while troubleshooting a specific problem, Debug
    289  *                                                  logging should not be used in shipping software. They are only
    290  *                                                  captured in memory when debug logging is enabled through a
    291  *                                                  configuration change.
    292  *
    293  *  @param FORMAT           A constant string or format string that produces a human-readable log message. The format
    294  *                          string follows the IEEE printf specification, besides the following customized format specifiers:
    295  *                              %{mdnsresponder:domain_name}.*P     the pointer to a DNS lable sequence
    296  *                              %{mdnsresponder:ip_addr}.20P        the pointer to a mDNSAddr variable
    297  *                              %{network:in_addr}.4P               the pointer to a mDNSv4Addr variable
    298  *                              %{network:in6_addr}.16P             the pointer to a mDNSv6Addr variable
    299  *                              %{mdnsresponder:mac_addr}.6P        the pointer to a 6-byte-length MAC address
    300  *
    301  *  @param ...              The parameter list that will be formated by the format string. Note that if the customized
    302  *                          format specifiers are used and the data length is not specified in the format string, the
    303  *                          size should be listed before the pointer to the data, for example:
    304  *                              "%{mdnsresponder:domain_name}.*P", (name ? (int)DomainNameLength((const domainname *)name) : 0), <the pointer to a DNS label sequence>
    305  *
    306  */
    307     #define JOIN(X, Y) JOIN_AGAIN(X, Y)
    308     #define JOIN_AGAIN(X, Y) X ## Y
    309 
    310     #define LogRedact(CATEGORY, LEVEL, FORMAT, ...)                                         \
    311         do                                                                                  \
    312         {                                                                                   \
    313             if (!gSensitiveLoggingEnabled || ((CATEGORY) == (MDNS_LOG_CATEGORY_STATE)))     \
    314             {                                                                               \
    315                 os_log_with_type(CATEGORY, LEVEL, FORMAT, ## __VA_ARGS__);                  \
    316             }                                                                               \
    317             else                                                                            \
    318             {                                                                               \
    319                 os_log_with_type(JOIN(CATEGORY, _redacted), LEVEL, FORMAT, ## __VA_ARGS__); \
    320             }                                                                               \
    321         } while(0)
    322 #else
    323     #if (MDNS_HAS_VA_ARG_MACROS)
    324         #if (MDNS_C99_VA_ARGS)
    325             #define LogRedact(CATEGORY, LEVEL, ...) \
    326                 do { if (mDNS_LoggingEnabled) LogMsgWithLevel(CATEGORY, LEVEL, __VA_ARGS__); } while (0)
    327         #elif (MDNS_GNU_VA_ARGS)
    328             #define LogRedact(CATEGORY, LEVEL, ARGS...) \
    329                 do { if (mDNS_LoggingEnabled) LogMsgWithLevel(CATEGORY, LEVEL, ARGS); } while (0)
    330         #else
    331             #error "Unknown variadic macros"
    332         #endif
    333     #else
    334         #define LogRedact      (mDNS_LoggingEnabled == 0) ? ((void)0) : LogRedact_
    335         extern void LogRedact_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
    336     #endif
    337 #endif // MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    338 
    339 //======================================================================================================================
    340 // MARK: - RData Log Helper
    341 
    342 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    343     #define MDNS_CORE_LOG_RDATA_WITH_BUFFER(CATEGORY, LEVEL, RR_PTR, RDATA_BUF, RDATA_BUF_LEN, FORMAT, ...)     \
    344         do                                                                                                      \
    345         {                                                                                                       \
    346             mStatus _get_rdata_err;                                                                             \
    347             mDNSu16 _rdataLen;                                                                                  \
    348             const mDNSu8 *const _rdataBytes = ResourceRecordGetRDataBytesPointer((RR_PTR), (RDATA_BUF),         \
    349                 (RDATA_BUF_LEN), &_rdataLen, &_get_rdata_err);                                                  \
    350             if (!_get_rdata_err)                                                                                \
    351             {                                                                                                   \
    352                 mDNSu8 *_typeRDataBuf = mDNSNULL;                                                               \
    353                 mDNSu32 _typeRDataLen = 0;                                                                      \
    354                 mDNSu8 *_typeRDataBufHeap = mDNSNULL;                                                           \
    355                 if (sizeof(mDNSStorage.MsgBuffer) >= 2 + _rdataLen)                                             \
    356                 {                                                                                               \
    357                     _typeRDataBuf = (mDNSu8 *)mDNSStorage.MsgBuffer;                                            \
    358                     _typeRDataLen = sizeof(mDNSStorage.MsgBuffer);                                              \
    359                 }                                                                                               \
    360                 else                                                                                            \
    361                 {                                                                                               \
    362                     _typeRDataLen = 2 + _rdataLen;                                                              \
    363                     _typeRDataBufHeap = mDNSPlatformMemAllocate(_typeRDataLen);                                 \
    364                     _typeRDataBuf = _typeRDataBufHeap;                                                          \
    365                 }                                                                                               \
    366                 LogRedact(CATEGORY, LEVEL,                                                                      \
    367                     FORMAT "type: " PUB_DNS_TYPE ", rdata: " PRI_RDATA,                                         \
    368                     ##__VA_ARGS__, DNS_TYPE_PARAM((RR_PTR)->rrtype), RDATA_PARAM(_typeRDataBuf, _typeRDataLen,  \
    369                     (RR_PTR)->rrtype, _rdataBytes, _rdataLen));                                                 \
    370                 mDNSPlatformMemFree(_typeRDataBufHeap);                                                         \
    371             }                                                                                                   \
    372         } while (0)
    373 #else
    374     #define MDNS_CORE_LOG_RDATA_WITH_BUFFER(CATEGORY, LEVEL, RR_PTR, RDATA_BUF, RDATA_BUF_LEN, FORMAT, ...)         \
    375         do                                                                                                          \
    376         {                                                                                                           \
    377             (void)(RDATA_BUF);                                                                                      \
    378             (void)(RDATA_BUF_LEN);                                                                                  \
    379             LogRedact(CATEGORY, LEVEL, FORMAT " " PRI_S, ##__VA_ARGS__, RRDisplayString(&mDNSStorage, (RR_PTR)));   \
    380         } while (0)
    381 #endif
    382 
    383 #define MDNS_CORE_LOG_RDATA(CATEGORY, LEVEL, RR_PTR, FORMAT, ...)                                                   \
    384     do                                                                                                              \
    385     {                                                                                                               \
    386         mDNSu8 *_rdataBuffer = NULL;                                                                                \
    387         mDNSu8 *_rdataBufferHeap = NULL;                                                                            \
    388         mDNSu16 _rdataBufferLen;                                                                                    \
    389         if ((RR_PTR)->rdlength <= sizeof(mDNSStorage.RDataBuffer))                                                  \
    390         {                                                                                                           \
    391             _rdataBuffer = mDNSStorage.RDataBuffer;                                                                 \
    392             _rdataBufferLen = sizeof(mDNSStorage.RDataBuffer);                                                      \
    393         }                                                                                                           \
    394         else                                                                                                        \
    395         {                                                                                                           \
    396             _rdataBufferHeap = mDNSPlatformMemAllocate((RR_PTR)->rdlength);                                         \
    397             _rdataBuffer = _rdataBufferHeap;                                                                        \
    398             _rdataBufferLen = (RR_PTR)->rdlength;                                                                   \
    399         }                                                                                                           \
    400         if ((RR_PTR)->rdlength == 0)                                                                                \
    401         {                                                                                                           \
    402             LogRedact(CATEGORY, LEVEL,                                                                              \
    403                 FORMAT "type: " PUB_DNS_TYPE ", rdata: <none>", ##__VA_ARGS__, DNS_TYPE_PARAM((RR_PTR)->rrtype));   \
    404         }                                                                                                           \
    405         else                                                                                                        \
    406         {                                                                                                           \
    407             MDNS_CORE_LOG_RDATA_WITH_BUFFER(CATEGORY, LEVEL, RR_PTR, _rdataBuffer, _rdataBufferLen, FORMAT,         \
    408                 ##__VA_ARGS__);                                                                                     \
    409         }                                                                                                           \
    410         mDNSPlatformMemFree(_rdataBufferHeap);                                                                      \
    411     }                                                                                                               \
    412     while(0)
    413 
    414 //======================================================================================================================
    415 // MARK: - Customized Log Specifier
    416 
    417 // The followings are the customized log specifier defined in os_log. For compatibility, we have to define it when it is
    418 // not on the Apple platform, for example, the Posix platform. The keyword "public" or "private" is used to control whether
    419 // the content would be redacted when the redaction is turned on: "public" means the content will always be printed;
    420 // "private" means the content will be printed as <mask.hash: '<The hashed string from binary data>'> if the redaction is turned on,
    421 // only when the redaction is turned off, the content will be printed as what it should be. Note that the hash performed
    422 // to the data is a salted hashing transformation, and the salt is generated randomly on a per-process basis, meaning
    423 // that hashes cannot be correlated across processes or devices.
    424 
    425 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    426     #define PRI_PREFIX "{sensitive, mask.hash}"
    427 #else
    428     #define PRI_PREFIX
    429 #endif
    430 
    431 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    432     #define PUB_S "%{public}s"
    433     #define PRI_S "%{sensitive, mask.hash}s"
    434 #else
    435     #define PUB_S "%s"
    436     #define PRI_S PUB_S
    437 #endif
    438 
    439 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    440     #define PUB_BOOL                    "%{mdns:yesno}d"
    441     #define BOOL_PARAM(boolean_value)   (boolean_value)
    442 #else
    443     #define PUB_BOOL                    PUB_S
    444     #define BOOL_PARAM(boolean_value)   ((boolean_value) ? "yes" : "no")
    445 #endif
    446 
    447 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    448     #define PUB_TIMEV                   "%{public, timeval}.*P"
    449     #define TIMEV_PARAM(time_val_ptr)   ((int)sizeof(*time_val_ptr)), time_val_ptr
    450 #else
    451     #define PUB_TIMEV                   "%ld"
    452     #define TIMEV_PARAM(time_val_ptr)   ((time_val_ptr)->tv_sec)
    453 #endif
    454 
    455 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    456     #define DNS_MSG_ID_FLAGS                                "%{mdns:dns.idflags}08lX"
    457     #define DNS_MSG_ID_FLAGS_PARAM(HEADER, ID_AND_FLAGS)    ((unsigned long)(ID_AND_FLAGS))
    458 #else
    459     #define DNS_MSG_ID_FLAGS                                "id: 0x%04X (%u), flags: 0x%04X"
    460     #define DNS_MSG_ID_FLAGS_PARAM(HEADER, ID_AND_FLAGS)    mDNSVal16((HEADER).id), mDNSVal16((HEADER).id), \
    461                                                                 ((HEADER).flags.b)
    462 #endif
    463 
    464 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    465     #define DNS_MSG_COUNTS                          "%{mdns:dns.counts}016llX"
    466     #define DNS_MSG_COUNTS_PARAM(HEADER, COUNTS)    ((unsigned long long)(COUNTS))
    467 #else
    468     #define DNS_MSG_COUNTS                          "counts: %u/%u/%u/%u"
    469     #define DNS_MSG_COUNTS_PARAM(HEADER, COUNTS)    (HEADER).numQuestions, (HEADER).numAnswers, \
    470                                                         (HEADER).numAuthorities, (HEADER).numAdditionals
    471 #endif
    472 
    473 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    474     #define MDNS_NAME_HASH_TYPE_BYTES \
    475         "%{sensitive, mask.hash, mdnsresponder:mdns_name_hash_type_bytes}.*P"
    476     #define MDNS_NAME_HASH_TYPE_BYTES_PARAM(BYTES, BYTES_LEN) BYTES_LEN, BYTES
    477 #else
    478     // If os_log is not supported, there is no way to parse the name hash type bytes.
    479     #define MDNS_NAME_HASH_TYPE_BYTES                           "%s"
    480     #define MDNS_NAME_HASH_TYPE_BYTES_PARAM(BYTES, BYTES_LEN)   ""
    481 #endif
    482 
    483 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    484     #define PUB_DNS_TYPE                "%{mdns:rrtype}d"
    485     #define DNS_TYPE_PARAM(type_value)  (type_value)
    486 #else
    487     #define PUB_DNS_TYPE                PUB_S
    488     #define DNS_TYPE_PARAM(type_value)  (DNSTypeName(type_value))
    489 #endif
    490 
    491 // Notes about using RMV rather than REMOVE:
    492 // Both "add" and "rmv" are three characters so that when the log is printed, the content will be aligned which is good
    493 // for log searching. For example:
    494 // DNSServiceBrowse(_test._tcp.local., PTR) RESULT ADD interface 1:   23 _test._tcp.local. PTR demo._test._tcp.local.
    495 // DNSServiceBrowse(_test._tcp.local., PTR) RESULT RMV interface 1:   23 _test._tcp.local. PTR demo._test._tcp.local.
    496 // is better than:
    497 // DNSServiceBrowse(_test._tcp.local., PTR) RESULT ADD interface 1:   23 _test._tcp.local. PTR demo._test._tcp.local.
    498 // DNSServiceBrowse(_test._tcp.local., PTR) RESULT REMOVE interface 1:   23 _test._tcp.local. PTR demo._test._tcp.local.
    499 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    500     #define PUB_ADD_RMV                     "%{mdns:addrmv}d"
    501     #define ADD_RMV_PARAM(add_rmv_value)    (add_rmv_value)
    502 #else
    503     #define PUB_ADD_RMV                     PUB_S
    504     #define ADD_RMV_PARAM(add_rmv_value)    ((add_rmv_value) ? "add" : "rmv")
    505 #endif
    506 
    507 // Here we have the uppercase style so that it can be used to match the original mDNSResponder RESULT ADD/RMV all
    508 // uppercase.
    509 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    510     #define PUB_ADD_RMV_U                   "%{mdns:addrmv_upper}d"
    511     #define ADD_RMV_U_PARAM(add_rmv_value)  (add_rmv_value)
    512 #else
    513     #define PUB_ADD_RMV_U                   PUB_S
    514     #define ADD_RMV_U_PARAM(add_rmv_value)  ((add_rmv_value) ? "ADD" : "RMV")
    515 #endif
    516 
    517 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    518     #define PUB_PN                      "%{mdns:pos/neg}d"
    519     #define PN_PARAM(pn_boolean_value)  (pn_boolean_value)
    520 #else
    521     #define PUB_PN                      PUB_S
    522     #define PN_PARAM(pn_boolean_value)  ((pn_boolean_value) ? "positive" : "negative")
    523 #endif
    524 
    525 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    526     #define PUB_MORTALITY                       "%{mdns:mortality}d"
    527     #define MORTALITY_PARAM(mortality_value)    (mortality_value)
    528 #else
    529     #define PUB_MORTALITY                       PUB_S
    530     #define MORTALITY_PARAM(mortality_value)    (MortalityDisplayString(mortality_value))
    531 #endif
    532 
    533 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    534     #define PUB_DM_NAME                 "%{public, mdnsresponder:domain_name}.*P"
    535     #define PRI_DM_NAME                 "%{sensitive, mask.hash, mdnsresponder:domain_name}.*P"
    536     // When DM_NAME_PARAM is used, the file where the function is defined must include DNSEmbeddedAPI.h
    537     #define DM_NAME_PARAM(name)         ((name) ? ((int)DomainNameLength((name))) : 0), (name)
    538     #define DM_NAME_PARAM_NONNULL(name) (int)DomainNameLength(name), (name)
    539 #else
    540     #define PUB_DM_NAME                 "%##s"
    541     #define PRI_DM_NAME                 PUB_DM_NAME
    542     #define DM_NAME_PARAM(name)         (name)
    543     #define DM_NAME_PARAM_NONNULL(name) (name)
    544 #endif
    545 
    546 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    547     #define PUB_DM_LABEL                "%{public, mdnsresponder:domain_label}.*P"
    548     #define PRI_DM_LABEL                "%{sensitive, mask.hash, mdnsresponder:domain_label}.*P"
    549     #define DM_LABEL_PARAM(label)       1 + ((label)->c[0]), ((label)->c)
    550     #define DM_LABEL_PARAM_SAFE(label)  (label ? 1 + ((label)->c[0]) : 0), ((label)->c)
    551 #else
    552     #define PUB_DM_LABEL                "%#s"
    553     #define PRI_DM_LABEL                PUB_DM_LABEL
    554     #define DM_LABEL_PARAM(label)       (label)
    555     #define DM_LABEL_PARAM_SAFE(label)  (label)
    556 #endif
    557 
    558 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    559     #define PUB_IP_ADDR "%{public, mdnsresponder:ip_addr}.20P"
    560     #define PRI_IP_ADDR "%{sensitive, mask.hash, mdnsresponder:ip_addr}.20P"
    561 
    562     #define PUB_IPv4_ADDR "%{public, network:in_addr}.4P"
    563     #define PRI_IPv4_ADDR "%{sensitive, mask.hash, network:in_addr}.4P"
    564 
    565     #define PUB_IPv6_ADDR "%{public, network:in6_addr}.16P"
    566     #define PRI_IPv6_ADDR "%{sensitive, mask.hash, network:in6_addr}.16P"
    567 #else
    568     #define PUB_IP_ADDR "%#a"
    569     #define PRI_IP_ADDR PUB_IP_ADDR
    570 
    571     #define PUB_IPv4_ADDR "%.4a"
    572     #define PRI_IPv4_ADDR PUB_IPv4_ADDR
    573 
    574     #define PUB_IPv6_ADDR "%.16a"
    575     #define PRI_IPv6_ADDR PUB_IPv6_ADDR
    576 #endif
    577 
    578 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    579     #define PUB_MAC_ADDR "%{public, mdnsresponder:mac_addr}.6P"
    580     #define PRI_MAC_ADDR "%{sensitive, mask.hash, mdnsresponder:mac_addr}.6P"
    581 #else
    582     #define PUB_MAC_ADDR "%.6a"
    583     #define PRI_MAC_ADDR PUB_MAC_ADDR
    584 #endif
    585 
    586 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    587     #define PUB_HEX "%{public, mdnsresponder:hex_sequence}.*P"
    588     #define PRI_HEX "%{sensitive, mask.hash, mdnsresponder:hex_sequence}.*P"
    589     #define HEX_PARAM(hex, hex_length) (int)(hex_length), (hex)
    590 #else
    591     #define PUB_HEX "%p"
    592     #define PRI_HEX PUB_HEX
    593     #define HEX_PARAM(hex, hex_length) (hex)
    594 #endif
    595 
    596 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    597     #define PUB_DNSKEY "%{public, mdns:rd.dnskey}.*P"
    598     #define PRI_DNSKEY "%{sensitive, mask.hash, mdns:rd.dnskey}.*P"
    599     #define DNSKEY_PARAM(rdata, rdata_length) (rdata_length), (rdata)
    600 #else
    601     #define PUB_DNSKEY "%p"
    602     #define PRI_DNSKEY PUB_DNSKEY
    603     #define DNSKEY_PARAM(rdata, rdata_length) (rdata)
    604 #endif
    605 
    606 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    607     #define PUB_DS "%{public, mdns:rd.ds}.*P"
    608     #define PRI_DS "%{sensitive, mask.hash, mdns:rd.ds}.*P"
    609     #define DS_PARAM(rdata, rdata_length) (rdata_length), (rdata)
    610 #else
    611     #define PUB_DS "%p"
    612     #define PRI_DS PUB_DS
    613     #define DS_PARAM(rdata, rdata_length) (rdata)
    614 #endif
    615 
    616 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    617     #define PUB_NSEC "%{public, mdns:rd.nsec}.*P"
    618     #define PRI_NSEC "%{sensitive, mask.hash, mdns:rd.nsec}.*P"
    619     #define NSEC_PARAM(rdata, rdata_length) (rdata_length), (rdata)
    620 #else
    621     #define PUB_NSEC "%p"
    622     #define PRI_NSEC PUB_NSEC
    623     #define NSEC_PARAM(rdata, rdata_length) (rdata)
    624 #endif
    625 
    626 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    627     #define PUB_NSEC3 "%{public, mdns:rd.nsec3}.*P"
    628     #define PRI_NSEC3 "%{sensitive, mask.hash, mdns:rd.nsec3}.*P"
    629     #define NSEC3_PARAM(rdata, rdata_length) (rdata_length), (rdata)
    630 #else
    631     #define PUB_NSEC3 "%p"
    632     #define PRI_NSEC3 PUB_NSEC3
    633     #define NSEC3_PARAM(rdata, rdata_length) (rdata)
    634 #endif
    635 
    636 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    637     #define PUB_RRSIG "%{public, mdns:rd.rrsig}.*P"
    638     #define PRI_RRSIG "%{sensitive, mask.hash, mdns:rd.rrsig}.*P"
    639     #define RRSIG_PARAM(rdata, rdata_length) (rdata_length), (rdata)
    640 #else
    641     #define PUB_RRSIG "%p"
    642     #define PRI_RRSIG PUB_RRSIG
    643     #define RRSIG_PARAM(rdata, rdata_length) (rdata)
    644 #endif
    645 
    646 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    647     #define PUB_SVCB "%{public, mdns:rd.svcb}.*P"
    648     #define PRI_SVCB "%{sensitive, mask.hash, mdns:rd.svcb}.*P"
    649     #define SVCB_PARAM(rdata, rdata_length) (rdata_length), (rdata)
    650 #else
    651     #define PUB_SVCB "%p"
    652     #define PRI_SVCB PUB_SVCB
    653     #define SVCB_PARAM(rdata, rdata_length) (rdata)
    654 #endif
    655 
    656 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
    657     #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    658         #define PUB_DNSSEC_RESULT                           "%{public, mdns:dnssec_result}d"
    659         #define DNSSEC_RESULT_PARAM(dnssec_result_value)    (dnssec_result_value)
    660     #else
    661         #define PUB_DNSSEC_RESULT                           "%s"
    662         #define DNSSEC_RESULT_PARAM(dnssec_result_value)    (dnssec_result_to_description(dnssec_result_value))
    663     #endif
    664 #else
    665         #define PUB_DNSSEC_RESULT                           "%s"
    666         #define DNSSEC_RESULT_PARAM(dnssec_result_value)    ("<DNSSEC Unsupported>")
    667 #endif
    668 
    669 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
    670     #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    671         #define PUB_DNSSEC_INVAL_STATE                  "%{public, mdns:dnssec_inval_state}d"
    672         #define DNSSEC_INVAL_STATE_PARAM(state_value)   (state_value)
    673     #else
    674         #define PUB_DNSSEC_INVAL_STATE                  "%s"
    675         #define DNSSEC_INVAL_STATE_PARAM(state_value)   (dnssec_insecure_validation_state_to_description(state_value))
    676     #endif
    677 #else
    678         #define PUB_DNSSEC_INVAL_STATE                  "%s"
    679         #define DNSSEC_INVAL_STATE_PARAM(state_value)   ("<DNSSEC Unsupported>")
    680 #endif
    681 
    682 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    683     #define PUB_TIME_DUR    "%{mdns:time_duration}u"
    684 #else
    685     #define PUB_TIME_DUR    "%us"
    686 #endif
    687 
    688 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    689     #define PUB_OS_ERR    "%{mdns:err}ld"
    690 #else
    691     #define PUB_OS_ERR    "%ld"
    692 #endif
    693 
    694 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    695     #define PUB_RDATA       "%{public, mdns:rdata}.*P"
    696     #define PRI_RDATA       "%{sensitive, mask.hash, mdns:rdata}.*P"
    697     #define RDATA_PARAM(buf, buf_len, rrtype, rdata, rdata_len) \
    698                             (rdata_len + 2), GetPrintableRDataBytes(buf, buf_len, rrtype, rdata, rdata_len)
    699 
    700     #define PUB_TYPE_RDATA  "%{public, mdns:rrtype+rdata}.*P"
    701     #define PRI_TYPE_RDATA  "%{sensitive, mask.hash, mdns:rrtype+rdata}.*P"
    702     #define TYPE_RDATA_PARAM(buf, buf_len, rrtype, rdata, rdata_len) RDATA_PARAM(buf, buf_len, rrtype, rdata, rdata_len)
    703 #else
    704     #define PUB_RDATA       "%p"
    705     #define PRI_RDATA       PUB_RDATA
    706     #define RDATA_PARAM(buf, buf_len, rrtype, rdata, rdata_len) (rdata)
    707 
    708     #define PUB_TYPE_RDATA  PUB_S " %p"
    709     #define PRI_TYPE_RDATA  PUB_TYPE_RDATA
    710     #define TYPE_RDATA_PARAM(buf, buf_len, rrtype, rdata, rdata_len) \
    711                             DNSTypeName(rrtype), RDATA_PARAM(buf, buf_len, rrtype, rdata, rdata_len)
    712 #endif
    713 
    714 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    715     #define PUB_D2D_SRV_EVENT   "%{public, mdnsresponder:d2d_service_event}d"
    716 #endif
    717 
    718 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
    719     #define PUB_DNS_SCOPE_TYPE          "%{public, mdnsresponder:dns_scope_type}d"
    720     #define DNS_SCOPE_TYPE_PARAM(type)  (type)
    721 #else
    722     #define PUB_DNS_SCOPE_TYPE          "%s"
    723     #define DNS_SCOPE_TYPE_PARAM(type)  DNSScopeToString(type)
    724 #endif
    725 
    726 extern void LogToFD(int fd, const char *format, ...);
    727 
    728 #endif // __mDNSDebug_h
    729