Line data Source code
1 : /* 2 : * Unix SMB/CIFS implementation. 3 : * store smbd profiling information in shared memory 4 : * Copyright (C) Andrew Tridgell 1999 5 : * Copyright (C) James Peach 2006 6 : * 7 : * This program is free software; you can redistribute it and/or modify 8 : * it under the terms of the GNU General Public License as published by 9 : * the Free Software Foundation; either version 3 of the License, or 10 : * (at your option) any later version. 11 : * 12 : * This program is distributed in the hope that it will be useful, 13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 : * GNU General Public License for more details. 16 : * 17 : * You should have received a copy of the GNU General Public License 18 : * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 : */ 20 : 21 : #include "replace.h" 22 : #include <tdb.h> 23 : #include <gnutls/gnutls.h> 24 : #include <gnutls/crypto.h> 25 : #include "lib/crypto/gnutls_helpers.h" 26 : #include "lib/util/byteorder.h" 27 : #include "source3/include/smbprofile.h" 28 : 29 0 : void smbprofile_stats_accumulate(struct profile_stats *acc, 30 : const struct profile_stats *add) 31 : { 32 : #define SMBPROFILE_STATS_START 33 : #define SMBPROFILE_STATS_SECTION_START(name, display) 34 : #define SMBPROFILE_STATS_COUNT(name) \ 35 : do { \ 36 : acc->values.name##_stats.count += \ 37 : add->values.name##_stats.count; \ 38 : } while (0); 39 : #define SMBPROFILE_STATS_TIME(name) \ 40 : do { \ 41 : acc->values.name##_stats.time += \ 42 : add->values.name##_stats.time; \ 43 : } while (0); 44 : #define SMBPROFILE_STATS_BASIC(name) \ 45 : do { \ 46 : acc->values.name##_stats.count += \ 47 : add->values.name##_stats.count; \ 48 : acc->values.name##_stats.time += \ 49 : add->values.name##_stats.time; \ 50 : } while (0); 51 : #define SMBPROFILE_STATS_BYTES(name) \ 52 : do { \ 53 : acc->values.name##_stats.count += \ 54 : add->values.name##_stats.count; \ 55 : acc->values.name##_stats.time += \ 56 : add->values.name##_stats.time; \ 57 : acc->values.name##_stats.idle += \ 58 : add->values.name##_stats.idle; \ 59 : acc->values.name##_stats.bytes += \ 60 : add->values.name##_stats.bytes; \ 61 : } while (0); 62 : #define SMBPROFILE_STATS_IOBYTES(name) \ 63 : do { \ 64 : acc->values.name##_stats.count += \ 65 : add->values.name##_stats.count; \ 66 : acc->values.name##_stats.time += \ 67 : add->values.name##_stats.time; \ 68 : acc->values.name##_stats.idle += \ 69 : add->values.name##_stats.idle; \ 70 : acc->values.name##_stats.inbytes += \ 71 : add->values.name##_stats.inbytes; \ 72 : acc->values.name##_stats.outbytes += \ 73 : add->values.name##_stats.outbytes; \ 74 : } while (0); 75 : #define SMBPROFILE_STATS_SECTION_END 76 : #define SMBPROFILE_STATS_END 77 0 : SMBPROFILE_STATS_ALL_SECTIONS 78 : #undef SMBPROFILE_STATS_START 79 : #undef SMBPROFILE_STATS_SECTION_START 80 : #undef SMBPROFILE_STATS_COUNT 81 : #undef SMBPROFILE_STATS_TIME 82 : #undef SMBPROFILE_STATS_BASIC 83 : #undef SMBPROFILE_STATS_BYTES 84 : #undef SMBPROFILE_STATS_IOBYTES 85 : #undef SMBPROFILE_STATS_SECTION_END 86 : #undef SMBPROFILE_STATS_END 87 0 : } 88 : 89 2 : int smbprofile_magic(const struct profile_stats *stats, uint64_t *_magic) 90 2 : { 91 2 : uint8_t digest[gnutls_hash_get_len(GNUTLS_DIG_SHA1)]; 92 2 : gnutls_hash_hd_t hash_hnd = NULL; 93 0 : int rc; 94 : 95 2 : GNUTLS_FIPS140_SET_LAX_MODE(); 96 : 97 2 : rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA1); 98 2 : if (rc < 0) { 99 0 : goto out; 100 : } 101 2 : rc = gnutls_hash(hash_hnd, stats, sizeof(*stats)); 102 : 103 : #define __UPDATE(str) \ 104 : do { \ 105 : rc |= gnutls_hash(hash_hnd, str, strlen(str)); \ 106 : } while (0) 107 : #define SMBPROFILE_STATS_START 108 : #define SMBPROFILE_STATS_SECTION_START(name, display) \ 109 : do { \ 110 : __UPDATE(#name "+" #display); \ 111 : } while (0); 112 : #define SMBPROFILE_STATS_COUNT(name) \ 113 : do { \ 114 : __UPDATE(#name "+count"); \ 115 : } while (0); 116 : #define SMBPROFILE_STATS_TIME(name) \ 117 : do { \ 118 : __UPDATE(#name "+time"); \ 119 : } while (0); 120 : #define SMBPROFILE_STATS_BASIC(name) \ 121 : do { \ 122 : __UPDATE(#name "+count"); \ 123 : __UPDATE(#name "+time"); \ 124 : } while (0); 125 : #define SMBPROFILE_STATS_BYTES(name) \ 126 : do { \ 127 : __UPDATE(#name "+count"); \ 128 : __UPDATE(#name "+time"); \ 129 : __UPDATE(#name "+idle"); \ 130 : __UPDATE(#name "+bytes"); \ 131 : } while (0); 132 : #define SMBPROFILE_STATS_IOBYTES(name) \ 133 : do { \ 134 : __UPDATE(#name "+count"); \ 135 : __UPDATE(#name "+time"); \ 136 : __UPDATE(#name "+idle"); \ 137 : __UPDATE(#name "+inbytes"); \ 138 : __UPDATE(#name "+outbytes"); \ 139 : } while (0); 140 : #define SMBPROFILE_STATS_SECTION_END 141 : #define SMBPROFILE_STATS_END 142 2 : SMBPROFILE_STATS_ALL_SECTIONS 143 : #undef __UPDATE 144 : #undef SMBPROFILE_STATS_START 145 : #undef SMBPROFILE_STATS_SECTION_START 146 : #undef SMBPROFILE_STATS_COUNT 147 : #undef SMBPROFILE_STATS_TIME 148 : #undef SMBPROFILE_STATS_BASIC 149 : #undef SMBPROFILE_STATS_BYTES 150 : #undef SMBPROFILE_STATS_IOBYTES 151 : #undef SMBPROFILE_STATS_SECTION_END 152 : #undef SMBPROFILE_STATS_END 153 2 : if (rc != 0) { 154 0 : gnutls_hash_deinit(hash_hnd, NULL); 155 0 : goto out; 156 : } 157 : 158 2 : gnutls_hash_deinit(hash_hnd, digest); 159 2 : out: 160 2 : GNUTLS_FIPS140_SET_STRICT_MODE(); 161 : 162 2 : if (rc == 0) { 163 2 : uint64_t magic = PULL_LE_U64(digest, 0); 164 2 : if (magic == 0) { 165 0 : magic = PULL_LE_U64(digest, 0); 166 : } 167 2 : *_magic = magic; 168 : } 169 : 170 2 : return rc; 171 : } 172 : 173 0 : static int smbprofile_collect_fn(struct tdb_context *tdb, 174 : TDB_DATA key, 175 : TDB_DATA value, 176 : void *private_data) 177 : { 178 0 : struct profile_stats *acc = (struct profile_stats *)private_data; 179 0 : const struct profile_stats *v; 180 : 181 0 : if (value.dsize != sizeof(struct profile_stats)) { 182 0 : return 0; 183 : } 184 : 185 0 : v = (const struct profile_stats *)value.dptr; 186 : 187 0 : if (v->magic != acc->magic) { 188 0 : return 0; 189 : } 190 : 191 0 : smbprofile_stats_accumulate(acc, v); 192 0 : return 0; 193 : } 194 : 195 2 : void smbprofile_collect_tdb(struct tdb_context *tdb, 196 : uint64_t magic, 197 : struct profile_stats *stats) 198 : { 199 2 : *stats = (struct profile_stats){.magic = magic}; 200 : 201 2 : tdb_traverse_read(tdb, smbprofile_collect_fn, stats); 202 2 : }