]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/mdns_objects/log_mdns.m
mDNSResponder-1310.40.42.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / mdns_objects / log_mdns.m
1 /*
2 * Copyright (c) 2019-2020 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 #import "DNSMessage.h"
18
19 #import <CoreUtils/CoreUtils.h>
20 #import <Foundation/Foundation.h>
21 #import <os/log_private.h>
22
23 #if !COMPILER_ARC
24 #error "This file must be compiled with ARC."
25 #endif
26
27 //======================================================================================================================
28 // MARK: - Specifiers
29 //
30 // Data Type Specifier Arguments Notes
31 // DNS message %{mdns:dnsmsg}.*P length (int), pointer (void *) -
32 // DNS message header %{mdns:dnshdr}.*P length (int), pointer (void *) -
33 // Error code integer %{mdns:err}d, %{mdns:err}ld, etc. error code (int, OSStatus, etc.) 1
34 // DNS record data %{mdns:rd.<record type>}.*P length (int), pointer (void *) 2,3,4
35 // DNS record type %{mdns:rrtype}d record type (int)
36 //
37 // Notes:
38 // 1. Formatting is handled by NSPrintTypedObject() from the CoreUtils framework, which handles a large variety of
39 // error codes, including errno and kDNSServiceErr_* error codes.
40 // 2. The DNS record data must be fully expanded, i.e., it must not contain any compressed DNS domain names.
41 // 3. The <record type> portion of the specifier is a case-insensitive DNS record type mnemonic, e.g., A, AAAA,
42 // DNSKEY, DS, etc.
43 // 4. Formatting is handled by DNSRecordDataToString(), which currently only handles a subset of record types.
44 // This subset consists of the record types most commonly encountered by mDNSResponder. This subset may grow
45 // as needed.
46 //
47 // The specifiers for DNSSEC record data, %{mdns:dnskey}, %{mdns:ds}, %{mdns:nsec}, %{mdns:nsec3}, and
48 // %{mdns:rrsig}, have been deprecated in favor of the %{mdns:rd.<record type>} style of record data specifiers.
49
50 #define LOG_MDNS_SPECIFIER_DNS_MESSAGE "dnsmsg"
51 #define LOG_MDNS_SPECIFIER_DNS_MESSAGE_HEADER "dnshdr"
52 #define LOG_MDNS_SPECIFIER_ERROR "err"
53 #define LOG_MDNS_SPECIFIER_RDATA_PREFIX "rd."
54 #define LOG_MDNS_SPECIFIER_DNS_RECORD_TYPE "rrtype"
55
56 //======================================================================================================================
57 // MARK: - Data Structures
58
59 typedef NSAttributedString *
60 (*log_mdns_data_formatter_f)(NSData *data);
61
62 typedef struct {
63 const char * specifier;
64 log_mdns_data_formatter_f formatter;
65 } log_mdns_data_formatter_item_t;
66
67 typedef NSAttributedString *
68 (*log_mdns_number_formatter_f)(NSNumber *number);
69
70 typedef struct {
71 const char * specifier;
72 log_mdns_number_formatter_f formatter;
73 } log_mdns_number_formatter_item_t;
74
75 //======================================================================================================================
76 // MARK: - Local Prototypes
77
78 static NSAttributedString *
79 _log_mdns_format_dns_message(NSData *data);
80
81 static NSAttributedString *
82 _log_mdns_format_dns_message_header(NSData *data);
83
84 static NSAttributedString *
85 _log_mdns_format_record_data(NSData *data, int record_type);
86
87 static NSAttributedString *
88 _log_mdns_format_err(NSNumber *number);
89
90 static NSAttributedString *
91 _log_mdns_format_dns_record_type(NSNumber *number);
92
93 static NSAttributedString *
94 _log_mdns_format_dns_message_ex(NSData *data, DNSMessageToStringFlags extra_flags);
95
96 //======================================================================================================================
97 // MARK: - DNS Record Data Formatters
98
99 #define LOG_MDNS_DEFINE_RDATA_FORMATTER(RECORD_TYPE) \
100 static NSAttributedString * \
101 _log_mdns_format_record_data_ ## RECORD_TYPE (NSData * const rdata) \
102 { \
103 return _log_mdns_format_record_data(rdata, kDNSRecordType_ ## RECORD_TYPE); \
104 } \
105 extern int _log_mdns_dummy_variable
106
107 LOG_MDNS_DEFINE_RDATA_FORMATTER(DNSKEY);
108 LOG_MDNS_DEFINE_RDATA_FORMATTER(DS);
109 LOG_MDNS_DEFINE_RDATA_FORMATTER(NSEC);
110 LOG_MDNS_DEFINE_RDATA_FORMATTER(NSEC3);
111 LOG_MDNS_DEFINE_RDATA_FORMATTER(RRSIG);
112
113 //======================================================================================================================
114 // MARK: - External Functions
115
116 #define LOG_MDNS_RDATA_FORMATTER_ITEM(RECORD_TYPE) { # RECORD_TYPE, _log_mdns_format_record_data_ ## RECORD_TYPE }
117
118 NSAttributedString *
119 OSLogCopyFormattedString(const char * const specifier, const id arg, __unused const os_log_type_info_t info)
120 {
121 if ([arg isKindOfClass:[NSData class]]) {
122 NSData * const data = (NSData *)arg;
123 if (stricmp_prefix(specifier, LOG_MDNS_SPECIFIER_RDATA_PREFIX) == 0) {
124 const char * const type_str = specifier + sizeof_string(LOG_MDNS_SPECIFIER_RDATA_PREFIX);
125 const int type_value = DNSRecordTypeStringToValue(type_str);
126 if (type_value != 0) {
127 return _log_mdns_format_record_data(data, type_value);
128 }
129 } else {
130 const log_mdns_data_formatter_item_t log_mdns_data_formatter_table[] = {
131 { LOG_MDNS_SPECIFIER_DNS_MESSAGE, _log_mdns_format_dns_message },
132 { LOG_MDNS_SPECIFIER_DNS_MESSAGE_HEADER, _log_mdns_format_dns_message_header },
133 LOG_MDNS_RDATA_FORMATTER_ITEM(DNSKEY),
134 LOG_MDNS_RDATA_FORMATTER_ITEM(DS),
135 LOG_MDNS_RDATA_FORMATTER_ITEM(NSEC),
136 LOG_MDNS_RDATA_FORMATTER_ITEM(NSEC3),
137 LOG_MDNS_RDATA_FORMATTER_ITEM(RRSIG)
138 };
139 for (size_t i = 0; i < countof(log_mdns_data_formatter_table); ++i) {
140 const log_mdns_data_formatter_item_t * const item = &log_mdns_data_formatter_table[i];
141 if (strcasecmp(specifier, item->specifier) == 0) {
142 return item->formatter(data);
143 }
144 }
145 }
146 } else if ([arg isKindOfClass:[NSNumber class]]) {
147 const log_mdns_number_formatter_item_t log_mdns_number_formatter_table[] = {
148 { LOG_MDNS_SPECIFIER_ERROR, _log_mdns_format_err },
149 { LOG_MDNS_SPECIFIER_DNS_RECORD_TYPE, _log_mdns_format_dns_record_type }
150 };
151 NSNumber * const number = (NSNumber *)arg;
152 for (size_t i = 0; i < countof(log_mdns_number_formatter_table); ++i) {
153 const log_mdns_number_formatter_item_t * const item = &log_mdns_number_formatter_table[i];
154 if (strcasecmp(specifier, item->specifier) == 0) {
155 return item->formatter(number);
156 }
157 }
158 }
159 return nil;
160 }
161
162 //======================================================================================================================
163 // MARK: - Internal Functions
164
165 static NSAttributedString *
166 _log_mdns_format_dns_message(NSData * const data)
167 {
168 return _log_mdns_format_dns_message_ex(data, kDNSMessageToStringFlag_Null);
169 }
170
171 //======================================================================================================================
172
173 static NSAttributedString *
174 _log_mdns_format_dns_message_header(NSData * const data)
175 {
176 return _log_mdns_format_dns_message_ex(data, kDNSMessageToStringFlag_HeaderOnly);
177 }
178
179 //======================================================================================================================
180
181 static NSAttributedString *
182 _log_mdns_format_err(NSNumber * const number)
183 {
184 return NSPrintTypedObject("err", number, NULL);
185 }
186
187 //======================================================================================================================
188
189 static NSAttributedString *
190 _log_mdns_format_dns_record_type(NSNumber * const number)
191 {
192 unsigned long long value = [number unsignedLongLongValue];
193 require_return_value(value <= INT_MAX, nil);
194
195 NSString *nsstr;
196 const char *cstr = DNSRecordTypeValueToString((int)value);
197 if (cstr) {
198 nsstr = [[NSString alloc] initWithFormat:@"%s", cstr];
199 require_return_value(nsstr, nil);
200 } else {
201 nsstr = [[NSString alloc] initWithFormat:@"TYPE%u", (unsigned int)value];
202 require_return_value(nsstr, nil);
203 }
204 return [[NSAttributedString alloc] initWithString:nsstr];
205 }
206
207 //======================================================================================================================
208
209 static NSAttributedString *
210 _log_mdns_format_record_data(NSData * const rdata, const int record_type)
211 {
212 char *cstr = NULL;
213 DNSRecordDataToString(rdata.bytes, rdata.length, record_type, &cstr);
214 if (!cstr) {
215 return nil;
216 }
217 const size_t len = strlen(cstr);
218 NSString * const nsstr = [[NSString alloc] initWithBytesNoCopy:cstr length:len encoding:NSUTF8StringEncoding
219 freeWhenDone:YES];
220 if (!nsstr) {
221 ForgetMem(&cstr);
222 return nil;
223 }
224 return [[NSAttributedString alloc] initWithString:nsstr];
225 }
226
227 //======================================================================================================================
228
229 static NSAttributedString *
230 _log_mdns_format_dns_message_ex(NSData * const data, const DNSMessageToStringFlags extra_flags)
231 {
232 char *msg_cstr = NULL;
233 const DNSMessageToStringFlags flags = kDNSMessageToStringFlag_OneLine | extra_flags;
234 DNSMessageToString(data.bytes, data.length, flags, &msg_cstr);
235 require_return_value(msg_cstr, nil);
236
237 NSString *msg_nsstr = [[NSString alloc] initWithBytesNoCopy:msg_cstr length:strlen(msg_cstr)
238 encoding:NSUTF8StringEncoding freeWhenDone:YES];
239 require_return_value_action(msg_nsstr, nil, ForgetMem(&msg_cstr));
240
241 return [[NSAttributedString alloc] initWithString:msg_nsstr];
242 }