|
1 | 1 | extern crate system_configuration;
|
2 | 2 |
|
3 |
| -extern crate core_foundation; |
| 3 | +use system_configuration::network_configuration::{SCNetworkGlobal, SCNetworkServiceDNS}; |
4 | 4 |
|
5 |
| -use core_foundation::array::CFArray; |
6 |
| -use core_foundation::base::TCFType; |
7 |
| -use core_foundation::dictionary::CFDictionary; |
8 |
| -use core_foundation::propertylist::CFPropertyList; |
9 |
| -use core_foundation::string::{CFString, CFStringRef}; |
10 |
| - |
11 |
| -use system_configuration::dynamic_store::{SCDynamicStore, SCDynamicStoreBuilder}; |
| 5 | +use std::net::{IpAddr, Ipv4Addr}; |
12 | 6 |
|
13 | 7 | // This example will change the DNS settings on the primary
|
14 | 8 | // network interface to 8.8.8.8 and 8.8.4.4
|
15 | 9 |
|
16 |
| -fn main() { |
17 |
| - let store = SCDynamicStoreBuilder::new("my-test-dyn-store").build(); |
18 |
| - let primary_service_uuid = get_primary_service_uuid(&store).expect("No PrimaryService active"); |
19 |
| - println!("PrimaryService UUID: {}", primary_service_uuid); |
20 |
| - |
21 |
| - let primary_service_path = CFString::new(&format!( |
22 |
| - "State:/Network/Service/{}/DNS", |
23 |
| - primary_service_uuid |
24 |
| - )); |
25 |
| - println!("PrimaryService path: {}", primary_service_path); |
26 |
| - |
27 |
| - let dns_dictionary = create_dns_dictionary(&[ |
28 |
| - CFString::from_static_string("8.8.8.8"), |
29 |
| - CFString::from_static_string("8.8.4.4"), |
30 |
| - ]); |
31 |
| - |
32 |
| - let success = store.set(primary_service_path, dns_dictionary); |
33 |
| - println!("success? {}", success); |
34 |
| -} |
| 10 | +// Usage: |
35 | 11 |
|
36 |
| -fn get_primary_service_uuid(store: &SCDynamicStore) -> Option<CFString> { |
37 |
| - let dictionary = store |
38 |
| - .get("State:/Network/Global/IPv4") |
39 |
| - .and_then(CFPropertyList::downcast_into::<CFDictionary>); |
40 |
| - if let Some(dictionary) = dictionary { |
41 |
| - dictionary |
42 |
| - .find2(&CFString::from_static_string("PrimaryService")) |
43 |
| - .map(|ptr| unsafe { CFString::wrap_under_get_rule(ptr as CFStringRef) }) |
44 |
| - } else { |
45 |
| - None |
46 |
| - } |
47 |
| -} |
| 12 | +// $ cargo build --example set_dns |
| 13 | +// $ sudo ../target/debug/examples/set_dns |
48 | 14 |
|
49 |
| -fn create_dns_dictionary(addresses: &[CFString]) -> CFDictionary { |
50 |
| - let key = CFString::from_static_string("ServerAddresses"); |
51 |
| - let value = CFArray::from_CFTypes(addresses); |
52 |
| - CFDictionary::from_CFType_pairs(&[(key, value)]) |
| 15 | +fn main() { |
| 16 | + let addrs = vec![ |
| 17 | + IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)), |
| 18 | + IpAddr::V4(Ipv4Addr::new(8, 8, 4, 4)), |
| 19 | + ]; |
| 20 | + |
| 21 | + let global_service = SCNetworkGlobal.service().expect("No PrimaryService active"); |
| 22 | + let global_interface = global_service |
| 23 | + .interface() |
| 24 | + .expect("No PrimaryInterface active"); |
| 25 | + |
| 26 | + println!("Global Service:"); |
| 27 | + println!("\tid: {:?}", global_service.id()); |
| 28 | + println!("\tname: {:?}", global_service.name()); |
| 29 | + println!("\tenabled: {:?}", global_service.enabled()); |
| 30 | + println!("\tdns: {:?}", global_service.dns()); |
| 31 | + println!("\tinterface: {:?}", global_interface.name().unwrap()); |
| 32 | + |
| 33 | + println!( |
| 34 | + "Set dns to {:?} on {:?} service ...", |
| 35 | + addrs, |
| 36 | + global_service.name() |
| 37 | + ); |
| 38 | + |
| 39 | + let dns = SCNetworkServiceDNS::new((None, None), (None, Some(addrs))); |
| 40 | + |
| 41 | + println!("Success: {:?}", global_service.set_dns(dns)); |
| 42 | + |
| 43 | + // Check |
| 44 | + // networksetup -getdnsservers "Wi-Fi" |
| 45 | + // scutil --dns |
| 46 | + // dig |
| 47 | + println!("{:?}", global_service.dns()); |
| 48 | + |
| 49 | + println!( |
| 50 | + "\n\nUse Command `networksetup -setdnsservers \"{}\" \"Empty\"` to restore DNS setting. ", |
| 51 | + global_service.name() |
| 52 | + ); |
53 | 53 | }
|
0 commit comments