summaryrefslogtreecommitdiff
path: root/lib9p/idl/1992-9P0.9p.wip
blob: 086e8e457797edcbbc0170eb11742af853520917 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# lib9p/idl/1992-9P0.9p - Definitions of 9P0 (Plan 9 1st ed) messages
#
# Copyright (C) 2024-2025  Luke T. Shumaker <lukeshu@lukeshu.com>
# SPDX-License-Identifier: AGPL-3.0-or-later

# The original 9P protocol ("9P0"), from Plan 9 1st edition.
#
# Documentation:
# - https://github.com/plan9foundation/plan9/tree/1e-1993-01-03/sys/man/5
# - https://github.com/plan9foundation/plan9/tree/1e-1993-01-03/sys/man/6/auth
# - https://man.cat-v.org/plan_9_1st_ed/5/
# - https://man.cat-v.org/plan_9_1st_ed/6/auth
#
# Implementation references:
# - https://github.com/plan9foundation/plan9/blob/1e-1993-01-03/sys/include/fcall.h (MAXFDATA)
# - https://github.com/plan9foundation/plan9/blob/1e-1993-01-03/sys/include/libc.h (`ch` bits)
# - https://github.com/plan9foundation/plan9/blob/1e-1993-01-03/sys/src/fs/port/fcall.c (`stat`)
# - https://github.com/plan9foundation/plan9/blob/1e-1993-01-03/sys/src/fs/port/fs.c (`offset:max`)
# - https://github.com/plan9foundation/plan9/blob/1e-1993-01-03/sys/src/fs/port/portdata.h (MAXDAT)
version "9P0"

# tag - identify a request/response pair
num tag = 2

# file identifier - like a UNIX file-descriptor
num fid = 2

# uni"Q"ue "ID"entification
struct qid = "path[4] version[4]"

# a nul-terminated+padded string
struct name = "28*(txt[1])"

# a nul-terminated+padded string
struct errstr = "64*(txt[1])"

# "O"pen flags (flags to pass to Topen and Tcreate)
# Unused bits are *ignored*.
bitfield o = 1
	"0=mode_0" # low bit of the 2-bit READ/WRITE/RDWR/EXEC enum
	"1=mode_1" # high bit of the 2-bit READ/WRITE/RDWR/EXEC enum
	#"2=unused"
	#"3=unused"
	"4=TRUNC"
	#"5=_reserved_CEXEC" # close-on-exec
	"6=RCLOSE" # remove-on-close
	#"7=unused"

	"READ  = 0" # make available for this FID: Tread()
	"WRITE = 1" # make available for this FID: Twrite()
	"RDWR  = 2" # make available for this FID: Tread() and Twrite()
	"EXEC  = 3" # make available for this FID: Tread()

	"MODE_MASK = 0b00000011"
	"FLAG_MASK = 0b11111100"

# "C"??? "H"??? - file permissions and attributes
bitfield ch = 4
	"31=DIR"
	"30=APPEND"
	"29=EXCL"
	#...
	"8=OWNER_R"
	"7=OWNER_W"
	"6=OWNER_X"
	"5=GROUP_R"
	"4=GROUP_W"
	"3=GROUP_X"
	"2=OTHER_R"
	"1=OTHER_W"
	"0=OTHER_X"

	"PERM_MASK=0777" # {OWNER,GROUP,OTHER}_{R,W,X}

struct stat = "file_name[name]"
              "file_owner[name]"
              "file_group[name]"
              "file_qid[qid]"
              "file_mode[ch]"
              "file_atime[4]"
              "file_mtime[4]"
              "file_size[8]"
              "kern_type[2]"
              "kern_dev[2]"

# Authentication uses symetric-key encryption, using a per-client
# secret-key.  The encryption scheme is beyond the scope of this
# document.
struct auth_ticket = "15*(dat[1])"
struct encrypted_auth_challenge = "36*(ciphertext[1])"
struct cleartext_auth_challenge = "magic[1,val=1] 7*(client_challenge[1]) server[name]"
struct encrypted_auth_response = "30*(ciphertext[1])"
struct cleartext_auth_response = "magic[1,val=4] 7*(client_challenge[1]) ticket[auth_ticket]"

