• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source4/nbt_server/
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/*
30  send a name status reply
31*/
32static void nbtd_node_status_reply(struct nbt_name_socket *nbtsock,
33				   struct nbt_name_packet *request_packet,
34				   struct socket_address *src,
35				   struct nbt_name *name,
36				   struct nbtd_interface *iface)
37{
38	struct nbt_name_packet *packet;
39	uint32_t name_count;
40	struct nbtd_iface_name *iname;
41	struct nbtd_server *nbtsrv = iface->nbtsrv;
42
43	/* work out how many names to send */
44	name_count = 0;
45	for (iname=iface->names;iname;iname=iname->next) {
46		if ((iname->nb_flags & NBT_NM_ACTIVE) &&
47		    strcmp(iname->name.name, "*") != 0) {
48			name_count++;
49		}
50	}
51
52	packet = talloc_zero(nbtsock, struct nbt_name_packet);
53	if (packet == NULL) return;
54
55	packet->name_trn_id = request_packet->name_trn_id;
56	packet->ancount = 1;
57	packet->operation = NBT_OPCODE_QUERY | NBT_FLAG_REPLY | NBT_FLAG_AUTHORITIVE;
58
59	packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
60	if (packet->answers == NULL) goto failed;
61
62	packet->answers[0].name     = *name;
63	packet->answers[0].rr_type  = NBT_QTYPE_STATUS;
64	packet->answers[0].rr_class = NBT_QCLASS_IP;
65	packet->answers[0].ttl      = 0;
66	packet->answers[0].rdata.status.num_names = name_count;
67	packet->answers[0].rdata.status.names = talloc_array(packet->answers,
68							     struct nbt_status_name, name_count);
69	if (packet->answers[0].rdata.status.names == NULL) goto failed;
70
71	name_count = 0;
72	for (iname=iface->names;iname;iname=iname->next) {
73		if ((iname->nb_flags & NBT_NM_ACTIVE) &&
74		    strcmp(iname->name.name, "*") != 0) {
75			struct nbt_status_name *n = &packet->answers[0].rdata.status.names[name_count];
76			n->name = talloc_asprintf(packet->answers, "%-15s", iname->name.name);
77			if (n->name == NULL) goto failed;
78			n->type     = iname->name.type;
79			n->nb_flags = iname->nb_flags;
80			name_count++;
81		}
82	}
83	/* we deliberately don't fill in the statistics structure as
84	   it could lead to giving attackers too much information */
85	ZERO_STRUCT(packet->answers[0].rdata.status.statistics);
86
87	DEBUG(7,("Sending node status reply for %s to %s:%d\n",
88		 nbt_name_string(packet, name), src->addr, src->port));
89
90	nbtsrv->stats.total_sent++;
91	nbt_name_reply_send(nbtsock, src, packet);
92
93failed:
94	talloc_free(packet);
95}
96
97
98/*
99  answer a node status query
100*/
101void nbtd_query_status(struct nbt_name_socket *nbtsock,
102		       struct nbt_name_packet *packet,
103		       struct socket_address *src)
104{
105	struct nbt_name *name;
106	struct nbtd_iface_name *iname;
107	struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
108						       struct nbtd_interface);
109
110	NBTD_ASSERT_PACKET(packet, src, packet->qdcount == 1);
111	NBTD_ASSERT_PACKET(packet, src, packet->questions[0].question_type == NBT_QTYPE_STATUS);
112	NBTD_ASSERT_PACKET(packet, src, packet->questions[0].question_class == NBT_QCLASS_IP);
113
114	/* see if we have the requested name on this interface */
115	name = &packet->questions[0].name;
116
117	iname = nbtd_find_iname(iface, name, NBT_NM_ACTIVE);
118	if (iname == NULL) {
119		DEBUG(7,("Node status query for %s from %s - not found on %s\n",
120			 nbt_name_string(packet, name), src->addr, iface->ip_address));
121		return;
122	}
123
124	nbtd_node_status_reply(nbtsock, packet, src,
125			       &iname->name, iface);
126}
127