• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/libcli/dgram/
1/*
2   Unix SMB/CIFS implementation.
3
4   packet handling for mailslot 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/*
23   This implements "Class 2 mailslots", i.e. the communication mechanism
24   used for all mailslot packets smaller than 425 bytes.
25
26   "Class 1 mailslots" (which use SMB) are used for messages larger
27   than 426 bytes and are supported on some systems. These are not implemented
28   in Samba4 yet, as there don't appear to be any core services that use
29   them.
30
31   425 and 426-byte sized messages are not supported at all.
32*/
33
34#include "includes.h"
35#include "lib/events/events.h"
36#include "../lib/util/dlinklist.h"
37#include "libcli/dgram/libdgram.h"
38#include "lib/socket/socket.h"
39
40/*
41  destroy a mailslot handler
42*/
43static int dgram_mailslot_destructor(struct dgram_mailslot_handler *dgmslot)
44{
45	DLIST_REMOVE(dgmslot->dgmsock->mailslot_handlers, dgmslot);
46	return 0;
47}
48
49/*
50  start listening on a mailslot. talloc_free() the handle to stop listening
51*/
52struct dgram_mailslot_handler *dgram_mailslot_listen(struct nbt_dgram_socket *dgmsock,
53						     const char *mailslot_name,
54						     dgram_mailslot_handler_t handler,
55						     void *private_data)
56{
57	struct dgram_mailslot_handler *dgmslot;
58
59	dgmslot = talloc(dgmsock, struct dgram_mailslot_handler);
60	if (dgmslot == NULL) return NULL;
61
62	dgmslot->dgmsock = dgmsock;
63	dgmslot->mailslot_name = talloc_strdup(dgmslot, mailslot_name);
64	if (dgmslot->mailslot_name == NULL) {
65		talloc_free(dgmslot);
66		return NULL;
67	}
68	dgmslot->handler = handler;
69	dgmslot->private_data = private_data;
70
71	DLIST_ADD(dgmsock->mailslot_handlers, dgmslot);
72	talloc_set_destructor(dgmslot, dgram_mailslot_destructor);
73
74	EVENT_FD_READABLE(dgmsock->fde);
75
76	return dgmslot;
77}
78
79/*
80  find the handler for a specific mailslot name
81*/
82struct dgram_mailslot_handler *dgram_mailslot_find(struct nbt_dgram_socket *dgmsock,
83						   const char *mailslot_name)
84{
85	struct dgram_mailslot_handler *h;
86	for (h=dgmsock->mailslot_handlers;h;h=h->next) {
87		if (strcasecmp(h->mailslot_name, mailslot_name) == 0) {
88			return h;
89		}
90	}
91	return NULL;
92}
93
94/*
95  check that a datagram packet is a valid mailslot request, and return the
96  mailslot name if it is, otherwise return NULL
97*/
98const char *dgram_mailslot_name(struct nbt_dgram_packet *packet)
99{
100	if (packet->msg_type != DGRAM_DIRECT_UNIQUE &&
101	    packet->msg_type != DGRAM_DIRECT_GROUP &&
102	    packet->msg_type != DGRAM_BCAST) {
103		return NULL;
104	}
105	if (packet->data.msg.dgram_body_type != DGRAM_SMB) return NULL;
106	if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL;
107	return packet->data.msg.body.smb.body.trans.mailslot_name;
108}
109
110
111/*
112  create a temporary mailslot handler for a reply mailslot, allocating
113  a new mailslot name using the given base name and a random integer extension
114*/
115struct dgram_mailslot_handler *dgram_mailslot_temp(struct nbt_dgram_socket *dgmsock,
116						   const char *mailslot_name,
117						   dgram_mailslot_handler_t handler,
118						   void *private_data)
119{
120	char *name;
121	int i;
122	struct dgram_mailslot_handler *dgmslot;
123
124	/* try a 100 times at most */
125	for (i=0;i<100;i++) {
126		name = talloc_asprintf(dgmsock, "%s%03u",
127				       mailslot_name,
128				       generate_random() % 1000);
129		if (name == NULL) return NULL;
130		if (dgram_mailslot_find(dgmsock, name)) {
131			talloc_free(name);
132			return NULL;
133		}
134		dgmslot = dgram_mailslot_listen(dgmsock, name, handler, private_data);
135		talloc_free(name);
136		if (dgmslot != NULL) {
137			return dgmslot;
138		}
139	}
140	DEBUG(2,("Unable to create temporary mailslot from %s\n", mailslot_name));
141	return NULL;
142}
143
144
145/*
146  send a mailslot request
147*/
148NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock,
149			     enum dgram_msg_type msg_type,
150			     const char *mailslot_name,
151			     struct nbt_name *dest_name,
152			     struct socket_address *dest,
153			     struct nbt_name *src_name,
154			     DATA_BLOB *request)
155{
156	TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
157	struct nbt_dgram_packet packet;
158	struct dgram_message *msg;
159	struct dgram_smb_packet *smb;
160	struct smb_trans_body *trans;
161	struct socket_address *src;
162	NTSTATUS status;
163
164	if (dest->port == 0) {
165		return NT_STATUS_INVALID_PARAMETER;
166	}
167
168	ZERO_STRUCT(packet);
169	packet.msg_type = msg_type;
170	packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD;
171	packet.dgram_id = generate_random() % UINT16_MAX;
172	src = socket_get_my_addr(dgmsock->sock, tmp_ctx);
173	if (!src) {
174		return NT_STATUS_NO_MEMORY;
175	}
176	packet.src_addr = src->addr;
177	packet.src_port = src->port;
178
179	msg = &packet.data.msg;
180	/* this length calculation is very crude - it should be based on gensize
181	   calls */
182	msg->length = 138 + strlen(mailslot_name) + request->length;
183	msg->offset = 0;
184
185	msg->source_name = *src_name;
186	msg->dest_name = *dest_name;
187	msg->dgram_body_type = DGRAM_SMB;
188
189	smb = &msg->body.smb;
190	smb->smb_command = SMB_TRANSACTION;
191
192	trans = &smb->body.trans;
193	trans->total_data_count = request->length;
194	trans->timeout     = 1000;
195	trans->data_count  = request->length;
196	trans->data_offset = 70 + strlen(mailslot_name);
197	trans->opcode      = 1; /* write mail slot */
198	trans->priority    = 1;
199	trans->_class      = 2;
200	trans->mailslot_name = mailslot_name;
201	trans->data = *request;
202
203	status = nbt_dgram_send(dgmsock, &packet, dest);
204
205	talloc_free(tmp_ctx);
206
207	return status;
208}
209
210/*
211  return the mailslot data portion from a mailslot packet
212*/
213DATA_BLOB dgram_mailslot_data(struct nbt_dgram_packet *dgram)
214{
215	struct smb_trans_body *trans = &dgram->data.msg.body.smb.body.trans;
216	DATA_BLOB ret = trans->data;
217	int pad = trans->data_offset - (70 + strlen(trans->mailslot_name));
218
219	if (pad < 0 || pad > ret.length) {
220		DEBUG(2,("Badly formatted data in mailslot - pad = %d\n", pad));
221		return data_blob(NULL, 0);
222	}
223	ret.data += pad;
224	ret.length -= pad;
225	return ret;
226}
227