Change the multibyte character set support so that
[kai/samba.git] / source3 / nmbd / asyncdns.c
index a451f6b6176075d4f2a00498e3dc5d6c60268632..3fb16a08e94497993f4742e1a08d4bd14e205816 100644 (file)
@@ -1,8 +1,7 @@
 /*
    Unix SMB/Netbios implementation.
-   Version 1.9.
    a async DNS handler
-   Copyright (C) Andrew Tridgell 1994-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
    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.
-   
-   Revision History:
-
-   14 jan 96: lkcl@pires.co.uk
-   added multiple workgroup domain master support
-
-*/
+   */
 
 #include "includes.h"
 
 extern int DEBUGLEVEL;
 
-
 /***************************************************************************
-  add a DNS result to the name cache
-  ****************************************************************************/
+  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;
-
+  
+  
   if (!addr.s_addr) {
     /* add the fail to WINS cache of names. give it 1 hour in the cache */
-    DEBUG(3,("Negative DNS answer for %s\n", qname));
-    add_netbios_entry(wins_client_subnet,qname,name_type,NB_ACTIVE,60*60,
-                      DNSFAIL,addr,True);
+    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,("DNS gave answer for %s of %s\n", qname, inet_ntoa(addr)));
+  DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr)));
 
-  return add_netbios_entry(wins_client_subnet,qname,name_type,NB_ACTIVE,
-                           2*60*60,DNS,addr, True);
+  return add_name_to_subnet(wins_server_subnet,qname,name_type,
+                            NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr);
 }
 
 
@@ -108,6 +102,31 @@ static void asyncdns_process(void)
        _exit(0);
 }
 
+/**************************************************************************** **
+  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()
+{
+  _exit(0);
+  /* Keep compiler happy.. */
+  return 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()
+{
+  if(child_pid != 0 && child_pid != -1)
+    kill(child_pid, SIGTERM);
+}
 
 /***************************************************************************
   create a child process to handle DNS lookups
@@ -135,6 +154,11 @@ void start_async_dns(void)
        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 );
+
        asyncdns_process();
 }
 
@@ -145,7 +169,7 @@ check if a particular name is already being queried
 static BOOL query_current(struct query_record *r)
 {
        return dns_current &&
-               name_equal(&r->name, 
+               nmb_name_equal(&r->name, 
                           &dns_current->packet.nmb.question.question_name);
 }
 
@@ -169,23 +193,41 @@ void run_dns_queue(void)
 {
        struct query_record r;
        struct packet_struct *p, *p2;
+       struct name_record *namerec;
+       int size;
 
        if (fd_in == -1)
                return;
 
-       if (read_data(fd_in, (char *)&r, sizeof(r)) != sizeof(r)) {
-               DEBUG(0,("Incomplete DNS answer from child!\n"));
-               fd_in = -1;
+        /* Allow SIGTERM to kill us. */
+        BlockSignals(False, SIGTERM);
+
+       if (!process_exists(child_pid)) {
+               close(fd_in);
+               start_async_dns();
+       }
+
+       if ((size=read_data(fd_in, (char *)&r, sizeof(r))) != sizeof(r)) {
+               if (size) {
+                       DEBUG(0,("Incomplete DNS answer from child!\n"));
+                       fd_in = -1;
+               }
+                BlockSignals(True, SIGTERM);
                return;
        }
 
-       add_dns_result(&r.name, r.result);
+        BlockSignals(True, SIGTERM);
+
+       namerec = add_dns_result(&r.name, r.result);
 
        if (dns_current) {
                if (query_current(&r)) {
-                       DEBUG(3,("DNS calling reply_name_query\n"));
+                       DEBUG(3,("DNS calling send_wins_name_query_response\n"));
                        in_dns = 1;
-                       reply_name_query(dns_current);
+                        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;
                }
 
@@ -200,10 +242,13 @@ void run_dns_queue(void)
                struct nmb_packet *nmb = &p->packet.nmb;
                struct nmb_name *question = &nmb->question.question_name;
 
-               if (name_equal(question, &r.name)) {
-                       DEBUG(3,("DNS calling reply_name_query\n"));
+               if (nmb_name_equal(question, &r.name)) {
+                       DEBUG(3,("DNS calling send_wins_name_query_response\n"));
                        in_dns = 1;
-                       reply_name_query(p);
+                        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;
 
@@ -273,15 +318,32 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
 BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
                     struct name_record **n)
 {
-       int name_type = question->name_type;
        char *qname = question->name;
        struct in_addr dns_ip;
 
        DEBUG(3,("DNS search for %s - ", namestr(question)));
 
+        /* Unblock TERM signal so we can be killed in DNS lookup. */
+        BlockSignals(False, SIGTERM);
+
        dns_ip.s_addr = interpret_addr(qname);
 
+        /* Re-block TERM signal. */
+        BlockSignals(True, SIGTERM);
+
        *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);
        return False;
 }
+
+/***************************************************************************
+ With sync dns there is no child to kill on SIGTERM.
+  ****************************************************************************/
+void kill_async_dns_child()
+{
+  return;
+}
 #endif