2 8d1b399b 2021-07-22 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
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.
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.
17 8d1b399b 2021-07-22 op #include "compat.h"
19 c5d518da 2021-07-29 op #include <sys/stat.h>
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>
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"
37 2adb951f 2021-08-01 op #define DEBUG_PACKETS 0
39 c5d518da 2021-07-29 op STAILQ_HEAD(qidhead, qid) qids;
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;
49 053e2652 2021-08-01 op char fpath[PATH_MAX];
50 1c08fc54 2021-08-01 op struct stat sb;
52 c5d518da 2021-07-29 op STAILQ_ENTRY(qid) entries;
55 c5d518da 2021-07-29 op STAILQ_HEAD(fidhead, fid) fids;
59 c5d518da 2021-07-29 op struct qid *qid;
60 c5d518da 2021-07-29 op STAILQ_ENTRY(fid) entries;
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;
67 5c420a81 2021-07-30 op static int handshaked, attached;
68 5c485996 2021-07-28 op uint32_t msize;
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 *);
75 2ef72ade 2021-07-28 op static int client_send_listener(int, const void *, uint16_t);
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 *);
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 *);
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 **);
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);
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);
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 *);
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 *);
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)
122 48192874 2021-08-01 op #define NPREADSTR(f, b, bl, src, len) np_readstr(__func__, f, b, bl, src, len)
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);
131 06a84967 2021-07-22 op ATTR_DEAD void
132 8d1b399b 2021-07-22 op client(int debug, int verbose)
134 8d1b399b 2021-07-22 op struct event ev_sigint, ev_sigterm;
136 8d1b399b 2021-07-22 op log_init(debug, LOG_DAEMON);
137 8d1b399b 2021-07-22 op log_setverbose(verbose);
139 8d1b399b 2021-07-22 op setproctitle("client");
140 8d1b399b 2021-07-22 op log_procinit("client");
142 8d1b399b 2021-07-22 op log_debug("warming up");
144 8d1b399b 2021-07-22 op event_init();
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);
150 8d1b399b 2021-07-22 op signal_add(&ev_sigint, NULL);
151 8d1b399b 2021-07-22 op signal_add(&ev_sigterm, NULL);
153 8d1b399b 2021-07-22 op signal(SIGPIPE, SIG_IGN);
154 8d1b399b 2021-07-22 op signal(SIGHUP, SIG_IGN);
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)
160 8d1b399b 2021-07-22 op imsg_init(&iev_listener->ibuf, 3);
161 8d1b399b 2021-07-22 op iev_listener->handler = client_dispatch_listener;
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);
169 8d1b399b 2021-07-22 op event_dispatch();
170 8d1b399b 2021-07-22 op client_shutdown();
173 06a84967 2021-07-22 op static ATTR_DEAD void
174 8d1b399b 2021-07-22 op client_shutdown(void)
176 2ef72ade 2021-07-28 op if (evb != NULL)
177 2ef72ade 2021-07-28 op evbuffer_free(evb);
179 8d1b399b 2021-07-22 op msgbuf_clear(&iev_listener->ibuf.w);
180 8d1b399b 2021-07-22 op close(iev_listener->ibuf.fd);
182 8d1b399b 2021-07-22 op free(iev_listener);
184 223c9e73 2021-08-06 op log_debug("client exiting");
189 8d1b399b 2021-07-22 op client_sig_handler(int sig, short event, void *d)
192 8d1b399b 2021-07-22 op * Normal signal handler rules don't apply because libevent
193 8d1b399b 2021-07-22 op * decouples for us.
196 8d1b399b 2021-07-22 op switch (sig) {
198 8d1b399b 2021-07-22 op case SIGTERM:
199 8d1b399b 2021-07-22 op client_shutdown();
201 8d1b399b 2021-07-22 op fatalx("unexpected signal %d", sig);
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
210 8d1b399b 2021-07-22 op client_dispatch_listener(int fd, short event, void *d)
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;
219 8d1b399b 2021-07-22 op int shut = 0;
221 8d1b399b 2021-07-22 op ibuf = &iev->ibuf;
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 */
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 */
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. */
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;
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));
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",
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));
262 8d1b399b 2021-07-22 op case IMSG_BUF:
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));
269 8d1b399b 2021-07-22 op case IMSG_CONN_GONE:
270 8d1b399b 2021-07-22 op log_debug("closing");
274 8d1b399b 2021-07-22 op log_debug("%s: unexpected imsg %d",
275 8d1b399b 2021-07-22 op __func__, imsg.hdr.type);
278 8d1b399b 2021-07-22 op imsg_free(&imsg);
282 8d1b399b 2021-07-22 op imsg_event_add(iev);
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 223c9e73 2021-08-06 op log_debug("pipe closed, shutting down...");
287 8d1b399b 2021-07-22 op event_loopexit(NULL);
292 8d1b399b 2021-07-22 op client_privdrop(const char *username, const char *dir)
294 8d1b399b 2021-07-22 op struct passwd *pw;
296 8d1b399b 2021-07-22 op setproctitle("client %s", username);
298 8d1b399b 2021-07-22 op if ((pw = getpwnam(username)) == NULL)
299 8d1b399b 2021-07-22 op fatalx("getpwnam(%s) failed", username);
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(\"/\")");
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");
311 8d1b399b 2021-07-22 op sandbox_client();
312 66a9a40a 2021-07-28 op log_debug("client ready; user=%s dir=%s", username, dir);
314 2ef72ade 2021-07-28 op if ((evb = evbuffer_new()) == NULL)
315 2ef72ade 2021-07-28 op fatal("evbuffer_new");
319 2ef72ade 2021-07-28 op client_send_listener(int type, const void *data, uint16_t len)
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);
330 053e2652 2021-08-01 op /* set qid fields from the sb field */
332 053e2652 2021-08-01 op qid_set_from_sb(struct qid *qid)
334 1c08fc54 2021-08-01 op qid->path = qid->sb.st_ino;
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.
340 1c08fc54 2021-08-01 op qid->vers = qid->sb.st_mtim.tv_sec;
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;
350 053e2652 2021-08-01 op /* update qid info */
352 053e2652 2021-08-01 op qid_update_stat(struct qid *qid)
354 053e2652 2021-08-01 op if (fstat(qid->fd, &qid->sb) == -1)
357 053e2652 2021-08-01 op qid_set_from_sb(qid);
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)
365 053e2652 2021-08-01 op struct qid *q;
367 053e2652 2021-08-01 op if ((q = calloc(1, sizeof(*q))) == NULL)
371 053e2652 2021-08-01 op memcpy(q->fpath, qid->fpath, sizeof(q->fpath));
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));
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)
385 c5d518da 2021-07-29 op struct qid *qid;
387 c5d518da 2021-07-29 op if ((qid = calloc(1, sizeof(*qid))) == NULL)
390 c5d518da 2021-07-29 op qid->fd = fd;
391 1c08fc54 2021-08-01 op qid_update_stat(qid);
393 053e2652 2021-08-01 op STAILQ_INSERT_HEAD(&qids, qid, entries);
398 c377c1b9 2021-07-30 op static struct qid *
399 053e2652 2021-08-01 op qid_from_path(const char *path)
401 053e2652 2021-08-01 op struct qid *qid;
403 053e2652 2021-08-01 op if ((qid = calloc(1, sizeof(*qid))) == NULL)
406 053e2652 2021-08-01 op qid->fd = -1;
408 053e2652 2021-08-01 op if (stat(path, &qid->sb) == -1) {
413 053e2652 2021-08-01 op qid_set_from_sb(qid);
415 053e2652 2021-08-01 op STAILQ_INSERT_HEAD(&qids, qid, entries);
420 053e2652 2021-08-01 op static struct qid *
421 c377c1b9 2021-07-30 op qid_incref(struct qid *qid)
423 c377c1b9 2021-07-30 op qid->refcount++;
428 c377c1b9 2021-07-30 op qid_decref(struct qid *qid)
430 c377c1b9 2021-07-30 op if (--qid->refcount > 0)
433 c377c1b9 2021-07-30 op STAILQ_REMOVE(&qids, qid, qid, entries);
435 c377c1b9 2021-07-30 op close(qid->fd);
438 c377c1b9 2021-07-30 op if (STAILQ_EMPTY(&qids))
439 c377c1b9 2021-07-30 op attached = 0;
442 c5d518da 2021-07-29 op static struct fid *
443 c5d518da 2021-07-29 op new_fid(struct qid *qid, uint32_t fid)
445 c5d518da 2021-07-29 op struct fid *f;
447 c5d518da 2021-07-29 op if ((f = calloc(1, sizeof(*f))) == NULL)
450 c377c1b9 2021-07-30 op f->qid = qid_incref(qid);
451 c5d518da 2021-07-29 op f->fid = fid;
453 c5d518da 2021-07-29 op STAILQ_INSERT_HEAD(&fids, f, entries);
458 c377c1b9 2021-07-30 op static struct fid *
459 c377c1b9 2021-07-30 op fid_by_id(uint32_t fid)
461 c377c1b9 2021-07-30 op struct fid *f;
463 c377c1b9 2021-07-30 op STAILQ_FOREACH(f, &fids, entries) {
464 c377c1b9 2021-07-30 op if (f->fid == fid)
472 c377c1b9 2021-07-30 op free_fid(struct fid *f)
474 c377c1b9 2021-07-30 op qid_decref(f->qid);
476 c377c1b9 2021-07-30 op STAILQ_REMOVE(&fids, f, fid, entries);
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)
484 48192874 2021-08-01 op size_t olen = len;
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))
491 48192874 2021-08-01 op if (olen != hdr->len)
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* */
500 23e03c88 2021-07-26 op hdr->tag = le32toh(hdr->tag);
502 48192874 2021-08-01 op *cnt = (uint8_t *)data;
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");
511 83f6b305 2021-08-01 op np_write16(uint16_t x)
513 83f6b305 2021-08-01 op x = htole16(x);
514 83f6b305 2021-08-01 op evbuffer_add(evb, &x, sizeof(x));
518 2ef72ade 2021-07-28 op np_header(uint32_t len, uint8_t type, uint16_t tag)
520 9ebb95a7 2021-07-30 op len += HEADERSIZE;
522 63f681aa 2021-07-28 op len = htole32(len);
523 63f681aa 2021-07-28 op tag = htole16(tag);
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));
531 5c485996 2021-07-28 op np_string(uint16_t len, const char *str)
533 5c485996 2021-07-28 op uint16_t l = len;
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);
541 c5d518da 2021-07-29 op np_qid(struct qid *qid)
543 c5d518da 2021-07-29 op uint64_t path;
544 c5d518da 2021-07-29 op uint32_t vers;
546 c5d518da 2021-07-29 op path = htole64(qid->path);
547 c5d518da 2021-07-29 op vers = htole32(qid->vers);
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));
555 2ef72ade 2021-07-28 op do_send(void)
560 2ef72ade 2021-07-28 op len = EVBUFFER_LENGTH(evb);
561 64c19d90 2021-07-30 op data = EVBUFFER_DATA(evb);
563 64c19d90 2021-07-30 op #if DEBUG_PACKETS
564 78b94752 2021-08-01 op hexdump("outgoing packet", data, len);
566 64c19d90 2021-07-30 op client_send_listener(IMSG_BUF, data, len);
567 2ef72ade 2021-07-28 op evbuffer_drain(evb, len);
571 5c485996 2021-07-28 op np_version(uint16_t tag, uint32_t msize, const char *version)
575 5c485996 2021-07-28 op l = strlen(version);
577 5c485996 2021-07-28 op msize = htole32(msize);
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);
586 c5d518da 2021-07-29 op np_attach(uint16_t tag, struct qid *qid)
588 9ebb95a7 2021-07-30 op np_header(QIDSIZE, Rattach, tag);
594 c377c1b9 2021-07-30 op np_clunk(uint16_t tag)
596 9ebb95a7 2021-07-30 op np_header(0, Rclunk, tag);
601 36b30273 2021-07-30 op np_flush(uint16_t tag)
603 9ebb95a7 2021-07-30 op np_header(0, Rflush, tag);
608 1c08fc54 2021-08-01 op np_walk(uint16_t tag, int nwqid, struct qid *wqid)
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);
622 2ef72ade 2021-07-28 op np_error(uint16_t tag, const char *errstr)
626 2ef72ade 2021-07-28 op l = strlen(errstr);
628 9ebb95a7 2021-07-30 op np_header(sizeof(l) + l, Rerror, tag);
629 5c485996 2021-07-28 op np_string(l, errstr);
634 c5d518da 2021-07-29 op np_errno(uint16_t tag)
636 9b088310 2021-07-30 op int saved_errno;
637 c5d518da 2021-07-29 op char buf[64];
639 9b088310 2021-07-30 op saved_errno = errno;
641 c5d518da 2021-07-29 op strerror_r(errno, buf, sizeof(buf));
642 c5d518da 2021-07-29 op np_error(tag, buf);
644 9b088310 2021-07-30 op errno = saved_errno;
648 48192874 2021-08-01 op np_read8(const char *t, const char *f, uint8_t *dst, const uint8_t **src,
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);
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);
665 48192874 2021-08-01 op np_read16(const char *t, const char *f, uint16_t *dst, const uint8_t **src,
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);
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);
683 48192874 2021-08-01 op np_read32(const char *t, const char *f, uint32_t *dst, const uint8_t **src,
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);
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);
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)
705 48192874 2021-08-01 op char buf[32];
707 48192874 2021-08-01 op strlcpy(buf, f, sizeof(buf));
708 48192874 2021-08-01 op strlcat(buf, "-len", sizeof(buf));
710 48192874 2021-08-01 op if (!np_read16(t, buf, &sl, src, len))
711 48192874 2021-08-01 op return READSTRERR;
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;
719 48192874 2021-08-01 op if (*len > reslen-1)
720 48192874 2021-08-01 op return READSTRTRUNC;
722 48192874 2021-08-01 op memcpy(res, *src, sl);
723 48192874 2021-08-01 op res[sl] = '\0';
731 e60f4e08 2021-07-30 op tversion(struct np_msg_header *hdr, const uint8_t *data, size_t len)
733 48192874 2021-08-01 op char *dot, version[32];
735 e60f4e08 2021-07-30 op if (handshaked)
738 3d20424d 2021-08-01 op /* msize[4] version[s] */
739 48192874 2021-08-01 op if (!NPREAD32("msize", &msize, &data, &len))
742 48192874 2021-08-01 op switch (NPREADSTR("version", version, sizeof(version), &data, &len)) {
743 48192874 2021-08-01 op case READSTRERR:
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;
750 48192874 2021-08-01 op if ((dot = strchr(version, '.')) != NULL)
753 48192874 2021-08-01 op if (strcmp(version, VERSION9P) != 0 ||
755 48192874 2021-08-01 op goto mismatch;
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);
765 48192874 2021-08-01 op log_warnx("unknown 9P version string: \"%s\", want "VERSION9P,
767 48192874 2021-08-01 op np_version(hdr->tag, MSIZE9P, "unknown");
771 e60f4e08 2021-07-30 op client_send_listener(IMSG_CLOSE, NULL, 0);
772 e60f4e08 2021-07-30 op client_shutdown();
776 e60f4e08 2021-07-30 op tattach(struct np_msg_header *hdr, const uint8_t *data, size_t len)
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];
783 e60f4e08 2021-07-30 op if (attached) {
784 e60f4e08 2021-07-30 op np_error(hdr->tag, "already attached");
788 e60f4e08 2021-07-30 op /* fid[4] afid[4] uname[s] aname[s] */
790 48192874 2021-08-01 op if (!NPREAD32("fid", &fid, &data, &len) ||
791 48192874 2021-08-01 op !NPREAD32("afid", &afid, &data, &len))
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:
798 48192874 2021-08-01 op case READSTRTRUNC:
799 48192874 2021-08-01 op np_error(hdr->tag, "name too long");
803 48192874 2021-08-01 op switch (NPREADSTR("aname", aname, sizeof(aname), &data, &len)) {
804 48192874 2021-08-01 op case READSTRERR:
806 48192874 2021-08-01 op case READSTRTRUNC:
807 014adfc2 2021-07-30 op np_error(hdr->tag, "name too long");
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));
816 014adfc2 2021-07-30 op log_debug("attached %s", aname);
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");
824 e60f4e08 2021-07-30 op np_attach(hdr->tag, qid);
825 e60f4e08 2021-07-30 op attached = 1;
829 014adfc2 2021-07-30 op client_send_listener(IMSG_CLOSE, NULL, 0);
830 014adfc2 2021-07-30 op client_shutdown();
834 c377c1b9 2021-07-30 op tclunk(struct np_msg_header *hdr, const uint8_t *data, size_t len)
836 c377c1b9 2021-07-30 op struct fid *f;
837 c377c1b9 2021-07-30 op uint32_t fid;
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();
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");
852 c377c1b9 2021-07-30 op np_clunk(hdr->tag);
856 36b30273 2021-07-30 op tflush(struct np_msg_header *hdr, const uint8_t *data, size_t len)
858 36b30273 2021-07-30 op uint16_t oldtag;
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.
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();
874 36b30273 2021-07-30 op np_flush(hdr->tag);
878 1c08fc54 2021-08-01 op twalk(struct np_msg_header *hdr, const uint8_t *data, size_t len)
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];
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))
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);
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");
903 1c08fc54 2021-08-01 op if (fid == newfid)
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");
911 913eba5c 2021-08-01 op /* special case: fid duplication */
912 22dfb5a0 2021-08-01 op if (nwname == 0) {
914 1c08fc54 2021-08-01 op * TODO: should we forbid fids duplication when fid ==
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");
923 1c08fc54 2021-08-01 op np_walk(hdr->tag, 1, f->qid);
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");
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");
937 053e2652 2021-08-01 op strlcpy(path, f->qid->fpath, sizeof(path));
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:
943 48192874 2021-08-01 op case READSTRTRUNC:
944 1c08fc54 2021-08-01 op np_error(hdr->tag, "wname too long");
948 053e2652 2021-08-01 op strlcat(path, "/", sizeof(path));
949 053e2652 2021-08-01 op strlcat(path, wnam, sizeof(path));
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);
955 1c08fc54 2021-08-01 op np_walk(hdr->tag, nwqid, wqid);
959 b806d4d5 2021-08-01 op qid_set_from_sb(&wqid[nwqid]);
962 053e2652 2021-08-01 op if ((qid = qid_from_path(path)) == NULL)
963 eafb23b1 2021-08-01 op fatal("qid_from_fd");
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");
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);
974 1c08fc54 2021-08-01 op np_walk(hdr->tag, nwqid, wqid);
979 1c08fc54 2021-08-01 op client_send_listener(IMSG_CLOSE, NULL, 0);
980 1c08fc54 2021-08-01 op client_shutdown();
984 e60f4e08 2021-07-30 op handle_message(struct imsg *imsg, size_t len)
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);
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},
996 e60f4e08 2021-07-30 op struct np_msg_header hdr;
998 e60f4e08 2021-07-30 op uint8_t *data;
1000 64c19d90 2021-07-30 op #if DEBUG_PACKETS
1001 78b94752 2021-08-01 op hexdump("incoming packet", imsg->data, len);
1004 e60f4e08 2021-07-30 op parse_message(imsg->data, len, &hdr, &data);
1005 e60f4e08 2021-07-30 op len -= HEADERSIZE;
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);
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();
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)
1020 e60f4e08 2021-07-30 op msgs[i].fn(&hdr, data, len);
1024 e60f4e08 2021-07-30 op np_error(hdr.tag, "Not supported.");