r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text
[vlendec/samba-autobuild/.git] / source3 / nmbd / asyncdns.c
index e0d262f72ca4a681c5f37f2dcd54dc3de378b098..f572aefc784081e2d8b5243a10fdb5175192a1ce 100644 (file)
@@ -1,11 +1,11 @@
 /*
-   Unix SMB/Netbios implementation.
+   Unix SMB/CIFS implementation.
    a async DNS handler
-   Copyright (C) Andrew Tridgell 1997
+   Copyright (C) Andrew Tridgell 1997-1998
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */
 
 #include "includes.h"
 
-extern int DEBUGLEVEL;
-
 /***************************************************************************
   Add a DNS result to the name cache.
 ****************************************************************************/
 
 static struct name_record *add_dns_result(struct nmb_name *question, struct in_addr addr)
 {
-  int name_type = question->name_type;
-  char *qname = question->name;
-  
+       int name_type = question->name_type;
+       unstring qname;
+
+       pull_ascii_nstring(qname, sizeof(qname), question->name);
   
-  if (!addr.s_addr) {
-    /* add the fail to WINS cache of names. give it 1 hour in the cache */
-    DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname));
-    add_name_to_subnet(wins_server_subnet,qname,name_type,
-                       NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr);
-    return NULL;
-  }
-
-  /* add it to our WINS cache of names. give it 2 hours in the cache */
-  DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr)));
-
-  return add_name_to_subnet(wins_server_subnet,qname,name_type,
-                            NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr);
-}
+       if (!addr.s_addr) {
+               /* add the fail to WINS cache of names. give it 1 hour in the cache */
+               DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname));
+               add_name_to_subnet( wins_server_subnet, qname, name_type,
+                               NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr );
+               return NULL;
+       }
 
+       /* add it to our WINS cache of names. give it 2 hours in the cache */
+       DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr)));
 
+       add_name_to_subnet( wins_server_subnet, qname, name_type,
+                              NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr);
+
+       return find_name_on_subnet(wins_server_subnet, question, FIND_ANY_NAME);
+}
 
 #ifndef SYNC_DNS
 
 static int fd_in = -1, fd_out = -1;
-static int child_pid = -1;
+static pid_t child_pid = -1;
 static int in_dns;
 
 /* this is the structure that is passed between the parent and child */
@@ -72,6 +70,7 @@ static struct packet_struct *dns_current;
   return the fd used to gather async dns replies. This is added to the select
   loop
   ****************************************************************************/
+
 int asyncdns_fd(void)
 {
        return fd_in;
@@ -83,7 +82,7 @@ int asyncdns_fd(void)
 static void asyncdns_process(void)
 {
        struct query_record r;
-       fstring qname;
+       unstring qname;
 
        DEBUGLEVEL = -1;
 
@@ -91,8 +90,7 @@ static void asyncdns_process(void)
                if (read_data(fd_in, (char *)&r, sizeof(r)) != sizeof(r)) 
                        break;
 
-               fstrcpy(qname, r.name.name);
-
+               pull_ascii_nstring( qname, sizeof(qname), r.name.name);
                r.result.s_addr = interpret_addr(qname);
 
                if (write_data(fd_out, (char *)&r, sizeof(r)) != sizeof(r))
@@ -103,17 +101,29 @@ static void asyncdns_process(void)
 }
 
 /**************************************************************************** **
-  catch a sigterm
+  catch a sigterm (in the child process - the parent has a different handler
+  see nmbd.c for details).
   We need a separate term handler here so we don't release any 
   names that our parent is going to release, or overwrite a 
   WINS db that our parent is going to write.
  **************************************************************************** */
 
-static int sig_term()
+static void sig_term(int sig)
 {
-  _exit(0);
-  /* Keep compiler happy.. */
-  return 0;
+       _exit(0);
+}
+
+/***************************************************************************
+ Called by the parent process when it receives a SIGTERM - also kills the
+ child so we don't get child async dns processes lying around, causing trouble.
+  ****************************************************************************/
+
+void kill_async_dns_child(void)
+{
+       if (child_pid > 0) {
+               kill(child_pid, SIGTERM);
+               child_pid = -1;
+       }
 }
 
 /***************************************************************************
@@ -123,29 +133,31 @@ void start_async_dns(void)
 {
        int fd1[2], fd2[2];
 
-       signal(SIGCLD, SIG_IGN);
+       CatchChild();
 
        if (pipe(fd1) || pipe(fd2)) {
+               DEBUG(0,("can't create asyncdns pipes\n"));
                return;
        }
 
-       child_pid = fork();
+       child_pid = sys_fork();
 
        if (child_pid) {
                fd_in = fd1[0];
                fd_out = fd2[1];
                close(fd1[1]);
                close(fd2[0]);
+               DEBUG(0,("started asyncdns process %d\n", (int)child_pid));
                return;
        }
 
        fd_in = fd2[0];
        fd_out = fd1[1];
 
-       signal(SIGUSR2, SIG_IGN);
-       signal(SIGUSR1, SIG_IGN);
-       signal(SIGHUP, SIG_IGN);
-        signal(SIGTERM, SIGNAL_CAST sig_term );
+       CatchSignal(SIGUSR2, SIG_IGN);
+       CatchSignal(SIGUSR1, SIG_IGN);
+       CatchSignal(SIGHUP, SIG_IGN);
+        CatchSignal(SIGTERM, SIGNAL_CAST sig_term );
 
        asyncdns_process();
 }
@@ -187,8 +199,12 @@ void run_dns_queue(void)
        if (fd_in == -1)
                return;
 
-       if (!process_exists(child_pid)) {
+        /* Allow SIGTERM to kill us. */
+        BlockSignals(False, SIGTERM);
+
+       if (!process_exists_by_pid(child_pid)) {
                close(fd_in);
+               close(fd_out);
                start_async_dns();
        }
 
@@ -197,19 +213,22 @@ void run_dns_queue(void)
                        DEBUG(0,("Incomplete DNS answer from child!\n"));
                        fd_in = -1;
                }
