ctdb-scripts: Move connection tracking to 10.interface
[samba4-gss.git] / source4 / libcli / dgram / mailslot.c
bloba24800c515f6d980cd2ea7aa0b26624e424b11a3
1 /*
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
29 them.
31 425 and 426-byte sized messages are not supported at all.
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"
40 #undef strcasecmp
43 destroy a mailslot handler
45 static int dgram_mailslot_destructor(struct dgram_mailslot_handler *dgmslot)
47 DLIST_REMOVE(dgmslot->dgmsock->mailslot_handlers, dgmslot);
48 return 0;
52 start listening on a mailslot. talloc_free() the handle to stop listening
54 struct dgram_mailslot_handler *dgram_mailslot_listen(struct nbt_dgram_socket *dgmsock,
55 const char *mailslot_name,
56 dgram_mailslot_handler_t handler,
57 void *private_data)
59 struct dgram_mailslot_handler *dgmslot;
61 dgmslot = talloc(dgmsock, struct dgram_mailslot_handler);
62 if (dgmslot == NULL) return NULL;
64 dgmslot->dgmsock = dgmsock;
65 dgmslot->mailslot_name = talloc_strdup(dgmslot, mailslot_name);
66 if (dgmslot->mailslot_name == NULL) {
67 talloc_free(dgmslot);
68 return NULL;
70 dgmslot->handler = handler;
71 dgmslot->private_data = private_data;
73 DLIST_ADD(dgmsock->mailslot_handlers, dgmslot);
74 talloc_set_destructor(dgmslot, dgram_mailslot_destructor);
76 TEVENT_FD_READABLE(dgmsock->fde);
78 return dgmslot;
82 find the handler for a specific mailslot name
84 struct dgram_mailslot_handler *dgram_mailslot_find(struct nbt_dgram_socket *dgmsock,
85 const char *mailslot_name)
87 struct dgram_mailslot_handler *h;
88 for (h=dgmsock->mailslot_handlers;h;h=h->next) {
89 if (strcasecmp(h->mailslot_name, mailslot_name) == 0) {
90 return h;
93 return NULL;
97 check that a datagram packet is a valid mailslot request, and return the
98 mailslot name if it is, otherwise return NULL
100 const char *dgram_mailslot_name(struct nbt_dgram_packet *packet)
102 if (packet->msg_type != DGRAM_DIRECT_UNIQUE &&
103 packet->msg_type != DGRAM_DIRECT_GROUP &&
104 packet->msg_type != DGRAM_BCAST) {
105 return NULL;
107 if (packet->data.msg.dgram_body_type != DGRAM_SMB) return NULL;
108 if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL;
109 return packet->data.msg.body.smb.body.trans.mailslot_name;
114 create a temporary mailslot handler for a reply mailslot, allocating
115 a new mailslot name using the given base name and a random integer extension
117 struct dgram_mailslot_handler *dgram_mailslot_temp(struct nbt_dgram_socket *dgmsock,
118 const char *mailslot_name,
119 dgram_mailslot_handler_t handler,
120 void *private_data)
122 char *name;
123 int i;
124 struct dgram_mailslot_handler *dgmslot;
126 /* try a 100 times at most */
127 for (i=0;i<100;i++) {
128 name = talloc_asprintf(dgmsock, "%s%03u",
129 mailslot_name,
130 generate_random() % 1000);
131 if (name == NULL) return NULL;
132 if (dgram_mailslot_find(dgmsock, name)) {
133 talloc_free(name);
134 continue;
136 dgmslot = dgram_mailslot_listen(dgmsock, name, handler, private_data);
137 talloc_free(name);
138 if (dgmslot != NULL) {
139 return dgmslot;
142 DEBUG(2,("Unable to create temporary mailslot from %s\n", mailslot_name));
143 return NULL;
148 send a mailslot request
150 NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock,
151 enum dgram_msg_type msg_type,
152 const char *mailslot_name,
153 struct nbt_name *dest_name,
154 struct socket_address *dest,
155 struct nbt_name *src_name,
156 DATA_BLOB *request)
158 TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
159 struct nbt_dgram_packet packet;
160 struct dgram_message *msg;
161 struct dgram_smb_packet *smb;
162 struct smb_trans_body *trans;
163 struct socket_address *src;
164 NTSTATUS status;
166 if (dest->port == 0) {
167 return NT_STATUS_INVALID_PARAMETER;
170 ZERO_STRUCT(packet);
171 packet.msg_type = msg_type;
172 packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD;
173 packet.dgram_id = generate_random() % UINT16_MAX;
174 src = socket_get_my_addr(dgmsock->sock, tmp_ctx);
175 if (!src) {
176 talloc_free(tmp_ctx);
177 return NT_STATUS_NO_MEMORY;
179 packet.src_addr = src->addr;
180 packet.src_port = src->port;
182 msg = &packet.data.msg;
183 /* this length calculation is very crude - it should be based on gensize
184 calls */
185 msg->length = 138 + strlen(mailslot_name) + request->length;
186 msg->offset = 0;
188 msg->source_name = *src_name;
189 msg->dest_name = *dest_name;
190 msg->dgram_body_type = DGRAM_SMB;
192 smb = &msg->body.smb;
193 smb->smb_command = SMB_TRANSACTION;
195 trans = &smb->body.trans;
196 trans->total_data_count = request->length;
197 trans->timeout = 1000;
198 trans->data_count = request->length;
199 trans->data_offset = 70 + strlen(mailslot_name);
200 trans->opcode = 1; /* write mail slot */
201 trans->priority = 1;
202 trans->_class = 2;
203 trans->mailslot_name = mailslot_name;
204 trans->data = *request;
206 status = nbt_dgram_send(dgmsock, &packet, dest);
208 talloc_free(tmp_ctx);
210 return status;
214 return the mailslot data portion from a mailslot packet
216 DATA_BLOB dgram_mailslot_data(struct nbt_dgram_packet *dgram)
218 struct smb_trans_body *trans = &dgram->data.msg.body.smb.body.trans;
219 DATA_BLOB ret = trans->data;
220 int pad = trans->data_offset - (70 + strlen(trans->mailslot_name));
222 if (pad < 0 || pad > ret.length) {
223 DEBUG(2,("Badly formatted data in mailslot - pad = %d\n", pad));
224 return data_blob(NULL, 0);
226 ret.data += pad;
227 ret.length -= pad;
228 return ret;