0

Regarding the RFC of TFTP (Trivial File Transfer Protocol), the RRQ/WRQ (Read\write requests) packet has this format:

    2 bytes     string    1 byte     string   1 byte
    ------------------------------------------------
    | Opcode |  Filename  |   0  |    Mode    |   0 |
    ------------------------------------------------

Mode can be either "netascii", "octet" (equivalent to binary) or "mail". The thing is netascii is 8 letters, octet has 5 and mail has 4.

I am creating my packet in my client like this:

paq = struct.pack('!H'+str(len(fileName))+'sB'+str(len(mode))+'sB', 02, fileName, 0, mode, 0)

And then I send the packet to the server so the server knows what to expect (A read in case of an RRQ or a write otherwise).

The thing is, I don't know how to unpack the packet if I don't know the string lengths on the server's side... Only the client knows the file length and the mode length, since he makes the packet.

Should I send the lengths to the server before the RRQ/WRQ packet so I know the format to use when unpacking? Is there another way?

Thank you!

yuvalm2
  • 866
  • 2
  • 10
  • 27
xBurnsed
  • 410
  • 4
  • 12
  • The strings are terminated by a `0` byte. Search for that byte and then extract the string up to it. – Barmar May 22 '18 at 21:04
  • You can't use `unpack()` to extract the fields, except for the Opcode. – Barmar May 22 '18 at 21:05
  • Are you sure the mode is `binari`? I'd expect it to be `binary`, since the designers of TFTP spoke English. – Barmar May 22 '18 at 21:06
  • @Barmar actually there are three modes which are "netascii", "octet" (equivalent to binary), and "mail". Problem still the same.. different lenghts. How would you extract the string until it finds a 0? – xBurnsed May 22 '18 at 21:14
  • If the packet is in `p`, `p[2:p.find('\0')]` is the filename – Barmar May 22 '18 at 21:18

1 Answers1

1

If the received packet is in the byte array p, you can search for the 0 delimiters with find().

opcode = p[0:2].decode('ASCII')
nameEnd = p.find(b'\0', start=2)
filename = p[2:nameEnd].decode('ASCII')
modeEnd = p.find(b'\0', start=nameEnd+1)
mode = p[nameEnd+1:modeEnd].decode('ASCII')
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Thanks a lot! I really appreciate it! I knew how to use the packet[ : ] thing but I didn't know it could be combined with .find() method! I really appreciate your help! – xBurnsed May 22 '18 at 21:30
  • Why wouldn't you be able to combine it with `find()`? It's just numbers, it doesn't matter how you get the numbers. – Barmar May 22 '18 at 21:32