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/nbt/libnbt.h"
39 #include "libcli/dgram/libdgram.h"
40 #include "lib/socket/socket.h"
43 destroy a mailslot handler
45 static int dgram_mailslot_destructor(void *ptr)
47 struct dgram_mailslot_handler *dgmslot =
48 talloc_get_type(ptr, struct dgram_mailslot_handler);
50 DLIST_REMOVE(dgmslot->dgmsock->mailslot_handlers, dgmslot);
55 start listening on a mailslot. talloc_free() the handle to stop listening
57 struct dgram_mailslot_handler *dgram_mailslot_listen(struct nbt_dgram_socket *dgmsock,
58 const char *mailslot_name,
59 dgram_mailslot_handler_t handler,
62 struct dgram_mailslot_handler *dgmslot;
64 dgmslot = talloc(dgmsock, struct dgram_mailslot_handler);
65 if (dgmslot == NULL) return NULL;
67 dgmslot->dgmsock = dgmsock;
68 dgmslot->mailslot_name = talloc_strdup(dgmslot, mailslot_name);
69 if (dgmslot->mailslot_name == NULL) {
73 dgmslot->handler = handler;
74 dgmslot->private = private;
76 DLIST_ADD(dgmsock->mailslot_handlers, dgmslot);
77 talloc_set_destructor(dgmslot, dgram_mailslot_destructor);
79 EVENT_FD_READABLE(dgmsock->fde);
85 find the handler for a specific mailslot name
87 struct dgram_mailslot_handler *dgram_mailslot_find(struct nbt_dgram_socket *dgmsock,
88 const char *mailslot_name)
90 struct dgram_mailslot_handler *h;
91 for (h=dgmsock->mailslot_handlers;h;h=h->next) {
92 if (strcasecmp(h->mailslot_name, mailslot_name) == 0) {
100 check that a datagram packet is a valid mailslot request, and return the
101 mailslot name if it is, otherwise return NULL
103 const char *dgram_mailslot_name(struct nbt_dgram_packet *packet)
105 if (packet->msg_type != DGRAM_DIRECT_UNIQUE &&
106 packet->msg_type != DGRAM_DIRECT_GROUP &&
107 packet->msg_type != DGRAM_BCAST) {
110 if (packet->data.msg.dgram_body_type != DGRAM_SMB) return NULL;
111 if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL;
112 return packet->data.msg.body.smb.body.trans.mailslot_name;
117 create a temporary mailslot handler for a reply mailslot, allocating
118 a new mailslot name using the given base name and a random integer extension
120 struct dgram_mailslot_handler *dgram_mailslot_temp(struct nbt_dgram_socket *dgmsock,
121 const char *mailslot_name,
122 dgram_mailslot_handler_t handler,
127 struct dgram_mailslot_handler *dgmslot;
129 /* try a 100 times at most */
130 for (i=0;i<100;i++) {
131 name = talloc_asprintf(dgmsock, "%s%03u",
133 generate_random() % 1000);
134 if (name == NULL) return NULL;
135 if (dgram_mailslot_find(dgmsock, name)) {
139 dgmslot = dgram_mailslot_listen(dgmsock, name, handler, private);
143 DEBUG(2,("Unable to create temporary mailslot from %s\n", mailslot_name));
149 send a mailslot request
151 NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock,
152 enum dgram_msg_type msg_type,
153 const char *mailslot_name,
154 struct nbt_name *dest_name,
155 const struct nbt_peer_socket *_dest,
156 struct nbt_name *src_name,
159 TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
160 struct nbt_dgram_packet packet;
161 struct nbt_peer_socket dest = *_dest;
162 struct dgram_message *msg;
163 struct dgram_smb_packet *smb;
164 struct smb_trans_body *trans;
167 if (dest.port == 0) {
168 dest.port = lp_dgram_port();
172 packet.msg_type = msg_type;
173 packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD;
174 packet.dgram_id = generate_random() % UINT16_MAX;
175 packet.src_addr = socket_get_my_addr(dgmsock->sock, tmp_ctx);
176 packet.src_port = socket_get_my_port(dgmsock->sock);
178 msg = &packet.data.msg;
179 /* this length calculation is very crude - it should be based on gensize
181 msg->length = 138 + strlen(mailslot_name) + request->length;
184 msg->source_name = *src_name;
185 msg->dest_name = *dest_name;
186 msg->dgram_body_type = DGRAM_SMB;
188 smb = &msg->body.smb;
189 smb->smb_command = SMB_TRANSACTION;
191 trans = &smb->body.trans;
192 trans->total_data_count = request->length;
193 trans->timeout = 1000;
194 trans->data_count = request->length;
195 trans->data_offset = 70 + strlen(mailslot_name);
196 trans->opcode = 1; /* write mail slot */
199 trans->mailslot_name = mailslot_name;
200 trans->data = *request;
202 status = nbt_dgram_send(dgmsock, &packet, &dest);
204 talloc_free(tmp_ctx);
210 return the mailslot data portion from a mailslot packet
212 DATA_BLOB dgram_mailslot_data(struct nbt_dgram_packet *dgram)
214 struct smb_trans_body *trans = &dgram->data.msg.body.smb.body.trans;
215 DATA_BLOB ret = trans->data;
216 int pad = trans->data_offset - (70 + strlen(trans->mailslot_name));
218 if (pad < 0 || pad > ret.length) {
219 DEBUG(2,("Badly formatted data in mailslot - pad = %d\n", pad));
220 return data_blob(NULL, 0);