I need to list all available SMB hosts with their network addresses on the local network on a Mac. Any method works (BSD API, (Core)Foundation API or shell command).
Details
When using the macOS Finder, Go -> Network (shift-cmd-K), it is able to list systems running Windows or Linux that share volumes via smb. This proves that the servers are discoverable somehow.
I've tried to see if the servers are advertised over Bonjour or SSDP, but that's not the case.
How does Apple's code find them and how can I do this, too?
Does Windows/SMB perhaps use yet-another service announcement protocol for this? If so, what is it?
Ok, I've researched a bit more: this is done via NetBIOS. If you check out this answer it'll use
nmblookup __SAMBA__, which is something you can also do on macOS viasmbutil view //__SAMBA__.So you may need to find a NetBIOS library to do the lookup from within your app.
Edit: Further investigation shows that it's indeed the WINS protocol that's used here.
nmblookupperforms an UDP broadcast, which I've captured with Wireshark (in this case vianmblookup WORKGROUP, which in my setup returns the same information asnmblookup "*"):The answers come in one after the other and their UDP packets contain the IP-Addressed in their last for bytes:
I've tried creating an example Python script that opens an UDP socket and sends the request, but receiving turned out to be a bit more difficult.
Another update: I've found a UDP broadcast example and adapted it a WINS request: GitHub Gist.
Basically you create a socket via
socket(), enable broadcasts viasetsockopt()and then you send the packet viasendto().To read the various responses, use
select()andrecvfrom()multiple times. Provide a reasonable timeout to not wait indefinitely, in case no further responses have been received.Sockets are weird API for sure.