print-nfs.c
来自「TCPDUMP的C语言源代码,是在数据链路层的应用」· C语言 代码 · 共 1,821 行 · 第 1/3 页
C
1,821 行
if (v3) { TCHECK(dp[2]); printf(" %u (%u) bytes @ %" PRIu64, EXTRACT_32BITS(&dp[4]), EXTRACT_32BITS(&dp[2]), EXTRACT_64BITS(&dp[0])); if (vflag) { dp += 3; TCHECK(dp[0]); printf(" <%s>", tok2str(nfsv3_writemodes, NULL, EXTRACT_32BITS(dp))); } } else { TCHECK(dp[3]); printf(" %u (%u) bytes @ %u (%u)", EXTRACT_32BITS(&dp[3]), EXTRACT_32BITS(&dp[2]), EXTRACT_32BITS(&dp[1]), EXTRACT_32BITS(&dp[0])); } return; } break; case NFSPROC_CREATE: printf(" create"); if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp, v3) != NULL) return; break; case NFSPROC_MKDIR: printf(" mkdir"); if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp, v3) != 0) return; break; case NFSPROC_SYMLINK: printf(" symlink"); if ((dp = parsereq(rp, length)) != 0 && (dp = parsefhn(dp, v3)) != 0) { fputs(" ->", stdout); if (v3 && (dp = parse_sattr3(dp, &sa3)) == 0) break; if (parsefn(dp) == 0) break; if (v3 && vflag) print_sattr3(&sa3, vflag); return; } break; case NFSPROC_MKNOD: printf(" mknod"); if ((dp = parsereq(rp, length)) != 0 && (dp = parsefhn(dp, v3)) != 0) { TCHECK(*dp); type = (nfs_type)EXTRACT_32BITS(dp); dp++; if ((dp = parse_sattr3(dp, &sa3)) == 0) break; printf(" %s", tok2str(type2str, "unk-ft %d", type)); if (vflag && (type == NFCHR || type == NFBLK)) { TCHECK(dp[1]); printf(" %u/%u", EXTRACT_32BITS(&dp[0]), EXTRACT_32BITS(&dp[1])); dp += 2; } if (vflag) print_sattr3(&sa3, vflag); return; } break; case NFSPROC_REMOVE: printf(" remove"); if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp, v3) != NULL) return; break; case NFSPROC_RMDIR: printf(" rmdir"); if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp, v3) != NULL) return; break; case NFSPROC_RENAME: printf(" rename"); if ((dp = parsereq(rp, length)) != NULL && (dp = parsefhn(dp, v3)) != NULL) { fputs(" ->", stdout); if (parsefhn(dp, v3) != NULL) return; } break; case NFSPROC_LINK: printf(" link"); if ((dp = parsereq(rp, length)) != NULL && (dp = parsefh(dp, v3)) != NULL) { fputs(" ->", stdout); if (parsefhn(dp, v3) != NULL) return; } break; case NFSPROC_READDIR: printf(" readdir"); if ((dp = parsereq(rp, length)) != NULL && (dp = parsefh(dp, v3)) != NULL) { if (v3) { TCHECK(dp[4]); /* * We shouldn't really try to interpret the * offset cookie here. */ printf(" %u bytes @ %" PRId64, EXTRACT_32BITS(&dp[4]), EXTRACT_64BITS(&dp[0])); if (vflag) printf(" verf %08x%08x", dp[2], dp[3]); } else { TCHECK(dp[1]); /* * Print the offset as signed, since -1 is * common, but offsets > 2^31 aren't. */ printf(" %u bytes @ %d", EXTRACT_32BITS(&dp[1]), EXTRACT_32BITS(&dp[0])); } return; } break; case NFSPROC_READDIRPLUS: printf(" readdirplus"); if ((dp = parsereq(rp, length)) != NULL && (dp = parsefh(dp, v3)) != NULL) { TCHECK(dp[4]); /* * We don't try to interpret the offset * cookie here. */ printf(" %u bytes @ %" PRId64, EXTRACT_32BITS(&dp[4]), EXTRACT_64BITS(&dp[0])); if (vflag) { TCHECK(dp[5]); printf(" max %u verf %08x%08x", EXTRACT_32BITS(&dp[5]), dp[2], dp[3]); } return; } break; case NFSPROC_FSSTAT: printf(" fsstat"); if ((dp = parsereq(rp, length)) != NULL && parsefh(dp, v3) != NULL) return; break; case NFSPROC_FSINFO: printf(" fsinfo"); if ((dp = parsereq(rp, length)) != NULL && parsefh(dp, v3) != NULL) return; break; case NFSPROC_PATHCONF: printf(" pathconf"); if ((dp = parsereq(rp, length)) != NULL && parsefh(dp, v3) != NULL) return; break; case NFSPROC_COMMIT: printf(" commit"); if ((dp = parsereq(rp, length)) != NULL && (dp = parsefh(dp, v3)) != NULL) { TCHECK(dp[2]); printf(" %u bytes @ %" PRIu64, EXTRACT_32BITS(&dp[2]), EXTRACT_64BITS(&dp[0])); return; } break; default: printf(" proc-%u", EXTRACT_32BITS(&rp->rm_call.cb_proc)); return; }trunc: if (!nfserr) fputs(" [|nfs]", stdout);}/* * Print out an NFS file handle. * We assume packet was not truncated before the end of the * file handle pointed to by dp. * * Note: new version (using portable file-handle parser) doesn't produce * generation number. It probably could be made to do that, with some * additional hacking on the parser code. */static voidnfs_printfh(register const u_int32_t *dp, const u_int len){ my_fsid fsid; ino_t ino; const char *sfsname = NULL; char *spacep; if (uflag) { u_int i; char const *sep = ""; printf(" fh["); for (i=0; i<len; i++) { (void)printf("%s%x", sep, dp[i]); sep = ":"; } printf("]"); return; } Parse_fh((const u_char *)dp, len, &fsid, &ino, NULL, &sfsname, 0); if (sfsname) { /* file system ID is ASCII, not numeric, for this server OS */ static char temp[NFSX_V3FHMAX+1]; /* Make sure string is null-terminated */ strncpy(temp, sfsname, NFSX_V3FHMAX); temp[sizeof(temp) - 1] = '\0'; /* Remove trailing spaces */ spacep = strchr(temp, ' '); if (spacep) *spacep = '\0'; (void)printf(" fh %s/", temp); } else { (void)printf(" fh %d,%d/", fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor); } if(fsid.Fsid_dev.Minor == 257) /* Print the undecoded handle */ (void)printf("%s", fsid.Opaque_Handle); else (void)printf("%ld", (long) ino);}/* * Maintain a small cache of recent client.XID.server/proc pairs, to allow * us to match up replies with requests and thus to know how to parse * the reply. */struct xid_map_entry { u_int32_t xid; /* transaction ID (net order) */ int ipver; /* IP version (4 or 6) */#ifdef INET6 struct in6_addr client; /* client IP address (net order) */ struct in6_addr server; /* server IP address (net order) */#else struct in_addr client; /* client IP address (net order) */ struct in_addr server; /* server IP address (net order) */#endif u_int32_t proc; /* call proc number (host order) */ u_int32_t vers; /* program version (host order) */};/* * Map entries are kept in an array that we manage as a ring; * new entries are always added at the tail of the ring. Initially, * all the entries are zero and hence don't match anything. */#define XIDMAPSIZE 64struct xid_map_entry xid_map[XIDMAPSIZE];int xid_map_next = 0;int xid_map_hint = 0;static intxid_map_enter(const struct sunrpc_msg *rp, const u_char *bp){ struct ip *ip = NULL;#ifdef INET6 struct ip6_hdr *ip6 = NULL;#endif struct xid_map_entry *xmep; if (!TTEST(rp->rm_call.cb_vers)) return (0); switch (IP_V((struct ip *)bp)) { case 4: ip = (struct ip *)bp; break;#ifdef INET6 case 6: ip6 = (struct ip6_hdr *)bp; break;#endif default: return (1); } xmep = &xid_map[xid_map_next]; if (++xid_map_next >= XIDMAPSIZE) xid_map_next = 0; xmep->xid = rp->rm_xid; if (ip) { xmep->ipver = 4; memcpy(&xmep->client, &ip->ip_src, sizeof(ip->ip_src)); memcpy(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst)); }#ifdef INET6 else if (ip6) { xmep->ipver = 6; memcpy(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src)); memcpy(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst)); }#endif xmep->proc = EXTRACT_32BITS(&rp->rm_call.cb_proc); xmep->vers = EXTRACT_32BITS(&rp->rm_call.cb_vers); return (1);}/* * Returns 0 and puts NFSPROC_xxx in proc return and * version in vers return, or returns -1 on failure */static intxid_map_find(const struct sunrpc_msg *rp, const u_char *bp, u_int32_t *proc, u_int32_t *vers){ int i; struct xid_map_entry *xmep; u_int32_t xid = rp->rm_xid; struct ip *ip = (struct ip *)bp;#ifdef INET6 struct ip6_hdr *ip6 = (struct ip6_hdr *)bp;#endif int cmp; /* Start searching from where we last left off */ i = xid_map_hint; do { xmep = &xid_map[i]; cmp = 1; if (xmep->ipver != IP_V(ip) || xmep->xid != xid) goto nextitem; switch (xmep->ipver) { case 4: if (memcmp(&ip->ip_src, &xmep->server, sizeof(ip->ip_src)) != 0 || memcmp(&ip->ip_dst, &xmep->client, sizeof(ip->ip_dst)) != 0) { cmp = 0; } break;#ifdef INET6 case 6: if (memcmp(&ip6->ip6_src, &xmep->server, sizeof(ip6->ip6_src)) != 0 || memcmp(&ip6->ip6_dst, &xmep->client, sizeof(ip6->ip6_dst)) != 0) { cmp = 0; } break;#endif default: cmp = 0; break; } if (cmp) { /* match */ xid_map_hint = i; *proc = xmep->proc; *vers = xmep->vers; return 0; } nextitem: if (++i >= XIDMAPSIZE) i = 0; } while (i != xid_map_hint); /* search failed */ return (-1);}/* * Routines for parsing reply packets *//* * Return a pointer to the beginning of the actual results. * If the packet was truncated, return 0. */static const u_int32_t *parserep(register const struct sunrpc_msg *rp, register u_int length){ register const u_int32_t *dp; u_int len; enum sunrpc_accept_stat astat; /* * Portability note: * Here we find the address of the ar_verf credentials. * Originally, this calculation was * dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf * On the wire, the rp_acpt field starts immediately after * the (32 bit) rp_stat field. However, rp_acpt (which is a * "struct accepted_reply") contains a "struct opaque_auth", * whose internal representation contains a pointer, so on a * 64-bit machine the compiler inserts 32 bits of padding * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use * the internal representation to parse the on-the-wire * representation. Instead, we skip past the rp_stat field, * which is an "enum" and so occupies one 32-bit word. */ dp = ((const u_int32_t *)&rp->rm_reply) + 1; TCHECK(dp[1]); len = EXTRACT_32BITS(&dp[1]); if (len >= length) return (NULL); /* * skip past the ar_verf credentials. */ dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t); TCHECK2(dp[0], 0); /* * now we can check the ar_stat field */ astat = (enum sunrpc_accept_stat) EXTRACT_32BITS(dp); switch (astat) { case SUNRPC_SUCCESS: break; case SUNRPC_PROG_UNAVAIL: printf(" PROG_UNAVAIL"); nfserr = 1; /* suppress trunc string */ return (NULL); case SUNRPC_PROG_MISMATCH: printf(" PROG_MISMATCH"); nfserr = 1; /* suppress trunc string */ return (NULL); case SUNRPC_PROC_UNAVAIL: printf(" PROC_UNAVAIL"); nfserr = 1; /* suppress trunc string */ return (NULL); case SUNRPC_GARBAGE_ARGS: printf(" GARBAGE_ARGS"); nfserr = 1; /* suppress trunc string */ return (NULL); case SUNRPC_SYSTEM_ERR: printf(" SYSTEM_ERR"); nfserr = 1; /* suppress trunc string */ return (NULL); default: printf(" ar_stat %d", astat); nfserr = 1; /* suppress trunc string */ return (NULL); } /* successful return */ TCHECK2(*dp, sizeof(astat)); return ((u_int32_t *) (sizeof(astat) + ((char *)dp)));trunc: return (0);}static const u_int32_t *parsestatus(const u_int32_t *dp, int *er){ int errnum; TCHECK(dp[0]); errnum = EXTRACT_32BITS(&dp[0]); if (er) *er = errnum; if (errnum != 0) { if (!qflag) printf(" ERROR: %s", tok2str(status2str, "unk %d", errnum)); nfserr = 1; } return (dp + 1);trunc: return NULL;}static const u_int32_t *parsefattr(const u_int32_t *dp, int verbose, int v3){ const struct nfs_fattr *fap; fap = (const struct nfs_fattr *)dp; TCHECK(fap->fa_gid); if (verbose) { printf(" %s %o ids %d/%d", tok2str(type2str, "unk-ft %d ", EXTRACT_32BITS(&fap->fa_type)), EXTRACT_32BITS(&fap->fa_mode), EXTRACT_32BITS(&fap->fa_uid), EXTRACT_32BITS(&fap->fa_gid)); if (v3) { TCHECK(fap->fa3_size); printf(" sz %" PRIu64, EXTRACT_64BITS((u_int32_t *)&fap->fa3_size)); } else { TCHECK(fap->fa2_size); printf(" sz %d", EXTRACT_32BITS(&fap->fa2_size)); } } /* print lots more stuff */ if (verbose > 1) { if (v3) { TCHECK(fap->fa3_ctime); printf(" nlink %d rdev %d/%d", EXTRACT_32BITS(&fap->fa_nlink), EXTRACT_32BITS(&fap->fa3_rdev.specdata1), EXTRACT_32BITS(&fap->fa3_rdev.specdata2)); printf(" fsid %" PRIx64, EXTRACT_64BITS((u_int32_t *)&fap->fa3_fsid)); printf(" fileid %" PRIx64, EXTRACT_64BITS((u_int32_t *)&fap->fa3_fileid)); printf(" a/m/ctime %u.%06u", EXTRACT_32BITS(&fap->fa3_atime.nfsv3_sec), EXTRACT_32BITS(&fap->fa3_atime.nfsv3_nsec)); printf(" %u.%06u", EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_sec), EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_nsec)); printf(" %u.%06u", EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_sec), EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_nsec)); } else { TCHECK(fap->fa2_ctime); printf(" nlink %d rdev %x fsid %x nodeid %x a/m/ctime", EXTRACT_32BITS(&fap->fa_nlink), EXTRACT_32BITS(&fap->fa2_rdev), EXTRACT_32BITS(&fap->fa2_fsid), EXTRACT_32BITS(&fap->fa2_fileid)); printf(" %u.%06u", EXTRACT_32BITS(&fap->fa2_atime.nfsv2_sec), EXTRACT_32BITS(&fap->fa2_atime.nfsv2_usec)); printf(" %u.%06u", EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_sec), EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_usec)); printf(" %u.%06u", EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_sec), EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_usec)); } } return ((const u_int32_t *)((unsigned char *)dp + (v3 ? NFSX_V3FATTR : NFSX_V2FATTR)));trunc: return (NULL);}static intparseattrstat(const u_int32_t *dp, int verbose, int v3){ int er; dp = parsestatus(dp, &er); if (dp == NULL) return (0); if (er) return (1); return (parsefattr(dp, verbose, v3) != NULL);}static intparsediropres(const u_int32_t *dp){ int er; if (!(dp = parsestatus(dp, &er))) return (0); if (er) return (1); dp = parsefh(dp, 0); if (dp == NULL) return (0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?