Skip to content

Commit

Permalink
feat: implement tftp server
Browse files Browse the repository at this point in the history
  • Loading branch information
teodor-pripoae committed Nov 30, 2024
1 parent e8ed699 commit ef544db
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 7 deletions.
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ go_sdk.download(version = "1.23.3")

go_deps = use_extension("@bazel_gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")
use_repo(go_deps, "com_github_spf13_cobra")
use_repo(go_deps, "com_github_pin_tftp_v3", "com_github_sirupsen_logrus", "com_github_spf13_cobra")

###############################################################################
# RPM
Expand Down
8 changes: 7 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ module toni.systems/goisoboot

go 1.22.0

require github.com/spf13/cobra v1.8.1
require (
github.com/pin/tftp/v3 v3.1.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.1
)

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
)
21 changes: 21 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pin/tftp/v3 v3.1.0 h1:rQaxd4pGwcAJnpId8zC+O2NX3B2/NscjDZQaqEjuE7c=
github.com/pin/tftp/v3 v3.1.0/go.mod h1:xwQaN4viYL019tM4i8iecm++5cGxSqen6AJEOEyEI0w=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
5 changes: 4 additions & 1 deletion pkg/cli/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ go_library(
],
importpath = "toni.systems/goisoboot/pkg/cli",
visibility = ["//visibility:public"],
deps = ["@com_github_spf13_cobra//:cobra"],
deps = [
"//pkg/tftp",
"@com_github_spf13_cobra//:cobra",
],
)
19 changes: 15 additions & 4 deletions pkg/cli/server.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
package cli

import "github.com/spf13/cobra"
import (
"fmt"
"os"

func server(cmd *cobra.Command, args []string) error {
return nil
"github.com/spf13/cobra"
"toni.systems/goisoboot/pkg/tftp"
)

func server(cmd *cobra.Command, args []string) {
tftp := tftp.New()

if err := tftp.Run(); err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
}

func NewServerCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "server",
Short: "Start the goisoboot server",
Long: "Starts TFTP and HTTP Server",
RunE: server,
Run: server,
}

cmd.Flags().IntP("http-port", "p", 8080, "HTTP Port")
Expand Down
12 changes: 12 additions & 0 deletions pkg/tftp/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
load("@rules_go//go:def.bzl", "go_library")

go_library(
name = "tftp",
srcs = ["server.go"],
importpath = "toni.systems/goisoboot/pkg/tftp",
visibility = ["//visibility:public"],
deps = [
"@com_github_pin_tftp_v3//:tftp",
"@com_github_sirupsen_logrus//:logrus",
],
)
70 changes: 70 additions & 0 deletions pkg/tftp/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package tftp

import (
"errors"
"io"
"os"
"time"

"github.com/pin/tftp/v3"
log "github.com/sirupsen/logrus"
)

const (
ipxeFilename = "ipxe.efi"
listenAddr = ":69"
)

var (
timeout = 5 * time.Second
ErrInvalidFilename = errors.New("invalid filename, expected ipxe.efi")
ErrFailedToOpenFile = errors.New("failed to open file")
ErrFailedToReadFile = errors.New("failed to read file")
)

type Server interface {
Run() error
}

type server struct {
tftp *tftp.Server
filename string
}

func New() Server {
s := &server{
filename: "./ipxe/ipxe.efi",
}

t := tftp.NewServer(s.ReadHandler, nil)
t.SetTimeout(timeout)
s.tftp = t

return s
}

func (s *server) Run() error {
log.Infof("Starting TFTP server on %s", listenAddr)
return s.tftp.ListenAndServe(listenAddr) // blocks until s.Shutdown() is called
}

func (s *server) ReadHandler(filename string, rf io.ReaderFrom) error {
log.Infof("Getting file %s", filename)
if filename != ipxeFilename {
log.Warnf("Filename %s not allowed", filename)
return ErrInvalidFilename
}

file, err := os.Open(s.filename)
if err != nil {
return errors.Join(err, ErrFailedToOpenFile)
}

n, err := rf.ReadFrom(file)
if err != nil {
return errors.Join(err, ErrFailedToReadFile)
}

log.Infof("File %s %d bytes sent\n", filename, n)
return nil
}

0 comments on commit ef544db

Please sign in to comment.