1 use std
::sync
::{Arc, Mutex}
;
4 use lazy_static
::lazy_static
;
7 use serde_json
::{json, Value}
;
9 use proxmox
::{sortable, identity}
;
10 use proxmox
::api
::{ApiHandler, ApiMethod, Router, RpcEnvironment}
;
11 use proxmox
::api
::schema
::*;
12 use proxmox
::tools
::fs
::{file_get_contents, file_set_contents}
;
13 use proxmox
::tools
::*; // required to use IPRE!() macro ???
15 use crate::api2
::types
::*;
17 static RESOLV_CONF_FN
: &str = "/etc/resolv.conf";
19 fn read_etc_resolv_conf() -> Result
<Value
, Error
> {
21 let mut result
= json
!({}
);
25 let raw
= file_get_contents(RESOLV_CONF_FN
)?
;
27 result
["digest"] = Value
::from(proxmox
::tools
::digest_to_hex(&sha
::sha256(&raw
)));
29 let data
= String
::from_utf8(raw
)?
;
32 static ref DOMAIN_REGEX
: Regex
= Regex
::new(r
"^\s*(?:search|domain)\s+(\S+)\s*").unwrap();
33 static ref SERVER_REGEX
: Regex
= Regex
::new(
34 concat
!(r
"^\s*nameserver\s+(", IPRE
!(), r
")\s*")).unwrap();
37 for line
in data
.lines() {
39 if let Some(caps
) = DOMAIN_REGEX
.captures(&line
) {
40 result
["search"] = Value
::from(&caps
[1]);
41 } else if let Some(caps
) = SERVER_REGEX
.captures(&line
) {
43 if nscount
> 3 { continue }
;
44 let nameserver
= &caps
[1];
45 let id
= format
!("dns{}", nscount
);
46 result
[id
] = Value
::from(nameserver
);
56 _rpcenv
: &mut dyn RpcEnvironment
,
57 ) -> Result
<Value
, Error
> {
60 static ref MUTEX
: Arc
<Mutex
<usize>> = Arc
::new(Mutex
::new(0));
63 let _guard
= MUTEX
.lock();
65 let search
= crate::tools
::required_string_param(¶m
, "search")?
;
67 let raw
= file_get_contents(RESOLV_CONF_FN
)?
;
68 let old_digest
= proxmox
::tools
::digest_to_hex(&sha
::sha256(&raw
));
70 if let Some(digest
) = param
["digest"].as_str() {
71 crate::tools
::assert_if_modified(&old_digest
, &digest
)?
;
74 let old_data
= String
::from_utf8(raw
)?
;
76 let mut data
= format
!("search {}\n", search
);
78 for opt
in &["dns1", "dns2", "dns3"] {
79 if let Some(server
) = param
[opt
].as_str() {
80 data
.push_str(&format
!("nameserver {}\n", server
));
86 static ref SKIP_REGEX
: Regex
= Regex
::new(r
"^(search|domain|nameserver)\s+").unwrap();
88 for line
in old_data
.lines() {
89 if SKIP_REGEX
.is_match(line
) { continue; }
94 file_set_contents(RESOLV_CONF_FN
, data
.as_bytes(), None
)?
;
102 _rpcenv
: &mut dyn RpcEnvironment
,
103 ) -> Result
<Value
, Error
> {
105 read_etc_resolv_conf()
109 pub const ROUTER
: Router
= Router
::new()
112 &ApiHandler
::Sync(&get_dns
),
114 "Read DNS settings.",
115 &sorted
!([ ("node", false, &NODE_SCHEMA
) ]),
119 "Returns DNS server IPs and sreach domain.",
121 ("digest", false, &PVE_CONFIG_DIGEST_SCHEMA
),
122 ("search", true, &SEARCH_DOMAIN_SCHEMA
),
123 ("dns1", true, &FIRST_DNS_SERVER_SCHEMA
),
124 ("dns2", true, &SECOND_DNS_SERVER_SCHEMA
),
125 ("dns3", true, &THIRD_DNS_SERVER_SCHEMA
),
132 &ApiHandler
::Sync(&update_dns
),
134 "Returns DNS server IPs and sreach domain.",
136 ("node", false, &NODE_SCHEMA
),
137 ("search", false, &SEARCH_DOMAIN_SCHEMA
),
138 ("dns1", true, &FIRST_DNS_SERVER_SCHEMA
),
139 ("dns2", true, &SECOND_DNS_SERVER_SCHEMA
),
140 ("dns3", true, &THIRD_DNS_SERVER_SCHEMA
),
141 ("digest", true, &PVE_CONFIG_DIGEST_SCHEMA
),