mirror of
https://github.com/samba-team/samba.git
synced 2025-02-07 01:58:28 +03:00
203 lines
6.1 KiB
C
203 lines
6.1 KiB
C
|
/*
|
||
|
* Unix SMB/CIFS implementation.
|
||
|
* store smbd profiling information in shared memory
|
||
|
* Copyright (C) Andrew Tridgell 1999
|
||
|
* Copyright (C) James Peach 2006
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include "replace.h"
|
||
|
#include <tdb.h>
|
||
|
#include <gnutls/gnutls.h>
|
||
|
#include <gnutls/crypto.h>
|
||
|
#include "lib/crypto/gnutls_helpers.h"
|
||
|
#include "lib/util/byteorder.h"
|
||
|
#include "source3/include/smbprofile.h"
|
||
|
|
||
|
void smbprofile_stats_accumulate(struct profile_stats *acc,
|
||
|
const struct profile_stats *add)
|
||
|
{
|
||
|
#define SMBPROFILE_STATS_START
|
||
|
#define SMBPROFILE_STATS_SECTION_START(name, display)
|
||
|
#define SMBPROFILE_STATS_COUNT(name) \
|
||
|
do { \
|
||
|
acc->values.name##_stats.count += \
|
||
|
add->values.name##_stats.count; \
|
||
|
} while (0);
|
||
|
#define SMBPROFILE_STATS_TIME(name) \
|
||
|
do { \
|
||
|
acc->values.name##_stats.time += \
|
||
|
add->values.name##_stats.time; \
|
||
|
} while (0);
|
||
|
#define SMBPROFILE_STATS_BASIC(name) \
|
||
|
do { \
|
||
|
acc->values.name##_stats.count += \
|
||
|
add->values.name##_stats.count; \
|
||
|
acc->values.name##_stats.time += \
|
||
|
add->values.name##_stats.time; \
|
||
|
} while (0);
|
||
|
#define SMBPROFILE_STATS_BYTES(name) \
|
||
|
do { \
|
||
|
acc->values.name##_stats.count += \
|
||
|
add->values.name##_stats.count; \
|
||
|
acc->values.name##_stats.time += \
|
||
|
add->values.name##_stats.time; \
|
||
|
acc->values.name##_stats.idle += \
|
||
|
add->values.name##_stats.idle; \
|
||
|
acc->values.name##_stats.bytes += \
|
||
|
add->values.name##_stats.bytes; \
|
||
|
} while (0);
|
||
|
#define SMBPROFILE_STATS_IOBYTES(name) \
|
||
|
do { \
|
||
|
acc->values.name##_stats.count += \
|
||
|
add->values.name##_stats.count; \
|
||
|
acc->values.name##_stats.time += \
|
||
|
add->values.name##_stats.time; \
|
||
|
acc->values.name##_stats.idle += \
|
||
|
add->values.name##_stats.idle; \
|
||
|
acc->values.name##_stats.inbytes += \
|
||
|
add->values.name##_stats.inbytes; \
|
||
|
acc->values.name##_stats.outbytes += \
|
||
|
add->values.name##_stats.outbytes; \
|
||
|
} while (0);
|
||
|
#define SMBPROFILE_STATS_SECTION_END
|
||
|
#define SMBPROFILE_STATS_END
|
||
|
SMBPROFILE_STATS_ALL_SECTIONS
|
||
|
#undef SMBPROFILE_STATS_START
|
||
|
#undef SMBPROFILE_STATS_SECTION_START
|
||
|
#undef SMBPROFILE_STATS_COUNT
|
||
|
#undef SMBPROFILE_STATS_TIME
|
||
|
#undef SMBPROFILE_STATS_BASIC
|
||
|
#undef SMBPROFILE_STATS_BYTES
|
||
|
#undef SMBPROFILE_STATS_IOBYTES
|
||
|
#undef SMBPROFILE_STATS_SECTION_END
|
||
|
#undef SMBPROFILE_STATS_END
|
||
|
}
|
||
|
|
||
|
int smbprofile_magic(const struct profile_stats *stats, uint64_t *_magic)
|
||
|
{
|
||
|
uint8_t digest[gnutls_hash_get_len(GNUTLS_DIG_SHA1)];
|
||
|
gnutls_hash_hd_t hash_hnd = NULL;
|
||
|
int rc;
|
||
|
|
||
|
GNUTLS_FIPS140_SET_LAX_MODE();
|
||
|
|
||
|
rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA1);
|
||
|
if (rc < 0) {
|
||
|
goto out;
|
||
|
}
|
||
|
rc = gnutls_hash(hash_hnd, stats, sizeof(*stats));
|
||
|
|
||
|
#define __UPDATE(str) \
|
||
|
do { \
|
||
|
rc |= gnutls_hash(hash_hnd, str, strlen(str)); \
|
||
|
} while (0)
|
||
|
#define SMBPROFILE_STATS_START
|
||
|
#define SMBPROFILE_STATS_SECTION_START(name, display) \
|
||
|
do { \
|
||
|
__UPDATE(#name "+" #display); \
|
||
|
} while (0);
|
||
|
#define SMBPROFILE_STATS_COUNT(name) \
|
||
|
do { \
|
||
|
__UPDATE(#name "+count"); \
|
||
|
} while (0);
|
||
|
#define SMBPROFILE_STATS_TIME(name) \
|
||
|
do { \
|
||
|
__UPDATE(#name "+time"); \
|
||
|
} while (0);
|
||
|
#define SMBPROFILE_STATS_BASIC(name) \
|
||
|
do { \
|
||
|
__UPDATE(#name "+count"); \
|
||
|
__UPDATE(#name "+time"); \
|
||
|
} while (0);
|
||
|
#define SMBPROFILE_STATS_BYTES(name) \
|
||
|
do { \
|
||
|
__UPDATE(#name "+count"); \
|
||
|
__UPDATE(#name "+time"); \
|
||
|
__UPDATE(#name "+idle"); \
|
||
|
__UPDATE(#name "+bytes"); \
|
||
|
} while (0);
|
||
|
#define SMBPROFILE_STATS_IOBYTES(name) \
|
||
|
do { \
|
||
|
__UPDATE(#name "+count"); \
|
||
|
__UPDATE(#name "+time"); \
|
||
|
__UPDATE(#name "+idle"); \
|
||
|
__UPDATE(#name "+inbytes"); \
|
||
|
__UPDATE(#name "+outbytes"); \
|
||
|
} while (0);
|
||
|
#define SMBPROFILE_STATS_SECTION_END
|
||
|
#define SMBPROFILE_STATS_END
|
||
|
SMBPROFILE_STATS_ALL_SECTIONS
|
||
|
#undef __UPDATE
|
||
|
#undef SMBPROFILE_STATS_START
|
||
|
#undef SMBPROFILE_STATS_SECTION_START
|
||
|
#undef SMBPROFILE_STATS_COUNT
|
||
|
#undef SMBPROFILE_STATS_TIME
|
||
|
#undef SMBPROFILE_STATS_BASIC
|
||
|
#undef SMBPROFILE_STATS_BYTES
|
||
|
#undef SMBPROFILE_STATS_IOBYTES
|
||
|
#undef SMBPROFILE_STATS_SECTION_END
|
||
|
#undef SMBPROFILE_STATS_END
|
||
|
if (rc != 0) {
|
||
|
gnutls_hash_deinit(hash_hnd, NULL);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
gnutls_hash_deinit(hash_hnd, digest);
|
||
|
out:
|
||
|
GNUTLS_FIPS140_SET_STRICT_MODE();
|
||
|
|
||
|
if (rc == 0) {
|
||
|
uint64_t magic = PULL_LE_U64(digest, 0);
|
||
|
if (magic == 0) {
|
||
|
magic = PULL_LE_U64(digest, 0);
|
||
|
}
|
||
|
*_magic = magic;
|
||
|
}
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
static int smbprofile_collect_fn(struct tdb_context *tdb,
|
||
|
TDB_DATA key,
|
||
|
TDB_DATA value,
|
||
|
void *private_data)
|
||
|
{
|
||
|
struct profile_stats *acc = (struct profile_stats *)private_data;
|
||
|
const struct profile_stats *v;
|
||
|
|
||
|
if (value.dsize != sizeof(struct profile_stats)) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
v = (const struct profile_stats *)value.dptr;
|
||
|
|
||
|
if (v->magic != acc->magic) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
smbprofile_stats_accumulate(acc, v);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void smbprofile_collect_tdb(struct tdb_context *tdb,
|
||
|
uint64_t magic,
|
||
|
struct profile_stats *stats)
|
||
|
{
|
||
|
*stats = (struct profile_stats){.magic = magic};
|
||
|
|
||
|
tdb_traverse_read(tdb, smbprofile_collect_fn, stats);
|
||
|
}
|