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 9761 : _PUBLIC_ struct nbt_name_request *nbt_name_query_send(struct nbt_name_socket *nbtsock,
31 : struct nbt_name_query *io)
32 : {
33 30 : struct nbt_name_request *req;
34 30 : struct nbt_name_packet *packet;
35 30 : struct socket_address *dest;
36 :
37 9761 : packet = talloc_zero(nbtsock, struct nbt_name_packet);
38 9761 : if (packet == NULL) return NULL;
39 :
40 9761 : packet->qdcount = 1;
41 9761 : packet->operation = NBT_OPCODE_QUERY;
42 9761 : if (io->in.broadcast) {
43 628 : packet->operation |= NBT_FLAG_BROADCAST;
44 : }
45 9761 : if (io->in.wins_lookup) {
46 8738 : packet->operation |= NBT_FLAG_RECURSION_DESIRED;
47 : }
48 :
49 9761 : packet->questions = talloc_array(packet, struct nbt_name_question, 1);
50 9761 : if (packet->questions == NULL) goto failed;
51 :
52 9761 : packet->questions[0].name = io->in.name;
53 9761 : packet->questions[0].question_type = NBT_QTYPE_NETBIOS;
54 9761 : packet->questions[0].question_class = NBT_QCLASS_IP;
55 :
56 9791 : dest = socket_address_from_strings(packet, nbtsock->sock->backend_name,
57 9761 : io->in.dest_addr, io->in.dest_port);
58 9761 : if (dest == NULL) goto failed;
59 9761 : req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
60 : io->in.timeout, io->in.retries, false);
61 9761 : if (req == NULL) goto failed;
62 :
63 9761 : talloc_free(packet);
64 9761 : 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 9676 : _PUBLIC_ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req,
75 : TALLOC_CTX *mem_ctx, struct nbt_name_query *io)
76 : {
77 30 : NTSTATUS status;
78 30 : struct nbt_name_packet *packet;
79 30 : int i;
80 :
81 9676 : status = nbt_name_request_recv(req);
82 9676 : if (!NT_STATUS_IS_OK(status) ||
83 876 : req->num_replies == 0) {
84 8800 : talloc_free(req);
85 8800 : return status;
86 : }
87 :
88 876 : packet = req->replies[0].packet;
89 876 : io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr);
90 :
91 876 : 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 846 : if (packet->ancount != 1 ||
98 846 : packet->answers[0].rr_type != NBT_QTYPE_NETBIOS ||
99 822 : packet->answers[0].rr_class != NBT_QCLASS_IP) {
100 0 : talloc_free(req);
101 0 : return status;
102 : }
103 :
104 846 : io->out.name = packet->answers[0].name;
105 846 : io->out.num_addrs = packet->answers[0].rdata.netbios.length / 6;
106 846 : io->out.reply_addrs = talloc_array(mem_ctx, const char *, io->out.num_addrs+1);
107 846 : if (io->out.reply_addrs == NULL) {
108 0 : talloc_free(req);
109 0 : return NT_STATUS_NO_MEMORY;
110 : }
111 :
112 1722 : for (i=0;i<io->out.num_addrs;i++) {
113 876 : io->out.reply_addrs[i] = talloc_steal(io->out.reply_addrs,
114 : packet->answers[0].rdata.netbios.addresses[i].ipaddr);
115 : }
116 846 : io->out.reply_addrs[i] = NULL;
117 :
118 846 : talloc_steal(mem_ctx, io->out.name.name);
119 846 : talloc_steal(mem_ctx, io->out.name.scope);
120 :
121 846 : talloc_free(req);
122 :
123 846 : return NT_STATUS_OK;
124 : }
125 :
126 : /**
127 : wait for a name query reply
128 : */
129 960 : _PUBLIC_ NTSTATUS nbt_name_query(struct nbt_name_socket *nbtsock,
130 : TALLOC_CTX *mem_ctx, struct nbt_name_query *io)
131 : {
132 960 : struct nbt_name_request *req = nbt_name_query_send(nbtsock, io);
133 960 : return nbt_name_query_recv(req, mem_ctx, io);
134 : }
135 :
136 :
137 : /**
138 : send a nbt name status
139 : */
140 2 : _PUBLIC_ struct nbt_name_request *nbt_name_status_send(struct nbt_name_socket *nbtsock,
141 : struct nbt_name_status *io)
142 : {
143 0 : struct nbt_name_request *req;
144 0 : struct nbt_name_packet *packet;
145 0 : struct socket_address *dest;
146 :
147 2 : packet = talloc_zero(nbtsock, struct nbt_name_packet);
148 2 : if (packet == NULL) return NULL;
149 :
150 2 : packet->qdcount = 1;
151 2 : packet->operation = NBT_OPCODE_QUERY;
152 :
153 2 : packet->questions = talloc_array(packet, struct nbt_name_question, 1);
154 2 : if (packet->questions == NULL) goto failed;
155 :
156 2 : packet->questions[0].name = io->in.name;
157 2 : packet->questions[0].question_type = NBT_QTYPE_STATUS;
158 2 : packet->questions[0].question_class = NBT_QCLASS_IP;
159 :
160 2 : dest = socket_address_from_strings(packet, nbtsock->sock->backend_name,
161 2 : io->in.dest_addr, io->in.dest_port);
162 2 : if (dest == NULL) goto failed;
163 2 : req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
164 : io->in.timeout, io->in.retries, false);
165 2 : if (req == NULL) goto failed;
166 :
167 2 : talloc_free(packet);
168 2 : 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 2 : _PUBLIC_ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req,
179 : TALLOC_CTX *mem_ctx, struct nbt_name_status *io)
180 : {
181 0 : NTSTATUS status;
182 0 : struct nbt_name_packet *packet;
183 0 : int i;
184 :
185 2 : status = nbt_name_request_recv(req);
186 2 : if (!NT_STATUS_IS_OK(status) ||
187 2 : req->num_replies == 0) {
188 0 : talloc_free(req);
189 0 : return status;
190 : }
191 :
192 2 : packet = req->replies[0].packet;
193 2 : io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr);
194 :
195 2 : 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 2 : if (packet->ancount != 1 ||
202 2 : packet->answers[0].rr_type != NBT_QTYPE_STATUS ||
203 2 : packet->answers[0].rr_class != NBT_QCLASS_IP) {
204 0 : talloc_free(req);
205 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
206 : }
207 :
208 2 : io->out.name = packet->answers[0].name;
209 2 : talloc_steal(mem_ctx, io->out.name.name);
210 2 : talloc_steal(mem_ctx, io->out.name.scope);
211 :
212 2 : io->out.status = packet->answers[0].rdata.status;
213 2 : talloc_steal(mem_ctx, io->out.status.names);
214 20 : for (i=0;i<io->out.status.num_names;i++) {
215 18 : talloc_steal(io->out.status.names, io->out.status.names[i].name);
216 : }
217 :
218 :
219 2 : talloc_free(req);
220 :
221 2 : return NT_STATUS_OK;
222 : }
223 :
224 : /**
225 : wait for a name status reply
226 : */
227 2 : _PUBLIC_ NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock,
228 : TALLOC_CTX *mem_ctx, struct nbt_name_status *io)
229 : {
230 2 : struct nbt_name_request *req = nbt_name_status_send(nbtsock, io);
231 2 : return nbt_name_status_recv(req, mem_ctx, io);
232 : }
233 :
234 :
|