root/source3/libsmb/unexpected.c

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

DEFINITIONS

This source file includes following definitions.
  1. unexpected_packet
  2. traverse_fn
  3. clear_unexpected
  4. traverse_match
  5. receive_unexpected

   1 /*
   2    Unix SMB/CIFS implementation.
   3    handle unexpected packets
   4    Copyright (C) Andrew Tridgell 2000
   5 
   6    This program is free software; you can redistribute it and/or modify
   7    it under the terms of the GNU General Public License as published by
   8    the Free Software Foundation; either version 3 of the License, or
   9    (at your option) any later version.
  10 
  11    This program is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU General Public License for more details.
  15 
  16    You should have received a copy of the GNU General Public License
  17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 
  19 */
  20 
  21 #include "includes.h"
  22 
  23 static TDB_CONTEXT *tdbd = NULL;
  24 
  25 /* the key type used in the unexpected packet database */
  26 struct unexpected_key {
  27         enum packet_type packet_type;
  28         time_t timestamp;
  29         int count;
  30 };
  31 
  32 /****************************************************************************
  33  All unexpected packets are passed in here, to be stored in a unexpected
  34  packet database. This allows nmblookup and other tools to receive packets
  35  erroneously sent to the wrong port by broken MS systems.
  36 **************************************************************************/
  37 
  38 void unexpected_packet(struct packet_struct *p)
     /* [<][>][^][v][top][bottom][index][help] */
  39 {
  40         static int count;
  41         TDB_DATA kbuf, dbuf;
  42         struct unexpected_key key;
  43         char buf[1024];
  44         int len=0;
  45         uint32_t enc_ip;
  46 
  47         if (!tdbd) {
  48                 tdbd = tdb_open_log(lock_path("unexpected.tdb"), 0,
  49                                TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
  50                                O_RDWR | O_CREAT, 0644);
  51                 if (!tdbd) {
  52                         DEBUG(0,("Failed to open unexpected.tdb\n"));
  53                         return;
  54                 }
  55         }
  56 
  57         memset(buf,'\0',sizeof(buf));
  58 
  59         /* Encode the ip addr and port. */
  60         enc_ip = ntohl(p->ip.s_addr);
  61         SIVAL(buf,0,enc_ip);
  62         SSVAL(buf,4,p->port);
  63 
  64         len = build_packet(&buf[6], sizeof(buf)-6, p) + 6;
  65 
  66         ZERO_STRUCT(key);       /* needed for potential alignment */
  67 
  68         key.packet_type = p->packet_type;
  69         key.timestamp = p->timestamp;
  70         key.count = count++;
  71 
  72         kbuf.dptr = (uint8_t *)&key;
  73         kbuf.dsize = sizeof(key);
  74         dbuf.dptr = (uint8_t *)buf;
  75         dbuf.dsize = len;
  76 
  77         tdb_store(tdbd, kbuf, dbuf, TDB_REPLACE);
  78 }
  79 
  80 
  81 static time_t lastt;
  82 
  83 /****************************************************************************
  84  Delete the record if it is too old.
  85 **************************************************************************/
  86 
  87 static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
     /* [<][>][^][v][top][bottom][index][help] */
  88 {
  89         struct unexpected_key key;
  90 
  91         if (kbuf.dsize != sizeof(key)) {
  92                 tdb_delete(ttdb, kbuf);
  93         }
  94 
  95         memcpy(&key, kbuf.dptr, sizeof(key));
  96 
  97         if (lastt - key.timestamp > NMBD_UNEXPECTED_TIMEOUT) {
  98                 tdb_delete(ttdb, kbuf);
  99         }
 100 
 101         return 0;
 102 }
 103 
 104 
 105 /****************************************************************************
 106  Delete all old unexpected packets.
 107 **************************************************************************/
 108 
 109 void clear_unexpected(time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 110 {
 111         if (!tdbd) return;
 112 
 113         if ((lastt != 0) && (t < lastt + NMBD_UNEXPECTED_TIMEOUT))
 114                 return;
 115 
 116         lastt = t;
 117 
 118         tdb_traverse(tdbd, traverse_fn, NULL);
 119 }
 120 
 121 struct receive_unexpected_state {
 122         struct packet_struct *matched_packet;
 123         int match_id;
 124         enum packet_type match_type;
 125         const char *match_name;
 126 };
 127 
 128 /****************************************************************************
 129  tdb traversal fn to find a matching 137 packet.
 130 **************************************************************************/
 131 
 132 static int traverse_match(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf,
     /* [<][>][^][v][top][bottom][index][help] */
 133                           void *private_data)
 134 {
 135         struct receive_unexpected_state *state =
 136                 (struct receive_unexpected_state *)private_data;
 137         struct unexpected_key key;
 138         struct in_addr ip;
 139         uint32_t enc_ip;
 140         int port;
 141         struct packet_struct *p;
 142 
 143         if (kbuf.dsize != sizeof(key)) {
 144                 return 0;
 145         }
 146 
 147         memcpy(&key, kbuf.dptr, sizeof(key));
 148 
 149         if (key.packet_type != state->match_type) return 0;
 150 
 151         if (dbuf.dsize < 6) {
 152                 return 0;
 153         }
 154 
 155         /* Decode the ip addr and port. */
 156         enc_ip = IVAL(dbuf.dptr,0);
 157         ip.s_addr = htonl(enc_ip);
 158         port = SVAL(dbuf.dptr,4);
 159 
 160         p = parse_packet((char *)&dbuf.dptr[6],
 161                         dbuf.dsize-6,
 162                         state->match_type,
 163                         ip,
 164                         port);
 165         if (!p)
 166                 return 0;
 167 
 168         if ((state->match_type == NMB_PACKET &&
 169              p->packet.nmb.header.name_trn_id == state->match_id) ||
 170             (state->match_type == DGRAM_PACKET &&
 171              match_mailslot_name(p, state->match_name))) {
 172                 state->matched_packet = p;
 173                 return -1;
 174         }
 175 
 176         free_packet(p);
 177 
 178         return 0;
 179 }
 180 
 181 /****************************************************************************
 182  Check for a particular packet in the unexpected packet queue.
 183 **************************************************************************/
 184 
 185 struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
     /* [<][>][^][v][top][bottom][index][help] */
 186                                          const char *mailslot_name)
 187 {
 188         TDB_CONTEXT *tdb2;
 189         struct receive_unexpected_state state;
 190 
 191         tdb2 = tdb_open_log(lock_path("unexpected.tdb"), 0, 0, O_RDONLY, 0);
 192         if (!tdb2) return NULL;
 193 
 194         state.matched_packet = NULL;
 195         state.match_id = id;
 196         state.match_type = packet_type;
 197         state.match_name = mailslot_name;
 198 
 199         tdb_traverse(tdb2, traverse_match, &state);
 200 
 201         tdb_close(tdb2);
 202 
 203         return state.matched_packet;
 204 }

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