mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-08-07 07:29:03 +00:00
tftp RRQ basics - can send a file but not retries & ACKS are ignored
git-svn-id: http://svn.code.sf.net/p/netboot65/code@10 93682198-c243-4bdb-bd91-e943c89aac3b
This commit is contained in:
parent
f5887251dd
commit
4e307b0b48
@ -5,16 +5,17 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
Thread.abort_on_exception=true
|
||||||
|
|
||||||
def log_msg(msg)
|
def log_msg(msg)
|
||||||
puts "#{Time.now} #{msg}"
|
puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")} #{msg}"
|
||||||
end
|
end
|
||||||
|
|
||||||
$:.unshift(File.dirname(__FILE__)) unless
|
$:.unshift(File.dirname(__FILE__)) unless
|
||||||
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
||||||
require 'netboot65_tftp'
|
require 'netboot65_tftp'
|
||||||
|
|
||||||
bootfile_dir=File.expand_path(File.dirname(__FILE__)+"//..//clients")
|
bootfile_dir=File.expand_path(File.dirname(__FILE__)+"//..//boot")
|
||||||
tftp_server=Netboot65TFTPServer.new(bootfile_dir)
|
tftp_server=Netboot65TFTPServer.new(bootfile_dir)
|
||||||
|
|
||||||
tftp_server.start
|
tftp_server.start
|
||||||
|
@ -8,11 +8,52 @@
|
|||||||
require 'socket'
|
require 'socket'
|
||||||
class Netboot65TFTPServer
|
class Netboot65TFTPServer
|
||||||
|
|
||||||
|
TFTP_OPCODES={
|
||||||
|
1=>'RRQ', #read request
|
||||||
|
2=>'WRQ', #write request
|
||||||
|
3=>'DATA',
|
||||||
|
4=>'ACK',
|
||||||
|
5=>'ERROR',
|
||||||
|
}
|
||||||
|
|
||||||
|
TFTP_ERRORCODES={
|
||||||
|
1 =>'File not found.',
|
||||||
|
2 =>'Access violation.',
|
||||||
|
3 =>'Disk full or allocation exceeded.',
|
||||||
|
4 =>'Illegal TFTP operation.',
|
||||||
|
5 =>'Unknown transfer ID.',
|
||||||
|
6 =>'File already exists.',
|
||||||
|
7 =>'No such user.',
|
||||||
|
}
|
||||||
|
TFTP_MAX_RESENDS=10
|
||||||
|
|
||||||
attr_reader :bootfile_dir,:port,:server_thread
|
attr_reader :bootfile_dir,:port,:server_thread
|
||||||
def initialize(bootfile_dir,port=6969)
|
def initialize(bootfile_dir,port=69)
|
||||||
@bootfile_dir=bootfile_dir
|
@bootfile_dir=bootfile_dir
|
||||||
@port=port
|
@port=port
|
||||||
@server_thread=nil
|
@server_thread=nil
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_error(client_ip,client_port,error_code,error_msg)
|
||||||
|
packet=[5,error_code,error_msg,0].pack("nnA#{error_msg.length}c")
|
||||||
|
socket=UDPSocket.open.send(packet,0,client_ip,client_port)
|
||||||
|
log_msg("sent error #{error_code}:'#{error_msg}' to #{client_ip}:#{client_port}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_file(client_ip,client_port,filename)
|
||||||
|
|
||||||
|
client_sock=UDPSocket.open
|
||||||
|
client_sock.connect(client_ip,client_port)
|
||||||
|
data_to_send=File.open(filename,"rb").read
|
||||||
|
blocks_to_send=(data_to_send.length.to_f/512.0).ceil
|
||||||
|
log_msg("sending #{filename} to #{client_ip}:#{client_port} (#{blocks_to_send} blocks)")
|
||||||
|
blocks_to_send.times do |block_number|
|
||||||
|
block_data=data_to_send[block_number*512,512]
|
||||||
|
packet=[3,block_number+1,block_data].pack("nnA*")
|
||||||
|
log_msg("sending block #{block_number+1}/#{blocks_to_send} to #{client_ip}:#{client_port} - #{block_data.length} bytes")
|
||||||
|
client_sock.send(packet,0,client_ip,client_port)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def start()
|
def start()
|
||||||
@ -28,11 +69,32 @@ class Netboot65TFTPServer
|
|||||||
data,addr_info=socket.recvfrom(4096)
|
data,addr_info=socket.recvfrom(4096)
|
||||||
client_ip=addr_info[3]
|
client_ip=addr_info[3]
|
||||||
client_port=addr_info[1]
|
client_port=addr_info[1]
|
||||||
log_msg "TFTP: connect from #{client_ip}:#{client_port}"
|
opcode=data[0,2].unpack("n")[0]
|
||||||
|
opcode_description=TFTP_OPCODES[opcode]
|
||||||
|
opcode_description="[UNK]" if opcode_description.nil?
|
||||||
|
log_msg "TFTP: connect from #{client_ip}:#{client_port} - opcode #{opcode} : #{opcode_description}"
|
||||||
|
case opcode
|
||||||
|
when 1 : #READ REQUEST
|
||||||
|
opcode,filename_and_mode=data.unpack("nA*")
|
||||||
|
filename,mode=filename_and_mode.split(0.chr)
|
||||||
|
log_msg "RRQ for #{filename} (#{mode})"
|
||||||
|
if filename=~/^\./ || filename=~/\.\./ then #looks like something dodgy - either a dotfile or a directory traversal attempt
|
||||||
|
send_error(client_ip,client_port,1,"'#{filename}' invalid")
|
||||||
|
else
|
||||||
|
full_filename="#{bootfile_dir}/#{filename}"
|
||||||
|
if File.file?(full_filename) then
|
||||||
|
send_file(client_ip,client_port,full_filename)
|
||||||
|
else
|
||||||
|
send_error(client_ip,client_port,1,"'#{filename}' not found")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
send_error(client_ip,client_port,4,"opcode #{opcode} not supported")
|
||||||
|
end
|
||||||
socket.close
|
socket.close
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
#server_thread.join
|
# @server_thread.join
|
||||||
end
|
end
|
||||||
|
|
||||||
def shutdown()
|
def shutdown()
|
||||||
|
Loading…
Reference in New Issue
Block a user