first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[kai/samba.git] / source3 / nmbd / nmbd_packets.c
index 10ce2da0c1eb40bcb8c91d56261c6289d7c53853..0a7696a46631a1e26ada3206c8e37c96ca2eca80 100644 (file)
@@ -37,6 +37,9 @@ extern struct in_addr loopback_ip;
 
 static void queue_packet(struct packet_struct *packet);
 
+BOOL rescan_listen_set = False;
+
+
 /*******************************************************************
   The global packet linked-list. Incoming entries are 
   added to the end of this list. It is supposed to remain fairly 
@@ -114,7 +117,7 @@ static void debug_browse_data(char *outbuf, int len)
       DEBUGADD( 4, ( "%c", x ) );
     }
 
-    DEBUGADD( 4, ( " hex ") );
+    DEBUGADD( 4, ( "%*s hex", 16-j, "" ) );
 
     for (j = 0; j < 16; j++)
     {
@@ -138,7 +141,7 @@ static uint16 generate_name_trn_id(void)
 
   if (!name_trn_id)
   {
-    name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
+    name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)getpid()%(unsigned)100);
   }
   name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
   return name_trn_id;
@@ -192,7 +195,7 @@ static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmb
     return NULL;
   }
     
-  bzero((char *)packet,sizeof(*packet));
+  memset((char *)packet,'\0',sizeof(*packet));
 
   nmb = &packet->packet.nmb;
 
@@ -239,13 +242,17 @@ static BOOL create_and_init_additional_record(struct packet_struct *packet,
     return False;
   }
 
-  bzero((char *)nmb->additional,sizeof(struct res_rec));
+  memset((char *)nmb->additional,'\0',sizeof(struct res_rec));
 
   nmb->additional->rr_name  = nmb->question.question_name;
   nmb->additional->rr_type  = RR_TYPE_NB;
   nmb->additional->rr_class = RR_CLASS_IN;
 
-  nmb->additional->ttl = lp_max_ttl();
+  /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
+  if (nmb->header.nm_flags.bcast)
+    nmb->additional->ttl = PERMANENT_TTL;
+  else
+    nmb->additional->ttl = lp_max_ttl();
 
   nmb->additional->rdlength = 6;
 
@@ -279,7 +286,7 @@ static BOOL initiate_name_query_packet( struct packet_struct *packet)
   nmb->header.nm_flags.recursion_desired = True;
 
   DEBUG(4,("initiate_name_query_packet: sending query for name %s (bcast=%s) to IP %s\n",
-          namestr(&nmb->question.question_name), 
+          nmb_namestr(&nmb->question.question_name), 
            BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
 
   return send_netbios_packet( packet );
@@ -301,7 +308,7 @@ static BOOL initiate_name_query_packet_from_wins_server( struct packet_struct *p
   nmb->header.nm_flags.recursion_desired = False;
   
   DEBUG(4,("initiate_name_query_packet_from_wins_server: sending query for name %s (bcast=%s) to IP %s\n",
-           namestr(&nmb->question.question_name),
+           nmb_namestr(&nmb->question.question_name),
            BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
     
   return send_netbios_packet( packet );
@@ -325,7 +332,7 @@ static BOOL initiate_name_register_packet( struct packet_struct *packet,
     return False;
 
   DEBUG(4,("initiate_name_register_packet: sending registration for name %s (bcast=%s) to IP %s\n",
-          namestr(&nmb->additional->rr_name),
+          nmb_namestr(&nmb->additional->rr_name),
            BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
 
   return send_netbios_packet( packet );
@@ -353,7 +360,7 @@ static BOOL initiate_multihomed_name_register_packet( struct packet_struct *pack
 
   DEBUG(4,("initiate_multihomed_name_register_packet: sending registration \
 for name %s IP %s (bcast=%s) to IP %s\n",
-          namestr(&nmb->additional->rr_name), inet_ntoa(*register_ip),
+          nmb_namestr(&nmb->additional->rr_name), inet_ntoa(*register_ip),
            BOOLSTR(nmb->header.nm_flags.bcast), second_ip_buf ));
 
   return send_netbios_packet( packet );
@@ -377,7 +384,7 @@ static BOOL initiate_name_refresh_packet( struct packet_struct *packet,
     return False;
 
   DEBUG(4,("initiate_name_refresh_packet: sending refresh for name %s (bcast=%s) to IP %s\n",
-          namestr(&nmb->additional->rr_name),
+          nmb_namestr(&nmb->additional->rr_name),
            BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
 
   return send_netbios_packet( packet );
@@ -401,7 +408,7 @@ static BOOL initiate_name_release_packet( struct packet_struct *packet,
     return False;
 
   DEBUG(4,("initiate_name_release_packet: sending release for name %s (bcast=%s) to IP %s\n",
-          namestr(&nmb->additional->rr_name),
+          nmb_namestr(&nmb->additional->rr_name),
            BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
 
   return send_netbios_packet( packet );
@@ -423,7 +430,7 @@ static BOOL initiate_node_status_packet( struct packet_struct *packet )
   nmb->question.question_type = QUESTION_TYPE_NB_STATUS;
 
   DEBUG(4,("initiate_node_status_packet: sending node status request for name %s to IP %s\n",
-          namestr(&nmb->question.question_name),
+          nmb_namestr(&nmb->question.question_name),
            inet_ntoa(packet->ip)));
 
   return send_netbios_packet( packet );
@@ -898,7 +905,7 @@ void reply_netbios_packet(struct packet_struct *orig_packet,
     default:
     {
       DEBUG(0,("reply_netbios_packet: Unknown packet type: %s %s to ip %s\n",
-                   packet_type, namestr(&orig_nmb->question.question_name),
+                   packet_type, nmb_namestr(&orig_nmb->question.question_name),
                     inet_ntoa(packet.ip)));
 
       return;
@@ -907,7 +914,7 @@ void reply_netbios_packet(struct packet_struct *orig_packet,
 
   DEBUG(4,("reply_netbios_packet: sending a reply of packet type: %s %s to ip %s \
 for id %hu\n",
-          packet_type, namestr(&orig_nmb->question.question_name),
+          packet_type, nmb_namestr(&orig_nmb->question.question_name),
            inet_ntoa(packet.ip), orig_nmb->header.name_trn_id));
 
   nmb->header.name_trn_id = orig_nmb->header.name_trn_id;
@@ -923,10 +930,10 @@ for id %hu\n",
   nmb->header.nscount = 0;
   nmb->header.arcount = 0;
   
-  bzero((char*)&nmb->question,sizeof(nmb->question));
+  memset((char*)&nmb->question,'\0',sizeof(nmb->question));
   
   nmb->answers = &answers;
-  bzero((char*)nmb->answers,sizeof(*nmb->answers));
+  memset((char*)nmb->answers,'\0',sizeof(*nmb->answers));
   
   nmb->answers->rr_name  = orig_nmb->question.question_name;
   nmb->answers->rr_type  = orig_nmb->question.question_type;
@@ -1033,7 +1040,7 @@ mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, scop
   if (is_myname(dgram->source_name.name))
   {
     DEBUG(0,("process_browse_packet: Discarding datagram from IP %s. Source name \
-%s is one of our names !\n", inet_ntoa(p->ip), namestr(&dgram->source_name)));
+%s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name)));
     return;
   }
 
@@ -1072,15 +1079,6 @@ mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, scop
     case ANN_GetBackupListReq:
     {
       debug_browse_data(buf, len);
-
-      /* This is one occasion where we change a subnet that is
-        given to us. If the packet was sent to WORKGROUP<1b> instead
-        of WORKGROUP<1d> then it was unicast to us a domain master
-        browser. Change subrec to unicast.
-      */
-      if(dgram->dest_name.name_type == 0x1b)
-        subrec = unicast_subnet;
-
       process_get_backup_list_request(subrec, p, buf+1);
       break;
     }
