Add config to mark server as read-only

This commit is contained in:
Foorack / Max Faxälv 2023-07-16 17:26:59 +02:00 committed by Altuğ Bakan
parent b14d066d5a
commit 38e6ad3360
3 changed files with 29 additions and 3 deletions

View file

@ -26,10 +26,10 @@ cargo install tftpd
tftpd --help
```
To run the server on the IP address `0.0.0.0`, port `1234` in the `/home/user/tftp` directory:
To run the server on the IP address `0.0.0.0`, read-only, on port `1234` in the `/home/user/tftp` directory:
```bash
tftpd -i 0.0.0.0 -p 1234 -d "/home/user/tftp"
tftpd -i 0.0.0.0 -p 1234 -d "/home/user/tftp" --read-only
```
## License

View file

@ -27,6 +27,8 @@ pub struct Config {
pub directory: PathBuf,
/// Use a single port for both sending and receiving. (default: false)
pub single_port: bool,
/// Refuse all write requests, making the server read-only. (default: false)
pub read_only: bool,
}
impl Config {
@ -38,6 +40,7 @@ impl Config {
port: 69,
directory: env::current_dir().unwrap_or_else(|_| env::temp_dir()),
single_port: false,
read_only: false,
};
args.next();
@ -71,6 +74,9 @@ impl Config {
"-s" | "--single-port" => {
config.single_port = true;
}
"-r" | "--read-only" => {
config.read_only = true;
}
"-h" | "--help" => {
println!("TFTP Server Daemon\n");
println!("Usage: tftpd [OPTIONS]\n");
@ -81,6 +87,7 @@ impl Config {
);
println!(" -d, --directory <DIRECTORY>\tSet the listening port of the server (default: Current Working Directory)");
println!(" -s, --single-port\t\tUse a single port for both sending and receiving (default: false)");
println!(" -r, --read-only\t\tRefuse all write requests, making the server read-only (default: false)");
println!(" -h, --help\t\t\tPrint help information");
process::exit(0);
}
@ -101,7 +108,7 @@ mod tests {
#[test]
fn parses_full_config() {
let config = Config::new(
vec!["/", "-i", "0.0.0.0", "-p", "1234", "-d", "/", "-s"]
vec!["/", "-i", "0.0.0.0", "-p", "1234", "-d", "/", "-s", "-r"]
.iter()
.map(|s| s.to_string()),
)
@ -111,6 +118,7 @@ mod tests {
assert_eq!(config.port, 1234);
assert_eq!(config.directory, PathBuf::from_str("/").unwrap());
assert!(config.single_port);
assert!(config.read_only);
}
#[test]

View file

@ -31,6 +31,7 @@ pub struct Server {
socket: UdpSocket,
directory: PathBuf,
single_port: bool,
read_only: bool,
largest_block_size: usize,
clients: HashMap<SocketAddr, Sender<Packet>>,
}
@ -44,6 +45,7 @@ impl Server {
socket,
directory: config.directory.clone(),
single_port: config.single_port,
read_only: config.read_only,
largest_block_size: DEFAULT_BLOCK_SIZE,
clients: HashMap::new(),
};
@ -77,6 +79,22 @@ impl Server {
mut options,
..
} => {
if self.read_only {
if Socket::send_to(
&self.socket,
&Packet::Error {
code: ErrorCode::AccessViolation,
msg: "server is read-only".to_string(),
},
&from,
)
.is_err()
{
eprintln!("Could not send error packet");
};
eprintln!("Received invalid request");
continue;
}
println!("Receiving {filename} from {from}");
if let Err(err) = self.handle_wrq(filename.clone(), &mut options, &from) {
eprintln!("Error while receiving file: {err}")