74
int opennet(char *name, int port, int sdp) {
75
int opennet(char *name, char* portstr, int sdp) {
77
77
struct addrinfo hints;
78
78
struct addrinfo *ai = NULL;
79
79
struct addrinfo *rp = NULL;
82
snprintf(portstr, sizeof(portstr), "%d", port);
84
82
memset(&hints,'\0',sizeof(hints));
85
83
hints.ai_family = AF_UNSPEC;
86
84
hints.ai_socktype = SOCK_STREAM;
128
void negotiate(int sock, u64 *rsize64, u32 *flags) {
126
void negotiate(int sock, u64 *rsize64, u32 *flags, char* name) {
129
127
u64 magic, size64;
130
129
char buf[256] = "\0\0\0\0\0\0\0\0\0";
132
131
printf("Negotiation: ");
140
139
if (read(sock, &magic, sizeof(magic)) < 0)
141
140
err("Failed/2: %m");
142
141
magic = ntohll(magic);
143
if (magic != cliserv_magic)
144
err("Not enough cliserv_magic");
145
uint32_t reserved = 0;
147
if (magic != opts_magic)
148
err("Not enough opts_magic");
150
if(read(sock, &tmp, sizeof(uint16_t)) < 0) {
151
err("Failed reading flags: %m");
153
*flags = ((u32)ntohs(tmp)) << 16;
155
/* reserved for future use*/
156
if (write(sock, &reserved, sizeof(reserved)) < 0)
157
err("Failed/2.1: %m");
159
/* Write the export name that we're after */
160
magic = ntohll(opts_magic);
161
if (write(sock, &magic, sizeof(magic)) < 0)
162
err("Failed/2.2: %m");
163
opt = ntohl(NBD_OPT_EXPORT_NAME);
164
if (write(sock, &opt, sizeof(opt)) < 0)
165
err("Failed/2.3: %m");
166
namesize = (u32)strlen(name);
167
namesize = ntohl(namesize);
168
if (write(sock, &namesize, sizeof(namesize)) < 0)
169
err("Failed/2.4: %m");
170
if (write(sock, name, strlen(name)) < 0)
171
err("Failed/2.4: %m");
173
if (magic != cliserv_magic)
174
err("Not enough cliserv_magic");
147
178
if (read(sock, &size64, sizeof(size64)) < 0)
148
179
err("Failed/3: %m\n");
149
180
size64 = ntohll(size64);
151
182
#ifdef NBD_SET_SIZE_BLOCKS
152
if ((size64>>10) > (~0UL >> 1)) {
183
if ((size64>>12) > (uint64_t)~0UL) {
153
184
printf("size = %luMB", (unsigned long)(size64>>20));
154
185
err("Exported device is too big for me. Get 64-bit machine :-(\n");
156
printf("size = %luKB", (unsigned long)(size64>>10));
187
printf("size = %luMB", (unsigned long)(size64>>20));
158
189
if (size64 > (~0UL >> 1)) {
159
190
printf("size = %luKB", (unsigned long)(size64>>10));
162
193
printf("size = %lu", (unsigned long)(size64));
165
if (read(sock, flags, sizeof(*flags)) < 0)
166
err("Failed/4: %m\n");
167
*flags = ntohl(*flags);
197
if (read(sock, flags, sizeof(*flags)) < 0)
198
err("Failed/4: %m\n");
199
*flags = ntohl(*flags);
201
if(read(sock, &tmp, sizeof(tmp)) < 0)
202
err("Failed/4: %m\n");
203
*flags |= (uint32_t)ntohs(tmp);
169
206
if (read(sock, &buf, 124) < 0)
170
207
err("Failed/5: %m\n");
178
215
int read_only = (flags & NBD_FLAG_READ_ONLY) ? 1 : 0;
180
217
#ifdef NBD_SET_SIZE_BLOCKS
181
if (size64/blocksize > (~0UL >> 1))
218
if (size64>>12 > (uint64_t)~0UL)
182
219
err("Device too large.\n");
185
if (ioctl(nbd, NBD_SET_BLKSIZE, (unsigned long)blocksize) < 0)
222
if (ioctl(nbd, NBD_SET_BLKSIZE, 4096UL) < 0)
186
223
err("Ioctl/1.1a failed: %m\n");
187
size = (unsigned long)(size64/blocksize);
224
size = (unsigned long)(size64>>12);
188
225
if ((er = ioctl(nbd, NBD_SET_SIZE_BLOCKS, size)) < 0)
189
226
err("Ioctl/1.1b failed: %m\n");
190
fprintf(stderr, "bs=%d, sz=%lu\n", blocksize, size);
227
if (ioctl(nbd, NBD_SET_BLKSIZE, (unsigned long)blocksize) < 0)
228
err("Ioctl/1.1c failed: %m\n");
229
fprintf(stderr, "bs=%d, sz=%llu bytes\n", blocksize, 4096ULL*size);
193
232
if (size64 > (~0UL >> 1)) {
225
264
mlockall(MCL_CURRENT | MCL_FUTURE);
229
fprintf(stderr, "nbd-client version %s\n", PACKAGE_VERSION);
230
fprintf(stderr, "Usage: nbd-client [bs=blocksize] [timeout=sec] host port nbd_device [-swap] [-sdp] [-persist] [-nofork]\n");
267
void usage(char* errmsg, ...) {
271
va_start(ap, errmsg);
272
snprintf(tmp, 256, "ERROR: %s\n\n", errmsg);
273
vfprintf(stderr, errmsg, ap);
276
fprintf(stderr, "nbd-client version %s\n", PACKAGE_VERSION);
278
fprintf(stderr, "Usage: nbd-client host port nbd_device [-block-size|-b block size] [-timeout|-t timeout] [-swap|-s] [-sdp|-S] [-persist|-p] [-nofork|-n] [-name|-N name]\n");
231
279
fprintf(stderr, "Or : nbd-client -d nbd_device\n");
232
280
fprintf(stderr, "Or : nbd-client -c nbd_device\n");
281
fprintf(stderr, "Or : nbd-client -h|--help\n");
233
282
fprintf(stderr, "Default value for blocksize is 1024 (recommended for ethernet)\n");
234
283
fprintf(stderr, "Allowed values for blocksize are 512,1024,2048,4096\n"); /* will be checked in kernel :) */
235
284
fprintf(stderr, "Note, that kernel 2.4.2 and older ones do not work correctly with\n");
275
324
int nonspecial=0;
276
326
struct option long_options[] = {
277
327
{ "block-size", required_argument, NULL, 'b' },
278
328
{ "check", required_argument, NULL, 'c' },
279
329
{ "disconnect", required_argument, NULL, 'd' },
280
330
{ "help", no_argument, NULL, 'h' },
331
{ "name", required_argument, NULL, 'N' },
281
332
{ "nofork", no_argument, NULL, 'n' },
282
333
{ "persist", no_argument, NULL, 'p' },
283
334
{ "sdp", no_argument, NULL, 'S' },
284
335
{ "swap", no_argument, NULL, 's' },
285
336
{ "timeout", required_argument, NULL, 't' },
290
while((c=getopt_long_only(argc, argv, "-b:c:d:hnpSst:", long_options, NULL))>=0) {
342
while((c=getopt_long_only(argc, argv, "-b:c:d:hnN:pSst:", long_options, NULL))>=0) {
293
345
// non-option argument
316
port = strtol(optarg, NULL, 0);
368
if(!strtol(optarg, NULL, 0)) {
369
// not parseable as a number, assume it's the device and we have a name
375
usage("port and name specified at the same time. This is not supported.");
323
fprintf(stderr, "ERROR: too many non-option arguments specified\n");
385
usage("too many non-option arguments specified");
324
386
exit(EXIT_FAILURE);
371
441
sock = opennet(hostname, port, sdp);
373
negotiate(sock, &size64, &flags);
443
negotiate(sock, &size64, &flags, name);
374
444
setsizes(nbd, size64, blocksize, flags);
375
445
set_timeout(nbd, timeout);
376
446
finish_sock(sock, nbd, swap);
417
490
close(sock); close(nbd);
418
491
sock = opennet(hostname, port, sdp);
419
492
nbd = open(nbddev, O_RDWR);
420
negotiate(sock, &new_size, &new_flags);
493
negotiate(sock, &new_size, &new_flags, name);
421
494
if (size64 != new_size) {
422
495
err("Size of the device changed. Bye");