]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/SymptomReporter.c
mDNSResponder-1310.80.1.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / SymptomReporter.c
1 /*
2 * Copyright (c) 2015-2019 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 * http://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 "SymptomReporter.h"
18
19 #if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS) && !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
20 #include <arpa/inet.h>
21 #include <dlfcn.h>
22 #include <stddef.h>
23 #include <stdint.h>
24 #include <sys/socket.h>
25 #include <AvailabilityMacros.h>
26 #include <SymptomReporter/SymptomReporter.h>
27
28 #define SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID 101
29 #define SYMPTOM_REPORTER_mDNSResponder_TEXT_ID "com.apple.mDNSResponder"
30
31 #define SYMPTOM_DNS_NO_REPLIES 0x00065001
32 #define SYMPTOM_DNS_RESUMED_RESPONDING 0x00065002
33
34 mDNSu32 NumUnreachableDNSServers;
35
36 static symptom_framework_t symptomReporter = mDNSNULL;
37 static symptom_framework_t (*symptom_framework_init_f)(symptom_ident_t id, const char *originator_string) = mDNSNULL;
38 static symptom_t (*symptom_new_f)(symptom_framework_t framework, symptom_ident_t id) = mDNSNULL;
39 static int (*symptom_set_additional_qualifier_f)(symptom_t symptom, uint32_t qualifier_type, size_t qualifier_len, void *qualifier_data) = mDNSNULL;
40 static int (*symptom_send_f)(symptom_t symptom) = mDNSNULL;
41
42 mDNSlocal mStatus SymptomReporterInitCheck(void)
43 {
44 mStatus err;
45 static mDNSBool triedInit = mDNSfalse;
46 static void *symptomReporterLib = mDNSNULL;
47 static const char path[] = "/System/Library/PrivateFrameworks/SymptomReporter.framework/SymptomReporter";
48
49 if (!triedInit)
50 {
51 triedInit = mDNStrue;
52
53 symptomReporterLib = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
54 if (!symptomReporterLib)
55 goto exit;
56
57 symptom_framework_init_f = dlsym(symptomReporterLib, "symptom_framework_init");
58 if (!symptom_framework_init_f)
59 goto exit;
60
61 symptom_new_f = dlsym(symptomReporterLib, "symptom_new");
62 if (!symptom_new_f)
63 goto exit;
64
65 symptom_set_additional_qualifier_f = dlsym(symptomReporterLib, "symptom_set_additional_qualifier");
66 if (!symptom_set_additional_qualifier_f)
67 goto exit;
68
69 symptom_send_f = dlsym(symptomReporterLib, "symptom_send");
70 if (!symptom_send_f)
71 goto exit;
72
73 symptomReporter = symptom_framework_init_f(SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID, SYMPTOM_REPORTER_mDNSResponder_TEXT_ID);
74 }
75
76 exit:
77 err = symptomReporter ? mStatus_NoError : mStatus_NotInitializedErr;
78 return err;
79 }
80
81 mDNSlocal mStatus SymptomReporterReportDNSReachability(const mDNSAddr *addr, mDNSBool isReachable)
82 {
83 mStatus err;
84 symptom_t symptom;
85 struct sockaddr_storage sockAddr;
86 size_t sockAddrSize;
87
88 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
89 "SymptomReporterReportDNSReachability: DNS server " PRI_IP_ADDR " is " PUB_S "reachable", addr, isReachable ? "" : "un");
90
91 if (addr->type == mDNSAddrType_IPv4)
92 {
93 struct sockaddr_in *sin = (struct sockaddr_in *)&sockAddr;
94 sockAddrSize = sizeof(*sin);
95 mDNSPlatformMemZero(sin, sockAddrSize);
96 sin->sin_len = sockAddrSize;
97 sin->sin_family = AF_INET;
98 sin->sin_addr.s_addr = addr->ip.v4.NotAnInteger;
99 }
100 else if (addr->type == mDNSAddrType_IPv6)
101 {
102 struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&sockAddr;
103 sockAddrSize = sizeof(*sin6);
104 mDNSPlatformMemZero(sin6, sockAddrSize);
105 sin6->sin6_len = sockAddrSize;
106 sin6->sin6_family = AF_INET6;
107 sin6->sin6_addr = *(struct in6_addr *)&addr->ip.v6;
108 }
109 else
110 {
111 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
112 "SymptomReporterReportDNSReachability: addr is not an IPv4 or IPv6 address!");
113 err = mStatus_BadParamErr;
114 goto exit;
115 }
116
117 symptom = symptom_new_f(symptomReporter, isReachable ? SYMPTOM_DNS_RESUMED_RESPONDING : SYMPTOM_DNS_NO_REPLIES);
118 symptom_set_additional_qualifier_f(symptom, 1, sockAddrSize, (void *)&sockAddr);
119 symptom_send_f(symptom);
120 err = mStatus_NoError;
121
122 exit:
123 return err;
124 }
125
126 mDNSexport mStatus SymptomReporterDNSServerReachable(mDNS *const m, const mDNSAddr *addr)
127 {
128 mStatus err;
129 DNSServer *s;
130 mDNSBool found = mDNSfalse;
131
132 err = SymptomReporterInitCheck();
133 if (err != mStatus_NoError)
134 goto exit;
135
136 for (s = m->DNSServers; s; s = s->next)
137 {
138 if (s->flags & DNSServerFlag_Delete)
139 continue;
140 if ((s->flags & DNSServerFlag_Unreachable) && mDNSSameAddress(addr, &s->addr))
141 {
142 s->flags &= ~DNSServerFlag_Unreachable;
143 NumUnreachableDNSServers--;
144 found = mDNStrue;
145 }
146 }
147
148 if (!found)
149 {
150 err = mStatus_NoSuchNameErr;
151 goto exit;
152 }
153
154 err = SymptomReporterReportDNSReachability(addr, mDNStrue);
155
156 exit:
157 return err;
158 }
159
160 mDNSexport mStatus SymptomReporterDNSServerUnreachable(DNSServer *s)
161 {
162 mStatus err;
163
164 err = SymptomReporterInitCheck();
165 if (err != mStatus_NoError)
166 goto exit;
167
168 if ((s->flags & DNSServerFlag_Delete) || (s->flags & DNSServerFlag_Unreachable))
169 goto exit;
170
171 s->flags |= DNSServerFlag_Unreachable;
172 NumUnreachableDNSServers++;
173
174 err = SymptomReporterReportDNSReachability(&s->addr, mDNSfalse);
175
176 exit:
177 return err;
178 }
179 #endif // MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)