Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : make nbt name query requests
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 : #include "includes.h"
23 : #include "../libcli/nbt/libnbt.h"
24 : #include "../libcli/nbt/nbt_proto.h"
25 : #include "lib/socket/socket.h"
26 :
27 : /**
28 : send a nbt name query
29 : */
30 7239 : _PUBLIC_ struct nbt_name_request *nbt_name_query_send(struct nbt_name_socket *nbtsock,
31 : struct nbt_name_query *io)
32 : {
33 : struct nbt_name_request *req;
34 : struct nbt_name_packet *packet;
35 : struct socket_address *dest;
36 :
37 7239 : packet = talloc_zero(nbtsock, struct nbt_name_packet);
38 7239 : if (packet == NULL) return NULL;
39 :
40 7239 : packet->qdcount = 1;
41 7239 : packet->operation = NBT_OPCODE_QUERY;
42 7239 : if (io->in.broadcast) {
43 670 : packet->operation |= NBT_FLAG_BROADCAST;
44 : }
45 7239 : if (io->in.wins_lookup) {
46 6246 : packet->operation |= NBT_FLAG_RECURSION_DESIRED;
47 : }
48 :
49 7239 : packet->questions = talloc_array(packet, struct nbt_name_question, 1);
50 7239 : if (packet->questions == NULL) goto failed;
51 :
52 7239 : packet->questions[0].name = io->in.name;
53 7239 : packet->questions[0].question_type = NBT_QTYPE_NETBIOS;
54 7239 : packet->questions[0].question_class = NBT_QCLASS_IP;
55 :
56 7239 : dest = socket_address_from_strings(packet, nbtsock->sock->backend_name,
57 7239 : io->in.dest_addr, io->in.dest_port);
58 7239 : if (dest == NULL) goto failed;
59 7239 : req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
60 : io->in.timeout, io->in.retries, false);
61 7239 : if (req == NULL) goto failed;
62 :
63 7239 : talloc_free(packet);
64 7239 : return req;
65 :
66 0 : failed:
67 0 : talloc_free(packet);
68 0 : return NULL;
69 : }
70 :
71 : /**
72 : wait for a name query reply
73 : */
74 7194 : _PUBLIC_ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req,
75 : TALLOC_CTX *mem_ctx, struct nbt_name_query *io)
76 : {
77 : NTSTATUS status;
78 : struct nbt_name_packet *packet;
79 : int i;
80 :
81 7194 : status = nbt_name_request_recv(req);
82 7924 : if (!NT_STATUS_IS_OK(status) ||
83 910 : req->num_replies == 0) {
84 6284 : talloc_free(req);
85 6284 : return status;
86 : }
87 :
88 910 : packet = req->replies[0].packet;
89 910 : io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr);
90 :
91 910 : if ((packet->operation & NBT_RCODE) != 0) {
92 30 : status = nbt_rcode_to_ntstatus(packet->operation & NBT_RCODE);
93 30 : talloc_free(req);
94 30 : return status;
95 : }
96 :
97 1580 : if (packet->ancount != 1 ||
98 1580 : packet->answers[0].rr_type != NBT_QTYPE_NETBIOS ||
99 880 : packet->answers[0].rr_class != NBT_QCLASS_IP) {
100 0 : talloc_free(req);
101 0 : return status;
102 : }
103 :
104 880 : io->out.name = packet->answers[0].name;
105 880 : io->out.num_addrs = packet->answers[0].rdata.netbios.length / 6;
106 880 : io->out.reply_addrs = talloc_array(mem_ctx, const char *, io->out.num_addrs+1);
107 880 : if (io->out.reply_addrs == NULL) {
108 0 : talloc_free(req);
109 0 : return NT_STATUS_NO_MEMORY;
110 : }
111 :
112 1790 : for (i=0;i<io->out.num_addrs;i++) {
113 910 : io->out.reply_addrs[i] = talloc_steal(io->out.reply_addrs,
114 : packet->answers[0].rdata.netbios.addresses[i].ipaddr);
115 : }
116 880 : io->out.reply_addrs[i] = NULL;
117 :
118 880 : talloc_steal(mem_ctx, io->out.name.name);
119 880 : talloc_steal(mem_ctx, io->out.name.scope);
120 :
121 880 : talloc_free(req);
122 :
123 880 : return NT_STATUS_OK;
124 : }
125 :
126 : /**
127 : wait for a name query reply
128 : */
129 790 : _PUBLIC_ NTSTATUS nbt_name_query(struct nbt_name_socket *nbtsock,
130 : TALLOC_CTX *mem_ctx, struct nbt_name_query *io)
131 : {
132 790 : struct nbt_name_request *req = nbt_name_query_send(nbtsock, io);
133 790 : return nbt_name_query_recv(req, mem_ctx, io);
134 : }
135 :
136 :
137 : /**
138 : send a nbt name status
139 : */
140 0 : _PUBLIC_ struct nbt_name_request *nbt_name_status_send(struct nbt_name_socket *nbtsock,
141 : struct nbt_name_status *io)
142 : {
143 : struct nbt_name_request *req;
144 : struct nbt_name_packet *packet;
145 : struct socket_address *dest;
146 :
147 0 : packet = talloc_zero(nbtsock, struct nbt_name_packet);
148 0 : if (packet == NULL) return NULL;
149 :
150 0 : packet->qdcount = 1;
151 0 : packet->operation = NBT_OPCODE_QUERY;
152 :
153 0 : packet->questions = talloc_array(packet, struct nbt_name_question, 1);
154 0 : if (packet->questions == NULL) goto failed;
155 :
156 0 : packet->questions[0].name = io->in.name;
157 0 : packet->questions[0].question_type = NBT_QTYPE_STATUS;
158 0 : packet->questions[0].question_class = NBT_QCLASS_IP;
159 :
160 0 : dest = socket_address_from_strings(packet, nbtsock->sock->backend_name,
161 0 : io->in.dest_addr, io->in.dest_port);
162 0 : if (dest == NULL) goto failed;
163 0 : req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
164 : io->in.timeout, io->in.retries, false);
165 0 : if (req == NULL) goto failed;
166 :
167 0 : talloc_free(packet);
168 0 : return req;
169 :
170 0 : failed:
171 0 : talloc_free(packet);
172 0 : return NULL;
173 : }
174 :
175 : /**
176 : wait for a name status reply
177 : */
178 0 : _PUBLIC_ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req,
179 : TALLOC_CTX *mem_ctx, struct nbt_name_status *io)
180 : {
181 : NTSTATUS status;
182 : struct nbt_name_packet *packet;
183 : int i;
184 :
185 0 : status = nbt_name_request_recv(req);
186 0 : if (!NT_STATUS_IS_OK(status) ||
187 0 : req->num_replies == 0) {
188 0 : talloc_free(req);
189 0 : return status;
190 : }
191 :
192 0 : packet = req->replies[0].packet;
193 0 : io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr);
194 :
195 0 : if ((packet->operation & NBT_RCODE) != 0) {
196 0 : status = nbt_rcode_to_ntstatus(packet->operation & NBT_RCODE);
197 0 : talloc_free(req);
198 0 : return status;
199 : }
200 :
201 0 : if (packet->ancount != 1 ||
202 0 : packet->answers[0].rr_type != NBT_QTYPE_STATUS ||
203 0 : packet->answers[0].rr_class != NBT_QCLASS_IP) {
204 0 : talloc_free(req);
205 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
206 : }
207 :
208 0 : io->out.name = packet->answers[0].name;
209 0 : talloc_steal(mem_ctx, io->out.name.name);
210 0 : talloc_steal(mem_ctx, io->out.name.scope);
211 :
212 0 : io->out.status = packet->answers[0].rdata.status;
213 0 : talloc_steal(mem_ctx, io->out.status.names);
214 0 : for (i=0;i<io->out.status.num_names;i++) {
215 0 : talloc_steal(io->out.status.names, io->out.status.names[i].name);
216 : }
217 :
218 :
219 0 : talloc_free(req);
220 :
221 0 : return NT_STATUS_OK;
222 : }
223 :
224 : /**
225 : wait for a name status reply
226 : */
227 0 : _PUBLIC_ NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock,
228 : TALLOC_CTX *mem_ctx, struct nbt_name_status *io)
229 : {
230 0 : struct nbt_name_request *req = nbt_name_status_send(nbtsock, io);
231 0 : return nbt_name_status_recv(req, mem_ctx, io);
232 : }
233 :
234 :
|