Blame


1 8d1b399b 2021-07-22 op /*
2 8d1b399b 2021-07-22 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
3 8d1b399b 2021-07-22 op *
4 8d1b399b 2021-07-22 op * Permission to use, copy, modify, and distribute this software for any
5 8d1b399b 2021-07-22 op * purpose with or without fee is hereby granted, provided that the above
6 8d1b399b 2021-07-22 op * copyright notice and this permission notice appear in all copies.
7 8d1b399b 2021-07-22 op *
8 8d1b399b 2021-07-22 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 8d1b399b 2021-07-22 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 8d1b399b 2021-07-22 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 8d1b399b 2021-07-22 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 8d1b399b 2021-07-22 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 8d1b399b 2021-07-22 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 8d1b399b 2021-07-22 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 8d1b399b 2021-07-22 op */
16 8d1b399b 2021-07-22 op
17 8d1b399b 2021-07-22 op #include "compat.h"
18 8d1b399b 2021-07-22 op
19 c5d518da 2021-07-29 op #include <sys/stat.h>
20 c5d518da 2021-07-29 op
21 23e03c88 2021-07-26 op #include <endian.h>
22 8d1b399b 2021-07-22 op #include <errno.h>
23 c5d518da 2021-07-29 op #include <fcntl.h>
24 8d1b399b 2021-07-22 op #include <pwd.h>
25 8d1b399b 2021-07-22 op #include <signal.h>
26 8d1b399b 2021-07-22 op #include <stdlib.h>
27 8d1b399b 2021-07-22 op #include <string.h>
28 8d1b399b 2021-07-22 op #include <syslog.h>
29 8d1b399b 2021-07-22 op #include <unistd.h>
30 8d1b399b 2021-07-22 op
31 8d1b399b 2021-07-22 op #include "client.h"
32 8d1b399b 2021-07-22 op #include "kamid.h"
33 8d1b399b 2021-07-22 op #include "log.h"
34 8d1b399b 2021-07-22 op #include "sandbox.h"
35 23e03c88 2021-07-26 op #include "utils.h"
36 e0dce04c 2021-07-30 op
37 2adb951f 2021-08-01 op #define DEBUG_PACKETS 0
38 8d1b399b 2021-07-22 op
39 c5d518da 2021-07-29 op STAILQ_HEAD(qidhead, qid) qids;
40 c5d518da 2021-07-29 op struct qid {
41 c5d518da 2021-07-29 op /* definition of a qid */
42 c5d518da 2021-07-29 op uint64_t path;
43 c5d518da 2021-07-29 op uint32_t vers;
44 c5d518da 2021-07-29 op uint8_t type;
45 c5d518da 2021-07-29 op
46 c5d518da 2021-07-29 op int fd;
47 c377c1b9 2021-07-30 op int refcount;
48 c5d518da 2021-07-29 op
49 053e2652 2021-08-01 op char fpath[PATH_MAX];
50 1c08fc54 2021-08-01 op struct stat sb;
51 1c08fc54 2021-08-01 op
52 c5d518da 2021-07-29 op STAILQ_ENTRY(qid) entries;
53 c5d518da 2021-07-29 op };
54 c5d518da 2021-07-29 op
55 c5d518da 2021-07-29 op STAILQ_HEAD(fidhead, fid) fids;
56 c5d518da 2021-07-29 op struct fid {
57 c5d518da 2021-07-29 op uint32_t fid;
58 1c08fc54 2021-08-01 op int iomode;
59 c5d518da 2021-07-29 op struct qid *qid;
60 c5d518da 2021-07-29 op STAILQ_ENTRY(fid) entries;
61 c5d518da 2021-07-29 op };
62 c5d518da 2021-07-29 op
63 8d1b399b 2021-07-22 op static struct imsgev *iev_listener;
64 2ef72ade 2021-07-28 op static struct evbuffer *evb;
65 2ef72ade 2021-07-28 op static uint32_t peerid;
66 8d1b399b 2021-07-22 op
67 5c420a81 2021-07-30 op static int handshaked, attached;
68 5c485996 2021-07-28 op uint32_t msize;
69 5c485996 2021-07-28 op
70 06a84967 2021-07-22 op static ATTR_DEAD void client_shutdown(void);
71 8d1b399b 2021-07-22 op static void client_sig_handler(int, short, void *);
72 8d1b399b 2021-07-22 op static void client_dispatch_listener(int, short, void *);
73 8d1b399b 2021-07-22 op static void client_privdrop(const char *, const char *);
74 8d1b399b 2021-07-22 op
75 2ef72ade 2021-07-28 op static int client_send_listener(int, const void *, uint16_t);
76 5c485996 2021-07-28 op
77 053e2652 2021-08-01 op static void qid_set_from_sb(struct qid *);
78 1c08fc54 2021-08-01 op static int qid_update_stat(struct qid *);
79 053e2652 2021-08-01 op static struct qid *qid_from_copy(const struct qid *);
80 eafb23b1 2021-08-01 op static struct qid *qid_from_fd(int);
81 053e2652 2021-08-01 op static struct qid *qid_from_path(const char *);
82 c377c1b9 2021-07-30 op static struct qid *qid_incref(struct qid *);
83 c377c1b9 2021-07-30 op static void qid_decref(struct qid *);
84 c377c1b9 2021-07-30 op
85 c5d518da 2021-07-29 op static struct fid *new_fid(struct qid *, uint32_t);
86 c377c1b9 2021-07-30 op static struct fid *fid_by_id(uint32_t);
87 c377c1b9 2021-07-30 op static void free_fid(struct fid *);
88 c5d518da 2021-07-29 op
89 48192874 2021-08-01 op static void parse_message(const uint8_t *, size_t,
90 48192874 2021-08-01 op struct np_msg_header *, uint8_t **);
91 8d1b399b 2021-07-22 op
92 83f6b305 2021-08-01 op static void np_write16(uint16_t);
93 2845cccb 2021-07-29 op static void np_header(uint32_t, uint8_t, uint16_t);
94 2845cccb 2021-07-29 op static void np_string(uint16_t, const char *);
95 c5d518da 2021-07-29 op static void np_qid(struct qid *);
96 84b10f04 2021-07-29 op static void do_send(void);
97 2845cccb 2021-07-29 op
98 2845cccb 2021-07-29 op static void np_version(uint16_t, uint32_t, const char *);
99 c5d518da 2021-07-29 op static void np_attach(uint16_t, struct qid *);
100 c377c1b9 2021-07-30 op static void np_clunk(uint16_t);
101 36b30273 2021-07-30 op static void np_flush(uint16_t);
102 1c08fc54 2021-08-01 op static void np_walk(uint16_t, int, struct qid *);
103 2ef72ade 2021-07-28 op static void np_error(uint16_t, const char *);
104 c5d518da 2021-07-29 op static void np_errno(uint16_t);
105 2ef72ade 2021-07-28 op
106 48192874 2021-08-01 op static int np_read8(const char *, const char *, uint8_t *,
107 48192874 2021-08-01 op const uint8_t **, size_t *);
108 48192874 2021-08-01 op static int np_read16(const char *, const char *, uint16_t *,
109 48192874 2021-08-01 op const uint8_t **, size_t *);
110 48192874 2021-08-01 op static int np_read32(const char *, const char *, uint32_t *,
111 48192874 2021-08-01 op const uint8_t **, size_t *);
112 48192874 2021-08-01 op
113 48192874 2021-08-01 op #define READSTRERR -1
114 48192874 2021-08-01 op #define READSTRTRUNC -2
115 48192874 2021-08-01 op static int np_readstr(const char *, const char *, char *, size_t,
116 48192874 2021-08-01 op const uint8_t **, size_t *);
117 48192874 2021-08-01 op
118 48192874 2021-08-01 op #define NPREAD8(f, dst, src, len) np_read8(__func__, f, dst, src, len)
119 48192874 2021-08-01 op #define NPREAD16(f, dst, src, len) np_read16(__func__, f, dst, src, len)
120 48192874 2021-08-01 op #define NPREAD32(f, dst, src, len) np_read32(__func__, f, dst, src, len)
121 48192874 2021-08-01 op
122 48192874 2021-08-01 op #define NPREADSTR(f, b, bl, src, len) np_readstr(__func__, f, b, bl, src, len)
123 48192874 2021-08-01 op
124 e60f4e08 2021-07-30 op static void tversion(struct np_msg_header *, const uint8_t *, size_t);
125 e60f4e08 2021-07-30 op static void tattach(struct np_msg_header *, const uint8_t *, size_t);
126 c377c1b9 2021-07-30 op static void tclunk(struct np_msg_header *, const uint8_t *, size_t);
127 36b30273 2021-07-30 op static void tflush(struct np_msg_header *, const uint8_t *, size_t);
128 1c08fc54 2021-08-01 op static void twalk(struct np_msg_header *, const uint8_t *, size_t);
129 e60f4e08 2021-07-30 op static void handle_message(struct imsg *, size_t);
130 64c19d90 2021-07-30 op
131 06a84967 2021-07-22 op ATTR_DEAD void
132 8d1b399b 2021-07-22 op client(int debug, int verbose)
133 8d1b399b 2021-07-22 op {
134 8d1b399b 2021-07-22 op struct event ev_sigint, ev_sigterm;
135 8d1b399b 2021-07-22 op
136 8d1b399b 2021-07-22 op log_init(debug, LOG_DAEMON);
137 8d1b399b 2021-07-22 op log_setverbose(verbose);
138 8d1b399b 2021-07-22 op
139 8d1b399b 2021-07-22 op setproctitle("client");
140 8d1b399b 2021-07-22 op log_procinit("client");
141 8d1b399b 2021-07-22 op
142 8d1b399b 2021-07-22 op log_debug("warming up");
143 8d1b399b 2021-07-22 op
144 8d1b399b 2021-07-22 op event_init();
145 8d1b399b 2021-07-22 op
146 8d1b399b 2021-07-22 op /* Setup signal handlers */
147 8d1b399b 2021-07-22 op signal_set(&ev_sigint, SIGINT, client_sig_handler, NULL);
148 8d1b399b 2021-07-22 op signal_set(&ev_sigterm, SIGTERM, client_sig_handler, NULL);
149 8d1b399b 2021-07-22 op
150 8d1b399b 2021-07-22 op signal_add(&ev_sigint, NULL);
151 8d1b399b 2021-07-22 op signal_add(&ev_sigterm, NULL);
152 8d1b399b 2021-07-22 op
153 8d1b399b 2021-07-22 op signal(SIGPIPE, SIG_IGN);
154 8d1b399b 2021-07-22 op signal(SIGHUP, SIG_IGN);
155 8d1b399b 2021-07-22 op
156 8d1b399b 2021-07-22 op /* Setup pipe and event handler to the listener process */
157 8d1b399b 2021-07-22 op if ((iev_listener = malloc(sizeof(*iev_listener))) == NULL)
158 8d1b399b 2021-07-22 op fatal(NULL);
159 8d1b399b 2021-07-22 op
160 8d1b399b 2021-07-22 op imsg_init(&iev_listener->ibuf, 3);
161 8d1b399b 2021-07-22 op iev_listener->handler = client_dispatch_listener;
162 8d1b399b 2021-07-22 op
163 8d1b399b 2021-07-22 op /* Setup event handlers. */
164 8d1b399b 2021-07-22 op iev_listener->events = EV_READ;
165 8d1b399b 2021-07-22 op event_set(&iev_listener->ev, iev_listener->ibuf.fd,
166 8d1b399b 2021-07-22 op iev_listener->events, iev_listener->handler, iev_listener);
167 8d1b399b 2021-07-22 op event_add(&iev_listener->ev, NULL);
168 8d1b399b 2021-07-22 op
169 8d1b399b 2021-07-22 op event_dispatch();
170 8d1b399b 2021-07-22 op client_shutdown();
171 8d1b399b 2021-07-22 op }
172 8d1b399b 2021-07-22 op
173 06a84967 2021-07-22 op static ATTR_DEAD void
174 8d1b399b 2021-07-22 op client_shutdown(void)
175 8d1b399b 2021-07-22 op {
176 2ef72ade 2021-07-28 op if (evb != NULL)
177 2ef72ade 2021-07-28 op evbuffer_free(evb);
178 2ef72ade 2021-07-28 op
179 8d1b399b 2021-07-22 op msgbuf_clear(&iev_listener->ibuf.w);
180 8d1b399b 2021-07-22 op close(iev_listener->ibuf.fd);
181 8d1b399b 2021-07-22 op
182 8d1b399b 2021-07-22 op free(iev_listener);
183 8d1b399b 2021-07-22 op
184 8d1b399b 2021-07-22 op log_info("client exiting");
185 8d1b399b 2021-07-22 op exit(0);
186 8d1b399b 2021-07-22 op }
187 8d1b399b 2021-07-22 op
188 8d1b399b 2021-07-22 op static void
189 8d1b399b 2021-07-22 op client_sig_handler(int sig, short event, void *d)
190 8d1b399b 2021-07-22 op {
191 8d1b399b 2021-07-22 op /*
192 8d1b399b 2021-07-22 op * Normal signal handler rules don't apply because libevent
193 8d1b399b 2021-07-22 op * decouples for us.
194 8d1b399b 2021-07-22 op */
195 8d1b399b 2021-07-22 op
196 8d1b399b 2021-07-22 op switch (sig) {
197 8d1b399b 2021-07-22 op case SIGINT:
198 8d1b399b 2021-07-22 op case SIGTERM:
199 8d1b399b 2021-07-22 op client_shutdown();
200 8d1b399b 2021-07-22 op default:
201 8d1b399b 2021-07-22 op fatalx("unexpected signal %d", sig);
202 8d1b399b 2021-07-22 op }
203 8d1b399b 2021-07-22 op }
204 8d1b399b 2021-07-22 op
205 8d1b399b 2021-07-22 op #define AUTH_NONE 0
206 8d1b399b 2021-07-22 op #define AUTH_USER 1
207 8d1b399b 2021-07-22 op #define AUTH_DONE 2
208 8d1b399b 2021-07-22 op
209 8d1b399b 2021-07-22 op static void
210 8d1b399b 2021-07-22 op client_dispatch_listener(int fd, short event, void *d)
211 8d1b399b 2021-07-22 op {
212 8d1b399b 2021-07-22 op static int auth = AUTH_NONE;
213 8d1b399b 2021-07-22 op static char username[64] = {0};
214 8d1b399b 2021-07-22 op static char dir[PATH_MAX] = {0};
215 8d1b399b 2021-07-22 op struct imsg imsg;
216 8d1b399b 2021-07-22 op struct imsgev *iev = d;
217 8d1b399b 2021-07-22 op struct imsgbuf *ibuf;
218 8d1b399b 2021-07-22 op ssize_t n;
219 8d1b399b 2021-07-22 op int shut = 0;
220 8d1b399b 2021-07-22 op
221 8d1b399b 2021-07-22 op ibuf = &iev->ibuf;
222 8d1b399b 2021-07-22 op
223 8d1b399b 2021-07-22 op if (event & EV_READ) {
224 8d1b399b 2021-07-22 op if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
225 8d1b399b 2021-07-22 op fatal("imsg_read error");
226 8d1b399b 2021-07-22 op if (n == 0) /* Connection closed */
227 8d1b399b 2021-07-22 op shut = 1;
228 8d1b399b 2021-07-22 op }
229 8d1b399b 2021-07-22 op if (event & EV_WRITE) {
230 8d1b399b 2021-07-22 op if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
231 8d1b399b 2021-07-22 op fatal("msgbuf_write");
232 8d1b399b 2021-07-22 op if (n == 0) /* Connection closed */
233 8d1b399b 2021-07-22 op shut = 1;
234 8d1b399b 2021-07-22 op }
235 8d1b399b 2021-07-22 op
236 8d1b399b 2021-07-22 op for (;;) {
237 8d1b399b 2021-07-22 op if ((n = imsg_get(ibuf, &imsg)) == -1)
238 8d1b399b 2021-07-22 op fatal("%s: imsg_get error", __func__);
239 8d1b399b 2021-07-22 op if (n == 0) /* No more messages. */
240 8d1b399b 2021-07-22 op break;
241 8d1b399b 2021-07-22 op
242 8d1b399b 2021-07-22 op switch (imsg.hdr.type) {
243 8d1b399b 2021-07-22 op case IMSG_AUTH:
244 2ef72ade 2021-07-28 op peerid = imsg.hdr.peerid;
245 8d1b399b 2021-07-22 op if (auth)
246 8d1b399b 2021-07-22 op fatalx("%s: IMSG_AUTH already done", __func__);
247 8d1b399b 2021-07-22 op auth = AUTH_USER;
248 8d1b399b 2021-07-22 op ((char *)imsg.data)[IMSG_DATA_SIZE(imsg)-1] = '\0';
249 8d1b399b 2021-07-22 op strlcpy(username, imsg.data, sizeof(username));
250 8d1b399b 2021-07-22 op break;
251 8d1b399b 2021-07-22 op case IMSG_AUTH_DIR:
252 8d1b399b 2021-07-22 op if (auth != AUTH_USER)
253 8d1b399b 2021-07-22 op fatalx("%s: IMSG_AUTH_DIR not after IMSG_AUTH",
254 8d1b399b 2021-07-22 op __func__);
255 8d1b399b 2021-07-22 op auth = AUTH_DONE;
256 8d1b399b 2021-07-22 op ((char *)imsg.data)[IMSG_DATA_SIZE(imsg)-1] = '\0';
257 8d1b399b 2021-07-22 op strlcpy(dir, imsg.data, sizeof(dir));
258 8d1b399b 2021-07-22 op client_privdrop(username, dir);
259 8d1b399b 2021-07-22 op memset(username, 0, sizeof(username));
260 8d1b399b 2021-07-22 op memset(dir, 0, sizeof(username));
261 8d1b399b 2021-07-22 op break;
262 8d1b399b 2021-07-22 op case IMSG_BUF:
263 8d1b399b 2021-07-22 op /* echo! */
264 23e03c88 2021-07-26 op if (!auth)
265 23e03c88 2021-07-26 op fatalx("%s: can't handle messages before"
266 23e03c88 2021-07-26 op " doing the auth", __func__);
267 23e03c88 2021-07-26 op handle_message(&imsg, IMSG_DATA_SIZE(imsg));
268 8d1b399b 2021-07-22 op break;
269 8d1b399b 2021-07-22 op case IMSG_CONN_GONE:
270 8d1b399b 2021-07-22 op log_debug("closing");
271 8d1b399b 2021-07-22 op shut = 1;
272 8d1b399b 2021-07-22 op break;
273 8d1b399b 2021-07-22 op default:
274 8d1b399b 2021-07-22 op log_debug("%s: unexpected imsg %d",
275 8d1b399b 2021-07-22 op __func__, imsg.hdr.type);
276 8d1b399b 2021-07-22 op break;
277 8d1b399b 2021-07-22 op }
278 8d1b399b 2021-07-22 op imsg_free(&imsg);
279 8d1b399b 2021-07-22 op }
280 8d1b399b 2021-07-22 op
281 8d1b399b 2021-07-22 op if (!shut)
282 8d1b399b 2021-07-22 op imsg_event_add(iev);
283 8d1b399b 2021-07-22 op else {
284 8d1b399b 2021-07-22 op /* This pipe is dead. Remove its event handler. */
285 8d1b399b 2021-07-22 op event_del(&iev->ev);
286 8d1b399b 2021-07-22 op log_warnx("pipe closed, shutting down...");
287 8d1b399b 2021-07-22 op event_loopexit(NULL);
288 8d1b399b 2021-07-22 op }
289 8d1b399b 2021-07-22 op }
290 8d1b399b 2021-07-22 op
291 8d1b399b 2021-07-22 op static void
292 8d1b399b 2021-07-22 op client_privdrop(const char *username, const char *dir)
293 8d1b399b 2021-07-22 op {
294 8d1b399b 2021-07-22 op struct passwd *pw;
295 8d1b399b 2021-07-22 op
296 8d1b399b 2021-07-22 op setproctitle("client %s", username);
297 8d1b399b 2021-07-22 op
298 8d1b399b 2021-07-22 op if ((pw = getpwnam(username)) == NULL)
299 8d1b399b 2021-07-22 op fatalx("getpwnam(%s) failed", username);
300 8d1b399b 2021-07-22 op
301 8d1b399b 2021-07-22 op if (chroot(dir) == -1)
302 8d1b399b 2021-07-22 op fatal("chroot");
303 8d1b399b 2021-07-22 op if (chdir("/") == -1)
304 8d1b399b 2021-07-22 op fatal("chdir(\"/\")");
305 8d1b399b 2021-07-22 op
306 8d1b399b 2021-07-22 op if (setgroups(1, &pw->pw_gid) ||
307 8d1b399b 2021-07-22 op setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
308 8d1b399b 2021-07-22 op setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
309 8d1b399b 2021-07-22 op fatal("can't drop privileges");
310 8d1b399b 2021-07-22 op
311 8d1b399b 2021-07-22 op sandbox_client();
312 66a9a40a 2021-07-28 op log_debug("client ready; user=%s dir=%s", username, dir);
313 2ef72ade 2021-07-28 op
314 2ef72ade 2021-07-28 op if ((evb = evbuffer_new()) == NULL)
315 2ef72ade 2021-07-28 op fatal("evbuffer_new");
316 8d1b399b 2021-07-22 op }
317 8d1b399b 2021-07-22 op
318 8d1b399b 2021-07-22 op static int
319 2ef72ade 2021-07-28 op client_send_listener(int type, const void *data, uint16_t len)
320 8d1b399b 2021-07-22 op {
321 8d1b399b 2021-07-22 op int ret;
322 8d1b399b 2021-07-22 op
323 8d1b399b 2021-07-22 op if ((ret = imsg_compose(&iev_listener->ibuf, type, peerid, 0, -1,
324 8d1b399b 2021-07-22 op data, len)) != -1)
325 8d1b399b 2021-07-22 op imsg_event_add(iev_listener);
326 8d1b399b 2021-07-22 op
327 8d1b399b 2021-07-22 op return ret;
328 23e03c88 2021-07-26 op }
329 23e03c88 2021-07-26 op
330 053e2652 2021-08-01 op /* set qid fields from the sb field */
331 053e2652 2021-08-01 op static void
332 053e2652 2021-08-01 op qid_set_from_sb(struct qid *qid)
333 1c08fc54 2021-08-01 op {
334 1c08fc54 2021-08-01 op qid->path = qid->sb.st_ino;
335 1c08fc54 2021-08-01 op
336 1c08fc54 2021-08-01 op /*
337 1c08fc54 2021-08-01 op * Theoretically (and hopefully!) this should be a 64 bit
338 1c08fc54 2021-08-01 op * number. Unfortunately, 9P uses 32 bit timestamps.
339 1c08fc54 2021-08-01 op */
340 1c08fc54 2021-08-01 op qid->vers = qid->sb.st_mtim.tv_sec;
341 1c08fc54 2021-08-01 op
342 1c08fc54 2021-08-01 op if (S_ISREG(qid->sb.st_mode))
343 1c08fc54 2021-08-01 op qid->type = QTFILE;
344 1c08fc54 2021-08-01 op else if (S_ISDIR(qid->sb.st_mode))
345 1c08fc54 2021-08-01 op qid->type = QTDIR;
346 1c08fc54 2021-08-01 op else if (S_ISLNK(qid->sb.st_mode))
347 1c08fc54 2021-08-01 op qid->type = QTSYMLINK;
348 053e2652 2021-08-01 op }
349 1c08fc54 2021-08-01 op
350 053e2652 2021-08-01 op /* update qid info */
351 053e2652 2021-08-01 op static int
352 053e2652 2021-08-01 op qid_update_stat(struct qid *qid)
353 053e2652 2021-08-01 op {
354 053e2652 2021-08-01 op if (fstat(qid->fd, &qid->sb) == -1)
355 053e2652 2021-08-01 op return -1;
356 053e2652 2021-08-01 op
357 053e2652 2021-08-01 op qid_set_from_sb(qid);
358 1c08fc54 2021-08-01 op return 0;
359 1c08fc54 2021-08-01 op }
360 1c08fc54 2021-08-01 op
361 053e2652 2021-08-01 op /* create a new qid by copying info from an existing one */
362 053e2652 2021-08-01 op static struct qid *
363 053e2652 2021-08-01 op qid_from_copy(const struct qid *qid)
364 053e2652 2021-08-01 op {
365 053e2652 2021-08-01 op struct qid *q;
366 053e2652 2021-08-01 op
367 053e2652 2021-08-01 op if ((q = calloc(1, sizeof(*q))) == NULL)
368 053e2652 2021-08-01 op return NULL;
369 053e2652 2021-08-01 op q->fd = -1;
370 053e2652 2021-08-01 op
371 053e2652 2021-08-01 op memcpy(q->fpath, qid->fpath, sizeof(q->fpath));
372 053e2652 2021-08-01 op
373 053e2652 2021-08-01 op memcpy(&q->sb, &qid->sb, sizeof(q->sb));
374 053e2652 2021-08-01 op memcpy(&q->path, &qid->path, sizeof(q->path));
375 053e2652 2021-08-01 op memcpy(&q->vers, &qid->vers, sizeof(q->vers));
376 053e2652 2021-08-01 op memcpy(&q->type, &qid->type, sizeof(q->type));
377 053e2652 2021-08-01 op
378 053e2652 2021-08-01 op return q;
379 053e2652 2021-08-01 op }
380 053e2652 2021-08-01 op
381 c5d518da 2021-07-29 op /* creates a qid given a fd */
382 c5d518da 2021-07-29 op static struct qid *
383 eafb23b1 2021-08-01 op qid_from_fd(int fd)
384 c5d518da 2021-07-29 op {
385 c5d518da 2021-07-29 op struct qid *qid;
386 c5d518da 2021-07-29 op
387 c5d518da 2021-07-29 op if ((qid = calloc(1, sizeof(*qid))) == NULL)
388 c5d518da 2021-07-29 op return NULL;
389 c5d518da 2021-07-29 op
390 c5d518da 2021-07-29 op qid->fd = fd;
391 1c08fc54 2021-08-01 op qid_update_stat(qid);
392 c5d518da 2021-07-29 op
393 053e2652 2021-08-01 op STAILQ_INSERT_HEAD(&qids, qid, entries);
394 c5d518da 2021-07-29 op
395 c5d518da 2021-07-29 op return qid;
396 c377c1b9 2021-07-30 op }
397 c377c1b9 2021-07-30 op
398 c377c1b9 2021-07-30 op static struct qid *
399 053e2652 2021-08-01 op qid_from_path(const char *path)
400 053e2652 2021-08-01 op {
401 053e2652 2021-08-01 op struct qid *qid;
402 053e2652 2021-08-01 op
403 053e2652 2021-08-01 op if ((qid = calloc(1, sizeof(*qid))) == NULL)
404 053e2652 2021-08-01 op return NULL;
405 053e2652 2021-08-01 op
406 053e2652 2021-08-01 op qid->fd = -1;
407 053e2652 2021-08-01 op
408 053e2652 2021-08-01 op if (stat(path, &qid->sb) == -1) {
409 053e2652 2021-08-01 op free(qid);
410 053e2652 2021-08-01 op return NULL;
411 053e2652 2021-08-01 op }
412 053e2652 2021-08-01 op
413 053e2652 2021-08-01 op qid_set_from_sb(qid);
414 053e2652 2021-08-01 op
415 053e2652 2021-08-01 op STAILQ_INSERT_HEAD(&qids, qid, entries);
416 053e2652 2021-08-01 op
417 053e2652 2021-08-01 op return qid;
418 053e2652 2021-08-01 op }
419 053e2652 2021-08-01 op
420 053e2652 2021-08-01 op static struct qid *
421 c377c1b9 2021-07-30 op qid_incref(struct qid *qid)
422 c377c1b9 2021-07-30 op {
423 c377c1b9 2021-07-30 op qid->refcount++;
424 c377c1b9 2021-07-30 op return qid;
425 c377c1b9 2021-07-30 op }
426 c377c1b9 2021-07-30 op
427 c377c1b9 2021-07-30 op static void
428 c377c1b9 2021-07-30 op qid_decref(struct qid *qid)
429 c377c1b9 2021-07-30 op {
430 c377c1b9 2021-07-30 op if (--qid->refcount > 0)
431 c377c1b9 2021-07-30 op return;
432 c377c1b9 2021-07-30 op
433 c377c1b9 2021-07-30 op STAILQ_REMOVE(&qids, qid, qid, entries);
434 c377c1b9 2021-07-30 op
435 c377c1b9 2021-07-30 op close(qid->fd);
436 c377c1b9 2021-07-30 op free(qid);
437 c377c1b9 2021-07-30 op
438 c377c1b9 2021-07-30 op if (STAILQ_EMPTY(&qids))
439 c377c1b9 2021-07-30 op attached = 0;
440 c5d518da 2021-07-29 op }
441 c5d518da 2021-07-29 op
442 c5d518da 2021-07-29 op static struct fid *
443 c5d518da 2021-07-29 op new_fid(struct qid *qid, uint32_t fid)
444 c5d518da 2021-07-29 op {
445 c5d518da 2021-07-29 op struct fid *f;
446 c5d518da 2021-07-29 op
447 c5d518da 2021-07-29 op if ((f = calloc(1, sizeof(*f))) == NULL)
448 c5d518da 2021-07-29 op return NULL;
449 c5d518da 2021-07-29 op
450 c377c1b9 2021-07-30 op f->qid = qid_incref(qid);
451 c5d518da 2021-07-29 op f->fid = fid;
452 c5d518da 2021-07-29 op
453 c5d518da 2021-07-29 op STAILQ_INSERT_HEAD(&fids, f, entries);
454 c5d518da 2021-07-29 op
455 c5d518da 2021-07-29 op return f;
456 c5d518da 2021-07-29 op }
457 c5d518da 2021-07-29 op
458 c377c1b9 2021-07-30 op static struct fid *
459 c377c1b9 2021-07-30 op fid_by_id(uint32_t fid)
460 c377c1b9 2021-07-30 op {
461 c377c1b9 2021-07-30 op struct fid *f;
462 c377c1b9 2021-07-30 op
463 c377c1b9 2021-07-30 op STAILQ_FOREACH(f, &fids, entries) {
464 c377c1b9 2021-07-30 op if (f->fid == fid)
465 c377c1b9 2021-07-30 op return f;
466 c377c1b9 2021-07-30 op }
467 c377c1b9 2021-07-30 op
468 c377c1b9 2021-07-30 op return NULL;
469 c377c1b9 2021-07-30 op }
470 c377c1b9 2021-07-30 op
471 5c485996 2021-07-28 op static void
472 c377c1b9 2021-07-30 op free_fid(struct fid *f)
473 c377c1b9 2021-07-30 op {
474 c377c1b9 2021-07-30 op qid_decref(f->qid);
475 c377c1b9 2021-07-30 op
476 c377c1b9 2021-07-30 op STAILQ_REMOVE(&fids, f, fid, entries);
477 c377c1b9 2021-07-30 op free(f);
478 c377c1b9 2021-07-30 op }
479 c377c1b9 2021-07-30 op
480 c377c1b9 2021-07-30 op static void
481 48192874 2021-08-01 op parse_message(const uint8_t *data, size_t len, struct np_msg_header *hdr,
482 5c485996 2021-07-28 op uint8_t **cnt)
483 23e03c88 2021-07-26 op {
484 48192874 2021-08-01 op size_t olen = len;
485 12c6d699 2021-07-26 op
486 48192874 2021-08-01 op if (!NPREAD32("len", &hdr->len, &data, &len) ||
487 48192874 2021-08-01 op !NPREAD8("type", &hdr->type, &data, &len) ||
488 48192874 2021-08-01 op !NPREAD16("tag", &hdr->tag, &data, &len))
489 48192874 2021-08-01 op goto err;
490 63f681aa 2021-07-28 op
491 48192874 2021-08-01 op if (olen != hdr->len)
492 23e03c88 2021-07-26 op goto err;
493 23e03c88 2021-07-26 op
494 23e03c88 2021-07-26 op if (hdr->type < Tversion ||
495 23e03c88 2021-07-26 op hdr->type >= Tmax ||
496 23e03c88 2021-07-26 op hdr->type == Terror ||
497 23e03c88 2021-07-26 op (hdr->type & 0x1) != 0) /* cannot recv a R* */
498 23e03c88 2021-07-26 op goto err;
499 23e03c88 2021-07-26 op
500 23e03c88 2021-07-26 op hdr->tag = le32toh(hdr->tag);
501 23e03c88 2021-07-26 op
502 48192874 2021-08-01 op *cnt = (uint8_t *)data;
503 23e03c88 2021-07-26 op return;
504 23e03c88 2021-07-26 op
505 23e03c88 2021-07-26 op err:
506 23e03c88 2021-07-26 op /* TODO: send a proper message to terminate the connection. */
507 23e03c88 2021-07-26 op fatalx("got invalid message");
508 83f6b305 2021-08-01 op }
509 83f6b305 2021-08-01 op
510 83f6b305 2021-08-01 op static void
511 83f6b305 2021-08-01 op np_write16(uint16_t x)
512 83f6b305 2021-08-01 op {
513 83f6b305 2021-08-01 op x = htole16(x);
514 83f6b305 2021-08-01 op evbuffer_add(evb, &x, sizeof(x));
515 2ef72ade 2021-07-28 op }
516 2ef72ade 2021-07-28 op
517 2845cccb 2021-07-29 op static void
518 2ef72ade 2021-07-28 op np_header(uint32_t len, uint8_t type, uint16_t tag)
519 2ef72ade 2021-07-28 op {
520 9ebb95a7 2021-07-30 op len += HEADERSIZE;
521 9ebb95a7 2021-07-30 op
522 63f681aa 2021-07-28 op len = htole32(len);
523 63f681aa 2021-07-28 op tag = htole16(tag);
524 63f681aa 2021-07-28 op
525 2ef72ade 2021-07-28 op evbuffer_add(evb, &len, sizeof(len));
526 2ef72ade 2021-07-28 op evbuffer_add(evb, &type, sizeof(type));
527 2ef72ade 2021-07-28 op evbuffer_add(evb, &tag, sizeof(tag));
528 5c485996 2021-07-28 op }
529 5c485996 2021-07-28 op
530 2845cccb 2021-07-29 op static void
531 5c485996 2021-07-28 op np_string(uint16_t len, const char *str)
532 5c485996 2021-07-28 op {
533 5c485996 2021-07-28 op uint16_t l = len;
534 5c485996 2021-07-28 op
535 5c485996 2021-07-28 op len = htole16(len);
536 5c485996 2021-07-28 op evbuffer_add(evb, &len, sizeof(len));
537 5c485996 2021-07-28 op evbuffer_add(evb, str, l);
538 8d1b399b 2021-07-22 op }
539 23e03c88 2021-07-26 op
540 84b10f04 2021-07-29 op static void
541 c5d518da 2021-07-29 op np_qid(struct qid *qid)
542 c5d518da 2021-07-29 op {
543 c5d518da 2021-07-29 op uint64_t path;
544 c5d518da 2021-07-29 op uint32_t vers;
545 c5d518da 2021-07-29 op
546 c5d518da 2021-07-29 op path = htole64(qid->path);
547 c5d518da 2021-07-29 op vers = htole32(qid->vers);
548 c5d518da 2021-07-29 op
549 c5d518da 2021-07-29 op evbuffer_add(evb, &qid->type, sizeof(qid->type));
550 8d448d55 2021-07-30 op evbuffer_add(evb, &vers, sizeof(vers));
551 8d448d55 2021-07-30 op evbuffer_add(evb, &path, sizeof(path));
552 c5d518da 2021-07-29 op }
553 c5d518da 2021-07-29 op
554 c5d518da 2021-07-29 op static void
555 2ef72ade 2021-07-28 op do_send(void)
556 2ef72ade 2021-07-28 op {
557 64c19d90 2021-07-30 op size_t len;
558 64c19d90 2021-07-30 op void *data;
559 2ef72ade 2021-07-28 op
560 2ef72ade 2021-07-28 op len = EVBUFFER_LENGTH(evb);
561 64c19d90 2021-07-30 op data = EVBUFFER_DATA(evb);
562 64c19d90 2021-07-30 op
563 64c19d90 2021-07-30 op #if DEBUG_PACKETS
564 78b94752 2021-08-01 op hexdump("outgoing packet", data, len);
565 64c19d90 2021-07-30 op #endif
566 64c19d90 2021-07-30 op client_send_listener(IMSG_BUF, data, len);
567 2ef72ade 2021-07-28 op evbuffer_drain(evb, len);
568 2ef72ade 2021-07-28 op }
569 2ef72ade 2021-07-28 op
570 23e03c88 2021-07-26 op static void
571 5c485996 2021-07-28 op np_version(uint16_t tag, uint32_t msize, const char *version)
572 5c485996 2021-07-28 op {
573 5c485996 2021-07-28 op uint16_t l;
574 5c485996 2021-07-28 op
575 5c485996 2021-07-28 op l = strlen(version);
576 5c485996 2021-07-28 op
577 5c485996 2021-07-28 op msize = htole32(msize);
578 5c485996 2021-07-28 op
579 9ebb95a7 2021-07-30 op np_header(sizeof(msize) + sizeof(l) + l, Rversion, tag);
580 5c485996 2021-07-28 op evbuffer_add(evb, &msize, sizeof(msize));
581 5c485996 2021-07-28 op np_string(l, version);
582 5c485996 2021-07-28 op do_send();
583 5c485996 2021-07-28 op }
584 5c485996 2021-07-28 op
585 5c485996 2021-07-28 op static void
586 c5d518da 2021-07-29 op np_attach(uint16_t tag, struct qid *qid)
587 c5d518da 2021-07-29 op {
588 9ebb95a7 2021-07-30 op np_header(QIDSIZE, Rattach, tag);
589 c5d518da 2021-07-29 op np_qid(qid);
590 c5d518da 2021-07-29 op do_send();
591 c5d518da 2021-07-29 op }
592 c5d518da 2021-07-29 op
593 c5d518da 2021-07-29 op static void
594 c377c1b9 2021-07-30 op np_clunk(uint16_t tag)
595 c377c1b9 2021-07-30 op {
596 9ebb95a7 2021-07-30 op np_header(0, Rclunk, tag);
597 c377c1b9 2021-07-30 op do_send();
598 c377c1b9 2021-07-30 op }
599 c377c1b9 2021-07-30 op
600 c377c1b9 2021-07-30 op static void
601 36b30273 2021-07-30 op np_flush(uint16_t tag)
602 36b30273 2021-07-30 op {
603 9ebb95a7 2021-07-30 op np_header(0, Rflush, tag);
604 36b30273 2021-07-30 op do_send();
605 36b30273 2021-07-30 op }
606 36b30273 2021-07-30 op
607 36b30273 2021-07-30 op static void
608 1c08fc54 2021-08-01 op np_walk(uint16_t tag, int nwqid, struct qid *wqid)
609 1c08fc54 2021-08-01 op {
610 1c08fc54 2021-08-01 op int i;
611 1c08fc54 2021-08-01 op
612 83f6b305 2021-08-01 op /* two bytes for the counter */
613 83f6b305 2021-08-01 op np_header(2 + QIDSIZE * nwqid, Rwalk, tag);
614 83f6b305 2021-08-01 op np_write16(nwqid);
615 1c08fc54 2021-08-01 op for (i = 0; i < nwqid; ++i)
616 1c08fc54 2021-08-01 op np_qid(wqid + i);
617 1c08fc54 2021-08-01 op
618 1c08fc54 2021-08-01 op do_send();
619 1c08fc54 2021-08-01 op }
620 1c08fc54 2021-08-01 op
621 1c08fc54 2021-08-01 op static void
622 2ef72ade 2021-07-28 op np_error(uint16_t tag, const char *errstr)
623 2ef72ade 2021-07-28 op {
624 2ef72ade 2021-07-28 op uint16_t l;
625 2ef72ade 2021-07-28 op
626 2ef72ade 2021-07-28 op l = strlen(errstr);
627 2ef72ade 2021-07-28 op
628 9ebb95a7 2021-07-30 op np_header(sizeof(l) + l, Rerror, tag);
629 5c485996 2021-07-28 op np_string(l, errstr);
630 2ef72ade 2021-07-28 op do_send();
631 2ef72ade 2021-07-28 op }
632 2ef72ade 2021-07-28 op
633 2ef72ade 2021-07-28 op static void
634 c5d518da 2021-07-29 op np_errno(uint16_t tag)
635 c5d518da 2021-07-29 op {
636 9b088310 2021-07-30 op int saved_errno;
637 c5d518da 2021-07-29 op char buf[64];
638 c5d518da 2021-07-29 op
639 9b088310 2021-07-30 op saved_errno = errno;
640 9b088310 2021-07-30 op
641 c5d518da 2021-07-29 op strerror_r(errno, buf, sizeof(buf));
642 c5d518da 2021-07-29 op np_error(tag, buf);
643 9b088310 2021-07-30 op
644 9b088310 2021-07-30 op errno = saved_errno;
645 48192874 2021-08-01 op }
646 48192874 2021-08-01 op
647 48192874 2021-08-01 op static int
648 48192874 2021-08-01 op np_read8(const char *t, const char *f, uint8_t *dst, const uint8_t **src,
649 48192874 2021-08-01 op size_t *len)
650 48192874 2021-08-01 op {
651 48192874 2021-08-01 op if (*len < sizeof(*dst)) {
652 48192874 2021-08-01 op log_warnx("%s: wanted %zu bytes for the %s field but only "
653 48192874 2021-08-01 op "%zu are available.", t, sizeof(*dst), f, *len);
654 48192874 2021-08-01 op return -1;
655 48192874 2021-08-01 op }
656 48192874 2021-08-01 op
657 48192874 2021-08-01 op memcpy(dst, *src, sizeof(*dst));
658 48192874 2021-08-01 op *src += sizeof(*dst);
659 48192874 2021-08-01 op *len -= sizeof(*dst);
660 48192874 2021-08-01 op
661 48192874 2021-08-01 op return 1;
662 48192874 2021-08-01 op }
663 48192874 2021-08-01 op
664 48192874 2021-08-01 op static int
665 48192874 2021-08-01 op np_read16(const char *t, const char *f, uint16_t *dst, const uint8_t **src,
666 48192874 2021-08-01 op size_t *len)
667 48192874 2021-08-01 op {
668 48192874 2021-08-01 op if (*len < sizeof(*dst)) {
669 48192874 2021-08-01 op log_warnx("%s: wanted %zu bytes for the %s field but only "
670 48192874 2021-08-01 op "%zu are available.", t, sizeof(*dst), f, *len);
671 48192874 2021-08-01 op return -1;
672 48192874 2021-08-01 op }
673 48192874 2021-08-01 op
674 48192874 2021-08-01 op memcpy(dst, *src, sizeof(*dst));
675 48192874 2021-08-01 op *src += sizeof(*dst);
676 48192874 2021-08-01 op *len -= sizeof(*dst);
677 48192874 2021-08-01 op *dst = le16toh(*dst);
678 48192874 2021-08-01 op
679 48192874 2021-08-01 op return 1;
680 c5d518da 2021-07-29 op }
681 c5d518da 2021-07-29 op
682 48192874 2021-08-01 op static int
683 48192874 2021-08-01 op np_read32(const char *t, const char *f, uint32_t *dst, const uint8_t **src,
684 48192874 2021-08-01 op size_t *len)
685 48192874 2021-08-01 op {
686 48192874 2021-08-01 op if (*len < sizeof(*dst)) {
687 48192874 2021-08-01 op log_warnx("%s: wanted %zu bytes for the %s field but only "
688 48192874 2021-08-01 op "%zu are available.", t, sizeof(*dst), f, *len);
689 48192874 2021-08-01 op return -1;
690 48192874 2021-08-01 op }
691 48192874 2021-08-01 op
692 48192874 2021-08-01 op memcpy(dst, *src, sizeof(*dst));
693 48192874 2021-08-01 op *src += sizeof(*dst);
694 48192874 2021-08-01 op *len -= sizeof(*dst);
695 48192874 2021-08-01 op *dst = le32toh(*dst);
696 48192874 2021-08-01 op
697 48192874 2021-08-01 op return 1;
698 48192874 2021-08-01 op }
699 48192874 2021-08-01 op
700 48192874 2021-08-01 op static int
701 48192874 2021-08-01 op np_readstr(const char *t, const char *f, char *res, size_t reslen,
702 48192874 2021-08-01 op const uint8_t **src, size_t *len)
703 48192874 2021-08-01 op {
704 48192874 2021-08-01 op uint16_t sl;
705 48192874 2021-08-01 op char buf[32];
706 48192874 2021-08-01 op
707 48192874 2021-08-01 op strlcpy(buf, f, sizeof(buf));
708 48192874 2021-08-01 op strlcat(buf, "-len", sizeof(buf));
709 48192874 2021-08-01 op
710 48192874 2021-08-01 op if (!np_read16(t, buf, &sl, src, len))
711 48192874 2021-08-01 op return READSTRERR;
712 48192874 2021-08-01 op
713 48192874 2021-08-01 op if (*len < sl) {
714 48192874 2021-08-01 op log_warnx("%s: wanted %d bytes for the %s field but only "
715 48192874 2021-08-01 op "%zu are available.", t, sl, f, *len);
716 48192874 2021-08-01 op return READSTRERR;
717 48192874 2021-08-01 op }
718 48192874 2021-08-01 op
719 48192874 2021-08-01 op if (*len > reslen-1)
720 48192874 2021-08-01 op return READSTRTRUNC;
721 48192874 2021-08-01 op
722 48192874 2021-08-01 op memcpy(res, *src, sl);
723 48192874 2021-08-01 op res[sl] = '\0';
724 48192874 2021-08-01 op *src += sl;
725 48192874 2021-08-01 op *len -= sl;
726 48192874 2021-08-01 op
727 48192874 2021-08-01 op return 0;
728 48192874 2021-08-01 op }
729 48192874 2021-08-01 op
730 c5d518da 2021-07-29 op static void
731 e60f4e08 2021-07-30 op tversion(struct np_msg_header *hdr, const uint8_t *data, size_t len)
732 23e03c88 2021-07-26 op {
733 48192874 2021-08-01 op char *dot, version[32];
734 23e03c88 2021-07-26 op
735 e60f4e08 2021-07-30 op if (handshaked)
736 5c485996 2021-07-28 op goto err;
737 5c485996 2021-07-28 op
738 3d20424d 2021-08-01 op /* msize[4] version[s] */
739 48192874 2021-08-01 op if (!NPREAD32("msize", &msize, &data, &len))
740 e60f4e08 2021-07-30 op goto err;
741 5c485996 2021-07-28 op
742 48192874 2021-08-01 op switch (NPREADSTR("version", version, sizeof(version), &data, &len)) {
743 48192874 2021-08-01 op case READSTRERR:
744 48192874 2021-08-01 op goto err;
745 48192874 2021-08-01 op case READSTRTRUNC:
746 48192874 2021-08-01 op log_warnx("9P version string too long, truncated");
747 48192874 2021-08-01 op goto mismatch;
748 e60f4e08 2021-07-30 op }
749 db8dca01 2021-07-29 op
750 48192874 2021-08-01 op if ((dot = strchr(version, '.')) != NULL)
751 48192874 2021-08-01 op *dot = '\0';
752 5c485996 2021-07-28 op
753 48192874 2021-08-01 op if (strcmp(version, VERSION9P) != 0 ||
754 48192874 2021-08-01 op msize == 0)
755 48192874 2021-08-01 op goto mismatch;
756 48192874 2021-08-01 op
757 48192874 2021-08-01 op /* version matched */
758 48192874 2021-08-01 op handshaked = 1;
759 e60f4e08 2021-07-30 op msize = MIN(msize, MSIZE9P);
760 e60f4e08 2021-07-30 op client_send_listener(IMSG_MSIZE, &msize, sizeof(msize));
761 e60f4e08 2021-07-30 op np_version(hdr->tag, msize, VERSION9P);
762 e60f4e08 2021-07-30 op return;
763 5c485996 2021-07-28 op
764 48192874 2021-08-01 op mismatch:
765 48192874 2021-08-01 op log_warnx("unknown 9P version string: \"%s\", want "VERSION9P,
766 48192874 2021-08-01 op version);
767 48192874 2021-08-01 op np_version(hdr->tag, MSIZE9P, "unknown");
768 48192874 2021-08-01 op return;
769 48192874 2021-08-01 op
770 e60f4e08 2021-07-30 op err:
771 e60f4e08 2021-07-30 op client_send_listener(IMSG_CLOSE, NULL, 0);
772 e60f4e08 2021-07-30 op client_shutdown();
773 e60f4e08 2021-07-30 op }
774 5c485996 2021-07-28 op
775 e60f4e08 2021-07-30 op static void
776 e60f4e08 2021-07-30 op tattach(struct np_msg_header *hdr, const uint8_t *data, size_t len)
777 e60f4e08 2021-07-30 op {
778 e60f4e08 2021-07-30 op struct qid *qid;
779 e60f4e08 2021-07-30 op struct fid *f;
780 48192874 2021-08-01 op uint32_t fid, afid;
781 014adfc2 2021-07-30 op char aname[PATH_MAX];
782 5c420a81 2021-07-30 op
783 e60f4e08 2021-07-30 op if (attached) {
784 e60f4e08 2021-07-30 op np_error(hdr->tag, "already attached");
785 e60f4e08 2021-07-30 op return;
786 e60f4e08 2021-07-30 op }
787 c5d518da 2021-07-29 op
788 e60f4e08 2021-07-30 op /* fid[4] afid[4] uname[s] aname[s] */
789 c5d518da 2021-07-29 op
790 48192874 2021-08-01 op if (!NPREAD32("fid", &fid, &data, &len) ||
791 48192874 2021-08-01 op !NPREAD32("afid", &afid, &data, &len))
792 014adfc2 2021-07-30 op goto err;
793 014adfc2 2021-07-30 op
794 48192874 2021-08-01 op /* read the uname but don't actually use it */
795 48192874 2021-08-01 op switch (NPREADSTR("uname", aname, sizeof(aname), &data, &len)) {
796 48192874 2021-08-01 op case READSTRERR:
797 014adfc2 2021-07-30 op goto err;
798 48192874 2021-08-01 op case READSTRTRUNC:
799 48192874 2021-08-01 op np_error(hdr->tag, "name too long");
800 48192874 2021-08-01 op return;
801 3fe030c5 2021-07-30 op }
802 3fe030c5 2021-07-30 op
803 48192874 2021-08-01 op switch (NPREADSTR("aname", aname, sizeof(aname), &data, &len)) {
804 48192874 2021-08-01 op case READSTRERR:
805 48192874 2021-08-01 op goto err;
806 48192874 2021-08-01 op case READSTRTRUNC:
807 014adfc2 2021-07-30 op np_error(hdr->tag, "name too long");
808 014adfc2 2021-07-30 op return;
809 014adfc2 2021-07-30 op }
810 014adfc2 2021-07-30 op
811 053e2652 2021-08-01 op if ((qid = qid_from_path(aname)) == NULL) {
812 e60f4e08 2021-07-30 op np_errno(hdr->tag);
813 014adfc2 2021-07-30 op log_debug("failed to attach %s: %s", aname, strerror(errno));
814 e60f4e08 2021-07-30 op return;
815 e60f4e08 2021-07-30 op }
816 014adfc2 2021-07-30 op log_debug("attached %s", aname);
817 c5d518da 2021-07-29 op
818 e60f4e08 2021-07-30 op if ((f = new_fid(qid, fid)) == NULL) {
819 053e2652 2021-08-01 op qid_decref(qid);
820 e60f4e08 2021-07-30 op np_error(hdr->tag, "no memory");
821 e60f4e08 2021-07-30 op return;
822 5c485996 2021-07-28 op }
823 5c485996 2021-07-28 op
824 e60f4e08 2021-07-30 op np_attach(hdr->tag, qid);
825 e60f4e08 2021-07-30 op attached = 1;
826 5c485996 2021-07-28 op return;
827 014adfc2 2021-07-30 op
828 014adfc2 2021-07-30 op err:
829 014adfc2 2021-07-30 op client_send_listener(IMSG_CLOSE, NULL, 0);
830 014adfc2 2021-07-30 op client_shutdown();
831 c377c1b9 2021-07-30 op }
832 c377c1b9 2021-07-30 op
833 c377c1b9 2021-07-30 op static void
834 c377c1b9 2021-07-30 op tclunk(struct np_msg_header *hdr, const uint8_t *data, size_t len)
835 c377c1b9 2021-07-30 op {
836 c377c1b9 2021-07-30 op struct fid *f;
837 c377c1b9 2021-07-30 op uint32_t fid;
838 c377c1b9 2021-07-30 op
839 c377c1b9 2021-07-30 op /* fid[4] */
840 48192874 2021-08-01 op if (!NPREAD32("fid", &fid, &data, &len)) {
841 c377c1b9 2021-07-30 op client_send_listener(IMSG_CLOSE, NULL, 0);
842 c377c1b9 2021-07-30 op client_shutdown();
843 c377c1b9 2021-07-30 op return;
844 c377c1b9 2021-07-30 op }
845 c377c1b9 2021-07-30 op
846 c377c1b9 2021-07-30 op if ((f = fid_by_id(fid)) == NULL) {
847 c377c1b9 2021-07-30 op np_error(hdr->tag, "invalid fid");
848 c377c1b9 2021-07-30 op return;
849 c377c1b9 2021-07-30 op }
850 c377c1b9 2021-07-30 op
851 c377c1b9 2021-07-30 op free_fid(f);
852 c377c1b9 2021-07-30 op np_clunk(hdr->tag);
853 36b30273 2021-07-30 op }
854 36b30273 2021-07-30 op
855 36b30273 2021-07-30 op static void
856 36b30273 2021-07-30 op tflush(struct np_msg_header *hdr, const uint8_t *data, size_t len)
857 36b30273 2021-07-30 op {
858 36b30273 2021-07-30 op uint16_t oldtag;
859 36b30273 2021-07-30 op
860 36b30273 2021-07-30 op /*
861 36b30273 2021-07-30 op * We're doing only synchronous I/O. Tflush is implemented
862 36b30273 2021-07-30 op * only because it's illegal to reply with a Rerror.
863 36b30273 2021-07-30 op */
864 36b30273 2021-07-30 op
865 36b30273 2021-07-30 op /* oldtag[2] */
866 36b30273 2021-07-30 op if (len != sizeof(oldtag)) {
867 36b30273 2021-07-30 op log_warnx("Tclunk with the wrong size: got %zu want %zu",
868 36b30273 2021-07-30 op len, sizeof(oldtag));
869 36b30273 2021-07-30 op client_send_listener(IMSG_CLOSE, NULL, 0);
870 36b30273 2021-07-30 op client_shutdown();
871 36b30273 2021-07-30 op return;
872 36b30273 2021-07-30 op }
873 36b30273 2021-07-30 op
874 36b30273 2021-07-30 op np_flush(hdr->tag);
875 e60f4e08 2021-07-30 op }
876 5c485996 2021-07-28 op
877 e60f4e08 2021-07-30 op static void
878 1c08fc54 2021-08-01 op twalk(struct np_msg_header *hdr, const uint8_t *data, size_t len)
879 1c08fc54 2021-08-01 op {
880 053e2652 2021-08-01 op struct qid *qid, wqid[MAXWELEM] = {0};
881 1c08fc54 2021-08-01 op struct fid *f, *nf;
882 1c08fc54 2021-08-01 op uint32_t fid, newfid;
883 7ddddcfe 2021-08-01 op uint16_t nwname;
884 053e2652 2021-08-01 op int nwqid = 0;
885 053e2652 2021-08-01 op char wnam[PATH_MAX+1], path[PATH_MAX+1];
886 1c08fc54 2021-08-01 op
887 48192874 2021-08-01 op if (!NPREAD32("fid", &fid, &data, &len) ||
888 48192874 2021-08-01 op !NPREAD32("newfid", &newfid, &data, &len) ||
889 48192874 2021-08-01 op !NPREAD16("nwname", &nwname, &data, &len))
890 48192874 2021-08-01 op goto err;
891 1c08fc54 2021-08-01 op
892 1c08fc54 2021-08-01 op if (nwname > MAXWELEM) {
893 1c08fc54 2021-08-01 op log_warnx("Twalk: more than %d path elements: %d",
894 1c08fc54 2021-08-01 op MAXWELEM, nwname);
895 1c08fc54 2021-08-01 op goto err;
896 1c08fc54 2021-08-01 op }
897 1c08fc54 2021-08-01 op
898 1c08fc54 2021-08-01 op if ((f = fid_by_id(fid)) == NULL) {
899 1c08fc54 2021-08-01 op np_error(hdr->tag, "invalid fid");
900 1c08fc54 2021-08-01 op return;
901 1c08fc54 2021-08-01 op }
902 1c08fc54 2021-08-01 op
903 1c08fc54 2021-08-01 op if (fid == newfid)
904 1c08fc54 2021-08-01 op nf = f;
905 1c08fc54 2021-08-01 op else if ((nf = fid_by_id(newfid)) != NULL) {
906 1c08fc54 2021-08-01 op np_error(hdr->tag, "newfid already in use");
907 1c08fc54 2021-08-01 op return;
908 1c08fc54 2021-08-01 op } else
909 1c08fc54 2021-08-01 op nf = NULL;
910 1c08fc54 2021-08-01 op
911 913eba5c 2021-08-01 op /* special case: fid duplication */
912 22dfb5a0 2021-08-01 op if (nwname == 0) {
913 1c08fc54 2021-08-01 op /*
914 1c08fc54 2021-08-01 op * TODO: should we forbid fids duplication when fid ==
915 1c08fc54 2021-08-01 op * newfid?
916 1c08fc54 2021-08-01 op */
917 1c08fc54 2021-08-01 op
918 1c08fc54 2021-08-01 op if (nf == NULL) {
919 83f6b305 2021-08-01 op if ((nf = new_fid(f->qid, newfid)) == NULL)
920 83f6b305 2021-08-01 op fatal("new_fid duplication");
921 1c08fc54 2021-08-01 op }
922 1c08fc54 2021-08-01 op
923 1c08fc54 2021-08-01 op np_walk(hdr->tag, 1, f->qid);
924 1c08fc54 2021-08-01 op return;
925 1c08fc54 2021-08-01 op }
926 1c08fc54 2021-08-01 op
927 053e2652 2021-08-01 op if (f->iomode != 0) {
928 053e2652 2021-08-01 op np_error(hdr->tag, "fid already opened for I/O");
929 053e2652 2021-08-01 op return;
930 053e2652 2021-08-01 op }
931 053e2652 2021-08-01 op
932 053e2652 2021-08-01 op if (f->qid->type != QTDIR) {
933 053e2652 2021-08-01 op np_error(hdr->tag, "fid doesn't represent a directory");
934 053e2652 2021-08-01 op return;
935 053e2652 2021-08-01 op }
936 053e2652 2021-08-01 op
937 053e2652 2021-08-01 op strlcpy(path, f->qid->fpath, sizeof(path));
938 053e2652 2021-08-01 op
939 1c08fc54 2021-08-01 op for (nwqid = 0; nwqid < nwname; nwqid++) {
940 053e2652 2021-08-01 op switch (NPREADSTR("wname", wnam, sizeof(wnam), &data, &len)) {
941 48192874 2021-08-01 op case READSTRERR:
942 1c08fc54 2021-08-01 op goto err;
943 48192874 2021-08-01 op case READSTRTRUNC:
944 1c08fc54 2021-08-01 op np_error(hdr->tag, "wname too long");
945 1c08fc54 2021-08-01 op return;
946 1c08fc54 2021-08-01 op }
947 1c08fc54 2021-08-01 op
948 053e2652 2021-08-01 op strlcat(path, "/", sizeof(path));
949 053e2652 2021-08-01 op strlcat(path, wnam, sizeof(path));
950 053e2652 2021-08-01 op
951 053e2652 2021-08-01 op if (stat(path, &wqid[nwqid].sb) == -1) {
952 1c08fc54 2021-08-01 op if (nwqid == 0)
953 1c08fc54 2021-08-01 op np_errno(hdr->tag);
954 1c08fc54 2021-08-01 op else
955 1c08fc54 2021-08-01 op np_walk(hdr->tag, nwqid, wqid);
956 1c08fc54 2021-08-01 op return;
957 1c08fc54 2021-08-01 op }
958 b806d4d5 2021-08-01 op
959 b806d4d5 2021-08-01 op qid_set_from_sb(&wqid[nwqid]);
960 1c08fc54 2021-08-01 op }
961 1c08fc54 2021-08-01 op
962 053e2652 2021-08-01 op if ((qid = qid_from_path(path)) == NULL)
963 eafb23b1 2021-08-01 op fatal("qid_from_fd");
964 1c08fc54 2021-08-01 op
965 1c08fc54 2021-08-01 op if (nf == NULL) {
966 1c08fc54 2021-08-01 op if ((nf = new_fid(qid, newfid)) == NULL)
967 1c08fc54 2021-08-01 op fatal("new_fid");
968 1c08fc54 2021-08-01 op } else {
969 1c08fc54 2021-08-01 op /* swap qid */
970 1c08fc54 2021-08-01 op qid_decref(nf->qid);
971 1c08fc54 2021-08-01 op nf->qid = qid_incref(qid);
972 1c08fc54 2021-08-01 op }
973 1c08fc54 2021-08-01 op
974 1c08fc54 2021-08-01 op np_walk(hdr->tag, nwqid, wqid);
975 1c08fc54 2021-08-01 op
976 1c08fc54 2021-08-01 op return;
977 1c08fc54 2021-08-01 op
978 1c08fc54 2021-08-01 op err:
979 1c08fc54 2021-08-01 op client_send_listener(IMSG_CLOSE, NULL, 0);
980 1c08fc54 2021-08-01 op client_shutdown();
981 1c08fc54 2021-08-01 op }
982 1c08fc54 2021-08-01 op
983 1c08fc54 2021-08-01 op static void
984 e60f4e08 2021-07-30 op handle_message(struct imsg *imsg, size_t len)
985 e60f4e08 2021-07-30 op {
986 e60f4e08 2021-07-30 op struct msg {
987 e60f4e08 2021-07-30 op uint8_t type;
988 e60f4e08 2021-07-30 op void (*fn)(struct np_msg_header *, const uint8_t *, size_t);
989 e60f4e08 2021-07-30 op } msgs[] = {
990 e60f4e08 2021-07-30 op {Tversion, tversion},
991 e60f4e08 2021-07-30 op {Tattach, tattach},
992 c377c1b9 2021-07-30 op {Tclunk, tclunk},
993 36b30273 2021-07-30 op {Tflush, tflush},
994 1c08fc54 2021-08-01 op {Twalk, twalk},
995 e60f4e08 2021-07-30 op };
996 e60f4e08 2021-07-30 op struct np_msg_header hdr;
997 e60f4e08 2021-07-30 op size_t i;
998 e60f4e08 2021-07-30 op uint8_t *data;
999 64c19d90 2021-07-30 op
1000 64c19d90 2021-07-30 op #if DEBUG_PACKETS
1001 78b94752 2021-08-01 op hexdump("incoming packet", imsg->data, len);
1002 64c19d90 2021-07-30 op #endif
1003 e60f4e08 2021-07-30 op
1004 e60f4e08 2021-07-30 op parse_message(imsg->data, len, &hdr, &data);
1005 e60f4e08 2021-07-30 op len -= HEADERSIZE;
1006 e60f4e08 2021-07-30 op
1007 e60f4e08 2021-07-30 op log_debug("got request: len=%d type=%d[%s] tag=%d",
1008 e60f4e08 2021-07-30 op hdr.len, hdr.type, pp_msg_type(hdr.type), hdr.tag);
1009 e0dce04c 2021-07-30 op
1010 e60f4e08 2021-07-30 op if (!handshaked && hdr.type != Tversion) {
1011 e60f4e08 2021-07-30 op client_send_listener(IMSG_CLOSE, NULL, 0);
1012 e60f4e08 2021-07-30 op client_shutdown();
1013 e60f4e08 2021-07-30 op return;
1014 e60f4e08 2021-07-30 op }
1015 e60f4e08 2021-07-30 op
1016 e60f4e08 2021-07-30 op for (i = 0; i < sizeof(msgs)/sizeof(msgs[0]); ++i) {
1017 e60f4e08 2021-07-30 op if (msgs[i].type != hdr.type)
1018 e60f4e08 2021-07-30 op continue;
1019 e60f4e08 2021-07-30 op
1020 e60f4e08 2021-07-30 op msgs[i].fn(&hdr, data, len);
1021 e60f4e08 2021-07-30 op return;
1022 e60f4e08 2021-07-30 op }
1023 e60f4e08 2021-07-30 op
1024 e60f4e08 2021-07-30 op np_error(hdr.tag, "Not supported.");
1025 64c19d90 2021-07-30 op }