[GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch.
[samba.git] / source / nmbd / nmbd_packets.c
index 4baf2d3d6cecab6c108c4f48cf9de5c8c456d052..875e13fdc8861f0a4128b54a41e7b45d4ec8c30e 100644 (file)
@@ -7,7 +7,7 @@
    
    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,
@@ -16,8 +16,7 @@
    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/>.
    
 */
 
@@ -536,6 +535,8 @@ void queue_wins_refresh(struct nmb_name *nmbname,
 
        userdata = (struct userdata_struct *)SMB_MALLOC(sizeof(*userdata) + strlen(tag) + 1);
        if (!userdata) {
+               p->locked = False;
+               free_packet(p);
                DEBUG(0,("Failed to allocate userdata structure!\n"));
                return;
        }
@@ -765,7 +766,7 @@ struct response_record *queue_query_name( struct subnet_record *subrec,
 /****************************************************************************
  Queue a query name packet to a given address from the WINS subnet.
 ****************************************************************************/
+
 struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip,
                           response_function resp_fn,
                           timeout_response_function timeout_fn,
@@ -804,7 +805,7 @@ struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip,
 /****************************************************************************
  Queue a node status packet to a given name and address.
 ****************************************************************************/
+
 struct response_record *queue_node_status( struct subnet_record *subrec,
                           response_function resp_fn,
                           timeout_response_function timeout_fn,
@@ -834,7 +835,7 @@ unicast subnet. subnet is %s\n.", subrec->subnet_name ));
                p->locked = False;
                free_packet(p);
                return NULL;
-       } 
+       }
 
        if((rrec = make_response_record(subrec,           /* subnet record. */
                                        p,                     /* packet we sent. */
@@ -866,11 +867,11 @@ void reply_netbios_packet(struct packet_struct *orig_packet,
        BOOL loopback_this_packet = False;
        int rr_type = RR_TYPE_NB;
        const char *packet_type = "unknown";
-  
+
        /* Check if we are sending to or from ourselves. */
        if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port))
                loopback_this_packet = True;
-  
+
        nmb = &packet.packet.nmb;
 
        /* Do a partial copy of the packet. We clear the locked flag and
@@ -943,28 +944,28 @@ for id %hu\n", packet_type, nmb_namestr(&orig_nmb->question.question_name),
        nmb->header.nm_flags.bcast = False;
        nmb->header.nm_flags.trunc = False;
        nmb->header.nm_flags.authoritative = True;
-  
+
        nmb->header.rcode = rcode;
        nmb->header.qdcount = 0;
        nmb->header.ancount = 1;
        nmb->header.nscount = 0;
        nmb->header.arcount = 0;
-  
+
        memset((char*)&nmb->question,'\0',sizeof(nmb->question));
-  
+
        nmb->answers = &answers;
        memset((char*)nmb->answers,'\0',sizeof(*nmb->answers));
-  
+
        nmb->answers->rr_name  = orig_nmb->question.question_name;
        nmb->answers->rr_type  = rr_type;
        nmb->answers->rr_class = RR_CLASS_IN;
        nmb->answers->ttl      = ttl;
-  
+
        if (data && len) {
                nmb->answers->rdlength = len;
                memcpy(nmb->answers->rdata, data, len);
        }
-  
+
        packet.packet_type = NMB_PACKET;
        /* Ensure we send out on the same fd that the original
                packet came in on to give the correct source IP address. */
@@ -972,7 +973,7 @@ for id %hu\n", packet_type, nmb_namestr(&orig_nmb->question.question_name),
        packet.timestamp = time(NULL);
 
        debug_nmb_packet(&packet);
-  
+
        if(loopback_this_packet) {
                struct packet_struct *lo_packet;
                DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n"));
@@ -999,9 +1000,9 @@ static void queue_packet(struct packet_struct *packet)
                packet_queue = packet;
                return;
        }
-  
+
        /* find the bottom */
-       for (p=packet_queue;p->next;p=p->next) 
+       for (p=packet_queue;p->next;p=p->next)
                ;
 
        p->next = packet;
@@ -1103,7 +1104,7 @@ packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip)));
                        process_master_browser_announce(subrec, p, buf+1);
                        break;
                case ANN_BecomeBackup:
-                       /* 
+                       /*
                         * We don't currently implement this. Log it just in case.
                         */
                        debug_browse_data(buf, len);
@@ -1117,7 +1118,7 @@ command ANN_BecomeBackup from %s IP %s to %s\n", subrec->subnet_name, nmb_namest
 command code %d from %s IP %s to %s\n", subrec->subnet_name, command, nmb_namestr(&dgram->source_name),
                                inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
                        break;
-       } 
+       }
 }
 
 /****************************************************************************
@@ -1151,10 +1152,10 @@ mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, global_scope()));
        switch (command) {
                case ANN_HostAnnouncement:
                        debug_browse_data(buf, len);
-                       process_lm_host_announce(subrec, p, buf+1);
+                       process_lm_host_announce(subrec, p, buf+1, len > 1 ? len-1 : 0);
                        break;
                case ANN_AnnouncementRequest:
-                       process_lm_announce_request(subrec, p, buf+1);
+                       process_lm_announce_request(subrec, p, buf+1, len > 1 ? len-1 : 0);
                        break;
                default:
                        DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \
@@ -1246,7 +1247,7 @@ packet sent to name %s from IP %s\n",
 packet sent to name %s from IP %s\n",
                        dgram->datasize,
                        len,
-                       PTR_DIFF(buf2, dgram->data),
+                       (int)PTR_DIFF(buf2, dgram->data),
                        nmb_namestr(&dgram->dest_name),
                        inet_ntoa(p->ip) ));
                return;
@@ -1257,7 +1258,7 @@ packet sent to name %s from IP %s\n",
 packet sent to name %s from IP %s\n",
                        dgram->datasize,
                        len,
-                       PTR_DIFF(buf2, dgram->data),
+                       (int)PTR_DIFF(buf2, dgram->data),
                        nmb_namestr(&dgram->dest_name),
                        inet_ntoa(p->ip) ));
                return;
@@ -1344,7 +1345,7 @@ static BOOL validate_nmb_response_packet( struct nmb_packet *nmb )
 
        return ignore;
 }
+
 /****************************************************************************
   Validate a request nmb packet.
 ****************************************************************************/
