#include <sys/param.h>
#include <sys/time.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <bsm/audit.h>
#include <bsm/libbsm.h>
#include <bsm/audit_record.h>
#include <synch.h>
#define AU_TABLE_LENGTH 16
#define AU_TABLE_MAX 256
static token_t **au_d;
static int au_d_length = 0;
static int au_d_required_length = AU_TABLE_LENGTH;
static mutex_t mutex_au_d = DEFAULTMUTEX;
int
au_open(void)
{
int d;
token_t **au_d_new;
(void) mutex_lock(&mutex_au_d);
if (au_d_required_length > au_d_length) {
au_d_new = (token_t **)calloc(au_d_required_length,
sizeof (au_d));
if (au_d_new == NULL) {
au_d_required_length = au_d_length;
(void) mutex_unlock(&mutex_au_d);
return (-1);
}
if (au_d_length > 0) {
(void) memcpy(au_d_new, au_d, au_d_length *
sizeof (au_d));
free(au_d);
}
au_d = au_d_new;
au_d_length = au_d_required_length;
}
for (d = 0; d < au_d_length; d++) {
if (au_d[d] == (token_t *)0) {
au_d[d] = (token_t *)&au_d;
(void) mutex_unlock(&mutex_au_d);
return (d);
}
}
if (au_d_length >= AU_TABLE_MAX) {
(void) mutex_unlock(&mutex_au_d);
return (-1);
}
au_d_required_length += AU_TABLE_LENGTH;
(void) mutex_unlock(&mutex_au_d);
return (au_open());
}
int
au_write(int d, token_t *m)
{
token_t *mp;
if (d < 0)
return (-1);
if (m == (token_t *)0)
return (-1);
(void) mutex_lock(&mutex_au_d);
if ((d >= au_d_length) || (au_d[d] == (token_t *)0)) {
(void) mutex_unlock(&mutex_au_d);
return (-1);
} else if (au_d[d] == (token_t *)&au_d) {
au_d[d] = m;
(void) mutex_unlock(&mutex_au_d);
return (0);
}
for (mp = au_d[d]; mp->tt_next != (token_t *)0; mp = mp->tt_next)
;
mp->tt_next = m;
(void) mutex_unlock(&mutex_au_d);
return (0);
}
int
au_close(int d, int right, au_event_t e_type)
{
au_emod_t e_mod;
struct timeval now;
adr_t adr;
auditinfo_addr_t audit_info;
au_tid_addr_t *host_info = &audit_info.ai_termid;
token_t *dchain;
token_t *record;
char data_header;
char version;
char *buffer;
int byte_count;
int v;
(void) mutex_lock(&mutex_au_d);
if (d < 0 || d >= au_d_length ||
((dchain = au_d[d]) == (token_t *)0)) {
(void) mutex_unlock(&mutex_au_d);
return (-1);
}
au_d[d] = (token_t *)0;
if (dchain == (token_t *)&au_d) {
(void) mutex_unlock(&mutex_au_d);
return (0);
}
if (!right) {
while (dchain != (token_t *)0) {
record = dchain;
dchain = dchain->tt_next;
free(record->tt_data);
free(record);
}
(void) mutex_unlock(&mutex_au_d);
return (0);
}
byte_count = sizeof (char) * 2 + sizeof (short) * 2 +
sizeof (int32_t) + sizeof (struct timeval);
for (record = dchain; record != (token_t *)0;
record = record->tt_next) {
byte_count += record->tt_size;
}
#ifdef _LP64
#define HEADER_ID AUT_HEADER64
#define HEADER_ID_EX AUT_HEADER64_EX
#else
#define HEADER_ID AUT_HEADER32
#define HEADER_ID_EX AUT_HEADER32_EX
#endif
data_header = HEADER_ID;
if (auditon(A_GETKAUDIT, (caddr_t)&audit_info,
sizeof (audit_info)) == 0) {
int have_valid_addr;
if (host_info->at_type == AU_IPv6)
have_valid_addr = IN6_IS_ADDR_UNSPECIFIED(
(in6_addr_t *)host_info->at_addr) ? 0 : 1;
else
have_valid_addr = (host_info->at_addr[0] ==
htonl(INADDR_ANY)) ? 0 : 1;
if (have_valid_addr) {
data_header = HEADER_ID_EX;
byte_count += sizeof (int32_t) + host_info->at_type;
}
}
if ((buffer = malloc((size_t)byte_count)) == NULL) {
while (dchain != (token_t *)0) {
record = dchain;
dchain = dchain->tt_next;
free(record->tt_data);
free(record);
}
(void) mutex_unlock(&mutex_au_d);
return (-1);
}
(void) gettimeofday(&now, NULL);
version = TOKEN_VERSION;
e_mod = 0;
adr_start(&adr, buffer);
adr_char(&adr, &data_header, 1);
adr_int32(&adr, (int32_t *)&byte_count, 1);
adr_char(&adr, &version, 1);
adr_ushort(&adr, &e_type, 1);
adr_ushort(&adr, &e_mod, 1);
if (data_header == HEADER_ID_EX) {
adr_int32(&adr, (int32_t *)&host_info->at_type, 1);
adr_char(&adr, (char *)&host_info->at_addr[0],
(int)host_info->at_type);
}
#ifdef _LP64
adr_int64(&adr, (int64_t *)&now, 2);
#else
adr_int32(&adr, (int32_t *)&now, 2);
#endif
while (dchain != (token_t *)0) {
(void) memcpy(adr.adr_now, dchain->tt_data, dchain->tt_size);
adr.adr_now += dchain->tt_size;
record = dchain;
dchain = dchain->tt_next;
free(record->tt_data);
free(record);
}
v = audit((caddr_t)buffer, byte_count);
free(buffer);
(void) mutex_unlock(&mutex_au_d);
return (v);
}