+                BlockSignals(True, SIGTERM);
                return;
        }
 
+        BlockSignals(True, SIGTERM);
+
        namerec = add_dns_result(&r.name, r.result);
 
        if (dns_current) {
                if (query_current(&r)) {
                        DEBUG(3,("DNS calling send_wins_name_query_response\n"));
                        in_dns = 1;
-                        if(namerec == NULL)
-                          send_wins_name_query_response(NAM_ERR, dns_current, NULL);
-                        else
-                         send_wins_name_query_response(0,dns_current,namerec);
+                       if(namerec == NULL)
+                               send_wins_name_query_response(NAM_ERR, dns_current, NULL);
+                       else
+                               send_wins_name_query_response(0,dns_current,namerec);
                        in_dns = 0;
                }
 
@@ -227,10 +246,10 @@ void run_dns_queue(void)
                if (nmb_name_equal(question, &r.name)) {
                        DEBUG(3,("DNS calling send_wins_name_query_response\n"));
                        in_dns = 1;
-                        if(namerec == NULL)
-                         send_wins_name_query_response(NAM_ERR, p, NULL);
-                        else
-                          send_wins_name_query_response(0,p,namerec);
+                       if(namerec == NULL)
+                               send_wins_name_query_response(NAM_ERR, p, NULL);
+                       else
+                               send_wins_name_query_response(0,p,namerec);
                        in_dns = 0;
                        p->locked = False;
 
@@ -251,7 +270,8 @@ void run_dns_queue(void)
        if (dns_queue) {
                dns_current = dns_queue;
                dns_queue = dns_queue->next;
-               if (dns_queue) dns_queue->prev = NULL;
+               if (dns_queue)
+                       dns_queue->prev = NULL;
                dns_current->next = NULL;
 
                if (!write_child(dns_current)) {
@@ -259,14 +279,13 @@ void run_dns_queue(void)
                        return;
                }
        }
-
 }
 
 /***************************************************************************
 queue a DNS query
   ****************************************************************************/
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
-                    struct name_record **n)
+
+BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question)
 {
        if (in_dns || fd_in == -1)
                return False;
@@ -287,7 +306,7 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
                dns_queue = p;
        }
 
-       DEBUG(3,("added DNS query for %s\n", namestr(question)));
+       DEBUG(3,("added DNS query for %s\n", nmb_namestr(question)));
        return True;
 }
 
@@ -295,23 +314,42 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
 
 
 /***************************************************************************
-  we use this then we can't do async DNS lookups
+  we use this when we can't do async DNS lookups
   ****************************************************************************/
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
-                    struct name_record **n)
+
+BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question)
 {
-       char *qname = question->name;
+       struct name_record *namerec = NULL;
        struct in_addr dns_ip;
+       unstring qname;
+
+       pull_ascii_nstring(qname, sizeof(qname), question->name);
 
-       DEBUG(3,("DNS search for %s - ", namestr(question)));
+       DEBUG(3,("DNS search for %s - ", nmb_namestr(question)));
+
+        /* Unblock TERM signal so we can be killed in DNS lookup. */
+        BlockSignals(False, SIGTERM);
 
        dns_ip.s_addr = interpret_addr(qname);
 
-       *n = add_dns_result(question, dns_ip);
-        if(*n == NULL)
-          send_wins_name_query_response(NAM_ERR, p, NULL);
-        else
-          send_wins_name_query_response(0, p, *n);
+        /* Re-block TERM signal. */
+        BlockSignals(True, SIGTERM);
+
+       namerec = add_dns_result(question, dns_ip);
+       if(namerec == NULL) {
+               send_wins_name_query_response(NAM_ERR, p, NULL);
+       } else {
+               send_wins_name_query_response(0, p, namerec);
+       }
        return False;
 }
+
+/***************************************************************************
+ With sync dns there is no child to kill on SIGTERM.
+  ****************************************************************************/
+
+void kill_async_dns_child(void)
+{
+       return;
+}
 #endif