System Configuration

RSS for tag

System Configuration allows applications to access a device’s network configuration settings and determine the reachability of the device.

System Configuration Documentation

Posts under System Configuration tag

14 Posts
Sort by:
Post not yet marked as solved
1 Replies
258 Views
I am encountering an issue while using the SystemConfiguration framework to detect IPv4 address changes and active interfaces on macOS. Specifically, I'm facing difficulties when the interface switches from one network to another. When connected to a network with a Captive Portal enabled, I'm unable to retrieve the active interface using the stored key State:/Network/Global/IPv4. The output I receive is: No such key However, when I attempt to retrieve interface information using scutil --nwi, the output is as follows: IPv4 network interface information No IPv4 states found REACH : flags 0x00000000 (Not Reachable) IPv6 network interface information No IPv6 states found REACH : flags 0x00000000 (Not Reachable) Network interfaces: en0 Despite this output, the interface en0 is active and has a valid IPv4 address: when checking through ifconfig: en0:flags=8b63<UP,BROADCAST,SMART,RUNNING,PROMISC,ALLMULTI,SIMPLEX,MULTICAST> mtu 1500 options=6460<TSO4,TSO6,CHANNEL_IO,PARTIAL_CSUM,ZEROINVERT_CSUM> ether bc:d0:74:07:2a:33 inet6 fe80::412:ec:40df:4211%en0 prefixlen 64 secured scopeid 0x12 inet 10.42.0.5 netmask 0xffffff00 broadcast 10.42.0.255 nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active It's evident that the interface is active and has a valid IPv4 address, but the retrieval methods using SystemConfiguration framework are not providing the expected output. I'm seeking assistance in resolving this discrepancy and accurately detecting active interfaces on macOS. Any insights or suggestions would be greatly appreciated. Thank you.
Posted
by jainash.
Last updated
.
Post not yet marked as solved
5 Replies
1.5k Views
This is happening Mac M1 Monterey OS .Environment supports both IPv4 and IPV6. When a http client calls gettaddrinfo() it is returning both IPv6,IPv4 IPs . first v6 IPs and then v4 IPs. We need to have a way to sort gettaddrinfo() output to get v4 ip first and then v6. We tried changing DNS order with scutil by putting v4 DNS first , but still getaddrInfo() listing v6 IPs first . In linux there is a way to control gettaddrinfo() o/p with /etc/gai.conf https://man7.org/linux/man-pages/man5/gai.conf.5.html . In Mac I did not find any option like this , scutil changing order DNS is not effective . can you tell us what is way to do this in MAC OSx ?
Posted Last updated
.
Post not yet marked as solved
3 Replies
340 Views
Hi, I have a C++ application on OSX that normally works on systems with multiple network interfaces and I'd like to offer a dialog to the users to select the appropriate NIC for the different tasks. It would be fine to show the users the name they assigned to the NIC inside the system settings but I don't know how to read these names. I tried to use SCNetworkInterfaceGetLocalizedDisplayName() but that only gives me the name before I entered my own user defined name (something like "USB 10/100/1000 LAN"). Is there a way to read the user defined name of each NIC? Thanks and best regards, Johannes
Posted Last updated
.
Post not yet marked as solved
1 Replies
316 Views
Hi, I'm looking for feedback regarding SCNetworkReachability under macOS Sonoma. It seems that since beta 3 the notifications behaviour changed. In a LaunchAgent I'm using SCNetworkReachabilityCreateWithName + SCNetworkReachabilitySetCallback + SCNetworkReachabilityScheduleWithRunLoop and wait for callbacks looking at the kSCNetworkReachabilityFlagsReachable flag. This is running fine under macOS 12.x, 13.x and 14.0 for more than a year. If I log all callback entries I observe unexpected notifications as if the looked host became unreachable for very small amount of time (ms). The host is flagged as unreachable then few ms later reachable again then unreachable again. Fast switching is fine, I can accept that the service is unreachable even for 1s but the probleme is the latest status do not reflect actual reachability of the service. This is in a corporate network with the complexity of using a proxy.pac. Does anybody noticed something similar ? I filled a Feedback FB13442134 in case it could be a regression of 14.2
Posted Last updated
.
Post not yet marked as solved
0 Replies
285 Views
Working a DTS incident today, someone asked me exactly how you use SCNetworkReachabilityCreateWithAddressPair to monitor a socket’s viability (per the advice in TN3151). I thought I’d posted code for that many times but, on searching my records, it turns out that I haven’t. Ever. Weird! Anyway, this post rectifies that. If you have questions or comments, start a new thread here on DevForums. Tag it with System Configuration so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Monitoring Socket Viability The BSD Sockets best practices section of TN3151 Choosing the right networking API says: Once you’ve established a connection, use SCNetworkReachabilityCreateWithAddressPair to monitor its viability. Without this, your program won’t notice that a connection is stuck due to a TCP/IP stack reconfiguration. While this is correct, it’s not exactly expansive. This post shows how you might use that call to monitor the viability of a socket. It explains this technique using a Swift example, but there’s a C version of the code below for those with a “sad devotion to that ancient religion” (-: Seriously though, this code is very specific to Apple platforms, where you also have access to Network framework, and that has built-in support for this sort of thing. Only use this code if you absolutely must stick with BSD Sockets. IMPORTANT The Swift code in this post relies on the QSocket2023 library from Calling BSD Sockets from Swift. To start, I assume you have a class like this: final class QConnection { private var socket: FileDescriptor private var queue: DispatchQueue private var targetQ: SCNetworkReachability? … initialiser elided … } Each instance of this class ‘owns’ the socket. It uses a Dispatch queue that serialises all access to the instance. Finally, the targetQ property holds a reachability object that monitor’s the socket’s viability. Once an instance has connected its socket, it calls this method to start monitoring its viability: extension QConnection { fileprivate func startMonitoring() throws { let local = try socket.getSockName() let remote = try socket.getPeerName() let target = try scCall { try QSockAddr.withSockAddr(address: local.address, port: local.port) { saLocal, _ in try QSockAddr.withSockAddr(address: remote.address, port: remote.port) { saRemote, _ in SCNetworkReachabilityCreateWithAddressPair(nil, saLocal, saRemote) } } } var context = SCNetworkReachabilityContext() context.info = Unmanaged.passUnretained(self).toOpaque() try scCall{ SCNetworkReachabilitySetCallback(target, { target, flags, info in let obj = Unmanaged<QConnection>.fromOpaque(info!).takeUnretainedValue() let isViable = flags.contains(.reachable) obj.viabilityDidChange(isViable) }, &context) } try! scCall{ SCNetworkReachabilitySetDispatchQueue(target, self.queue) } self.targetQ = target } } This creates a reachability object with the socket’s local and remote addresses. It then sets up a callback on that object that runs on the instance’s Dispatch queue. That callback calls viabilityDidChange(_:) when the reachability flags change. Here’s the viabilityDidChange(_:) method: extension QConnection { fileprivate func viabilityDidChange(_ isViable: Bool) { dispatchPrecondition(condition: .onQueue(self.queue)) print("isViable: \(isViable)") } } This just prints the new value. In a real product you would: Merge duplicate changes. Debounce the change. The way that reachability works, you might see transient events, and it’s best to ignore those. If the socket is non-viable for too long, start the process of closing it down. Finally, here’s the code to stop viability monitoring. extension QConnection { fileprivate func stopMonitoring() { guard let target = self.targetQ else { return } self.targetQ = nil try! scCall { SCNetworkReachabilitySetCallback(target, nil, nil) } try! scCall { SCNetworkReachabilitySetDispatchQueue(target, nil) } } } Note The snippets above assume two simple helper routines that turn System Configuration framework errors into Swift errors: func scCall(_ body: () throws -> Bool) throws { let ok = try body() guard ok else { throw SCCopyLastError() } } func scCall<Result>(_ body: () throws -> Result?) throws -> Result { guard let result = try body() else { throw SCCopyLastError() } return result } And for those of you working with a C-based language, here’s pretty much the same code in plain ol’ C: struct QConnection { int sock; dispatch_queue_t queue; SCNetworkReachabilityRef target; }; typedef struct QConnection QConnection; static bool _QConnectionStartMonitoring(QConnection * connection) { struct sockaddr_storage local = {}; socklen_t localLen = sizeof(local); bool ok = getsockname(connection->sock, (struct sockaddr *) &local, &localLen) >= 0; if ( ! ok ) { return false; } struct sockaddr_storage remote = {}; socklen_t remoteLen = sizeof(remote); ok = getpeername(connection->sock, (struct sockaddr *) &remote, &remoteLen) >= 0; if ( ! ok ) { return false; } SCNetworkReachabilityRef target = SCNetworkReachabilityCreateWithAddressPair( NULL, (const struct sockaddr *) &local, (const struct sockaddr *) &remote ); if (target == NULL) { return false; } SCNetworkReachabilityContext context = { .info = connection }; ok = SCNetworkReachabilitySetCallback(target, _QConnectionReachabilityCallback, &context); if ( ! ok ) { CFRelease(target); return false; } ok = SCNetworkReachabilitySetDispatchQueue(target, connection->queue); if ( ! ok ) { ok = SCNetworkReachabilitySetCallback(target, NULL, NULL); assert(ok); CFRelease(target); return false; } connection->target = target; return true; } static void _QConnectionReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void * info) { #pragma unused(target) #pragma unused(info) QConnection * connection = (QConnection *) info; bool isViable = (flags & kSCNetworkReachabilityFlagsReachable) != 0; _QConnectionViabilityDidChange(connection, isViable); } static void _QConnectionViabilityDidChange(QConnection * connection, bool isViable) { dispatch_assert_queue(connection->queue); fprintf(stderr, "isViable: %d\n", isViable); } static void _QConnectionStopMonitoring(QConnection * connection) { SCNetworkReachabilityRef target = connection->target; if (target == NULL) { return; } connection->target = NULL; bool ok = SCNetworkReachabilitySetCallback(target, NULL, NULL); assert(ok); ok = SCNetworkReachabilitySetDispatchQueue(target, NULL); assert(ok); CFRelease(target); }
Posted
by eskimo.
Last updated
.
Post not yet marked as solved
4 Replies
396 Views
Hello, I experienced a strange (and in my opinion unexpected) behavior from DynamicStore/configd. In our application we setup the routes in the system by setting AdditionalRoutes property on a specific interface to route part of the network traffic through it. The routes are set properly, but I noticed that the they are not cleared once removed from AdditionalRoutes. After a while I figured, that the problem lies in the DestinationAddress I set in AdditionalRoutes. I was using the following configuration: var newRoutes: [[String: NSObject]] = [ ["DestinationAddress": "10.0.0.1" as NSObject, "SubnetMask": "255.0.0.0" as NSObject ] ] and it resulted in a new route: 10 link#16 UCS en0 ! which was not cleared when AdditionalRoutes were reset to the original value. When I changed the DestinationAddress to: var newRoutes: [[String: NSObject]] = [ ["DestinationAddress": "10.0.0.0" as NSObject, "SubnetMask": "255.0.0.0" as NSObject ] ] both, setting and clearing routes works as expected. The only difference is changing the DestinationAddress from 10.0.0.1 to 10.0.0.1. In my opinion this incosistent behavior. Although I can understand that the system might reject 10.0.0.1 as a valid DestinationAddress for creating routes, I don't think it's correct behavior to accept such address, but never clear the routes. The full source code which might be used to verify my claims: import Foundation import SystemConfiguration let en0ServiceIPv4 = "State:/Network/Service/***/IPv4" as CFString let store = SCDynamicStoreCreate(nil, "dseditor" as CFString, nil, nil)! let originalValue = SCDynamicStoreCopyValue(store, en0ServiceIPv4) as! [String: NSObject] var newValue = originalValue print("AdditionalRoutes: \(String(describing: originalValue["AdditionalRoutes"]))") var newRoutes: [[String: NSObject]] = [ ["DestinationAddress": "10.0.0.1" as NSObject, "SubnetMask": "255.0.0.0" as NSObject ] ] newValue["AdditionalRoutes"] = newRoutes as NSObject print("newValue: \(newValue)") var result = SCDynamicStoreSetValue(store, en0ServiceIPv4, newValue as CFPropertyList) print("set new value: \(result)") sleep(3) result = SCDynamicStoreSetValue(store, en0ServiceIPv4, originalValue as CFPropertyList) print("restore old value: \(result)") Naturally, the en0ServiceIPv4 needs to be changed and the program needs to be run as root. Can you please share your thoughts, if this is an OS bug or expected behavior? If it is expected, what is the reasoning behind it?
Posted
by twardakm.
Last updated
.
Post marked as solved
9 Replies
2.4k Views
Hi. I have docker on my MacBook air 15 M2 and inside I have a container with DNS. For this container, I need port 53 for TCP and UDP. After the update, I can't run this container anymore. Looks like some system demon of macOS use this port and does not allow other application to use it.. How to fix it?
Posted
by deimjons.
Last updated
.
Post not yet marked as solved
1 Replies
449 Views
Hey, I want to retrieve the 802.1x status when a user starts 802.1x authentication so that I'll know when the user gets successfully authenticated via 802.1x. I refered the eapolclient code on apple opensource and wrote the below code but it's failing to retrieve the state. #include &lt;CoreFoundation/CoreFoundation.h&gt; #include &lt;SystemConfiguration/SystemConfiguration.h&gt; #include &lt;iostream&gt; #ifndef kSCEntNetEAPOL #define kSCEntNetEAPOL CFSTR("EAPOL") #endif /* kSCEntNetEAPOL */ class MyService { public: static void handleEAPOLStatusChange( SCDynamicStoreRef store, CFArrayRef changedKeys, void *context) { MyService *serviceInstance = static_cast&lt;MyService *&gt;(context); serviceInstance-&gt;handleEAPOLStatus(store); } void handleEAPOLStatus(SCDynamicStoreRef store) { // Function to handle EAPOL status change events CFStringRef key = createEAPOLControlAnyInterfaceKey(); CFPropertyListRef eapolStatusValue = SCDynamicStoreCopyValue(store, key); CFShow(eapolStatusValue); CFRelease(key); if (eapolStatusValue) { if (CFGetTypeID(eapolStatusValue) == CFDictionaryGetTypeID()) { CFDictionaryRef eapolStatusDict = static_cast&lt;CFDictionaryRef&gt;(eapolStatusValue); std::cout &lt;&lt; "EAPOL Status Dictionary: " &lt;&lt; std::endl; CFShow(eapolStatusDict); CFRelease(eapolStatusDict); } else { std::cerr &lt;&lt; "Error: The retrieved value is not a dictionary." &lt;&lt; std::endl; } CFRelease(eapolStatusValue); } else { std::cerr &lt;&lt; "Error: Failed to get EAPOL status." &lt;&lt; std::endl; } } void setupDynamicStore() { CFStringRef key; CFArrayRef patterns; CFRunLoopSourceRef rls; SCDynamicStoreContext context; bzero(&amp;context, sizeof(context)); context.info = this; store_ = SCDynamicStoreCreate(NULL, CFSTR("eapolclient"), &amp;MyService::handleEAPOLStatusChange, &amp;context); if (store_ == NULL) { std::cerr &lt;&lt; "SCDynamicStoreCreate() failed." &lt;&lt; std::endl; return; } key = createEAPOLControlAnyInterfaceKey(); patterns = CFArrayCreate(NULL, (const void **)&amp;key, 1, &amp;kCFTypeArrayCallBacks); CFRelease(key); SCDynamicStoreSetNotificationKeys(store_, NULL, patterns); CFRelease(patterns); rls = SCDynamicStoreCreateRunLoopSource(NULL, store_, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); CFRelease(rls); } private: SCDynamicStoreRef store_; CFStringRef createEAPOLControlAnyInterfaceKey() { return SCDynamicStoreKeyCreateNetworkInterfaceEntity( NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetEAPOL); } }; int main() { MyService myService; myService.setupDynamicStore(); CFRunLoopRun(); return 0; }
Posted
by swapug.
Last updated
.
Post marked as solved
6 Replies
2.6k Views
Hi, Many developers are working behind a company proxy and Xcode doesn't seem to pick up the system's settings (either with automatic or manual configuration). It makes it impossible to use SPM as Xcode is not able to fetch dependencies, getting very regularly the error message "No Route to host (-1)". I came across some workaround like changing the java config to use the system's settings or modifying the java exec used by Xcode to specify the proxy, but Xcode 14 doesn't seem to use java anymore (or at least I can't find where the config is located now). I also tried to set the JAVA_TOOL_OPTIONS env variable with my proxy details and with java.net.useSystemProxies=true, with no luck. Is there any way to configure the proxy within Xcode ? As anyone managed to make Xcode and SPM work behind a company proxy? I'd really appreciate some help. Thanks!
Posted Last updated
.
Post not yet marked as solved
1 Replies
530 Views
Hello everyone, I'm currently working on an iOS app that relies on accurate time information even when the app is offline. I need to determine whether the device time is set to automatic or manual in such situations. Is there any way to programmatically detect this in iOS? My aim is to provide a warning or prompt the user to switch to automatic time if it's currently set to manual, ensuring the app functions correctly even in offline scenarios. I have found few solutions but they are not completely working. I would greatly appreciate any insights or suggestions on how to achieve this! Thank you in advance!
Posted Last updated
.
Post not yet marked as solved
1 Replies
1.1k Views
In https://support.apple.com/guide/mac-help/configuration-profiles-standardize-settings-mh35561/mac, Apple says View an installed configuration profile: On your Mac, choose Apple menu → System Settings, click Privacy and Security in the sidebar, then click Profiles on the right. (You may need to scroll down.) Select a profile in the Profiles list to view information about it. Is there a way to get this information on the command line or via an API? I would like to include a dump of all of this info in my debug logs of my application, so that I know when it misbehaves whether or not the system permissions were set correctly.
Posted Last updated
.
Post not yet marked as solved
1 Replies
593 Views
SCDynamicStoreCopyProxies() appears to only return proxy setting of the first connected adapter. It looks to be the equivalent of scutil --proxy. What Swift or Objective-C API would allow me to query the proxy for a given adapter? I am looking for the networksetup -getwebproxy "Wi-Fi" equivalent. Thanks, Billy
Posted Last updated
.