|
Packit Service |
99d1c0 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
|
Packit Service |
99d1c0 |
* Use is subject to license terms.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
#include <sys/stat.h>
|
|
Packit Service |
99d1c0 |
#include <sys/types.h>
|
|
Packit Service |
99d1c0 |
#include <unistd.h>
|
|
Packit Service |
99d1c0 |
#include <fcntl.h>
|
|
Packit Service |
99d1c0 |
#include <sys/mman.h>
|
|
Packit Service |
99d1c0 |
#include <k5-int.h>
|
|
Packit Service |
99d1c0 |
#include <stdlib.h>
|
|
Packit Service |
99d1c0 |
#include <limits.h>
|
|
Packit Service |
99d1c0 |
#include <syslog.h>
|
|
Packit Service |
99d1c0 |
#include "kdb5.h"
|
|
Packit Service |
99d1c0 |
#include "kdb_log.h"
|
|
Packit Service |
99d1c0 |
#include "kdb5int.h"
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
#ifndef MAP_FAILED
|
|
Packit Service |
99d1c0 |
#define MAP_FAILED ((void *)-1)
|
|
Packit Service |
99d1c0 |
#endif
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* This module includes all the necessary functions that create and modify the
|
|
Packit Service |
99d1c0 |
* Kerberos principal update and header logs. */
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
#define getpagesize() sysconf(_SC_PAGESIZE)
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static int pagesize = 0;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
#define INIT_ULOG(ctx) \
|
|
Packit Service |
99d1c0 |
log_ctx = ctx->kdblog_context; \
|
|
Packit Service |
99d1c0 |
assert(log_ctx != NULL); \
|
|
Packit Service |
99d1c0 |
ulog = log_ctx->ulog; \
|
|
Packit Service |
99d1c0 |
assert(ulog != NULL)
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Initialize context->kdblog_context if it does not yet exist, and return it.
|
|
Packit Service |
99d1c0 |
* Return NULL on allocation failure. */
|
|
Packit Service |
99d1c0 |
static kdb_log_context *
|
|
Packit Service |
99d1c0 |
create_log_context(krb5_context context)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
kdb_log_context *log_ctx;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (context->kdblog_context != NULL)
|
|
Packit Service |
99d1c0 |
return context->kdblog_context;
|
|
Packit Service |
99d1c0 |
log_ctx = calloc(1, sizeof(*log_ctx));
|
|
Packit Service |
99d1c0 |
if (log_ctx == NULL)
|
|
Packit Service |
99d1c0 |
return NULL;
|
|
Packit Service |
99d1c0 |
log_ctx->ulogfd = -1;
|
|
Packit Service |
99d1c0 |
context->kdblog_context = log_ctx;
|
|
Packit Service |
99d1c0 |
return log_ctx;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static inline krb5_boolean
|
|
Packit Service |
99d1c0 |
time_equal(const kdbe_time_t *a, const kdbe_time_t *b)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
return a->seconds == b->seconds && a->useconds == b->useconds;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
time_current(kdbe_time_t *out)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
struct timeval timestamp;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
(void)gettimeofday(×tamp, NULL);
|
|
Packit Service |
99d1c0 |
out->seconds = timestamp.tv_sec;
|
|
Packit Service |
99d1c0 |
out->useconds = timestamp.tv_usec;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Sync update entry to disk. */
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
sync_update(kdb_hlog_t *ulog, kdb_ent_header_t *upd)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
unsigned long start, end, size;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (!pagesize)
|
|
Packit Service |
99d1c0 |
pagesize = getpagesize();
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
start = (unsigned long)upd & ~(pagesize - 1);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
end = ((unsigned long)upd + ulog->kdb_block + (pagesize - 1)) &
|
|
Packit Service |
99d1c0 |
~(pagesize - 1);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
size = end - start;
|
|
Packit Service |
99d1c0 |
if (msync((caddr_t)start, size, MS_SYNC)) {
|
|
Packit Service |
99d1c0 |
/* Couldn't sync to disk, let's panic. */
|
|
Packit Service |
99d1c0 |
syslog(LOG_ERR, _("could not sync ulog update to disk"));
|
|
Packit Service |
99d1c0 |
abort();
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Sync memory to disk for the update log header. */
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
sync_header(kdb_hlog_t *ulog)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
if (!pagesize)
|
|
Packit Service |
99d1c0 |
pagesize = getpagesize();
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (msync((caddr_t)ulog, pagesize, MS_SYNC)) {
|
|
Packit Service |
99d1c0 |
/* Couldn't sync to disk, let's panic. */
|
|
Packit Service |
99d1c0 |
syslog(LOG_ERR, _("could not sync ulog header to disk"));
|
|
Packit Service |
99d1c0 |
abort();
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Return true if the ulog entry for sno matches sno and timestamp. */
|
|
Packit Service |
99d1c0 |
static krb5_boolean
|
|
Packit Service |
99d1c0 |
check_sno(kdb_log_context *log_ctx, kdb_sno_t sno,
|
|
Packit Service |
99d1c0 |
const kdbe_time_t *timestamp)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
unsigned int indx = (sno - 1) % log_ctx->ulogentries;
|
|
Packit Service |
99d1c0 |
kdb_ent_header_t *ent = INDEX(log_ctx->ulog, indx);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
return ent->kdb_entry_sno == sno && time_equal(&ent->kdb_time, timestamp);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Check last against our ulog and determine whether it is up to date
|
|
Packit Service |
99d1c0 |
* (UPDATE_NIL), so far out of date that a full dump is required
|
|
Packit Service |
99d1c0 |
* (UPDATE_FULL_RESYNC_NEEDED), or okay to update with ulog entries
|
|
Packit Service |
99d1c0 |
* (UPDATE_OK).
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
static update_status_t
|
|
Packit Service |
99d1c0 |
get_sno_status(kdb_log_context *log_ctx, const kdb_last_t *last)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog = log_ctx->ulog;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* If last matches the ulog's last serial number and time exactly, it are
|
|
Packit Service |
99d1c0 |
* up to date even if the ulog is empty. */
|
|
Packit Service |
99d1c0 |
if (last->last_sno == ulog->kdb_last_sno &&
|
|
Packit Service |
99d1c0 |
time_equal(&last->last_time, &ulog->kdb_last_time))
|
|
Packit Service |
99d1c0 |
return UPDATE_NIL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* If our ulog is empty or does not contain last_sno, a full resync is
|
|
Packit Service |
99d1c0 |
* required. */
|
|
Packit Service |
99d1c0 |
if (ulog->kdb_num == 0 || last->last_sno > ulog->kdb_last_sno ||
|
|
Packit Service |
99d1c0 |
last->last_sno < ulog->kdb_first_sno)
|
|
Packit Service |
99d1c0 |
return UPDATE_FULL_RESYNC_NEEDED;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* If the timestamp in our ulog entry does not match last, then sno was
|
|
Packit Service |
99d1c0 |
* reused and a full resync is required. */
|
|
Packit Service |
99d1c0 |
if (!check_sno(log_ctx, last->last_sno, &last->last_time))
|
|
Packit Service |
99d1c0 |
return UPDATE_FULL_RESYNC_NEEDED;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* last is not fully up to date, but can be updated using our ulog. */
|
|
Packit Service |
99d1c0 |
return UPDATE_OK;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Extend update log file. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
extend_file_to(int fd, unsigned int new_size)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
off_t current_offset;
|
|
Packit Service |
99d1c0 |
static const char zero[512];
|
|
Packit Service |
99d1c0 |
ssize_t wrote_size;
|
|
Packit Service |
99d1c0 |
size_t write_size;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
current_offset = lseek(fd, 0, SEEK_END);
|
|
Packit Service |
99d1c0 |
if (current_offset < 0)
|
|
Packit Service |
99d1c0 |
return errno;
|
|
Packit Service |
99d1c0 |
if (new_size > INT_MAX)
|
|
Packit Service |
99d1c0 |
return EINVAL;
|
|
Packit Service |
99d1c0 |
while (current_offset < (off_t)new_size) {
|
|
Packit Service |
99d1c0 |
write_size = new_size - current_offset;
|
|
Packit Service |
99d1c0 |
if (write_size > 512)
|
|
Packit Service |
99d1c0 |
write_size = 512;
|
|
Packit Service |
99d1c0 |
wrote_size = write(fd, zero, write_size);
|
|
Packit Service |
99d1c0 |
if (wrote_size < 0)
|
|
Packit Service |
99d1c0 |
return errno;
|
|
Packit Service |
99d1c0 |
if (wrote_size == 0)
|
|
Packit Service |
99d1c0 |
return EINVAL;
|
|
Packit Service |
99d1c0 |
current_offset += wrote_size;
|
|
Packit Service |
99d1c0 |
write_size = new_size - current_offset;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Resize the array elements. We reinitialize the update log rather than
|
|
Packit Service |
99d1c0 |
* unrolling the the log and copying it over to a temporary log for obvious
|
|
Packit Service |
99d1c0 |
* performance reasons. Replicas will subsequently do a full resync, but the
|
|
Packit Service |
99d1c0 |
* need for resizing should be very small.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd,
|
|
Packit Service |
99d1c0 |
unsigned int recsize)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
unsigned int new_block, new_size;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (ulog == NULL)
|
|
Packit Service |
99d1c0 |
return KRB5_LOG_ERROR;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
new_size = sizeof(kdb_hlog_t);
|
|
Packit Service |
99d1c0 |
new_block = (recsize / ULOG_BLOCK) + 1;
|
|
Packit Service |
99d1c0 |
new_block *= ULOG_BLOCK;
|
|
Packit Service |
99d1c0 |
new_size += ulogentries * new_block;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (new_size > MAXLOGLEN)
|
|
Packit Service |
99d1c0 |
return KRB5_LOG_ERROR;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Reinit log with new block size. */
|
|
Packit Service |
99d1c0 |
memset(ulog, 0, sizeof(*ulog));
|
|
Packit Service |
99d1c0 |
ulog->kdb_hmagic = KDB_ULOG_HDR_MAGIC;
|
|
Packit Service |
99d1c0 |
ulog->db_version_num = KDB_VERSION;
|
|
Packit Service |
99d1c0 |
ulog->kdb_state = KDB_STABLE;
|
|
Packit Service |
99d1c0 |
ulog->kdb_block = new_block;
|
|
Packit Service |
99d1c0 |
sync_header(ulog);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Expand log considering new block size. */
|
|
Packit Service |
99d1c0 |
return extend_file_to(ulogfd, new_size);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Set the ulog to contain only a dummy entry with the given serial number and
|
|
Packit Service |
99d1c0 |
* timestamp. */
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
set_dummy(kdb_log_context *log_ctx, kdb_sno_t sno, const kdbe_time_t *kdb_time)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog = log_ctx->ulog;
|
|
Packit Service |
99d1c0 |
kdb_ent_header_t *ent = INDEX(ulog, (sno - 1) % log_ctx->ulogentries);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
memset(ent, 0, sizeof(*ent));
|
|
Packit Service |
99d1c0 |
ent->kdb_umagic = KDB_ULOG_MAGIC;
|
|
Packit Service |
99d1c0 |
ent->kdb_entry_sno = sno;
|
|
Packit Service |
99d1c0 |
ent->kdb_time = *kdb_time;
|
|
Packit Service |
99d1c0 |
sync_update(ulog, ent);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
ulog->kdb_num = 1;
|
|
Packit Service |
99d1c0 |
ulog->kdb_first_sno = ulog->kdb_last_sno = sno;
|
|
Packit Service |
99d1c0 |
ulog->kdb_first_time = ulog->kdb_last_time = *kdb_time;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Reinitialize the ulog header, starting from sno 1 with the current time. */
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
reset_ulog(kdb_log_context *log_ctx)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
kdbe_time_t kdb_time;
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog = log_ctx->ulog;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
memset(ulog, 0, sizeof(*ulog));
|
|
Packit Service |
99d1c0 |
ulog->kdb_hmagic = KDB_ULOG_HDR_MAGIC;
|
|
Packit Service |
99d1c0 |
ulog->db_version_num = KDB_VERSION;
|
|
Packit Service |
99d1c0 |
ulog->kdb_block = ULOG_BLOCK;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Create a dummy entry to remember the timestamp for downstreams. */
|
|
Packit Service |
99d1c0 |
time_current(&kdb_time);
|
|
Packit Service |
99d1c0 |
set_dummy(log_ctx, 1, &kdb_time);
|
|
Packit Service |
99d1c0 |
ulog->kdb_state = KDB_STABLE;
|
|
Packit Service |
99d1c0 |
sync_header(ulog);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* If any database operations will be invoked while the ulog lock is held, the
|
|
Packit Service |
99d1c0 |
* caller must explicitly lock the database before locking the ulog, or
|
|
Packit Service |
99d1c0 |
* deadlock may result.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
lock_ulog(krb5_context context, int mode)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
kdb_log_context *log_ctx = NULL;
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog = NULL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
INIT_ULOG(context);
|
|
Packit Service |
99d1c0 |
return krb5_lock_file(context, log_ctx->ulogfd, mode);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
unlock_ulog(krb5_context context)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
(void)lock_ulog(context, KRB5_LOCKMODE_UNLOCK);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Add an update to the log. The update's kdb_entry_sno and kdb_time fields
|
|
Packit Service |
99d1c0 |
* must already be set. The layout of the update log looks like:
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* header log -> [ update header -> xdr(kdb_incr_update_t) ], ...
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
store_update(kdb_log_context *log_ctx, kdb_incr_update_t *upd)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
XDR xdrs;
|
|
Packit Service |
99d1c0 |
kdb_ent_header_t *indx_log;
|
|
Packit Service |
99d1c0 |
unsigned int i, recsize;
|
|
Packit Service |
99d1c0 |
unsigned long upd_size;
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog = log_ctx->ulog;
|
|
Packit Service |
99d1c0 |
uint32_t ulogentries = log_ctx->ulogentries;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
upd_size = xdr_sizeof((xdrproc_t)xdr_kdb_incr_update_t, upd);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
recsize = sizeof(kdb_ent_header_t) + upd_size;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (recsize > ulog->kdb_block) {
|
|
Packit Service |
99d1c0 |
retval = resize(ulog, ulogentries, log_ctx->ulogfd, recsize);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
ulog->kdb_state = KDB_UNSTABLE;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
i = (upd->kdb_entry_sno - 1) % ulogentries;
|
|
Packit Service |
99d1c0 |
indx_log = INDEX(ulog, i);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
memset(indx_log, 0, ulog->kdb_block);
|
|
Packit Service |
99d1c0 |
indx_log->kdb_umagic = KDB_ULOG_MAGIC;
|
|
Packit Service |
99d1c0 |
indx_log->kdb_entry_size = upd_size;
|
|
Packit Service |
99d1c0 |
indx_log->kdb_entry_sno = upd->kdb_entry_sno;
|
|
Packit Service |
99d1c0 |
indx_log->kdb_time = upd->kdb_time;
|
|
Packit Service |
99d1c0 |
indx_log->kdb_commit = FALSE;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
xdrmem_create(&xdrs, (char *)indx_log->entry_data,
|
|
Packit Service |
99d1c0 |
indx_log->kdb_entry_size, XDR_ENCODE);
|
|
Packit Service |
99d1c0 |
if (!xdr_kdb_incr_update_t(&xdrs, upd))
|
|
Packit Service |
99d1c0 |
return KRB5_LOG_CONV;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
indx_log->kdb_commit = TRUE;
|
|
Packit Service |
99d1c0 |
sync_update(ulog, indx_log);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Modify the ulog header to reflect the new update. */
|
|
Packit Service |
99d1c0 |
ulog->kdb_last_sno = upd->kdb_entry_sno;
|
|
Packit Service |
99d1c0 |
ulog->kdb_last_time = upd->kdb_time;
|
|
Packit Service |
99d1c0 |
if (ulog->kdb_num == 0) {
|
|
Packit Service |
99d1c0 |
/* We should only see this in old ulogs. */
|
|
Packit Service |
99d1c0 |
ulog->kdb_num = 1;
|
|
Packit Service |
99d1c0 |
ulog->kdb_first_sno = upd->kdb_entry_sno;
|
|
Packit Service |
99d1c0 |
ulog->kdb_first_time = upd->kdb_time;
|
|
Packit Service |
99d1c0 |
} else if (ulog->kdb_num < ulogentries) {
|
|
Packit Service |
99d1c0 |
ulog->kdb_num++;
|
|
Packit Service |
99d1c0 |
} else {
|
|
Packit Service |
99d1c0 |
/* We are circling; set kdb_first_sno and time to the next update. */
|
|
Packit Service |
99d1c0 |
i = upd->kdb_entry_sno % ulogentries;
|
|
Packit Service |
99d1c0 |
indx_log = INDEX(ulog, i);
|
|
Packit Service |
99d1c0 |
ulog->kdb_first_sno = indx_log->kdb_entry_sno;
|
|
Packit Service |
99d1c0 |
ulog->kdb_first_time = indx_log->kdb_time;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
ulog->kdb_state = KDB_STABLE;
|
|
Packit Service |
99d1c0 |
sync_header(ulog);
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Add an entry to the update log. */
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
ulog_add_update(krb5_context context, kdb_incr_update_t *upd)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code ret;
|
|
Packit Service |
99d1c0 |
kdb_log_context *log_ctx;
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
INIT_ULOG(context);
|
|
Packit Service |
99d1c0 |
ret = lock_ulog(context, KRB5_LOCKMODE_EXCLUSIVE);
|
|
Packit Service |
99d1c0 |
if (ret)
|
|
Packit Service |
99d1c0 |
return ret;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* If we have reached the last possible serial number, reinitialize the
|
|
Packit Service |
99d1c0 |
* ulog and start over. Replicas will do a full resync. */
|
|
Packit Service |
99d1c0 |
if (ulog->kdb_last_sno == (kdb_sno_t)-1)
|
|
Packit Service |
99d1c0 |
reset_ulog(log_ctx);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
upd->kdb_entry_sno = ulog->kdb_last_sno + 1;
|
|
Packit Service |
99d1c0 |
time_current(&upd->kdb_time);
|
|
Packit Service |
99d1c0 |
ret = store_update(log_ctx, upd);
|
|
Packit Service |
99d1c0 |
unlock_ulog(context);
|
|
Packit Service |
99d1c0 |
return ret;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Used by the replica to update its hash db from the incr update log. */
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
ulog_replay(krb5_context context, kdb_incr_result_t *incr_ret, char **db_args)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_db_entry *entry = NULL;
|
|
Packit Service |
99d1c0 |
kdb_incr_update_t *upd = NULL, *fupd;
|
|
Packit Service |
99d1c0 |
int i, no_of_updates;
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
krb5_principal dbprinc;
|
|
Packit Service |
99d1c0 |
char *dbprincstr;
|
|
Packit Service |
99d1c0 |
kdb_log_context *log_ctx;
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog = NULL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
INIT_ULOG(context);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = krb5_db_open(context, db_args,
|
|
Packit Service |
99d1c0 |
KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
no_of_updates = incr_ret->updates.kdb_ulog_t_len;
|
|
Packit Service |
99d1c0 |
upd = incr_ret->updates.kdb_ulog_t_val;
|
|
Packit Service |
99d1c0 |
fupd = upd;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
for (i = 0; i < no_of_updates; i++) {
|
|
Packit Service |
99d1c0 |
if (!upd->kdb_commit)
|
|
Packit Service |
99d1c0 |
continue;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Replay this update in the database. */
|
|
Packit Service |
99d1c0 |
if (upd->kdb_deleted) {
|
|
Packit Service |
99d1c0 |
dbprincstr = k5memdup0(upd->kdb_princ_name.utf8str_t_val,
|
|
Packit Service |
99d1c0 |
upd->kdb_princ_name.utf8str_t_len, &retval);
|
|
Packit Service |
99d1c0 |
if (dbprincstr == NULL)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = krb5_parse_name(context, dbprincstr, &dbprinc);
|
|
Packit Service |
99d1c0 |
free(dbprincstr);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = krb5int_delete_principal_no_log(context, dbprinc);
|
|
Packit Service |
99d1c0 |
krb5_free_principal(context, dbprinc);
|
|
Packit Service |
99d1c0 |
if (retval == KRB5_KDB_NOENTRY)
|
|
Packit Service |
99d1c0 |
retval = 0;
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
} else {
|
|
Packit Service |
99d1c0 |
retval = ulog_conv_2dbentry(context, &entry, upd);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = krb5int_put_principal_no_log(context, entry);
|
|
Packit Service |
99d1c0 |
krb5_db_free_principal(context, entry);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = lock_ulog(context, KRB5_LOCKMODE_EXCLUSIVE);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* If (unexpectedly) this update does not follow the last one we
|
|
Packit Service |
99d1c0 |
* stored, discard any previous ulog state. */
|
|
Packit Service |
99d1c0 |
if (ulog->kdb_num != 0 && upd->kdb_entry_sno != ulog->kdb_last_sno + 1)
|
|
Packit Service |
99d1c0 |
reset_ulog(log_ctx);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Store this update in the ulog for any downstream KDCs. */
|
|
Packit Service |
99d1c0 |
retval = store_update(log_ctx, upd);
|
|
Packit Service |
99d1c0 |
unlock_ulog(context);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
upd++;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
(void)ulog_init_header(context);
|
|
Packit Service |
99d1c0 |
if (fupd)
|
|
Packit Service |
99d1c0 |
ulog_free_entries(fupd, no_of_updates);
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Reinitialize the log header. */
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
ulog_init_header(krb5_context context)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code ret;
|
|
Packit Service |
99d1c0 |
kdb_log_context *log_ctx;
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
INIT_ULOG(context);
|
|
Packit Service |
99d1c0 |
ret = lock_ulog(context, KRB5_LOCKMODE_EXCLUSIVE);
|
|
Packit Service |
99d1c0 |
if (ret)
|
|
Packit Service |
99d1c0 |
return ret;
|
|
Packit Service |
99d1c0 |
reset_ulog(log_ctx);
|
|
Packit Service |
99d1c0 |
unlock_ulog(context);
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Map the log file to memory for performance and simplicity. */
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
ulog_map(krb5_context context, const char *logname, uint32_t ulogentries)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
struct stat st;
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
uint32_t filesize;
|
|
Packit Service |
99d1c0 |
kdb_log_context *log_ctx;
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog = NULL;
|
|
Packit Service |
99d1c0 |
krb5_boolean locked = FALSE;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
log_ctx = create_log_context(context);
|
|
Packit Service |
99d1c0 |
if (log_ctx == NULL)
|
|
Packit Service |
99d1c0 |
return ENOMEM;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (stat(logname, &st) == -1) {
|
|
rpm-build |
f9650e |
log_ctx->ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600);
|
|
Packit Service |
99d1c0 |
if (log_ctx->ulogfd == -1) {
|
|
Packit Service |
99d1c0 |
retval = errno;
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
filesize = sizeof(kdb_hlog_t) + ulogentries * ULOG_BLOCK;
|
|
Packit Service |
99d1c0 |
retval = extend_file_to(log_ctx->ulogfd, filesize);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
} else {
|
|
Packit Service |
99d1c0 |
log_ctx->ulogfd = open(logname, O_RDWR, 0600);
|
|
Packit Service |
99d1c0 |
if (log_ctx->ulogfd == -1) {
|
|
Packit Service |
99d1c0 |
retval = errno;
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
ulog = mmap(0, MAXLOGLEN, PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
Packit Service |
99d1c0 |
log_ctx->ulogfd, 0);
|
|
Packit Service |
99d1c0 |
if (ulog == MAP_FAILED) {
|
|
Packit Service |
99d1c0 |
retval = errno;
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
log_ctx->ulog = ulog;
|
|
Packit Service |
99d1c0 |
log_ctx->ulogentries = ulogentries;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = lock_ulog(context, KRB5_LOCKMODE_EXCLUSIVE);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
locked = TRUE;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (ulog->kdb_hmagic != KDB_ULOG_HDR_MAGIC) {
|
|
Packit Service |
99d1c0 |
if (ulog->kdb_hmagic != 0) {
|
|
Packit Service |
99d1c0 |
retval = KRB5_LOG_CORRUPT;
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
reset_ulog(log_ctx);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Reinit ulog if ulogentries changed such that we have too many entries or
|
|
Packit Service |
99d1c0 |
* our first or last entry was written to the wrong location. */
|
|
Packit Service |
99d1c0 |
if (ulog->kdb_num != 0 &&
|
|
Packit Service |
99d1c0 |
(ulog->kdb_num > ulogentries ||
|
|
Packit Service |
99d1c0 |
!check_sno(log_ctx, ulog->kdb_first_sno, &ulog->kdb_first_time) ||
|
|
Packit Service |
99d1c0 |
!check_sno(log_ctx, ulog->kdb_last_sno, &ulog->kdb_last_time)))
|
|
Packit Service |
99d1c0 |
reset_ulog(log_ctx);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (ulog->kdb_num != ulogentries) {
|
|
Packit Service |
99d1c0 |
/* Expand the ulog file if it isn't big enough. */
|
|
Packit Service |
99d1c0 |
filesize = sizeof(kdb_hlog_t) + ulogentries * ulog->kdb_block;
|
|
Packit Service |
99d1c0 |
retval = extend_file_to(log_ctx->ulogfd, filesize);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
if (locked)
|
|
Packit Service |
99d1c0 |
unlock_ulog(context);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
ulog_fini(context);
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Get the last set of updates seen, (last+1) to n is returned. */
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
ulog_get_entries(krb5_context context, const kdb_last_t *last,
|
|
Packit Service |
99d1c0 |
kdb_incr_result_t *ulog_handle)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
XDR xdrs;
|
|
Packit Service |
99d1c0 |
kdb_ent_header_t *indx_log;
|
|
Packit Service |
99d1c0 |
kdb_incr_update_t *upd;
|
|
Packit Service |
99d1c0 |
unsigned int indx, count;
|
|
Packit Service |
99d1c0 |
uint32_t sno;
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
kdb_log_context *log_ctx;
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog = NULL;
|
|
Packit Service |
99d1c0 |
uint32_t ulogentries;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
INIT_ULOG(context);
|
|
Packit Service |
99d1c0 |
ulogentries = log_ctx->ulogentries;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = lock_ulog(context, KRB5_LOCKMODE_SHARED);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* If another process terminated mid-update, reset the ulog and force full
|
|
Packit Service |
99d1c0 |
* resyncs. */
|
|
Packit Service |
99d1c0 |
if (ulog->kdb_state != KDB_STABLE)
|
|
Packit Service |
99d1c0 |
reset_ulog(log_ctx);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
ulog_handle->ret = get_sno_status(log_ctx, last);
|
|
Packit Service |
99d1c0 |
if (ulog_handle->ret != UPDATE_OK)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
sno = last->last_sno;
|
|
Packit Service |
99d1c0 |
count = ulog->kdb_last_sno - sno;
|
|
Packit Service |
99d1c0 |
upd = calloc(count, sizeof(kdb_incr_update_t));
|
|
Packit Service |
99d1c0 |
if (upd == NULL) {
|
|
Packit Service |
99d1c0 |
ulog_handle->ret = UPDATE_ERROR;
|
|
Packit Service |
99d1c0 |
retval = ENOMEM;
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
ulog_handle->updates.kdb_ulog_t_val = upd;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
for (; sno < ulog->kdb_last_sno; sno++) {
|
|
Packit Service |
99d1c0 |
indx = sno % ulogentries;
|
|
Packit Service |
99d1c0 |
indx_log = INDEX(ulog, indx);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
memset(upd, 0, sizeof(kdb_incr_update_t));
|
|
Packit Service |
99d1c0 |
xdrmem_create(&xdrs, (char *)indx_log->entry_data,
|
|
Packit Service |
99d1c0 |
indx_log->kdb_entry_size, XDR_DECODE);
|
|
Packit Service |
99d1c0 |
if (!xdr_kdb_incr_update_t(&xdrs, upd)) {
|
|
Packit Service |
99d1c0 |
ulog_handle->ret = UPDATE_ERROR;
|
|
Packit Service |
99d1c0 |
retval = KRB5_LOG_CONV;
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Mark commitment since we didn't want to decode and encode the incr
|
|
Packit Service |
99d1c0 |
* update record the first time. */
|
|
Packit Service |
99d1c0 |
upd->kdb_commit = indx_log->kdb_commit;
|
|
Packit Service |
99d1c0 |
upd++;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
ulog_handle->updates.kdb_ulog_t_len = count;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
ulog_handle->lastentry.last_sno = ulog->kdb_last_sno;
|
|
Packit Service |
99d1c0 |
ulog_handle->lastentry.last_time.seconds = ulog->kdb_last_time.seconds;
|
|
Packit Service |
99d1c0 |
ulog_handle->lastentry.last_time.useconds = ulog->kdb_last_time.useconds;
|
|
Packit Service |
99d1c0 |
ulog_handle->ret = UPDATE_OK;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
unlock_ulog(context);
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
ulog_set_role(krb5_context ctx, iprop_role role)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
if (create_log_context(ctx) == NULL)
|
|
Packit Service |
99d1c0 |
return ENOMEM;
|
|
Packit Service |
99d1c0 |
ctx->kdblog_context->iproprole = role;
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
update_status_t
|
|
Packit Service |
99d1c0 |
ulog_get_sno_status(krb5_context context, const kdb_last_t *last)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
update_status_t status;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (lock_ulog(context, KRB5_LOCKMODE_SHARED) != 0)
|
|
Packit Service |
99d1c0 |
return UPDATE_ERROR;
|
|
Packit Service |
99d1c0 |
status = get_sno_status(context->kdblog_context, last);
|
|
Packit Service |
99d1c0 |
unlock_ulog(context);
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
ulog_get_last(krb5_context context, kdb_last_t *last_out)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code ret;
|
|
Packit Service |
99d1c0 |
kdb_log_context *log_ctx;
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
INIT_ULOG(context);
|
|
Packit Service |
99d1c0 |
ret = lock_ulog(context, KRB5_LOCKMODE_SHARED);
|
|
Packit Service |
99d1c0 |
if (ret)
|
|
Packit Service |
99d1c0 |
return ret;
|
|
Packit Service |
99d1c0 |
last_out->last_sno = log_ctx->ulog->kdb_last_sno;
|
|
Packit Service |
99d1c0 |
last_out->last_time = log_ctx->ulog->kdb_last_time;
|
|
Packit Service |
99d1c0 |
unlock_ulog(context);
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
ulog_set_last(krb5_context context, const kdb_last_t *last)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code ret;
|
|
Packit Service |
99d1c0 |
kdb_log_context *log_ctx;
|
|
Packit Service |
99d1c0 |
kdb_hlog_t *ulog;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
INIT_ULOG(context);
|
|
Packit Service |
99d1c0 |
ret = lock_ulog(context, KRB5_LOCKMODE_EXCLUSIVE);
|
|
Packit Service |
99d1c0 |
if (ret)
|
|
Packit Service |
99d1c0 |
return ret;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
set_dummy(log_ctx, last->last_sno, &last->last_time);
|
|
Packit Service |
99d1c0 |
sync_header(ulog);
|
|
Packit Service |
99d1c0 |
unlock_ulog(context);
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
void
|
|
Packit Service |
99d1c0 |
ulog_fini(krb5_context context)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
kdb_log_context *log_ctx = context->kdblog_context;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (log_ctx == NULL)
|
|
Packit Service |
99d1c0 |
return;
|
|
Packit Service |
99d1c0 |
if (log_ctx->ulog != NULL)
|
|
Packit Service |
99d1c0 |
munmap(log_ctx->ulog, MAXLOGLEN);
|
|
Packit Service |
99d1c0 |
if (log_ctx->ulogfd != -1)
|
|
Packit Service |
99d1c0 |
close(log_ctx->ulogfd);
|
|
Packit Service |
99d1c0 |
free(log_ctx);
|
|
Packit Service |
99d1c0 |
context->kdblog_context = NULL;
|
|
Packit Service |
99d1c0 |
}
|