Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : answer node status queries
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 "../lib/util/dlinklist.h"
24 : #include "system/network.h"
25 : #include "nbt_server/nbt_server.h"
26 : #include "lib/socket/socket.h"
27 : #include "librpc/gen_ndr/ndr_nbt.h"
28 :
29 19 : struct nbt_name_packet *nbtd_node_status_reply_packet(
30 : TALLOC_CTX *mem_ctx,
31 : uint16_t trn_id,
32 : const struct nbt_name *name,
33 : struct nbtd_interface *iface)
34 : {
35 0 : struct nbtd_iface_name *iname;
36 0 : struct nbt_name_packet *packet;
37 0 : struct nbt_res_rec *answer;
38 0 : struct nbt_rdata_status *stat;
39 0 : uint32_t num_names;
40 0 : NTSTATUS status;
41 :
42 19 : num_names = 0;
43 186 : for (iname = iface->names; iname != NULL; iname = iname->next) {
44 167 : if ((iname->nb_flags & NBT_NM_ACTIVE) == 0) {
45 0 : continue;
46 : }
47 167 : if (strcmp(iname->name.name, "*") == 0) {
48 19 : continue;
49 : }
50 148 : num_names += 1;
51 : }
52 :
53 19 : packet = talloc_zero(mem_ctx, struct nbt_name_packet);
54 19 : if (packet == NULL) {
55 0 : return NULL;
56 : }
57 :
58 19 : packet->name_trn_id = trn_id;
59 19 : packet->ancount = 1;
60 19 : packet->operation =
61 : NBT_OPCODE_QUERY |
62 : NBT_FLAG_REPLY |
63 : NBT_FLAG_AUTHORITATIVE;
64 :
65 19 : packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
66 19 : if (packet->answers == NULL) {
67 0 : goto failed;
68 : }
69 :
70 19 : answer = &packet->answers[0];
71 :
72 19 : status = nbt_name_dup(packet->answers, name, &answer->name);
73 19 : if (!NT_STATUS_IS_OK(status)) {
74 0 : goto failed;
75 : }
76 :
77 19 : answer->rr_type = NBT_QTYPE_STATUS;
78 19 : answer->rr_class = NBT_QCLASS_IP;
79 19 : answer->ttl = 0;
80 :
81 19 : stat = &packet->answers[0].rdata.status;
82 :
83 19 : stat->num_names = num_names;
84 19 : stat->names = talloc_zero_array(
85 : packet->answers,
86 : struct nbt_status_name,
87 : num_names);
88 19 : if (stat->names == NULL) {
89 0 : goto failed;
90 : }
91 :
92 19 : num_names = 0;
93 186 : for (iname = iface->names; iname != NULL; iname = iname->next) {
94 167 : struct nbt_status_name *n = &stat->names[num_names];
95 :
96 167 : if ((iname->nb_flags & NBT_NM_ACTIVE) == 0) {
97 0 : continue;
98 : }
99 167 : if (strcmp(iname->name.name, "*") == 0) {
100 19 : continue;
101 : }
102 :
103 296 : n->name = talloc_asprintf(
104 148 : stat->names,
105 : "%-15s",
106 : iname->name.name);
107 148 : if (n->name == NULL) {
108 0 : goto failed;
109 : }
110 148 : n->type = iname->name.type;
111 148 : n->nb_flags = iname->nb_flags;
112 :
113 148 : num_names += 1;
114 : }
115 :
116 19 : return packet;
117 :
118 0 : failed:
119 0 : TALLOC_FREE(packet);
120 0 : return NULL;
121 : }
122 :
123 : /*
124 : send a name status reply
125 : */
126 19 : static void nbtd_node_status_reply(struct nbt_name_socket *nbtsock,
127 : struct nbt_name_packet *request_packet,
128 : struct socket_address *src,
129 : struct nbt_name *name,
130 : struct nbtd_interface *iface)
131 : {
132 0 : struct nbt_name_packet *packet;
133 19 : struct nbtd_server *nbtsrv = iface->nbtsrv;
134 :
135 19 : packet = nbtd_node_status_reply_packet(
136 : nbtsock,
137 19 : request_packet->name_trn_id,
138 : name,
139 : iface);
140 19 : if (packet == NULL) {
141 0 : return;
142 : }
143 :
144 19 : DEBUG(7,("Sending node status reply for %s to %s:%d\n",
145 : nbt_name_string(packet, name), src->addr, src->port));
146 :
147 19 : nbtsrv->stats.total_sent++;
148 19 : nbt_name_reply_send(nbtsock, src, packet);
149 :
150 19 : talloc_free(packet);
151 : }
152 :
153 :
154 : /*
155 : answer a node status query
156 : */
157 19 : void nbtd_query_status(struct nbt_name_socket *nbtsock,
158 : struct nbt_name_packet *packet,
159 : struct socket_address *src)
160 : {
161 0 : struct nbt_name *name;
162 0 : struct nbtd_iface_name *iname;
163 19 : struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
164 : struct nbtd_interface);
165 :
166 19 : NBTD_ASSERT_PACKET(packet, src, packet->qdcount == 1);
167 19 : NBTD_ASSERT_PACKET(packet, src, packet->questions[0].question_type == NBT_QTYPE_STATUS);
168 19 : NBTD_ASSERT_PACKET(packet, src, packet->questions[0].question_class == NBT_QCLASS_IP);
169 :
170 : /* see if we have the requested name on this interface */
171 19 : name = &packet->questions[0].name;
172 :
173 19 : iname = nbtd_find_iname(iface, name, NBT_NM_ACTIVE);
174 19 : if (iname == NULL) {
175 0 : DEBUG(7,("Node status query for %s from %s - not found on %s\n",
176 : nbt_name_string(packet, name), src->addr, iface->ip_address));
177 0 : return;
178 : }
179 :
180 19 : nbtd_node_status_reply(nbtsock, packet, src,
181 : &iname->name, iface);
182 : }
|