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> 37 #include <sys/mount.h> 44 #include <linux/ioctl.h> 45 #define MY_NAME "nbd_client" 52 #define NBDC_DO_LIST 1 60 if( (p=strrchr(devname,
'/')) ) {
63 if((p=strchr(devname,
'p'))) {
67 snprintf(buf, 256,
"/sys/block/%s/pid", devname);
68 if((fd=open(buf, O_RDONLY))<0) {
75 len=read(fd, buf, 256);
77 perror(
"could not read from server");
80 buf[(len < 256) ? len : 255]=
'\0';
81 if(do_print) printf(
"%s\n", buf);
86 int opennet(
char *name,
char* portstr,
int sdp) {
88 struct addrinfo hints;
89 struct addrinfo *ai = NULL;
90 struct addrinfo *rp = NULL;
93 memset(&hints,
'\0',
sizeof(hints));
94 hints.ai_family = AF_UNSPEC;
95 hints.ai_socktype = SOCK_STREAM;
97 hints.ai_protocol = IPPROTO_TCP;
99 e = getaddrinfo(name, portstr, &hints, &ai);
102 fprintf(stderr,
"getaddrinfo failed: %s\n", gai_strerror(e));
109 if (ai->ai_family == AF_INET)
110 ai->ai_family = AF_INET_SDP;
111 else (ai->ai_family == AF_INET6)
112 ai->ai_family = AF_INET6_SDP;
114 err(
"Can't do SDP: I was not compiled with SDP support!");
118 for(rp = ai; rp != NULL; rp = rp->ai_next) {
119 sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
124 if(connect(sock, rp->ai_addr, rp->ai_addrlen) != -1)
144 struct sockaddr_un un_addr;
145 memset(&un_addr, 0,
sizeof(un_addr));
147 un_addr.sun_family = AF_UNIX;
148 if (strnlen(path,
sizeof(un_addr.sun_path)) ==
sizeof(un_addr.sun_path)) {
153 strncpy(un_addr.sun_path, path,
sizeof(un_addr.sun_path) - 1);
155 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
160 if (connect(sock, &un_addr,
sizeof(un_addr)) == -1) {
174 const int BUF_SIZE = 1024;
178 if (write(sock, &magic,
sizeof(magic)) < 0)
179 err(
"Failed/2.2: %m");
183 if(write(sock, &opt,
sizeof(opt)) < 0) {
184 err(
"writing list option failed: %m");
188 if(write(sock, &len,
sizeof(len)) < 0) {
189 err(
"writing length failed: %m");
194 memset(buf, 0, 1024);
195 if(read(sock, &magic,
sizeof(magic)) < 0) {
196 err(
"Reading magic from server: %m");
198 if(read(sock, &opt_server,
sizeof(opt_server)) < 0) {
199 err(
"Reading option: %m");
201 if(read(sock, &reptype,
sizeof(reptype)) <0) {
202 err(
"Reading reply from server: %m");
204 if(read(sock, &len,
sizeof(len)) < 0) {
205 err(
"Reading length from server: %m");
209 reptype=ntohl(reptype);
211 err(
"Not enough magic from server");
216 fprintf(stderr,
"\nE: listing not allowed by server.\n");
219 fprintf(stderr,
"\nE: unexpected error from server.\n");
222 if(len > 0 && len < BUF_SIZE) {
223 if(len=read(sock, buf, len) < 0) {
224 fprintf(stderr,
"\nE: could not read error message from server\n");
227 fprintf(stderr,
"Server said: %s\n", buf);
233 err(
"Server sent us a reply we don't understand!");
235 if(read(sock, &len,
sizeof(len)) < 0) {
236 fprintf(stderr,
"\nE: could not read export name length from server\n");
240 if (len >= BUF_SIZE) {
241 fprintf(stderr,
"\nE: export name on server too long\n");
244 if(read(sock, buf, len) < 0) {
245 fprintf(stderr,
"\nE: could not read export name from server\n");
256 if (write(sock, &magic,
sizeof(magic)) < 0)
257 err(
"Failed/2.2: %m");
258 if (write(sock, &opt,
sizeof(opt)) < 0)
259 err(
"Failed writing abort");
260 if (write(sock, &len,
sizeof(len)) < 0)
261 err(
"Failed writing length");
264 void negotiate(
int sock, u64 *rsize64, uint16_t *flags,
char* name, uint32_t needed_flags, uint32_t client_flags, uint32_t do_opts) {
267 uint16_t global_flags;
268 char buf[256] =
"\0\0\0\0\0\0\0\0\0";
272 printf(
"Negotiation: ");
273 if (read(sock, buf, 8) < 0)
276 err(
"Server closed connection");
278 err(
"INIT_PASSWD bad");
280 if (read(sock, &magic,
sizeof(magic)) < 0)
285 err(
"It looks like you're trying to connect to an oldstyle server. This is no longer supported since nbd 3.10.");
289 if(read(sock, &tmp,
sizeof(uint16_t)) < 0) {
290 err(
"Failed reading flags: %m");
292 global_flags = ntohs(tmp);
293 if((needed_flags & global_flags) != needed_flags) {
297 fprintf(stderr,
"\nE: Server does not support listing exports\n");
304 client_flags = htonl(client_flags);
305 if (write(sock, &client_flags,
sizeof(client_flags)) < 0)
306 err(
"Failed/2.1: %m");
315 if (write(sock, &magic,
sizeof(magic)) < 0)
316 err(
"Failed/2.2: %m");
319 if (write(sock, &opt,
sizeof(opt)) < 0)
320 err(
"Failed/2.3: %m");
321 namesize = (u32)strlen(name);
322 namesize = ntohl(namesize);
323 if (write(sock, &namesize,
sizeof(namesize)) < 0)
324 err(
"Failed/2.4: %m");
325 if (write(sock, name, strlen(name)) < 0)
326 err(
"Failed/2.4: %m");
328 if (read(sock, &size64,
sizeof(size64)) <= 0) {
330 err(
"Server closed connection");
331 err(
"Failed/3: %m\n");
335 if ((size64>>12) > (uint64_t)~0UL) {
336 printf(
"size = %luMB", (
unsigned long)(size64>>20));
337 err(
"Exported device is too big for me. Get 64-bit machine :-(\n");
339 printf(
"size = %luMB", (
unsigned long)(size64>>20));
341 if(read(sock, &tmp,
sizeof(tmp)) < 0)
342 err(
"Failed/4: %m\n");
343 *flags = (uint32_t)ntohs(tmp);
345 if (!(global_flags & NBD_FLAG_NO_ZEROES)) {
346 if (read(sock, &buf, 124) < 0)
347 err(
"Failed/5: %m\n");
354 void setsizes(
int nbd, u64 size64,
int blocksize, u32 flags) {
358 if (size64>>12 > (uint64_t)~0UL)
359 err(
"Device too large.\n");
362 err(
"Ioctl/1.1a failed: %m\n");
363 size = (
unsigned long)(size64>>12);
365 err(
"Ioctl/1.1b failed: %m\n");
367 err(
"Ioctl/1.1c failed: %m\n");
368 fprintf(stderr,
"bs=%d, sz=%llu bytes\n", blocksize, 4096ULL*size);
376 if (ioctl(nbd, BLKROSET, (
unsigned long) &read_only) < 0)
377 err(
"Unable to set read-only attribute for device");
383 err(
"Ioctl NBD_SET_TIMEOUT failed: %m\n");
384 fprintf(stderr,
"timeout=%d\n", timeout);
390 err(
"Ioctl NBD_SET_SOCK failed: %m\n");
394 mlockall(MCL_CURRENT | MCL_FUTURE);
404 fd = open(file, O_WRONLY);
408 rc = write(fd, value, len) != (ssize_t) len;
417 va_start(ap, errmsg);
418 snprintf(tmp, 256,
"ERROR: %s\n\n", errmsg);
419 vfprintf(stderr, tmp, ap);
424 fprintf(stderr,
"Usage: nbd-client -name|-N name host [port] nbd_device [-block-size|-b block size] [-timeout|-t timeout] [-swap|-s] [-sdp|-S] [-persist|-p] [-nofork|-n] [-systemd-mark|-m]\n");
425 fprintf(stderr,
"Or : nbd-client -d nbd_device\n");
426 fprintf(stderr,
"Or : nbd-client -c nbd_device\n");
427 fprintf(stderr,
"Or : nbd-client -h|--help\n");
428 fprintf(stderr,
"Or : nbd-client -l|--list host\n");
429 fprintf(stderr,
"Default value for blocksize is 1024 (recommended for ethernet)\n");
430 fprintf(stderr,
"Allowed values for blocksize are 512,1024,2048,4096\n");
431 fprintf(stderr,
"Note, that kernel 2.4.2 and older ones do not work correctly with\n");
432 fprintf(stderr,
"blocksizes other than 1024 without patches\n");
433 fprintf(stderr,
"Default value for port with -N is 10809. Note that port must always be numeric\n");
437 int nbd = open(device, O_RDWR);
440 err(
"Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded.");
441 printf(
"disconnect, ");
443 err(
"Ioctl failed: %m\n");
446 err(
"Ioctl failed: %m\n");
450 int main(
int argc,
char *argv[]) {
467 uint16_t needed_flags=0;
472 struct option long_options[] = {
473 {
"block-size", required_argument, NULL,
'b' },
474 {
"check", required_argument, NULL,
'c' },
475 {
"disconnect", required_argument, NULL,
'd' },
476 {
"help", no_argument, NULL,
'h' },
477 {
"list", no_argument, NULL,
'l' },
478 {
"name", required_argument, NULL,
'N' },
479 {
"nofork", no_argument, NULL,
'n' },
480 {
"persist", no_argument, NULL,
'p' },
481 {
"sdp", no_argument, NULL,
'S' },
482 {
"swap", no_argument, NULL,
's' },
483 {
"systemd-mark", no_argument, NULL,
'm' },
484 {
"timeout", required_argument, NULL,
't' },
485 {
"unix", no_argument, NULL,
'u' },
491 while((c=getopt_long_only(argc, argv,
"-b:c:d:hlnN:pSst:u", long_options, NULL))>=0) {
495 if(strchr(optarg,
'=')) {
498 fprintf(stderr,
"WARNING: old-style command-line argument encountered. This is deprecated.\n");
499 if(!strncmp(optarg,
"bs=", 3)) {
503 if(!strncmp(optarg,
"timeout=", 8)) {
507 usage(
"unknown option %s encountered", optarg);
510 switch(nonspecial++) {
517 if(!strtol(optarg, NULL, 0)) {
530 usage(
"too many non-option arguments specified");
536 blocksize=(int)strtol(optarg, NULL, 0);
576 timeout=strtol(optarg, NULL, 0);
582 fprintf(stderr,
"E: option eaten by 42 mice\n");
589 err(
"swap option unsupported on Android because mlockall is unsupported.");
592 if(!hostname || ((!name || !nbddev) && !(opts &
NBDC_DO_LIST))) {
593 usage(
"not enough information specified");
600 sock =
opennet(hostname, port, sdp);
604 negotiate(sock, &size64, &flags, name, needed_flags, cflags, opts);
606 nbd = open(nbddev, O_RDWR);
608 err(
"Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded.");
610 setsizes(nbd, size64, blocksize, flags);
615 if (
oom_adjust(
"/proc/self/oom_score_adj",
"-1000")) {
626 err(
"Cannot detach from terminal");
629 memset(&sa, 0,
sizeof(sa));
630 sa.sa_handler = SIG_IGN;
631 sigaction(SIGCHLD, &sa, NULL);
637 sigdelset(&block, SIGKILL);
638 sigdelset(&block, SIGTERM);
639 sigdelset(&block, SIGPIPE);
640 sigprocmask(SIG_SETMASK, &block, &old);
657 open(nbddev, O_RDONLY);
664 fprintf(stderr,
"nbd,%d: Kernel call returned: %d", getpid(), error);
674 close(sock); close(nbd);
676 fprintf(stderr,
" Reconnecting\n");
680 sock =
opennet(hostname, port, sdp);
685 nbd = open(nbddev, O_RDWR);
687 err(
"Cannot open NBD: %m");
688 negotiate(sock, &new_size, &new_flags, name, needed_flags, cflags, opts);
689 if (size64 != new_size) {
690 err(
"Size of the device changed. Bye");
703 fprintf(stderr,
"Kernel call returned.");
void setsizes(int nbd, u64 size64, int blocksize, u32 flags)
void disconnect(char *device)
#define NBD_REP_FLAG_ERROR
void negotiate(int sock, u64 *rsize64, uint16_t *flags, char *name, uint32_t needed_flags, uint32_t client_flags, uint32_t do_opts)
#define NBD_FLAG_C_NO_ZEROES
#define NBD_FLAG_NO_ZEROES
void finish_sock(int sock, int nbd, int swap)
#define NBD_REP_ERR_POLICY
#define NBD_SET_SIZE_BLOCKS
void usage(char *errmsg,...)
#define NBD_OPT_EXPORT_NAME
void setmysockopt(int sock)
void err_nonfatal(const char *s)
int check_conn(char *devname, int do_print)
#define NBD_FLAG_C_FIXED_NEWSTYLE
#define NBD_FLAG_READ_ONLY
void set_timeout(int nbd, int timeout)
int openunix(const char *path)
int main(int argc, char *argv[])
static int oom_adjust(const char *file, const char *value)
int opennet(char *name, char *portstr, int sdp)
#define NBD_FLAG_FIXED_NEWSTYLE
void logging(const char *name)