#include <sys/types.h>
#include <sys/errno.h>
#include <sys/tiuser.h>
#include <setjmp.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/clnt.h>
#include <rpc/rpc_msg.h>
#include <string.h>
#include "snoop.h"
#include "snoop_nfs.h"
#include <sys/stat.h>
#include <rpcsvc/nfs_prot.h>
static char *perms(int);
static char *filetype(int);
static char *sum_readdirres(void);
static void detail_readdirres(void);
static void detail_diroparg(void);
static void nfscall2(int);
static void nfsreply2(int);
static void detail_mode(int);
static void detail_sattr(void);
static void interpret_nfs2(int, int, int, int, int, char *, int);
extern jmp_buf xdr_err;
static char *procnames_short[] = {
"NULL2",
"GETATTR2",
"SETATTR2",
"ROOT2",
"LOOKUP2",
"READLINK2",
"READ2",
"WRITECACHE2",
"WRITE2",
"CREATE2",
"REMOVE2",
"RENAME2",
"LINK2",
"SYMLINK2",
"MKDIR2",
"RMDIR2",
"READDIR2",
"STATFS2",
};
static char *procnames_long[] = {
"Null procedure",
"Get file attributes",
"Set file attributes",
"Get root filehandle",
"Look up file name",
"Read from symbolic link",
"Read from file",
"Write to cache",
"Write to file",
"Create file",
"Remove file",
"Rename",
"Link",
"Make symbolic link",
"Make directory",
"Remove directory",
"Read from directory",
"Get filesystem attributes",
};
#define MAXPROC 17
void
interpret_nfs(flags, type, xid, vers, proc, data, len)
int flags, type, xid, vers, proc;
char *data;
int len;
{
if (vers == 2) {
interpret_nfs2(flags, type, xid, vers, proc, data, len);
return;
}
if (vers == 3) {
interpret_nfs3(flags, type, xid, vers, proc, data, len);
return;
}
if (vers == 4) {
interpret_nfs4(flags, type, xid, vers, proc, data, len);
return;
}
}
static void
interpret_nfs2(flags, type, xid, vers, proc, data, len)
int flags, type, xid, vers, proc;
char *data;
int len;
{
char *line;
char buff[NFS_MAXPATHLEN + 1];
int off, sz;
char *fh;
if (proc < 0 || proc > MAXPROC)
return;
if (flags & F_SUM) {
line = get_sum_line();
if (type == CALL) {
(void) sprintf(line,
"NFS C %s",
procnames_short[proc]);
line += strlen(line);
switch (proc) {
case NFSPROC_GETATTR:
case NFSPROC_READLINK:
case NFSPROC_STATFS:
case NFSPROC_SETATTR:
(void) sprintf(line, sum_nfsfh());
break;
case NFSPROC_LOOKUP:
case NFSPROC_REMOVE:
case NFSPROC_RMDIR:
case NFSPROC_CREATE:
case NFSPROC_MKDIR:
fh = sum_nfsfh();
(void) sprintf(line, "%s %s",
fh,
getxdr_string(buff, NFS_MAXNAMLEN));
break;
case NFSPROC_WRITE:
fh = sum_nfsfh();
(void) getxdr_long();
off = getxdr_long();
(void) getxdr_long();
sz = getxdr_long();
(void) sprintf(line, "%s at %d for %d",
fh, off, sz);
break;
case NFSPROC_RENAME:
fh = sum_nfsfh();
(void) sprintf(line, "%s %s",
fh,
getxdr_string(buff, NFS_MAXNAMLEN));
line += strlen(line);
fh = sum_nfsfh();
(void) sprintf(line, " to%s %s",
fh,
getxdr_string(buff, NFS_MAXNAMLEN));
break;
case NFSPROC_LINK:
fh = sum_nfsfh();
(void) sprintf(line, "%s", fh);
line += strlen(line);
fh = sum_nfsfh();
(void) sprintf(line, " to%s %s",
fh,
getxdr_string(buff, NFS_MAXNAMLEN));
break;
case NFSPROC_SYMLINK:
fh = sum_nfsfh();
(void) sprintf(line, "%s %s",
fh,
getxdr_string(buff, NFS_MAXNAMLEN));
line += strlen(line);
(void) sprintf(line, " to %s",
getxdr_string(buff, NFS_MAXPATHLEN));
break;
case NFSPROC_READDIR:
fh = sum_nfsfh();
(void) sprintf(line, "%s Cookie=%lu",
fh, getxdr_u_long());
break;
case NFSPROC_READ:
fh = sum_nfsfh();
off = getxdr_long();
sz = getxdr_long();
(void) sprintf(line, "%s at %d for %d",
fh, off, sz);
break;
default:
break;
}
check_retransmit(line, (ulong_t)xid);
} else {
(void) sprintf(line, "NFS R %s ",
procnames_short[proc]);
line += strlen(line);
switch (proc) {
case NFSPROC_CREATE:
case NFSPROC_MKDIR:
case NFSPROC_LOOKUP:
if (sum_nfsstat(line) == 0) {
line += strlen(line);
(void) sprintf(line, sum_nfsfh());
}
break;
case NFSPROC_READLINK:
if (sum_nfsstat(line) == 0) {
line += strlen(line);
(void) sprintf(line, " (Path=%s)",
getxdr_string(buff,
NFS_MAXPATHLEN));
}
break;
case NFSPROC_GETATTR:
case NFSPROC_SYMLINK:
case NFSPROC_STATFS:
case NFSPROC_SETATTR:
case NFSPROC_REMOVE:
case NFSPROC_RMDIR:
case NFSPROC_WRITE:
case NFSPROC_RENAME:
case NFSPROC_LINK:
(void) sum_nfsstat(line);
break;
case NFSPROC_READDIR:
if (sum_nfsstat(line) == 0) {
line += strlen(line);
(void) strcat(line, sum_readdirres());
}
break;
case NFSPROC_READ:
if (sum_nfsstat(line) == 0) {
line += strlen(line);
xdr_skip(68);
(void) sprintf(line, " (%ld bytes)",
getxdr_long());
}
break;
default:
break;
}
}
}
if (flags & F_DTAIL) {
show_header("NFS: ", "Sun NFS", len);
show_space();
(void) sprintf(get_line(0, 0), "Proc = %d (%s)",
proc, procnames_long[proc]);
if (type == CALL)
nfscall2(proc);
else
nfsreply2(proc);
show_trailer();
}
}
static void
nfscall2(proc)
int proc;
{
switch (proc) {
case NFSPROC_GETATTR:
case NFSPROC_READLINK:
case NFSPROC_STATFS:
detail_nfsfh();
break;
case NFSPROC_SETATTR:
detail_nfsfh();
detail_sattr();
break;
case NFSPROC_LOOKUP:
case NFSPROC_REMOVE:
case NFSPROC_RMDIR:
detail_diroparg();
break;
case NFSPROC_MKDIR:
case NFSPROC_CREATE:
detail_diroparg();
detail_sattr();
break;
case NFSPROC_WRITE:
detail_nfsfh();
(void) getxdr_long();
(void) showxdr_long("Offset = %d");
(void) getxdr_long();
(void) showxdr_long("(%d bytes(s) of data)");
break;
case NFSPROC_RENAME:
detail_diroparg();
detail_diroparg();
break;
case NFSPROC_LINK:
detail_nfsfh();
detail_diroparg();
break;
case NFSPROC_SYMLINK:
detail_diroparg();
(void) showxdr_string(NFS_MAXPATHLEN, "Path = %s");
detail_sattr();
break;
case NFSPROC_READDIR:
detail_nfsfh();
(void) showxdr_u_long("Cookie = %lu");
(void) showxdr_long("Count = %d");
break;
case NFSPROC_READ:
detail_nfsfh();
(void) showxdr_long("Offset = %d");
(void) showxdr_long("Count = %d");
break;
default:
break;
}
}
static void
nfsreply2(proc)
int proc;
{
switch (proc) {
case NFSPROC_GETATTR:
case NFSPROC_SETATTR:
case NFSPROC_WRITE:
if (detail_nfsstat() == 0) {
detail_fattr();
}
break;
case NFSPROC_LOOKUP:
case NFSPROC_CREATE:
case NFSPROC_MKDIR:
if (detail_nfsstat() == 0) {
detail_nfsfh();
detail_fattr();
}
break;
case NFSPROC_READLINK:
if (detail_nfsstat() == 0) {
(void) showxdr_string(NFS_MAXPATHLEN, "Path = %s");
}
break;
case NFSPROC_READ:
if (detail_nfsstat() == 0) {
detail_fattr();
(void) showxdr_long("(%d byte(s) of data)");
}
break;
case NFSPROC_REMOVE:
case NFSPROC_RENAME:
case NFSPROC_LINK:
case NFSPROC_SYMLINK:
case NFSPROC_RMDIR:
detail_nfsstat();
break;
case NFSPROC_READDIR:
if (detail_nfsstat() == 0)
detail_readdirres();
break;
case NFSPROC_STATFS:
if (detail_nfsstat() == 0) {
(void) showxdr_long("Transfer size = %d");
(void) showxdr_long("Block size = %d");
(void) showxdr_long("Total blocks = %d");
(void) showxdr_long("Free blocks = %d");
(void) showxdr_long("Available blocks = %d");
}
break;
default:
break;
}
}
static void
detail_diroparg()
{
detail_nfsfh();
(void) showxdr_string(NFS_MAXPATHLEN, "File name = %s");
}
static char *
statusmsg(status)
ulong_t status;
{
switch (status) {
case NFS_OK: return ("OK");
case NFSERR_PERM: return ("Not owner");
case NFSERR_NOENT: return ("No such file or directory");
case NFSERR_IO: return ("I/O error");
case NFSERR_NXIO: return ("No such device or address");
case NFSERR_ACCES: return ("Permission denied");
case NFSERR_EXIST: return ("File exists");
case NFSERR_XDEV: return ("Cross-device link");
case NFSERR_NODEV: return ("No such device");
case NFSERR_NOTDIR: return ("Not a directory");
case NFSERR_ISDIR: return ("Is a directory");
case NFSERR_INVAL: return ("Invalid argument");
case NFSERR_FBIG: return ("File too large");
case NFSERR_NOSPC: return ("No space left on device");
case NFSERR_ROFS: return ("Read-only file system");
case NFSERR_OPNOTSUPP: return ("Operation not supported");
case NFSERR_NAMETOOLONG: return ("File name too long");
case NFSERR_NOTEMPTY: return ("Directory not empty");
case NFSERR_DQUOT: return ("Disc quota exceeded");
case NFSERR_STALE: return ("Stale NFS file handle");
case NFSERR_REMOTE: return ("Object is remote");
case NFSERR_WFLUSH: return ("write cache flushed");
default: return ("(unknown error)");
}
}
int
sum_nfsstat(line)
char *line;
{
ulong_t status;
status = getxdr_long();
(void) strcpy(line, statusmsg(status));
return (status);
}
int
detail_nfsstat()
{
ulong_t status;
int pos;
pos = getxdr_pos();
status = getxdr_long();
(void) sprintf(get_line(pos, getxdr_pos()),
"Status = %lu (%s)",
status, statusmsg(status));
return ((int)status);
}
int
sum_filehandle(len)
int len;
{
int i, l;
int fh = 0;
for (i = 0; i < len; i += 4) {
l = getxdr_long();
fh ^= (l >> 16) ^ l;
}
return (fh);
}
char *
sum_nfsfh()
{
int fh;
static char buff[16];
fh = sum_filehandle(NFS_FHSIZE);
(void) sprintf(buff, " FH=%04X", fh & 0xFFFF);
return (buff);
}
void
detail_nfsfh()
{
int pos;
int fh;
pos = getxdr_pos();
fh = sum_filehandle(NFS_FHSIZE);
setxdr_pos(pos);
(void) sprintf(get_line(0, 0), "File handle = [%04X]", fh & 0xFFFF);
(void) showxdr_hex(NFS_FHSIZE, " %s");
}
static void
detail_mode(mode)
int mode;
{
char *str;
switch (mode & S_IFMT) {
case S_IFDIR: str = "Directory"; break;
case S_IFCHR: str = "Character"; break;
case S_IFBLK: str = "Block"; break;
case S_IFREG: str = "Regular file"; break;
case S_IFLNK: str = "Link"; break;
case S_IFSOCK: str = "Socket"; break;
case S_IFIFO: str = "Fifo"; break;
default: str = "?"; break;
}
(void) sprintf(get_line(0, 0), "Mode = 0%o", mode);
(void) sprintf(get_line(0, 0), " Type = %s", str);
(void) sprintf(get_line(0, 0),
" Setuid = %d, Setgid = %d, Sticky = %d",
(mode & S_ISUID) != 0,
(mode & S_ISGID) != 0,
(mode & S_ISVTX) != 0);
(void) sprintf(get_line(0, 0), " Owner's permissions = %s",
perms(mode >> 6 & 0x7));
(void) sprintf(get_line(0, 0), " Group's permissions = %s",
perms(mode >> 3 & 0x7));
(void) sprintf(get_line(0, 0), " Other's permissions = %s",
perms(mode & 0x7));
}
void
detail_fattr()
{
int fltype, mode, nlinks, uid, gid, size, blksz;
int rdev, blocks, fsid, fileid;
fltype = getxdr_long();
mode = getxdr_long();
nlinks = getxdr_long();
uid = getxdr_long();
gid = getxdr_long();
size = getxdr_long();
blksz = getxdr_long();
rdev = getxdr_long();
blocks = getxdr_long();
fsid = getxdr_long();
fileid = getxdr_long();
(void) sprintf(get_line(0, 0),
"File type = %d (%s)",
fltype, filetype(fltype));
detail_mode(mode);
(void) sprintf(get_line(0, 0),
"Link count = %d, UID = %d, GID = %d, Rdev = 0x%x",
nlinks, uid, gid, rdev);
(void) sprintf(get_line(0, 0),
"File size = %d, Block size = %d, No. of blocks = %d",
size, blksz, blocks);
(void) sprintf(get_line(0, 0),
"File system id = %d, File id = %d",
fsid, fileid);
(void) showxdr_date("Access time = %s");
(void) showxdr_date("Modification time = %s");
(void) showxdr_date("Inode change time = %s");
}
static void
detail_sattr()
{
int mode;
mode = getxdr_long();
detail_mode(mode);
(void) showxdr_long("UID = %d");
(void) showxdr_long("GID = %d");
(void) showxdr_long("Size = %d");
(void) showxdr_date("Access time = %s");
(void) showxdr_date("Modification time = %s");
}
static char *
filetype(n)
int n;
{
switch (n) {
case NFREG: return ("Regular File");
case NFDIR: return ("Directory");
case NFBLK: return ("Block special");
case NFCHR: return ("Character special");
case NFLNK: return ("Symbolic Link");
default: return ("?");
}
}
static char *
perms(n)
int n;
{
static char buff[4];
buff[0] = n & 4 ? 'r' : '-';
buff[1] = n & 2 ? 'w' : '-';
buff[2] = n & 1 ? 'x' : '-';
buff[3] = '\0';
return (buff);
}
static char *
sum_readdirres()
{
static char buff[NFS_MAXNAMLEN + 1];
int entries = 0;
if (setjmp(xdr_err)) {
(void) sprintf(buff, " %d+ entries (incomplete)", entries);
return (buff);
}
while (getxdr_long()) {
entries++;
(void) getxdr_long();
(void) getxdr_string(buff, NFS_MAXNAMLEN);
(void) getxdr_u_long();
}
(void) sprintf(buff, " %d entries (%s)",
entries,
getxdr_long() ? "No more" : "More");
return (buff);
}
static void
detail_readdirres()
{
ulong_t fileid, cookie;
int entries = 0;
char *name;
char buff[NFS_MAXNAMLEN + 1];
(void) sprintf(get_line(0, 0), " File id Cookie Name");
if (setjmp(xdr_err)) {
(void) sprintf(get_line(0, 0),
" %d+ entries. (Frame is incomplete)",
entries);
return;
}
while (getxdr_long()) {
entries++;
fileid = getxdr_long();
name = (char *)getxdr_string(buff, NFS_MAXNAMLEN);
cookie = getxdr_u_long();
(void) sprintf(get_line(0, 0),
" %7lu %7lu %s",
fileid, cookie, name);
}
(void) sprintf(get_line(0, 0), " %d entries", entries);
(void) showxdr_long("EOF = %d");
}
void
skip_fattr()
{
xdr_skip(17 * 4);
}