1 /* $NetBSD: ninebuf.c,v 1.10 2025/12/22 16:30:49 nia Exp $ */ 2 3 /* 4 * Copyright (c) 2006, 2007 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 #ifndef lint 30 __RCSID("$NetBSD: ninebuf.c,v 1.10 2025/12/22 16:30:49 nia Exp $"); 31 #endif /* !lint */ 32 33 #include <sys/types.h> 34 #include <sys/time.h> 35 #include <sys/vnode.h> 36 #include <sys/socket.h> 37 38 #include <err.h> 39 #include <errno.h> 40 #include <endian.h> 41 #include <stdlib.h> 42 #include <util.h> 43 #include <unistd.h> 44 45 #include "ninepuffs.h" 46 47 #define CHECK(v) if (!(v)) abort() 48 49 uint8_t 50 p9pbuf_get_type(struct puffs_framebuf *pb) 51 { 52 uint8_t val; 53 54 puffs_framebuf_getdata_atoff(pb, 4, &val, 1); 55 return val; 56 } 57 58 uint16_t 59 p9pbuf_get_tag(struct puffs_framebuf *pb) 60 { 61 uint16_t val; 62 63 puffs_framebuf_getdata_atoff(pb, 5, &val, 2); 64 return le16toh(val); 65 } 66 67 static uint32_t 68 p9pbuf_get_len(struct puffs_framebuf *pb) 69 { 70 uint32_t val; 71 72 puffs_framebuf_getdata_atoff(pb, 0, &val, 4); 73 return le32toh(val); 74 } 75 76 #define CUROFF(pb) (puffs_framebuf_telloff(pb)) 77 int 78 p9pbuf_read(struct puffs_usermount *pu, struct puffs_framebuf *pb, 79 int fd, int *done) 80 { 81 void *win; 82 ssize_t n; 83 size_t howmuch, winlen; 84 int lenstate; 85 86 the_next_level: 87 if ((lenstate = (CUROFF(pb) < 4))) 88 howmuch = 4 - CUROFF(pb); 89 else 90 howmuch = p9pbuf_get_len(pb) - CUROFF(pb); 91 92 if (puffs_framebuf_reserve_space(pb, howmuch) == -1) 93 return errno; 94 95 while (howmuch) { 96 winlen = howmuch; 97 if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1) 98 return errno; 99 n = read(fd, win, winlen); 100 switch (n) { 101 case 0: 102 return ECONNRESET; 103 case -1: 104 if (errno == EAGAIN) 105 return 0; 106 return errno; 107 default: 108 howmuch -= n; 109 puffs_framebuf_seekset(pb, CUROFF(pb) + n); 110 break; 111 } 112 } 113 114 if (!lenstate) { 115 puffs_framebuf_seekset(pb, 7); 116 *done = 1; 117 return 0; 118 } else 119 goto the_next_level; 120 } 121 122 int 123 p9pbuf_write(struct puffs_usermount *pu, struct puffs_framebuf *pb, 124 int fd, int *done) 125 { 126 void *win; 127 ssize_t n; 128 size_t winlen, howmuch; 129 130 if (CUROFF(pb) == 0) { 131 uint32_t len; 132 133 len = htole32(puffs_framebuf_tellsize(pb)); 134 puffs_framebuf_putdata_atoff(pb, 0, &len, 4); 135 } 136 137 howmuch = puffs_framebuf_tellsize(pb) - CUROFF(pb); 138 while (howmuch) { 139 winlen = howmuch; 140 if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1) 141 return errno; 142 n = write(fd, win, winlen); 143 switch (n) { 144 case 0: 145 return ECONNRESET; 146 case -1: 147 if (errno == EAGAIN) 148 return 0; 149 return errno; 150 default: 151 howmuch -= n; 152 puffs_framebuf_seekset(pb, CUROFF(pb) + n); 153 break; 154 } 155 } 156 157 *done = 1; 158 return 0; 159 } 160 #undef CUROFF 161 162 int 163 p9pbuf_cmp(struct puffs_usermount *pu, 164 struct puffs_framebuf *c1, struct puffs_framebuf *c2, int *notresp) 165 { 166 167 return p9pbuf_get_tag(c1) != p9pbuf_get_tag(c2); 168 } 169 170 struct puffs_framebuf * 171 p9pbuf_makeout() 172 { 173 struct puffs_framebuf *pb; 174 175 pb = puffs_framebuf_make(); 176 puffs_framebuf_seekset(pb, 4); 177 return pb; 178 } 179 180 void 181 p9pbuf_recycleout(struct puffs_framebuf *pb) 182 { 183 184 puffs_framebuf_recycle(pb); 185 puffs_framebuf_seekset(pb, 4); 186 } 187 188 void 189 p9pbuf_put_1(struct puffs_framebuf *pb, uint8_t val) 190 { 191 int rv; 192 193 rv = puffs_framebuf_putdata(pb, &val, 1); 194 CHECK(rv == 0); 195 } 196 197 void 198 p9pbuf_put_2(struct puffs_framebuf *pb, uint16_t val) 199 { 200 int rv; 201 202 HTOLE16(val); 203 rv = puffs_framebuf_putdata(pb, &val, 2); 204 CHECK(rv == 0); 205 } 206 207 void 208 p9pbuf_put_4(struct puffs_framebuf *pb, uint32_t val) 209 { 210 int rv; 211 212 HTOLE32(val); 213 rv = puffs_framebuf_putdata(pb, &val, 4); 214 CHECK(rv == 0); 215 } 216 217 void 218 p9pbuf_put_8(struct puffs_framebuf *pb, uint64_t val) 219 { 220 int rv; 221 222 HTOLE64(val); 223 rv = puffs_framebuf_putdata(pb, &val, 8); 224 CHECK(rv == 0); 225 } 226 227 void 228 p9pbuf_put_data(struct puffs_framebuf *pb, const void *data, uint16_t dlen) 229 { 230 int rv; 231 232 p9pbuf_put_2(pb, dlen); 233 rv = puffs_framebuf_putdata(pb, data, dlen); 234 CHECK(rv == 0); 235 } 236 237 void 238 p9pbuf_put_str(struct puffs_framebuf *pb, const char *str) 239 { 240 241 p9pbuf_put_data(pb, str, strlen(str)); 242 } 243 244 void 245 p9pbuf_write_data(struct puffs_framebuf *pb, uint8_t *data, uint32_t dlen) 246 { 247 int rv; 248 249 rv = puffs_framebuf_putdata(pb, data, dlen); 250 CHECK(rv == 0); 251 } 252 253 #define ERETURN(rv) return ((rv) == -1 ? errno : 0) 254 255 int 256 p9pbuf_get_1(struct puffs_framebuf *pb, uint8_t *val) 257 { 258 259 ERETURN(puffs_framebuf_getdata(pb, val, 1)); 260 } 261 262 int 263 p9pbuf_get_2(struct puffs_framebuf *pb, uint16_t *val) 264 { 265 int rv; 266 267 rv = puffs_framebuf_getdata(pb, val, 2); 268 LE16TOH(*val); 269 270 ERETURN(rv); 271 } 272 273 int 274 p9pbuf_get_4(struct puffs_framebuf *pb, uint32_t *val) 275 { 276 int rv; 277 278 rv = puffs_framebuf_getdata(pb, val, 4); 279 LE32TOH(*val); 280 281 ERETURN(rv); 282 } 283 284 int 285 p9pbuf_get_8(struct puffs_framebuf *pb, uint64_t *val) 286 { 287 int rv; 288 289 rv = puffs_framebuf_getdata(pb, val, 8); 290 LE64TOH(*val); 291 292 ERETURN(rv); 293 } 294 295 int 296 p9pbuf_get_data(struct puffs_framebuf *pb, uint8_t **dp, uint16_t *dlenp) 297 { 298 uint8_t *data; 299 uint16_t len; 300 int rv; 301 302 rv = p9pbuf_get_2(pb, &len); 303 if (rv) 304 return errno; 305 306 if (puffs_framebuf_remaining(pb) < len) 307 return EPROTO; 308 309 if (dp) { 310 data = emalloc(len+1); 311 rv = puffs_framebuf_getdata(pb, data, len); 312 if (rv) { 313 free(data); 314 return errno; 315 } 316 data[len] = '\0'; 317 *dp = data; 318 } else 319 puffs_framebuf_seekset(pb, puffs_framebuf_telloff(pb)+len); 320 321 if (dlenp) 322 *dlenp = len; 323 324 return 0; 325 } 326 327 int 328 p9pbuf_read_data(struct puffs_framebuf *pb, uint8_t *buf, uint32_t dlen) 329 { 330 331 ERETURN(puffs_framebuf_getdata(pb, buf, dlen)); 332 } 333 334 int 335 p9pbuf_get_str(struct puffs_framebuf *pb, char **dp, uint16_t *dlenp) 336 { 337 338 return p9pbuf_get_data(pb, (uint8_t **)dp, dlenp); 339 } 340