r38: configure.in:
[nbd.git] / nbd-server.c
index bd46507..5163fb3 100644 (file)
  *     so that processes don't think they have to wait for us, which is
  *     interesting for initscripts as well. Wouter Verhelst
  *     <wouter@debian.org>
+ * Version 2.5 - Bugfix release: forgot to reset child_arraysize to
+ *      zero after fork()ing, resulting in nbd-server going berserk
+ *      when it receives a signal with at least one child open. Wouter
+ *      Verhelst <wouter@debian.org>
+ * 10/10/2003 - Added socket option SO_KEEPALIVE (sf.net bug 819235);
+ *     rectified type of mainloop::size_host (sf.net bugs 814435 and
+ *     817385); close the PID file after writing to it, so that the
+ *     daemon can actually be found. Wouter Verhelst
+ *     <wouter@debian.org>
  */
 
 #define VERSION PACKAGE_VERSION
 // #define ISSERVER
 #define MY_NAME "nbd_server"
 
-/* Authorization file should contain lines with IP addresses of 
-   clients authorized to use the server. If it does not exist,
-   access is permitted. 
-   
-   You may want to set this to an absolute path if you're not using
-   -DNODAEMON, since if you don't, nbd-server will look for this file
-   in the root-directory ("/"). */
-#define AUTH_FILE "nbd_server.allow"
 /* how much space for child PIDs we have by default. Dynamically
    allocated, and will be realloc()ed if out of space, so this should
    probably be fair for most situations. */
@@ -74,7 +75,6 @@
 //#undef _IO
 /* Deep magic: ioctl.h defines _IO macro (at least on linux) */
 
-
 /* Debugging macros, now nothing goes to syslog unless you say ISSERVER */
 #ifdef ISSERVER
 #define msg2(a,b) syslog(a,b)
@@ -86,7 +86,6 @@
 #define msg4(a,b,c,d) do { fprintf(stderr,b,c,d); fputs("\n",stderr) ; } while(0)
 #endif
 
-
 #include <sys/ioctl.h>
 #include <sys/mount.h>         /* For BLKGETSIZE */
 
@@ -108,6 +107,7 @@ void set_peername(int net,char *clientname);
 char difffilename[256];
 unsigned int timeout = 0;
 int autoreadonly = 0;
+char *auth_file="nbd_server.allow";
 
 int authorized_client(char *name)
 /* 0 - authorization refused, 1 - OK 
@@ -118,9 +118,9 @@ int authorized_client(char *name)
    
        char line[LINELEN] ; 
 
-       if ((f=fopen(AUTH_FILE,"r"))==NULL) {
+       if ((f=fopen(auth_file,"r"))==NULL) {
                msg4(LOG_INFO,"Can't open authorization file %s (%s).",
-                    AUTH_FILE,strerror(errno)) ;
+                    auth_file,strerror(errno)) ;
                return 1 ; 
        }
   
@@ -193,6 +193,7 @@ void cmdline(int argc, char *argv[])
                       "        -r read only\n"
                       "        -m multiple file\n"
                       "        -c copy on write\n"
+                      "        -l file with list of hosts that are allowed to connect.\n"
                       "        -a maximum idle seconds, terminates when idle time exceeded\n"
                       "        if port is set to 0, stdin is used (for running from inetd)\n"
                       "        if file_to_export contains '%%s', it is substituted with IP\n"
@@ -212,6 +213,14 @@ void cmdline(int argc, char *argv[])
                                break;
                        case 'c': flags |=F_COPYONWRITE;
                                break;
+                       case 'l':
+                               free(auth_file);
+                               if (i+1<argc) {
+                                       auth_file=argv[++i];
+                               } else {
+                                       fprintf(stderr, "host list file requires an argument");
+                               }
+                               break;
                        case 'a': 
                                if (i+1<argc) {
                                        timeout = atoi(argv[i+1]);
@@ -305,6 +314,7 @@ void connectme(int port)
                pidf=fopen(pidfname, "w");
                if(pidf) {
                        fprintf(pidf,"%d", (int)getpid());
+                       fclose(pidf);
                } else {
                        perror("fopen");
                        fprintf(stderr, "Not fatal; continuing");
@@ -318,7 +328,10 @@ void connectme(int port)
 
        /* lose the pesky "Address already in use" error message */
        if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
-               err("setsockopt");
+               err("setsockopt SO_REUSEADDR");
+       }
+       if (setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,&yes,sizeof(int)) == -1) {
+               err("setsockopt SO_KEEPALIVE");
        }
 
        DEBUG("Waiting for connections... bind, ");
@@ -371,6 +384,7 @@ void connectme(int port)
                        close(net) ; continue ; }
                /* child */
                realloc(children,0);
+               child_arraysize=0;
                close(sock) ;
 #endif // NOFORK
                msg2(LOG_INFO,"Starting to serve") ;
@@ -492,7 +506,7 @@ int mainloop(int net)
        struct nbd_reply reply;
        char zeros[300];
        int i = 0;
-       off_t size_host;
+       u64 size_host;
 
        memset(zeros, 0, 290);
        if (write(net, INIT_PASSWD, 8) < 0)
@@ -500,7 +514,7 @@ int mainloop(int net)
        cliserv_magic = htonll(cliserv_magic);
        if (write(net, &cliserv_magic, sizeof(cliserv_magic)) < 0)
                err("Negotiation failed: %m");
-       size_host = htonll(exportsize);
+       size_host = htonll((u64)exportsize);
        if (write(net, &size_host, 8) < 0)
                err("Negotiation failed: %m");
        if (write(net, zeros, 128) < 0)