2 Unix SMB/CIFS implementation.
4 packet handling for mailslot requests.
6 Copyright (C) Andrew Tridgell 2005
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 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This implements "Class 2 mailslots", i.e. the communication mechanism
25 used for all mailslot packets smaller then 425 bytes.
27 "Class 1 mailslots" (which use SMB) are used for messages larger
28 then 426 bytes and are supported on some systems. These are not implemented
29 in Samba4 yet, as there don't appear to be any core services that use
32 425 and 426-byte sized messages are not supported at all.
36 #include "lib/events/events.h"
37 #include "dlinklist.h"
38 #include "libcli/dgram/libdgram.h"
39 #include "lib/socket/socket.h"
42 destroy a mailslot handler
44 static int dgram_mailslot_destructor(struct dgram_mailslot_handler *dgmslot)
46 DLIST_REMOVE(dgmslot->dgmsock->mailslot_handlers, dgmslot);
51 start listening on a mailslot. talloc_free() the handle to stop listening
53 struct dgram_mailslot_handler *dgram_mailslot_listen(struct nbt_dgram_socket *dgmsock,
54 const char *mailslot_name,
55 dgram_mailslot_handler_t handler,
58 struct dgram_mailslot_handler *dgmslot;
60 dgmslot = talloc(dgmsock, struct dgram_mailslot_handler);
61 if (dgmslot == NULL) return NULL;
63 dgmslot->dgmsock = dgmsock;
64 dgmslot->mailslot_name = talloc_strdup(dgmslot, mailslot_name);
65 if (dgmslot->mailslot_name == NULL) {
69 dgmslot->handler = handler;
70 dgmslot->private = private;
72 DLIST_ADD(dgmsock->mailslot_handlers, dgmslot);
73 talloc_set_destructor(dgmslot, dgram_mailslot_destructor);
75 EVENT_FD_READABLE(dgmsock->fde);
81 find the handler for a specific mailslot name
83 struct dgram_mailslot_handler *dgram_mailslot_find(struct nbt_dgram_socket *dgmsock,
84 const char *mailslot_name)
86 struct dgram_mailslot_handler *h;
87 for (h=dgmsock->mailslot_handlers;h;h=h->next) {
88 if (strcasecmp(h->mailslot_name, mailslot_name) == 0) {
96 check that a datagram packet is a valid mailslot request, and return the
97 mailslot name if it is, otherwise return NULL
99 const char *dgram_mailslot_name(struct nbt_dgram_packet *packet)
101 if (packet->msg_type != DGRAM_DIRECT_UNIQUE &&
102 packet->msg_type != DGRAM_DIRECT_GROUP &&
103 packet->msg_type != DGRAM_BCAST) {
106 if (packet->data.msg.dgram_body_type != DGRAM_SMB) return NULL;
107 if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL;
108 return packet->data.msg.body.smb.body.trans.mailslot_name;
113 create a temporary mailslot handler for a reply mailslot, allocating
114 a new mailslot name using the given base name and a random integer extension
116 struct dgram_mailslot_handler *dgram_mailslot_temp(struct nbt_dgram_socket *dgmsock,
117 const char *mailslot_name,
118 dgram_mailslot_handler_t handler,
123 struct dgram_mailslot_handler *dgmslot;
125 /* try a 100 times at most */
126 for (i=0;i<100;i++) {
127 name = talloc_asprintf(dgmsock, "%s%03u",
129 generate_random() % 1000);
130 if (name == NULL) return NULL;
131 if (dgram_mailslot_find(dgmsock, name)) {
135 dgmslot = dgram_mailslot_listen(dgmsock, name, handler, private);
137 if (dgmslot != NULL) {
141 DEBUG(2,("Unable to create temporary mailslot from %s\n", mailslot_name));
147 send a mailslot request
149 NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock,
150 enum dgram_msg_type msg_type,
151 const char *mailslot_name,
152 struct nbt_name *dest_name,
153 struct socket_address *_dest,
154 struct nbt_name *src_name,
157 TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
158 struct nbt_dgram_packet packet;
159 struct socket_address *dest;
160 struct dgram_message *msg;
161 struct dgram_smb_packet *smb;
162 struct smb_trans_body *trans;
163 struct socket_address *src;
166 if (_dest->port == 0) {
167 dest = socket_address_from_strings(tmp_ctx, _dest->family,
168 _dest->addr, lp_dgram_port());
173 return NT_STATUS_NO_MEMORY;
177 packet.msg_type = msg_type;
178 packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD;
179 packet.dgram_id = generate_random() % UINT16_MAX;
180 src = socket_get_my_addr(dgmsock->sock, tmp_ctx);
182 return NT_STATUS_NO_MEMORY;
184 packet.src_addr = src->addr;
185 packet.src_port = src->port;
187 msg = &packet.data.msg;
188 /* this length calculation is very crude - it should be based on gensize
190 msg->length = 138 + strlen(mailslot_name) + request->length;
193 msg->source_name = *src_name;
194 msg->dest_name = *dest_name;
195 msg->dgram_body_type = DGRAM_SMB;
197 smb = &msg->body.smb;
198 smb->smb_command = SMB_TRANSACTION;
200 trans = &smb->body.trans;
201 trans->total_data_count = request->length;
202 trans->timeout = 1000;
203 trans->data_count = request->length;
204 trans->data_offset = 70 + strlen(mailslot_name);
205 trans->opcode = 1; /* write mail slot */
208 trans->mailslot_name = mailslot_name;
209 trans->data = *request;
211 status = nbt_dgram_send(dgmsock, &packet, dest);
213 talloc_free(tmp_ctx);
219 return the mailslot data portion from a mailslot packet
221 DATA_BLOB dgram_mailslot_data(struct nbt_dgram_packet *dgram)
223 struct smb_trans_body *trans = &dgram->data.msg.body.smb.body.trans;
224 DATA_BLOB ret = trans->data;
225 int pad = trans->data_offset - (70 + strlen(trans->mailslot_name));
227 if (pad < 0 || pad > ret.length) {
228 DEBUG(2,("Badly formatted data in mailslot - pad = %d\n", pad));
229 return data_blob(NULL, 0);