#define _REENTRANT
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/utsname.h>
#include <errno.h>
#include <time.h>
#include <limits.h>
#include <libintl.h>
#include <pwd.h>
#include <netdb.h>
#include <syslog.h>
#include <rpc/rpc.h>
#include <netconfig.h>
#include <netdir.h>
#include <nfs/nfs_sec.h>
#include <nfs/export.h>
#include <rpc/auth.h>
#include <rpc/svc.h>
#include <rpc/xdr.h>
#include <rpc/clnt.h>
#include <nfs/nfs.h>
#include <nfs/nfs_log.h>
#include "fhtab.h"
#include "nfslogd.h"
static char empty_name[4] = "-";
static char ftype3_names[NF3FIFO + 1][20] = {
"\"none\"", "\"file\"", "\"dir\"", "\"blk device\"",
"\"chr device\"", "\"link\"", "\"socket\"", "\"fifo\""
};
#define NFSL_FTYPE3(ftype) \
((((ftype) >= 0) && ((ftype) <= NF3FIFO)) ? \
ftype3_names[ftype] : empty_name)
static char createmode3_names[EXCLUSIVE + 1][20] = {
"\"unchecked", "\"guarded\"", "\"exclusive\""
};
#define NFSL_CREATEMODE3(createmode) \
((((createmode) >= 0) && ((createmode) <= EXCLUSIVE)) ? \
createmode3_names[createmode] : empty_name)
static char auth_flavor_name[RPCSEC_GSS + 1][20] = {
"\"auth_null\"", "\"auth_unix\"", "\"auth_short\"", "\"auth_des\"",
"\"auth_kerb\"", "\"none\"", "\"rpcsec_gss\""
};
#define NFSL_AUTH_FLAVOR_PRINT(auth_flavor) \
(((auth_flavor) <= RPCSEC_GSS) ? \
auth_flavor_name[auth_flavor] : empty_name)
#define NFSL_ERR_CNT 31
static char nfsl_status_name[NFSL_ERR_CNT][30] = {
"\"ok\"", "\"perm\"", "\"noent\"", "\"io\"",
"\"nxio\"", "\"access\"", "\"exist\"", "\"xdev\"",
"\"nodev\"", "\"notdir\"", "\"isdir\"", "\"inval\"",
"\"fbig\"", "\"nospc\"", "\"rofs\"", "\"mlink\"",
"\"notsupp\"", "\"nametoolong\"", "\"notempty\"", "\"dquot\"",
"\"stale\"", "\"remote\"", "\"wflush\"", "\"badhandle\"",
"\"not_sync\"", "\"bad_cookie\"", "\"notsupp\"", "\"toosmall\"",
"\"serverfault\"", "\"badtype\"", "\"jukebox\"",
};
static short nfsl_status[NFSL_ERR_CNT] = {
0, 1, 2, 5, 6, 13, 17, 18,
19, 20, 21, 22, 27, 28, 30, 31,
45, 63, 66, 69, 70, 71, 99, 10001,
10002, 10003, 10004, 10005, 10006, 10007, 10008
};
static struct nfsl_log_file *elf_file_list = NULL;
extern void bcopy(const void *s1, void *s2, size_t n);
static void nfsl_log_file_free(struct nfsl_log_file *elfrec);
static void nfsl_log_file_add(struct nfsl_log_file *elfrec,
struct nfsl_log_file **elf_listp);
static struct nfsl_log_file *nfsl_log_file_find(struct nfsl_log_file *elfrec,
struct nfsl_log_file *elf_list);
static struct nfsl_log_file *nfsl_log_file_del(struct nfsl_log_file *elfrec,
struct nfsl_log_file **elf_listp);
static char *nfsl_get_time(time_t tt);
static char *nfsl_get_date(time_t tt);
static char *nfsl_get_date_nq(time_t tt);
static int nfsl_write_elfbuf(struct nfsl_log_file *elfrec);
static void nfsl_ipaddr_print(struct nfsl_log_file *, struct netbuf *);
static void nfsl_elf_record_header_print(struct nfsl_log_file *,
nfslog_record_header *, char *, char *,
struct nfsl_proc_disp *, char *);
static void nfsl_elf_buffer_header_print(struct nfsl_log_file *,
nfslog_buffer_header *);
static struct nfsl_proc_disp *nfsl_find_elf_dispatch(
nfslog_request_record *, char **);
static void nfsl_elf_rpc_print(struct nfsl_log_file *,
nfslog_request_record *, struct nfsl_proc_disp *,
char *, char *, char *);
static void nfslog_size3_print(struct nfsl_log_file *, set_size3 *);
static void nfslog_null_args(struct nfsl_log_file *, caddr_t *);
static void nfslog_null_res(struct nfsl_log_file *, caddr_t *);
static void nfslog_fhandle_print(struct nfsl_log_file *, fhandle_t *);
static void nfslog_diropargs_print(struct nfsl_log_file *, nfslog_diropargs *);
static void nfslog_setattrargs_print(struct nfsl_log_file *,
nfslog_setattrargs *);
static void nfslog_sattr_print(struct nfsl_log_file *,
nfslog_sattr *);
static void nfslog_nfsreadargs_print(struct nfsl_log_file *,
nfslog_nfsreadargs *);
static void nfslog_writeargs_print(struct nfsl_log_file *,
nfslog_writeargs *);
static void nfslog_writeresult_print(struct nfsl_log_file *,
nfslog_writeresult *, bool_t);
static void nfslog_creatargs_print(struct nfsl_log_file *,
nfslog_createargs *);
static void nfslog_rddirargs_print(struct nfsl_log_file *, nfslog_rddirargs *);
static void nfslog_linkargs_print(struct nfsl_log_file *, nfslog_linkargs *);
static void nfslog_rnmargs_print(struct nfsl_log_file *, nfslog_rnmargs *);
static void nfslog_symlinkargs_print(struct nfsl_log_file *,
nfslog_symlinkargs *);
static void nfslog_sharefsargs_print(struct nfsl_log_file *,
nfslog_sharefsargs *);
static void nfslog_getfhargs_print(struct nfsl_log_file *,
nfslog_getfhargs *);
static void nfslog_nfsstat_print(struct nfsl_log_file *, enum nfsstat *,
bool_t);
static void nfslog_diropres_print(struct nfsl_log_file *, nfslog_diropres *,
bool_t);
static void nfslog_rdlnres_print(struct nfsl_log_file *, nfslog_rdlnres *,
bool_t);
static void nfslog_rdresult_print(struct nfsl_log_file *,
nfslog_rdresult *, bool_t);
static void nfslog_rddirres_print(struct nfsl_log_file *, nfslog_rddirres *,
bool_t);
static void nfslog_fh3_print(struct nfsl_log_file *, nfs_fh3 *);
static void nfslog_diropargs3_print(struct nfsl_log_file *,
nfslog_diropargs3 *);
static void nfslog_SETATTR3args_print(struct nfsl_log_file *,
nfslog_SETATTR3args *);
static void nfslog_READ3args_print(struct nfsl_log_file *, nfslog_READ3args *);
static void nfslog_WRITE3args_print(struct nfsl_log_file *,
nfslog_WRITE3args *);
static void nfslog_CREATE3args_print(struct nfsl_log_file *,
nfslog_CREATE3args *);
static void nfslog_MKDIR3args_print(struct nfsl_log_file *,
nfslog_MKDIR3args *);
static void nfslog_SYMLINK3args_print(struct nfsl_log_file *,
nfslog_SYMLINK3args *);
static void nfslog_MKNOD3args_print(struct nfsl_log_file *,
nfslog_MKNOD3args *);
static void nfslog_REMOVE3args_print(struct nfsl_log_file *,
nfslog_REMOVE3args *);
static void nfslog_RMDIR3args_print(struct nfsl_log_file *,
nfslog_RMDIR3args *);
static void nfslog_RENAME3args_print(struct nfsl_log_file *,
nfslog_RENAME3args *);
static void nfslog_LINK3args_print(struct nfsl_log_file *,
nfslog_LINK3args *);
static void nfslog_COMMIT3args_print(struct nfsl_log_file *,
nfslog_COMMIT3args *);
static void nfslog_READDIRPLUS3args_print(struct nfsl_log_file *,
nfslog_READDIRPLUS3args *);
static void nfslog_nfsstat3_print(struct nfsl_log_file *,
nfsstat3 *, bool_t);
static void nfslog_LOOKUP3res_print(struct nfsl_log_file *,
nfslog_LOOKUP3res *, bool_t);
static void nfslog_READLINK3res_print(struct nfsl_log_file *,
nfslog_READLINK3res *, bool_t);
static void nfslog_READ3res_print(struct nfsl_log_file *,
nfslog_READ3res *, bool_t);
static void nfslog_WRITE3res_print(struct nfsl_log_file *,
nfslog_WRITE3res *, bool_t);
static void nfslog_CREATE3res_print(struct nfsl_log_file *,
nfslog_CREATE3res *, bool_t);
static void nfslog_MKDIR3res_print(struct nfsl_log_file *,
nfslog_MKDIR3res *, bool_t);
static void nfslog_SYMLINK3res_print(struct nfsl_log_file *,
nfslog_SYMLINK3res *, bool_t);
static void nfslog_MKNOD3res_print(struct nfsl_log_file *,
nfslog_MKNOD3res *, bool_t);
static void nfslog_READDIRPLUS3res_print(struct nfsl_log_file *,
nfslog_READDIRPLUS3res *, bool_t);
extern int debug;
static bool_t nfsl_print_fh = FALSE;
#define DFLT_BUFFERSIZE 8192
#define DFLT_OVFSIZE 3072
static char hostname[MAXHOSTNAMELEN];
static struct nfsl_proc_disp nfsl_elf_proc_v2[] = {
{nfslog_null_args, nfslog_null_res, "\"null\""},
{nfslog_fhandle_print, nfslog_nfsstat_print, "\"getattr\""},
{nfslog_setattrargs_print, nfslog_nfsstat_print, "\"setattr\""},
{nfslog_null_args, nfslog_null_res, "\"root\""},
{nfslog_diropargs_print, nfslog_diropres_print, "\"lookup\""},
{nfslog_fhandle_print, nfslog_rdlnres_print, "\"readlink\""},
{nfslog_nfsreadargs_print, nfslog_rdresult_print, "\"read\""},
{nfslog_null_args, nfslog_null_res, "\"writecache\""},
{nfslog_writeargs_print, nfslog_writeresult_print, "\"write\""},
{nfslog_creatargs_print, nfslog_diropres_print, "\"create\""},
{nfslog_diropargs_print, nfslog_nfsstat_print, "\"remove\""},
{nfslog_rnmargs_print, nfslog_nfsstat_print, "\"rename\""},
{nfslog_linkargs_print, nfslog_nfsstat_print, "\"link\""},
{nfslog_symlinkargs_print, nfslog_nfsstat_print, "\"symlink\""},
{nfslog_creatargs_print, nfslog_diropres_print, "\"mkdir\""},
{nfslog_diropargs_print, nfslog_nfsstat_print, "\"rmdir\""},
{nfslog_rddirargs_print, nfslog_rddirres_print, "\"readdir\""},
{nfslog_fhandle_print, nfslog_nfsstat_print, "\"statfs\""},
};
static struct nfsl_proc_disp nfsl_elf_proc_v3[] = {
{nfslog_null_args, nfslog_null_res, "\"null\""},
{nfslog_fh3_print, nfslog_nfsstat3_print, "\"getattr\""},
{nfslog_SETATTR3args_print, nfslog_nfsstat3_print, "\"setattr\""},
{nfslog_diropargs3_print, nfslog_LOOKUP3res_print, "\"lookup\""},
{nfslog_fh3_print, nfslog_nfsstat3_print, "\"access\""},
{nfslog_fh3_print, nfslog_READLINK3res_print, "\"readlink\""},
{nfslog_READ3args_print, nfslog_READ3res_print, "\"read\""},
{nfslog_WRITE3args_print, nfslog_WRITE3res_print, "\"write\""},
{nfslog_CREATE3args_print, nfslog_CREATE3res_print, "\"create\""},
{nfslog_MKDIR3args_print, nfslog_MKDIR3res_print, "\"mkdir\""},
{nfslog_SYMLINK3args_print, nfslog_SYMLINK3res_print, "\"symlink\""},
{nfslog_MKNOD3args_print, nfslog_MKNOD3res_print, "\"mknod\""},
{nfslog_REMOVE3args_print, nfslog_nfsstat3_print, "\"remove\""},
{nfslog_RMDIR3args_print, nfslog_nfsstat3_print, "\"rmdir\""},
{nfslog_RENAME3args_print, nfslog_nfsstat3_print, "\"rename\""},
{nfslog_LINK3args_print, nfslog_nfsstat3_print, "\"link\""},
{nfslog_fh3_print, nfslog_nfsstat3_print, "\"readdir\""},
{nfslog_READDIRPLUS3args_print, nfslog_READDIRPLUS3res_print,
"\"readdirplus\""},
{nfslog_fh3_print, nfslog_nfsstat3_print, "\"fsstat\""},
{nfslog_fh3_print, nfslog_nfsstat3_print, "\"fsinfo\""},
{nfslog_fh3_print, nfslog_nfsstat3_print, "\"pathconf\""},
{nfslog_COMMIT3args_print, nfslog_nfsstat3_print, "\"commit\""},
};
static struct nfsl_proc_disp nfsl_log_elf_proc_v1[] = {
{nfslog_null_args, nfslog_null_res, "\"null\""},
{nfslog_sharefsargs_print, nfslog_nfsstat_print, "\"log_share\""},
{nfslog_sharefsargs_print, nfslog_nfsstat_print, "\"log_unshare\""},
{nfslog_diropargs3_print, nfslog_LOOKUP3res_print, "\"lookup\""},
{nfslog_getfhargs_print, nfslog_nfsstat_print, "\"log_getfh\""},
};
static struct nfsl_vers_disp nfsl_elf_vers_disptable[] = {
{sizeof (nfsl_elf_proc_v2) / sizeof (nfsl_elf_proc_v2[0]),
nfsl_elf_proc_v2},
{sizeof (nfsl_elf_proc_v3) / sizeof (nfsl_elf_proc_v3[0]),
nfsl_elf_proc_v3},
};
static struct nfsl_vers_disp nfsl_log_elf_vers_disptable[] = {
{sizeof (nfsl_log_elf_proc_v1) / sizeof (nfsl_log_elf_proc_v1[0]),
nfsl_log_elf_proc_v1},
};
static struct nfsl_prog_disp nfsl_elf_dispatch_table[] = {
{NFS_PROGRAM,
NFS_VERSMIN,
sizeof (nfsl_elf_vers_disptable) /
sizeof (nfsl_elf_vers_disptable[0]),
nfsl_elf_vers_disptable, "nfs"},
{NFSLOG_PROGRAM,
NFSLOG_VERSMIN,
sizeof (nfsl_log_elf_vers_disptable) /
sizeof (nfsl_log_elf_vers_disptable[0]),
nfsl_log_elf_vers_disptable, "nfslog"},
};
static int nfsl_elf_dispatch_table_arglen =
sizeof (nfsl_elf_dispatch_table) /
sizeof (nfsl_elf_dispatch_table[0]);
static char *
nfslog_get_status(short status)
{
int low, mid, high;
short errstat;
if (status == 0)
return (nfsl_status_name[0]);
low = 0;
high = NFSL_ERR_CNT;
mid = NFSL_ERR_CNT / 2;
while (((errstat = nfsl_status[mid]) != status) && (low < mid) &&
(mid < high)) {
if (errstat > status) {
high = mid;
} else {
low = mid;
}
mid = low + ((high - low) / 2);
}
if (errstat == status) {
return (nfsl_status_name[mid]);
}
return (NULL);
}
static char *
nfsl_get_time(time_t tt)
{
static char timestr[20];
static time_t lasttime;
struct tm tmst;
if (tt == lasttime)
return (timestr);
if (localtime_r(&tt, &tmst) == NULL) {
return (empty_name);
}
(void) sprintf(timestr, "%02d:%02d:%02d",
tmst.tm_hour, tmst.tm_min, tmst.tm_sec);
lasttime = tt;
return (timestr);
}
static char *
nfsl_get_date(time_t tt)
{
static char timestr[30];
static time_t lasttime;
struct tm tmst;
if (tt == lasttime)
return (timestr);
if (localtime_r(&tt, &tmst) == NULL) {
return (empty_name);
}
(void) sprintf(timestr, "\"%04d-%02d-%02d %02d:%02d:%02d\"",
tmst.tm_year + 1900, tmst.tm_mon + 1, tmst.tm_mday,
tmst.tm_hour, tmst.tm_min, tmst.tm_sec);
lasttime = tt;
return (timestr);
}
static char *
nfsl_get_date_nq(time_t tt)
{
static char timestr[30];
static time_t lasttime;
struct tm tmst;
if (tt == lasttime)
return (timestr);
if (localtime_r(&tt, &tmst) == NULL) {
return (empty_name);
}
(void) sprintf(timestr, "%04d-%02d-%02d %02d:%02d:%02d",
tmst.tm_year + 1900, tmst.tm_mon + 1, tmst.tm_mday,
tmst.tm_hour, tmst.tm_min, tmst.tm_sec);
return (timestr);
}
static int
nfsl_write_elfbuf(struct nfsl_log_file *elfrec)
{
int rc;
char *elfbuf = elfrec->buf;
int elfbufoffset = elfrec->bufoffset;
if (debug > 1)
(void) printf("nfsl_write_elfbuf: bufoffset %d\n",
elfbufoffset);
if (elfbufoffset <= 0)
return (0);
elfbuf[elfbufoffset] = '\0';
if ((rc = fputs(elfbuf, elfrec->fp)) < 0) {
syslog(LOG_ERR, gettext("Write to %s failed: %s\n"),
elfrec->path, strerror(errno));
return (-1);
}
if (rc != elfbufoffset) {
syslog(LOG_ERR, gettext("Write %d bytes to %s returned %d\n"),
elfbufoffset, elfrec->path, rc);
return (-1);
}
elfrec->bufoffset = 0;
return (0);
}
static void
nfslog_null_args(struct nfsl_log_file *elfrec, caddr_t *nfsl_args)
{
}
static void
nfslog_null_res(struct nfsl_log_file *elfrec, caddr_t *nfsl_res)
{
}
static void
nfslog_fh3_print(struct nfsl_log_file *elfrec, nfs_fh3 *fh3)
{
if (!nfsl_print_fh)
return;
if (fh3->fh3_length == sizeof (fhandle_t)) {
nfslog_fhandle_print(elfrec, (fhandle_t *)&fh3->fh3_u.data);
} else {
nfslog_opaque_print_buf(fh3->fh3_u.data, fh3->fh3_length,
elfrec->buf, &elfrec->bufoffset,
DFLT_BUFFERSIZE + DFLT_OVFSIZE);
}
}
static void
nfslog_fhandle_print(struct nfsl_log_file *elfrec, fhandle_t *args)
{
if (!nfsl_print_fh)
return;
nfslog_opaque_print_buf(args, sizeof (*args),
elfrec->buf, &elfrec->bufoffset,
DFLT_BUFFERSIZE + DFLT_OVFSIZE);
}
static void
nfslog_diropargs_print(struct nfsl_log_file *elfrec, nfslog_diropargs *args)
{
char *elfbuf = elfrec->buf;
int elfbufoffset = elfrec->bufoffset;
if (nfsl_print_fh) {
nfslog_fhandle_print(elfrec, &args->da_fhandle);
elfbufoffset = elfrec->bufoffset;
if (args->da_name != NULL) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" \"%s\"", args->da_name);
} else {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
empty_name);
}
}
elfrec->bufoffset = elfbufoffset;
}
static void
nfslog_sattr_print(struct nfsl_log_file *elfrec, nfslog_sattr *args)
{
char *elfbuf = elfrec->buf;
int elfbufoffset = elfrec->bufoffset;
if (args->sa_mode != (uint32_t)-1) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" \"mode=0%o\"", args->sa_mode);
}
if (args->sa_uid != (uint32_t)-1) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" \"uid=0x%x\"", args->sa_uid);
}
if (args->sa_gid != (uint32_t)-1) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" \"gid=0x%x\"", args->sa_gid);
}
if (args->sa_size != (uint32_t)-1) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" \"size=0x%x\"", args->sa_size);
}
if (args->sa_atime.tv_sec != (uint32_t)-1) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" \"atime=%s\"",
nfsl_get_date_nq((time_t)args->sa_atime.tv_sec));
}
if (args->sa_mtime.tv_sec != (uint32_t)-1) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" \"mtime=%s\"",
nfsl_get_date_nq((time_t)args->sa_mtime.tv_sec));
}
elfrec->bufoffset = elfbufoffset;
}
static void
nfslog_setattrargs_print(struct nfsl_log_file *elfrec, nfslog_setattrargs *args)
{
nfslog_fhandle_print(elfrec, &args->saa_fh);
nfslog_sattr_print(elfrec, &args->saa_sa);
}
static void
nfslog_nfsreadargs_print(struct nfsl_log_file *elfrec,
nfslog_nfsreadargs *args)
{
char *elfbuf = elfrec->buf;
int elfbufoffset;
nfslog_fhandle_print(elfrec, &args->ra_fhandle);
elfbufoffset = elfrec->bufoffset;
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->ra_offset);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->ra_count);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->ra_totcount);
elfrec->bufoffset = elfbufoffset;
}
static void
nfslog_writeargs_print(struct nfsl_log_file *elfrec, nfslog_writeargs *args)
{
char *elfbuf = elfrec->buf;
int elfbufoffset = elfrec->bufoffset;
nfslog_fhandle_print(elfrec, &args->waargs_fhandle);
elfbufoffset = elfrec->bufoffset;
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->waargs_begoff);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->waargs_offset);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->waargs_totcount);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%x",
args->waargs_count);
}
static void
nfslog_writeresult_print(struct nfsl_log_file *elfrec, nfslog_writeresult *res,
bool_t print_status)
{
char *elfbuf = elfrec->buf;
int elfbufoffset = elfrec->bufoffset;
if (print_status) {
nfslog_nfsstat_print(elfrec, &res->wr_status, print_status);
} else if (res->wr_status == NFS_OK) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
res->nfslog_writeresult_u.wr_size);
elfrec->bufoffset = elfbufoffset;
}
}
static void
nfslog_creatargs_print(struct nfsl_log_file *elfrec, nfslog_createargs *args)
{
nfslog_diropargs_print(elfrec, &args->ca_da);
nfslog_sattr_print(elfrec, &args->ca_sa);
}
static void
nfslog_rddirargs_print(struct nfsl_log_file *elfrec, nfslog_rddirargs *args)
{
char *elfbuf = elfrec->buf;
int elfbufoffset;
nfslog_fhandle_print(elfrec, &args->rda_fh);
elfbufoffset = elfrec->bufoffset;
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->rda_offset);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->rda_count);
elfrec->bufoffset = elfbufoffset;
}
static void
nfslog_rnmargs_print(struct nfsl_log_file *elfrec, nfslog_rnmargs *args)
{
nfslog_diropargs_print(elfrec, &args->rna_from);
nfslog_diropargs_print(elfrec, &args->rna_to);
}
static void
nfslog_linkargs_print(struct nfsl_log_file *elfrec, nfslog_linkargs *args)
{
nfslog_fhandle_print(elfrec, &args->la_from);
nfslog_diropargs_print(elfrec, &args->la_to);
}
static void
nfslog_symlinkargs_print(struct nfsl_log_file *elfrec, nfslog_symlinkargs *args)
{
char *elfbuf = elfrec->buf;
int elfbufoffset;
nfslog_diropargs_print(elfrec, &args->sla_from);
elfbufoffset = elfrec->bufoffset;
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " \"%s\"",
args->sla_tnm);
elfrec->bufoffset = elfbufoffset;
nfslog_sattr_print(elfrec, &args->sla_sa);
}
static void
nfslog_sharefsargs_print(struct nfsl_log_file *elfrec,
nfslog_sharefsargs *args)
{
unsigned int elfbufoffset;
char *elfbuf = elfrec->buf;
nfslog_fhandle_print(elfrec, &args->sh_fh_buf);
elfbufoffset = elfrec->bufoffset;
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->sh_flags);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->sh_anon);
if (nfsl_print_fh) {
if (args->sh_path != NULL) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" \"%s\"", args->sh_path);
} else {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
empty_name);
}
}
elfrec->bufoffset = elfbufoffset;
}
static void
nfslog_getfhargs_print(struct nfsl_log_file *elfrec,
nfslog_getfhargs *args)
{
unsigned int elfbufoffset;
char *elfbuf = elfrec->buf;
nfslog_fhandle_print(elfrec, &args->gfh_fh_buf);
elfbufoffset = elfrec->bufoffset;
if (nfsl_print_fh) {
if (args->gfh_path != NULL) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" \"%s\"", args->gfh_path);
} else {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
empty_name);
}
}
elfrec->bufoffset = elfbufoffset;
}
static void
nfslog_nfsstat_print(struct nfsl_log_file *elfrec, enum nfsstat *res,
bool_t print_status)
{
if (print_status) {
char *statp = nfslog_get_status((short)(*res));
if (statp != NULL)
elfrec->bufoffset +=
sprintf(&elfrec->buf[elfrec->bufoffset], " %s",
statp);
else
elfrec->bufoffset +=
sprintf(&elfrec->buf[elfrec->bufoffset], " %5d",
*res);
}
}
static void
nfslog_diropres_print(struct nfsl_log_file *elfrec, nfslog_diropres *res,
bool_t print_status)
{
if (print_status) {
nfslog_nfsstat_print(elfrec, &res->dr_status, print_status);
} else if (res->dr_status == NFS_OK) {
nfslog_fhandle_print(elfrec,
&res->nfslog_diropres_u.dr_ok.drok_fhandle);
}
}
static void
nfslog_rdlnres_print(struct nfsl_log_file *elfrec, nfslog_rdlnres *res,
bool_t print_status)
{
if (print_status) {
nfslog_nfsstat_print(elfrec, &res->rl_status, print_status);
} else if (res->rl_status == NFS_OK) {
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" \"%s\"", res->nfslog_rdlnres_u.rl_ok);
}
}
static void
nfslog_rdresult_print(struct nfsl_log_file *elfrec, nfslog_rdresult *res,
bool_t print_status)
{
if (print_status) {
nfslog_nfsstat_print(elfrec, &res->r_status, print_status);
} else if (res->r_status == NFS_OK) {
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" 0x%x", res->nfslog_rdresult_u.r_ok.filesize);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" 0x%x", res->nfslog_rdresult_u.r_ok.rrok_count);
}
}
static void
nfslog_rddirres_print(struct nfsl_log_file *elfrec, nfslog_rddirres *res,
bool_t print_status)
{
if (print_status) {
nfslog_nfsstat_print(elfrec, &res->rd_status, print_status);
} else if (res->rd_status == NFS_OK) {
char *elfbuf = elfrec->buf;
int elfbufoffset = elfrec->bufoffset;
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
res->nfslog_rddirres_u.rd_ok.rdok_offset);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
res->nfslog_rddirres_u.rd_ok.rdok_size);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
res->nfslog_rddirres_u.rd_ok.rdok_eof);
elfrec->bufoffset = elfbufoffset;
}
}
static void
nfslog_diropargs3_print(struct nfsl_log_file *elfrec,
nfslog_diropargs3 *args)
{
if (nfsl_print_fh) {
nfslog_fh3_print(elfrec, &args->dir);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" \"%s\"", args->name);
}
}
static void
nfslog_size3_print(struct nfsl_log_file *elfrec, set_size3 *args)
{
char *elfbuf = elfrec->buf;
int elfbufoffset = elfrec->bufoffset;
if (args->set_it) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" \"size=0x%llx\"", args->size);
}
elfrec->bufoffset = elfbufoffset;
}
static void
nfslog_SETATTR3args_print(struct nfsl_log_file *elfrec,
nfslog_SETATTR3args *args)
{
nfslog_fh3_print(elfrec, &args->object);
nfslog_size3_print(elfrec, &args->size);
}
static void
nfslog_READ3args_print(struct nfsl_log_file *elfrec, nfslog_READ3args *args)
{
nfslog_fh3_print(elfrec, &args->file);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%llx",
args->offset);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%x",
args->count);
}
static void
nfslog_WRITE3args_print(struct nfsl_log_file *elfrec,
nfslog_WRITE3args *args)
{
char *elfbuf = elfrec->buf;
int elfbufoffset;
nfslog_fh3_print(elfrec, &args->file);
elfbufoffset = elfrec->bufoffset;
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%llx",
args->offset);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->count);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
args->stable);
elfrec->bufoffset = elfbufoffset;
}
static void
nfslog_CREATE3args_print(struct nfsl_log_file *elfrec,
nfslog_CREATE3args *args)
{
nfslog_diropargs3_print(elfrec, &args->where);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " %s",
NFSL_CREATEMODE3(args->how.mode));
if (args->how.mode != EXCLUSIVE) {
nfslog_size3_print(elfrec,
&args->how.nfslog_createhow3_u.size);
}
}
static void
nfslog_MKDIR3args_print(struct nfsl_log_file *elfrec,
nfslog_MKDIR3args *args)
{
nfslog_diropargs3_print(elfrec, &args->where);
}
static void
nfslog_SYMLINK3args_print(struct nfsl_log_file *elfrec,
nfslog_SYMLINK3args *args)
{
nfslog_diropargs3_print(elfrec, &args->where);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" \"%s\"", args->symlink_data);
}
static void
nfslog_MKNOD3args_print(struct nfsl_log_file *elfrec,
nfslog_MKNOD3args *args)
{
nfslog_diropargs3_print(elfrec, &args->where);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " %s",
NFSL_FTYPE3(args->type));
}
static void
nfslog_REMOVE3args_print(struct nfsl_log_file *elfrec,
nfslog_REMOVE3args *args)
{
nfslog_diropargs3_print(elfrec, &args->object);
}
static void
nfslog_RMDIR3args_print(struct nfsl_log_file *elfrec,
nfslog_RMDIR3args *args)
{
nfslog_diropargs3_print(elfrec, &args->object);
}
static void
nfslog_RENAME3args_print(struct nfsl_log_file *elfrec,
nfslog_RENAME3args *args)
{
nfslog_diropargs3_print(elfrec, &args->from);
nfslog_diropargs3_print(elfrec, &args->to);
}
static void
nfslog_LINK3args_print(struct nfsl_log_file *elfrec, nfslog_LINK3args *args)
{
nfslog_fh3_print(elfrec, &args->file);
nfslog_diropargs3_print(elfrec, &args->link);
}
static void
nfslog_READDIRPLUS3args_print(struct nfsl_log_file *elfrec,
nfslog_READDIRPLUS3args *args)
{
nfslog_fh3_print(elfrec, &args->dir);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%x",
args->dircount);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%x",
args->maxcount);
}
static void
nfslog_COMMIT3args_print(struct nfsl_log_file *elfrec,
nfslog_COMMIT3args *args)
{
nfslog_fh3_print(elfrec, &args->file);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%llx",
args->offset);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%x",
args->count);
}
static void
nfslog_nfsstat3_print(struct nfsl_log_file *elfrec, enum nfsstat3 *res,
bool_t print_status)
{
if (print_status) {
char *statp = nfslog_get_status((short)(*res));
if (statp != NULL)
elfrec->bufoffset +=
sprintf(&elfrec->buf[elfrec->bufoffset], " %s",
statp);
else
elfrec->bufoffset +=
sprintf(&elfrec->buf[elfrec->bufoffset], " %5d",
*res);
}
}
static void
nfslog_LOOKUP3res_print(struct nfsl_log_file *elfrec,
nfslog_LOOKUP3res *res, bool_t print_status)
{
if (print_status) {
nfslog_nfsstat3_print(elfrec, &res->status, print_status);
} else if (res->status == NFS3_OK) {
nfslog_fh3_print(elfrec, &res->nfslog_LOOKUP3res_u.object);
}
}
static void
nfslog_READLINK3res_print(struct nfsl_log_file *elfrec,
nfslog_READLINK3res *res, bool_t print_status)
{
if (print_status) {
nfslog_nfsstat3_print(elfrec, &res->status, print_status);
} else if (res->status == NFS3_OK) {
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" %s", res->nfslog_READLINK3res_u.data);
}
}
static void
nfslog_READ3res_print(struct nfsl_log_file *elfrec, nfslog_READ3res *res,
bool_t print_status)
{
if (print_status) {
nfslog_nfsstat3_print(elfrec, &res->status, print_status);
} else if (res->status == NFS3_OK) {
char *elfbuf = elfrec->buf;
int elfbufoffset = elfrec->bufoffset;
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%llx",
res->nfslog_READ3res_u.ok.filesize);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
res->nfslog_READ3res_u.ok.count);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
res->nfslog_READ3res_u.ok.eof);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
res->nfslog_READ3res_u.ok.size);
elfrec->bufoffset = elfbufoffset;
}
}
static void
nfslog_WRITE3res_print(struct nfsl_log_file *elfrec, nfslog_WRITE3res *res,
bool_t print_status)
{
if (print_status) {
nfslog_nfsstat3_print(elfrec, &res->status, print_status);
} else if (res->status == NFS3_OK) {
char *elfbuf = elfrec->buf;
int elfbufoffset = elfrec->bufoffset;
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%llx",
res->nfslog_WRITE3res_u.ok.filesize);
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" 0x%x", res->nfslog_WRITE3res_u.ok.count);
elfbufoffset += sprintf(&elfrec->buf[elfbufoffset],
" 0x%x", res->nfslog_WRITE3res_u.ok.committed);
elfrec->bufoffset = elfbufoffset;
}
}
static void
nfslog_CREATE3res_print(struct nfsl_log_file *elfrec, nfslog_CREATE3res *res,
bool_t print_status)
{
if (print_status) {
nfslog_nfsstat3_print(elfrec, &res->status, print_status);
} else if (res->status == NFS3_OK) {
if (res->nfslog_CREATE3res_u.ok.obj.handle_follows) {
nfslog_fh3_print(elfrec,
&res->nfslog_CREATE3res_u.ok.obj.handle);
}
}
}
static void
nfslog_MKDIR3res_print(struct nfsl_log_file *elfrec, nfslog_MKDIR3res *res,
bool_t print_status)
{
if (print_status) {
nfslog_nfsstat3_print(elfrec, &res->status, print_status);
} else if (res->status == NFS3_OK) {
if (res->nfslog_MKDIR3res_u.obj.handle_follows) {
nfslog_fh3_print(elfrec,
&res->nfslog_MKDIR3res_u.obj.handle);
}
}
}
static void
nfslog_SYMLINK3res_print(struct nfsl_log_file *elfrec, nfslog_SYMLINK3res *res,
bool_t print_status)
{
if (print_status) {
nfslog_nfsstat3_print(elfrec, &res->status, print_status);
} else if (res->status == NFS3_OK) {
if (res->nfslog_SYMLINK3res_u.obj.handle_follows) {
nfslog_fh3_print(elfrec,
&res->nfslog_SYMLINK3res_u.obj.handle);
}
}
}
static void
nfslog_MKNOD3res_print(struct nfsl_log_file *elfrec, nfslog_MKNOD3res *res,
bool_t print_status)
{
if (print_status) {
nfslog_nfsstat3_print(elfrec, &res->status, print_status);
} else if (res->status == NFS3_OK) {
if (res->nfslog_MKNOD3res_u.obj.handle_follows) {
nfslog_fh3_print(elfrec,
&res->nfslog_MKNOD3res_u.obj.handle);
}
}
}
static void
nfslog_READDIRPLUS3res_print(struct nfsl_log_file *elfrec,
nfslog_READDIRPLUS3res *res, bool_t print_status)
{
if (print_status) {
nfslog_nfsstat3_print(elfrec, &res->status, print_status);
}
}
static void
nfsl_ipaddr_print(struct nfsl_log_file *elfrec, struct netbuf *ptr)
{
struct hostent *hp;
extern char *inet_ntop();
int size, sin_family, error;
char *elfbuf = elfrec->buf;
char *addrp;
int elfbufoffset = elfrec->bufoffset;
if (ptr->len == 0) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
empty_name);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
empty_name);
elfrec->bufoffset = elfbufoffset;
return;
}
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " ");
sin_family = ((struct sockaddr_in *)ptr->buf)->sin_family;
switch (sin_family) {
case (AF_INET):
addrp = (char *)&((struct sockaddr_in *)ptr->buf)->sin_addr;
size = sizeof (struct in_addr);
break;
case (AF_INET6):
addrp = (char *)&((struct sockaddr_in6 *)ptr->buf)->sin6_addr;
size = sizeof (struct in6_addr);
break;
default:
for (size = ptr->len, addrp = ptr->buf; size > 0; size--) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], "%02x",
*addrp);
}
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
empty_name);
elfrec->bufoffset = elfbufoffset;
return;
}
if (inet_ntop(sin_family, addrp, &elfbuf[elfbufoffset],
(size_t)(DFLT_BUFFERSIZE + DFLT_OVFSIZE - elfbufoffset))
== NULL) {
elfbuf[elfrec->bufoffset] = '\0';
return;
}
elfbufoffset += strlen(&elfbuf[elfbufoffset]);
hp = getipnodebyaddr(addrp, size, sin_family, &error);
if (hp != NULL) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " \"%s\"",
hp->h_name);
} else {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
empty_name);
}
elfrec->bufoffset = elfbufoffset;
}
static void
nfsl_elf_record_header_print(struct nfsl_log_file *elfrec,
nfslog_record_header *lhp, char *principal_name, char *tag,
struct nfsl_proc_disp *disp, char *progname)
{
struct passwd *pwp = NULL;
char *elfbuf = elfrec->buf;
int elfbufoffset = elfrec->bufoffset;
elfbufoffset += sprintf(&elfbuf[elfbufoffset], "%s",
nfsl_get_time((time_t)lhp->rh_timestamp.tv_sec));
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x",
lhp->rh_reclen);
if ((tag != NULL) && (tag[0] != '\0')) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " \"%s\"", tag);
} else {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
empty_name);
}
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s 0x%x %s",
progname, lhp->rh_version, disp->procname);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
NFSL_AUTH_FLAVOR_PRINT(lhp->rh_auth_flavor));
if ((principal_name != NULL) && (principal_name[0] != '\0')) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " \"%s\"",
principal_name);
if ((pwp = getpwnam(principal_name)) != NULL) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" 0x%lx", pwp->pw_uid);
} else {
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" %s", empty_name);
}
} else {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
empty_name);
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
empty_name);
}
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%lx", lhp->rh_uid);
if (((pwp = getpwuid(lhp->rh_uid)) != NULL) && (pwp->pw_name != NULL)) {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " \"%s\"",
pwp->pw_name);
} else {
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s",
empty_name);
}
elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%lx", lhp->rh_gid);
elfrec->bufoffset = elfbufoffset;
}
static void
nfsl_elf_buffer_header_print(struct nfsl_log_file *elfrec,
nfslog_buffer_header *bufhdr)
{
int rc;
struct utsname name;
char *elfbuf = elfrec->buf;
int elfbufoffset = elfrec->bufoffset;
rc = uname(&name);
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
"#Version %d.0\n#Software \"%s\"\n",
bufhdr->bh_version, ((rc >= 0) ? name.sysname : empty_name));
elfbufoffset += sprintf(&elfbuf[elfbufoffset], "#Date %s\n",
nfsl_get_date((time_t)bufhdr->bh_timestamp.tv_sec));
elfbufoffset += sprintf(&elfbuf[elfbufoffset], "#Remark %s\n",
empty_name);
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
"#Fields: time bytes tag");
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" rpc-program rpc-version rpc-procedure");
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" auth-flavor s-user-name s-uid uid u-name gid net-id c-ip");
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" c-dns s-dns status rpcarg-path");
elfbufoffset += sprintf(&elfbuf[elfbufoffset],
" rpc-arguments... rpc-response...\n");
elfrec->bufoffset = elfbufoffset;
}
static struct nfsl_proc_disp *
nfsl_find_elf_dispatch(nfslog_request_record *logrec, char **prognamep)
{
nfslog_record_header *logrechdr = &logrec->re_header;
struct nfsl_prog_disp *progtable;
struct nfsl_vers_disp *verstable;
int i, vers;
for (i = 0; (i < nfsl_elf_dispatch_table_arglen) &&
(logrechdr->rh_prognum != nfsl_elf_dispatch_table[i].nfsl_dis_prog);
i++);
if (i >= nfsl_elf_dispatch_table_arglen) {
return (NULL);
}
progtable = &nfsl_elf_dispatch_table[i];
vers = logrechdr->rh_version - progtable->nfsl_dis_versmin;
verstable = &progtable->nfsl_dis_vers_table[vers];
*prognamep = progtable->progname;
return (&verstable->nfsl_dis_proc_table[logrechdr->rh_procnum]);
}
static void
nfsl_elf_rpc_print(struct nfsl_log_file *elfrec,
nfslog_request_record *logrec, struct nfsl_proc_disp *disp,
char *progname, char *path1, char *path2)
{
if (debug > 1) {
(void) printf("%s %d %s", progname,
logrec->re_header.rh_version, disp->procname);
(void) printf(": '%s', '%s'\n",
((path1 != NULL) ? path1 : empty_name),
((path2 != NULL) ? path2 : empty_name));
}
nfsl_elf_record_header_print(elfrec, &logrec->re_header,
logrec->re_principal_name, logrec->re_tag,
disp, progname);
if ((logrec->re_netid != NULL) && (logrec->re_netid[0] != '\0')) {
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" \"%s\"", logrec->re_netid);
} else {
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" %s", empty_name);
}
nfsl_ipaddr_print(elfrec, &logrec->re_ipaddr);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" \"%s\"", hostname);
(*disp->nfsl_dis_res)(elfrec, logrec->re_rpc_res, TRUE);
if (path1 != NULL) {
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" \"%s\"", path1);
} else {
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" %s", empty_name);
}
if (path2 != NULL) {
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset],
" \"%s\"", path2);
}
(*disp->nfsl_dis_args)(elfrec, logrec->re_rpc_arg);
(*disp->nfsl_dis_res)(elfrec, logrec->re_rpc_res, FALSE);
elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], "\n");
}
static void
nfsl_log_file_add(struct nfsl_log_file *elfrec,
struct nfsl_log_file **elf_listp)
{
elfrec->next = *elf_listp;
elfrec->prev = NULL;
if (*elf_listp != NULL) {
(*elf_listp)->prev = elfrec;
}
*elf_listp = elfrec;
}
static struct nfsl_log_file *
nfsl_log_file_find(struct nfsl_log_file *elfrec,
struct nfsl_log_file *elf_list)
{
struct nfsl_log_file *rec;
for (rec = elf_list; (rec != NULL) && (rec != elfrec);
rec = rec->next);
return (rec);
}
static struct nfsl_log_file *
nfsl_log_file_del(struct nfsl_log_file *elfrec,
struct nfsl_log_file **elf_listp)
{
struct nfsl_log_file *rec;
if ((rec = nfsl_log_file_find(elfrec, *elf_listp)) == NULL) {
return (NULL);
}
if (rec->prev != NULL) {
rec->prev->next = rec->next;
} else {
*elf_listp = rec->next;
}
if (rec->next != NULL) {
rec->next->prev = rec->prev;
}
return (rec);
}
static void
nfsl_log_file_free(struct nfsl_log_file *elfrec)
{
if (elfrec == NULL)
return;
if (elfrec->path != NULL)
free(elfrec->path);
if (elfrec->buf != NULL)
free(elfrec->buf);
free(elfrec);
}
void *
nfslog_open_elf_file(char *elfpath, nfslog_buffer_header *bufhdr, int *error)
{
struct nfsl_log_file *elfrec;
struct stat stat_buf;
int preverror = *error;
if ((elfrec = malloc(sizeof (*elfrec))) == NULL) {
*error = errno;
if (*error != preverror) {
syslog(LOG_ERR, gettext("nfslog_open_elf_file: %s"),
strerror(*error));
}
return (NULL);
}
bzero(elfrec, sizeof (*elfrec));
elfrec->buf = (char *)malloc(DFLT_BUFFERSIZE + DFLT_OVFSIZE);
if (elfrec->buf == NULL) {
*error = errno;
if (*error != preverror) {
syslog(LOG_ERR, gettext("nfslog_open_elf_file: %s"),
strerror(*error));
}
nfsl_log_file_free(elfrec);
return (NULL);
}
if ((elfrec->path = strdup(elfpath)) == NULL) {
*error = errno;
if (*error != preverror) {
syslog(LOG_ERR, gettext("nfslog_open_elf_file: %s"),
strerror(*error));
}
nfsl_log_file_free(elfrec);
return (NULL);
}
if ((elfrec->fp = fopen(elfpath, "a")) == NULL) {
*error = errno;
if (*error != preverror) {
syslog(LOG_ERR, gettext("Cannot open '%s': %s"),
elfpath, strerror(*error));
}
nfsl_log_file_free(elfrec);
return (NULL);
}
if (stat(elfpath, &stat_buf) == -1) {
*error = errno;
if (*error != preverror) {
syslog(LOG_ERR, gettext("Cannot stat '%s': %s"),
elfpath, strerror(*error));
}
(void) fclose(elfrec->fp);
nfsl_log_file_free(elfrec);
return (NULL);
}
nfsl_log_file_add(elfrec, &elf_file_list);
if (stat_buf.st_size == 0) {
nfsl_elf_buffer_header_print(elfrec, bufhdr);
}
if (hostname[0] == '\0') {
(void) gethostname(hostname, MAXHOSTNAMELEN);
}
return (elfrec);
}
void
nfslog_close_elf_file(void **elfcookie)
{
struct nfsl_log_file *elfrec;
if ((*elfcookie == NULL) || ((elfrec = nfsl_log_file_del(
*elfcookie, &elf_file_list)) == NULL)) {
*elfcookie = NULL;
return;
}
if (elfrec->fp != NULL) {
(void) nfsl_write_elfbuf(elfrec);
(void) fclose(elfrec->fp);
}
nfsl_log_file_free(elfrec);
*elfcookie = NULL;
}
int
nfslog_process_elf_rec(void *elfcookie, nfslog_request_record *logrec,
char *path1, char *path2)
{
struct nfsl_log_file *elfrec;
struct nfsl_proc_disp *disp;
char *progname;
if ((elfrec = nfsl_log_file_find(elfcookie, elf_file_list)) == NULL) {
return (EINVAL);
}
if (elfrec->bufoffset > DFLT_BUFFERSIZE) {
if (nfsl_write_elfbuf(elfrec) < 0) {
return (errno);
}
}
if ((disp = nfsl_find_elf_dispatch(logrec, &progname)) != NULL) {
nfsl_elf_rpc_print(elfrec, logrec, disp, progname,
path1, path2);
}
return (0);
}