tftp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/LICENSE +13 -0
- data/README.md +21 -0
- data/Rakefile +7 -0
- data/lib/tftp.rb +3 -0
- data/lib/tftp/error.rb +22 -0
- data/lib/tftp/protocol.rb +80 -0
- data/lib/tftp/version.rb +3 -0
- data/spec/helper.rb +3 -0
- data/spec/protocol_spec.rb +42 -0
- data/tftp.gemspec +26 -0
- metadata +125 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2013 Michael Pellon <michael@p3ll0n.net>
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and distribute this software for any
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#### TFTP
|
2
|
+
|
3
|
+
[](https://codeclimate.com/github/p3ll0n/tftp)
|
4
|
+
|
5
|
+
tftp is a pure Ruby TFTP library.
|
6
|
+
|
7
|
+
It includes client and server classes, with sample implementations.
|
8
|
+
|
9
|
+
##### The TFTP Protocol
|
10
|
+
|
11
|
+
Trivial File Transfer Protocol (TFTP) is a file transfer protocol implemented
|
12
|
+
on top of the User Datagram Protocol (UDP) notable for its simplicity.
|
13
|
+
|
14
|
+
Its simple design makes it ideal for low memory platforms where it is commonly
|
15
|
+
used for booting devices without any storage (routers) and as a part of
|
16
|
+
network based installation systems.
|
17
|
+
|
18
|
+
TFTP is currently defined by RFC 1350.
|
19
|
+
|
20
|
+
Due to its complete lack of an authentication mechanism it is strongly advised
|
21
|
+
the TFTP run only one private, local networks.
|
data/Rakefile
ADDED
data/lib/tftp.rb
ADDED
data/lib/tftp/error.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module TFTP
|
2
|
+
# An exception raised by TFTP code.
|
3
|
+
class Error < StandardError
|
4
|
+
|
5
|
+
MESSAGES = {
|
6
|
+
:invalid_block_num => "Block nums must begin with 1 and increase by one for each new block of data.",
|
7
|
+
:no_filename_provided => "All RRQ/WRQ packets are required to have a filename.",
|
8
|
+
:unsupported_mode => "Octet is the only mode currently supported."
|
9
|
+
}
|
10
|
+
|
11
|
+
def self.message(key, *args)
|
12
|
+
string = MESSAGES[key] or raise "[TFTP BUG] No error messages for #{key}"
|
13
|
+
(args.empty? ? string : string % args).rstrip
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param message [String] The error message
|
17
|
+
def initialize(message = nil)
|
18
|
+
super(message)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'tftp/error'
|
2
|
+
|
3
|
+
module TFTP
|
4
|
+
module Protocol
|
5
|
+
|
6
|
+
# Opcodes
|
7
|
+
OP_RRQ = 1 # Read request
|
8
|
+
OP_WRQ = 2 # Write request
|
9
|
+
OP_DATA = 3 # Data
|
10
|
+
OP_ACK = 4 # Acknowledgment
|
11
|
+
OP_ERROR = 5 # Error
|
12
|
+
|
13
|
+
MIN_PACKET_SIZE = 4 # Minimum packet size
|
14
|
+
MAX_PACKET_SIZE = 516 # Maximum packet size
|
15
|
+
DATABLOCK_SIZE = 512 # Size of blocks used to send files
|
16
|
+
|
17
|
+
VALID_MODES = ['netascii', 'octet']
|
18
|
+
|
19
|
+
# RRQ Packet
|
20
|
+
class RRQ < BinData::Record
|
21
|
+
bit16 :opcode
|
22
|
+
stringz :filename
|
23
|
+
stringz :mode
|
24
|
+
end
|
25
|
+
|
26
|
+
# WRQ Packet
|
27
|
+
class WRQ < BinData::Record
|
28
|
+
bit16 :opcode
|
29
|
+
stringz :filename
|
30
|
+
stringz :mode
|
31
|
+
|
32
|
+
def create(opts = {})
|
33
|
+
self.opcode = OP_WRQ
|
34
|
+
|
35
|
+
if opts[:filename] == nil
|
36
|
+
raise TFTP::Error.message(:no_filename_provided)
|
37
|
+
else
|
38
|
+
self.filename = opts[:filename]
|
39
|
+
end
|
40
|
+
|
41
|
+
self.mode = opts.fetch(:mode, "octet")
|
42
|
+
|
43
|
+
raise TFTP::Error.message(:unsupported_mode) if !VALID_MODES.any?{ |s| s.casecmp(self.mode)==0 }
|
44
|
+
|
45
|
+
self
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Data Packet
|
50
|
+
class Data < BinData::Record
|
51
|
+
bit16 :opcode
|
52
|
+
bit16 :block_num
|
53
|
+
string :data
|
54
|
+
end
|
55
|
+
|
56
|
+
# ACK Packet
|
57
|
+
class ACK < BinData::Record
|
58
|
+
bit16 :opcode
|
59
|
+
bit16 :block_num
|
60
|
+
|
61
|
+
def create(opts = {})
|
62
|
+
self.opcode = OP_ACK
|
63
|
+
self.block_num = opts.fetch(:block_num, 0)
|
64
|
+
|
65
|
+
# Catch the invalid block nums
|
66
|
+
raise TFTP::Error.message(:invalid_block_num) if opts[:block_num].to_i < 0
|
67
|
+
|
68
|
+
self
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Error Packet
|
73
|
+
class Error < BinData::Record
|
74
|
+
bit16 :opcode
|
75
|
+
bit16 :error_code
|
76
|
+
stringz :error_msg
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
data/lib/tftp/version.rb
ADDED
data/spec/helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe 'TFTP::Protocol' do
|
4
|
+
context "when creating packets" do
|
5
|
+
describe 'TFTP::Protocol::ACK.create' do
|
6
|
+
|
7
|
+
let(:packet) { TFTP::Protocol::ACK.new }
|
8
|
+
|
9
|
+
context "when not providing a block number" do
|
10
|
+
it { packet.create.to_binary_s.should == "\x00\x04\x00\x00" }
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when providing a valid block number, e.g., 1" do
|
14
|
+
it { packet.create({:block_num => 1}).to_binary_s.should == "\x00\x04\x00\x01" }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when not providing a valid block number, e.g. -1" do
|
18
|
+
it { expect { packet.create({:block_num => -1}) }.to raise_error(RuntimeError, 'Block nums must begin with 1 and increase by one for each new block of data.') }
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'TFTP::Protocol::WRQ.create' do
|
24
|
+
|
25
|
+
let(:packet) { TFTP::Protocol::WRQ.new }
|
26
|
+
|
27
|
+
context "when not providing a filename" do
|
28
|
+
it { expect { packet.create }.to raise_error(RuntimeError, 'All RRQ/WRQ packets are required to have a filename.') }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when not providing a mode" do
|
32
|
+
it { packet.create({:filename => "test.txt"}).to_binary_s.should == "\x00\x02test.txt\x00octet\x00" }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when providing an unsupported mode" do
|
36
|
+
it { expect { packet.create({:filename => "test.txt", :mode => "badmode"})}.to raise_error(RuntimeError, 'Octet is the only mode currently supported.') }
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
data/tftp.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'tftp/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "tftp"
|
8
|
+
spec.version = Tftp::VERSION
|
9
|
+
spec.authors = ["Michael Pellon"]
|
10
|
+
spec.email = ["michael@p3ll0n.net"]
|
11
|
+
spec.description = %q{A pure Ruby TFTP library.}
|
12
|
+
spec.summary = %q{A pure Ruby TFTP library.}
|
13
|
+
spec.homepage = "https://github.com/p3ll0n/tftp"
|
14
|
+
spec.license = "ISC"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split("\n")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "bindata", "~> 1.5.0"
|
22
|
+
|
23
|
+
spec.add_development_dependency "rake", "~> 10.1.0"
|
24
|
+
spec.add_development_dependency "rspec", "~> 2.14.1"
|
25
|
+
spec.add_development_dependency "should_not", "~> 1.0.0"
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tftp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Pellon
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bindata
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 1.5.0
|
21
|
+
none: false
|
22
|
+
requirement: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.5.0
|
27
|
+
none: false
|
28
|
+
prerelease: false
|
29
|
+
type: :runtime
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
version_requirements: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ~>
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 10.1.0
|
37
|
+
none: false
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ~>
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 10.1.0
|
43
|
+
none: false
|
44
|
+
prerelease: false
|
45
|
+
type: :development
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ~>
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 2.14.1
|
53
|
+
none: false
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ~>
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 2.14.1
|
59
|
+
none: false
|
60
|
+
prerelease: false
|
61
|
+
type: :development
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: should_not
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.0.0
|
69
|
+
none: false
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ~>
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 1.0.0
|
75
|
+
none: false
|
76
|
+
prerelease: false
|
77
|
+
type: :development
|
78
|
+
description: A pure Ruby TFTP library.
|
79
|
+
email:
|
80
|
+
- michael@p3ll0n.net
|
81
|
+
executables: []
|
82
|
+
extensions: []
|
83
|
+
extra_rdoc_files: []
|
84
|
+
files:
|
85
|
+
- .gitignore
|
86
|
+
- .rspec
|
87
|
+
- Gemfile
|
88
|
+
- LICENSE
|
89
|
+
- README.md
|
90
|
+
- Rakefile
|
91
|
+
- lib/tftp.rb
|
92
|
+
- lib/tftp/error.rb
|
93
|
+
- lib/tftp/protocol.rb
|
94
|
+
- lib/tftp/version.rb
|
95
|
+
- spec/helper.rb
|
96
|
+
- spec/protocol_spec.rb
|
97
|
+
- tftp.gemspec
|
98
|
+
homepage: https://github.com/p3ll0n/tftp
|
99
|
+
licenses:
|
100
|
+
- ISC
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
none: false
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
none: false
|
117
|
+
requirements: []
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 1.8.24
|
120
|
+
signing_key:
|
121
|
+
specification_version: 3
|
122
|
+
summary: A pure Ruby TFTP library.
|
123
|
+
test_files:
|
124
|
+
- spec/helper.rb
|
125
|
+
- spec/protocol_spec.rb
|