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