Skip to content

Commit 2c359b8

Browse files
committed
✨ feat: Return version number for dummy domains version, ver
and v
1 parent f95fdd8 commit 2c359b8

File tree

5 files changed

+143
-4
lines changed

5 files changed

+143
-4
lines changed

Cargo.lock

Lines changed: 83 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rustyalias"
3-
version = "1.5.3"
3+
version = "1.6.0"
44
edition = "2021"
55
readme = "README.md"
66
rust-version = "1.79.0"
@@ -10,4 +10,5 @@ description = "Wildcard DNS for any IP Address"
1010

1111
[dependencies]
1212
log = "0.4"
13-
env_logger = "0.11"
13+
env_logger = "0.11"
14+
toml = "0.8"

src/config.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::env;
2+
use std::fs;
23
use std::net::Ipv4Addr;
4+
use toml::Value;
35

46
#[derive(Clone)]
57
pub struct Config {
@@ -12,10 +14,24 @@ pub struct Config {
1214
pub retry: u32,
1315
pub expire: u32,
1416
pub minimum: u32,
17+
pub version: String,
1518
}
1619

1720
impl Config {
1821
pub fn from_env() -> Self {
22+
let version = fs::read_to_string("Cargo.toml")
23+
.ok()
24+
.and_then(|content| {
25+
content.parse::<Value>().ok().and_then(|value| {
26+
value
27+
.get("package")
28+
.and_then(|pkg| pkg.get("version"))
29+
.and_then(|ver| ver.as_str())
30+
.map(String::from)
31+
})
32+
})
33+
.unwrap_or_else(|| "unknown".to_string());
34+
1935
Self {
2036
glue_name: env::var("GLUE_NAME").unwrap_or_else(|_| "ns.example.com".to_string()),
2137
glue_ip: env::var("GLUE_IP")
@@ -45,6 +61,7 @@ impl Config {
4561
.unwrap_or_else(|_| "3600".to_string())
4662
.parse()
4763
.expect("Invalid MINIMUM"),
64+
version,
4865
}
4966
}
5067
}

src/dns/query.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::ip_parser::interpret_ip;
2-
use super::response::{build_response, build_soa_response, SoaParams};
2+
use super::response::{build_response, build_soa_response, build_txt_response, SoaParams};
33
use crate::config::Config;
44
use log::{debug, info};
55
use std::io::Result as IoResult;
@@ -23,6 +23,14 @@ pub fn handle_query(
2323
);
2424
let response = build_response(query, Some((&config.glue_name, config.glue_ip)), None);
2525
socket.send_to(&response, src)?;
26+
} else if domain.eq_ignore_ascii_case("version")
27+
|| domain.eq_ignore_ascii_case("ver")
28+
|| domain.eq_ignore_ascii_case("v")
29+
{
30+
info!("Client [{}] requested version TXT record", src);
31+
let nameandversion = format!("RustyAlias v{}", config.version);
32+
let response = build_txt_response(query, &nameandversion);
33+
socket.send_to(&response, src)?;
2634
} else if let Some(ip) = interpret_ip(&domain) {
2735
info!("Client [{}] resolved [{}] to [{:?}]", src, domain, ip);
2836
let response = build_response(query, None, Some(ip));
@@ -112,6 +120,9 @@ pub fn handle_query_internal(query: &[u8], src: SocketAddr, config: &Config) ->
112120
src, domain, config.glue_ip
113121
);
114122
build_response(query, Some((&config.glue_name, config.glue_ip)), None)
123+
} else if domain.eq_ignore_ascii_case("version") || domain.eq_ignore_ascii_case("ver") {
124+
info!("Client [{}] requested version TXT record", src);
125+
build_txt_response(query, &config.version)
115126
} else if let Some(ip) = interpret_ip(&domain) {
116127
info!("Client [{}] resolved [{}] to [{:?}]", src, domain, ip);
117128
build_response(query, None, Some(ip))

src/dns/response.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,31 @@ pub fn encode_domain_name(name: &str) -> Vec<u8> {
124124
encoded.push(0); // End of the domain name
125125
encoded
126126
}
127+
128+
pub fn build_txt_response(query: &[u8], txt_data: &str) -> Vec<u8> {
129+
let mut response: Vec<u8> = Vec::with_capacity(512);
130+
response.extend(&query[0..2]); // ID
131+
response.extend(&[0x81, 0x80]); // Flags: response, authoritative
132+
response.extend(&query[4..6]); // QDCOUNT
133+
response.extend(&[0x00, 0x01]); // ANCOUNT
134+
response.extend(&[0x00, 0x00]); // NSCOUNT
135+
response.extend(&[0x00, 0x00]); // ARCOUNT
136+
137+
let question_end = 12 + query[12..].iter().position(|&x| x == 0).unwrap() + 5;
138+
response.extend(&query[12..question_end]); // Original question
139+
140+
// TXT Record
141+
response.extend(&[0xC0, 0x0C]); // Pointer to the domain name
142+
response.extend(&[0x00, 0x10]); // Type TXT
143+
response.extend(&[0x00, 0x01]); // Class IN
144+
response.extend(&[0x00, 0x00, 0x00, 0x3C]); // TTL: 60 seconds
145+
146+
// TXT data format: <length><string>
147+
let txt_bytes = txt_data.as_bytes();
148+
response.extend(&(txt_bytes.len() as u16 + 1).to_be_bytes()); // RDLENGTH
149+
response.push(txt_bytes.len() as u8); // Length of the string
150+
response.extend(txt_bytes); // The actual string
151+
152+
debug!("Built TXT response: {:?}", response);
153+
response
154+
}

0 commit comments

Comments
 (0)