~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/client/dnsbrowse.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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,
 
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)
 
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,
 
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)
 
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)
 
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