@@ -1509,7 +1510,7 @@ not allowed.\n"));
                                        break;
                        }
                        break;
-      
+
                case NMB_NAME_RELEASE_OPCODE:
                        if(subrec == wins_server_subnet)
                                wins_process_name_release_request(subrec, p);
@@ -1548,7 +1549,7 @@ found for id = %hu. Ignoring packet.\n", nmb->header.name_trn_id));
        rrec->num_msgs++;
        /* Ensure we don't re-send the request. */
        rrec->repeat_count = 0;
-  
+
        /* Call the response received function for this packet. */
        (*rrec->resp_fn)(subrec, rrec, p);
 }
@@ -1581,7 +1582,7 @@ void run_packet_queue(void)
                }
                free_packet(p);
        }
-} 
+}
 
 /*******************************************************************
  Retransmit or timeout elements from all the outgoing subnet response
@@ -1600,7 +1601,7 @@ void retransmit_or_expire_response_records(time_t t)
 
                for (rrec = subrec->responselist; rrec; rrec = nextrrec) {
                        nextrrec = rrec->next;
-   
+
                        if (rrec->repeat_time <= t) {
                                if (rrec->repeat_count > 0) {
                                        /* Resend while we have a non-zero repeat_count. */
@@ -1668,11 +1669,13 @@ static BOOL create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_n
        if((count*2) + 2 > FD_SETSIZE) {
                DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \
 only use %d.\n", (count*2) + 2, FD_SETSIZE));
+               SAFE_FREE(pset);
                return True;
        }
 
        if((sock_array = SMB_MALLOC_ARRAY(int, (count*2) + 2)) == NULL) {
                DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n"));
+               SAFE_FREE(pset);
                return True;
        }
 
@@ -1709,7 +1712,7 @@ only use %d.\n", (count*2) + 2, FD_SETSIZE));
 
        *ppset = pset;
        *psock_array = sock_array;
+
        return False;
 }
 
@@ -1726,7 +1729,8 @@ BOOL listen_for_packets(BOOL run_election)
        int i;
        static int maxfd = 0;
 
