trivial v0.1.0 Trivial View Source

A Read-only TFTP Service for Elixir

Motivation

Erlang's :tftp module is quite complex in order to service a broad featureset and has some critical bugs which prevent it from being used in a PXE Boot context.

This library addresses some of these limitations and gives you a way to instrument TFTP read requests in a clear and concise fashion. An emphasis has been made on code documentation and commenting, code structuring good practices, with direct references to relevant RFC content where appropriate.

Trivial is designed to be a companion to ExDhcp to make it easy to build observable and reproducible PXE-Booting solutions.

Security notes

TFTP is a fundamentally insecure protocol. Use of this library for purposes other than its intent (PXE booting) is highly discouraged. Even when using it for its intended purpose, please be very careful and only use this in networks where you are confident you have visibility and control over OSI layer 2.

Quick Start (Linux)

  1. Write your MyApplication.Tftp module with the appropriate Trivial.Server behaviour callbacks.

     defmodule MyApplication.Tftp do
       @behaviour Trivial.Server
    
       @impl true
       def init(request, data) do
    
       ...
  2. Set up a trivial server in your application supervisory tree:

     defmodule MyApplication
    
       ...
    
       def start(_type, _args) do
    
       children = [
         {Trivial, {MyApplication.Tftp, nil, port: 69}}
       ]
    
       ...
    
  3. as superuser, give your beam.smp a the capability to get low ports:

     setcap 'cap_net_bind_service,cap_net_raw=+ep' /usr/lib/erlang/erts-10.6.1/bin/beam.smp

    NB: the path to your beam.smp may be different

Note that you may want to use a different strategy to provide access to the server, for example, forwarding port 69 to port 6969 via iptables.

Supervision Tree

Trivial generates the following supervision tree:

  • Supervisor :one_for_all

    • Daemon
    • DynamicSupervisor :one_for_one

      • < Servers >

By default, the top supervisor is named Trivial

Without supervision

See Trivial.Daemon.start_link/3

Link to this section Summary

Functions

Returns a specification to start this module under a supervisor.

retrieves the PID of the Trivial.Daemon process being supervised by the target supervisor.

retrieves the UDP port of the daemon process.

retrieves the PID of the DynamicSupervisor process being supervised by the target supervisor.

starts a supervised TFTP service.

Link to this section Functions

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

daemon(supervisor \\ __MODULE__) View Source
daemon(Supervisor.supervisor()) :: pid()

retrieves the PID of the Trivial.Daemon process being supervised by the target supervisor.

retrieves the UDP port of the daemon process.

Link to this function

server_supervisor(supervisor \\ __MODULE__) View Source
server_supervisor(Supervisor.supervisor()) :: pid()

retrieves the PID of the DynamicSupervisor process being supervised by the target supervisor.

Link to this function

start_link(srv_module, srv_init, opts) View Source
start_link(server_module :: module(), server_init :: term(), opts :: keyword()) ::
  Supervisor.on_start()

starts a supervised TFTP service.

srv_module should be a module that implements the Trivial.Server behaviour; srv_init is the initial data given to the child processes.

Options

  • trivial_name: name given to the trivial server. Defaults to Trivial
  • port: the UDP port that the Daemon will bind to. Defaults to 6969