tests/rodc_rwdc: fix message format
[vlendec/samba-autobuild/.git] / source4 / nbt_server / nodestatus.c
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 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         struct nbtd_iface_name *iname;
36         struct nbt_name_packet *packet;
37         struct nbt_res_rec *answer;
38         struct nbt_rdata_status *stat;
39         uint32_t num_names;
40         NTSTATUS status;
41
42         num_names = 0;
43         for (iname = iface->names; iname != NULL; iname = iname->next) {
44                 if ((iname->nb_flags & NBT_NM_ACTIVE) == 0) {
45                         continue;
46                 }
47                 if (strcmp(iname->name.name, "*") == 0) {
48                         continue;
49                 }
50                 num_names += 1;
51         }
52
53         packet = talloc_zero(mem_ctx, struct nbt_name_packet);
54         if (packet == NULL) {
55                 return NULL;
56         }
57
58         packet->name_trn_id = trn_id;
59         packet->ancount = 1;
60         packet->operation =
61                 NBT_OPCODE_QUERY |
62                 NBT_FLAG_REPLY |
63                 NBT_FLAG_AUTHORITATIVE;
64
65         packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
66         if (packet->answers == NULL) {
67                 goto failed;
68         }
69
70         answer = &packet->answers[0];
71
72         status = nbt_name_dup(packet->answers, name, &answer->name);
73         if (!NT_STATUS_IS_OK(status)) {
74                 goto failed;
75         }
76
77         answer->rr_type  = NBT_QTYPE_STATUS;
78         answer->rr_class = NBT_QCLASS_IP;
79         answer->ttl      = 0;
80
81         stat = &packet->answers[0].rdata.status;
82
83         stat->num_names = num_names;
84         stat->names = talloc_zero_array(
85                 packet->answers,
86                 struct nbt_status_name,
87                 num_names);
88         if (stat->names == NULL) {
89                 goto failed;
90         }
91
92         num_names = 0;
93         for (iname = iface->names; iname != NULL; iname = iname->next) {
94                 struct nbt_status_name *n = &stat->names[num_names];
95
96                 if ((iname->nb_flags & NBT_NM_ACTIVE) == 0) {
97                         continue;
98                 }
99                 if (strcmp(iname->name.name, "*") == 0) {
100                         continue;
101                 }
102
103                 n->name = talloc_asprintf(
104                         stat->names,
105                         "%-15s",
106                         iname->name.name);
107                 if (n->name == NULL) {
108                         goto failed;
109                 }
110                 n->type = iname->name.type;
111                 n->nb_flags = iname->nb_flags;
112
113                 num_names += 1;
114         }
115
116         return packet;
117
118 failed:
119         TALLOC_FREE(packet);
120         return NULL;
121 }
122
123 /*
124   send a name status reply
125 */
126 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         struct nbt_name_packet *packet;
133         struct nbtd_server *nbtsrv = iface->nbtsrv;
134
135         packet = nbtd_node_status_reply_packet(
136                 nbtsock,
137                 request_packet->name_trn_id,
138                 name,
139                 iface);
140         if (packet == NULL) {
141                 return;
142         }
143
144         DEBUG(7,("Sending node status reply for %s to %s:%d\n", 
145                  nbt_name_string(packet, name), src->addr, src->port));
146         
147         nbtsrv->stats.total_sent++;
148         nbt_name_reply_send(nbtsock, src, packet);
149
150         talloc_free(packet);
151 }
152
153
154 /*
155   answer a node status query
156 */
157 void nbtd_query_status(struct nbt_name_socket *nbtsock, 
158                        struct nbt_name_packet *packet, 
159                        struct socket_address *src)
160 {
161         struct nbt_name *name;
162         struct nbtd_iface_name *iname;
163         struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
164                                                        struct nbtd_interface);
165
166         NBTD_ASSERT_PACKET(packet, src, packet->qdcount == 1);
167         NBTD_ASSERT_PACKET(packet, src, packet->questions[0].question_type == NBT_QTYPE_STATUS);
168         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         name = &packet->questions[0].name;
172
173         iname = nbtd_find_iname(iface, name, NBT_NM_ACTIVE);
174         if (iname == NULL) {
175                 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                 return;
178         }
179
180         nbtd_node_status_reply(nbtsock, packet, src, 
181                                &iname->name, iface);
182 }