summaryrefslogtreecommitdiffstats
path: root/source3/profile/profile_read.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/profile/profile_read.c')
-rw-r--r--source3/profile/profile_read.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/source3/profile/profile_read.c b/source3/profile/profile_read.c
new file mode 100644
index 0000000..45a1980
--- /dev/null
+++ b/source3/profile/profile_read.c
@@ -0,0 +1,202 @@
+/*
+ * 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);
+}