namepacket.c: Block SIGTERM correctly - we can only take them at defined points.
[samba.git] / source3 / nameservreply.c
index b01c2c25b4cc51ec43fe18b57fbd2857230d0ecd..9f7b3da70ba7cf8a9425f974907773398ad1f7bd 100644 (file)
@@ -2,7 +2,7 @@
    Unix SMB/Netbios implementation.
    Version 1.9.
    NBT netbios routines and daemon - version 2
-   Copyright (C) Andrew Tridgell 1994-1996
+   Copyright (C) Andrew Tridgell 1994-1997
    
    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
@@ -36,7 +36,7 @@ extern int ClientNMB;
 
 extern int DEBUGLEVEL;
 
-extern struct in_addr ipgrp;
+extern struct in_addr wins_ip;
 
 
 /****************************************************************************
@@ -120,35 +120,38 @@ void reply_name_release(struct packet_struct *p)
           namestr(&nmb->question.question_name)));
   
   if (!(d = find_req_subnet(p->ip, bcast)))
-  {
-    DEBUG(3,("response packet: bcast %s not known\n",
-                       inet_ntoa(p->ip)));
-    return;
-  }
+    {
+      DEBUG(3,("response packet: bcast %s not known\n",
+              inet_ntoa(p->ip)));
+      return;
+    }
 
   if (bcast)
-       search &= FIND_LOCAL;
+    search |= FIND_LOCAL;
   else
-       search &= FIND_WINS;
+    search |= FIND_WINS;
 
   n = find_name_search(&d, &nmb->question.question_name, 
-                                       search, ip);
+                      search, ip);
   
   /* XXXX under what conditions should we reject the removal?? */
-  if (n && n->ip_flgs[0].nb_flags == nb_flags)
-  {
+  /* For now - remove if the names match and the group bit matches. */
+  if (n && (NAME_GROUP(n->ip_flgs[0].nb_flags) == NAME_GROUP(nb_flags)))
+    {
       success = True;
       
+      DEBUG(5, ("reply_name_release: Removing name %s on subnet %s\n",
+                namestr(&nmb->question.question_name), inet_ntoa(d->bcast_ip)));
       remove_name(d,n);
       n = NULL;
-  }
+    }
   
   if (bcast) return;
   
   /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
   send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REL,
-                                               success, False,
-                                               &nmb->question.question_name, nb_flags, 0, ip);
+                    success, False,
+                    &nmb->question.question_name, nb_flags, 0, ip);
 }
 
 
@@ -183,33 +186,34 @@ void reply_name_reg(struct packet_struct *p)
   putip((char *)&from_ip,&nmb->additional->rdata[2]);
   ip = from_ip;
   