@@ -1090,7 +1088,7 @@ mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, scop
       /* We never send ANN_GetBackupListReq so we
          should never get these. */
       DEBUG(0,("process_browse_packet: Discarding GetBackupListResponse \
-packet from %s IP %s\n", namestr(&dgram->source_name), inet_ntoa(p->ip)));
+packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip)));
       break;
     }
     case ANN_ResetBrowserState:
@@ -1117,8 +1115,8 @@ packet from %s IP %s\n", namestr(&dgram->source_name), inet_ntoa(p->ip)));
       debug_browse_data(buf, len);
       DEBUG(10,("process_browse_packet: On subnet %s ignoring browse packet \
 command ANN_BecomeBackup from %s IP %s to %s\n",
-            subrec->subnet_name, namestr(&dgram->source_name),
-            inet_ntoa(p->ip), namestr(&dgram->dest_name)));
+            subrec->subnet_name, nmb_namestr(&dgram->source_name),
+            inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
       break;
     }
     default:
@@ -1126,8 +1124,8 @@ command ANN_BecomeBackup from %s IP %s to %s\n",
       debug_browse_data(buf, len);
       DEBUG(0,("process_browse_packet: On subnet %s ignoring browse packet \
 command code %d from %s IP %s to %s\n", 
-            subrec->subnet_name, command, namestr(&dgram->source_name),
-            inet_ntoa(p->ip), namestr(&dgram->dest_name)));
+            subrec->subnet_name, command, nmb_namestr(&dgram->source_name),
+            inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
     }
   } 
 }
@@ -1154,7 +1152,7 @@ mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, scop
   if (is_myname(dgram->source_name.name))
   {
     DEBUG(0,("process_lanman_packet: Discarding datagram from IP %s. Source name \
-%s is one of our names !\n", inet_ntoa(p->ip), namestr(&dgram->source_name)));
+%s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name)));
     return;
   }
 
