Fix memleak
[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 = serve->socket;
603         serve->socket_family = serve->socket_family;
604         serve->cidrlen = s->cidrlen;
605
606         if(s->prerun)
607                 serve->prerun = g_strdup(s->prerun);
608
609         if(s->postrun)
610                 serve->postrun = g_strdup(s->postrun);
611         
612         if(s->servename)
613                 serve->servename = g_strdup(s->servename);
614
615         serve->max_connections = s->max_connections;
616
617         return serve;
618 }
619
620 /**
621  * append new server to array
622  * @param s server
623  * @param a server array
624  * @return 0 success, -1 error
625  */
626 int append_serve(SERVER *s, GArray *a) {
627         SERVER *ns = NULL;
628         struct addrinfo hints;
629         struct addrinfo *ai = NULL;
630         struct addrinfo *rp = NULL;
631         char   host[NI_MAXHOST];
632         gchar  *port = NULL;
633         int e;
634         int ret;
635
636         if(!s) {
637                 err("Invalid parsing server");
638                 return -1;
639         }
640
641         port = g_strdup_printf("%d", s->port);
642
643         memset(&hints,'\0',sizeof(hints));
644         hints.ai_family = AF_UNSPEC;
645         hints.ai_socktype = SOCK_STREAM;
646         hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
647         hints.ai_protocol = IPPROTO_TCP;
648
649         e = getaddrinfo(s->listenaddr, port, &hints, &ai);
650
651         if (port)
652                 g_free(port);
653
654         if(e == 0) {
655                 for (rp = ai; rp != NULL; rp = rp->ai_next) {
656                         e = getnameinfo(rp->ai_addr, rp->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
657
658                         if (e != 0) { // error
659                                 fprintf(stderr, "getnameinfo: %s\n", gai_strerror(e));
660                                 continue;
661                         }
662
663                         // duplicate server and set listenaddr to resolved IP address
664                         ns = dup_serve (s);
665                         if (ns) {
666                                 ns->listenaddr = g_strdup(host);
667                                 ns->socket_family = rp->ai_family;
668                                 g_array_append_val(a, *ns);
669                                 free(ns);
670                                 ns = NULL;
671                         }
672                 }
673
674                 ret = 0;
675         } else {
676                 fprintf(stderr, "getaddrinfo failed on listen host/address: %s (%s)\n", s->listenaddr ? s->listenaddr : "any", gai_strerror(e));
677                 ret = -1;
678         }
679
680         if (ai)
681                 freeaddrinfo(ai);
682
683         return ret;
684 }
685
686 /**
687  * Parse the config file.
688  *
689  * @param f the name of the config file
690  * @param e a GError. @see CFILE_ERRORS for what error values this function can
691  *      return.
692  * @return a Array of SERVER* pointers, If the config file is empty or does not
693  *      exist, returns an empty GHashTable; if the config file contains an
694  *      error, returns NULL, and e is set appropriately
695  **/
696 GArray* parse_cfile(gchar* f, GError** e) {
697         const char* DEFAULT_ERROR = "Could not parse %s in group %s: %s";
698         const char* MISSING_REQUIRED_ERROR = "Could not find required value %s in group %s: %s";
699         SERVER s;
700         gchar *virtstyle=NULL;
701         PARAM lp[] = {
702                 { "exportname", TRUE,   PARAM_STRING,   NULL, 0 },
703                 { "port",       TRUE,   PARAM_INT,      NULL, 0 },
704                 { "authfile",   FALSE,  PARAM_STRING,   NULL, 0 },
705                 { "filesize",   FALSE,  PARAM_INT,      NULL, 0 },
706                 { "virtstyle",  FALSE,  PARAM_STRING,   NULL, 0 },
707                 { "prerun",     FALSE,  PARAM_STRING,   NULL, 0 },
708                 { "postrun",    FALSE,  PARAM_STRING,   NULL, 0 },
709                 { "readonly",   FALSE,  PARAM_BOOL,     NULL, F_READONLY },
710                 { "multifile",  FALSE,  PARAM_BOOL,     NULL, F_MULTIFILE },
711                 { "copyonwrite", FALSE, PARAM_BOOL,     NULL, F_COPYONWRITE },
712                 { "sparse_cow", FALSE,  PARAM_BOOL,     NULL, F_SPARSE },
713                 { "sdp",        FALSE,  PARAM_BOOL,     NULL, F_SDP },
714                 { "sync",       FALSE,  PARAM_BOOL,     NULL, F_SYNC },
715                 { "listenaddr", FALSE,  PARAM_STRING,   NULL, 0 },
716                 { "maxconnections", FALSE, PARAM_INT,   NULL, 0 },
717         };
718         const int lp_size=sizeof(lp)/sizeof(PARAM);
719         PARAM gp[] = {
720                 { "user",       FALSE, PARAM_STRING,    &runuser,       0 },
721                 { "group",      FALSE, PARAM_STRING,    &rungroup,      0 },
722                 { "oldstyle",   FALSE, PARAM_BOOL,      &do_oldstyle,   1 },
723                 { "listenaddr", FALSE, PARAM_STRING,    &modern_listen, 0 },
724         };
725         PARAM* p=gp;
726         int p_size=sizeof(gp)/sizeof(PARAM);
727         GKeyFile *cfile;
728         GError *err = NULL;
729         const char *err_msg=NULL;
730         GQuark errdomain;
731         GArray *retval=NULL;
732         gchar **groups;
733         gboolean value;
734         gchar* startgroup;
735         gint i;
736         gint j;
737
738         errdomain = g_quark_from_string("parse_cfile");
739         cfile = g_key_file_new();
740         retval = g_array_new(FALSE, TRUE, sizeof(SERVER));
741         if(!g_key_file_load_from_file(cfile, f, G_KEY_FILE_KEEP_COMMENTS |
742                         G_KEY_FILE_KEEP_TRANSLATIONS, &err)) {
743                 g_set_error(e, errdomain, CFILE_NOTFOUND, "Could not open config file %s.", f);
744                 g_key_file_free(cfile);
745                 return retval;
746         }
747         startgroup = g_key_file_get_start_group(cfile);
748         if(!startgroup || strcmp(startgroup, "generic")) {
749                 g_set_error(e, errdomain, CFILE_MISSING_GENERIC, "Config file does not contain the [generic] group!");
750                 g_key_file_free(cfile);
751                 return NULL;
752         }
753         groups = g_key_file_get_groups(cfile, NULL);
754         for(i=0;groups[i];i++) {
755                 memset(&s, '\0', sizeof(SERVER));
756                 lp[0].target=&(s.exportname);
757                 lp[1].target=&(s.port);
758                 lp[2].target=&(s.authname);
759                 lp[3].target=&(s.expected_size);
760                 lp[4].target=&(virtstyle);
761                 lp[5].target=&(s.prerun);
762                 lp[6].target=&(s.postrun);
763                 lp[7].target=lp[8].target=lp[9].target=
764                                 lp[10].target=lp[11].target=
765                                 lp[12].target=&(s.flags);
766                 lp[13].target=&(s.listenaddr);
767                 lp[14].target=&(s.max_connections);
768
769                 /* After the [generic] group, start parsing exports */
770                 if(i==1) {
771                         p=lp;
772                         p_size=lp_size;
773                 } 
774                 for(j=0;j<p_size;j++) {
775                         g_assert(p[j].target != NULL);
776                         g_assert(p[j].ptype==PARAM_INT||p[j].ptype==PARAM_STRING||p[j].ptype==PARAM_BOOL);
777                         switch(p[j].ptype) {
778                                 case PARAM_INT:
779                                         *((gint*)p[j].target) =
780                                                 g_key_file_get_integer(cfile,
781                                                                 groups[i],
782                                                                 p[j].paramname,
783                                                                 &err);
784                                         break;
785                                 case PARAM_STRING:
786                                         *((gchar**)p[j].target) =
787                                                 g_key_file_get_string(cfile,
788                                                                 groups[i],
789                                                                 p[j].paramname,
790                                                                 &err);
791                                         break;
792                                 case PARAM_BOOL:
793                                         value = g_key_file_get_boolean(cfile,
794                                                         groups[i],
795                                                         p[j].paramname, &err);
796                                         if(!err) {
797                                                 if(value) {
798                                                         *((gint*)p[j].target) |= p[j].flagval;
799                                                 } else {
800                                                         *((gint*)p[j].target) &= ~(p[j].flagval);
801                                                 }
802                                         }
803                                         break;
804                         }
805                         if(!strcmp(p[j].paramname, "port") && !strcmp(p[j].target, NBD_DEFAULT_PORT)) {
806                                 g_set_error(e, errdomain, CFILE_INCORRECT_PORT, "Config file specifies default port for oldstyle export");
807                                 g_key_file_free(cfile);
808                                 return NULL;
809                         }
810                         if(err) {
811                                 if(err->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
812                                         if(!p[j].required) {
813                                                 /* Ignore not-found error for optional values */
814                                                 g_clear_error(&err);
815                                                 continue;
816                                         } else {
817                                                 err_msg = MISSING_REQUIRED_ERROR;
818                                         }
819                                 } else {
820                                         err_msg = DEFAULT_ERROR;
821                                 }
822                                 g_set_error(e, errdomain, CFILE_VALUE_INVALID, err_msg, p[j].paramname, groups[i], err->message);
823                                 g_array_free(retval, TRUE);
824                                 g_error_free(err);
825                                 g_key_file_free(cfile);
826                                 return NULL;
827                         }
828                 }
829                 if(virtstyle) {
830                         if(!strncmp(virtstyle, "none", 4)) {
831                                 s.virtstyle=VIRT_NONE;
832                         } else if(!strncmp(virtstyle, "ipliteral", 9)) {
833                                 s.virtstyle=VIRT_IPLIT;
834                         } else if(!strncmp(virtstyle, "iphash", 6)) {
835                                 s.virtstyle=VIRT_IPHASH;
836                         } else if(!strncmp(virtstyle, "cidrhash", 8)) {
837                                 s.virtstyle=VIRT_CIDR;
838                                 if(strlen(virtstyle)<10) {
839                                         g_set_error(e, errdomain, CFILE_VALUE_INVALID, "Invalid value %s for parameter virtstyle in group %s: missing length", virtstyle, groups[i]);
840                                         g_array_free(retval, TRUE);
841                                         g_key_file_free(cfile);
842                                         return NULL;
843                                 }
844                                 s.cidrlen=strtol(virtstyle+8, NULL, 0);
845                         } else {
846                                 g_set_error(e, errdomain, CFILE_VALUE_INVALID, "Invalid value %s for parameter virtstyle in group %s", virtstyle, groups[i]);
847                                 g_array_free(retval, TRUE);
848                                 g_key_file_free(cfile);
849                                 return NULL;
850                         }
851                         if(s.port && !do_oldstyle) {
852                                 g_warning("A port was specified, but oldstyle exports were not requested. This may not do what you expect.");
853                                 g_warning("Please read 'man 5 nbd-server' and search for oldstyle for more info");
854                         }
855                 } else {
856                         s.virtstyle=VIRT_IPLIT;
857                 }
858                 /* Don't need to free this, it's not our string */
859                 virtstyle=NULL;
860                 /* Don't append values for the [generic] group */
861                 if(i>0) {
862                         s.socket_family = AF_UNSPEC;
863                         s.servename = groups[i];
864
865                         append_serve(&s, retval);
866                 } else {
867                         if(!do_oldstyle) {
868                                 lp[1].required = 0;
869                         }
870                 }
871 #ifndef WITH_SDP
872                 if(s.flags & F_SDP) {
873                         g_set_error(e, errdomain, CFILE_VALUE_UNSUPPORTED, "This nbd-server was built without support for SDP, yet group %s uses it", groups[i]);
874                         g_array_free(retval, TRUE);
875                         g_key_file_free(cfile);
876                         return NULL;
877                 }
878 #endif
879         }
880         if(i==1) {
881                 g_set_error(e, errdomain, CFILE_NO_EXPORTS, "The config file does not specify any exports");
882         }
883         g_key_file_free(cfile);
884         return retval;
885 }
886
887 /**
888  * Signal handler for SIGCHLD
889  * @param s the signal we're handling (must be SIGCHLD, or something
890  * is severely wrong)
891  **/
892 void sigchld_handler(int s) {
893         int status;
894         int* i;
895         pid_t pid;
896
897         while((pid=waitpid(-1, &status, WNOHANG)) > 0) {
898                 if(WIFEXITED(status)) {
899                         msg3(LOG_INFO, "Child exited with %d", WEXITSTATUS(status));
900                 }
901                 i=g_hash_table_lookup(children, &pid);
902                 if(!i) {
903                         msg3(LOG_INFO, "SIGCHLD received for an unknown child with PID %ld", (long)pid);
904                 } else {
905                         DEBUG2("Removing %d from the list of children", pid);
906                         g_hash_table_remove(children, &pid);
907                 }
908         }
909 }
910
911 /**
912  * Kill a child. Called from sigterm_handler::g_hash_table_foreach.
913  *
914  * @param key the key
915  * @param value the value corresponding to the above key
916  * @param user_data a pointer which we always set to 1, so that we know what
917  * will happen next.
918  **/
919 void killchild(gpointer key, gpointer value, gpointer user_data) {
920         pid_t *pid=value;
921         int *parent=user_data;
922
923         kill(*pid, SIGTERM);
924         *parent=1;
925 }
926
927 /**
928  * Handle SIGTERM and dispatch it to our children
929  * @param s the signal we're handling (must be SIGTERM, or something
930  * is severely wrong).
931  **/
932 void sigterm_handler(int s) {
933         int parent=0;
934
935         g_hash_table_foreach(children, killchild, &parent);
936
937         if(parent) {
938                 unlink(pidfname);
939         }
940
941         exit(EXIT_SUCCESS);
942 }
943
944 /**
945  * Detect the size of a file.
946  *
947  * @param fhandle An open filedescriptor
948  * @return the size of the file, or OFFT_MAX if detection was
949  * impossible.
950  **/
951 off_t size_autodetect(int fhandle) {
952         off_t es;
953         u64 bytes;
954         struct stat stat_buf;
955         int error;
956
957 #ifdef HAVE_SYS_MOUNT_H
958 #ifdef HAVE_SYS_IOCTL_H
959 #ifdef BLKGETSIZE64
960         DEBUG("looking for export size with ioctl BLKGETSIZE64\n");
961         if (!ioctl(fhandle, BLKGETSIZE64, &bytes) && bytes) {
962                 return (off_t)bytes;
963         }
964 #endif /* BLKGETSIZE64 */
965 #endif /* HAVE_SYS_IOCTL_H */
966 #endif /* HAVE_SYS_MOUNT_H */
967
968         DEBUG("looking for fhandle size with fstat\n");
969         stat_buf.st_size = 0;
970         error = fstat(fhandle, &stat_buf);
971         if (!error) {
972                 if(stat_buf.st_size > 0)
973                         return (off_t)stat_buf.st_size;
974         } else {
975                 err("fstat failed: %m");
976         }
977
978         DEBUG("looking for fhandle size with lseek SEEK_END\n");
979         es = lseek(fhandle, (off_t)0, SEEK_END);
980         if (es > ((off_t)0)) {
981                 return es;
982         } else {
983                 DEBUG2("lseek failed: %d", errno==EBADF?1:(errno==ESPIPE?2:(errno==EINVAL?3:4)));
984         }
985
986         err("Could not find size of exported block device: %m");
987         return OFFT_MAX;
988 }
989
990 /**
991  * Get the file handle and offset, given an export offset.
992  *
993  * @param export An array of export files
994  * @param a The offset to get corresponding file/offset for
995  * @param fhandle [out] File descriptor
996  * @param foffset [out] Offset into fhandle
997  * @param maxbytes [out] Tells how many bytes can be read/written
998  * from fhandle starting at foffset (0 if there is no limit)
999  * @return 0 on success, -1 on failure
1000  **/
1001 int get_filepos(GArray* export, off_t a, int* fhandle, off_t* foffset, size_t* maxbytes ) {
1002         /* Negative offset not allowed */
1003         if(a < 0)
1004                 return -1;
1005
1006         /* Binary search for last file with starting offset <= a */
1007         FILE_INFO fi;
1008         int start = 0;
1009         int end = export->len - 1;
1010         while( start <= end ) {
1011                 int mid = (start + end) / 2;
1012                 fi = g_array_index(export, FILE_INFO, mid);
1013                 if( fi.startoff < a ) {
1014                         start = mid + 1;
1015                 } else if( fi.startoff > a ) {
1016                         end = mid - 1;
1017                 } else {
1018                         start = end = mid;
1019                         break;
1020                 }
1021         }
1022
1023         /* end should never go negative, since first startoff is 0 and a >= 0 */
1024         g_assert(end >= 0);
1025
1026         fi = g_array_index(export, FILE_INFO, end);
1027         *fhandle = fi.fhandle;
1028         *foffset = a - fi.startoff;
1029         *maxbytes = 0;
1030         if( end+1 < export->len ) {
1031                 FILE_INFO fi_next = g_array_index(export, FILE_INFO, end+1);
1032                 *maxbytes = fi_next.startoff - a;
1033         }
1034
1035         return 0;
1036 }
1037
1038 /**
1039  * seek to a position in a file, with error handling.
1040  * @param handle a filedescriptor
1041  * @param a position to seek to
1042  * @todo get rid of this; lastpoint is a global variable right now, but it
1043  * shouldn't be. If we pass it on as a parameter, that makes things a *lot*
1044  * easier.
1045  **/
1046 void myseek(int handle,off_t a) {
1047         if (lseek(handle, a, SEEK_SET) < 0) {
1048                 err("Can not seek locally!\n");
1049         }
1050 }
1051
1052 /**
1053  * Write an amount of bytes at a given offset to the right file. This
1054  * abstracts the write-side of the multiple file option.
1055  *
1056  * @param a The offset where the write should start
1057  * @param buf The buffer to write from
1058  * @param len The length of buf
1059  * @param client The client we're serving for
1060  * @return The number of bytes actually written, or -1 in case of an error
1061  **/
1062 ssize_t rawexpwrite(off_t a, char *buf, size_t len, CLIENT *client) {
1063         int fhandle;
1064         off_t foffset;
1065         size_t maxbytes;
1066         ssize_t retval;
1067
1068         if(get_filepos(client->export, a, &fhandle, &foffset, &maxbytes))
1069                 return -1;
1070         if(maxbytes && len > maxbytes)
1071                 len = maxbytes;
1072
1073         DEBUG4("(WRITE to fd %d offset %llu len %u), ", fhandle, foffset, len);
1074
1075         myseek(fhandle, foffset);
1076         retval = write(fhandle, buf, len);
1077         if(client->server->flags & F_SYNC) {
1078                 fsync(fhandle);
1079         }
1080         return retval;
1081 }
1082
1083 /**
1084  * Call rawexpwrite repeatedly until all data has been written.
1085  * @return 0 on success, nonzero on failure
1086  **/
1087 int rawexpwrite_fully(off_t a, char *buf, size_t len, CLIENT *client) {
1088         ssize_t ret=0;
1089
1090         while(len > 0 && (ret=rawexpwrite(a, buf, len, client)) > 0 ) {
1091                 a += ret;
1092                 buf += ret;
1093                 len -= ret;
1094         }
1095         return (ret < 0 || len != 0);
1096 }
1097
1098 /**
1099  * Read an amount of bytes at a given offset from the right file. This
1100  * abstracts the read-side of the multiple files option.
1101  *
1102  * @param a The offset where the read should start
1103  * @param buf A buffer to read into
1104  * @param len The size of buf
1105  * @param client The client we're serving for
1106  * @return The number of bytes actually read, or -1 in case of an
1107  * error.
1108  **/
1109 ssize_t rawexpread(off_t a, char *buf, size_t len, CLIENT *client) {
1110         int fhandle;
1111         off_t foffset;
1112         size_t maxbytes;
1113
1114         if(get_filepos(client->export, a, &fhandle, &foffset, &maxbytes))
1115                 return -1;
1116         if(maxbytes && len > maxbytes)
1117                 len = maxbytes;
1118
1119         DEBUG4("(READ from fd %d offset %llu len %u), ", fhandle, foffset, len);
1120
1121         myseek(fhandle, foffset);
1122         return read(fhandle, buf, len);
1123 }
1124
1125 /**
1126  * Call rawexpread repeatedly until all data has been read.
1127  * @return 0 on success, nonzero on failure
1128  **/
1129 int rawexpread_fully(off_t a, char *buf, size_t len, CLIENT *client) {
1130         ssize_t ret=0;
1131
1132         while(len > 0 && (ret=rawexpread(a, buf, len, client)) > 0 ) {
1133                 a += ret;
1134                 buf += ret;
1135                 len -= ret;
1136         }
1137         return (ret < 0 || len != 0);
1138 }
1139
1140 /**
1141  * Read an amount of bytes at a given offset from the right file. This
1142  * abstracts the read-side of the copyonwrite stuff, and calls
1143  * rawexpread() with the right parameters to do the actual work.
1144  * @param a The offset where the read should start
1145  * @param buf A buffer to read into
1146  * @param len The size of buf
1147  * @param client The client we're going to read for
1148  * @return 0 on success, nonzero on failure
1149  **/
1150 int expread(off_t a, char *buf, size_t len, CLIENT *client) {
1151         off_t rdlen, offset;
1152         off_t mapcnt, mapl, maph, pagestart;
1153
1154         if (!(client->server->flags & F_COPYONWRITE))
1155                 return(rawexpread_fully(a, buf, len, client));
1156         DEBUG3("Asked to read %d bytes at %llu.\n", len, (unsigned long long)a);
1157
1158         mapl=a/DIFFPAGESIZE; maph=(a+len-1)/DIFFPAGESIZE;
1159
1160         for (mapcnt=mapl;mapcnt<=maph;mapcnt++) {
1161                 pagestart=mapcnt*DIFFPAGESIZE;
1162                 offset=a-pagestart;
1163                 rdlen=(0<DIFFPAGESIZE-offset && len<(size_t)(DIFFPAGESIZE-offset)) ?
1164                         len : (size_t)DIFFPAGESIZE-offset;
1165                 if (client->difmap[mapcnt]!=(u32)(-1)) { /* the block is already there */
1166                         DEBUG3("Page %llu is at %lu\n", (unsigned long long)mapcnt,
1167                                (unsigned long)(client->difmap[mapcnt]));
1168                         myseek(client->difffile, client->difmap[mapcnt]*DIFFPAGESIZE+offset);
1169                         if (read(client->difffile, buf, rdlen) != rdlen) return -1;
1170                 } else { /* the block is not there */
1171                         DEBUG2("Page %llu is not here, we read the original one\n",
1172                                (unsigned long long)mapcnt);
1173                         if(rawexpread_fully(a, buf, rdlen, client)) return -1;
1174                 }
1175                 len-=rdlen; a+=rdlen; buf+=rdlen;
1176         }
1177         return 0;
1178 }
1179
1180 /**
1181  * Write an amount of bytes at a given offset to the right file. This
1182  * abstracts the write-side of the copyonwrite option, and calls
1183  * rawexpwrite() with the right parameters to do the actual work.
1184  *
1185  * @param a The offset where the write should start
1186  * @param buf The buffer to write from
1187  * @param len The length of buf
1188  * @param client The client we're going to write for.
1189  * @return 0 on success, nonzero on failure
1190  **/
1191 int expwrite(off_t a, char *buf, size_t len, CLIENT *client) {
1192         char pagebuf[DIFFPAGESIZE];
1193         off_t mapcnt,mapl,maph;
1194         off_t wrlen,rdlen; 
1195         off_t pagestart;
1196         off_t offset;
1197
1198         if (!(client->server->flags & F_COPYONWRITE))
1199                 return(rawexpwrite_fully(a, buf, len, client)); 
1200         DEBUG3("Asked to write %d bytes at %llu.\n", len, (unsigned long long)a);
1201
1202         mapl=a/DIFFPAGESIZE ; maph=(a+len-1)/DIFFPAGESIZE ;
1203
1204         for (mapcnt=mapl;mapcnt<=maph;mapcnt++) {
1205                 pagestart=mapcnt*DIFFPAGESIZE ;
1206                 offset=a-pagestart ;
1207                 wrlen=(0<DIFFPAGESIZE-offset && len<(size_t)(DIFFPAGESIZE-offset)) ?
1208                         len : (size_t)DIFFPAGESIZE-offset;
1209
1210                 if (client->difmap[mapcnt]!=(u32)(-1)) { /* the block is already there */
1211                         DEBUG3("Page %llu is at %lu\n", (unsigned long long)mapcnt,
1212                                (unsigned long)(client->difmap[mapcnt])) ;
1213                         myseek(client->difffile,
1214                                         client->difmap[mapcnt]*DIFFPAGESIZE+offset);
1215                         if (write(client->difffile, buf, wrlen) != wrlen) return -1 ;
1216                 } else { /* the block is not there */
1217                         myseek(client->difffile,client->difffilelen*DIFFPAGESIZE) ;
1218                         client->difmap[mapcnt]=(client->server->flags&F_SPARSE)?mapcnt:client->difffilelen++;
1219                         DEBUG3("Page %llu is not here, we put it at %lu\n",
1220                                (unsigned long long)mapcnt,
1221                                (unsigned long)(client->difmap[mapcnt]));
1222                         rdlen=DIFFPAGESIZE ;
1223                         if (rawexpread_fully(pagestart, pagebuf, rdlen, client))
1224                                 return -1;
1225                         memcpy(pagebuf+offset,buf,wrlen) ;
1226                         if (write(client->difffile, pagebuf, DIFFPAGESIZE) !=
1227                                         DIFFPAGESIZE)
1228                                 return -1;
1229                 }                                                   
1230                 len-=wrlen ; a+=wrlen ; buf+=wrlen ;
1231         }
1232         return 0;
1233 }
1234
1235 /**
1236  * Do the initial negotiation.
1237  *
1238  * @param client The client we're negotiating with.
1239  **/
1240 CLIENT* negotiate(int net, CLIENT *client, GArray* servers) {
1241         char zeros[128];
1242         uint64_t size_host;
1243         uint32_t flags = NBD_FLAG_HAS_FLAGS;
1244         uint16_t smallflags = 0;
1245         uint64_t magic;
1246
1247         memset(zeros, '\0', sizeof(zeros));
1248         if(!client || !client->modern) {
1249                 /* common */
1250                 if (write(net, INIT_PASSWD, 8) < 0) {
1251                         err_nonfatal("Negotiation failed: %m");
1252                         if(client)
1253                                 exit(EXIT_FAILURE);
1254                 }
1255                 if(!client || client->modern) {
1256                         /* modern */
1257                         magic = htonll(opts_magic);
1258                 } else {
1259                         /* oldstyle */
1260                         magic = htonll(cliserv_magic);
1261                 }
1262                 if (write(net, &magic, sizeof(magic)) < 0) {
1263                         err_nonfatal("Negotiation failed: %m");
1264                         if(client)
1265                                 exit(EXIT_FAILURE);
1266                 }
1267         }
1268         if(!client) {
1269                 /* modern */
1270                 uint32_t reserved;
1271                 uint32_t opt;
1272                 uint32_t namelen;
1273                 char* name;
1274                 int i;
1275
1276                 if(!servers)
1277                         err("programmer error");
1278                 if (write(net, &smallflags, sizeof(uint16_t)) < 0)
1279                         err("Negotiation failed: %m");
1280                 if (read(net, &reserved, sizeof(reserved)) < 0)
1281                         err("Negotiation failed: %m");
1282                 if (read(net, &magic, sizeof(magic)) < 0)
1283                         err("Negotiation failed: %m");
1284                 magic = ntohll(magic);
1285                 if(magic != opts_magic) {
1286                         close(net);
1287                         return NULL;
1288                 }
1289                 if (read(net, &opt, sizeof(opt)) < 0)
1290                         err("Negotiation failed: %m");
1291                 opt = ntohl(opt);
1292                 if(opt != NBD_OPT_EXPORT_NAME) {
1293                         close(net);
1294                         return NULL;
1295                 }
1296                 if (read(net, &namelen, sizeof(namelen)) < 0)
1297                         err("Negotiation failed: %m");
1298                 namelen = ntohl(namelen);
1299                 name = malloc(namelen+1);
1300                 name[namelen]=0;
1301                 if (read(net, name, namelen) < 0)
1302                         err("Negotiation failed: %m");
1303                 for(i=0; i<servers->len; i++) {
1304                         SERVER* serve = &(g_array_index(servers, SERVER, i));
1305                         if(!strcmp(serve->servename, name)) {
1306                                 CLIENT* client = g_new0(CLIENT, 1);
1307                                 client->server = serve;
1308                                 client->exportsize = OFFT_MAX;
1309                                 client->net = net;
1310                                 client->modern = TRUE;
1311                                 free(name);
1312                                 return client;
1313                         }
1314                 }
1315                 free(name);
1316                 return NULL;
1317         }
1318         /* common */
1319         size_host = htonll((u64)(client->exportsize));
1320         if (write(net, &size_host, 8) < 0)
1321                 err("Negotiation failed: %m");
1322         if (client->server->flags & F_READONLY)
1323                 flags |= NBD_FLAG_READ_ONLY;
1324         if (!client->modern) {
1325                 /* oldstyle */
1326                 flags = htonl(flags);
1327                 if (write(client->net, &flags, 4) < 0)
1328                         err("Negotiation failed: %m");
1329         } else {
1330                 /* modern */
1331                 smallflags = (uint16_t)(flags & ~((uint16_t)0));
1332                 smallflags = htons(smallflags);
1333                 if (write(client->net, &smallflags, sizeof(smallflags)) < 0) {
1334                         err("Negotiation failed: %m");
1335                 }
1336         }
1337         /* common */
1338         if (write(client->net, zeros, 124) < 0)
1339                 err("Negotiation failed: %m");
1340         return NULL;
1341 }
1342
1343 /** sending macro. */
1344 #define SEND(net,reply) writeit( net, &reply, sizeof( reply ));
1345 /** error macro. */
1346 #define ERROR(client,reply,errcode) { reply.error = htonl(errcode); SEND(client->net,reply); reply.error = 0; }
1347 /**
1348  * Serve a file to a single client.
1349  *
1350  * @todo This beast needs to be split up in many tiny little manageable
1351  * pieces. Preferably with a chainsaw.
1352  *
1353  * @param client The client we're going to serve to.
1354  * @return when the client disconnects
1355  **/
1356 int mainloop(CLIENT *client) {
1357         struct nbd_request request;
1358         struct nbd_reply reply;
1359         gboolean go_on=TRUE;
1360 #ifdef DODBG
1361         int i = 0;
1362 #endif
1363         negotiate(client->net, client, NULL);
1364         DEBUG("Entering request loop!\n");
1365         reply.magic = htonl(NBD_REPLY_MAGIC);
1366         reply.error = 0;
1367         while (go_on) {
1368                 char buf[BUFSIZE];
1369                 char* p;
1370                 size_t len;
1371                 size_t currlen;
1372                 size_t writelen;
1373 #ifdef DODBG
1374                 i++;
1375                 printf("%d: ", i);
1376 #endif
1377                 readit(client->net, &request, sizeof(request));
1378                 request.from = ntohll(request.from);
1379                 request.type = ntohl(request.type);
1380
1381                 if (request.type==NBD_CMD_DISC) {
1382                         msg2(LOG_INFO, "Disconnect request received.");
1383                         if (client->server->flags & F_COPYONWRITE) { 
1384                                 if (client->difmap) g_free(client->difmap) ;
1385                                 close(client->difffile);
1386                                 unlink(client->difffilename);
1387                                 free(client->difffilename);
1388                         }
1389                         go_on=FALSE;
1390                         continue;
1391                 }
1392
1393                 len = ntohl(request.len);
1394
1395                 if (request.magic != htonl(NBD_REQUEST_MAGIC))
1396                         err("Not enough magic.");
1397                 if (len > BUFSIZE - sizeof(struct nbd_reply)) {
1398                         currlen = BUFSIZE - sizeof(struct nbd_reply);
1399                         msg2(LOG_INFO, "oversized request (this is not a problem)");
1400                 } else {
1401                         currlen = len;
1402                 }
1403 #ifdef DODBG
1404                 printf("%s from %llu (%llu) len %d, ", request.type ? "WRITE" :
1405                                 "READ", (unsigned long long)request.from,
1406                                 (unsigned long long)request.from / 512, len);
1407 #endif
1408                 memcpy(reply.handle, request.handle, sizeof(reply.handle));
1409                 if ((request.from + len) > (OFFT_MAX)) {
1410                         DEBUG("[Number too large!]");
1411                         ERROR(client, reply, EINVAL);
1412                         continue;
1413                 }
1414
1415                 if (((ssize_t)((off_t)request.from + len) > client->exportsize)) {
1416                         DEBUG("[RANGE!]");
1417                         ERROR(client, reply, EINVAL);
1418                         continue;
1419                 }
1420
1421                 if (request.type==NBD_CMD_WRITE) {
1422                         DEBUG("wr: net->buf, ");
1423                         while(len > 0) {
1424                                 readit(client->net, buf, currlen);
1425                                 DEBUG("buf->exp, ");
1426                                 if ((client->server->flags & F_READONLY) ||
1427                                     (client->server->flags & F_AUTOREADONLY)) {
1428                                         DEBUG("[WRITE to READONLY!]");
1429                                         ERROR(client, reply, EPERM);
1430                                         continue;
1431                                 }
1432                                 if (expwrite(request.from, buf, len, client)) {
1433                                         DEBUG("Write failed: %m" );
1434                                         ERROR(client, reply, errno);
1435                                         continue;
1436                                 }
1437                                 SEND(client->net, reply);
1438                                 DEBUG("OK!\n");
1439                                 len -= currlen;
1440                                 currlen = (len < BUFSIZE) ? len : BUFSIZE;
1441                         }
1442                         continue;
1443                 }
1444                 /* READ */
1445
1446                 DEBUG("exp->buf, ");
1447                 memcpy(buf, &reply, sizeof(struct nbd_reply));
1448                 p = buf + sizeof(struct nbd_reply);
1449                 writelen = currlen + sizeof(struct nbd_reply);
1450                 while(len > 0) {
1451                         if (expread(request.from, p, currlen, client)) {
1452                                 DEBUG("Read failed: %m");
1453                                 ERROR(client, reply, errno);
1454                                 continue;
1455                         }
1456
1457                         DEBUG("buf->net, ");
1458                         writeit(client->net, buf, writelen);
1459                         len -= currlen;
1460                         currlen = (len < BUFSIZE) ? len : BUFSIZE;
1461                         p = buf;
1462                         writelen = currlen;
1463                 }
1464                 DEBUG("OK!\n");
1465         }
1466         return 0;
1467 }
1468
1469 /**
1470  * Set up client export array, which is an array of FILE_INFO.
1471  * Also, split a single exportfile into multiple ones, if that was asked.
1472  * @param client information on the client which we want to setup export for
1473  **/
1474 void setupexport(CLIENT* client) {
1475         int i;
1476         off_t laststartoff = 0, lastsize = 0;
1477         int multifile = (client->server->flags & F_MULTIFILE);
1478
1479         client->export = g_array_new(TRUE, TRUE, sizeof(FILE_INFO));
1480
1481         /* If multi-file, open as many files as we can.
1482          * If not, open exactly one file.
1483          * Calculate file sizes as we go to get total size. */
1484         for(i=0; ; i++) {
1485                 FILE_INFO fi;
1486                 gchar *tmpname;
1487                 gchar* error_string;
1488                 mode_t mode = (client->server->flags & F_READONLY) ? O_RDONLY : O_RDWR;
1489
1490                 if(multifile) {
1491                         tmpname=g_strdup_printf("%s.%d", client->exportname, i);
1492                 } else {
1493                         tmpname=g_strdup(client->exportname);
1494                 }
1495                 DEBUG2( "Opening %s\n", tmpname );
1496                 fi.fhandle = open(tmpname, mode);
1497                 if(fi.fhandle == -1 && mode == O_RDWR) {
1498                         /* Try again because maybe media was read-only */
1499                         fi.fhandle = open(tmpname, O_RDONLY);
1500                         if(fi.fhandle != -1) {
1501                                 /* Opening the base file in copyonwrite mode is
1502                                  * okay */
1503                                 if(!(client->server->flags & F_COPYONWRITE)) {
1504                                         client->server->flags |= F_AUTOREADONLY;
1505                                         client->server->flags |= F_READONLY;
1506                                 }
1507                         }
1508                 }
1509                 if(fi.fhandle == -1) {
1510                         if(multifile && i>0)
1511                                 break;
1512                         error_string=g_strdup_printf(
1513                                 "Could not open exported file %s: %%m",
1514                                 tmpname);
1515                         err(error_string);
1516                 }
1517                 fi.startoff = laststartoff + lastsize;
1518                 g_array_append_val(client->export, fi);
1519                 g_free(tmpname);
1520
1521                 /* Starting offset and size of this file will be used to
1522                  * calculate starting offset of next file */
1523                 laststartoff = fi.startoff;
1524                 lastsize = size_autodetect(fi.fhandle);
1525
1526                 if(!multifile)
1527                         break;
1528         }
1529
1530         /* Set export size to total calculated size */
1531         client->exportsize = laststartoff + lastsize;
1532
1533         /* Export size may be overridden */
1534         if(client->server->expected_size) {
1535                 /* desired size must be <= total calculated size */
1536                 if(client->server->expected_size > client->exportsize) {
1537                         err("Size of exported file is too big\n");
1538                 }
1539
1540                 client->exportsize = client->server->expected_size;
1541         }
1542
1543         msg3(LOG_INFO, "Size of exported file/device is %llu", (unsigned long long)client->exportsize);
1544         if(multifile) {
1545                 msg3(LOG_INFO, "Total number of files: %d", i);
1546         }
1547 }
1548
1549 int copyonwrite_prepare(CLIENT* client) {
1550         off_t i;
1551         if ((client->difffilename = malloc(1024))==NULL)
1552                 err("Failed to allocate string for diff file name");
1553         snprintf(client->difffilename, 1024, "%s-%s-%d.diff",client->exportname,client->clientname,
1554                 (int)getpid()) ;
1555         client->difffilename[1023]='\0';
1556         msg3(LOG_INFO,"About to create map and diff file %s",client->difffilename) ;
1557         client->difffile=open(client->difffilename,O_RDWR | O_CREAT | O_TRUNC,0600) ;
1558         if (client->difffile<0) err("Could not create diff file (%m)") ;
1559         if ((client->difmap=calloc(client->exportsize/DIFFPAGESIZE,sizeof(u32)))==NULL)
1560                 err("Could not allocate memory") ;
1561         for (i=0;i<client->exportsize/DIFFPAGESIZE;i++) client->difmap[i]=(u32)-1 ;
1562
1563         return 0;
1564 }
1565
1566 /**
1567  * Run a command. This is used for the ``prerun'' and ``postrun'' config file
1568  * options
1569  *
1570  * @param command the command to be ran. Read from the config file
1571  * @param file the file name we're about to export
1572  **/
1573 int do_run(gchar* command, gchar* file) {
1574         gchar* cmd;
1575         int retval=0;
1576
1577         if(command && *command) {
1578                 cmd = g_strdup_printf(command, file);
1579                 retval=system(cmd);
1580                 g_free(cmd);
1581         }
1582         return retval;
1583 }
1584
1585 /**
1586  * Serve a connection. 
1587  *
1588  * @todo allow for multithreading, perhaps use libevent. Not just yet, though;
1589  * follow the road map.
1590  *
1591  * @param client a connected client
1592  **/
1593 void serveconnection(CLIENT *client) {
1594         if(do_run(client->server->prerun, client->exportname)) {
1595                 exit(EXIT_FAILURE);
1596         }
1597         setupexport(client);
1598
1599         if (client->server->flags & F_COPYONWRITE) {
1600                 copyonwrite_prepare(client);
1601         }
1602
1603         setmysockopt(client->net);
1604
1605         mainloop(client);
1606         do_run(client->server->postrun, client->exportname);
1607 }
1608
1609 /**
1610  * Find the name of the file we have to serve. This will use g_strdup_printf
1611  * to put the IP address of the client inside a filename containing
1612  * "%s" (in the form as specified by the "virtstyle" option). That name
1613  * is then written to client->exportname.
1614  *
1615  * @param net A socket connected to an nbd client
1616  * @param client information about the client. The IP address in human-readable
1617  * format will be written to a new char* buffer, the address of which will be
1618  * stored in client->clientname.
1619  **/
1620 void set_peername(int net, CLIENT *client) {
1621         struct sockaddr_storage addrin;
1622         struct sockaddr_storage netaddr;
1623         struct sockaddr_in  *netaddr4 = NULL;
1624         struct sockaddr_in6 *netaddr6 = NULL;
1625         size_t addrinlen = sizeof( addrin );
1626         struct addrinfo hints;
1627         struct addrinfo *ai = NULL;
1628         char peername[NI_MAXHOST];
1629         char netname[NI_MAXHOST];
1630         char *tmp = NULL;
1631         int i;
1632         int e;
1633         int shift;
1634
1635         if (getpeername(net, (struct sockaddr *) &addrin, (socklen_t *)&addrinlen) < 0)
1636                 err("getsockname failed: %m");
1637
1638         getnameinfo((struct sockaddr *)&addrin, (socklen_t)addrinlen,
1639                 peername, sizeof (peername), NULL, 0, NI_NUMERICHOST);
1640
1641         memset(&hints, '\0', sizeof (hints));
1642         hints.ai_flags = AI_ADDRCONFIG;
1643         e = getaddrinfo(peername, NULL, &hints, &ai);
1644
1645         if(e != 0) {
1646                 fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(e));
1647                 freeaddrinfo(ai);
1648                 return;
1649         }
1650
1651         switch(client->server->virtstyle) {
1652                 case VIRT_NONE:
1653                         client->exportname=g_strdup(client->server->exportname);
1654                         break;
1655                 case VIRT_IPHASH:
1656                         for(i=0;i<strlen(peername);i++) {
1657                                 if(peername[i]=='.') {
1658                                         peername[i]='/';
1659                                 }
1660                         }
1661                 case VIRT_IPLIT:
1662                         client->exportname=g_strdup_printf(client->server->exportname, peername);
1663                         break;
1664                 case VIRT_CIDR:
1665                         memcpy(&netaddr, &addrin, addrinlen);
1666                         if(ai->ai_family == AF_INET) {
1667                                 netaddr4 = (struct sockaddr_in *)&netaddr;
1668                                 (netaddr4->sin_addr).s_addr>>=32-(client->server->cidrlen);
1669                                 (netaddr4->sin_addr).s_addr<<=32-(client->server->cidrlen);
1670
1671                                 getnameinfo((struct sockaddr *) netaddr4, (socklen_t) addrinlen,
1672                                                         netname, sizeof (netname), NULL, 0, NI_NUMERICHOST);
1673                                 tmp=g_strdup_printf("%s/%s", netname, peername);
1674                         }else if(ai->ai_family == AF_INET6) {
1675                                 netaddr6 = (struct sockaddr_in6 *)&netaddr;
1676
1677                                 shift = 128-(client->server->cidrlen);
1678                                 i = 3;
1679                                 while(shift >= 32) {
1680                                         ((netaddr6->sin6_addr).s6_addr32[i])=0;
1681                                         shift-=32;
1682                                         i--;
1683                                 }
1684                                 (netaddr6->sin6_addr).s6_addr32[i]>>=shift;
1685                                 (netaddr6->sin6_addr).s6_addr32[i]<<=shift;
1686
1687                                 getnameinfo((struct sockaddr *)netaddr6, (socklen_t)addrinlen,
1688                                             netname, sizeof(netname), NULL, 0, NI_NUMERICHOST);
1689                                 tmp=g_strdup_printf("%s/%s", netname, peername);
1690                         }
1691
1692                         if(tmp != NULL)
1693                           client->exportname=g_strdup_printf(client->server->exportname, tmp);
1694
1695                         break;
1696         }
1697
1698         freeaddrinfo(ai);
1699         msg4(LOG_INFO, "connect from %s, assigned file is %s", 
1700              peername, client->exportname);
1701         client->clientname=g_strdup(peername);
1702 }
1703
1704 /**
1705  * Destroy a pid_t*
1706  * @param data a pointer to pid_t which should be freed
1707  **/
1708 void destroy_pid_t(gpointer data) {
1709         g_free(data);
1710 }
1711
1712 /**
1713  * Loop through the available servers, and serve them. Never returns.
1714  **/
1715 int serveloop(GArray* servers) {
1716         struct sockaddr_storage addrin;
1717         socklen_t addrinlen=sizeof(addrin);
1718         int i;
1719         int max;
1720         int sock;
1721         fd_set mset;
1722         fd_set rset;
1723
1724         /* 
1725          * Set up the master fd_set. The set of descriptors we need
1726          * to select() for never changes anyway and it buys us a *lot*
1727          * of time to only build this once. However, if we ever choose
1728          * to not fork() for clients anymore, we may have to revisit
1729          * this.
1730          */
1731         max=0;
1732         FD_ZERO(&mset);
1733         for(i=0;i<servers->len;i++) {
1734                 if((sock=(g_array_index(servers, SERVER, i)).socket)) {
1735                         FD_SET(sock, &mset);
1736                         max=sock>max?sock:max;
1737                 }
1738         }
1739         if(modernsock) {
1740                 FD_SET(modernsock, &mset);
1741                 max=modernsock>max?modernsock:max;
1742         }
1743         for(;;) {
1744                 CLIENT *client = NULL;
1745                 pid_t *pid;
1746
1747                 memcpy(&rset, &mset, sizeof(fd_set));
1748                 if(select(max+1, &rset, NULL, NULL, NULL)>0) {
1749                         int net = 0;
1750                         SERVER* serve=NULL;
1751
1752                         DEBUG("accept, ");
1753                         if(FD_ISSET(modernsock, &rset)) {
1754                                 if((net=accept(modernsock, (struct sockaddr *) &addrin, &addrinlen)) < 0)
1755                                         err("accept: %m");
1756                                 client = negotiate(net, NULL, servers);
1757                                 if(!client) {
1758                                         err_nonfatal("negotiation failed");
1759                                         close(net);
1760                                         net=0;
1761                                 }
1762                                 serve = client->server;
1763                         }
1764                         for(i=0;i<servers->len && !net;i++) {
1765                                 serve=&(g_array_index(servers, SERVER, i));
1766                                 if(FD_ISSET(serve->socket, &rset)) {
1767                                         if ((net=accept(serve->socket, (struct sockaddr *) &addrin, &addrinlen)) < 0)
1768                                                 err("accept: %m");
1769                                 }
1770                         }
1771                         if(net) {
1772                                 int sock_flags;
1773
1774                                 if(serve->max_connections > 0 &&
1775                                    g_hash_table_size(children) >= serve->max_connections) {
1776                                         msg2(LOG_INFO, "Max connections reached");
1777                                         close(net);
1778                                         continue;
1779                                 }
1780                                 if((sock_flags = fcntl(net, F_GETFL, 0))==-1) {
1781                                         err("fcntl F_GETFL");
1782                                 }
1783                                 if(fcntl(net, F_SETFL, sock_flags &~O_NONBLOCK)==-1) {
1784                                         err("fcntl F_SETFL ~O_NONBLOCK");
1785                                 }
1786                                 if(!client) {
1787                                         client = g_new0(CLIENT, 1);
1788                                         client->server=serve;
1789                                         client->exportsize=OFFT_MAX;
1790                                         client->net=net;
1791                                 }
1792                                 set_peername(net, client);
1793                                 if (!authorized_client(client)) {
1794                                         msg2(LOG_INFO,"Unauthorized client") ;
1795                                         close(net);
1796                                         continue;
1797                                 }
1798                                 msg2(LOG_INFO,"Authorized client") ;
1799                                 pid=g_malloc(sizeof(pid_t));
1800 #ifndef NOFORK
1801                                 if ((*pid=fork())<0) {
1802                                         msg3(LOG_INFO,"Could not fork (%s)",strerror(errno)) ;
1803                                         close(net);
1804                                         continue;
1805                                 }
1806                                 if (*pid>0) { /* parent */
1807                                         close(net);
1808                                         g_hash_table_insert(children, pid, pid);
1809                                         continue;
1810                                 }
1811                                 /* child */
1812                                 g_hash_table_destroy(children);
1813                                 for(i=0;i<servers->len;i++) {
1814                                         serve=&g_array_index(servers, SERVER, i);
1815                                         close(serve->socket);
1816                                 }
1817                                 /* FALSE does not free the
1818                                 actual data. This is required,
1819                                 because the client has a
1820                                 direct reference into that
1821                                 data, and otherwise we get a
1822                                 segfault... */
1823                                 g_array_free(servers, FALSE);
1824 #endif // NOFORK
1825                                 msg2(LOG_INFO,"Starting to serve");
1826                                 serveconnection(client);
1827                                 exit(EXIT_SUCCESS);
1828                         }
1829                 }
1830         }
1831 }
1832
1833 void dosockopts(int socket) {
1834 #ifndef sun
1835         int yes=1;
1836 #else
1837         char yes='1';
1838 #endif /* sun */
1839         int sock_flags;
1840
1841         /* lose the pesky "Address already in use" error message */
1842         if (setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
1843                 err("setsockopt SO_REUSEADDR");
1844         }
1845         if (setsockopt(socket,SOL_SOCKET,SO_KEEPALIVE,&yes,sizeof(int)) == -1) {
1846                 err("setsockopt SO_KEEPALIVE");
1847         }
1848
1849         /* make the listening socket non-blocking */
1850         if ((sock_flags = fcntl(socket, F_GETFL, 0)) == -1) {
1851                 err("fcntl F_GETFL");
1852         }
1853         if (fcntl(socket, F_SETFL, sock_flags | O_NONBLOCK) == -1) {
1854                 err("fcntl F_SETFL O_NONBLOCK");
1855         }
1856 }
1857
1858 /**
1859  * Connect a server's socket.
1860  *
1861  * @param serve the server we want to connect.
1862  **/
1863 int setup_serve(SERVER *serve) {
1864         struct addrinfo hints;
1865         struct addrinfo *ai = NULL;
1866         gchar *port = NULL;
1867         int e;
1868
1869         if(!do_oldstyle) {
1870                 return serve->servename ? 1 : 0;
1871         }
1872         memset(&hints,'\0',sizeof(hints));
1873         hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG | AI_NUMERICSERV;
1874         hints.ai_socktype = SOCK_STREAM;
1875         hints.ai_family = serve->socket_family;
1876
1877         port = g_strdup_printf ("%d", serve->port);
1878         if (port == NULL)
1879                 return 0;
1880
1881         e = getaddrinfo(serve->listenaddr,port,&hints,&ai);
1882
1883         g_free(port);
1884
1885         if(e != 0) {
1886                 fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(e));
1887                 serve->socket = -1;
1888                 freeaddrinfo(ai);
1889                 exit(EXIT_FAILURE);
1890         }
1891
1892         if(serve->socket_family == AF_UNSPEC)
1893                 serve->socket_family = ai->ai_family;
1894
1895 #ifdef WITH_SDP
1896         if ((serve->flags) && F_SDP) {
1897                 if (ai->ai_family == AF_INET)
1898                         ai->ai_family = AF_INET_SDP;
1899                 else (ai->ai_family == AF_INET6)
1900                         ai->ai_family = AF_INET6_SDP;
1901         }
1902 #endif
1903         if ((serve->socket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0)
1904                 err("socket: %m");
1905
1906         dosockopts(serve->socket);
1907
1908         DEBUG("Waiting for connections... bind, ");
1909         e = bind(serve->socket, ai->ai_addr, ai->ai_addrlen);
1910         if (e != 0 && errno != EADDRINUSE)
1911                 err("bind: %m");
1912         DEBUG("listen, ");
1913         if (listen(serve->socket, 1) < 0)
1914                 err("listen: %m");
1915
1916         freeaddrinfo (ai);
1917         if(serve->servename) {
1918                 return 1;
1919         } else {
1920                 return 0;
1921         }
1922 }
1923
1924 void open_modern(void) {
1925         struct addrinfo hints;
1926         struct addrinfo* ai = NULL;
1927         struct sock_flags;
1928         int e;
1929
1930         memset(&hints, '\0', sizeof(hints));
1931         hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
1932         hints.ai_socktype = SOCK_STREAM;
1933         hints.ai_family = AF_UNSPEC;
1934         hints.ai_protocol = IPPROTO_TCP;
1935         e = getaddrinfo(modern_listen, NBD_DEFAULT_PORT, &hints, &ai);
1936         if(e != 0) {
1937                 fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(e));
1938                 exit(EXIT_FAILURE);
1939         }
1940         if((modernsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol))<0) {
1941                 err("socket: %m");
1942         }
1943
1944         dosockopts(modernsock);
1945
1946         if(bind(modernsock, ai->ai_addr, ai->ai_addrlen)) {
1947                 err("bind: %m");
1948         }
1949         if(listen(modernsock, 10) <0) {
1950                 err("listen: %m");
1951         }
1952
1953         freeaddrinfo(ai);
1954 }
1955
1956 /**
1957  * Connect our servers.
1958  **/
1959 void setup_servers(GArray* servers) {
1960         int i;
1961         struct sigaction sa;
1962         int want_modern=0;
1963
1964         for(i=0;i<servers->len;i++) {
1965                 want_modern |= setup_serve(&(g_array_index(servers, SERVER, i)));
1966         }
1967         if(want_modern) {
1968                 open_modern();
1969         }
1970         children=g_hash_table_new_full(g_int_hash, g_int_equal, NULL, destroy_pid_t);
1971
1972         sa.sa_handler = sigchld_handler;
1973         sigemptyset(&sa.sa_mask);
1974         sa.sa_flags = SA_RESTART;
1975         if(sigaction(SIGCHLD, &sa, NULL) == -1)
1976                 err("sigaction: %m");
1977         sa.sa_handler = sigterm_handler;
1978         sigemptyset(&sa.sa_mask);
1979         sa.sa_flags = SA_RESTART;
1980         if(sigaction(SIGTERM, &sa, NULL) == -1)
1981                 err("sigaction: %m");
1982 }
1983
1984 /**
1985  * Go daemon (unless we specified at compile time that we didn't want this)
1986  * @param serve the first server of our configuration. If its port is zero,
1987  *      then do not daemonize, because we're doing inetd then. This parameter
1988  *      is only used to create a PID file of the form
1989  *      /var/run/nbd-server.&lt;port&gt;.pid; it's not modified in any way.
1990  **/
1991 #if !defined(NODAEMON) && !defined(NOFORK)
1992 void daemonize(SERVER* serve) {
1993         FILE*pidf;
1994
1995         if(serve && !(serve->port)) {
1996                 return;
1997         }
1998         if(daemon(0,0)<0) {
1999                 err("daemon");
2000         }
2001         if(!*pidftemplate) {
2002                 if(serve) {
2003                         strncpy(pidftemplate, "/var/run/nbd-server.%d.pid", 255);
2004                 } else {
2005                         strncpy(pidftemplate, "/var/run/nbd-server.pid", 255);
2006                 }
2007         }
2008         snprintf(pidfname, 255, pidftemplate, serve ? serve->port : 0);
2009         pidf=fopen(pidfname, "w");
2010         if(pidf) {
2011                 fprintf(pidf,"%d\n", (int)getpid());
2012                 fclose(pidf);
2013         } else {
2014                 perror("fopen");
2015                 fprintf(stderr, "Not fatal; continuing");
2016         }
2017 }
2018 #else
2019 #define daemonize(serve)
2020 #endif /* !defined(NODAEMON) && !defined(NOFORK) */
2021
2022 /*
2023  * Everything beyond this point (in the file) is run in non-daemon mode.
2024  * The stuff above daemonize() isn't.
2025  */
2026
2027 void serve_err(SERVER* serve, const char* msg) G_GNUC_NORETURN;
2028
2029 void serve_err(SERVER* serve, const char* msg) {
2030         g_message("Export of %s on port %d failed:", serve->exportname,
2031                         serve->port);
2032         err(msg);
2033 }
2034
2035 /**
2036  * Set up user-ID and/or group-ID
2037  **/
2038 void dousers(void) {
2039         struct passwd *pw;
2040         struct group *gr;
2041         gchar* str;
2042         if(rungroup) {
2043                 gr=getgrnam(rungroup);
2044                 if(!gr) {
2045                         str = g_strdup_printf("Invalid group name: %s", rungroup);
2046                         err(str);
2047                 }
2048                 if(setgid(gr->gr_gid)<0) {
2049                         err("Could not set GID: %m"); 
2050                 }
2051         }
2052         if(runuser) {
2053                 pw=getpwnam(runuser);
2054                 if(!pw) {
2055                         str = g_strdup_printf("Invalid user name: %s", runuser);
2056                         err(str);
2057                 }
2058                 if(setuid(pw->pw_uid)<0) {
2059                         err("Could not set UID: %m");
2060                 }
2061         }
2062 }
2063
2064 #ifndef ISSERVER
2065 void glib_message_syslog_redirect(const gchar *log_domain,
2066                                   GLogLevelFlags log_level,
2067                                   const gchar *message,
2068                                   gpointer user_data)
2069 {
2070     int level=LOG_DEBUG;
2071     
2072     switch( log_level )
2073     {
2074       case G_LOG_FLAG_FATAL:
2075       case G_LOG_LEVEL_CRITICAL:
2076       case G_LOG_LEVEL_ERROR:    
2077         level=LOG_ERR; 
2078         break;
2079       case G_LOG_LEVEL_WARNING:
2080         level=LOG_WARNING;
2081         break;
2082       case G_LOG_LEVEL_MESSAGE:
2083       case G_LOG_LEVEL_INFO:
2084         level=LOG_INFO;
2085         break;
2086       case G_LOG_LEVEL_DEBUG:
2087         level=LOG_DEBUG;
2088       default:
2089         level=LOG_ERR;
2090     }
2091     syslog(level, "%s", message);
2092 }
2093 #endif
2094
2095 /**
2096  * Main entry point...
2097  **/
2098 int main(int argc, char *argv[]) {
2099         SERVER *serve;
2100         GArray *servers;
2101         GError *err=NULL;
2102
2103         if (sizeof( struct nbd_request )!=28) {
2104                 fprintf(stderr,"Bad size of structure. Alignment problems?\n");
2105                 exit(EXIT_FAILURE) ;
2106         }
2107
2108         memset(pidftemplate, '\0', 256);
2109
2110         logging();
2111         config_file_pos = g_strdup(CFILE);
2112         serve=cmdline(argc, argv);
2113         servers = parse_cfile(config_file_pos, &err);
2114         
2115         if(serve) {
2116                 serve->socket_family = AF_UNSPEC;
2117
2118                 append_serve(serve, servers);
2119      
2120                 if (!(serve->port)) {
2121                         CLIENT *client;
2122 #ifndef ISSERVER
2123                         /* You really should define ISSERVER if you're going to use
2124                          * inetd mode, but if you don't, closing stdout and stderr
2125                          * (which inetd had connected to the client socket) will let it
2126                          * work. */
2127                         close(1);
2128                         close(2);
2129                         open("/dev/null", O_WRONLY);
2130                         open("/dev/null", O_WRONLY);
2131                         g_log_set_default_handler( glib_message_syslog_redirect, NULL );
2132 #endif
2133                         client=g_malloc(sizeof(CLIENT));
2134                         client->server=serve;
2135                         client->net=0;
2136                         client->exportsize=OFFT_MAX;
2137                         set_peername(0,client);
2138                         serveconnection(client);
2139                         return 0;
2140                 }
2141         }
2142     
2143         if(!servers || !servers->len) {
2144                 if(err && !(err->domain == g_quark_from_string("parse_cfile")
2145                                 && err->code == CFILE_NOTFOUND)) {
2146                         g_warning("Could not parse config file: %s", 
2147                                         err ? err->message : "Unknown error");
2148                 }
2149         }
2150         if(serve) {
2151                 g_warning("Specifying an export on the command line is deprecated.");
2152                 g_warning("Please use a configuration file instead.");
2153         }
2154
2155         if((!serve) && (!servers||!servers->len)) {
2156                 g_message("No configured exports; quitting.");
2157                 exit(EXIT_FAILURE);
2158         }
2159         daemonize(serve);
2160         setup_servers(servers);
2161         dousers();
2162         serveloop(servers);
2163         return 0 ;
2164 }