~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/libcli/resolve/nbtlist.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
 
 
4
   nbt list of addresses name resolution module
 
5
 
 
6
   Copyright (C) Andrew Tridgell 2005
 
7
   
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
   
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
   
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*/
 
21
 
 
22
/*
 
23
  TODO: we should lower the timeout, and add retries for each name
 
24
*/
 
25
 
 
26
#include "includes.h"
 
27
#include "libcli/composite/composite.h"
 
28
#include "system/network.h"
 
29
#include "lib/socket/socket.h"
 
30
#include "lib/socket/netif.h"
 
31
#include "librpc/gen_ndr/ndr_nbt.h"
 
32
#include "../libcli/nbt/libnbt.h"
 
33
#include "param/param.h"
 
34
#include "libcli/resolve/resolve.h"
 
35
 
 
36
struct nbtlist_state {
 
37
        uint16_t flags;
 
38
        uint16_t port;
 
39
        struct nbt_name name;
 
40
        struct nbt_name_socket *nbtsock;
 
41
        int num_queries;
 
42
        struct nbt_name_request **queries;
 
43
        struct nbt_name_query *io_queries;
 
44
        struct socket_address **addrs;
 
45
        char **names;
 
46
        struct interface *ifaces;
 
47
};
 
48
 
 
49
/*
 
50
  handle events during nbtlist name resolution
 
51
*/
 
52
static void nbtlist_handler(struct nbt_name_request *req)
 
53
{
 
54
        struct composite_context *c = talloc_get_type(req->async.private_data,
 
55
                                                      struct composite_context);
 
56
        struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state);
 
57
        struct nbt_name_query *q;
 
58
        int i;
 
59
 
 
60
        for (i=0;i<state->num_queries;i++) {
 
61
                if (req == state->queries[i]) break;
 
62
        }
 
63
 
 
64
        if (i == state->num_queries) {
 
65
                /* not for us?! */
 
66
                composite_error(c, NT_STATUS_INTERNAL_ERROR);
 
67
                return;
 
68
        }
 
69
 
 
70
        q = &state->io_queries[i];
 
71
 
 
72
        c->status = nbt_name_query_recv(req, state, q);
 
73
 
 
74
        /* free the network resource directly */
 
75
        talloc_free(state->nbtsock);
 
76
        if (!composite_is_ok(c)) return;
 
77
 
 
78
        if (q->out.num_addrs < 1) {
 
79
                composite_error(c, NT_STATUS_UNEXPECTED_NETWORK_ERROR);
 
80
                return;
 
81
        }
 
82
 
 
83
        state->addrs = talloc_array(state, struct socket_address *,
 
84
                                    q->out.num_addrs + 1);
 
85
        if (composite_nomem(state->addrs, c)) return;
 
86
 
 
87
        state->names = talloc_array(state, char *, q->out.num_addrs + 1);
 
88
        if (composite_nomem(state->names, c)) return;
 
89
 
 
90
        for (i=0;i<q->out.num_addrs;i++) {
 
91
                state->addrs[i] = socket_address_from_strings(state->addrs,
 
92
                                                              "ipv4",
 
93
                                                              q->out.reply_addrs[i],
 
94
                                                              state->port);
 
95
                if (composite_nomem(state->addrs[i], c)) return;
 
96
 
 
97
                state->names[i] = talloc_strdup(state->names, state->name.name);
 
98
                if (composite_nomem(state->names[i], c)) return;
 
99
        }
 
100
        state->addrs[i] = NULL;
 
101
        state->names[i] = NULL;
 
102
 
 
103
        composite_done(c);
 
104
}
 
105
 
 
106
/*
 
107
  nbtlist name resolution method - async send
 
108
 */
 
109
struct composite_context *resolve_name_nbtlist_send(TALLOC_CTX *mem_ctx,
 
110
                                                    struct tevent_context *event_ctx,
 
111
                                                    uint32_t flags,
 
112
                                                    uint16_t port,
 
113
                                                    struct nbt_name *name, 
 
114
                                                    const char **address_list,
 
115
                                                    struct interface *ifaces,
 
116
                                                    uint16_t nbt_port,
 
117
                                                    int nbt_timeout,
 
118
                                                    bool broadcast,
 
119
                                                    bool wins_lookup)
 
