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