namepacket.c: Block SIGTERM correctly - we can only take them at defined points.
[samba.git] / source3 / namepacket.c
index 5bfa55d4f1646645c4788f97588a99dd3cb6b943..418155bbd85b1fa19baa70093f432c3a1e39becc 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-1995
+   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 num_response_packets;
 
 BOOL CanRecurse = True;
 extern pstring scope;
-extern struct in_addr ipgrp;
+extern struct in_addr wins_ip;
 
 static uint16 name_trn_id=0;
 
@@ -91,9 +91,9 @@ static void update_name_trn_id(void)
   initiate a netbios packet
   ****************************************************************************/
 void initiate_netbios_packet(uint16 *id,
-                               int fd,int quest_type,char *name,int name_type,
-                           int nb_flags,BOOL bcast,BOOL recurse,
-                           struct in_addr to_ip)
+                            int fd,int quest_type,char *name,int name_type,
+                            int nb_flags,BOOL bcast,BOOL recurse,
+                            struct in_addr to_ip)
 {
   struct packet_struct p;
   struct nmb_packet *nmb = &p.packet.nmb;
@@ -141,28 +141,29 @@ void initiate_netbios_packet(uint16 *id,
   
   make_nmb_name(&nmb->question.question_name,name,name_type,scope);
   
-  nmb->question.question_type = quest_type;
+  nmb->question.question_type = quest_type == NMB_STATUS ? 0x21 : 0x20;
   nmb->question.question_class = 0x1;
   
   if (quest_type == NMB_REG ||
       quest_type == NMB_REG_REFRESH ||
       quest_type == NMB_REL)
-    {
+  {
       nmb->additional = &additional_rec;
       bzero((char *)nmb->additional,sizeof(*nmb->additional));
       
       nmb->additional->rr_name  = nmb->question.question_name;
-      nmb->additional->rr_type  = nmb->question.question_type;
-      nmb->additional->rr_class = nmb->question.question_class;
+      nmb->additional->rr_type  = 0x20;
+      nmb->additional->rr_class = 0x1;
       
       if (quest_type == NMB_REG || quest_type == NMB_REG_REFRESH)
-       nmb->additional->ttl = lp_max_ttl();
+        nmb->additional->ttl = lp_max_ttl();
       else
-       nmb->additional->ttl = 0;
+        nmb->additional->ttl = 0;
+
       nmb->additional->rdlength = 6;
       nmb->additional->rdata[0] = nb_flags;
       putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
-    }
+  }
   
   p.ip = to_ip;
   p.port = NMB_PORT;
@@ -170,6 +171,8 @@ void initiate_netbios_packet(uint16 *id,
   p.timestamp = time(NULL);
   p.packet_type = NMB_PACKET;
   
+  debug_nmb_packet(&p);
+  
   if (!send_packet(&p)) {
     DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port));
     *id = 0xffff;
@@ -252,7 +255,7 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id,
   nmb->header.ancount = 1;
   nmb->header.nscount = 0;
   nmb->header.arcount = 0;
-  nmb->header.rcode = 0;
+  nmb->header.rcode = rcode;
   
   bzero((char*)&nmb->question,sizeof(nmb->question));
   
@@ -320,8 +323,10 @@ static BOOL listening(struct packet_struct *p,struct nmb_name *n)
   struct subnet_record *d;
   struct name_record *n1;
 
+  /* We explicitly don't search WINS here - this will be done
+     in find_name_search if it was a packet from a non-local subnet. */
   d = find_subnet(p->ip);
-  
+
   n1 = find_name_search(&d,n,FIND_LOCAL|FIND_WINS|FIND_SELF,p->ip);
 
   return (n1 != NULL);
@@ -340,13 +345,21 @@ static void process_dgram(struct packet_struct *p)
 
   /* if we aren't listening to the destination name then ignore the packet */
   if (!listening(p,&dgram->dest_name))
+  {
+    DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s(%x) from %s\n",
+           dgram->dest_name.name, dgram->dest_name.name_type, inet_ntoa(p->ip)));
     return;
-
+  }
 
   if (dgram->header.msg_type != 0x10 &&
       dgram->header.msg_type != 0x11 &&
-      dgram->header.msg_type != 0x12) {
+      dgram->header.msg_type != 0x12) 
+  {
     /* don't process error packets etc yet */
+    DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s(%d) from %s as it is \
+           an error packet of type %x\n",
+           dgram->dest_name.name, dgram->dest_name.name_type, 
+           inet_ntoa(p->ip), dgram->header.msg_type));
     return;
   }
 
@@ -359,7 +372,7 @@ static void process_dgram(struct packet_struct *p)
   len = SVAL(buf,smb_vwv11);
   buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
 
-  DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n",
+  DEBUG(4,("process_dgram: datagram from %s to %s for %s of type %d len=%d\n",
           namestr(&dgram->source_name),namestr(&dgram->dest_name),
           smb_buf(buf),CVAL(buf2,0),len));
 
@@ -394,12 +407,17 @@ static void process_nmb(struct packet_struct *p)
     case NMB_REG:
     case NMB_REG_REFRESH:
     {
-       if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
        if (nmb->header.response)
+        {
+          if (nmb->header.ancount ==0) break;
          response_netbios_packet(p); /* response to registration dealt 
                                         with here */
+        }
        else
+        {
+          if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
          reply_name_reg(p);
+        }
        break;
     }
       
