Make -Wall -Werror compile again
[nbd.git] / nbd-server.c
1 /*
2  * Network Block Device - server
3  *
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>
8  *
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
34  *      <wouter@debian.org>
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
43  *      <wouter@debian.org>
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
51  *      <wouter@debian.org>
52  */
53
54 /* Includes LFS defines, which defines behaviours of some of the following
55  * headers, so must come before those */
56 #include "lfs.h"
57
58 #include <sys/types.h>
59 #include <sys/socket.h>
60 #include <sys/stat.h>
61 #include <sys/select.h>         /* select */
62 #include <sys/wait.h>           /* wait */
63 #ifdef HAVE_SYS_IOCTL_H
64 #include <sys/ioctl.h>
65 #endif
66 #include <sys/param.h>
67 #ifdef HAVE_SYS_MOUNT_H
68 #include <sys/mount.h>          /* For BLKGETSIZE */
69 #endif
70 #include <signal.h>             /* sigaction */
71 #include <errno.h>
72 #include <netinet/tcp.h>
73 #include <netinet/in.h>         /* sockaddr_in, htons, in_addr */
74 #include <netdb.h>              /* hostent, gethostby*, getservby* */
75 #include <syslog.h>
76 #include <unistd.h>
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <string.h>
80 #include <fcntl.h>
81 #include <arpa/inet.h>
82 #include <strings.h>
83 #include <dirent.h>
84 #include <unistd.h>
85 #include <getopt.h>
86 #include <pwd.h>
87 #include <grp.h>
88
89 #include <glib.h>
90
91 /* used in cliserv.h, so must come first */
92 #define MY_NAME "nbd_server"
93 #include "cliserv.h"
94
95 /** Default position of the config file */
96 #ifndef SYSCONFDIR
97 #define SYSCONFDIR "/etc"
98 #endif
99 #define CFILE SYSCONFDIR "/nbd-server/config"
100
101 /** Where our config file actually is */
102 gchar* config_file_pos;
103
104 /** What user we're running as */
105 gchar* runuser=NULL;
106 /** What group we're running as */
107 gchar* rungroup=NULL;
108
109 /** Logging macros, now nothing goes to syslog unless you say ISSERVER */
110 #ifdef ISSERVER
111 #define msg2(a,b) syslog(a,b)
112 #define msg3(a,b,c) syslog(a,b,c)
113 #define msg4(a,b,c,d) syslog(a,b,c,d)
114 #else
115 #define msg2(a,b) g_message(b)
116 #define msg3(a,b,c) g_message(b,c)
117 #define msg4(a,b,c,d) g_message(b,c,d)
118 #endif
119
120 /* Debugging macros */
121 //#define DODBG
122 #ifdef DODBG
123 #define DEBUG( a ) printf( a )
124 #define DEBUG2( a,b ) printf( a,b )
125 #define DEBUG3( a,b,c ) printf( a,b,c )
126 #define DEBUG4( a,b,c,d ) printf( a,b,c,d )
127 #else
128 #define DEBUG( a )
129 #define DEBUG2( a,b ) 
130 #define DEBUG3( a,b,c ) 
131 #define DEBUG4( a,b,c,d ) 
132 #endif
133 #ifndef PACKAGE_VERSION
134 #define PACKAGE_VERSION ""
135 #endif
136 /**
137  * The highest value a variable of type off_t can reach. This is a signed
138  * integer, so set all bits except for the leftmost one.
139  **/
140 #define OFFT_MAX ~((off_t)1<<(sizeof(off_t)*8-1))
141 #define LINELEN 256       /**< Size of static buffer used to read the
142                                authorization file (yuck) */
143 #define BUFSIZE (1024*1024) /**< Size of buffer that can hold requests */
144 #define DIFFPAGESIZE 4096 /**< diff file uses those chunks */
145 #define F_READONLY 1      /**< flag to tell us a file is readonly */
146 #define F_MULTIFILE 2     /**< flag to tell us a file is exported using -m */
147 #define F_COPYONWRITE 4   /**< flag to tell us a file is exported using
148                             copyonwrite */
149 #define F_AUTOREADONLY 8  /**< flag to tell us a file is set to autoreadonly */
150 #define F_SPARSE 16       /**< flag to tell us copyronwrite should use a sparse file */
151 #define F_SDP 32          /**< flag to tell us the export should be done using the Socket Direct Protocol for RDMA */
152 #define F_SYNC 64         /**< Whether to fsync() after a write */
153 GHashTable *children;
154 char pidfname[256]; /**< name of our PID file */
155 char pidftemplate[256]; /**< template to be used for the filename of the PID file */
156 char default_authname[] = SYSCONFDIR "/nbd-server/allow"; /**< default name of allow file */
157
158 /**
159  * Types of virtuatlization
160  **/
161 typedef enum {
162         VIRT_NONE=0,    /**< No virtualization */
163         VIRT_IPLIT,     /**< Literal IP address as part of the filename */
164         VIRT_IPHASH,    /**< Replacing all dots in an ip address by a / before
165                              doing the same as in IPLIT */
166         VIRT_CIDR,      /**< Every subnet in its own directory */
167 } VIRT_STYLE;
168
169 /**
170  * Variables associated with a server.
171  **/
172 typedef struct {
173         gchar* exportname;    /**< (unprocessed) filename of the file we're exporting */
174         off_t expected_size; /**< size of the exported file as it was told to
175                                us through configuration */
176         gchar* listenaddr;   /**< The IP address we're listening on */
177         unsigned int port;   /**< port we're exporting this file at */
178         char* authname;      /**< filename of the authorization file */
179         int flags;           /**< flags associated with this exported file */
180         int socket;          /**< The socket of this server. */
181         VIRT_STYLE virtstyle;/**< The style of virtualization, if any */
182         uint8_t cidrlen;     /**< The length of the mask when we use
183                                   CIDR-style virtualization */
184         gchar* prerun;       /**< command to be ran after connecting a client,
185                                   but before starting to serve */
186         gchar* postrun;      /**< command that will be ran after the client
187                                   disconnects */
188 } SERVER;
189
190 /**
191  * Variables associated with a client socket.
192  **/
193 typedef struct {
194         int fhandle;      /**< file descriptor */
195         off_t startoff;   /**< starting offset of this file */
196 } FILE_INFO;
197
198 typedef struct {
199         off_t exportsize;    /**< size of the file we're exporting */
200         char *clientname;    /**< peer */
201         char *exportname;    /**< (processed) filename of the file we're exporting */
202         GArray *export;    /**< array of FILE_INFO of exported files;
203                                array size is always 1 unless we're
204                                doing the multiple file option */
205         int net;             /**< The actual client socket */
206         SERVER *server;      /**< The server this client is getting data from */
207         char* difffilename;  /**< filename of the copy-on-write file, if any */
208         int difffile;        /**< filedescriptor of copyonwrite file. @todo
209                                shouldn't this be an array too? (cfr export) Or
210                                make -m and -c mutually exclusive */
211         u32 difffilelen;     /**< number of pages in difffile */
212         u32 *difmap;         /**< see comment on the global difmap for this one */
213 } CLIENT;
214
215 /**
216  * Type of configuration file values
217  **/
218 typedef enum {
219         PARAM_INT,              /**< This parameter is an integer */
220         PARAM_STRING,           /**< This parameter is a string */
221         PARAM_BOOL,             /**< This parameter is a boolean */
222 } PARAM_TYPE;
223
224 /**
225  * Configuration file values
226  **/
227 typedef struct {
228         gchar *paramname;       /**< Name of the parameter, as it appears in
229                                   the config file */
230         gboolean required;      /**< Whether this is a required (as opposed to
231                                   optional) parameter */
232         PARAM_TYPE ptype;       /**< Type of the parameter. */
233         gpointer target;        /**< Pointer to where the data of this
234                                   parameter should be written. If ptype is
235                                   PARAM_BOOL, the data is or'ed rather than
236                                   overwritten. */
237         gint flagval;           /**< Flag mask for this parameter in case ptype
238                                   is PARAM_BOOL. */
239 } PARAM;
240
241 /**
242  * Check whether a client is allowed to connect. Works with an authorization
243  * file which contains one line per machine, no wildcards.
244  *
245  * @param opts The client who's trying to connect.
246  * @return 0 - authorization refused, 1 - OK
247  **/
248 int authorized_client(CLIENT *opts) {
249         const char *ERRMSG="Invalid entry '%s' in authfile '%s', so, refusing all connections.";
250         FILE *f ;
251         char line[LINELEN]; 
252         char *tmp;
253         struct in_addr addr;
254         struct in_addr client;
255         struct in_addr cltemp;
256         int len;
257
258         if ((f=fopen(opts->server->authname,"r"))==NULL) {
259                 msg4(LOG_INFO,"Can't open authorization file %s (%s).",
260                      opts->server->authname,strerror(errno)) ;
261                 return 1 ; 
262         }
263   
264         inet_aton(opts->clientname, &client);
265         while (fgets(line,LINELEN,f)!=NULL) {
266                 if((tmp=index(line, '/'))) {
267                         if(strlen(line)<=tmp-line) {
268                                 msg4(LOG_CRIT, ERRMSG, line, opts->server->authname);
269                                 return 0;
270                         }
271                         *(tmp++)=0;
272                         if(inet_aton(line,&addr)) {
273                                 msg4(LOG_CRIT, ERRMSG, line, opts->server->authname);
274                                 return 0;
275                         }
276                         len=strtol(tmp, NULL, 0);
277                         addr.s_addr>>=32-len;
278                         addr.s_addr<<=32-len;
279                         memcpy(&cltemp,&client,sizeof(client));
280                         cltemp.s_addr>>=32-len;
281                         cltemp.s_addr<<=32-len;
282                         if(addr.s_addr == cltemp.s_addr) {
283                                 return 1;
284                         }
285                 }
286                 if (strncmp(line,opts->clientname,strlen(opts->clientname))==0) {
287                         fclose(f);
288                         return 1;
289                 }
290         }
291         fclose(f);
292         return 0;
293 }
294
295 /**
296  * Read data from a file descriptor into a buffer
297  *
298  * @param f a file descriptor
299  * @param buf a buffer
300  * @param len the number of bytes to be read
301  **/
302 inline void readit(int f, void *buf, size_t len) {
303         ssize_t res;
304         while (len > 0) {
305                 DEBUG("*");
306                 if ((res = read(f, buf, len)) <= 0) {
307                         if(errno != EAGAIN) {
308                                 err("Read failed: %m");
309                         }
310                 } else {
311                         len -= res;
312                         buf += res;
313                 }
314         }
315 }
316
317 /**
318  * Write data from a buffer into a filedescriptor
319  *
320  * @param f a file descriptor
321  * @param buf a buffer containing data
322  * @param len the number of bytes to be written
323  **/
324 inline void writeit(int f, void *buf, size_t len) {
325         ssize_t res;
326         while (len > 0) {
327                 DEBUG("+");
328                 if ((res = write(f, buf, len)) <= 0)
329                         err("Send failed: %m");
330                 len -= res;
331                 buf += res;
332         }
333 }
334
335 /**
336  * Print out a message about how to use nbd-server. Split out to a separate
337  * function so that we can call it from multiple places
338  */
339 void usage() {
340         printf("This is nbd-server version " VERSION "\n");
341         printf("Usage: [ip:]port file_to_export [size][kKmM] [-l authorize_file] [-r] [-m] [-c] [-C configuration file] [-p PID file name] [-o section name]\n"
342                "\t-r|--read-only\t\tread only\n"
343                "\t-m|--multi-file\t\tmultiple file\n"
344                "\t-c|--copy-on-write\tcopy on write\n"
345                "\t-C|--config-file\tspecify an alternate configuration file\n"
346                "\t-l|--authorize-file\tfile with list of hosts that are allowed to\n\t\t\t\tconnect.\n"
347                "\t-p|--pid-file\t\tspecify a filename to write our PID to\n"
348                "\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\n"
349                "\tif port is set to 0, stdin is used (for running from inetd)\n"
350                "\tif file_to_export contains '%%s', it is substituted with the IP\n"
351                "\t\taddress of the machine trying to connect\n" 
352                "\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");
353         printf("Using configuration file %s\n", CFILE);
354 }
355
356 /* Dumps a config file section of the given SERVER*, and exits. */
357 void dump_section(SERVER* serve, gchar* section_header) {
358         printf("[%s]\n", section_header);
359         printf("\texportname = %s\n", serve->exportname);
360         printf("\tlistenaddr = %s\n", serve->listenaddr);
361         printf("\tport = %d\n", serve->port);
362         if(serve->flags & F_READONLY) {
363                 printf("\treadonly = true\n");
364         }
365         if(serve->flags & F_MULTIFILE) {
366                 printf("\tmultifile = true\n");
367         }
368         if(serve->flags & F_COPYONWRITE) {
369                 printf("\tcopyonwrite = true\n");
370         }
371         if(serve->expected_size) {
372                 printf("\tfilesize = %lld\n", (long long int)serve->expected_size);
373         }
374         if(serve->authname) {
375                 printf("\tauthfile = %s\n", serve->authname);
376         }
377         exit(EXIT_SUCCESS);
378 }
379
380 /**
381  * Parse the command line.
382  *
383  * @param argc the argc argument to main()
384  * @param argv the argv argument to main()
385  **/
386 SERVER* cmdline(int argc, char *argv[]) {
387         int i=0;
388         int nonspecial=0;
389         int c;
390         struct option long_options[] = {
391                 {"read-only", no_argument, NULL, 'r'},
392                 {"multi-file", no_argument, NULL, 'm'},
393                 {"copy-on-write", no_argument, NULL, 'c'},
394                 {"authorize-file", required_argument, NULL, 'l'},
395                 {"config-file", required_argument, NULL, 'C'},
396                 {"pid-file", required_argument, NULL, 'p'},
397                 {"output-config", required_argument, NULL, 'o'},
398                 {0,0,0,0}
399         };
400         SERVER *serve;
401         off_t es;
402         size_t last;
403         char suffix;
404         gboolean do_output=FALSE;
405         gchar* section_header="";
406         gchar** addr_port;
407
408         if(argc==1) {
409                 return NULL;
410         }
411         serve=g_new0(SERVER, 1);
412         serve->authname = g_strdup(default_authname);
413         serve->virtstyle=VIRT_IPLIT;
414         while((c=getopt_long(argc, argv, "-C:cl:mo:rp:", long_options, &i))>=0) {
415                 switch (c) {
416                 case 1:
417                         /* non-option argument */
418                         switch(nonspecial++) {
419                         case 0:
420                                 addr_port=g_strsplit(optarg, ":", 2);
421                                 if(addr_port[1]) {
422                                         serve->port=strtol(addr_port[1], NULL, 0);
423                                         serve->listenaddr=g_strdup(addr_port[0]);
424                                 } else {
425                                         serve->listenaddr=g_strdup("0.0.0.0");
426                                         serve->port=strtol(addr_port[0], NULL, 0);
427                                 }
428                                 g_strfreev(addr_port);
429                                 break;
430                         case 1:
431                                 serve->exportname = g_strdup(optarg);
432                                 if(serve->exportname[0] != '/') {
433                                         fprintf(stderr, "E: The to be exported file needs to be an absolute filename!\n");
434                                         exit(EXIT_FAILURE);
435                                 }
436                                 break;
437                         case 2:
438                                 last=strlen(optarg)-1;
439                                 suffix=optarg[last];
440                                 if (suffix == 'k' || suffix == 'K' ||
441                                     suffix == 'm' || suffix == 'M')
442                                         optarg[last] = '\0';
443                                 es = (off_t)atoll(optarg);
444                                 switch (suffix) {
445                                         case 'm':
446                                         case 'M':  es <<= 10;
447                                         case 'k':
448                                         case 'K':  es <<= 10;
449                                         default :  break;
450                                 }
451                                 serve->expected_size = es;
452                                 break;
453                         }
454                         break;
455                 case 'r':
456                         serve->flags |= F_READONLY;
457                         break;
458                 case 'm':
459                         serve->flags |= F_MULTIFILE;
460                         break;
461                 case 'o':
462                         do_output = TRUE;
463                         section_header = g_strdup(optarg);
464                         break;
465                 case 'p':
466                         strncpy(pidftemplate, optarg, 256);
467                         break;
468                 case 'c': 
469                         serve->flags |=F_COPYONWRITE;
470                         break;
471                 case 'C':
472                         g_free(config_file_pos);
473                         config_file_pos=g_strdup(optarg);
474                         break;
475                 case 'l':
476                         g_free(serve->authname);
477                         serve->authname=g_strdup(optarg);
478                         break;
479                 default:
480                         usage();
481                         exit(EXIT_FAILURE);
482                         break;
483                 }
484         }
485         /* What's left: the port to export, the name of the to be exported
486          * file, and, optionally, the size of the file, in that order. */
487         if(nonspecial<2) {
488                 g_free(serve);
489                 serve=NULL;
490         }
491         if(do_output) {
492                 if(!serve) {
493                         g_critical("Need a complete configuration on the command line to output a config file section!");
494                         exit(EXIT_FAILURE);
495                 }
496                 dump_section(serve, section_header);
497         }
498         return serve;
499 }
500
501 /**
502  * Error codes for config file parsing
503  **/
504 typedef enum {
505         CFILE_NOTFOUND,         /**< The configuration file is not found */
506         CFILE_MISSING_GENERIC,  /**< The (required) group "generic" is missing */
507         CFILE_KEY_MISSING,      /**< A (required) key is missing */
508         CFILE_VALUE_INVALID,    /**< A value is syntactically invalid */
509         CFILE_VALUE_UNSUPPORTED,/**< A value is not supported in this build */
510         CFILE_PROGERR,          /**< Programmer error */
511         CFILE_NO_EXPORTS        /**< A config file was specified that does not
512                                      define any exports */
513 } CFILE_ERRORS;
514
515 /**
516  * Remove a SERVER from memory. Used from the hash table
517  **/
518 void remove_server(gpointer s) {
519         SERVER *server;
520
521         server=(SERVER*)s;
522         g_free(server->exportname);
523         if(server->authname)
524                 g_free(server->authname);
525         g_free(server);
526 }
527
528 /**
529  * Parse the config file.
530  *
531  * @param f the name of the config file
532  * @param e a GError. @see CFILE_ERRORS for what error values this function can
533  *      return.
534  * @return a Array of SERVER* pointers, If the config file is empty or does not
535  *      exist, returns an empty GHashTable; if the config file contains an
536  *      error, returns NULL, and e is set appropriately
537  **/
538 GArray* parse_cfile(gchar* f, GError** e) {
539         const char* DEFAULT_ERROR = "Could not parse %s in group %s: %s";
540         const char* MISSING_REQUIRED_ERROR = "Could not find required value %s in group %s: %s";
541         SERVER s;
542         gchar *virtstyle=NULL;
543         PARAM lp[] = {
544                 { "exportname", TRUE,   PARAM_STRING,   NULL, 0 },
545                 { "port",       TRUE,   PARAM_INT,      NULL, 0 },
546                 { "authfile",   FALSE,  PARAM_STRING,   NULL, 0 },
547                 { "filesize",   FALSE,  PARAM_INT,      NULL, 0 },
548                 { "virtstyle",  FALSE,  PARAM_STRING,   NULL, 0 },
549                 { "prerun",     FALSE,  PARAM_STRING,   NULL, 0 },
550                 { "postrun",    FALSE,  PARAM_STRING,   NULL, 0 },
551                 { "readonly",   FALSE,  PARAM_BOOL,     NULL, F_READONLY },
552                 { "multifile",  FALSE,  PARAM_BOOL,     NULL, F_MULTIFILE },
553                 { "copyonwrite", FALSE, PARAM_BOOL,     NULL, F_COPYONWRITE },
554                 { "sparse_cow", FALSE,  PARAM_BOOL,     NULL, F_SPARSE },
555                 { "sdp",        FALSE,  PARAM_BOOL,     NULL, F_SDP },
556                 { "sync",       FALSE,  PARAM_BOOL,     NULL, F_SYNC },
557                 { "listenaddr", FALSE,  PARAM_STRING,   NULL, 0 },
558         };
559         const int lp_size=sizeof(lp)/sizeof(PARAM);
560         PARAM gp[] = {
561                 { "user",       FALSE, PARAM_STRING,    &runuser,       0 },
562                 { "group",      FALSE, PARAM_STRING,    &rungroup,      0 },
563         };
564         PARAM* p=gp;
565         int p_size=sizeof(gp)/sizeof(PARAM);
566         GKeyFile *cfile;
567         GError *err = NULL;
568         const char *err_msg=NULL;
569         GQuark errdomain;
570         GArray *retval=NULL;
571         gchar **groups;
572         gboolean value;
573         gchar* startgroup;
574         gint i;
575         gint j;
576
577         errdomain = g_quark_from_string("parse_cfile");
578         cfile = g_key_file_new();
579         retval = g_array_new(FALSE, TRUE, sizeof(SERVER));
580         if(!g_key_file_load_from_file(cfile, f, G_KEY_FILE_KEEP_COMMENTS |
581                         G_KEY_FILE_KEEP_TRANSLATIONS, &err)) {
582                 g_set_error(e, errdomain, CFILE_NOTFOUND, "Could not open config file %s.", f);
583                 g_key_file_free(cfile);
584                 return retval;
585         }
586         startgroup = g_key_file_get_start_group(cfile);
587         if(!startgroup || strcmp(startgroup, "generic")) {
588                 g_set_error(e, errdomain, CFILE_MISSING_GENERIC, "Config file does not contain the [generic] group!");
589                 g_key_file_free(cfile);
590                 return NULL;
591         }
592         groups = g_key_file_get_groups(cfile, NULL);
593         for(i=0;groups[i];i++) {
594                 memset(&s, '\0', sizeof(SERVER));
595                 lp[0].target=&(s.exportname);
596                 lp[1].target=&(s.port);
597                 lp[2].target=&(s.authname);
598                 lp[3].target=&(s.expected_size);
599                 lp[4].target=&(virtstyle);
600                 lp[5].target=&(s.prerun);
601                 lp[6].target=&(s.postrun);
602                 lp[7].target=lp[8].target=lp[9].target=
603                                 lp[10].target=lp[11].target=
604                                 lp[12].target=&(s.flags);
605                 lp[13].target=&(s.listenaddr);
606
607                 /* After the [generic] group, start parsing exports */
608                 if(i==1) {
609                         p=lp;
610                         p_size=lp_size;
611                 } 
612                 for(j=0;j<p_size;j++) {
613                         g_assert(p[j].target != NULL);
614                         g_assert(p[j].ptype==PARAM_INT||p[j].ptype==PARAM_STRING||p[j].ptype==PARAM_BOOL);
615                         switch(p[j].ptype) {
616                                 case PARAM_INT:
617                                         *((gint*)p[j].target) =
618                                                 g_key_file_get_integer(cfile,
619                                                                 groups[i],
620                                                                 p[j].paramname,
621                                                                 &err);
622                                         break;
623                                 case PARAM_STRING:
624                                         *((gchar**)p[j].target) =
625                                                 g_key_file_get_string(cfile,
626                                                                 groups[i],
627                                                                 p[j].paramname,
628                                                                 &err);
629                                         break;
630                                 case PARAM_BOOL:
631                                         value = g_key_file_get_boolean(cfile,
632                                                         groups[i],
633                                                         p[j].paramname, &err);
634                                         if(!err) {
635                                                 if(value) {
636                                                         *((gint*)p[j].target) |= p[j].flagval;
637                                                 } else {
638                                                         *((gint*)p[j].target) &= ~(p[j].flagval);
639                                                 }
640                                         }
641                                         break;
642                         }
643                         if(err) {
644                                 if(err->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
645                                         if(!p[j].required) {
646                                                 /* Ignore not-found error for optional values */
647                                                 g_clear_error(&err);
648                                                 continue;
649                                         } else {
650                                                 err_msg = MISSING_REQUIRED_ERROR;
651                                         }
652                                 } else {
653                                         err_msg = DEFAULT_ERROR;
654                                 }
655                                 g_set_error(e, errdomain, CFILE_VALUE_INVALID, err_msg, p[j].paramname, groups[i], err->message);
656                                 g_array_free(retval, TRUE);
657                                 g_error_free(err);
658                                 g_key_file_free(cfile);
659                                 return NULL;
660                         }
661                 }
662                 if(virtstyle) {
663                         if(!strncmp(virtstyle, "none", 4)) {
664                                 s.virtstyle=VIRT_NONE;
665                         } else if(!strncmp(virtstyle, "ipliteral", 9)) {
666                                 s.virtstyle=VIRT_IPLIT;
667                         } else if(!strncmp(virtstyle, "iphash", 6)) {
668                                 s.virtstyle=VIRT_IPHASH;
669                         } else if(!strncmp(virtstyle, "cidrhash", 8)) {
670                                 s.virtstyle=VIRT_CIDR;
671                                 if(strlen(virtstyle)<10) {
672                                         g_set_error(e, errdomain, CFILE_VALUE_INVALID, "Invalid value %s for parameter virtstyle in group %s: missing length", virtstyle, groups[i]);
673                                         g_array_free(retval, TRUE);
674                                         g_key_file_free(cfile);
675                                         return NULL;
676                                 }
677                                 s.cidrlen=strtol(virtstyle+8, NULL, 0);
678                         } else {
679                                 g_set_error(e, errdomain, CFILE_VALUE_INVALID, "Invalid value %s for parameter virtstyle in group %s", virtstyle, groups[i]);
680                                 g_array_free(retval, TRUE);
681                                 g_key_file_free(cfile);
682                                 return NULL;
683                         }
684                 } else {
685                         s.virtstyle=VIRT_IPLIT;
686                 }
687                 /* Don't need to free this, it's not our string */
688                 virtstyle=NULL;
689                 /* Don't append values for the [generic] group */
690                 if(i>0) {
691                         if(!s.listenaddr) {
692                                 s.listenaddr = g_strdup("0.0.0.0");
693                         }
694                         g_array_append_val(retval, s);
695                 }
696 #ifndef WITH_SDP
697                 if(s.flags & F_SDP) {
698                         g_set_error(e, errdomain, CFILE_VALUE_UNSUPPORTED, "This nbd-server was built without support for SDP, yet group %s uses it", groups[i]);
699                         g_array_free(retval, TRUE);
700                         g_key_file_free(cfile);
701                         return NULL;
702                 }
703 #endif
704         }
705         if(i==1) {
706                 g_set_error(e, errdomain, CFILE_NO_EXPORTS, "The config file does not specify any exports");
707         }
708         g_key_file_free(cfile);
709         return retval;
710 }
711
712 /**
713  * Signal handler for SIGCHLD
714  * @param s the signal we're handling (must be SIGCHLD, or something
715  * is severely wrong)
716  **/
717 void sigchld_handler(int s) {
718         int status;
719         int* i;
720         pid_t pid;
721
722         while((pid=waitpid(-1, &status, WNOHANG)) > 0) {
723                 if(WIFEXITED(status)) {
724                         msg3(LOG_INFO, "Child exited with %d", WEXITSTATUS(status));
725                 }
726                 i=g_hash_table_lookup(children, &pid);
727                 if(!i) {
728                         msg3(LOG_INFO, "SIGCHLD received for an unknown child with PID %ld", (long)pid);
729                 } else {
730                         DEBUG2("Removing %d from the list of children", pid);
731                         g_hash_table_remove(children, &pid);
732                 }
733         }
734 }
735
736 /**
737  * Kill a child. Called from sigterm_handler::g_hash_table_foreach.
738  *
739  * @param key the key
740  * @param value the value corresponding to the above key
741  * @param user_data a pointer which we always set to 1, so that we know what
742  * will happen next.
743  **/
744 void killchild(gpointer key, gpointer value, gpointer user_data) {
745         pid_t *pid=value;
746         int *parent=user_data;
747
748         kill(*pid, SIGTERM);
749         *parent=1;
750 }
751
752 /**
753  * Handle SIGTERM and dispatch it to our children
754  * @param s the signal we're handling (must be SIGTERM, or something
755  * is severely wrong).
756  **/
757 void sigterm_handler(int s) {
758         int parent=0;
759
760         g_hash_table_foreach(children, killchild, &parent);
761
762         if(parent) {
763                 unlink(pidfname);
764         }
765
766         exit(EXIT_SUCCESS);
767 }
768
769 /**
770  * Detect the size of a file.
771  *
772  * @param fhandle An open filedescriptor
773  * @return the size of the file, or OFFT_MAX if detection was
774  * impossible.
775  **/
776 off_t size_autodetect(int fhandle) {
777         off_t es;
778         u64 bytes;
779         struct stat stat_buf;
780         int error;
781
782 #ifdef HAVE_SYS_MOUNT_H
783 #ifdef HAVE_SYS_IOCTL_H
784 #ifdef BLKGETSIZE64
785         DEBUG("looking for export size with ioctl BLKGETSIZE64\n");
786         if (!ioctl(fhandle, BLKGETSIZE64, bytes) && bytes) {
787                 return (off_t)bytes;
788         }
789 #endif /* BLKGETSIZE64 */
790 #endif /* HAVE_SYS_IOCTL_H */
791 #endif /* HAVE_SYS_MOUNT_H */
792
793         DEBUG("looking for fhandle size with fstat\n");
794         stat_buf.st_size = 0;
795         error = fstat(fhandle, &stat_buf);
796         if (!error) {
797                 if(stat_buf.st_size > 0)
798                         return (off_t)stat_buf.st_size;
799         } else {
800                 err("fstat failed: %m");
801         }
802
803         DEBUG("looking for fhandle size with lseek SEEK_END\n");
804         es = lseek(fhandle, (off_t)0, SEEK_END);
805         if (es > ((off_t)0)) {
806                 return es;
807         } else {
808                 DEBUG2("lseek failed: %d", errno==EBADF?1:(errno==ESPIPE?2:(errno==EINVAL?3:4)));
809         }
810
811         err("Could not find size of exported block device: %m");
812         return OFFT_MAX;
813 }
814
815 /**
816  * Get the file handle and offset, given an export offset.
817  *
818  * @param export An array of export files
819  * @param a The offset to get corresponding file/offset for
820  * @param fhandle [out] File descriptor
821  * @param foffset [out] Offset into fhandle
822  * @param maxbytes [out] Tells how many bytes can be read/written
823  * from fhandle starting at foffset (0 if there is no limit)
824  * @return 0 on success, -1 on failure
825  **/
826 int get_filepos(GArray* export, off_t a, int* fhandle, off_t* foffset, size_t* maxbytes ) {
827         /* Negative offset not allowed */
828         if(a < 0)
829                 return -1;
830
831         /* Binary search for last file with starting offset <= a */
832         FILE_INFO fi;
833         int start = 0;
834         int end = export->len - 1;
835         while( start <= end ) {
836                 int mid = (start + end) / 2;
837                 fi = g_array_index(export, FILE_INFO, mid);
838                 if( fi.startoff < a ) {
839                         start = mid + 1;
840                 } else if( fi.startoff > a ) {
841                         end = mid - 1;
842                 } else {
843                         start = end = mid;
844                         break;
845                 }
846         }
847
848         /* end should never go negative, since first startoff is 0 and a >= 0 */
849         g_assert(end >= 0);
850
851         fi = g_array_index(export, FILE_INFO, end);
852         *fhandle = fi.fhandle;
853         *foffset = a - fi.startoff;
854         *maxbytes = 0;
855         if( end+1 < export->len ) {
856                 FILE_INFO fi_next = g_array_index(export, FILE_INFO, end+1);
857                 *maxbytes = fi_next.startoff - a;
858         }
859
860         return 0;
861 }
862
863 /**
864  * seek to a position in a file, with error handling.
865  * @param handle a filedescriptor
866  * @param a position to seek to
867  * @todo get rid of this; lastpoint is a global variable right now, but it
868  * shouldn't be. If we pass it on as a parameter, that makes things a *lot*
869  * easier.
870  **/
871 void myseek(int handle,off_t a) {
872         if (lseek(handle, a, SEEK_SET) < 0) {
873                 err("Can not seek locally!\n");
874         }
875 }
876
877 /**
878  * Write an amount of bytes at a given offset to the right file. This
879  * abstracts the write-side of the multiple file option.
880  *
881  * @param a The offset where the write should start
882  * @param buf The buffer to write from
883  * @param len The length of buf
884  * @param client The client we're serving for
885  * @return The number of bytes actually written, or -1 in case of an error
886  **/
887 ssize_t rawexpwrite(off_t a, char *buf, size_t len, CLIENT *client) {
888         int fhandle;
889         off_t foffset;
890         size_t maxbytes;
891         ssize_t retval;
892
893         if(get_filepos(client->export, a, &fhandle, &foffset, &maxbytes))
894                 return -1;
895         if(maxbytes && len > maxbytes)
896                 len = maxbytes;
897
898         DEBUG4("(WRITE to fd %d offset %llu len %u), ", fhandle, foffset, len);
899
900         myseek(fhandle, foffset);
901         retval = write(fhandle, buf, len);
902         if(client->server->flags & F_SYNC) {
903                 fsync(fhandle);
904         }
905         return retval;
906 }
907
908 /**
909  * Call rawexpwrite repeatedly until all data has been written.
910  * @return 0 on success, nonzero on failure
911  **/
912 int rawexpwrite_fully(off_t a, char *buf, size_t len, CLIENT *client) {
913         ssize_t ret=0;
914
915         while(len > 0 && (ret=rawexpwrite(a, buf, len, client)) > 0 ) {
916                 a += ret;
917                 buf += ret;
918                 len -= ret;
919         }
920         return (ret < 0 || len != 0);
921 }
922
923 /**
924  * Read an amount of bytes at a given offset from the right file. This
925  * abstracts the read-side of the multiple files option.
926  *
927  * @param a The offset where the read should start
928  * @param buf A buffer to read into
929  * @param len The size of buf
930  * @param client The client we're serving for
931  * @return The number of bytes actually read, or -1 in case of an
932  * error.
933  **/
934 ssize_t rawexpread(off_t a, char *buf, size_t len, CLIENT *client) {
935         int fhandle;
936         off_t foffset;
937         size_t maxbytes;
938
939         if(get_filepos(client->export, a, &fhandle, &foffset, &maxbytes))
940                 return -1;
941         if(maxbytes && len > maxbytes)
942                 len = maxbytes;
943
944         DEBUG4("(READ from fd %d offset %llu len %u), ", fhandle, foffset, len);
945
946         myseek(fhandle, foffset);
947         return read(fhandle, buf, len);
948 }
949
950 /**
951  * Call rawexpread repeatedly until all data has been read.
952  * @return 0 on success, nonzero on failure
953  **/
954 int rawexpread_fully(off_t a, char *buf, size_t len, CLIENT *client) {
955         ssize_t ret=0;
956
957         while(len > 0 && (ret=rawexpread(a, buf, len, client)) > 0 ) {
958                 a += ret;
959                 buf += ret;
960                 len -= ret;
961         }
962         return (ret < 0 || len != 0);
963 }
964
965 /**
966  * Read an amount of bytes at a given offset from the right file. This
967  * abstracts the read-side of the copyonwrite stuff, and calls
968  * rawexpread() with the right parameters to do the actual work.
969  * @param a The offset where the read should start
970  * @param buf A buffer to read into
971  * @param len The size of buf
972  * @param client The client we're going to read for
973  * @return 0 on success, nonzero on failure
974  **/
975 int expread(off_t a, char *buf, size_t len, CLIENT *client) {
976         off_t rdlen, offset;
977         off_t mapcnt, mapl, maph, pagestart;
978
979         if (!(client->server->flags & F_COPYONWRITE))
980                 return(rawexpread_fully(a, buf, len, client));
981         DEBUG3("Asked to read %d bytes at %llu.\n", len, (unsigned long long)a);
982
983         mapl=a/DIFFPAGESIZE; maph=(a+len-1)/DIFFPAGESIZE;
984
985         for (mapcnt=mapl;mapcnt<=maph;mapcnt++) {
986                 pagestart=mapcnt*DIFFPAGESIZE;
987                 offset=a-pagestart;
988                 rdlen=(0<DIFFPAGESIZE-offset && len<(size_t)(DIFFPAGESIZE-offset)) ?
989                         len : (size_t)DIFFPAGESIZE-offset;
990                 if (client->difmap[mapcnt]!=(u32)(-1)) { /* the block is already there */
991                         DEBUG3("Page %llu is at %lu\n", (unsigned long long)mapcnt,
992                                (unsigned long)(client->difmap[mapcnt]));
993                         myseek(client->difffile, client->difmap[mapcnt]*DIFFPAGESIZE+offset);
994                         if (read(client->difffile, buf, rdlen) != rdlen) return -1;
995                 } else { /* the block is not there */
996                         DEBUG2("Page %llu is not here, we read the original one\n",
997                                (unsigned long long)mapcnt);
998                         if(rawexpread_fully(a, buf, rdlen, client)) return -1;
999                 }
1000                 len-=rdlen; a+=rdlen; buf+=rdlen;
1001         }
1002         return 0;
1003 }
1004
1005 /**
1006  * Write an amount of bytes at a given offset to the right file. This
1007  * abstracts the write-side of the copyonwrite option, and calls
1008  * rawexpwrite() with the right parameters to do the actual work.
1009  *
1010  * @param a The offset where the write should start
1011  * @param buf The buffer to write from
1012  * @param len The length of buf
1013  * @param client The client we're going to write for.
1014  * @return 0 on success, nonzero on failure
1015  **/
1016 int expwrite(off_t a, char *buf, size_t len, CLIENT *client) {
1017         char pagebuf[DIFFPAGESIZE];
1018         off_t mapcnt,mapl,maph;
1019         off_t wrlen,rdlen; 
1020         off_t pagestart;
1021         off_t offset;
1022
1023         if (!(client->server->flags & F_COPYONWRITE))
1024                 return(rawexpwrite_fully(a, buf, len, client)); 
1025         DEBUG3("Asked to write %d bytes at %llu.\n", len, (unsigned long long)a);
1026
1027         mapl=a/DIFFPAGESIZE ; maph=(a+len-1)/DIFFPAGESIZE ;
1028
1029         for (mapcnt=mapl;mapcnt<=maph;mapcnt++) {
1030                 pagestart=mapcnt*DIFFPAGESIZE ;
1031                 offset=a-pagestart ;
1032                 wrlen=(0<DIFFPAGESIZE-offset && len<(size_t)(DIFFPAGESIZE-offset)) ?
1033                         len : (size_t)DIFFPAGESIZE-offset;
1034
1035                 if (client->difmap[mapcnt]!=(u32)(-1)) { /* the block is already there */
1036                         DEBUG3("Page %llu is at %lu\n", (unsigned long long)mapcnt,
1037                                (unsigned long)(client->difmap[mapcnt])) ;
1038                         myseek(client->difffile,
1039                                         client->difmap[mapcnt]*DIFFPAGESIZE+offset);
1040                         if (write(client->difffile, buf, wrlen) != wrlen) return -1 ;
1041                 } else { /* the block is not there */
1042                         myseek(client->difffile,client->difffilelen*DIFFPAGESIZE) ;
1043                         client->difmap[mapcnt]=(client->server->flags&F_SPARSE)?mapcnt:client->difffilelen++;
1044                         DEBUG3("Page %llu is not here, we put it at %lu\n",
1045                                (unsigned long long)mapcnt,
1046                                (unsigned long)(client->difmap[mapcnt]));
1047                         rdlen=DIFFPAGESIZE ;
1048                         if (rawexpread_fully(pagestart, pagebuf, rdlen, client))
1049                                 return -1;
1050                         memcpy(pagebuf+offset,buf,wrlen) ;
1051                         if (write(client->difffile, pagebuf, DIFFPAGESIZE) !=
1052                                         DIFFPAGESIZE)
1053                                 return -1;
1054                 }                                                   
1055                 len-=wrlen ; a+=wrlen ; buf+=wrlen ;
1056         }
1057         return 0;
1058 }
1059
1060 /**
1061  * Do the initial negotiation.
1062  *
1063  * @param client The client we're negotiating with.
1064  **/
1065 void negotiate(CLIENT *client) {
1066         char zeros[128];
1067         u64 size_host;
1068         u32 flags = NBD_FLAG_HAS_FLAGS;
1069
1070         memset(zeros, '\0', sizeof(zeros));
1071         if (write(client->net, INIT_PASSWD, 8) < 0)
1072                 err("Negotiation failed: %m");
1073         cliserv_magic = htonll(cliserv_magic);
1074         if (write(client->net, &cliserv_magic, sizeof(cliserv_magic)) < 0)
1075                 err("Negotiation failed: %m");
1076         size_host = htonll((u64)(client->exportsize));
1077         if (write(client->net, &size_host, 8) < 0)
1078                 err("Negotiation failed: %m");
1079         if (client->server->flags & F_READONLY)
1080                 flags |= NBD_FLAG_READ_ONLY;
1081         flags = htonl(flags);
1082         if (write(client->net, &flags, 4) < 0)
1083                 err("Negotiation failed: %m");
1084         if (write(client->net, zeros, 124) < 0)
1085                 err("Negotiation failed: %m");
1086 }
1087
1088 /** sending macro. */
1089 #define SEND(net,reply) writeit( net, &reply, sizeof( reply ));
1090 /** error macro. */
1091 #define ERROR(client,reply,errcode) { reply.error = htonl(errcode); SEND(client->net,reply); reply.error = 0; }
1092 /**
1093  * Serve a file to a single client.
1094  *
1095  * @todo This beast needs to be split up in many tiny little manageable
1096  * pieces. Preferably with a chainsaw.
1097  *
1098  * @param client The client we're going to serve to.
1099  * @return when the client disconnects
1100  **/
1101 int mainloop(CLIENT *client) {
1102         struct nbd_request request;
1103         struct nbd_reply reply;
1104         gboolean go_on=TRUE;
1105 #ifdef DODBG
1106         int i = 0;
1107 #endif
1108         negotiate(client);
1109         DEBUG("Entering request loop!\n");
1110         reply.magic = htonl(NBD_REPLY_MAGIC);
1111         reply.error = 0;
1112         while (go_on) {
1113                 char buf[BUFSIZE];
1114                 size_t len;
1115 #ifdef DODBG
1116                 i++;
1117                 printf("%d: ", i);
1118 #endif
1119                 readit(client->net, &request, sizeof(request));
1120                 request.from = ntohll(request.from);
1121                 request.type = ntohl(request.type);
1122
1123                 if (request.type==NBD_CMD_DISC) {
1124                         msg2(LOG_INFO, "Disconnect request received.");
1125                         if (client->server->flags & F_COPYONWRITE) { 
1126                                 if (client->difmap) g_free(client->difmap) ;
1127                                 close(client->difffile);
1128                                 unlink(client->difffilename);
1129                                 free(client->difffilename);
1130                         }
1131                         go_on=FALSE;
1132                         continue;
1133                 }
1134
1135                 len = ntohl(request.len);
1136
1137                 if (request.magic != htonl(NBD_REQUEST_MAGIC))
1138                         err("Not enough magic.");
1139                 if (len > BUFSIZE + sizeof(struct nbd_reply))
1140                         err("Request too big!");
1141 #ifdef DODBG
1142                 printf("%s from %llu (%llu) len %d, ", request.type ? "WRITE" :
1143                                 "READ", (unsigned long long)request.from,
1144                                 (unsigned long long)request.from / 512, len);
1145 #endif
1146                 memcpy(reply.handle, request.handle, sizeof(reply.handle));
1147                 if ((request.from + len) > (OFFT_MAX)) {
1148                         DEBUG("[Number too large!]");
1149                         ERROR(client, reply, EINVAL);
1150                         continue;
1151                 }
1152
1153                 if (((ssize_t)((off_t)request.from + len) > client->exportsize)) {
1154                         DEBUG("[RANGE!]");
1155                         ERROR(client, reply, EINVAL);
1156                         continue;
1157                 }
1158
1159                 if (request.type==NBD_CMD_WRITE) {
1160                         DEBUG("wr: net->buf, ");
1161                         readit(client->net, buf, len);
1162                         DEBUG("buf->exp, ");
1163                         if ((client->server->flags & F_READONLY) ||
1164                             (client->server->flags & F_AUTOREADONLY)) {
1165                                 DEBUG("[WRITE to READONLY!]");
1166                                 ERROR(client, reply, EPERM);
1167                                 continue;
1168                         }
1169                         if (expwrite(request.from, buf, len, client)) {
1170                                 DEBUG("Write failed: %m" );
1171                                 ERROR(client, reply, errno);
1172                                 continue;
1173                         }
1174                         SEND(client->net, reply);
1175                         DEBUG("OK!\n");
1176                         continue;
1177                 }
1178                 /* READ */
1179
1180                 DEBUG("exp->buf, ");
1181                 if (expread(request.from, buf + sizeof(struct nbd_reply), len, client)) {
1182                         DEBUG("Read failed: %m");
1183                         ERROR(client, reply, errno);
1184                         continue;
1185                 }
1186
1187                 DEBUG("buf->net, ");
1188                 memcpy(buf, &reply, sizeof(struct nbd_reply));
1189                 writeit(client->net, buf, len + sizeof(struct nbd_reply));
1190                 DEBUG("OK!\n");
1191         }
1192         return 0;
1193 }
1194
1195 /**
1196  * Set up client export array, which is an array of FILE_INFO.
1197  * Also, split a single exportfile into multiple ones, if that was asked.
1198  * @param client information on the client which we want to setup export for
1199  **/
1200 void setupexport(CLIENT* client) {
1201         int i;
1202         off_t laststartoff = 0, lastsize = 0;
1203         int multifile = (client->server->flags & F_MULTIFILE);
1204
1205         client->export = g_array_new(TRUE, TRUE, sizeof(FILE_INFO));
1206
1207         /* If multi-file, open as many files as we can.
1208          * If not, open exactly one file.
1209          * Calculate file sizes as we go to get total size. */
1210         for(i=0; ; i++) {
1211                 FILE_INFO fi;
1212                 gchar *tmpname;
1213                 gchar* error_string;
1214                 mode_t mode = (client->server->flags & F_READONLY) ? O_RDONLY : O_RDWR;
1215
1216                 if(multifile) {
1217                         tmpname=g_strdup_printf("%s.%d", client->exportname, i);
1218                 } else {
1219                         tmpname=g_strdup(client->exportname);
1220                 }
1221                 DEBUG2( "Opening %s\n", tmpname );
1222                 fi.fhandle = open(tmpname, mode);
1223                 if(fi.fhandle == -1 && mode == O_RDWR) {
1224                         /* Try again because maybe media was read-only */
1225                         fi.fhandle = open(tmpname, O_RDONLY);
1226                         if(fi.fhandle != -1) {
1227                                 /* Opening the base file in copyonwrite mode is
1228                                  * okay */
1229                                 if(!(client->server->flags & F_COPYONWRITE)) {
1230                                         client->server->flags |= F_AUTOREADONLY;
1231                                         client->server->flags |= F_READONLY;
1232                                 }
1233                         }
1234                 }
1235                 if(fi.fhandle == -1) {
1236                         if(multifile && i>0)
1237                                 break;
1238                         error_string=g_strdup_printf(
1239                                 "Could not open exported file %s: %%m",
1240                                 tmpname);
1241                         err(error_string);
1242                 }
1243                 fi.startoff = laststartoff + lastsize;
1244                 g_array_append_val(client->export, fi);
1245                 g_free(tmpname);
1246
1247                 /* Starting offset and size of this file will be used to
1248                  * calculate starting offset of next file */
1249                 laststartoff = fi.startoff;
1250                 lastsize = size_autodetect(fi.fhandle);
1251
1252                 if(!multifile)
1253                         break;
1254         }
1255
1256         /* Set export size to total calculated size */
1257         client->exportsize = laststartoff + lastsize;
1258
1259         /* Export size may be overridden */
1260         if(client->server->expected_size) {
1261                 /* desired size must be <= total calculated size */
1262                 if(client->server->expected_size > client->exportsize) {
1263                         err("Size of exported file is too big\n");
1264                 }
1265
1266                 client->exportsize = client->server->expected_size;
1267         }
1268
1269         msg3(LOG_INFO, "Size of exported file/device is %llu", (unsigned long long)client->exportsize);
1270         if(multifile) {
1271                 msg3(LOG_INFO, "Total number of files: %d", i);
1272         }
1273 }
1274
1275 int copyonwrite_prepare(CLIENT* client) {
1276         off_t i;
1277         if ((client->difffilename = malloc(1024))==NULL)
1278                 err("Failed to allocate string for diff file name");
1279         snprintf(client->difffilename, 1024, "%s-%s-%d.diff",client->exportname,client->clientname,
1280                 (int)getpid()) ;
1281         client->difffilename[1023]='\0';
1282         msg3(LOG_INFO,"About to create map and diff file %s",client->difffilename) ;
1283         client->difffile=open(client->difffilename,O_RDWR | O_CREAT | O_TRUNC,0600) ;
1284         if (client->difffile<0) err("Could not create diff file (%m)") ;
1285         if ((client->difmap=calloc(client->exportsize/DIFFPAGESIZE,sizeof(u32)))==NULL)
1286                 err("Could not allocate memory") ;
1287         for (i=0;i<client->exportsize/DIFFPAGESIZE;i++) client->difmap[i]=(u32)-1 ;
1288
1289         return 0;
1290 }
1291
1292 /**
1293  * Run a command. This is used for the ``prerun'' and ``postrun'' config file
1294  * options
1295  *
1296  * @param command the command to be ran. Read from the config file
1297  * @param file the file name we're about to export
1298  **/
1299 int do_run(gchar* command, gchar* file) {
1300         gchar* cmd;
1301         int retval=0;
1302
1303         if(command && *command) {
1304                 cmd = g_strdup_printf(command, file);
1305                 retval=system(cmd);
1306                 g_free(cmd);
1307         }
1308         return retval;
1309 }
1310
1311 /**
1312  * Serve a connection. 
1313  *
1314  * @todo allow for multithreading, perhaps use libevent. Not just yet, though;
1315  * follow the road map.
1316  *
1317  * @param client a connected client
1318  **/
1319 void serveconnection(CLIENT *client) {
1320         if(do_run(client->server->prerun, client->exportname)) {
1321                 exit(EXIT_FAILURE);
1322         }
1323         setupexport(client);
1324
1325         if (client->server->flags & F_COPYONWRITE) {
1326                 copyonwrite_prepare(client);
1327         }
1328
1329         setmysockopt(client->net);
1330
1331         mainloop(client);
1332         do_run(client->server->postrun, client->exportname);
1333 }
1334
1335 /**
1336  * Find the name of the file we have to serve. This will use g_strdup_printf
1337  * to put the IP address of the client inside a filename containing
1338  * "%s" (in the form as specified by the "virtstyle" option). That name
1339  * is then written to client->exportname.
1340  *
1341  * @param net A socket connected to an nbd client
1342  * @param client information about the client. The IP address in human-readable
1343  * format will be written to a new char* buffer, the address of which will be
1344  * stored in client->clientname.
1345  **/
1346 void set_peername(int net, CLIENT *client) {
1347         struct sockaddr_in addrin;
1348         struct sockaddr_in netaddr;
1349         size_t addrinlen = sizeof( addrin );
1350         char *peername;
1351         char *netname;
1352         char *tmp;
1353         int i;
1354
1355         if (getpeername(net, (struct sockaddr *) &addrin, (socklen_t *)&addrinlen) < 0)
1356                 err("getsockname failed: %m");
1357         peername = g_strdup(inet_ntoa(addrin.sin_addr));
1358         switch(client->server->virtstyle) {
1359                 case VIRT_NONE:
1360                         client->exportname=g_strdup(client->server->exportname);
1361                         break;
1362                 case VIRT_IPHASH:
1363                         for(i=0;i<strlen(peername);i++) {
1364                                 if(peername[i]=='.') {
1365                                         peername[i]='/';
1366                                 }
1367                         }
1368                 case VIRT_IPLIT:
1369                         client->exportname=g_strdup_printf(client->server->exportname, peername);
1370                         break;
1371                 case VIRT_CIDR:
1372                         memcpy(&netaddr, &addrin, addrinlen);
1373                         netaddr.sin_addr.s_addr>>=32-(client->server->cidrlen);
1374                         netaddr.sin_addr.s_addr<<=32-(client->server->cidrlen);
1375                         netname = inet_ntoa(netaddr.sin_addr);
1376                         tmp=g_strdup_printf("%s/%s", netname, peername);
1377                         client->exportname=g_strdup_printf(client->server->exportname, tmp);
1378                         break;
1379         }
1380
1381         msg4(LOG_INFO, "connect from %s, assigned file is %s", 
1382              peername, client->exportname);
1383         client->clientname=g_strdup(peername);
1384         g_free(peername);
1385 }
1386
1387 /**
1388  * Destroy a pid_t*
1389  * @param data a pointer to pid_t which should be freed
1390  **/
1391 void destroy_pid_t(gpointer data) {
1392         g_free(data);
1393 }
1394
1395 /**
1396  * Loop through the available servers, and serve them. Never returns.
1397  **/
1398 int serveloop(GArray* servers) {
1399         struct sockaddr_in addrin;
1400         socklen_t addrinlen=sizeof(addrin);
1401         SERVER *serve;
1402         int i;
1403         int max;
1404         int sock;
1405         fd_set mset;
1406         fd_set rset;
1407
1408         /* 
1409          * Set up the master fd_set. The set of descriptors we need
1410          * to select() for never changes anyway and it buys us a *lot*
1411          * of time to only build this once. However, if we ever choose
1412          * to not fork() for clients anymore, we may have to revisit
1413          * this.
1414          */
1415         max=0;
1416         FD_ZERO(&mset);
1417         for(i=0;i<servers->len;i++) {
1418                 sock=(g_array_index(servers, SERVER, i)).socket;
1419                 FD_SET(sock, &mset);
1420                 max=sock>max?sock:max;
1421         }
1422         for(;;) {
1423                 CLIENT *client;
1424                 int net;
1425                 pid_t *pid;
1426
1427                 memcpy(&rset, &mset, sizeof(fd_set));
1428                 if(select(max+1, &rset, NULL, NULL, NULL)>0) {
1429                         DEBUG("accept, ");
1430                         for(i=0;i<servers->len;i++) {
1431                                 serve=&(g_array_index(servers, SERVER, i));
1432                                 if(FD_ISSET(serve->socket, &rset)) {
1433                                         int sock_flags;
1434                                         if ((net=accept(serve->socket, (struct sockaddr *) &addrin, &addrinlen)) < 0)
1435                                                 err("accept: %m");
1436
1437                                         if((sock_flags = fcntl(net, F_GETFL, 0))==-1) {
1438                                                 err("fcntl F_GETFL");
1439                                         }
1440                                         if(fcntl(net, F_SETFL, sock_flags &~O_NONBLOCK)==-1) {
1441                                                 err("fcntl F_SETFL ~O_NONBLOCK");
1442                                         }
1443                                         client = g_malloc(sizeof(CLIENT));
1444                                         client->server=serve;
1445                                         client->exportsize=OFFT_MAX;
1446                                         client->net=net;
1447                                         set_peername(net, client);
1448                                         if (!authorized_client(client)) {
1449                                                 msg2(LOG_INFO,"Unauthorized client") ;
1450                                                 close(net);
1451                                                 continue;
1452                                         }
1453                                         msg2(LOG_INFO,"Authorized client") ;
1454                                         pid=g_malloc(sizeof(pid_t));
1455 #ifndef NOFORK
1456                                         if ((*pid=fork())<0) {
1457                                                 msg3(LOG_INFO,"Could not fork (%s)",strerror(errno)) ;
1458                                                 close(net);
1459                                                 continue;
1460                                         }
1461                                         if (*pid>0) { /* parent */
1462                                                 close(net);
1463                                                 g_hash_table_insert(children, pid, pid);
1464                                                 continue;
1465                                         }
1466                                         /* child */
1467                                         g_hash_table_destroy(children);
1468                                         for(i=0;i<servers->len;i++) {
1469                                                 serve=&g_array_index(servers, SERVER, i);
1470                                                 close(serve->socket);
1471                                         }
1472                                         /* FALSE does not free the
1473                                         actual data. This is required,
1474                                         because the client has a
1475                                         direct reference into that
1476                                         data, and otherwise we get a
1477                                         segfault... */
1478                                         g_array_free(servers, FALSE);
1479 #endif // NOFORK
1480                                         msg2(LOG_INFO,"Starting to serve");
1481                                         serveconnection(client);
1482                                         exit(EXIT_SUCCESS);
1483                                 }
1484                         }
1485                 }
1486         }
1487 }
1488
1489 /**
1490  * Connect a server's socket.
1491  *
1492  * @param serve the server we want to connect.
1493  **/
1494 void setup_serve(SERVER *serve) {
1495         struct sockaddr_in addrin;
1496         struct sigaction sa;
1497         int addrinlen = sizeof(addrin);
1498         int sock_flags;
1499         int af;
1500 #ifndef sun
1501         int yes=1;
1502 #else
1503         char yes='1';
1504 #endif /* sun */
1505
1506         af = AF_INET;
1507 #ifdef WITH_SDP
1508         if ((serve->flags) && F_SDP) {
1509                 af = AF_INET_SDP;
1510         }
1511 #endif
1512         if ((serve->socket = socket(af, SOCK_STREAM, IPPROTO_TCP)) < 0)
1513                 err("socket: %m");
1514
1515         /* lose the pesky "Address already in use" error message */
1516         if (setsockopt(serve->socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
1517                 err("setsockopt SO_REUSEADDR");
1518         }
1519         if (setsockopt(serve->socket,SOL_SOCKET,SO_KEEPALIVE,&yes,sizeof(int)) == -1) {
1520                 err("setsockopt SO_KEEPALIVE");
1521         }
1522
1523         /* make the listening socket non-blocking */
1524         if ((sock_flags = fcntl(serve->socket, F_GETFL, 0)) == -1) {
1525                 err("fcntl F_GETFL");
1526         }
1527         if (fcntl(serve->socket, F_SETFL, sock_flags | O_NONBLOCK) == -1) {
1528                 err("fcntl F_SETFL O_NONBLOCK");
1529         }
1530
1531         DEBUG("Waiting for connections... bind, ");
1532         addrin.sin_family = AF_INET;
1533 #ifdef WITH_SDP
1534         if(serve->flags & F_SDP) {
1535                 addrin.sin_family = AF_INET_SDP;
1536         }
1537 #endif
1538         addrin.sin_port = htons(serve->port);
1539         if(!inet_aton(serve->listenaddr, &(addrin.sin_addr)))
1540                 err("could not parse listen address");
1541         if (bind(serve->socket, (struct sockaddr *) &addrin, addrinlen) < 0)
1542                 err("bind: %m");
1543         DEBUG("listen, ");
1544         if (listen(serve->socket, 1) < 0)
1545                 err("listen: %m");
1546         sa.sa_handler = sigchld_handler;
1547         sigemptyset(&sa.sa_mask);
1548         sa.sa_flags = SA_RESTART;
1549         if(sigaction(SIGCHLD, &sa, NULL) == -1)
1550                 err("sigaction: %m");
1551         sa.sa_handler = sigterm_handler;
1552         sigemptyset(&sa.sa_mask);
1553         sa.sa_flags = SA_RESTART;
1554         if(sigaction(SIGTERM, &sa, NULL) == -1)
1555                 err("sigaction: %m");
1556 }
1557
1558 /**
1559  * Connect our servers.
1560  **/
1561 void setup_servers(GArray* servers) {
1562         int i;
1563
1564         for(i=0;i<servers->len;i++) {
1565                 setup_serve(&(g_array_index(servers, SERVER, i)));
1566         }
1567         children=g_hash_table_new_full(g_int_hash, g_int_equal, NULL, destroy_pid_t);
1568 }
1569
1570 /**
1571  * Go daemon (unless we specified at compile time that we didn't want this)
1572  * @param serve the first server of our configuration. If its port is zero,
1573  *      then do not daemonize, because we're doing inetd then. This parameter
1574  *      is only used to create a PID file of the form
1575  *      /var/run/nbd-server.&lt;port&gt;.pid; it's not modified in any way.
1576  **/
1577 #if !defined(NODAEMON) && !defined(NOFORK)
1578 void daemonize(SERVER* serve) {
1579         FILE*pidf;
1580
1581         if(serve && !(serve->port)) {
1582                 return;
1583         }
1584         if(daemon(0,0)<0) {
1585                 err("daemon");
1586         }
1587         if(!*pidftemplate) {
1588                 if(serve) {
1589                         strncpy(pidftemplate, "/var/run/nbd-server.%d.pid", 255);
1590                 } else {
1591                         strncpy(pidftemplate, "/var/run/nbd-server.pid", 255);
1592                 }
1593         }
1594         snprintf(pidfname, 255, pidftemplate, serve ? serve->port : 0);
1595         pidf=fopen(pidfname, "w");
1596         if(pidf) {
1597                 fprintf(pidf,"%d\n", (int)getpid());
1598                 fclose(pidf);
1599         } else {
1600                 perror("fopen");
1601                 fprintf(stderr, "Not fatal; continuing");
1602         }
1603 }
1604 #else
1605 #define daemonize(serve)
1606 #endif /* !defined(NODAEMON) && !defined(NOFORK) */
1607
1608 /*
1609  * Everything beyond this point (in the file) is run in non-daemon mode.
1610  * The stuff above daemonize() isn't.
1611  */
1612
1613 void serve_err(SERVER* serve, const char* msg) G_GNUC_NORETURN;
1614
1615 void serve_err(SERVER* serve, const char* msg) {
1616         g_message("Export of %s on port %d failed:", serve->exportname,
1617                         serve->port);
1618         err(msg);
1619 }
1620
1621 /**
1622  * Set up user-ID and/or group-ID
1623  **/
1624 void dousers(void) {
1625         struct passwd *pw;
1626         struct group *gr;
1627         gchar* str;
1628         if(rungroup) {
1629                 gr=getgrnam(rungroup);
1630                 if(!gr) {
1631                         str = g_strdup_printf("Invalid group name: %s", rungroup);
1632                         err(str);
1633                 }
1634                 if(setgid(gr->gr_gid)<0) {
1635                         err("Could not set GID: %m"); 
1636                 }
1637         }
1638         if(runuser) {
1639                 pw=getpwnam(runuser);
1640                 if(!pw) {
1641                         str = g_strdup_printf("Invalid user name: %s", runuser);
1642                         err(str);
1643                 }
1644                 if(setuid(pw->pw_uid)<0) {
1645                         err("Could not set UID: %m");
1646                 }
1647         }
1648 }
1649
1650 #ifndef ISSERVER
1651 void glib_message_syslog_redirect(const gchar *log_domain,
1652                                   GLogLevelFlags log_level,
1653                                   const gchar *message,
1654                                   gpointer user_data)
1655 {
1656     int level=LOG_DEBUG;
1657     
1658     switch( log_level )
1659     {
1660       case G_LOG_FLAG_FATAL:
1661       case G_LOG_LEVEL_CRITICAL:
1662       case G_LOG_LEVEL_ERROR:    
1663         level=LOG_ERR; 
1664         break;
1665       case G_LOG_LEVEL_WARNING:
1666         level=LOG_WARNING;
1667         break;
1668       case G_LOG_LEVEL_MESSAGE:
1669       case G_LOG_LEVEL_INFO:
1670         level=LOG_INFO;
1671         break;
1672       case G_LOG_LEVEL_DEBUG:
1673         level=LOG_DEBUG;
1674       default:
1675         level=LOG_ERR;
1676     }
1677     syslog(level, message);
1678 }
1679 #endif
1680
1681 /**
1682  * Main entry point...
1683  **/
1684 int main(int argc, char *argv[]) {
1685         SERVER *serve;
1686         GArray *servers;
1687         GError *err=NULL;
1688
1689         if (sizeof( struct nbd_request )!=28) {
1690                 fprintf(stderr,"Bad size of structure. Alignment problems?\n");
1691                 exit(EXIT_FAILURE) ;
1692         }
1693
1694         memset(pidftemplate, '\0', 256);
1695
1696         logging();
1697         config_file_pos = g_strdup(CFILE);
1698         serve=cmdline(argc, argv);
1699         servers = parse_cfile(config_file_pos, &err);
1700         
1701         if(serve) {
1702                 g_array_append_val(servers, *serve);
1703      
1704                 if (!(serve->port)) {
1705                         CLIENT *client;
1706 #ifndef ISSERVER
1707                         /* You really should define ISSERVER if you're going to use
1708                          * inetd mode, but if you don't, closing stdout and stderr
1709                          * (which inetd had connected to the client socket) will let it
1710                          * work. */
1711                         close(1);
1712                         close(2);
1713                         open("/dev/null", O_WRONLY);
1714                         open("/dev/null", O_WRONLY);
1715                         g_log_set_default_handler( glib_message_syslog_redirect, NULL );
1716 #endif
1717                         client=g_malloc(sizeof(CLIENT));
1718                         client->server=serve;
1719                         client->net=0;
1720                         client->exportsize=OFFT_MAX;
1721                         set_peername(0,client);
1722                         serveconnection(client);
1723                         return 0;
1724                 }
1725         }
1726     
1727     if(!servers || !servers->len) {
1728                 g_warning("Could not parse config file: %s", 
1729                                 err ? err->message : "Unknown error");
1730         }
1731     
1732         if((!serve) && (!servers||!servers->len)) {
1733                 g_message("Nothing to do! Bye!");
1734                 exit(EXIT_FAILURE);
1735         }
1736         daemonize(serve);
1737         setup_servers(servers);
1738         dousers();
1739         serveloop(servers);
1740         return 0 ;
1741 }