root/source4/libcli/dgram/mailslot.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dgram_mailslot_destructor
  2. dgram_mailslot_listen
  3. dgram_mailslot_find
  4. dgram_mailslot_name
  5. dgram_mailslot_temp
  6. dgram_mailslot_send
  7. dgram_mailslot_data

   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 /*
  41   destroy a mailslot handler
  42 */
  43 static int dgram_mailslot_destructor(struct dgram_mailslot_handler *dgmslot)
     /* [<][>][^][v][top][bottom][index][help] */
  44 {
  45         DLIST_REMOVE(dgmslot->dgmsock->mailslot_handlers, dgmslot);
  46         return 0;
  47 }
  48 
  49 /*
  50   start listening on a mailslot. talloc_free() the handle to stop listening
  51 */
  52 struct dgram_mailslot_handler *dgram_mailslot_listen(struct nbt_dgram_socket *dgmsock,
     /* [<][>][^][v][top][bottom][index][help] */
  53                                                      const char *mailslot_name,
  54                                                      dgram_mailslot_handler_t handler,
  55                                                      void *private_data)
  56 {
  57         struct dgram_mailslot_handler *dgmslot;
  58 
  59         dgmslot = talloc(dgmsock, struct dgram_mailslot_handler);
  60         if (dgmslot == NULL) return NULL;
  61 
  62         dgmslot->dgmsock = dgmsock;
  63         dgmslot->mailslot_name = talloc_strdup(dgmslot, mailslot_name);
  64         if (dgmslot->mailslot_name == NULL) {
  65                 talloc_free(dgmslot);
  66                 return NULL;
  67         }
  68         dgmslot->handler = handler;
  69         dgmslot->private_data = private_data;
  70 
  71         DLIST_ADD(dgmsock->mailslot_handlers, dgmslot);
  72         talloc_set_destructor(dgmslot, dgram_mailslot_destructor);
  73 
  74         EVENT_FD_READABLE(dgmsock->fde);
  75 
  76         return dgmslot;
  77 }
  78 
  79 /*
  80   find the handler for a specific mailslot name
  81 */
  82 struct dgram_mailslot_handler *dgram_mailslot_find(struct nbt_dgram_socket *dgmsock,
     /* [<][>][^][v][top][bottom][index][help] */
  83                                                    const char *mailslot_name)
  84 {
  85         struct dgram_mailslot_handler *h;
  86         for (h=dgmsock->mailslot_handlers;h;h=h->next) {
  87                 if (strcasecmp(h->mailslot_name, mailslot_name) == 0) {
  88                         return h;
  89                 }
  90         }
  91         return NULL;
  92 }
  93 
  94 /*
  95   check that a datagram packet is a valid mailslot request, and return the 
  96   mailslot name if it is, otherwise return NULL
  97 */
  98 const char *dgram_mailslot_name(struct nbt_dgram_packet *packet)
     /* [<][>][^][v][top][bottom][index][help] */
  99 {
 100         if (packet->msg_type != DGRAM_DIRECT_UNIQUE &&
 101             packet->msg_type != DGRAM_DIRECT_GROUP &&
 102             packet->msg_type != DGRAM_BCAST) {
 103                 return NULL;
 104         }
 105         if (packet->data.msg.dgram_body_type != DGRAM_SMB) return NULL;
 106         if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL;
 107         return packet->data.msg.body.smb.body.trans.mailslot_name;
 108 }
 109 
 110 
 111 /*
 112   create a temporary mailslot handler for a reply mailslot, allocating
 113   a new mailslot name using the given base name and a random integer extension
 114 */
 115 struct dgram_mailslot_handler *dgram_mailslot_temp(struct nbt_dgram_socket *dgmsock,
     /* [<][>][^][v][top][bottom][index][help] */
 116                                                    const char *mailslot_name,
 117                                                    dgram_mailslot_handler_t handler,
 118                                                    void *private_data)
 119 {
 120         char *name;
 121         int i;
 122         struct dgram_mailslot_handler *dgmslot;
 123 
 124         /* try a 100 times at most */
 125         for (i=0;i<100;i++) {
 126                 name = talloc_asprintf(dgmsock, "%s%03u", 
 127                                        mailslot_name,
 128                                        generate_random() % 1000);
 129                 if (name == NULL) return NULL;
 130                 if (dgram_mailslot_find(dgmsock, name)) {
 131                         talloc_free(name);
 132                         return NULL;
 133                 }
 134                 dgmslot = dgram_mailslot_listen(dgmsock, name, handler, private_data);
 135                 talloc_free(name);
 136                 if (dgmslot != NULL) {
 137                         return dgmslot;
 138                 }
 139         }
 140         DEBUG(2,("Unable to create temporary mailslot from %s\n", mailslot_name));
 141         return NULL;
 142 }
 143 
 144 
 145 /*
 146   send a mailslot request
 147 */
 148 NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock,
     /* [<][>][^][v][top][bottom][index][help] */
 149                              enum dgram_msg_type msg_type,
 150                              const char *mailslot_name,
 151                              struct nbt_name *dest_name,
 152                              struct socket_address *dest,
 153                              struct nbt_name *src_name,
 154                              DATA_BLOB *request)
 155 {
 156         TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
 157         struct nbt_dgram_packet packet;
 158         struct dgram_message *msg;
 159         struct dgram_smb_packet *smb;
 160         struct smb_trans_body *trans;
 161         struct socket_address *src;
 162         NTSTATUS status;
 163 
 164         if (dest->port == 0) {
 165                 return NT_STATUS_INVALID_PARAMETER;
 166         }
 167 
 168         ZERO_STRUCT(packet);
 169         packet.msg_type = msg_type;
 170         packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD;
 171         packet.dgram_id = generate_random() % UINT16_MAX;
 172         src = socket_get_my_addr(dgmsock->sock, tmp_ctx);
 173         if (!src) {
 174                 return NT_STATUS_NO_MEMORY;
 175         }
 176         packet.src_addr = src->addr;
 177         packet.src_port = src->port;
 178 
 179         msg = &packet.data.msg;
 180         /* this length calculation is very crude - it should be based on gensize
 181            calls */
 182         msg->length = 138 + strlen(mailslot_name) + request->length;
 183         msg->offset = 0;
 184 
 185         msg->source_name = *src_name;
 186         msg->dest_name = *dest_name;
 187         msg->dgram_body_type = DGRAM_SMB;
 188 
 189         smb = &msg->body.smb;
 190         smb->smb_command = SMB_TRANSACTION;
 191 
 192         trans = &smb->body.trans;
 193         trans->total_data_count = request->length;
 194         trans->timeout     = 1000;
 195         trans->data_count  = request->length;
 196         trans->data_offset = 70 + strlen(mailslot_name);
 197         trans->opcode      = 1; /* write mail slot */
 198         trans->priority    = 1;
 199         trans->_class      = 2;
 200         trans->mailslot_name = mailslot_name;
 201         trans->data = *request;
 202 
 203         status = nbt_dgram_send(dgmsock, &packet, dest);
 204 
 205         talloc_free(tmp_ctx);
 206 
 207         return status;
 208 }
 209 
 210 /*
 211   return the mailslot data portion from a mailslot packet
 212 */
 213 DATA_BLOB dgram_mailslot_data(struct nbt_dgram_packet *dgram)
     /* [<][>][^][v][top][bottom][index][help] */
 214 {
 215         struct smb_trans_body *trans = &dgram->data.msg.body.smb.body.trans;
 216         DATA_BLOB ret = trans->data;
 217         int pad = trans->data_offset - (70 + strlen(trans->mailslot_name));
 218 
 219         if (pad < 0 || pad > ret.length) {
 220                 DEBUG(2,("Badly formatted data in mailslot - pad = %d\n", pad));
 221                 return data_blob(NULL, 0);
 222         }
 223         ret.data += pad;
 224         ret.length -= pad;
 225         return ret;     
 226 }

/* [<][>][^][v][top][bottom][index][help] */