~ubuntu-branches/ubuntu/precise/nbd/precise-security

« back to all changes in this revision

Viewing changes to nbd-client.c

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Graber
  • Date: 2011-05-04 11:41:23 UTC
  • mfrom: (21.1.20 sid)
  • Revision ID: james.westby@ubuntu.com-20110504114123-fvixh2plph8qbu5s
Tags: 1:2.9.20-2ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Drop /etc/modprobe.d/nbd-client; the kernel default is already
    appropriate. Ubuntu-specific change.
    + Modify debian/nbd-client.dirs
    + Remove debian/nbd-client.modprobe
    + Add debian/nbd-client.preinst

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include <sys/mman.h>
36
36
#include <errno.h>
37
37
#include <getopt.h>
38
 
 
39
 
#ifndef __GNUC__
40
 
#error I need GCC to work
41
 
#endif
 
38
#include <stdarg.h>
42
39
 
43
40
#include <linux/ioctl.h>
44
41
#define MY_NAME "nbd_client"
45
42
#include "cliserv.h"
46
43
 
 
44
#ifdef WITH_SDP
 
45
#include <sdp_inet.h>
 
46
#endif
 
47
 
47
48
int check_conn(char* devname, int do_print) {
48
49
        char buf[256];
49
50
        char* p;
71
72
        return 0;
72
73
}
73
74
 
74
 
int opennet(char *name, int port, int sdp) {
 
75
int opennet(char *name, char* portstr, int sdp) {
75
76
        int sock;
76
 
        char portstr[6];
77
77
        struct addrinfo hints;
78
78
        struct addrinfo *ai = NULL;
79
79
        struct addrinfo *rp = NULL;
80
80
        int e;
81
81
 
82
 
        snprintf(portstr, sizeof(portstr), "%d", port);
83
 
 
84
82
        memset(&hints,'\0',sizeof(hints));
85
83
        hints.ai_family = AF_UNSPEC;
86
84
        hints.ai_socktype = SOCK_STREAM;
125
123
        return sock;
126
124
}
127
125
 
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;
 
128
        uint16_t tmp;
130
129
        char buf[256] = "\0\0\0\0\0\0\0\0\0";
131
130
 
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
 
        printf(".");
 
142
        if(name) {
 
143
                uint32_t opt;
 
144
                uint32_t namesize;
 
145
                uint32_t reserved = 0;
 
146
 
 
147
                if (magic != opts_magic)
 
148
                        err("Not enough opts_magic");
 
149
                printf(".");
 
150
                if(read(sock, &tmp, sizeof(uint16_t)) < 0) {
 
151
                        err("Failed reading flags: %m");
 
152
                }
 
153
                *flags = ((u32)ntohs(tmp)) << 16;
 
154
 
 
155
                /* reserved for future use*/
 
156
                if (write(sock, &reserved, sizeof(reserved)) < 0)
 
157
                        err("Failed/2.1: %m");
 
158
 
 
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");
 
172
        } else {
 
173
                if (magic != cliserv_magic)
 
174
                        err("Not enough cliserv_magic");
 
175
                printf(".");
 
176
        }
146
177
 
147
178
        if (read(sock, &size64, sizeof(size64)) < 0)
148
179
                err("Failed/3: %m\n");
149
180
        size64 = ntohll(size64);
150
181
 
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");
155
186
        } else
156
 
                printf("size = %luKB", (unsigned long)(size64>>10));
 
187
                printf("size = %luMB", (unsigned long)(size64>>20));
157
188
#else
158
189
        if (size64 > (~0UL >> 1)) {
159
190
                printf("size = %luKB", (unsigned long)(size64>>10));
162
193
                printf("size = %lu", (unsigned long)(size64));
163
194
#endif
164
195
 
165
 
        if (read(sock, flags, sizeof(*flags)) < 0)
166
 
                err("Failed/4: %m\n");
167
 
        *flags = ntohl(*flags);
 
196
        if(!name) {
 
197
                if (read(sock, flags, sizeof(*flags)) < 0)
 
198
                        err("Failed/4: %m\n");
 
199
                *flags = ntohl(*flags);
 
200
        } else {
 
201
                if(read(sock, &tmp, sizeof(tmp)) < 0)
 
202
                        err("Failed/4: %m\n");
 
203
                *flags |= (uint32_t)ntohs(tmp);
 
204
        }
168
205
 
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;
179
216
 
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");
183
220
        else {
184
221
                int er;
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);
191
230
        }
