The branch, v3-5-test has been updated
       via  6fe7ee1... More of the fix for bug #7118 - nmbd problems with 
socket address.
       via  05123ef... Make "nmbd bind explicit broadcast" on by default.
      from  5456e5e... s3:docs-xml: document "nmbd bind explicit broadcast"

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-5-test


- Log -----------------------------------------------------------------
commit 6fe7ee1d216fcf722b3efa23fd80782ce0dd0e9f
Author: Jeremy Allison <j...@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.

commit 05123ef78c903de2a12b95fb30632f03ac919a4d
Author: Jeremy Allison <j...@samba.org>
Date:   Mon Feb 8 14:35:02 2010 -0800

    Make "nmbd bind explicit broadcast" on by default.
    
    Fix a comment typo.
    
    Jeremy.

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

Summary of changes:
 .../smbdotconf/misc/nmbdbindexplicitbroadcast.xml  |   11 ++-
 source3/nmbd/nmbd_packets.c                        |   91 +++++++++++++++++++-
 source3/param/loadparm.c                           |    5 +
 3 files changed, 101 insertions(+), 6 deletions(-)


Changeset truncated at 500 lines:

diff --git a/docs-xml/smbdotconf/misc/nmbdbindexplicitbroadcast.xml 
b/docs-xml/smbdotconf/misc/nmbdbindexplicitbroadcast.xml
index f328594..3a44a69 100644
--- a/docs-xml/smbdotconf/misc/nmbdbindexplicitbroadcast.xml
+++ b/docs-xml/smbdotconf/misc/nmbdbindexplicitbroadcast.xml
@@ -5,12 +5,13 @@
                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc";>
 <description>
        <para>
-       This option allows you to setup 
<citerefentry><refentrytitle>nmbd</refentrytitle>
-       <manvolnum>8</manvolnum></citerefentry> to explicit bind to the
-       broadcast address of the local subnets. This is only useful in
-       combination with the <smbconfoption name="socket address"/> option.
+       This option causes <citerefentry><refentrytitle>nmbd</refentrytitle>
+       <manvolnum>8</manvolnum></citerefentry> to explicitly bind to the
+       broadcast address of the local subnets. This is needed to make nmbd
+       work correctly in combination with the <smbconfoption name="socket 
address"/> option.
+       You should not need to unset this option.
        </para>
 </description>
 
-<value type="default">no</value>
+<value type="default">yes</value>
 </samba:parameter>
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index 013ebf6..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)) {
@@ -1863,7 +1941,7 @@ bool listen_for_packets(bool run_election)
                        client_fd = ClientNMB;
                        client_port = global_nmb_port;
                } else {
-                       /* Port 137 */
+                       /* Port 138 */
                        packet_type = DGRAM_PACKET;
                        packet_name = "dgram";
                        client_fd = ClientDGRAM;
@@ -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;
 }
 
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 4f5aba7..31e5ce4 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -4968,6 +4968,11 @@ static void init_globals(bool first_time_only)
        string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
        string_set(&Globals.szPidDir, get_dyn_PIDDIR());
        string_set(&Globals.szSocketAddress, "0.0.0.0");
+       /*
+        * By default support explicit binding to broadcast
+        * addresses.
+        */
+       Globals.bNmbdBindExplicitBroadcast = true;
 
        if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
                smb_panic("init_globals: ENOMEM");


-- 
Samba Shared Repository

Reply via email to