-       fd_set fds;
+       fd_set r_fds;
+       fd_set w_fds;
        int selrtn;
        struct timeval timeout;
 #ifndef SYNC_DNS
@@ -1741,17 +1745,18 @@ BOOL listen_for_packets(BOOL run_election)
                rescan_listen_set = False;
        }
 
-       memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set));
+       memcpy((char *)&r_fds, (char *)listen_set, sizeof(fd_set));
+       FD_ZERO(&w_fds);
 
 #ifndef SYNC_DNS
        dns_fd = asyncdns_fd();
        if (dns_fd != -1) {
-               FD_SET(dns_fd, &fds);
+               FD_SET(dns_fd, &r_fds);
                maxfd = MAX( maxfd, dns_fd);
        }
 #endif
 
-       /* 
+       /*
         * 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
@@ -1761,11 +1766,24 @@ BOOL listen_for_packets(BOOL run_election)
        timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
        timeout.tv_usec = 0;
 
+       {
+               struct timeval now = timeval_current();
+               event_add_to_select_args(nmbd_event_context(), &now,
+                                        &r_fds, &w_fds, &timeout, &maxfd);
+       }
+
+       if (timeval_is_zero(&timeout)) {
+               /* Process a timed event now... */
+               if (run_events(nmbd_event_context(), 0, NULL, NULL)) {
+                       return False;
+               }
+       }
+
        /* Prepare for the select - allow certain signals. */
 
        BlockSignals(False, SIGTERM);
 
-       selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&timeout);
+       selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&timeout);
 
        /* We can only take signals when we are in the select - block them again here. */
 
@@ -1775,8 +1793,12 @@ BOOL listen_for_packets(BOOL run_election)
                return False;
        }
 
+       if (run_events(nmbd_event_context(), selrtn, &r_fds, &w_fds)) {
+               return False;
+       }
+
 #ifndef SYNC_DNS
-       if (dns_fd != -1 && FD_ISSET(dns_fd,&fds)) {
+       if (dns_fd != -1 && FD_ISSET(dns_fd,&r_fds)) {
                run_dns_queue();
        }
 #endif
@@ -1784,7 +1806,7 @@ BOOL listen_for_packets(BOOL run_election)
        for(i = 0; i < listen_number; i++) {
                if (i < (listen_number/2)) {
                        /* Processing a 137 socket. */
-                       if (FD_ISSET(sock_array[i],&fds)) {
+                       if (FD_ISSET(sock_array[i],&r_fds)) {
                                struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET);
                                if (packet) {
                                        /*
@@ -1811,7 +1833,7 @@ BOOL listen_for_packets(BOOL run_election)
                        }
                } else {
                        /* Processing a 138 socket. */
-                               if (FD_ISSET(sock_array[i],&fds)) {
+                               if (FD_ISSET(sock_array[i],&r_fds)) {
                                struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET);
                                if (packet) {
                                        /*
@@ -1864,7 +1886,7 @@ BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len,
        /* generate_name_trn_id(); */ /* Not used, so gone, RJS */
 
        /* DIRECT GROUP or UNIQUE datagram. */
-       dgram->header.msg_type = unique ? 0x10 : 0x11; 
+       dgram->header.msg_type = unique ? 0x10 : 0x11;
        dgram->header.flags.node_type = M_NODE;
        dgram->header.flags.first = True;
        dgram->header.flags.more = False;
@@ -1873,7 +1895,7 @@ BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len,
        dgram->header.source_port = DGRAM_PORT;
        dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
        dgram->header.packet_offset = 0;
-  
+
        make_nmb_name(&dgram->source_name,srcname,src_type);
        make_nmb_name(&dgram->dest_name,dstname,dest_type);
 
@@ -1895,8 +1917,8 @@ BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len,
        SSVAL(ptr,smb_vwv16,2);
        p2 = smb_buf(ptr);
        safe_strcpy_base(p2, mailslot, dgram->data, sizeof(dgram->data));
-       p2 = skip_string(p2,1);
-  
+       p2 = skip_string(ptr,MAX_DGRAM_SIZE,p2);
+
        if (((p2+len) > dgram->data+sizeof(dgram->data)) || ((p2+len) < p2)) {
                DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n"));
                return False;