]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/mdns_objects/mdns_helpers.c
mDNSResponder-1310.40.42.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / mdns_objects / mdns_helpers.c
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 #include "mdns_helpers.h"
18
19 #include <CoreUtils/CoreUtils.h>
20 #include "DNSMessage.h"
21
22 //======================================================================================================================
23 // MARK: - Internals
24
25 MDNS_LOG_CATEGORY_DEFINE(helpers, "helpers");
26
27 //======================================================================================================================
28
29 int
30 mdns_snprintf_add(char **ptr, const char *lim, const char *fmt, ...)
31 {
32 va_list args;
33 char * const dst = ptr ? *ptr : NULL;
34 const size_t len = (size_t)(lim - dst);
35 va_start(args, fmt);
36 const int n = vsnprintf(dst, len, fmt, args);
37 va_end(args);
38 require_quiet(n >= 0, exit);
39
40 if (ptr) {
41 if (((size_t)n) > len) {
42 *ptr = dst + len;
43 } else {
44 *ptr = dst + n;
45 }
46 }
47
48 exit:
49 return n;
50 }
51
52 //======================================================================================================================
53
54 OSStatus
55 mdns_replace_string(char **string_ptr, const char *replacement)
56 {
57 OSStatus err;
58 char *new_string;
59 if (replacement) {
60 new_string = strdup(replacement);
61 require_action_quiet(new_string, exit, err = kNoMemoryErr);
62 } else {
63 new_string = NULL;
64 }
65 FreeNullSafe(*string_ptr);
66 *string_ptr = new_string;
67 err = kNoErr;
68
69 exit:
70 return err;
71 }
72
73 //======================================================================================================================
74
75 OSStatus
76 mdns_make_socket_nonblocking(int sock)
77 {
78 int flags = fcntl(sock, F_GETFL, 0);
79 flags |= O_NONBLOCK;
80 OSStatus err = fcntl(sock, F_SETFL, flags);
81 err = map_global_value_errno(err != -1, err);
82 return err;
83 }
84
85 //======================================================================================================================
86
87 uint64_t
88 mdns_mach_ticks_per_second(void)
89 {
90 static dispatch_once_t s_once = 0;
91 static uint64_t s_ticks_per_second = 0;
92 dispatch_once(&s_once,
93 ^{
94 mach_timebase_info_data_t info;
95 const kern_return_t err = mach_timebase_info(&info);
96 if (!err && (info.numer != 0) && (info.denom != 0)) {
97 s_ticks_per_second = (info.denom * UINT64_C_safe(kNanosecondsPerSecond)) / info.numer;
98 } else {
99 os_log_error(_mdns_helpers_log(),
100 "Unexpected results from mach_timebase_info: err %d numer %u denom %u", err, info.numer, info.denom);
101 s_ticks_per_second = kNanosecondsPerSecond;
102 }
103 });
104 return s_ticks_per_second;
105 }
106
107 //======================================================================================================================
108
109 int
110 mdns_print_obfuscated_ip_address(char * const buf_ptr, const size_t buf_len, const struct sockaddr * const sa)
111 {
112 int n;
113 char strbuf[64];
114 switch (sa->sa_family) {
115 case AF_INET: {
116 const struct sockaddr_in * const sin = (const struct sockaddr_in *)sa;
117 n = DNSMessagePrintObfuscatedIPv4Address(strbuf, sizeof(strbuf), ntohl(sin->sin_addr.s_addr));
118 require_return_value(n >= 0, n);
119 return snprintf(buf_ptr, buf_len, "<IPv4:%s>", strbuf);
120 }
121 case AF_INET6: {
122 const struct sockaddr_in6 * const sin6 = (const struct sockaddr_in6 *)sa;
123 n = DNSMessagePrintObfuscatedIPv6Address(strbuf, sizeof(strbuf), sin6->sin6_addr.s6_addr);
124 require_return_value(n >= 0, n);
125 return snprintf(buf_ptr, buf_len, "<IPv6:%s>", strbuf);
126 }
127 default: {
128 return kTypeErr;
129 }
130 }
131 }