@@ -1175,8 +1173,8 @@ mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, scop
     {
       DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \
 command code %d from %s IP %s to %s\n",
-            subrec->subnet_name, command, namestr(&dgram->source_name),
-            inet_ntoa(p->ip), namestr(&dgram->dest_name)));
+            subrec->subnet_name, command, nmb_namestr(&dgram->source_name),
+            inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
     }
   }
 }
@@ -1218,7 +1216,7 @@ static void process_dgram(struct packet_struct *p)
   if (!listening(p,&dgram->dest_name))
   {
     DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n",
-           namestr(&dgram->dest_name), inet_ntoa(p->ip)));
+           nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip)));
     return;
   }
 
@@ -1229,7 +1227,7 @@ static void process_dgram(struct packet_struct *p)
     /* Don't process error packets etc yet */
     DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \
            an error packet of type %x\n",
-           namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type));
+           nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type));
     return;
   }
 
@@ -1244,7 +1242,7 @@ static void process_dgram(struct packet_struct *p)
   buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
 
   DEBUG(4,("process_dgram: datagram from %s to %s IP %s for %s of type %d len=%d\n",
-          namestr(&dgram->source_name),namestr(&dgram->dest_name),
+          nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name),
           inet_ntoa(p->ip), smb_buf(buf),CVAL(buf2,0),len));
 
  
@@ -1633,16 +1631,31 @@ to IP %s on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip),
 on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), 
                  subrec->subnet_name));
 
-          /* Call the timeout function. This will deal with removing the
-             timed out packet. */
-          if(rrec->timeout_fn)
-            (*rrec->timeout_fn)(subrec, rrec);
-          else
+          /*
+           * Check the flag in this record to prevent recursion if we end
+           * up in this function again via the timeout function call.
+           */
+
+          if(!rrec->in_expiration_processing)
           {
-            /* We must remove the record ourself if there is
-               no timeout function. */
-            remove_response_record(subrec, rrec);
-          }
+
+            /*
+             * Set the recursion protection flag in this record.
+             */
+
+            rrec->in_expiration_processing = True;
+
+            /* Call the timeout function. This will deal with removing the
+               timed out packet. */
+            if(rrec->timeout_fn)
+              (*rrec->timeout_fn)(subrec, rrec);
+            else
+            {
+              /* We must remove the record ourself if there is
+                 no timeout function. */
+              remove_response_record(subrec, rrec);
+            }
+          } /* !rrec->in_expitation_processing */
         } /* rrec->repeat_count > 0 */
       } /* rrec->repeat_time <= t */
     } /* end for rrec */
@@ -1710,6 +1723,10 @@ only use %d.\n", (count*2) + 2, FD_SETSIZE));
   }
 
   *listen_number = (count*2) + 2;
+
+  if (*ppset) free(*ppset);
+  if (*psock_array) free(*psock_array);
+
   *ppset = pset;
   *psock_array = sock_array;
  
@@ -1733,13 +1750,14 @@ BOOL listen_for_packets(BOOL run_election)
   int dns_fd;
 #endif
 
-  if(listen_set == NULL)
+  if(listen_set == NULL || rescan_listen_set)
   {
     if(create_listen_fdset(&listen_set, &sock_array, &listen_number))
     {
       DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n"));
       return True;
     }
+    rescan_listen_set = False;
   }
 
   memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set));
@@ -1772,7 +1790,7 @@ BOOL listen_for_packets(BOOL run_election)
   BlockSignals(False, SIGUSR2);
 #endif /* SIGUSR2 */
 
-  selrtn = sys_select(256,&fds,&timeout);
+  selrtn = sys_select(FD_SETSIZE,&fds,&timeout);
 
   /* We can only take signals when we are in the select - block them again here. */
 
@@ -1887,7 +1905,7 @@ BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len,
   char *ptr,*p2;
   char tmp[4];
 
-  bzero((char *)&p,sizeof(p));
+  memset((char *)&p,'\0',sizeof(p));
 
   if(ismyip(dest_ip))
     loopback_this_packet = True;
@@ -1940,8 +1958,8 @@ BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len,
   p.packet_type = DGRAM_PACKET;
 
   DEBUG(4,("send_mailslot: Sending to mailslot %s from %s IP %s ", mailslot,
-                    namestr(&dgram->source_name), inet_ntoa(src_ip)));
-  DEBUG(4,("to %s IP %s\n", namestr(&dgram->dest_name), inet_ntoa(dest_ip)));
+                    nmb_namestr(&dgram->source_name), inet_ntoa(src_ip)));
+  DEBUG(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), inet_ntoa(dest_ip)));
 
   debug_browse_data(buf, len);