192
231
#else
193
232
        if (size64 > (~0UL >> 1)) {
225
264
                mlockall(MCL_CURRENT | MCL_FUTURE);
226
265
}
227
266
 
228
 
void usage(void) {
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, ...) {
 
268
        if(errmsg) {
 
269
                char tmp[256];
 
270
                va_list ap;
 
271
                va_start(ap, errmsg);
 
272
                snprintf(tmp, 256, "ERROR: %s\n\n", errmsg);
 
273
                vfprintf(stderr, errmsg, ap);
 
274
                va_end(ap);
 
275
        } else {
 
276
                fprintf(stderr, "nbd-client version %s\n", PACKAGE_VERSION);
 
277
        }
 
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");
259
308
}
260
309
 
261
310
int main(int argc, char *argv[]) {
262
 
        int port=0;
 
311
        char* port=NULL;
263
312
        int sock, nbd;
264
313
        int blocksize=1024;
265
314
        char *hostname=NULL;
273
322
        u32 flags;
274
323
        int c;
275
324
        int nonspecial=0;
 
325
        char* name=NULL;
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' },
 
337
                { 0, 0, 0, 0 }, 
286
338
        };
287
339
 
288
340
        logging();
289
341
 
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) {
291
343
                switch(c) {
292
344
                case 1:
293
345
                        // non-option argument
303
355
                                        optarg+=8;
304
356
                                        goto timeout;
305
357
                                }
306
 
                                fprintf(stderr, "ERROR: unknown option %s encountered\n", optarg);
 
358
                                usage("unknown option %s encountered", optarg);
307
359
                                exit(EXIT_FAILURE);
308
360
                        }
309
361
                        switch(nonspecial++) {
313
365
                                        break;
314
366
                                case 1:
315
367
                                        // port
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
 
370
                                                nbddev = optarg;
 
371
                                                nonspecial++;
 
372
                                        } else {
 
373
                                                port = optarg;
 
374
                                                if(name) {
 
375
                                                        usage("port and name specified at the same time. This is not supported.");
 
376
                                                        exit(EXIT_FAILURE);
 
377
                                                }
 
378
                                        }
317
379
                                        break;
318
380
                                case 2:
319
381
                                        // device
320
382
                                        nbddev = optarg;
321
383
                                        break;
322
384
                                default:
323
 
                                        fprintf(stderr, "ERROR: too many non-option arguments specified\n");
 
385
                                        usage("too many non-option arguments specified");
324
386
                                        exit(EXIT_FAILURE);
325
387
                        }
326
388
                        break;
334
396
                        disconnect(optarg);
335
397
                        exit(EXIT_SUCCESS);
336
398
                case 'h':
337
 
                        usage();
 
399
                        usage(NULL);
338
400
                        exit(EXIT_SUCCESS);
339
401
                case 'n':
340
402
                        nofork=1;
341
403
                        break;
 
404
                case 'N':
 
405
                        name=optarg;
 
406
                        if(port) {
 
407
                                usage("port and name specified at the same time. This is not supported.");
 
408
                                exit(EXIT_FAILURE);
 
409
                        }
 
410
                        port = NBD_DEFAULT_PORT;
 
411
                        break;
342
412
                case 'p':
343
413
                        cont=1;
344
414
                        break;
358
428
                }
359
429
        }
360
430
 
361
 
        if(!port || !hostname || !nbddev) {
362
 
                usage();
 
431
        if((!port && !name) || !hostname || !nbddev) {
 
432
                usage("not enough information specified");
363
433
                exit(EXIT_FAILURE);
364
434
        }
365
435
 
370
440
 
371
441
        sock = opennet(hostname, port, sdp);
372
442
 
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);
378
448
        /* Go daemon */
379
449
        
380
450
#ifndef NOFORK
381
 
        if(!nofork) daemon(0,0);
 
451
        if(!nofork) {
 
452
                if (daemon(0,0) < 0)
 
453
                        err("Cannot detach from terminal");
 
454
        }
382
455
#endif
383
456
        do {
384
457
#ifndef NOFORK
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");
423
496
                                        }