Add config to mark server as read-only
This commit is contained in:
parent
b14d066d5a
commit
38e6ad3360
3 changed files with 29 additions and 3 deletions
|
|
@ -26,10 +26,10 @@ cargo install tftpd
|
||||||
tftpd --help
|
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
|
```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
|
## License
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ pub struct Config {
|
||||||
pub directory: PathBuf,
|
pub directory: PathBuf,
|
||||||
/// Use a single port for both sending and receiving. (default: false)
|
/// Use a single port for both sending and receiving. (default: false)
|
||||||
pub single_port: bool,
|
pub single_port: bool,
|
||||||
|
/// Refuse all write requests, making the server read-only. (default: false)
|
||||||
|
pub read_only: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
|
@ -38,6 +40,7 @@ impl Config {
|
||||||
port: 69,
|
port: 69,
|
||||||
directory: env::current_dir().unwrap_or_else(|_| env::temp_dir()),
|
directory: env::current_dir().unwrap_or_else(|_| env::temp_dir()),
|
||||||
single_port: false,
|
single_port: false,
|
||||||
|
read_only: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
args.next();
|
args.next();
|
||||||
|
|
@ -71,6 +74,9 @@ impl Config {
|
||||||
"-s" | "--single-port" => {
|
"-s" | "--single-port" => {
|
||||||
config.single_port = true;
|
config.single_port = true;
|
||||||
}
|
}
|
||||||
|
"-r" | "--read-only" => {
|
||||||
|
config.read_only = true;
|
||||||
|
}
|
||||||
"-h" | "--help" => {
|
"-h" | "--help" => {
|
||||||
println!("TFTP Server Daemon\n");
|
println!("TFTP Server Daemon\n");
|
||||||
println!("Usage: tftpd [OPTIONS]\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!(" -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!(" -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");
|
println!(" -h, --help\t\t\tPrint help information");
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +108,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn parses_full_config() {
|
fn parses_full_config() {
|
||||||
let config = Config::new(
|
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()
|
.iter()
|
||||||
.map(|s| s.to_string()),
|
.map(|s| s.to_string()),
|
||||||
)
|
)
|
||||||
|
|
@ -111,6 +118,7 @@ mod tests {
|
||||||
assert_eq!(config.port, 1234);
|
assert_eq!(config.port, 1234);
|
||||||
assert_eq!(config.directory, PathBuf::from_str("/").unwrap());
|
assert_eq!(config.directory, PathBuf::from_str("/").unwrap());
|
||||||
assert!(config.single_port);
|
assert!(config.single_port);
|
||||||
|
assert!(config.read_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ pub struct Server {
|
||||||
socket: UdpSocket,
|
socket: UdpSocket,
|
||||||
directory: PathBuf,
|
directory: PathBuf,
|
||||||
single_port: bool,
|
single_port: bool,
|
||||||
|
read_only: bool,
|
||||||
largest_block_size: usize,
|
largest_block_size: usize,
|
||||||
clients: HashMap<SocketAddr, Sender<Packet>>,
|
clients: HashMap<SocketAddr, Sender<Packet>>,
|
||||||
}
|
}
|
||||||
|
|
@ -44,6 +45,7 @@ impl Server {
|
||||||
socket,
|
socket,
|
||||||
directory: config.directory.clone(),
|
directory: config.directory.clone(),
|
||||||
single_port: config.single_port,
|
single_port: config.single_port,
|
||||||
|
read_only: config.read_only,
|
||||||
largest_block_size: DEFAULT_BLOCK_SIZE,
|
largest_block_size: DEFAULT_BLOCK_SIZE,
|
||||||
clients: HashMap::new(),
|
clients: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
@ -77,6 +79,22 @@ impl Server {
|
||||||
mut options,
|
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}");
|
println!("Receiving {filename} from {from}");
|
||||||
if let Err(err) = self.handle_wrq(filename.clone(), &mut options, &from) {
|
if let Err(err) = self.handle_wrq(filename.clone(), &mut options, &from) {
|
||||||
eprintln!("Error while receiving file: {err}")
|
eprintln!("Error while receiving file: {err}")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue