2 * Copyright (c) 2015-2019 Apple Inc. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "SymptomReporter.h"
19 #if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS) && !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
20 #include <arpa/inet.h>
24 #include <sys/socket.h>
25 #include <AvailabilityMacros.h>
26 #include <SymptomReporter/SymptomReporter.h>
28 #define SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID 101
29 #define SYMPTOM_REPORTER_mDNSResponder_TEXT_ID "com.apple.mDNSResponder"
31 #define SYMPTOM_DNS_NO_REPLIES 0x00065001
32 #define SYMPTOM_DNS_RESUMED_RESPONDING 0x00065002
34 mDNSu32 NumUnreachableDNSServers
;
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
;
42 mDNSlocal mStatus
SymptomReporterInitCheck(void)
45 static mDNSBool triedInit
= mDNSfalse
;
46 static void *symptomReporterLib
= mDNSNULL
;
47 static const char path
[] = "/System/Library/PrivateFrameworks/SymptomReporter.framework/SymptomReporter";
53 symptomReporterLib
= dlopen(path
, RTLD_LAZY
| RTLD_LOCAL
);
54 if (!symptomReporterLib
)
57 symptom_framework_init_f
= dlsym(symptomReporterLib
, "symptom_framework_init");
58 if (!symptom_framework_init_f
)
61 symptom_new_f
= dlsym(symptomReporterLib
, "symptom_new");
65 symptom_set_additional_qualifier_f
= dlsym(symptomReporterLib
, "symptom_set_additional_qualifier");
66 if (!symptom_set_additional_qualifier_f
)
69 symptom_send_f
= dlsym(symptomReporterLib
, "symptom_send");
73 symptomReporter
= symptom_framework_init_f(SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID
, SYMPTOM_REPORTER_mDNSResponder_TEXT_ID
);
77 err
= symptomReporter
? mStatus_NoError
: mStatus_NotInitializedErr
;
81 mDNSlocal mStatus
SymptomReporterReportDNSReachability(const mDNSAddr
*addr
, mDNSBool isReachable
)
85 struct sockaddr_storage sockAddr
;
88 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_INFO
,
89 "SymptomReporterReportDNSReachability: DNS server " PRI_IP_ADDR
" is " PUB_S
"reachable", addr
, isReachable
? "" : "un");
91 if (addr
->type
== mDNSAddrType_IPv4
)
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
;
100 else if (addr
->type
== mDNSAddrType_IPv6
)
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
;
111 LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_ERROR
,
112 "SymptomReporterReportDNSReachability: addr is not an IPv4 or IPv6 address!");
113 err
= mStatus_BadParamErr
;
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
;
126 mDNSexport mStatus
SymptomReporterDNSServerReachable(mDNS
*const m
, const mDNSAddr
*addr
)
130 mDNSBool found
= mDNSfalse
;
132 err
= SymptomReporterInitCheck();
133 if (err
!= mStatus_NoError
)
136 for (s
= m
->DNSServers
; s
; s
= s
->next
)
138 if (s
->flags
& DNSServerFlag_Delete
)
140 if ((s
->flags
& DNSServerFlag_Unreachable
) && mDNSSameAddress(addr
, &s
->addr
))
142 s
->flags
&= ~DNSServerFlag_Unreachable
;
143 NumUnreachableDNSServers
--;
150 err
= mStatus_NoSuchNameErr
;
154 err
= SymptomReporterReportDNSReachability(addr
, mDNStrue
);
160 mDNSexport mStatus
SymptomReporterDNSServerUnreachable(DNSServer
*s
)
164 err
= SymptomReporterInitCheck();
165 if (err
!= mStatus_NoError
)
168 if ((s
->flags
& DNSServerFlag_Delete
) || (s
->flags
& DNSServerFlag_Unreachable
))
171 s
->flags
|= DNSServerFlag_Unreachable
;
172 NumUnreachableDNSServers
++;
174 err
= SymptomReporterReportDNSReachability(&s
->addr
, mDNSfalse
);
179 #endif // MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)