Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : packet handling for mailslot requests.
5 :
6 : Copyright (C) Andrew Tridgell 2005
7 :
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.
12 :
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.
17 :
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/>.
20 : */
21 :
22 : /*
23 : This implements "Class 2 mailslots", i.e. the communication mechanism
24 : used for all mailslot packets smaller than 425 bytes.
25 :
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.
30 :
31 : 425 and 426-byte sized messages are not supported at all.
32 : */
33 :
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"
39 :
40 : #undef strcasecmp
41 :
42 : /*
43 : destroy a mailslot handler
44 : */
45 624 : static int dgram_mailslot_destructor(struct dgram_mailslot_handler *dgmslot)
46 : {
47 624 : DLIST_REMOVE(dgmslot->dgmsock->mailslot_handlers, dgmslot);
48 624 : return 0;
49 : }
50 :
51 : /*
52 : start listening on a mailslot. talloc_free() the handle to stop listening
53 : */
54 624 : 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)
58 : {
59 18 : struct dgram_mailslot_handler *dgmslot;
60 :
61 624 : dgmslot = talloc(dgmsock, struct dgram_mailslot_handler);
62 624 : if (dgmslot == NULL) return NULL;
63 :
64 624 : dgmslot->dgmsock = dgmsock;
65 624 : dgmslot->mailslot_name = talloc_strdup(dgmslot, mailslot_name);
66 624 : if (dgmslot->mailslot_name == NULL) {
67 0 : talloc_free(dgmslot);
68 0 : return NULL;
69 : }
70 624 : dgmslot->handler = handler;
71 624 : dgmslot->private_data = private_data;
72 :
73 624 : DLIST_ADD(dgmsock->mailslot_handlers, dgmslot);
74 624 : talloc_set_destructor(dgmslot, dgram_mailslot_destructor);
75 :
76 624 : TEVENT_FD_READABLE(dgmsock->fde);
77 :
78 624 : return dgmslot;
79 : }
80 :
81 : /*
82 : find the handler for a specific mailslot name
83 : */
84 953 : struct dgram_mailslot_handler *dgram_mailslot_find(struct nbt_dgram_socket *dgmsock,
85 : const char *mailslot_name)
86 : {
87 0 : struct dgram_mailslot_handler *h;
88 1109 : for (h=dgmsock->mailslot_handlers;h;h=h->next) {
89 1055 : if (strcasecmp(h->mailslot_name, mailslot_name) == 0) {
90 899 : return h;
91 : }
92 : }
93 54 : return NULL;
94 : }
95 :
96 : /*
97 : check that a datagram packet is a valid mailslot request, and return the
98 : mailslot name if it is, otherwise return NULL
99 : */
100 929 : const char *dgram_mailslot_name(struct nbt_dgram_packet *packet)
101 : {
102 929 : if (packet->msg_type != DGRAM_DIRECT_UNIQUE &&
103 827 : packet->msg_type != DGRAM_DIRECT_GROUP &&
104 0 : packet->msg_type != DGRAM_BCAST) {
105 0 : return NULL;
106 : }
107 929 : if (packet->data.msg.dgram_body_type != DGRAM_SMB) return NULL;
108 929 : if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL;
109 929 : return packet->data.msg.body.smb.body.trans.mailslot_name;
110 : }
111 :
112 :
113 : /*
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
116 : */
117 39 : 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)
121 : {
122 0 : char *name;
123 0 : int i;
124 0 : struct dgram_mailslot_handler *dgmslot;
125 :
126 : /* try a 100 times at most */
127 39 : for (i=0;i<100;i++) {
128 39 : name = talloc_asprintf(dgmsock, "%s%03u",
129 : mailslot_name,
130 39 : generate_random() % 1000);
131 39 : if (name == NULL) return NULL;
132 39 : if (dgram_mailslot_find(dgmsock, name)) {
133 0 : talloc_free(name);
134 0 : continue;
135 : }
136 39 : dgmslot = dgram_mailslot_listen(dgmsock, name, handler, private_data);
137 39 : talloc_free(name);
138 39 : if (dgmslot != NULL) {
139 39 : return dgmslot;
140 : }
141 : }
142 0 : DEBUG(2,("Unable to create temporary mailslot from %s\n", mailslot_name));
143 0 : return NULL;
144 : }
145 :
146 :
147 : /*
148 : send a mailslot request
149 : */
150 87 : 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)
157 : {
158 87 : TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
159 0 : struct nbt_dgram_packet packet;
160 0 : struct dgram_message *msg;
161 0 : struct dgram_smb_packet *smb;
162 0 : struct smb_trans_body *trans;
163 0 : struct socket_address *src;
164 0 : NTSTATUS status;
165 :
166 87 : if (dest->port == 0) {
167 0 : return NT_STATUS_INVALID_PARAMETER;
168 : }
169 :
170 87 : ZERO_STRUCT(packet);
171 87 : packet.msg_type = msg_type;
172 87 : packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD;
173 87 : packet.dgram_id = generate_random() % UINT16_MAX;
174 87 : src = socket_get_my_addr(dgmsock->sock, tmp_ctx);
175 87 : if (!src) {
176 0 : talloc_free(tmp_ctx);
177 0 : return NT_STATUS_NO_MEMORY;
178 : }
179 87 : packet.src_addr = src->addr;
180 87 : packet.src_port = src->port;
181 :
182 87 : msg = &packet.data.msg;
183 : /* this length calculation is very crude - it should be based on gensize
184 : calls */
185 87 : msg->length = 138 + strlen(mailslot_name) + request->length;
186 87 : msg->offset = 0;
187 :
188 87 : msg->source_name = *src_name;
189 87 : msg->dest_name = *dest_name;
190 87 : msg->dgram_body_type = DGRAM_SMB;
191 :
192 87 : smb = &msg->body.smb;
193 87 : smb->smb_command = SMB_TRANSACTION;
194 :
195 87 : trans = &smb->body.trans;
196 87 : trans->total_data_count = request->length;
197 87 : trans->timeout = 1000;
198 87 : trans->data_count = request->length;
199 87 : trans->data_offset = 70 + strlen(mailslot_name);
200 87 : trans->opcode = 1; /* write mail slot */
201 87 : trans->priority = 1;
202 87 : trans->_class = 2;
203 87 : trans->mailslot_name = mailslot_name;
204 87 : trans->data = *request;
205 :
206 87 : status = nbt_dgram_send(dgmsock, &packet, dest);
207 :
208 87 : talloc_free(tmp_ctx);
209 :
210 87 : return status;
211 : }
212 :
213 : /*
214 : return the mailslot data portion from a mailslot packet
215 : */
216 899 : DATA_BLOB dgram_mailslot_data(struct nbt_dgram_packet *dgram)
217 : {
218 899 : struct smb_trans_body *trans = &dgram->data.msg.body.smb.body.trans;
219 899 : DATA_BLOB ret = trans->data;
220 899 : int pad = trans->data_offset - (70 + strlen(trans->mailslot_name));
221 :
222 899 : if (pad < 0 || pad > ret.length) {
223 0 : DEBUG(2,("Badly formatted data in mailslot - pad = %d\n", pad));
224 0 : return data_blob(NULL, 0);
225 : }
226 899 : ret.data += pad;
227 899 : ret.length -= pad;
228 899 : return ret;
229 : }
|