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 #include "lib/events/events.h"
25 #include "dlinklist.h"
26 #include "libcli/nbt/libnbt.h"
27 #include "libcli/dgram/libdgram.h"
28 #include "lib/socket/socket.h"
31 destroy a mailslot handler
33 static int dgram_mailslot_destructor(void *ptr)
35 struct dgram_mailslot_handler *dgmslot =
36 talloc_get_type(ptr, struct dgram_mailslot_handler);
38 DLIST_REMOVE(dgmslot->dgmsock->mailslot_handlers, dgmslot);
43 start listening on a mailslot. talloc_free() the handle to stop listening
45 struct dgram_mailslot_handler *dgram_mailslot_listen(struct nbt_dgram_socket *dgmsock,
46 const char *mailslot_name,
47 dgram_mailslot_handler_t handler,
50 struct dgram_mailslot_handler *dgmslot;
52 dgmslot = talloc(dgmsock, struct dgram_mailslot_handler);
53 if (dgmslot == NULL) return NULL;
55 dgmslot->dgmsock = dgmsock;
56 dgmslot->mailslot_name = talloc_strdup(dgmslot, mailslot_name);
57 if (dgmslot->mailslot_name == NULL) {
61 dgmslot->handler = handler;
62 dgmslot->private = private;
64 DLIST_ADD(dgmsock->mailslot_handlers, dgmslot);
65 talloc_set_destructor(dgmslot, dgram_mailslot_destructor);
67 EVENT_FD_READABLE(dgmsock->fde);
73 find the handler for a specific mailslot name
75 struct dgram_mailslot_handler *dgram_mailslot_find(struct nbt_dgram_socket *dgmsock,
76 const char *mailslot_name)
78 struct dgram_mailslot_handler *h;
79 for (h=dgmsock->mailslot_handlers;h;h=h->next) {
80 if (strcasecmp(h->mailslot_name, mailslot_name) == 0) {
88 check that a datagram packet is a valid mailslot request, and return the
89 mailslot name if it is, otherwise return NULL
91 const char *dgram_mailslot_name(struct nbt_dgram_packet *packet)
93 if (packet->msg_type != DGRAM_DIRECT_UNIQUE &&
94 packet->msg_type != DGRAM_DIRECT_GROUP &&
95 packet->msg_type != DGRAM_BCAST) {
98 if (packet->data.msg.dgram_body_type != DGRAM_SMB) return NULL;
99 if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL;
100 if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL;
101 return packet->data.msg.body.smb.body.trans.mailslot_name;
106 create a temporary mailslot handler for a reply mailslot, allocating
107 a new mailslot name using the given base name and a random integer extension
109 struct dgram_mailslot_handler *dgram_mailslot_temp(struct nbt_dgram_socket *dgmsock,
110 const char *mailslot_name,
111 dgram_mailslot_handler_t handler,
116 struct dgram_mailslot_handler *dgmslot;
118 /* try a 100 times at most */
119 for (i=0;i<100;i++) {
120 name = talloc_asprintf(dgmsock, "%s%03u",
122 generate_random() % 1000);
123 if (name == NULL) return NULL;
124 if (dgram_mailslot_find(dgmsock, name)) {
128 dgmslot = dgram_mailslot_listen(dgmsock, name, handler, private);
132 DEBUG(2,("Unable to create temporary mailslot from %s\n", mailslot_name));
138 send a mailslot request
140 NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock,
141 enum dgram_msg_type msg_type,
142 const char *mailslot_name,
143 struct nbt_name *dest_name,
144 const char *dest_address,
146 struct nbt_name *src_name,
149 TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
150 struct nbt_dgram_packet packet;
151 struct dgram_message *msg;
152 struct dgram_smb_packet *smb;
153 struct smb_trans_body *trans;
156 if (dest_port == 0) {
157 dest_port = lp_dgram_port();
161 packet.msg_type = msg_type;
162 packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD;
163 packet.dgram_id = generate_random() % UINT16_MAX;
164 packet.source = socket_get_my_addr(dgmsock->sock, tmp_ctx);
165 packet.src_port = socket_get_my_port(dgmsock->sock);
167 msg = &packet.data.msg;
168 /* this length calculation is very crude - it should be based on gensize
170 msg->length = 138 + strlen(mailslot_name) + request->length;
173 msg->source_name = *src_name;
174 msg->dest_name = *dest_name;
175 msg->dgram_body_type = DGRAM_SMB;
177 smb = &msg->body.smb;
178 smb->smb_command = SMB_TRANSACTION;
180 trans = &smb->body.trans;
181 trans->total_data_count = request->length;
182 trans->timeout = 1000;
183 trans->data_count = request->length;
184 trans->data_offset = 70 + strlen(mailslot_name);
185 trans->opcode = 1; /* write mail slot */
188 trans->mailslot_name = mailslot_name;
189 trans->data = *request;
191 status = nbt_dgram_send(dgmsock, &packet, dest_address, dest_port);
193 talloc_free(tmp_ctx);