>Number: 1540
>Category: system
>Synopsis: tcpdump incorrectly print port numbers when parsing NFS packets.
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bugs
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Dec 2 12:30:01 MST 2000
>Last-Modified:
>Originator: Grigoriy Orlov
>Organization:
>Release: 2.8-current
>Environment:
System : OpenBSD 2.8-current 20.11.2000
Architecture: OpenBSD.i386
Machine : i686
>Description:
tcpdump incorrectly print port numbers for nfs packets.
Part of "tcpdump -n" output from mount session:
20:36:04.468431 x.x.x.x.938 > y.y.y.y.111: udp 56
20:36:04.468482 y.y.y.y.111 > x.x.x.x.938: udp 28
20:36:04.469588 x.x.x.x.3a2f2a94 > y.y.y.y.801: 40 null
20:36:04.469645 y.y.y.y.801 > x.x.x.x.3a2f2a94: reply ok 24 null
801 is nfs port in hex (0x0801 = 2049)
3a2f2a94 is xid - transaction identifier.
The same part of "tcpdump -n" output from patched tcpdump:
22:17:02.144416 x.x.x.x.907 > y.y.y.y.111: udp 56
22:17:02.144465 y.y.y.y.111 > x.x.x.x.907: udp 28
22:17:02.145569 x.x.x.x.908 > y.y.y.y.2049: xid 0x3a2c44ff 40 null
22:17:02.145626 y.y.y.y.2049 > x.x.x.x.908: xid 0x3a2c44ff reply ok 24 null
>How-To-Repeat:
run "tcpdump -n" and mount NFS-exported partition.
>Fix:
Index: print-nfs.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-nfs.c,v
retrieving revision 1.8
diff -u -r1.8 print-nfs.c
--- print-nfs.c 2000/10/03 14:31:58 1.8
+++ print-nfs.c 2000/12/02 17:19:24
@@ -75,24 +75,9 @@
rp = (const struct rpc_msg *)bp;
ip = (const struct ip *)bp2;
- if (!nflag)
- (void)printf("%s.nfs > %s.%x: reply %s %d",
- ipaddr_string(&ip->ip_src),
- ipaddr_string(&ip->ip_dst),
- (u_int32_t)ntohl(rp->rm_xid),
- ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED?
- "ok":"ERR",
- length);
- else
- (void)printf("%s.%x > %s.%x: reply %s %d",
- ipaddr_string(&ip->ip_src),
- NFS_PORT,
- ipaddr_string(&ip->ip_dst),
- (u_int32_t)ntohl(rp->rm_xid),
- ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED?
- "ok":"ERR",
- length);
-
+ printf("xid 0x%x reply %s %d", (u_int32_t)ntohl(rp->rm_xid),
+ ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED ? "ok":"ERR",
+ length);
if (xid_map_find(rp, ip, &proc))
interp_reply(rp, proc, length);
}
@@ -198,19 +183,7 @@
nfserr = 0; /* assume no error */
rp = (const struct rpc_msg *)bp;
ip = (const struct ip *)bp2;
- if (!nflag)
- (void)printf("%s.%x > %s.nfs: %d",
- ipaddr_string(&ip->ip_src),
- (u_int32_t)ntohl(rp->rm_xid),
- ipaddr_string(&ip->ip_dst),
- length);
- else
- (void)printf("%s.%x > %s.%x: %d",
- ipaddr_string(&ip->ip_src),
- (u_int32_t)ntohl(rp->rm_xid),
- ipaddr_string(&ip->ip_dst),
- NFS_PORT,
- length);
+ printf("xid 0x%x %d", (u_int32_t)ntohl(rp->rm_xid), length);
xid_map_enter(rp, ip); /* record proc number for later on */
Index: print-sunrpc.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-sunrpc.c,v
retrieving revision 1.9
diff -u -r1.9 print-sunrpc.c
--- print-sunrpc.c 2000/10/03 14:31:58 1.9
+++ print-sunrpc.c 2000/12/02 17:19:25
@@ -80,19 +80,7 @@
rp = (struct rpc_msg *)bp;
ip = (struct ip *)bp2;
- if (!nflag)
- (void)printf("%s.%x > %s.sunrpc: %d",
- ipaddr_string(&ip->ip_src),
- (u_int32_t)ntohl(rp->rm_xid),
- ipaddr_string(&ip->ip_dst),
- length);
- else
- (void)printf("%s.%x > %s.%x: %d",
- ipaddr_string(&ip->ip_src),
- (u_int32_t)ntohl(rp->rm_xid),
- ipaddr_string(&ip->ip_dst),
- PMAPPORT,
- length);
+ printf("xid 0x%x %d", (u_int32_t)ntohl(rp->rm_xid), length);
printf(" %s", tok2str(proc2str, " proc #%u",
(u_int32_t)ntohl(rp->rm_call.cb_proc)));
x = ntohl(rp->rm_call.cb_rpcvers);
Index: print-tcp.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-tcp.c,v
retrieving revision 1.12
diff -u -r1.12 print-tcp.c
--- print-tcp.c 2000/10/03 14:21:56 1.12
+++ print-tcp.c 2000/12/02 17:19:25
@@ -205,26 +205,6 @@
urp = ntohs(tp->th_urp);
hlen = tp->th_off * 4;
- /*
- * If data present and NFS port used, assume NFS.
- * Pass offset of data plus 4 bytes for RPC TCP msg length
- * to NFS print routines.
- */
- if (!qflag) {
- u_int len = length - hlen;
- if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend &&
- dport == NFS_PORT) {
- nfsreq_print((u_char *)tp + hlen + 4, len,
- (u_char *)ip);
- return;
- }
- else if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend &&
- sport == NFS_PORT) {
- nfsreply_print((u_char *)tp + hlen + 4, len,
- (u_char *)ip);
- return;
- }
- }
#ifdef INET6
if (ip6) {
@@ -256,6 +236,24 @@
if (qflag) {
(void)printf("tcp %d", length - tp->th_off * 4);
return;
+ } else {
+ /*
+ * If data present and NFS port used, assume NFS.
+ * Pass offset of data plus 4 bytes for RPC TCP msg length
+ * to NFS print routines.
+ */
+ u_int len = length - hlen;
+ if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend &&
+ dport == NFS_PORT) {
+ nfsreq_print((u_char *)tp + hlen + 4, len,
+ (u_char *)ip);
+ return;
+ } else if ((u_char *)tp + 4 +
+ sizeof(struct rpc_msg) <= snapend && sport == NFS_PORT) {
+ nfsreply_print((u_char *)tp + hlen + 4, len,
+ (u_char *)ip);
+ return;
+ }
}
if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH|
TH_ECNECHO|TH_CWR)) {
Index: print-udp.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-udp.c,v
retrieving revision 1.14
diff -u -r1.14 print-udp.c
--- print-udp.c 2000/10/03 14:21:57 1.14
+++ print-udp.c 2000/12/02 17:19:27
@@ -423,6 +423,11 @@
break;
case PT_RPC:
+ (void)printf("%s.%s > %s.%s: ",
+ ipaddr_string(&ip->ip_src),
+ udpport_string(sport),
+ ipaddr_string(&ip->ip_dst),
+ udpport_string(dport));
rp = (struct rpc_msg *)(up + 1);
direction = (enum msg_type)ntohl(rp->rm_direction);
if (direction == CALL)
@@ -466,17 +471,32 @@
if (TTEST(rp->rm_direction)) {
direction = (enum msg_type)ntohl(rp->rm_direction);
if (dport == NFS_PORT && direction == CALL) {
+ (void)printf("%s.%s > %s.%s: ",
+ ipaddr_string(&ip->ip_src),
+ udpport_string(sport),
+ ipaddr_string(&ip->ip_dst),
+ udpport_string(dport));
nfsreq_print((u_char *)rp, length,
(u_char *)ip);
return;
}
if (sport == NFS_PORT && direction == REPLY) {
+ (void)printf("%s.%s > %s.%s: ",
+ ipaddr_string(&ip->ip_src),
+ udpport_string(sport),
+ ipaddr_string(&ip->ip_dst),
+ udpport_string(dport));
nfsreply_print((u_char *)rp, length,
(u_char *)ip);
return;
}
#ifdef notdef
if (dport == SUNRPC_PORT && direction == CALL) {
+ (void)printf("%s.%s > %s.%s: ",
+ ipaddr_string(&ip->ip_src),
+ udpport_string(sport),
+ ipaddr_string(&ip->ip_dst),
+ udpport_string(dport));
sunrpcrequest_print((u_char *)rp, length, (u_char
*)ip);
return;
}
>Audit-Trail:
>Unformatted: