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