docs: Tweak location of qemu nbd extensions
[nbd.git] / nbd-client.c
blob175116de5cb11937557dd7d046544929861d21be
1 /*
2 * Open connection for network block device
4 * Copyright 1997,1998 Pavel Machek, distribute under GPL
5 * <pavel@atrey.karlin.mff.cuni.cz>
6 * Copyright (c) 2002 - 2011 Wouter Verhelst <w@uter.be>
8 * Version 1.0 - 64bit issues should be fixed, now
9 * Version 1.1 - added bs (blocksize) option (Alexey Guzeev, aga@permonline.ru)
10 * Version 1.2 - I added new option '-d' to send the disconnect request
11 * Version 2.0 - Version synchronised with server
12 * Version 2.1 - Check for disconnection before INIT_PASSWD is received
13 * to make errormsg a bit more helpful in case the server can't
14 * open the exported file.
15 * 16/03/2010 - Add IPv6 support.
16 * Kitt Tientanopajai <kitt@kitty.in.th>
17 * Neutron Soutmun <neo.neutron@gmail.com>
18 * Suriya Soutmun <darksolar@gmail.com>
21 #include "config.h"
22 #include "lfs.h"
24 #include <sys/ioctl.h>
25 #include <sys/socket.h>
26 #include <sys/un.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <netinet/tcp.h>
30 #include <netinet/in.h>
31 #include <netdb.h>
32 #include "netdb-compat.h"
33 #include <inttypes.h>
34 #include <stdio.h>
35 #include <fcntl.h>
36 #include <syslog.h>
37 #include <stdlib.h>
38 #include <sys/mount.h>
39 #include <sys/mman.h>
40 #include <signal.h>
41 #include <errno.h>
42 #include <getopt.h>
43 #include <stdarg.h>
44 #include <stdbool.h>
45 #include <time.h>
47 #include <linux/ioctl.h>
49 #if HAVE_NETLINK
50 #include "nbd-netlink.h"
51 #include <netlink/netlink.h>
52 #include <netlink/genl/genl.h>
53 #include <netlink/genl/ctrl.h>
54 #endif
56 #define MY_NAME "nbd_client"
57 #include "cliserv.h"
59 #if HAVE_GNUTLS && !defined(NOTLS)
60 #include "crypto-gnutls.h"
61 #endif
63 #include "nbdclt.h"
64 #include "nbdtab_parser.tab.h"
66 CLIENT* cur_client;
67 extern FILE *yyin, *yyout;
68 bool found_config = false;
69 bool parse_error = false;
71 #define SET_PROP(str, member, rval) if(!strcmp(property, str)) { cur_client->member = (rval); return; }
72 void nbdtab_set_property(char *property, char *val) {
73 if(found_config) return;
74 SET_PROP("port", port, val);
75 SET_PROP("certfile", cert, val);
76 SET_PROP("keyfile", key, val);
77 SET_PROP("cacertfile", cacert, val);
78 SET_PROP("tlshostname", tlshostn, val);
79 SET_PROP("priority", priority, val);
80 SET_PROP("bs", bs, strtol(val, NULL, 10));
81 SET_PROP("timeout", timeout, strtol(val, NULL, 10));
82 SET_PROP("conns", nconn, strtol(val, NULL, 10));
83 if(*property != '_') {
84 fprintf(stderr, "Warning: unknown option '%s' found in nbdtab file", property);
87 #undef SET_PROP
89 #define SET_FLAG(str, member) if(!strcmp(property, str)) { cur_client->member = true; return; }
90 void nbdtab_set_flag(char *property) {
91 if(found_config) return;
92 SET_FLAG("no_optgo", no_optgo);
93 SET_FLAG("persist", persist);
94 SET_FLAG("swap", swap);
95 SET_FLAG("unix", b_unix);
96 SET_FLAG("preinit", preinit);
97 SET_FLAG("tls", tls);
98 if(*property != '_') {
99 fprintf(stderr, "Warning: unknown option '%s' found in nbdtab file", property);
103 void nbdtab_commit_line(char *devn, char *hostn, char *exportname) {
104 if(!strncmp(devn, "/dev/", 5)) {
105 devn += 5;
107 if(!strcmp(cur_client->dev, devn)) {
108 found_config = true;
109 cur_client->hostn = hostn;
110 cur_client->name = exportname;
111 } else {
112 if(!found_config) {
113 char *tmp = cur_client->dev;
114 memset(cur_client, 0, sizeof(CLIENT));
115 cur_client->bs = 512;
116 cur_client->nconn = 1;
117 cur_client->dev = tmp;
120 return;
123 void yyerror(char *msg) {
124 parse_error = true;
125 fprintf(stderr, "parse error parsing " SYSCONFDIR "/nbdtab: %s", msg);
128 #undef SET_FLAG
130 #define NBDC_DO_LIST 1
132 #if HAVE_NETLINK
133 static int callback(struct nl_msg *msg, void *arg) {
134 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
135 struct nlattr *msg_attr[NBD_ATTR_MAX + 1];
136 int ret;
137 uint32_t index;
139 ret = nla_parse(msg_attr, NBD_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
140 genlmsg_attrlen(gnlh, 0), NULL);
141 if (ret)
142 err("Invalid response from the kernel\n");
143 if (!msg_attr[NBD_ATTR_INDEX])
144 err("Did not receive index from the kernel\n");
145 index = nla_get_u32(msg_attr[NBD_ATTR_INDEX]);
146 printf("Connected /dev/nbd%d\n", (int)index);
147 return NL_OK;
150 static struct nl_sock *get_nbd_socket(int *driver_id) {
151 struct nl_sock *socket;
153 socket = nl_socket_alloc();
154 if (!socket)
155 err("Couldn't allocate netlink socket\n");
157 if (genl_connect(socket))
158 err("Couldn't connect to the generic netlink socket\n");
159 *driver_id = genl_ctrl_resolve(socket, "nbd");
160 if (*driver_id < 0)
161 err("Couldn't resolve the nbd netlink family, make sure the nbd module is loaded and your nbd driver supports the netlink interface.\n");
162 return socket;
165 static void netlink_configure(int index, int *sockfds, int num_connects,
166 u64 size64, int blocksize, uint16_t flags,
167 int timeout) {
168 struct nl_sock *socket;
169 struct nlattr *sock_attr;
170 struct nl_msg *msg;
171 int driver_id, i;
173 socket = get_nbd_socket(&driver_id);
174 nl_socket_modify_cb(socket, NL_CB_VALID, NL_CB_CUSTOM, callback, NULL);
176 msg = nlmsg_alloc();
177 if (!msg)
178 err("Couldn't allocate netlink message\n");
179 genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, driver_id, 0, 0,
180 NBD_CMD_CONNECT, 0);
181 if (index >= 0)
182 NLA_PUT_U32(msg, NBD_ATTR_INDEX, index);
183 NLA_PUT_U64(msg, NBD_ATTR_SIZE_BYTES, size64);
184 NLA_PUT_U64(msg, NBD_ATTR_BLOCK_SIZE_BYTES, blocksize);
185 NLA_PUT_U64(msg, NBD_ATTR_SERVER_FLAGS, flags);
186 if (timeout)
187 NLA_PUT_U64(msg, NBD_ATTR_TIMEOUT, timeout);
189 sock_attr = nla_nest_start(msg, NBD_ATTR_SOCKETS);
190 if (!sock_attr)
191 err("Couldn't nest the sockets for our connection\n");
192 for (i = 0; i < num_connects; i++) {
193 struct nlattr *sock_opt;
194 sock_opt = nla_nest_start(msg, NBD_SOCK_ITEM);
195 if (!sock_opt)
196 err("Couldn't nest the sockets for our connection\n");
197 NLA_PUT_U32(msg, NBD_SOCK_FD, sockfds[i]);
198 nla_nest_end(msg, sock_opt);
200 nla_nest_end(msg, sock_attr);
202 if (nl_send_sync(socket, msg) < 0) {
203 if(geteuid() != 0) {
204 err("Failed to setup device. Are you root?\n");
205 } else {
206 err("Failed to setup device, check dmesg\n");
209 return;
210 nla_put_failure:
211 err("Failed to create netlink message\n");
214 static void netlink_disconnect(char *nbddev) {
215 struct nl_sock *socket;
216 struct nl_msg *msg;
217 int driver_id;
219 int index = -1;
220 if (nbddev) {
221 if (sscanf(nbddev, "/dev/nbd%d", &index) != 1)
222 err("Invalid nbd device target\n");
224 if (index < 0)
225 err("Invalid nbd device target\n");
227 socket = get_nbd_socket(&driver_id);
229 msg = nlmsg_alloc();
230 if (!msg)
231 err("Couldn't allocate netlink message\n");
232 genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, driver_id, 0, 0,
233 NBD_CMD_DISCONNECT, 0);
234 NLA_PUT_U32(msg, NBD_ATTR_INDEX, index);
235 if (nl_send_sync(socket, msg) < 0)
236 err("Failed to disconnect device, check dmsg\n");
237 nl_socket_free(socket);
238 return;
239 nla_put_failure:
240 err("Failed to create netlink message\n");
242 #else
243 static void netlink_configure(int index, int *sockfds, int num_connects,
244 u64 size64, int blocksize, uint16_t flags,
245 int timeout)
249 static void netlink_disconnect(char *nbddev)
252 #endif /* HAVE_NETLINK */
254 int check_conn(char* devname, int do_print) {
255 char buf[256];
256 char* p;
257 int fd;
258 int len;
260 if( (p=strrchr(devname, '/')) ) {
261 devname=p+1;
263 if((p=strchr(devname, 'p'))) {
264 /* We can't do checks on partitions. */
265 *p='\0';
267 snprintf(buf, 256, "/sys/block/%s/pid", devname);
268 if((fd=open(buf, O_RDONLY))<0) {
269 if(errno==ENOENT) {
270 return 1;
271 } else {
272 return 2;
275 len=read(fd, buf, 256);
276 if(len < 0) {
277 perror("could not read from server");
278 close(fd);
279 return 2;
281 buf[(len < 256) ? len : 255]='\0';
282 if(do_print) printf("%s\n", buf);
283 close(fd);
284 return 0;
287 int opennet(char *name, char* portstr) {
288 int sock;
289 struct addrinfo hints;
290 struct addrinfo *ai = NULL;
291 struct addrinfo *rp = NULL;
292 int e;
294 memset(&hints,'\0',sizeof(hints));
295 hints.ai_family = AF_UNSPEC;
296 hints.ai_socktype = SOCK_STREAM;
297 hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
298 hints.ai_protocol = IPPROTO_TCP;
300 e = getaddrinfo(name, portstr, &hints, &ai);
302 if(e != 0) {
303 fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(e));
304 freeaddrinfo(ai);
305 return -1;
308 for(rp = ai; rp != NULL; rp = rp->ai_next) {
309 sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
311 if(sock == -1)
312 continue; /* error */
314 if(connect(sock, rp->ai_addr, rp->ai_addrlen) != -1)
315 break; /* success */
317 close(sock);
320 if (rp == NULL) {
321 err_nonfatal("Socket failed: %m");
322 sock = -1;
323 goto err;
326 setmysockopt(sock);
327 err:
328 freeaddrinfo(ai);
329 return sock;
332 int openunix(const char *path) {
333 int sock;
334 struct sockaddr_un un_addr;
335 memset(&un_addr, 0, sizeof(un_addr));
337 un_addr.sun_family = AF_UNIX;
338 if (strnlen(path, sizeof(un_addr.sun_path)) == sizeof(un_addr.sun_path)) {
339 err_nonfatal("UNIX socket path too long");
340 return -1;
343 strncpy(un_addr.sun_path, path, sizeof(un_addr.sun_path) - 1);
345 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
346 err_nonfatal("SOCKET failed");
347 return -1;
350 if (connect(sock, (struct sockaddr*)&un_addr, sizeof(un_addr)) == -1) {
351 err_nonfatal("CONNECT failed");
352 close(sock);
353 return -1;
355 return sock;
358 void send_request(int sock, uint32_t opt, ssize_t datasize, void* data) {
359 struct {
360 uint64_t magic;
361 uint32_t opt;
362 uint32_t datasize;
363 } __attribute__((packed)) header = {
364 ntohll(opts_magic),
365 ntohl(opt),
366 ntohl(datasize),
368 if(datasize < 0) {
369 datasize = strlen((char*)data);
370 header.datasize = htonl(datasize);
372 writeit(sock, &header, sizeof(header));
373 if(data != NULL) {
374 writeit(sock, data, datasize);
378 void send_info_request(int sock, uint32_t opt, int n_reqs, uint16_t* reqs, char* name) {
379 uint16_t rlen = htons(n_reqs);
380 uint32_t nlen = htonl(strlen(name));
382 send_request(sock, opt, sizeof(uint32_t) + strlen(name) + sizeof(uint16_t) + n_reqs * sizeof(uint16_t), NULL);
383 writeit(sock, &nlen, sizeof(nlen));
384 writeit(sock, name, strlen(name));
385 writeit(sock, &rlen, sizeof(rlen));
386 if(n_reqs > 0) {
387 writeit(sock, reqs, n_reqs * sizeof(uint16_t));
391 struct reply {
392 uint64_t magic;
393 uint32_t opt;
394 uint32_t reply_type;
395 uint32_t datasize;
396 char data[];
397 } __attribute__((packed));
399 struct reply* read_reply(int sock) {
400 struct reply *retval = malloc(sizeof(struct reply));
402 if (retval == NULL)
403 return NULL;
405 if(readit(sock, retval, sizeof(*retval)) < 0) {
406 free(retval);
407 return NULL;
410 retval->magic = ntohll(retval->magic);
411 retval->opt = ntohl(retval->opt);
412 retval->reply_type = ntohl(retval->reply_type);
413 retval->datasize = ntohl(retval->datasize);
414 if (retval->magic != rep_magic) {
415 fprintf(stderr, "E: received invalid negotiation magic %" PRIu64 " (expected %" PRIu64 ")", retval->magic, rep_magic);
416 exit(EXIT_FAILURE);
418 if (retval->datasize > 0 && retval->datasize < 4096) {
419 struct reply *retval_r = realloc(retval, sizeof(struct reply) + retval->datasize);
420 if (retval_r == NULL) {
421 free(retval);
422 return NULL;
424 retval = retval_r;
425 readit(sock, &(retval->data), retval->datasize);
427 return retval;
430 void ask_list(int sock) {
431 uint32_t opt_server;
432 uint32_t len;
433 uint32_t lenn;
434 uint32_t reptype;
435 uint64_t magic;
436 int rlen;
437 const int BUF_SIZE = 1024;
438 char buf[BUF_SIZE];
440 send_request(sock, NBD_OPT_LIST, 0, NULL);
441 /* newline, move away from the "Negotiation:" line */
442 printf("\n");
443 do {
444 memset(buf, 0, 1024);
445 if(read(sock, &magic, sizeof(magic)) < 0) {
446 err("Reading magic from server: %m");
448 if(read(sock, &opt_server, sizeof(opt_server)) < 0) {
449 err("Reading option: %m");
451 if(read(sock, &reptype, sizeof(reptype)) <0) {
452 err("Reading reply from server: %m");
454 if(read(sock, &len, sizeof(len)) < 0) {
455 err("Reading length from server: %m");
457 magic=ntohll(magic);
458 len=ntohl(len);
459 reptype=ntohl(reptype);
460 if(magic != rep_magic) {
461 err("Not enough magic from server");
463 if(reptype & NBD_REP_FLAG_ERROR) {
464 switch(reptype) {
465 case NBD_REP_ERR_POLICY:
466 fprintf(stderr, "\nE: listing not allowed by server.\n");
467 break;
468 default:
469 fprintf(stderr, "\nE: unexpected error from server.\n");
470 break;
472 if(len > 0 && len < BUF_SIZE) {
473 if((rlen=read(sock, buf, len)) < 0) {
474 fprintf(stderr, "\nE: could not read error message from server\n");
475 } else {
476 buf[rlen] = '\0';
477 fprintf(stderr, "Server said: %s\n", buf);
480 exit(EXIT_FAILURE);
481 } else {
482 if(reptype != NBD_REP_ACK) {
483 if(reptype != NBD_REP_SERVER) {
484 err("Server sent us a reply we don't understand!");
486 if(read(sock, &lenn, sizeof(lenn)) < 0) {
487 fprintf(stderr, "\nE: could not read export name length from server\n");
488 exit(EXIT_FAILURE);
490 lenn=ntohl(lenn);
491 if (lenn >= BUF_SIZE) {
492 fprintf(stderr, "\nE: export name on server too long\n");
493 exit(EXIT_FAILURE);
495 if(read(sock, buf, lenn) < 0) {
496 fprintf(stderr, "\nE: could not read export name from server\n");
497 exit(EXIT_FAILURE);
499 buf[lenn] = 0;
500 printf("%s", buf);
501 len -= lenn;
502 len -= sizeof(lenn);
503 if(len > 0) {
504 if(len >= BUF_SIZE) {
505 fprintf(stderr, "\nE: export description read buffer overflow\n");
506 exit(EXIT_FAILURE);
508 if(read(sock, buf, len) < 0) {
509 fprintf(stderr, "\nE: could not read export description from server\n");
510 exit(EXIT_FAILURE);
512 buf[len] = 0;
513 printf(": %s\n", buf);
514 } else {
515 printf("\n");
519 } while(reptype != NBD_REP_ACK);
520 send_request(sock, NBD_OPT_ABORT, 0, NULL);
523 void parse_sizes(char *buf, uint64_t *size, uint16_t *flags) {
524 memcpy(size, buf, sizeof(*size));
525 *size = ntohll(*size);
526 buf += sizeof(*size);
527 memcpy(flags, buf, sizeof(*flags));
528 *flags = ntohs(*flags);
530 if ((*size>>12) > (uint64_t)~0UL) {
531 printf("size = %luMB", (unsigned long)(*size>>20));
532 err("Exported device is too big for me. Get 64-bit machine :-(\n");
533 } else {
534 printf("size = %luMB", (unsigned long)(*size>>20));
536 printf("\n");
539 void send_opt_exportname(int sock, u64 *rsize64, uint16_t *flags, bool can_opt_go, char* name, uint16_t global_flags) {
540 send_request(sock, NBD_OPT_EXPORT_NAME, -1, name);
541 char b[sizeof(*flags) + sizeof(*rsize64)];
542 if(readit(sock, b, sizeof(b)) < 0 && can_opt_go) {
543 err("E: server does not support NBD_OPT_GO and dropped connection after sending NBD_OPT_EXPORT_NAME. Try -g.");
545 parse_sizes(b, rsize64, flags);
546 if(!(global_flags & NBD_FLAG_NO_ZEROES)) {
547 char buf[125];
548 readit(sock, buf, 124);
552 void negotiate(int *sockp, u64 *rsize64, uint16_t *flags, char* name, uint32_t needed_flags, uint32_t client_flags, uint32_t do_opts, char *certfile, char *keyfile, char *cacertfile, char *tlshostname, bool tls, char *priority, bool can_opt_go) {
553 u64 magic;
554 uint16_t tmp;
555 uint16_t global_flags;
556 char buf[256] = "\0\0\0\0\0\0\0\0\0";
557 int sock = *sockp;
559 printf("Negotiation: ");
560 readit(sock, buf, 8);
561 if (strcmp(buf, INIT_PASSWD))
562 err("INIT_PASSWD bad");
563 printf(".");
564 readit(sock, &magic, sizeof(magic));
565 magic = ntohll(magic);
566 if (magic != opts_magic) {
567 if(magic == cliserv_magic) {
568 err("It looks like you're trying to connect to an oldstyle server. This is no longer supported since nbd 3.10.");
571 printf(".");
572 readit(sock, &tmp, sizeof(uint16_t));
573 global_flags = ntohs(tmp);
574 if((needed_flags & global_flags) != needed_flags) {
575 /* There's currently really only one reason why this
576 * check could possibly fail, but we may need to change
577 * this error message in the future... */
578 fprintf(stderr, "\nE: Server does not support listing exports\n");
579 exit(EXIT_FAILURE);
582 if (global_flags & NBD_FLAG_NO_ZEROES) {
583 client_flags |= NBD_FLAG_C_NO_ZEROES;
585 client_flags = htonl(client_flags);
586 if (write(sock, &client_flags, sizeof(client_flags)) < 0)
587 err("Failed/2.1: %m");
589 #if HAVE_GNUTLS && !defined(NOTLS)
590 /* TLS */
591 if (tls) {
592 int plainfd[2]; // [0] is used by the proxy, [1] is used by NBD
593 tlssession_t *s = NULL;
594 int ret;
595 uint32_t tmp32;
596 uint64_t tmp64;
598 send_request(sock, NBD_OPT_STARTTLS, 0, NULL);
600 if (read(sock, &tmp64, sizeof(tmp64)) < 0)
601 err("Could not read cliserv_magic: %m");
602 tmp64 = ntohll(tmp64);
603 if (tmp64 != NBD_OPT_REPLY_MAGIC) {
604 err("reply magic does not match");
606 if (read(sock, &tmp32, sizeof(tmp32)) < 0)
607 err("Could not read option type: %m");
608 tmp32 = ntohl(tmp32);
609 if (tmp32 != NBD_OPT_STARTTLS)
610 err("Reply to wrong option");
611 if (read(sock, &tmp32, sizeof(tmp32)) < 0)
612 err("Could not read option reply type: %m");
613 tmp32 = ntohl(tmp32);
614 if (tmp32 != NBD_REP_ACK) {
615 err("Option reply type != NBD_REP_ACK");
617 if (read(sock, &tmp32, sizeof(tmp32)) < 0) err(
618 "Could not read option data length: %m");
619 tmp32 = ntohl(tmp32);
620 if (tmp32 != 0) {
621 err("Option reply data length != 0");
623 s = tlssession_new(0,
624 keyfile,
625 certfile,
626 cacertfile,
627 tlshostname,
628 priority,
629 !cacertfile || !tlshostname, // insecure flag
630 #ifdef DODBG
631 1, // debug
632 #else
633 0, // debug
634 #endif
635 NULL, // quitfn
636 NULL, // erroutfn
637 NULL // opaque
639 if (!s)
640 err("Cannot establish TLS session");
642 if (socketpair(AF_UNIX, SOCK_STREAM, 0, plainfd) < 0)
643 err("Cannot get socket pair");
645 if (set_nonblocking(plainfd[0], 0) <0 ||
646 set_nonblocking(plainfd[1], 0) <0 ||
647 set_nonblocking(sock, 0) <0) {
648 close(plainfd[0]);
649 close(plainfd[1]);
650 err("Cannot set socket options");
653 ret = fork();
654 if (ret < 0)
655 err("Could not fork");
656 else if (ret == 0) {
657 // we are the child
658 if (daemon(0, 0) < 0) {
659 /* no one will see this */
660 fprintf(stderr, "Can't detach from the terminal");
661 exit(1);
663 signal (SIGPIPE, SIG_IGN);
664 close(plainfd[1]);
665 tlssession_mainloop(sock, plainfd[0], s);
666 close(sock);
667 close(plainfd[0]);
668 exit(0);
670 close(plainfd[0]);
671 close(sock);
672 sock = plainfd[1]; /* use the decrypted FD from now on */
673 *sockp = sock;
675 #else
676 if (keyfile) {
677 err("TLS requested but support not compiled in");
679 #endif
681 if(do_opts & NBDC_DO_LIST) {
682 ask_list(sock);
683 exit(EXIT_SUCCESS);
686 struct reply *rep = NULL;
688 if(!can_opt_go) {
689 send_opt_exportname(sock, rsize64, flags, can_opt_go, name, global_flags);
690 return;
693 send_info_request(sock, NBD_OPT_GO, 0, NULL, name);
695 do {
696 if(rep != NULL) free(rep);
697 rep = read_reply(sock);
698 if(rep == NULL) {
699 err("Unable to read reply.");
700 exit(EXIT_FAILURE);
702 if(rep->reply_type & NBD_REP_FLAG_ERROR) {
703 switch(rep->reply_type) {
704 case NBD_REP_ERR_UNSUP:
705 /* server doesn't support NBD_OPT_GO or NBD_OPT_INFO,
706 * fall back to NBD_OPT_EXPORT_NAME */
707 send_opt_exportname(sock, rsize64, flags, can_opt_go, name, global_flags);
708 free(rep);
709 return;
710 case NBD_REP_ERR_POLICY:
711 if(rep->datasize > 0) {
712 char errstr[1024];
713 rep->data[rep->datasize - 1] = '\0';
714 snprintf(errstr, sizeof errstr, "Connection not allowed by server policy. Server said: %s", rep->data);
715 err(errstr);
716 } else {
717 err("Connection not allowed by server policy.");
719 free(rep);
720 exit(EXIT_FAILURE);
721 default:
722 if(rep->datasize > 0) {
723 char errstr[1024];
724 rep->data[rep->datasize - 1] = '\0';
725 snprintf(errstr, sizeof errstr, "Unknown error returned by server. Server said: %s", rep->data);
726 err(errstr);
727 } else {
728 err("Unknown error returned by server.");
730 free(rep);
731 exit(EXIT_FAILURE);
734 uint16_t info_type;
735 switch(rep->reply_type) {
736 case NBD_REP_INFO:
737 memcpy(&info_type, rep->data, 2);
738 info_type = htons(info_type);
739 switch(info_type) {
740 case NBD_INFO_EXPORT:
741 parse_sizes(rep->data + 2, rsize64, flags);
742 break;
743 default:
744 // ignore these, don't need them
745 break;
747 break;
748 case NBD_REP_ACK:
749 break;
750 default:
751 err_nonfatal("Unknown reply to NBD_OPT_GO received, ignoring");
753 } while(rep->reply_type != NBD_REP_ACK);
754 free(rep);
757 bool get_from_config(char* cfgname, char** name_ptr, char** dev_ptr, char** hostn_ptr, int* bs, int* timeout, int* persist, int* swap, int* b_unix, char**port, int* num_conns, char **certfile, char **keyfile, char **cacertfile, char **tlshostname, char **priority, bool *can_opt_go) {
758 bool retval = false;
759 cur_client = calloc(sizeof(CLIENT), 1);
760 cur_client->bs = 512;
761 cur_client->nconn = 1;
762 cur_client->port = NBD_DEFAULT_PORT;
763 yyin = fopen(SYSCONFDIR "/nbdtab", "r");
764 yyout = fopen("/dev/null", "w");
766 if(!strncmp(cfgname, "/dev/", 5)) {
767 cfgname += 5;
769 cur_client->dev = cfgname;
770 if(yyin == NULL) {
771 fprintf(stderr, "while opening %s: ", SYSCONFDIR "/nbdtab");
772 perror("could not open config file");
773 goto out;
775 yyparse();
777 if(!found_config || parse_error) {
778 goto out;
780 *name_ptr = cur_client->name;
781 *dev_ptr = calloc(strlen(cur_client->dev) + 6, 1);
782 if (!*dev_ptr) {
783 goto out;
785 snprintf(*dev_ptr, strlen(cur_client->dev) + 6, "/dev/%s", cur_client->dev);
786 *hostn_ptr = cur_client->hostn;
787 *bs = cur_client->bs;
788 *timeout = cur_client->timeout;
789 *persist = cur_client->persist ? 1 : 0;
790 *swap = cur_client->swap ? 1 : 0;
791 *b_unix = cur_client->b_unix ? 1 : 0;
792 *port = cur_client->port;
793 *num_conns = cur_client->nconn;
794 *certfile = cur_client->cert;
795 *keyfile = cur_client->key;
796 *cacertfile = cur_client->cacert;
797 *tlshostname = cur_client->tlshostn;
798 *priority = cur_client->priority;
799 *can_opt_go = !(cur_client->no_optgo);
801 retval = true;
802 out:
803 if(yyin != NULL) {
804 fclose(yyin);
806 if(yyout != NULL) {
807 fclose(yyout);
809 return retval;
812 void setsizes(int nbd, u64 size64, int blocksize, u32 flags) {
813 unsigned long size;
814 int read_only = (flags & NBD_FLAG_READ_ONLY) ? 1 : 0;
816 if (size64>>12 > (uint64_t)~0UL)
817 err("Device too large.\n");
818 else {
819 int tmp_blocksize = 4096;
820 if (size64 / (u64)blocksize <= (uint64_t)~0UL)
821 tmp_blocksize = blocksize;
822 if (ioctl(nbd, NBD_SET_BLKSIZE, tmp_blocksize) < 0) {
823 fprintf(stderr, "Failed to set blocksize %d\n",
824 tmp_blocksize);
825 err("Ioctl/1.1a failed: %m\n");
827 size = (unsigned long)(size64 / (u64)tmp_blocksize);
828 if (ioctl(nbd, NBD_SET_SIZE_BLOCKS, size) < 0)
829 err("Ioctl/1.1b failed: %m\n");
830 if (tmp_blocksize != blocksize) {
831 if (ioctl(nbd, NBD_SET_BLKSIZE, (unsigned long)blocksize) < 0) {
832 fprintf(stderr, "Failed to set blocksize %d\n",
833 blocksize);
834 err("Ioctl/1.1c failed: %m\n");
837 fprintf(stderr, "bs=%d, sz=%" PRIu64 " bytes\n", blocksize, (u64)tmp_blocksize * size);
840 ioctl(nbd, NBD_CLEAR_SOCK);
842 /* ignore error as kernel may not support */
843 ioctl(nbd, NBD_SET_FLAGS, (unsigned long) flags);
845 if (ioctl(nbd, BLKROSET, (unsigned long) &read_only) < 0)
846 err("Unable to set read-only attribute for device");
849 void set_timeout(int nbd, int timeout) {
850 if (timeout) {
851 if (ioctl(nbd, NBD_SET_TIMEOUT, (unsigned long)timeout) < 0)
852 err("Ioctl NBD_SET_TIMEOUT failed: %m\n");
853 fprintf(stderr, "timeout=%d\n", timeout);
857 void finish_sock(int sock, int nbd, int swap) {
858 if (ioctl(nbd, NBD_SET_SOCK, sock) < 0) {
859 if (errno == EBUSY)
860 err("Kernel doesn't support multiple connections\n");
861 else
862 err("Ioctl NBD_SET_SOCK failed: %m\n");
865 #ifndef __ANDROID__
866 if (swap)
867 mlockall(MCL_CURRENT | MCL_FUTURE);
868 #endif
871 static int
872 oom_adjust(const char *file, const char *value)
874 int fd, rc;
875 size_t len;
877 fd = open(file, O_WRONLY);
878 if (fd < 0)
879 return -1;
880 len = strlen(value);
881 rc = write(fd, value, len) != (ssize_t) len;
882 close(fd);
883 return rc ? -1 : 0;
886 void usage(char* errmsg, ...) {
887 if(errmsg) {
888 char tmp[256];
889 va_list ap;
890 va_start(ap, errmsg);
891 snprintf(tmp, 256, "ERROR: %s\n\n", errmsg);
892 vfprintf(stderr, tmp, ap);
893 va_end(ap);
894 } else {
895 fprintf(stderr, "%s version %s\n", PROG_NAME, PACKAGE_VERSION);
897 #if HAVE_NETLINK
898 fprintf(stderr, "Usage: nbd-client -name|-N name host [port] nbd_device\n\t[-block-size|-b block size] [-timeout|-t timeout] [-swap|-s]\n\t[-persist|-p] [-nofork|-n] [-systemd-mark|-m] [-nonetlink|-L]\n\t[-readonly|-R] [-size|-B bytes] [-preinit|-P]\n");
899 #else
900 fprintf(stderr, "Usage: nbd-client -name|-N name host [port] nbd_device\n\t[-block-size|-b block size] [-timeout|-t timeout] [-swap|-s]\n\t[-persist|-p] [-nofork|-n] [-systemd-mark|-m]\n\t[-readonly|-R] [-size|-B bytes] [-preinit|-P]\n");
901 #endif
902 fprintf(stderr, "Or : nbd-client -u (with same arguments as above)\n");
903 fprintf(stderr, "Or : nbd-client nbdX\n");
904 fprintf(stderr, "Or : nbd-client -d nbd_device\n");
905 fprintf(stderr, "Or : nbd-client -c nbd_device\n");
906 fprintf(stderr, "Or : nbd-client -h|--help\n");
907 fprintf(stderr, "Or : nbd-client -l|--list host\n");
908 fprintf(stderr, "Or : nbd-client -V|--version\n");
909 #if HAVE_GNUTLS && !defined(NOTLS)
910 fprintf(stderr, "All commands that connect to a host also take:\n\t[-F|-certfile certfile] [-K|-keyfile keyfile]\n\t[-A|-cacertfile cacertfile] [-H|-tlshostname hostname] [-x|-enable-tls]\n\t[-y|-priority gnutls-priority-string]\n");
911 #endif
912 fprintf(stderr, "Default value for blocksize is 512\n");
913 fprintf(stderr, "Allowed values for blocksize are 512,1024,2048,4096\n"); /* will be checked in kernel :) */
914 fprintf(stderr, "Note, that kernel 2.4.2 and older ones do not work correctly with\n");
915 fprintf(stderr, "blocksizes other than 1024 without patches\n");
916 fprintf(stderr, "Default value for port is 10809. Note that port must always be numeric\n");
917 fprintf(stderr, "Bug reports and general discussion should go to %s\n", PACKAGE_BUGREPORT);
920 void disconnect(char* device) {
921 int nbd = open(device, O_RDWR);
923 if (nbd < 0)
924 err("Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded.");
925 printf("disconnect, ");
926 if (ioctl(nbd, NBD_DISCONNECT)<0)
927 err("Ioctl failed: %m\n");
928 printf("sock, ");
929 if (ioctl(nbd, NBD_CLEAR_SOCK)<0)
930 err("Ioctl failed: %m\n");
931 printf("done\n");
932 close(nbd);
935 static const char *short_opts = "-B:b:c:d:gH:hlnN:PpRSst:uVxy:"
936 #if HAVE_NETLINK
938 #endif
939 #if HAVE_GNUTLS
940 "A:C:F:K:"
941 #endif
944 int main(int argc, char *argv[]) {
945 char* port=NBD_DEFAULT_PORT;
946 int sock, nbd;
947 int blocksize=512;
948 char *hostname=NULL;
949 char *nbddev=NULL;
950 int swap=0;
951 int cont=0;
952 int timeout=0;
953 int G_GNUC_UNUSED nofork=0; // if -dNOFORK
954 pid_t main_pid;
955 u64 size64 = 0;
956 u64 force_size64 = 0;
957 uint16_t flags = 0;
958 bool force_read_only = false;
959 bool preinit = false;
960 int c;
961 int nonspecial=0;
962 int b_unix=0;
963 char* name="";
964 uint16_t needed_flags=0;
965 uint32_t cflags=NBD_FLAG_C_FIXED_NEWSTYLE;
966 uint32_t opts=0;
967 sigset_t block, old;
968 char *certfile = NULL;
969 char *keyfile = NULL;
970 char *cacertfile = NULL;
971 char *tlshostname = NULL;
972 char *priority = NULL;
973 bool tls = false;
974 struct sigaction sa;
975 int num_connections = 1;
976 int netlink = HAVE_NETLINK;
977 int need_disconnect = 0;
978 int *sockfds;
979 struct option long_options[] = {
980 { "cacertfile", required_argument, NULL, 'A' },
981 { "block-size", required_argument, NULL, 'b' },
982 { "size", required_argument, NULL, 'B' },
983 { "check", required_argument, NULL, 'c' },
984 { "connections", required_argument, NULL, 'C'},
985 { "disconnect", required_argument, NULL, 'd' },
986 { "certfile", required_argument, NULL, 'F' },
987 { "no-optgo", no_argument, NULL, 'g' },
988 { "help", no_argument, NULL, 'h' },
989 { "tlshostname", required_argument, NULL, 'H' },
990 { "keyfile", required_argument, NULL, 'K' },
991 { "list", no_argument, NULL, 'l' },
992 #if HAVE_NETLINK
993 { "nonetlink", no_argument, NULL, 'L' },
994 #endif
995 { "systemd-mark", no_argument, NULL, 'm' },
996 { "nofork", no_argument, NULL, 'n' },
997 { "name", required_argument, NULL, 'N' },
998 { "persist", no_argument, NULL, 'p' },
999 { "preinit", no_argument, NULL, 'P' },
1000 { "readonly", no_argument, NULL, 'R' },
1001 { "swap", no_argument, NULL, 's' },
1002 { "timeout", required_argument, NULL, 't' },
1003 { "unix", no_argument, NULL, 'u' },
1004 { "version", no_argument, NULL, 'V' },
1005 { "enable-tls", no_argument, NULL, 'x' },
1006 { "priority", required_argument, NULL, 'y' },
1007 { 0, 0, 0, 0 },
1009 int i;
1010 bool can_opt_go = true;
1012 logging(MY_NAME);
1014 #if HAVE_GNUTLS && !defined(NOTLS)
1015 tlssession_init();
1016 #endif
1018 while((c=getopt_long_only(argc, argv, short_opts, long_options, NULL))>=0) {
1019 switch(c) {
1020 case 1:
1021 // non-option argument
1022 if(strchr(optarg, '=')) {
1023 // old-style 'bs=' or 'timeout='
1024 // argument
1025 fprintf(stderr, "WARNING: old-style command-line argument encountered. This is deprecated.\n");
1026 if(!strncmp(optarg, "bs=", 3)) {
1027 optarg+=3;
1028 goto blocksize;
1030 if(!strncmp(optarg, "timeout=", 8)) {
1031 optarg+=8;
1032 goto timeout;
1034 usage("unknown option %s encountered", optarg);
1035 exit(EXIT_FAILURE);
1037 switch(nonspecial++) {
1038 case 0:
1039 // host
1040 hostname=optarg;
1041 break;
1042 case 1:
1043 // port
1044 if(!strtol(optarg, NULL, 0)) {
1045 // not parseable as a number, assume it's the device
1046 nbddev = optarg;
1047 nonspecial++;
1048 } else {
1049 port = optarg;
1051 break;
1052 case 2:
1053 // device
1054 nbddev = optarg;
1055 break;
1056 default:
1057 usage("too many non-option arguments specified");
1058 exit(EXIT_FAILURE);
1060 break;
1061 case 'b':
1062 blocksize:
1063 blocksize=(int)strtol(optarg, NULL, 0);
1064 if(blocksize == 0 || (blocksize % 512) != 0) {
1065 fprintf(stderr, "E: blocksize is not a multiple of 512! This is not allowed\n");
1066 exit(EXIT_FAILURE);
1068 break;
1069 case 'B':
1070 force_size64=(u64)strtoull(optarg, NULL, 0);
1071 if(force_size64 == 0) {
1072 fprintf(stderr, "E: Invalid size\n");
1073 exit(EXIT_FAILURE);
1075 break;
1076 case 'c':
1077 return check_conn(optarg, 1);
1078 case 'C':
1079 num_connections = (int)strtol(optarg, NULL, 0);
1080 break;
1081 case 'd':
1082 need_disconnect = 1;
1083 nbddev = strdup(optarg);
1084 break;
1085 case 'g':
1086 can_opt_go = false;
1087 break;
1088 case 'h':
1089 usage(NULL);
1090 exit(EXIT_SUCCESS);
1091 case 'l':
1092 needed_flags |= NBD_FLAG_FIXED_NEWSTYLE;
1093 opts |= NBDC_DO_LIST;
1094 nbddev="";
1095 break;
1096 #if HAVE_NETLINK
1097 case 'L':
1098 netlink = 0;
1099 break;
1100 #endif
1101 case 'm':
1102 argv[0][0] = '@';
1103 break;
1104 case 'n':
1105 nofork=1;
1106 break;
1107 case 'N':
1108 name=optarg;
1109 break;
1110 case 'p':
1111 cont=1;
1112 break;
1113 case 'P':
1114 preinit = true;
1115 break;
1116 case 'R':
1117 force_read_only = true;
1118 break;
1119 case 's':
1120 swap=1;
1121 break;
1122 case 't':
1123 timeout:
1124 timeout=strtol(optarg, NULL, 0);
1125 break;
1126 case 'u':
1127 b_unix = 1;
1128 break;
1129 case 'V':
1130 printf("This is %s, from %s\n", PROG_NAME, PACKAGE_STRING);
1131 return 0;
1132 #if HAVE_GNUTLS && !defined(NOTLS)
1133 case 'x':
1134 tls = true;
1135 break;
1136 case 'F':
1137 certfile=strdup(optarg);
1138 break;
1139 case 'K':
1140 keyfile=strdup(optarg);
1141 break;
1142 case 'A':
1143 cacertfile=strdup(optarg);
1144 break;
1145 case 'H':
1146 tlshostname=strdup(optarg);
1147 break;
1148 case 'y':
1149 priority=strdup(optarg);
1150 break;
1151 #else
1152 case 'F':
1153 case 'K':
1154 case 'H':
1155 case 'A':
1156 case 'y':
1157 fprintf(stderr, "E: TLS support not compiled in\n");
1158 exit(EXIT_FAILURE);
1159 #endif
1160 default:
1161 fprintf(stderr, "E: option eaten by 42 mice\n");
1162 exit(EXIT_FAILURE);
1166 if (need_disconnect) {
1167 if (netlink)
1168 netlink_disconnect(nbddev);
1169 else
1170 disconnect(nbddev);
1171 exit(EXIT_SUCCESS);
1173 #ifdef __ANDROID__
1174 if (swap)
1175 err("swap option unsupported on Android because mlockall is unsupported.");
1176 #endif
1177 if(hostname) {
1178 if((!name || !nbddev) && !(opts & NBDC_DO_LIST)) {
1179 if(!strncmp(hostname, "nbd", 3) || !strncmp(hostname, "/dev/nbd", 8)) {
1180 if(!get_from_config(hostname, &name, &nbddev, &hostname, &blocksize, &timeout, &cont, &swap, &b_unix, &port, &num_connections, &certfile, &keyfile, &cacertfile, &tlshostname, &priority, &can_opt_go)) {
1181 usage("no valid configuration for specified device found", hostname);
1182 exit(EXIT_FAILURE);
1184 } else if (!netlink) {
1185 usage("not enough information specified, and argument didn't look like an nbd device");
1186 exit(EXIT_FAILURE);
1189 } else {
1190 usage("no information specified");
1191 exit(EXIT_FAILURE);
1194 if (keyfile && !certfile)
1195 certfile = strdup(keyfile);
1197 if (certfile != NULL || keyfile != NULL || cacertfile != NULL || tlshostname != NULL) {
1198 tls = true;
1201 if (preinit) {
1202 if (tls) {
1203 fprintf(stderr, "E: preinit connection cannot be used with TLS\n");
1204 exit(EXIT_FAILURE);
1206 if (!force_size64) {
1207 fprintf(stderr, "E: preinit connection requires specifying size\n");
1208 exit(EXIT_FAILURE);
1212 if (!tlshostname && hostname && !b_unix)
1213 tlshostname = strdup(hostname);
1215 if (netlink)
1216 nofork = 1;
1218 if((force_size64 % blocksize) != 0) {
1219 fprintf(stderr, "E: size (%" PRIu64 " bytes) is not a multiple of blocksize (%d)!\n", force_size64, blocksize);
1220 exit(EXIT_FAILURE);
1223 if(strlen(name)==0 && !(opts & NBDC_DO_LIST)) {
1224 printf("Warning: the oldstyle protocol is no longer supported.\nThis method now uses the newstyle protocol with a default export\n");
1227 if(!(opts & NBDC_DO_LIST) && !netlink) {
1228 nbd = open(nbddev, O_RDWR);
1229 if (nbd < 0)
1230 err("Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded.");
1233 if (netlink) {
1234 sockfds = malloc(sizeof(int) * num_connections);
1235 if (!sockfds)
1236 err("Cannot allocate the socket fd's array");
1239 for (i = 0; i < num_connections; i++) {
1240 if (b_unix)
1241 sock = openunix(hostname);
1242 else
1243 sock = opennet(hostname, port);
1244 if (sock < 0)
1245 exit(EXIT_FAILURE);
1247 if (!preinit)
1248 negotiate(&sock, &size64, &flags, name, needed_flags, cflags, opts, certfile, keyfile, cacertfile, tlshostname, tls, priority, can_opt_go);
1249 if (force_read_only)
1250 flags |= NBD_FLAG_READ_ONLY;
1251 if (force_size64)
1252 size64 = force_size64;
1253 if (netlink) {
1254 sockfds[i] = sock;
1255 continue;
1258 if (i == 0) {
1259 setsizes(nbd, size64, blocksize, flags);
1260 set_timeout(nbd, timeout);
1262 finish_sock(sock, nbd, swap);
1263 if (swap) {
1264 if (keyfile)
1265 fprintf(stderr, "Warning: using swap and TLS is prone to deadlock\n");
1266 /* try linux >= 2.6.36 interface first */
1267 if (oom_adjust("/proc/self/oom_score_adj", "-1000")) {
1268 /* fall back to linux <= 2.6.35 interface */
1269 oom_adjust("/proc/self/oom_adj", "-17");
1274 if (netlink) {
1275 int index = -1;
1276 if (nbddev) {
1277 if (sscanf(nbddev, "/dev/nbd%d", &index) != 1)
1278 err("Invalid nbd device target\n");
1280 netlink_configure(index, sockfds, num_connections,
1281 size64, blocksize, flags, timeout);
1282 return 0;
1284 /* Go daemon */
1286 #ifndef NOFORK
1287 if(!nofork) {
1288 if (daemon(0,0) < 0)
1289 err("Cannot detach from terminal");
1292 memset(&sa, 0, sizeof(sa));
1293 sa.sa_handler = SIG_IGN;
1294 sigaction(SIGCHLD, &sa, NULL);
1295 #endif
1296 /* For child to check its parent */
1297 main_pid = getpid();
1298 do {
1299 #ifndef NOFORK
1301 sigfillset(&block);
1302 sigdelset(&block, SIGKILL);
1303 sigdelset(&block, SIGTERM);
1304 sigdelset(&block, SIGPIPE);
1305 sigprocmask(SIG_SETMASK, &block, &old);
1307 if (!fork()) {
1308 /* Due to a race, the kernel NBD driver cannot
1309 * call for a reread of the partition table
1310 * in the handling of the NBD_DO_IT ioctl().
1311 * Therefore, this is done in the first open()
1312 * of the device. We therefore make sure that
1313 * the device is opened at least once after the
1314 * connection was made. This has to be done in a
1315 * separate process, since the NBD_DO_IT ioctl()
1316 * does not return until the NBD device has
1317 * disconnected.
1319 struct timespec req = {
1320 .tv_sec = 0,
1321 .tv_nsec = 100000000,
1323 while(check_conn(nbddev, 0)) {
1324 if (main_pid != getppid()) {
1325 /* check_conn() will not return 0 when nbd disconnected
1326 * and parent exited during this loop. So the child has to
1327 * explicitly check parent identity and exit if parent
1328 * exited */
1329 exit(0);
1331 nanosleep(&req, NULL);
1333 if(open(nbddev, O_RDONLY) < 0) {
1334 perror("could not open device for updating partition table");
1336 exit(0);
1338 #endif
1340 if (ioctl(nbd, NBD_DO_IT) < 0) {
1341 int error = errno;
1342 fprintf(stderr, "nbd,%d: Kernel call returned: %s\n", main_pid, strerror(errno));
1343 if(error==EBADR) {
1344 /* The user probably did 'nbd-client -d' on us.
1345 * quit */
1346 cont=0;
1347 } else {
1348 if(cont) {
1349 u64 new_size;
1350 uint16_t new_flags;
1352 close(sock); close(nbd);
1353 for (;;) {
1354 fprintf(stderr, " Reconnecting\n");
1355 if (b_unix)
1356 sock = openunix(hostname);
1357 else
1358 sock = opennet(hostname, port);
1359 if (sock >= 0)
1360 break;
1361 sleep (1);
1363 nbd = open(nbddev, O_RDWR);
1364 if (nbd < 0)
1365 err("Cannot open NBD: %m");
1366 negotiate(&sock, &new_size, &new_flags, name, needed_flags, cflags, opts, certfile, keyfile, cacertfile, tlshostname, tls, priority, can_opt_go);
1367 if (size64 != new_size) {
1368 err("Size of the device changed. Bye");
1370 setsizes(nbd, size64, blocksize,
1371 new_flags);
1373 set_timeout(nbd, timeout);
1374 finish_sock(sock,nbd,swap);
1377 } else {
1378 /* We're on 2.4. It's not clearly defined what exactly
1379 * happened at this point. Probably best to quit, now
1381 fprintf(stderr, "Kernel call returned.\n");
1382 cont=0;
1384 } while(cont);
1385 printf("sock, ");
1386 ioctl(nbd, NBD_CLEAR_SOCK);
1387 printf("done\n");
1388 return 0;