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