]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/SymptomReporter.c
mDNSResponder-765.20.4.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / SymptomReporter.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2015 Apple Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include "mDNSEmbeddedAPI.h"
19
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 <TargetConditionals.h>
27
28 #define TARGET_OS_MACOSX (TARGET_OS_MAC && !TARGET_OS_IPHONE)
29
30 #if (!TARGET_OS_MACOSX || (MAC_OS_X_VERSION_MAX_ALLOWED >= 101200))
31 #include <SymptomReporter/SymptomReporter.h>
32 #else
33 #include <Symptoms/SymptomReporter.h>
34 #endif
35
36 #define SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID 101
37 #define SYMPTOM_REPORTER_mDNSResponder_TEXT_ID "com.apple.mDNSResponder"
38
39 #define SYMPTOM_DNS_NO_REPLIES 0x00065001
40 #define SYMPTOM_DNS_RESUMED_RESPONDING 0x00065002
41
42 static symptom_framework_t symptomReporter = mDNSNULL;
43 static symptom_framework_t (*symptom_framework_init_f)(symptom_ident_t id, const char *originator_string) = mDNSNULL;
44 static symptom_t (*symptom_new_f)(symptom_framework_t framework, symptom_ident_t id) = mDNSNULL;
45 static int (*symptom_set_additional_qualifier_f)(symptom_t symptom, uint32_t qualifier_type, size_t qualifier_len, void *qualifier_data) = mDNSNULL;
46 static int (*symptom_send_f)(symptom_t symptom) = mDNSNULL;
47
48 mDNSlocal mStatus SymptomReporterInitCheck(void)
49 {
50 mStatus err;
51 static mDNSBool triedInit = mDNSfalse;
52 static void *symptomReporterLib = mDNSNULL;
53 #if (!TARGET_OS_MACOSX || (MAC_OS_X_VERSION_MAX_ALLOWED >= 101200))
54 static const char path[] = "/System/Library/PrivateFrameworks/SymptomReporter.framework/SymptomReporter";
55 #else
56 static const char path[] = "/System/Library/PrivateFrameworks/Symptoms.framework/Frameworks/SymptomReporter.framework/SymptomReporter";
57 #endif
58
59 if (!triedInit)
60 {
61 triedInit = mDNStrue;
62
63 symptomReporterLib = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
64 if (!symptomReporterLib)
65 goto exit;
66
67 symptom_framework_init_f = dlsym(symptomReporterLib, "symptom_framework_init");
68 if (!symptom_framework_init_f)
69 goto exit;
70
71 symptom_new_f = dlsym(symptomReporterLib, "symptom_new");
72 if (!symptom_new_f)
73 goto exit;
74
75 symptom_set_additional_qualifier_f = dlsym(symptomReporterLib, "symptom_set_additional_qualifier");
76 if (!symptom_set_additional_qualifier_f)
77 goto exit;
78
79 symptom_send_f = dlsym(symptomReporterLib, "symptom_send");
80 if (!symptom_send_f)
81 goto exit;
82
83 symptomReporter = symptom_framework_init_f(SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID, SYMPTOM_REPORTER_mDNSResponder_TEXT_ID);
84 }
85
86 exit:
87 err = symptomReporter ? mStatus_NoError : mStatus_NotInitializedErr;
88 return err;
89 }
90
91 mDNSlocal mStatus SymptomReporterReportDNSReachability(const mDNSAddr *addr, mDNSBool isReachable)
92 {
93 mStatus err;
94 symptom_t symptom;
95 struct sockaddr_storage sockAddr;
96 size_t sockAddrSize;
97
98 LogInfo("SymptomReporterReportDNSReachability: DNS server %#a is %sreachable", addr, isReachable ? "" : "un");
99
100 if (addr->type == mDNSAddrType_IPv4)
101 {
102 struct sockaddr_in *sin = (struct sockaddr_in *)&sockAddr;
103 sockAddrSize = sizeof(*sin);
104 mDNSPlatformMemZero(sin, sockAddrSize);
105 sin->sin_len = sockAddrSize;
106 sin->sin_family = AF_INET;
107 sin->sin_addr.s_addr = addr->ip.v4.NotAnInteger;
108 }
109 else if (addr->type == mDNSAddrType_IPv6)
110 {
111 struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&sockAddr;
112 sockAddrSize = sizeof(*sin6);
113 mDNSPlatformMemZero(sin6, sockAddrSize);
114 sin6->sin6_len = sockAddrSize;
115 sin6->sin6_family = AF_INET6;
116 sin6->sin6_addr = *(struct in6_addr *)&addr->ip.v6;
117 }
118 else
119 {
120 LogMsg("SymptomReporterReportDNSReachability: addr is not an IPv4 or IPv6 address!");
121 err = mStatus_BadParamErr;
122 goto exit;
123 }
124
125 symptom = symptom_new_f(symptomReporter, isReachable ? SYMPTOM_DNS_RESUMED_RESPONDING : SYMPTOM_DNS_NO_REPLIES);
126 symptom_set_additional_qualifier_f(symptom, 1, sockAddrSize, (void *)&sockAddr);
127 symptom_send_f(symptom);
128 err = mStatus_NoError;
129
130 exit:
131 return err;
132 }
133
134 mDNSexport mStatus SymptomReporterDNSServerReachable(mDNS *const m, const mDNSAddr *addr)
135 {
136 mStatus err;
137 DNSServer *s;
138 mDNSBool found = mDNSfalse;
139
140 err = SymptomReporterInitCheck();
141 if (err != mStatus_NoError)
142 goto exit;
143
144 for (s = m->DNSServers; s; s = s->next)
145 {
146 if (s->flags & DNSServer_FlagDelete)
147 continue;
148 if ((s->flags & DNSServer_FlagUnreachable) && mDNSSameAddress(addr, &s->addr))
149 {
150 s->flags &= ~DNSServer_FlagUnreachable;
151 NumUnreachableDNSServers--;
152 found = mDNStrue;
153 }
154 }
155
156 if (!found)
157 {
158 err = mStatus_NoSuchNameErr;
159 goto exit;
160 }
161
162 err = SymptomReporterReportDNSReachability(addr, mDNStrue);
163
164 exit:
165 return err;
166 }
167
168 mDNSexport mStatus SymptomReporterDNSServerUnreachable(DNSServer *s)
169 {
170 mStatus err;
171
172 err = SymptomReporterInitCheck();
173 if (err != mStatus_NoError)
174 goto exit;
175
176 if ((s->flags & DNSServer_FlagDelete) || (s->flags & DNSServer_FlagUnreachable))
177 goto exit;
178
179 s->flags |= DNSServer_FlagUnreachable;
180 NumUnreachableDNSServers++;
181
182 err = SymptomReporterReportDNSReachability(&s->addr, mDNSfalse);
183
184 exit:
185 return err;
186 }