mirror of
https://github.com/samba-team/samba.git
synced 2024-12-29 11:21:54 +03:00
042201bcc1
(This used to be commit e5bd32812d
)
238 lines
5.3 KiB
C
238 lines
5.3 KiB
C
/*
|
|
Unix SMB/CIFS implementation.
|
|
DNS-SD browse client
|
|
Copyright (C) Rishi Srivatsavai 2007
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "client/client_proto.h"
|
|
|
|
#ifdef WITH_DNSSD_SUPPORT
|
|
|
|
#include <dns_sd.h>
|
|
|
|
/* Holds service instances found during DNS browse */
|
|
struct mdns_smbsrv_result
|
|
{
|
|
char *serviceName;
|
|
char *regType;
|
|
char *domain;
|
|
uint32_t ifIndex;
|
|
struct mdns_smbsrv_result *nextResult;
|
|
};
|
|
|
|
/* Maintains state during DNS browse */
|
|
struct mdns_browse_state
|
|
{
|
|
struct mdns_smbsrv_result *listhead; /* Browse result list head */
|
|
int browseDone;
|
|
|
|
};
|
|
|
|
|
|
static void
|
|
do_smb_resolve_reply (DNSServiceRef sdRef, DNSServiceFlags flags,
|
|
uint32_t interfaceIndex, DNSServiceErrorType errorCode,
|
|
const char *fullname, const char *hosttarget, uint16_t port,
|
|
uint16_t txtLen, const unsigned char *txtRecord, void *context)
|
|
{
|
|
printf("SMB service available on %s port %u\n",
|
|
hosttarget, ntohs(port));
|
|
}
|
|
|
|
|
|
static void do_smb_resolve(struct mdns_smbsrv_result *browsesrv)
|
|
{
|
|
DNSServiceRef mdns_conn_sdref = NULL;
|
|
int mdnsfd;
|
|
int fdsetsz;
|
|
int ret;
|
|
fd_set *fdset = NULL;
|
|
struct timeval tv;
|
|
DNSServiceErrorType err;
|
|
|
|
TALLOC_CTX * ctx = talloc_tos();
|
|
|
|
err = DNSServiceResolve(&mdns_conn_sdref, 0 /* flags */,
|
|
browsesrv->ifIndex,
|
|
browsesrv->serviceName, browsesrv->regType, browsesrv->domain,
|
|
do_smb_resolve_reply, NULL);
|
|
|
|
if (err != kDNSServiceErr_NoError) {
|
|
return;
|
|
}
|
|
|
|
mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
|
|
for (;;) {
|
|
if (fdset != NULL) {
|
|
TALLOC_FREE(fdset);
|
|
}
|
|
|
|
fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
|
|
fdset = TALLOC_ZERO(ctx, fdsetsz);
|
|
FD_SET(mdnsfd, fdset);
|
|
|
|
tv.tv_sec = 1;
|
|
tv.tv_usec = 0;
|
|
|
|
/* Wait until response received from mDNS daemon */
|
|
ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv);
|
|
if (ret <= 0 && errno != EINTR) {
|
|
break;
|
|
}
|
|
|
|
if (FD_ISSET(mdnsfd, fdset)) {
|
|
/* Invoke callback function */
|
|
DNSServiceProcessResult(mdns_conn_sdref);
|
|
break;
|
|
}
|
|
}
|
|
|
|
TALLOC_FREE(fdset);
|
|
DNSServiceRefDeallocate(mdns_conn_sdref);
|
|
}
|
|
|
|
|
|
static void
|
|
do_smb_browse_reply(DNSServiceRef sdRef, DNSServiceFlags flags,
|
|
uint32_t interfaceIndex, DNSServiceErrorType errorCode,
|
|
const char *serviceName, const char *regtype,
|
|
const char *replyDomain, void *context)
|
|
{
|
|
struct mdns_browse_state *bstatep = (struct mdns_browse_state *)context;
|
|
struct mdns_smbsrv_result *bresult;
|
|
|
|
if (bstatep == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (errorCode != kDNSServiceErr_NoError) {
|
|
bstatep->browseDone = 1;
|
|
return;
|
|
}
|
|
|
|
if (flags & kDNSServiceFlagsMoreComing) {
|
|
bstatep->browseDone = 0;
|
|
} else {
|
|
bstatep->browseDone = 1;
|
|
}
|
|
|
|
if (!(flags & kDNSServiceFlagsAdd)) {
|
|
return;
|
|
}
|
|
|
|
bresult = TALLOC_ARRAY(talloc_tos(), struct mdns_smbsrv_result, 1);
|
|
if (bresult == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (bstatep->listhead != NULL) {
|
|
bresult->nextResult = bstatep->listhead;
|
|
}
|
|
|
|
bresult->serviceName = talloc_strdup(talloc_tos(), serviceName);
|
|
bresult->regType = talloc_strdup(talloc_tos(), regtype);
|
|
bresult->domain = talloc_strdup(talloc_tos(), replyDomain);
|
|
bresult->ifIndex = interfaceIndex;
|
|
bstatep->listhead = bresult;
|
|
}
|
|
|
|
int do_smb_browse(void)
|
|
{
|
|
int mdnsfd;
|
|
int fdsetsz;
|
|
int ret;
|
|
fd_set *fdset = NULL;
|
|
struct mdns_browse_state bstate;
|
|
struct mdns_smbsrv_result *resptr;
|
|
struct timeval tv;
|
|
DNSServiceRef mdns_conn_sdref = NULL;
|
|
DNSServiceErrorType err;
|
|
|
|
TALLOC_CTX * ctx = talloc_stackframe();
|
|
|
|
ZERO_STRUCT(bstate);
|
|
|
|
err = DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "",
|
|
do_smb_browse_reply, &bstate);
|
|
|
|
if (err != kDNSServiceErr_NoError) {
|
|
d_printf("Error connecting to the Multicast DNS daemon\n");
|
|
TALLOC_FREE(ctx);
|
|
return 1;
|
|
}
|
|
|
|
mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
|
|
for (;;) {
|
|
if (fdset != NULL) {
|
|
TALLOC_FREE(fdset);
|
|
}
|
|
|
|
fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
|
|
fdset = TALLOC_ZERO(ctx, fdsetsz);
|
|
FD_SET(mdnsfd, fdset);
|
|
|
|
tv.tv_sec = 1;
|
|
tv.tv_usec = 0;
|
|
|
|
/* Wait until response received from mDNS daemon */
|
|
ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv);
|
|
if (ret <= 0 && errno != EINTR) {
|
|
break;
|
|
}
|
|
|
|
if (FD_ISSET(mdnsfd, fdset)) {
|
|
/* Invoke callback function */
|
|
if (DNSServiceProcessResult(mdns_conn_sdref)) {
|
|
break;
|
|
}
|
|
if (bstate.browseDone) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
DNSServiceRefDeallocate(mdns_conn_sdref);
|
|
|
|
if (bstate.listhead != NULL) {
|
|
resptr = bstate.listhead;
|
|
while (resptr != NULL) {
|
|
struct mdns_smbsrv_result *oldresptr;
|
|
oldresptr = resptr;
|
|
|
|
/* Resolve smb service instance */
|
|
do_smb_resolve(resptr);
|
|
|
|
resptr = resptr->nextResult;
|
|
}
|
|
}
|
|
|
|
TALLOC_FREE(ctx);
|
|
return 0;
|
|
}
|
|
|
|
#else /* WITH_DNSSD_SUPPORT */
|
|
|
|
int do_smb_browse(void)
|
|
{
|
|
d_printf("DNS-SD browsing is not supported on this platform\n");
|
|
return 1;
|
|
}
|
|
|
|
#endif /* WITH_DNSSD_SUPPORT */
|
|
|
|
|