1 use std
::sync
::{Arc, Mutex}
;
4 use lazy_static
::lazy_static
;
7 use serde_json
::{json, Value}
;
9 use proxmox
::api
::{api, ApiMethod, Router, RpcEnvironment, Permission}
;
10 use proxmox
::tools
::fs
::{file_get_contents, replace_file, CreateOptions}
;
11 use proxmox
::{IPRE, IPV4RE, IPV6RE, IPV4OCTET, IPV6H16, IPV6LS32}
;
13 use crate::api2
::types
::*;
14 use crate::config
::acl
::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY}
;
16 static RESOLV_CONF_FN
: &str = "/etc/resolv.conf";
18 pub fn read_etc_resolv_conf() -> Result
<Value
, Error
> {
20 let mut result
= json
!({}
);
24 let raw
= file_get_contents(RESOLV_CONF_FN
)?
;
26 result
["digest"] = Value
::from(proxmox
::tools
::digest_to_hex(&sha
::sha256(&raw
)));
28 let data
= String
::from_utf8(raw
)?
;
31 static ref DOMAIN_REGEX
: Regex
= Regex
::new(r
"^\s*(?:search|domain)\s+(\S+)\s*").unwrap();
32 static ref SERVER_REGEX
: Regex
= Regex
::new(
33 concat
!(r
"^\s*nameserver\s+(", IPRE
!(), r
")\s*")).unwrap();
36 for line
in data
.lines() {
38 if let Some(caps
) = DOMAIN_REGEX
.captures(&line
) {
39 result
["search"] = Value
::from(&caps
[1]);
40 } else if let Some(caps
) = SERVER_REGEX
.captures(&line
) {
42 if nscount
> 3 { continue }
;
43 let nameserver
= &caps
[1];
44 let id
= format
!("dns{}", nscount
);
45 result
[id
] = Value
::from(nameserver
);
55 description
: "Update DNS settings.",
61 schema
: SEARCH_DOMAIN_SCHEMA
,
65 schema
: FIRST_DNS_SERVER_SCHEMA
,
69 schema
: SECOND_DNS_SERVER_SCHEMA
,
73 schema
: THIRD_DNS_SERVER_SCHEMA
,
77 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
82 permission
: &Permission
::Privilege(&[], PRIV_SYS_MODIFY
, false),
85 /// Update DNS settings
89 _rpcenv
: &mut dyn RpcEnvironment
,
90 ) -> Result
<Value
, Error
> {
93 static ref MUTEX
: Arc
<Mutex
<usize>> = Arc
::new(Mutex
::new(0));
96 let _guard
= MUTEX
.lock();
98 let search
= crate::tools
::required_string_param(¶m
, "search")?
;
100 let raw
= file_get_contents(RESOLV_CONF_FN
)?
;
101 let old_digest
= proxmox
::tools
::digest_to_hex(&sha
::sha256(&raw
));
103 if let Some(digest
) = param
["digest"].as_str() {
104 crate::tools
::assert_if_modified(&old_digest
, &digest
)?
;
107 let old_data
= String
::from_utf8(raw
)?
;
109 let mut data
= format
!("search {}\n", search
);
111 for opt
in &["dns1", "dns2", "dns3"] {
112 if let Some(server
) = param
[opt
].as_str() {
113 data
.push_str(&format
!("nameserver {}\n", server
));
119 static ref SKIP_REGEX
: Regex
= Regex
::new(r
"^(search|domain|nameserver)\s+").unwrap();
121 for line
in old_data
.lines() {
122 if SKIP_REGEX
.is_match(line
) { continue; }
127 replace_file(RESOLV_CONF_FN
, data
.as_bytes(), CreateOptions
::new())?
;
141 description
: "Returns DNS server IPs and sreach domain.",
145 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
149 schema
: SEARCH_DOMAIN_SCHEMA
,
153 schema
: FIRST_DNS_SERVER_SCHEMA
,
157 schema
: SECOND_DNS_SERVER_SCHEMA
,
161 schema
: THIRD_DNS_SERVER_SCHEMA
,
166 permission
: &Permission
::Privilege(&[], PRIV_SYS_AUDIT
, false),
169 /// Read DNS settings.
173 _rpcenv
: &mut dyn RpcEnvironment
,
174 ) -> Result
<Value
, Error
> {
176 read_etc_resolv_conf()
179 pub const ROUTER
: Router
= Router
::new()
180 .get(&API_METHOD_GET_DNS
)
181 .put(&API_METHOD_UPDATE_DNS
);