1 1.14 andvar /* $NetBSD: nineproto.c,v 1.14 2021/09/03 21:55:01 andvar Exp $ */ 2 1.1 pooka 3 1.1 pooka /* 4 1.1 pooka * Copyright (c) 2007 Antti Kantee. All Rights Reserved. 5 1.1 pooka * 6 1.1 pooka * Redistribution and use in source and binary forms, with or without 7 1.1 pooka * modification, are permitted provided that the following conditions 8 1.1 pooka * are met: 9 1.1 pooka * 1. Redistributions of source code must retain the above copyright 10 1.1 pooka * notice, this list of conditions and the following disclaimer. 11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 pooka * notice, this list of conditions and the following disclaimer in the 13 1.1 pooka * documentation and/or other materials provided with the distribution. 14 1.1 pooka * 15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 pooka * SUCH DAMAGE. 26 1.1 pooka */ 27 1.1 pooka 28 1.1 pooka #include <sys/cdefs.h> 29 1.1 pooka #ifndef lint 30 1.14 andvar __RCSID("$NetBSD: nineproto.c,v 1.14 2021/09/03 21:55:01 andvar Exp $"); 31 1.1 pooka #endif /* !lint */ 32 1.1 pooka 33 1.1 pooka #include <sys/types.h> 34 1.1 pooka 35 1.1 pooka #include <errno.h> 36 1.1 pooka #include <grp.h> 37 1.1 pooka #include <pwd.h> 38 1.1 pooka #include <puffs.h> 39 1.1 pooka #include <stdio.h> 40 1.1 pooka #include <stdlib.h> 41 1.1 pooka 42 1.1 pooka #include "ninepuffs.h" 43 1.1 pooka #include "nineproto.h" 44 1.1 pooka 45 1.1 pooka int 46 1.3 pooka proto_getqid(struct puffs_framebuf *pb, struct qid9p *qid) 47 1.1 pooka { 48 1.1 pooka 49 1.4 pooka if (puffs_framebuf_remaining(pb) < 1+4+8) 50 1.3 pooka return ENOBUFS; 51 1.1 pooka 52 1.1 pooka p9pbuf_get_1(pb, &qid->qidtype); 53 1.1 pooka p9pbuf_get_4(pb, &qid->qidvers); 54 1.1 pooka p9pbuf_get_8(pb, &qid->qidpath); 55 1.1 pooka 56 1.3 pooka return 0; 57 1.1 pooka } 58 1.1 pooka 59 1.1 pooka static uid_t 60 1.1 pooka ustr2uid(char *uid) 61 1.1 pooka { 62 1.1 pooka struct passwd *pw; 63 1.1 pooka 64 1.1 pooka pw = getpwnam(uid); 65 1.1 pooka if (pw == NULL) 66 1.1 pooka return 0; /* XXXXX */ 67 1.1 pooka 68 1.1 pooka return pw->pw_uid; 69 1.1 pooka } 70 1.1 pooka 71 1.1 pooka static gid_t 72 1.1 pooka gstr2gid(char *gid) 73 1.1 pooka { 74 1.1 pooka struct group *grr; 75 1.1 pooka 76 1.1 pooka grr = getgrnam(gid); 77 1.1 pooka if (grr == NULL) 78 1.1 pooka return 0; /* more XXXX */ 79 1.1 pooka 80 1.1 pooka return grr->gr_gid; 81 1.1 pooka } 82 1.1 pooka 83 1.1 pooka static const char * 84 1.1 pooka uid2ustr(uid_t uid) 85 1.1 pooka { 86 1.1 pooka struct passwd *pw; 87 1.1 pooka 88 1.1 pooka pw = getpwuid(uid); 89 1.1 pooka if (pw == NULL) 90 1.1 pooka return "root"; /* XXXXX */ 91 1.1 pooka 92 1.1 pooka return pw->pw_name; 93 1.1 pooka } 94 1.1 pooka 95 1.1 pooka static const char * 96 1.1 pooka gid2gstr(gid_t gid) 97 1.1 pooka { 98 1.1 pooka struct group *grr; 99 1.1 pooka 100 1.1 pooka grr = getgrgid(gid); 101 1.1 pooka if (grr == NULL) 102 1.1 pooka return "wheel"; /* XXXXXX */ 103 1.1 pooka 104 1.1 pooka return grr->gr_name; 105 1.1 pooka } 106 1.1 pooka 107 1.1 pooka #define GETFIELD(a,b,unitsize) \ 108 1.1 pooka do { \ 109 1.3 pooka if (size < unitsize) return EPROTO; \ 110 1.3 pooka if ((rv = (a(pb, b)))) return rv; \ 111 1.1 pooka size -= unitsize; \ 112 1.1 pooka } while (/*CONSTCOND*/0) 113 1.1 pooka #define GETSTR(val,strsize) \ 114 1.1 pooka do { \ 115 1.3 pooka if ((rv = p9pbuf_get_str(pb, val, strsize))) return rv; \ 116 1.3 pooka if (*strsize > size) return EPROTO; \ 117 1.1 pooka size -= *strsize; \ 118 1.1 pooka } while (/*CONSTCOND*/0) 119 1.1 pooka int 120 1.10 ozaki proto_getstat(struct puffs_usermount *pu, struct puffs_framebuf *pb, struct vattr *vap, 121 1.3 pooka char **name, uint16_t *rs) 122 1.1 pooka { 123 1.10 ozaki struct puffs9p *p9p = puffs_getspecific(pu); 124 1.1 pooka char *uid, *gid; 125 1.1 pooka struct qid9p qid; 126 1.1 pooka uint64_t flen; 127 1.1 pooka uint32_t rdev, mode, atime, mtime; 128 1.1 pooka uint16_t size, v16; 129 1.3 pooka int rv; 130 1.1 pooka 131 1.1 pooka /* check size */ 132 1.3 pooka if ((rv = p9pbuf_get_2(pb, &size))) 133 1.3 pooka return rv; 134 1.4 pooka if (puffs_framebuf_remaining(pb) < size) 135 1.3 pooka return ENOBUFS; 136 1.1 pooka 137 1.1 pooka if (rs) 138 1.1 pooka *rs = size+2; /* compensate for size field itself */ 139 1.1 pooka 140 1.1 pooka GETFIELD(p9pbuf_get_2, &v16, 2); 141 1.1 pooka GETFIELD(p9pbuf_get_4, &rdev, 4); 142 1.1 pooka GETFIELD(proto_getqid, &qid, 13); 143 1.1 pooka GETFIELD(p9pbuf_get_4, &mode, 4); 144 1.1 pooka GETFIELD(p9pbuf_get_4, &atime, 4); 145 1.1 pooka GETFIELD(p9pbuf_get_4, &mtime, 4); 146 1.1 pooka GETFIELD(p9pbuf_get_8, &flen, 8); 147 1.1 pooka GETSTR(name, &v16); 148 1.1 pooka GETSTR(&uid, &v16); 149 1.1 pooka GETSTR(&gid, &v16); 150 1.1 pooka 151 1.1 pooka vap->va_rdev = rdev; 152 1.1 pooka vap->va_mode = mode & 0777; /* may contain other uninteresting bits */ 153 1.1 pooka vap->va_atime.tv_sec = atime; 154 1.1 pooka vap->va_mtime.tv_sec = mtime; 155 1.1 pooka vap->va_ctime.tv_sec = mtime; 156 1.1 pooka vap->va_atime.tv_nsec=vap->va_mtime.tv_nsec=vap->va_ctime.tv_nsec = 0; 157 1.1 pooka vap->va_birthtime.tv_sec = vap->va_birthtime.tv_nsec = 0; 158 1.1 pooka vap->va_size = vap->va_bytes = flen; 159 1.1 pooka vap->va_uid = ustr2uid(uid); 160 1.1 pooka vap->va_gid = gstr2gid(gid); 161 1.2 pooka free(uid); 162 1.2 pooka free(gid); 163 1.1 pooka qid2vattr(vap, &qid); 164 1.1 pooka 165 1.1 pooka /* some defaults */ 166 1.1 pooka if (vap->va_type == VDIR) 167 1.1 pooka vap->va_nlink = 1906; 168 1.1 pooka else 169 1.1 pooka vap->va_nlink = 1; 170 1.1 pooka vap->va_blocksize = 512; 171 1.1 pooka vap->va_flags = vap->va_vaflags = 0; 172 1.1 pooka vap->va_filerev = PUFFS_VNOVAL; 173 1.1 pooka 174 1.1 pooka /* muid, not used */ 175 1.1 pooka GETSTR(NULL, &v16); 176 1.10 ozaki if (p9p->protover == P9PROTO_VERSION_U) { 177 1.10 ozaki uint32_t dummy; 178 1.14 andvar GETSTR(NULL, &v16); /* extension[s], not used */ 179 1.10 ozaki GETFIELD(p9pbuf_get_4, &dummy, 4); /* n_uid[4], not used */ 180 1.10 ozaki GETFIELD(p9pbuf_get_4, &dummy, 4); /* n_gid[4], not used */ 181 1.10 ozaki GETFIELD(p9pbuf_get_4, &dummy, 4); /* n_muid[4], not used */ 182 1.10 ozaki } 183 1.1 pooka 184 1.3 pooka return 0; 185 1.1 pooka } 186 1.1 pooka 187 1.11 ozaki static int 188 1.11 ozaki proto_rerror(struct puffs_usermount *pu, struct puffs_framebuf *pb, 189 1.11 ozaki uint32_t *_errno) 190 1.11 ozaki { 191 1.11 ozaki struct puffs9p *p9p = puffs_getspecific(pu); 192 1.11 ozaki uint16_t size; 193 1.11 ozaki int rv; 194 1.11 ozaki char *name; 195 1.11 ozaki 196 1.11 ozaki /* Skip size[4] Rerror tag[2] */ 197 1.11 ozaki rv = puffs_framebuf_seekset(pb, 198 1.11 ozaki sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint16_t)); 199 1.11 ozaki if (rv == -1) 200 1.11 ozaki return EPROTO; 201 1.11 ozaki 202 1.11 ozaki rv = p9pbuf_get_str(pb, &name, &size); 203 1.11 ozaki if (rv != 0) 204 1.11 ozaki return rv; 205 1.11 ozaki if (p9p->protover == P9PROTO_VERSION_U) { 206 1.11 ozaki rv = p9pbuf_get_4(pb, _errno); 207 1.11 ozaki } else { 208 1.11 ozaki /* TODO Convert error string to errno */ 209 1.11 ozaki rv = EPROTO; 210 1.11 ozaki } 211 1.11 ozaki 212 1.11 ozaki return rv; 213 1.11 ozaki } 214 1.11 ozaki 215 1.11 ozaki int 216 1.11 ozaki proto_handle_rerror(struct puffs_usermount *pu, struct puffs_framebuf *pb) 217 1.11 ozaki { 218 1.11 ozaki int rv; 219 1.11 ozaki uint32_t _errno; 220 1.11 ozaki 221 1.11 ozaki if (p9pbuf_get_type(pb) != P9PROTO_R_ERROR) 222 1.11 ozaki return EPROTO; 223 1.11 ozaki 224 1.11 ozaki rv = proto_rerror(pu, pb, &_errno); 225 1.11 ozaki if (rv == 0) 226 1.11 ozaki rv = _errno; 227 1.11 ozaki return rv; 228 1.11 ozaki } 229 1.11 ozaki 230 1.1 pooka int 231 1.9 pooka proto_cc_dupfid(struct puffs_usermount *pu, p9pfid_t oldfid, p9pfid_t newfid) 232 1.1 pooka { 233 1.9 pooka struct puffs_cc *pcc = puffs_cc_getcc(pu); 234 1.9 pooka struct puffs9p *p9p = puffs_getspecific(pu); 235 1.3 pooka struct puffs_framebuf *pb; 236 1.13 uwe p9ptag_t tag; 237 1.1 pooka uint16_t qids; 238 1.7 pooka int rv = 0; 239 1.1 pooka 240 1.3 pooka pb = p9pbuf_makeout(); 241 1.13 uwe tag = NEXTTAG(p9p); 242 1.1 pooka p9pbuf_put_1(pb, P9PROTO_T_WALK); 243 1.1 pooka p9pbuf_put_2(pb, tag); 244 1.1 pooka p9pbuf_put_4(pb, oldfid); 245 1.1 pooka p9pbuf_put_4(pb, newfid); 246 1.1 pooka p9pbuf_put_2(pb, 0); 247 1.6 pooka GETRESPONSE(pb); 248 1.1 pooka 249 1.11 ozaki rv = proto_expect_walk_nqids(pu, pb, &qids); 250 1.7 pooka if (rv == 0 && qids != 0) 251 1.7 pooka rv = EPROTO; 252 1.1 pooka 253 1.7 pooka out: 254 1.3 pooka puffs_framebuf_destroy(pb); 255 1.7 pooka return rv; 256 1.1 pooka } 257 1.1 pooka 258 1.1 pooka int 259 1.9 pooka proto_cc_clunkfid(struct puffs_usermount *pu, p9pfid_t fid, int waitforit) 260 1.1 pooka { 261 1.9 pooka struct puffs_cc *pcc = puffs_cc_getcc(pu); 262 1.9 pooka struct puffs9p *p9p = puffs_getspecific(pu); 263 1.3 pooka struct puffs_framebuf *pb; 264 1.13 uwe p9ptag_t tag; 265 1.7 pooka int rv = 0; 266 1.1 pooka 267 1.3 pooka pb = p9pbuf_makeout(); 268 1.13 uwe tag = NEXTTAG(p9p); 269 1.1 pooka p9pbuf_put_1(pb, P9PROTO_T_CLUNK); 270 1.1 pooka p9pbuf_put_2(pb, tag); 271 1.1 pooka p9pbuf_put_4(pb, fid); 272 1.1 pooka 273 1.1 pooka if (waitforit) { 274 1.8 pooka if (puffs_framev_enqueue_cc(pcc, p9p->servsock, pb, 0) == 0) { 275 1.7 pooka if (p9pbuf_get_type(pb) != P9PROTO_R_CLUNK) 276 1.11 ozaki rv = proto_handle_rerror(pu, pb); 277 1.7 pooka } else { 278 1.7 pooka rv = errno; 279 1.7 pooka } 280 1.3 pooka puffs_framebuf_destroy(pb); 281 1.1 pooka } else { 282 1.6 pooka JUSTSEND(pb); 283 1.1 pooka } 284 1.1 pooka 285 1.7 pooka out: 286 1.7 pooka return rv; 287 1.1 pooka } 288 1.1 pooka 289 1.1 pooka /* 290 1.1 pooka * walk a new fid, then open it 291 1.1 pooka */ 292 1.1 pooka int 293 1.9 pooka proto_cc_open(struct puffs_usermount *pu, p9pfid_t fid, 294 1.9 pooka p9pfid_t newfid, int mode) 295 1.1 pooka { 296 1.9 pooka struct puffs_cc *pcc = puffs_cc_getcc(pu); 297 1.9 pooka struct puffs9p *p9p = puffs_getspecific(pu); 298 1.3 pooka struct puffs_framebuf *pb; 299 1.13 uwe p9ptag_t tag; 300 1.7 pooka int rv; 301 1.1 pooka 302 1.9 pooka rv = proto_cc_dupfid(pu, fid, newfid); 303 1.7 pooka if (rv) 304 1.7 pooka return rv; 305 1.1 pooka 306 1.3 pooka pb = p9pbuf_makeout(); 307 1.13 uwe tag = NEXTTAG(p9p); 308 1.1 pooka p9pbuf_put_1(pb, P9PROTO_T_OPEN); 309 1.1 pooka p9pbuf_put_2(pb, tag); 310 1.1 pooka p9pbuf_put_4(pb, newfid); 311 1.1 pooka p9pbuf_put_1(pb, mode); 312 1.6 pooka GETRESPONSE(pb); 313 1.3 pooka if (p9pbuf_get_type(pb) != P9PROTO_R_OPEN) 314 1.11 ozaki rv = proto_handle_rerror(pu, pb); 315 1.1 pooka 316 1.7 pooka out: 317 1.3 pooka puffs_framebuf_destroy(pb); 318 1.7 pooka return rv; 319 1.1 pooka } 320 1.1 pooka 321 1.1 pooka void 322 1.10 ozaki proto_make_stat(struct puffs_usermount *pu, struct puffs_framebuf *pb, 323 1.10 ozaki const struct vattr *vap, const char *filename, enum vtype vt) 324 1.1 pooka { 325 1.10 ozaki struct puffs9p *p9p = puffs_getspecific(pu); 326 1.1 pooka struct vattr fakeva; 327 1.1 pooka uint32_t mode, atime, mtime; 328 1.1 pooka uint64_t flen; 329 1.1 pooka const char *owner, *group; 330 1.1 pooka int startoff, curoff; 331 1.1 pooka 332 1.1 pooka if (vap == NULL) { 333 1.1 pooka puffs_vattr_null(&fakeva); 334 1.1 pooka vap = &fakeva; 335 1.1 pooka } 336 1.1 pooka 337 1.3 pooka startoff = puffs_framebuf_telloff(pb); 338 1.3 pooka puffs_framebuf_seekset(pb, startoff + 2+2); /* stat[n] incl. stat[2] */ 339 1.1 pooka 340 1.1 pooka if (vap->va_mode != (mode_t)PUFFS_VNOVAL) 341 1.5 pooka mode = vap->va_mode | (vt == VDIR ? P9PROTO_CPERM_DIR : 0); 342 1.1 pooka else 343 1.1 pooka mode = P9PROTO_STAT_NOVAL4; 344 1.1 pooka if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) 345 1.1 pooka atime = vap->va_atime.tv_sec; 346 1.1 pooka else 347 1.1 pooka atime = P9PROTO_STAT_NOVAL4; 348 1.1 pooka if (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL) 349 1.1 pooka mtime = vap->va_mtime.tv_sec; 350 1.1 pooka else 351 1.1 pooka mtime = P9PROTO_STAT_NOVAL4; 352 1.1 pooka if (vap->va_size != (u_quad_t)PUFFS_VNOVAL) 353 1.1 pooka flen = vap->va_size; 354 1.1 pooka else 355 1.1 pooka flen = P9PROTO_STAT_NOVAL8; 356 1.1 pooka if (vap->va_uid != (uid_t)PUFFS_VNOVAL) 357 1.1 pooka owner = uid2ustr(vap->va_uid); 358 1.1 pooka else 359 1.1 pooka owner = ""; 360 1.1 pooka if (vap->va_gid != (gid_t)PUFFS_VNOVAL) 361 1.1 pooka group = gid2gstr(vap->va_gid); 362 1.1 pooka else 363 1.1 pooka group = ""; 364 1.1 pooka 365 1.1 pooka p9pbuf_put_2(pb, P9PROTO_STAT_NOVAL2); /* kernel type */ 366 1.1 pooka p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* dev */ 367 1.1 pooka p9pbuf_put_1(pb, P9PROTO_STAT_NOVAL1); /* type */ 368 1.1 pooka p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* version */ 369 1.1 pooka p9pbuf_put_8(pb, P9PROTO_STAT_NOVAL8); /* path */ 370 1.1 pooka p9pbuf_put_4(pb, mode); 371 1.1 pooka p9pbuf_put_4(pb, atime); 372 1.1 pooka p9pbuf_put_4(pb, mtime); 373 1.1 pooka p9pbuf_put_8(pb, flen); 374 1.1 pooka p9pbuf_put_str(pb, filename ? filename : ""); 375 1.1 pooka p9pbuf_put_str(pb, owner); 376 1.1 pooka p9pbuf_put_str(pb, group); 377 1.1 pooka p9pbuf_put_str(pb, ""); /* muid */ 378 1.10 ozaki if (p9p->protover == P9PROTO_VERSION_U) { 379 1.14 andvar p9pbuf_put_str(pb, P9PROTO_STAT_NOSTR); /* extensions[s] */ 380 1.10 ozaki p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* n_uid[4] */ 381 1.10 ozaki p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* n_gid[4] */ 382 1.10 ozaki p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* n_muid[4] */ 383 1.10 ozaki } 384 1.1 pooka 385 1.3 pooka curoff = puffs_framebuf_telloff(pb); 386 1.3 pooka puffs_framebuf_seekset(pb, startoff); 387 1.1 pooka p9pbuf_put_2(pb, curoff-(startoff+2)); /* stat[n] size */ 388 1.1 pooka p9pbuf_put_2(pb, curoff-(startoff+4)); /* size[2] stat */ 389 1.1 pooka 390 1.3 pooka puffs_framebuf_seekset(pb, curoff); 391 1.1 pooka } 392 1.1 pooka 393 1.1 pooka int 394 1.11 ozaki proto_expect_walk_nqids(struct puffs_usermount *pu, struct puffs_framebuf *pb, 395 1.11 ozaki uint16_t *nqids) 396 1.1 pooka { 397 1.1 pooka 398 1.3 pooka if (p9pbuf_get_type(pb) != P9PROTO_R_WALK) 399 1.11 ozaki return proto_handle_rerror(pu, pb); 400 1.3 pooka return p9pbuf_get_2(pb, nqids); 401 1.1 pooka } 402 1.1 pooka 403 1.1 pooka int 404 1.11 ozaki proto_expect_qid(struct puffs_usermount *pu, struct puffs_framebuf *pb, 405 1.11 ozaki uint8_t op, struct qid9p *qid) 406 1.1 pooka { 407 1.1 pooka 408 1.3 pooka if (p9pbuf_get_type(pb) != op) 409 1.11 ozaki return proto_handle_rerror(pu, pb); 410 1.3 pooka return proto_getqid(pb, qid); 411 1.1 pooka } 412 1.1 pooka 413 1.1 pooka int 414 1.10 ozaki proto_expect_stat(struct puffs_usermount *pu, struct puffs_framebuf *pb, 415 1.10 ozaki struct vattr *va) 416 1.1 pooka { 417 1.1 pooka uint16_t dummy; 418 1.3 pooka int rv; 419 1.1 pooka 420 1.3 pooka if (p9pbuf_get_type(pb) != P9PROTO_R_STAT) 421 1.11 ozaki return proto_handle_rerror(pu, pb); 422 1.3 pooka if ((rv = p9pbuf_get_2(pb, &dummy))) 423 1.3 pooka return rv; 424 1.10 ozaki return proto_getstat(pu, pb, va, NULL, NULL); 425 1.1 pooka } 426