tftp.options
tftp.options
Option negotiation (RFC 2347): handlers, registry, server policy, profiles.
Every option is an :class:OptionHandler in an :class:OptionRegistry, so
an application can add its own (vendor options, an option that selects
content) without touching the transfer code. The RFC options (blksize,
timeout, tsize, windowsize) are accepted by default; tftp-hpa's
extensions (blksize2, utimeout, rollover, cookie) only when a
server allows them, for example through a :class:Profile.
Blksize2Option
ClientOptionContext(result, requested, is_read)
What a client-side option handler sees while checking an OACK.
Source code in src/tftp/options/_handler.py
154 155 156 157 | |
CookieOption
MstfwindowOption
Bases: OptionHandler
Microsoft's variable-window extension (Windows 8+ bootmgr, WDS).
The client offers mstfwindow=31416; a server that speaks it answers
27182 and both start with a window of 4 blocks. The client may then
resize the window through its ACKs, in a format Microsoft has not
published; this library keeps the window at 4 (bytes after an ACK's
block number are ignored). A windowsize negotiated alongside wins.
Negotiated(*, blksize=DEFAULT_BLKSIZE, windowsize=1, timeout=1.0, tsize=None, rollover=0, options=None, extra=None)
The parameters a transfer actually runs with, after negotiation.
options is what was acknowledged (the OACK contents), empty when the
transfer runs on RFC 1350 defaults. extra holds what custom option
handlers decided, keyed by option name.
Source code in src/tftp/options/_handler.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
OptionHandler
One option's rules, for both ends of the negotiation.
Subclass and register an instance (see :class:OptionRegistry) to add
an option. name is lower-case; standard marks the RFC-defined
options a server accepts by default.
accept(requested, acked, ctx)
Client side: check the server's answer and apply it.
Raise :func:refuse for a value the RFC does not allow; the client
then sends ERROR 8 and abandons the transfer.
Source code in src/tftp/options/_handler.py
179 180 181 182 183 184 185 | |
negotiate(value, ctx)
Server side: the value to acknowledge, or None to leave it out.
Leaving an option out is how RFC 2347 refuses it; the transfer then
runs as if it had not been requested. Set fields on ctx.result.
Source code in src/tftp/options/_handler.py
171 172 173 174 175 176 177 | |
OptionRegistry(handlers=BUILTIN_OPTIONS)
Option handlers by name, kept in negotiation order.
Registration order is negotiation order, so an option whose answer depends
on another (windowsize on the block size) is registered after it.
Source code in src/tftp/options/_registry.py
23 24 25 26 | |
register(handler, *, replace=False)
Add handler; an existing name needs replace=True.
Source code in src/tftp/options/_registry.py
28 29 30 31 32 33 34 35 36 37 38 | |
standard()
Names of the RFC-defined options (what a server allows by default).
Source code in src/tftp/options/_registry.py
55 56 57 | |
Profile(name, server, client)
A server policy and client settings that belong together.
Source code in src/tftp/options/_profiles.py
44 45 46 47 | |
client
property
Keyword arguments for TFTPClient (a fresh dict each time).
server
property
The server policy (a fresh copy each time, so changing it changes no profile).
ServerOptionContext(result, requested, policy, is_read, size=None, mtu=None, ipv6=False, stream=None)
What a server-side option handler sees while negotiating one request.
:ivar result: the :class:Negotiated being built; handlers set fields on it.
:ivar requested: every requested option (lower-case names).
:ivar acked: what has been acknowledged so far, in registry order.
:ivar policy: the server's :class:TFTPServerOptions.
:ivar is_read: RRQ (True) or WRQ.
:ivar size: the file size for an RRQ (tsize), or None.
:ivar mtu: link MTU of the interface the request arrived on, when known.
:ivar ipv6: the transfer runs over IPv6 (header size for MTU arithmetic).
:ivar stream: what the handler opened for an RRQ (options may describe
it: x-mtime, x-list), else None.
Source code in src/tftp/options/_handler.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | |
max_blksize
property
The policy's max_blksize, lowered to fit the MTU when asked to.
TFTPServerOptions(*, max_blksize=MAX_BLKSIZE, max_windowsize=64, max_window_bytes=4 << 20, allowed=None, refused=(), fit_mtu=False, registry=None)
A server's negotiation policy.
:param max_blksize: largest blksize granted; a larger request is
answered with this value, which RFC 2348 allows.
:param max_windowsize: largest windowsize granted.
:param max_window_bytes: windowsize is also lowered so that one
window of the negotiated block size fits in this many bytes -- the
memory a sender holds per transfer.
:param allowed: option names acknowledged at all. Defaults to the RFC
options (blksize, timeout, tsize, windowsize); add
:data:EXTENSION_OPTIONS names to accept extensions.
:param refused: names never acknowledged even when allowed -- for
firmware that asks for an option and then mishandles it.
:param fit_mtu: lower blksize so a DATA packet fits the MTU of the
interface the request arrived on (needs pktinfo). Boot ROMs often
cannot reassemble IP fragments.
:param registry: where option handlers come from; custom options are
registered there.
Source code in src/tftp/options/_policy.py
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | |
replace(**changes)
A new policy with every field of this one, except those in changes.
As :func:dataclasses.replace: the result is built through the
constructor, so it is validated, and this policy is not modified.
:raises TypeError: a name that is not a field.
Source code in src/tftp/options/_policy.py
96 97 98 99 100 101 102 103 104 105 106 107 108 109 | |
XListOption
Bases: OptionHandler
pytftp's directory listing (see :mod:tftp.listing): x-list=1.
Acknowledged only when the handler answered the RRQ with a listing
(a stream with lists_directories = True); a client seeing it left out of the
OACK knows it is receiving a file.
XMtimeOption
Bases: OptionHandler
pytftp's x-mtime: an RRQ's OACK carries the file's modification
time (whole seconds since the epoch), when the source knows it.
accept_oack(requested, oack, *, is_read, timeout, registry=None)
Client side: validate a server's OACK against what was requested.
Raises :class:TFTPProtocolError with code 8 when the server acknowledged an
option that was not requested, or answered outside what the option's RFC
allows (a larger blksize or windowsize than asked for, ...). The
caller sends that ERROR to the server and abandons the transfer. An
option the server left out runs on its default.
Source code in src/tftp/options/_negotiate.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
negotiate(requested, policy, *, is_read, timeout, size=None, mtu=None, ipv6=False, stream=None)
Server side: decide which requested options to acknowledge.
Options the server does not know, does not allow, or that carry an
unusable value are left out of the acknowledgement -- RFC 2347's way of
refusing them; the transfer then runs on that option's default. A server
never acknowledges an option that was not requested. size is the file
size for an RRQ tsize; mtu/ipv6 feed fit_mtu; stream
is the RRQ's opened source, for options that describe it.
Source code in src/tftp/options/_negotiate.py
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | |
refuse(message)
The ERROR 8 a client sends for an OACK it cannot accept.
Source code in src/tftp/options/_handler.py
93 94 95 | |
register_option(handler, replace=False)
Add handler to :data:DEFAULT_REGISTRY (usable as a class decorator's result).
Source code in src/tftp/options/_registry.py
70 71 72 | |
request_options(*, blksize=None, windowsize=None, timeout=None, tsize=None, rollover=None, utimeout=False, extra=None)
Client side: the options to put in a request.
timeout is sent as timeout when it is a whole number of seconds in
1..255; a fractional one is sent as utimeout only with
utimeout=True (an extension) and otherwise not at all. tsize is
0 for a read and the upload size for a write; None leaves it out.
extra adds options verbatim (custom or extension options), after the
built-in ones.
Source code in src/tftp/options/_negotiate.py
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | |