tftp.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Copyright 2019 Yunion
  15. // Copyright 2016 Google Inc.
  16. //
  17. // Licensed under the Apache License, Version 2.0 (the "License");
  18. // you may not use this file except in compliance with the License.
  19. // You may obtain a copy of the License at
  20. //
  21. // http://www.apache.org/licenses/LICENSE-2.0
  22. //
  23. // Unless required by applicable law or agreed to in writing, software
  24. // distributed under the License is distributed on an "AS IS" BASIS,
  25. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  26. // See the License for the specific language governing permissions and
  27. // limitations under the License.
  28. // Package tftp implements a read-only TFTP server.
  29. package tftp
  30. import (
  31. "bytes"
  32. "encoding/binary"
  33. "errors"
  34. "fmt"
  35. "io"
  36. "net"
  37. "strconv"
  38. "time"
  39. )
  40. const (
  41. // DefaultWriteTimeout is the duration a client has to acknowledge
  42. // a data packet from the server. This can be overridden by
  43. // setting Server.WriteTimeout.
  44. DefaultWriteTimeout = 2 * time.Second
  45. // DefaultWriteAttempts is the maximum number of times a single
  46. // packet will be (re)sent before timing out a client. This can be
  47. // overridden by setting Server.WriteAttempts.
  48. DefaultWriteAttempts = 5
  49. // DefaultBlockSize is the maximum block size used to send data to
  50. // clients. The server will respect a request for a smaller block
  51. // size, but requests for larger block sizes will be clamped to
  52. // DefaultBlockSize. This can be overridden by setting
  53. // Server.MaxBlockSize.
  54. DefaultBlockSize = 1450
  55. // maxErrorSize is the largest error message string that will be
  56. // sent to the client without truncation.
  57. maxErrorSize = 500
  58. )
  59. // A Handler provides bytes for a file.
  60. //
  61. // If size is non-zero, it must be equal to the number of bytes in
  62. // file. The server will offer the "tsize" extension to clients that
  63. // request it.
  64. //
  65. // Note that some clients (particularly firmware TFTP clients) can be
  66. // very capricious about servers not supporting all the options that
  67. // they request, so passing a size of 0 may cause TFTP transfers to
  68. // fail for some clients.
  69. type Handler func(path string, clientAddr net.Addr) (file io.ReadCloser, size int64, err error)
  70. // A Server defines parameters for running a TFTP server.
  71. type Server struct {
  72. Handler Handler // handler to invoke for requests
  73. // WriteTimeout sets the duration to wait for the client to
  74. // acknowledge a data packet. Defaults to DefaultWriteTimeout.
  75. WriteTimeout time.Duration
  76. // WriteAttempts sets how many times a packet will be (re)sent
  77. // before timing out the client and aborting the transfer. If 0,
  78. // uses DefaultWriteAttempts.
  79. WriteAttempts int
  80. // MaxBlockSize sets the maximum block size used for file
  81. // transfers. If 0, uses DefaultBlockSize.
  82. MaxBlockSize int64
  83. // InfoLog specifies an optional logger for informational
  84. // messages. If nil, informational messages are suppressed.
  85. InfoLog func(msg string)
  86. // TransferLog specifies an optional logger for completed
  87. // transfers. A successful transfer is logged with err == nil. If
  88. // nil, transfer logs are suppressed.
  89. TransferLog func(clientAddr net.Addr, path string, err error)
  90. // Dial specifies a function to use when setting up a "connected"
  91. // UDP socket to a TFTP client. While this is mostly here for
  92. // testing, it can also be used to implement advanced relay
  93. // functionality (e.g. serving TFTP through SOCKS). If nil,
  94. // net.Dial is used.
  95. Dial func(network, addr string) (net.Conn, error)
  96. }
  97. // ListenAndServe listens on the UDP network address addr and then
  98. // calls Serve to handle TFTP requests. If addr is blank, ":69" is
  99. // used.
  100. func (s *Server) ListenAndServe(addr string) error {
  101. if addr == "" {
  102. addr = ":69"
  103. }
  104. l, err := net.ListenPacket("udp", addr)
  105. if err != nil {
  106. return err
  107. }
  108. defer l.Close()
  109. s.infoLog("TFTP listening on %s", l.LocalAddr())
  110. return s.Serve(l)
  111. }
  112. // Serve accepts requests on listener l, creating a new transfer
  113. // goroutine for each. The transfer goroutines use s.Handler to get
  114. // bytes, and transfers them to the client.
  115. func (s *Server) Serve(l net.PacketConn) error {
  116. if s.Handler == nil {
  117. return errors.New("can't serve, Handler is nil")
  118. }
  119. if err := l.SetDeadline(time.Time{}); err != nil {
  120. return err
  121. }
  122. buf := make([]byte, 2048)
  123. for {
  124. n, addr, err := l.ReadFrom(buf)
  125. if err != nil {
  126. return err
  127. }
  128. req, err := parseRRQ(buf[:n])
  129. if err != nil {
  130. s.infoLog("bad request from %q: %s", addr, err)
  131. continue
  132. }
  133. go s.transferAndLog(addr, req)
  134. }
  135. }
  136. func (s *Server) infoLog(msg string, args ...interface{}) {
  137. if s.InfoLog != nil {
  138. s.InfoLog(fmt.Sprintf(msg, args...))
  139. }
  140. }
  141. func (s *Server) transferLog(addr net.Addr, path string, err error) {
  142. if s.TransferLog != nil {
  143. s.TransferLog(addr, path, err)
  144. }
  145. }
  146. func (s *Server) transferAndLog(addr net.Addr, req *rrq) {
  147. err := s.transfer(addr, req)
  148. if err != nil {
  149. err = fmt.Errorf("%q: %s", addr, err)
  150. }
  151. s.transferLog(addr, req.Filename, err)
  152. }
  153. func (s *Server) transfer(addr net.Addr, req *rrq) error {
  154. d := s.Dial
  155. if d == nil {
  156. d = net.Dial
  157. }
  158. conn, err := d("udp", addr.String())
  159. if err != nil {
  160. return fmt.Errorf("creating socket: %s", err)
  161. }
  162. defer conn.Close()
  163. file, size, err := s.Handler(req.Filename, addr)
  164. if err != nil {
  165. conn.Write(tftpError("failed to get file"))
  166. return fmt.Errorf("getting file bytes: %s", err)
  167. }
  168. defer file.Close()
  169. var b bytes.Buffer
  170. if req.BlockSize != 0 || (req.WantSize && size != 0) {
  171. // Client requested options, need to OACK them before sending
  172. // data.
  173. b.WriteByte(0)
  174. b.WriteByte(6)
  175. if req.BlockSize != 0 {
  176. maxBlockSize := s.MaxBlockSize
  177. if maxBlockSize <= 0 {
  178. maxBlockSize = DefaultBlockSize
  179. }
  180. if req.BlockSize > maxBlockSize {
  181. s.infoLog("clamping blocksize to %q: %d -> %d", addr, req.BlockSize, maxBlockSize)
  182. req.BlockSize = maxBlockSize
  183. }
  184. b.WriteString("blksize")
  185. b.WriteByte(0)
  186. b.WriteString(strconv.FormatInt(req.BlockSize, 10))
  187. b.WriteByte(0)
  188. }
  189. if req.WantSize && size != 0 {
  190. b.WriteString("tsize")
  191. b.WriteByte(0)
  192. b.WriteString(strconv.FormatInt(size, 10))
  193. b.WriteByte(0)
  194. }
  195. if err := s.send(conn, b.Bytes(), 0); err != nil {
  196. return fmt.Errorf("sending OACK: %s", err)
  197. }
  198. b.Reset()
  199. }
  200. if req.BlockSize == 0 {
  201. // Client didn't negotiate, use classic blocksize from RFC.
  202. req.BlockSize = 512
  203. }
  204. seq := uint16(1)
  205. b.Grow(int(req.BlockSize + 4))
  206. b.WriteByte(0)
  207. b.WriteByte(3)
  208. for {
  209. b.Truncate(2)
  210. if err = binary.Write(&b, binary.BigEndian, seq); err != nil {
  211. conn.Write(tftpError("internal server error"))
  212. return fmt.Errorf("writing seqnum: %s", err)
  213. }
  214. n, err := io.CopyN(&b, file, req.BlockSize)
  215. if err != nil && err != io.EOF {
  216. conn.Write(tftpError("internal server error"))
  217. return fmt.Errorf("reading bytes for block %d: %s", seq, err)
  218. }
  219. if err = s.send(conn, b.Bytes(), seq); err != nil {
  220. conn.Write(tftpError("timeout"))
  221. return fmt.Errorf("sending data packet %d: %s", seq, err)
  222. }
  223. seq++
  224. if n < req.BlockSize {
  225. // Transfer complete
  226. return nil
  227. }
  228. }
  229. }
  230. func (s *Server) send(conn net.Conn, b []byte, seq uint16) error {
  231. timeout := s.WriteTimeout
  232. if timeout <= 0 {
  233. timeout = DefaultWriteTimeout
  234. }
  235. attempts := s.WriteAttempts
  236. if attempts <= 0 {
  237. attempts = DefaultWriteAttempts
  238. }
  239. Attempt:
  240. for attempt := 0; attempt < attempts; attempt++ {
  241. if _, err := conn.Write(b); err != nil {
  242. return err
  243. }
  244. conn.SetReadDeadline(time.Now().Add(timeout))
  245. var recv [256]byte
  246. for {
  247. n, err := conn.Read(recv[:])
  248. if err != nil {
  249. if t, ok := err.(net.Error); ok && t.Timeout() {
  250. continue Attempt
  251. }
  252. return err
  253. }
  254. if n < 4 { // packet too small
  255. continue
  256. }
  257. switch binary.BigEndian.Uint16(recv[:2]) {
  258. case 4:
  259. if binary.BigEndian.Uint16(recv[2:4]) == seq {
  260. return nil
  261. }
  262. case 5:
  263. msg, _, _ := tftpStr(recv[4:])
  264. return fmt.Errorf("client aborted transfer: %s", msg)
  265. }
  266. }
  267. }
  268. return errors.New("timeout waiting for ACK")
  269. }
  270. type rrq struct {
  271. Filename string
  272. BlockSize int64
  273. WantSize bool
  274. }
  275. func parseRRQ(bs []byte) (*rrq, error) {
  276. // Smallest a useful TFTP packet can be is 6 bytes: 2b opcode, 1b
  277. // filename, 1b null, 1b mode, 1b null.
  278. if len(bs) < 6 || binary.BigEndian.Uint16(bs[:2]) != 1 {
  279. return nil, errors.New("not an RRQ packet")
  280. }
  281. fname, bs, err := tftpStr(bs[2:])
  282. if err != nil {
  283. return nil, fmt.Errorf("reading filename: %s", err)
  284. }
  285. mode, bs, err := tftpStr(bs)
  286. if err != nil {
  287. return nil, fmt.Errorf("reading mode: %s", err)
  288. }
  289. if mode != "octet" {
  290. // Only support octet mode, because in practice that's the
  291. // only remaining sensible use of TFTP (i.e. PXE booting)
  292. return nil, fmt.Errorf("unsupported transfer mode %q", mode)
  293. }
  294. req := &rrq{
  295. Filename: fname,
  296. }
  297. for len(bs) > 0 {
  298. opt, rest, err := tftpStr(bs)
  299. if err != nil {
  300. return nil, fmt.Errorf("reading option name: %s", err)
  301. }
  302. bs = rest
  303. val, rest, err := tftpStr(bs)
  304. if err != nil {
  305. return nil, fmt.Errorf("reading option %q value: %s", opt, err)
  306. }
  307. bs = rest
  308. if opt != "blksize" {
  309. if opt == "tsize" {
  310. req.WantSize = true
  311. }
  312. continue
  313. }
  314. size, err := strconv.ParseInt(val, 10, 64)
  315. if err != nil {
  316. return nil, fmt.Errorf("non-integer block size value %q", val)
  317. }
  318. if size < 8 || size > 65464 {
  319. return nil, fmt.Errorf("unsupported block size %q", size)
  320. }
  321. req.BlockSize = size
  322. }
  323. return req, nil
  324. }
  325. // tftpError constructs an ERROR packet.
  326. //
  327. // The error is coerced to the sensible subset of "netascii", namely
  328. // the printable ASCII characters plus newline.
  329. func tftpError(msg string) []byte {
  330. if len(msg) > maxErrorSize {
  331. msg = msg[:maxErrorSize]
  332. }
  333. var ret bytes.Buffer
  334. ret.Grow(len(msg) + 5)
  335. ret.Write([]byte{0, 5, 0, 0}) // generic "see message" error packet
  336. for _, b := range msg {
  337. switch {
  338. case b >= 0x20 && b <= 0x7E:
  339. ret.WriteRune(b)
  340. case b == '\r':
  341. // Assume this is the start of a CRLF sequence and just
  342. // swallow the CR. The LF will output CRLF, see
  343. // below. Also, please stop using CRLF line termination in
  344. // Go.
  345. case b == '\n':
  346. ret.WriteString("\r\n")
  347. default:
  348. ret.WriteByte('?')
  349. }
  350. }
  351. ret.WriteByte(0)
  352. return ret.Bytes()
  353. }
  354. // tftpStr extracts a null-terminated string from the given bytes, and
  355. // returns any remaining bytes.
  356. //
  357. // String content is checked to be a "read-useful" subset of
  358. // "netascii", itself a subset of ASCII. Specifically, all byte values
  359. // must fall in the range 0x20 to 0x7E inclusive.
  360. func tftpStr(bs []byte) (str string, remaining []byte, err error) {
  361. for i, b := range bs {
  362. if b == 0 {
  363. return string(bs[:i]), bs[i+1:], nil
  364. } else if b < 0x20 || b > 0x7E {
  365. return "", nil, fmt.Errorf("invalid netascii byte %q at offset %d", b, i)
  366. }
  367. }
  368. return "", nil, errors.New("no null terminated string found")
  369. }