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>
24 #include <sys/ioctl.h>
25 #include <sys/socket.h>
27 #include <sys/types.h>
29 #include <netinet/tcp.h>
30 #include <netinet/in.h>
32 #include "netdb-compat.h"
38 #include <sys/mount.h>
47 #include <linux/ioctl.h>
50 #include "nbd-netlink.h"
51 #include <netlink/netlink.h>
52 #include <netlink/genl/genl.h>
53 #include <netlink/genl/ctrl.h>
56 #define MY_NAME "nbd_client"
59 #if HAVE_GNUTLS && !defined(NOTLS)
60 #include "crypto-gnutls.h"
64 #include "nbdtab_parser.tab.h"
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
);
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
);
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)) {
107 if(!strcmp(cur_client
->dev
, devn
)) {
109 cur_client
->hostn
= hostn
;
110 cur_client
->name
= exportname
;
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
;
123 void yyerror(char *msg
) {
125 fprintf(stderr
, "parse error parsing " SYSCONFDIR
"/nbdtab: %s", msg
);
130 #define NBDC_DO_LIST 1
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];
139 ret
= nla_parse(msg_attr
, NBD_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
140 genlmsg_attrlen(gnlh
, 0), NULL
);
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
);
150 static struct nl_sock
*get_nbd_socket(int *driver_id
) {
151 struct nl_sock
*socket
;
153 socket
= nl_socket_alloc();
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");
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");
165 static void netlink_configure(int index
, int *sockfds
, int num_connects
,
166 u64 size64
, int blocksize
, uint16_t flags
,
167 int timeout
, const char *identifier
) {
168 struct nl_sock
*socket
;
169 struct nlattr
*sock_attr
;
173 socket
= get_nbd_socket(&driver_id
);
174 nl_socket_modify_cb(socket
, NL_CB_VALID
, NL_CB_CUSTOM
, callback
, NULL
);
178 err("Couldn't allocate netlink message\n");
179 genlmsg_put(msg
, NL_AUTO_PORT
, NL_AUTO_SEQ
, driver_id
, 0, 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
);
187 NLA_PUT_U64(msg
, NBD_ATTR_TIMEOUT
, timeout
);
189 NLA_PUT_STRING(msg
, NBD_ATTR_BACKEND_IDENTIFIER
, identifier
);
191 sock_attr
= nla_nest_start(msg
, NBD_ATTR_SOCKETS
);
193 err("Couldn't nest the sockets for our connection\n");
194 for (i
= 0; i
< num_connects
; i
++) {
195 struct nlattr
*sock_opt
;
196 sock_opt
= nla_nest_start(msg
, NBD_SOCK_ITEM
);
198 err("Couldn't nest the sockets for our connection\n");
199 NLA_PUT_U32(msg
, NBD_SOCK_FD
, sockfds
[i
]);
200 nla_nest_end(msg
, sock_opt
);
202 nla_nest_end(msg
, sock_attr
);
204 if (nl_send_sync(socket
, msg
) < 0) {
206 err("Failed to setup device. Are you root?\n");
208 err("Failed to setup device, check dmesg\n");
213 err("Failed to create netlink message\n");
216 static void netlink_disconnect(char *nbddev
) {
217 struct nl_sock
*socket
;
223 if (sscanf(nbddev
, "/dev/nbd%d", &index
) != 1)
224 err("Invalid nbd device target\n");
227 err("Invalid nbd device target\n");
229 socket
= get_nbd_socket(&driver_id
);
233 err("Couldn't allocate netlink message\n");
234 genlmsg_put(msg
, NL_AUTO_PORT
, NL_AUTO_SEQ
, driver_id
, 0, 0,
235 NBD_CMD_DISCONNECT
, 0);
236 NLA_PUT_U32(msg
, NBD_ATTR_INDEX
, index
);
237 if (nl_send_sync(socket
, msg
) < 0)
238 err("Failed to disconnect device, check dmsg\n");
239 nl_socket_free(socket
);
242 err("Failed to create netlink message\n");
245 static void netlink_configure(int index
, int *sockfds
, int num_connects
,
246 u64 size64
, int blocksize
, uint16_t flags
,
247 int timeout
, const char *identifier
)
251 static void netlink_disconnect(char *nbddev
)
254 #endif /* HAVE_NETLINK */
256 int check_conn(char* devname
, int do_print
) {
262 if( (p
=strrchr(devname
, '/')) ) {
265 if((p
=strchr(devname
, 'p'))) {
266 /* We can't do checks on partitions. */
269 snprintf(buf
, 256, "/sys/block/%s/pid", devname
);
270 if((fd
=open(buf
, O_RDONLY
))<0) {
277 len
=read(fd
, buf
, 256);
279 perror("could not read from server");
283 buf
[(len
< 256) ? len
: 255]='\0';
284 if(do_print
) printf("%s\n", buf
);
291 struct addrinfo hints
;
292 struct addrinfo
*ai
= NULL
;
293 struct addrinfo
*rp
= NULL
;
296 memset(&hints
,'\0',sizeof(hints
));
297 hints
.ai_family
= AF_UNSPEC
;
298 hints
.ai_socktype
= SOCK_STREAM
;
299 hints
.ai_flags
= AI_ADDRCONFIG
| AI_NUMERICSERV
;
300 hints
.ai_protocol
= IPPROTO_TCP
;
302 e
= getaddrinfo(cur_client
->hostn
, cur_client
->port
, &hints
, &ai
);
305 fprintf(stderr
, "getaddrinfo failed: %s\n", gai_strerror(e
));
310 for(rp
= ai
; rp
!= NULL
; rp
= rp
->ai_next
) {
311 sock
= socket(rp
->ai_family
, rp
->ai_socktype
, rp
->ai_protocol
);
314 continue; /* error */
316 if(connect(sock
, rp
->ai_addr
, rp
->ai_addrlen
) != -1)
323 err_nonfatal("Socket failed: %m");
336 char *path
= cur_client
->hostn
;
337 struct sockaddr_un un_addr
;
338 memset(&un_addr
, 0, sizeof(un_addr
));
340 un_addr
.sun_family
= AF_UNIX
;
341 if (strnlen(path
, sizeof(un_addr
.sun_path
)) == sizeof(un_addr
.sun_path
)) {
342 err_nonfatal("UNIX socket path too long");
346 strncpy(un_addr
.sun_path
, path
, sizeof(un_addr
.sun_path
) - 1);
348 if ((sock
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1) {
349 err_nonfatal("SOCKET failed");
353 if (connect(sock
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
)) == -1) {
354 err_nonfatal("CONNECT failed");
361 void send_request(int sock
, uint32_t opt
, ssize_t datasize
, void* data
) {
366 } __attribute__((packed
)) header
= {
372 datasize
= strlen((char*)data
);
373 header
.datasize
= htonl(datasize
);
375 writeit(sock
, &header
, sizeof(header
));
377 writeit(sock
, data
, datasize
);
381 void send_info_request(int sock
, uint32_t opt
, int n_reqs
, uint16_t* reqs
, char* name
) {
382 uint16_t rlen
= htons(n_reqs
);
383 uint32_t nlen
= htonl(strlen(name
));
385 send_request(sock
, opt
, sizeof(uint32_t) + strlen(name
) + sizeof(uint16_t) + n_reqs
* sizeof(uint16_t), NULL
);
386 writeit(sock
, &nlen
, sizeof(nlen
));
387 writeit(sock
, name
, strlen(name
));
388 writeit(sock
, &rlen
, sizeof(rlen
));
390 writeit(sock
, reqs
, n_reqs
* sizeof(uint16_t));
400 } __attribute__((packed
));
402 struct reply
* read_reply(int sock
) {
403 struct reply
*retval
= malloc(sizeof(struct reply
));
408 if(readit(sock
, retval
, sizeof(*retval
)) < 0) {
413 retval
->magic
= ntohll(retval
->magic
);
414 retval
->opt
= ntohl(retval
->opt
);
415 retval
->reply_type
= ntohl(retval
->reply_type
);
416 retval
->datasize
= ntohl(retval
->datasize
);
417 if (retval
->magic
!= rep_magic
) {
418 fprintf(stderr
, "E: received invalid negotiation magic %" PRIu64
" (expected %" PRIu64
")", retval
->magic
, rep_magic
);
421 if (retval
->datasize
> 0 && retval
->datasize
< 4096) {
422 struct reply
*retval_r
= realloc(retval
, sizeof(struct reply
) + retval
->datasize
);
423 if (retval_r
== NULL
) {
428 readit(sock
, &(retval
->data
), retval
->datasize
);
433 void ask_list(int sock
) {
440 const int BUF_SIZE
= 1024;
443 send_request(sock
, NBD_OPT_LIST
, 0, NULL
);
444 /* newline, move away from the "Negotiation:" line */
447 memset(buf
, 0, 1024);
448 if(read(sock
, &magic
, sizeof(magic
)) < 0) {
449 err("Reading magic from server: %m");
451 if(read(sock
, &opt_server
, sizeof(opt_server
)) < 0) {
452 err("Reading option: %m");
454 if(read(sock
, &reptype
, sizeof(reptype
)) <0) {
455 err("Reading reply from server: %m");
457 if(read(sock
, &len
, sizeof(len
)) < 0) {
458 err("Reading length from server: %m");
462 reptype
=ntohl(reptype
);
463 if(magic
!= rep_magic
) {
464 err("Not enough magic from server");
466 if(reptype
& NBD_REP_FLAG_ERROR
) {
468 case NBD_REP_ERR_POLICY
:
469 fprintf(stderr
, "\nE: listing not allowed by server.\n");
472 fprintf(stderr
, "\nE: unexpected error from server.\n");
475 if(len
> 0 && len
< BUF_SIZE
) {
476 if((rlen
=read(sock
, buf
, len
)) < 0) {
477 fprintf(stderr
, "\nE: could not read error message from server\n");
480 fprintf(stderr
, "Server said: %s\n", buf
);
485 if(reptype
!= NBD_REP_ACK
) {
486 if(reptype
!= NBD_REP_SERVER
) {
487 err("Server sent us a reply we don't understand!");
489 if(read(sock
, &lenn
, sizeof(lenn
)) < 0) {
490 fprintf(stderr
, "\nE: could not read export name length from server\n");
494 if (lenn
>= BUF_SIZE
) {
495 fprintf(stderr
, "\nE: export name on server too long\n");
498 if(read(sock
, buf
, lenn
) < 0) {
499 fprintf(stderr
, "\nE: could not read export name from server\n");
507 if(len
>= BUF_SIZE
) {
508 fprintf(stderr
, "\nE: export description read buffer overflow\n");
511 if(read(sock
, buf
, len
) < 0) {
512 fprintf(stderr
, "\nE: could not read export description from server\n");
516 printf(": %s\n", buf
);
522 } while(reptype
!= NBD_REP_ACK
);
523 send_request(sock
, NBD_OPT_ABORT
, 0, NULL
);
526 void parse_sizes(char *buf
, uint64_t *size
, uint16_t *flags
) {
527 memcpy(size
, buf
, sizeof(*size
));
528 *size
= ntohll(*size
);
529 buf
+= sizeof(*size
);
530 memcpy(flags
, buf
, sizeof(*flags
));
531 *flags
= ntohs(*flags
);
533 if ((*size
>>12) > (uint64_t)~0UL) {
534 printf("size = %luMB", (unsigned long)(*size
>>20));
535 err("Exported device is too big for me. Get 64-bit machine :-(\n");
537 printf("size = %luMB", (unsigned long)(*size
>>20));
542 void send_opt_exportname(int sock
, uint16_t *flags
, char* name
, uint16_t global_flags
) {
543 send_request(sock
, NBD_OPT_EXPORT_NAME
, -1, name
);
544 char b
[sizeof(*flags
) + sizeof(cur_client
->size64
)];
545 if(readit(sock
, b
, sizeof(b
)) < 0 && !cur_client
->no_optgo
) {
546 err("E: server does not support NBD_OPT_GO and dropped connection after sending NBD_OPT_EXPORT_NAME. Try -g.");
548 parse_sizes(b
, &(cur_client
->size64
), flags
);
549 if(!(global_flags
& NBD_FLAG_NO_ZEROES
)) {
551 readit(sock
, buf
, 124);
555 void negotiate(int *sockp
, uint16_t *flags
, uint32_t needed_flags
, uint32_t client_flags
, uint32_t do_opts
) {
558 uint16_t global_flags
;
559 char buf
[256] = "\0\0\0\0\0\0\0\0\0";
562 printf("Negotiation: ");
563 readit(sock
, buf
, 8);
564 if (strcmp(buf
, INIT_PASSWD
))
565 err("INIT_PASSWD bad");
567 readit(sock
, &magic
, sizeof(magic
));
568 magic
= ntohll(magic
);
569 if (magic
!= opts_magic
) {
570 if(magic
== cliserv_magic
) {
571 err("It looks like you're trying to connect to an oldstyle server. This is no longer supported since nbd 3.10.");
575 readit(sock
, &tmp
, sizeof(uint16_t));
576 global_flags
= ntohs(tmp
);
577 if((needed_flags
& global_flags
) != needed_flags
) {
578 /* There's currently really only one reason why this
579 * check could possibly fail, but we may need to change
580 * this error message in the future... */
581 fprintf(stderr
, "\nE: Server does not support listing exports\n");
585 if (global_flags
& NBD_FLAG_NO_ZEROES
) {
586 client_flags
|= NBD_FLAG_C_NO_ZEROES
;
588 client_flags
= htonl(client_flags
);
589 if (write(sock
, &client_flags
, sizeof(client_flags
)) < 0)
590 err("Failed/2.1: %m");
592 #if HAVE_GNUTLS && !defined(NOTLS)
594 if (cur_client
->tls
) {
595 int plainfd
[2]; // [0] is used by the proxy, [1] is used by NBD
596 tlssession_t
*s
= NULL
;
601 send_request(sock
, NBD_OPT_STARTTLS
, 0, NULL
);
603 if (read(sock
, &tmp64
, sizeof(tmp64
)) < 0)
604 err("Could not read cliserv_magic: %m");
605 tmp64
= ntohll(tmp64
);
606 if (tmp64
!= NBD_OPT_REPLY_MAGIC
) {
607 err("reply magic does not match");
609 if (read(sock
, &tmp32
, sizeof(tmp32
)) < 0)
610 err("Could not read option type: %m");
611 tmp32
= ntohl(tmp32
);
612 if (tmp32
!= NBD_OPT_STARTTLS
)
613 err("Reply to wrong option");
614 if (read(sock
, &tmp32
, sizeof(tmp32
)) < 0)
615 err("Could not read option reply type: %m");
616 tmp32
= ntohl(tmp32
);
617 if (tmp32
!= NBD_REP_ACK
) {
618 err("Option reply type != NBD_REP_ACK");
620 if (read(sock
, &tmp32
, sizeof(tmp32
)) < 0) err(
621 "Could not read option data length: %m");
622 tmp32
= ntohl(tmp32
);
624 err("Option reply data length != 0");
626 s
= tlssession_new(0,
630 cur_client
->tlshostn
,
631 cur_client
->priority
,
632 !(cur_client
->cacert
) || !(cur_client
->tlshostn
), // insecure flag
643 err("Cannot establish TLS session");
645 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, plainfd
) < 0)
646 err("Cannot get socket pair");
648 if (set_nonblocking(plainfd
[0], 0) <0 ||
649 set_nonblocking(plainfd
[1], 0) <0 ||
650 set_nonblocking(sock
, 0) <0) {
653 err("Cannot set socket options");
658 err("Could not fork");
661 if (daemon(0, 0) < 0) {
662 /* no one will see this */
663 fprintf(stderr
, "Can't detach from the terminal");
666 signal (SIGPIPE
, SIG_IGN
);
668 tlssession_mainloop(sock
, plainfd
[0], s
);
675 sock
= plainfd
[1]; /* use the decrypted FD from now on */
679 if (cur_client
->tls
) {
680 err("TLS requested but support not compiled in");
684 if(do_opts
& NBDC_DO_LIST
) {
689 struct reply
*rep
= NULL
;
691 if(cur_client
->no_optgo
) {
692 send_opt_exportname(sock
, flags
, cur_client
->name
, global_flags
);
696 send_info_request(sock
, NBD_OPT_GO
, 0, NULL
, cur_client
->name
);
699 if(rep
!= NULL
) free(rep
);
700 rep
= read_reply(sock
);
702 err("Unable to read reply.");
705 if(rep
->reply_type
& NBD_REP_FLAG_ERROR
) {
706 switch(rep
->reply_type
) {
707 case NBD_REP_ERR_UNSUP
:
708 /* server doesn't support NBD_OPT_GO or NBD_OPT_INFO,
709 * fall back to NBD_OPT_EXPORT_NAME */
710 send_opt_exportname(sock
, flags
, cur_client
->name
, global_flags
);
713 case NBD_REP_ERR_POLICY
:
714 if(rep
->datasize
> 0) {
716 rep
->data
[rep
->datasize
- 1] = '\0';
717 snprintf(errstr
, sizeof errstr
, "Connection not allowed by server policy. Server said: %s", rep
->data
);
720 err("Connection not allowed by server policy.");
725 if(rep
->datasize
> 0) {
727 rep
->data
[rep
->datasize
- 1] = '\0';
728 snprintf(errstr
, sizeof errstr
, "Unknown error returned by server. Server said: %s", rep
->data
);
731 err("Unknown error returned by server.");
738 switch(rep
->reply_type
) {
740 memcpy(&info_type
, rep
->data
, 2);
741 info_type
= htons(info_type
);
743 case NBD_INFO_EXPORT
:
744 parse_sizes(rep
->data
+ 2, &(cur_client
->size64
), flags
);
747 // ignore these, don't need them
754 err_nonfatal("Unknown reply to NBD_OPT_GO received, ignoring");
756 } while(rep
->reply_type
!= NBD_REP_ACK
);
760 bool get_from_config() {
762 yyin
= fopen(SYSCONFDIR
"/nbdtab", "r");
763 yyout
= fopen("/dev/null", "w");
765 if(!strncmp(cur_client
->dev
, "/dev/", 5)) {
766 cur_client
->dev
+= 5;
769 fprintf(stderr
, "while opening %s: ", SYSCONFDIR
"/nbdtab");
770 perror("could not open config file");
775 if(!found_config
|| parse_error
) {
790 void setsizes(int nbd
, u64 size64
, int blocksize
, u32 flags
) {
792 int read_only
= (flags
& NBD_FLAG_READ_ONLY
) ? 1 : 0;
794 if (size64
>>12 > (uint64_t)~0UL)
795 err("Device too large.\n");
797 int tmp_blocksize
= 4096;
798 if (size64
/ (u64
)blocksize
<= (uint64_t)~0UL)
799 tmp_blocksize
= blocksize
;
800 if (ioctl(nbd
, NBD_SET_BLKSIZE
, tmp_blocksize
) < 0) {
801 fprintf(stderr
, "Failed to set blocksize %d\n",
803 err("Ioctl/1.1a failed: %m\n");
805 size
= (unsigned long)(size64
/ (u64
)tmp_blocksize
);
806 if (ioctl(nbd
, NBD_SET_SIZE_BLOCKS
, size
) < 0)
807 err("Ioctl/1.1b failed: %m\n");
808 if (tmp_blocksize
!= blocksize
) {
809 if (ioctl(nbd
, NBD_SET_BLKSIZE
, (unsigned long)blocksize
) < 0) {
810 fprintf(stderr
, "Failed to set blocksize %d\n",
812 err("Ioctl/1.1c failed: %m\n");
815 fprintf(stderr
, "bs=%d, sz=%" PRIu64
" bytes\n", blocksize
, (u64
)tmp_blocksize
* size
);
818 ioctl(nbd
, NBD_CLEAR_SOCK
);
820 /* ignore error as kernel may not support */
821 ioctl(nbd
, NBD_SET_FLAGS
, (unsigned long) flags
);
823 if (ioctl(nbd
, BLKROSET
, (unsigned long) &read_only
) < 0)
824 err("Unable to set read-only attribute for device");
827 void set_timeout(int nbd
, int timeout
) {
829 if (ioctl(nbd
, NBD_SET_TIMEOUT
, (unsigned long)timeout
) < 0)
830 err("Ioctl NBD_SET_TIMEOUT failed: %m\n");
831 fprintf(stderr
, "timeout=%d\n", timeout
);
835 void finish_sock(int sock
, int nbd
, int swap
) {
836 if (ioctl(nbd
, NBD_SET_SOCK
, sock
) < 0) {
838 err("Kernel doesn't support multiple connections\n");
840 err("Ioctl NBD_SET_SOCK failed: %m\n");
845 mlockall(MCL_CURRENT
| MCL_FUTURE
);
850 oom_adjust(const char *file
, const char *value
)
855 fd
= open(file
, O_WRONLY
);
859 rc
= write(fd
, value
, len
) != (ssize_t
) len
;
864 void usage(char* errmsg
, ...) {
868 va_start(ap
, errmsg
);
869 snprintf(tmp
, 256, "ERROR: %s\n\n", errmsg
);
870 vfprintf(stderr
, tmp
, ap
);
873 fprintf(stderr
, "%s version %s\n", PROG_NAME
, PACKAGE_VERSION
);
876 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] [-i ident|-nonetlink|-L]\n\t[-readonly|-R] [-size|-B bytes] [-preinit|-P]\n");
878 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");
880 fprintf(stderr
, "Or : nbd-client -u (with same arguments as above)\n");
881 fprintf(stderr
, "Or : nbd-client nbdX\n");
882 fprintf(stderr
, "Or : nbd-client -d nbd_device\n");
883 fprintf(stderr
, "Or : nbd-client -c nbd_device\n");
884 fprintf(stderr
, "Or : nbd-client -h|--help\n");
885 fprintf(stderr
, "Or : nbd-client -l|--list host\n");
886 fprintf(stderr
, "Or : nbd-client -V|--version\n");
887 #if HAVE_GNUTLS && !defined(NOTLS)
888 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");
890 fprintf(stderr
, "Default value for blocksize is 512\n");
891 fprintf(stderr
, "Allowed values for blocksize are 512,1024,2048,4096\n"); /* will be checked in kernel :) */
892 fprintf(stderr
, "Note, that kernel 2.4.2 and older ones do not work correctly with\n");
893 fprintf(stderr
, "blocksizes other than 1024 without patches\n");
894 fprintf(stderr
, "Default value for port is 10809. Note that port must always be numeric\n");
895 fprintf(stderr
, "Bug reports and general discussion should go to %s\n", PACKAGE_BUGREPORT
);
898 void disconnect(char* device
) {
899 int nbd
= open(device
, O_RDWR
);
902 err("Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded.");
903 printf("disconnect, ");
904 if (ioctl(nbd
, NBD_DISCONNECT
)<0)
905 err("Ioctl failed: %m\n");
907 if (ioctl(nbd
, NBD_CLEAR_SOCK
)<0)
908 err("Ioctl failed: %m\n");
913 static const char *short_opts
= "-B:b:c:d:gH:hlnN:PpRSst:uVxy:"
922 int main(int argc
, char *argv
[]) {
923 char* port
=NBD_DEFAULT_PORT
;
926 int G_GNUC_UNUSED nofork
=0; // if -dNOFORK
931 uint16_t needed_flags
=0;
932 uint32_t cflags
=NBD_FLAG_C_FIXED_NEWSTYLE
;
936 char *identifier
= NULL
;
937 int netlink
= HAVE_NETLINK
;
938 int need_disconnect
= 0;
940 struct option long_options
[] = {
941 { "cacertfile", required_argument
, NULL
, 'A' },
942 { "block-size", required_argument
, NULL
, 'b' },
943 { "size", required_argument
, NULL
, 'B' },
944 { "check", required_argument
, NULL
, 'c' },
945 { "connections", required_argument
, NULL
, 'C'},
946 { "disconnect", required_argument
, NULL
, 'd' },
947 { "certfile", required_argument
, NULL
, 'F' },
948 { "no-optgo", no_argument
, NULL
, 'g' },
949 { "help", no_argument
, NULL
, 'h' },
950 { "tlshostname", required_argument
, NULL
, 'H' },
952 { "identifier", required_argument
, NULL
, 'i' },
954 { "keyfile", required_argument
, NULL
, 'K' },
955 { "list", no_argument
, NULL
, 'l' },
957 { "nonetlink", no_argument
, NULL
, 'L' },
959 { "systemd-mark", no_argument
, NULL
, 'm' },
960 { "nofork", no_argument
, NULL
, 'n' },
961 { "name", required_argument
, NULL
, 'N' },
962 { "persist", no_argument
, NULL
, 'p' },
963 { "preinit", no_argument
, NULL
, 'P' },
964 { "readonly", no_argument
, NULL
, 'R' },
965 { "swap", no_argument
, NULL
, 's' },
966 { "timeout", required_argument
, NULL
, 't' },
967 { "unix", no_argument
, NULL
, 'u' },
968 { "version", no_argument
, NULL
, 'V' },
969 { "enable-tls", no_argument
, NULL
, 'x' },
970 { "priority", required_argument
, NULL
, 'y' },
977 #if HAVE_GNUTLS && !defined(NOTLS)
980 cur_client
= calloc(sizeof(CLIENT
), 1);
981 cur_client
->bs
= 512;
982 cur_client
->nconn
= 1;
983 cur_client
->port
= NBD_DEFAULT_PORT
;
985 while((c
=getopt_long_only(argc
, argv
, short_opts
, long_options
, NULL
))>=0) {
988 // non-option argument
989 if(strchr(optarg
, '=')) {
990 // old-style 'bs=' or 'timeout='
992 fprintf(stderr
, "WARNING: old-style command-line argument encountered. This is deprecated.\n");
993 if(!strncmp(optarg
, "bs=", 3)) {
997 if(!strncmp(optarg
, "timeout=", 8)) {
1001 usage("unknown option %s encountered", optarg
);
1004 switch(nonspecial
++) {
1007 cur_client
->hostn
=optarg
;
1011 if(!strtol(optarg
, NULL
, 0)) {
1012 // not parseable as a number, assume it's the device
1013 cur_client
->dev
= optarg
;
1021 cur_client
->dev
= optarg
;
1024 usage("too many non-option arguments specified");
1030 cur_client
->bs
=(int)strtol(optarg
, NULL
, 0);
1031 if(cur_client
->bs
== 0 || (cur_client
->bs
% 512) != 0) {
1032 fprintf(stderr
, "E: blocksize is not a multiple of 512! This is not allowed\n");
1037 cur_client
->force_size64
=(uint64_t)strtoull(optarg
, NULL
, 0);
1038 if(cur_client
->force_size64
== 0) {
1039 fprintf(stderr
, "E: Invalid size\n");
1044 return check_conn(optarg
, 1);
1046 cur_client
->nconn
= (int)strtol(optarg
, NULL
, 0);
1049 need_disconnect
= 1;
1050 cur_client
->dev
= strdup(optarg
);
1053 cur_client
->no_optgo
= true;
1060 identifier
= optarg
;
1064 needed_flags
|= NBD_FLAG_FIXED_NEWSTYLE
;
1065 opts
|= NBDC_DO_LIST
;
1080 cur_client
->name
= optarg
;
1086 cur_client
->preinit
= true;
1089 cur_client
->force_ro
= true;
1092 cur_client
->swap
= true;
1096 cur_client
->timeout
= strtol(optarg
, NULL
, 0);
1099 cur_client
->b_unix
= 1;
1102 printf("This is %s, from %s\n", PROG_NAME
, PACKAGE_STRING
);
1104 #if HAVE_GNUTLS && !defined(NOTLS)
1106 cur_client
->tls
= true;
1109 cur_client
->cert
=strdup(optarg
);
1112 cur_client
->key
=strdup(optarg
);
1115 cur_client
->cacert
=strdup(optarg
);
1118 cur_client
->tlshostn
=strdup(optarg
);
1121 cur_client
->priority
=strdup(optarg
);
1129 fprintf(stderr
, "E: TLS support not compiled in\n");
1133 fprintf(stderr
, "E: option eaten by 42 mice\n");
1138 if (need_disconnect
) {
1140 netlink_disconnect(cur_client
->dev
);
1142 disconnect(cur_client
->dev
);
1147 err("swap option unsupported on Android because mlockall is unsupported.");
1149 if(cur_client
->hostn
) {
1150 if((!cur_client
->name
|| !cur_client
->dev
) && !(opts
& NBDC_DO_LIST
)) {
1151 if(!strncmp(cur_client
->hostn
, "nbd", 3) || !strncmp(cur_client
->hostn
, "/dev/nbd", 8)) {
1152 cur_client
->dev
= cur_client
->hostn
;
1153 if(!get_from_config()) {
1154 usage("no valid configuration for specified device found", cur_client
->hostn
);
1157 } else if (!netlink
) {
1158 usage("not enough information specified, and argument didn't look like an nbd device");
1163 usage("no information specified");
1167 if (cur_client
->key
&& !cur_client
->cert
)
1168 cur_client
->cert
= strdup(cur_client
->key
);
1170 if (cur_client
->cert
!= NULL
|| cur_client
->key
!= NULL
|| cur_client
->cacert
!= NULL
|| cur_client
->tlshostn
!= NULL
) {
1171 cur_client
->tls
= true;
1174 if (cur_client
->preinit
) {
1175 if (cur_client
->tls
) {
1176 fprintf(stderr
, "E: preinit connection cannot be used with TLS\n");
1179 if (!cur_client
->force_size64
) {
1180 fprintf(stderr
, "E: preinit connection requires specifying size\n");
1185 if (!cur_client
->tlshostn
&& cur_client
->hostn
&& !cur_client
->b_unix
)
1186 cur_client
->tlshostn
= strdup(cur_client
->hostn
);
1190 else if (identifier
) {
1191 fprintf(stderr
, "E: identifier is only useful with netlink\n");
1195 if((cur_client
->force_size64
% cur_client
->bs
) != 0) {
1196 fprintf(stderr
, "E: size (%" PRIu64
" bytes) is not a multiple of blocksize (%d)!\n", cur_client
->force_size64
, cur_client
->bs
);
1200 if(!cur_client
->name
)
1201 cur_client
->name
= "";
1202 if((strlen(cur_client
->name
)==0) && !(opts
& NBDC_DO_LIST
)) {
1203 printf("Warning: the oldstyle protocol is no longer supported.\nThis method now uses the newstyle protocol with a default export\n");
1206 if(!(opts
& NBDC_DO_LIST
) && !netlink
) {
1207 nbd
= open(cur_client
->dev
, O_RDWR
);
1209 err("Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded.");
1213 sockfds
= malloc(sizeof(int) * cur_client
->nconn
);
1215 err("Cannot allocate the socket fd's array");
1218 for (i
= 0; i
< cur_client
->nconn
; i
++) {
1219 if (cur_client
->b_unix
)
1220 sock
= openunix(cur_client
->hostn
);
1222 sock
= opennet(cur_client
->hostn
, cur_client
->port
);
1226 if (!cur_client
->preinit
)
1227 negotiate(&sock
, &flags
, needed_flags
, cflags
, opts
);
1228 if (cur_client
->force_ro
)
1229 flags
|= NBD_FLAG_READ_ONLY
;
1230 if (cur_client
->force_size64
)
1231 cur_client
->size64
= cur_client
->force_size64
;
1238 setsizes(nbd
, cur_client
->size64
, cur_client
->bs
, flags
);
1239 set_timeout(nbd
, cur_client
->timeout
);
1241 finish_sock(sock
, nbd
, cur_client
->swap
);
1242 if (cur_client
->swap
) {
1243 if (cur_client
->tls
)
1244 fprintf(stderr
, "Warning: using swap and TLS is prone to deadlock\n");
1245 /* try linux >= 2.6.36 interface first */
1246 if (oom_adjust("/proc/self/oom_score_adj", "-1000")) {
1247 /* fall back to linux <= 2.6.35 interface */
1248 oom_adjust("/proc/self/oom_adj", "-17");
1255 if (cur_client
->dev
) {
1256 if (sscanf(cur_client
->dev
, "/dev/nbd%d", &index
) != 1)
1257 err("Invalid nbd device target\n");
1259 netlink_configure(index
, sockfds
, cur_client
->nconn
,
1260 cur_client
->size64
, cur_client
->bs
, flags
, cur_client
->timeout
,
1268 if (daemon(0,0) < 0)
1269 err("Cannot detach from terminal");
1272 memset(&sa
, 0, sizeof(sa
));
1273 sa
.sa_handler
= SIG_IGN
;
1274 sigaction(SIGCHLD
, &sa
, NULL
);
1276 /* For child to check its parent */
1277 main_pid
= getpid();
1282 sigdelset(&block
, SIGKILL
);
1283 sigdelset(&block
, SIGTERM
);
1284 sigdelset(&block
, SIGPIPE
);
1285 sigprocmask(SIG_SETMASK
, &block
, &old
);
1288 /* Due to a race, the kernel NBD driver cannot
1289 * call for a reread of the partition table
1290 * in the handling of the NBD_DO_IT ioctl().
1291 * Therefore, this is done in the first open()
1292 * of the device. We therefore make sure that
1293 * the device is opened at least once after the
1294 * connection was made. This has to be done in a
1295 * separate process, since the NBD_DO_IT ioctl()
1296 * does not return until the NBD device has
1299 struct timespec req
= {
1301 .tv_nsec
= 100000000,
1303 while(check_conn(cur_client
->dev
, 0)) {
1304 if (main_pid
!= getppid()) {
1305 /* check_conn() will not return 0 when nbd disconnected
1306 * and parent exited during this loop. So the child has to
1307 * explicitly check parent identity and exit if parent
1311 nanosleep(&req
, NULL
);
1313 if(open(cur_client
->dev
, O_RDONLY
) < 0) {
1314 perror("could not open device for updating partition table");
1320 if (ioctl(nbd
, NBD_DO_IT
) < 0) {
1322 fprintf(stderr
, "nbd,%d: Kernel call returned: %s\n", main_pid
, strerror(errno
));
1324 /* The user probably did 'nbd-client -d' on us.
1329 uint64_t old_size
= cur_client
->size64
;
1332 close(sock
); close(nbd
);
1334 fprintf(stderr
, " Reconnecting\n");
1335 if (cur_client
->b_unix
)
1343 nbd
= open(cur_client
->dev
, O_RDWR
);
1345 err("Cannot open NBD: %m");
1346 negotiate(&sock
, &new_flags
, needed_flags
, cflags
, opts
);
1347 if (old_size
!= cur_client
->size64
) {
1348 err("Size of the device changed. Bye");
1350 setsizes(nbd
, cur_client
->size64
, cur_client
->bs
,
1353 set_timeout(nbd
, cur_client
->timeout
);
1354 finish_sock(sock
,nbd
,cur_client
->swap
);
1358 /* We're on 2.4. It's not clearly defined what exactly
1359 * happened at this point. Probably best to quit, now
1361 fprintf(stderr
, "Kernel call returned.\n");
1366 ioctl(nbd
, NBD_CLEAR_SOCK
);