-  DEBUG(3,("Name registration for name %s at %s\n",
+  DEBUG(3,("Name registration for name %s at %s - ",
                   namestr(question),inet_ntoa(ip)));
   
   if (group)
     {
       /* apparently we should return 255.255.255.255 for group queries
         (email from MS) */
-      ip = ipgrp;
+      ip = wins_ip;
     }
   
   if (!(d = find_req_subnet(p->ip, bcast)))
   {
-    DEBUG(3,("response packet: bcast %s not known\n",
+    DEBUG(3,("reply_name_reg: subnet %s not known\n",
                                inet_ntoa(p->ip)));
     return;
   }
 
   if (bcast)
-       search &= FIND_LOCAL;
+       search |= FIND_LOCAL;
   else
-       search &= FIND_WINS;
+       search |= FIND_WINS;
 
   /* see if the name already exists */
   n = find_name_search(&d, question, search, from_ip);
   
   if (n)
   {
+    DEBUG(3,("found\n"));
     if (!group) /* unique names */
        {
          if (n->source == SELF || NAME_GROUP(n->ip_flgs[0].nb_flags))
@@ -259,6 +263,7 @@ void reply_name_reg(struct packet_struct *p)
   }
   else
   {
+      DEBUG(3,("not found\n"));
       /* add the name to our name/subnet, or WINS, database */
       n = add_netbios_entry(d,qname,qname_type,nb_flags,ttl,REGISTER,ip,
                                True,!bcast);
@@ -391,8 +396,8 @@ void reply_name_status(struct packet_struct *p)
       
       if (!strequal(n->name.name,"*") &&
          !strequal(n->name.name,"__SAMBA__") &&
-         (name_type < 0x1b || name_type > 0x20 || 
-          ques_type < 0x1b || ques_type > 0x20 ||
+         (name_type < 0x1b || name_type >= 0x20 || 
+          ques_type < 0x1b || ques_type >= 0x20 ||
           strequal(qname, n->name.name)))
       {
         /* start with first bit of putting info in buffer: the name */
@@ -431,7 +436,7 @@ void reply_name_status(struct packet_struct *p)
       /* end of this name list: add wins names too? */
       struct subnet_record *w_d;
 
-      if (!(w_d = find_subnet(ipgrp))) break;
+      if (!(w_d = wins_subnet)) break;
 
       if (w_d != d)
       {
@@ -458,10 +463,8 @@ void reply_name_status(struct packet_struct *p)
   reply_netbios_packet(p,nmb->header.name_trn_id,
                           0,NMB_STATUS,0,True,
                       &nmb->question.question_name,
-                      nmb->question.question_type,
-                      nmb->question.question_class,
-                      0,
-                      rdata,PTR_DIFF(buf,rdata));
+                      0x21, 0x01,
+                      0, rdata,PTR_DIFF(buf,rdata));
 }
 
 
@@ -502,19 +505,14 @@ void reply_name_query(struct packet_struct *p)
   char rdata[6];
   struct subnet_record *d = NULL;
   BOOL success = True;
-  struct name_record *n;
+  struct name_record *n = NULL;
 
   /* directed queries are for WINS server: broadcasts are local SELF queries.
      the exception is Domain Master names.  */
 
-  int search = bcast ? FIND_LOCAL | FIND_SELF : FIND_WINS;
-  
-  if (name_type == 0x1b)
-  {
-    search |= FIND_WINS;
-  }
+  int search = bcast ? FIND_LOCAL | FIND_WINS: FIND_WINS;
 
-  if (search | FIND_LOCAL)
+  if (search & FIND_LOCAL)
   {
     if (!(d = find_req_subnet(p->ip, bcast)))
     {
@@ -525,7 +523,7 @@ void reply_name_query(struct packet_struct *p)
   }
   else
   {
-    if (!(d = find_subnet(ipgrp)))
+    if (!(d = wins_subnet))
     {
       DEBUG(3,("name query: wins search %s not known\n",
                                    inet_ntoa(p->ip)));
@@ -533,7 +531,8 @@ void reply_name_query(struct packet_struct *p)
     }
   }
 
-  DEBUG(3,("Name query "));
+  DEBUG(3,("Name query from %s for name %s<0x%x>\n", 
+                  inet_ntoa(p->ip), question->name, question->name_type));
   
   if (search == 0)
   {
@@ -548,13 +547,42 @@ void reply_name_query(struct packet_struct *p)
     success = False;
   }
 
-  if (success && (n = search_for_name(&d,question,p->ip,p->timestamp, search)))
+  if (success)
   {
-      /* don't respond to broadcast queries unless the query is for
-         a name we own or it is for a Primary Domain Controller name */
+    /* look up the name in the cache */
+    n = find_name_search(&d, question, search, p->ip);
 
-      if (bcast && n->source != SELF && name_type != 0x1b) {
-           if (!lp_wins_proxy() || same_net(p->ip,n->ip_flgs[0].ip,*iface_nmask(p->ip))) {
+    /* it is a name that already failed DNS lookup or it's expired */
+    if (n && (n->source == DNSFAIL ||
+              (n->death_time && n->death_time < p->timestamp)))
+    {
+      success = False;
+    }
+   
+    /* do we want to do dns lookups? */
+    /* XXXX this DELAYS nmbd while it does a search. not a good idea
+       but there's no pleasant alternative. phil@hands.com suggested
+       making the name a full DNS name, which would succeed / fail
+       much quicker.
+     */
+    if (success && !n && (lp_wins_proxy() || !bcast))
+    {
+      n = dns_name_search(question, p->timestamp);
+    }
+  }
+
+  if (!n) success = False;
+  
+  if (success)
+  {
+      if (bcast && n->source != SELF && name_type != 0x1b)
+      {
+        /* don't respond to broadcast queries unless the query is for
+           a name we own or it is for a Primary Domain Controller name */
+
+           if (!lp_wins_proxy() || 
+            same_net(p->ip,n->ip_flgs[0].ip,*iface_nmask(p->ip)))
+        {
              /* never reply with a negative response to broadcast queries */
              return;
            }
@@ -574,12 +602,9 @@ void reply_name_query(struct packet_struct *p)
       retip = n->ip_flgs[0].ip;
       nb_flags = n->ip_flgs[0].nb_flags;
   }
-  else
-  {
-      if (bcast) return; /* never reply negative response to bcasts */
-      success = False;
-  }
-  
+
+  if (!success && bcast) return; /* never reply negative response to bcasts */
+
   /* if the IP is 0 then substitute my IP */
   if (zero_ip(retip)) retip = *iface_ip(p->ip);
 
@@ -604,10 +629,7 @@ void reply_name_query(struct packet_struct *p)
   reply_netbios_packet(p,nmb->header.name_trn_id,
                           rcode,NMB_QUERY,0,True,
                       &nmb->question.question_name,
-                      nmb->question.question_type,
-                      nmb->question.question_class,
+               0x20, 0x01,
                       ttl,
                       rdata, success ? 6 : 0);
 }
-
-