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"
67 #define NBDC_DO_LIST 1
70 static int callback(struct nl_msg
*msg
, void *arg
) {
71 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
72 struct nlattr
*msg_attr
[NBD_ATTR_MAX
+ 1];
76 ret
= nla_parse(msg_attr
, NBD_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
77 genlmsg_attrlen(gnlh
, 0), NULL
);
79 err("Invalid response from the kernel\n");
80 if (!msg_attr
[NBD_ATTR_INDEX
])
81 err("Did not receive index from the kernel\n");
82 index
= nla_get_u32(msg_attr
[NBD_ATTR_INDEX
]);
83 printf("Connected /dev/nbd%d\n", (int)index
);
87 static struct nl_sock
*get_nbd_socket(int *driver_id
) {
88 struct nl_sock
*socket
;
90 socket
= nl_socket_alloc();
92 err("Couldn't allocate netlink socket\n");
94 if (genl_connect(socket
))
95 err("Couldn't connect to the generic netlink socket\n");
96 *driver_id
= genl_ctrl_resolve(socket
, "nbd");
98 err("Couldn't resolve the nbd netlink family, make sure the nbd module is loaded and your nbd driver supports the netlink interface.\n");
102 static void netlink_configure(int index
, int *sockfds
, int num_connects
,
103 u64 size64
, int blocksize
, uint16_t flags
,
105 struct nl_sock
*socket
;
106 struct nlattr
*sock_attr
;
110 socket
= get_nbd_socket(&driver_id
);
111 nl_socket_modify_cb(socket
, NL_CB_VALID
, NL_CB_CUSTOM
, callback
, NULL
);
115 err("Couldn't allocate netlink message\n");
116 genlmsg_put(msg
, NL_AUTO_PORT
, NL_AUTO_SEQ
, driver_id
, 0, 0,
119 NLA_PUT_U32(msg
, NBD_ATTR_INDEX
, index
);
120 NLA_PUT_U64(msg
, NBD_ATTR_SIZE_BYTES
, size64
);
121 NLA_PUT_U64(msg
, NBD_ATTR_BLOCK_SIZE_BYTES
, blocksize
);
122 NLA_PUT_U64(msg
, NBD_ATTR_SERVER_FLAGS
, flags
);
124 NLA_PUT_U64(msg
, NBD_ATTR_TIMEOUT
, timeout
);
126 sock_attr
= nla_nest_start(msg
, NBD_ATTR_SOCKETS
);
128 err("Couldn't nest the sockets for our connection\n");
129 for (i
= 0; i
< num_connects
; i
++) {
130 struct nlattr
*sock_opt
;
131 sock_opt
= nla_nest_start(msg
, NBD_SOCK_ITEM
);
133 err("Couldn't nest the sockets for our connection\n");
134 NLA_PUT_U32(msg
, NBD_SOCK_FD
, sockfds
[i
]);
135 nla_nest_end(msg
, sock_opt
);
137 nla_nest_end(msg
, sock_attr
);
139 if (nl_send_sync(socket
, msg
) < 0)
140 err("Failed to setup device, check dmesg\n");
143 err("Failed to create netlink message\n");
146 static void netlink_disconnect(char *nbddev
) {
147 struct nl_sock
*socket
;
153 if (sscanf(nbddev
, "/dev/nbd%d", &index
) != 1)
154 err("Invalid nbd device target\n");
157 err("Invalid nbd device target\n");
159 socket
= get_nbd_socket(&driver_id
);
163 err("Couldn't allocate netlink message\n");
164 genlmsg_put(msg
, NL_AUTO_PORT
, NL_AUTO_SEQ
, driver_id
, 0, 0,
165 NBD_CMD_DISCONNECT
, 0);
166 NLA_PUT_U32(msg
, NBD_ATTR_INDEX
, index
);
167 if (nl_send_sync(socket
, msg
) < 0)
168 err("Failed to disconnect device, check dmsg\n");
169 nl_socket_free(socket
);
172 err("Failed to create netlink message\n");
175 static void netlink_configure(int index
, int *sockfds
, int num_connects
,
176 u64 size64
, int blocksize
, uint16_t flags
,
181 static void netlink_disconnect(char *nbddev
)
184 #endif /* HAVE_NETLINK */
186 int check_conn(char* devname
, int do_print
) {
192 if( (p
=strrchr(devname
, '/')) ) {
195 if((p
=strchr(devname
, 'p'))) {
196 /* We can't do checks on partitions. */
199 snprintf(buf
, 256, "/sys/block/%s/pid", devname
);
200 if((fd
=open(buf
, O_RDONLY
))<0) {
207 len
=read(fd
, buf
, 256);
209 perror("could not read from server");
213 buf
[(len
< 256) ? len
: 255]='\0';
214 if(do_print
) printf("%s\n", buf
);
219 int opennet(char *name
, char* portstr
, int sdp
) {
221 struct addrinfo hints
;
222 struct addrinfo
*ai
= NULL
;
223 struct addrinfo
*rp
= NULL
;
226 memset(&hints
,'\0',sizeof(hints
));
227 hints
.ai_family
= AF_UNSPEC
;
228 hints
.ai_socktype
= SOCK_STREAM
;
229 hints
.ai_flags
= AI_ADDRCONFIG
| AI_NUMERICSERV
;
230 hints
.ai_protocol
= IPPROTO_TCP
;
232 e
= getaddrinfo(name
, portstr
, &hints
, &ai
);
235 fprintf(stderr
, "getaddrinfo failed: %s\n", gai_strerror(e
));
242 if (ai
->ai_family
== AF_INET
)
243 ai
->ai_family
= AF_INET_SDP
;
244 else (ai
->ai_family
== AF_INET6
)
245 ai
->ai_family
= AF_INET6_SDP
;
247 err("Can't do SDP: I was not compiled with SDP support!");
251 for(rp
= ai
; rp
!= NULL
; rp
= rp
->ai_next
) {
252 sock
= socket(rp
->ai_family
, rp
->ai_socktype
, rp
->ai_protocol
);
255 continue; /* error */
257 if(connect(sock
, rp
->ai_addr
, rp
->ai_addrlen
) != -1)
264 err_nonfatal("Socket failed: %m");
275 int openunix(const char *path
) {
277 struct sockaddr_un un_addr
;
278 memset(&un_addr
, 0, sizeof(un_addr
));
280 un_addr
.sun_family
= AF_UNIX
;
281 if (strnlen(path
, sizeof(un_addr
.sun_path
)) == sizeof(un_addr
.sun_path
)) {
282 err_nonfatal("UNIX socket path too long");
286 strncpy(un_addr
.sun_path
, path
, sizeof(un_addr
.sun_path
) - 1);
288 if ((sock
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1) {
289 err_nonfatal("SOCKET failed");
293 if (connect(sock
, &un_addr
, sizeof(un_addr
)) == -1) {
294 err_nonfatal("CONNECT failed");
301 void send_request(int sock
, uint32_t opt
, ssize_t datasize
, void* data
) {
306 } __attribute__((packed
)) header
= {
312 datasize
= strlen((char*)data
);
313 header
.datasize
= htonl(datasize
);
315 writeit(sock
, &header
, sizeof(header
));
317 writeit(sock
, data
, datasize
);
321 void send_info_request(int sock
, uint32_t opt
, int n_reqs
, uint16_t* reqs
, char* name
) {
322 uint16_t rlen
= htons(n_reqs
);
323 uint32_t nlen
= htonl(strlen(name
));
325 send_request(sock
, opt
, sizeof(uint32_t) + strlen(name
) + sizeof(uint16_t) + n_reqs
* sizeof(uint16_t), NULL
);
326 writeit(sock
, &nlen
, sizeof(nlen
));
327 writeit(sock
, name
, strlen(name
));
328 writeit(sock
, &rlen
, sizeof(rlen
));
330 writeit(sock
, reqs
, n_reqs
* sizeof(uint16_t));
340 } __attribute__((packed
));
342 struct reply
* read_reply(int sock
) {
343 struct reply
*retval
= malloc(sizeof(struct reply
));
344 readit(sock
, retval
, sizeof(*retval
));
345 retval
->magic
= ntohll(retval
->magic
);
346 retval
->opt
= ntohl(retval
->opt
);
347 retval
->reply_type
= ntohl(retval
->reply_type
);
348 retval
->datasize
= ntohl(retval
->datasize
);
349 if (retval
->magic
!= rep_magic
) {
350 fprintf(stderr
, "E: received invalid negotiation magic %" PRIu64
" (expected %" PRIu64
")", retval
->magic
, rep_magic
);
353 if (retval
->datasize
> 0) {
354 retval
= realloc(retval
, sizeof(struct reply
) + retval
->datasize
);
355 readit(sock
, &(retval
->data
), retval
->datasize
);
360 void ask_list(int sock
) {
367 const int BUF_SIZE
= 1024;
370 send_request(sock
, NBD_OPT_LIST
, 0, NULL
);
371 /* newline, move away from the "Negotiation:" line */
374 memset(buf
, 0, 1024);
375 if(read(sock
, &magic
, sizeof(magic
)) < 0) {
376 err("Reading magic from server: %m");
378 if(read(sock
, &opt_server
, sizeof(opt_server
)) < 0) {
379 err("Reading option: %m");
381 if(read(sock
, &reptype
, sizeof(reptype
)) <0) {
382 err("Reading reply from server: %m");
384 if(read(sock
, &len
, sizeof(len
)) < 0) {
385 err("Reading length from server: %m");
389 reptype
=ntohl(reptype
);
390 if(magic
!= rep_magic
) {
391 err("Not enough magic from server");
393 if(reptype
& NBD_REP_FLAG_ERROR
) {
395 case NBD_REP_ERR_POLICY
:
396 fprintf(stderr
, "\nE: listing not allowed by server.\n");
399 fprintf(stderr
, "\nE: unexpected error from server.\n");
402 if(len
> 0 && len
< BUF_SIZE
) {
403 if((rlen
=read(sock
, buf
, len
)) < 0) {
404 fprintf(stderr
, "\nE: could not read error message from server\n");
407 fprintf(stderr
, "Server said: %s\n", buf
);
412 if(reptype
!= NBD_REP_ACK
) {
413 if(reptype
!= NBD_REP_SERVER
) {
414 err("Server sent us a reply we don't understand!");
416 if(read(sock
, &lenn
, sizeof(lenn
)) < 0) {
417 fprintf(stderr
, "\nE: could not read export name length from server\n");
421 if (lenn
>= BUF_SIZE
) {
422 fprintf(stderr
, "\nE: export name on server too long\n");
425 if(read(sock
, buf
, lenn
) < 0) {
426 fprintf(stderr
, "\nE: could not read export name from server\n");
434 if(read(sock
, buf
, len
) < 0) {
435 fprintf(stderr
, "\nE: could not read export description from server\n");
439 printf(": %s\n", buf
);
445 } while(reptype
!= NBD_REP_ACK
);
446 send_request(sock
, NBD_OPT_ABORT
, 0, NULL
);
449 void parse_sizes(char *buf
, uint64_t *size
, uint16_t *flags
) {
450 memcpy(size
, buf
, sizeof(*size
));
451 *size
= ntohll(*size
);
452 buf
+= sizeof(*size
);
453 memcpy(flags
, buf
, sizeof(*flags
));
454 *flags
= ntohs(*flags
);
456 if ((*size
>>12) > (uint64_t)~0UL) {
457 printf("size = %luMB", (unsigned long)(*size
>>20));
458 err("Exported device is too big for me. Get 64-bit machine :-(\n");
460 printf("size = %luMB", (unsigned long)(*size
>>20));
465 void send_opt_exportname(int sock
, u64
*rsize64
, uint16_t *flags
, bool can_opt_go
, char* name
, uint16_t global_flags
) {
466 send_request(sock
, NBD_OPT_EXPORT_NAME
, -1, name
);
467 char b
[sizeof(*flags
) + sizeof(*rsize64
)];
468 if(readit(sock
, b
, sizeof(b
)) < 0 && can_opt_go
) {
469 err("E: server does not support NBD_OPT_GO and dropped connection after sending NBD_OPT_EXPORT_NAME. Try -g.");
471 parse_sizes(b
, rsize64
, flags
);
472 if(!global_flags
& NBD_FLAG_NO_ZEROES
) {
474 readit(sock
, buf
, 124);
478 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
, bool can_opt_go
) {
481 uint16_t global_flags
;
482 char buf
[256] = "\0\0\0\0\0\0\0\0\0";
485 printf("Negotiation: ");
486 readit(sock
, buf
, 8);
487 if (strcmp(buf
, INIT_PASSWD
))
488 err("INIT_PASSWD bad");
490 readit(sock
, &magic
, sizeof(magic
));
491 magic
= ntohll(magic
);
492 if (magic
!= opts_magic
) {
493 if(magic
== cliserv_magic
) {
494 err("It looks like you're trying to connect to an oldstyle server. This is no longer supported since nbd 3.10.");
498 readit(sock
, &tmp
, sizeof(uint16_t));
499 global_flags
= ntohs(tmp
);
500 if((needed_flags
& global_flags
) != needed_flags
) {
501 /* There's currently really only one reason why this
502 * check could possibly fail, but we may need to change
503 * this error message in the future... */
504 fprintf(stderr
, "\nE: Server does not support listing exports\n");
508 if (global_flags
& NBD_FLAG_NO_ZEROES
) {
509 client_flags
|= NBD_FLAG_C_NO_ZEROES
;
511 client_flags
= htonl(client_flags
);
512 if (write(sock
, &client_flags
, sizeof(client_flags
)) < 0)
513 err("Failed/2.1: %m");
515 #if HAVE_GNUTLS && !defined(NOTLS)
518 int plainfd
[2]; // [0] is used by the proxy, [1] is used by NBD
519 tlssession_t
*s
= NULL
;
524 send_request(sock
, NBD_OPT_STARTTLS
, 0, NULL
);
526 if (read(sock
, &tmp64
, sizeof(tmp64
)) < 0)
527 err("Could not read cliserv_magic: %m");
528 tmp64
= ntohll(tmp64
);
529 if (tmp64
!= NBD_OPT_REPLY_MAGIC
) {
530 err("reply magic does not match");
532 if (read(sock
, &tmp32
, sizeof(tmp32
)) < 0)
533 err("Could not read option type: %m");
534 tmp32
= ntohl(tmp32
);
535 if (tmp32
!= NBD_OPT_STARTTLS
)
536 err("Reply to wrong option");
537 if (read(sock
, &tmp32
, sizeof(tmp32
)) < 0)
538 err("Could not read option reply type: %m");
539 tmp32
= ntohl(tmp32
);
540 if (tmp32
!= NBD_REP_ACK
) {
541 err("Option reply type != NBD_REP_ACK");
543 if (read(sock
, &tmp32
, sizeof(tmp32
)) < 0) err(
544 "Could not read option data length: %m");
545 tmp32
= ntohl(tmp32
);
547 err("Option reply data length != 0");
549 s
= tlssession_new(0,
554 !cacertfile
|| !tlshostname
, // insecure flag
565 err("Cannot establish TLS session");
567 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, plainfd
) < 0)
568 err("Cannot get socket pair");
570 if (set_nonblocking(plainfd
[0], 0) <0 ||
571 set_nonblocking(plainfd
[1], 0) <0 ||
572 set_nonblocking(sock
, 0) <0) {
575 err("Cannot set socket options");
580 err("Could not fork");
583 if (daemon(0, 0) < 0) {
584 /* no one will see this */
585 fprintf(stderr
, "Can't detach from the terminal");
588 signal (SIGPIPE
, SIG_IGN
);
590 tlssession_mainloop(sock
, plainfd
[0], s
);
597 sock
= plainfd
[1]; /* use the decrypted FD from now on */
602 err("TLS requested but support not compiled in");
606 if(do_opts
& NBDC_DO_LIST
) {
611 struct reply
*rep
= NULL
;
614 send_opt_exportname(sock
, rsize64
, flags
, can_opt_go
, name
, global_flags
);
618 send_info_request(sock
, NBD_OPT_GO
, 0, NULL
, name
);
621 if(rep
!= NULL
) free(rep
);
622 rep
= read_reply(sock
);
623 if(rep
&& (rep
->reply_type
& NBD_REP_FLAG_ERROR
)) {
624 switch(rep
->reply_type
) {
625 case NBD_REP_ERR_UNSUP
:
626 /* server doesn't support NBD_OPT_GO or NBD_OPT_INFO,
627 * fall back to NBD_OPT_EXPORT_NAME */
628 send_opt_exportname(sock
, rsize64
, flags
, can_opt_go
, name
, global_flags
);
631 case NBD_REP_ERR_POLICY
:
632 if(rep
->datasize
> 0) {
634 snprintf(errstr
, sizeof errstr
, "Connection not allowed by server policy. Server said: %s", rep
->data
);
637 err("Connection not allowed by server policy.");
642 if(rep
->datasize
> 0) {
644 snprintf(errstr
, sizeof errstr
, "Unknown error returned by server. Server said: %s", rep
->data
);
647 err("Unknown error returned by server.");
654 switch(rep
->reply_type
) {
656 memcpy(&info_type
, rep
->data
, 2);
657 info_type
= htons(info_type
);
659 case NBD_INFO_EXPORT
:
660 parse_sizes(rep
->data
+ 2, rsize64
, flags
);
663 // ignore these, don't need them
670 err_nonfatal("Unknown reply to NBD_OPT_GO received, ignoring");
672 } while(rep
->reply_type
!= NBD_REP_ACK
);
676 bool get_from_config(char* cfgname
, char** name_ptr
, char** dev_ptr
, char** hostn_ptr
, int* bs
, int* timeout
, int* persist
, int* swap
, int* sdp
, int* b_unix
, char**port
, int* num_conns
, char **certfile
, char **keyfile
, char **cacertfile
, char **tlshostname
, bool *can_opt_go
) {
677 int fd
= open(SYSCONFDIR
"/nbdtab", O_RDONLY
);
680 fprintf(stderr
, "while opening %s: ", SYSCONFDIR
"/nbdtab");
681 perror("could not open config file");
684 off_t size
= lseek(fd
, 0, SEEK_END
);
685 lseek(fd
, 0, SEEK_SET
);
687 char *fsep
= "\n\t# ";
691 perror("E: mmap'ing nbdtab");
695 data
= mmap(NULL
, (size_t)size
, PROT_READ
, MAP_SHARED
, fd
, 0);
696 if(!strncmp(cfgname
, "/dev/", 5)) {
699 char *loc
= strstr((const char*)data
, cfgname
);
703 size_t l
= strlen(cfgname
) + 6;
704 *dev_ptr
= malloc(l
);
705 snprintf(*dev_ptr
, l
, "/dev/%s", cfgname
);
707 size_t line_len
, field_len
, ws_len
;
708 #define CHECK_LEN field_len = strcspn(loc, fsep); ws_len = strspn(loc+field_len, fsep); if(field_len > line_len || line_len <= 0) { goto out; }
709 #define MOVE_NEXT line_len -= field_len + ws_len; loc += field_len + ws_len
710 // find length of line
711 line_len
= strcspn(loc
, lsep
);
712 // first field is the device node name, which we already know, so skip it
715 // next field is the hostname
717 *hostn_ptr
= strndup(loc
, field_len
);
719 // third field is the export name
721 *name_ptr
= strndup(loc
, field_len
);
722 if(ws_len
+ field_len
> line_len
) {
723 // optional last field is not there, so return success
731 // fourth field is the options field, a comma-separated field of options
733 if(!strncmp(loc
, "conns=", 6)) {
734 *num_conns
= (int)strtol(loc
+6, &loc
, 0);
737 if(!strncmp(loc
, "bs=", 3)) {
738 *bs
= (int)strtol(loc
+3, &loc
, 0);
741 if(!strncmp(loc
, "timeout=", 8)) {
742 *timeout
= (int)strtol(loc
+8, &loc
, 0);
745 if(!strncmp(loc
, "port=", 5)) {
746 *port
= strndup(loc
+5, strcspn(loc
+5, ","));
749 if(!strncmp(loc
, "persist", 7)) {
754 if(!strncmp(loc
, "swap", 4)) {
759 if(!strncmp(loc
, "sdp", 3)) {
764 if(!strncmp(loc
, "unix", 4)) {
769 if(!strncmp(loc
, "certfile=", 9)) {
770 *certfile
= strndup(loc
+9, strcspn(loc
+9, ","));
773 if(!strncmp(loc
, "keyfile=", 8)) {
774 *keyfile
= strndup(loc
+8, strcspn(loc
+8, ","));
777 if(!strncmp(loc
, "cacertfile=", 11)) {
778 *cacertfile
= strndup(loc
+11, strcspn(loc
+11, ","));
781 if(!strncmp(loc
, "tlshostname=", 9)) {
782 *tlshostname
= strndup(loc
+9, strcspn(loc
+9, ","));
785 if(!strncmp(loc
, "no_optgo", 8)) {
789 // skip unknown options, with a warning unless they start with a '_'
790 l
= strcspn(loc
, ",");
792 char* s
= strndup(loc
, l
);
793 fprintf(stderr
, "Warning: unknown option '%s' found in nbdtab file", s
);
801 } while(strcspn(loc
, lsep
) > 0);
813 void setsizes(int nbd
, u64 size64
, int blocksize
, u32 flags
) {
815 int read_only
= (flags
& NBD_FLAG_READ_ONLY
) ? 1 : 0;
817 if (size64
>>12 > (uint64_t)~0UL)
818 err("Device too large.\n");
820 int tmp_blocksize
= 4096;
821 if (size64
/ (u64
)blocksize
<= (uint64_t)~0UL)
822 tmp_blocksize
= blocksize
;
823 if (ioctl(nbd
, NBD_SET_BLKSIZE
, tmp_blocksize
) < 0) {
824 fprintf(stderr
, "Failed to set blocksize %d\n",
826 err("Ioctl/1.1a failed: %m\n");
828 size
= (unsigned long)(size64
/ (u64
)tmp_blocksize
);
829 if (ioctl(nbd
, NBD_SET_SIZE_BLOCKS
, size
) < 0)
830 err("Ioctl/1.1b failed: %m\n");
831 if (tmp_blocksize
!= blocksize
) {
832 if (ioctl(nbd
, NBD_SET_BLKSIZE
, (unsigned long)blocksize
) < 0) {
833 fprintf(stderr
, "Failed to set blocksize %d\n",
835 err("Ioctl/1.1c failed: %m\n");
838 fprintf(stderr
, "bs=%d, sz=%" PRIu64
" bytes\n", blocksize
, (u64
)tmp_blocksize
* size
);
841 ioctl(nbd
, NBD_CLEAR_SOCK
);
843 /* ignore error as kernel may not support */
844 ioctl(nbd
, NBD_SET_FLAGS
, (unsigned long) flags
);
846 if (ioctl(nbd
, BLKROSET
, (unsigned long) &read_only
) < 0)
847 err("Unable to set read-only attribute for device");
850 void set_timeout(int nbd
, int timeout
) {
852 if (ioctl(nbd
, NBD_SET_TIMEOUT
, (unsigned long)timeout
) < 0)
853 err("Ioctl NBD_SET_TIMEOUT failed: %m\n");
854 fprintf(stderr
, "timeout=%d\n", timeout
);
858 void finish_sock(int sock
, int nbd
, int swap
) {
859 if (ioctl(nbd
, NBD_SET_SOCK
, sock
) < 0) {
861 err("Kernel doesn't support multiple connections\n");
863 err("Ioctl NBD_SET_SOCK failed: %m\n");
868 mlockall(MCL_CURRENT
| MCL_FUTURE
);
873 oom_adjust(const char *file
, const char *value
)
878 fd
= open(file
, O_WRONLY
);
882 rc
= write(fd
, value
, len
) != (ssize_t
) len
;
887 void usage(char* errmsg
, ...) {
891 va_start(ap
, errmsg
);
892 snprintf(tmp
, 256, "ERROR: %s\n\n", errmsg
);
893 vfprintf(stderr
, tmp
, ap
);
896 fprintf(stderr
, "%s version %s\n", PROG_NAME
, PACKAGE_VERSION
);
899 fprintf(stderr
, "Usage: nbd-client -name|-N name host [port] nbd_device\n\t[-block-size|-b block size] [-timeout|-t timeout] [-swap|-s] [-sdp|-S]\n\t[-persist|-p] [-nofork|-n] [-systemd-mark|-m] [-nonetlink|-L]\n");
901 fprintf(stderr
, "Usage: nbd-client -name|-N name host [port] nbd_device\n\t[-block-size|-b block size] [-timeout|-t timeout] [-swap|-s] [-sdp|-S]\n\t[-persist|-p] [-nofork|-n] [-systemd-mark|-m]\n");
903 fprintf(stderr
, "Or : nbd-client -u (with same arguments as above)\n");
904 fprintf(stderr
, "Or : nbd-client nbdX\n");
905 fprintf(stderr
, "Or : nbd-client -d nbd_device\n");
906 fprintf(stderr
, "Or : nbd-client -c nbd_device\n");
907 fprintf(stderr
, "Or : nbd-client -h|--help\n");
908 fprintf(stderr
, "Or : nbd-client -l|--list host\n");
909 fprintf(stderr
, "Or : nbd-client -V|--version\n");
910 #if HAVE_GNUTLS && !defined(NOTLS)
911 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");
913 fprintf(stderr
, "Default value for blocksize is 1024 (recommended for ethernet)\n");
914 fprintf(stderr
, "Allowed values for blocksize are 512,1024,2048,4096\n"); /* will be checked in kernel :) */
915 fprintf(stderr
, "Note, that kernel 2.4.2 and older ones do not work correctly with\n");
916 fprintf(stderr
, "blocksizes other than 1024 without patches\n");
917 fprintf(stderr
, "Default value for port is 10809. Note that port must always be numeric\n");
918 fprintf(stderr
, "Bug reports and general discussion should go to %s\n", PACKAGE_BUGREPORT
);
921 void disconnect(char* device
) {
922 int nbd
= open(device
, O_RDWR
);
925 err("Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded.");
926 printf("disconnect, ");
927 if (ioctl(nbd
, NBD_DISCONNECT
)<0)
928 err("Ioctl failed: %m\n");
930 if (ioctl(nbd
, NBD_CLEAR_SOCK
)<0)
931 err("Ioctl failed: %m\n");
936 static const char *short_opts
= "-A:b:c:C:d:H:hK:LlnN:pSst:uVx";
938 static const char *short_opts
= "-A:b:c:C:d:gH:hK:lnN:pSst:uVx";
941 int main(int argc
, char *argv
[]) {
942 char* port
=NBD_DEFAULT_PORT
;
951 int G_GNUC_UNUSED nofork
=0; // if -dNOFORK
959 uint16_t needed_flags
=0;
960 uint32_t cflags
=NBD_FLAG_C_FIXED_NEWSTYLE
;
963 char *certfile
= NULL
;
964 char *keyfile
= NULL
;
965 char *cacertfile
= NULL
;
966 char *tlshostname
= NULL
;
969 int num_connections
= 1;
970 int netlink
= HAVE_NETLINK
;
971 int need_disconnect
= 0;
973 struct option long_options
[] = {
974 { "cacertfile", required_argument
, NULL
, 'A' },
975 { "block-size", required_argument
, NULL
, 'b' },
976 { "check", required_argument
, NULL
, 'c' },
977 { "connections", required_argument
, NULL
, 'C'},
978 { "disconnect", required_argument
, NULL
, 'd' },
979 { "certfile", required_argument
, NULL
, 'F' },
980 { "no-optgo", no_argument
, NULL
, 'g' },
981 { "help", no_argument
, NULL
, 'h' },
982 { "tlshostname", required_argument
, NULL
, 'H' },
983 { "keyfile", required_argument
, NULL
, 'K' },
984 { "list", no_argument
, NULL
, 'l' },
986 { "nonetlink", no_argument
, NULL
, 'L' },
988 { "systemd-mark", no_argument
, NULL
, 'm' },
989 { "nofork", no_argument
, NULL
, 'n' },
990 { "name", required_argument
, NULL
, 'N' },
991 { "persist", no_argument
, NULL
, 'p' },
992 { "sdp", no_argument
, NULL
, 'S' },
993 { "swap", no_argument
, NULL
, 's' },
994 { "timeout", required_argument
, NULL
, 't' },
995 { "unix", no_argument
, NULL
, 'u' },
996 { "version", no_argument
, NULL
, 'V' },
997 { "enable-tls", no_argument
, NULL
, 'x' },
1001 bool can_opt_go
= true;
1005 #if HAVE_GNUTLS && !defined(NOTLS)
1009 while((c
=getopt_long_only(argc
, argv
, short_opts
, long_options
, NULL
))>=0) {
1012 // non-option argument
1013 if(strchr(optarg
, '=')) {
1014 // old-style 'bs=' or 'timeout='
1016 fprintf(stderr
, "WARNING: old-style command-line argument encountered. This is deprecated.\n");
1017 if(!strncmp(optarg
, "bs=", 3)) {
1021 if(!strncmp(optarg
, "timeout=", 8)) {
1025 usage("unknown option %s encountered", optarg
);
1028 switch(nonspecial
++) {
1035 if(!strtol(optarg
, NULL
, 0)) {
1036 // not parseable as a number, assume it's the device
1048 usage("too many non-option arguments specified");
1054 blocksize
=(int)strtol(optarg
, NULL
, 0);
1057 return check_conn(optarg
, 1);
1059 num_connections
= (int)strtol(optarg
, NULL
, 0);
1062 need_disconnect
= 1;
1063 nbddev
= strdup(optarg
);
1072 needed_flags
|= NBD_FLAG_FIXED_NEWSTYLE
;
1073 opts
|= NBDC_DO_LIST
;
1101 timeout
=strtol(optarg
, NULL
, 0);
1107 printf("This is %s, from %s\n", PROG_NAME
, PACKAGE_STRING
);
1109 #if HAVE_GNUTLS && !defined(NOTLS)
1114 certfile
=strdup(optarg
);
1117 keyfile
=strdup(optarg
);
1120 cacertfile
=strdup(optarg
);
1123 tlshostname
=strdup(optarg
);
1130 fprintf(stderr
, "E: TLS support not compiled in\n");
1134 fprintf(stderr
, "E: option eaten by 42 mice\n");
1139 if (need_disconnect
) {
1141 netlink_disconnect(nbddev
);
1148 err("swap option unsupported on Android because mlockall is unsupported.");
1151 if((!name
|| !nbddev
) && !(opts
& NBDC_DO_LIST
)) {
1152 if(!strncmp(hostname
, "nbd", 3) || !strncmp(hostname
, "/dev/nbd", 8)) {
1153 if(!get_from_config(hostname
, &name
, &nbddev
, &hostname
, &blocksize
, &timeout
, &cont
, &swap
, &sdp
, &b_unix
, &port
, &num_connections
, &certfile
, &keyfile
, &cacertfile
, &hostname
, &can_opt_go
)) {
1154 usage("no valid configuration for specified device found", hostname
);
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 (keyfile
&& !certfile
)
1168 certfile
= strdup(keyfile
);
1170 if (certfile
!= NULL
|| keyfile
!= NULL
|| cacertfile
!= NULL
|| tlshostname
!= NULL
) {
1174 if (!tlshostname
&& hostname
)
1175 tlshostname
= strdup(hostname
);
1180 if(strlen(name
)==0 && !(opts
& NBDC_DO_LIST
)) {
1181 printf("Warning: the oldstyle protocol is no longer supported.\nThis method now uses the newstyle protocol with a default export\n");
1184 if(!(opts
& NBDC_DO_LIST
) && !netlink
) {
1185 nbd
= open(nbddev
, O_RDWR
);
1187 err("Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded.");
1191 sockfds
= malloc(sizeof(int) * num_connections
);
1193 err("Cannot allocate the socket fd's array");
1196 for (i
= 0; i
< num_connections
; i
++) {
1198 sock
= openunix(hostname
);
1200 sock
= opennet(hostname
, port
, sdp
);
1204 negotiate(&sock
, &size64
, &flags
, name
, needed_flags
, cflags
, opts
, certfile
, keyfile
, cacertfile
, tlshostname
, tls
, can_opt_go
);
1211 setsizes(nbd
, size64
, blocksize
, flags
);
1212 set_timeout(nbd
, timeout
);
1214 finish_sock(sock
, nbd
, swap
);
1217 fprintf(stderr
, "Warning: using swap and TLS is prone to deadlock\n");
1218 /* try linux >= 2.6.36 interface first */
1219 if (oom_adjust("/proc/self/oom_score_adj", "-1000")) {
1220 /* fall back to linux <= 2.6.35 interface */
1221 oom_adjust("/proc/self/oom_adj", "-17");
1229 if (sscanf(nbddev
, "/dev/nbd%d", &index
) != 1)
1230 err("Invalid nbd device target\n");
1232 netlink_configure(index
, sockfds
, num_connections
,
1233 size64
, blocksize
, flags
, timeout
);
1240 if (daemon(0,0) < 0)
1241 err("Cannot detach from terminal");
1244 memset(&sa
, 0, sizeof(sa
));
1245 sa
.sa_handler
= SIG_IGN
;
1246 sigaction(SIGCHLD
, &sa
, NULL
);
1248 /* For child to check its parent */
1249 main_pid
= getpid();
1254 sigdelset(&block
, SIGKILL
);
1255 sigdelset(&block
, SIGTERM
);
1256 sigdelset(&block
, SIGPIPE
);
1257 sigprocmask(SIG_SETMASK
, &block
, &old
);
1260 /* Due to a race, the kernel NBD driver cannot
1261 * call for a reread of the partition table
1262 * in the handling of the NBD_DO_IT ioctl().
1263 * Therefore, this is done in the first open()
1264 * of the device. We therefore make sure that
1265 * the device is opened at least once after the
1266 * connection was made. This has to be done in a
1267 * separate process, since the NBD_DO_IT ioctl()
1268 * does not return until the NBD device has
1271 struct timespec req
= {
1273 .tv_nsec
= 100000000,
1275 while(check_conn(nbddev
, 0)) {
1276 if (main_pid
!= getppid()) {
1277 /* check_conn() will not return 0 when nbd disconnected
1278 * and parent exited during this loop. So the child has to
1279 * explicitly check parent identity and exit if parent
1283 nanosleep(&req
, NULL
);
1285 if(open(nbddev
, O_RDONLY
) < 0) {
1286 perror("could not open device for updating partition table");
1292 if (ioctl(nbd
, NBD_DO_IT
) < 0) {
1294 fprintf(stderr
, "nbd,%d: Kernel call returned: %s\n", main_pid
, strerror(errno
));
1296 /* The user probably did 'nbd-client -d' on us.
1304 close(sock
); close(nbd
);
1306 fprintf(stderr
, " Reconnecting\n");
1308 sock
= openunix(hostname
);
1310 sock
= opennet(hostname
, port
, sdp
);
1315 nbd
= open(nbddev
, O_RDWR
);
1317 err("Cannot open NBD: %m");
1318 negotiate(&sock
, &new_size
, &new_flags
, name
, needed_flags
, cflags
, opts
, certfile
, keyfile
, cacertfile
, tlshostname
, tls
, can_opt_go
);
1319 if (size64
!= new_size
) {
1320 err("Size of the device changed. Bye");
1322 setsizes(nbd
, size64
, blocksize
,
1325 set_timeout(nbd
, timeout
);
1326 finish_sock(sock
,nbd
,swap
);
1330 /* We're on 2.4. It's not clearly defined what exactly
1331 * happened at this point. Probably best to quit, now
1333 fprintf(stderr
, "Kernel call returned.\n");
1338 ioctl(nbd
, NBD_CLEAR_SOCK
);