120
{
 
121
        struct composite_context *c;
 
122
        struct nbtlist_state *state;
 
123
        int i;
 
124
 
 
125
        c = composite_create(mem_ctx, event_ctx);
 
126
        if (c == NULL) return NULL;
 
127
 
 
128
        if (flags & RESOLVE_NAME_FLAG_FORCE_DNS) {
 
129
                composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 
130
                return c;
 
131
        }
 
132
 
 
133
        if (strlen(name->name) > 15) {
 
134
                composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 
135
                return c;
 
136
        }
 
137
 
 
138
        state = talloc(c, struct nbtlist_state);
 
139
        if (composite_nomem(state, c)) return c;
 
140
        c->private_data = state;
 
141
 
 
142
        state->flags = flags;
 
143
        state->port = port;
 
144
 
 
145
        c->status = nbt_name_dup(state, name, &state->name);
 
146
        if (!composite_is_ok(c)) return c;
 
147
 
 
148
        state->name.name = strupper_talloc(state, state->name.name);
 
149
        if (composite_nomem(state->name.name, c)) return c;
 
150
        if (state->name.scope) {
 
151
                state->name.scope = strupper_talloc(state, state->name.scope);
 
152
                if (composite_nomem(state->name.scope, c)) return c;
 
153
        }
 
154
 
 
155
        state->ifaces = talloc_reference(state, ifaces);
 
156
 
 
157
        /*
 
158
         * we can't push long names on the wire,
 
159
         * so bail out here to give a useful error message
 
160
         */
 
161
        if (strlen(state->name.name) > 15) {
 
162
                composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 
163
                return c;
 
164
        }
 
165
 
 
166
        state->nbtsock = nbt_name_socket_init(state, event_ctx, 
 
167
                                              global_iconv_convenience);
 
168
        if (composite_nomem(state->nbtsock, c)) return c;
 
169
 
 
170
        /* count the address_list size */
 
171
        for (i=0;address_list[i];i++) /* noop */ ;
 
172
 
 
173
        state->num_queries = i;
 
174
        state->io_queries = talloc_array(state, struct nbt_name_query, state->num_queries);
 
175
        if (composite_nomem(state->io_queries, c)) return c;
 
176
 
 
177
        state->queries = talloc_array(state, struct nbt_name_request *, state->num_queries);
 
178
        if (composite_nomem(state->queries, c)) return c;
 
179
 
 
180
        for (i=0;i<state->num_queries;i++) {
 
181
                state->io_queries[i].in.name        = state->name;
 
182
                state->io_queries[i].in.dest_addr   = talloc_strdup(state->io_queries, address_list[i]);
 
183
                state->io_queries[i].in.dest_port   = nbt_port;
 
184
                if (composite_nomem(state->io_queries[i].in.dest_addr, c)) return c;
 
185
 
 
186
                state->io_queries[i].in.broadcast   = broadcast;
 
187
                state->io_queries[i].in.wins_lookup = wins_lookup;
 
188
                state->io_queries[i].in.timeout     = nbt_timeout;
 
189
                state->io_queries[i].in.retries     = 2;
 
190
 
 
191
                state->queries[i] = nbt_name_query_send(state->nbtsock, &state->io_queries[i]);
 
192
                if (composite_nomem(state->queries[i], c)) return c;
 
193
 
 
194
                state->queries[i]->async.fn      = nbtlist_handler;
 
195
                state->queries[i]->async.private_data = c;
 
196
        }
 
197
 
 
198
        return c;
 
199
}
 
200
 
 
201
/*
 
202
  nbt list of addresses name resolution method - recv side
 
203
 */
 
204
NTSTATUS resolve_name_nbtlist_recv(struct composite_context *c, 
 
205
                                   TALLOC_CTX *mem_ctx,
 
206
                                   struct socket_address ***addrs,
 
207
                                   char ***names)
 
208
{
 
209
        NTSTATUS status;
 
210
 
 
211
        status = composite_wait(c);
 
212
 
 
213
        if (NT_STATUS_IS_OK(status)) {
 
214
                struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state);
 
215
                *addrs = talloc_steal(mem_ctx, state->addrs);
 
216
                if (names) {
 
217
                        *names = talloc_steal(mem_ctx, state->names);
 
218
                }
 
219
        }
 
220
 
 
221
        talloc_free(c);
 
222
        return status;
 
223
}
 
224