smbc_opendir() returns -1 but sets errno to 0

Christopher R. Hertel crh at ubiqx.mn.org
Wed Nov 26 00:51:57 GMT 2003


Derrell.Lipman at unwireduniverse.com wrote:
> 
> "Christopher R. Hertel" <crh at ubiqx.mn.org> writes:
> 
> > So, the workgroup<1D> name should not be getting resolved via the DNS at
> > all.  As a workgroup name, and there is no assumption that it will match
> > the host name of any host on your network.  From the smb.conf(5) man page:
> >
> >     Note that this method is only used if the NetBIOS name type being
> >     queried is the 0x20 (server)  name type, otherwise it is ignored.
> >
> > The same is true for the <1B> name (the Domain Master Browser name).
> > This should not be resolved via the DNS because, again, the NetBIOS name
> > is not going to match the DNS hostname of the system that registered it.
> 
> Let me disambiguate the matter a bit.  The workgroup name isn't actually the
> one being looked up; it's the name returned as the master browser for that
> workgroup.

Sorry to be so annoyingly long-winded...

One thing about NetBIOS names vs. DNS names is that a DNS name represents an
IP address (which, in turn, represents an interface on a machine).  The
NetBIOS name represents an application or service address.  Very different.
(...but you knew that).

The Local Master Browser (LMB) registers the workgroup<1D> name so that it
can be found.  Nothing to do with the LMB's host name or base NetBIOS
machine name.  So, in theory, when you enter SMB://WORKGROUP_NAME/ the
underlying system should look for WORKGROUP_NAME<1D>.

Thing is, the SMB URI format is overloaded.  It handles both the Server
Service (SMB filesharing) and the Browse Service (as you've noticed).

So, when someone enters 'smb://foo/' the name "foo" could be a Server
Service name (FOO<20>) or it could be a Workgroup Name (FOO<1D> *or*
FOO<1B>).

Folks from the IETF have asked that the next SMB URI Internet Draft provide
a best practices mechanism for resolving the reference in a situation like
the one above.

In the mean time, many tools will jump through many hoops trying the name as
a <20> name, a <1B> and/or <1D> name, a DNS name, and even an IP address.

> I retrieved the workgroup name by browsing for workgroups:
> smbc_opendir("smb//") and then browsed for servers in the workgroup:
> smbc_opendir("smb://WORKGROUP_NAME").  Since there's no WINS server here, I
> believe it determined the list of workgroups (and the master browser for
> each) via broadcast query.

The list of workgroups can only be discovered by contacting a Local Master
Browser (well, there is an interesting fiddle built into Samba's NBNS
implementation... you can send a unicast query for *<1B>).

So, "smb://" queries any LMB on the local LAN for a list of known
workgroups.
If there are DMBs available (and a WINS server to let them be found) then
the list may contain workgroups that are not represented on the local LAN
(and, therefore, have no local LMB).

Assuming no NBNS, "smb://foo/" should generate NBT broadcast queries for
FOO<20> and FOO<1D>.  Only one system should answer, since workgroup names
and machine names should never match (but can, in a misconfigured network). 
The response should let you know which kind of node you've found in any
case.

Things get a little fuzzy when DNS lookups are thrown into the mix, as you
might expect.

>  When receiving the responses, it therefore had access to
> the IP address from which the response originated.  Would it be an
> appropriate modification to libsmbclient, to cache the IP address
> from these responses, in order to behave in a more expected fashion?

Well... no, not really.  If there is a new election and some other node
becomes LMB then the cache would be invalid.  The real question is:  Why did
a query for smb://WORKGROUP_NAME/ return the IP address of something other
than a browser for the WORKGROUP_NAME workgroup?  Another question: Is it
possible that the workgroup browse list was, in fact, empty?  That can
happen fairly easily.

Ethereal... Your best friend.

> > Another thing to note (yeah, I know I'm full of this stuff...):
> > Many Windows systems register both the machine<00> unique name and the
> > workgroup<00> group name.  If the workgroup name matches a machine name
> > then there will be a name registration conflict.
> 
> Yup.  I think this is handled in libsmbclient by assuming the name
> represents a server unless no server by that name exists, in which case it
> changes the assumption to the name representing a workgroup.

That's one way to do it.  I'm in favor of returning an error and providing
functions that work either way (that is, functions that let you query the
server for the share list or query the Browser for the server list, or
both...depending on what you want your application to do).

> >> 2. Given that smbc_opendir() is returning -1, should errno be set to
> >> something other than 0 to help identify the problem -- even though the NT
> >> errno from which errno is being derived was "success"?
> >
> > Dunno.  Would have to check the workings of that function.  If those
> > values indicate an empty list, then it's behaving correctly.
> 
> 0 indicates success, -1 indicates error with errno set to indicate which
> error occurred, a la many posix functions.  There is no time that I know
> of, in posix functions, that -1 is returned but errno set to 0.  An empty
> list should probably be returned as a successful return value of 0.  (OTOH,
> this is not really a successful result with an empty set since the result
> came from the wrong MB.)

Right, but the failure is in the name-to-IP resolution, not the
NetServerEnum2 call.

Re: Posix...  I'm not sure what Richard's design goals were but returning
posix-style results is a reasonable thing to do.  Have to ask him.  :)

> Is it ever possible for a MB to advertise itself as the MB for a workgroup,
> but then return an empty list of servers?

At first I thought it might be, but as you say...

> It was my understanding that the
> negotiation for master browser required a server in that workgroup to
> determine whether it should be the MB, so it should at a minimum, return
> itself...  No?

Even if the LMB is not offering any other services it should list itself as
the LMB (SV_TYPE_MASTER_BROWSER == 0x00040000).  It would be interesting to
see what request mask is being sent by libsmbclient (again, Ethereal).

An Ethereal trace would show which IP address was being queried for the list
of servers.  The thing to do then would be to send a node status query to
that IP address and see if it really believes itself to be the LMB for the
workgroup.

Hope that helps.

Chris -)-----

-- 
"Implementing CIFS - the Common Internet FileSystem" ISBN: 013047116X
Samba Team -- http://www.samba.org/     -)-----   Christopher R. Hertel
jCIFS Team -- http://jcifs.samba.org/   -)-----   ubiqx development, uninq.
ubiqx Team -- http://www.ubiqx.org/     -)-----   crh at ubiqx.mn.org
OnLineBook -- http://ubiqx.org/cifs/    -)-----   crh at ubiqx.org



More information about the samba-technical mailing list