1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/types.h>
27 #include <sys/errno.h>
28 #include <setjmp.h>
29
30 #include <netinet/in.h>
31 #include <netdb.h>
32
33 #include <sys/tiuser.h>
34 #include <rpc/types.h>
35 #include <rpc/xdr.h>
36 #include <rpc/auth.h>
37 #include <rpc/auth_unix.h>
38 #include <rpc/auth_des.h>
39 #include <rpc/clnt.h>
40 #include <rpc/rpc_msg.h>
41 #include <rpc/pmap_clnt.h>
42 #include <rpc/svc.h>
43 #include <rpcsvc/yp_prot.h>
44 #include <rpc/pmap_prot.h>
45 #include "snoop.h"
46
47 #ifndef MIN
48 #define MIN(a, b) ((a) < (b) ? (a) : (b))
49 #endif
50
51 int pos;
52 struct cache_struct *find_xid();
53 extern jmp_buf xdr_err;
54 void protoprint();
55 void print_rpcsec_gss_cred(int xid, int authlen);
56 char *nameof_prog();
57 char *nameof_astat();
58 char *nameof_why();
59 static void rpc_detail_call(int, int, int, int, int, int, char *, int);
60 static void rpc_detail_reply(int, int, struct cache_struct *, char *, int len);
61 static void print_creds(int);
62 static void print_verif(int);
63 static void stash_xid(ulong_t, int, int, int, int);
64 struct cache_struct xid_cache[XID_CACHE_SIZE];
65
66 #define LAST_FRAG ((ulong_t)1 << 31)
67
68 int
interpret_rpc(int flags,char * rpc,int fraglen,int type)69 interpret_rpc(int flags, char *rpc, int fraglen, int type)
70 {
71 ulong_t xid;
72 int direction;
73 struct cache_struct *x;
74 int rpcvers, prog, vers, proc;
75 int status, astat, rstat, why;
76 char *lp;
77 unsigned recmark;
78 int markpos;
79 extern int pi_frame;
80 int lo, hi;
81
82 xdr_init(rpc, fraglen);
83
84 if (setjmp(xdr_err)) {
85 if (flags & F_DTAIL)
86 (void) sprintf(get_line(0, 0),
87 "---- short frame ---");
88 return (fraglen);
89 }
90
91 if (type == IPPROTO_TCP) { /* record mark */
92 markpos = getxdr_pos();
93 recmark = getxdr_long();
94 }
95
96 xid = getxdr_u_long();
97 direction = getxdr_long();
98
99 if (direction == CALL) {
100 rpcvers = getxdr_long();
101 pos = getxdr_pos();
102 prog = getxdr_long();
103 vers = getxdr_long();
104 proc = getxdr_long();
105 stash_xid(xid, pi_frame, prog, vers, proc);
106 if (!(flags & (F_SUM | F_DTAIL))) {
107 protoprint(flags, CALL, xid, prog, vers, proc,
108 rpc, fraglen);
109 }
110 } else {
111 x = find_xid(xid);
112 }
113
114 if (flags & F_SUM) {
115 switch (direction) {
116 case CALL:
117 (void) sprintf(get_sum_line(),
118 "RPC C XID=%lu PROG=%d (%s) VERS=%d PROC=%d",
119 xid,
120 prog, nameof_prog(prog),
121 vers, proc);
122 if (getxdr_long() == RPCSEC_GSS) { /* Cred auth type */
123 extract_rpcsec_gss_cred_info(xid);
124 /* RPCSEC_GSS cred auth data */
125 } else {
126 xdr_skip(getxdr_long());
127 /* non RPCSEC_GSS cred auth data */
128 }
129 xdr_skip(4); /* Verf auth type */
130 xdr_skip(RNDUP(getxdr_long())); /* Verf auth data */
131
132 protoprint(flags, CALL, xid, prog, vers, proc,
133 rpc, fraglen);
134 break;
135
136 case REPLY:
137 lp = get_sum_line();
138 if (x == NULL)
139 (void) sprintf(lp, "RPC R XID=%lu", xid);
140 else
141 (void) sprintf(lp, "RPC R (#%d) XID=%lu",
142 x->xid_frame, xid);
143
144 lp += strlen(lp);
145 status = getxdr_long();
146 switch (status) {
147 case MSG_ACCEPTED:
148 /* eat flavor and verifier */
149 (void) getxdr_long();
150 xdr_skip(RNDUP(getxdr_long()));
151 astat = getxdr_long();
152 (void) sprintf(lp, " %s",
153 nameof_astat(astat));
154 lp += strlen(lp);
155
156 switch (astat) {
157 case SUCCESS:
158 if (x) {
159 protoprint(flags, REPLY,
160 xid,
161 x->xid_prog,
162 x->xid_vers,
163 x->xid_proc,
164 rpc, fraglen);
165 }
166 break;
167
168 case PROG_UNAVAIL :
169 case PROG_MISMATCH:
170 case PROC_UNAVAIL :
171 lo = getxdr_long();
172 hi = getxdr_long();
173 (void) sprintf(lp,
174 " (low=%d, high=%d)",
175 lo, hi);
176 break;
177
178 case GARBAGE_ARGS:
179 case SYSTEM_ERR:
180 default:
181 ;
182 }
183 break;
184
185 case MSG_DENIED:
186 rstat = getxdr_long();
187
188 switch (rstat) {
189 case RPC_MISMATCH:
190 lo = getxdr_long();
191 hi = getxdr_long();
192 (void) sprintf(lp,
193 " Vers mismatch (low=%d, high=%d)",
194 lo, hi);
195 break;
196
197 case AUTH_ERROR:
198 why = getxdr_u_long();
199 (void) sprintf(lp,
200 " Can't authenticate (%s)",
201 nameof_why(why));
202 break;
203 }
204 }
205 break;
206 }
207 }
208
209 if (flags & F_DTAIL) {
210 show_header("RPC: ", "SUN RPC Header", fraglen);
211 show_space();
212 if (type == IPPROTO_TCP) { /* record mark */
213 (void) sprintf(get_line(markpos, markpos+4),
214 "Record Mark: %s fragment, length = %d",
215 recmark & LAST_FRAG ? "last" : "",
216 recmark & ~LAST_FRAG);
217 }
218
219 (void) sprintf(get_line(0, 0),
220 "Transaction id = %lu",
221 xid);
222 (void) sprintf(get_line(0, 0),
223 "Type = %d (%s)",
224 direction,
225 direction == CALL ? "Call":"Reply");
226
227 switch (direction) {
228 case CALL:
229 rpc_detail_call(flags, xid, rpcvers,
230 prog, vers, proc, rpc, fraglen);
231 break;
232 case REPLY:
233 rpc_detail_reply(flags, xid, x, rpc, fraglen);
234 break;
235 }
236 }
237
238 return (fraglen);
239 }
240
241 static void
rpc_detail_call(int flags,int xid,int rpcvers,int prog,int vers,int proc,char * data,int len)242 rpc_detail_call(int flags, int xid, int rpcvers, int prog, int vers, int proc,
243 char *data, int len)
244 {
245 char *nameof_flavor();
246 char *nameof_prog();
247
248 (void) sprintf(get_line(pos, getxdr_pos()),
249 "RPC version = %d",
250 rpcvers);
251 (void) sprintf(get_line(pos, getxdr_pos()),
252 "Program = %d (%s), version = %d, procedure = %d",
253 prog, nameof_prog(prog), vers, proc);
254 print_creds(xid);
255 print_verif(CALL);
256 show_trailer();
257 protoprint(flags, CALL, xid, prog, vers, proc, data, len);
258 }
259
260 char *
nameof_flavor(int flavor)261 nameof_flavor(int flavor)
262 {
263 switch (flavor) {
264 case AUTH_NONE : return ("None");
265 case AUTH_UNIX : return ("Unix");
266 case AUTH_SHORT: return ("Unix short");
267 case AUTH_DES : return ("DES");
268 case RPCSEC_GSS: return ("RPCSEC_GSS");
269 default: return ("unknown");
270 }
271 }
272
273 char *
tohex(char * p,int len)274 tohex(char *p, int len)
275 {
276 int i, j;
277 static char hbuff[1024];
278 static char *hexstr = "0123456789ABCDEF";
279 char toobig = 0;
280
281 if (len * 2 > sizeof (hbuff)) {
282 toobig++;
283 len = sizeof (hbuff) / 2;
284 }
285
286 j = 0;
287 for (i = 0; i < len; i++) {
288 hbuff[j++] = hexstr[p[i] >> 4 & 0x0f];
289 hbuff[j++] = hexstr[p[i] & 0x0f];
290 }
291
292 if (toobig) {
293 hbuff[len * 2 - strlen("<Too Long>")] = '\0';
294 strcat(hbuff, "<Too Long>");
295 } else
296 hbuff[j] = '\0';
297
298 return (hbuff);
299 }
300
301 static void
print_creds(int xid)302 print_creds(int xid)
303 {
304 int pos, flavor, authlen;
305 int uid, gid, len;
306 int tlen, idlen;
307 int i, namekind;
308 char *p, *line;
309
310 pos = getxdr_pos();
311 flavor = getxdr_long();
312 authlen = getxdr_long();
313 (void) sprintf(get_line(pos, getxdr_pos()),
314 "Credentials: Flavor = %d (%s), len = %d bytes",
315 flavor, nameof_flavor(flavor), authlen);
316 if (authlen <= 0)
317 return;
318
319 switch (flavor) {
320 case AUTH_UNIX:
321 (void) showxdr_time(" Time = %s");
322 (void) showxdr_string(MAX_MACHINE_NAME, " Hostname = %s");
323 pos = getxdr_pos();
324 uid = getxdr_u_long();
325 gid = getxdr_u_long();
326 (void) sprintf(get_line(pos, getxdr_pos()),
327 " Uid = %d, Gid = %d",
328 uid, gid);
329 len = getxdr_u_long();
330 line = get_line(pos, len * 4);
331 if (len == 0)
332 (void) sprintf(line, " Groups = (none)");
333 else {
334 (void) sprintf(line, " Groups = ");
335 line += strlen(line);
336 while (len--) {
337 gid = getxdr_u_long();
338 (void) sprintf(line, "%d ", gid);
339 line += strlen(line);
340 }
341 }
342 break;
343
344 case AUTH_DES:
345 namekind = getxdr_u_long();
346 (void) sprintf(get_line(pos, getxdr_pos()),
347 " Name kind = %d (%s)",
348 namekind,
349 namekind == ADN_FULLNAME ?
350 "fullname" : "nickname");
351 switch (namekind) {
352 case ADN_FULLNAME:
353 (void) showxdr_string(64,
354 " Network name = %s");
355 (void) showxdr_hex(8,
356 " Conversation key = 0x%s (DES encrypted)");
357 (void) showxdr_hex(4,
358 " Window = 0x%s (DES encrypted)");
359 break;
360
361 case ADN_NICKNAME:
362 (void) showxdr_hex(4, " Nickname = 0x%s");
363 break;
364 };
365 break;
366
367 case RPCSEC_GSS:
368 print_rpcsec_gss_cred(xid, authlen);
369 break;
370
371 default:
372 (void) showxdr_hex(authlen, "[%s]");
373 break;
374 }
375 }
376
377 static void
print_verif(int direction)378 print_verif(int direction)
379 {
380 int pos, flavor, verlen;
381
382 pos = getxdr_pos();
383 flavor = getxdr_long();
384 verlen = getxdr_long();
385 (void) sprintf(get_line(pos, getxdr_pos()),
386 "Verifier : Flavor = %d (%s), len = %d bytes",
387 flavor, nameof_flavor(flavor), verlen);
388 if (verlen == 0)
389 return;
390
391 switch (flavor) {
392 case AUTH_DES:
393 (void) showxdr_hex(8, " Timestamp = 0x%s (DES encrypted)");
394 if (direction == CALL)
395 (void) showxdr_hex(4,
396 " Window = 0x%s (DES encrypted)");
397 else
398 (void) showxdr_hex(4, " Nickname = 0x%s");
399 break;
400
401 /* For other flavors like AUTH_NONE, AUTH_UNIX, RPCSEC_GSS etc. */
402 default:
403 (void) showxdr_hex(verlen, "[%s]");
404 break;
405 }
406 }
407
408 struct rpcnames {
409 int rp_prog;
410 char *rp_name;
411 } rpcnames[] = {
412 100000, "PMAP", /* Portmapper */
413 100001, "RSTAT", /* Remote stats */
414 100002, "RUSERS", /* Remote users */
415 100003, "NFS", /* Nfs */
416 100004, "NIS", /* Network Information Service */
417 100005, "MOUNT", /* Mount demon */
418 100006, "DBX", /* Remote dbx */
419 100007, "NISBIND", /* NIS binder */
420 100008, "WALL", /* Shutdown msg */
421 100009, "NISPASSWD", /* Yppasswd server */
422 100010, "ETHERSTAT", /* Ether stats */
423 100011, "RQUOTA", /* Disk quotas */
424 100012, "SPRAY", /* Spray packets */
425 100013, "IBM3270", /* 3270 mapper */
426 100014, "IBMRJE", /* RJE mapper */
427 100015, "SELNSVC", /* Selection service */
428 100016, "RDATABASE", /* Remote database access */
429 100017, "REX", /* Remote execution */
430 100018, "ALICE", /* Alice Office Automation */
431 100019, "SCHED", /* Scheduling service */
432 100020, "LLM", /* Local lock manager */
433 100021, "NLM", /* Network lock manager */
434 100022, "X25INR", /* X.25 inr protocol */
435 100023, "STATMON1", /* Status monitor 1 */
436 100024, "STATMON2", /* Status monitor 2 */
437 100025, "SELNLIB", /* Selection library */
438 100026, "BOOTPARAM", /* Boot parameters service */
439 100027, "MAZEPROG", /* Mazewars game */
440 100028, "NISUPDATE", /* NIS update */
441 100029, "KEYSERVE", /* Key server */
442 100030, "SECURECMD", /* Secure login */
443 100031, "NETFWDI", /* NFS net forwarder init */
444 100032, "NETFWDT", /* NFS net forwarder trans */
445 100033, "SUNLINKMAP", /* Sunlink MAP */
446 100034, "NETMON", /* Network monitor */
447 100035, "DBASE", /* Lightweight database */
448 100036, "PWDAUTH", /* Password authorization */
449 100037, "TFS", /* Translucent file svc */
450 100038, "NSE", /* NSE server */
451 100039, "NSE_ACTIVATE", /* NSE activate daemon */
452 100040, "SUNVIEW_HELP", /* Sunview help */
453 100041, "PNP", /* PNP install */
454 100042, "IPADDR_ALLOC", /* IP addr allocator */
455 100043, "FILEHANDLE", /* Show filehandle */
456 100044, "MVSNFS", /* MVS NFS mount */
457 100045, "REM_FILEOP_USER", /* Remote user file operations */
458 100046, "BATCH_NISUPDATE", /* Batched ypupdate */
459 100047, "NEM", /* Network execution mgr */
460 100048, "RAYTRACE_RD", /* Raytrace/mandelbrot remote daemon */
461 100049, "RAYTRACE_LD", /* Raytrace/mandelbrot local daemon */
462 100050, "REM_FILEOP_GROUP", /* Remote group file operations */
463 100051, "REM_FILEOP_SYSTEM", /* Remote system file operations */
464 100052, "REM_SYSTEM_ROLE", /* Remote system role operations */
465 100055, "IOADMD", /* Ioadmd */
466 100056, "FILEMERGE", /* Filemerge */
467 100057, "NAMEBIND", /* Name Binding Program */
468 100058, "NJE", /* Sunlink NJE */
469 100059, "MVSATTR", /* MVSNFS get attribute service */
470 100060, "RMGR", /* SunAccess/SunLink resource manager */
471 100061, "UIDALLOC", /* UID allocation service */
472 100062, "LBSERVER", /* License broker */
473 100063, "LBBINDER", /* NETlicense client binder */
474 100064, "GIDALLOC", /* GID allocation service */
475 100065, "SUNISAM", /* SunIsam */
476 100066, "RDBSRV", /* Remote Debug Server */
477 100067, "NETDIR", /* Network directory daemon */
478 100068, "CMSD", /* Network calendar program */
479 100069, "NISXFR", /* NIS transfer */
480 100070, "TIMED", /* RPC.timed */
481 100071, "BUGTRAQ", /* Bugtraqd */
482 100072, "NeFS", /* Internal use only */
483 100073, "BILLBOARD", /* Connectathon Billboard - NFS */
484 100074, "BILLBOARD", /* Connectathon Billboard - X */
485 100075, "SCHEDROOM", /* Sun meeting room scheduler */
486 100076, "AUTHNEGOTIATE", /* Authentication negotiation */
487 100077, "ATTRPROG", /* Database manipulation */
488 100080, "AUTODUMP", /* Sun consulting special */
489 100081, "EVENT_SVC", /* Event protocol */
490 100085, "ARM_PSD", /* ARM policy */
491 100086, "ARMTOD", /* ARM TOD */
492 100087, "NA.ADMIN", /* Sun (SNAG) administration agent */
493 100099, "PLD", /* Genesil 8.1 hot plot */
494 100101, "NA.EVENT", /* SNM (SunNet Manager) event dispatcher */
495 100102, "NA.LOGGER", /* SNM report logger */
496 100103, "NA.DISCOVER", /* SNM network discovery agent */
497 100104, "NA.SYNC", /* SNM sync interface agent */
498 100105, "NA.DISKINFO", /* SNM disk info agent */
499 100106, "NA.IOSTAT", /* SNM iostat agent */
500 100107, "NA.HOSTPERF", /* SNM rstat proxy agent */
501 100108, "NA.CONFIG", /* SNM host configuration agent */
502 100109, "NA.ACTIVITY", /* SNM activity daemon */
503 100111, "NA.LPSTAT", /* SNM printer agent */
504 100112, "NA.HOSTMEM", /* SNM host network memory agent */
505 100113, "NA.SAMPLE", /* SNM sample agent */
506 100114, "NA.X25", /* SNM X.25 agent */
507 100115, "NA.PING", /* SNM ping proxy agent */
508 100116, "NA.RPCNFS", /* SNM rpc and nfs agent */
509 100117, "NA.HOSTIF", /* SNM host interface agent */
510 100118, "NA.ETHERIF", /* SNM ethernet interface agent */
511 100119, "NA.IPPATH", /* SNM traceroute proxy agent */
512 100120, "NA.IPROUTES", /* SNM routing table agent */
513 100121, "NA.LAYERS", /* SNM protocol layers gent */
514 100122, "NA.SNMP", /* SNM SNMP proxy agent */
515 100123, "NA.TRAFFIC", /* SNM network traffic agent */
516 100124, "NA.DNI", /* DNI (DECnet) proxy agent */
517 100125, "NA.CHAT", /* IBM Channel attach proxy agent */
518 100126, "NA.FDDI", /* FDDI agent */
519 100127, "NA.FDDISMT", /* FDDI SMT proxy agent */
520 100128, "NA.MHS", /* MHS agent */
521 100130, "SNM_GRAPHER", /* SNM 3D grapher */
522 100132, "NA.TR", /* Token Ring agent */
523 100134, "NA.TOKENRING", /* Token Ring agent */
524 100136, "NA.FRAMERELAY", /* Frame Relay agent */
525 100175, "NA.SNMPTRAP", /* SNM SNMP trap daemon */
526 100180, "NA.MIPROUTES", /* SNM multicast routing table agent */
527 100201, "MVSNFSSTAT", /* MVS/NFS Memory usage statistic server */
528 100227, "NFS_ACL", /* NFS ACL support */
529 101002, "NSELINKTOOL", /* NSE link daemon */
530 101003, "NSELINKAPP", /* NSE link application */
531 110001, "GOLABEL", /* SunOS MLS */
532 110002, "PUC", /* SunOS MLS */
533 150001, "PCNFSD", /* PC passwd authorization */
534 150002, "TOPS", /* TOPS name mapping */
535 150003, "TOPS", /* TOPS external attribute storage */
536 150004, "TOPS", /* TOPS hierarchical file system */
537 150005, "TOPS", /* TOPS NFS transparency extensions */
538 150006, "SOLARNET_FW", /* SolarNet Framework protocol */
539 160001, "CM", /* Nihon Sun - Japanese Input system */
540 300004, "FRAME 1", /* Frame program 1 */
541 300009, "FRAME 2", /* Frame program 2 */
542 390101, "RAP", /* Legato RAP protocol */
543 390102, "RAPRD", /* Legato RAP resource dir protocol */
544 500021, "ZNS", /* Zeus Network Service */
545 };
546
547 int
compare(struct rpcnames * a,struct rpcnames * b)548 compare(struct rpcnames *a, struct rpcnames *b)
549 {
550 return (a->rp_prog - b->rp_prog);
551 }
552
553 char *
nameof_prog(int prog)554 nameof_prog(int prog)
555 {
556 struct rpcnames *r;
557 struct rpcnames *bsearch();
558 int elems = sizeof (rpcnames) / sizeof (*r);
559
560 r = bsearch(&prog, rpcnames, elems, sizeof (*r), compare);
561 if (r)
562 return (r->rp_name);
563
564 if (prog >= 0x40000000 && prog <= 0x5fffffff)
565 return ("transient");
566
567 return ("?");
568 }
569
570 char *
nameof_astat(int status)571 nameof_astat(int status)
572 {
573 switch (status) {
574 case SUCCESS : return ("Success");
575 case PROG_UNAVAIL : return ("Program unavailable");
576 case PROG_MISMATCH: return ("Program number mismatch");
577 case PROC_UNAVAIL : return ("Procedure unavailable");
578 case GARBAGE_ARGS : return ("Garbage arguments");
579 case SYSTEM_ERR : return ("System error");
580 default: return ("unknown");
581 }
582 }
583
584 char *
nameof_why(int why)585 nameof_why(int why)
586 {
587 switch (why) {
588 case AUTH_BADCRED: return ("bogus credentials (seal broken)");
589 case AUTH_REJECTEDCRED: return ("client should begin new session");
590 case AUTH_BADVERF: return ("bogus verifier (seal broken)");
591 case AUTH_REJECTEDVERF: return ("verifier expired or was replayed");
592 case AUTH_TOOWEAK: return ("too weak");
593 case AUTH_INVALIDRESP: return ("bogus response verifier");
594 case AUTH_TIMEEXPIRE: return ("time of credential expired");
595 case AUTH_TKT_FILE: return ("something wrong with ticket file");
596 case AUTH_DECODE: return ("can't decode authenticator");
597 case AUTH_NET_ADDR: return ("net address in ticket wrong");
598 case RPCSEC_GSS_NOCRED: return ("no credentials for user");
599 case RPCSEC_GSS_FAILED: return ("GSS failure, credentials deleted");
600 case AUTH_FAILED:
601 default:
602 return ("unknown reason");
603 }
604 }
605
606 static void
rpc_detail_reply(int flags,int xid,struct cache_struct * x,char * data,int len)607 rpc_detail_reply(int flags, int xid, struct cache_struct *x, char *data,
608 int len)
609 {
610 int status;
611 int astat, rstat, why;
612 int pos;
613
614 if (x) {
615 (void) sprintf(get_line(0, 0),
616 "This is a reply to frame %d",
617 x->xid_frame);
618 }
619 pos = getxdr_pos();
620 status = getxdr_long();
621 (void) sprintf(get_line(pos, getxdr_pos()),
622 "Status = %d (%s)",
623 status, status ? "Denied" : "Accepted");
624
625 switch (status) {
626 case MSG_ACCEPTED:
627 print_verif(REPLY);
628 pos = getxdr_pos();
629 astat = getxdr_long();
630 (void) sprintf(get_line(pos, getxdr_pos()),
631 "Accept status = %d (%s)",
632 astat, nameof_astat(astat));
633
634 switch (astat) {
635 case SUCCESS:
636 if (x) {
637 show_trailer();
638 protoprint(flags, REPLY, xid,
639 x->xid_prog, x->xid_vers, x->xid_proc,
640 data, len);
641 }
642 break;
643 case PROG_UNAVAIL :
644 break;
645 case PROG_MISMATCH:
646 case PROC_UNAVAIL :
647 showxdr_long(" Low = %d");
648 showxdr_long(" High = %d");
649 break;
650 case GARBAGE_ARGS:
651 case SYSTEM_ERR:
652 default:
653 ;
654 }
655
656 break;
657
658 case MSG_DENIED:
659 pos = getxdr_pos();
660 rstat = getxdr_long();
661 (void) sprintf(get_line(pos, getxdr_pos()),
662 "Reject status = %d (%s)",
663 rstat,
664 rstat ? "can't authenticate"
665 : "version mismatch");
666
667 switch (rstat) {
668 case RPC_MISMATCH:
669 showxdr_long(" Low = %d");
670 showxdr_long(" High = %d");
671 break;
672 case AUTH_ERROR:
673 why = getxdr_u_long();
674 (void) sprintf(get_line(pos, getxdr_pos()),
675 " Why = %d (%s)",
676 why, nameof_why(why));
677 break;
678 }
679 break;
680 }
681 }
682
683 /*
684 * Return true if this is a valid RPC packet
685 */
686 int
valid_rpc(char * rpc,int rpclen)687 valid_rpc(char *rpc, int rpclen)
688 {
689 XDR xdrm;
690 struct rpc_msg msg;
691
692 if (rpclen < 12)
693 return (0);
694
695 xdrmem_create(&xdrm, rpc, rpclen, XDR_DECODE);
696 if (xdr_u_int(&xdrm, &msg.rm_xid) &&
697 xdr_u_int(&xdrm, (uint_t *)&msg.rm_direction)) {
698 switch (msg.rm_direction) {
699 case CALL:
700 if (xdr_rpcvers(&xdrm, &msg.rm_call.cb_rpcvers) &&
701 msg.rm_call.cb_rpcvers == 2)
702 return (1);
703 break;
704 case REPLY:
705 if (xdr_u_int(&xdrm,
706 (uint_t *)&msg.rm_reply.rp_stat) &&
707 (msg.rm_reply.rp_stat == MSG_ACCEPTED ||
708 msg.rm_reply.rp_stat == MSG_DENIED))
709 return (1);
710 break;
711 }
712 }
713
714 return (0);
715 }
716
717 struct cache_struct *xcpfirst = &xid_cache[0];
718 struct cache_struct *xcp = &xid_cache[0];
719 struct cache_struct *xcplast = &xid_cache[XID_CACHE_SIZE - 1];
720
721 struct cache_struct *
find_xid(ulong_t xid)722 find_xid(ulong_t xid)
723 {
724 struct cache_struct *x;
725
726 for (x = xcp; x >= xcpfirst; x--)
727 if (x->xid_num == xid)
728 return (x);
729 for (x = xcplast; x > xcp; x--)
730 if (x->xid_num == xid)
731 return (x);
732 return (NULL);
733 }
734
735 static void
stash_xid(ulong_t xid,int frame,int prog,int vers,int proc)736 stash_xid(ulong_t xid, int frame, int prog, int vers, int proc)
737 {
738 struct cache_struct *x;
739
740 x = find_xid(xid);
741 if (x == NULL) {
742 x = xcp++;
743 if (xcp > xcplast)
744 xcp = xcpfirst;
745 x->xid_num = xid;
746 x->xid_frame = frame;
747 }
748 x->xid_prog = prog;
749 x->xid_vers = vers;
750 x->xid_proc = proc;
751 x->xid_gss_proc = RPCSEC_GSS_DATA;
752 x->xid_gss_service = rpc_gss_svc_default;
753 }
754
755 void
check_retransmit(char * line,ulong_t xid)756 check_retransmit(char *line, ulong_t xid)
757 {
758 struct cache_struct *x;
759 extern int pi_frame;
760
761 x = find_xid(xid);
762 if (x && x->xid_frame != pi_frame)
763 (void) strcat(line, " (retransmit)");
764 }
765