Fix error output
[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-a|--idle-time\t\tmaximum idle seconds; server terminates when\n\t\t\t\tidle time exceeded\n"
348                "\t-p|--pid-file\t\tspecify a filename to write our PID to\n"
349                "\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"
350                "\tif port is set to 0, stdin is used (for running from inetd)\n"
351                "\tif file_to_export contains '%%s', it is substituted with the IP\n"
352                "\t\taddress of the machine trying to connect\n" 
353                "\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");
354         printf("Using configuration file %s\n", CFILE);
355 }
356
357 /* Dumps a config file section of the given SERVER*, and exits. */
358 void dump_section(SERVER* serve, gchar* section_header) {
359         printf("[%s]\n", section_header);
360         printf("\texportname = %s\n", serve->exportname);
361         printf("\tlistenaddr = %s\n", serve->listenaddr);
362         printf("\tport = %d\n", serve->port);
363         if(serve->flags & F_READONLY) {
364                 printf("\treadonly = true\n");
365         }
366         if(serve->flags & F_MULTIFILE) {
367                 printf("\tmultifile = true\n");
368         }
369         if(serve->flags & F_COPYONWRITE) {
370                 printf("\tcopyonwrite = true\n");
371         }
372         if(serve->expected_size) {
373                 printf("\tfilesize = %lld\n", (long long int)serve->expected_size);
374         }
375         if(serve->authname) {
376                 printf("\tauthfile = %s\n", serve->authname);
377         }
378         exit(EXIT_SUCCESS);
379 }
380
381 /**
382  * Parse the command line.
383  *
384  * @param argc the argc argument to main()
385  * @param argv the argv argument to main()
386  **/
387 SERVER* cmdline(int argc, char *argv[]) {
388         int i=0;
389         int nonspecial=0;
390         int c;
391         struct option long_options[] = {
392                 {"read-only", no_argument, NULL, 'r'},
393                 {"multi-file", no_argument, NULL, 'm'},
394                 {"copy-on-write", no_argument, NULL, 'c'},
395                 {"authorize-file", required_argument, NULL, 'l'},
396                 {"idle-time", required_argument, NULL, 'a'},
397                 {"config-file", required_argument, NULL, 'C'},
398                 {"pid-file", required_argument, NULL, 'p'},
399                 {"output-config", required_argument, NULL, 'o'},
400                 {0,0,0,0}
401         };
402         SERVER *serve;
403         off_t es;
404         size_t last;
405         char suffix;
406         gboolean do_output=FALSE;
407         gchar* section_header="";
408         gchar** addr_port;
409
410         if(argc==1) {
411                 return NULL;
412         }
413         serve=g_new0(SERVER, 1);
414         serve->authname = g_strdup(default_authname);
415         serve->virtstyle=VIRT_IPLIT;
416         while((c=getopt_long(argc, argv, "-a:C:cl:mo:rp:", long_options, &i))>=0) {
417                 switch (c) {
418                 case 1:
419                         /* non-option argument */
420                         switch(nonspecial++) {
421                         case 0:
422                                 addr_port=g_strsplit(optarg, ":", 2);
423                                 if(addr_port[1]) {
424                                         serve->port=strtol(addr_port[1], NULL, 0);
425                                         serve->listenaddr=g_strdup(addr_port[0]);
426                                 } else {
427                                         serve->listenaddr=g_strdup("0.0.0.0");
428                                         serve->port=strtol(addr_port[0], NULL, 0);
429                                 }
430                                 g_strfreev(addr_port);
431                                 break;
432                         case 1:
433                                 serve->exportname = g_strdup(optarg);
434                                 if(serve->exportname[0] != '/') {
435                                         fprintf(stderr, "E: The to be exported file needs to be an absolute filename!\n");
436                                         exit(EXIT_FAILURE);
437                                 }
438                                 break;
439                         case 2:
440                                 last=strlen(optarg)-1;
441                                 suffix=optarg[last];
442                                 if (suffix == 'k' || suffix == 'K' ||
443                                     suffix == 'm' || suffix == 'M')
444                                         optarg[last] = '\0';
445                                 es = (off_t)atoll(optarg);
446                                 switch (suffix) {
447                                         case 'm':
448                                         case 'M':  es <<= 10;
449                                         case 'k':
450                                         case 'K':  es <<= 10;
451                                         default :  break;
452                                 }
453                                 serve->expected_size = es;
454                                 break;
455                         }
456                         break;
457                 case 'r':
458                         serve->flags |= F_READONLY;
459                         break;
460                 case 'm':
461                         serve->flags |= F_MULTIFILE;
462                         break;
463                 case 'o':
464                         do_output = TRUE;
465                         section_header = g_strdup(optarg);
466                         break;
467                 case 'p':
468                         strncpy(pidftemplate, optarg, 256);
469                         break;
470                 case 'c': 
471                         serve->flags |=F_COPYONWRITE;
472                         break;
473                 case 'C':
474                         g_free(config_file_pos);
475                         config_file_pos=g_strdup(optarg);
476                         break;
477                 case 'l':
478                         g_free(serve->authname);
479                         serve->authname=g_strdup(optarg);
480                         break;
481                 default:
482                         usage();
483                         exit(EXIT_FAILURE);
484                         break;
485                 }
486         }
487         /* What's left: the port to export, the name of the to be exported
488          * file, and, optionally, the size of the file, in that order. */
489         if(nonspecial<2) {
490                 g_free(serve);
491                 serve=NULL;
492         }
493         if(do_output) {
494                 if(!serve) {
495                         g_critical("Need a complete configuration on the command line to output a config file section!");
496                         exit(EXIT_FAILURE);
497                 }
498                 dump_section(serve, section_header);
499         }
500         return serve;
501 }
502
503 /**
504  * Error codes for config file parsing
505  **/
506 typedef enum {
507         CFILE_NOTFOUND,         /**< The configuration file is not found */
508         CFILE_MISSING_GENERIC,  /**< The (required) group "generic" is missing */
509         CFILE_KEY_MISSING,      /**< A (required) key is missing */
510         CFILE_VALUE_INVALID,    /**< A value is syntactically invalid */
511         CFILE_VALUE_UNSUPPORTED,/**< A value is not supported in this build */
512         CFILE_PROGERR,          /**< Programmer error */
513         CFILE_NO_EXPORTS        /**< A config file was specified that does not
514                                      define any exports */
515 } CFILE_ERRORS;
516
517 /**
518  * Remove a SERVER from memory. Used from the hash table
519  **/
520 void remove_server(gpointer s) {
521         SERVER *server;
522
523         server=(SERVER*)s;
524         g_free(server->exportname);
525         if(server->authname)
526                 g_free(server->authname);
527         g_free(server);
528 }
529
530 /**
531  * Parse the config file.
532  *
533  * @param f the name of the config file
534  * @param e a GError. @see CFILE_ERRORS for what error values this function can
535  *      return.
536  * @return a Array of SERVER* pointers, If the config file is empty or does not
537  *      exist, returns an empty GHashTable; if the config file contains an
538  *      error, returns NULL, and e is set appropriately
539  **/
540 GArray* parse_cfile(gchar* f, GError** e) {
541         const char* DEFAULT_ERROR = "Could not parse %s in group %s: %s";
542         const char* MISSING_REQUIRED_ERROR = "Could not find required value %s in group %s: %s";
543         SERVER s;
544         gchar *virtstyle=NULL;
545         PARAM lp[] = {
546                 { "exportname", TRUE,   PARAM_STRING,   NULL, 0 },
547                 { "port",       TRUE,   PARAM_INT,      NULL, 0 },
548                 { "authfile",   FALSE,  PARAM_STRING,   NULL, 0 },
549                 { "filesize",   FALSE,  PARAM_INT,      NULL, 0 },
550                 { "virtstyle",  FALSE,  PARAM_STRING,   NULL, 0 },
551                 { "prerun",     FALSE,  PARAM_STRING,   NULL, 0 },
552                 { "postrun",    FALSE,  PARAM_STRING,   NULL, 0 },
553                 { "readonly",   FALSE,  PARAM_BOOL,     NULL, F_READONLY },
554                 { "multifile",  FALSE,  PARAM_BOOL,     NULL, F_MULTIFILE },
555                 { "copyonwrite", FALSE, PARAM_BOOL,     NULL, F_COPYONWRITE },
556                 { "sparse_cow", FALSE,  PARAM_BOOL,     NULL, F_SPARSE },
557                 { "sdp",        FALSE,  PARAM_BOOL,     NULL, F_SDP },
558                 { "sync",       FALSE,  PARAM_BOOL,     NULL, F_SYNC },
559                 { "listenaddr", FALSE,  PARAM_STRING,   NULL, 0 },
560         };
561         const int lp_size=sizeof(lp)/sizeof(PARAM);
562         PARAM gp[] = {
563                 { "user",       FALSE, PARAM_STRING,    &runuser,       0 },
564                 { "group",      FALSE, PARAM_STRING,    &rungroup,      0 },
565         };
566         PARAM* p=gp;
567         int p_size=sizeof(gp)/sizeof(PARAM);
568         GKeyFile *cfile;
569         GError *err = NULL;
570         const char *err_msg=NULL;
571         GQuark errdomain;
572         GArray *retval=NULL;
573         gchar **groups;
574         gboolean value;
575         gchar* startgroup;
576         gint i;
577         gint j;
578
579         errdomain = g_quark_from_string("parse_cfile");
580         cfile = g_key_file_new();
581         retval = g_array_new(FALSE, TRUE, sizeof(SERVER));
582         if(!g_key_file_load_from_file(cfile, f, G_KEY_FILE_KEEP_COMMENTS |
583                         G_KEY_FILE_KEEP_TRANSLATIONS, &err)) {
584                 g_set_error(e, errdomain, CFILE_NOTFOUND, "Could not open config file %s.", f);
585                 g_key_file_free(cfile);
586                 return retval;
587         }
588         startgroup = g_key_file_get_start_group(cfile);
589         if(!startgroup || strcmp(startgroup, "generic")) {
590                 g_set_error(e, errdomain, CFILE_MISSING_GENERIC, "Config file does not contain the [generic] group!");
591                 g_key_file_free(cfile);
592                 return NULL;
593         }
594         groups = g_key_file_get_groups(cfile, NULL);
595         for(i=0;groups[i];i++) {
596                 memset(&s, '\0', sizeof(SERVER));
597                 lp[0].target=&(s.exportname);
598                 lp[1].target=&(s.port);
599                 lp[2].target=&(s.authname);
600                 lp[3].target=&(s.expected_size);
601                 lp[4].target=&(virtstyle);
602                 lp[5].target=&(s.prerun);
603                 lp[6].target=&(s.postrun);
604                 lp[7].target=lp[8].target=lp[9].target=
605                                 lp[10].target=lp[11].target=
606                                 lp[12].target=&(s.flags);
607                 lp[13].target=&(s.listenaddr);
608
609                 /* After the [generic] group, start parsing exports */
610                 if(i==1) {
611                         p=lp;
612                         p_size=lp_size;
613                 } 
614                 for(j=0;j<p_size;j++) {
615                         g_assert(p[j].target != NULL);
616                         g_assert(p[j].ptype==PARAM_INT||p[j].ptype==PARAM_STRING||p[j].ptype==PARAM_BOOL);
617                         switch(p[j].ptype) {
618                                 case PARAM_INT:
619                                         *((gint*)p[j].target) =
620                                                 g_key_file_get_integer(cfile,
621                                                                 groups[i],
622                                                                 p[j].paramname,
623                                                                 &err);
624                                         break;
625                                 case PARAM_STRING:
626                                         *((gchar**)p[j].target) =
627                                                 g_key_file_get_string(cfile,
628                                                                 groups[i],
629                                                                 p[j].paramname,
630                                                                 &err);
631                                         break;
632                                 case PARAM_BOOL:
633                                         value = g_key_file_get_boolean(cfile,
634                                                         groups[i],
635                                                         p[j].paramname, &err);
636                                         if(!err) {
637                                                 if(value) {
638                                                         *((gint*)p[j].target) |= p[j].flagval;
639                                                 } else {
640                                                         *((gint*)p[j].target) &= ~(p[j].flagval);
641                                                 }
642                                         }
643                                         break;
644                         }
645                         if(err) {
646                                 if(err->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
647                                         if(!p[j].required) {
648                                                 /* Ignore not-found error for optional values */
649                                                 g_clear_error(&err);
650                                                 continue;
651                                         } else {
652                                                 err_msg = MISSING_REQUIRED_ERROR;
653                                         }
654                                 } else {
655                                         err_msg = DEFAULT_ERROR;
656                                 }
657                                 g_set_error(e, errdomain, CFILE_VALUE_INVALID, err_msg, p[j].paramname, groups[i], err->message);
658                                 g_array_free(retval, TRUE);
659                                 g_error_free(err);
660                                 g_key_file_free(cfile);
661                                 return NULL;
662                         }
663                 }
664                 if(virtstyle) {
665                         if(!strncmp(virtstyle, "none", 4)) {
666                                 s.virtstyle=VIRT_NONE;
667                         } else if(!strncmp(virtstyle, "ipliteral", 9)) {
668                                 s.virtstyle=VIRT_IPLIT;
669                         } else if(!strncmp(virtstyle, "iphash", 6)) {
670                                 s.virtstyle=VIRT_IPHASH;
671                         } else if(!strncmp(virtstyle, "cidrhash", 8)) {
672                                 s.virtstyle=VIRT_CIDR;
673                                 if(strlen(virtstyle)<10) {
674                                         g_set_error(e, errdomain, CFILE_VALUE_INVALID, "Invalid value %s for parameter virtstyle in group %s: missing length", virtstyle, groups[i]);
675                                         g_array_free(retval, TRUE);
676                                         g_key_file_free(cfile);
677                                         return NULL;
678                                 }
679                                 s.cidrlen=strtol(virtstyle+8, NULL, 0);
680                         } else {
681                                 g_set_error(e, errdomain, CFILE_VALUE_INVALID, "Invalid value %s for parameter virtstyle in group %s", virtstyle, groups[i]);
682                                 g_array_free(retval, TRUE);
683                                 g_key_file_free(cfile);
684                                 return NULL;
685                         }
686                 } else {
687                         s.virtstyle=VIRT_IPLIT;
688                 }
689                 /* Don't need to free this, it's not our string */
690                 virtstyle=NULL;
691                 /* Don't append values for the [generic] group */
692                 if(i>0) {
693                         if(!s.listenaddr) {
694                                 s.listenaddr = g_strdup("0.0.0.0");
695                         }
696                         g_array_append_val(retval, s);
697                 }
698 #ifndef WITH_SDP
699                 if(s.flags & F_SDP) {
700                         g_set_error(e, errdomain, CFILE_VALUE_UNSUPPORTED, "This nbd-server was built without support for SDP, yet group %s uses it", groups[i]);
701                         g_array_free(retval, TRUE);
702                         g_key_file_free(cfile);
703                         return NULL;
704                 }
705 #endif
706         }
707         if(i==1) {
708                 g_set_error(e, errdomain, CFILE_NO_EXPORTS, "The config file does not specify any exports");
709         }
710         g_key_file_free(cfile);
711         return retval;
712 }
713
714 /**
715  * Signal handler for SIGCHLD
716  * @param s the signal we're handling (must be SIGCHLD, or something
717  * is severely wrong)
718  **/
719 void sigchld_handler(int s) {
720         int status;
721         int* i;
722         pid_t pid;
723
724         while((pid=waitpid(-1, &status, WNOHANG)) > 0) {
725                 if(WIFEXITED(status)) {
726                         msg3(LOG_INFO, "Child exited with %d", WEXITSTATUS(status));
727                 }
728                 i=g_hash_table_lookup(children, &pid);
729                 if(!i) {
730                         msg3(LOG_INFO, "SIGCHLD received for an unknown child with PID %ld", (long)pid);
731                 } else {
732                         DEBUG2("Removing %d from the list of children", pid);
733                         g_hash_table_remove(children, &pid);
734                 }
735         }
736 }
737
738 /**
739  * Kill a child. Called from sigterm_handler::g_hash_table_foreach.
740  *
741  * @param key the key
742  * @param value the value corresponding to the above key
743  * @param user_data a pointer which we always set to 1, so that we know what
744  * will happen next.
745  **/
746 void killchild(gpointer key, gpointer value, gpointer user_data) {
747         pid_t *pid=value;
748         int *parent=user_data;
749
750         kill(*pid, SIGTERM);
751         *parent=1;
752 }
753
754 /**
755  * Handle SIGTERM and dispatch it to our children
756  * @param s the signal we're handling (must be SIGTERM, or something
757  * is severely wrong).
758  **/
759 void sigterm_handler(int s) {
760         int parent=0;
761
762         g_hash_table_foreach(children, killchild, &parent);
763
764         if(parent) {
765                 unlink(pidfname);
766         }
767
768         exit(EXIT_SUCCESS);
769 }
770
771 /**
772  * Detect the size of a file.
773  *
774  * @param fhandle An open filedescriptor
775  * @return the size of the file, or OFFT_MAX if detection was
776  * impossible.
777  **/
778 off_t size_autodetect(int fhandle) {
779         off_t es;
780         u64 bytes;
781         struct stat stat_buf;
782         int error;
783
784 #ifdef HAVE_SYS_MOUNT_H
785 #ifdef HAVE_SYS_IOCTL_H
786 #ifdef BLKGETSIZE64
787         DEBUG("looking for export size with ioctl BLKGETSIZE64\n");
788         if (!ioctl(fhandle, BLKGETSIZE64, bytes) && bytes) {
789                 return (off_t)bytes;
790         }
791 #endif /* BLKGETSIZE64 */
792 #endif /* HAVE_SYS_IOCTL_H */
793 #endif /* HAVE_SYS_MOUNT_H */
794
795         DEBUG("looking for fhandle size with fstat\n");
796         stat_buf.st_size = 0;
797         error = fstat(fhandle, &stat_buf);
798         if (!error) {
799                 if(stat_buf.st_size > 0)
800                         return (off_t)stat_buf.st_size;
801         } else {
802                 err("fstat failed: %m");
803         }
804
805         DEBUG("looking for fhandle size with lseek SEEK_END\n");
806         es = lseek(fhandle, (off_t)0, SEEK_END);
807         if (es > ((off_t)0)) {
808                 return es;
809         } else {
810                 DEBUG2("lseek failed: %d", errno==EBADF?1:(errno==ESPIPE?2:(errno==EINVAL?3:4)));
811         }
812
813         err("Could not find size of exported block device: %m");
814         return OFFT_MAX;
815 }
816
817 /**
818  * Get the file handle and offset, given an export offset.
819  *
820  * @param export An array of export files
821  * @param a The offset to get corresponding file/offset for
822  * @param fhandle [out] File descriptor
823  * @param foffset [out] Offset into fhandle
824  * @param maxbytes [out] Tells how many bytes can be read/written
825  * from fhandle starting at foffset (0 if there is no limit)
826  * @return 0 on success, -1 on failure
827  **/
828 int get_filepos(GArray* export, off_t a, int* fhandle, off_t* foffset, size_t* maxbytes ) {
829         /* Negative offset not allowed */
830         if(a < 0)
831                 return -1;
832
833         /* Binary search for last file with starting offset <= a */
834         FILE_INFO fi;
835         int start = 0;
836         int end = export->len - 1;
837         while( start <= end ) {
838                 int mid = (start + end) / 2;
839                 fi = g_array_index(export, FILE_INFO, mid);
840                 if( fi.startoff < a ) {
841                         start = mid + 1;
842                 } else if( fi.startoff > a ) {
843                         end = mid - 1;
844                 } else {
845                         start = end = mid;
846                         break;
847                 }
848         }
849
850         /* end should never go negative, since first startoff is 0 and a >= 0 */
851         g_assert(end >= 0);
852
853         fi = g_array_index(export, FILE_INFO, end);
854         *fhandle = fi.fhandle;
855         *foffset = a - fi.startoff;
856         *maxbytes = 0;
857         if( end+1 < export->len ) {
858                 FILE_INFO fi_next = g_array_index(export, FILE_INFO, end+1);
859                 *maxbytes = fi_next.startoff - a;
860         }
861
862         return 0;
863 }
864
865 /**
866  * seek to a position in a file, with error handling.
867  * @param handle a filedescriptor
868  * @param a position to seek to
869  * @todo get rid of this; lastpoint is a global variable right now, but it
870  * shouldn't be. If we pass it on as a parameter, that makes things a *lot*
871  * easier.
872  **/
873 void myseek(int handle,off_t a) {
874         if (lseek(handle, a, SEEK_SET) < 0) {
875                 err("Can not seek locally!\n");
876         }
877 }
878
879 /**
880  * Write an amount of bytes at a given offset to the right file. This
881  * abstracts the write-side of the multiple file option.
882  *
883  * @param a The offset where the write should start
884  * @param buf The buffer to write from
885  * @param len The length of buf
886  * @param client The client we're serving for
887  * @return The number of bytes actually written, or -1 in case of an error
888  **/
889 ssize_t rawexpwrite(off_t a, char *buf, size_t len, CLIENT *client) {
890         int fhandle;
891         off_t foffset;
892         size_t maxbytes;
893         ssize_t retval;
894
895         if(get_filepos(client->export, a, &fhandle, &foffset, &maxbytes))
896                 return -1;
897         if(maxbytes && len > maxbytes)
898                 len = maxbytes;
899
900         DEBUG4("(WRITE to fd %d offset %llu len %u), ", fhandle, foffset, len);
901
902         myseek(fhandle, foffset);
903         retval = write(fhandle, buf, len);
904         if(client->server->flags & F_SYNC) {
905                 fsync(fhandle);
906         }
907         return retval;
908 }
909
910 /**
911  * Call rawexpwrite repeatedly until all data has been written.
912  * @return 0 on success, nonzero on failure
913  **/
914 int rawexpwrite_fully(off_t a, char *buf, size_t len, CLIENT *client) {
915         ssize_t ret=0;
916
917         while(len > 0 && (ret=rawexpwrite(a, buf, len, client)) > 0 ) {
918                 a += ret;
919                 buf += ret;
920                 len -= ret;
921         }
922         return (ret < 0 || len != 0);
923 }
924
925 /**
926  * Read an amount of bytes at a given offset from the right file. This
927  * abstracts the read-side of the multiple files option.
928  *
929  * @param a The offset where the read should start
930  * @param buf A buffer to read into
931  * @param len The size of buf
932  * @param client The client we're serving for
933  * @return The number of bytes actually read, or -1 in case of an
934  * error.
935  **/
936 ssize_t rawexpread(off_t a, char *buf, size_t len, CLIENT *client) {
937         int fhandle;
938         off_t foffset;
939         size_t maxbytes;
940
941         if(get_filepos(client->export, a, &fhandle, &foffset, &maxbytes))
942                 return -1;
943         if(maxbytes && len > maxbytes)
944                 len = maxbytes;
945
946         DEBUG4("(READ from fd %d offset %llu len %u), ", fhandle, foffset, len);
947
948         myseek(fhandle, foffset);
949         return read(fhandle, buf, len);
950 }
951
952 /**
953  * Call rawexpread repeatedly until all data has been read.
954  * @return 0 on success, nonzero on failure
955  **/
956 int rawexpread_fully(off_t a, char *buf, size_t len, CLIENT *client) {
957         ssize_t ret=0;
958
959         while(len > 0 && (ret=rawexpread(a, buf, len, client)) > 0 ) {
960                 a += ret;
961                 buf += ret;
962                 len -= ret;
963         }
964         return (ret < 0 || len != 0);
965 }
966
967 /**
968  * Read an amount of bytes at a given offset from the right file. This
969  * abstracts the read-side of the copyonwrite stuff, and calls
970  * rawexpread() with the right parameters to do the actual work.
971  * @param a The offset where the read should start
972  * @param buf A buffer to read into
973  * @param len The size of buf
974  * @param client The client we're going to read for
975  * @return 0 on success, nonzero on failure
976  **/
977 int expread(off_t a, char *buf, size_t len, CLIENT *client) {
978         off_t rdlen, offset;
979         off_t mapcnt, mapl, maph, pagestart;
980
981         if (!(client->server->flags & F_COPYONWRITE))
982                 return(rawexpread_fully(a, buf, len, client));
983         DEBUG3("Asked to read %d bytes at %llu.\n", len, (unsigned long long)a);
984
985         mapl=a/DIFFPAGESIZE; maph=(a+len-1)/DIFFPAGESIZE;
986
987         for (mapcnt=mapl;mapcnt<=maph;mapcnt++) {
988                 pagestart=mapcnt*DIFFPAGESIZE;
989                 offset=a-pagestart;
990                 rdlen=(0<DIFFPAGESIZE-offset && len<(size_t)(DIFFPAGESIZE-offset)) ?
991                         len : (size_t)DIFFPAGESIZE-offset;
992                 if (client->difmap[mapcnt]!=(u32)(-1)) { /* the block is already there */
993                         DEBUG3("Page %llu is at %lu\n", (unsigned long long)mapcnt,
994                                (unsigned long)(client->difmap[mapcnt]));
995                         myseek(client->difffile, client->difmap[mapcnt]*DIFFPAGESIZE+offset);
996                         if (read(client->difffile, buf, rdlen) != rdlen) return -1;
997                 } else { /* the block is not there */
998                         DEBUG2("Page %llu is not here, we read the original one\n",
999                                (unsigned long long)mapcnt);
1000                         if(rawexpread_fully(a, buf, rdlen, client)) return -1;
1001                 }
1002                 len-=rdlen; a+=rdlen; buf+=rdlen;
1003         }
1004         return 0;
1005 }
1006
1007 /**
1008  * Write an amount of bytes at a given offset to the right file. This
1009  * abstracts the write-side of the copyonwrite option, and calls
1010  * rawexpwrite() with the right parameters to do the actual work.
1011  *
1012  * @param a The offset where the write should start
1013  * @param buf The buffer to write from
1014  * @param len The length of buf
1015  * @param client The client we're going to write for.
1016  * @return 0 on success, nonzero on failure
1017  **/
1018 int expwrite(off_t a, char *buf, size_t len, CLIENT *client) {
1019         char pagebuf[DIFFPAGESIZE];
1020         off_t mapcnt,mapl,maph;
1021         off_t wrlen,rdlen; 
1022         off_t pagestart;
1023         off_t offset;
1024
1025         if (!(client->server->flags & F_COPYONWRITE))
1026                 return(rawexpwrite_fully(a, buf, len, client)); 
1027         DEBUG3("Asked to write %d bytes at %llu.\n", len, (unsigned long long)a);
1028
1029         mapl=a/DIFFPAGESIZE ; maph=(a+len-1)/DIFFPAGESIZE ;
1030
1031         for (mapcnt=mapl;mapcnt<=maph;mapcnt++) {
1032                 pagestart=mapcnt*DIFFPAGESIZE ;
1033                 offset=a-pagestart ;
1034                 wrlen=(0<DIFFPAGESIZE-offset && len<(size_t)(DIFFPAGESIZE-offset)) ?
1035                         len : (size_t)DIFFPAGESIZE-offset;
1036
1037                 if (client->difmap[mapcnt]!=(u32)(-1)) { /* the block is already there */
1038                         DEBUG3("Page %llu is at %lu\n", (unsigned long long)mapcnt,
1039                                (unsigned long)(client->difmap[mapcnt])) ;
1040                         myseek(client->difffile,
1041                                         client->difmap[mapcnt]*DIFFPAGESIZE+offset);
1042                         if (write(client->difffile, buf, wrlen) != wrlen) return -1 ;
1043                 } else { /* the block is not there */
1044                         myseek(client->difffile,client->difffilelen*DIFFPAGESIZE) ;
1045                         client->difmap[mapcnt]=(client->server->flags&F_SPARSE)?mapcnt:client->difffilelen++;
1046                         DEBUG3("Page %llu is not here, we put it at %lu\n",
1047                                (unsigned long long)mapcnt,
1048                                (unsigned long)(client->difmap[mapcnt]));
1049                         rdlen=DIFFPAGESIZE ;
1050                         if (rawexpread_fully(pagestart, pagebuf, rdlen, client))
1051                                 return -1;
1052                         memcpy(pagebuf+offset,buf,wrlen) ;
1053                         if (write(client->difffile, pagebuf, DIFFPAGESIZE) !=
1054                                         DIFFPAGESIZE)
1055                                 return -1;
1056                 }                                                   
1057                 len-=wrlen ; a+=wrlen ; buf+=wrlen ;
1058         }
1059         return 0;
1060 }
1061
1062 /**
1063  * Do the initial negotiation.
1064  *
1065  * @param client The client we're negotiating with.
1066  **/
1067 void negotiate(CLIENT *client) {
1068         char zeros[128];
1069         u64 size_host;
1070         u32 flags = NBD_FLAG_HAS_FLAGS;
1071
1072         memset(zeros, '\0', sizeof(zeros));
1073         if (write(client->net, INIT_PASSWD, 8) < 0)
1074                 err("Negotiation failed: %m");
1075         cliserv_magic = htonll(cliserv_magic);
1076         if (write(client->net, &cliserv_magic, sizeof(cliserv_magic)) < 0)
1077                 err("Negotiation failed: %m");
1078         size_host = htonll((u64)(client->exportsize));
1079         if (write(client->net, &size_host, 8) < 0)
1080                 err("Negotiation failed: %m");
1081         if (client->server->flags & F_READONLY)
1082                 flags |= NBD_FLAG_READ_ONLY;
1083         flags = htonl(flags);
1084         if (write(client->net, &flags, 4) < 0)
1085                 err("Negotiation failed: %m");
1086         if (write(client->net, zeros, 124) < 0)
1087                 err("Negotiation failed: %m");
1088 }
1089
1090 /** sending macro. */
1091 #define SEND(net,reply) writeit( net, &reply, sizeof( reply ));
1092 /** error macro. */
1093 #define ERROR(client,reply,errcode) { reply.error = htonl(errcode); SEND(client->net,reply); reply.error = 0; }
1094 /**
1095  * Serve a file to a single client.
1096  *
1097  * @todo This beast needs to be split up in many tiny little manageable
1098  * pieces. Preferably with a chainsaw.
1099  *
1100  * @param client The client we're going to serve to.
1101  * @return when the client disconnects
1102  **/
1103 int mainloop(CLIENT *client) {
1104         struct nbd_request request;
1105         struct nbd_reply reply;
1106         gboolean go_on=TRUE;
1107 #ifdef DODBG
1108         int i = 0;
1109 #endif
1110         negotiate(client);
1111         DEBUG("Entering request loop!\n");
1112         reply.magic = htonl(NBD_REPLY_MAGIC);
1113         reply.error = 0;
1114         while (go_on) {
1115                 char buf[BUFSIZE];
1116                 size_t len;
1117 #ifdef DODBG
1118                 i++;
1119                 printf("%d: ", i);
1120 #endif
1121                 readit(client->net, &request, sizeof(request));
1122                 request.from = ntohll(request.from);
1123                 request.type = ntohl(request.type);
1124
1125                 if (request.type==NBD_CMD_DISC) {
1126                         msg2(LOG_INFO, "Disconnect request received.");
1127                         if (client->server->flags & F_COPYONWRITE) { 
1128                                 if (client->difmap) g_free(client->difmap) ;
1129                                 close(client->difffile);
1130                                 unlink(client->difffilename);
1131                                 free(client->difffilename);
1132                         }
1133                         go_on=FALSE;
1134                         continue;
1135                 }
1136
1137                 len = ntohl(request.len);
1138
1139                 if (request.magic != htonl(NBD_REQUEST_MAGIC))
1140                         err("Not enough magic.");
1141                 if (len > BUFSIZE + sizeof(struct nbd_reply))
1142                         err("Request too big!");
1143 #ifdef DODBG
1144                 printf("%s from %llu (%llu) len %d, ", request.type ? "WRITE" :
1145                                 "READ", (unsigned long long)request.from,
1146                                 (unsigned long long)request.from / 512, len);
1147 #endif
1148                 memcpy(reply.handle, request.handle, sizeof(reply.handle));
1149                 if ((request.from + len) > (OFFT_MAX)) {
1150                         DEBUG("[Number too large!]");
1151                         ERROR(client, reply, EINVAL);
1152                         continue;
1153                 }
1154
1155                 if (((ssize_t)((off_t)request.from + len) > client->exportsize)) {
1156                         DEBUG("[RANGE!]");
1157                         ERROR(client, reply, EINVAL);
1158                         continue;
1159                 }
1160
1161                 if (request.type==NBD_CMD_WRITE) {
1162                         DEBUG("wr: net->buf, ");
1163                         readit(client->net, buf, len);
1164                         DEBUG("buf->exp, ");
1165                         if ((client->server->flags & F_READONLY) ||
1166                             (client->server->flags & F_AUTOREADONLY)) {
1167                                 DEBUG("[WRITE to READONLY!]");
1168                                 ERROR(client, reply, EPERM);
1169                                 continue;
1170                         }
1171                         if (expwrite(request.from, buf, len, client)) {
1172                                 DEBUG("Write failed: %m" );
1173                                 ERROR(client, reply, errno);
1174                                 continue;
1175                         }
1176                         SEND(client->net, reply);
1177                         DEBUG("OK!\n");
1178                         continue;
1179                 }
1180                 /* READ */
1181
1182                 DEBUG("exp->buf, ");
1183                 if (expread(request.from, buf + sizeof(struct nbd_reply), len, client)) {
1184                         DEBUG("Read failed: %m");
1185                         ERROR(client, reply, errno);
1186                         continue;
1187                 }
1188
1189                 DEBUG("buf->net, ");
1190                 memcpy(buf, &reply, sizeof(struct nbd_reply));
1191                 writeit(client->net, buf, len + sizeof(struct nbd_reply));
1192                 DEBUG("OK!\n");
1193         }
1194         return 0;
1195 }
1196
1197 /**
1198  * Set up client export array, which is an array of FILE_INFO.
1199  * Also, split a single exportfile into multiple ones, if that was asked.
1200  * @param client information on the client which we want to setup export for
1201  **/
1202 void setupexport(CLIENT* client) {
1203         int i;
1204         off_t laststartoff = 0, lastsize = 0;
1205         int multifile = (client->server->flags & F_MULTIFILE);
1206
1207         client->export = g_array_new(TRUE, TRUE, sizeof(FILE_INFO));
1208
1209         /* If multi-file, open as many files as we can.
1210          * If not, open exactly one file.
1211          * Calculate file sizes as we go to get total size. */
1212         for(i=0; ; i++) {
1213                 FILE_INFO fi;
1214                 gchar *tmpname;
1215                 gchar* error_string;
1216                 mode_t mode = (client->server->flags & F_READONLY) ? O_RDONLY : O_RDWR;
1217
1218                 if(multifile) {
1219                         tmpname=g_strdup_printf("%s.%d", client->exportname, i);
1220                 } else {
1221                         tmpname=g_strdup(client->exportname);
1222                 }
1223                 DEBUG2( "Opening %s\n", tmpname );
1224                 fi.fhandle = open(tmpname, mode);
1225                 if(fi.fhandle == -1 && mode == O_RDWR) {
1226                         /* Try again because maybe media was read-only */
1227                         fi.fhandle = open(tmpname, O_RDONLY);
1228                         if(fi.fhandle != -1) {
1229                                 /* Opening the base file in copyonwrite mode is
1230                                  * okay */
1231                                 if(!(client->server->flags & F_COPYONWRITE)) {
1232                                         client->server->flags |= F_AUTOREADONLY;
1233                                         client->server->flags |= F_READONLY;
1234                                 }
1235                         }
1236                 }
1237                 if(fi.fhandle == -1) {
1238                         if(multifile && i>0)
1239                                 break;
1240                         error_string=g_strdup_printf(
1241                                 "Could not open exported file %s: %%m",
1242                                 tmpname);
1243                         err(error_string);
1244                 }
1245                 fi.startoff = laststartoff + lastsize;
1246                 g_array_append_val(client->export, fi);
1247                 g_free(tmpname);
1248
1249                 /* Starting offset and size of this file will be used to
1250                  * calculate starting offset of next file */
1251                 laststartoff = fi.startoff;
1252                 lastsize = size_autodetect(fi.fhandle);
1253
1254                 if(!multifile)
1255                         break;
1256         }
1257
1258         /* Set export size to total calculated size */
1259         client->exportsize = laststartoff + lastsize;
1260
1261         /* Export size may be overridden */
1262         if(client->server->expected_size) {
1263                 /* desired size must be <= total calculated size */
1264                 if(client->server->expected_size > client->exportsize) {
1265                         err("Size of exported file is too big\n");
1266                 }
1267
1268                 client->exportsize = client->server->expected_size;
1269         }
1270
1271         msg3(LOG_INFO, "Size of exported file/device is %llu", (unsigned long long)client->exportsize);
1272         if(multifile) {
1273                 msg3(LOG_INFO, "Total number of files: %d", i);
1274         }
1275 }
1276
1277 int copyonwrite_prepare(CLIENT* client) {
1278         off_t i;
1279         if ((client->difffilename = malloc(1024))==NULL)
1280                 err("Failed to allocate string for diff file name");
1281         snprintf(client->difffilename, 1024, "%s-%s-%d.diff",client->exportname,client->clientname,
1282                 (int)getpid()) ;
1283         client->difffilename[1023]='\0';
1284         msg3(LOG_INFO,"About to create map and diff file %s",client->difffilename) ;
1285         client->difffile=open(client->difffilename,O_RDWR | O_CREAT | O_TRUNC,0600) ;
1286         if (client->difffile<0) err("Could not create diff file (%m)") ;
1287         if ((client->difmap=calloc(client->exportsize/DIFFPAGESIZE,sizeof(u32)))==NULL)
1288                 err("Could not allocate memory") ;
1289         for (i=0;i<client->exportsize/DIFFPAGESIZE;i++) client->difmap[i]=(u32)-1 ;
1290
1291         return 0;
1292 }
1293
1294 /**
1295  * Run a command. This is used for the ``prerun'' and ``postrun'' config file
1296  * options
1297  *
1298  * @param command the command to be ran. Read from the config file
1299  * @param file the file name we're about to export
1300  **/
1301 int do_run(gchar* command, gchar* file) {
1302         gchar* cmd;
1303         int retval=0;
1304
1305         if(command && *command) {
1306                 cmd = g_strdup_printf(command, file);
1307                 retval=system(cmd);
1308                 g_free(cmd);
1309         }
1310         return retval;
1311 }
1312
1313 /**
1314  * Serve a connection. 
1315  *
1316  * @todo allow for multithreading, perhaps use libevent. Not just yet, though;
1317  * follow the road map.
1318  *
1319  * @param client a connected client
1320  **/
1321 void serveconnection(CLIENT *client) {
1322         if(do_run(client->server->prerun, client->exportname)) {
1323                 exit(EXIT_FAILURE);
1324         }
1325         setupexport(client);
1326
1327         if (client->server->flags & F_COPYONWRITE) {
1328                 copyonwrite_prepare(client);
1329         }
1330
1331         setmysockopt(client->net);
1332
1333         mainloop(client);
1334         do_run(client->server->postrun, client->exportname);
1335 }
1336
1337 /**
1338  * Find the name of the file we have to serve. This will use g_strdup_printf
1339  * to put the IP address of the client inside a filename containing
1340  * "%s" (in the form as specified by the "virtstyle" option). That name
1341  * is then written to client->exportname.
1342  *
1343  * @param net A socket connected to an nbd client
1344  * @param client information about the client. The IP address in human-readable
1345  * format will be written to a new char* buffer, the address of which will be
1346  * stored in client->clientname.
1347  **/
1348 void set_peername(int net, CLIENT *client) {
1349         struct sockaddr_in addrin;
1350         struct sockaddr_in netaddr;
1351         size_t addrinlen = sizeof( addrin );
1352         char *peername;
1353         char *netname;
1354         char *tmp;
1355         int i;
1356
1357         if (getpeername(net, (struct sockaddr *) &addrin, (socklen_t *)&addrinlen) < 0)
1358                 err("getsockname failed: %m");
1359         peername = g_strdup(inet_ntoa(addrin.sin_addr));
1360         switch(client->server->virtstyle) {
1361                 case VIRT_NONE:
1362                         client->exportname=g_strdup(client->server->exportname);
1363                         break;
1364                 case VIRT_IPHASH:
1365                         for(i=0;i<strlen(peername);i++) {
1366                                 if(peername[i]=='.') {
1367                                         peername[i]='/';
1368                                 }
1369                         }
1370                 case VIRT_IPLIT:
1371                         client->exportname=g_strdup_printf(client->server->exportname, peername);
1372                         break;
1373                 case VIRT_CIDR:
1374                         memcpy(&netaddr, &addrin, addrinlen);
1375                         netaddr.sin_addr.s_addr>>=32-(client->server->cidrlen);
1376                         netaddr.sin_addr.s_addr<<=32-(client->server->cidrlen);
1377                         netname = inet_ntoa(netaddr.sin_addr);
1378                         tmp=g_strdup_printf("%s/%s", netname, peername);
1379                         client->exportname=g_strdup_printf(client->server->exportname, tmp);
1380                         break;
1381         }
1382
1383         msg4(LOG_INFO, "connect from %s, assigned file is %s", 
1384              peername, client->exportname);
1385         client->clientname=g_strdup(peername);
1386         g_free(peername);
1387 }
1388
1389 /**
1390  * Destroy a pid_t*
1391  * @param data a pointer to pid_t which should be freed
1392  **/
1393 void destroy_pid_t(gpointer data) {
1394         g_free(data);
1395 }
1396
1397 /**
1398  * Loop through the available servers, and serve them. Never returns.
1399  **/
1400 int serveloop(GArray* servers) {
1401         struct sockaddr_in addrin;
1402         socklen_t addrinlen=sizeof(addrin);
1403         SERVER *serve;
1404         int i;
1405         int max;
1406         int sock;
1407         fd_set mset;
1408         fd_set rset;
1409
1410         /* 
1411          * Set up the master fd_set. The set of descriptors we need
1412          * to select() for never changes anyway and it buys us a *lot*
1413          * of time to only build this once. However, if we ever choose
1414          * to not fork() for clients anymore, we may have to revisit
1415          * this.
1416          */
1417         max=0;
1418         FD_ZERO(&mset);
1419         for(i=0;i<servers->len;i++) {
1420                 sock=(g_array_index(servers, SERVER, i)).socket;
1421                 FD_SET(sock, &mset);
1422                 max=sock>max?sock:max;
1423         }
1424         for(;;) {
1425                 CLIENT *client;
1426                 int net;
1427                 pid_t *pid;
1428
1429                 memcpy(&rset, &mset, sizeof(fd_set));
1430                 if(select(max+1, &rset, NULL, NULL, NULL)>0) {
1431                         DEBUG("accept, ");
1432                         for(i=0;i<servers->len;i++) {
1433                                 serve=&(g_array_index(servers, SERVER, i));
1434                                 if(FD_ISSET(serve->socket, &rset)) {
1435                                         int sock_flags;
1436                                         if ((net=accept(serve->socket, (struct sockaddr *) &addrin, &addrinlen)) < 0)
1437                                                 err("accept: %m");
1438
1439                                         if((sock_flags = fcntl(net, F_GETFL, 0))==-1) {
1440                                                 err("fcntl F_GETFL");
1441                                         }
1442                                         if(fcntl(net, F_SETFL, sock_flags &~O_NONBLOCK)==-1) {
1443                                                 err("fcntl F_SETFL ~O_NONBLOCK");
1444                                         }
1445                                         client = g_malloc(sizeof(CLIENT));
1446                                         client->server=serve;
1447                                         client->exportsize=OFFT_MAX;
1448                                         client->net=net;
1449                                         set_peername(net, client);
1450                                         if (!authorized_client(client)) {
1451                                                 msg2(LOG_INFO,"Unauthorized client") ;
1452                                                 close(net);
1453                                                 continue;
1454                                         }
1455                                         msg2(LOG_INFO,"Authorized client") ;
1456                                         pid=g_malloc(sizeof(pid_t));
1457 #ifndef NOFORK
1458                                         if ((*pid=fork())<0) {
1459                                                 msg3(LOG_INFO,"Could not fork (%s)",strerror(errno)) ;
1460                                                 close(net);
1461                                                 continue;
1462                                         }
1463                                         if (*pid>0) { /* parent */
1464                                                 close(net);
1465                                                 g_hash_table_insert(children, pid, pid);
1466                                                 continue;
1467                                         }
1468                                         /* child */
1469                                         g_hash_table_destroy(children);
1470                                         for(i=0;i<servers->len;i++) {
1471                                                 serve=&g_array_index(servers, SERVER, i);
1472                                                 close(serve->socket);
1473                                         }
1474                                         /* FALSE does not free the
1475                                         actual data. This is required,
1476                                         because the client has a
1477                                         direct reference into that
1478                                         data, and otherwise we get a
1479                                         segfault... */
1480                                         g_array_free(servers, FALSE);
1481 #endif // NOFORK
1482                                         msg2(LOG_INFO,"Starting to serve");
1483                                         serveconnection(client);
1484                                         exit(EXIT_SUCCESS);
1485                                 }
1486                         }
1487                 }
1488         }
1489 }
1490
1491 /**
1492  * Connect a server's socket.
1493  *
1494  * @param serve the server we want to connect.
1495  **/
1496 void setup_serve(SERVER *serve) {
1497         struct sockaddr_in addrin;
1498         struct sigaction sa;
1499         int addrinlen = sizeof(addrin);
1500         int sock_flags;
1501         int af;
1502 #ifndef sun
1503         int yes=1;
1504 #else
1505         char yes='1';
1506 #endif /* sun */
1507
1508         af = AF_INET;
1509 #ifdef WITH_SDP
1510         if ((serve->flags) && F_SDP) {
1511                 af = AF_INET_SDP;
1512         }
1513 #endif
1514         if ((serve->socket = socket(af, SOCK_STREAM, IPPROTO_TCP)) < 0)
1515                 err("socket: %m");
1516
1517         /* lose the pesky "Address already in use" error message */
1518         if (setsockopt(serve->socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
1519                 err("setsockopt SO_REUSEADDR");
1520         }
1521         if (setsockopt(serve->socket,SOL_SOCKET,SO_KEEPALIVE,&yes,sizeof(int)) == -1) {
1522                 err("setsockopt SO_KEEPALIVE");
1523         }
1524
1525         /* make the listening socket non-blocking */
1526         if ((sock_flags = fcntl(serve->socket, F_GETFL, 0)) == -1) {
1527                 err("fcntl F_GETFL");
1528         }
1529         if (fcntl(serve->socket, F_SETFL, sock_flags | O_NONBLOCK) == -1) {
1530                 err("fcntl F_SETFL O_NONBLOCK");
1531         }
1532
1533         DEBUG("Waiting for connections... bind, ");
1534         addrin.sin_family = AF_INET;
1535 #ifdef WITH_SDP
1536         if(serve->flags & F_SDP) {
1537                 addrin.sin_family = AF_INET_SDP;
1538         }
1539 #endif
1540         addrin.sin_port = htons(serve->port);
1541         if(!inet_aton(serve->listenaddr, &(addrin.sin_addr)))
1542                 err("could not parse listen address");
1543         if (bind(serve->socket, (struct sockaddr *) &addrin, addrinlen) < 0)
1544                 err("bind: %m");
1545         DEBUG("listen, ");
1546         if (listen(serve->socket, 1) < 0)
1547                 err("listen: %m");
1548         sa.sa_handler = sigchld_handler;
1549         sigemptyset(&sa.sa_mask);
1550         sa.sa_flags = SA_RESTART;
1551         if(sigaction(SIGCHLD, &sa, NULL) == -1)
1552                 err("sigaction: %m");
1553         sa.sa_handler = sigterm_handler;
1554         sigemptyset(&sa.sa_mask);
1555         sa.sa_flags = SA_RESTART;
1556         if(sigaction(SIGTERM, &sa, NULL) == -1)
1557                 err("sigaction: %m");
1558 }
1559
1560 /**
1561  * Connect our servers.
1562  **/
1563 void setup_servers(GArray* servers) {
1564         int i;
1565
1566         for(i=0;i<servers->len;i++) {
1567                 setup_serve(&(g_array_index(servers, SERVER, i)));
1568         }
1569         children=g_hash_table_new_full(g_int_hash, g_int_equal, NULL, destroy_pid_t);
1570 }
1571
1572 /**
1573  * Go daemon (unless we specified at compile time that we didn't want this)
1574  * @param serve the first server of our configuration. If its port is zero,
1575  *      then do not daemonize, because we're doing inetd then. This parameter
1576  *      is only used to create a PID file of the form
1577  *      /var/run/nbd-server.&lt;port&gt;.pid; it's not modified in any way.
1578  **/
1579 #if !defined(NODAEMON) && !defined(NOFORK)
1580 void daemonize(SERVER* serve) {
1581         FILE*pidf;
1582
1583         if(serve && !(serve->port)) {
1584                 return;
1585         }
1586         if(daemon(0,0)<0) {
1587                 err("daemon");
1588         }
1589         if(!*pidftemplate) {
1590                 if(serve) {
1591                         strncpy(pidftemplate, "/var/run/nbd-server.%d.pid", 255);
1592                 } else {
1593                         strncpy(pidftemplate, "/var/run/nbd-server.pid", 255);
1594                 }
1595         }
1596         snprintf(pidfname, 255, pidftemplate, serve ? serve->port : 0);
1597         pidf=fopen(pidfname, "w");
1598         if(pidf) {
1599                 fprintf(pidf,"%d\n", (int)getpid());
1600                 fclose(pidf);
1601         } else {
1602                 perror("fopen");
1603                 fprintf(stderr, "Not fatal; continuing");
1604         }
1605 }
1606 #else
1607 #define daemonize(serve)
1608 #endif /* !defined(NODAEMON) && !defined(NOFORK) */
1609
1610 /*
1611  * Everything beyond this point (in the file) is run in non-daemon mode.
1612  * The stuff above daemonize() isn't.
1613  */
1614
1615 void serve_err(SERVER* serve, const char* msg) G_GNUC_NORETURN;
1616
1617 void serve_err(SERVER* serve, const char* msg) {
1618         g_message("Export of %s on port %d failed:", serve->exportname,
1619                         serve->port);
1620         err(msg);
1621 }
1622
1623 /**
1624  * Set up user-ID and/or group-ID
1625  **/
1626 void dousers(void) {
1627         struct passwd *pw;
1628         struct group *gr;
1629         gchar* str;
1630         if(rungroup) {
1631                 gr=getgrnam(rungroup);
1632                 if(!gr) {
1633                         str = g_strdup_printf("Invalid group name: %s", rungroup);
1634                         err(str);
1635                 }
1636                 if(setgid(gr->gr_gid)<0) {
1637                         err("Could not set GID: %m"); 
1638                 }
1639         }
1640         if(runuser) {
1641                 pw=getpwnam(runuser);
1642                 if(!pw) {
1643                         str = g_strdup_printf("Invalid user name: %s", runuser);
1644                         err(str);
1645                 }
1646                 if(setuid(pw->pw_uid)<0) {
1647                         err("Could not set UID: %m");
1648                 }
1649         }
1650 }
1651
1652 #ifndef ISSERVER
1653 void glib_message_syslog_redirect(const gchar *log_domain,
1654                                   GLogLevelFlags log_level,
1655                                   const gchar *message,
1656                                   gpointer user_data)
1657 {
1658     int level=LOG_DEBUG;
1659     
1660     switch( log_level )
1661     {
1662       case G_LOG_FLAG_FATAL:
1663       case G_LOG_LEVEL_CRITICAL:
1664       case G_LOG_LEVEL_ERROR:    
1665         level=LOG_ERR; 
1666         break;
1667       case G_LOG_LEVEL_WARNING:
1668         level=LOG_WARNING;
1669         break;
1670       case G_LOG_LEVEL_MESSAGE:
1671       case G_LOG_LEVEL_INFO:
1672         level=LOG_INFO;
1673         break;
1674       case G_LOG_LEVEL_DEBUG:
1675         level=LOG_DEBUG;
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 }