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);
71 find the handler for a specific mailslot name
73 struct dgram_mailslot_handler *dgram_mailslot_find(struct nbt_dgram_socket *dgmsock,
74 const char *mailslot_name)
76 struct dgram_mailslot_handler *h;
77 for (h=dgmsock->mailslot_handlers;h;h=h->next) {
78 if (strcasecmp(h->mailslot_name, mailslot_name) == 0) {
86 check that a datagram packet is a valid mailslot request, and return the
87 mailslot name if it is, otherwise return NULL
89 const char *dgram_mailslot_name(struct nbt_dgram_packet *packet)
91 if (packet->msg_type != DGRAM_DIRECT_UNIQUE &&
92 packet->msg_type != DGRAM_DIRECT_GROUP &&
93 packet->msg_type != DGRAM_BCAST) {
96 if (packet->data.msg.dgram_body_type != DGRAM_SMB) return NULL;
97 if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL;
98 if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL;
99 return packet->data.msg.body.smb.body.trans.mailslot_name;
104 create a temporary mailslot handler for a reply mailslot, allocating
105 a new mailslot name using the given base name and a random integer extension
107 struct dgram_mailslot_handler *dgram_mailslot_temp(struct nbt_dgram_socket *dgmsock,
108 const char *mailslot_name,
109 dgram_mailslot_handler_t handler,
114 struct dgram_mailslot_handler *dgmslot;
116 /* try a 100 times at most */
117 for (i=0;i<100;i++) {
118 name = talloc_asprintf(dgmsock, "%s%03u",
120 generate_random() % 1000);
121 if (name == NULL) return NULL;
122 if (dgram_mailslot_find(dgmsock, name)) {
126 dgmslot = dgram_mailslot_listen(dgmsock, name, handler, private);
130 DEBUG(2,("Unable to create temporary mailslot from %s\n", mailslot_name));
136 send a mailslot request
138 NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock,
139 enum dgram_msg_type msg_type,
140 const char *mailslot_name,
141 struct nbt_name *dest_name,
142 const char *dest_address,
143 struct nbt_name *src_name,
146 TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
147 struct nbt_dgram_packet packet;
148 struct dgram_message *msg;
149 struct dgram_smb_packet *smb;
150 struct smb_trans_body *trans;
154 packet.msg_type = msg_type;
155 packet.flags = DGRAM_FLAG_FIRST;
156 packet.dgram_id = generate_random() % UINT16_MAX;
157 packet.source = socket_get_my_addr(dgmsock->sock, tmp_ctx);
158 packet.src_port = socket_get_my_port(dgmsock->sock);
160 msg = &packet.data.msg;
161 /* this length calculation is very crude - it should be based on gensize
163 msg->length = 138 + strlen(mailslot_name) + request->length;
166 msg->source_name = *src_name;
167 msg->dest_name = *dest_name;
168 msg->dgram_body_type = DGRAM_SMB;
170 smb = &msg->body.smb;
171 smb->smb_command = SMB_TRANSACTION;
173 trans = &smb->body.trans;
174 trans->total_data_count = request->length;
175 trans->timeout = (uint32_t)-1;
176 trans->data_count = request->length;
177 trans->data_offset = 70 + strlen(mailslot_name);
178 trans->opcode = 1; /* write mail slot */
181 trans->mailslot_name = mailslot_name;
182 trans->data = *request;
184 status = nbt_dgram_send(dgmsock, &packet, dest_address, lp_dgram_port());
186 talloc_free(tmp_ctx);