Blame


1 f3a795ae 2021-08-03 op These days I’m hacking on 9P. In case you don’t know, 9P is a protocol for a network file system that was developed as part of the plan9 operating system.
2 f3a795ae 2021-08-03 op
3 f3a795ae 2021-08-03 op Now, to make it clear, I’ve never — sigh! — used 9P nor plan9 before. I’m just starting to explore the 9P protocol, hacking something together (for a secret project), and writing some notes here on my blog.
4 f3a795ae 2021-08-03 op
5 f3a795ae 2021-08-03 op If you find some errors please be kind and notify me. The contacts are at the end of every entry in the Gemini version of this blog.
6 f3a795ae 2021-08-03 op
7 f3a795ae 2021-08-03 op The 9P protocol is pretty simple: the client sends requests (called T-messages) and the server replies (with R-messages). Replies can be delayed or received out of order. A transaction of some type is completed when the server replies with the matching R-message (or with an error).
8 f3a795ae 2021-08-03 op
9 f3a795ae 2021-08-03 op I’m going to use the same syntax used in the plan9 manpages to describe the packets. Fields are written as name[n] where ‘name’ represents the name of the field and ‘n’ (which is either 1, 2, 4, 8 or 13) represents the number of byte. An exception to this rule are strings and other variable-width fields: they are represented by a two-byte integer counter followed by the actual data. Strings in particular are denoted as name[s] (where ‘s’ is a literal s character.)
10 f3a795ae 2021-08-03 op
11 f3a795ae 2021-08-03 op Integers are transmitted in little-endian format, and strings are encoded in UTF-8 without the NUL-terminator. The NUL byte is illegal in strings transmitted over 9P and thus excluded by paths, user login names etc.
12 f3a795ae 2021-08-03 op
13 f3a795ae 2021-08-03 op Both the requests and the replies share a common structure, the header, which looks like this
14 f3a795ae 2021-08-03 op
15 f3a795ae 2021-08-03 op ``` 9P header
16 f3a795ae 2021-08-03 op size[4] type[1] tag[2]
17 f3a795ae 2021-08-03 op ```
18 f3a795ae 2021-08-03 op
19 f3a795ae 2021-08-03 op Size, the first field, is a 32 bit field that indicates the length of the message (including ‘size’ itself!). Type is a one-byte integer that specifies the type of the requests and tag is an arbitrary client-chosen integer that uniquely represents this transaction. The client cannot issue two or more ongoing transaction with the same tag.
20 f3a795ae 2021-08-03 op
21 f3a795ae 2021-08-03 op Following the header there is an optional body whose structure depends on the type of message.
22 f3a795ae 2021-08-03 op
23 f3a795ae 2021-08-03 op Clients can only send T-messages, and the server can only reply with a R-message.
24 f3a795ae 2021-08-03 op
25 f3a795ae 2021-08-03 op The available messages are:
26 f3a795ae 2021-08-03 op
27 f3a795ae 2021-08-03 op * Tversion/Rversion
28 f3a795ae 2021-08-03 op * Tauth/Rauth
29 f3a795ae 2021-08-03 op * Rerror (Terror does not exist)
30 f3a795ae 2021-08-03 op * Tflush/Rflush
31 f3a795ae 2021-08-03 op * Tattach/Rattach
32 f3a795ae 2021-08-03 op * Twalk/Rwalk
33 f3a795ae 2021-08-03 op * Topen/Ropen
34 f3a795ae 2021-08-03 op * Tcreate/Rcreate
35 f3a795ae 2021-08-03 op * Tread/Rread
36 f3a795ae 2021-08-03 op * Twrite/Rwrite
37 f3a795ae 2021-08-03 op * Tclunk/Rclunk
38 f3a795ae 2021-08-03 op * Tremove/Rremove
39 f3a795ae 2021-08-03 op * Tstat/Rstat
40 f3a795ae 2021-08-03 op * Twstat/Rwstat
41 f3a795ae 2021-08-03 op
42 f3a795ae 2021-08-03 op There are some extension (or “dialects” should I say) of 9P which adds (and slightly change) these messages, but at least for now I’m trying to stick to 9P2000 “vanilla”.
43 f3a795ae 2021-08-03 op
44 f3a795ae 2021-08-03 op An important role in 9P is played by “qid”s and “fid”s. A fid is a 32bit integer chosen by the client that identifies a “current file” on the server. They are similar, albeit different, to UNIX file descriptors. Qids are the server idea of a file: they are a jumbo object of a whopping 13 bytes: the first one identifies the type (whether is a file, directory, and so on), a four byte integer unique among all files in the hierarchy called “path” and a four byte “version” field that should get incremented every time the file is modified.
45 f3a795ae 2021-08-03 op
46 f3a795ae 2021-08-03 op Fids are often present in T-messages and qids in R-messages.
47 f3a795ae 2021-08-03 op
48 f3a795ae 2021-08-03 op The first message that a client should issue after it has established a connection to a file server is Tversion to negotiate the version used and the maximum size of the packets. The Tversion signature is
49 f3a795ae 2021-08-03 op
50 f3a795ae 2021-08-03 op ```
51 f3a795ae 2021-08-03 op size[4] Tversion tag[2] msize[4] version[s]
52 f3a795ae 2021-08-03 op ```
53 f3a795ae 2021-08-03 op
54 f3a795ae 2021-08-03 op (from now on I’ll omit the three header fields when describing the structure of a packet)
55 f3a795ae 2021-08-03 op
56 f3a795ae 2021-08-03 op The msize is the maximum size of a packet that the client is willing to accept, and the version is a string the identifies the protocol version used. It MUST start with the “9P” characters. The client can’t issue further requests until the server replies with a Rversion, which has the same structure. The msize replied by the server has to be smaller or equal to the one proposed by the client.
57 f3a795ae 2021-08-03 op
58 f3a795ae 2021-08-03 op Then there is an optional authentication using Tauth. I’m not interested in how “normal” authentication works in 9P in my project (for now at least), but the idea is that the server provides to the client a special “authentication file” that an unauthenticated client can read and write to. This is used to implement a custom auth protocol which is external to 9P.
59 f3a795ae 2021-08-03 op
60 f3a795ae 2021-08-03 op At this point the client can “attach” a file tree using Tattach:
61 f3a795ae 2021-08-03 op
62 f3a795ae 2021-08-03 op ```
63 f3a795ae 2021-08-03 op fid[4] afid[4] uname[s] aname[s]
64 f3a795ae 2021-08-03 op ```
65 f3a795ae 2021-08-03 op
66 f3a795ae 2021-08-03 op If successful, fid will represent the file tree accessed by aname. ‘afid’ is the authentication fid, which can be -1 (i.e. 0xFFFFFFFF) for the no-authentication case. ‘uname’ is the user name.
67 f3a795ae 2021-08-03 op
68 f3a795ae 2021-08-03 op If successful, the client has access to a file tree and can start moving around (by means of Twalk) and messing with files (Topen, Tremove, …). This is also all for the introduction: future entries will focus in particular about the other kinds of messages.