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 3 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, see <http://www.gnu.org/licenses/>.
23 This implements "Class 2 mailslots", i.e. the communication mechanism
24 used for all mailslot packets smaller than 425 bytes.
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
31 425 and 426-byte sized messages are not supported at all.
35 #include "lib/events/events.h"
36 #include "lib/util/dlinklist.h"
37 #include "libcli/dgram/libdgram.h"
38 #include "lib/socket/socket.h"
41 destroy a mailslot handler
43 static int dgram_mailslot_destructor(struct dgram_mailslot_handler *dgmslot)
45 DLIST_REMOVE(dgmslot->dgmsock->mailslot_handlers, dgmslot);
50 start listening on a mailslot. talloc_free() the handle to stop listening
52 struct dgram_mailslot_handler *dgram_mailslot_listen(struct nbt_dgram_socket *dgmsock,
53 const char *mailslot_name,
54 dgram_mailslot_handler_t handler,
57 struct dgram_mailslot_handler *dgmslot;
59 dgmslot = talloc(dgmsock, struct dgram_mailslot_handler);
60 if (dgmslot == NULL) return NULL;
62 dgmslot->dgmsock = dgmsock;
63 dgmslot->mailslot_name = talloc_strdup(dgmslot, mailslot_name);
64 if (dgmslot->mailslot_name == NULL) {
68 dgmslot->handler = handler;
69 dgmslot->private = private;
71 DLIST_ADD(dgmsock->mailslot_handlers, dgmslot);
72 talloc_set_destructor(dgmslot, dgram_mailslot_destructor);
74 EVENT_FD_READABLE(dgmsock->fde);
80 find the handler for a specific mailslot name
82 struct dgram_mailslot_handler *dgram_mailslot_find(struct nbt_dgram_socket *dgmsock,
83 const char *mailslot_name)
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) {
95 check that a datagram packet is a valid mailslot request, and return the
96 mailslot name if it is, otherwise return NULL
98 const char *dgram_mailslot_name(struct nbt_dgram_packet *packet)
100 if (packet->msg_type != DGRAM_DIRECT_UNIQUE &&
101 packet->msg_type != DGRAM_DIRECT_GROUP &&
102 packet->msg_type != DGRAM_BCAST) {
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;
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
115 struct dgram_mailslot_handler *dgram_mailslot_temp(struct nbt_dgram_socket *dgmsock,
116 const char *mailslot_name,
117 dgram_mailslot_handler_t handler,
122 struct dgram_mailslot_handler *dgmslot;
124 /* try a 100 times at most */
125 for (i=0;i<100;i++) {
126 name = talloc_asprintf(dgmsock, "%s%03u",
128 generate_random() % 1000);
129 if (name == NULL) return NULL;
130 if (dgram_mailslot_find(dgmsock, name)) {
134 dgmslot = dgram_mailslot_listen(dgmsock, name, handler, private);
136 if (dgmslot != NULL) {
140 DEBUG(2,("Unable to create temporary mailslot from %s\n", mailslot_name));
146 send a mailslot request
148 NTSTATUS 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,
156 TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
157 struct nbt_dgram_packet packet;
158 struct socket_address *dest;
159 struct dgram_message *msg;
160 struct dgram_smb_packet *smb;
161 struct smb_trans_body *trans;
162 struct socket_address *src;
165 if (_dest->port == 0) {
166 dest = socket_address_from_strings(tmp_ctx, _dest->family,
167 _dest->addr, lp_dgram_port());
172 return NT_STATUS_NO_MEMORY;
176 packet.msg_type = msg_type;
177 packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD;
178 packet.dgram_id = generate_random() % UINT16_MAX;
179 src = socket_get_my_addr(dgmsock->sock, tmp_ctx);
181 return NT_STATUS_NO_MEMORY;
183 packet.src_addr = src->addr;
184 packet.src_port = src->port;
186 msg = &packet.data.msg;
187 /* this length calculation is very crude - it should be based on gensize
189 msg->length = 138 + strlen(mailslot_name) + request->length;
192 msg->source_name = *src_name;
193 msg->dest_name = *dest_name;
194 msg->dgram_body_type = DGRAM_SMB;
196 smb = &msg->body.smb;
197 smb->smb_command = SMB_TRANSACTION;
199 trans = &smb->body.trans;
200 trans->total_data_count = request->length;
201 trans->timeout = 1000;
202 trans->data_count = request->length;
203 trans->data_offset = 70 + strlen(mailslot_name);
204 trans->opcode = 1; /* write mail slot */
207 trans->mailslot_name = mailslot_name;
208 trans->data = *request;
210 status = nbt_dgram_send(dgmsock, &packet, dest);
212 talloc_free(tmp_ctx);
218 return the mailslot data portion from a mailslot packet
220 DATA_BLOB dgram_mailslot_data(struct nbt_dgram_packet *dgram)
222 struct smb_trans_body *trans = &dgram->data.msg.body.smb.body.trans;
223 DATA_BLOB ret = trans->data;
224 int pad = trans->data_offset - (70 + strlen(trans->mailslot_name));
226 if (pad < 0 || pad > ret.length) {
227 DEBUG(2,("Badly formatted data in mailslot - pad = %d\n", pad));
228 return data_blob(NULL, 0);