# A 9P0 session goes:
#
#    [nop()]
#    session()
#    [auth_tok=auth()]
#    attach([auth_tok])
#    ...

msg Tmux      = "typ[1,val=48] mux[2]" # Undocumented, but implemented by mux(3) / libmux.a
#msg Rmux      = "typ[1,val=49] illegal"
msg Tnop      = "typ[1,val=50] tag[tag,val=0xFFFF]"
msg Rnop      = "typ[1,val=51] tag[tag,val=0xFFFF]"
msg Tsession  = "typ[1,val=52] tag[tag,val=0xFFFF]"
msg Rsession  = "typ[1,val=53] tag[tag,val=0xFFFF]"
#msg Terror    = "typ[1,val=54] illegal"
msg Rerror    = "typ[1,val=55] tag[tag] ename[errstr]"
msg Tflush    = "typ[1,val=56] tag[tag] oldtag[tag]"
msg Rflush    = "typ[1,val=57] tag[tag]"
msg Tattach   = "typ[1,val=58] tag[tag] fid[fid] uid[name] aname[name] auth[auth_ticket] 13*(pad[1])" # Pad to allow auth_tickets up to 28 bytes.
msg Rattach   = "typ[1,val=59] tag[tag] fid[fid] qid[qid]"
msg Tclone    = "typ[1,val=60] tag[tag] fid[fid] newfid[fid]"
msg Rclone    = "typ[1,val=61] tag[tag] fid[fid]"
msg Twalk     = "typ[1,val=62] tag[tag] fid[fid] name[name]"
msg Rwalk     = "typ[1,val=63] tag[tag] fid[fid] qid[qid]"
msg Topen     = "typ[1,val=64] tag[tag] fid[fid] mode[o]"
msg Ropen     = "typ[1,val=65] tag[tag] fid[fid] qid[qid]"
msg Tcreate   = "typ[1,val=66] tag[tag] fid[fid] name[name] perm[ch] mode[o]"
msg Rcreate   = "typ[1,val=67] tag[tag] fid[fid] qid[qid]"
# For `count:max`, see 1e/2e/3e `sys/include/fcall.h:MAXFDATA` or 1e/2e `sys/src/fs/port/portdata.h:MAXDAT`.
# For read `offset:max`, see 1e/2e/3e `sys/src/fs/port/fs.c:f_read()` or 3e `sys/src/lib9p/srv.c:srv():case Tread`.
# For write `offset:max`, see 1e/2e/3e `sys/src/fs/port/fs.c:f_write()`.
msg Tread     = "typ[1,val=68] tag[tag] fid[fid] offset[8,max=s64_max] count[2,max=8192]"
msg Rread     = "typ[1,val=69] tag[tag] fid[fid] count[2,max=8192] pad[1] count*(data[1])"
msg Twrite    = "typ[1,val=70] tag[tag] fid[fid] offset[8,max=s64_max] count[2,max=8192] pad[1] count*(data[1])"
msg Rwrite    = "typ[1,val=71] tag[tag] fid[fid] count[2,max=8192]"
msg Tclunk    = "typ[1,val=72] tag[tag] fid[fid]"
msg Rclunk    = "typ[1,val=73] tag[tag] fid[fid]"
msg Tremove   = "typ[1,val=74] tag[tag] fid[fid]"
msg Rremove   = "typ[1,val=75] tag[tag] fid[fid]"
msg Tstat     = "typ[1,val=76] tag[tag] fid[fid]"
msg Rstat     = "typ[1,val=77] tag[tag] fid[fid] stat[stat]"
msg Twstat    = "typ[1,val=78] tag[tag] fid[fid] stat[stat]"
msg Rwstat    = "typ[1,val=79] tag[tag] fid[fid]"
msg Tclwalk   = "typ[1,val=80] tag[tag] fid[fid] newfid[fid] name[name]"
msg Rclwalk   = "typ[1,val=81] tag[tag] fid[fid] qid[qid]"
msg Tauth     = "typ[1,val=82] tag[tag] fid[fid] uid[name] chal[encrypted_auth_challenge]" # chal is an encrypted
msg Rauth     = "typ[1,val=83] tag[tag] fid[fid] chal[encrypted_auth_response]"