root/source3/client/dnsbrowse.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. do_smb_resolve_reply
  2. do_smb_resolve
  3. do_smb_browse_reply
  4. do_smb_browse
  5. do_smb_browse

   1 /*
   2    Unix SMB/CIFS implementation.
   3    DNS-SD browse client
   4    Copyright (C) Rishi Srivatsavai 2007
   5 
   6    This program is free software; you can redistribute it and/or modify
   7    it under the terms of the GNU General Public License as published by
   8    the Free Software Foundation; either version 3 of the License, or
   9    (at your option) any later version.
  10 
  11    This program is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU General Public License for more details.
  15 
  16    You should have received a copy of the GNU General Public License
  17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19 
  20 #include "includes.h"
  21 #include "client/client_proto.h"
  22 
  23 #ifdef WITH_DNSSD_SUPPORT
  24 
  25 #include <dns_sd.h>
  26 
  27 /* Holds service instances found during DNS browse */
  28 struct mdns_smbsrv_result
  29 {
  30         char *serviceName;
  31         char *regType;
  32         char *domain;
  33         uint32_t ifIndex;
  34         struct mdns_smbsrv_result *nextResult;
  35 };
  36 
  37 /* Maintains state during DNS browse */
  38 struct mdns_browse_state
  39 {
  40         struct mdns_smbsrv_result *listhead; /* Browse result list head */
  41         int browseDone;
  42 
  43 };
  44 
  45 
  46 static void
  47 do_smb_resolve_reply (DNSServiceRef sdRef, DNSServiceFlags flags,
     /* [<][>][^][v][top][bottom][index][help] */
  48                 uint32_t interfaceIndex, DNSServiceErrorType errorCode,
  49                 const char *fullname, const char *hosttarget, uint16_t port,
  50                 uint16_t txtLen, const unsigned char *txtRecord, void *context)
  51 {
  52         printf("SMB service available on %s port %u\n",
  53                 hosttarget, ntohs(port));
  54 }
  55 
  56 
  57 static void do_smb_resolve(struct mdns_smbsrv_result *browsesrv)
     /* [<][>][^][v][top][bottom][index][help] */
  58 {
  59         DNSServiceRef mdns_conn_sdref = NULL;
  60         int mdnsfd;
  61         int fdsetsz;
  62         int ret;
  63         fd_set *fdset = NULL;
  64         struct timeval tv;
  65         DNSServiceErrorType err;
  66 
  67         TALLOC_CTX * ctx = talloc_tos();
  68 
  69         err = DNSServiceResolve(&mdns_conn_sdref, 0 /* flags */,
  70                 browsesrv->ifIndex,
  71                 browsesrv->serviceName, browsesrv->regType, browsesrv->domain,
  72                 do_smb_resolve_reply, NULL);
  73 
  74         if (err != kDNSServiceErr_NoError) {
  75                 return;
  76         }
  77 
  78         mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
  79         for (;;)  {
  80                 if (fdset != NULL) {
  81                         TALLOC_FREE(fdset);
  82                 }
  83 
  84                 fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
  85                 fdset = TALLOC_ZERO(ctx, fdsetsz);
  86                 FD_SET(mdnsfd, fdset);
  87 
  88                 tv.tv_sec = 1;
  89                 tv.tv_usec = 0;
  90 
  91                 /* Wait until response received from mDNS daemon */
  92                 ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv);
  93                 if (ret <= 0 && errno != EINTR) {
  94                         break;
  95                 }
  96 
  97                 if (FD_ISSET(mdnsfd, fdset)) {
  98                         /* Invoke callback function */
  99                         DNSServiceProcessResult(mdns_conn_sdref);
 100                         break;
 101                 }
 102         }
 103 
 104         TALLOC_FREE(fdset);
 105         DNSServiceRefDeallocate(mdns_conn_sdref);
 106 }
 107 
 108 
 109 static void
 110 do_smb_browse_reply(DNSServiceRef sdRef, DNSServiceFlags flags,
     /* [<][>][^][v][top][bottom][index][help] */
 111         uint32_t interfaceIndex, DNSServiceErrorType errorCode,
 112         const char  *serviceName, const char *regtype,
 113         const char  *replyDomain, void  *context)
 114 {
 115         struct mdns_browse_state *bstatep = (struct mdns_browse_state *)context;
 116         struct mdns_smbsrv_result *bresult;
 117 
 118         if (bstatep == NULL) {
 119                 return;
 120         }
 121 
 122         if (errorCode != kDNSServiceErr_NoError) {
 123                 bstatep->browseDone = 1;
 124                 return;
 125         }
 126 
 127         if (flags & kDNSServiceFlagsMoreComing) {
 128                 bstatep->browseDone = 0;
 129         } else {
 130                 bstatep->browseDone = 1;
 131         }
 132 
 133         if (!(flags & kDNSServiceFlagsAdd)) {
 134                 return;
 135         }
 136 
 137         bresult = TALLOC_ARRAY(talloc_tos(), struct mdns_smbsrv_result, 1);
 138         if (bresult == NULL) {
 139                 return;
 140         }
 141 
 142         if (bstatep->listhead != NULL) {
 143                 bresult->nextResult = bstatep->listhead;
 144         }
 145 
 146         bresult->serviceName = talloc_strdup(talloc_tos(), serviceName);
 147         bresult->regType = talloc_strdup(talloc_tos(), regtype);
 148         bresult->domain = talloc_strdup(talloc_tos(), replyDomain);
 149         bresult->ifIndex = interfaceIndex;
 150         bstatep->listhead = bresult;
 151 }
 152 
 153 int do_smb_browse(void)
     /* [<][>][^][v][top][bottom][index][help] */
 154 {
 155         int mdnsfd;
 156         int fdsetsz;
 157         int ret;
 158         fd_set *fdset = NULL;
 159         struct mdns_browse_state bstate;
 160         struct mdns_smbsrv_result *resptr;
 161         struct timeval tv;
 162         DNSServiceRef mdns_conn_sdref = NULL;
 163         DNSServiceErrorType err;
 164 
 165         TALLOC_CTX * ctx = talloc_stackframe();
 166 
 167         ZERO_STRUCT(bstate);
 168 
 169         err = DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "",
 170                         do_smb_browse_reply, &bstate);
 171 
 172         if (err != kDNSServiceErr_NoError) {
 173                 d_printf("Error connecting to the Multicast DNS daemon\n");
 174                 TALLOC_FREE(ctx);
 175                 return 1;
 176         }
 177 
 178         mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
 179         for (;;)  {
 180                 if (fdset != NULL) {
 181                         TALLOC_FREE(fdset);
 182                 }
 183 
 184                 fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
 185                 fdset = TALLOC_ZERO(ctx, fdsetsz);
 186                 FD_SET(mdnsfd, fdset);
 187 
 188                 tv.tv_sec = 1;
 189                 tv.tv_usec = 0;
 190 
 191                 /* Wait until response received from mDNS daemon */
 192                 ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv);
 193                 if (ret <= 0 && errno != EINTR) {
 194                         break;
 195                 }
 196 
 197                 if (FD_ISSET(mdnsfd, fdset)) {
 198                         /* Invoke callback function */
 199                         if (DNSServiceProcessResult(mdns_conn_sdref)) {
 200                                 break;
 201                         }
 202                         if (bstate.browseDone) {
 203                                 break;
 204                         }
 205                 }
 206         }
 207 
 208         DNSServiceRefDeallocate(mdns_conn_sdref);
 209 
 210         if (bstate.listhead != NULL) {
 211                 resptr = bstate.listhead;
 212                 while (resptr != NULL) {
 213                         struct mdns_smbsrv_result *oldresptr;
 214                         oldresptr = resptr;
 215 
 216                         /* Resolve smb service instance */
 217                         do_smb_resolve(resptr);
 218 
 219                         resptr = resptr->nextResult;
 220                 }
 221         }
 222 
 223         TALLOC_FREE(ctx);
 224         return 0;
 225 }
 226 
 227 #else /* WITH_DNSSD_SUPPORT */
 228 
 229 int do_smb_browse(void)
     /* [<][>][^][v][top][bottom][index][help] */
 230 {
 231     d_printf("DNS-SD browsing is not supported on this platform\n");
 232     return 1;
 233 }
 234 
 235 #endif /* WITH_DNSSD_SUPPORT */
 236 
 237 

/* [<][>][^][v][top][bottom][index][help] */