[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Wed Feb 10 13:38:03 MST 2010


The branch, master has been updated
       via  c2f3ed4... More of the fix for bug #7118 - nmbd problems with socket address.
      from  84fba3c... Change the default of "nmbd bind explicit broadcast" to "no" until the double processing problem in bug #7118 is fixed.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit c2f3ed48c5ac253bb17387800579f94d933b71e1
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Feb 10 12:32:05 2010 -0800

    More of the fix for bug #7118 - nmbd problems with socket address.
    
    Add a simple "processed packet queue" cache to stop nmbd responding to
    packets received on the broadcast and non-broadcast socket (which
    it has opened when "nmbd bind explicit broadcast = yes").
    
    This is a very simple packet queue - it only keeps the packets
    processed during a single call to listen_for_packets() (i.e. one
    select call). This means that if the delivery notification for a
    packet received on both broadcast and non-broadcast addresses
    is done in two different select calls, the packet will still be
    processed twice. This is a very rare occurrance and we can just
    live with it when it does as the protocol is stateless. If this
    is ever flagged as a repeatable problem then we can add a longer
    lived cache, using timeout processing to clear etc. etc. But without
    storing all packets processed we can never be *sure* we've eliminated
    the race condition so I'm going to go with this simple solution until
    someone proves a more complex one is needed :-).
    
    Jeremy.

-----------------------------------------------------------------------

Summary of changes:
 source3/nmbd/nmbd_packets.c |   89 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 89 insertions(+), 0 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index 55fd24d..a753b28 100644
--- a/source3/nmbd/nmbd_packets.c
+++ b/source3/nmbd/nmbd_packets.c
@@ -1765,6 +1765,83 @@ only use %d.\n", count, FD_SETSIZE));
 }
 
 /****************************************************************************
+ List of packets we're processing this select.
+***************************************************************************/
+
+struct processed_packet {
+	struct processed_packet *next;
+	struct processed_packet *prev;
+	enum packet_type packet_type;
+	struct in_addr ip;
+	int packet_id;
+};
+
+/****************************************************************************
+ Have we seen this before ?
+***************************************************************************/
+
+static bool is_processed_packet(struct processed_packet *processed_packet_list,
+				struct packet_struct *packet)
+{
+	struct processed_packet *p = NULL;
+
+	for (p = processed_packet_list; p; p = p->next) {
+		if (ip_equal_v4(p->ip, packet->ip) && p->packet_type == packet->packet_type) {
+			if ((p->packet_type == NMB_PACKET) &&
+				(p->packet_id ==
+					packet->packet.nmb.header.name_trn_id)) {
+				return true;
+			} else if ((p->packet_type == DGRAM_PACKET) &&
+				(p->packet_id ==
+					packet->packet.dgram.header.dgm_id)) {
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+/****************************************************************************
+ Keep a list of what we've seen before.
+***************************************************************************/
+
+static bool store_processed_packet(struct processed_packet **pp_processed_packet_list,
+				struct packet_struct *packet)
+{
+	struct processed_packet *p = SMB_MALLOC_P(struct processed_packet);
+	if (!p) {
+		return false;
+	}
+	p->packet_type = packet->packet_type;
+	p->ip = packet->ip;
+	if (packet->packet_type == NMB_PACKET) {
+		p->packet_id = packet->packet.nmb.header.name_trn_id;
+	} else if (packet->packet_type == DGRAM_PACKET) {
+		p->packet_id = packet->packet.dgram.header.dgm_id;
+	} else {
+		return false;
+	}
+
+	DLIST_ADD(*pp_processed_packet_list, p);
+	return true;
+}
+
+/****************************************************************************
+ Throw away what we've seen before.
+***************************************************************************/
+
+static void free_processed_packet_list(struct processed_packet **pp_processed_packet_list)
+{
+	struct processed_packet *p = NULL, *next = NULL;
+
+	for (p = *pp_processed_packet_list; p; p = next) {
+		next = p->next;
+		DLIST_REMOVE(*pp_processed_packet_list, p);
+		SAFE_FREE(p);
+	}
+}
+
+/****************************************************************************
   Listens for NMB or DGRAM packets, and queues them.
   return True if the socket is dead
 ***************************************************************************/
@@ -1784,6 +1861,7 @@ bool listen_for_packets(bool run_election)
 #ifndef SYNC_DNS
 	int dns_fd;
 #endif
+	struct processed_packet *processed_packet_list = NULL;
 
 	if(listen_set == NULL || rescan_listen_set) {
 		if(create_listen_fdset(&listen_set, &sock_array, &listen_number, &maxfd)) {
@@ -1906,6 +1984,16 @@ bool listen_for_packets(bool run_election)
 			}
 		}
 
+
+		if (is_processed_packet(processed_packet_list, packet)) {
+			DEBUG(7,("discarding duplicate packet from %s:%d\n",
+				inet_ntoa(packet->ip),packet->port));
+			free_packet(packet);
+			continue;
+		}
+
+		store_processed_packet(&processed_packet_list, packet);
+
 		/*
 		 * 0,2,4,... are unicast sockets
 		 * 1,3,5,... are broadcast sockets
@@ -1926,6 +2014,7 @@ bool listen_for_packets(bool run_election)
 		queue_packet(packet);
 	}
 
+	free_processed_packet_list(&processed_packet_list);
 	return False;
 }
 


-- 
Samba Shared Repository


More information about the samba-cvs mailing list