2 * Network Block Device - server
4 * Copyright 1996-1998 Pavel Machek, distribute under GPL
5 * <pavel@atrey.karlin.mff.cuni.cz>
6 * Copyright 2001-2004 Wouter Verhelst <wouter@debian.org>
7 * Copyright 2002 Anton Altaparmakov <aia21@cam.ac.uk>
9 * Version 1.0 - hopefully 64-bit-clean
10 * Version 1.1 - merging enhancements from Josh Parsons, <josh@coombs.anu.edu.au>
11 * Version 1.2 - autodetect size of block devices, thanx to Peter T. Breuer" <ptb@it.uc3m.es>
12 * Version 1.5 - can compile on Unix systems that don't have 64 bit integer
13 * type, or don't have 64 bit file offsets by defining FS_32BIT
14 * in compile options for nbd-server *only*. This can be done
15 * with make FSCHOICE=-DFS_32BIT nbd-server. (I don't have the
16 * original autoconf input file, or I would make it a configure
17 * option.) Ken Yap <ken@nlc.net.au>.
18 * Version 1.6 - fix autodetection of block device size and really make 64 bit
19 * clean on 32 bit machines. Anton Altaparmakov <aia21@cam.ac.uk>
20 * Version 2.0 - Version synchronised with client
21 * Version 2.1 - Reap zombie client processes when they exit. Removed
22 * (uncommented) the _IO magic, it's no longer necessary. Wouter
23 * Verhelst <wouter@debian.org>
24 * Version 2.2 - Auto switch to read-only mode (usefull for floppies).
25 * Version 2.3 - Fixed code so that Large File Support works. This
26 * removes the FS_32BIT compile-time directive; define
27 * _FILE_OFFSET_BITS=64 and _LARGEFILE_SOURCE if you used to be
28 * using FS_32BIT. This will allow you to use files >2GB instead of
29 * having to use the -m option. Wouter Verhelst <wouter@debian.org>
30 * Version 2.4 - Added code to keep track of children, so that we can
31 * properly kill them from initscripts. Add a call to daemon(),
32 * so that processes don't think they have to wait for us, which is
33 * interesting for initscripts as well. Wouter Verhelst
35 * Version 2.5 - Bugfix release: forgot to reset child_arraysize to
36 * zero after fork()ing, resulting in nbd-server going berserk
37 * when it receives a signal with at least one child open. Wouter
38 * Verhelst <wouter@debian.org>
39 * 10/10/2003 - Added socket option SO_KEEPALIVE (sf.net bug 819235);
40 * rectified type of mainloop::size_host (sf.net bugs 814435 and
41 * 817385); close the PID file after writing to it, so that the
42 * daemon can actually be found. Wouter Verhelst
44 * 10/10/2003 - Size of the data "size_host" was wrong and so was not
45 * correctly put in network endianness. Many types were corrected
46 * (size_t and off_t instead of int). <vspaceg@sourceforge.net>
47 * Version 2.6 - Some code cleanup.
48 * Version 2.7 - Better build system.
49 * 11/02/2004 - Doxygenified the source, modularized it a bit. Needs a
50 * lot more work, but this is a start. Wouter Verhelst
52 * 16/03/2010 - Add IPv6 support.
53 * Kitt Tientanopajai <kitt@kitty.in.th>
54 * Neutron Soutmun <neo.neutron@gmail.com>
55 * Suriya Soutmun <darksolar@gmail.com>
58 /* Includes LFS defines, which defines behaviours of some of the following
59 * headers, so must come before those */
62 #include <sys/types.h>
63 #include <sys/socket.h>
65 #include <sys/select.h> /* select */
66 #include <sys/wait.h> /* wait */
67 #ifdef HAVE_SYS_IOCTL_H
68 #include <sys/ioctl.h>
70 #include <sys/param.h>
71 #ifdef HAVE_SYS_MOUNT_H
72 #include <sys/mount.h> /* For BLKGETSIZE */
74 #include <signal.h> /* sigaction */
76 #include <netinet/tcp.h>
77 #include <netinet/in.h>
85 #include <arpa/inet.h>
95 /* used in cliserv.h, so must come first */
96 #define MY_NAME "nbd_server"
100 #include <sdp_inet.h>
103 /** Default position of the config file */
105 #define SYSCONFDIR "/etc"
107 #define CFILE SYSCONFDIR "/nbd-server/config"
109 /** Where our config file actually is */
110 gchar* config_file_pos;
112 /** What user we're running as */
114 /** What group we're running as */
115 gchar* rungroup=NULL;
116 /** whether to export using the old negotiation protocol (port-based) */
117 gboolean do_oldstyle=FALSE;
119 /** Logging macros, now nothing goes to syslog unless you say ISSERVER */
121 #define msg2(a,b) syslog(a,b)
122 #define msg3(a,b,c) syslog(a,b,c)
123 #define msg4(a,b,c,d) syslog(a,b,c,d)
125 #define msg2(a,b) g_message(b)
126 #define msg3(a,b,c) g_message(b,c)
127 #define msg4(a,b,c,d) g_message(b,c,d)
130 /* Debugging macros */
133 #define DEBUG( a ) printf( a )
134 #define DEBUG2( a,b ) printf( a,b )
135 #define DEBUG3( a,b,c ) printf( a,b,c )
136 #define DEBUG4( a,b,c,d ) printf( a,b,c,d )
139 #define DEBUG2( a,b )
140 #define DEBUG3( a,b,c )
141 #define DEBUG4( a,b,c,d )
143 #ifndef PACKAGE_VERSION
144 #define PACKAGE_VERSION ""
147 * The highest value a variable of type off_t can reach. This is a signed
148 * integer, so set all bits except for the leftmost one.
150 #define OFFT_MAX ~((off_t)1<<(sizeof(off_t)*8-1))
151 #define LINELEN 256 /**< Size of static buffer used to read the
152 authorization file (yuck) */
153 #define BUFSIZE ((1024*1024)+sizeof(struct nbd_reply)) /**< Size of buffer that can hold requests */
154 #define DIFFPAGESIZE 4096 /**< diff file uses those chunks */
155 #define F_READONLY 1 /**< flag to tell us a file is readonly */
156 #define F_MULTIFILE 2 /**< flag to tell us a file is exported using -m */
157 #define F_COPYONWRITE 4 /**< flag to tell us a file is exported using
159 #define F_AUTOREADONLY 8 /**< flag to tell us a file is set to autoreadonly */
160 #define F_SPARSE 16 /**< flag to tell us copyronwrite should use a sparse file */
161 #define F_SDP 32 /**< flag to tell us the export should be done using the Socket Direct Protocol for RDMA */
162 #define F_SYNC 64 /**< Whether to fsync() after a write */
163 GHashTable *children;
164 char pidfname[256]; /**< name of our PID file */
165 char pidftemplate[256]; /**< template to be used for the filename of the PID file */
166 char default_authname[] = SYSCONFDIR "/nbd-server/allow"; /**< default name of allow file */
168 int modernsock=0; /**< Socket for the modern handler. Not used
169 if a client was only specified on the
170 command line; only port used if
171 oldstyle is set to false (and then the
172 command-line client isn't used, gna gna) */
173 char* modern_listen; /**< listenaddr value for modernsock */
176 * Types of virtuatlization
179 VIRT_NONE=0, /**< No virtualization */
180 VIRT_IPLIT, /**< Literal IP address as part of the filename */
181 VIRT_IPHASH, /**< Replacing all dots in an ip address by a / before
182 doing the same as in IPLIT */
183 VIRT_CIDR, /**< Every subnet in its own directory */
187 * Variables associated with a server.
190 gchar* exportname; /**< (unprocessed) filename of the file we're exporting */
191 off_t expected_size; /**< size of the exported file as it was told to
192 us through configuration */
193 gchar* listenaddr; /**< The IP address we're listening on */
194 unsigned int port; /**< port we're exporting this file at */
195 char* authname; /**< filename of the authorization file */
196 int flags; /**< flags associated with this exported file */
197 int socket; /**< The socket of this server. */
198 int socket_family; /**< family of the socket */
199 VIRT_STYLE virtstyle;/**< The style of virtualization, if any */
200 uint8_t cidrlen; /**< The length of the mask when we use
201 CIDR-style virtualization */
202 gchar* prerun; /**< command to be ran after connecting a client,
203 but before starting to serve */
204 gchar* postrun; /**< command that will be ran after the client
206 gchar* servename; /**< name of the export as selected by nbd-client */
207 int max_connections; /**< maximum number of opened connections */
211 * Variables associated with a client socket.
214 int fhandle; /**< file descriptor */
215 off_t startoff; /**< starting offset of this file */
219 off_t exportsize; /**< size of the file we're exporting */
220 char *clientname; /**< peer */
221 char *exportname; /**< (processed) filename of the file we're exporting */
222 GArray *export; /**< array of FILE_INFO of exported files;
223 array size is always 1 unless we're
224 doing the multiple file option */
225 int net; /**< The actual client socket */
226 SERVER *server; /**< The server this client is getting data from */
227 char* difffilename; /**< filename of the copy-on-write file, if any */
228 int difffile; /**< filedescriptor of copyonwrite file. @todo
229 shouldn't this be an array too? (cfr export) Or
230 make -m and -c mutually exclusive */
231 u32 difffilelen; /**< number of pages in difffile */
232 u32 *difmap; /**< see comment on the global difmap for this one */
233 gboolean modern; /**< client was negotiated using modern negotiation protocol */
237 * Type of configuration file values
240 PARAM_INT, /**< This parameter is an integer */
241 PARAM_STRING, /**< This parameter is a string */
242 PARAM_BOOL, /**< This parameter is a boolean */
246 * Configuration file values
249 gchar *paramname; /**< Name of the parameter, as it appears in
251 gboolean required; /**< Whether this is a required (as opposed to
252 optional) parameter */
253 PARAM_TYPE ptype; /**< Type of the parameter. */
254 gpointer target; /**< Pointer to where the data of this
255 parameter should be written. If ptype is
256 PARAM_BOOL, the data is or'ed rather than
258 gint flagval; /**< Flag mask for this parameter in case ptype
263 * Check whether a client is allowed to connect. Works with an authorization
264 * file which contains one line per machine, no wildcards.
266 * @param opts The client who's trying to connect.
267 * @return 0 - authorization refused, 1 - OK
269 int authorized_client(CLIENT *opts) {
270 const char *ERRMSG="Invalid entry '%s' in authfile '%s', so, refusing all connections.";
275 struct in_addr client;
276 struct in_addr cltemp;
279 if ((f=fopen(opts->server->authname,"r"))==NULL) {
280 msg4(LOG_INFO,"Can't open authorization file %s (%s).",
281 opts->server->authname,strerror(errno)) ;
285 inet_aton(opts->clientname, &client);
286 while (fgets(line,LINELEN,f)!=NULL) {
287 if((tmp=index(line, '/'))) {
288 if(strlen(line)<=tmp-line) {
289 msg4(LOG_CRIT, ERRMSG, line, opts->server->authname);
293 if(!inet_aton(line,&addr)) {
294 msg4(LOG_CRIT, ERRMSG, line, opts->server->authname);
297 len=strtol(tmp, NULL, 0);
298 addr.s_addr>>=32-len;
299 addr.s_addr<<=32-len;
300 memcpy(&cltemp,&client,sizeof(client));
301 cltemp.s_addr>>=32-len;
302 cltemp.s_addr<<=32-len;
303 if(addr.s_addr == cltemp.s_addr) {
307 if (strncmp(line,opts->clientname,strlen(opts->clientname))==0) {
317 * Read data from a file descriptor into a buffer
319 * @param f a file descriptor
320 * @param buf a buffer
321 * @param len the number of bytes to be read
323 static inline void readit(int f, void *buf, size_t len) {
327 if ((res = read(f, buf, len)) <= 0) {
328 if(errno != EAGAIN) {
329 err("Read failed: %m");
339 * Write data from a buffer into a filedescriptor
341 * @param f a file descriptor
342 * @param buf a buffer containing data
343 * @param len the number of bytes to be written
345 static inline void writeit(int f, void *buf, size_t len) {
349 if ((res = write(f, buf, len)) <= 0)
350 err("Send failed: %m");
357 * Print out a message about how to use nbd-server. Split out to a separate
358 * function so that we can call it from multiple places
361 printf("This is nbd-server version " VERSION "\n");
362 printf("Usage: [ip:|ip6@]port file_to_export [size][kKmM] [-l authorize_file] [-r] [-m] [-c] [-C configuration file] [-p PID file name] [-o section name] [-M max connections]\n"
363 "\t-r|--read-only\t\tread only\n"
364 "\t-m|--multi-file\t\tmultiple file\n"
365 "\t-c|--copy-on-write\tcopy on write\n"
366 "\t-C|--config-file\tspecify an alternate configuration file\n"
367 "\t-l|--authorize-file\tfile with list of hosts that are allowed to\n\t\t\t\tconnect.\n"
368 "\t-p|--pid-file\t\tspecify a filename to write our PID to\n"
369 "\t-o|--output-config\toutput a config file section for what you\n\t\t\t\tspecified on the command line, with the\n\t\t\t\tspecified section name\n"
370 "\t-M|--max-connections\tspecify the maximum number of opened connections\n\n"
371 "\tif port is set to 0, stdin is used (for running from inetd)\n"
372 "\tif file_to_export contains '%%s', it is substituted with the IP\n"
373 "\t\taddress of the machine trying to connect\n"
374 "\tif ip is set, it contains the local IP address on which we're listening.\n\tif not, the server will listen on all local IP addresses\n");
375 printf("Using configuration file %s\n", CFILE);
378 /* Dumps a config file section of the given SERVER*, and exits. */
379 void dump_section(SERVER* serve, gchar* section_header) {
380 printf("[%s]\n", section_header);
381 printf("\texportname = %s\n", serve->exportname);
382 printf("\tlistenaddr = %s\n", serve->listenaddr);
383 printf("\tport = %d\n", serve->port);
384 if(serve->flags & F_READONLY) {
385 printf("\treadonly = true\n");
387 if(serve->flags & F_MULTIFILE) {
388 printf("\tmultifile = true\n");
390 if(serve->flags & F_COPYONWRITE) {
391 printf("\tcopyonwrite = true\n");
393 if(serve->expected_size) {
394 printf("\tfilesize = %lld\n", (long long int)serve->expected_size);
396 if(serve->authname) {
397 printf("\tauthfile = %s\n", serve->authname);
403 * Parse the command line.
405 * @param argc the argc argument to main()
406 * @param argv the argv argument to main()
408 SERVER* cmdline(int argc, char *argv[]) {
412 struct option long_options[] = {
413 {"read-only", no_argument, NULL, 'r'},
414 {"multi-file", no_argument, NULL, 'm'},
415 {"copy-on-write", no_argument, NULL, 'c'},
416 {"authorize-file", required_argument, NULL, 'l'},
417 {"config-file", required_argument, NULL, 'C'},
418 {"pid-file", required_argument, NULL, 'p'},
419 {"output-config", required_argument, NULL, 'o'},
420 {"max-connection", required_argument, NULL, 'M'},
427 gboolean do_output=FALSE;
428 gchar* section_header="";
434 serve=g_new0(SERVER, 1);
435 serve->authname = g_strdup(default_authname);
436 serve->virtstyle=VIRT_IPLIT;
437 while((c=getopt_long(argc, argv, "-C:cl:mo:rp:M:", long_options, &i))>=0) {
440 /* non-option argument */
441 switch(nonspecial++) {
443 if(strchr(optarg, ':') == strrchr(optarg, ':')) {
444 addr_port=g_strsplit(optarg, ":", 2);
446 /* Check for "@" - maybe user using this separator
449 g_strfreev(addr_port);
450 addr_port=g_strsplit(optarg, "@", 2);
453 addr_port=g_strsplit(optarg, "@", 2);
457 serve->port=strtol(addr_port[1], NULL, 0);
458 serve->listenaddr=g_strdup(addr_port[0]);
460 serve->listenaddr=NULL;
461 serve->port=strtol(addr_port[0], NULL, 0);
463 g_strfreev(addr_port);
466 serve->exportname = g_strdup(optarg);
467 if(serve->exportname[0] != '/') {
468 fprintf(stderr, "E: The to be exported file needs to be an absolute filename!\n");
473 last=strlen(optarg)-1;
475 if (suffix == 'k' || suffix == 'K' ||
476 suffix == 'm' || suffix == 'M')
478 es = (off_t)atoll(optarg);
486 serve->expected_size = es;
491 serve->flags |= F_READONLY;
494 serve->flags |= F_MULTIFILE;
498 section_header = g_strdup(optarg);
501 strncpy(pidftemplate, optarg, 256);
504 serve->flags |=F_COPYONWRITE;
507 g_free(config_file_pos);
508 config_file_pos=g_strdup(optarg);
511 g_free(serve->authname);
512 serve->authname=g_strdup(optarg);
515 serve->max_connections = strtol(optarg, NULL, 0);
523 /* What's left: the port to export, the name of the to be exported
524 * file, and, optionally, the size of the file, in that order. */
533 g_critical("Need a complete configuration on the command line to output a config file section!");
536 dump_section(serve, section_header);
542 * Error codes for config file parsing
545 CFILE_NOTFOUND, /**< The configuration file is not found */
546 CFILE_MISSING_GENERIC, /**< The (required) group "generic" is missing */
547 CFILE_KEY_MISSING, /**< A (required) key is missing */
548 CFILE_VALUE_INVALID, /**< A value is syntactically invalid */
549 CFILE_VALUE_UNSUPPORTED,/**< A value is not supported in this build */
550 CFILE_PROGERR, /**< Programmer error */
551 CFILE_NO_EXPORTS, /**< A config file was specified that does not
552 define any exports */
553 CFILE_INCORRECT_PORT, /**< The reserved port was specified for an
558 * Remove a SERVER from memory. Used from the hash table
560 void remove_server(gpointer s) {
564 g_free(server->exportname);
566 g_free(server->authname);
567 if(server->listenaddr)
568 g_free(server->listenaddr);
570 g_free(server->prerun);
572 g_free(server->postrun);
578 * @param s the old server we want to duplicate
579 * @return new duplicated server
581 SERVER* dup_serve(SERVER *s) {
582 SERVER *serve = NULL;
584 serve=g_new0(SERVER, 1);
589 serve->exportname = g_strdup(s->exportname);
591 serve->expected_size = s->expected_size;
594 serve->listenaddr = g_strdup(s->listenaddr);
596 serve->port = s->port;
599 serve->authname = strdup(s->authname);
601 serve->flags = s->flags;
602 serve->socket = s->socket;
603 serve->socket_family = s->socket_family;
604 serve->virtstyle = s->virtstyle;
605 serve->cidrlen = s->cidrlen;
608 serve->prerun = g_strdup(s->prerun);
611 serve->postrun = g_strdup(s->postrun);
614 serve->servename = g_strdup(s->servename);
616 serve->max_connections = s->max_connections;
622 * append new server to array
624 * @param a server array
625 * @return 0 success, -1 error
627 int append_serve(SERVER *s, GArray *a) {
629 struct addrinfo hints;
630 struct addrinfo *ai = NULL;
631 struct addrinfo *rp = NULL;
632 char host[NI_MAXHOST];
638 err("Invalid parsing server");
642 port = g_strdup_printf("%d", s->port);
644 memset(&hints,'\0',sizeof(hints));
645 hints.ai_family = AF_UNSPEC;
646 hints.ai_socktype = SOCK_STREAM;
647 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
648 hints.ai_protocol = IPPROTO_TCP;
650 e = getaddrinfo(s->listenaddr, port, &hints, &ai);
656 for (rp = ai; rp != NULL; rp = rp->ai_next) {
657 e = getnameinfo(rp->ai_addr, rp->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
659 if (e != 0) { // error
660 fprintf(stderr, "getnameinfo: %s\n", gai_strerror(e));
664 // duplicate server and set listenaddr to resolved IP address
667 ns->listenaddr = g_strdup(host);
668 ns->socket_family = rp->ai_family;
669 g_array_append_val(a, *ns);
677 fprintf(stderr, "getaddrinfo failed on listen host/address: %s (%s)\n", s->listenaddr ? s->listenaddr : "any", gai_strerror(e));
688 * Parse the config file.
690 * @param f the name of the config file
691 * @param e a GError. @see CFILE_ERRORS for what error values this function can
693 * @return a Array of SERVER* pointers, If the config file is empty or does not
694 * exist, returns an empty GHashTable; if the config file contains an
695 * error, returns NULL, and e is set appropriately
697 GArray* parse_cfile(gchar* f, GError** e) {
698 const char* DEFAULT_ERROR = "Could not parse %s in group %s: %s";
699 const char* MISSING_REQUIRED_ERROR = "Could not find required value %s in group %s: %s";
701 gchar *virtstyle=NULL;
703 { "exportname", TRUE, PARAM_STRING, &(s.exportname), 0 },
704 { "port", TRUE, PARAM_INT, &(s.port), 0 },
705 { "authfile", FALSE, PARAM_STRING, &(s.authname), 0 },
706 { "filesize", FALSE, PARAM_INT, &(s.expected_size), 0 },
707 { "virtstyle", FALSE, PARAM_STRING, &(virtstyle), 0 },
708 { "prerun", FALSE, PARAM_STRING, &(s.prerun), 0 },
709 { "postrun", FALSE, PARAM_STRING, &(s.postrun), 0 },
710 { "readonly", FALSE, PARAM_BOOL, &(s.flags), F_READONLY },
711 { "multifile", FALSE, PARAM_BOOL, &(s.flags), F_MULTIFILE },
712 { "copyonwrite", FALSE, PARAM_BOOL, &(s.flags), F_COPYONWRITE },
713 { "sparse_cow", FALSE, PARAM_BOOL, &(s.flags), F_SPARSE },
714 { "sdp", FALSE, PARAM_BOOL, &(s.flags), F_SDP },
715 { "sync", FALSE, PARAM_BOOL, &(s.flags), F_SYNC },
716 { "listenaddr", FALSE, PARAM_STRING, &(s.listenaddr), 0 },
717 { "maxconnections", FALSE, PARAM_INT, &(s.max_connections), 0 },
719 const int lp_size=sizeof(lp)/sizeof(PARAM);
721 { "user", FALSE, PARAM_STRING, &runuser, 0 },
722 { "group", FALSE, PARAM_STRING, &rungroup, 0 },
723 { "oldstyle", FALSE, PARAM_BOOL, &do_oldstyle, 1 },
724 { "listenaddr", FALSE, PARAM_STRING, &modern_listen, 0 },
727 int p_size=sizeof(gp)/sizeof(PARAM);
730 const char *err_msg=NULL;
739 errdomain = g_quark_from_string("parse_cfile");
740 cfile = g_key_file_new();
741 retval = g_array_new(FALSE, TRUE, sizeof(SERVER));
742 if(!g_key_file_load_from_file(cfile, f, G_KEY_FILE_KEEP_COMMENTS |
743 G_KEY_FILE_KEEP_TRANSLATIONS, &err)) {
744 g_set_error(e, errdomain, CFILE_NOTFOUND, "Could not open config file %s.", f);
745 g_key_file_free(cfile);
748 startgroup = g_key_file_get_start_group(cfile);
749 if(!startgroup || strcmp(startgroup, "generic")) {
750 g_set_error(e, errdomain, CFILE_MISSING_GENERIC, "Config file does not contain the [generic] group!");
751 g_key_file_free(cfile);
754 groups = g_key_file_get_groups(cfile, NULL);
755 for(i=0;groups[i];i++) {
756 memset(&s, '\0', sizeof(SERVER));
758 /* After the [generic] group, start parsing exports */
763 for(j=0;j<p_size;j++) {
764 g_assert(p[j].target != NULL);
765 g_assert(p[j].ptype==PARAM_INT||p[j].ptype==PARAM_STRING||p[j].ptype==PARAM_BOOL);
768 *((gint*)p[j].target) =
769 g_key_file_get_integer(cfile,
775 *((gchar**)p[j].target) =
776 g_key_file_get_string(cfile,
782 value = g_key_file_get_boolean(cfile,
784 p[j].paramname, &err);
787 *((gint*)p[j].target) |= p[j].flagval;
789 *((gint*)p[j].target) &= ~(p[j].flagval);
794 if(!strcmp(p[j].paramname, "port") && !strcmp(p[j].target, NBD_DEFAULT_PORT)) {
795 g_set_error(e, errdomain, CFILE_INCORRECT_PORT, "Config file specifies default port for oldstyle export");
796 g_key_file_free(cfile);
800 if(err->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
802 /* Ignore not-found error for optional values */
806 err_msg = MISSING_REQUIRED_ERROR;
809 err_msg = DEFAULT_ERROR;
811 g_set_error(e, errdomain, CFILE_VALUE_INVALID, err_msg, p[j].paramname, groups[i], err->message);
812 g_array_free(retval, TRUE);
814 g_key_file_free(cfile);
819 if(!strncmp(virtstyle, "none", 4)) {
820 s.virtstyle=VIRT_NONE;
821 } else if(!strncmp(virtstyle, "ipliteral", 9)) {
822 s.virtstyle=VIRT_IPLIT;
823 } else if(!strncmp(virtstyle, "iphash", 6)) {
824 s.virtstyle=VIRT_IPHASH;
825 } else if(!strncmp(virtstyle, "cidrhash", 8)) {
826 s.virtstyle=VIRT_CIDR;
827 if(strlen(virtstyle)<10) {
828 g_set_error(e, errdomain, CFILE_VALUE_INVALID, "Invalid value %s for parameter virtstyle in group %s: missing length", virtstyle, groups[i]);
829 g_array_free(retval, TRUE);
830 g_key_file_free(cfile);
833 s.cidrlen=strtol(virtstyle+8, NULL, 0);
835 g_set_error(e, errdomain, CFILE_VALUE_INVALID, "Invalid value %s for parameter virtstyle in group %s", virtstyle, groups[i]);
836 g_array_free(retval, TRUE);
837 g_key_file_free(cfile);
840 if(s.port && !do_oldstyle) {
841 g_warning("A port was specified, but oldstyle exports were not requested. This may not do what you expect.");
842 g_warning("Please read 'man 5 nbd-server' and search for oldstyle for more info");
845 s.virtstyle=VIRT_IPLIT;
847 /* Don't need to free this, it's not our string */
849 /* Don't append values for the [generic] group */
851 s.socket_family = AF_UNSPEC;
852 s.servename = groups[i];
854 append_serve(&s, retval);
861 if(s.flags & F_SDP) {
862 g_set_error(e, errdomain, CFILE_VALUE_UNSUPPORTED, "This nbd-server was built without support for SDP, yet group %s uses it", groups[i]);
863 g_array_free(retval, TRUE);
864 g_key_file_free(cfile);
870 g_set_error(e, errdomain, CFILE_NO_EXPORTS, "The config file does not specify any exports");
872 g_key_file_free(cfile);
877 * Signal handler for SIGCHLD
878 * @param s the signal we're handling (must be SIGCHLD, or something
881 void sigchld_handler(int s) {
886 while((pid=waitpid(-1, &status, WNOHANG)) > 0) {
887 if(WIFEXITED(status)) {
888 msg3(LOG_INFO, "Child exited with %d", WEXITSTATUS(status));
890 i=g_hash_table_lookup(children, &pid);
892 msg3(LOG_INFO, "SIGCHLD received for an unknown child with PID %ld", (long)pid);
894 DEBUG2("Removing %d from the list of children", pid);
895 g_hash_table_remove(children, &pid);
901 * Kill a child. Called from sigterm_handler::g_hash_table_foreach.
904 * @param value the value corresponding to the above key
905 * @param user_data a pointer which we always set to 1, so that we know what
908 void killchild(gpointer key, gpointer value, gpointer user_data) {
910 int *parent=user_data;
917 * Handle SIGTERM and dispatch it to our children
918 * @param s the signal we're handling (must be SIGTERM, or something
919 * is severely wrong).
921 void sigterm_handler(int s) {
924 g_hash_table_foreach(children, killchild, &parent);
934 * Detect the size of a file.
936 * @param fhandle An open filedescriptor
937 * @return the size of the file, or OFFT_MAX if detection was
940 off_t size_autodetect(int fhandle) {
943 struct stat stat_buf;
946 #ifdef HAVE_SYS_MOUNT_H
947 #ifdef HAVE_SYS_IOCTL_H
949 DEBUG("looking for export size with ioctl BLKGETSIZE64\n");
950 if (!ioctl(fhandle, BLKGETSIZE64, &bytes) && bytes) {
953 #endif /* BLKGETSIZE64 */
954 #endif /* HAVE_SYS_IOCTL_H */
955 #endif /* HAVE_SYS_MOUNT_H */
957 DEBUG("looking for fhandle size with fstat\n");
958 stat_buf.st_size = 0;
959 error = fstat(fhandle, &stat_buf);
961 if(stat_buf.st_size > 0)
962 return (off_t)stat_buf.st_size;
964 err("fstat failed: %m");
967 DEBUG("looking for fhandle size with lseek SEEK_END\n");
968 es = lseek(fhandle, (off_t)0, SEEK_END);
969 if (es > ((off_t)0)) {
972 DEBUG2("lseek failed: %d", errno==EBADF?1:(errno==ESPIPE?2:(errno==EINVAL?3:4)));
975 err("Could not find size of exported block device: %m");
980 * Get the file handle and offset, given an export offset.
982 * @param export An array of export files
983 * @param a The offset to get corresponding file/offset for
984 * @param fhandle [out] File descriptor
985 * @param foffset [out] Offset into fhandle
986 * @param maxbytes [out] Tells how many bytes can be read/written
987 * from fhandle starting at foffset (0 if there is no limit)
988 * @return 0 on success, -1 on failure
990 int get_filepos(GArray* export, off_t a, int* fhandle, off_t* foffset, size_t* maxbytes ) {
991 /* Negative offset not allowed */
995 /* Binary search for last file with starting offset <= a */
998 int end = export->len - 1;
999 while( start <= end ) {
1000 int mid = (start + end) / 2;
1001 fi = g_array_index(export, FILE_INFO, mid);
1002 if( fi.startoff < a ) {
1004 } else if( fi.startoff > a ) {
1012 /* end should never go negative, since first startoff is 0 and a >= 0 */
1015 fi = g_array_index(export, FILE_INFO, end);
1016 *fhandle = fi.fhandle;
1017 *foffset = a - fi.startoff;
1019 if( end+1 < export->len ) {
1020 FILE_INFO fi_next = g_array_index(export, FILE_INFO, end+1);
1021 *maxbytes = fi_next.startoff - a;
1028 * seek to a position in a file, with error handling.
1029 * @param handle a filedescriptor
1030 * @param a position to seek to
1031 * @todo get rid of this; lastpoint is a global variable right now, but it
1032 * shouldn't be. If we pass it on as a parameter, that makes things a *lot*
1035 void myseek(int handle,off_t a) {
1036 if (lseek(handle, a, SEEK_SET) < 0) {
1037 err("Can not seek locally!\n");
1042 * Write an amount of bytes at a given offset to the right file. This
1043 * abstracts the write-side of the multiple file option.
1045 * @param a The offset where the write should start
1046 * @param buf The buffer to write from
1047 * @param len The length of buf
1048 * @param client The client we're serving for
1049 * @return The number of bytes actually written, or -1 in case of an error
1051 ssize_t rawexpwrite(off_t a, char *buf, size_t len, CLIENT *client) {
1057 if(get_filepos(client->export, a, &fhandle, &foffset, &maxbytes))
1059 if(maxbytes && len > maxbytes)
1062 DEBUG4("(WRITE to fd %d offset %llu len %u), ", fhandle, foffset, len);
1064 myseek(fhandle, foffset);
1065 retval = write(fhandle, buf, len);
1066 if(client->server->flags & F_SYNC) {
1073 * Call rawexpwrite repeatedly until all data has been written.
1074 * @return 0 on success, nonzero on failure
1076 int rawexpwrite_fully(off_t a, char *buf, size_t len, CLIENT *client) {
1079 while(len > 0 && (ret=rawexpwrite(a, buf, len, client)) > 0 ) {
1084 return (ret < 0 || len != 0);
1088 * Read an amount of bytes at a given offset from the right file. This
1089 * abstracts the read-side of the multiple files option.
1091 * @param a The offset where the read should start
1092 * @param buf A buffer to read into
1093 * @param len The size of buf
1094 * @param client The client we're serving for
1095 * @return The number of bytes actually read, or -1 in case of an
1098 ssize_t rawexpread(off_t a, char *buf, size_t len, CLIENT *client) {
1103 if(get_filepos(client->export, a, &fhandle, &foffset, &maxbytes))
1105 if(maxbytes && len > maxbytes)
1108 DEBUG4("(READ from fd %d offset %llu len %u), ", fhandle, foffset, len);
1110 myseek(fhandle, foffset);
1111 return read(fhandle, buf, len);
1115 * Call rawexpread repeatedly until all data has been read.
1116 * @return 0 on success, nonzero on failure
1118 int rawexpread_fully(off_t a, char *buf, size_t len, CLIENT *client) {
1121 while(len > 0 && (ret=rawexpread(a, buf, len, client)) > 0 ) {
1126 return (ret < 0 || len != 0);
1130 * Read an amount of bytes at a given offset from the right file. This
1131 * abstracts the read-side of the copyonwrite stuff, and calls
1132 * rawexpread() with the right parameters to do the actual work.
1133 * @param a The offset where the read should start
1134 * @param buf A buffer to read into
1135 * @param len The size of buf
1136 * @param client The client we're going to read for
1137 * @return 0 on success, nonzero on failure
1139 int expread(off_t a, char *buf, size_t len, CLIENT *client) {
1140 off_t rdlen, offset;
1141 off_t mapcnt, mapl, maph, pagestart;
1143 if (!(client->server->flags & F_COPYONWRITE))
1144 return(rawexpread_fully(a, buf, len, client));
1145 DEBUG3("Asked to read %d bytes at %llu.\n", len, (unsigned long long)a);
1147 mapl=a/DIFFPAGESIZE; maph=(a+len-1)/DIFFPAGESIZE;
1149 for (mapcnt=mapl;mapcnt<=maph;mapcnt++) {
1150 pagestart=mapcnt*DIFFPAGESIZE;
1152 rdlen=(0<DIFFPAGESIZE-offset && len<(size_t)(DIFFPAGESIZE-offset)) ?
1153 len : (size_t)DIFFPAGESIZE-offset;
1154 if (client->difmap[mapcnt]!=(u32)(-1)) { /* the block is already there */
1155 DEBUG3("Page %llu is at %lu\n", (unsigned long long)mapcnt,
1156 (unsigned long)(client->difmap[mapcnt]));
1157 myseek(client->difffile, client->difmap[mapcnt]*DIFFPAGESIZE+offset);
1158 if (read(client->difffile, buf, rdlen) != rdlen) return -1;
1159 } else { /* the block is not there */
1160 DEBUG2("Page %llu is not here, we read the original one\n",
1161 (unsigned long long)mapcnt);
1162 if(rawexpread_fully(a, buf, rdlen, client)) return -1;
1164 len-=rdlen; a+=rdlen; buf+=rdlen;
1170 * Write an amount of bytes at a given offset to the right file. This
1171 * abstracts the write-side of the copyonwrite option, and calls
1172 * rawexpwrite() with the right parameters to do the actual work.
1174 * @param a The offset where the write should start
1175 * @param buf The buffer to write from
1176 * @param len The length of buf
1177 * @param client The client we're going to write for.
1178 * @return 0 on success, nonzero on failure
1180 int expwrite(off_t a, char *buf, size_t len, CLIENT *client) {
1181 char pagebuf[DIFFPAGESIZE];
1182 off_t mapcnt,mapl,maph;
1187 if (!(client->server->flags & F_COPYONWRITE))
1188 return(rawexpwrite_fully(a, buf, len, client));
1189 DEBUG3("Asked to write %d bytes at %llu.\n", len, (unsigned long long)a);
1191 mapl=a/DIFFPAGESIZE ; maph=(a+len-1)/DIFFPAGESIZE ;
1193 for (mapcnt=mapl;mapcnt<=maph;mapcnt++) {
1194 pagestart=mapcnt*DIFFPAGESIZE ;
1195 offset=a-pagestart ;
1196 wrlen=(0<DIFFPAGESIZE-offset && len<(size_t)(DIFFPAGESIZE-offset)) ?
1197 len : (size_t)DIFFPAGESIZE-offset;
1199 if (client->difmap[mapcnt]!=(u32)(-1)) { /* the block is already there */
1200 DEBUG3("Page %llu is at %lu\n", (unsigned long long)mapcnt,
1201 (unsigned long)(client->difmap[mapcnt])) ;
1202 myseek(client->difffile,
1203 client->difmap[mapcnt]*DIFFPAGESIZE+offset);
1204 if (write(client->difffile, buf, wrlen) != wrlen) return -1 ;
1205 } else { /* the block is not there */
1206 myseek(client->difffile,client->difffilelen*DIFFPAGESIZE) ;
1207 client->difmap[mapcnt]=(client->server->flags&F_SPARSE)?mapcnt:client->difffilelen++;
1208 DEBUG3("Page %llu is not here, we put it at %lu\n",
1209 (unsigned long long)mapcnt,
1210 (unsigned long)(client->difmap[mapcnt]));
1211 rdlen=DIFFPAGESIZE ;
1212 if (rawexpread_fully(pagestart, pagebuf, rdlen, client))
1214 memcpy(pagebuf+offset,buf,wrlen) ;
1215 if (write(client->difffile, pagebuf, DIFFPAGESIZE) !=
1219 len-=wrlen ; a+=wrlen ; buf+=wrlen ;
1225 * Do the initial negotiation.
1227 * @param client The client we're negotiating with.
1229 CLIENT* negotiate(int net, CLIENT *client, GArray* servers) {
1232 uint32_t flags = NBD_FLAG_HAS_FLAGS;
1233 uint16_t smallflags = 0;
1236 memset(zeros, '\0', sizeof(zeros));
1237 if(!client || !client->modern) {
1239 if (write(net, INIT_PASSWD, 8) < 0) {
1240 err_nonfatal("Negotiation failed: %m");
1244 if(!client || client->modern) {
1246 magic = htonll(opts_magic);
1249 magic = htonll(cliserv_magic);
1251 if (write(net, &magic, sizeof(magic)) < 0) {
1252 err_nonfatal("Negotiation failed: %m");
1266 err("programmer error");
1267 if (write(net, &smallflags, sizeof(uint16_t)) < 0)
1268 err("Negotiation failed: %m");
1269 if (read(net, &reserved, sizeof(reserved)) < 0)
1270 err("Negotiation failed: %m");
1271 if (read(net, &magic, sizeof(magic)) < 0)
1272 err("Negotiation failed: %m");
1273 magic = ntohll(magic);
1274 if(magic != opts_magic) {
1278 if (read(net, &opt, sizeof(opt)) < 0)
1279 err("Negotiation failed: %m");
1281 if(opt != NBD_OPT_EXPORT_NAME) {
1285 if (read(net, &namelen, sizeof(namelen)) < 0)
1286 err("Negotiation failed: %m");
1287 namelen = ntohl(namelen);
1288 name = malloc(namelen+1);
1290 if (read(net, name, namelen) < 0)
1291 err("Negotiation failed: %m");
1292 for(i=0; i<servers->len; i++) {
1293 SERVER* serve = &(g_array_index(servers, SERVER, i));
1294 if(!strcmp(serve->servename, name)) {
1295 CLIENT* client = g_new0(CLIENT, 1);
1296 client->server = serve;
1297 client->exportsize = OFFT_MAX;
1299 client->modern = TRUE;
1308 size_host = htonll((u64)(client->exportsize));
1309 if (write(net, &size_host, 8) < 0)
1310 err("Negotiation failed: %m");
1311 if (client->server->flags & F_READONLY)
1312 flags |= NBD_FLAG_READ_ONLY;
1313 if (!client->modern) {
1315 flags = htonl(flags);
1316 if (write(client->net, &flags, 4) < 0)
1317 err("Negotiation failed: %m");
1320 smallflags = (uint16_t)(flags & ~((uint16_t)0));
1321 smallflags = htons(smallflags);
1322 if (write(client->net, &smallflags, sizeof(smallflags)) < 0) {
1323 err("Negotiation failed: %m");
1327 if (write(client->net, zeros, 124) < 0)
1328 err("Negotiation failed: %m");
1332 /** sending macro. */
1333 #define SEND(net,reply) writeit( net, &reply, sizeof( reply ));
1335 #define ERROR(client,reply,errcode) { reply.error = htonl(errcode); SEND(client->net,reply); reply.error = 0; }
1337 * Serve a file to a single client.
1339 * @todo This beast needs to be split up in many tiny little manageable
1340 * pieces. Preferably with a chainsaw.
1342 * @param client The client we're going to serve to.
1343 * @return when the client disconnects
1345 int mainloop(CLIENT *client) {
1346 struct nbd_request request;
1347 struct nbd_reply reply;
1348 gboolean go_on=TRUE;
1352 negotiate(client->net, client, NULL);
1353 DEBUG("Entering request loop!\n");
1354 reply.magic = htonl(NBD_REPLY_MAGIC);
1366 readit(client->net, &request, sizeof(request));
1367 request.from = ntohll(request.from);
1368 request.type = ntohl(request.type);
1370 if (request.type==NBD_CMD_DISC) {
1371 msg2(LOG_INFO, "Disconnect request received.");
1372 if (client->server->flags & F_COPYONWRITE) {
1373 if (client->difmap) g_free(client->difmap) ;
1374 close(client->difffile);
1375 unlink(client->difffilename);
1376 free(client->difffilename);
1382 len = ntohl(request.len);
1384 if (request.magic != htonl(NBD_REQUEST_MAGIC))
1385 err("Not enough magic.");
1386 if (len > BUFSIZE - sizeof(struct nbd_reply)) {
1387 currlen = BUFSIZE - sizeof(struct nbd_reply);
1388 msg2(LOG_INFO, "oversized request (this is not a problem)");
1393 printf("%s from %llu (%llu) len %d, ", request.type ? "WRITE" :
1394 "READ", (unsigned long long)request.from,
1395 (unsigned long long)request.from / 512, len);
1397 memcpy(reply.handle, request.handle, sizeof(reply.handle));
1398 if ((request.from + len) > (OFFT_MAX)) {
1399 DEBUG("[Number too large!]");
1400 ERROR(client, reply, EINVAL);
1404 if (((ssize_t)((off_t)request.from + len) > client->exportsize)) {
1406 ERROR(client, reply, EINVAL);
1410 if (request.type==NBD_CMD_WRITE) {
1411 DEBUG("wr: net->buf, ");
1413 readit(client->net, buf, currlen);
1414 DEBUG("buf->exp, ");
1415 if ((client->server->flags & F_READONLY) ||
1416 (client->server->flags & F_AUTOREADONLY)) {
1417 DEBUG("[WRITE to READONLY!]");
1418 ERROR(client, reply, EPERM);
1421 if (expwrite(request.from, buf, len, client)) {
1422 DEBUG("Write failed: %m" );
1423 ERROR(client, reply, errno);
1426 SEND(client->net, reply);
1429 currlen = (len < BUFSIZE) ? len : BUFSIZE;
1435 DEBUG("exp->buf, ");
1436 memcpy(buf, &reply, sizeof(struct nbd_reply));
1437 p = buf + sizeof(struct nbd_reply);
1438 writelen = currlen + sizeof(struct nbd_reply);
1440 if (expread(request.from, p, currlen, client)) {
1441 DEBUG("Read failed: %m");
1442 ERROR(client, reply, errno);
1446 DEBUG("buf->net, ");
1447 writeit(client->net, buf, writelen);
1449 currlen = (len < BUFSIZE) ? len : BUFSIZE;
1459 * Set up client export array, which is an array of FILE_INFO.
1460 * Also, split a single exportfile into multiple ones, if that was asked.
1461 * @param client information on the client which we want to setup export for
1463 void setupexport(CLIENT* client) {
1465 off_t laststartoff = 0, lastsize = 0;
1466 int multifile = (client->server->flags & F_MULTIFILE);
1468 client->export = g_array_new(TRUE, TRUE, sizeof(FILE_INFO));
1470 /* If multi-file, open as many files as we can.
1471 * If not, open exactly one file.
1472 * Calculate file sizes as we go to get total size. */
1476 gchar* error_string;
1477 mode_t mode = (client->server->flags & F_READONLY) ? O_RDONLY : O_RDWR;
1480 tmpname=g_strdup_printf("%s.%d", client->exportname, i);
1482 tmpname=g_strdup(client->exportname);
1484 DEBUG2( "Opening %s\n", tmpname );
1485 fi.fhandle = open(tmpname, mode);
1486 if(fi.fhandle == -1 && mode == O_RDWR) {
1487 /* Try again because maybe media was read-only */
1488 fi.fhandle = open(tmpname, O_RDONLY);
1489 if(fi.fhandle != -1) {
1490 /* Opening the base file in copyonwrite mode is
1492 if(!(client->server->flags & F_COPYONWRITE)) {
1493 client->server->flags |= F_AUTOREADONLY;
1494 client->server->flags |= F_READONLY;
1498 if(fi.fhandle == -1) {
1499 if(multifile && i>0)
1501 error_string=g_strdup_printf(
1502 "Could not open exported file %s: %%m",
1506 fi.startoff = laststartoff + lastsize;
1507 g_array_append_val(client->export, fi);
1510 /* Starting offset and size of this file will be used to
1511 * calculate starting offset of next file */
1512 laststartoff = fi.startoff;
1513 lastsize = size_autodetect(fi.fhandle);
1519 /* Set export size to total calculated size */
1520 client->exportsize = laststartoff + lastsize;
1522 /* Export size may be overridden */
1523 if(client->server->expected_size) {
1524 /* desired size must be <= total calculated size */
1525 if(client->server->expected_size > client->exportsize) {
1526 err("Size of exported file is too big\n");
1529 client->exportsize = client->server->expected_size;
1532 msg3(LOG_INFO, "Size of exported file/device is %llu", (unsigned long long)client->exportsize);
1534 msg3(LOG_INFO, "Total number of files: %d", i);
1538 int copyonwrite_prepare(CLIENT* client) {
1540 if ((client->difffilename = malloc(1024))==NULL)
1541 err("Failed to allocate string for diff file name");
1542 snprintf(client->difffilename, 1024, "%s-%s-%d.diff",client->exportname,client->clientname,
1544 client->difffilename[1023]='\0';
1545 msg3(LOG_INFO,"About to create map and diff file %s",client->difffilename) ;
1546 client->difffile=open(client->difffilename,O_RDWR | O_CREAT | O_TRUNC,0600) ;
1547 if (client->difffile<0) err("Could not create diff file (%m)") ;
1548 if ((client->difmap=calloc(client->exportsize/DIFFPAGESIZE,sizeof(u32)))==NULL)
1549 err("Could not allocate memory") ;
1550 for (i=0;i<client->exportsize/DIFFPAGESIZE;i++) client->difmap[i]=(u32)-1 ;
1556 * Run a command. This is used for the ``prerun'' and ``postrun'' config file
1559 * @param command the command to be ran. Read from the config file
1560 * @param file the file name we're about to export
1562 int do_run(gchar* command, gchar* file) {
1566 if(command && *command) {
1567 cmd = g_strdup_printf(command, file);
1575 * Serve a connection.
1577 * @todo allow for multithreading, perhaps use libevent. Not just yet, though;
1578 * follow the road map.
1580 * @param client a connected client
1582 void serveconnection(CLIENT *client) {
1583 if(do_run(client->server->prerun, client->exportname)) {
1586 setupexport(client);
1588 if (client->server->flags & F_COPYONWRITE) {
1589 copyonwrite_prepare(client);
1592 setmysockopt(client->net);
1595 do_run(client->server->postrun, client->exportname);
1599 * Find the name of the file we have to serve. This will use g_strdup_printf
1600 * to put the IP address of the client inside a filename containing
1601 * "%s" (in the form as specified by the "virtstyle" option). That name
1602 * is then written to client->exportname.
1604 * @param net A socket connected to an nbd client
1605 * @param client information about the client. The IP address in human-readable
1606 * format will be written to a new char* buffer, the address of which will be
1607 * stored in client->clientname.
1609 void set_peername(int net, CLIENT *client) {
1610 struct sockaddr_storage addrin;
1611 struct sockaddr_storage netaddr;
1612 struct sockaddr_in *netaddr4 = NULL;
1613 struct sockaddr_in6 *netaddr6 = NULL;
1614 size_t addrinlen = sizeof( addrin );
1615 struct addrinfo hints;
1616 struct addrinfo *ai = NULL;
1617 char peername[NI_MAXHOST];
1618 char netname[NI_MAXHOST];
1624 if (getpeername(net, (struct sockaddr *) &addrin, (socklen_t *)&addrinlen) < 0)
1625 err("getsockname failed: %m");
1627 getnameinfo((struct sockaddr *)&addrin, (socklen_t)addrinlen,
1628 peername, sizeof (peername), NULL, 0, NI_NUMERICHOST);
1630 memset(&hints, '\0', sizeof (hints));
1631 hints.ai_flags = AI_ADDRCONFIG;
1632 e = getaddrinfo(peername, NULL, &hints, &ai);
1635 fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(e));
1640 switch(client->server->virtstyle) {
1642 client->exportname=g_strdup(client->server->exportname);
1645 for(i=0;i<strlen(peername);i++) {
1646 if(peername[i]=='.') {
1651 client->exportname=g_strdup_printf(client->server->exportname, peername);
1654 memcpy(&netaddr, &addrin, addrinlen);
1655 if(ai->ai_family == AF_INET) {
1656 netaddr4 = (struct sockaddr_in *)&netaddr;
1657 (netaddr4->sin_addr).s_addr>>=32-(client->server->cidrlen);
1658 (netaddr4->sin_addr).s_addr<<=32-(client->server->cidrlen);
1660 getnameinfo((struct sockaddr *) netaddr4, (socklen_t) addrinlen,
1661 netname, sizeof (netname), NULL, 0, NI_NUMERICHOST);
1662 tmp=g_strdup_printf("%s/%s", netname, peername);
1663 }else if(ai->ai_family == AF_INET6) {
1664 netaddr6 = (struct sockaddr_in6 *)&netaddr;
1666 shift = 128-(client->server->cidrlen);
1668 while(shift >= 32) {
1669 ((netaddr6->sin6_addr).s6_addr32[i])=0;
1673 (netaddr6->sin6_addr).s6_addr32[i]>>=shift;
1674 (netaddr6->sin6_addr).s6_addr32[i]<<=shift;
1676 getnameinfo((struct sockaddr *)netaddr6, (socklen_t)addrinlen,
1677 netname, sizeof(netname), NULL, 0, NI_NUMERICHOST);
1678 tmp=g_strdup_printf("%s/%s", netname, peername);
1682 client->exportname=g_strdup_printf(client->server->exportname, tmp);
1688 msg4(LOG_INFO, "connect from %s, assigned file is %s",
1689 peername, client->exportname);
1690 client->clientname=g_strdup(peername);
1695 * @param data a pointer to pid_t which should be freed
1697 void destroy_pid_t(gpointer data) {
1702 * Loop through the available servers, and serve them. Never returns.
1704 int serveloop(GArray* servers) {
1705 struct sockaddr_storage addrin;
1706 socklen_t addrinlen=sizeof(addrin);
1714 * Set up the master fd_set. The set of descriptors we need
1715 * to select() for never changes anyway and it buys us a *lot*
1716 * of time to only build this once. However, if we ever choose
1717 * to not fork() for clients anymore, we may have to revisit
1722 for(i=0;i<servers->len;i++) {
1723 if((sock=(g_array_index(servers, SERVER, i)).socket)) {
1724 FD_SET(sock, &mset);
1725 max=sock>max?sock:max;
1729 FD_SET(modernsock, &mset);
1730 max=modernsock>max?modernsock:max;
1733 CLIENT *client = NULL;
1736 memcpy(&rset, &mset, sizeof(fd_set));
1737 if(select(max+1, &rset, NULL, NULL, NULL)>0) {
1742 if(FD_ISSET(modernsock, &rset)) {
1743 if((net=accept(modernsock, (struct sockaddr *) &addrin, &addrinlen)) < 0)
1745 client = negotiate(net, NULL, servers);
1747 err_nonfatal("negotiation failed");
1752 serve = client->server;
1754 for(i=0;i<servers->len && !net;i++) {
1755 serve=&(g_array_index(servers, SERVER, i));
1756 if(FD_ISSET(serve->socket, &rset)) {
1757 if ((net=accept(serve->socket, (struct sockaddr *) &addrin, &addrinlen)) < 0)
1764 if(serve->max_connections > 0 &&
1765 g_hash_table_size(children) >= serve->max_connections) {
1766 msg2(LOG_INFO, "Max connections reached");
1770 if((sock_flags = fcntl(net, F_GETFL, 0))==-1) {
1771 err("fcntl F_GETFL");
1773 if(fcntl(net, F_SETFL, sock_flags &~O_NONBLOCK)==-1) {
1774 err("fcntl F_SETFL ~O_NONBLOCK");
1777 client = g_new0(CLIENT, 1);
1778 client->server=serve;
1779 client->exportsize=OFFT_MAX;
1782 set_peername(net, client);
1783 if (!authorized_client(client)) {
1784 msg2(LOG_INFO,"Unauthorized client") ;
1788 msg2(LOG_INFO,"Authorized client") ;
1789 pid=g_malloc(sizeof(pid_t));
1791 if ((*pid=fork())<0) {
1792 msg3(LOG_INFO,"Could not fork (%s)",strerror(errno)) ;
1796 if (*pid>0) { /* parent */
1798 g_hash_table_insert(children, pid, pid);
1802 g_hash_table_destroy(children);
1803 for(i=0;i<servers->len;i++) {
1804 serve=&g_array_index(servers, SERVER, i);
1805 close(serve->socket);
1807 /* FALSE does not free the
1808 actual data. This is required,
1809 because the client has a
1810 direct reference into that
1811 data, and otherwise we get a
1813 g_array_free(servers, FALSE);
1815 msg2(LOG_INFO,"Starting to serve");
1816 serveconnection(client);
1823 void dosockopts(int socket) {
1831 /* lose the pesky "Address already in use" error message */
1832 if (setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
1833 err("setsockopt SO_REUSEADDR");
1835 if (setsockopt(socket,SOL_SOCKET,SO_KEEPALIVE,&yes,sizeof(int)) == -1) {
1836 err("setsockopt SO_KEEPALIVE");
1839 /* make the listening socket non-blocking */
1840 if ((sock_flags = fcntl(socket, F_GETFL, 0)) == -1) {
1841 err("fcntl F_GETFL");
1843 if (fcntl(socket, F_SETFL, sock_flags | O_NONBLOCK) == -1) {
1844 err("fcntl F_SETFL O_NONBLOCK");
1849 * Connect a server's socket.
1851 * @param serve the server we want to connect.
1853 int setup_serve(SERVER *serve) {
1854 struct addrinfo hints;
1855 struct addrinfo *ai = NULL;
1860 return serve->servename ? 1 : 0;
1862 memset(&hints,'\0',sizeof(hints));
1863 hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG | AI_NUMERICSERV;
1864 hints.ai_socktype = SOCK_STREAM;
1865 hints.ai_family = serve->socket_family;
1867 port = g_strdup_printf ("%d", serve->port);
1871 e = getaddrinfo(serve->listenaddr,port,&hints,&ai);
1876 fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(e));
1882 if(serve->socket_family == AF_UNSPEC)
1883 serve->socket_family = ai->ai_family;
1886 if ((serve->flags) && F_SDP) {
1887 if (ai->ai_family == AF_INET)
1888 ai->ai_family = AF_INET_SDP;
1889 else (ai->ai_family == AF_INET6)
1890 ai->ai_family = AF_INET6_SDP;
1893 if ((serve->socket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0)
1896 dosockopts(serve->socket);
1898 DEBUG("Waiting for connections... bind, ");
1899 e = bind(serve->socket, ai->ai_addr, ai->ai_addrlen);
1900 if (e != 0 && errno != EADDRINUSE)
1903 if (listen(serve->socket, 1) < 0)
1907 if(serve->servename) {
1914 void open_modern(void) {
1915 struct addrinfo hints;
1916 struct addrinfo* ai = NULL;
1920 memset(&hints, '\0', sizeof(hints));
1921 hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
1922 hints.ai_socktype = SOCK_STREAM;
1923 hints.ai_family = AF_UNSPEC;
1924 hints.ai_protocol = IPPROTO_TCP;
1925 e = getaddrinfo(modern_listen, NBD_DEFAULT_PORT, &hints, &ai);
1927 fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(e));
1930 if((modernsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol))<0) {
1934 dosockopts(modernsock);
1936 if(bind(modernsock, ai->ai_addr, ai->ai_addrlen)) {
1939 if(listen(modernsock, 10) <0) {
1947 * Connect our servers.
1949 void setup_servers(GArray* servers) {
1951 struct sigaction sa;
1954 for(i=0;i<servers->len;i++) {
1955 want_modern |= setup_serve(&(g_array_index(servers, SERVER, i)));
1960 children=g_hash_table_new_full(g_int_hash, g_int_equal, NULL, destroy_pid_t);
1962 sa.sa_handler = sigchld_handler;
1963 sigemptyset(&sa.sa_mask);
1964 sa.sa_flags = SA_RESTART;
1965 if(sigaction(SIGCHLD, &sa, NULL) == -1)
1966 err("sigaction: %m");
1967 sa.sa_handler = sigterm_handler;
1968 sigemptyset(&sa.sa_mask);
1969 sa.sa_flags = SA_RESTART;
1970 if(sigaction(SIGTERM, &sa, NULL) == -1)
1971 err("sigaction: %m");
1975 * Go daemon (unless we specified at compile time that we didn't want this)
1976 * @param serve the first server of our configuration. If its port is zero,
1977 * then do not daemonize, because we're doing inetd then. This parameter
1978 * is only used to create a PID file of the form
1979 * /var/run/nbd-server.<port>.pid; it's not modified in any way.
1981 #if !defined(NODAEMON) && !defined(NOFORK)
1982 void daemonize(SERVER* serve) {
1985 if(serve && !(serve->port)) {
1991 if(!*pidftemplate) {
1993 strncpy(pidftemplate, "/var/run/nbd-server.%d.pid", 255);
1995 strncpy(pidftemplate, "/var/run/nbd-server.pid", 255);
1998 snprintf(pidfname, 255, pidftemplate, serve ? serve->port : 0);
1999 pidf=fopen(pidfname, "w");
2001 fprintf(pidf,"%d\n", (int)getpid());
2005 fprintf(stderr, "Not fatal; continuing");
2009 #define daemonize(serve)
2010 #endif /* !defined(NODAEMON) && !defined(NOFORK) */
2013 * Everything beyond this point (in the file) is run in non-daemon mode.
2014 * The stuff above daemonize() isn't.
2017 void serve_err(SERVER* serve, const char* msg) G_GNUC_NORETURN;
2019 void serve_err(SERVER* serve, const char* msg) {
2020 g_message("Export of %s on port %d failed:", serve->exportname,
2026 * Set up user-ID and/or group-ID
2028 void dousers(void) {
2033 gr=getgrnam(rungroup);
2035 str = g_strdup_printf("Invalid group name: %s", rungroup);
2038 if(setgid(gr->gr_gid)<0) {
2039 err("Could not set GID: %m");
2043 pw=getpwnam(runuser);
2045 str = g_strdup_printf("Invalid user name: %s", runuser);
2048 if(setuid(pw->pw_uid)<0) {
2049 err("Could not set UID: %m");
2055 void glib_message_syslog_redirect(const gchar *log_domain,
2056 GLogLevelFlags log_level,
2057 const gchar *message,
2060 int level=LOG_DEBUG;
2064 case G_LOG_FLAG_FATAL:
2065 case G_LOG_LEVEL_CRITICAL:
2066 case G_LOG_LEVEL_ERROR:
2069 case G_LOG_LEVEL_WARNING:
2072 case G_LOG_LEVEL_MESSAGE:
2073 case G_LOG_LEVEL_INFO:
2076 case G_LOG_LEVEL_DEBUG:
2081 syslog(level, "%s", message);
2086 * Main entry point...
2088 int main(int argc, char *argv[]) {
2093 if (sizeof( struct nbd_request )!=28) {
2094 fprintf(stderr,"Bad size of structure. Alignment problems?\n");
2095 exit(EXIT_FAILURE) ;
2098 memset(pidftemplate, '\0', 256);
2101 config_file_pos = g_strdup(CFILE);
2102 serve=cmdline(argc, argv);
2103 servers = parse_cfile(config_file_pos, &err);
2106 serve->socket_family = AF_UNSPEC;
2108 append_serve(serve, servers);
2110 if (!(serve->port)) {
2113 /* You really should define ISSERVER if you're going to use
2114 * inetd mode, but if you don't, closing stdout and stderr
2115 * (which inetd had connected to the client socket) will let it
2119 open("/dev/null", O_WRONLY);
2120 open("/dev/null", O_WRONLY);
2121 g_log_set_default_handler( glib_message_syslog_redirect, NULL );
2123 client=g_malloc(sizeof(CLIENT));
2124 client->server=serve;
2126 client->exportsize=OFFT_MAX;
2127 set_peername(0,client);
2128 serveconnection(client);
2133 if(!servers || !servers->len) {
2134 if(err && !(err->domain == g_quark_from_string("parse_cfile")
2135 && err->code == CFILE_NOTFOUND)) {
2136 g_warning("Could not parse config file: %s",
2137 err ? err->message : "Unknown error");
2141 g_warning("Specifying an export on the command line is deprecated.");
2142 g_warning("Please use a configuration file instead.");
2145 if((!serve) && (!servers||!servers->len)) {
2146 g_message("No configured exports; quitting.");
2150 setup_servers(servers);