pin / tftp Goto Github PK
View Code? Open in Web Editor NEWTFTP server and client library for Golang
License: MIT License
TFTP server and client library for Golang
License: MIT License
Hi @pin
Currently there is no close method available for client. It would be good to have close method on client, for some abrupt manual closing of sending/receiving.
In my application I use a blksize of 65432 to transfer big ISO images by tftp (speed 60MB/s). With the new blksize logic the speed now drops to 10MB/s. Is it possible to introduce a boolean flag to disable this smart negotiation handling for people who know their network components and simply use the blksize value again which the client provides.
It looks like some of the tests are currently failing on the debian build infrastructure:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1036256
@pin maybe you could have a look if you can reproduce them?
The traces maybe hint to one of the time.sleep calls which might add up
After being pointed to the Debian Bug #1008412 we tried to reproduce.
The Debian Bug points to the test TestServerSendTimeoutSinglePort
, in our tests the same(?) bug occurred, but in the test TestSendReceiveSinglePort
.
Note: This seems to happen only when the build host has only the loopback interface available.
Here is the complete build output:
[0] 13:26 [email protected]:~/foo/golang-github-pin-tftp debian/sid $ newnet
[0] 13:26 [email protected]:~/foo/golang-github-pin-tftp debian/sid 2s $ dbp
Using existing ../golang-github-pin-tftp_2.2.0.orig.tar.gz
Script started, output log file is '../log'.
DEB_CHECK_COMMAND=lintian dpkg-buildpackage -rfakeroot -us -uc -i -I -j8
dpkg-buildpackage: Information: Quellpaket golang-github-pin-tftp
dpkg-buildpackage: Information: Quellversion 2.2.0-1
dpkg-buildpackage: Information: Quelldistribution unstable
dpkg-buildpackage: Information: Quelle geändert durch Dominik George <[email protected]>
dpkg-buildpackage: Information: Host-Architektur amd64
dpkg-source -i -I --before-build .
debian/rules clean
dh clean --builddirectory=_build --buildsystem=golang --with=golang
dh_auto_clean -O--builddirectory=_build -O--buildsystem=golang
dh_autoreconf_clean -O--builddirectory=_build -O--buildsystem=golang
dh_clean -O--builddirectory=_build -O--buildsystem=golang
dpkg-source -i -I -b .
dpkg-source: Information: Quellformat »3.0 (quilt)« wird verwendet
dpkg-source: Information: golang-github-pin-tftp wird unter Benutzung des existierenden ./golang-github-pin-tftp_2.2.0.orig.tar.gz gebaut
dpkg-source: Information: golang-github-pin-tftp wird in golang-github-pin-tftp_2.2.0-1.debian.tar.xz gebaut
dpkg-source: Information: golang-github-pin-tftp wird in golang-github-pin-tftp_2.2.0-1.dsc gebaut
debian/rules binary
dh binary --builddirectory=_build --buildsystem=golang --with=golang
dh_update_autotools_config -O--builddirectory=_build -O--buildsystem=golang
dh_autoreconf -O--builddirectory=_build -O--buildsystem=golang
dh_auto_configure -O--builddirectory=_build -O--buildsystem=golang
dh_auto_build -O--builddirectory=_build -O--buildsystem=golang
cd _build && go install -trimpath -v -p 8 github.com/pin/tftp github.com/pin/tftp/netascii
internal/unsafeheader
internal/goarch
internal/goos
internal/race
internal/goexperiment
internal/cpu
runtime/internal/atomic
runtime/internal/syscall
sync/atomic
unicode
unicode/utf8
math/bits
internal/abi
runtime/internal/math
runtime/internal/sys
internal/itoa
internal/bytealg
golang.org/x/net/internal/iana
math
golang.org/x/sys/internal/unsafeheader
internal/nettrace
runtime
internal/reflectlite
sync
internal/singleflight
internal/testlog
math/rand
runtime/cgo
errors
sort
io
internal/oserror
path
vendor/golang.org/x/net/dns/dnsmessage
strconv
syscall
github.com/pin/tftp/netascii
bytes
strings
reflect
internal/syscall/execenv
internal/syscall/unix
time
context
io/fs
internal/poll
os
internal/fmtsort
encoding/binary
golang.org/x/sys/unix
internal/godebug
fmt
internal/intern
net/netip
golang.org/x/net/bpf
net
golang.org/x/net/internal/socket
golang.org/x/net/ipv4
golang.org/x/net/ipv6
github.com/pin/tftp
dh_auto_test -O--builddirectory=_build -O--buildsystem=golang
cd _build && go test -vet=off -v -p 8 github.com/pin/tftp github.com/pin/tftp/netascii
=== RUN TestZeroLengthSinglePort
--- PASS: TestZeroLengthSinglePort (0.00s)
=== RUN TestSendReceiveSinglePort
panic: test timed out after 10m0s
goroutine 1390 [running]:
testing.(*M).startAlarm.func1()
/usr/lib/go-1.18/src/testing/testing.go:2029 +0x8e
created by time.goFunc
/usr/lib/go-1.18/src/time/sleep.go:176 +0x32
goroutine 1 [chan receive, 10 minutes]:
testing.(*T).Run(0xc000003860, {0x61c075?, 0x4d1885?}, 0x62ae28)
/usr/lib/go-1.18/src/testing/testing.go:1487 +0x37a
testing.runTests.func1(0xc00007a180?)
/usr/lib/go-1.18/src/testing/testing.go:1839 +0x6e
testing.tRunner(0xc000003860, 0xc00010bcd8)
/usr/lib/go-1.18/src/testing/testing.go:1439 +0x102
testing.runTests(0xc000182000?, {0x791c60, 0x1d, 0x1d}, {0x7f4b92c47100?, 0xc00010bd78?, 0x797800?})
/usr/lib/go-1.18/src/testing/testing.go:1837 +0x457
testing.(*M).Run(0xc000182000)
/usr/lib/go-1.18/src/testing/testing.go:1719 +0x5d9
main.main()
_testmain.go:103 +0x1aa
goroutine 9 [chan receive, 9 minutes]:
github.com/pin/tftp.(*Server).internalGC(0xc0001880e0)
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:121 +0x70
created by github.com/pin/tftp.(*Server).EnableSinglePort
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/server.go:129 +0x16f
goroutine 8 [chan send, 9 minutes]:
github.com/pin/tftp.(*Server).Shutdown(0xc0001880e0)
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/server.go:310 +0x65
github.com/pin/tftp.TestSendReceiveSinglePort(0x0?)
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port_test.go:19 +0xaa
testing.tRunner(0xc0001a0000, 0x62ae28)
/usr/lib/go-1.18/src/testing/testing.go:1439 +0x102
created by testing.(*T).Run
/usr/lib/go-1.18/src/testing/testing.go:1486 +0x35f
goroutine 6 [chan receive, 10 minutes]:
github.com/pin/tftp.(*Server).internalGC(0xc000188000)
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:121 +0x70
created by github.com/pin/tftp.(*Server).EnableSinglePort
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/server.go:129 +0x16f
goroutine 10 [IO wait, 9 minutes]:
internal/poll.runtime_pollWait(0x7f4b919480d8, 0x72)
/usr/lib/go-1.18/src/runtime/netpoll.go:302 +0x89
internal/poll.(*pollDesc).wait(0xc00007c300?, 0x28?, 0x0)
/usr/lib/go-1.18/src/internal/poll/fd_poll_runtime.go:83 +0x32
internal/poll.(*pollDesc).waitRead(...)
/usr/lib/go-1.18/src/internal/poll/fd_poll_runtime.go:88
internal/poll.(*FD).RawRead(0xc00007c300, 0xc000827680)
/usr/lib/go-1.18/src/internal/poll/fd_unix.go:766 +0x145
net.(*rawConn).Read(0xc000010060, 0x28?)
/usr/lib/go-1.18/src/net/rawconn.go:43 +0x45
golang.org/x/net/internal/socket.(*Conn).recvMsg(0xc00006e0c0, 0xc0007621a8, 0x0)
/home/cbe/foo/golang-github-pin-tftp/_build/src/golang.org/x/net/internal/socket/rawconn_msg.go:29 +0x202
golang.org/x/net/internal/socket.(*Conn).RecvMsg(...)
/home/cbe/foo/golang-github-pin-tftp/_build/src/golang.org/x/net/internal/socket/socket.go:247
golang.org/x/net/ipv6.(*payloadHandler).ReadFrom(0xc0000121f0, {0xc0007ad800, 0x7d4, 0x7d4})
/home/cbe/foo/golang-github-pin-tftp/_build/src/golang.org/x/net/ipv6/payload_cmsg.go:32 +0x1fc
github.com/pin/tftp.(*Server).getPacket(0xc000188170?, {0xc0007ad800?, 0xc000401e05?, 0x0?})
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:77 +0x185
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc0001880e0)
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:43 +0x2af
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fec0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc0001880e0)
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fec0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc0001880e0)
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fec0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc0001880e0)
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fec0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc0001880e0)
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fec0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc0001880e0)
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).Serve(0xc0001880e0, {0x661ba0?, 0xc000010048})
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/server.go:222 +0x24f
created by github.com/pin/tftp.makeTestServer
/home/cbe/foo/golang-github-pin-tftp/_build/src/github.com/pin/tftp/tftp_test.go:439 +0x245
FAIL github.com/pin/tftp 600.063s
=== RUN TestTo
--- PASS: TestTo (0.00s)
=== RUN TestFrom
--- PASS: TestFrom (0.00s)
=== RUN TestWriteRead
--- PASS: TestWriteRead (0.00s)
=== RUN TestOneByte
--- PASS: TestOneByte (0.00s)
PASS
ok github.com/pin/tftp/netascii 0.008s
FAIL
dh_auto_test: error: cd _build && go test -vet=off -v -p 8 github.com/pin/tftp github.com/pin/tftp/netascii returned exit code 1
make: *** [debian/rules:4: binary] Fehler 255
dpkg-buildpackage: Fehler: Unterprozess debian/rules binary lieferte Exitstatus 2
Script done.
It is also possile to run the test without running the build everytime.
[0] 11:53 cbe@benz:/tmp/go/b001 $ newnet ./tftp.test -test.run 'TestSendReceiveSinglePort$' -test.v -test.timeout 1m
=== RUN TestSendReceiveSinglePort
--- PASS: TestSendReceiveSinglePort (0.70s)
PASS
[0] 11:53 cbe@benz:/tmp/go/b001 $ newnet ./tftp.test -test.run 'TestSendReceiveSinglePort$' -test.v -test.timeout 1m
=== RUN TestSendReceiveSinglePort
panic: test timed out after 1m0s
goroutine 1667 [running]:
testing.(*M).startAlarm.func1()
/usr/lib/go-1.18/src/testing/testing.go:2029 +0x8e
created by time.goFunc
/usr/lib/go-1.18/src/time/sleep.go:176 +0x32
goroutine 1 [chan receive]:
testing.(*T).Run(0xc000113860, {0x61c08d?, 0x4d1945?}, 0x62ae40)
/usr/lib/go-1.18/src/testing/testing.go:1487 +0x37a
testing.runTests.func1(0xc00007d7d0?)
/usr/lib/go-1.18/src/testing/testing.go:1839 +0x6e
testing.tRunner(0xc000113860, 0xc000155cd8)
/usr/lib/go-1.18/src/testing/testing.go:1439 +0x102
testing.runTests(0xc000119360?, {0x791c60, 0x1d, 0x1d}, {0x7f76c90fe108?, 0x40?, 0x797820?})
/usr/lib/go-1.18/src/testing/testing.go:1837 +0x457
testing.(*M).Run(0xc000119360)
/usr/lib/go-1.18/src/testing/testing.go:1719 +0x5d9
main.main()
_testmain.go:103 +0x1aa
goroutine 8 [chan send]:
github.com/pin/tftp.(*Server).Shutdown(0xc000192000)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/server.go:310 +0x65
github.com/pin/tftp.TestSendReceiveSinglePort(0x0?)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port_test.go:19 +0xaa
testing.tRunner(0xc000113a00, 0x62ae40)
/usr/lib/go-1.18/src/testing/testing.go:1439 +0x102
created by testing.(*T).Run
/usr/lib/go-1.18/src/testing/testing.go:1486 +0x35f
goroutine 9 [chan receive]:
github.com/pin/tftp.(*Server).internalGC(0xc000192000)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:121 +0x70
created by github.com/pin/tftp.(*Server).EnableSinglePort
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/server.go:129 +0x16f
goroutine 10 [IO wait]:
internal/poll.runtime_pollWait(0x7f76a1c8b1d8, 0x72)
/usr/lib/go-1.18/src/runtime/netpoll.go:302 +0x89
internal/poll.(*pollDesc).wait(0xc000168200?, 0x28?, 0x0)
/usr/lib/go-1.18/src/internal/poll/fd_poll_runtime.go:83 +0x32
internal/poll.(*pollDesc).waitRead(...)
/usr/lib/go-1.18/src/internal/poll/fd_poll_runtime.go:88
internal/poll.(*FD).RawRead(0xc000168200, 0xc000482090)
/usr/lib/go-1.18/src/internal/poll/fd_unix.go:766 +0x145
net.(*rawConn).Read(0xc000094008, 0x28?)
/usr/lib/go-1.18/src/net/rawconn.go:43 +0x45
golang.org/x/net/internal/socket.(*Conn).recvMsg(0xc00009a000, 0xc0007e7278, 0x0)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/golang.org/x/net/internal/socket/rawconn_msg.go:29 +0x202
golang.org/x/net/internal/socket.(*Conn).RecvMsg(...)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/golang.org/x/net/internal/socket/socket.go:247
golang.org/x/net/ipv6.(*payloadHandler).ReadFrom(0xc000096060, {0xc000544800, 0x7d4, 0x7d4})
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/golang.org/x/net/ipv6/payload_cmsg.go:32 +0x1fc
github.com/pin/tftp.(*Server).getPacket(0xc000192090?, {0xc000544800?, 0xc0005e0cc5?, 0x0?})
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:77 +0x185
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc000192000)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:43 +0x2af
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fef0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc000192000)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fef0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc000192000)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fef0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc000192000)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fef0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc000192000)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fef0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc000192000)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fef0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc000192000)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fef0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc000192000)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).singlePortProcessRequests.func1()
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:29 +0x314
panic({0x5e18c0, 0x65fef0})
/usr/lib/go-1.18/src/runtime/panic.go:838 +0x207
github.com/pin/tftp.(*Server).singlePortProcessRequests(0xc000192000)
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/single_port.go:55 +0x465
github.com/pin/tftp.(*Server).Serve(0xc000192000, {0x661be0?, 0xc000010088})
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/server.go:222 +0x24f
created by github.com/pin/tftp.makeTestServer
/home/cbe/credativ/gardenlinux/golang-github-pin-tftp/_build/src/github.com/pin/tftp/tftp_test.go:439 +0x245
Thanks for the package!
In our production, we found FD leak happened from time to time.
Result of netstat
.
udp6 0 0 :::35808 :::* 1/imgsvc
udp6 0 0 :::60384 :::* 1/imgsvc
udp6 0 0 :::35811 :::* 1/imgsvc
udp6 0 0 :::48099 :::* 1/imgsvc
udp6 0 0 :::48101 :::* 1/imgsvc
udp6 0 0 :::44006 :::* 1/imgsvc
udp6 0 0 :::60391 :::* 1/imgsvc
udp6 0 0 :::39913 :::* 1/imgsvc
Result of lsof
imgsvc 1 root 97u IPv6 2499572613 0t0 UDP *:39620
imgsvc 1 root 98u IPv6 2499572625 0t0 UDP *:53887
imgsvc 1 root 99u IPv6 2499574158 0t0 UDP *:35839
imgsvc 1 root 100u IPv6 2499571638 0t0 UDP *:40739
imgsvc 1 root 101u IPv6 2499572645 0t0 UDP *:39966
imgsvc 1 root 102u IPv6 2499574181 0t0 UDP *:37082
imgsvc 1 root 103u IPv6 2499572675 0t0 UDP *:60167
imgsvc 1 root 104u IPv6 2499572703 0t0 UDP *:60581
imgsvc 1 root 105u IPv6 2499572717 0t0 UDP *:60832
imgsvc 1 root 106u IPv6 2499575882 0t0 UDP *:51438
imgsvc 1 root 107u IPv6 2499575159 0t0 UDP *:40391
imgsvc 1 root 108u IPv6 2499575980 0t0 UDP *:47018
imgsvc 1 root 109u IPv6 2499574463 0t0 UDP *:48728
imgsvc 1 root 110u IPv6 2499574738 0t0 UDP *:41585
imgsvc 1 root 111u IPv6 2499579012 0t0 UDP *:50600
imgsvc 1 root 112u IPv6 2499577856 0t0 UDP *:52925
imgsvc 1 root 113u IPv6 2499580893 0t0 UDP *:58937
imgsvc 1 root 114u IPv6 2499581898 0t0 UDP *:56533
imgsvc 1 root 115u IPv6 2499600282 0t0 UDP *:51884
imgsvc 1 root 116u IPv6 2499602688 0t0 UDP *:48947
imgsvc 1 root 117u IPv6 2499600345 0t0 UDP *:37447
We only have one readHandler like example in README, so the leak seems coming from the server itself. Looking at the codes https://github.com/pin/tftp/blob/master/server.go#L416, seems like connection is not closed, so can you please help check if it is the root cause or not.
conn, err := net.ListenUDP("udp", listenAddr)
if err != nil {
return err
}
rf.conn = &connConnection{conn: conn}
}
if s.sendAEnable { /* senderAnticipate if enabled in server */
rf.sendA.enabled = true /* pass enable from server to sender */
sendAInit(&rf.sendA, datagramLength, s.sendAWinSz)
}
s.wg.Add(1)
go func() {
if s.readHandler != nil {
err := s.readHandler(filename, rf)
if err != nil {
rf.abort(err)
}
} else {
rf.abort(fmt.Errorf("server does not support read requests"))
}
s.wg.Done()
}()
Currently with the examples provided the tftp server and client requests are not designed for any validation of requested path. This results in a risk of pulling or writing data to anywhere on the file system depending on the privilege of the user running the binary. Example with the client read example filename string of "/etc/shadow" can be specified and is retrieved. Likewise write operation handling is equally dangerous as it could result in remote user adds and drop files in sudoers.d on system. Perhaps an improvement would be to require specific path to serve data from specified in config. I know this is a broader problem for those using your tool and they should be mindful of potential security risks but I figured it was worth mentioning it.
I can't use your package when using go mod
:
$ go mod tidy
go: finding module for package github.com/pin/tftp/v2
tftpserver imports
github.com/pin/tftp/v2: no matching versions for query "latest"
The reason is explained with this command:
go list -m -versions -json github.com/pin/tftp/v2
go: loading module retractions for github.com/pin/tftp/[email protected]: version "v2.2.0" invalid: go.mod has non-.../v2 module path "github.com/pin/tftp" (and .../v2/go.mod does not exist) at revision v2.2.0
I guess the solution is to add v2.3.0
tag which has v2/go.mod
file and use /v2
suffing in go.mod
Could you please fix it? :) Thank you
Hello,
can you please release this project as a binary? or a Docker image. Since most tftp servers out there are not very beginner friendly.
Thanks,
I was just playing around with your library and ran into a small issue when using the default tftp program in OS X 10.10.3. It looks like there is a \x00 byte that gets passed into the filename parameter, which causes a read error if you attempt to do an os.Open(filename) in a tftp ReadHandler.
I fixed this just by stripping the \x00 from the RQ in my fork -- I'll submit a PR for it if you'd like.
Also, my vim setup runs "go fmt" on save and I noticed it hadn't been run on this repo. I fixed that in a separate commit.
If the inbound connections are bound a specific interface (wlan0 vs eth0), how can I instruct the outbound connections to also be bound to this interface?
Thanks for your contribution.
Hi! Thanks for this package. For it to be properly consumable from gb, it would be great if you could create a v1.0.0
or similar tag on this package (and then continue doing so when making new releases :).
(Background, if you like: http://dave.cheney.net/2016/06/24/gophers-please-tag-your-releases)
Thanks for the library! I've probably a stupid question. How can I close a client connection to a server? The expected close function is not exported.
There have been multiple commits to master since 2.1.0 was released in 2016. Is it possible to cut another one? If it's not backwards compatible, then it could require a major version bump to 3.
Thanks
If a TFTP client broadcasts a request (destination IP 255.255.255.255) the reply packet must not use 255.255.255.255 as source IP but use a valid host IP as source.
There is already a pending pull request that seem to solve this issue. Kindly consider merging this.
Thank you for developing such a package.
I'm using it in my project,but I don't know how to get the sent bytes in real time
Both reader and writer should close file handles. Cheers!
Hi,
Just making an issue to inform you that I have packaged tftp for Fedora and requested it be reviewed for approval, and someone has done that. (Ref: Bugzilla#2189641)
If all goes well and further necessary steps are taken, tftp will be in the next release of Fedora, i.e., Fedora 39 which will be released in October, 2023.
The tftp package in Fedora will be named: golang-github-pin-tftp-3
it is passed when the server and the client are all on the same machine.
but other situation,such as between the real machine and the virtual machine, it can't work, and the error returned are:
the client(when send file):
read udp [::]:57470: i/o timeout
the server:
read udp [::]:38673: i/o timeout
read udp [::]:40223: i/o timeout
read udp [::]:34300: i/o timeout
...
and the other question
what's the effect of the parameter filename
of func (c Client) Send(filename string, mode string) (io.ReaderFrom, error)
?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.