diff src/dnsbl.cpp @ 60:390ed250c5d2 stable-4-1

use local unix domain socket for resolver process communication
author carl
date Thu, 06 Jan 2005 11:35:38 -0800
parents 510a511ad554
children 7f44a4974bf6
line wrap: on
line diff
--- a/src/dnsbl.cpp	Mon Jan 03 18:35:50 2005 -0800
+++ b/src/dnsbl.cpp	Thu Jan 06 11:35:38 2005 -0800
@@ -201,7 +201,7 @@
 static std::set<int>    fd_pool;
 
 static int    NULL_SOCKET       = -1;
-static int    resolver_port     = 0;            // global port number to talk to the dns resolver process
+static char  *resolver_port     = NULL;         // unix domain socket to talk to the dns resolver process
 static int    resolver_socket   = NULL_SOCKET;  // socket used to listen for resolver requests
 static time_t ERROR_SOCKET_TIME = 60;           // number of seconds between attempts to open the spam filter socket
 static time_t last_error_time;
@@ -305,13 +305,11 @@
 
     // nothing recent, maybe this time it will work
     int sock = NULL_SOCKET;
-    hostent *host = gethostbyname("localhost");
-    if (host) {
-        sockaddr_in server;
-        server.sin_family = host->h_addrtype;
-        server.sin_port   = htons(resolver_port);
-        memcpy(&server.sin_addr, host->h_addr_list[0], host->h_length);
-        sock = socket(PF_INET, SOCK_STREAM, 0);
+    sockaddr_un server;
+    memset(&server, '\0', sizeof(server));
+    server.sun_family = AF_UNIX;
+    strncpy(server.sun_path, resolver_port, sizeof(server.sun_path)-1);
+    sock = socket(AF_UNIX, SOCK_STREAM, 0);
         if (sock != NULL_SOCKET) {
             bool rc = (connect(sock, (sockaddr *)&server, sizeof(server)) == 0);
             if (!rc) {
@@ -322,7 +320,6 @@
             }
         }
         else last_error_time = now;
-    }
     return sock;
 }
 
