]> git.saurik.com Git - apple/configd.git/blob - nwi/network_state_information_logging.h
configd-963.200.27.tar.gz
[apple/configd.git] / nwi / network_state_information_logging.h
1 /*
2 * Copyright (c) 2017, 2018 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #ifndef _NETWORK_STATE_INFORMATION_LOGGING_H
25 #define _NETWORK_STATE_INFORMATION_LOGGING_H
26
27 #include <os/availability.h>
28 #include <TargetConditionals.h>
29 #include <sys/cdefs.h>
30 #include <CoreFoundation/CoreFoundation.h>
31 #include <SystemConfiguration/SystemConfiguration.h>
32 #include <SystemConfiguration/SCPrivate.h>
33
34 #include <network_information.h>
35 #include "network_state_information_priv.c"
36
37 __BEGIN_DECLS
38
39 #ifndef my_log
40 #define my_log(__level, __format, ...) SC_log(__level, __format, ## __VA_ARGS__)
41 #define MY_LOG_DEFINED_LOCALLY
42 #endif // !my_log
43
44 #ifndef my_log_context_type
45 #define my_log_context_type void *
46 #define MY_LOG_CONTEXT_TYPE_DEFINED_LOCALLY
47 #endif // !my_log_context_type
48
49 #ifndef my_log_context_name
50 #define my_log_context_name context
51 #define MY_LOG_CONTEXT_NAME_DEFINED_LOCALLY
52 #endif // !my_log_context_name
53
54 #include "SCNetworkReachabilityLogging.h"
55
56 /*
57 * _nwi_ifstate_flags_str()
58 *
59 * Returns a string representation of the nwi_state flags.
60 * "(IPv4,IPv6,DNS,...)"
61 */
62 static __inline__ void
63 _nwi_ifstate_flags_str(nwi_ifstate_flags flags, char *str, size_t len)
64 {
65 size_t n;
66 nwi_ifstate_flags remaining;
67
68 assert(len >= sizeof("(0x01234567)")); // check min buffer size
69
70 flags &= NWI_IFSTATE_FLAGS_MASK;
71 if (flags == 0) {
72 str[0] = '\0';
73 return;
74 }
75
76 len--; // leave room for the closing paren
77 n = strlcpy(str, "(", len);
78 remaining = flags;
79
80 if ((remaining & NWI_IFSTATE_FLAGS_HAS_IPV4) &&
81 (n < len) && ((len - n) > sizeof("IPv4,"))) {
82 n = strlcat(str, "IPv4,", len);
83 remaining &= ~NWI_IFSTATE_FLAGS_HAS_IPV4;
84 }
85
86 if ((remaining & NWI_IFSTATE_FLAGS_HAS_IPV6) &&
87 (n < len) && ((len - n) > sizeof("IPv6,"))) {
88 n = strlcat(str, "IPv6,", len);
89 remaining &= ~NWI_IFSTATE_FLAGS_HAS_IPV6;
90 }
91
92 if ((remaining & NWI_IFSTATE_FLAGS_HAS_DNS) &&
93 (n < len) && ((len - n) > sizeof("DNS,"))) {
94 n = strlcat(str, "DNS,", len);
95 remaining &= ~NWI_IFSTATE_FLAGS_HAS_DNS;
96 }
97
98 if ((remaining & NWI_IFSTATE_FLAGS_HAS_CLAT46) &&
99 (n < len) && ((len - n) > sizeof("CLAT46,"))) {
100 n = strlcat(str, "CLAT46,", len);
101 remaining &= ~NWI_IFSTATE_FLAGS_HAS_CLAT46;
102 }
103
104 if ((remaining & NWI_IFSTATE_FLAGS_NOT_IN_LIST) &&
105 (n < len) && ((len - n) > sizeof("NOT-IN-LIST,"))) {
106 n = strlcat(str, "NOT-IN-LIST,", len);
107 remaining &= ~NWI_IFSTATE_FLAGS_NOT_IN_LIST;
108 }
109
110 if ((remaining & NWI_IFSTATE_FLAGS_HAS_SIGNATURE) &&
111 (n < len) && ((len - n) > sizeof("SIGNATURE,"))) {
112 n = strlcat(str, "SIGNATURE,", len);
113 remaining &= ~NWI_IFSTATE_FLAGS_HAS_SIGNATURE;
114 }
115
116 if ((remaining & NWI_IFSTATE_FLAGS_NOT_IN_IFLIST) &&
117 (n < len) && ((len - n) > sizeof("NOT-IN-IFLIST,"))) {
118 n = strlcat(str, "NOT-IN-IFLIST,", len);
119 remaining &= ~NWI_IFSTATE_FLAGS_NOT_IN_IFLIST;
120 }
121
122 if (remaining != 0) {
123 if ((n >= len) ||
124 ((len - n) <= sizeof("0x01234567,"))) {
125 // if we don't have enough space, truncate and start over
126 n = strlcpy(str, "(", len);
127 remaining = flags;
128 }
129
130 n += snprintf(str + n, len - n, ",%p", (void *)remaining);
131 }
132
133 if (n-- > 0) {
134 str[n] = ')'; // trailing "," --> ")"
135 }
136
137 return;
138 }
139
140 static __inline__ const char *
141 _nwi_ifstate_rank_str(Rank rank)
142 {
143 const char *str = "???";
144
145 switch (RANK_ASSERTION_MASK(rank)) {
146 case kRankAssertionFirst:
147 str = "First";
148 break;
149 case kRankAssertionDefault:
150 str = "Default";
151 break;
152 case kRankAssertionLast:
153 str = "Last";
154 break;
155 case kRankAssertionNever:
156 str = "Never";
157 break;
158 case kRankAssertionScoped:
159 str = "Scoped";
160 break;
161 default:
162 str = "???";
163 break;
164 }
165
166 return str;
167 }
168
169 static __inline__ void
170 _nwi_ifstate_log(nwi_ifstate_t ifstate, boolean_t debug, my_log_context_type my_log_context_name)
171 {
172 #if defined(MY_LOG_CONTEXT_TYPE_DEFINED_LOCALLY) && defined(MY_LOG_CONTEXT_NAME_DEFINED_LOCALLY)
173 #pragma unused(my_log_context_name)
174 #endif
175 union {
176 const void *bytes;
177 const struct in_addr *ia;
178 const struct in6_addr *ia6;
179 } addr;
180 char addr_str[INET6_ADDRSTRLEN];
181 nwi_ifstate_flags flags_ifstate;
182 char flags_str[100];
183 const char *if_name;
184 SCNetworkReachabilityFlags reach_flags;
185 char reach_str[100];
186 const struct sockaddr *vpn_addr;
187
188 // nwi_ifstate flags
189 flags_ifstate = nwi_ifstate_get_flags(ifstate);
190 if (debug) {
191 flags_ifstate |= NWI_IFSTATE_FLAGS(ifstate->flags);
192 }
193 flags_ifstate &= ~NWI_IFSTATE_FLAGS_HAS_SIGNATURE; // exclude flag ('cause we'll report the signature only if present)
194 _nwi_ifstate_flags_str(flags_ifstate, flags_str, sizeof(flags_str));
195
196 // if_name
197 if_name = nwi_ifstate_get_ifname(ifstate);
198
199 // reachability flags
200 reach_flags = nwi_ifstate_get_reachability_flags(ifstate);
201
202 // IP address
203 addr.bytes = nwi_ifstate_get_address(ifstate);
204 if (inet_ntop(ifstate->af, addr.bytes, addr_str, sizeof(addr_str)) == NULL) {
205 strlcpy(addr_str, "???", sizeof(addr_str));
206 }
207
208 // verbose format (e.g. scutil)
209 my_log(LOG_INFO, " %7s : flags : %p %s",
210 if_name,
211 (void *)flags_ifstate,
212 flags_str);
213
214 my_log(LOG_INFO, " address : %s", addr_str);
215
216 // VPN server address
217 vpn_addr = nwi_ifstate_get_vpn_server(ifstate);
218 if (vpn_addr != NULL) {
219 char vpn_str[INET6_ADDRSTRLEN];
220
221 _SC_sockaddr_to_string(vpn_addr, vpn_str, sizeof(vpn_str));
222 my_log(LOG_INFO, " VPN server : %s", vpn_str);
223 }
224
225 // reachability
226 __SCNetworkReachability_flags_string(reach_flags, TRUE, reach_str, sizeof(reach_str));
227 my_log(LOG_INFO, " reach : %s", reach_str);
228
229 if (debug) {
230 uint64_t generation;
231 Rank rank;
232 uint32_t rank_index;
233 const char *rank_str;
234 const uint8_t *signature;
235 int signature_length;
236
237 // Rank
238 rank = ifstate->rank;
239 rank_str = _nwi_ifstate_rank_str(rank);
240 rank_index = RANK_INDEX_MASK(rank);
241 if (rank_index != kRankIndexMask) {
242 my_log(LOG_INFO, " rank : 0x%08x (%s, %u)", rank, rank_str, rank_index);
243 } else {
244 my_log(LOG_INFO, " rank : 0x%08x (%s, Last)", rank, rank_str);
245 }
246
247 // signature
248 signature = nwi_ifstate_get_signature(ifstate, AF_UNSPEC, &signature_length);
249 if (signature != NULL) {
250 CFDataRef digest;
251
252 digest = CFDataCreate(NULL, signature, CC_SHA1_DIGEST_LENGTH);
253 my_log(LOG_INFO, " signature : %@", digest);
254 CFRelease(digest);
255 }
256
257 // generation
258 generation = nwi_ifstate_get_generation(ifstate);
259 my_log(LOG_INFO, " generation : %llu", generation);
260 }
261
262 return;
263 }
264
265 static __inline__ void
266 _nwi_state_reachability_log(nwi_state_t state, boolean_t debug, int af, my_log_context_type my_log_context_name)
267 {
268 #if defined(MY_LOG_CONTEXT_TYPE_DEFINED_LOCALLY) && defined(MY_LOG_CONTEXT_NAME_DEFINED_LOCALLY)
269 #pragma unused(my_log_context_name)
270 #endif
271 uint32_t flags;
272 char flags_str[100];
273
274 flags = nwi_state_get_reachability_flags(state, af);
275 __SCNetworkReachability_flags_string(flags, TRUE, flags_str, sizeof(flags_str));
276 if (!debug) {
277 my_log(LOG_INFO, "%s", "");
278 }
279 my_log(LOG_INFO, " REACH : flags %s", flags_str);
280
281 return;
282 }
283
284 static __inline__ void
285 _nwi_state_log(nwi_state_t state, boolean_t debug, my_log_context_type my_log_context_name)
286 {
287 #if defined(MY_LOG_CONTEXT_TYPE_DEFINED_LOCALLY) && defined(MY_LOG_CONTEXT_NAME_DEFINED_LOCALLY)
288 #pragma unused(my_log_context_name)
289 #endif
290 unsigned int count;
291 nwi_ifindex_t i;
292 nwi_ifstate_t ifstate;
293
294 if (!debug) {
295 my_log(LOG_INFO, "%s", "Network information");
296 } else {
297 my_log(LOG_INFO,
298 "Network information (generation %llu size=%lu)",
299 nwi_state_get_generation(state),
300 nwi_state_size(state));
301 }
302
303 // report IPv4 state
304 if (!debug) {
305 // show regular interfaces
306 my_log(LOG_INFO, "%s", "");
307 my_log(LOG_INFO, "%s", "IPv4 network interface information");
308 ifstate = nwi_state_get_first_ifstate(state, AF_INET);
309 if (ifstate == NULL) {
310 my_log(LOG_INFO, "%s", " No IPv4 states found");
311 } else {
312 while (ifstate != NULL) {
313 _nwi_ifstate_log(ifstate, debug, my_log_context_name);
314 ifstate = nwi_ifstate_get_next(ifstate, AF_INET);
315 }
316 }
317 } else {
318 my_log(LOG_INFO, "%s", "IPv4 network interface information");
319 if (state->ipv4_count > 0) {
320 // show ALL interfaces
321 for (i = 0, ifstate = nwi_state_ifstate_list(state, AF_INET);
322 i < state->ipv4_count; i++, ifstate++) {
323 _nwi_ifstate_log(ifstate, debug, my_log_context_name);
324 }
325 } else {
326 my_log(LOG_INFO, "%s", " No IPv4 states found");
327 }
328 }
329 _nwi_state_reachability_log(state, debug, AF_INET, my_log_context_name);
330
331 // report IPv6 state
332 if (!debug) {
333 // show regular interfaces
334 my_log(LOG_INFO, "%s", "");
335 my_log(LOG_INFO, "%s", "IPv6 network interface information");
336 ifstate = nwi_state_get_first_ifstate(state, AF_INET6);
337 if (ifstate == NULL) {
338 my_log(LOG_INFO, "%s", " No IPv6 states found\n");
339 } else {
340 while (ifstate != NULL) {
341 _nwi_ifstate_log(ifstate, debug, my_log_context_name);
342 ifstate = nwi_ifstate_get_next(ifstate, AF_INET6);
343 }
344 }
345 } else {
346 my_log(LOG_INFO, "%s", "IPv6 network interface information");
347 if (state->ipv6_count > 0) {
348 // show ALL interfaces
349 for (i = 0, ifstate = nwi_state_ifstate_list(state, AF_INET6);
350 i < state->ipv6_count; i++, ifstate++) {
351 _nwi_ifstate_log(ifstate, debug, my_log_context_name);
352 }
353 } else {
354 my_log(LOG_INFO, "%s", " No IPv6 states found\n");
355 }
356 }
357 _nwi_state_reachability_log(state, debug, AF_INET6, my_log_context_name);
358
359 count = nwi_state_get_interface_names(state, NULL, 0);
360 if (count > 0) {
361 const char *names[count];
362
363 count = nwi_state_get_interface_names(state, names, count);
364 if (count > 0) {
365 char str[count * (IFNAMSIZ + 1)];
366
367 memset(str, 0, sizeof(str));
368 for (unsigned int i = 0; i < count; i++) {
369 if (i != 0) {
370 strlcat(str, " ", sizeof(str));
371 }
372 strlcat(str, names[i], sizeof(str));
373 }
374
375 if (!debug) {
376 my_log(LOG_INFO, "%s", "");
377 }
378 my_log(LOG_INFO, "Network interfaces: %s", str);
379 }
380 }
381
382 return;
383 }
384
385 #ifdef MY_LOG_DEFINED_LOCALLY
386 #undef my_log
387 #undef MY_LOG_DEFINED_LOCALLY
388 #endif // MY_LOG_DEFINED_LOCALLY
389
390 #ifdef MY_LOG_CONTEXT_TYPE_DEFINED_LOCALLY
391 #undef my_log_context_type
392 #undef MY_LOG_CONTEXT_TYPE_DEFINED_LOCALLY
393 #endif // MY_LOG_CONTEXT_TYPE_DEFINED_LOCALLY
394
395 #ifdef MY_LOG_CONTEXT_NAME_DEFINED_LOCALLY
396 #undef my_log_context_name
397 #undef MY_LOG_CONTEXT_NAME_DEFINED_LOCALLY
398 #endif // MY_LOG_CONTEXT_NAME_DEFINED_LOCALLY
399
400 __END_DECLS
401
402 #endif // _NETWORK_STATE_INFORMATION_LOGGING_H