mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
237 lines
5.3 KiB
C
237 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"
|
||
|
|
||
|
#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 */
|
||
|
|
||
|
|