@@ -637,7 +634,7 @@
             }
             else {
                 // peer closed the socket
-              //my_syslog("child worker process, peer closed socket while reading question");
+              //my_syslog("!!child worker process, peer closed socket while reading question");
                 shutdown(socket, SHUT_RDWR);
                 close(socket);
                 return;
@@ -646,7 +643,7 @@
 
         // find the answer
       //char text[1000];
-      //snprintf(text, sizeof(text), "child worker process has a question %s", question);
+      //snprintf(text, sizeof(text), "!!child worker process has a question %s", question);
       //my_syslog(text);
         glom.length = res_search(question, ns_c_in, ns_t_a, glom.answer, sizeof(glom.answer));
         if (glom.length < 0) glom.length = 0;   // represent all errors as zero length answers
@@ -654,7 +651,7 @@
         // write the answer
         char *buf = (char *)&glom;
         int   len = glom.length + sizeof(glom.length);
-      //snprintf(text, sizeof(text), "child worker process writing answer length %d for total %d", glom.length, len);
+      //snprintf(text, sizeof(text), "!!child worker process writing answer length %d for total %d", glom.length, len);
       //my_syslog(text);
         int    ws = 0;
         while (len > ws) {
@@ -664,7 +661,7 @@
             }
             else {
                 // peer closed the socket!
-              //my_syslog("child worker process, peer closed socket while writing answer");
+              //my_syslog("!!child worker process, peer closed socket while writing answer");
                 shutdown(socket, SHUT_RDWR);
                 close(socket);
                 return;
@@ -695,9 +692,9 @@
     char *buf = (char *)&glom;
     priv.my_read(buf, sizeof(glom.length));
     buf += sizeof(glom.length);
-  //char text[1000];
-  //snprintf(text, sizeof(text), "milter thread wrote question %s and has answer length %d", question, glom.length);
-  //my_syslog(text);
+ ///char text[1000];
+ ///snprintf(text, sizeof(text), "!!milter thread wrote question %s and has answer length %d", question, glom.length);
+ ///my_syslog(text);
     if ((glom.length < 0) || (glom.length > sizeof(glom.answer))) {
         priv.err = true;
         return 0;  // cannot process overlarge answers
@@ -1609,6 +1606,7 @@
 {
     fprintf(stderr, "Usage: %s  [-d] [-c] -r port -p sm-sock-addr [-t timeout]\n", prog);
     fprintf(stderr, "where port is for the connection to our own dns resolver processes\n");
+    fprintf(stderr, "    and should be local-domain-socket-file-name\n");
     fprintf(stderr, "where sm-sock-addr is for the connection to sendmail\n");
     fprintf(stderr, "    and should be one of\n");
     fprintf(stderr, "        inet:port@ip-address\n");
@@ -1649,7 +1647,8 @@
                     fprintf(stderr, "Illegal resolver socket: %s\n", optarg);
                     exit(EX_USAGE);
                 }
-                resolver_port = atoi(optarg);
+                resolver_port = strdup(optarg);
+                setup_socket(resolver_port);
                 setreso = true;
                 break;
 
@@ -1749,6 +1748,17 @@
     pthread_mutex_init(&resolve_mutex, 0);
     pthread_mutex_init(&fd_pool_mutex, 0);
 
+    // drop root privs
+    struct passwd *pw = getpwnam("dnsbl");
+    if (pw) {
+        if (setgid(pw->pw_gid) == -1) {
+            my_syslog("failed to switch to group dnsbl");
+        }
+        if (setuid(pw->pw_uid) == -1) {
+            my_syslog("failed to switch to user dnsbl");
+        }
+    }
+
 #ifdef NS_PACKETSZ
     // fork off the resolver listener process
     pid_t child = fork();
@@ -1758,22 +1768,22 @@
     }
     if (child == 0) {
         // we are the child - dns resolver listener process
-        resolver_socket = socket(PF_INET, SOCK_STREAM, 0);
+        resolver_socket = socket(AF_UNIX, SOCK_STREAM, 0);
         if (resolver_socket < 0) {
             my_syslog("child failed to create resolver socket");
             exit(0);   // failed
         }
-        sockaddr_in server;
-        server.sin_family   = AF_INET;
-        server.sin_port     = htons(resolver_port);
-        server.sin_addr.s_addr = 0;
+        sockaddr_un server;
+        memset(&server, '\0', sizeof(server));
+        server.sun_family = AF_UNIX;
+        strncpy(server.sun_path, resolver_port, sizeof(server.sun_path)-1);
         // set the socket options
-        int      reuse_addr = 1;
-        linger linger_opt;
-        linger_opt.l_onoff  = 0;    // off
-        linger_opt.l_linger = 0;
-        setsockopt(resolver_socket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&reuse_addr), sizeof(reuse_addr));
-        setsockopt(resolver_socket, SOL_SOCKET, SO_LINGER,    reinterpret_cast<char*>(&linger_opt), sizeof(linger_opt));
+     ///int      reuse_addr = 1;
+     ///linger linger_opt;
+     ///linger_opt.l_onoff  = 0;    // off
+     ///linger_opt.l_linger = 0;
+     ///setsockopt(resolver_socket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&reuse_addr), sizeof(reuse_addr));
+     ///setsockopt(resolver_socket, SOL_SOCKET, SO_LINGER,    reinterpret_cast<char*>(&linger_opt), sizeof(linger_opt));
      ///// set nonblocking mode
      ///int     dummy = 0;
      ///int     flags = fcntl(resolver_socket, F_GETFL, dummy);
@@ -1793,29 +1803,10 @@
             shutdown(resolver_socket, SHUT_RDWR);
             close(resolver_socket);
             my_syslog("child failed to listen to the resolver socket");
-            return -1;
-        }
-    }
-    else {
-        sleep(2);   // allow child to get started
+            exit(0);   // failed
     }
-#endif
-
-    // drop root privs
-    struct passwd *pw = getpwnam("dnsbl");
-    if (pw) {
-        if (setgid(pw->pw_gid) == -1) {
-            my_syslog("failed to switch to group dnsbl");
-        }
-        if (setuid(pw->pw_uid) == -1) {
-            my_syslog("failed to switch to user dnsbl");
-        }
-    }
-
-#ifdef NS_PACKETSZ
-    if (child == 0) {
         while (true) {
-            sockaddr_in client;
+            sockaddr_un client;
             socklen_t   clientlen = sizeof(client);
             int s = accept(resolver_socket, (sockaddr *)&client, &clientlen);
             if (s > 0) {
@@ -1824,15 +1815,25 @@
                 int newchild = fork();
                 if (newchild == 0) {
                     // this is the worker process
+                    // child does not need the listening socket
+                    close(resolver_socket);
                     my_syslog("child forked a worker process");
                     process_resolver_requests(s);
                     my_syslog("child terminated a worker process");
                     exit(0);
                 }
+                else {
+                    // this is the parent
+                    // parent does not need the accepted socket
+                    close(s);
+                }
             }
         }
         exit(0);    // make sure we don't fall thru.
     }
+    else {
+        sleep(2);   // allow child to get started
+    }
 #endif
 
     // load the initial config