aboutsummaryrefslogtreecommitdiff
path: root/src/tftpd.rs
diff options
context:
space:
mode:
authorReiner Herrmann <reiner@reiner-h.de>2019-03-02 18:21:43 +0100
committerReiner Herrmann <reiner@reiner-h.de>2019-03-02 18:21:43 +0100
commit644b518e10f17e6360af088794c6fb710c7e7ce4 (patch)
treed72facb72a55c701036f586dc40ce0b6c40e39fa /src/tftpd.rs
parentbec78b4f5c32f54fd693f188eb5f2130b95508e8 (diff)
Implement TFTP client
no support for TFTP Options yet
Diffstat (limited to 'src/tftpd.rs')
-rw-r--r--src/tftpd.rs57
1 files changed, 42 insertions, 15 deletions
diff --git a/src/tftpd.rs b/src/tftpd.rs
index 02acb14..ce108de 100644
--- a/src/tftpd.rs
+++ b/src/tftpd.rs
@@ -4,6 +4,8 @@
*/
use std::net::{SocketAddr,UdpSocket};
+use std::fs::OpenOptions;
+use std::fs::File;
use std::path::{Path,PathBuf};
use std::error::Error;
use std::env;
@@ -19,12 +21,12 @@ use getopts::Options;
mod tftp;
struct Configuration {
- pub port: u16,
- pub uid: u32,
- pub gid: u32,
- pub ro: bool,
- pub wo: bool,
- pub dir: PathBuf,
+ port: u16,
+ uid: u32,
+ gid: u32,
+ ro: bool,
+ wo: bool,
+ dir: PathBuf,
}
struct Tftpd {
@@ -92,15 +94,25 @@ impl Tftpd {
}
};
- match self.tftp.recv_file(&socket, &path) {
+ let mut file = match OpenOptions::new().write(true).create_new(true).open(&path) {
+ Ok(f) => f,
+ Err(ref err) if err.kind() == io::ErrorKind::AlreadyExists => {
+ println!("Receiving {} from {} failed ({}).", path.display(), cl, err);
+ self.tftp.send_error(&socket, 6, "File already exists")?;
+ return Err(io::Error::new(err.kind(), "already exists"));
+ },
+ Err(err) => {
+ println!("Receiving {} from {} failed ({}).", path.display(), cl, err);
+ self.tftp.send_error(&socket, 6, "Permission denied")?;
+ return Err(io::Error::new(io::ErrorKind::PermissionDenied, "permission denied"));
+ }
+ };
+
+ match self.tftp.recv_file(&socket, &mut file) {
Ok(_) => println!("Received {} from {}.", path.display(), cl),
Err(ref err) => {
- println!("Receiving {} from {} failed ({}).", path.display(), cl, err.to_string());
- match err.kind() {
- io::ErrorKind::PermissionDenied => self.tftp.send_error(&socket, 2, "Permission denied")?,
- io::ErrorKind::AlreadyExists => self.tftp.send_error(&socket, 6, "File already exists")?,
- _ => self.tftp.send_error(&socket, 0, "Receiving error")?,
- }
+ println!("Receiving {} from {} failed ({}).", path.display(), cl, err);
+ self.tftp.send_error(&socket, 0, "Receiving error")?;
return Err(io::Error::new(err.kind(), err.to_string()));
}
}
@@ -128,7 +140,22 @@ impl Tftpd {
}
};
- match self.tftp.send_file(&socket, &path) {
+ let mut file = match File::open(&path) {
+ Ok(f) => f,
+ Err(ref error) if error.kind() == io::ErrorKind::NotFound => {
+ self.tftp.send_error(&socket, 1, "File not found")?;
+ return Err(io::Error::new(io::ErrorKind::NotFound, "file not found"));
+ },
+ Err(_) => {
+ self.tftp.send_error(&socket, 2, "Permission denied")?;
+ return Err(io::Error::new(io::ErrorKind::PermissionDenied, "permission denied"));
+ }
+ };
+ if !file.metadata()?.is_file() {
+ self.tftp.send_error(&socket, 1, "File not found")?;
+ return Err(io::Error::new(io::ErrorKind::NotFound, "file not found"));
+ }
+ match self.tftp.send_file(&socket, &mut file) {
Ok(_) => println!("Sent {} to {}.", path.display(), cl),
Err(err) => println!("Sending {} to {} failed ({}).", path.display(), cl, err.to_string()),
}
@@ -137,8 +164,8 @@ impl Tftpd {
pub fn handle_client(&mut self, cl: &SocketAddr, buf: &[u8]) -> Result<(), io::Error> {
let socket = UdpSocket::bind("[::]:0")?;
- socket.connect(cl)?;
socket.set_read_timeout(Some(Duration::from_secs(5)))?;
+ socket.connect(cl)?;
let _opcode = match u16::from_be_bytes([buf[0], buf[1]]) {
1 /* RRQ */ => {