LCOV - code coverage report
Current view: top level - source4/libcli/dgram - mailslot.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 77 100 77.0 %
Date: 2024-02-28 12:06:22 Functions: 7 7 100.0 %

          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         618 : static int dgram_mailslot_destructor(struct dgram_mailslot_handler *dgmslot)
      46             : {
      47         618 :         DLIST_REMOVE(dgmslot->dgmsock->mailslot_handlers, dgmslot);
      48         618 :         return 0;
      49             : }
      50             : 
      51             : /*
      52             :   start listening on a mailslot. talloc_free() the handle to stop listening
      53             : */
      54         618 : 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         618 :         dgmslot = talloc(dgmsock, struct dgram_mailslot_handler);
      62         618 :         if (dgmslot == NULL) return NULL;
      63             : 
      64         618 :         dgmslot->dgmsock = dgmsock;
      65         618 :         dgmslot->mailslot_name = talloc_strdup(dgmslot, mailslot_name);
      66         618 :         if (dgmslot->mailslot_name == NULL) {
      67           0 :                 talloc_free(dgmslot);
      68           0 :                 return NULL;
      69             :         }
      70         618 :         dgmslot->handler = handler;
      71         618 :         dgmslot->private_data = private_data;
      72             : 
      73         618 :         DLIST_ADD(dgmsock->mailslot_handlers, dgmslot);
      74         618 :         talloc_set_destructor(dgmslot, dgram_mailslot_destructor);
      75             : 
      76         618 :         TEVENT_FD_READABLE(dgmsock->fde);
      77             : 
      78         618 :         return dgmslot;
      79             : }
      80             : 
      81             : /*
      82             :   find the handler for a specific mailslot name
      83             : */
      84         929 : 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        1011 :         for (h=dgmsock->mailslot_handlers;h;h=h->next) {
      89         978 :                 if (strcasecmp(h->mailslot_name, mailslot_name) == 0) {
      90         896 :                         return h;
      91             :                 }
      92             :         }
      93          33 :         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         896 : const char *dgram_mailslot_name(struct nbt_dgram_packet *packet)
     101             : {
     102         896 :         if (packet->msg_type != DGRAM_DIRECT_UNIQUE &&
     103         836 :             packet->msg_type != DGRAM_DIRECT_GROUP &&
     104           0 :             packet->msg_type != DGRAM_BCAST) {
     105           0 :                 return NULL;
     106             :         }
     107         896 :         if (packet->data.msg.dgram_body_type != DGRAM_SMB) return NULL;
     108         896 :         if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL;
     109         896 :         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          33 : 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          33 :         for (i=0;i<100;i++) {
     128          33 :                 name = talloc_asprintf(dgmsock, "%s%03u", 
     129             :                                        mailslot_name,
     130          33 :                                        generate_random() % 1000);
     131          33 :                 if (name == NULL) return NULL;
     132          33 :                 if (dgram_mailslot_find(dgmsock, name)) {
     133           0 :                         talloc_free(name);
     134           0 :                         continue;
     135             :                 }
     136          33 :                 dgmslot = dgram_mailslot_listen(dgmsock, name, handler, private_data);
     137          33 :                 talloc_free(name);
     138          33 :                 if (dgmslot != NULL) {
     139          33 :                         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          64 : 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          64 :         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          64 :         if (dest->port == 0) {
     167           0 :                 return NT_STATUS_INVALID_PARAMETER;
     168             :         }
     169             : 
     170          64 :         ZERO_STRUCT(packet);
     171          64 :         packet.msg_type = msg_type;
     172          64 :         packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD;
     173          64 :         packet.dgram_id = generate_random() % UINT16_MAX;
     174          64 :         src = socket_get_my_addr(dgmsock->sock, tmp_ctx);
     175          64 :         if (!src) {
     176           0 :                 talloc_free(tmp_ctx);
     177           0 :                 return NT_STATUS_NO_MEMORY;
     178             :         }
     179          64 :         packet.src_addr = src->addr;
     180          64 :         packet.src_port = src->port;
     181             : 
     182          64 :         msg = &packet.data.msg;
     183             :         /* this length calculation is very crude - it should be based on gensize
     184             :            calls */
     185          64 :         msg->length = 138 + strlen(mailslot_name) + request->length;
     186          64 :         msg->offset = 0;
     187             : 
     188          64 :         msg->source_name = *src_name;
     189          64 :         msg->dest_name = *dest_name;
     190          64 :         msg->dgram_body_type = DGRAM_SMB;
     191             : 
     192          64 :         smb = &msg->body.smb;
     193          64 :         smb->smb_command = SMB_TRANSACTION;
     194             : 
     195          64 :         trans = &smb->body.trans;
     196          64 :         trans->total_data_count = request->length;
     197          64 :         trans->timeout     = 1000;
     198          64 :         trans->data_count  = request->length;
     199          64 :         trans->data_offset = 70 + strlen(mailslot_name);
     200          64 :         trans->opcode      = 1; /* write mail slot */
     201          64 :         trans->priority    = 1;
     202          64 :         trans->_class      = 2;
     203          64 :         trans->mailslot_name = mailslot_name;
     204          64 :         trans->data = *request;
     205             : 
     206          64 :         status = nbt_dgram_send(dgmsock, &packet, dest);
     207             : 
     208          64 :         talloc_free(tmp_ctx);
     209             : 
     210          64 :         return status;
     211             : }
     212             : 
     213             : /*
     214             :   return the mailslot data portion from a mailslot packet
     215             : */
     216         896 : DATA_BLOB dgram_mailslot_data(struct nbt_dgram_packet *dgram)
     217             : {
     218         896 :         struct smb_trans_body *trans = &dgram->data.msg.body.smb.body.trans;
     219         896 :         DATA_BLOB ret = trans->data;
     220         896 :         int pad = trans->data_offset - (70 + strlen(trans->mailslot_name));
     221             : 
     222         896 :         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         896 :         ret.data += pad;
     227         896 :         ret.length -= pad;
     228         896 :         return ret;     
     229             : }

Generated by: LCOV version 1.14