#include #include #include #include "rpc-nfs.h" #include "xdr.h" #include "util.h" #include "vars.h" #define PROC_NULL 0 #define PROC_GETATTR 1 #define PROC_SETATTR 2 #define PROC_ROOT 3 #define PROC_LOOKUP 4 #define PROC_READLINK 5 #define PROC_READ 6 #define PROC_WRITECACHE 7 #define PROC_WRITE 8 #define PROC_CREATE 9 #define PROC_REMOVE 10 #define PROC_RENAME 11 #define PROC_LINK 12 #define PROC_SYMLINK 13 #define PROC_MKDIR 14 #define PROC_RMDIR 15 #define PROC_READDIR 16 #define PROC_STATFS 17 #define FHSIZE 32 #define COOKIESIZE 4 #define NFS_OK 0 #define NFSERR_PERM 1 #define NFSERR_NOENT 2 #define NFSERR_IO 5 #define NFSERR_NXIO 6 #define NFSERR_ACCES 13 #define NFSERR_EXIST 17 #define NFSERR_NODEV 19 #define NFSERR_NOTDIR 20 #define NFSERR_ISDIR 21 #define NFSERR_FBIG 27 #define NFSERR_NOSPC 28 #define NFSERR_ROFS 30 #define NFSERR_NAMETOOLONG 63 #define NFSERR_NOTEMPTY 66 #define NFSERR_DQUOT 69 #define NFSERR_STALE 70 #define NFSERR_WFLUSH 99 #define NFNON 0 #define NFREG 1 #define NFDIR 2 #define NFBLK 3 #define NFCHR 4 #define NFLNK 5 #define NFSOCK 6 #define NFBAD 7 #define NFFIFO 8 #define NFSMODE_FMT 0170000 #define NFSMODE_DIR 0040000 #define NFSMODE_CHR 0020000 #define NFSMODE_BLK 0060000 #define NFSMODE_REG 0100000 #define NFSMODE_LNK 0120000 #define NFSMODE_SOCK 0140000 #define NFSMODE_FIFO 0010000 static void dump_xdr_fh(const char *tag) { need(FHSIZE,"file handle"); printx(pkt,FHSIZE); printf("%sfile handle\n",tag); consume(FHSIZE); } static void dump_xdr_cookie(const char *tag) { need(COOKIESIZE,"cookie"); printx(pkt,COOKIESIZE); printf("%scookie\n",tag); consume(COOKIESIZE); } static void dump_xdr_timestamp(const char *tag) { unsigned int sec; unsigned int usec; need(8,"timestamp"); printx(pkt,8); sec = get32(0); usec = get32(4); consume(8); printf("%s[%u.%06u]\n",tag,sec,usec); } static void dump_xdr_sattr(const char *tag) { unsigned int mode; unsigned int uid; unsigned int gid; unsigned int size; need(32,"file attributes"); printx(pkt,4); mode = get32(0); printf("%smode\n",tag); consume(4); printx(pkt,4); uid = get32(0); printf("%suid\n",tag); consume(4); printx(pkt,4); gid = get32(0); printf("%sgid\n",tag); consume(4); printx(pkt,4); size = get32(0); printf("%ssize\n",tag); consume(4); { char *t; t = malloc(strlen(tag)+6+1); sprintf(t,"%satime ",tag); dump_xdr_timestamp(t); sprintf(t,"%smtime ",tag); dump_xdr_timestamp(t); free(t); } } static const char *nfsstatus_name(unsigned int s) { switch (s) { case NFS_OK: return("NFS_OK"); break; case NFSERR_PERM: return("NFSERR_PERM"); break; case NFSERR_NOENT: return("NFSERR_NOENT"); break; case NFSERR_IO: return("NFSERR_IO"); break; case NFSERR_NXIO: return("NFSERR_NXIO"); break; case NFSERR_ACCES: return("NFSERR_ACCES"); break; case NFSERR_EXIST: return("NFSERR_EXIST"); break; case NFSERR_NODEV: return("NFSERR_NODEV"); break; case NFSERR_NOTDIR: return("NFSERR_NOTDIR"); break; case NFSERR_ISDIR: return("NFSERR_ISDIR"); break; case NFSERR_FBIG: return("NFSERR_FBIG"); break; case NFSERR_NOSPC: return("NFSERR_NOSPC"); break; case NFSERR_ROFS: return("NFSERR_ROFS"); break; case NFSERR_NAMETOOLONG: return("NFSERR_NAMETOOLONG"); break; case NFSERR_NOTEMPTY: return("NFSERR_NOTEMPTY"); break; case NFSERR_DQUOT: return("NFSERR_DQUOT"); break; case NFSERR_STALE: return("NFSERR_STALE"); break; case NFSERR_WFLUSH: return("NFSERR_WFLUSH"); break; } return(0); } static void dump_xdr_fattr(const char *tag) { unsigned int type; unsigned int mode; unsigned int nlink; unsigned int uid; unsigned int gid; unsigned int size; unsigned int blocksize; unsigned int rdev; unsigned int blocks; unsigned int fsid; unsigned int fileid; need(17*4,"attributes"); printx(pkt,4); type = get32(0); consume(4); printf("%stype",tag); switch (type) { case NFNON: printf(" [NFNON]"); break; case NFREG: printf(" [NFREG]"); break; case NFDIR: printf(" [NFDIR]"); break; case NFBLK: printf(" [NFBLK]"); break; case NFCHR: printf(" [NFCHR]"); break; case NFLNK: printf(" [NFLNK]"); break; case NFSOCK: printf(" [NFSOCK]"); break; case NFBAD: printf(" [NFBAD]"); break; case NFFIFO: printf(" [NFFIFO]"); break; default: printf(" [unknown]"); break; } printf("\n"); printx(pkt,4); mode = get32(0); consume(4); printf("%smode",tag); switch (mode & NFSMODE_FMT) { case NFSMODE_DIR: printf(" [NFSMODE_DIR|%#o]",mode&~NFSMODE_FMT); break; case NFSMODE_CHR: printf(" [NFSMODE_CHR|%#o]",mode&~NFSMODE_FMT); break; case NFSMODE_BLK: printf(" [NFSMODE_BLK|%#o]",mode&~NFSMODE_FMT); break; case NFSMODE_REG: printf(" [NFSMODE_REG|%#o]",mode&~NFSMODE_FMT); break; case NFSMODE_LNK: printf(" [NFSMODE_LNK|%#o]",mode&~NFSMODE_FMT); break; case NFSMODE_SOCK: printf(" [NFSMODE_SOCK|%#o]",mode&~NFSMODE_FMT); break; case NFSMODE_FIFO: printf(" [NFSMODE_FIFO|%#o]",mode&~NFSMODE_FMT); break; default: printf(" [%#o]",mode); break; } printf("\n"); printx(pkt,4); nlink = get32(0); consume(4); printf("%snlink = %u\n",tag,nlink); printx(pkt,4); uid = get32(0); consume(4); printf("%suid = %u\n",tag,uid); printx(pkt,4); gid = get32(0); consume(4); printf("%sgid = %u\n",tag,gid); printx(pkt,4); size = get32(0); consume(4); printf("%ssize = %u\n",tag,size); printx(pkt,4); blocksize = get32(0); consume(4); printf("%sblocksize = %u\n",tag,blocksize); printx(pkt,4); rdev = get32(0); consume(4); printf("%srdev = %u\n",tag,rdev); printx(pkt,4); blocks = get32(0); consume(4); printf("%sblocks = %u\n",tag,blocks); printx(pkt,4); fsid = get32(0); consume(4); printf("%sfsid = %u\n",tag,fsid); printx(pkt,4); fileid = get32(0); consume(4); printf("%sfileid = %u\n",tag,fileid); { char *t; t = malloc(strlen(tag)+6+1); sprintf(t,"%satime ",tag); dump_xdr_timestamp(t); sprintf(t,"%smtime ",tag); dump_xdr_timestamp(t); sprintf(t,"%sctime ",tag); dump_xdr_timestamp(t); free(t); } } static int dump_xdr_status_ok(const char *tag) { unsigned int status; const char *ss; need(4,"NFS status"); printx(pkt,4); status = get32(0); printf("%sstatus = %u",tag,status); ss = nfsstatus_name(status); if (ss) printf(" [%s]",ss); printf("\n"); consume(4); return(status==NFS_OK); } static void dump_xdr_attrstat(const char *tag) { if (dump_xdr_status_ok(tag)) { dump_xdr_fattr(tag); } } static void dump_xdr_diropres(const char *tag) { if (dump_xdr_status_ok(tag)) { dump_xdr_fh(tag); dump_xdr_fattr(tag); } } void *dumprpc_nfs(RPCDUMP_ARGS) { switch (op) { case DO_CALL: printx(pkt,0); switch (proc) { case PROC_NULL: printf("nfs NULL request\n"); break; case PROC_GETATTR: printf("nfs GETATTR request\n"); dump_xdr_fh(""); break; case PROC_SETATTR: printf("nfs SETATTR request\n"); dump_xdr_fh(""); dump_xdr_sattr(""); break; case PROC_ROOT: printf("nfs ROOT request\n"); break; case PROC_LOOKUP: printf("nfs LOOKUP request\n"); dump_xdr_fh(""); dump_xdr_string("name "); break; case PROC_READLINK: printf("nfs READLINK request\n"); dump_xdr_fh(""); break; case PROC_READ: printf("nfs READ request\n"); { unsigned int v; dump_xdr_fh(""); need(12,"READ args"); printx(pkt,4); v = get32(0); printf("offset\n"); consume(4); printx(pkt,4); v = get32(0); printf("count\n"); consume(4); printx(pkt,4); v = get32(0); printf("totalcount\n"); consume(4); } break; case PROC_WRITECACHE: printf("nfs WRITECACHE request\n"); break; case PROC_WRITE: printf("nfs WRITE request\n"); { unsigned int v; dump_xdr_fh(""); need(12,"WRITE args"); printx(pkt,4); v = get32(0); printf("offset\n"); consume(4); printx(pkt,4); v = get32(0); printf("count\n"); consume(4); printx(pkt,4); v = get32(0); printf("totalcount\n"); consume(4); dump_limited_xdr_string("data",128,64); } break; case PROC_CREATE: printf("nfs CREATE request\n"); dump_xdr_fh("dir "); dump_xdr_string("name "); dump_xdr_sattr(""); break; case PROC_REMOVE: printf("nfs REMOVE request\n"); dump_xdr_fh("dir "); dump_xdr_string("name "); break; case PROC_RENAME: printf("nfs RENAME request\n"); dump_xdr_fh("from dir "); dump_xdr_string("from name "); dump_xdr_fh("to dir "); dump_xdr_string("to name "); break; case PROC_LINK: printf("nfs LINK request\n"); dump_xdr_fh("from "); dump_xdr_fh("to dir "); dump_xdr_string("to name "); break; case PROC_SYMLINK: printf("nfs SYMLINK request\n"); dump_xdr_fh("from dir "); dump_xdr_string("from name "); dump_xdr_string("to path "); dump_xdr_sattr(""); break; case PROC_MKDIR: printf("nfs MKDIR request\n"); dump_xdr_fh("dir "); dump_xdr_string("name "); dump_xdr_sattr(""); break; case PROC_RMDIR: printf("nfs RMDIR request\n"); dump_xdr_fh("dir "); dump_xdr_string("name "); break; case PROC_READDIR: printf("nfs READDIR request\n"); { unsigned int count; dump_xdr_fh("dir "); dump_xdr_cookie("offset "); need(4,"READDIR count"); printx(pkt,4); count = get32(0); printf("count = %u\n",count); consume(4); } break; case PROC_STATFS: printf("nfs STATFS request\n"); dump_xdr_fh(""); break; default: printf("nfs request, unknown proc %u\n",proc); break; } return(0); break; case DO_REPLY: printx(pkt,0); switch (proc) { case PROC_NULL: printf("nfs NULL reply\n"); break; case PROC_GETATTR: printf("nfs GETATTR reply\n"); dump_xdr_attrstat(""); break; case PROC_SETATTR: printf("nfs SETATTR reply\n"); dump_xdr_attrstat(""); break; case PROC_ROOT: printf("nfs ROOT reply\n"); break; case PROC_LOOKUP: printf("nfs LOOKUP reply\n"); dump_xdr_diropres(""); break; case PROC_READLINK: printf("nfs READLINK reply\n"); if (dump_xdr_status_ok("")) { dump_xdr_string(""); } break; case PROC_READ: printf("nfs READ reply\n"); if (dump_xdr_status_ok("")) { dump_xdr_fattr(""); dump_limited_xdr_string("data",128,64); } break; case PROC_WRITECACHE: printf("nfs WRITECACHE reply\n"); break; case PROC_WRITE: printf("nfs WRITE reply\n"); dump_xdr_attrstat(""); break; case PROC_CREATE: printf("nfs CREATE reply\n"); dump_xdr_diropres(""); break; case PROC_REMOVE: printf("nfs REMOVE reply\n"); dump_xdr_status_ok(""); break; case PROC_RENAME: printf("nfs RENAME reply\n"); dump_xdr_status_ok(""); break; case PROC_LINK: printf("nfs LINK reply\n"); dump_xdr_status_ok(""); break; case PROC_SYMLINK: printf("nfs SYMLINK reply\n"); dump_xdr_status_ok(""); break; case PROC_MKDIR: printf("nfs MKDIR reply\n"); dump_xdr_diropres(""); break; case PROC_RMDIR: printf("nfs RMDIR reply\n"); dump_xdr_status_ok(""); break; case PROC_READDIR: printf("nfs READDIR reply\n"); if (dump_xdr_status_ok("")) { unsigned int i; while (1) { need(4,"READDIR list boolean"); printx(pkt,4); i = get32(0); consume(4); printf("another? "); switch (i) { case 0: printf("[no]\n"); break; case 1: printf("[yes]\n"); break; default: printf("[?%d]\n",i); break; } if (i != 1) break; need(4,"READDIR fileid"); printx(pkt,4); i = get32(0); consume(4); printf("fileid = %d\n",i); dump_xdr_string("name "); dump_xdr_cookie("next entry "); } need(4,"READDIR eof boolean"); printx(pkt,4); i = get32(0); consume(4); printf("eof? "); switch (i) { case 0: printf("[no]\n"); break; case 1: printf("[yes]\n"); break; default: printf("[?%d]\n",i); break; } } break; case PROC_STATFS: printf("nfs STATFS reply\n"); if (dump_xdr_status_ok("")) { unsigned int v; need(20,"STATFS OK reply"); printx(pkt,4); v = get32(0); printf("tsize = %u\n",v); consume(4); printx(pkt,4); v = get32(0); printf("bsize = %u\n",v); consume(4); printx(pkt,4); v = get32(0); printf("blocks = %u\n",v); consume(4); printx(pkt,4); v = get32(0); printf("bfree = %u\n",v); consume(4); printx(pkt,4); v = get32(0); printf("bavail = %u\n",v); consume(4); } break; default: printf("nfs reply, unknown proc %u\n",proc); break; } break; case DO_FREE: break; } return(0); } #if 0 typedef opaque nfscookie[NFS_COOKIESIZE]; struct entry { unsigned fileid; filename name; nfscookie cookie; entry *nextentry; }; struct dirlist { entry *entries; bool eof; }; union readdirres switch (nfsstat status) { case NFS_OK: dirlist reply; default: void; }; #endif