1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2015 Apple Inc. All rights reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "mDNSEmbeddedAPI.h"
20 #include <arpa/inet.h>
24 #include <sys/socket.h>
25 #include <AvailabilityMacros.h>
26 #include <TargetConditionals.h>
28 #define TARGET_OS_MACOSX (TARGET_OS_MAC && !TARGET_OS_IPHONE)
30 #if (!TARGET_OS_MACOSX || (MAC_OS_X_VERSION_MAX_ALLOWED >= 101200))
31 #include <SymptomReporter/SymptomReporter.h>
33 #include <Symptoms/SymptomReporter.h>
36 #define SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID 101
37 #define SYMPTOM_REPORTER_mDNSResponder_TEXT_ID "com.apple.mDNSResponder"
39 #define SYMPTOM_DNS_NO_REPLIES 0x00065001
40 #define SYMPTOM_DNS_RESUMED_RESPONDING 0x00065002
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
;
48 mDNSlocal mStatus
SymptomReporterInitCheck(void)
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";
56 static const char path
[] = "/System/Library/PrivateFrameworks/Symptoms.framework/Frameworks/SymptomReporter.framework/SymptomReporter";
63 symptomReporterLib
= dlopen(path
, RTLD_LAZY
| RTLD_LOCAL
);
64 if (!symptomReporterLib
)
67 symptom_framework_init_f
= dlsym(symptomReporterLib
, "symptom_framework_init");
68 if (!symptom_framework_init_f
)
71 symptom_new_f
= dlsym(symptomReporterLib
, "symptom_new");
75 symptom_set_additional_qualifier_f
= dlsym(symptomReporterLib
, "symptom_set_additional_qualifier");
76 if (!symptom_set_additional_qualifier_f
)
79 symptom_send_f
= dlsym(symptomReporterLib
, "symptom_send");
83 symptomReporter
= symptom_framework_init_f(SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID
, SYMPTOM_REPORTER_mDNSResponder_TEXT_ID
);
87 err
= symptomReporter
? mStatus_NoError
: mStatus_NotInitializedErr
;
91 mDNSlocal mStatus
SymptomReporterReportDNSReachability(const mDNSAddr
*addr
, mDNSBool isReachable
)
95 struct sockaddr_storage sockAddr
;
98 LogInfo("SymptomReporterReportDNSReachability: DNS server %#a is %sreachable", addr
, isReachable
? "" : "un");
100 if (addr
->type
== mDNSAddrType_IPv4
)
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
;
109 else if (addr
->type
== mDNSAddrType_IPv6
)
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
;
120 LogMsg("SymptomReporterReportDNSReachability: addr is not an IPv4 or IPv6 address!");
121 err
= mStatus_BadParamErr
;
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
;
134 mDNSexport mStatus
SymptomReporterDNSServerReachable(mDNS
*const m
, const mDNSAddr
*addr
)
138 mDNSBool found
= mDNSfalse
;
140 err
= SymptomReporterInitCheck();
141 if (err
!= mStatus_NoError
)
144 for (s
= m
->DNSServers
; s
; s
= s
->next
)
146 if (s
->flags
& DNSServer_FlagDelete
)
148 if ((s
->flags
& DNSServer_FlagUnreachable
) && mDNSSameAddress(addr
, &s
->addr
))
150 s
->flags
&= ~DNSServer_FlagUnreachable
;
151 NumUnreachableDNSServers
--;
158 err
= mStatus_NoSuchNameErr
;
162 err
= SymptomReporterReportDNSReachability(addr
, mDNStrue
);
168 mDNSexport mStatus
SymptomReporterDNSServerUnreachable(DNSServer
*s
)
172 err
= SymptomReporterInitCheck();
173 if (err
!= mStatus_NoError
)
176 if ((s
->flags
& DNSServer_FlagDelete
) || (s
->flags
& DNSServer_FlagUnreachable
))
179 s
->flags
|= DNSServer_FlagUnreachable
;
180 NumUnreachableDNSServers
++;
182 err
= SymptomReporterReportDNSReachability(&s
->addr
, mDNSfalse
);