@@ -439,17 +457,17 @@ static void process_nmb(struct packet_struct *p)
       
     case NMB_REL:
     {
-      if (nmb->header.qdcount==0 || nmb->header.arcount==0)
-         {
-           DEBUG(2,("netbios release packet rejected\n"));
-           break;
-         }
-       
        if (nmb->header.response)
-         response_netbios_packet(p); /* response to reply dealt with 
-                                        in here */
+        {
+          if (nmb->header.ancount ==0) break;
+         response_netbios_packet(p); /* response to release dealt 
+                                        with here */
+        }
        else
+        {
+          if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
          reply_name_release(p);
+        }
       break;
     }
   }
@@ -487,58 +505,63 @@ void run_packet_queue()
   ***************************************************************************/
 void listen_for_packets(BOOL run_election)
 {
-  fd_set fds;
-  int selrtn;
-  struct timeval timeout;
+       fd_set fds;
+       int selrtn;
+       struct timeval timeout;
 
-try_again:
+       FD_ZERO(&fds);
+       FD_SET(ClientNMB,&fds);
+       FD_SET(ClientDGRAM,&fds);
 
-  FD_ZERO(&fds);
-  FD_SET(ClientNMB,&fds);
-  FD_SET(ClientDGRAM,&fds);
+       /* during elections and when expecting a netbios response packet we
+       need to send election packets at tighter intervals 
 
-  /* during elections and when expecting a netbios response packet we
-     need to send election packets at tighter intervals 
+       ideally it needs to be the interval (in ms) between time now and
+       the time we are expecting the next netbios packet */
 
-     ideally it needs to be the interval (in ms) between time now and
-     the time we are expecting the next netbios packet */
+       timeout.tv_sec = (run_election||num_response_packets) ? 1:NMBD_SELECT_LOOP;
+       timeout.tv_usec = 0;
 
-  timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
-  timeout.tv_usec = 0;
+        /* We can only take term signals when we are in the select. */
+        BlockSignals(False, SIGTERM);
+       selrtn = sys_select(&fds,&timeout);
+        BlockSignals(True, SIGTERM);
 
-  selrtn = sys_select(&fds,&timeout);
-
-  if (FD_ISSET(ClientNMB,&fds))
-    {
-      struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
-      if (packet) {
-       if (ismyip(packet->ip) &&
-           (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
-         DEBUG(7,("discarding own packet from %s:%d\n",
-                  inet_ntoa(packet->ip),packet->port));          
-         free_packet(packet);
-         goto try_again;
-       } else {
-         queue_packet(packet);
+       if (FD_ISSET(ClientNMB,&fds))
+       {
+               struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
+               if (packet)
+               {
+                       if (ismyip(packet->ip) && packet->port == NMB_PORT)
+                       {
+                               DEBUG(7,("discarding own packet from %s:%d\n",
+                                         inet_ntoa(packet->ip),packet->port));   
+                               free_packet(packet);
+                       }
+                       else
+                       {
+                               queue_packet(packet);
+                       }
+               }
        }
-      }
-    }
 
-  if (FD_ISSET(ClientDGRAM,&fds))
-    {
-      struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
-      if (packet) {
-       if (ismyip(packet->ip) &&
-             (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
-         DEBUG(7,("discarding own packet from %s:%d\n",
-                  inet_ntoa(packet->ip),packet->port));          
-         free_packet(packet);
-         goto try_again;
-       } else {
-         queue_packet(packet);
+       if (FD_ISSET(ClientDGRAM,&fds))
+       {
+               struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
+               if (packet)
+               {
+                       if (ismyip(packet->ip) && packet->port == DGRAM_PORT)
+                       {
+                               DEBUG(7,("discarding own packet from %s:%d\n",
+                                         inet_ntoa(packet->ip),packet->port));   
+                               free_packet(packet);
+                       }
+                       else
+                       {
+                               queue_packet(packet);
+                       }
+               }
        }
-      }
-    }
 }
 
 
@@ -549,13 +572,12 @@ try_again:
   Note that this currently sends all answers to port 138. thats the
   wrong things to do! I should send to the requestors port. XXX
   **************************************************************************/
-BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
+BOOL send_mailslot_reply(BOOL unique, char *mailslot,int fd,char *buf,int len,char *srcname,
                         char *dstname,int src_type,int dest_type,
                         struct in_addr dest_ip,struct in_addr src_ip)
 {
   struct packet_struct p;
   struct dgram_packet *dgram = &p.packet.dgram;
-  struct in_addr wins_ip = ipgrp;
   char *ptr,*p2;
   char tmp[4];
 
@@ -566,7 +588,8 @@ BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
 
   update_name_trn_id();
 
-  dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
+  /* DIRECT GROUP or UNIQUE datagram */
+  dgram->header.msg_type = unique ? 0x10 : 0x11; 
   dgram->header.flags.node_type = M_NODE;
   dgram->header.flags.first = True;
   dgram->header.flags.more = False;