1 /* 2 * Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws> 3 * 4 * Network Block Device Client Side 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; under version 2 of the License. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "nbd-internal.h" 20 21 static int nbd_errno_to_system_errno(int err) 22 { 23 switch (err) { 24 case NBD_SUCCESS: 25 return 0; 26 case NBD_EPERM: 27 return EPERM; 28 case NBD_EIO: 29 return EIO; 30 case NBD_ENOMEM: 31 return ENOMEM; 32 case NBD_ENOSPC: 33 return ENOSPC; 34 case NBD_EINVAL: 35 default: 36 return EINVAL; 37 } 38 } 39 40 /* Definitions for opaque data types */ 41 42 static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); 43 44 /* That's all folks */ 45 46 /* Basic flow for negotiation 47 48 Server Client 49 Negotiate 50 51 or 52 53 Server Client 54 Negotiate #1 55 Option 56 Negotiate #2 57 58 ---- 59 60 followed by 61 62 Server Client 63 Request 64 Response 65 Request 66 Response 67 ... 68 ... 69 Request (type == 2) 70 71 */ 72 73 int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, 74 off_t *size, Error **errp) 75 { 76 char buf[256]; 77 uint64_t magic, s; 78 uint16_t tmp; 79 int rc; 80 81 TRACE("Receiving negotiation."); 82 83 rc = -EINVAL; 84 85 if (read_sync(csock, buf, 8) != 8) { 86 error_setg(errp, "Failed to read data"); 87 goto fail; 88 } 89 90 buf[8] = '\0'; 91 if (strlen(buf) == 0) { 92 error_setg(errp, "Server connection closed unexpectedly"); 93 goto fail; 94 } 95 96 TRACE("Magic is %c%c%c%c%c%c%c%c", 97 qemu_isprint(buf[0]) ? buf[0] : '.', 98 qemu_isprint(buf[1]) ? buf[1] : '.', 99 qemu_isprint(buf[2]) ? buf[2] : '.', 100 qemu_isprint(buf[3]) ? buf[3] : '.', 101 qemu_isprint(buf[4]) ? buf[4] : '.', 102 qemu_isprint(buf[5]) ? buf[5] : '.', 103 qemu_isprint(buf[6]) ? buf[6] : '.', 104 qemu_isprint(buf[7]) ? buf[7] : '.'); 105 106 if (memcmp(buf, "NBDMAGIC", 8) != 0) { 107 error_setg(errp, "Invalid magic received"); 108 goto fail; 109 } 110 111 if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { 112 error_setg(errp, "Failed to read magic"); 113 goto fail; 114 } 115 magic = be64_to_cpu(magic); 116 TRACE("Magic is 0x%" PRIx64, magic); 117 118 if (name) { 119 uint32_t reserved = 0; 120 uint32_t opt; 121 uint32_t namesize; 122 123 TRACE("Checking magic (opts_magic)"); 124 if (magic != NBD_OPTS_MAGIC) { 125 if (magic == NBD_CLIENT_MAGIC) { 126 error_setg(errp, "Server does not support export names"); 127 } else { 128 error_setg(errp, "Bad magic received"); 129 } 130 goto fail; 131 } 132 if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { 133 error_setg(errp, "Failed to read server flags"); 134 goto fail; 135 } 136 *flags = be16_to_cpu(tmp) << 16; 137 /* reserved for future use */ 138 if (write_sync(csock, &reserved, sizeof(reserved)) != 139 sizeof(reserved)) { 140 error_setg(errp, "Failed to read reserved field"); 141 goto fail; 142 } 143 /* write the export name */ 144 magic = cpu_to_be64(magic); 145 if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { 146 error_setg(errp, "Failed to send export name magic"); 147 goto fail; 148 } 149 opt = cpu_to_be32(NBD_OPT_EXPORT_NAME); 150 if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) { 151 error_setg(errp, "Failed to send export name option number"); 152 goto fail; 153 } 154 namesize = cpu_to_be32(strlen(name)); 155 if (write_sync(csock, &namesize, sizeof(namesize)) != 156 sizeof(namesize)) { 157 error_setg(errp, "Failed to send export name length"); 158 goto fail; 159 } 160 if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) { 161 error_setg(errp, "Failed to send export name"); 162 goto fail; 163 } 164 } else { 165 TRACE("Checking magic (cli_magic)"); 166 167 if (magic != NBD_CLIENT_MAGIC) { 168 if (magic == NBD_OPTS_MAGIC) { 169 error_setg(errp, "Server requires an export name"); 170 } else { 171 error_setg(errp, "Bad magic received"); 172 } 173 goto fail; 174 } 175 } 176 177 if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) { 178 error_setg(errp, "Failed to read export length"); 179 goto fail; 180 } 181 *size = be64_to_cpu(s); 182 TRACE("Size is %" PRIu64, *size); 183 184 if (!name) { 185 if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) { 186 error_setg(errp, "Failed to read export flags"); 187 goto fail; 188 } 189 *flags = be32_to_cpup(flags); 190 } else { 191 if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { 192 error_setg(errp, "Failed to read export flags"); 193 goto fail; 194 } 195 *flags |= be16_to_cpu(tmp); 196 } 197 if (read_sync(csock, &buf, 124) != 124) { 198 error_setg(errp, "Failed to read reserved block"); 199 goto fail; 200 } 201 rc = 0; 202 203 fail: 204 return rc; 205 } 206 207 #ifdef __linux__ 208 int nbd_init(int fd, int csock, uint32_t flags, off_t size) 209 { 210 TRACE("Setting NBD socket"); 211 212 if (ioctl(fd, NBD_SET_SOCK, csock) < 0) { 213 int serrno = errno; 214 LOG("Failed to set NBD socket"); 215 return -serrno; 216 } 217 218 TRACE("Setting block size to %lu", (unsigned long)BDRV_SECTOR_SIZE); 219 220 if (ioctl(fd, NBD_SET_BLKSIZE, (size_t)BDRV_SECTOR_SIZE) < 0) { 221 int serrno = errno; 222 LOG("Failed setting NBD block size"); 223 return -serrno; 224 } 225 226 TRACE("Setting size to %zd block(s)", (size_t)(size / BDRV_SECTOR_SIZE)); 227 228 if (ioctl(fd, NBD_SET_SIZE_BLOCKS, (size_t)(size / BDRV_SECTOR_SIZE)) < 0) { 229 int serrno = errno; 230 LOG("Failed setting size (in blocks)"); 231 return -serrno; 232 } 233 234 if (ioctl(fd, NBD_SET_FLAGS, flags) < 0) { 235 if (errno == ENOTTY) { 236 int read_only = (flags & NBD_FLAG_READ_ONLY) != 0; 237 TRACE("Setting readonly attribute"); 238 239 if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) { 240 int serrno = errno; 241 LOG("Failed setting read-only attribute"); 242 return -serrno; 243 } 244 } else { 245 int serrno = errno; 246 LOG("Failed setting flags"); 247 return -serrno; 248 } 249 } 250 251 TRACE("Negotiation ended"); 252 253 return 0; 254 } 255 256 int nbd_client(int fd) 257 { 258 int ret; 259 int serrno; 260 261 TRACE("Doing NBD loop"); 262 263 ret = ioctl(fd, NBD_DO_IT); 264 if (ret < 0 && errno == EPIPE) { 265 /* NBD_DO_IT normally returns EPIPE when someone has disconnected 266 * the socket via NBD_DISCONNECT. We do not want to return 1 in 267 * that case. 268 */ 269 ret = 0; 270 } 271 serrno = errno; 272 273 TRACE("NBD loop returned %d: %s", ret, strerror(serrno)); 274 275 TRACE("Clearing NBD queue"); 276 ioctl(fd, NBD_CLEAR_QUE); 277 278 TRACE("Clearing NBD socket"); 279 ioctl(fd, NBD_CLEAR_SOCK); 280 281 errno = serrno; 282 return ret; 283 } 284 #else 285 int nbd_init(int fd, int csock, uint32_t flags, off_t size) 286 { 287 return -ENOTSUP; 288 } 289 290 int nbd_client(int fd) 291 { 292 return -ENOTSUP; 293 } 294 #endif 295 296 ssize_t nbd_send_request(int csock, struct nbd_request *request) 297 { 298 uint8_t buf[NBD_REQUEST_SIZE]; 299 ssize_t ret; 300 301 cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC); 302 cpu_to_be32w((uint32_t*)(buf + 4), request->type); 303 cpu_to_be64w((uint64_t*)(buf + 8), request->handle); 304 cpu_to_be64w((uint64_t*)(buf + 16), request->from); 305 cpu_to_be32w((uint32_t*)(buf + 24), request->len); 306 307 TRACE("Sending request to client: " 308 "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}", 309 request->from, request->len, request->handle, request->type); 310 311 ret = write_sync(csock, buf, sizeof(buf)); 312 if (ret < 0) { 313 return ret; 314 } 315 316 if (ret != sizeof(buf)) { 317 LOG("writing to socket failed"); 318 return -EINVAL; 319 } 320 return 0; 321 } 322 323 ssize_t nbd_receive_reply(int csock, struct nbd_reply *reply) 324 { 325 uint8_t buf[NBD_REPLY_SIZE]; 326 uint32_t magic; 327 ssize_t ret; 328 329 ret = read_sync(csock, buf, sizeof(buf)); 330 if (ret < 0) { 331 return ret; 332 } 333 334 if (ret != sizeof(buf)) { 335 LOG("read failed"); 336 return -EINVAL; 337 } 338 339 /* Reply 340 [ 0 .. 3] magic (NBD_REPLY_MAGIC) 341 [ 4 .. 7] error (0 == no error) 342 [ 7 .. 15] handle 343 */ 344 345 magic = be32_to_cpup((uint32_t*)buf); 346 reply->error = be32_to_cpup((uint32_t*)(buf + 4)); 347 reply->handle = be64_to_cpup((uint64_t*)(buf + 8)); 348 349 reply->error = nbd_errno_to_system_errno(reply->error); 350 351 TRACE("Got reply: " 352 "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }", 353 magic, reply->error, reply->handle); 354 355 if (magic != NBD_REPLY_MAGIC) { 356 LOG("invalid magic (got 0x%x)", magic); 357 return -EINVAL; 358 } 359 return 0; 360 } 361 362