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